summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2013-03-07 19:27:26 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2013-03-07 19:27:26 +0000
commit10774fbe8e5e2978d40fade9e10e76706bf57af3 (patch)
tree2a9f682bd611edebb3935003b3c0401ec77f7ef7
parent496f21ea5bc3456f11899d70855500e975747265 (diff)
add submethod support to AuthenticationMethods; ok and freedback djm@
-rw-r--r--usr.bin/ssh/auth.h5
-rw-r--r--usr.bin/ssh/auth2-chall.c12
-rw-r--r--usr.bin/ssh/auth2.c76
-rw-r--r--usr.bin/ssh/monitor.c11
-rw-r--r--usr.bin/ssh/sshd_config.518
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