summaryrefslogtreecommitdiff
path: root/auth2-pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r--auth2-pubkey.c580
1 files changed, 128 insertions, 452 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 3e5706f4dbef..169839b01ed7 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -27,7 +27,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
@@ -52,7 +51,7 @@
#include "misc.h"
#include "servconf.h"
#include "compat.h"
-#include "key.h"
+#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "pathnames.h"
@@ -75,42 +74,52 @@ extern u_char *session_id2;
extern u_int session_id2_len;
static int
-userauth_pubkey(Authctxt *authctxt)
+userauth_pubkey(struct ssh *ssh)
{
- Buffer b;
- Key *key = NULL;
- char *pkalg, *userstyle, *fp = NULL;
- u_char *pkblob, *sig;
- u_int alen, blen, slen;
- int have_sig, pktype;
+ Authctxt *authctxt = ssh->authctxt;
+ struct sshbuf *b;
+ struct sshkey *key = NULL;
+ char *pkalg, *userstyle = NULL, *fp = NULL;
+ u_char *pkblob, *sig, have_sig;
+ size_t blen, slen;
+ int r, pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("%s: disabled because of invalid user", __func__);
return 0;
}
- have_sig = packet_get_char();
- if (datafellows & SSH_BUG_PKAUTH) {
+ if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0)
+ fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r));
+ if (ssh->compat & SSH_BUG_PKAUTH) {
debug2("%s: SSH_BUG_PKAUTH", __func__);
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
/* no explicit pkalg given */
- pkblob = packet_get_string(&blen);
- buffer_init(&b);
- buffer_append(&b, pkblob, blen);
/* so we have to extract the pkalg from the pkblob */
- pkalg = buffer_get_string(&b, &alen);
- buffer_free(&b);
+ /* XXX use sshbuf_from() */
+ if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
+ (r = sshbuf_put(b, pkblob, blen)) != 0 ||
+ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0)
+ fatal("%s: failed: %s", __func__, ssh_err(r));
+ sshbuf_free(b);
} else {
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
+ if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
+ fatal("%s: sshpkt_get_cstring failed: %s",
+ __func__, ssh_err(r));
}
- pktype = key_type_from_name(pkalg);
+ pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
logit("%s: unsupported public key algorithm: %s",
__func__, pkalg);
goto done;
}
- key = key_from_blob(pkblob, blen);
+ if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ error("%s: could not parse key: %s", __func__, ssh_err(r));
+ goto done;
+ }
if (key == NULL) {
error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
@@ -120,15 +129,15 @@ userauth_pubkey(Authctxt *authctxt)
"(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
- if (key_type_plain(key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
logit("Refusing RSA key because client uses unsafe "
"signature scheme");
goto done;
}
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
- if (auth2_userkey_already_used(authctxt, key)) {
- logit("refusing previously-used %s key", key_type(key));
+ if (auth2_key_already_used(authctxt, key)) {
+ logit("refusing previously-used %s key", sshkey_type(key));
goto done;
}
if (match_pattern_list(sshkey_ssh_name(key),
@@ -141,54 +150,65 @@ userauth_pubkey(Authctxt *authctxt)
if (have_sig) {
debug3("%s: have signature for %s %s",
__func__, sshkey_type(key), fp);
- sig = packet_get_string(&slen);
- packet_check_eom();
- buffer_init(&b);
- if (datafellows & SSH_OLD_SESSIONID) {
- buffer_append(&b, session_id2, session_id2_len);
+ if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (ssh->compat & SSH_OLD_SESSIONID) {
+ if ((r = sshbuf_put(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put session id: %s",
+ __func__, ssh_err(r));
} else {
- buffer_put_string(&b, session_id2, session_id2_len);
+ if ((r = sshbuf_put_string(b, session_id2,
+ session_id2_len)) != 0)
+ fatal("%s: sshbuf_put_string session id: %s",
+ __func__, ssh_err(r));
}
/* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
- buffer_put_cstring(&b, userstyle);
- free(userstyle);
- buffer_put_cstring(&b,
- datafellows & SSH_BUG_PKSERVICE ?
- "ssh-userauth" :
- authctxt->service);
- if (datafellows & SSH_BUG_PKAUTH) {
- buffer_put_char(&b, have_sig);
+ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
+ (r = sshbuf_put_cstring(b, userstyle)) != 0 ||
+ (r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ?
+ "ssh-userauth" : authctxt->service)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
+ if (ssh->compat & SSH_BUG_PKAUTH) {
+ if ((r = sshbuf_put_u8(b, have_sig)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
} else {
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, have_sig);
- buffer_put_cstring(&b, pkalg);
+ if ((r = sshbuf_put_cstring(b, "publickey")) != 0 ||
+ (r = sshbuf_put_u8(b, have_sig)) != 0 ||
+ (r = sshbuf_put_cstring(b, pkalg) != 0))
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
}
- buffer_put_string(&b, pkblob, blen);
+ if ((r = sshbuf_put_string(b, pkblob, blen)) != 0)
+ fatal("%s: build packet failed: %s",
+ __func__, ssh_err(r));
#ifdef DEBUG_PK
- buffer_dump(&b);
+ sshbuf_dump(b, stderr);
#endif
- pubkey_auth_info(authctxt, key, NULL);
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
- buffer_len(&b))) == 1) {
+ PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
+ sshbuf_len(b), ssh->compat)) == 0) {
authenticated = 1;
- /* Record the successful key to prevent reuse */
- auth2_record_userkey(authctxt, key);
- key = NULL; /* Don't free below */
}
- buffer_free(&b);
+ sshbuf_free(b);
free(sig);
+ auth2_record_key(authctxt, authenticated, key);
} else {
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
__func__, sshkey_type(key), fp);
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
/* XXX fake reply and always send PK_OK ? */
/*
@@ -199,11 +219,13 @@ userauth_pubkey(Authctxt *authctxt)
* issue? -markus
*/
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
- packet_start(SSH2_MSG_USERAUTH_PK_OK);
- packet_put_string(pkalg, alen);
- packet_put_string(pkblob, blen);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
+ != 0 ||
+ (r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
+ (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ ssh_packet_write_wait(ssh);
authctxt->postponed = 1;
}
}
@@ -211,333 +233,14 @@ userauth_pubkey(Authctxt *authctxt)
auth_clear_options();
done:
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
- if (key != NULL)
- key_free(key);
+ sshkey_free(key);
+ free(userstyle);
free(pkalg);
free(pkblob);
free(fp);
return authenticated;
}
-void
-pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
-{
- char *fp, *extra;
- va_list ap;
- int i;
-
- extra = NULL;
- if (fmt != NULL) {
- va_start(ap, fmt);
- i = vasprintf(&extra, fmt, ap);
- va_end(ap);
- if (i < 0 || extra == NULL)
- fatal("%s: vasprintf failed", __func__);
- }
-
- if (key_is_cert(key)) {
- fp = sshkey_fingerprint(key->cert->signature_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
- auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
- key_type(key), key->cert->key_id,
- (unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- } else {
- fp = sshkey_fingerprint(key, options.fingerprint_hash,
- SSH_FP_DEFAULT);
- auth_info(authctxt, "%s %s%s%s", key_type(key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- }
- free(extra);
-}
-
-/*
- * Splits 's' into an argument vector. Handles quoted string and basic
- * escape characters (\\, \", \'). Caller must free the argument vector
- * and its members.
- */
-static int
-split_argv(const char *s, int *argcp, char ***argvp)
-{
- int r = SSH_ERR_INTERNAL_ERROR;
- int argc = 0, quote, i, j;
- char *arg, **argv = xcalloc(1, sizeof(*argv));
-
- *argvp = NULL;
- *argcp = 0;
-
- for (i = 0; s[i] != '\0'; i++) {
- /* Skip leading whitespace */
- if (s[i] == ' ' || s[i] == '\t')
- continue;
-
- /* Start of a token */
- quote = 0;
- if (s[i] == '\\' &&
- (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
- i++;
- else if (s[i] == '\'' || s[i] == '"')
- quote = s[i++];
-
- argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
- arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
- argv[argc] = NULL;
-
- /* Copy the token in, removing escapes */
- for (j = 0; s[i] != '\0'; i++) {
- if (s[i] == '\\') {
- if (s[i + 1] == '\'' ||
- s[i + 1] == '\"' ||
- s[i + 1] == '\\') {
- i++; /* Skip '\' */
- arg[j++] = s[i];
- } else {
- /* Unrecognised escape */
- arg[j++] = s[i];
- }
- } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
- break; /* done */
- else if (quote != 0 && s[i] == quote)
- break; /* done */
- else
- arg[j++] = s[i];
- }
- if (s[i] == '\0') {
- if (quote != 0) {
- /* Ran out of string looking for close quote */
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- break;
- }
- }
- /* Success */
- *argcp = argc;
- *argvp = argv;
- argc = 0;
- argv = NULL;
- r = 0;
- out:
- if (argc != 0 && argv != NULL) {
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
- }
- return r;
-}
-
-/*
- * Reassemble an argument vector into a string, quoting and escaping as
- * necessary. Caller must free returned string.
- */
-static char *
-assemble_argv(int argc, char **argv)
-{
- int i, j, ws, r;
- char c, *ret;
- struct sshbuf *buf, *arg;
-
- if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
-
- for (i = 0; i < argc; i++) {
- ws = 0;
- sshbuf_reset(arg);
- for (j = 0; argv[i][j] != '\0'; j++) {
- r = 0;
- c = argv[i][j];
- switch (c) {
- case ' ':
- case '\t':
- ws = 1;
- r = sshbuf_put_u8(arg, c);
- break;
- case '\\':
- case '\'':
- case '"':
- if ((r = sshbuf_put_u8(arg, '\\')) != 0)
- break;
- /* FALLTHROUGH */
- default:
- r = sshbuf_put_u8(arg, c);
- break;
- }
- if (r != 0)
- fatal("%s: sshbuf_put_u8: %s",
- __func__, ssh_err(r));
- }
- if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
- (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
- (r = sshbuf_putb(buf, arg)) != 0 ||
- (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- }
- if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
- fatal("%s: malloc failed", __func__);
- memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
- ret[sshbuf_len(buf)] = '\0';
- sshbuf_free(buf);
- sshbuf_free(arg);
- return ret;
-}
-
-/*
- * Runs command in a subprocess. Returns pid on success and a FILE* to the
- * subprocess' stdout or 0 on failure.
- * NB. "command" is only used for logging.
- */
-static pid_t
-subprocess(const char *tag, struct passwd *pw, const char *command,
- int ac, char **av, FILE **child)
-{
- FILE *f;
- struct stat st;
- int devnull, p[2], i;
- pid_t pid;
- char *cp, errmsg[512];
- u_int envsize;
- char **child_env;
-
- *child = NULL;
-
- debug3("%s: %s command \"%s\" running as %s", __func__,
- tag, command, pw->pw_name);
-
- /* Verify the path exists and is safe-ish to execute */
- if (*av[0] != '/') {
- error("%s path is not absolute", tag);
- return 0;
- }
- temporarily_use_uid(pw);
- if (stat(av[0], &st) < 0) {
- error("Could not stat %s \"%s\": %s", tag,
- av[0], strerror(errno));
- restore_uid();
- return 0;
- }
- if (auth_secure_path(av[0], &st, NULL, 0,
- errmsg, sizeof(errmsg)) != 0) {
- error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
- restore_uid();
- return 0;
- }
-
- /*
- * Run the command; stderr is left in place, stdout is the
- * authorized_keys output.
- */
- if (pipe(p) != 0) {
- error("%s: pipe: %s", tag, strerror(errno));
- restore_uid();
- return 0;
- }
-
- /*
- * 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", tag, strerror(errno));
- close(p[0]);
- close(p[1]);
- return 0;
- case 0: /* child */
- /* Prepare a minimal environment for the child. */
- envsize = 5;
- child_env = xcalloc(sizeof(*child_env), envsize);
- child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
- child_set_env(&child_env, &envsize, "USER", pw->pw_name);
- child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
- child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
- if ((cp = getenv("LANG")) != NULL)
- child_set_env(&child_env, &envsize, "LANG", cp);
-
- for (i = 0; i < NSIG; i++)
- signal(i, SIG_DFL);
-
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
- error("%s: open %s: %s", tag, _PATH_DEVNULL,
- strerror(errno));
- _exit(1);
- }
- /* Keep stderr around a while longer to catch errors */
- if (dup2(devnull, STDIN_FILENO) == -1 ||
- dup2(p[1], STDOUT_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
- closefrom(STDERR_FILENO + 1);
-
- /* Don't use permanently_set_uid() here to avoid fatal() */
- if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
- error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
- strerror(errno));
- _exit(1);
- }
- if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
- error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
- strerror(errno));
- _exit(1);
- }
- /* stdin is pointed to /dev/null at this point */
- if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
-
- execve(av[0], av, child_env);
- error("%s exec \"%s\": %s", tag, command, strerror(errno));
- _exit(127);
- default: /* parent */
- break;
- }
-
- close(p[1]);
- if ((f = fdopen(p[0], "r")) == NULL) {
- error("%s: fdopen: %s", tag, strerror(errno));
- close(p[0]);
- /* Don't leave zombie child */
- kill(pid, SIGTERM);
- while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
- ;
- return 0;
- }
- /* Success */
- debug3("%s: %s pid %ld", __func__, tag, (long)pid);
- *child = f;
- return pid;
-}
-
-/* Returns 0 if pid exited cleanly, non-zero otherwise */
-static int
-exited_cleanly(pid_t pid, const char *tag, const char *cmd)
-{
- int status;
-
- while (waitpid(pid, &status, 0) == -1) {
- if (errno != EINTR) {
- error("%s: waitpid: %s", tag, strerror(errno));
- return -1;
- }
- }
- if (WIFSIGNALED(status)) {
- error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
- return -1;
- } else if (WEXITSTATUS(status) != 0) {
- error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
- return -1;
- }
- return 0;
-}
-
static int
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
{
@@ -559,7 +262,7 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
}
static int
-process_principals(FILE *f, char *file, struct passwd *pw,
+process_principals(FILE *f, const char *file, struct passwd *pw,
const struct sshkey_cert *cert)
{
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
@@ -597,8 +300,7 @@ process_principals(FILE *f, char *file, struct passwd *pw,
for (i = 0; i < cert->nprincipals; i++) {
if (strcmp(cp, cert->principals[i]) == 0) {
debug3("%s:%lu: matched principal \"%.100s\"",
- file == NULL ? "(command)" : file,
- linenum, cert->principals[i]);
+ file, linenum, cert->principals[i]);
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
@@ -671,7 +373,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
}
/* Turn the command into an argument vector */
- if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
+ if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
error("AuthorizedPrincipalsCommand \"%s\" contains "
"invalid quotes", command);
goto out;
@@ -720,21 +422,22 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
av[i] = tmp;
}
/* Prepare a printable command for logs, etc. */
- command = assemble_argv(ac, av);
+ command = argv_assemble(ac, av);
if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
- ac, av, &f)) == 0)
+ ac, av, &f,
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
temporarily_use_uid(pw);
- ok = process_principals(f, NULL, pw, cert);
+ ok = process_principals(f, "(command)", pw, cert);
fclose(f);
f = NULL;
- if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
+ if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0)
goto out;
/* Read completed successfully */
@@ -761,26 +464,25 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
+check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
int found_key = 0;
u_long linenum = 0;
- Key *found;
-
- found_key = 0;
+ struct sshkey *found = NULL;
- found = NULL;
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp, *key_options = NULL, *fp = NULL;
const char *reason = NULL;
- /* Always consume entrire file */
+ /* Always consume entire file */
if (found_key)
continue;
if (found != NULL)
- key_free(found);
- found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
+ sshkey_free(found);
+ found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type);
+ if (found == NULL)
+ goto done;
auth_clear_options();
/* Skip leading whitespace, empty and comment lines. */
@@ -789,7 +491,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
if (!*cp || *cp == '\n' || *cp == '#')
continue;
- if (key_read(found, &cp) != 1) {
+ if (sshkey_read(found, &cp) != 0) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
@@ -803,14 +505,14 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
- if (key_read(found, &cp) != 1) {
+ if (sshkey_read(found, &cp) != 0) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
- if (key_is_cert(key)) {
- if (!key_equal(found, key->cert->signature_key))
+ if (sshkey_is_cert(key)) {
+ if (!sshkey_equal(found, key->cert->signature_key))
continue;
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
@@ -821,7 +523,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching CA found: file %s, line %lu, %s %s",
- file, linenum, key_type(found), fp);
+ file, linenum, sshkey_type(found), fp);
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
@@ -838,7 +540,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
auth_debug_add("%s", reason);
continue;
}
- if (key_cert_check_authority(key, 0, 0,
+ if (sshkey_cert_check_authority(key, 0, 0,
authorized_principals == NULL ? pw->pw_name : NULL,
&reason) != 0)
goto fail_reason;
@@ -847,11 +549,11 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
verbose("Accepted certificate ID \"%s\" (serial %llu) "
"signed by %s CA %s via %s", key->cert->key_id,
(unsigned long long)key->cert->serial,
- key_type(found), fp, file);
+ sshkey_type(found), fp, file);
free(fp);
found_key = 1;
break;
- } else if (key_equal(found, key)) {
+ } else if (sshkey_equal(found, key)) {
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
@@ -861,14 +563,15 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
- file, linenum, key_type(found), fp);
+ file, linenum, sshkey_type(found), fp);
free(fp);
found_key = 1;
continue;
}
}
+ done:
if (found != NULL)
- key_free(found);
+ sshkey_free(found);
if (!found_key)
debug2("key not found");
return found_key;
@@ -876,24 +579,24 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
/* Authenticate a certificate key against TrustedUserCAKeys */
static int
-user_cert_trusted_ca(struct passwd *pw, Key *key)
+user_cert_trusted_ca(struct passwd *pw, struct sshkey *key)
{
char *ca_fp, *principals_file = NULL;
const char *reason;
- int ret = 0, found_principal = 0, use_authorized_principals;
+ int r, ret = 0, found_principal = 0, use_authorized_principals;
- if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+ if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
return 0;
- if (sshkey_in_file(key->cert->signature_key,
- options.trusted_user_ca_keys, 1, 0) != 0) {
- debug2("%s: CA %s %s is not listed in %s", __func__,
- key_type(key->cert->signature_key), ca_fp,
- options.trusted_user_ca_keys);
+ if ((r = sshkey_in_file(key->cert->signature_key,
+ options.trusted_user_ca_keys, 1, 0)) != 0) {
+ debug2("%s: CA %s %s is not listed in %s: %s", __func__,
+ sshkey_type(key->cert->signature_key), ca_fp,
+ options.trusted_user_ca_keys, ssh_err(r));
goto out;
}
/*
@@ -918,7 +621,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
auth_debug_add("%s", reason);
goto out;
}
- if (key_cert_check_authority(key, 0, 1,
+ if (sshkey_cert_check_authority(key, 0, 1,
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw, &reason) != 0)
@@ -927,7 +630,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
"%s CA %s via %s", key->cert->key_id,
(unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key), ca_fp,
+ sshkey_type(key->cert->signature_key), ca_fp,
options.trusted_user_ca_keys);
ret = 1;
@@ -942,7 +645,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file)
{
FILE *f;
int found_key = 0;
@@ -965,7 +668,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
-user_key_command_allowed2(struct passwd *user_pw, Key *key)
+user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
{
FILE *f = NULL;
int r, ok, found_key = 0;
@@ -1011,7 +714,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
}
/* Turn the command into an argument vector */
- if (split_argv(options.authorized_keys_command, &ac, &av) != 0) {
+ if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
command);
goto out;
@@ -1035,7 +738,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
av[i] = tmp;
}
/* Prepare a printable command for logs, etc. */
- command = assemble_argv(ac, av);
+ command = argv_assemble(ac, av);
/*
* If AuthorizedKeysCommand was run without arguments
@@ -1052,7 +755,8 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
}
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
- ac, av, &f)) == 0)
+ ac, av, &f,
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
@@ -1063,7 +767,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
fclose(f);
f = NULL;
- if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
+ if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0)
goto out;
/* Read completed successfully */
@@ -1088,14 +792,15 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
* Check whether key authenticates and authorises the user.
*/
int
-user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
+user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
{
u_int success, i;
char *file;
if (auth_key_is_revoked(key))
return 0;
- if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+ if (sshkey_is_cert(key) &&
+ auth_key_is_revoked(key->cert->signature_key))
return 0;
success = user_cert_trusted_ca(pw, key);
@@ -1120,35 +825,6 @@ user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
return success;
}
-/* Records a public key in the list of previously-successful keys */
-void
-auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
-{
- struct sshkey **tmp;
-
- if (authctxt->nprev_userkeys >= INT_MAX ||
- (tmp = reallocarray(authctxt->prev_userkeys,
- authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL)
- fatal("%s: reallocarray failed", __func__);
- authctxt->prev_userkeys = tmp;
- authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
- authctxt->nprev_userkeys++;
-}
-
-/* Checks whether a key has already been used successfully for authentication */
-int
-auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
-{
- u_int i;
-
- for (i = 0; i < authctxt->nprev_userkeys; i++) {
- if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
- return 1;
- }
- }
- return 0;
-}
-
Authmethod method_pubkey = {
"publickey",
userauth_pubkey,