Mercurial > dropbear
comparison common-algo.c @ 1733:d529a52b2f7c coverity coverity
merge coverity from main
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 26 Jun 2020 21:07:34 +0800 |
parents | c2c0f43ff827 |
children | 7c0fcd19e492 |
comparison
equal
deleted
inserted
replaced
1643:b59623a64678 | 1733:d529a52b2f7c |
---|---|
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 "gcm.h" | |
34 #include "chachapoly.h" | |
35 #include "ssh.h" | |
33 | 36 |
34 /* This file (algo.c) organises the ciphers which can be used, and is used to | 37 /* 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*/ | 38 * decide which ciphers/hashes/compression/signing to use during key exchange*/ |
36 | 39 |
37 static int void_cipher(const unsigned char* in, unsigned char* out, | 40 static int void_cipher(const unsigned char* in, unsigned char* out, |
59 #endif | 62 #endif |
60 #if DROPBEAR_AES128 | 63 #if DROPBEAR_AES128 |
61 static const struct dropbear_cipher dropbear_aes128 = | 64 static const struct dropbear_cipher dropbear_aes128 = |
62 {&aes_desc, 16, 16}; | 65 {&aes_desc, 16, 16}; |
63 #endif | 66 #endif |
64 #if DROPBEAR_BLOWFISH | |
65 static const struct dropbear_cipher dropbear_blowfish = | |
66 {&blowfish_desc, 16, 8}; | |
67 #endif | |
68 #if DROPBEAR_TWOFISH256 | 67 #if DROPBEAR_TWOFISH256 |
69 static const struct dropbear_cipher dropbear_twofish256 = | 68 static const struct dropbear_cipher dropbear_twofish256 = |
70 {&twofish_desc, 32, 16}; | 69 {&twofish_desc, 32, 16}; |
71 #endif | 70 #endif |
72 #if DROPBEAR_TWOFISH128 | 71 #if DROPBEAR_TWOFISH128 |
84 | 83 |
85 /* A few void* s are required to silence warnings | 84 /* A few void* s are required to silence warnings |
86 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */ | 85 * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */ |
87 #if DROPBEAR_ENABLE_CBC_MODE | 86 #if DROPBEAR_ENABLE_CBC_MODE |
88 const struct dropbear_cipher_mode dropbear_mode_cbc = | 87 const struct dropbear_cipher_mode dropbear_mode_cbc = |
89 {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt}; | 88 {(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL}; |
90 #endif /* DROPBEAR_ENABLE_CBC_MODE */ | 89 #endif /* DROPBEAR_ENABLE_CBC_MODE */ |
91 | 90 |
92 const struct dropbear_cipher_mode dropbear_mode_none = | 91 const struct dropbear_cipher_mode dropbear_mode_none = |
93 {void_start, void_cipher, void_cipher}; | 92 {void_start, void_cipher, void_cipher, NULL, NULL, NULL}; |
94 | 93 |
95 #if DROPBEAR_ENABLE_CTR_MODE | 94 #if DROPBEAR_ENABLE_CTR_MODE |
96 /* a wrapper to make ctr_start and cbc_start look the same */ | 95 /* a wrapper to make ctr_start and cbc_start look the same */ |
97 static int dropbear_big_endian_ctr_start(int cipher, | 96 static int dropbear_big_endian_ctr_start(int cipher, |
98 const unsigned char *IV, | 97 const unsigned char *IV, |
99 const unsigned char *key, int keylen, | 98 const unsigned char *key, int keylen, |
100 int num_rounds, symmetric_CTR *ctr) { | 99 int num_rounds, symmetric_CTR *ctr) { |
101 return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr); | 100 return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr); |
102 } | 101 } |
103 const struct dropbear_cipher_mode dropbear_mode_ctr = | 102 const struct dropbear_cipher_mode dropbear_mode_ctr = |
104 {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt}; | 103 {(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt, NULL, NULL, NULL}; |
105 #endif /* DROPBEAR_ENABLE_CTR_MODE */ | 104 #endif /* DROPBEAR_ENABLE_CTR_MODE */ |
106 | 105 |
107 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc. | 106 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc. |
108 {&hash_desc, keysize, hashsize} */ | 107 {&hash_desc, keysize, hashsize} */ |
109 | 108 |
135 /* The following map ssh names to internal values. | 134 /* The following map ssh names to internal values. |
136 * The ordering here is important for the client - the first mode | 135 * The ordering here is important for the client - the first mode |
137 * that is also supported by the server will get used. */ | 136 * that is also supported by the server will get used. */ |
138 | 137 |
139 algo_type sshciphers[] = { | 138 algo_type sshciphers[] = { |
139 #if DROPBEAR_CHACHA20POLY1305 | |
140 {"[email protected]", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly}, | |
141 #endif | |
142 | |
143 #if DROPBEAR_ENABLE_GCM_MODE | |
144 #if DROPBEAR_AES128 | |
145 {"[email protected]", 0, &dropbear_aes128, 1, &dropbear_mode_gcm}, | |
146 #endif | |
147 #if DROPBEAR_AES256 | |
148 {"[email protected]", 0, &dropbear_aes256, 1, &dropbear_mode_gcm}, | |
149 #endif | |
150 #endif /* DROPBEAR_ENABLE_GCM_MODE */ | |
151 | |
140 #if DROPBEAR_ENABLE_CTR_MODE | 152 #if DROPBEAR_ENABLE_CTR_MODE |
141 #if DROPBEAR_AES128 | 153 #if DROPBEAR_AES128 |
142 {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr}, | 154 {"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr}, |
143 #endif | 155 #endif |
144 #if DROPBEAR_AES256 | 156 #if DROPBEAR_AES256 |
167 {"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc}, | 179 {"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc}, |
168 #endif | 180 #endif |
169 #if DROPBEAR_TWOFISH128 | 181 #if DROPBEAR_TWOFISH128 |
170 {"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc}, | 182 {"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc}, |
171 #endif | 183 #endif |
184 #endif /* DROPBEAR_ENABLE_CBC_MODE */ | |
185 | |
172 #if DROPBEAR_3DES | 186 #if DROPBEAR_3DES |
187 #if DROPBEAR_ENABLE_CTR_MODE | |
173 {"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr}, | 188 {"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr}, |
174 #endif | 189 #endif |
175 #if DROPBEAR_3DES | 190 #if DROPBEAR_ENABLE_CBC_MODE |
176 {"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc}, | 191 {"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc}, |
177 #endif | 192 #endif |
178 #if DROPBEAR_BLOWFISH | 193 #endif /* DROPBEAR_3DES */ |
179 {"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc}, | 194 |
180 #endif | 195 #if DROPBEAR_ENABLE_CBC_MODE |
181 #endif /* DROPBEAR_ENABLE_CBC_MODE */ | 196 #endif /* DROPBEAR_ENABLE_CBC_MODE */ |
182 {NULL, 0, NULL, 0, NULL} | 197 {NULL, 0, NULL, 0, NULL} |
183 }; | 198 }; |
184 | 199 |
185 algo_type sshhashes[] = { | 200 algo_type sshhashes[] = { |
219 algo_type ssh_nocompress[] = { | 234 algo_type ssh_nocompress[] = { |
220 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL}, | 235 {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL}, |
221 {NULL, 0, NULL, 0, NULL} | 236 {NULL, 0, NULL, 0, NULL} |
222 }; | 237 }; |
223 | 238 |
224 algo_type sshhostkey[] = { | 239 algo_type sigalgs[] = { |
240 #if DROPBEAR_ED25519 | |
241 {"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL}, | |
242 #endif | |
225 #if DROPBEAR_ECDSA | 243 #if DROPBEAR_ECDSA |
226 #if DROPBEAR_ECC_256 | 244 #if DROPBEAR_ECC_256 |
227 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL}, | 245 {"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL}, |
228 #endif | 246 #endif |
229 #if DROPBEAR_ECC_384 | 247 #if DROPBEAR_ECC_384 |
230 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL}, | 248 {"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL}, |
231 #endif | 249 #endif |
232 #if DROPBEAR_ECC_521 | 250 #if DROPBEAR_ECC_521 |
233 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL}, | 251 {"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL}, |
234 #endif | 252 #endif |
235 #endif | 253 #endif |
236 #if DROPBEAR_RSA | 254 #if DROPBEAR_RSA |
237 {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL}, | 255 #if DROPBEAR_RSA_SHA256 |
256 {"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL}, | |
257 #endif | |
258 #if DROPBEAR_RSA_SHA1 | |
259 {"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL}, | |
260 #endif | |
238 #endif | 261 #endif |
239 #if DROPBEAR_DSS | 262 #if DROPBEAR_DSS |
240 {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL}, | 263 {"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL}, |
241 #endif | 264 #endif |
242 {NULL, 0, NULL, 0, NULL} | 265 {NULL, 0, NULL, 0, NULL} |
243 }; | 266 }; |
244 | 267 |
245 #if DROPBEAR_DH_GROUP1 | 268 #if DROPBEAR_DH_GROUP1 |
253 #endif | 276 #endif |
254 #if DROPBEAR_DH_GROUP16 | 277 #if DROPBEAR_DH_GROUP16 |
255 static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc }; | 278 static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc }; |
256 #endif | 279 #endif |
257 | 280 |
258 /* These can't be const since dropbear_ecc_fill_dp() fills out | |
259 ecc_curve at runtime */ | |
260 #if DROPBEAR_ECDH | 281 #if DROPBEAR_ECDH |
261 #if DROPBEAR_ECC_256 | 282 #if DROPBEAR_ECC_256 |
262 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc }; | 283 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc }; |
263 #endif | 284 #endif |
264 #if DROPBEAR_ECC_384 | 285 #if DROPBEAR_ECC_384 |
272 #if DROPBEAR_CURVE25519 | 293 #if DROPBEAR_CURVE25519 |
273 /* Referred to directly */ | 294 /* Referred to directly */ |
274 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc }; | 295 static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc }; |
275 #endif | 296 #endif |
276 | 297 |
298 /* data == NULL for non-kex algorithm identifiers */ | |
277 algo_type sshkex[] = { | 299 algo_type sshkex[] = { |
278 #if DROPBEAR_CURVE25519 | 300 #if DROPBEAR_CURVE25519 |
279 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL}, | 301 {"curve25519-sha256", 0, &kex_curve25519, 1, NULL}, |
280 {"[email protected]", 0, &kex_curve25519, 1, NULL}, | 302 {"[email protected]", 0, &kex_curve25519, 1, NULL}, |
281 #endif | 303 #endif |
301 #endif | 323 #endif |
302 #if DROPBEAR_DH_GROUP16 | 324 #if DROPBEAR_DH_GROUP16 |
303 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL}, | 325 {"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL}, |
304 #endif | 326 #endif |
305 #if DROPBEAR_KEXGUESS2 | 327 #if DROPBEAR_KEXGUESS2 |
306 {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL}, | 328 {KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL}, |
329 #endif | |
330 #if DROPBEAR_EXT_INFO | |
331 #if DROPBEAR_CLIENT | |
332 /* Set unusable by svr_algos_initialise() */ | |
333 {SSH_EXT_INFO_C, 0, NULL, 1, NULL}, | |
334 #endif | |
307 #endif | 335 #endif |
308 {NULL, 0, NULL, 0, NULL} | 336 {NULL, 0, NULL, 0, NULL} |
309 }; | 337 }; |
310 | 338 |
311 /* algolen specifies the length of algo, algos is our local list to match | |
312 * against. | |
313 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE | |
314 * otherwise */ | |
315 int have_algo(const char* algo, size_t algolen, const algo_type algos[]) { | |
316 | |
317 int i; | |
318 | |
319 for (i = 0; algos[i].name != NULL; i++) { | |
320 if (strlen(algos[i].name) == algolen | |
321 && (strncmp(algos[i].name, algo, algolen) == 0)) { | |
322 return DROPBEAR_SUCCESS; | |
323 } | |
324 } | |
325 | |
326 return DROPBEAR_FAILURE; | |
327 } | |
328 | |
329 /* Output a comma separated list of algorithms to a buffer */ | 339 /* Output a comma separated list of algorithms to a buffer */ |
330 void buf_put_algolist(buffer * buf, const algo_type localalgos[]) { | 340 void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall) { |
331 | |
332 unsigned int i, len; | 341 unsigned int i, len; |
333 unsigned int donefirst = 0; | 342 unsigned int donefirst = 0; |
334 buffer *algolist = NULL; | 343 unsigned int startpos; |
335 | 344 |
336 algolist = buf_new(300); | 345 startpos = buf->pos; |
346 /* Placeholder for length */ | |
347 buf_putint(buf, 0); | |
337 for (i = 0; localalgos[i].name != NULL; i++) { | 348 for (i = 0; localalgos[i].name != NULL; i++) { |
338 if (localalgos[i].usable) { | 349 if (localalgos[i].usable || useall) { |
339 if (donefirst) | 350 if (donefirst) { |
340 buf_putbyte(algolist, ','); | 351 buf_putbyte(buf, ','); |
352 } | |
341 donefirst = 1; | 353 donefirst = 1; |
342 len = strlen(localalgos[i].name); | 354 len = strlen(localalgos[i].name); |
343 buf_putbytes(algolist, (const unsigned char *) localalgos[i].name, len); | 355 buf_putbytes(buf, (const unsigned char *) localalgos[i].name, len); |
344 } | 356 } |
345 } | 357 } |
346 buf_putstring(buf, (const char*)algolist->data, algolist->len); | 358 /* Fill out the length */ |
347 TRACE(("algolist add '%*s'", algolist->len, algolist->data)) | 359 len = buf->pos - startpos - 4; |
348 buf_free(algolist); | 360 buf_setpos(buf, startpos); |
361 buf_putint(buf, len); | |
362 TRACE(("algolist add %d '%*s'", len, len, buf_getptr(buf, len))) | |
363 buf_incrwritepos(buf, len); | |
364 } | |
365 | |
366 void buf_put_algolist(buffer * buf, const algo_type localalgos[]) { | |
367 buf_put_algolist_all(buf, localalgos, 0); | |
368 } | |
369 | |
370 /* returns a list of pointers into algolist, of null-terminated names. | |
371 ret_list should be passed in with space for *ret_count elements, | |
372 on return *ret_count has the number of names filled. | |
373 algolist is modified. */ | |
374 static void get_algolist(char* algolist, unsigned int algolist_len, | |
375 const char* *ret_list, unsigned int *ret_count) { | |
376 unsigned int max_count = *ret_count; | |
377 unsigned int i; | |
378 | |
379 if (*ret_count == 0) { | |
380 return; | |
381 } | |
382 if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { | |
383 *ret_count = 0; | |
384 } | |
385 | |
386 /* ret_list will contain a list of the strings parsed out. | |
387 We will have at least one string (even if it's just "") */ | |
388 ret_list[0] = algolist; | |
389 *ret_count = 1; | |
390 for (i = 0; i < algolist_len; i++) { | |
391 if (algolist[i] == '\0') { | |
392 /* someone is trying something strange */ | |
393 *ret_count = 0; | |
394 return; | |
395 } | |
396 | |
397 if (algolist[i] == ',') { | |
398 if (*ret_count >= max_count) { | |
399 /* Too many */ | |
400 *ret_count = 0; | |
401 return; | |
402 } | |
403 algolist[i] = '\0'; | |
404 ret_list[*ret_count] = &algolist[i+1]; | |
405 (*ret_count)++; | |
406 } | |
407 } | |
408 } | |
409 | |
410 /* Return DROPBEAR_SUCCESS if the namelist contains algo, | |
411 DROPBEAR_FAILURE otherwise. buf position is not incremented. */ | |
412 int buf_has_algo(buffer *buf, const char *algo) { | |
413 unsigned char* algolist = NULL; | |
414 unsigned int orig_pos = buf->pos; | |
415 unsigned int len, remotecount, i; | |
416 const char *remotenames[MAX_PROPOSED_ALGO]; | |
417 int ret = DROPBEAR_FAILURE; | |
418 | |
419 algolist = buf_getstring(buf, &len); | |
420 remotecount = MAX_PROPOSED_ALGO; | |
421 get_algolist(algolist, len, remotenames, &remotecount); | |
422 for (i = 0; i < remotecount; i++) | |
423 { | |
424 if (strcmp(remotenames[i], algo) == 0) { | |
425 ret = DROPBEAR_SUCCESS; | |
426 break; | |
427 } | |
428 } | |
429 if (algolist) { | |
430 m_free(algolist); | |
431 } | |
432 buf_setpos(buf, orig_pos); | |
433 return ret; | |
434 } | |
435 | |
436 algo_type * first_usable_algo(algo_type algos[]) { | |
437 int i; | |
438 for (i = 0; algos[i].name != NULL; i++) { | |
439 if (algos[i].usable) { | |
440 return &algos[i]; | |
441 } | |
442 } | |
443 return NULL; | |
349 } | 444 } |
350 | 445 |
351 /* match the first algorithm in the comma-separated list in buf which is | 446 /* match the first algorithm in the comma-separated list in buf which is |
352 * also in localalgos[], or return NULL on failure. | 447 * also in localalgos[], or return NULL on failure. |
353 * (*goodguess) is set to 1 if the preferred client/server algos match, | 448 * (*goodguess) is set to 1 if the preferred client/server algos match, |
354 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are | 449 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are |
355 * guessed correctly */ | 450 * guessed correctly */ |
356 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], | 451 algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], |
357 enum kexguess2_used *kexguess2, int *goodguess) | 452 int kexguess2, int *goodguess) { |
358 { | |
359 | |
360 char * algolist = NULL; | 453 char * algolist = NULL; |
361 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; | 454 const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; |
362 unsigned int len; | 455 unsigned int len; |
363 unsigned int remotecount, localcount, clicount, servcount, i, j; | 456 unsigned int remotecount, localcount, clicount, servcount, i, j; |
364 algo_type * ret = NULL; | 457 algo_type * ret = NULL; |
369 } | 462 } |
370 | 463 |
371 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ | 464 /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ |
372 algolist = buf_getstring(buf, &len); | 465 algolist = buf_getstring(buf, &len); |
373 TRACE(("buf_match_algo: %s", algolist)) | 466 TRACE(("buf_match_algo: %s", algolist)) |
374 if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { | 467 remotecount = MAX_PROPOSED_ALGO; |
375 goto out; | 468 get_algolist(algolist, len, remotenames, &remotecount); |
376 } | |
377 | |
378 /* remotenames will contain a list of the strings parsed out */ | |
379 /* We will have at least one string (even if it's just "") */ | |
380 remotenames[0] = algolist; | |
381 remotecount = 1; | |
382 for (i = 0; i < len; i++) { | |
383 if (algolist[i] == '\0') { | |
384 /* someone is trying something strange */ | |
385 goto out; | |
386 } | |
387 if (algolist[i] == ',') { | |
388 algolist[i] = '\0'; | |
389 remotenames[remotecount] = &algolist[i+1]; | |
390 remotecount++; | |
391 } | |
392 if (remotecount >= MAX_PROPOSED_ALGO) { | |
393 break; | |
394 } | |
395 } | |
396 if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) { | |
397 for (i = 0; i < remotecount; i++) | |
398 { | |
399 if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) { | |
400 *kexguess2 = KEXGUESS2_YES; | |
401 break; | |
402 } | |
403 } | |
404 if (*kexguess2 == KEXGUESS2_LOOK) { | |
405 *kexguess2 = KEXGUESS2_NO; | |
406 } | |
407 } | |
408 | 469 |
409 for (i = 0; localalgos[i].name != NULL; i++) { | 470 for (i = 0; localalgos[i].name != NULL; i++) { |
410 if (localalgos[i].usable) { | 471 if (localalgos[i].usable) { |
411 localnames[i] = localalgos[i].name; | 472 localnames[i] = localalgos[i].name; |
412 } else { | 473 } else { |
434 /* unusable algos are NULL */ | 495 /* unusable algos are NULL */ |
435 continue; | 496 continue; |
436 } | 497 } |
437 if (strcmp(servnames[j], clinames[i]) == 0) { | 498 if (strcmp(servnames[j], clinames[i]) == 0) { |
438 /* set if it was a good guess */ | 499 /* set if it was a good guess */ |
439 if (goodguess && kexguess2) { | 500 if (goodguess != NULL) { |
440 if (*kexguess2 == KEXGUESS2_YES) { | 501 if (kexguess2) { |
441 if (i == 0) { | 502 if (i == 0) { |
442 *goodguess = 1; | 503 *goodguess = 1; |
443 } | 504 } |
444 | |
445 } else { | 505 } else { |
446 if (i == 0 && j == 0) { | 506 if (i == 0 && j == 0) { |
447 *goodguess = 1; | 507 *goodguess = 1; |
448 } | 508 } |
449 } | 509 } |