diff --git a/Sources/openssh-apple/main.swift b/Sources/openssh-apple/main.swift index d75bb1c..f0f6f9e 100644 --- a/Sources/openssh-apple/main.swift +++ b/Sources/openssh-apple/main.swift @@ -5,17 +5,17 @@ OutputLevel.default = .error enum Config { static let opensshOrigin = "https://github.com/openssh/openssh-portable.git" - static let opensshBranch = "V_8_6" - static let opensshVersion = "8.6.0" + static let opensshBranch = "V_8_9" + static let opensshVersion = "8.9.0" static let opensslLibsURL = "https://github.com/blinksh/openssl-apple/releases/download/v1.1.1k/openssl-libs.zip" static let opensslFrameworksURL = "https://github.com/blinksh/openssl-apple/releases/download/v1.1.1k/openssl-dynamic.frameworks.zip" static let frameworkName = "OpenSSH" - static let platforms: [Platform] = Platform.allCases - // static let platforms: [Platform] = [.iPhoneOS] - // static let platforms: [Platform] = [Platform.Catalyst] + //static let platforms: [Platform] = Platform.allCases + static let platforms: [Platform] = [.iPhoneOS, .iPhoneSimulator] + //static let platforms: [Platform] = [Platform.MacOSX] } extension Platform { @@ -32,11 +32,11 @@ extension Platform { try? sh("rm -rf openssh-portable") try sh("git clone --depth 1 \(Config.opensshOrigin) --branch \(Config.opensshBranch)") try sh("LC_CTYPE=C find ./openssh-portable -type f -exec sed -i '' -e 's/__progname/blink__progname/' {} \\;") -try sh("cp -f readpass.c sshkey.h authfd.h log.c ssh-sk-helper.c misc.c openssh-portable/") try sh("LC_CTYPE=C find ./openssh-portable -type f -exec sed -i '' -e 's/ssh_init(/openssh_init(/' {} \\;") try sh("LC_CTYPE=C find ./openssh-portable -type f -exec sed -i '' -e 's/ssh_free(/openssh_free(/' {} \\;") try sh("LC_CTYPE=C find ./openssh-portable -type f -exec sed -i '' -e 's/match_pattern_list(/openssh_match_pattern_list(/' {} \\;") try sh("LC_CTYPE=C find ./openssh-portable -type f -exec sed -i '' -e 's/match_hostname(/openssh_match_hostname(/' {} \\;") +try sh("cp -f authfd.h log.c misc.c readpass.c ssh-sk-helper.c ssh-sk.h sshkey.h openssh-portable/") try download(url: Config.opensslLibsURL) try? sh("rm -rf openssl") @@ -278,4 +278,4 @@ let releaseMD = | \(xcframeworkdStaticZipName) | \(try sha(path: xcframeworkdStaticZipName)) | """ -try write(content: releaseMD, atPath: "release.md") \ No newline at end of file +try write(content: releaseMD, atPath: "release.md") diff --git a/authfd.h b/authfd.h index 34ea8f9..56c1e68 100644 --- a/authfd.h +++ b/authfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.49 2020/06/26 05:03:36 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.51 2021/12/19 22:10:24 djm Exp $ */ /* * Author: Tatu Ylonen @@ -18,6 +18,9 @@ #include +struct sshbuf; +struct sshkey; + /* List of identities returned by ssh_fetch_identitylist() */ struct ssh_identitylist { size_t nkeys; @@ -25,6 +28,20 @@ struct ssh_identitylist { char **comments; }; +/* Key destination restrictions */ +struct dest_constraint_hop { + char *user; /* wildcards allowed */ + char *hostname; /* used to matching cert principals and for display */ + int is_ca; + u_int nkeys; /* number of entries in *both* 'keys' and 'key_is_ca' */ + struct sshkey **keys; + int *key_is_ca; +}; +struct dest_constraint { + struct dest_constraint_hop from; + struct dest_constraint_hop to; +}; + int ssh_get_authentication_socket(int *fdp); int ssh_get_authentication_socket_path(const char *authsocket, int *fdp); void ssh_close_authentication_socket(int sock); @@ -33,18 +50,25 @@ int ssh_lock_agent(int sock, int lock, const char *password); int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); void ssh_free_identitylist(struct ssh_identitylist *idl); int ssh_add_identity_constrained(int sock, struct sshkey *key, - const char *comment, u_int life, u_int confirm, u_int maxsign, - const char *provider); + const char *comment, u_int life, u_int confirm, u_int maxsign, + const char *provider, struct dest_constraint **dest_constraints, + size_t ndest_constraints); int ssh_agent_has_key(int sock, const struct sshkey *key); int ssh_remove_identity(int sock, const struct sshkey *key); int ssh_update_card(int sock, int add, const char *reader_id, - const char *pin, u_int life, u_int confirm); + const char *pin, u_int life, u_int confirm, + struct dest_constraint **dest_constraints, + size_t ndest_constraints); int ssh_remove_all_identities(int sock, int version); int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat); +int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, + const struct sshbuf *session_id, const struct sshbuf *signature, + int forwarding); + /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 @@ -78,6 +102,9 @@ int ssh_agent_sign(int sock, const struct sshkey *key, #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 +/* generic extension mechanism */ +#define SSH_AGENTC_EXTENSION 27 + #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 #define SSH_AGENT_CONSTRAIN_MAXSIGN 3 diff --git a/log.c b/log.c index ee7727a..359b110 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.58 2021/04/15 16:24:31 markus Exp $ */ +/* $OpenBSD: log.c,v 1.60 2021/09/16 15:11:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -346,6 +346,7 @@ do_log(LogLevel level, int force, const char *suffix, const char *fmt, int pri = LOG_INFO; int saved_errno = errno; log_handler_fn *tmp_handler; + const char *progname = argv0 != NULL ? argv0 : blink__progname; if (!force && level > log_level) return; @@ -403,16 +404,18 @@ do_log(LogLevel level, int force, const char *suffix, const char *fmt, tmp_handler(level, force, fmtbuf, log_handler_ctx); log_handler = tmp_handler; } else if (log_on_stderr) { - snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n", + snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n", + (log_on_stderr > 1) ? progname : "", + (log_on_stderr > 1) ? ": " : "", (int)sizeof msgbuf - 3, fmtbuf); (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) - openlog_r(argv0 ? argv0 : blink__progname, LOG_PID, log_facility, &sdata); + openlog_r(blink__progname, LOG_PID, log_facility, &sdata); syslog_r(pri, &sdata, "%.500s", fmtbuf); closelog_r(&sdata); #else - openlog(argv0 ? argv0 : blink__progname, LOG_PID, log_facility); + openlog(blink__progname, LOG_PID, log_facility); syslog(pri, "%.500s", fmtbuf); closelog(); #endif @@ -466,10 +469,11 @@ sshlogv(const char *file, const char *func, int line, int showfunc, const char *cp; size_t i; - snprintf(tag, sizeof(tag), "%.48s:%.48s():%d", - (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line); + snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)", + (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, + (long)getpid()); for (i = 0; i < nlog_verbose; i++) { - if (match_pattern_list(tag, log_verbose[i], 0) == 1) { + if (openssh_match_pattern_list(tag, log_verbose[i], 0) == 1) { forced = 1; break; } @@ -493,4 +497,4 @@ sshlogdirect(LogLevel level, int forced, const char *fmt, ...) va_start(args, fmt); do_log(level, forced, NULL, fmt, args); va_end(args); -} \ No newline at end of file +} diff --git a/misc.c b/misc.c index 6fc1790..4cb3e46 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.164 2021/04/03 06:18:40 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.174 2022/02/11 00:43:56 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -56,6 +56,7 @@ #ifdef HAVE_PATHS_H # include #include +#include #endif #ifdef SSH_TUN_OPENBSD #include @@ -85,6 +86,20 @@ chop(char *s) } +/* remove whitespace from end of string */ +void +rtrim(char *s) +{ + size_t i; + + if ((i = strlen(s)) == 0) + return; + for (i--; i > 0; i--) { + if (isspace((int)s[i])) + s[i] = '\0'; + } +} + /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) @@ -445,7 +460,7 @@ pwcopy(struct passwd *pw) struct passwd *copy = xcalloc(1, sizeof(*copy)); copy->pw_name = xstrdup(pw->pw_name); - copy->pw_passwd = xstrdup(pw->pw_passwd); + copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd); #ifdef HAVE_STRUCT_PASSWD_PW_GECOS copy->pw_gecos = xstrdup(pw->pw_gecos); #endif @@ -704,10 +719,16 @@ hpdelim2(char **cp, char *delim) return old; } +/* The common case: only accept colon as delimiter. */ char * hpdelim(char **cp) { - return hpdelim2(cp, NULL); + char *r, delim = '\0'; + + r = hpdelim2(cp, &delim); + if (delim == '/') + return NULL; + return r; } char * @@ -1101,45 +1122,82 @@ freeargs(arglist *args) * Expands tildes in the file name. Returns data allocated by xmalloc. * Warning: this calls getpw*. */ -char * -tilde_expand_filename(const char *filename, uid_t uid) +int +tilde_expand(const char *filename, uid_t uid, char **retp) { - const char *path, *sep; - char user[128], *ret; + char *ocopy = NULL, *copy, *s = NULL; + const char *path = NULL, *user = NULL; struct passwd *pw; - u_int len, slash; - - if (*filename != '~') - return (xstrdup(filename)); - filename++; - - path = strchr(filename, '/'); - if (path != NULL && path > filename) { /* ~user/path */ - slash = path - filename; - if (slash > sizeof(user) - 1) - fatal("tilde_expand_filename: ~username too long"); - memcpy(user, filename, slash); - user[slash] = '\0'; - if ((pw = getpwnam(user)) == NULL) - fatal("tilde_expand_filename: No such user %s", user); - } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ - fatal("tilde_expand_filename: No such uid %ld", (long)uid); + size_t len; + int ret = -1, r, slash; + + *retp = NULL; + if (*filename != '~') { + *retp = xstrdup(filename); + return 0; + } + ocopy = copy = xstrdup(filename + 1); + + if (*copy == '\0') /* ~ */ + path = NULL; + else if (*copy == '/') { + copy += strspn(copy, "/"); + if (*copy == '\0') + path = NULL; /* ~/ */ + else + path = copy; /* ~/path */ + } else { + user = copy; + if ((path = strchr(copy, '/')) != NULL) { + copy[path - copy] = '\0'; + path++; + path += strspn(path, "/"); + if (*path == '\0') /* ~user/ */ + path = NULL; + /* else ~user/path */ + } + /* else ~user */ + } + if (user != NULL) { + if ((pw = getpwnam(user)) == NULL) { + error_f("No such user %s", user); + goto out; + } + } else if ((pw = getpwuid(uid)) == NULL) { + error_f("No such uid %ld", (long)uid); + goto out; + } /* Make sure directory has a trailing '/' */ - len = strlen(pw->pw_dir); - if (len == 0 || pw->pw_dir[len - 1] != '/') - sep = "/"; - else - sep = ""; + slash = (len = strlen(pw->pw_dir)) == 0 || pw->pw_dir[len - 1] != '/'; - /* Skip leading '/' from specified path */ - if (path != NULL) - filename = path + 1; + if ((r = xasprintf(&s, "%s%s%s", pw->pw_dir, + slash ? "/" : "", path != NULL ? path : "")) <= 0) { + error_f("xasprintf failed"); + goto out; + } + if (r >= PATH_MAX) { + error_f("Path too long"); + goto out; + } + /* success */ + ret = 0; + *retp = s; + s = NULL; + out: + free(s); + free(ocopy); + return ret; +} - if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) - fatal("tilde_expand_filename: Path too long"); +char * +tilde_expand_filename(const char *filename, uid_t uid) +{ + char *ret; - return (ret); + if (tilde_expand(filename, uid, &ret) != 0) + cleanup_exit(255); + return ret; } /* @@ -1580,12 +1638,12 @@ ms_subtract_diff(struct timeval *start, int *ms) } void -ms_to_timeval(struct timeval *tv, int ms) +ms_to_timespec(struct timespec *ts, int ms) { if (ms < 0) ms = 0; - tv->tv_sec = ms / 1000; - tv->tv_usec = (ms % 1000) * 1000; + ts->tv_sec = ms / 1000; + ts->tv_nsec = (ms % 1000) * 1000 * 1000; } void @@ -1912,14 +1970,13 @@ daemonized(void) return 1; } - /* * Splits 's' into an argument vector. Handles quoted string and basic * escape characters (\\, \", \'). Caller must free the argument vector * and its members. */ int -argv_split(const char *s, int *argcp, char ***argvp) +argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment) { int r = SSH_ERR_INTERNAL_ERROR; int argc = 0, quote, i, j; @@ -1932,7 +1989,8 @@ argv_split(const char *s, int *argcp, char ***argvp) /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; - + if (terminate_on_comment && s[i] == '#') + break; /* Start of a token */ quote = 0; @@ -1945,7 +2003,8 @@ argv_split(const char *s, int *argcp, char ***argvp) if (s[i] == '\\') { if (s[i + 1] == '\'' || s[i + 1] == '\"' || - s[i + 1] == '\\') { + s[i + 1] == '\\' || + (quote == 0 && s[i + 1] == ' ')) { i++; /* Skip '\' */ arg[j++] = s[i]; } else { @@ -2039,6 +2098,36 @@ argv_assemble(int argc, char **argv) return ret; } +char * +argv_next(int *argcp, char ***argvp) +{ + char *ret = (*argvp)[0]; + + if (*argcp > 0 && ret != NULL) { + (*argcp)--; + (*argvp)++; + } + return ret; +} + +void +argv_consume(int *argcp) +{ + *argcp = 0; +} + +void +argv_free(char **av, int ac) +{ + int i; + + if (av == NULL) + return; + for (i = 0; i < ac; i++) + free(av[i]); + free(av); +} + /* Returns 0 if pid exited cleanly, non-zero otherwise */ int exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) @@ -2338,10 +2427,13 @@ parse_absolute_time(const char *s, uint64_t *tp) return 0; } +/* On OpenBSD time_t is int64_t which is long long. */ +/* #define SSH_TIME_T_MAX LLONG_MAX */ + void format_absolute_time(uint64_t t, char *buf, size_t len) { - time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */ + time_t tt = t > SSH_TIME_T_MAX ? SSH_TIME_T_MAX : t; struct tm tm; localtime_r(&tt, &tm); @@ -2517,5 +2609,21 @@ subprocess(const char *tag, const char *command, int ac, char **av, FILE **child, u_int flags, struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) { - return 0; + // Blink disabled + return 0; +} + +const char * +lookup_env_in_list(const char *env, char * const *envs, size_t nenvs) +{ + size_t i, envlen; + + envlen = strlen(env); + for (i = 0; i < nenvs; i++) { + if (strncmp(envs[i], env, envlen) == 0 && + envs[i][envlen] == '=') { + return envs[i] + envlen + 1; + } + } + return NULL; } diff --git a/readpass.c b/readpass.c index f01798e..f4c2ea0 100644 --- a/readpass.c +++ b/readpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.c,v 1.63 2020/08/11 09:45:54 djm Exp $ */ +/* $OpenBSD: readpass.c,v 1.69 2021/07/23 05:56:47 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -50,19 +50,36 @@ static char * ssh_askpass(char *askpass, const char *msg, const char *env_hint) { - return NULL; + // Blink disabled + return NULL; } +/* + * Reads a passphrase from /dev/tty with echo turned off/on. Returns the + * passphrase (allocated with xmalloc). Exits if EOF is encountered. If + * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no + * tty is or askpass program is available + */ char * read_passphrase(const char *prompt, int flags) { - return NULL; + // Blink disabled + return NULL; } int ask_permission(const char *fmt, ...) { - return 0; + // Blink disabled + return 0; +} + +static void +writemsg(const char *msg) +{ + (void)write(STDERR_FILENO, "\r", 1); + (void)write(STDERR_FILENO, msg, strlen(msg)); + (void)write(STDERR_FILENO, "\r\n", 2); } struct notifier_ctx { @@ -73,10 +90,12 @@ struct notifier_ctx { struct notifier_ctx * notify_start(int force_askpass, const char *fmt, ...) { - return NULL; + // Blink disabled + return NULL; } void notify_complete(struct notifier_ctx *ctx, const char *fmt, ...) { + // Blink disabled } diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c index 3931bd5..d392978 100644 --- a/ssh-sk-helper.c +++ b/ssh-sk-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk-helper.c,v 1.10 2020/05/26 01:59:46 djm Exp $ */ +/* $OpenBSD: ssh-sk-helper.c,v 1.12 2021/10/28 02:54:18 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -67,7 +67,7 @@ reply_error(int r, char *fmt, ...) free(msg); if (r >= 0) - fatal("%s: invalid error code %d", __func__, r); + fatal_f("invalid error code %d", r); if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", blink__progname); @@ -106,17 +106,19 @@ process_sign(struct sshbuf *req) (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */ (r = sshbuf_get_u32(req, &compat)) != 0 || (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: parse", blink__progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", blink__progname); if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) - fatal("Unable to parse private key: %s", ssh_err(r)); - if (!sshkey_is_sk(key)) - fatal("Unsupported key type %s", sshkey_ssh_name(key)); + fatal_r(r, "%s: Unable to parse private key", blink__progname); + if (!sshkey_is_sk(key)) { + fatal("%s: Unsupported key type %s", + blink__progname, sshkey_ssh_name(key)); + } - debug("%s: ready to sign with key %s, provider %s: " - "msg len %zu, compat 0x%lx", blink__progname, sshkey_type(key), + debug_f("ready to sign with key %s, provider %s: " + "msg len %zu, compat 0x%lx", sshkey_type(key), provider, msglen, (u_long)compat); null_empty(&pin); @@ -132,7 +134,7 @@ process_sign(struct sshbuf *req) if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 || (r = sshbuf_put_string(resp, sig, siglen)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: compose", blink__progname); out: sshkey_free(key); sshbuf_free(kbuf); @@ -166,7 +168,7 @@ process_enroll(struct sshbuf *req) (r = sshbuf_get_u8(req, &flags)) != 0 || (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || (r = sshbuf_froms(req, &challenge)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: parse", blink__progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", blink__progname); @@ -189,11 +191,11 @@ process_enroll(struct sshbuf *req) if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", blink__progname); if ((r = sshkey_private_serialize(key, kbuf)) != 0) - fatal("%s: serialize private key: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: encode key", blink__progname); if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 || (r = sshbuf_put_stringb(resp, kbuf)) != 0 || (r = sshbuf_put_stringb(resp, attest)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: compose", blink__progname); out: sshkey_free(key); @@ -214,25 +216,27 @@ process_load_resident(struct sshbuf *req) int r; char *provider, *pin, *device; struct sshbuf *kbuf, *resp; - struct sshkey **keys = NULL; - size_t nkeys = 0, i; + struct sshsk_resident_key **srks = NULL; + size_t nsrks = 0, i; + u_int flags; if ((kbuf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", blink__progname); if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || + (r = sshbuf_get_u32(req, &flags)) != 0) + fatal_r(r, "%s: parse", blink__progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", blink__progname); null_empty(&device); null_empty(&pin); - if ((r = sshsk_load_resident(provider, device, pin, - &keys, &nkeys)) != 0) { - resp = reply_error(r, " sshsk_load_resident failed: %s", + if ((r = sshsk_load_resident(provider, device, pin, flags, + &srks, &nsrks)) != 0) { + resp = reply_error(r, "sshsk_load_resident failed: %s", ssh_err(r)); goto out; } @@ -241,24 +245,24 @@ process_load_resident(struct sshbuf *req) fatal("%s: sshbuf_new failed", blink__progname); if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + fatal_r(r, "%s: compose", blink__progname); - for (i = 0; i < nkeys; i++) { - debug("%s: key %zu %s %s", __func__, i, - sshkey_type(keys[i]), keys[i]->sk_application); + for (i = 0; i < nsrks; i++) { + debug_f("key %zu %s %s uidlen %zu", i, + sshkey_type(srks[i]->key), srks[i]->key->sk_application, + srks[i]->user_id_len); sshbuf_reset(kbuf); - if ((r = sshkey_private_serialize(keys[i], kbuf)) != 0) - fatal("%s: serialize private key: %s", - blink__progname, ssh_err(r)); + if ((r = sshkey_private_serialize(srks[i]->key, kbuf)) != 0) + fatal_r(r, "%s: encode key", blink__progname); if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 || - (r = sshbuf_put_cstring(resp, "")) != 0) /* comment */ - fatal("%s: buffer error: %s", blink__progname, ssh_err(r)); + (r = sshbuf_put_cstring(resp, "")) != 0 || /* comment */ + (r = sshbuf_put_string(resp, srks[i]->user_id, + srks[i]->user_id_len)) != 0) + fatal_r(r, "%s: compose key", blink__progname); } out: - for (i = 0; i < nkeys; i++) - sshkey_free(keys[i]); - free(keys); + sshsk_free_resident_keys(srks, nsrks); sshbuf_free(kbuf); free(provider); if (pin != NULL) @@ -266,8 +270,11 @@ process_load_resident(struct sshbuf *req) return resp; } -int main() { - return 0; +int +main(int argc, char **argv) +{ + // Blink disabled + return (0); } -#endif /* ENABLE_SK */ +#endif diff --git a/ssh-sk.h b/ssh-sk.h new file mode 100644 index 0000000..c2a9a5e --- /dev/null +++ b/ssh-sk.h @@ -0,0 +1,81 @@ +/* $OpenBSD: ssh-sk.h,v 1.11 2021/10/28 02:54:18 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SSH_SK_H +#define _SSH_SK_H 1 + +#include + +struct sshbuf; +struct sshkey; +struct sk_option; + +/* Version of protocol expected from ssh-sk-helper */ +#define SSH_SK_HELPER_VERSION 5 + +/* ssh-sk-helper messages */ +#define SSH_SK_HELPER_ERROR 0 /* Only valid H->C */ +#define SSH_SK_HELPER_SIGN 1 +#define SSH_SK_HELPER_ENROLL 2 +#define SSH_SK_HELPER_LOAD_RESIDENT 3 + +struct sshsk_resident_key { + struct sshkey *key; + uint8_t *user_id; + size_t user_id_len; +}; + +/* + * Enroll (generate) a new security-key hosted private key of given type + * via the specified provider middleware. + * If challenge_buf is NULL then a random 256 bit challenge will be used. + * + * Returns 0 on success or a ssherr.h error code on failure. + * + * If successful and the attest_data buffer is not NULL then attestation + * information is placed there. + */ +int sshsk_enroll(int type, const char *provider_path, const char *device, + const char *application, const char *userid, uint8_t flags, + const char *pin, struct sshbuf *challenge_buf, + struct sshkey **keyp, struct sshbuf *attest); + +/* + * Calculate an ECDSA_SK or ED25519_SK signature using the specified key + * and provider middleware. + * + * Returns 0 on success or a ssherr.h error code on failure. + */ +int sshsk_sign(const char *provider_path, struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, + u_int compat, const char *pin); + +/* + * Enumerates and loads all SSH-compatible resident keys from a security + * key. + * + * Returns 0 on success or a ssherr.h error code on failure. + */ +int sshsk_load_resident(const char *provider_path, const char *device, + const char *pin, u_int flags, struct sshsk_resident_key ***srksp, + size_t *nsrksp); + +/* Free an array of sshsk_resident_key (as returned from sshsk_load_resident) */ +void sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks); + +#endif /* _SSH_SK_H */ + diff --git a/sshkey.h b/sshkey.h index fa7f404..c2e139c 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.49 2021/01/26 00:49:30 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.51 2022/01/06 22:05:42 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -28,6 +28,7 @@ #include #include +#include #ifdef WITH_OPENSSL #include @@ -193,10 +194,16 @@ int sshkey_is_cert(const struct sshkey *); int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); int sshkey_type_plain(int); + +/* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ +int sshkey_match_keyname_to_sigalgs(const char *, const char *); + int sshkey_to_certified(struct sshkey *); int sshkey_drop_cert(struct sshkey *); int sshkey_cert_copy(const struct sshkey *, struct sshkey *); int sshkey_cert_check_authority(const struct sshkey *, int, int, int, + uint64_t, const char *, const char **); +int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int, const char *, const char **); int sshkey_cert_check_host(const struct sshkey *, const char *, int , const char *, const char **); @@ -330,4 +337,4 @@ int ssh_xmss_verify(const struct sshkey *key, # undef EC_POINT #endif -#endif /* SSHKEY_H */ \ No newline at end of file +#endif /* SSHKEY_H */