mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-11-27 05:46:36 +08:00
- djm@cvs.openbsd.org 2012/11/04 11:09:15
[auth.h auth1.c auth2.c monitor.c servconf.c servconf.h sshd.c] [sshd_config.5] Support multiple required authentication via an AuthenticationMethods option. This option lists one or more comma-separated lists of authentication method names. Successful completion of all the methods in any list is required for authentication to complete; feedback and ok markus@
This commit is contained in:
parent
d0d1099b3b
commit
a6e3f01d1e
@ -7,6 +7,14 @@
|
||||
[auth2-pubkey.c sshd.c sshd_config.5]
|
||||
Remove default of AuthorizedCommandUser. Administrators are now expected
|
||||
to explicitly specify a user. feedback and ok markus@
|
||||
- djm@cvs.openbsd.org 2012/11/04 11:09:15
|
||||
[auth.h auth1.c auth2.c monitor.c servconf.c servconf.h sshd.c]
|
||||
[sshd_config.5]
|
||||
Support multiple required authentication via an AuthenticationMethods
|
||||
option. This option lists one or more comma-separated lists of
|
||||
authentication method names. Successful completion of all the methods in
|
||||
any list is required for authentication to complete;
|
||||
feedback and ok markus@
|
||||
|
||||
20121030
|
||||
- (djm) OpenBSD CVS Sync
|
||||
|
7
auth.h
7
auth.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.h,v 1.70 2012/10/30 21:29:54 djm Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.71 2012/11/04 11:09:15 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -64,6 +64,8 @@ struct Authctxt {
|
||||
#ifdef BSD_AUTH
|
||||
auth_session_t *as;
|
||||
#endif
|
||||
char **auth_methods; /* modified from server config */
|
||||
u_int num_auth_methods;
|
||||
#ifdef KRB5
|
||||
krb5_context krb5_ctx;
|
||||
krb5_ccache krb5_fwd_ccache;
|
||||
@ -152,6 +154,9 @@ void userauth_send_banner(const char *);
|
||||
int auth_root_allowed(char *);
|
||||
|
||||
char *auth2_read_banner(void);
|
||||
int auth2_methods_valid(const char *, int);
|
||||
int auth2_update_methods_lists(Authctxt *, const char *);
|
||||
int auth2_setup_methods_lists(Authctxt *);
|
||||
|
||||
void privsep_challenge_enable(void);
|
||||
|
||||
|
7
auth1.c
7
auth1.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
|
||||
/* $OpenBSD: auth1.c,v 1.76 2012/11/04 11:09:15 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -406,6 +406,11 @@ do_authentication(Authctxt *authctxt)
|
||||
authctxt->pw = fakepw();
|
||||
}
|
||||
|
||||
/* Configuration may have changed as a result of Match */
|
||||
if (options.num_auth_methods != 0)
|
||||
fatal("AuthenticationMethods is not supported with SSH "
|
||||
"protocol 1");
|
||||
|
||||
setproctitle("%s%s", authctxt->valid ? user : "unknown",
|
||||
use_privsep ? " [net]" : "");
|
||||
|
||||
|
218
auth2.c
218
auth2.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2.c,v 1.124 2011/12/07 05:44:38 djm Exp $ */
|
||||
/* $OpenBSD: auth2.c,v 1.125 2012/11/04 11:09:15 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -96,8 +96,10 @@ static void input_service_request(int, u_int32_t, void *);
|
||||
static void input_userauth_request(int, u_int32_t, void *);
|
||||
|
||||
/* helper */
|
||||
static Authmethod *authmethod_lookup(const char *);
|
||||
static char *authmethods_get(void);
|
||||
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 *);
|
||||
|
||||
char *
|
||||
auth2_read_banner(void)
|
||||
@ -255,6 +257,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
if (use_privsep)
|
||||
mm_inform_authserv(service, style);
|
||||
userauth_banner();
|
||||
if (auth2_setup_methods_lists(authctxt) != 0)
|
||||
packet_disconnect("no authentication methods enabled");
|
||||
} else if (strcmp(user, authctxt->user) != 0 ||
|
||||
strcmp(service, authctxt->service) != 0) {
|
||||
packet_disconnect("Change of username or service not allowed: "
|
||||
@ -277,7 +281,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
authctxt->server_caused_failure = 0;
|
||||
|
||||
/* try to authenticate user */
|
||||
m = authmethod_lookup(method);
|
||||
m = authmethod_lookup(authctxt, method);
|
||||
if (m != NULL && authctxt->failures < options.max_authtries) {
|
||||
debug2("input_userauth_request: try method %s", method);
|
||||
authenticated = m->userauth(authctxt);
|
||||
@ -293,6 +297,7 @@ void
|
||||
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
{
|
||||
char *methods;
|
||||
int partial = 0;
|
||||
|
||||
if (!authctxt->valid && authenticated)
|
||||
fatal("INTERNAL ERROR: authenticated invalid user %s",
|
||||
@ -335,7 +340,13 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
if (authctxt->postponed)
|
||||
return;
|
||||
|
||||
/* XXX todo: check if multiple auth methods are needed */
|
||||
if (authenticated && options.num_auth_methods != 0) {
|
||||
if (!auth2_update_methods_lists(authctxt, method)) {
|
||||
authenticated = 0;
|
||||
partial = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated == 1) {
|
||||
/* turn off userauth */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
|
||||
@ -356,34 +367,61 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
#endif
|
||||
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
|
||||
}
|
||||
methods = authmethods_get();
|
||||
methods = authmethods_get(authctxt);
|
||||
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
|
||||
partial, methods);
|
||||
packet_start(SSH2_MSG_USERAUTH_FAILURE);
|
||||
packet_put_cstring(methods);
|
||||
packet_put_char(0); /* XXX partial success, unused */
|
||||
packet_put_char(partial);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
xfree(methods);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether method is allowed by at least one AuthenticationMethods
|
||||
* methods list. Returns 1 if allowed, or no methods lists configured.
|
||||
* 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
method_allowed(Authctxt *authctxt, const char *method)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
/*
|
||||
* NB. authctxt->num_auth_methods might be zero as a result of
|
||||
* auth2_setup_methods_lists(), so check the configuration.
|
||||
*/
|
||||
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))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
authmethods_get(void)
|
||||
authmethods_get(Authctxt *authctxt)
|
||||
{
|
||||
Buffer b;
|
||||
char *list;
|
||||
int i;
|
||||
u_int i;
|
||||
|
||||
buffer_init(&b);
|
||||
for (i = 0; authmethods[i] != NULL; i++) {
|
||||
if (strcmp(authmethods[i]->name, "none") == 0)
|
||||
continue;
|
||||
if (authmethods[i]->enabled != NULL &&
|
||||
*(authmethods[i]->enabled) != 0) {
|
||||
if (buffer_len(&b) > 0)
|
||||
buffer_append(&b, ",", 1);
|
||||
buffer_append(&b, authmethods[i]->name,
|
||||
strlen(authmethods[i]->name));
|
||||
}
|
||||
if (authmethods[i]->enabled == NULL ||
|
||||
*(authmethods[i]->enabled) == 0)
|
||||
continue;
|
||||
if (!method_allowed(authctxt, authmethods[i]->name))
|
||||
continue;
|
||||
if (buffer_len(&b) > 0)
|
||||
buffer_append(&b, ",", 1);
|
||||
buffer_append(&b, authmethods[i]->name,
|
||||
strlen(authmethods[i]->name));
|
||||
}
|
||||
buffer_append(&b, "\0", 1);
|
||||
list = xstrdup(buffer_ptr(&b));
|
||||
@ -392,7 +430,7 @@ authmethods_get(void)
|
||||
}
|
||||
|
||||
static Authmethod *
|
||||
authmethod_lookup(const char *name)
|
||||
authmethod_lookup(Authctxt *authctxt, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -400,10 +438,154 @@ authmethod_lookup(const char *name)
|
||||
for (i = 0; authmethods[i] != NULL; i++)
|
||||
if (authmethods[i]->enabled != NULL &&
|
||||
*(authmethods[i]->enabled) != 0 &&
|
||||
strcmp(name, authmethods[i]->name) == 0)
|
||||
strcmp(name, authmethods[i]->name) == 0 &&
|
||||
method_allowed(authctxt, authmethods[i]->name))
|
||||
return authmethods[i];
|
||||
debug2("Unrecognized authentication method name: %s",
|
||||
name ? name : "NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a comma-separated list of methods for validity. Is need_enable is
|
||||
* non-zero, then also require that the methods are enabled.
|
||||
* Returns 0 on success or -1 if the methods list is invalid.
|
||||
*/
|
||||
int
|
||||
auth2_methods_valid(const char *_methods, int need_enable)
|
||||
{
|
||||
char *methods, *omethods, *method;
|
||||
u_int i, found;
|
||||
int ret = -1;
|
||||
|
||||
if (*_methods == '\0') {
|
||||
error("empty authentication method list");
|
||||
return -1;
|
||||
}
|
||||
omethods = methods = xstrdup(_methods);
|
||||
while ((method = strsep(&methods, ",")) != NULL) {
|
||||
for (found = i = 0; !found && authmethods[i] != NULL; i++) {
|
||||
if (strcmp(method, authmethods[i]->name) != 0)
|
||||
continue;
|
||||
if (need_enable) {
|
||||
if (authmethods[i]->enabled == NULL ||
|
||||
*(authmethods[i]->enabled) == 0) {
|
||||
error("Disabled method \"%s\" in "
|
||||
"AuthenticationMethods list \"%s\"",
|
||||
method, _methods);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
error("Unknown authentication method \"%s\" in list",
|
||||
method);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
free(omethods);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prune the AuthenticationMethods supplied in the configuration, removing
|
||||
* any methods lists that include disabled methods. Note that this might
|
||||
* leave authctxt->num_auth_methods == 0, even when multiple required auth
|
||||
* has been requested. For this reason, all tests for whether multiple is
|
||||
* enabled should consult options.num_auth_methods directly.
|
||||
*/
|
||||
int
|
||||
auth2_setup_methods_lists(Authctxt *authctxt)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (options.num_auth_methods == 0)
|
||||
return 0;
|
||||
debug3("%s: checking methods", __func__);
|
||||
authctxt->auth_methods = xcalloc(options.num_auth_methods,
|
||||
sizeof(*authctxt->auth_methods));
|
||||
authctxt->num_auth_methods = 0;
|
||||
for (i = 0; i < options.num_auth_methods; i++) {
|
||||
if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
|
||||
logit("Authentication methods list \"%s\" contains "
|
||||
"disabled method, skipping",
|
||||
options.auth_methods[i]);
|
||||
continue;
|
||||
}
|
||||
debug("authentication methods list %d: %s",
|
||||
authctxt->num_auth_methods, options.auth_methods[i]);
|
||||
authctxt->auth_methods[authctxt->num_auth_methods++] =
|
||||
xstrdup(options.auth_methods[i]);
|
||||
}
|
||||
if (authctxt->num_auth_methods == 0) {
|
||||
error("No AuthenticationMethods left after eliminating "
|
||||
"disabled methods");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
list_starts_with(const char *methods, const char *method)
|
||||
{
|
||||
size_t l = strlen(method);
|
||||
|
||||
if (strncmp(methods, method, l) != 0)
|
||||
return 0;
|
||||
if (methods[l] != ',' && methods[l] != '\0')
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove method from the start of a comma-separated list of methods.
|
||||
* Returns 0 if the list of methods did not start with that method or 1
|
||||
* if it did.
|
||||
*/
|
||||
static int
|
||||
remove_method(char **methods, const char *method)
|
||||
{
|
||||
char *omethods = *methods;
|
||||
size_t l = strlen(method);
|
||||
|
||||
if (!list_starts_with(omethods, method))
|
||||
return 0;
|
||||
*methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0));
|
||||
free(omethods);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after successful authentication. Will remove the successful method
|
||||
* from the start of each list in which it occurs. If it was the last method
|
||||
* in any list, then authentication is deemed successful.
|
||||
* Returns 1 if the method completed any authentication list or 0 otherwise.
|
||||
*/
|
||||
int
|
||||
auth2_update_methods_lists(Authctxt *authctxt, const char *method)
|
||||
{
|
||||
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))
|
||||
continue;
|
||||
found = 1;
|
||||
if (*authctxt->auth_methods[i] == '\0') {
|
||||
debug2("authentication methods list %d complete", i);
|
||||
return 1;
|
||||
}
|
||||
debug3("authentication methods list %d remaining: \"%s\"",
|
||||
i, authctxt->auth_methods[i]);
|
||||
}
|
||||
/* This should not happen, but would be bad if it did */
|
||||
if (!found)
|
||||
fatal("%s: method not in AuthenticationMethods", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
35
monitor.c
35
monitor.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor.c,v 1.117 2012/06/22 12:30:26 dtucker Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.118 2012/11/04 11:09:15 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -381,6 +381,21 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
while (!authenticated) {
|
||||
auth_method = "unknown";
|
||||
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
||||
|
||||
/* Special handling for multiple required authentications */
|
||||
if (options.num_auth_methods != 0) {
|
||||
if (!compat20)
|
||||
fatal("AuthenticationMethods is not supported"
|
||||
"with SSH protocol 1");
|
||||
if (authenticated &&
|
||||
!auth2_update_methods_lists(authctxt,
|
||||
auth_method)) {
|
||||
debug3("%s: method %s: partial", __func__,
|
||||
auth_method);
|
||||
authenticated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
if (!(ent->flags & MON_AUTHDECIDE))
|
||||
fatal("%s: unexpected authentication from %d",
|
||||
@ -401,7 +416,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
|
||||
auth_log(authctxt, authenticated, auth_method,
|
||||
compat20 ? " ssh2" : "");
|
||||
@ -781,7 +795,17 @@ mm_answer_pwnamallow(int sock, Buffer *m)
|
||||
COPY_MATCH_STRING_OPTS();
|
||||
#undef M_CP_STROPT
|
||||
#undef M_CP_STRARRAYOPT
|
||||
|
||||
|
||||
/* Create valid auth method lists */
|
||||
if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
|
||||
/*
|
||||
* The monitor will continue long enough to let the child
|
||||
* run to it's packet_disconnect(), but it must not allow any
|
||||
* authentication to succeed.
|
||||
*/
|
||||
debug("%s: no valid authentication method lists", __func__);
|
||||
}
|
||||
|
||||
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
|
||||
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
|
||||
|
||||
@ -918,7 +942,10 @@ mm_answer_bsdauthrespond(int sock, Buffer *m)
|
||||
debug3("%s: sending authenticated: %d", __func__, authok);
|
||||
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
|
||||
|
||||
auth_method = "bsdauth";
|
||||
if (compat20)
|
||||
auth_method = "keyboard-interactive";
|
||||
else
|
||||
auth_method = "bsdauth";
|
||||
|
||||
return (authok != 0);
|
||||
}
|
||||
|
26
servconf.c
26
servconf.c
@ -1,5 +1,5 @@
|
||||
|
||||
/* $OpenBSD: servconf.c,v 1.231 2012/10/30 21:29:54 djm Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.232 2012/11/04 11:09:15 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -48,6 +48,8 @@
|
||||
#include "groupaccess.h"
|
||||
#include "canohost.h"
|
||||
#include "packet.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
|
||||
static void add_listen_addr(ServerOptions *, char *, int);
|
||||
static void add_one_listen_addr(ServerOptions *, char *, int);
|
||||
@ -332,6 +334,7 @@ typedef enum {
|
||||
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
||||
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||||
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
||||
sAuthenticationMethods,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
@ -459,6 +462,7 @@ static struct {
|
||||
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
|
||||
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
@ -1522,6 +1526,24 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
*charptr = xstrdup(arg);
|
||||
break;
|
||||
|
||||
case sAuthenticationMethods:
|
||||
if (*activep && options->num_auth_methods == 0) {
|
||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||
if (options->num_auth_methods >=
|
||||
MAX_AUTH_METHODS)
|
||||
fatal("%s line %d: "
|
||||
"too many authentication methods.",
|
||||
filename, linenum);
|
||||
if (auth2_methods_valid(arg, 0) != 0)
|
||||
fatal("%s line %d: invalid "
|
||||
"authentication method list.",
|
||||
filename, linenum);
|
||||
options->auth_methods[
|
||||
options->num_auth_methods++] = xstrdup(arg);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case sDeprecated:
|
||||
logit("%s line %d: Deprecated option %s",
|
||||
filename, linenum, arg);
|
||||
@ -1953,6 +1975,8 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
|
||||
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
|
||||
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
|
||||
dump_cfg_strarray_oneline(sAuthenticationMethods,
|
||||
o->num_auth_methods, o->auth_methods);
|
||||
|
||||
/* other arguments */
|
||||
for (i = 0; i < o->num_subsystems; i++)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: servconf.h,v 1.104 2012/10/30 21:29:55 djm Exp $ */
|
||||
/* $OpenBSD: servconf.h,v 1.105 2012/11/04 11:09:15 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -28,6 +28,7 @@
|
||||
#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
|
||||
#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
|
||||
#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */
|
||||
#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */
|
||||
|
||||
/* permit_root_login */
|
||||
#define PERMIT_NOT_SET -1
|
||||
@ -170,6 +171,9 @@ typedef struct {
|
||||
char *authorized_keys_command_user;
|
||||
|
||||
char *version_addendum; /* Appended to SSH banner */
|
||||
|
||||
u_int num_auth_methods;
|
||||
char *auth_methods[MAX_AUTH_METHODS];
|
||||
} ServerOptions;
|
||||
|
||||
/* Information about the incoming connection as used by Match */
|
||||
@ -199,6 +203,7 @@ struct connection_info {
|
||||
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
|
||||
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
|
||||
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
|
||||
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
|
||||
} while (0)
|
||||
|
||||
struct connection_info *get_connection_info(int, int);
|
||||
|
23
sshd.c
23
sshd.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshd.c,v 1.395 2012/11/04 10:38:43 djm Exp $ */
|
||||
/* $OpenBSD: sshd.c,v 1.396 2012/11/04 11:09:15 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -1337,6 +1337,7 @@ main(int ac, char **av)
|
||||
int remote_port;
|
||||
char *line;
|
||||
int config_s[2] = { -1 , -1 };
|
||||
u_int n;
|
||||
u_int64_t ibytes, obytes;
|
||||
mode_t new_umask;
|
||||
Key *key;
|
||||
@ -1566,6 +1567,26 @@ main(int ac, char **av)
|
||||
fatal("AuthorizedKeysCommand set without "
|
||||
"AuthorizedKeysCommandUser");
|
||||
|
||||
/*
|
||||
* Check whether there is any path through configured auth methods.
|
||||
* Unfortunately it is not possible to verify this generally before
|
||||
* daemonisation in the presence of Match block, but this catches
|
||||
* and warns for trivial misconfigurations that could break login.
|
||||
*/
|
||||
if (options.num_auth_methods != 0) {
|
||||
if ((options.protocol & SSH_PROTO_1))
|
||||
fatal("AuthenticationMethods is not supported with "
|
||||
"SSH protocol 1");
|
||||
for (n = 0; n < options.num_auth_methods; n++) {
|
||||
if (auth2_methods_valid(options.auth_methods[n],
|
||||
1) == 0)
|
||||
break;
|
||||
}
|
||||
if (n >= options.num_auth_methods)
|
||||
fatal("AuthenticationMethods cannot be satisfied by "
|
||||
"enabled authentication methods");
|
||||
}
|
||||
|
||||
/* set default channel AF */
|
||||
channel_set_af(options.address_family);
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
.\" (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.148 2012/11/04 10:38:43 djm Exp $
|
||||
.\" $OpenBSD: sshd_config.5,v 1.149 2012/11/04 11:09:15 djm Exp $
|
||||
.Dd $Mdocdate: November 4 2012 $
|
||||
.Dt SSHD_CONFIG 5
|
||||
.Os
|
||||
@ -151,6 +151,28 @@ See
|
||||
in
|
||||
.Xr ssh_config 5
|
||||
for more information on patterns.
|
||||
.It Cm AuthenticationMethods
|
||||
Specifies the authentication methods that must be successfully completed
|
||||
for a user to be granted access.
|
||||
This option must be followed by one or more comma-separated lists of
|
||||
authentication method names.
|
||||
Successful authentication requires completion of every method in at least
|
||||
one of these lists.
|
||||
.Pp
|
||||
For example, an argument of
|
||||
.Dq publickey,password publickey,keyboard-interactive
|
||||
would require the user to complete public key authentication, followed by
|
||||
either password or keyboard interactive authentication.
|
||||
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
|
||||
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
|
||||
in the configuration.
|
||||
The default is not to require multiple authentication; successful completion
|
||||
of a single authentication method is sufficient.
|
||||
.It Cm AuthorizedKeysCommand
|
||||
Specifies a program to be used to look up the user's public keys.
|
||||
The program will be invoked with a single argument of the username
|
||||
@ -728,6 +750,7 @@ Available keywords are
|
||||
.Cm AllowGroups ,
|
||||
.Cm AllowTcpForwarding ,
|
||||
.Cm AllowUsers ,
|
||||
.Cm AuthenticationMethods ,
|
||||
.Cm AuthorizedKeysCommand ,
|
||||
.Cm AuthorizedKeysCommandUser ,
|
||||
.Cm AuthorizedKeysFile ,
|
||||
|
Loading…
Reference in New Issue
Block a user