summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-04-23 15:18:10 +1000
committerDamien Miller <djm@mindrot.org>2013-04-23 15:18:10 +1000
commit91a55f28f35431f9000b95815c343b5a18fda712 (patch)
treedc3339c3a51fd5f78776b0f80220e4c078f52cfb
parent4ce189d9108c62090a0dd5dea973d175328440db (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--ChangeLog3
-rw-r--r--auth.h5
-rw-r--r--auth2-chall.c12
-rw-r--r--auth2.c76
-rw-r--r--monitor.c11
-rw-r--r--sshd_config.518
6 files changed, 91 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 38f6fa8c3..7be6f7bfe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
2320130418 2620130418
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
diff --git a/auth.h b/auth.h
index c6fe84722..7ff59f1ba 100644
--- a/auth.h
+++ b/auth.h
@@ -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
158char *auth2_read_banner(void); 158char *auth2_read_banner(void);
159int auth2_methods_valid(const char *, int); 159int auth2_methods_valid(const char *, int);
160int auth2_update_methods_lists(Authctxt *, const char *); 160int auth2_update_methods_lists(Authctxt *, const char *, const char *);
161int auth2_setup_methods_lists(Authctxt *); 161int auth2_setup_methods_lists(Authctxt *);
162int auth2_method_allowed(Authctxt *, const char *, const char *);
162 163
163void privsep_challenge_enable(void); 164void 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 */
157static int 157static int
158kbdint_next_device(KbdintAuthctxt *kbdintctxt) 158kbdint_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 }
diff --git a/auth2.c b/auth2.c
index e367a1045..e44482164 100644
--- a/auth2.c
+++ b/auth2.c
@@ -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 */
99static Authmethod *authmethod_lookup(Authctxt *, const char *); 99static Authmethod *authmethod_lookup(Authctxt *, const char *);
100static char *authmethods_get(Authctxt *authctxt); 100static char *authmethods_get(Authctxt *authctxt);
101static int method_allowed(Authctxt *, const char *); 101
102static 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 */
106static int list_starts_with(const char *, const char *, const char *);
103 107
104char * 108char *
105auth2_read_banner(void) 109auth2_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 */
390static int 394int
391method_allowed(Authctxt *authctxt, const char *method) 395auth2_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)
457int 465int
458auth2_methods_valid(const char *_methods, int need_enable) 466auth2_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
535static int 545static int
536list_starts_with(const char *methods, const char *method) 546list_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 */
552static int 577static int
553remove_method(char **methods, const char *method) 578remove_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 */
571int 603int
572auth2_update_methods_lists(Authctxt *authctxt, const char *method) 604auth2_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') {
diff --git a/monitor.c b/monitor.c
index 34d7e1805..c0471a176 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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,
180so for this example, it would not be possible to attempt password or 180so for this example, it would not be possible to attempt password or
181keyboard-interactive authentication before public key. 181keyboard-interactive authentication before public key.
182.Pp 182.Pp
183For keyboard interactive authentication it is also possible to
184restrict authentication to a specific device by appending a
185colon followed by the device identifier
186.Dq bsdauth ,
187.Dq pam ,
188or
189.Dq skey ,
190depending on the server configuration.
191For example,
192.Dq keyboard-interactive:bsdauth
193would restrict keyboard interactive authentication to the
194.Dq bsdauth
195device.
196.Pp
183This option is only available for SSH protocol 2 and will yield a fatal 197This option is only available for SSH protocol 2 and will yield a fatal
184error if enabled if protocol 1 is also enabled. 198error if enabled if protocol 1 is also enabled.
185Note that each authentication method listed should also be explicitly enabled 199Note that each authentication method listed should also be explicitly enabled