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