- djm@cvs.openbsd.org 2012/10/30 21:29:55
[auth-rsa.c auth.c auth.h auth2-pubkey.c servconf.c servconf.h] [sshd.c sshd_config sshd_config.5] new sshd_config option AuthorizedKeysCommand to support fetching authorized_keys from a command in addition to (or instead of) from the filesystem. The command is run as the target server user unless another specified via a new AuthorizedKeysCommandUser option. patch originally by jchadima AT redhat.com, reworked by me; feedback and ok markus@
This commit is contained in:
parent
07daed505f
commit
09d3e12512
10
ChangeLog
10
ChangeLog
|
@ -3,6 +3,16 @@
|
|||
- markus@cvs.openbsd.org 2012/10/05 12:34:39
|
||||
[sftp.c]
|
||||
fix signed vs unsigned warning; feedback & ok: djm@
|
||||
- djm@cvs.openbsd.org 2012/10/30 21:29:55
|
||||
[auth-rsa.c auth.c auth.h auth2-pubkey.c servconf.c servconf.h]
|
||||
[sshd.c sshd_config sshd_config.5]
|
||||
new sshd_config option AuthorizedKeysCommand to support fetching
|
||||
authorized_keys from a command in addition to (or instead of) from
|
||||
the filesystem. The command is run as the target server user unless
|
||||
another specified via a new AuthorizedKeysCommandUser option.
|
||||
|
||||
patch originally by jchadima AT redhat.com, reworked by me; feedback
|
||||
and ok markus@
|
||||
|
||||
20121019
|
||||
- (tim) [buildpkg.sh.in] Double up on some backslashes so they end up in
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
|
||||
/* $OpenBSD: auth-rsa.c,v 1.81 2012/10/30 21:29:54 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -276,6 +276,8 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
|
|||
temporarily_use_uid(pw);
|
||||
|
||||
for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
|
||||
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
|
||||
continue;
|
||||
file = expand_authorized_keys(
|
||||
options.authorized_keys_files[i], pw);
|
||||
allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
|
||||
|
|
53
auth.c
53
auth.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */
|
||||
/* $OpenBSD: auth.c,v 1.97 2012/10/30 21:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -409,41 +409,42 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
|
|||
return host_status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check a given file for security. This is defined as all components
|
||||
* Check a given path for security. This is defined as all components
|
||||
* of the path to the file must be owned by either the owner of
|
||||
* of the file or root and no directories must be group or world writable.
|
||||
*
|
||||
* XXX Should any specific check be done for sym links ?
|
||||
*
|
||||
* Takes an open file descriptor, the file name, a uid and and
|
||||
* Takes an the file name, its stat information (preferably from fstat() to
|
||||
* avoid races), the uid of the expected owner, their home directory and an
|
||||
* error buffer plus max size as arguments.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
static int
|
||||
secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
char *err, size_t errlen)
|
||||
int
|
||||
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||
uid_t uid, char *err, size_t errlen)
|
||||
{
|
||||
uid_t uid = pw->pw_uid;
|
||||
char buf[MAXPATHLEN], homedir[MAXPATHLEN];
|
||||
char *cp;
|
||||
int comparehome = 0;
|
||||
struct stat st;
|
||||
|
||||
if (realpath(file, buf) == NULL) {
|
||||
snprintf(err, errlen, "realpath %s failed: %s", file,
|
||||
if (realpath(name, buf) == NULL) {
|
||||
snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (realpath(pw->pw_dir, homedir) != NULL)
|
||||
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
||||
comparehome = 1;
|
||||
|
||||
/* check the open file to avoid races */
|
||||
if (fstat(fileno(f), &st) < 0 ||
|
||||
(st.st_uid != 0 && st.st_uid != uid) ||
|
||||
(st.st_mode & 022) != 0) {
|
||||
if (!S_ISREG(stp->st_mode)) {
|
||||
snprintf(err, errlen, "%s is not a regular file", buf);
|
||||
return -1;
|
||||
}
|
||||
if ((stp->st_uid != 0 && stp->st_uid != uid) ||
|
||||
(stp->st_mode & 022) != 0) {
|
||||
snprintf(err, errlen, "bad ownership or modes for file %s",
|
||||
buf);
|
||||
return -1;
|
||||
|
@ -479,6 +480,28 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version of secure_path() that accepts an open file descriptor to
|
||||
* avoid races.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
static int
|
||||
secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
char *err, size_t errlen)
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
struct stat st;
|
||||
|
||||
/* check the open file to avoid races */
|
||||
if (fstat(fileno(f), &st) < 0) {
|
||||
snprintf(err, errlen, "cannot stat file %s: %s",
|
||||
buf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
||||
}
|
||||
|
||||
static FILE *
|
||||
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||
int log_missing, char *file_type)
|
||||
|
|
6
auth.h
6
auth.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.70 2012/10/30 21:29:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
|
@ -120,6 +120,10 @@ int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
|
|||
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
|
||||
int user_key_allowed(struct passwd *, Key *);
|
||||
|
||||
struct stat;
|
||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
||||
char *, size_t);
|
||||
|
||||
#ifdef KRB5
|
||||
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
|
||||
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
|
||||
|
|
206
auth2-pubkey.c
206
auth2-pubkey.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-pubkey.c,v 1.30 2011/09/25 05:44:47 djm Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.31 2012/10/30 21:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -27,9 +27,13 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
@ -240,7 +244,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
|
|||
if (strcmp(cp, cert->principals[i]) == 0) {
|
||||
debug3("matched principal \"%.100s\" "
|
||||
"from file \"%s\" on line %lu",
|
||||
cert->principals[i], file, linenum);
|
||||
cert->principals[i], file, linenum);
|
||||
if (auth_parse_options(pw, line_opts,
|
||||
file, linenum) != 1)
|
||||
continue;
|
||||
|
@ -253,31 +257,22 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
|
|||
fclose(f);
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* return 1 if user allows given key */
|
||||
/*
|
||||
* Checks whether key is allowed in authorized_keys-format file,
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
const char *reason;
|
||||
int found_key = 0;
|
||||
FILE *f;
|
||||
u_long linenum = 0;
|
||||
Key *found;
|
||||
char *fp;
|
||||
|
||||
/* Temporarily use the user's uid. */
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
debug("trying public key file %s", file);
|
||||
f = auth_openkeyfile(file, pw, options.strict_modes);
|
||||
|
||||
if (!f) {
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
|
||||
found_key = 0;
|
||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
|
||||
|
@ -370,8 +365,6 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
|||
break;
|
||||
}
|
||||
}
|
||||
restore_uid();
|
||||
fclose(f);
|
||||
key_free(found);
|
||||
if (!found_key)
|
||||
debug2("key not found");
|
||||
|
@ -433,7 +426,172 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* check whether given key is in .ssh/authorized_keys* */
|
||||
/*
|
||||
* Checks whether key is allowed in file.
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
{
|
||||
FILE *f;
|
||||
int found_key = 0;
|
||||
|
||||
/* Temporarily use the user's uid. */
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
debug("trying public key file %s", file);
|
||||
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
|
||||
found_key = check_authkeys_file(f, file, key, pw);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
restore_uid();
|
||||
return found_key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether key is allowed in output of command.
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
{
|
||||
FILE *f;
|
||||
int ok, found_key = 0;
|
||||
struct passwd *pw;
|
||||
struct stat st;
|
||||
int status, devnull, p[2], i;
|
||||
pid_t pid;
|
||||
char errmsg[512];
|
||||
|
||||
if (options.authorized_keys_command == NULL ||
|
||||
options.authorized_keys_command[0] != '/')
|
||||
return 0;
|
||||
|
||||
/* If no user specified to run commands the default to target user */
|
||||
if (options.authorized_keys_command_user == NULL)
|
||||
pw = user_pw;
|
||||
else {
|
||||
pw = getpwnam(options.authorized_keys_command_user);
|
||||
if (pw == NULL) {
|
||||
error("AuthorizedKeyCommandUser \"%s\" not found: %s",
|
||||
options.authorized_keys_command, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
if (stat(options.authorized_keys_command, &st) < 0) {
|
||||
error("Could not stat AuthorizedKeysCommand \"%s\": %s",
|
||||
options.authorized_keys_command, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
|
||||
errmsg, sizeof(errmsg)) != 0) {
|
||||
error("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pipe(p) != 0) {
|
||||
error("%s: pipe: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug3("Running AuthorizedKeysCommand: \"%s\" as \"%s\"",
|
||||
options.authorized_keys_command, pw->pw_name);
|
||||
|
||||
/*
|
||||
* Don't want to call this in the child, where it can fatal() and
|
||||
* run cleanup_exit() code.
|
||||
*/
|
||||
restore_uid();
|
||||
|
||||
switch ((pid = fork())) {
|
||||
case -1: /* error */
|
||||
error("%s: fork: %s", __func__, strerror(errno));
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
return 0;
|
||||
case 0: /* child */
|
||||
for (i = 0; i < NSIG; i++)
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
/* Don't use permanently_set_uid() here to avoid fatal() */
|
||||
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
||||
error("setresgid %u: %s", (u_int)pw->pw_gid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
||||
error("setresuid %u: %s", (u_int)pw->pw_uid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
close(p[0]);
|
||||
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||
error("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
if (dup2(devnull, STDIN_FILENO) == -1 ||
|
||||
dup2(p[1], STDOUT_FILENO) == -1 ||
|
||||
dup2(devnull, STDERR_FILENO) == -1) {
|
||||
error("%s: dup2: %s", __func__, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
execl(options.authorized_keys_command,
|
||||
options.authorized_keys_command, pw->pw_name, NULL);
|
||||
|
||||
error("AuthorizedKeysCommand %s exec failed: %s",
|
||||
options.authorized_keys_command, strerror(errno));
|
||||
_exit(127);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
close(p[1]);
|
||||
if ((f = fdopen(p[0], "r")) == NULL) {
|
||||
error("%s: fdopen: %s", __func__, strerror(errno));
|
||||
close(p[0]);
|
||||
/* Don't leave zombie child */
|
||||
kill(pid, SIGTERM);
|
||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||
;
|
||||
goto out;
|
||||
}
|
||||
ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
|
||||
fclose(f);
|
||||
|
||||
while (waitpid(pid, &status, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
error("%s: waitpid: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
error("AuthorizedKeysCommand %s exited on signal %d",
|
||||
options.authorized_keys_command, WTERMSIG(status));
|
||||
goto out;
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
error("AuthorizedKeysCommand %s returned status %d",
|
||||
options.authorized_keys_command, WEXITSTATUS(status));
|
||||
goto out;
|
||||
}
|
||||
found_key = ok;
|
||||
out:
|
||||
restore_uid();
|
||||
return found_key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether key authenticates and authorises the user.
|
||||
*/
|
||||
int
|
||||
user_key_allowed(struct passwd *pw, Key *key)
|
||||
{
|
||||
|
@ -449,9 +607,17 @@ user_key_allowed(struct passwd *pw, Key *key)
|
|||
if (success)
|
||||
return success;
|
||||
|
||||
success = user_key_command_allowed2(pw, key);
|
||||
if (success > 0)
|
||||
return success;
|
||||
|
||||
for (i = 0; !success && i < options.num_authkeys_files; i++) {
|
||||
|
||||
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
|
||||
continue;
|
||||
file = expand_authorized_keys(
|
||||
options.authorized_keys_files[i], pw);
|
||||
|
||||
success = user_key_allowed2(pw, key, file);
|
||||
xfree(file);
|
||||
}
|
||||
|
|
30
servconf.c
30
servconf.c
|
@ -1,5 +1,5 @@
|
|||
|
||||
/* $OpenBSD: servconf.c,v 1.230 2012/09/13 23:37:36 dtucker Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.231 2012/10/30 21:29:54 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
|
@ -135,6 +135,8 @@ initialize_server_options(ServerOptions *options)
|
|||
options->num_permitted_opens = -1;
|
||||
options->adm_forced_command = NULL;
|
||||
options->chroot_directory = NULL;
|
||||
options->authorized_keys_command = NULL;
|
||||
options->authorized_keys_command_user = NULL;
|
||||
options->zero_knowledge_password_authentication = -1;
|
||||
options->revoked_keys_file = NULL;
|
||||
options->trusted_user_ca_keys = NULL;
|
||||
|
@ -329,6 +331,7 @@ typedef enum {
|
|||
sZeroKnowledgePasswordAuthentication, sHostCertificate,
|
||||
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
||||
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||||
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
|
@ -453,6 +456,8 @@ static struct {
|
|||
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
|
||||
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
|
||||
{ "ipqos", sIPQoS, SSHCFG_ALL },
|
||||
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
|
||||
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
@ -1498,6 +1503,25 @@ process_server_config_line(ServerOptions *options, char *line,
|
|||
}
|
||||
return 0;
|
||||
|
||||
case sAuthorizedKeysCommand:
|
||||
len = strspn(cp, WHITESPACE);
|
||||
if (*activep && options->authorized_keys_command == NULL) {
|
||||
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
|
||||
fatal("%.200s line %d: AuthorizedKeysCommand "
|
||||
"must be an absolute path",
|
||||
filename, linenum);
|
||||
options->authorized_keys_command = xstrdup(cp + len);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case sAuthorizedKeysCommandUser:
|
||||
charptr = &options->authorized_keys_command_user;
|
||||
|
||||
arg = strdelim(&cp);
|
||||
if (*activep && *charptr == NULL)
|
||||
*charptr = xstrdup(arg);
|
||||
break;
|
||||
|
||||
case sDeprecated:
|
||||
logit("%s line %d: Deprecated option %s",
|
||||
filename, linenum, arg);
|
||||
|
@ -1648,6 +1672,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
|||
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
|
||||
M_CP_INTOPT(kbd_interactive_authentication);
|
||||
M_CP_INTOPT(zero_knowledge_password_authentication);
|
||||
M_CP_STROPT(authorized_keys_command);
|
||||
M_CP_STROPT(authorized_keys_command_user);
|
||||
M_CP_INTOPT(permit_root_login);
|
||||
M_CP_INTOPT(permit_empty_passwd);
|
||||
|
||||
|
@ -1908,6 +1934,8 @@ dump_config(ServerOptions *o)
|
|||
dump_cfg_string(sAuthorizedPrincipalsFile,
|
||||
o->authorized_principals_file);
|
||||
dump_cfg_string(sVersionAddendum, o->version_addendum);
|
||||
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
|
||||
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
|
||||
|
||||
/* string arguments requiring a lookup */
|
||||
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: servconf.h,v 1.103 2012/07/10 02:19:15 djm Exp $ */
|
||||
/* $OpenBSD: servconf.h,v 1.104 2012/10/30 21:29:55 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -166,6 +166,8 @@ typedef struct {
|
|||
char *revoked_keys_file;
|
||||
char *trusted_user_ca_keys;
|
||||
char *authorized_principals_file;
|
||||
char *authorized_keys_command;
|
||||
char *authorized_keys_command_user;
|
||||
|
||||
char *version_addendum; /* Appended to SSH banner */
|
||||
} ServerOptions;
|
||||
|
|
11
sshd.c
11
sshd.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshd.c,v 1.393 2012/07/10 02:19:15 djm Exp $ */
|
||||
/* $OpenBSD: sshd.c,v 1.394 2012/10/30 21:29:55 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -359,6 +359,15 @@ grace_alarm_handler(int sig)
|
|||
if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
|
||||
kill(pmonitor->m_pid, SIGALRM);
|
||||
|
||||
/*
|
||||
* Try to kill any processes that we have spawned, E.g. authorized
|
||||
* keys command helpers.
|
||||
*/
|
||||
if (getpgid(0) == getpid()) {
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
killpg(0, SIGTERM);
|
||||
}
|
||||
|
||||
/* Log error and exit. */
|
||||
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: sshd_config,v 1.87 2012/07/10 02:19:15 djm Exp $
|
||||
# $OpenBSD: sshd_config,v 1.88 2012/10/30 21:29:55 djm Exp $
|
||||
|
||||
# This is the sshd server system-wide configuration file. See
|
||||
# sshd_config(5) for more information.
|
||||
|
@ -51,6 +51,9 @@ AuthorizedKeysFile .ssh/authorized_keys
|
|||
|
||||
#AuthorizedPrincipalsFile none
|
||||
|
||||
#AuthorizedKeysCommand none
|
||||
#AuthorizedKeysCommandUser nobody
|
||||
|
||||
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
||||
#RhostsRSAAuthentication no
|
||||
# similar for protocol version 2
|
||||
|
|
|
@ -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.145 2012/10/04 13:21:50 markus Exp $
|
||||
.Dd $Mdocdate: October 4 2012 $
|
||||
.\" $OpenBSD: sshd_config.5,v 1.146 2012/10/30 21:29:55 djm Exp $
|
||||
.Dd $Mdocdate: October 30 2012 $
|
||||
.Dt SSHD_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -151,6 +151,22 @@ See
|
|||
in
|
||||
.Xr ssh_config 5
|
||||
for more information on patterns.
|
||||
.It Cm AuthorizedKeysCommand
|
||||
Specifies a program to be used for lookup of the user's public keys.
|
||||
The program will be invoked with a single argument of the username
|
||||
being authenticated, and should produce on standard output zero or
|
||||
more lines of authorized_keys output (see AUTHORIZED_KEYS in
|
||||
.Xr sshd 8 )
|
||||
If a key supplied by AuthorizedKeysCommand does not successfully authenticate
|
||||
and authorize the user then public key authentication continues using the usual
|
||||
.Cm AuthorizedKeysFile
|
||||
files.
|
||||
By default, no AuthorizedKeysCommand is run.
|
||||
.It Cm AuthorizedKeysCommandUser
|
||||
Specifies the user under whose account the AuthorizedKeysCommand is run.
|
||||
The default is the user being authenticated.
|
||||
It is recommended to use a dedicated user that has no other role on the host
|
||||
than running authorized keys commands.
|
||||
.It Cm AuthorizedKeysFile
|
||||
Specifies the file that contains the public keys that can be used
|
||||
for user authentication.
|
||||
|
@ -712,6 +728,8 @@ Available keywords are
|
|||
.Cm AllowTcpForwarding ,
|
||||
.Cm AllowUsers ,
|
||||
.Cm AuthorizedKeysFile ,
|
||||
.Cm AuthorizedKeysCommand ,
|
||||
.Cm AuthorizedKeysCommandUser ,
|
||||
.Cm AuthorizedPrincipalsFile ,
|
||||
.Cm Banner ,
|
||||
.Cm ChrootDirectory ,
|
||||
|
|
Loading…
Reference in New Issue