diff options
author | Damien Miller <djm@mindrot.org> | 2013-04-23 15:18:10 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2013-04-23 15:18:10 +1000 |
commit | 91a55f28f35431f9000b95815c343b5a18fda712 (patch) | |
tree | dc3339c3a51fd5f78776b0f80220e4c078f52cfb /auth2.c | |
parent | 4ce189d9108c62090a0dd5dea973d175328440db (diff) |
- markus@cvs.openbsd.org 2013/03/07 19:27:25
[auth.h auth2-chall.c auth2.c monitor.c sshd_config.5]
add submethod support to AuthenticationMethods; ok and freedback djm@
Diffstat (limited to 'auth2.c')
-rw-r--r-- | auth2.c | 76 |
1 files changed, 55 insertions, 21 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.127 2013/03/07 19:27:25 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -98,8 +98,12 @@ static void input_userauth_request(int, u_int32_t, void *); | |||
98 | /* helper */ | 98 | /* helper */ |
99 | static Authmethod *authmethod_lookup(Authctxt *, const char *); | 99 | static Authmethod *authmethod_lookup(Authctxt *, const char *); |
100 | static char *authmethods_get(Authctxt *authctxt); | 100 | static char *authmethods_get(Authctxt *authctxt); |
101 | static int method_allowed(Authctxt *, const char *); | 101 | |
102 | static int list_starts_with(const char *, const char *); | 102 | #define MATCH_NONE 0 /* method or submethod mismatch */ |
103 | #define MATCH_METHOD 1 /* method matches (no submethod specified) */ | ||
104 | #define MATCH_BOTH 2 /* method and submethod match */ | ||
105 | #define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */ | ||
106 | static int list_starts_with(const char *, const char *, const char *); | ||
103 | 107 | ||
104 | char * | 108 | char * |
105 | auth2_read_banner(void) | 109 | auth2_read_banner(void) |
@@ -316,7 +320,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
316 | } | 320 | } |
317 | 321 | ||
318 | if (authenticated && options.num_auth_methods != 0) { | 322 | if (authenticated && options.num_auth_methods != 0) { |
319 | if (!auth2_update_methods_lists(authctxt, method)) { | 323 | if (!auth2_update_methods_lists(authctxt, method, submethod)) { |
320 | authenticated = 0; | 324 | authenticated = 0; |
321 | partial = 1; | 325 | partial = 1; |
322 | } | 326 | } |
@@ -387,8 +391,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
387 | * methods list. Returns 1 if allowed, or no methods lists configured. | 391 | * methods list. Returns 1 if allowed, or no methods lists configured. |
388 | * 0 otherwise. | 392 | * 0 otherwise. |
389 | */ | 393 | */ |
390 | static int | 394 | int |
391 | method_allowed(Authctxt *authctxt, const char *method) | 395 | auth2_method_allowed(Authctxt *authctxt, const char *method, |
396 | const char *submethod) | ||
392 | { | 397 | { |
393 | u_int i; | 398 | u_int i; |
394 | 399 | ||
@@ -399,7 +404,8 @@ method_allowed(Authctxt *authctxt, const char *method) | |||
399 | if (options.num_auth_methods == 0) | 404 | if (options.num_auth_methods == 0) |
400 | return 1; | 405 | return 1; |
401 | for (i = 0; i < authctxt->num_auth_methods; i++) { | 406 | for (i = 0; i < authctxt->num_auth_methods; i++) { |
402 | if (list_starts_with(authctxt->auth_methods[i], method)) | 407 | if (list_starts_with(authctxt->auth_methods[i], method, |
408 | submethod) != MATCH_NONE) | ||
403 | return 1; | 409 | return 1; |
404 | } | 410 | } |
405 | return 0; | 411 | return 0; |
@@ -419,7 +425,8 @@ authmethods_get(Authctxt *authctxt) | |||
419 | if (authmethods[i]->enabled == NULL || | 425 | if (authmethods[i]->enabled == NULL || |
420 | *(authmethods[i]->enabled) == 0) | 426 | *(authmethods[i]->enabled) == 0) |
421 | continue; | 427 | continue; |
422 | if (!method_allowed(authctxt, authmethods[i]->name)) | 428 | if (!auth2_method_allowed(authctxt, authmethods[i]->name, |
429 | NULL)) | ||
423 | continue; | 430 | continue; |
424 | if (buffer_len(&b) > 0) | 431 | if (buffer_len(&b) > 0) |
425 | buffer_append(&b, ",", 1); | 432 | buffer_append(&b, ",", 1); |
@@ -442,7 +449,8 @@ authmethod_lookup(Authctxt *authctxt, const char *name) | |||
442 | if (authmethods[i]->enabled != NULL && | 449 | if (authmethods[i]->enabled != NULL && |
443 | *(authmethods[i]->enabled) != 0 && | 450 | *(authmethods[i]->enabled) != 0 && |
444 | strcmp(name, authmethods[i]->name) == 0 && | 451 | strcmp(name, authmethods[i]->name) == 0 && |
445 | method_allowed(authctxt, authmethods[i]->name)) | 452 | auth2_method_allowed(authctxt, |
453 | authmethods[i]->name, NULL)) | ||
446 | return authmethods[i]; | 454 | return authmethods[i]; |
447 | debug2("Unrecognized authentication method name: %s", | 455 | debug2("Unrecognized authentication method name: %s", |
448 | name ? name : "NULL"); | 456 | name ? name : "NULL"); |
@@ -457,7 +465,7 @@ authmethod_lookup(Authctxt *authctxt, const char *name) | |||
457 | int | 465 | int |
458 | auth2_methods_valid(const char *_methods, int need_enable) | 466 | auth2_methods_valid(const char *_methods, int need_enable) |
459 | { | 467 | { |
460 | char *methods, *omethods, *method; | 468 | char *methods, *omethods, *method, *p; |
461 | u_int i, found; | 469 | u_int i, found; |
462 | int ret = -1; | 470 | int ret = -1; |
463 | 471 | ||
@@ -468,6 +476,8 @@ auth2_methods_valid(const char *_methods, int need_enable) | |||
468 | omethods = methods = xstrdup(_methods); | 476 | omethods = methods = xstrdup(_methods); |
469 | while ((method = strsep(&methods, ",")) != NULL) { | 477 | while ((method = strsep(&methods, ",")) != NULL) { |
470 | for (found = i = 0; !found && authmethods[i] != NULL; i++) { | 478 | for (found = i = 0; !found && authmethods[i] != NULL; i++) { |
479 | if ((p = strchr(method, ':')) != NULL) | ||
480 | *p = '\0'; | ||
471 | if (strcmp(method, authmethods[i]->name) != 0) | 481 | if (strcmp(method, authmethods[i]->name) != 0) |
472 | continue; | 482 | continue; |
473 | if (need_enable) { | 483 | if (need_enable) { |
@@ -533,15 +543,30 @@ auth2_setup_methods_lists(Authctxt *authctxt) | |||
533 | } | 543 | } |
534 | 544 | ||
535 | static int | 545 | static int |
536 | list_starts_with(const char *methods, const char *method) | 546 | list_starts_with(const char *methods, const char *method, |
547 | const char *submethod) | ||
537 | { | 548 | { |
538 | size_t l = strlen(method); | 549 | size_t l = strlen(method); |
550 | int match; | ||
551 | const char *p; | ||
539 | 552 | ||
540 | if (strncmp(methods, method, l) != 0) | 553 | if (strncmp(methods, method, l) != 0) |
541 | return 0; | 554 | return MATCH_NONE; |
542 | if (methods[l] != ',' && methods[l] != '\0') | 555 | p = methods + l; |
543 | return 0; | 556 | match = MATCH_METHOD; |
544 | return 1; | 557 | if (*p == ':') { |
558 | if (!submethod) | ||
559 | return MATCH_PARTIAL; | ||
560 | l = strlen(submethod); | ||
561 | p += 1; | ||
562 | if (strncmp(submethod, p, l)) | ||
563 | return MATCH_NONE; | ||
564 | p += l; | ||
565 | match = MATCH_BOTH; | ||
566 | } | ||
567 | if (*p != ',' && *p != '\0') | ||
568 | return MATCH_NONE; | ||
569 | return match; | ||
545 | } | 570 | } |
546 | 571 | ||
547 | /* | 572 | /* |
@@ -550,14 +575,21 @@ list_starts_with(const char *methods, const char *method) | |||
550 | * if it did. | 575 | * if it did. |
551 | */ | 576 | */ |
552 | static int | 577 | static int |
553 | remove_method(char **methods, const char *method) | 578 | remove_method(char **methods, const char *method, const char *submethod) |
554 | { | 579 | { |
555 | char *omethods = *methods; | 580 | char *omethods = *methods, *p; |
556 | size_t l = strlen(method); | 581 | size_t l = strlen(method); |
582 | int match; | ||
557 | 583 | ||
558 | if (!list_starts_with(omethods, method)) | 584 | match = list_starts_with(omethods, method, submethod); |
585 | if (match != MATCH_METHOD && match != MATCH_BOTH) | ||
559 | return 0; | 586 | return 0; |
560 | *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0)); | 587 | p = omethods + l; |
588 | if (submethod && match == MATCH_BOTH) | ||
589 | p += 1 + strlen(submethod); /* include colon */ | ||
590 | if (*p == ',') | ||
591 | p++; | ||
592 | *methods = xstrdup(p); | ||
561 | free(omethods); | 593 | free(omethods); |
562 | return 1; | 594 | return 1; |
563 | } | 595 | } |
@@ -569,13 +601,15 @@ remove_method(char **methods, const char *method) | |||
569 | * Returns 1 if the method completed any authentication list or 0 otherwise. | 601 | * Returns 1 if the method completed any authentication list or 0 otherwise. |
570 | */ | 602 | */ |
571 | int | 603 | int |
572 | auth2_update_methods_lists(Authctxt *authctxt, const char *method) | 604 | auth2_update_methods_lists(Authctxt *authctxt, const char *method, |
605 | const char *submethod) | ||
573 | { | 606 | { |
574 | u_int i, found = 0; | 607 | u_int i, found = 0; |
575 | 608 | ||
576 | debug3("%s: updating methods list after \"%s\"", __func__, method); | 609 | debug3("%s: updating methods list after \"%s\"", __func__, method); |
577 | for (i = 0; i < authctxt->num_auth_methods; i++) { | 610 | for (i = 0; i < authctxt->num_auth_methods; i++) { |
578 | if (!remove_method(&(authctxt->auth_methods[i]), method)) | 611 | if (!remove_method(&(authctxt->auth_methods[i]), method, |
612 | submethod)) | ||
579 | continue; | 613 | continue; |
580 | found = 1; | 614 | found = 1; |
581 | if (*authctxt->auth_methods[i] == '\0') { | 615 | if (*authctxt->auth_methods[i] == '\0') { |