diff options
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r-- | auth2-pubkey.c | 580 |
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, |