diff options
author | Colin Watson <cjwatson@debian.org> | 2013-09-14 15:43:03 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2013-09-14 15:43:03 +0100 |
commit | 8faf8c84430cf3c19705b1d9f8889d256e7fd1fd (patch) | |
tree | e6cb74192adb00fda5e4d1457547851d7e0d86af /auth2.c | |
parent | 328b60656f29db6306994d7498dede386ec2d1c3 (diff) | |
parent | c41345ad7ee5a22689e2c009595e85fa27b4b39a (diff) |
merge 6.3p1
Diffstat (limited to 'auth2.c')
-rw-r--r-- | auth2.c | 93 |
1 files changed, 63 insertions, 30 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2.c,v 1.126 2012/12/02 20:34:09 djm Exp $ */ | 1 | /* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -100,8 +100,12 @@ static void input_userauth_request(int, u_int32_t, void *); | |||
100 | /* helper */ | 100 | /* helper */ |
101 | static Authmethod *authmethod_lookup(Authctxt *, const char *); | 101 | static Authmethod *authmethod_lookup(Authctxt *, const char *); |
102 | static char *authmethods_get(Authctxt *authctxt); | 102 | static char *authmethods_get(Authctxt *authctxt); |
103 | static int method_allowed(Authctxt *, const char *); | 103 | |
104 | static int list_starts_with(const char *, const char *); | 104 | #define MATCH_NONE 0 /* method or submethod mismatch */ |
105 | #define MATCH_METHOD 1 /* method matches (no submethod specified) */ | ||
106 | #define MATCH_BOTH 2 /* method and submethod match */ | ||
107 | #define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */ | ||
108 | static int list_starts_with(const char *, const char *, const char *); | ||
105 | 109 | ||
106 | char * | 110 | char * |
107 | auth2_read_banner(void) | 111 | auth2_read_banner(void) |
@@ -128,7 +132,7 @@ auth2_read_banner(void) | |||
128 | close(fd); | 132 | close(fd); |
129 | 133 | ||
130 | if (n != len) { | 134 | if (n != len) { |
131 | xfree(banner); | 135 | free(banner); |
132 | return (NULL); | 136 | return (NULL); |
133 | } | 137 | } |
134 | banner[n] = '\0'; | 138 | banner[n] = '\0'; |
@@ -164,8 +168,7 @@ userauth_banner(void) | |||
164 | userauth_send_banner(banner); | 168 | userauth_send_banner(banner); |
165 | 169 | ||
166 | done: | 170 | done: |
167 | if (banner) | 171 | free(banner); |
168 | xfree(banner); | ||
169 | } | 172 | } |
170 | 173 | ||
171 | /* | 174 | /* |
@@ -210,7 +213,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt) | |||
210 | debug("bad service request %s", service); | 213 | debug("bad service request %s", service); |
211 | packet_disconnect("bad service request %s", service); | 214 | packet_disconnect("bad service request %s", service); |
212 | } | 215 | } |
213 | xfree(service); | 216 | free(service); |
214 | } | 217 | } |
215 | 218 | ||
216 | /*ARGSUSED*/ | 219 | /*ARGSUSED*/ |
@@ -290,9 +293,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | |||
290 | } | 293 | } |
291 | userauth_finish(authctxt, authenticated, method, NULL); | 294 | userauth_finish(authctxt, authenticated, method, NULL); |
292 | 295 | ||
293 | xfree(service); | 296 | free(service); |
294 | xfree(user); | 297 | free(user); |
295 | xfree(method); | 298 | free(method); |
296 | } | 299 | } |
297 | 300 | ||
298 | void | 301 | void |
@@ -318,14 +321,14 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
318 | } | 321 | } |
319 | 322 | ||
320 | if (authenticated && options.num_auth_methods != 0) { | 323 | if (authenticated && options.num_auth_methods != 0) { |
321 | if (!auth2_update_methods_lists(authctxt, method)) { | 324 | if (!auth2_update_methods_lists(authctxt, method, submethod)) { |
322 | authenticated = 0; | 325 | authenticated = 0; |
323 | partial = 1; | 326 | partial = 1; |
324 | } | 327 | } |
325 | } | 328 | } |
326 | 329 | ||
327 | /* Log before sending the reply */ | 330 | /* Log before sending the reply */ |
328 | auth_log(authctxt, authenticated, partial, method, submethod, " ssh2"); | 331 | auth_log(authctxt, authenticated, partial, method, submethod); |
329 | 332 | ||
330 | if (authctxt->postponed) | 333 | if (authctxt->postponed) |
331 | return; | 334 | return; |
@@ -380,7 +383,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
380 | packet_put_char(partial); | 383 | packet_put_char(partial); |
381 | packet_send(); | 384 | packet_send(); |
382 | packet_write_wait(); | 385 | packet_write_wait(); |
383 | xfree(methods); | 386 | free(methods); |
384 | } | 387 | } |
385 | } | 388 | } |
386 | 389 | ||
@@ -389,8 +392,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
389 | * methods list. Returns 1 if allowed, or no methods lists configured. | 392 | * methods list. Returns 1 if allowed, or no methods lists configured. |
390 | * 0 otherwise. | 393 | * 0 otherwise. |
391 | */ | 394 | */ |
392 | static int | 395 | int |
393 | method_allowed(Authctxt *authctxt, const char *method) | 396 | auth2_method_allowed(Authctxt *authctxt, const char *method, |
397 | const char *submethod) | ||
394 | { | 398 | { |
395 | u_int i; | 399 | u_int i; |
396 | 400 | ||
@@ -401,7 +405,8 @@ method_allowed(Authctxt *authctxt, const char *method) | |||
401 | if (options.num_auth_methods == 0) | 405 | if (options.num_auth_methods == 0) |
402 | return 1; | 406 | return 1; |
403 | for (i = 0; i < authctxt->num_auth_methods; i++) { | 407 | for (i = 0; i < authctxt->num_auth_methods; i++) { |
404 | if (list_starts_with(authctxt->auth_methods[i], method)) | 408 | if (list_starts_with(authctxt->auth_methods[i], method, |
409 | submethod) != MATCH_NONE) | ||
405 | return 1; | 410 | return 1; |
406 | } | 411 | } |
407 | return 0; | 412 | return 0; |
@@ -421,7 +426,8 @@ authmethods_get(Authctxt *authctxt) | |||
421 | if (authmethods[i]->enabled == NULL || | 426 | if (authmethods[i]->enabled == NULL || |
422 | *(authmethods[i]->enabled) == 0) | 427 | *(authmethods[i]->enabled) == 0) |
423 | continue; | 428 | continue; |
424 | if (!method_allowed(authctxt, authmethods[i]->name)) | 429 | if (!auth2_method_allowed(authctxt, authmethods[i]->name, |
430 | NULL)) | ||
425 | continue; | 431 | continue; |
426 | if (buffer_len(&b) > 0) | 432 | if (buffer_len(&b) > 0) |
427 | buffer_append(&b, ",", 1); | 433 | buffer_append(&b, ",", 1); |
@@ -444,7 +450,8 @@ authmethod_lookup(Authctxt *authctxt, const char *name) | |||
444 | if (authmethods[i]->enabled != NULL && | 450 | if (authmethods[i]->enabled != NULL && |
445 | *(authmethods[i]->enabled) != 0 && | 451 | *(authmethods[i]->enabled) != 0 && |
446 | strcmp(name, authmethods[i]->name) == 0 && | 452 | strcmp(name, authmethods[i]->name) == 0 && |
447 | method_allowed(authctxt, authmethods[i]->name)) | 453 | auth2_method_allowed(authctxt, |
454 | authmethods[i]->name, NULL)) | ||
448 | return authmethods[i]; | 455 | return authmethods[i]; |
449 | debug2("Unrecognized authentication method name: %s", | 456 | debug2("Unrecognized authentication method name: %s", |
450 | name ? name : "NULL"); | 457 | name ? name : "NULL"); |
@@ -459,7 +466,7 @@ authmethod_lookup(Authctxt *authctxt, const char *name) | |||
459 | int | 466 | int |
460 | auth2_methods_valid(const char *_methods, int need_enable) | 467 | auth2_methods_valid(const char *_methods, int need_enable) |
461 | { | 468 | { |
462 | char *methods, *omethods, *method; | 469 | char *methods, *omethods, *method, *p; |
463 | u_int i, found; | 470 | u_int i, found; |
464 | int ret = -1; | 471 | int ret = -1; |
465 | 472 | ||
@@ -470,6 +477,8 @@ auth2_methods_valid(const char *_methods, int need_enable) | |||
470 | omethods = methods = xstrdup(_methods); | 477 | omethods = methods = xstrdup(_methods); |
471 | while ((method = strsep(&methods, ",")) != NULL) { | 478 | while ((method = strsep(&methods, ",")) != NULL) { |
472 | for (found = i = 0; !found && authmethods[i] != NULL; i++) { | 479 | for (found = i = 0; !found && authmethods[i] != NULL; i++) { |
480 | if ((p = strchr(method, ':')) != NULL) | ||
481 | *p = '\0'; | ||
473 | if (strcmp(method, authmethods[i]->name) != 0) | 482 | if (strcmp(method, authmethods[i]->name) != 0) |
474 | continue; | 483 | continue; |
475 | if (need_enable) { | 484 | if (need_enable) { |
@@ -535,15 +544,30 @@ auth2_setup_methods_lists(Authctxt *authctxt) | |||
535 | } | 544 | } |
536 | 545 | ||
537 | static int | 546 | static int |
538 | list_starts_with(const char *methods, const char *method) | 547 | list_starts_with(const char *methods, const char *method, |
548 | const char *submethod) | ||
539 | { | 549 | { |
540 | size_t l = strlen(method); | 550 | size_t l = strlen(method); |
551 | int match; | ||
552 | const char *p; | ||
541 | 553 | ||
542 | if (strncmp(methods, method, l) != 0) | 554 | if (strncmp(methods, method, l) != 0) |
543 | return 0; | 555 | return MATCH_NONE; |
544 | if (methods[l] != ',' && methods[l] != '\0') | 556 | p = methods + l; |
545 | return 0; | 557 | match = MATCH_METHOD; |
546 | return 1; | 558 | if (*p == ':') { |
559 | if (!submethod) | ||
560 | return MATCH_PARTIAL; | ||
561 | l = strlen(submethod); | ||
562 | p += 1; | ||
563 | if (strncmp(submethod, p, l)) | ||
564 | return MATCH_NONE; | ||
565 | p += l; | ||
566 | match = MATCH_BOTH; | ||
567 | } | ||
568 | if (*p != ',' && *p != '\0') | ||
569 | return MATCH_NONE; | ||
570 | return match; | ||
547 | } | 571 | } |
548 | 572 | ||
549 | /* | 573 | /* |
@@ -552,14 +576,21 @@ list_starts_with(const char *methods, const char *method) | |||
552 | * if it did. | 576 | * if it did. |
553 | */ | 577 | */ |
554 | static int | 578 | static int |
555 | remove_method(char **methods, const char *method) | 579 | remove_method(char **methods, const char *method, const char *submethod) |
556 | { | 580 | { |
557 | char *omethods = *methods; | 581 | char *omethods = *methods, *p; |
558 | size_t l = strlen(method); | 582 | size_t l = strlen(method); |
583 | int match; | ||
559 | 584 | ||
560 | if (!list_starts_with(omethods, method)) | 585 | match = list_starts_with(omethods, method, submethod); |
586 | if (match != MATCH_METHOD && match != MATCH_BOTH) | ||
561 | return 0; | 587 | return 0; |
562 | *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0)); | 588 | p = omethods + l; |
589 | if (submethod && match == MATCH_BOTH) | ||
590 | p += 1 + strlen(submethod); /* include colon */ | ||
591 | if (*p == ',') | ||
592 | p++; | ||
593 | *methods = xstrdup(p); | ||
563 | free(omethods); | 594 | free(omethods); |
564 | return 1; | 595 | return 1; |
565 | } | 596 | } |
@@ -571,13 +602,15 @@ remove_method(char **methods, const char *method) | |||
571 | * Returns 1 if the method completed any authentication list or 0 otherwise. | 602 | * Returns 1 if the method completed any authentication list or 0 otherwise. |
572 | */ | 603 | */ |
573 | int | 604 | int |
574 | auth2_update_methods_lists(Authctxt *authctxt, const char *method) | 605 | auth2_update_methods_lists(Authctxt *authctxt, const char *method, |
606 | const char *submethod) | ||
575 | { | 607 | { |
576 | u_int i, found = 0; | 608 | u_int i, found = 0; |
577 | 609 | ||
578 | debug3("%s: updating methods list after \"%s\"", __func__, method); | 610 | debug3("%s: updating methods list after \"%s\"", __func__, method); |
579 | for (i = 0; i < authctxt->num_auth_methods; i++) { | 611 | for (i = 0; i < authctxt->num_auth_methods; i++) { |
580 | if (!remove_method(&(authctxt->auth_methods[i]), method)) | 612 | if (!remove_method(&(authctxt->auth_methods[i]), method, |
613 | submethod)) | ||
581 | continue; | 614 | continue; |
582 | found = 1; | 615 | found = 1; |
583 | if (*authctxt->auth_methods[i] == '\0') { | 616 | if (*authctxt->auth_methods[i] == '\0') { |