diff --git a/openssh-6.7p1-fingerprint.patch b/openssh-6.7p1-fingerprint.patch new file mode 100644 index 0000000..da798dd --- /dev/null +++ b/openssh-6.7p1-fingerprint.patch @@ -0,0 +1,1289 @@ +diff -up openssh-6.7p1/auth2-hostbased.c.fingerprint openssh-6.7p1/auth2-hostbased.c +--- openssh-6.7p1/auth2-hostbased.c.fingerprint 2014-07-18 06:11:25.000000000 +0200 ++++ openssh-6.7p1/auth2-hostbased.c 2014-12-22 13:10:57.961878113 +0100 +@@ -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, + 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 -up openssh-6.7p1/auth2-pubkey.c.fingerprint openssh-6.7p1/auth2-pubkey.c +--- openssh-6.7p1/auth2-pubkey.c.fingerprint 2014-07-18 06:11:25.000000000 +0200 ++++ openssh-6.7p1/auth2-pubkey.c 2014-12-22 13:13:56.446258343 +0100 +@@ -213,7 +213,7 @@ pubkey_auth_info(Authctxt *authctxt, con + + 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, con + 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, + 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, + 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, + return 0; + + ca_fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, SSH_FP_HEX); ++ options.fingerprint_hash, SSH_FP_DEFAULT); + + if (key_in_file(key->cert->signature_key, + options.trusted_user_ca_keys, 1) != 1) { +diff -up openssh-6.7p1/auth.c.fingerprint openssh-6.7p1/auth.c +--- openssh-6.7p1/auth.c.fingerprint 2014-12-22 13:10:57.961878113 +0100 ++++ openssh-6.7p1/auth.c 2014-12-22 13:27:18.105463774 +0100 +@@ -702,7 +702,7 @@ auth_key_is_revoked(Key *key) + case 1: + revoked: + /* Key revoked */ +- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ key_fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); + error("WARNING: authentication attempt with a revoked " + "%s key %s ", key_type(key), key_fp); + free(key_fp); +diff -up openssh-6.7p1/auth-rsa.c.fingerprint openssh-6.7p1/auth-rsa.c +--- openssh-6.7p1/auth-rsa.c.fingerprint 2014-07-18 06:11:25.000000000 +0200 ++++ openssh-6.7p1/auth-rsa.c 2014-12-22 13:10:57.960878116 +0100 +@@ -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 *p + "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 -up openssh-6.7p1/digest.h.fingerprint openssh-6.7p1/digest.h +--- openssh-6.7p1/digest.h.fingerprint 2014-07-03 13:25:04.000000000 +0200 ++++ openssh-6.7p1/digest.h 2014-12-22 13:10:57.961878113 +0100 +@@ -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 -up openssh-6.7p1/digest-libc.c.fingerprint openssh-6.7p1/digest-libc.c +--- openssh-6.7p1/digest-libc.c.fingerprint 2014-07-02 07:28:03.000000000 +0200 ++++ openssh-6.7p1/digest-libc.c 2014-12-22 13:10:57.961878113 +0100 +@@ -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 -up openssh-6.7p1/digest-openssl.c.fingerprint openssh-6.7p1/digest-openssl.c +--- openssh-6.7p1/digest-openssl.c.fingerprint 2014-07-17 01:01:26.000000000 +0200 ++++ openssh-6.7p1/digest-openssl.c 2014-12-22 13:10:57.961878113 +0100 +@@ -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 -up openssh-6.7p1/dns.c.fingerprint openssh-6.7p1/dns.c +--- openssh-6.7p1/dns.c.fingerprint 2014-07-02 07:28:03.000000000 +0200 ++++ openssh-6.7p1/dns.c 2014-12-22 13:10:57.962878109 +0100 +@@ -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 + 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 + + 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 -up openssh-6.7p1/key.c.fingerprint openssh-6.7p1/key.c +--- openssh-6.7p1/key.c.fingerprint 2014-07-23 01:40:47.000000000 +0200 ++++ openssh-6.7p1/key.c 2014-12-22 13:10:57.962878109 +0100 +@@ -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 f + + 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 -up openssh-6.7p1/key.h.fingerprint openssh-6.7p1/key.h +--- openssh-6.7p1/key.h.fingerprint 2014-08-21 02:48:41.000000000 +0200 ++++ openssh-6.7p1/key.h 2014-12-22 13:10:57.962878109 +0100 +@@ -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 -up openssh-6.7p1/krl.c.fingerprint openssh-6.7p1/krl.c +--- openssh-6.7p1/krl.c.fingerprint 2014-12-22 13:10:57.962878109 +0100 ++++ openssh-6.7p1/krl.c 2014-12-22 13:24:45.969002948 +0100 +@@ -36,6 +36,7 @@ + #include "misc.h" + #include "log.h" + #include "xmalloc.h" ++#include "digest.h" + + #include "krl.h" + +@@ -406,7 +407,7 @@ ssh_krl_revoke_key_sha1(struct ssh_krl * + u_int len; + + debug3("%s: revoke type %s by sha1", __func__, key_type(key)); +- if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL) ++ if ((blob = key_fingerprint_raw(key, SSH_DIGEST_SHA1, &len)) == NULL) + return -1; + return revoke_blob(&krl->revoked_sha1s, blob, len); + } +@@ -1119,7 +1120,7 @@ is_key_revoked(struct ssh_krl *krl, cons + + /* Check explicitly revoked hashes first */ + memset(&rb, 0, sizeof(rb)); +- if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL) ++ if ((rb.blob = key_fingerprint_raw(key, SSH_DIGEST_SHA1, &rb.len)) == NULL) + return -1; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); + free(rb.blob); +diff -up openssh-6.7p1/readconf.c.fingerprint openssh-6.7p1/readconf.c +--- openssh-6.7p1/readconf.c.fingerprint 2014-07-18 06:11:26.000000000 +0200 ++++ openssh-6.7p1/readconf.c 2014-12-22 13:20:33.488879658 +0100 +@@ -56,6 +56,7 @@ + #include "kex.h" + #include "mac.h" + #include "uidswap.h" ++#include "digest.h" + + /* Format of the configuration file: + +@@ -151,6 +152,7 @@ typedef enum { + oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, + oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, + oStreamLocalBindMask, oStreamLocalBindUnlink, ++ oFingerprintHash, + oIgnoredUnknownOption, oDeprecated, oUnsupported + } OpCodes; + +@@ -265,6 +267,7 @@ static struct { + { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, + { "streamlocalbindmask", oStreamLocalBindMask }, + { "streamlocalbindunlink", oStreamLocalBindUnlink }, ++ { "fingerprinthash", oFingerprintHash }, + { "ignoreunknown", oIgnoreUnknown }, + + { NULL, oBadOption } +@@ -1097,6 +1100,9 @@ parse_int: + options->hostkeyalgorithms = xstrdup(arg); + break; + ++ case oFingerprintHash: ++ return ssh_digest_alg_name(val); ++ + case oProtocol: + intptr = &options->protocol; + arg = strdelim(&s); +@@ -1433,6 +1439,18 @@ parse_int: + intptr = &options->fwd_opts.streamlocal_bind_unlink; + goto parse_flag; + ++ 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); +@@ -1609,6 +1627,7 @@ initialize_options(Options * options) + options->canonicalize_max_dots = -1; + options->canonicalize_fallback_local = -1; + options->canonicalize_hostname = -1; ++ options->fingerprint_hash = -1; + } + + /* +@@ -1786,6 +1805,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)) { \ +diff -up openssh-6.7p1/readconf.h.fingerprint openssh-6.7p1/readconf.h +--- openssh-6.7p1/readconf.h.fingerprint 2014-12-22 13:10:57.963878106 +0100 ++++ openssh-6.7p1/readconf.h 2014-12-22 13:14:24.075162395 +0100 +@@ -144,6 +144,8 @@ typedef struct { + int num_permitted_cnames; + struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS]; + ++ int fingerprint_hash; ++ + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ + } Options; + +diff -up openssh-6.7p1/servconf.c.fingerprint openssh-6.7p1/servconf.c +--- openssh-6.7p1/servconf.c.fingerprint 2014-07-18 06:11:26.000000000 +0200 ++++ openssh-6.7p1/servconf.c 2014-12-22 13:25:22.626875655 +0100 +@@ -54,6 +54,7 @@ + #include "packet.h" + #include "hostfile.h" + #include "auth.h" ++#include "digest.h" + + static void add_listen_addr(ServerOptions *, char *, int); + static void add_one_listen_addr(ServerOptions *, char *, int); +@@ -157,6 +158,7 @@ initialize_server_options(ServerOptions + options->ip_qos_interactive = -1; + options->ip_qos_bulk = -1; + options->version_addendum = NULL; ++ options->fingerprint_hash = -1; + } + + void +@@ -312,6 +314,8 @@ fill_default_server_options(ServerOption + 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; +@@ -361,7 +365,7 @@ typedef enum { + sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, + sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, + sStreamLocalBindMask, sStreamLocalBindUnlink, +- sAllowStreamLocalForwarding, ++ sAllowStreamLocalForwarding, sFingerprintHash, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -492,6 +496,7 @@ static struct { + { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, + { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, + { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, ++ { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, + { NULL, sBadOption, 0 } + }; + +@@ -1663,6 +1668,18 @@ process_server_config_line(ServerOptions + 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); +@@ -1905,6 +1922,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: +@@ -2066,6 +2085,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 -up openssh-6.7p1/servconf.h.fingerprint openssh-6.7p1/servconf.h +--- openssh-6.7p1/servconf.h.fingerprint 2014-07-18 06:11:26.000000000 +0200 ++++ openssh-6.7p1/servconf.h 2014-12-22 13:10:57.964878102 +0100 +@@ -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 -up openssh-6.7p1/ssh.1.fingerprint openssh-6.7p1/ssh.1 +--- openssh-6.7p1/ssh.1.fingerprint 2014-07-30 04:32:28.000000000 +0200 ++++ openssh-6.7p1/ssh.1 2014-12-22 13:10:57.967878092 +0100 +@@ -1083,7 +1083,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 -up openssh-6.7p1/ssh-add.1.fingerprint openssh-6.7p1/ssh-add.1 +--- openssh-6.7p1/ssh-add.1.fingerprint 2013-12-18 07:46:28.000000000 +0100 ++++ openssh-6.7p1/ssh-add.1 2014-12-22 13:10:57.964878102 +0100 +@@ -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 pat + 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 -up openssh-6.7p1/ssh-add.c.fingerprint openssh-6.7p1/ssh-add.c +--- openssh-6.7p1/ssh-add.c.fingerprint 2014-07-11 01:19:05.000000000 +0200 ++++ openssh-6.7p1/ssh-add.c 2014-12-22 13:10:57.965878099 +0100 +@@ -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 + 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 -up openssh-6.7p1/ssh-agent.1.fingerprint openssh-6.7p1/ssh-agent.1 +--- openssh-6.7p1/ssh-agent.1.fingerprint 2014-04-20 05:25:09.000000000 +0200 ++++ openssh-6.7p1/ssh-agent.1 2014-12-22 13:10:57.965878099 +0100 +@@ -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 -up openssh-6.7p1/ssh-agent.c.fingerprint openssh-6.7p1/ssh-agent.c +--- openssh-6.7p1/ssh-agent.c.fingerprint 2014-07-30 04:32:46.000000000 +0200 ++++ openssh-6.7p1/ssh-agent.c 2014-12-22 13:10:57.965878099 +0100 +@@ -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 -up openssh-6.7p1/sshconnect2.c.fingerprint openssh-6.7p1/sshconnect2.c +--- openssh-6.7p1/sshconnect2.c.fingerprint 2014-07-18 06:11:27.000000000 +0200 ++++ openssh-6.7p1/sshconnect2.c 2014-12-22 13:10:57.968878088 +0100 +@@ -582,7 +582,7 @@ input_userauth_pk_ok(int type, u_int32_t + 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, + 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 -up openssh-6.7p1/sshconnect.c.fingerprint openssh-6.7p1/sshconnect.c +--- openssh-6.7p1/sshconnect.c.fingerprint 2014-07-18 06:11:26.000000000 +0200 ++++ openssh-6.7p1/sshconnect.c 2014-12-22 13:15:28.371939131 +0100 +@@ -915,9 +915,10 @@ check_host_key(char *hostname, struct so + "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); +@@ -956,9 +957,10 @@ check_host_key(char *hostname, struct so + 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) +@@ -1222,7 +1224,7 @@ verify_host_key(char *host, struct socka + char *fp; + Key *plain = NULL; + +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); + debug("Server host key: %s %s", key_type(host_key), fp); + free(fp); + +@@ -1356,8 +1358,10 @@ show_other_keys(struct hostkeys *hostkey + 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.", +@@ -1378,7 +1382,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 -up openssh-6.7p1/sshd_config.5.fingerprint openssh-6.7p1/sshd_config.5 +--- openssh-6.7p1/sshd_config.5.fingerprint 2014-10-03 01:24:57.000000000 +0200 ++++ openssh-6.7p1/sshd_config.5 2014-12-22 13:10:57.968878088 +0100 +@@ -483,6 +483,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 -up openssh-6.7p1/sshkey.c.fingerprint openssh-6.7p1/sshkey.c +--- openssh-6.7p1/sshkey.c.fingerprint 2014-07-21 17:07:11.000000000 +0200 ++++ openssh-6.7p1/sshkey.c 2014-12-22 13:10:57.969878085 +0100 +@@ -29,6 +29,7 @@ + + #include + #include ++#include + + #include + #include +@@ -852,29 +853,18 @@ sshkey_plain_to_blob(const struct sshkey + } + + 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 sshk + 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 sshk + 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 sshk + } + + 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; ++} ++ ++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; + +- /* Remove the trailing ':' character */ +- retval[(dgst_raw_len * 3) - 1] = '\0'; ++ 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_ra + #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, + * 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, + 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, + *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, + + /* 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, + } + + 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 -up openssh-6.7p1/ssh-keygen.1.fingerprint openssh-6.7p1/ssh-keygen.1 +--- openssh-6.7p1/ssh-keygen.1.fingerprint 2014-04-20 05:23:04.000000000 +0200 ++++ openssh-6.7p1/ssh-keygen.1 2014-12-22 13:10:57.966878095 +0100 +@@ -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 -up openssh-6.7p1/ssh-keygen.c.fingerprint openssh-6.7p1/ssh-keygen.c +--- openssh-6.7p1/ssh-keygen.c.fingerprint 2014-07-03 13:24:41.000000000 +0200 ++++ openssh-6.7p1/ssh-keygen.c 2014-12-22 13:10:57.966878095 +0100 +@@ -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) +@@ -991,13 +996,15 @@ printhost(FILE *f, const char *name, Key + { + 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) +@@ -1906,9 +1913,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), +@@ -2187,7 +2194,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, +@@ -2256,9 +2263,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; +@@ -2269,6 +2277,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; +@@ -2700,8 +2713,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 -up openssh-6.7p1/sshkey.h.fingerprint openssh-6.7p1/sshkey.h +--- openssh-6.7p1/sshkey.h.fingerprint 2014-08-20 03:06:51.000000000 +0200 ++++ openssh-6.7p1/sshkey.h 2014-12-22 13:10:57.969878085 +0100 +@@ -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 s + 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 *); +diff -up openssh-6.7p1/ssh-keysign.c.fingerprint openssh-6.7p1/ssh-keysign.c +--- openssh-6.7p1/ssh-keysign.c.fingerprint 2014-05-15 06:24:10.000000000 +0200 ++++ openssh-6.7p1/ssh-keysign.c 2014-12-22 13:10:57.967878092 +0100 +@@ -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/openssh.spec b/openssh.spec index 2be8093..28abea8 100644 --- a/openssh.spec +++ b/openssh.spec @@ -95,7 +95,7 @@ Patch0: openssh-5.9p1-wIm.patch #? Patch100: openssh-6.6.1p1-coverity.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1872 -Patch101: openssh-6.6p1-fingerprint.patch +Patch101: openssh-6.7p1-fingerprint.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1894 #https://bugzilla.redhat.com/show_bug.cgi?id=735889 Patch102: openssh-5.8p1-getaddrinfo.patch