From 4df30a2a723c5c348205c0a55a3e230aff69f2a0 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Aug 19 2015 11:43:36 +0000 Subject: Possibility to validate legacy systems by more fingerprints (#1249626) --- diff --git a/openssh-6.7p1-fips.patch b/openssh-6.7p1-fips.patch index c5c5dda..b8d5ede 100644 --- a/openssh-6.7p1-fips.patch +++ b/openssh-6.7p1-fips.patch @@ -350,7 +350,7 @@ diff -up openssh-7.0p1/readconf.c.fips openssh-7.0p1/readconf.c --- openssh-7.0p1/readconf.c.fips 2015-08-19 12:36:51.138412921 +0200 +++ openssh-7.0p1/readconf.c 2015-08-19 12:36:51.152412889 +0200 @@ -1915,9 +1915,12 @@ fill_default_options(Options * options) - options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + } if (options->update_hostkeys == -1) options->update_hostkeys = 0; - if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || diff --git a/openssh-7.0p1-show-more-fingerprints.patch b/openssh-7.0p1-show-more-fingerprints.patch new file mode 100644 index 0000000..368f152 --- /dev/null +++ b/openssh-7.0p1-show-more-fingerprints.patch @@ -0,0 +1,318 @@ +From e1d58c44bd911e5ee4dddb6205e16eb9a03cc736 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 7 Aug 2015 10:18:54 +0200 +Subject: [PATCH] Possibility tu specify more fingerprint algorithms on client + side for smother transition + +--- + clientloop.c | 8 ++++---- + readconf.c | 43 +++++++++++++++++++++++++++++-------------- + readconf.h | 4 +++- + ssh_config.5 | 4 ++-- + sshconnect.c | 48 +++++++++++++++++++++++++++--------------------- + sshconnect2.c | 6 +++--- + 6 files changed, 68 insertions(+), 45 deletions(-) + +diff --git a/clientloop.c b/clientloop.c +index 87ceb3d..4553114 100644 +--- a/clientloop.c ++++ b/clientloop.c +@@ -2194,7 +2194,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) + if (ctx->keys_seen[i] != 2) + continue; + if ((fp = sshkey_fingerprint(ctx->keys[i], +- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) ++ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + do_log2(loglevel, "Learned new hostkey: %s %s", + sshkey_type(ctx->keys[i]), fp); +@@ -2202,7 +2202,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) + } + for (i = 0; i < ctx->nold; i++) { + if ((fp = sshkey_fingerprint(ctx->old_keys[i], +- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) ++ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", + sshkey_type(ctx->old_keys[i]), fp); +@@ -2245,7 +2245,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) + (r = hostfile_replace_entries(options.user_hostfiles[0], + ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys, + options.hash_known_hosts, 0, +- options.fingerprint_hash)) != 0) ++ options.fingerprint_hash[0])) != 0) + error("%s: hostfile_replace_entries failed: %s", + __func__, ssh_err(r)); + } +@@ -2358,7 +2358,7 @@ client_input_hostkeys(void) + error("%s: parse key: %s", __func__, ssh_err(r)); + goto out; + } +- fp = sshkey_fingerprint(key, options.fingerprint_hash, ++ fp = sshkey_fingerprint(key, options.fingerprint_hash[0], + SSH_FP_DEFAULT); + debug3("%s: received %s key %s", __func__, + sshkey_type(key), fp); +diff --git a/readconf.c b/readconf.c +index 1d03bdf..6af4c62 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -1471,16 +1471,18 @@ parse_keytypes: + goto parse_string; + + case oFingerprintHash: +- intptr = &options->fingerprint_hash; +- 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 && *intptr == -1) +- *intptr = value; ++ if (*activep && options->num_fingerprint_hash == 0) ++ while ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ value = ssh_digest_alg_by_name(arg); ++ if (value == -1) ++ fatal("%s line %d: unknown fingerprints algorithm specs: %s.", ++ filename, linenum, arg); ++ if (options->num_fingerprint_hash >= SSH_DIGEST_MAX) ++ fatal("%s line %d: too many fingerprints algorithm specs.", ++ filename, linenum); ++ options->fingerprint_hash[ ++ options->num_fingerprint_hash++] = value; ++ } + break; + + case oUpdateHostkeys: +@@ -1673,7 +1675,7 @@ initialize_options(Options * options) + options->canonicalize_fallback_local = -1; + options->canonicalize_hostname = -1; + options->revoked_host_keys = NULL; +- options->fingerprint_hash = -1; ++ options->num_fingerprint_hash = 0; + options->update_hostkeys = -1; + options->hostbased_key_types = NULL; + options->pubkey_key_types = NULL; +@@ -1851,8 +1853,10 @@ 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; ++ if (options->num_fingerprint_hash == 0) { ++ options->fingerprint_hash[options->num_fingerprint_hash++] = SSH_DIGEST_SHA256; ++ options->fingerprint_hash[options->num_fingerprint_hash++] = SSH_DIGEST_MD5; ++ } + if (options->update_hostkeys == -1) + options->update_hostkeys = 0; + if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || +@@ -2189,6 +2193,17 @@ dump_cfg_strarray(OpCodes code, u_int count, char **vals) + } + + static void ++dump_cfg_fmtarray(OpCodes code, u_int count, int *vals) ++{ ++ u_int i; ++ ++ printf("%s", lookup_opcode_name(code)); ++ for (i = 0; i < count; i++) ++ printf(" %s", fmt_intarg(code, vals[i])); ++ printf("\n"); ++} ++ ++static void + dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) + { + u_int i; +@@ -2259,7 +2274,6 @@ 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); +@@ -2328,6 +2342,7 @@ dump_client_config(Options *o, const char *host) + dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); + dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); + dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); ++ dump_cfg_fmtarray(oFingerprintHash, o->num_fingerprint_hash, o->fingerprint_hash); + + /* Special cases */ + +diff --git a/readconf.h b/readconf.h +index bb2d552..d817f92 100644 +--- a/readconf.h ++++ b/readconf.h +@@ -21,6 +21,7 @@ + #define MAX_SEND_ENV 256 + #define SSH_MAX_HOSTS_FILES 32 + #define MAX_CANON_DOMAINS 32 ++#define MAX_SSH_DIGESTS 32 + #define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path) + + struct allowed_cname { +@@ -146,7 +147,8 @@ typedef struct { + + char *revoked_host_keys; + +- int fingerprint_hash; ++ int num_fingerprint_hash; ++ int fingerprint_hash[MAX_SSH_DIGESTS]; + + int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ + +diff --git a/ssh_config.5 b/ssh_config.5 +index 5b0975f..e8e6458 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -647,13 +647,13 @@ or + The default is + .Dq no . + .It Cm FingerprintHash +-Specifies the hash algorithm used when displaying key fingerprints. ++Specifies the hash algorithms used when displaying key fingerprints. + Valid options are: + .Dq md5 + and + .Dq sha256 . + The default is +-.Dq sha256 . ++.Dq "sha256 md5". + .It Cm ForwardAgent + Specifies whether the connection to the authentication agent (if any) + will be forwarded to the remote machine. +diff --git a/sshconnect.c b/sshconnect.c +index f41960c..e12932f 100644 +--- a/sshconnect.c ++++ b/sshconnect.c +@@ -920,9 +920,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, + "of known hosts.", type, ip); + } else if (options.visual_host_key) { + fp = sshkey_fingerprint(host_key, +- options.fingerprint_hash, SSH_FP_DEFAULT); ++ options.fingerprint_hash[0], SSH_FP_DEFAULT); + ra = sshkey_fingerprint(host_key, +- options.fingerprint_hash, SSH_FP_RANDOMART); ++ options.fingerprint_hash[0], SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); + logit("Host key fingerprint is %s\n%s\n", fp, ra); +@@ -964,12 +964,6 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, + else + snprintf(msg1, sizeof(msg1), "."); + /* The default */ +- fp = sshkey_fingerprint(host_key, +- options.fingerprint_hash, SSH_FP_DEFAULT); +- ra = sshkey_fingerprint(host_key, +- options.fingerprint_hash, SSH_FP_RANDOMART); +- if (fp == NULL || ra == NULL) +- fatal("%s: sshkey_fingerprint fail", __func__); + msg2[0] = '\0'; + if (options.verify_host_key_dns) { + if (matching_host_key_dns) +@@ -983,16 +977,28 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, + } + snprintf(msg, sizeof(msg), + "The authenticity of host '%.200s (%s)' can't be " +- "established%s\n" +- "%s key fingerprint is %s.%s%s\n%s" ++ "established%s\n", host, ip, msg1); ++ for (i = 0; i < options.num_fingerprint_hash; i++) { ++ fp = sshkey_fingerprint(host_key, ++ options.fingerprint_hash[i], SSH_FP_DEFAULT); ++ ra = sshkey_fingerprint(host_key, ++ options.fingerprint_hash[i], SSH_FP_RANDOMART); ++ if (fp == NULL || ra == NULL) ++ fatal("%s: sshkey_fingerprint fail", __func__); ++ len = strlen(msg); ++ snprintf(msg+len, sizeof(msg)-len, ++ "%s key fingerprint is %s.%s%s\n%s", ++ type, fp, ++ options.visual_host_key ? "\n" : "", ++ options.visual_host_key ? ra : "", ++ msg2); ++ free(ra); ++ free(fp); ++ } ++ len = strlen(msg); ++ snprintf(msg+len, sizeof(msg)-len, + "Are you sure you want to continue connecting " +- "(yes/no)? ", +- host, ip, msg1, type, fp, +- options.visual_host_key ? "\n" : "", +- options.visual_host_key ? ra : "", +- msg2); +- free(ra); +- free(fp); ++ "(yes/no)? "); + if (!confirm(msg)) + goto fail; + hostkey_trusted = 1; /* user explicitly confirmed */ +@@ -1241,7 +1247,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) + struct sshkey *plain = NULL; + + if ((fp = sshkey_fingerprint(host_key, +- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { ++ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL) { + error("%s: fingerprint host key: %s", __func__, ssh_err(r)); + r = -1; + goto out; +@@ -1405,9 +1411,9 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) + if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) + continue; + fp = sshkey_fingerprint(found->key, +- options.fingerprint_hash, SSH_FP_DEFAULT); ++ options.fingerprint_hash[0], SSH_FP_DEFAULT); + ra = sshkey_fingerprint(found->key, +- options.fingerprint_hash, SSH_FP_RANDOMART); ++ options.fingerprint_hash[0], SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); + logit("WARNING: %s key found for host %s\n" +@@ -1430,7 +1436,7 @@ warn_changed_key(Key *host_key) + { + char *fp; + +- fp = sshkey_fingerprint(host_key, options.fingerprint_hash, ++ fp = sshkey_fingerprint(host_key, options.fingerprint_hash[0], + SSH_FP_DEFAULT); + if (fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); +diff --git a/sshconnect2.c b/sshconnect2.c +index 7751031..82ed92e 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -589,7 +589,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) + key->type, pktype); + goto done; + } +- if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, ++ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash[0], + SSH_FP_DEFAULT)) == NULL) + goto done; + debug2("input_userauth_pk_ok: fp %s", fp); +@@ -1009,7 +1009,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) + int have_sig = 1; + char *fp; + +- if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, ++ if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash[0], + SSH_FP_DEFAULT)) == NULL) + return 0; + debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); +@@ -1635,7 +1635,7 @@ userauth_hostbased(Authctxt *authctxt) + goto out; + } + +- if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, ++ if ((fp = sshkey_fingerprint(private, options.fingerprint_hash[0], + SSH_FP_DEFAULT)) == NULL) { + error("%s: sshkey_fingerprint failed", __func__); + goto out; +-- +2.1.0 + + diff --git a/openssh.spec b/openssh.spec index dc92806..09cba7b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -227,7 +227,8 @@ Patch929: openssh-6.9p1-permit-root-login.patch Patch931: openssh-6.9p1-scp-progressmeter.patch # Add GSSAPIKexAlgorithms option for server and client application Patch932: openssh-7.0p1-gssKexAlgorithms.patch - +# Possibility to validate legacy systems by more fingerprints (#1249626)(#2439) +Patch933: openssh-7.0p1-show-more-fingerprints.patch License: BSD @@ -464,6 +465,7 @@ popd %patch929 -p1 -b .root-login %patch931 -p1 -b .progressmeter %patch932 -p1 -b .gsskexalg +%patch933 -p1 -b .fingerprint %patch200 -p1 -b .audit %patch700 -p1 -b .fips