diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2013-03-07 19:27:26 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2013-03-07 19:27:26 +0000 |
commit | 10774fbe8e5e2978d40fade9e10e76706bf57af3 (patch) | |
tree | 2a9f682bd611edebb3935003b3c0401ec77f7ef7 | |
parent | 496f21ea5bc3456f11899d70855500e975747265 (diff) |
add submethod support to AuthenticationMethods; ok and freedback djm@
-rw-r--r-- | usr.bin/ssh/auth.h | 5 | ||||
-rw-r--r-- | usr.bin/ssh/auth2-chall.c | 12 | ||||
-rw-r--r-- | usr.bin/ssh/auth2.c | 76 | ||||
-rw-r--r-- | usr.bin/ssh/monitor.c | 11 | ||||
-rw-r--r-- | usr.bin/ssh/sshd_config.5 | 18 |
5 files changed, 88 insertions, 34 deletions
diff --git a/usr.bin/ssh/auth.h b/usr.bin/ssh/auth.h index 962bfe4e9ea..d110f84de8e 100644 --- a/usr.bin/ssh/auth.h +++ b/usr.bin/ssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.72 2012/12/02 20:34:09 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.73 2013/03/07 19:27:25 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -134,8 +134,9 @@ int auth_root_allowed(const char *); char *auth2_read_banner(void); int auth2_methods_valid(const char *, int); -int auth2_update_methods_lists(Authctxt *, const char *); +int auth2_update_methods_lists(Authctxt *, const char *, const char *); int auth2_setup_methods_lists(Authctxt *); +int auth2_method_allowed(Authctxt *, const char *, const char *); void privsep_challenge_enable(void); diff --git a/usr.bin/ssh/auth2-chall.c b/usr.bin/ssh/auth2-chall.c index 6111f45d86c..2cfba12ae16 100644 --- a/usr.bin/ssh/auth2-chall.c +++ b/usr.bin/ssh/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.36 2012/12/03 00:14:06 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.37 2013/03/07 19:27:25 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -110,7 +110,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt) } /* get next device */ static int -kbdint_next_device(KbdintAuthctxt *kbdintctxt) +kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) { size_t len; char *t; @@ -124,9 +124,13 @@ kbdint_next_device(KbdintAuthctxt *kbdintctxt) if (len == 0) break; - for (i = 0; devices[i]; i++) + for (i = 0; devices[i]; i++) { + if (!auth2_method_allowed(authctxt, + "keyboard-interactive", devices[i]->name)) + continue; if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) kbdintctxt->device = devices[i]; + } t = kbdintctxt->devices; kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; xfree(t); @@ -176,7 +180,7 @@ auth2_challenge_start(Authctxt *authctxt) debug2("auth2_challenge_start: devices %s", kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); - if (kbdint_next_device(kbdintctxt) == 0) { + if (kbdint_next_device(authctxt, kbdintctxt) == 0) { auth2_challenge_stop(authctxt); return 0; } diff --git a/usr.bin/ssh/auth2.c b/usr.bin/ssh/auth2.c index 8b157b4bed9..4301ecdc84f 100644 --- a/usr.bin/ssh/auth2.c +++ b/usr.bin/ssh/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.126 2012/12/02 20:34:09 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.127 2013/03/07 19:27:25 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -94,8 +94,12 @@ static void input_userauth_request(int, u_int32_t, void *); /* helper */ static Authmethod *authmethod_lookup(Authctxt *, const char *); static char *authmethods_get(Authctxt *authctxt); -static int method_allowed(Authctxt *, const char *); -static int list_starts_with(const char *, const char *); + +#define MATCH_NONE 0 /* method or submethod mismatch */ +#define MATCH_METHOD 1 /* method matches (no submethod specified) */ +#define MATCH_BOTH 2 /* method and submethod match */ +#define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */ +static int list_starts_with(const char *, const char *, const char *); char * auth2_read_banner(void) @@ -292,7 +296,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, authenticated = 0; if (authenticated && options.num_auth_methods != 0) { - if (!auth2_update_methods_lists(authctxt, method)) { + if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } @@ -336,8 +340,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, * methods list. Returns 1 if allowed, or no methods lists configured. * 0 otherwise. */ -static int -method_allowed(Authctxt *authctxt, const char *method) +int +auth2_method_allowed(Authctxt *authctxt, const char *method, + const char *submethod) { u_int i; @@ -348,7 +353,8 @@ method_allowed(Authctxt *authctxt, const char *method) if (options.num_auth_methods == 0) return 1; for (i = 0; i < authctxt->num_auth_methods; i++) { - if (list_starts_with(authctxt->auth_methods[i], method)) + if (list_starts_with(authctxt->auth_methods[i], method, + submethod) != MATCH_NONE) return 1; } return 0; @@ -368,7 +374,8 @@ authmethods_get(Authctxt *authctxt) if (authmethods[i]->enabled == NULL || *(authmethods[i]->enabled) == 0) continue; - if (!method_allowed(authctxt, authmethods[i]->name)) + if (!auth2_method_allowed(authctxt, authmethods[i]->name, + NULL)) continue; if (buffer_len(&b) > 0) buffer_append(&b, ",", 1); @@ -391,7 +398,8 @@ authmethod_lookup(Authctxt *authctxt, const char *name) if (authmethods[i]->enabled != NULL && *(authmethods[i]->enabled) != 0 && strcmp(name, authmethods[i]->name) == 0 && - method_allowed(authctxt, authmethods[i]->name)) + auth2_method_allowed(authctxt, + authmethods[i]->name, NULL)) return authmethods[i]; debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); @@ -406,7 +414,7 @@ authmethod_lookup(Authctxt *authctxt, const char *name) int auth2_methods_valid(const char *_methods, int need_enable) { - char *methods, *omethods, *method; + char *methods, *omethods, *method, *p; u_int i, found; int ret = -1; @@ -417,6 +425,8 @@ auth2_methods_valid(const char *_methods, int need_enable) omethods = methods = xstrdup(_methods); while ((method = strsep(&methods, ",")) != NULL) { for (found = i = 0; !found && authmethods[i] != NULL; i++) { + if ((p = strchr(method, ':')) != NULL) + *p = '\0'; if (strcmp(method, authmethods[i]->name) != 0) continue; if (need_enable) { @@ -482,15 +492,30 @@ auth2_setup_methods_lists(Authctxt *authctxt) } static int -list_starts_with(const char *methods, const char *method) +list_starts_with(const char *methods, const char *method, + const char *submethod) { size_t l = strlen(method); + int match; + const char *p; if (strncmp(methods, method, l) != 0) - return 0; - if (methods[l] != ',' && methods[l] != '\0') - return 0; - return 1; + return MATCH_NONE; + p = methods + l; + match = MATCH_METHOD; + if (*p == ':') { + if (!submethod) + return MATCH_PARTIAL; + l = strlen(submethod); + p += 1; + if (strncmp(submethod, p, l)) + return MATCH_NONE; + p += l; + match = MATCH_BOTH; + } + if (*p != ',' && *p != '\0') + return MATCH_NONE; + return match; } /* @@ -499,14 +524,21 @@ list_starts_with(const char *methods, const char *method) * if it did. */ static int -remove_method(char **methods, const char *method) +remove_method(char **methods, const char *method, const char *submethod) { - char *omethods = *methods; + char *omethods = *methods, *p; size_t l = strlen(method); + int match; - if (!list_starts_with(omethods, method)) + match = list_starts_with(omethods, method, submethod); + if (match != MATCH_METHOD && match != MATCH_BOTH) return 0; - *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0)); + p = omethods + l; + if (submethod && match == MATCH_BOTH) + p += 1 + strlen(submethod); /* include colon */ + if (*p == ',') + p++; + *methods = xstrdup(p); free(omethods); return 1; } @@ -518,13 +550,15 @@ remove_method(char **methods, const char *method) * Returns 1 if the method completed any authentication list or 0 otherwise. */ int -auth2_update_methods_lists(Authctxt *authctxt, const char *method) +auth2_update_methods_lists(Authctxt *authctxt, const char *method, + const char *submethod) { u_int i, found = 0; debug3("%s: updating methods list after \"%s\"", __func__, method); for (i = 0; i < authctxt->num_auth_methods; i++) { - if (!remove_method(&(authctxt->auth_methods[i]), method)) + if (!remove_method(&(authctxt->auth_methods[i]), method, + submethod)) continue; found = 1; if (*authctxt->auth_methods[i] == '\0') { diff --git a/usr.bin/ssh/monitor.c b/usr.bin/ssh/monitor.c index 2f1f7e6b1cf..737c3c1abab 100644 --- a/usr.bin/ssh/monitor.c +++ b/usr.bin/ssh/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.121 2013/03/07 00:19:59 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.122 2013/03/07 19:27:25 markus Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -312,7 +312,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) "with SSH protocol 1"); if (authenticated && !auth2_update_methods_lists(authctxt, - auth_method)) { + auth_method, auth_submethod)) { debug3("%s: method %s: partial", __func__, auth_method); authenticated = 0; @@ -848,9 +848,10 @@ mm_answer_bsdauthrespond(int sock, Buffer *m) debug3("%s: sending authenticated: %d", __func__, authok); mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); - if (compat20) - auth_method = "keyboard-interactive"; /* XXX auth_submethod */ - else + if (compat20) { + auth_method = "keyboard-interactive"; + auth_submethod = "bsdauth"; + } else auth_method = "bsdauth"; return (authok != 0); diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5 index 17c07bc7b16..459e04270d4 100644 --- a/usr.bin/ssh/sshd_config.5 +++ b/usr.bin/ssh/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.156 2013/02/06 00:20:42 dtucker Exp $ -.Dd $Mdocdate: February 6 2013 $ +.\" $OpenBSD: sshd_config.5,v 1.157 2013/03/07 19:27:25 markus Exp $ +.Dd $Mdocdate: March 7 2013 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -180,6 +180,20 @@ Only methods that are next in one or more lists are offered at each stage, so for this example, it would not be possible to attempt password or keyboard-interactive authentication before public key. .Pp +For keyboard interactive authentication it is also possible to +restrict authentication to a specific device by appending a +colon followed by the device identifier +.Dq bsdauth , +.Dq pam , +or +.Dq skey , +depending on the server configuration. +For example, +.Dq keyboard-interactive:bsdauth +would restrict keyboard interactive authentication to the +.Dq bsdauth +device. +.Pp This option is only available for SSH protocol 2 and will yield a fatal error if enabled if protocol 1 is also enabled. Note that each authentication method listed should also be explicitly enabled |