From 5e39a49930d885aac9c76af3129332b6e772cd75 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 4 Dec 2014 02:24:32 +0000 Subject: upstream commit add RevokedHostKeys option for the client Allow textfile or KRL-based revocation of hostkeys. --- auth2-pubkey.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth2-pubkey.c b/auth2-pubkey.c index f3ca96592..0a3c1deee 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.42 2014/12/04 02:24:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -434,8 +434,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) ca_fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5, SSH_FP_HEX); - if (key_in_file(key->cert->signature_key, - options.trusted_user_ca_keys, 1) != 1) { + 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); -- cgit v1.2.3 From 56d1c83cdd1ac76f1c6bd41e01e80dad834f3994 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sun, 21 Dec 2014 22:27:55 +0000 Subject: upstream commit Add FingerprintHash option to control algorithm used for key fingerprints. Default changes from MD5 to SHA256 and format from hex to base64. Feedback and ok naddy@ markus@ --- auth-rsa.c | 5 ++- auth.c | 5 ++- auth2-hostbased.c | 7 ++-- auth2-pubkey.c | 16 ++++---- digest-libc.c | 22 ++++++++++- digest-openssl.c | 22 ++++++++++- digest.h | 8 +++- dns.c | 11 +++--- key.c | 7 ++-- key.h | 4 +- krl.c | 8 ++-- readconf.c | 24 +++++++++++- readconf.h | 4 +- servconf.c | 24 +++++++++++- servconf.h | 4 +- ssh-add.1 | 13 ++++++- ssh-add.c | 54 +++++++++++++++++++------- ssh-agent.1 | 13 ++++++- ssh-agent.c | 15 ++++++-- ssh-keygen.1 | 13 ++++++- ssh-keygen.c | 58 +++++++++++++++++----------- ssh-keysign.c | 5 ++- ssh.1 | 6 +-- sshconnect.c | 27 +++++++------ sshconnect2.c | 6 +-- sshd_config.5 | 13 ++++++- sshkey.c | 113 ++++++++++++++++++++++++++++++++++++------------------ sshkey.h | 16 ++++---- 28 files changed, 374 insertions(+), 149 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth-rsa.c b/auth-rsa.c index e9f4ede26..ff7a13221 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.89 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -236,7 +236,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(key), fp); free(fp); diff --git a/auth.c b/auth.c index 348ddc398..b259c6ef1 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.107 2014/12/04 02:24:32 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.108 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -679,7 +679,8 @@ auth_key_is_revoked(Key *key) if (options.revoked_keys_file == NULL) return 0; - if ((fp = sshkey_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX)) == NULL) { + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) { r = SSH_ERR_ALLOC_FAIL; error("%s: fingerprint key: %s", __func__, ssh_err(r)); goto out; diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 6787e4ca4..b7ae35356 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.19 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -208,13 +208,14 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, if (host_status == HOST_OK) { if (key_is_cert(key)) { fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + options.fingerprint_hash, SSH_FP_DEFAULT); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, key_type(key->cert->signature_key), fp, cuser, lookup); } else { - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); verbose("Accepted %s public key %s from %s@%s", key_type(key), fp, cuser, lookup); } diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 0a3c1deee..04b70e362 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.42 2014/12/04 02:24:32 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -213,7 +213,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) if (key_is_cert(key)) { fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + 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, @@ -221,7 +221,8 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } else { - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); auth_info(authctxt, "%s %s%s%s", key_type(key), fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); @@ -365,8 +366,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) continue; if (!key_is_cert_authority) continue; - fp = key_fingerprint(found, SSH_FP_MD5, - SSH_FP_HEX); + fp = key_fingerprint(found, options.fingerprint_hash, + SSH_FP_DEFAULT); debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); /* @@ -406,7 +407,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) if (key_is_cert_authority) continue; found_key = 1; - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(found, options.fingerprint_hash, + SSH_FP_DEFAULT); debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(found), fp); free(fp); @@ -432,7 +434,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) return 0; ca_fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + options.fingerprint_hash, SSH_FP_DEFAULT); if (sshkey_in_file(key->cert->signature_key, options.trusted_user_ca_keys, 1, 0) != 0) { diff --git a/digest-libc.c b/digest-libc.c index 1b4423a05..169ded075 100644 --- a/digest-libc.c +++ b/digest-libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */ +/* $OpenBSD: digest-libc.c,v 1.4 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. @@ -126,6 +126,26 @@ ssh_digest_by_alg(int alg) return &(digests[alg]); } +int +ssh_digest_alg_by_name(const char *name) +{ + int alg; + + for (alg = 0; alg < SSH_DIGEST_MAX; alg++) { + if (strcasecmp(name, digests[alg].name) == 0) + return digests[alg].id; + } + return -1; +} + +const char * +ssh_digest_alg_name(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + + return digest == NULL ? NULL : digest->name; +} + size_t ssh_digest_bytes(int alg) { diff --git a/digest-openssl.c b/digest-openssl.c index 02b170341..bb58ff226 100644 --- a/digest-openssl.c +++ b/digest-openssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-openssl.c,v 1.4 2014/07/03 03:26:43 djm Exp $ */ +/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -74,6 +74,26 @@ ssh_digest_by_alg(int alg) return &(digests[alg]); } +int +ssh_digest_alg_by_name(const char *name) +{ + int alg; + + for (alg = 0; digests[alg].id != -1; alg++) { + if (strcasecmp(name, digests[alg].name) == 0) + return digests[alg].id; + } + return -1; +} + +const char * +ssh_digest_alg_name(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + + return digest == NULL ? NULL : digest->name; +} + size_t ssh_digest_bytes(int alg) { diff --git a/digest.h b/digest.h index 6afb197f0..3fe073468 100644 --- a/digest.h +++ b/digest.h @@ -1,4 +1,4 @@ -/* $OpenBSD: digest.h,v 1.6 2014/07/03 04:36:45 djm Exp $ */ +/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -33,6 +33,12 @@ struct sshbuf; struct ssh_digest_ctx; +/* Looks up a digest algorithm by name */ +int ssh_digest_alg_by_name(const char *name); + +/* Returns the algorithm name for a digest identifier */ +const char *ssh_digest_alg_name(int alg); + /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_digest_bytes(int alg); diff --git a/dns.c b/dns.c index c4d073cf5..4b8ae44cf 100644 --- a/dns.c +++ b/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */ +/* $OpenBSD: dns.c,v 1.32 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -41,6 +41,7 @@ #include "key.h" #include "dns.h" #include "log.h" +#include "digest.h" static const char *errset_text[] = { "success", /* 0 ERRSET_SUCCESS */ @@ -80,7 +81,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, u_char **digest, u_int *digest_len, Key *key) { int success = 0; - enum fp_type fp_type = 0; + int fp_alg = -1; switch (key->type) { case KEY_RSA: @@ -110,17 +111,17 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, switch (*digest_type) { case SSHFP_HASH_SHA1: - fp_type = SSH_FP_SHA1; + fp_alg = SSH_DIGEST_SHA1; break; case SSHFP_HASH_SHA256: - fp_type = SSH_FP_SHA256; + fp_alg = SSH_DIGEST_SHA256; break; default: *digest_type = SSHFP_HASH_RESERVED; /* 0 */ } if (*algorithm && *digest_type) { - *digest = key_fingerprint_raw(key, fp_type, digest_len); + *digest = key_fingerprint_raw(key, fp_alg, digest_len); if (*digest == NULL) fatal("dns_read_key: null from key_fingerprint_raw()"); success = 1; diff --git a/key.c b/key.c index dd0f448a4..b821d9e1d 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.123 2014/12/04 20:47:36 djm Exp $ */ +/* $OpenBSD: key.c,v 1.124 2014/12/21 22:27:56 djm Exp $ */ /* * placed in the public domain */ @@ -40,8 +40,7 @@ key_new_private(int type) } u_char* -key_fingerprint_raw(const Key *k, enum fp_type dgst_type, - u_int *dgst_raw_length) +key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length) { u_char *ret = NULL; size_t dlen; @@ -49,7 +48,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type, if (dgst_raw_length != NULL) *dgst_raw_length = 0; - if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0) + if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0) fatal("%s: %s", __func__, ssh_err(r)); if (dlen > INT_MAX) fatal("%s: giant len %zu", __func__, dlen); diff --git a/key.h b/key.h index 212a169fa..de7865733 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.43 2014/12/04 20:47:36 djm Exp $ */ +/* $OpenBSD: key.h,v 1.44 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -67,7 +67,7 @@ void key_add_private(Key *); Key *key_new_private(int); void key_free(Key *); Key *key_demote(const Key *); -u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); +u_char *key_fingerprint_raw(const Key *, int, u_int *); int key_write(const Key *, FILE *); int key_read(Key *, char **); diff --git a/krl.c b/krl.c index 5a5cdde02..3439e9c29 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.20 2014/12/04 01:49:59 djm Exp $ */ +/* $OpenBSD: krl.c,v 1.21 2014/12/21 22:27:56 djm Exp $ */ #include "includes.h" @@ -36,6 +36,7 @@ #include "misc.h" #include "log.h" #include "ssherr.h" +#include "digest.h" #include "krl.h" @@ -411,7 +412,8 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key) int r; debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); - if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0) + if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, + &blob, &len)) != 0) return r; return revoke_blob(&krl->revoked_sha1s, blob, len); } @@ -1151,7 +1153,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) /* Check explicitly revoked hashes first */ memset(&rb, 0, sizeof(rb)); - if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, + if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, &rb.blob, &rb.len)) != 0) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); diff --git a/readconf.c b/readconf.c index e0386935f..399b73e98 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.223 2014/12/04 02:24:32 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.224 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -60,6 +60,7 @@ #include "mac.h" #include "uidswap.h" #include "myproposal.h" +#include "digest.h" /* Format of the configuration file: @@ -155,6 +156,7 @@ typedef enum { oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, + oFingerprintHash, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; @@ -270,6 +272,7 @@ static struct { { "streamlocalbindmask", oStreamLocalBindMask }, { "streamlocalbindunlink", oStreamLocalBindUnlink }, { "revokedhostkeys", oRevokedHostKeys }, + { "fingerprinthash", oFingerprintHash }, { "ignoreunknown", oIgnoreUnknown }, { NULL, oBadOption } @@ -1460,6 +1463,18 @@ parse_int: charptr = &options->revoked_host_keys; goto parse_string; + case oFingerprintHash: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if ((value = ssh_digest_alg_by_name(arg)) == -1) + fatal("%.200s line %d: Invalid hash algorithm \"%s\".", + filename, linenum, arg); + if (*activep) + options->fingerprint_hash = value; + break; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -1637,6 +1652,7 @@ initialize_options(Options * options) options->canonicalize_fallback_local = -1; options->canonicalize_hostname = -1; options->revoked_host_keys = NULL; + options->fingerprint_hash = -1; } /* @@ -1814,6 +1830,9 @@ fill_default_options(Options * options) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ @@ -2071,6 +2090,8 @@ fmt_intarg(OpCodes code, int val) return fmt_multistate_int(val, multistate_requesttty); case oCanonicalizeHostname: return fmt_multistate_int(val, multistate_canonicalizehostname); + case oFingerprintHash: + return ssh_digest_alg_name(val); case oProtocol: switch (val) { case SSH_PROTO_1: @@ -2205,6 +2226,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oControlMaster, o->control_master); dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); + dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(oForwardAgent, o->forward_agent); dump_cfg_fmtint(oForwardX11, o->forward_x11); dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); diff --git a/readconf.h b/readconf.h index 49858bff3..11a7332c2 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.104 2014/12/04 02:24:32 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.105 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen @@ -146,6 +146,8 @@ typedef struct { char *revoked_host_keys; + int fingerprint_hash; + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; diff --git a/servconf.c b/servconf.c index 99396fb1d..abc3c72fb 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.255 2014/11/24 03:39:22 jsg Exp $ */ +/* $OpenBSD: servconf.c,v 1.256 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -55,6 +55,7 @@ #include "hostfile.h" #include "auth.h" #include "myproposal.h" +#include "digest.h" static void add_listen_addr(ServerOptions *, char *, int); static void add_one_listen_addr(ServerOptions *, char *, int); @@ -158,6 +159,7 @@ initialize_server_options(ServerOptions *options) options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; + options->fingerprint_hash = -1; } void @@ -313,6 +315,8 @@ fill_default_server_options(ServerOptions *options) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = PRIVSEP_NOSANDBOX; @@ -362,7 +366,7 @@ typedef enum { sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, - sAllowStreamLocalForwarding, + sAllowStreamLocalForwarding, sFingerprintHash, sDeprecated, sUnsupported } ServerOpCodes; @@ -493,6 +497,7 @@ static struct { { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, + { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -1670,6 +1675,18 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->fwd_opts.streamlocal_bind_unlink; goto parse_flag; + case sFingerprintHash: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if ((value = ssh_digest_alg_by_name(arg)) == -1) + fatal("%.200s line %d: Invalid hash algorithm \"%s\".", + filename, linenum, arg); + if (*activep) + options->fingerprint_hash = value; + break; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); @@ -1912,6 +1929,8 @@ fmt_intarg(ServerOpCodes code, int val) return fmt_multistate_int(val, multistate_tcpfwd); case sAllowStreamLocalForwarding: return fmt_multistate_int(val, multistate_tcpfwd); + case sFingerprintHash: + return ssh_digest_alg_name(val); case sProtocol: switch (val) { case SSH_PROTO_1: @@ -2073,6 +2092,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); + dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); diff --git a/servconf.h b/servconf.h index 766db3a3d..49b228bdf 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: servconf.h,v 1.115 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen @@ -185,6 +185,8 @@ typedef struct { u_int num_auth_methods; char *auth_methods[MAX_AUTH_METHODS]; + + int fingerprint_hash; } ServerOptions; /* Information about the incoming connection as used by Match */ diff --git a/ssh-add.1 b/ssh-add.1 index 9da7a2835..926456f0b 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.60 2014/08/30 15:33:50 sobrado Exp $ +.\" $OpenBSD: ssh-add.1,v 1.61 2014/12/21 22:27:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: August 30 2014 $ +.Dd $Mdocdate: December 21 2014 $ .Dt SSH-ADD 1 .Os .Sh NAME @@ -44,6 +44,7 @@ .Sh SYNOPSIS .Nm ssh-add .Op Fl cDdkLlXx +.Op Fl E Ar fingerprint_hash .Op Fl t Ar life .Op Ar .Nm ssh-add @@ -108,6 +109,14 @@ If no public key is found at a given path, will append .Pa .pub and retry. +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . diff --git a/ssh-add.c b/ssh-add.c index ba11aa150..3680ab07a 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.114 2014/11/26 18:34:51 millert Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.115 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -63,6 +63,7 @@ #include "pathnames.h" #include "misc.h" #include "ssherr.h" +#include "digest.h" /* argv0 */ extern char *__progname; @@ -79,6 +80,8 @@ static char *default_files[] = { NULL }; +static int fingerprint_hash = SSH_FP_HASH_DEFAULT; + /* Default lifetime (0 == forever) */ static int lifetime = 0; @@ -340,8 +343,8 @@ list_identities(AuthenticationConnection *ac, int do_fp) key = ssh_get_next_identity(ac, &comment, version)) { had_identities = 1; if (do_fp) { - fp = key_fingerprint(key, SSH_FP_MD5, - SSH_FP_HEX); + fp = key_fingerprint(key, fingerprint_hash, + SSH_FP_DEFAULT); printf("%d %s %s (%s)\n", key_size(key), fp, comment, key_type(key)); free(fp); @@ -408,6 +411,7 @@ usage(void) fprintf(stderr, "usage: %s [options] [file ...]\n", __progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -l List fingerprints of all identities.\n"); + fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n"); fprintf(stderr, " -L List public key parameters of all identities.\n"); fprintf(stderr, " -k Load only keys and not certificates.\n"); fprintf(stderr, " -c Require confirmation to sign using identities\n"); @@ -428,6 +432,7 @@ main(int argc, char **argv) AuthenticationConnection *ac = NULL; char *pkcs11provider = NULL; int i, ch, deleting = 0, ret = 0, key_only = 0; + int xflag = 0, lflag = 0, Dflag = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -446,21 +451,28 @@ main(int argc, char **argv) "Could not open a connection to your authentication agent.\n"); exit(2); } - while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) { + while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) { switch (ch) { + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'k': key_only = 1; break; case 'l': case 'L': - if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) - ret = 1; - goto done; + if (lflag != 0) + fatal("-%c flag already specified", lflag); + lflag = ch; + break; case 'x': case 'X': - if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1) - ret = 1; - goto done; + if (xflag != 0) + fatal("-%c flag already specified", xflag); + xflag = ch; + break; case 'c': confirm = 1; break; @@ -468,9 +480,8 @@ main(int argc, char **argv) deleting = 1; break; case 'D': - if (delete_all(ac) == -1) - ret = 1; - goto done; + Dflag = 1; + break; case 's': pkcs11provider = optarg; break; @@ -491,6 +502,23 @@ main(int argc, char **argv) goto done; } } + + if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1) + fatal("Invalid combination of actions"); + else if (xflag) { + if (lock_agent(ac, xflag == 'x' ? 1 : 0) == -1) + ret = 1; + goto done; + } else if (lflag) { + if (list_identities(ac, lflag == 'l' ? 1 : 0) == -1) + ret = 1; + goto done; + } else if (Dflag) { + if (delete_all(ac) == -1) + ret = 1; + goto done; + } + argc -= optind; argv += optind; if (pkcs11provider != NULL) { diff --git a/ssh-agent.1 b/ssh-agent.1 index b55065327..6759afec3 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.56 2014/08/30 15:33:50 sobrado Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.57 2014/12/21 22:27:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: August 30 2014 $ +.Dd $Mdocdate: December 21 2014 $ .Dt SSH-AGENT 1 .Os .Sh NAME @@ -45,6 +45,7 @@ .Op Fl c | s .Op Fl d .Op Fl a Ar bind_address +.Op Fl E Ar fingerprint_hash .Op Fl t Ar life .Op Ar command Op Ar arg ... .Nm ssh-agent @@ -96,6 +97,14 @@ Debug mode. When this option is specified .Nm will not fork. +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl k Kill the current agent (given by the .Ev SSH_AGENT_PID diff --git a/ssh-agent.c b/ssh-agent.c index 9c11d48d1..c2dc1fa0c 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.191 2014/11/18 20:54:28 krw Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.192 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -142,6 +142,8 @@ extern char *__progname; /* Default lifetime in seconds (0 == forever) */ static long lifetime = 0; +static int fingerprint_hash = SSH_FP_HASH_DEFAULT; + static void close_socket(SocketEntry *e) { @@ -203,7 +205,7 @@ confirm_key(Identity *id) char *p; int ret = -1; - p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); + p = key_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", id->comment, p)) ret = 0; @@ -1026,7 +1028,7 @@ usage(void) { fprintf(stderr, "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" - " [command [arg ...]]\n" + " [-E fingerprint_hash] [command [arg ...]]\n" " ssh-agent [-c | -s] -k\n"); exit(1); } @@ -1069,8 +1071,13 @@ main(int ac, char **av) __progname = ssh_get_progname(av[0]); seed_rng(); - while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { + while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) { switch (ch) { + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'c': if (s_flag) usage(); diff --git a/ssh-keygen.1 b/ssh-keygen.1 index bf5f87bd3..b73c4606e 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.123 2014/08/30 15:33:50 sobrado Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.124 2014/12/21 22:27:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: August 30 2014 $ +.Dd $Mdocdate: December 21 2014 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -73,6 +73,7 @@ .Op Fl f Ar keyfile .Nm ssh-keygen .Fl l +.Op Fl E Ar fingerprint_hash .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl B @@ -269,6 +270,14 @@ When used in combination with this option indicates that a CA key resides in a PKCS#11 token (see the .Sx CERTIFICATES section for details). +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl e This option will read a private or public OpenSSH key file and print to stdout the key in one of the formats specified by the diff --git a/ssh-keygen.c b/ssh-keygen.c index e149eda3e..8daea7f76 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.250 2014/08/21 01:08:52 doug Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.251 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -53,6 +53,7 @@ #include "ssh-pkcs11.h" #include "atomicio.h" #include "krl.h" +#include "digest.h" /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ #define DEFAULT_BITS 2048 @@ -90,6 +91,9 @@ int show_cert = 0; int print_fingerprint = 0; int print_bubblebabble = 0; +/* Hash algorithm to use for fingerprints. */ +int fingerprint_hash = SSH_FP_HASH_DEFAULT; + /* The identity file name, given on the command line or entered by the user. */ char identity_file[1024]; int have_identity = 0; @@ -749,11 +753,11 @@ do_download(struct passwd *pw) Key **keys = NULL; int i, nkeys; enum fp_rep rep; - enum fp_type fptype; + int fptype; char *fp, *ra; - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; pkcs11_init(0); nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); @@ -762,7 +766,7 @@ do_download(struct passwd *pw) for (i = 0; i < nkeys; i++) { if (print_fingerprint) { fp = key_fingerprint(keys[i], fptype, rep); - ra = key_fingerprint(keys[i], SSH_FP_MD5, + ra = key_fingerprint(keys[i], fingerprint_hash, SSH_FP_RANDOMART); printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), fp, key_type(keys[i])); @@ -792,12 +796,11 @@ do_fingerprint(struct passwd *pw) char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; int i, skip = 0, num = 0, invalid = 1; enum fp_rep rep; - enum fp_type fptype; + int fptype; struct stat st; - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - + fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); if (stat(identity_file, &st) < 0) { @@ -807,7 +810,8 @@ do_fingerprint(struct passwd *pw) public = key_load_public(identity_file, &comment); if (public != NULL) { fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); + ra = key_fingerprint(public, fingerprint_hash, + SSH_FP_RANDOMART); printf("%u %s %s (%s)\n", key_size(public), fp, comment, key_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -873,7 +877,8 @@ do_fingerprint(struct passwd *pw) } comment = *cp ? cp : comment; fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); + ra = key_fingerprint(public, fingerprint_hash, + SSH_FP_RANDOMART); printf("%u %s %s (%s)\n", key_size(public), fp, comment ? comment : "no comment", key_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -993,13 +998,15 @@ printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash) { if (print_fingerprint) { enum fp_rep rep; - enum fp_type fptype; + int fptype; char *fp, *ra; - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + fptype = print_bubblebabble ? + SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); + ra = key_fingerprint(public, fingerprint_hash, + SSH_FP_RANDOMART); printf("%u %s %s (%s)\n", key_size(public), fp, name, key_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -1908,9 +1915,9 @@ do_show_cert(struct passwd *pw) fatal("%s is not a certificate", identity_file); v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; - key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + key_fp = key_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); ca_fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + fingerprint_hash, SSH_FP_DEFAULT); printf("%s:\n", identity_file); printf(" Type: %s %s certificate\n", key_ssh_name(key), @@ -2189,7 +2196,7 @@ usage(void) " ssh-keygen -e [-m key_format] [-f input_keyfile]\n" " ssh-keygen -y [-f input_keyfile]\n" " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" - " ssh-keygen -l [-f input_keyfile]\n" + " ssh-keygen -l [-E fingerprint_hash] [-f input_keyfile]\n" " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 fprintf(stderr, @@ -2258,9 +2265,10 @@ main(int argc, char **argv) exit(1); } - /* Remaining characters: EUYdw */ + /* Remaining characters: UYdw */ while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" - "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) { + "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:" + "a:b:f:g:j:m:n:r:s:t:z:")) != -1) { switch (opt) { case 'A': gen_all_hostkeys = 1; @@ -2271,6 +2279,11 @@ main(int argc, char **argv) fatal("Bits has bad value %s (%s)", optarg, errstr); break; + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'F': find_host = 1; rr_hostname = optarg; @@ -2702,8 +2715,9 @@ passphrase_again: fclose(f); if (!quiet) { - char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); - char *ra = key_fingerprint(public, SSH_FP_MD5, + char *fp = key_fingerprint(public, fingerprint_hash, + SSH_FP_DEFAULT); + char *ra = key_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); printf("Your public key has been saved in %s.\n", identity_file); diff --git a/ssh-keysign.c b/ssh-keysign.c index 6b73319e0..b86e18d8c 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.43 2014/10/08 22:20:25 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.44 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -246,7 +246,8 @@ main(int argc, char **argv) } } if (!found) { - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); fatal("no matching hostkey found for key %s %s", key_type(key), fp); } diff --git a/ssh.1 b/ssh.1 index 51201861b..d489047ce 100644 --- a/ssh.1 +++ b/ssh.1 @@ -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: ssh.1,v 1.351 2014/10/09 06:21:31 jmc Exp $ -.Dd $Mdocdate: October 9 2014 $ +.\" $OpenBSD: ssh.1,v 1.352 2014/12/21 22:27:56 djm Exp $ +.Dd $Mdocdate: December 21 2014 $ .Dt SSH 1 .Os .Sh NAME @@ -1091,7 +1091,7 @@ Fingerprints can be determined using If the fingerprint is already known, it can be matched and the key can be accepted or rejected. Because of the difficulty of comparing host keys -just by looking at hex strings, +just by looking at fingerprint strings, there is also support to compare host keys visually, using .Em random art . diff --git a/sshconnect.c b/sshconnect.c index 4b9681a5b..176a20a87 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.253 2014/12/11 08:20:09 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.254 2014/12/21 22:27:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -918,9 +918,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, "key for IP address '%.128s' to the list " "of known hosts.", type, ip); } else if (options.visual_host_key) { - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(host_key, SSH_FP_MD5, - SSH_FP_RANDOMART); + fp = key_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = key_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_RANDOMART); logit("Host key fingerprint is %s\n%s\n", fp, ra); free(ra); free(fp); @@ -959,9 +960,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, else snprintf(msg1, sizeof(msg1), "."); /* The default */ - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(host_key, SSH_FP_MD5, - SSH_FP_RANDOMART); + fp = key_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = key_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_RANDOMART); msg2[0] = '\0'; if (options.verify_host_key_dns) { if (matching_host_key_dns) @@ -1226,7 +1228,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) struct sshkey *plain = NULL; if ((fp = sshkey_fingerprint(host_key, - SSH_FP_MD5, SSH_FP_HEX)) == NULL) { + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error("%s: fingerprint host key: %s", __func__, ssh_err(r)); r = -1; goto out; @@ -1387,8 +1389,10 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) continue; if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) continue; - fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); + fp = key_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = key_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_RANDOMART); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", @@ -1409,7 +1413,8 @@ warn_changed_key(Key *host_key) { char *fp; - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(host_key, options.fingerprint_hash, + SSH_FP_DEFAULT); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); diff --git a/sshconnect2.c b/sshconnect2.c index 6884d6be1..ad20fae6a 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.211 2014/12/11 05:13:28 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.212 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -582,7 +582,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) key->type, pktype); goto done; } - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); debug2("input_userauth_pk_ok: fp %s", fp); free(fp); @@ -991,7 +991,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) int have_sig = 1; char *fp; - fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); + fp = key_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT); debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); free(fp); diff --git a/sshd_config.5 b/sshd_config.5 index ef36d3338..69d3be2b8 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -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.182 2014/12/12 00:02:17 djm Exp $ -.Dd $Mdocdate: December 12 2014 $ +.\" $OpenBSD: sshd_config.5,v 1.183 2014/12/21 22:27:55 djm Exp $ +.Dd $Mdocdate: December 21 2014 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -485,6 +485,15 @@ and finally See PATTERNS in .Xr ssh_config 5 for more information on patterns. +.It Cm FingerprintHash +Specifies the hash algorithm used when logging key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . +.Pp .It Cm ForceCommand Forces the execution of the command specified by .Cm ForceCommand , diff --git a/sshkey.c b/sshkey.c index cf126626e..a32bd36cc 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.6 2014/12/10 01:24:09 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.7 2014/12/21 22:27:55 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -852,29 +853,18 @@ sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) } int -sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, +sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, u_char **retp, size_t *lenp) { u_char *blob = NULL, *ret = NULL; size_t blob_len = 0; - int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR; + int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (lenp != NULL) *lenp = 0; - - switch (dgst_type) { - case SSH_FP_MD5: - hash_alg = SSH_DIGEST_MD5; - break; - case SSH_FP_SHA1: - hash_alg = SSH_DIGEST_SHA1; - break; - case SSH_FP_SHA256: - hash_alg = SSH_DIGEST_SHA256; - break; - default: + if (ssh_digest_bytes(dgst_alg) == 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } @@ -899,7 +889,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = ssh_digest_memory(hash_alg, blob, blob_len, + if ((r = ssh_digest_memory(dgst_alg, blob, blob_len, ret, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; /* success */ @@ -908,7 +898,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, ret = NULL; } if (lenp != NULL) - *lenp = ssh_digest_bytes(hash_alg); + *lenp = ssh_digest_bytes(dgst_alg); r = 0; out: free(ret); @@ -920,21 +910,45 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, } static char * -fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len) +fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) { - char *retval; - size_t i; + char *ret; + size_t plen = strlen(alg) + 1; + size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; + int r; - if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL) + if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) + return NULL; + strlcpy(ret, alg, rlen); + strlcat(ret, ":", rlen); + if (dgst_raw_len == 0) + return ret; + if ((r = b64_ntop(dgst_raw, dgst_raw_len, + ret + plen, rlen - plen)) == -1) { + explicit_bzero(ret, rlen); + free(ret); return NULL; - for (i = 0; i < dgst_raw_len; i++) { - char hex[4]; - snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); - strlcat(retval, hex, dgst_raw_len * 3 + 1); } + /* Trim padding characters from end */ + ret[strcspn(ret, "=")] = '\0'; + return ret; +} - /* Remove the trailing ':' character */ - retval[(dgst_raw_len * 3) - 1] = '\0'; +static char * +fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) +{ + char *retval, hex[5]; + size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2; + + if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL) + return NULL; + strlcpy(retval, alg, rlen); + strlcat(retval, ":", rlen); + for (i = 0; i < dgst_raw_len; i++) { + snprintf(hex, sizeof(hex), "%s%02x", + i > 0 ? ":" : "", dgst_raw[i]); + strlcat(retval, hex, rlen); + } return retval; } @@ -1020,7 +1034,7 @@ fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) #define FLDSIZE_Y (FLDBASE + 1) #define FLDSIZE_X (FLDBASE * 2 + 1) static char * -fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, +fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len, const struct sshkey *k) { /* @@ -1028,9 +1042,9 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, * intersects with itself. Matter of taste. */ char *augmentation_string = " .o+=*BOX@%&#/^SE"; - char *retval, *p, title[FLDSIZE_X]; + char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; u_char field[FLDSIZE_X][FLDSIZE_Y]; - size_t i, tlen; + size_t i, tlen, hlen; u_int b; int x, y, r; size_t len = strlen(augmentation_string) - 1; @@ -1075,8 +1089,12 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, sshkey_type(k), sshkey_size(k)); /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ if (r < 0 || r > (int)sizeof(title)) - snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); - tlen = strlen(title); + r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); + tlen = (r <= 0) ? 0 : strlen(title); + + /* assemble hash ID. */ + r = snprintf(hash, sizeof(hash), "[%s]", alg); + hlen = (r <= 0) ? 0 : strlen(hash); /* output upper border */ p = retval; @@ -1085,7 +1103,7 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, *p++ = '-'; memcpy(p, title, tlen); p += tlen; - for (i = p - retval - 1; i < FLDSIZE_X; i++) + for (i += tlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; *p++ = '\n'; @@ -1101,7 +1119,11 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, /* output lower border */ *p++ = '+'; - for (i = 0; i < FLDSIZE_X; i++) + for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) + *p++ = '-'; + memcpy(p, hash, hlen); + p += hlen; + for (i += hlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; @@ -1109,24 +1131,39 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, } char * -sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type, +sshkey_fingerprint(const struct sshkey *k, int dgst_alg, enum sshkey_fp_rep dgst_rep) { char *retval = NULL; u_char *dgst_raw; size_t dgst_raw_len; - if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0) + if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) return NULL; switch (dgst_rep) { + case SSH_FP_DEFAULT: + if (dgst_alg == SSH_DIGEST_MD5) { + retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + } else { + retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + } + break; case SSH_FP_HEX: - retval = fingerprint_hex(dgst_raw, dgst_raw_len); + retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + break; + case SSH_FP_BASE64: + retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); break; case SSH_FP_BUBBLEBABBLE: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); break; case SSH_FP_RANDOMART: - retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k); + retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len, k); break; default: explicit_bzero(dgst_raw, dgst_raw_len); diff --git a/sshkey.h b/sshkey.h index 450b30c1f..4554b09b5 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.2 2014/12/21 22:27:55 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -67,16 +67,14 @@ enum sshkey_types { KEY_UNSPEC }; -/* Fingerprint hash algorithms */ -enum sshkey_fp_type { - SSH_FP_SHA1, - SSH_FP_MD5, - SSH_FP_SHA256 -}; +/* Default fingerprint hash */ +#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256 /* Fingerprint representation formats */ enum sshkey_fp_rep { + SSH_FP_DEFAULT = 0, SSH_FP_HEX, + SSH_FP_BASE64, SSH_FP_BUBBLEBABBLE, SSH_FP_RANDOMART }; @@ -124,9 +122,9 @@ int sshkey_equal_public(const struct sshkey *, const struct sshkey *); int sshkey_equal(const struct sshkey *, const struct sshkey *); char *sshkey_fingerprint(const struct sshkey *, - enum sshkey_fp_type, enum sshkey_fp_rep); + int, enum sshkey_fp_rep); int sshkey_fingerprint_raw(const struct sshkey *k, - enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp); + int, u_char **retp, size_t *lenp); const char *sshkey_type(const struct sshkey *); const char *sshkey_cert_type(const struct sshkey *); int sshkey_write(const struct sshkey *, FILE *); -- cgit v1.2.3 From f69b69b8625be447b8826b21d87713874dac25a6 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 22 Dec 2014 07:51:30 +0000 Subject: upstream commit remember which public keys have been used for authentication and refuse to accept previously-used keys. This allows AuthenticationMethods=publickey,publickey to require that users authenticate using two _different_ pubkeys. ok markus@ --- auth.h | 9 ++++++++- auth2-pubkey.c | 42 ++++++++++++++++++++++++++++++++++++++++-- monitor.c | 10 ++++++++-- sshd_config.5 | 16 ++++++++++++++-- 4 files changed, 70 insertions(+), 7 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth.h b/auth.h index d081c94a6..c67e4a4d4 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.79 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -42,6 +42,8 @@ #include #endif +struct sshkey; + typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; typedef struct KbdintDevice KbdintDevice; @@ -75,6 +77,9 @@ struct Authctxt { #endif Buffer *loginmsg; void *methoddata; + + struct sshkey **prev_userkeys; + u_int nprev_userkeys; }; /* * Every authentication method has to handle authentication requests for @@ -123,6 +128,8 @@ int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); int user_key_allowed(struct passwd *, Key *); void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) __attribute__((__format__ (printf, 3, 4))); +void auth2_record_userkey(Authctxt *, struct sshkey *); +int auth2_userkey_already_used(Authctxt *, struct sshkey *); struct stat; int auth_secure_path(const char *, struct stat *, const char *, uid_t, diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 04b70e362..2b0486222 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.44 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -41,6 +41,7 @@ #include #include #include +#include #include "xmalloc.h" #include "ssh.h" @@ -122,6 +123,10 @@ userauth_pubkey(Authctxt *authctxt) "signature scheme"); goto done; } + if (auth2_userkey_already_used(authctxt, key)) { + logit("refusing previously-used %s key", key_type(key)); + goto done; + } if (have_sig) { sig = packet_get_string(&slen); packet_check_eom(); @@ -159,8 +164,12 @@ userauth_pubkey(Authctxt *authctxt) authenticated = 0; if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + buffer_len(&b))) == 1) { authenticated = 1; + /* Record the successful key to prevent reuse */ + auth2_record_userkey(authctxt, key); + key = NULL; /* Don't free below */ + } buffer_free(&b); free(sig); } else { @@ -682,6 +691,35 @@ user_key_allowed(struct passwd *pw, Key *key) 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, diff --git a/monitor.c b/monitor.c index dbe29f128..b830e0374 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: monitor.c,v 1.136 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1170,6 +1170,7 @@ mm_answer_keyallowed(int sock, Buffer *m) switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && + !auth2_userkey_already_used(authctxt, key) && user_key_allowed(authctxt->pw, key); pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; @@ -1397,7 +1398,12 @@ mm_answer_keyverify(int sock, Buffer *m) debug3("%s: key %p signature %s", __func__, key, (verified == 1) ? "verified" : "unverified"); - key_free(key); + /* If auth was successful then record key to ensure it isn't reused */ + if (verified == 1) + auth2_record_userkey(authctxt, key); + else + key_free(key); + free(blob); free(signature); free(data); diff --git a/sshd_config.5 b/sshd_config.5 index 938ba2f1a..d2ab28136 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -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.184 2014/12/21 23:35:14 jmc Exp $ -.Dd $Mdocdate: December 21 2014 $ +.\" $OpenBSD: sshd_config.5,v 1.185 2014/12/22 07:51:30 djm Exp $ +.Dd $Mdocdate: December 22 2014 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -210,6 +210,18 @@ would restrict keyboard interactive authentication to the .Dq bsdauth device. .Pp +If the +.Dq publickey +method is listed more than one, +.Xr sshd 8 +verifies that keys that have been used successfully are not reused for +subsequent authentications. +For example, an +.Cm AuthenticationMethods +of +.Dq publickey,publickey +will require successful authentication using two different public keys. +.Pp This option is only available for SSH protocol 2 and will yield a fatal error if enabled if protocol 1 is also enabled. Note that each authentication method listed should also be explicitly enabled -- cgit v1.2.3 From 1f729f0614d1376c3332fa1edb6a5e5cec7e9e03 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 13 Jan 2015 07:39:19 +0000 Subject: upstream commit add sshd_config HostbasedAcceptedKeyTypes and PubkeyAcceptedKeyTypes options to allow sshd to control what public key types will be accepted. Currently defaults to all. Feedback & ok markus@ --- auth2-hostbased.c | 11 ++++++++++- auth2-pubkey.c | 9 ++++++++- key.h | 3 +-- monitor.c | 14 +++++++++++++- readconf.c | 4 ++-- servconf.c | 44 +++++++++++++++++++++++++++++++++++++------- servconf.h | 6 +++++- sshd_config.5 | 28 ++++++++++++++++++++++++++-- sshkey.c | 32 +++++++++++++++++++++++++++----- sshkey.h | 4 ++-- 10 files changed, 131 insertions(+), 24 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 2db3d2524..9f8a01cbe 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.21 2015/01/08 10:14:08 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.22 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -48,6 +48,7 @@ #endif #include "monitor_wrap.h" #include "pathnames.h" +#include "match.h" /* import */ extern ServerOptions options; @@ -108,6 +109,14 @@ userauth_hostbased(Authctxt *authctxt) "signature format"); goto done; } + if (match_pattern_list(sshkey_ssh_name(key), + options.hostbased_key_types, + strlen(options.hostbased_key_types), 0) != 1) { + logit("%s: key type %s not in HostbasedAcceptedKeyTypes", + __func__, sshkey_type(key)); + goto done; + } + service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; buffer_init(&b); diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 2b0486222..d922eea26 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.44 2014/12/22 07:51:30 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.45 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -127,6 +127,13 @@ userauth_pubkey(Authctxt *authctxt) logit("refusing previously-used %s key", key_type(key)); goto done; } + if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types, + strlen(options.pubkey_key_types), 0) != 1) { + logit("%s: key type %s not in PubkeyAcceptedKeyTypes", + __func__, sshkey_ssh_name(key)); + goto done; + } + if (have_sig) { sig = packet_get_string(&slen); packet_check_eom(); diff --git a/key.h b/key.h index 7190b842d..bf884970c 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.45 2015/01/08 10:14:08 djm Exp $ */ +/* $OpenBSD: key.h,v 1.46 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -50,7 +50,6 @@ typedef struct sshkey Key; #define key_size sshkey_size #define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid #define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid -#define key_names_valid2 sshkey_names_valid2 #define key_is_cert sshkey_is_cert #define key_type_plain sshkey_type_plain #define key_cert_is_legacy sshkey_cert_is_legacy diff --git a/monitor.c b/monitor.c index b830e0374..5a28d1b34 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.136 2014/12/22 07:51:30 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.137 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -100,6 +100,7 @@ #include "ssh2.h" #include "roaming.h" #include "authfd.h" +#include "match.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -1167,10 +1168,18 @@ mm_answer_keyallowed(int sock, Buffer *m) debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { + /* These should not make it past the privsep child */ + if (key_type_plain(key->type) == KEY_RSA && + (datafellows & SSH_BUG_RSASIGMD5) != 0) + fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); + switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && !auth2_userkey_already_used(authctxt, key) && + match_pattern_list(sshkey_ssh_name(key), + options.pubkey_key_types, + strlen(options.pubkey_key_types), 0) == 1 && user_key_allowed(authctxt->pw, key); pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; @@ -1179,6 +1188,9 @@ mm_answer_keyallowed(int sock, Buffer *m) break; case MM_HOSTKEY: allowed = options.hostbased_authentication && + match_pattern_list(sshkey_ssh_name(key), + options.hostbased_key_types, + strlen(options.hostbased_key_types), 0) == 1 && hostbased_key_allowed(authctxt->pw, cuser, chost, key); pubkey_auth_info(authctxt, key, diff --git a/readconf.c b/readconf.c index f1601af2e..d7f1cf036 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.225 2015/01/08 13:44:36 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.226 2015/01/13 07:39:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1116,7 +1116,7 @@ parse_int: arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!key_names_valid2(arg)) + if (!sshkey_names_valid2(arg, 1)) fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", filename, linenum, arg ? arg : ""); if (*activep && options->hostkeyalgorithms == NULL) diff --git a/servconf.c b/servconf.c index 6eb368661..1b6bdb4af 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.257 2014/12/22 07:55:51 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.258 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -104,8 +104,10 @@ initialize_server_options(ServerOptions *options) options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; + options->hostbased_key_types = NULL; options->rsa_authentication = -1; options->pubkey_authentication = -1; + options->pubkey_key_types = NULL; options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; @@ -248,10 +250,14 @@ fill_default_server_options(ServerOptions *options) options->hostbased_authentication = 0; if (options->hostbased_uses_name_from_packet_only == -1) options->hostbased_uses_name_from_packet_only = 0; + if (options->hostbased_key_types == NULL) + options->hostbased_key_types = xstrdup("*"); if (options->rsa_authentication == -1) options->rsa_authentication = 1; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; + if (options->pubkey_key_types == NULL) + options->pubkey_key_types = xstrdup("*"); if (options->kerberos_authentication == -1) options->kerberos_authentication = 0; if (options->kerberos_or_local_passwd == -1) @@ -365,8 +371,8 @@ typedef enum { /* Portable-specific options */ sUsePAM, /* Standard Options */ - sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, - sPermitRootLogin, sLogFacility, sLogLevel, + sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, + sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, sRhostsRSAAuthentication, sRSAAuthentication, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, @@ -379,11 +385,11 @@ typedef enum { sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, - sMaxStartups, sMaxAuthTries, sMaxSessions, + sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, + sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, + sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, @@ -430,8 +436,10 @@ static struct { { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, + { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL }, { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, + { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ #ifdef KRB5 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, @@ -1111,6 +1119,20 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; + case sHostbasedAcceptedKeyTypes: + charptr = &options->hostbased_key_types; + parse_keytypes: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", + filename, linenum); + if (!sshkey_names_valid2(arg, 1)) + fatal("%s line %d: Bad key types '%s'.", + filename, linenum, arg ? arg : ""); + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + case sRSAAuthentication: intptr = &options->rsa_authentication; goto parse_flag; @@ -1119,6 +1141,10 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->pubkey_authentication; goto parse_flag; + case sPubkeyAcceptedKeyTypes: + charptr = &options->pubkey_key_types; + goto parse_keytypes; + case sKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; @@ -2142,6 +2168,10 @@ dump_config(ServerOptions *o) dump_cfg_string(sHostKeyAgent, o->host_key_agent); dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); + dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? + o->hostbased_key_types : KEX_DEFAULT_PK_ALG); + dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? + o->pubkey_key_types : KEX_DEFAULT_PK_ALG); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/servconf.h b/servconf.h index 49b228bdf..9922f0c8c 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.115 2014/12/21 22:27:56 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.116 2015/01/13 07:39:19 djm Exp $ */ /* * Author: Tatu Ylonen @@ -99,8 +99,10 @@ typedef struct { * authentication. */ int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ int hostbased_uses_name_from_packet_only; /* experimental */ + char *hostbased_key_types; /* Key types allowed for hostbased */ int rsa_authentication; /* If true, permit RSA authentication. */ int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ + char *pubkey_key_types; /* Key types allowed for public key */ int kerberos_authentication; /* If true, permit Kerberos * authentication. */ int kerberos_or_local_passwd; /* If true, permit kerberos @@ -215,6 +217,8 @@ struct connection_info { M_CP_STROPT(authorized_principals_file); \ M_CP_STROPT(authorized_keys_command); \ M_CP_STROPT(authorized_keys_command_user); \ + M_CP_STROPT(hostbased_key_types); \ + M_CP_STROPT(pubkey_key_types); \ M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ diff --git a/sshd_config.5 b/sshd_config.5 index cec2a023a..88fe90193 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -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.188 2014/12/22 09:05:17 djm Exp $ -.Dd $Mdocdate: December 22 2014 $ +.\" $OpenBSD: sshd_config.5,v 1.189 2015/01/13 07:39:19 djm Exp $ +.Dd $Mdocdate: January 13 2015 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -561,6 +561,17 @@ on logout. The default is .Dq yes . Note that this option applies to protocol version 2 only. +.It Cm HostbasedAcceptedKeyTypes +Specifies the key types that will be accepted for hostbased authentication +as a comma-separated pattern list. +The default +.Dq * +will allow all key types. +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed @@ -962,6 +973,7 @@ Available keywords are .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , +.Cm HostbasedAcceptedKeyTypes , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , .Cm KbdInteractiveAuthentication , @@ -975,6 +987,7 @@ Available keywords are .Cm PermitTTY , .Cm PermitTunnel , .Cm PermitUserRC , +.Cm PubkeyAcceptedKeyTypes , .Cm PubkeyAuthentication , .Cm RekeyLimit , .Cm RhostsRSAAuthentication , @@ -1182,6 +1195,17 @@ Specifying .Dq 2,1 is identical to .Dq 1,2 . +.It Cm PubkeyAcceptedKeyTypes +Specifies the key types that will be accepted for public key authentication +as a comma-separated pattern list. +The default +.Dq * +will allow all key types. +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm PubkeyAuthentication Specifies whether public key authentication is allowed. The default is diff --git a/sshkey.c b/sshkey.c index a680929fa..30f209a25 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.10 2015/01/12 20:13:27 markus Exp $ */ +/* $OpenBSD: sshkey.c,v 1.11 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -54,6 +54,7 @@ #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" +#include "match.h" /* openssh private key file format */ #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" @@ -219,9 +220,11 @@ key_alg_list(int certs_only, int plain_only) } int -sshkey_names_valid2(const char *names) +sshkey_names_valid2(const char *names, int allow_wildcard) { char *s, *cp, *p; + const struct keytype *kt; + int type; if (names == NULL || strcmp(names, "") == 0) return 0; @@ -229,9 +232,28 @@ sshkey_names_valid2(const char *names) return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { - switch (sshkey_type_from_name(p)) { - case KEY_RSA1: - case KEY_UNSPEC: + type = sshkey_type_from_name(p); + if (type == KEY_RSA1) { + free(s); + return 0; + } + if (type == KEY_UNSPEC) { + if (allow_wildcard) { + /* + * Try matching key types against the string. + * If any has a positive or negative match then + * the component is accepted. + */ + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == KEY_RSA1) + continue; + if (match_pattern_list(kt->name, + p, strlen(p), 0) != 0) + break; + } + if (kt->type != -1) + continue; + } free(s); return 0; } diff --git a/sshkey.h b/sshkey.h index 65194d6e4..7217f8875 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.3 2015/01/08 10:14:08 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.4 2015/01/13 07:39:19 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -156,7 +156,7 @@ int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); int sshkey_ec_validate_private(const EC_KEY *); const char *sshkey_ssh_name(const struct sshkey *); const char *sshkey_ssh_name_plain(const struct sshkey *); -int sshkey_names_valid2(const char *); +int sshkey_names_valid2(const char *, int); char *key_alg_list(int, int); int sshkey_from_blob(const u_char *, size_t, struct sshkey **); -- cgit v1.2.3 From 9ce86c926dfa6e0635161b035e3944e611cbccf0 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 28 Jan 2015 22:36:00 +0000 Subject: upstream commit update to new API (key_fingerprint => sshkey_fingerprint) check sshkey_fingerprint return values; ok markus --- auth-rsa.c | 7 ++++--- auth2-hostbased.c | 12 +++++++----- auth2-pubkey.c | 29 +++++++++++++++++------------ dns.c | 6 +++--- key.c | 19 +------------------ key.h | 5 +---- ssh-add.c | 5 +++-- ssh-agent.c | 5 +++-- ssh-keygen.c | 18 ++++++++++++++---- ssh-keysign.c | 7 ++++--- sshconnect.c | 26 +++++++++++++++++--------- sshconnect2.c | 10 +++++++--- 12 files changed, 81 insertions(+), 68 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth-rsa.c b/auth-rsa.c index 422c196cf..cbd971be1 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.89 2014/12/21 22:27:56 djm Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -238,8 +238,9 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); - fp = key_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + continue; debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(key), fp); free(fp); diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 6f69e89de..eebfe8fc3 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.23 2015/01/28 11:07:25 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.24 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -224,15 +224,17 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, if (host_status == HOST_OK) { if (key_is_cert(key)) { - fp = key_fingerprint(key->cert->signature_key, - options.fingerprint_hash, SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, key_type(key->cert->signature_key), fp, cuser, lookup); } else { - fp = key_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted %s public key %s from %s@%s", key_type(key), fp, cuser, lookup); } diff --git a/auth2-pubkey.c b/auth2-pubkey.c index d922eea26..d8f0aa3e2 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.45 2015/01/13 07:39:19 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.46 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -228,18 +228,20 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) } if (key_is_cert(key)) { - fp = key_fingerprint(key->cert->signature_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, + key_type(key->cert->signature_key), + fp == NULL ? "(null)" : "", extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } else { - fp = key_fingerprint(key, options.fingerprint_hash, + fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - auth_info(authctxt, "%s %s%s%s", key_type(key), fp, + auth_info(authctxt, "%s %s%s%s", key_type(key), + fp == NULL ? "(null)" : "", extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } @@ -382,8 +384,9 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) continue; if (!key_is_cert_authority) continue; - fp = key_fingerprint(found, options.fingerprint_hash, - SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(found, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + continue; debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); /* @@ -422,12 +425,13 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) continue; if (key_is_cert_authority) continue; - found_key = 1; - fp = key_fingerprint(found, options.fingerprint_hash, - SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(found, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + continue; debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(found), fp); free(fp); + found_key = 1; break; } } @@ -449,8 +453,9 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) return 0; - ca_fp = key_fingerprint(key->cert->signature_key, - options.fingerprint_hash, SSH_FP_DEFAULT); + 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) { diff --git a/dns.c b/dns.c index f45bec0bf..f201b602e 100644 --- a/dns.c +++ b/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.33 2015/01/15 09:40:00 djm Exp $ */ +/* $OpenBSD: dns.c,v 1.34 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -294,7 +294,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, free(dnskey_digest); } - free(hostkey_digest); /* from key_fingerprint_raw() */ + free(hostkey_digest); /* from sshkey_fingerprint_raw() */ freerrset(fingerprints); if (*flags & DNS_VERIFY_FOUND) @@ -337,7 +337,7 @@ export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic) for (i = 0; i < rdata_digest_len; i++) fprintf(f, "%02x", rdata_digest[i]); fprintf(f, "\n"); - free(rdata_digest); /* from key_fingerprint_raw() */ + free(rdata_digest); /* from sshkey_fingerprint_raw() */ success = 1; } } diff --git a/key.c b/key.c index c2b696af9..bbe027b66 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.126 2015/01/20 23:14:00 deraadt Exp $ */ +/* $OpenBSD: key.c,v 1.127 2015/01/28 22:36:00 djm Exp $ */ /* * placed in the public domain */ @@ -39,23 +39,6 @@ key_new_private(int type) return ret; } -u_char* -key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length) -{ - u_char *ret = NULL; - size_t dlen; - int r; - - if (dgst_raw_length != NULL) - *dgst_raw_length = 0; - if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - if (dlen > INT_MAX) - fatal("%s: giant len %zu", __func__, dlen); - *dgst_raw_length = dlen; - return ret; -} - int key_read(Key *ret, char **cpp) { diff --git a/key.h b/key.h index bf884970c..89fd5cfdf 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.46 2015/01/13 07:39:19 djm Exp $ */ +/* $OpenBSD: key.h,v 1.47 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -39,7 +39,6 @@ typedef struct sshkey Key; #define key_free sshkey_free #define key_equal_public sshkey_equal_public #define key_equal sshkey_equal -#define key_fingerprint sshkey_fingerprint #define key_type sshkey_type #define key_cert_type sshkey_cert_type #define key_ssh_name sshkey_ssh_name @@ -59,14 +58,12 @@ typedef struct sshkey Key; #define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg #define key_dump_ec_point sshkey_dump_ec_point #define key_dump_ec_key sshkey_dump_ec_key -#define key_fingerprint sshkey_fingerprint #endif void key_add_private(Key *); Key *key_new_private(int); void key_free(Key *); Key *key_demote(const Key *); -u_char *key_fingerprint_raw(const Key *, int, u_int *); int key_write(const Key *, FILE *); int key_read(Key *, char **); diff --git a/ssh-add.c b/ssh-add.c index 5ac51088f..676e65d16 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.117 2015/01/16 06:40:12 deraadt Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.118 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -375,7 +375,8 @@ list_identities(int agent_fd, int do_fp) fp = sshkey_fingerprint(idlist->keys[i], fingerprint_hash, SSH_FP_DEFAULT); printf("%d %s %s (%s)\n", - sshkey_size(idlist->keys[i]), fp, + sshkey_size(idlist->keys[i]), + fp == NULL ? "(null)" : fp, idlist->comments[i], sshkey_type(idlist->keys[i])); free(fp); diff --git a/ssh-agent.c b/ssh-agent.c index ba8d020ad..41e12acc9 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.196 2015/01/16 06:40:12 deraadt Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.197 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -212,7 +212,8 @@ confirm_key(Identity *id) int ret = -1; p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); - if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", + if (p != NULL && + ask_permission("Allow use of key %s?\nKey fingerprint %s.", id->comment, p)) ret = 0; free(p); diff --git a/ssh-keygen.c b/ssh-keygen.c index ac20723b8..b8489dc8b 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.258 2015/01/19 00:32:54 deraadt Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.259 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -800,6 +800,8 @@ do_download(struct passwd *pw) fp = sshkey_fingerprint(keys[i], fptype, rep); ra = sshkey_fingerprint(keys[i], fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]), fp, sshkey_type(keys[i])); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -846,6 +848,8 @@ do_fingerprint(struct passwd *pw) fp = sshkey_fingerprint(public, fptype, rep); ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment, sshkey_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -915,6 +919,8 @@ do_fingerprint(struct passwd *pw) fp = sshkey_fingerprint(public, fptype, rep); ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment ? comment : "no comment", sshkey_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) @@ -1902,6 +1908,8 @@ do_show_cert(struct passwd *pw) key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); ca_fp = sshkey_fingerprint(key->cert->signature_key, fingerprint_hash, SSH_FP_DEFAULT); + if (key_fp == NULL || ca_fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); printf("%s:\n", identity_file); printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), @@ -2216,7 +2224,7 @@ main(int argc, char **argv) { char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2; char *checkpoint = NULL; - char out_file[PATH_MAX], *rr_hostname = NULL, *ep; + char out_file[PATH_MAX], *rr_hostname = NULL, *ep, *fp, *ra; struct sshkey *private, *public; struct passwd *pw; struct stat st; @@ -2709,10 +2717,12 @@ passphrase_again: fclose(f); if (!quiet) { - char *fp = sshkey_fingerprint(public, fingerprint_hash, + fp = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_DEFAULT); - char *ra = sshkey_fingerprint(public, fingerprint_hash, + ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("sshkey_fingerprint failed"); printf("Your public key has been saved in %s.\n", identity_file); printf("The key fingerprint is:\n"); diff --git a/ssh-keysign.c b/ssh-keysign.c index 222327ef1..bcf897a05 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.46 2015/01/15 09:40:00 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.47 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -274,8 +274,9 @@ main(int argc, char **argv) } } if (!found) { - fp = sshkey_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); fatal("no matching hostkey found for key %s %s", sshkey_type(key), fp ? fp : ""); } diff --git a/sshconnect.c b/sshconnect.c index df921bec1..9e515066d 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.258 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.259 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -770,7 +770,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) - fatal("check_host_key: getnameinfo failed"); + fatal("%s: getnameinfo failed", __func__); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup("key, + fp = sshkey_fingerprint(found->key, options.fingerprint_hash, SSH_FP_DEFAULT); - ra = key_fingerprint(found->key, + ra = sshkey_fingerprint(found->key, options.fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", @@ -1423,8 +1429,10 @@ warn_changed_key(Key *host_key) { char *fp; - fp = key_fingerprint(host_key, options.fingerprint_hash, + fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); + if (fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); diff --git a/sshconnect2.c b/sshconnect2.c index 8da4d70dd..48882e3a5 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.221 2015/01/20 20:16:21 markus Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.222 2015/01/28 22:36:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -591,7 +591,9 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) key->type, pktype); goto done; } - fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + goto done; debug2("input_userauth_pk_ok: fp %s", fp); free(fp); @@ -1009,7 +1011,9 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) int have_sig = 1; char *fp; - fp = key_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT); + if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + return 0; debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); free(fp); -- cgit v1.2.3 From 13a39414d25646f93e6d355521d832a03aaaffe2 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 17 Feb 2015 00:14:05 +0000 Subject: upstream commit Regression: I broke logging of public key fingerprints in 1.46. Pointed out by Pontus Lundkvist --- auth2-pubkey.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth2-pubkey.c b/auth2-pubkey.c index d8f0aa3e2..d943efa1e 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.46 2015/01/28 22:36:00 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.47 2015/02/17 00:14:05 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -234,14 +234,14 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) key_type(key), key->cert->key_id, (unsigned long long)key->cert->serial, key_type(key->cert->signature_key), - fp == NULL ? "(null)" : "", + 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 == NULL ? "(null)" : fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } -- cgit v1.2.3