comparison common-algo.c @ 1676:d5cdc60db08e

ext-info handling for server-sig-algs only client side is handled
author Matt Johnston <matt@ucc.asn.au>
date Tue, 19 May 2020 00:31:41 +0800
parents ae41624c2198
children 4b4cfc92c5b7
comparison
equal deleted inserted replaced
1675:ae41624c2198 1676:d5cdc60db08e
28 #include "session.h" 28 #include "session.h"
29 #include "dbutil.h" 29 #include "dbutil.h"
30 #include "dh_groups.h" 30 #include "dh_groups.h"
31 #include "ltc_prng.h" 31 #include "ltc_prng.h"
32 #include "ecc.h" 32 #include "ecc.h"
33 #include "ssh.h"
33 34
34 /* This file (algo.c) organises the ciphers which can be used, and is used to 35 /* This file (algo.c) organises the ciphers which can be used, and is used to
35 * decide which ciphers/hashes/compression/signing to use during key exchange*/ 36 * decide which ciphers/hashes/compression/signing to use during key exchange*/
36 37
37 static int void_cipher(const unsigned char* in, unsigned char* out, 38 static int void_cipher(const unsigned char* in, unsigned char* out,
278 #if DROPBEAR_CURVE25519 279 #if DROPBEAR_CURVE25519
279 /* Referred to directly */ 280 /* Referred to directly */
280 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc }; 281 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
281 #endif 282 #endif
282 283
284 /* data == NULL for non-kex algorithm identifiers */
283 algo_type sshkex[] = { 285 algo_type sshkex[] = {
284 #if DROPBEAR_CURVE25519 286 #if DROPBEAR_CURVE25519
285 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL}, 287 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL},
286 {"[email protected]", 0, &kex_curve25519, 1, NULL}, 288 {"[email protected]", 0, &kex_curve25519, 1, NULL},
287 #endif 289 #endif
307 #endif 309 #endif
308 #if DROPBEAR_DH_GROUP16 310 #if DROPBEAR_DH_GROUP16
309 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL}, 311 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
310 #endif 312 #endif
311 #if DROPBEAR_KEXGUESS2 313 #if DROPBEAR_KEXGUESS2
312 {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL}, 314 {KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
315 #endif
316 #if DROPBEAR_CLIENT
317 /* Set unusable by svr_algos_initialise() */
318 {SSH_EXT_INFO_C, 0, NULL, 1, NULL},
313 #endif 319 #endif
314 {NULL, 0, NULL, 0, NULL} 320 {NULL, 0, NULL, 0, NULL}
315 }; 321 };
316 322
317 /* Output a comma separated list of algorithms to a buffer */ 323 /* Output a comma separated list of algorithms to a buffer */
334 buf_putstring(buf, (const char*)algolist->data, algolist->len); 340 buf_putstring(buf, (const char*)algolist->data, algolist->len);
335 TRACE(("algolist add '%*s'", algolist->len, algolist->data)) 341 TRACE(("algolist add '%*s'", algolist->len, algolist->data))
336 buf_free(algolist); 342 buf_free(algolist);
337 } 343 }
338 344
345 /* returns a list of pointers into algolist, of null-terminated names.
346 ret_list should be passed in with space for *ret_count elements,
347 on return *ret_count has the number of names filled.
348 algolist is modified. */
349 static void get_algolist(char* algolist, unsigned int algolist_len,
350 const char* *ret_list, unsigned int *ret_count) {
351 unsigned int max_count = *ret_count;
352 unsigned int i;
353
354 if (*ret_count == 0) {
355 return;
356 }
357 if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
358 *ret_count = 0;
359 }
360
361 /* ret_list will contain a list of the strings parsed out.
362 We will have at least one string (even if it's just "") */
363 ret_list[0] = algolist;
364 *ret_count = 1;
365 for (i = 0; i < algolist_len; i++) {
366 if (algolist[i] == '\0') {
367 /* someone is trying something strange */
368 *ret_count = 0;
369 return;
370 }
371
372 if (algolist[i] == ',') {
373 if (*ret_count >= max_count) {
374 /* Too many */
375 *ret_count = 0;
376 return;
377 }
378 algolist[i] = '\0';
379 ret_list[*ret_count] = &algolist[i+1];
380 (*ret_count)++;
381 }
382 }
383 }
384
385 /* Return DROPBEAR_SUCCESS if the namelist contains algo,
386 DROPBEAR_FAILURE otherwise. buf position is not incremented. */
387 int buf_has_algo(buffer *buf, const char *algo) {
388 unsigned char* algolist = NULL;
389 unsigned int orig_pos = buf->pos;
390 unsigned int len, remotecount, i;
391 const char *remotenames[MAX_PROPOSED_ALGO];
392 int ret = DROPBEAR_FAILURE;
393
394 algolist = buf_getstring(buf, &len);
395 remotecount = MAX_PROPOSED_ALGO;
396 get_algolist(algolist, len, remotenames, &remotecount);
397 for (i = 0; i < remotecount; i++)
398 {
399 if (strcmp(remotenames[i], algo) == 0) {
400 ret = DROPBEAR_SUCCESS;
401 break;
402 }
403 }
404 if (algolist) {
405 m_free(algolist);
406 }
407 buf_setpos(buf, orig_pos);
408 return ret;
409 }
410
339 /* match the first algorithm in the comma-separated list in buf which is 411 /* match the first algorithm in the comma-separated list in buf which is
340 * also in localalgos[], or return NULL on failure. 412 * also in localalgos[], or return NULL on failure.
341 * (*goodguess) is set to 1 if the preferred client/server algos match, 413 * (*goodguess) is set to 1 if the preferred client/server algos match,
342 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are 414 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
343 * guessed correctly */ 415 * guessed correctly */
344 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], 416 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
345 enum kexguess2_used *kexguess2, int *goodguess) 417 int kexguess2, int *goodguess) {
346 {
347
348 char * algolist = NULL; 418 char * algolist = NULL;
349 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; 419 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
350 unsigned int len; 420 unsigned int len;
351 unsigned int remotecount, localcount, clicount, servcount, i, j; 421 unsigned int remotecount, localcount, clicount, servcount, i, j;
352 algo_type * ret = NULL; 422 algo_type * ret = NULL;
357 } 427 }
358 428
359 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ 429 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
360 algolist = buf_getstring(buf, &len); 430 algolist = buf_getstring(buf, &len);
361 TRACE(("buf_match_algo: %s", algolist)) 431 TRACE(("buf_match_algo: %s", algolist))
362 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { 432 remotecount = MAX_PROPOSED_ALGO;
363 goto out; 433 get_algolist(algolist, len, remotenames, &remotecount);
364 }
365
366 /* remotenames will contain a list of the strings parsed out */
367 /* We will have at least one string (even if it's just "") */
368 remotenames[0] = algolist;
369 remotecount = 1;
370 for (i = 0; i < len; i++) {
371 if (algolist[i] == '\0') {
372 /* someone is trying something strange */
373 goto out;
374 }
375 if (algolist[i] == ',') {
376 algolist[i] = '\0';
377 remotenames[remotecount] = &algolist[i+1];
378 remotecount++;
379 }
380 if (remotecount >= MAX_PROPOSED_ALGO) {
381 break;
382 }
383 }
384 if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
385 for (i = 0; i < remotecount; i++)
386 {
387 if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
388 *kexguess2 = KEXGUESS2_YES;
389 break;
390 }
391 }
392 if (*kexguess2 == KEXGUESS2_LOOK) {
393 *kexguess2 = KEXGUESS2_NO;
394 }
395 }
396 434
397 for (i = 0; localalgos[i].name != NULL; i++) { 435 for (i = 0; localalgos[i].name != NULL; i++) {
398 if (localalgos[i].usable) { 436 if (localalgos[i].usable) {
399 localnames[i] = localalgos[i].name; 437 localnames[i] = localalgos[i].name;
400 } else { 438 } else {
422 /* unusable algos are NULL */ 460 /* unusable algos are NULL */
423 continue; 461 continue;
424 } 462 }
425 if (strcmp(servnames[j], clinames[i]) == 0) { 463 if (strcmp(servnames[j], clinames[i]) == 0) {
426 /* set if it was a good guess */ 464 /* set if it was a good guess */
427 if (goodguess && kexguess2) { 465 if (goodguess != NULL) {
428 if (*kexguess2 == KEXGUESS2_YES) { 466 if (kexguess2) {
429 if (i == 0) { 467 if (i == 0) {
430 *goodguess = 1; 468 *goodguess = 1;
431 } 469 }
432
433 } else { 470 } else {
434 if (i == 0 && j == 0) { 471 if (i == 0 && j == 0) {
435 *goodguess = 1; 472 *goodguess = 1;
436 } 473 }
437 } 474 }