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 | |
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@
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | auth.h | 5 | ||||
-rw-r--r-- | auth2-chall.c | 12 | ||||
-rw-r--r-- | auth2.c | 76 | ||||
-rw-r--r-- | monitor.c | 11 | ||||
-rw-r--r-- | sshd_config.5 | 18 |
6 files changed, 91 insertions, 34 deletions
@@ -19,6 +19,9 @@ | |||
19 | have included a style (e.g. "root:skey") when checking public key | 19 | have included a style (e.g. "root:skey") when checking public key |
20 | signatures. Fixes public key and hostbased auth when the client specified | 20 | signatures. Fixes public key and hostbased auth when the client specified |
21 | a style; ok markus@ | 21 | a style; ok markus@ |
22 | - markus@cvs.openbsd.org 2013/03/07 19:27:25 | ||
23 | [auth.h auth2-chall.c auth2.c monitor.c sshd_config.5] | ||
24 | add submethod support to AuthenticationMethods; ok and freedback djm@ | ||
22 | 25 | ||
23 | 20130418 | 26 | 20130418 |
24 | - (djm) [config.guess config.sub] Update to last versions before they switch | 27 | - (djm) [config.guess config.sub] Update to last versions before they switch |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.h,v 1.72 2012/12/02 20:34:09 djm Exp $ */ | 1 | /* $OpenBSD: auth.h,v 1.73 2013/03/07 19:27:25 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -157,8 +157,9 @@ void userauth_send_banner(const char *); | |||
157 | 157 | ||
158 | char *auth2_read_banner(void); | 158 | char *auth2_read_banner(void); |
159 | int auth2_methods_valid(const char *, int); | 159 | int auth2_methods_valid(const char *, int); |
160 | int auth2_update_methods_lists(Authctxt *, const char *); | 160 | int auth2_update_methods_lists(Authctxt *, const char *, const char *); |
161 | int auth2_setup_methods_lists(Authctxt *); | 161 | int auth2_setup_methods_lists(Authctxt *); |
162 | int auth2_method_allowed(Authctxt *, const char *, const char *); | ||
162 | 163 | ||
163 | void privsep_challenge_enable(void); | 164 | void privsep_challenge_enable(void); |
164 | 165 | ||
diff --git a/auth2-chall.c b/auth2-chall.c index 6505d4009..ed1acdd3b 100644 --- a/auth2-chall.c +++ b/auth2-chall.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-chall.c,v 1.36 2012/12/03 00:14:06 djm Exp $ */ | 1 | /* $OpenBSD: auth2-chall.c,v 1.37 2013/03/07 19:27:25 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2001 Per Allansson. All rights reserved. | 4 | * Copyright (c) 2001 Per Allansson. All rights reserved. |
@@ -155,7 +155,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt) | |||
155 | } | 155 | } |
156 | /* get next device */ | 156 | /* get next device */ |
157 | static int | 157 | static int |
158 | kbdint_next_device(KbdintAuthctxt *kbdintctxt) | 158 | kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) |
159 | { | 159 | { |
160 | size_t len; | 160 | size_t len; |
161 | char *t; | 161 | char *t; |
@@ -169,9 +169,13 @@ kbdint_next_device(KbdintAuthctxt *kbdintctxt) | |||
169 | 169 | ||
170 | if (len == 0) | 170 | if (len == 0) |
171 | break; | 171 | break; |
172 | for (i = 0; devices[i]; i++) | 172 | for (i = 0; devices[i]; i++) { |
173 | if (!auth2_method_allowed(authctxt, | ||
174 | "keyboard-interactive", devices[i]->name)) | ||
175 | continue; | ||
173 | if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) | 176 | if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) |
174 | kbdintctxt->device = devices[i]; | 177 | kbdintctxt->device = devices[i]; |
178 | } | ||
175 | t = kbdintctxt->devices; | 179 | t = kbdintctxt->devices; |
176 | kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; | 180 | kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; |
177 | xfree(t); | 181 | xfree(t); |
@@ -221,7 +225,7 @@ auth2_challenge_start(Authctxt *authctxt) | |||
221 | debug2("auth2_challenge_start: devices %s", | 225 | debug2("auth2_challenge_start: devices %s", |
222 | kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); | 226 | kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); |
223 | 227 | ||
224 | if (kbdint_next_device(kbdintctxt) == 0) { | 228 | if (kbdint_next_device(authctxt, kbdintctxt) == 0) { |
225 | auth2_challenge_stop(authctxt); | 229 | auth2_challenge_stop(authctxt); |
226 | return 0; | 230 | return 0; |
227 | } | 231 | } |
@@ -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') { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.121 2013/03/07 00:19:59 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.122 2013/03/07 19:27:25 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -392,7 +392,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
392 | "with SSH protocol 1"); | 392 | "with SSH protocol 1"); |
393 | if (authenticated && | 393 | if (authenticated && |
394 | !auth2_update_methods_lists(authctxt, | 394 | !auth2_update_methods_lists(authctxt, |
395 | auth_method)) { | 395 | auth_method, auth_submethod)) { |
396 | debug3("%s: method %s: partial", __func__, | 396 | debug3("%s: method %s: partial", __func__, |
397 | auth_method); | 397 | auth_method); |
398 | authenticated = 0; | 398 | authenticated = 0; |
@@ -949,9 +949,10 @@ mm_answer_bsdauthrespond(int sock, Buffer *m) | |||
949 | debug3("%s: sending authenticated: %d", __func__, authok); | 949 | debug3("%s: sending authenticated: %d", __func__, authok); |
950 | mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); | 950 | mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); |
951 | 951 | ||
952 | if (compat20) | 952 | if (compat20) { |
953 | auth_method = "keyboard-interactive"; /* XXX auth_submethod */ | 953 | auth_method = "keyboard-interactive"; |
954 | else | 954 | auth_submethod = "bsdauth"; |
955 | } else | ||
955 | auth_method = "bsdauth"; | 956 | auth_method = "bsdauth"; |
956 | 957 | ||
957 | return (authok != 0); | 958 | return (authok != 0); |
diff --git a/sshd_config.5 b/sshd_config.5 index cfa480697..4fe3c55b6 100644 --- a/sshd_config.5 +++ b/sshd_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd_config.5,v 1.156 2013/02/06 00:20:42 dtucker Exp $ | 36 | .\" $OpenBSD: sshd_config.5,v 1.157 2013/03/07 19:27:25 markus Exp $ |
37 | .Dd $Mdocdate: February 6 2013 $ | 37 | .Dd $Mdocdate: March 7 2013 $ |
38 | .Dt SSHD_CONFIG 5 | 38 | .Dt SSHD_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -180,6 +180,20 @@ Only methods that are next in one or more lists are offered at each stage, | |||
180 | so for this example, it would not be possible to attempt password or | 180 | so for this example, it would not be possible to attempt password or |
181 | keyboard-interactive authentication before public key. | 181 | keyboard-interactive authentication before public key. |
182 | .Pp | 182 | .Pp |
183 | For keyboard interactive authentication it is also possible to | ||
184 | restrict authentication to a specific device by appending a | ||
185 | colon followed by the device identifier | ||
186 | .Dq bsdauth , | ||
187 | .Dq pam , | ||
188 | or | ||
189 | .Dq skey , | ||
190 | depending on the server configuration. | ||
191 | For example, | ||
192 | .Dq keyboard-interactive:bsdauth | ||
193 | would restrict keyboard interactive authentication to the | ||
194 | .Dq bsdauth | ||
195 | device. | ||
196 | .Pp | ||
183 | This option is only available for SSH protocol 2 and will yield a fatal | 197 | This option is only available for SSH protocol 2 and will yield a fatal |
184 | error if enabled if protocol 1 is also enabled. | 198 | error if enabled if protocol 1 is also enabled. |
185 | Note that each authentication method listed should also be explicitly enabled | 199 | Note that each authentication method listed should also be explicitly enabled |