Mercurial > dropbear
comparison common-algo.c @ 747:077bbe1eb220
merge kexguess branch
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 03 Apr 2013 00:49:24 +0800 |
parents | 465fefc4f6e0 |
children | 7dcb46da72d9 3ca7113936c1 |
comparison
equal
deleted
inserted
replaced
736:0b854ab00333 | 747:077bbe1eb220 |
---|---|
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
24 * SOFTWARE. */ | 24 * SOFTWARE. */ |
25 | 25 |
26 #include "algo.h" | 26 #include "algo.h" |
27 #include "session.h" | |
27 #include "dbutil.h" | 28 #include "dbutil.h" |
28 | 29 |
29 /* This file (algo.c) organises the ciphers which can be used, and is used to | 30 /* This file (algo.c) organises the ciphers which can be used, and is used to |
30 * decide which ciphers/hashes/compression/signing to use during key exchange*/ | 31 * decide which ciphers/hashes/compression/signing to use during key exchange*/ |
31 | 32 |
213 }; | 214 }; |
214 | 215 |
215 algo_type sshkex[] = { | 216 algo_type sshkex[] = { |
216 {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, | 217 {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, |
217 {"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, | 218 {"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, |
219 #ifdef USE_KEXGUESS2 | |
220 {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL}, | |
221 #endif | |
218 {NULL, 0, NULL, 0, NULL} | 222 {NULL, 0, NULL, 0, NULL} |
219 }; | 223 }; |
220 | 224 |
221 | 225 |
222 /* Register the compiled in ciphers. | 226 /* Register the compiled in ciphers. |
303 buf_putbytes(algolist, localalgos[i].name, len); | 307 buf_putbytes(algolist, localalgos[i].name, len); |
304 } | 308 } |
305 } | 309 } |
306 buf_putstring(buf, algolist->data, algolist->len); | 310 buf_putstring(buf, algolist->data, algolist->len); |
307 buf_free(algolist); | 311 buf_free(algolist); |
312 } | |
313 | |
314 /* match the first algorithm in the comma-separated list in buf which is | |
315 * also in localalgos[], or return NULL on failure. | |
316 * (*goodguess) is set to 1 if the preferred client/server algos match, | |
317 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are | |
318 * guessed correctly */ | |
319 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], | |
320 enum kexguess2_used *kexguess2, int *goodguess) | |
321 { | |
322 | |
323 unsigned char * algolist = NULL; | |
324 const unsigned char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; | |
325 unsigned int len; | |
326 unsigned int remotecount, localcount, clicount, servcount, i, j; | |
327 algo_type * ret = NULL; | |
328 const unsigned char **clinames, **servnames; | |
329 | |
330 if (goodguess) { | |
331 *goodguess = 0; | |
332 } | |
333 | |
334 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ | |
335 algolist = buf_getstring(buf, &len); | |
336 TRACE(("buf_match_algo: %s", algolist)) | |
337 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { | |
338 goto out; | |
339 } | |
340 | |
341 /* remotenames will contain a list of the strings parsed out */ | |
342 /* We will have at least one string (even if it's just "") */ | |
343 remotenames[0] = algolist; | |
344 remotecount = 1; | |
345 for (i = 0; i < len; i++) { | |
346 if (algolist[i] == '\0') { | |
347 /* someone is trying something strange */ | |
348 goto out; | |
349 } | |
350 if (algolist[i] == ',') { | |
351 algolist[i] = '\0'; | |
352 remotenames[remotecount] = &algolist[i+1]; | |
353 remotecount++; | |
354 } | |
355 if (remotecount >= MAX_PROPOSED_ALGO) { | |
356 break; | |
357 } | |
358 } | |
359 if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) { | |
360 for (i = 0; i < remotecount; i++) | |
361 { | |
362 if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) { | |
363 *kexguess2 = KEXGUESS2_YES; | |
364 break; | |
365 } | |
366 } | |
367 if (*kexguess2 == KEXGUESS2_LOOK) { | |
368 *kexguess2 = KEXGUESS2_NO; | |
369 } | |
370 } | |
371 | |
372 for (i = 0; localalgos[i].name != NULL; i++) { | |
373 if (localalgos[i].usable) { | |
374 localnames[i] = localalgos[i].name; | |
375 } else { | |
376 localnames[i] = NULL; | |
377 } | |
378 } | |
379 localcount = i; | |
380 | |
381 if (IS_DROPBEAR_SERVER) { | |
382 clinames = remotenames; | |
383 clicount = remotecount; | |
384 servnames = localnames; | |
385 servcount = localcount; | |
386 } else { | |
387 clinames = localnames; | |
388 clicount = localcount; | |
389 servnames = remotenames; | |
390 servcount = remotecount; | |
391 } | |
392 | |
393 /* iterate and find the first match */ | |
394 for (i = 0; i < clicount; i++) { | |
395 for (j = 0; j < servcount; j++) { | |
396 if (!(servnames[j] && clinames[i])) { | |
397 // unusable algos are NULL | |
398 continue; | |
399 } | |
400 if (strcmp(servnames[j], clinames[i]) == 0) { | |
401 /* set if it was a good guess */ | |
402 if (goodguess && kexguess2) { | |
403 if (*kexguess2 == KEXGUESS2_YES) { | |
404 if (i == 0) { | |
405 *goodguess = 1; | |
406 } | |
407 | |
408 } else { | |
409 if (i == 0 && j == 0) { | |
410 *goodguess = 1; | |
411 } | |
412 } | |
413 } | |
414 /* set the algo to return */ | |
415 if (IS_DROPBEAR_SERVER) { | |
416 ret = &localalgos[j]; | |
417 } else { | |
418 ret = &localalgos[i]; | |
419 } | |
420 goto out; | |
421 } | |
422 } | |
423 } | |
424 | |
425 out: | |
426 m_free(algolist); | |
427 return ret; | |
308 } | 428 } |
309 | 429 |
310 #ifdef DROPBEAR_NONE_CIPHER | 430 #ifdef DROPBEAR_NONE_CIPHER |
311 | 431 |
312 void | 432 void |