summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2014-12-21 22:27:55 +0000
committerDamien Miller <djm@mindrot.org>2014-12-22 09:32:29 +1100
commit56d1c83cdd1ac76f1c6bd41e01e80dad834f3994 (patch)
tree700a872e702c686c1815bb1049eb93e88079b598
parent058f839fe15c51be8b3a844a76ab9a8db550be4f (diff)
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@
-rw-r--r--auth-rsa.c5
-rw-r--r--auth.c5
-rw-r--r--auth2-hostbased.c7
-rw-r--r--auth2-pubkey.c16
-rw-r--r--digest-libc.c22
-rw-r--r--digest-openssl.c22
-rw-r--r--digest.h8
-rw-r--r--dns.c11
-rw-r--r--key.c7
-rw-r--r--key.h4
-rw-r--r--krl.c8
-rw-r--r--readconf.c24
-rw-r--r--readconf.h4
-rw-r--r--servconf.c24
-rw-r--r--servconf.h4
-rw-r--r--ssh-add.113
-rw-r--r--ssh-add.c54
-rw-r--r--ssh-agent.113
-rw-r--r--ssh-agent.c15
-rw-r--r--ssh-keygen.113
-rw-r--r--ssh-keygen.c58
-rw-r--r--ssh-keysign.c5
-rw-r--r--ssh.16
-rw-r--r--sshconnect.c27
-rw-r--r--sshconnect2.c6
-rw-r--r--sshd_config.513
-rw-r--r--sshkey.c113
-rw-r--r--sshkey.h16
28 files changed, 374 insertions, 149 deletions
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 @@
1/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */ 1/* $OpenBSD: auth-rsa.c,v 1.89 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -236,7 +236,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
236 "actual %d vs. announced %d.", 236 "actual %d vs. announced %d.",
237 file, linenum, BN_num_bits(key->rsa->n), bits); 237 file, linenum, BN_num_bits(key->rsa->n), bits);
238 238
239 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 239 fp = key_fingerprint(key, options.fingerprint_hash,
240 SSH_FP_DEFAULT);
240 debug("matching key found: file %s, line %lu %s %s", 241 debug("matching key found: file %s, line %lu %s %s",
241 file, linenum, key_type(key), fp); 242 file, linenum, key_type(key), fp);
242 free(fp); 243 free(fp);
diff --git a/auth.c b/auth.c
index 348ddc398..b259c6ef1 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.107 2014/12/04 02:24:32 djm Exp $ */ 1/* $OpenBSD: auth.c,v 1.108 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -679,7 +679,8 @@ auth_key_is_revoked(Key *key)
679 679
680 if (options.revoked_keys_file == NULL) 680 if (options.revoked_keys_file == NULL)
681 return 0; 681 return 0;
682 if ((fp = sshkey_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX)) == NULL) { 682 if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
683 SSH_FP_DEFAULT)) == NULL) {
683 r = SSH_ERR_ALLOC_FAIL; 684 r = SSH_ERR_ALLOC_FAIL;
684 error("%s: fingerprint key: %s", __func__, ssh_err(r)); 685 error("%s: fingerprint key: %s", __func__, ssh_err(r));
685 goto out; 686 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 @@
1/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ 1/* $OpenBSD: auth2-hostbased.c,v 1.19 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -208,13 +208,14 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
208 if (host_status == HOST_OK) { 208 if (host_status == HOST_OK) {
209 if (key_is_cert(key)) { 209 if (key_is_cert(key)) {
210 fp = key_fingerprint(key->cert->signature_key, 210 fp = key_fingerprint(key->cert->signature_key,
211 SSH_FP_MD5, SSH_FP_HEX); 211 options.fingerprint_hash, SSH_FP_DEFAULT);
212 verbose("Accepted certificate ID \"%s\" signed by " 212 verbose("Accepted certificate ID \"%s\" signed by "
213 "%s CA %s from %s@%s", key->cert->key_id, 213 "%s CA %s from %s@%s", key->cert->key_id,
214 key_type(key->cert->signature_key), fp, 214 key_type(key->cert->signature_key), fp,
215 cuser, lookup); 215 cuser, lookup);
216 } else { 216 } else {
217 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 217 fp = key_fingerprint(key, options.fingerprint_hash,
218 SSH_FP_DEFAULT);
218 verbose("Accepted %s public key %s from %s@%s", 219 verbose("Accepted %s public key %s from %s@%s",
219 key_type(key), fp, cuser, lookup); 220 key_type(key), fp, cuser, lookup);
220 } 221 }
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 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.42 2014/12/04 02:24:32 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -213,7 +213,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
213 213
214 if (key_is_cert(key)) { 214 if (key_is_cert(key)) {
215 fp = key_fingerprint(key->cert->signature_key, 215 fp = key_fingerprint(key->cert->signature_key,
216 SSH_FP_MD5, SSH_FP_HEX); 216 options.fingerprint_hash, SSH_FP_DEFAULT);
217 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 217 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
218 key_type(key), key->cert->key_id, 218 key_type(key), key->cert->key_id,
219 (unsigned long long)key->cert->serial, 219 (unsigned long long)key->cert->serial,
@@ -221,7 +221,8 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
221 extra == NULL ? "" : ", ", extra == NULL ? "" : extra); 221 extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
222 free(fp); 222 free(fp);
223 } else { 223 } else {
224 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 224 fp = key_fingerprint(key, options.fingerprint_hash,
225 SSH_FP_DEFAULT);
225 auth_info(authctxt, "%s %s%s%s", key_type(key), fp, 226 auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
226 extra == NULL ? "" : ", ", extra == NULL ? "" : extra); 227 extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
227 free(fp); 228 free(fp);
@@ -365,8 +366,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
365 continue; 366 continue;
366 if (!key_is_cert_authority) 367 if (!key_is_cert_authority)
367 continue; 368 continue;
368 fp = key_fingerprint(found, SSH_FP_MD5, 369 fp = key_fingerprint(found, options.fingerprint_hash,
369 SSH_FP_HEX); 370 SSH_FP_DEFAULT);
370 debug("matching CA found: file %s, line %lu, %s %s", 371 debug("matching CA found: file %s, line %lu, %s %s",
371 file, linenum, key_type(found), fp); 372 file, linenum, key_type(found), fp);
372 /* 373 /*
@@ -406,7 +407,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
406 if (key_is_cert_authority) 407 if (key_is_cert_authority)
407 continue; 408 continue;
408 found_key = 1; 409 found_key = 1;
409 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); 410 fp = key_fingerprint(found, options.fingerprint_hash,
411 SSH_FP_DEFAULT);
410 debug("matching key found: file %s, line %lu %s %s", 412 debug("matching key found: file %s, line %lu %s %s",
411 file, linenum, key_type(found), fp); 413 file, linenum, key_type(found), fp);
412 free(fp); 414 free(fp);
@@ -432,7 +434,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
432 return 0; 434 return 0;
433 435
434 ca_fp = key_fingerprint(key->cert->signature_key, 436 ca_fp = key_fingerprint(key->cert->signature_key,
435 SSH_FP_MD5, SSH_FP_HEX); 437 options.fingerprint_hash, SSH_FP_DEFAULT);
436 438
437 if (sshkey_in_file(key->cert->signature_key, 439 if (sshkey_in_file(key->cert->signature_key,
438 options.trusted_user_ca_keys, 1, 0) != 0) { 440 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 @@
1/* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: digest-libc.c,v 1.4 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * Copyright (c) 2014 Markus Friedl. All rights reserved. 4 * Copyright (c) 2014 Markus Friedl. All rights reserved.
@@ -126,6 +126,26 @@ ssh_digest_by_alg(int alg)
126 return &(digests[alg]); 126 return &(digests[alg]);
127} 127}
128 128
129int
130ssh_digest_alg_by_name(const char *name)
131{
132 int alg;
133
134 for (alg = 0; alg < SSH_DIGEST_MAX; alg++) {
135 if (strcasecmp(name, digests[alg].name) == 0)
136 return digests[alg].id;
137 }
138 return -1;
139}
140
141const char *
142ssh_digest_alg_name(int alg)
143{
144 const struct ssh_digest *digest = ssh_digest_by_alg(alg);
145
146 return digest == NULL ? NULL : digest->name;
147}
148
129size_t 149size_t
130ssh_digest_bytes(int alg) 150ssh_digest_bytes(int alg)
131{ 151{
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 @@
1/* $OpenBSD: digest-openssl.c,v 1.4 2014/07/03 03:26:43 djm Exp $ */ 1/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -74,6 +74,26 @@ ssh_digest_by_alg(int alg)
74 return &(digests[alg]); 74 return &(digests[alg]);
75} 75}
76 76
77int
78ssh_digest_alg_by_name(const char *name)
79{
80 int alg;
81
82 for (alg = 0; digests[alg].id != -1; alg++) {
83 if (strcasecmp(name, digests[alg].name) == 0)
84 return digests[alg].id;
85 }
86 return -1;
87}
88
89const char *
90ssh_digest_alg_name(int alg)
91{
92 const struct ssh_digest *digest = ssh_digest_by_alg(alg);
93
94 return digest == NULL ? NULL : digest->name;
95}
96
77size_t 97size_t
78ssh_digest_bytes(int alg) 98ssh_digest_bytes(int alg)
79{ 99{
diff --git a/digest.h b/digest.h
index 6afb197f0..3fe073468 100644
--- a/digest.h
+++ b/digest.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest.h,v 1.6 2014/07/03 04:36:45 djm Exp $ */ 1/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -33,6 +33,12 @@
33struct sshbuf; 33struct sshbuf;
34struct ssh_digest_ctx; 34struct ssh_digest_ctx;
35 35
36/* Looks up a digest algorithm by name */
37int ssh_digest_alg_by_name(const char *name);
38
39/* Returns the algorithm name for a digest identifier */
40const char *ssh_digest_alg_name(int alg);
41
36/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ 42/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
37size_t ssh_digest_bytes(int alg); 43size_t ssh_digest_bytes(int alg);
38 44
diff --git a/dns.c b/dns.c
index c4d073cf5..4b8ae44cf 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: dns.c,v 1.32 2014/12/21 22:27:56 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -41,6 +41,7 @@
41#include "key.h" 41#include "key.h"
42#include "dns.h" 42#include "dns.h"
43#include "log.h" 43#include "log.h"
44#include "digest.h"
44 45
45static const char *errset_text[] = { 46static const char *errset_text[] = {
46 "success", /* 0 ERRSET_SUCCESS */ 47 "success", /* 0 ERRSET_SUCCESS */
@@ -80,7 +81,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
80 u_char **digest, u_int *digest_len, Key *key) 81 u_char **digest, u_int *digest_len, Key *key)
81{ 82{
82 int success = 0; 83 int success = 0;
83 enum fp_type fp_type = 0; 84 int fp_alg = -1;
84 85
85 switch (key->type) { 86 switch (key->type) {
86 case KEY_RSA: 87 case KEY_RSA:
@@ -110,17 +111,17 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
110 111
111 switch (*digest_type) { 112 switch (*digest_type) {
112 case SSHFP_HASH_SHA1: 113 case SSHFP_HASH_SHA1:
113 fp_type = SSH_FP_SHA1; 114 fp_alg = SSH_DIGEST_SHA1;
114 break; 115 break;
115 case SSHFP_HASH_SHA256: 116 case SSHFP_HASH_SHA256:
116 fp_type = SSH_FP_SHA256; 117 fp_alg = SSH_DIGEST_SHA256;
117 break; 118 break;
118 default: 119 default:
119 *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 120 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
120 } 121 }
121 122
122 if (*algorithm && *digest_type) { 123 if (*algorithm && *digest_type) {
123 *digest = key_fingerprint_raw(key, fp_type, digest_len); 124 *digest = key_fingerprint_raw(key, fp_alg, digest_len);
124 if (*digest == NULL) 125 if (*digest == NULL)
125 fatal("dns_read_key: null from key_fingerprint_raw()"); 126 fatal("dns_read_key: null from key_fingerprint_raw()");
126 success = 1; 127 success = 1;
diff --git a/key.c b/key.c
index dd0f448a4..b821d9e1d 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.123 2014/12/04 20:47:36 djm Exp $ */ 1/* $OpenBSD: key.c,v 1.124 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * placed in the public domain 3 * placed in the public domain
4 */ 4 */
@@ -40,8 +40,7 @@ key_new_private(int type)
40} 40}
41 41
42u_char* 42u_char*
43key_fingerprint_raw(const Key *k, enum fp_type dgst_type, 43key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length)
44 u_int *dgst_raw_length)
45{ 44{
46 u_char *ret = NULL; 45 u_char *ret = NULL;
47 size_t dlen; 46 size_t dlen;
@@ -49,7 +48,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
49 48
50 if (dgst_raw_length != NULL) 49 if (dgst_raw_length != NULL)
51 *dgst_raw_length = 0; 50 *dgst_raw_length = 0;
52 if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0) 51 if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0)
53 fatal("%s: %s", __func__, ssh_err(r)); 52 fatal("%s: %s", __func__, ssh_err(r));
54 if (dlen > INT_MAX) 53 if (dlen > INT_MAX)
55 fatal("%s: giant len %zu", __func__, dlen); 54 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 @@
1/* $OpenBSD: key.h,v 1.43 2014/12/04 20:47:36 djm Exp $ */ 1/* $OpenBSD: key.h,v 1.44 2014/12/21 22:27:56 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -67,7 +67,7 @@ void key_add_private(Key *);
67Key *key_new_private(int); 67Key *key_new_private(int);
68void key_free(Key *); 68void key_free(Key *);
69Key *key_demote(const Key *); 69Key *key_demote(const Key *);
70u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); 70u_char *key_fingerprint_raw(const Key *, int, u_int *);
71int key_write(const Key *, FILE *); 71int key_write(const Key *, FILE *);
72int key_read(Key *, char **); 72int key_read(Key *, char **);
73 73
diff --git a/krl.c b/krl.c
index 5a5cdde02..3439e9c29 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.20 2014/12/04 01:49:59 djm Exp $ */ 17/* $OpenBSD: krl.c,v 1.21 2014/12/21 22:27:56 djm Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -36,6 +36,7 @@
36#include "misc.h" 36#include "misc.h"
37#include "log.h" 37#include "log.h"
38#include "ssherr.h" 38#include "ssherr.h"
39#include "digest.h"
39 40
40#include "krl.h" 41#include "krl.h"
41 42
@@ -411,7 +412,8 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key)
411 int r; 412 int r;
412 413
413 debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); 414 debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key));
414 if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0) 415 if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
416 &blob, &len)) != 0)
415 return r; 417 return r;
416 return revoke_blob(&krl->revoked_sha1s, blob, len); 418 return revoke_blob(&krl->revoked_sha1s, blob, len);
417} 419}
@@ -1151,7 +1153,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
1151 1153
1152 /* Check explicitly revoked hashes first */ 1154 /* Check explicitly revoked hashes first */
1153 memset(&rb, 0, sizeof(rb)); 1155 memset(&rb, 0, sizeof(rb));
1154 if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, 1156 if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
1155 &rb.blob, &rb.len)) != 0) 1157 &rb.blob, &rb.len)) != 0)
1156 return r; 1158 return r;
1157 erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); 1159 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 @@
1/* $OpenBSD: readconf.c,v 1.223 2014/12/04 02:24:32 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.224 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -60,6 +60,7 @@
60#include "mac.h" 60#include "mac.h"
61#include "uidswap.h" 61#include "uidswap.h"
62#include "myproposal.h" 62#include "myproposal.h"
63#include "digest.h"
63 64
64/* Format of the configuration file: 65/* Format of the configuration file:
65 66
@@ -155,6 +156,7 @@ typedef enum {
155 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 156 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
156 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 157 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
157 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 158 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
159 oFingerprintHash,
158 oIgnoredUnknownOption, oDeprecated, oUnsupported 160 oIgnoredUnknownOption, oDeprecated, oUnsupported
159} OpCodes; 161} OpCodes;
160 162
@@ -270,6 +272,7 @@ static struct {
270 { "streamlocalbindmask", oStreamLocalBindMask }, 272 { "streamlocalbindmask", oStreamLocalBindMask },
271 { "streamlocalbindunlink", oStreamLocalBindUnlink }, 273 { "streamlocalbindunlink", oStreamLocalBindUnlink },
272 { "revokedhostkeys", oRevokedHostKeys }, 274 { "revokedhostkeys", oRevokedHostKeys },
275 { "fingerprinthash", oFingerprintHash },
273 { "ignoreunknown", oIgnoreUnknown }, 276 { "ignoreunknown", oIgnoreUnknown },
274 277
275 { NULL, oBadOption } 278 { NULL, oBadOption }
@@ -1460,6 +1463,18 @@ parse_int:
1460 charptr = &options->revoked_host_keys; 1463 charptr = &options->revoked_host_keys;
1461 goto parse_string; 1464 goto parse_string;
1462 1465
1466 case oFingerprintHash:
1467 arg = strdelim(&s);
1468 if (!arg || *arg == '\0')
1469 fatal("%.200s line %d: Missing argument.",
1470 filename, linenum);
1471 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1472 fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1473 filename, linenum, arg);
1474 if (*activep)
1475 options->fingerprint_hash = value;
1476 break;
1477
1463 case oDeprecated: 1478 case oDeprecated:
1464 debug("%s line %d: Deprecated option \"%s\"", 1479 debug("%s line %d: Deprecated option \"%s\"",
1465 filename, linenum, keyword); 1480 filename, linenum, keyword);
@@ -1637,6 +1652,7 @@ initialize_options(Options * options)
1637 options->canonicalize_fallback_local = -1; 1652 options->canonicalize_fallback_local = -1;
1638 options->canonicalize_hostname = -1; 1653 options->canonicalize_hostname = -1;
1639 options->revoked_host_keys = NULL; 1654 options->revoked_host_keys = NULL;
1655 options->fingerprint_hash = -1;
1640} 1656}
1641 1657
1642/* 1658/*
@@ -1814,6 +1830,9 @@ fill_default_options(Options * options)
1814 options->canonicalize_fallback_local = 1; 1830 options->canonicalize_fallback_local = 1;
1815 if (options->canonicalize_hostname == -1) 1831 if (options->canonicalize_hostname == -1)
1816 options->canonicalize_hostname = SSH_CANONICALISE_NO; 1832 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1833 if (options->fingerprint_hash == -1)
1834 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
1835
1817#define CLEAR_ON_NONE(v) \ 1836#define CLEAR_ON_NONE(v) \
1818 do { \ 1837 do { \
1819 if (option_clear_or_none(v)) { \ 1838 if (option_clear_or_none(v)) { \
@@ -2071,6 +2090,8 @@ fmt_intarg(OpCodes code, int val)
2071 return fmt_multistate_int(val, multistate_requesttty); 2090 return fmt_multistate_int(val, multistate_requesttty);
2072 case oCanonicalizeHostname: 2091 case oCanonicalizeHostname:
2073 return fmt_multistate_int(val, multistate_canonicalizehostname); 2092 return fmt_multistate_int(val, multistate_canonicalizehostname);
2093 case oFingerprintHash:
2094 return ssh_digest_alg_name(val);
2074 case oProtocol: 2095 case oProtocol:
2075 switch (val) { 2096 switch (val) {
2076 case SSH_PROTO_1: 2097 case SSH_PROTO_1:
@@ -2205,6 +2226,7 @@ dump_client_config(Options *o, const char *host)
2205 dump_cfg_fmtint(oControlMaster, o->control_master); 2226 dump_cfg_fmtint(oControlMaster, o->control_master);
2206 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2227 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2207 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2228 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2229 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2208 dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2230 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2209 dump_cfg_fmtint(oForwardX11, o->forward_x11); 2231 dump_cfg_fmtint(oForwardX11, o->forward_x11);
2210 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2232 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 @@
1/* $OpenBSD: readconf.h,v 1.104 2014/12/04 02:24:32 djm Exp $ */ 1/* $OpenBSD: readconf.h,v 1.105 2014/12/21 22:27:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -146,6 +146,8 @@ typedef struct {
146 146
147 char *revoked_host_keys; 147 char *revoked_host_keys;
148 148
149 int fingerprint_hash;
150
149 char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ 151 char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
150} Options; 152} Options;
151 153
diff --git a/servconf.c b/servconf.c
index 99396fb1d..abc3c72fb 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.255 2014/11/24 03:39:22 jsg Exp $ */ 2/* $OpenBSD: servconf.c,v 1.256 2014/12/21 22:27:56 djm Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -55,6 +55,7 @@
55#include "hostfile.h" 55#include "hostfile.h"
56#include "auth.h" 56#include "auth.h"
57#include "myproposal.h" 57#include "myproposal.h"
58#include "digest.h"
58 59
59static void add_listen_addr(ServerOptions *, char *, int); 60static void add_listen_addr(ServerOptions *, char *, int);
60static void add_one_listen_addr(ServerOptions *, char *, int); 61static void add_one_listen_addr(ServerOptions *, char *, int);
@@ -158,6 +159,7 @@ initialize_server_options(ServerOptions *options)
158 options->ip_qos_interactive = -1; 159 options->ip_qos_interactive = -1;
159 options->ip_qos_bulk = -1; 160 options->ip_qos_bulk = -1;
160 options->version_addendum = NULL; 161 options->version_addendum = NULL;
162 options->fingerprint_hash = -1;
161} 163}
162 164
163void 165void
@@ -313,6 +315,8 @@ fill_default_server_options(ServerOptions *options)
313 options->fwd_opts.streamlocal_bind_mask = 0177; 315 options->fwd_opts.streamlocal_bind_mask = 0177;
314 if (options->fwd_opts.streamlocal_bind_unlink == -1) 316 if (options->fwd_opts.streamlocal_bind_unlink == -1)
315 options->fwd_opts.streamlocal_bind_unlink = 0; 317 options->fwd_opts.streamlocal_bind_unlink = 0;
318 if (options->fingerprint_hash == -1)
319 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
316 /* Turn privilege separation on by default */ 320 /* Turn privilege separation on by default */
317 if (use_privsep == -1) 321 if (use_privsep == -1)
318 use_privsep = PRIVSEP_NOSANDBOX; 322 use_privsep = PRIVSEP_NOSANDBOX;
@@ -362,7 +366,7 @@ typedef enum {
362 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 366 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
363 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 367 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
364 sStreamLocalBindMask, sStreamLocalBindUnlink, 368 sStreamLocalBindMask, sStreamLocalBindUnlink,
365 sAllowStreamLocalForwarding, 369 sAllowStreamLocalForwarding, sFingerprintHash,
366 sDeprecated, sUnsupported 370 sDeprecated, sUnsupported
367} ServerOpCodes; 371} ServerOpCodes;
368 372
@@ -493,6 +497,7 @@ static struct {
493 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, 497 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
494 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, 498 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
495 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, 499 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
500 { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
496 { NULL, sBadOption, 0 } 501 { NULL, sBadOption, 0 }
497}; 502};
498 503
@@ -1670,6 +1675,18 @@ process_server_config_line(ServerOptions *options, char *line,
1670 intptr = &options->fwd_opts.streamlocal_bind_unlink; 1675 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1671 goto parse_flag; 1676 goto parse_flag;
1672 1677
1678 case sFingerprintHash:
1679 arg = strdelim(&cp);
1680 if (!arg || *arg == '\0')
1681 fatal("%.200s line %d: Missing argument.",
1682 filename, linenum);
1683 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1684 fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1685 filename, linenum, arg);
1686 if (*activep)
1687 options->fingerprint_hash = value;
1688 break;
1689
1673 case sDeprecated: 1690 case sDeprecated:
1674 logit("%s line %d: Deprecated option %s", 1691 logit("%s line %d: Deprecated option %s",
1675 filename, linenum, arg); 1692 filename, linenum, arg);
@@ -1912,6 +1929,8 @@ fmt_intarg(ServerOpCodes code, int val)
1912 return fmt_multistate_int(val, multistate_tcpfwd); 1929 return fmt_multistate_int(val, multistate_tcpfwd);
1913 case sAllowStreamLocalForwarding: 1930 case sAllowStreamLocalForwarding:
1914 return fmt_multistate_int(val, multistate_tcpfwd); 1931 return fmt_multistate_int(val, multistate_tcpfwd);
1932 case sFingerprintHash:
1933 return ssh_digest_alg_name(val);
1915 case sProtocol: 1934 case sProtocol:
1916 switch (val) { 1935 switch (val) {
1917 case SSH_PROTO_1: 1936 case SSH_PROTO_1:
@@ -2073,6 +2092,7 @@ dump_config(ServerOptions *o)
2073 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2092 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
2074 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); 2093 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
2075 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2094 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
2095 dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
2076 2096
2077 /* string arguments */ 2097 /* string arguments */
2078 dump_cfg_string(sPidFile, o->pid_file); 2098 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 @@
1/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */ 1/* $OpenBSD: servconf.h,v 1.115 2014/12/21 22:27:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -185,6 +185,8 @@ typedef struct {
185 185
186 u_int num_auth_methods; 186 u_int num_auth_methods;
187 char *auth_methods[MAX_AUTH_METHODS]; 187 char *auth_methods[MAX_AUTH_METHODS];
188
189 int fingerprint_hash;
188} ServerOptions; 190} ServerOptions;
189 191
190/* Information about the incoming connection as used by Match */ 192/* 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 @@
1.\" $OpenBSD: ssh-add.1,v 1.60 2014/08/30 15:33:50 sobrado Exp $ 1.\" $OpenBSD: ssh-add.1,v 1.61 2014/12/21 22:27:56 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.\" 37.\"
38.Dd $Mdocdate: August 30 2014 $ 38.Dd $Mdocdate: December 21 2014 $
39.Dt SSH-ADD 1 39.Dt SSH-ADD 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -44,6 +44,7 @@
44.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Nm ssh-add 45.Nm ssh-add
46.Op Fl cDdkLlXx 46.Op Fl cDdkLlXx
47.Op Fl E Ar fingerprint_hash
47.Op Fl t Ar life 48.Op Fl t Ar life
48.Op Ar 49.Op Ar
49.Nm ssh-add 50.Nm ssh-add
@@ -108,6 +109,14 @@ If no public key is found at a given path,
108will append 109will append
109.Pa .pub 110.Pa .pub
110and retry. 111and retry.
112.It Fl E Ar fingerprint_hash
113Specifies the hash algorithm used when displaying key fingerprints.
114Valid options are:
115.Dq md5
116and
117.Dq sha256 .
118The default is
119.Dq sha256 .
111.It Fl e Ar pkcs11 120.It Fl e Ar pkcs11
112Remove keys provided by the PKCS#11 shared library 121Remove keys provided by the PKCS#11 shared library
113.Ar pkcs11 . 122.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 @@
1/* $OpenBSD: ssh-add.c,v 1.114 2014/11/26 18:34:51 millert Exp $ */ 1/* $OpenBSD: ssh-add.c,v 1.115 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -63,6 +63,7 @@
63#include "pathnames.h" 63#include "pathnames.h"
64#include "misc.h" 64#include "misc.h"
65#include "ssherr.h" 65#include "ssherr.h"
66#include "digest.h"
66 67
67/* argv0 */ 68/* argv0 */
68extern char *__progname; 69extern char *__progname;
@@ -79,6 +80,8 @@ static char *default_files[] = {
79 NULL 80 NULL
80}; 81};
81 82
83static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
84
82/* Default lifetime (0 == forever) */ 85/* Default lifetime (0 == forever) */
83static int lifetime = 0; 86static int lifetime = 0;
84 87
@@ -340,8 +343,8 @@ list_identities(AuthenticationConnection *ac, int do_fp)
340 key = ssh_get_next_identity(ac, &comment, version)) { 343 key = ssh_get_next_identity(ac, &comment, version)) {
341 had_identities = 1; 344 had_identities = 1;
342 if (do_fp) { 345 if (do_fp) {
343 fp = key_fingerprint(key, SSH_FP_MD5, 346 fp = key_fingerprint(key, fingerprint_hash,
344 SSH_FP_HEX); 347 SSH_FP_DEFAULT);
345 printf("%d %s %s (%s)\n", 348 printf("%d %s %s (%s)\n",
346 key_size(key), fp, comment, key_type(key)); 349 key_size(key), fp, comment, key_type(key));
347 free(fp); 350 free(fp);
@@ -408,6 +411,7 @@ usage(void)
408 fprintf(stderr, "usage: %s [options] [file ...]\n", __progname); 411 fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
409 fprintf(stderr, "Options:\n"); 412 fprintf(stderr, "Options:\n");
410 fprintf(stderr, " -l List fingerprints of all identities.\n"); 413 fprintf(stderr, " -l List fingerprints of all identities.\n");
414 fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n");
411 fprintf(stderr, " -L List public key parameters of all identities.\n"); 415 fprintf(stderr, " -L List public key parameters of all identities.\n");
412 fprintf(stderr, " -k Load only keys and not certificates.\n"); 416 fprintf(stderr, " -k Load only keys and not certificates.\n");
413 fprintf(stderr, " -c Require confirmation to sign using identities\n"); 417 fprintf(stderr, " -c Require confirmation to sign using identities\n");
@@ -428,6 +432,7 @@ main(int argc, char **argv)
428 AuthenticationConnection *ac = NULL; 432 AuthenticationConnection *ac = NULL;
429 char *pkcs11provider = NULL; 433 char *pkcs11provider = NULL;
430 int i, ch, deleting = 0, ret = 0, key_only = 0; 434 int i, ch, deleting = 0, ret = 0, key_only = 0;
435 int xflag = 0, lflag = 0, Dflag = 0;
431 436
432 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 437 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
433 sanitise_stdfd(); 438 sanitise_stdfd();
@@ -446,21 +451,28 @@ main(int argc, char **argv)
446 "Could not open a connection to your authentication agent.\n"); 451 "Could not open a connection to your authentication agent.\n");
447 exit(2); 452 exit(2);
448 } 453 }
449 while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) { 454 while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
450 switch (ch) { 455 switch (ch) {
456 case 'E':
457 fingerprint_hash = ssh_digest_alg_by_name(optarg);
458 if (fingerprint_hash == -1)
459 fatal("Invalid hash algorithm \"%s\"", optarg);
460 break;
451 case 'k': 461 case 'k':
452 key_only = 1; 462 key_only = 1;
453 break; 463 break;
454 case 'l': 464 case 'l':
455 case 'L': 465 case 'L':
456 if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) 466 if (lflag != 0)
457 ret = 1; 467 fatal("-%c flag already specified", lflag);
458 goto done; 468 lflag = ch;
469 break;
459 case 'x': 470 case 'x':
460 case 'X': 471 case 'X':
461 if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1) 472 if (xflag != 0)
462 ret = 1; 473 fatal("-%c flag already specified", xflag);
463 goto done; 474 xflag = ch;
475 break;
464 case 'c': 476 case 'c':
465 confirm = 1; 477 confirm = 1;
466 break; 478 break;
@@ -468,9 +480,8 @@ main(int argc, char **argv)
468 deleting = 1; 480 deleting = 1;
469 break; 481 break;
470 case 'D': 482 case 'D':
471 if (delete_all(ac) == -1) 483 Dflag = 1;
472 ret = 1; 484 break;
473 goto done;
474 case 's': 485 case 's':
475 pkcs11provider = optarg; 486 pkcs11provider = optarg;
476 break; 487 break;
@@ -491,6 +502,23 @@ main(int argc, char **argv)
491 goto done; 502 goto done;
492 } 503 }
493 } 504 }
505
506 if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
507 fatal("Invalid combination of actions");
508 else if (xflag) {
509 if (lock_agent(ac, xflag == 'x' ? 1 : 0) == -1)
510 ret = 1;
511 goto done;
512 } else if (lflag) {
513 if (list_identities(ac, lflag == 'l' ? 1 : 0) == -1)
514 ret = 1;
515 goto done;
516 } else if (Dflag) {
517 if (delete_all(ac) == -1)
518 ret = 1;
519 goto done;
520 }
521
494 argc -= optind; 522 argc -= optind;
495 argv += optind; 523 argv += optind;
496 if (pkcs11provider != NULL) { 524 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 @@
1.\" $OpenBSD: ssh-agent.1,v 1.56 2014/08/30 15:33:50 sobrado Exp $ 1.\" $OpenBSD: ssh-agent.1,v 1.57 2014/12/21 22:27:56 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.Dd $Mdocdate: August 30 2014 $ 37.Dd $Mdocdate: December 21 2014 $
38.Dt SSH-AGENT 1 38.Dt SSH-AGENT 1
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -45,6 +45,7 @@
45.Op Fl c | s 45.Op Fl c | s
46.Op Fl d 46.Op Fl d
47.Op Fl a Ar bind_address 47.Op Fl a Ar bind_address
48.Op Fl E Ar fingerprint_hash
48.Op Fl t Ar life 49.Op Fl t Ar life
49.Op Ar command Op Ar arg ... 50.Op Ar command Op Ar arg ...
50.Nm ssh-agent 51.Nm ssh-agent
@@ -96,6 +97,14 @@ Debug mode.
96When this option is specified 97When this option is specified
97.Nm 98.Nm
98will not fork. 99will not fork.
100.It Fl E Ar fingerprint_hash
101Specifies the hash algorithm used when displaying key fingerprints.
102Valid options are:
103.Dq md5
104and
105.Dq sha256 .
106The default is
107.Dq sha256 .
99.It Fl k 108.It Fl k
100Kill the current agent (given by the 109Kill the current agent (given by the
101.Ev SSH_AGENT_PID 110.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 @@
1/* $OpenBSD: ssh-agent.c,v 1.191 2014/11/18 20:54:28 krw Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.192 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -142,6 +142,8 @@ extern char *__progname;
142/* Default lifetime in seconds (0 == forever) */ 142/* Default lifetime in seconds (0 == forever) */
143static long lifetime = 0; 143static long lifetime = 0;
144 144
145static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
146
145static void 147static void
146close_socket(SocketEntry *e) 148close_socket(SocketEntry *e)
147{ 149{
@@ -203,7 +205,7 @@ confirm_key(Identity *id)
203 char *p; 205 char *p;
204 int ret = -1; 206 int ret = -1;
205 207
206 p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); 208 p = key_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
207 if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", 209 if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
208 id->comment, p)) 210 id->comment, p))
209 ret = 0; 211 ret = 0;
@@ -1026,7 +1028,7 @@ usage(void)
1026{ 1028{
1027 fprintf(stderr, 1029 fprintf(stderr,
1028 "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" 1030 "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n"
1029 " [command [arg ...]]\n" 1031 " [-E fingerprint_hash] [command [arg ...]]\n"
1030 " ssh-agent [-c | -s] -k\n"); 1032 " ssh-agent [-c | -s] -k\n");
1031 exit(1); 1033 exit(1);
1032} 1034}
@@ -1069,8 +1071,13 @@ main(int ac, char **av)
1069 __progname = ssh_get_progname(av[0]); 1071 __progname = ssh_get_progname(av[0]);
1070 seed_rng(); 1072 seed_rng();
1071 1073
1072 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { 1074 while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) {
1073 switch (ch) { 1075 switch (ch) {
1076 case 'E':
1077 fingerprint_hash = ssh_digest_alg_by_name(optarg);
1078 if (fingerprint_hash == -1)
1079 fatal("Invalid hash algorithm \"%s\"", optarg);
1080 break;
1074 case 'c': 1081 case 'c':
1075 if (s_flag) 1082 if (s_flag)
1076 usage(); 1083 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 @@
1.\" $OpenBSD: ssh-keygen.1,v 1.123 2014/08/30 15:33:50 sobrado Exp $ 1.\" $OpenBSD: ssh-keygen.1,v 1.124 2014/12/21 22:27:56 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.\" 37.\"
38.Dd $Mdocdate: August 30 2014 $ 38.Dd $Mdocdate: December 21 2014 $
39.Dt SSH-KEYGEN 1 39.Dt SSH-KEYGEN 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -73,6 +73,7 @@
73.Op Fl f Ar keyfile 73.Op Fl f Ar keyfile
74.Nm ssh-keygen 74.Nm ssh-keygen
75.Fl l 75.Fl l
76.Op Fl E Ar fingerprint_hash
76.Op Fl f Ar input_keyfile 77.Op Fl f Ar input_keyfile
77.Nm ssh-keygen 78.Nm ssh-keygen
78.Fl B 79.Fl B
@@ -269,6 +270,14 @@ When used in combination with
269this option indicates that a CA key resides in a PKCS#11 token (see the 270this option indicates that a CA key resides in a PKCS#11 token (see the
270.Sx CERTIFICATES 271.Sx CERTIFICATES
271section for details). 272section for details).
273.It Fl E Ar fingerprint_hash
274Specifies the hash algorithm used when displaying key fingerprints.
275Valid options are:
276.Dq md5
277and
278.Dq sha256 .
279The default is
280.Dq sha256 .
272.It Fl e 281.It Fl e
273This option will read a private or public OpenSSH key file and 282This option will read a private or public OpenSSH key file and
274print to stdout the key in one of the formats specified by the 283print 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 @@
1/* $OpenBSD: ssh-keygen.c,v 1.250 2014/08/21 01:08:52 doug Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.251 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -53,6 +53,7 @@
53#include "ssh-pkcs11.h" 53#include "ssh-pkcs11.h"
54#include "atomicio.h" 54#include "atomicio.h"
55#include "krl.h" 55#include "krl.h"
56#include "digest.h"
56 57
57/* Number of bits in the RSA/DSA key. This value can be set on the command line. */ 58/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
58#define DEFAULT_BITS 2048 59#define DEFAULT_BITS 2048
@@ -90,6 +91,9 @@ int show_cert = 0;
90int print_fingerprint = 0; 91int print_fingerprint = 0;
91int print_bubblebabble = 0; 92int print_bubblebabble = 0;
92 93
94/* Hash algorithm to use for fingerprints. */
95int fingerprint_hash = SSH_FP_HASH_DEFAULT;
96
93/* The identity file name, given on the command line or entered by the user. */ 97/* The identity file name, given on the command line or entered by the user. */
94char identity_file[1024]; 98char identity_file[1024];
95int have_identity = 0; 99int have_identity = 0;
@@ -749,11 +753,11 @@ do_download(struct passwd *pw)
749 Key **keys = NULL; 753 Key **keys = NULL;
750 int i, nkeys; 754 int i, nkeys;
751 enum fp_rep rep; 755 enum fp_rep rep;
752 enum fp_type fptype; 756 int fptype;
753 char *fp, *ra; 757 char *fp, *ra;
754 758
755 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 759 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
756 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 760 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
757 761
758 pkcs11_init(0); 762 pkcs11_init(0);
759 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); 763 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
@@ -762,7 +766,7 @@ do_download(struct passwd *pw)
762 for (i = 0; i < nkeys; i++) { 766 for (i = 0; i < nkeys; i++) {
763 if (print_fingerprint) { 767 if (print_fingerprint) {
764 fp = key_fingerprint(keys[i], fptype, rep); 768 fp = key_fingerprint(keys[i], fptype, rep);
765 ra = key_fingerprint(keys[i], SSH_FP_MD5, 769 ra = key_fingerprint(keys[i], fingerprint_hash,
766 SSH_FP_RANDOMART); 770 SSH_FP_RANDOMART);
767 printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), 771 printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
768 fp, key_type(keys[i])); 772 fp, key_type(keys[i]));
@@ -792,12 +796,11 @@ do_fingerprint(struct passwd *pw)
792 char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; 796 char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
793 int i, skip = 0, num = 0, invalid = 1; 797 int i, skip = 0, num = 0, invalid = 1;
794 enum fp_rep rep; 798 enum fp_rep rep;
795 enum fp_type fptype; 799 int fptype;
796 struct stat st; 800 struct stat st;
797 801
798 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 802 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
799 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 803 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
800
801 if (!have_identity) 804 if (!have_identity)
802 ask_filename(pw, "Enter file in which the key is"); 805 ask_filename(pw, "Enter file in which the key is");
803 if (stat(identity_file, &st) < 0) { 806 if (stat(identity_file, &st) < 0) {
@@ -807,7 +810,8 @@ do_fingerprint(struct passwd *pw)
807 public = key_load_public(identity_file, &comment); 810 public = key_load_public(identity_file, &comment);
808 if (public != NULL) { 811 if (public != NULL) {
809 fp = key_fingerprint(public, fptype, rep); 812 fp = key_fingerprint(public, fptype, rep);
810 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); 813 ra = key_fingerprint(public, fingerprint_hash,
814 SSH_FP_RANDOMART);
811 printf("%u %s %s (%s)\n", key_size(public), fp, comment, 815 printf("%u %s %s (%s)\n", key_size(public), fp, comment,
812 key_type(public)); 816 key_type(public));
813 if (log_level >= SYSLOG_LEVEL_VERBOSE) 817 if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -873,7 +877,8 @@ do_fingerprint(struct passwd *pw)
873 } 877 }
874 comment = *cp ? cp : comment; 878 comment = *cp ? cp : comment;
875 fp = key_fingerprint(public, fptype, rep); 879 fp = key_fingerprint(public, fptype, rep);
876 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); 880 ra = key_fingerprint(public, fingerprint_hash,
881 SSH_FP_RANDOMART);
877 printf("%u %s %s (%s)\n", key_size(public), fp, 882 printf("%u %s %s (%s)\n", key_size(public), fp,
878 comment ? comment : "no comment", key_type(public)); 883 comment ? comment : "no comment", key_type(public));
879 if (log_level >= SYSLOG_LEVEL_VERBOSE) 884 if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -993,13 +998,15 @@ printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash)
993{ 998{
994 if (print_fingerprint) { 999 if (print_fingerprint) {
995 enum fp_rep rep; 1000 enum fp_rep rep;
996 enum fp_type fptype; 1001 int fptype;
997 char *fp, *ra; 1002 char *fp, *ra;
998 1003
999 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 1004 fptype = print_bubblebabble ?
1000 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 1005 SSH_DIGEST_SHA1 : fingerprint_hash;
1006 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1001 fp = key_fingerprint(public, fptype, rep); 1007 fp = key_fingerprint(public, fptype, rep);
1002 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); 1008 ra = key_fingerprint(public, fingerprint_hash,
1009 SSH_FP_RANDOMART);
1003 printf("%u %s %s (%s)\n", key_size(public), fp, name, 1010 printf("%u %s %s (%s)\n", key_size(public), fp, name,
1004 key_type(public)); 1011 key_type(public));
1005 if (log_level >= SYSLOG_LEVEL_VERBOSE) 1012 if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -1908,9 +1915,9 @@ do_show_cert(struct passwd *pw)
1908 fatal("%s is not a certificate", identity_file); 1915 fatal("%s is not a certificate", identity_file);
1909 v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; 1916 v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
1910 1917
1911 key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 1918 key_fp = key_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
1912 ca_fp = key_fingerprint(key->cert->signature_key, 1919 ca_fp = key_fingerprint(key->cert->signature_key,
1913 SSH_FP_MD5, SSH_FP_HEX); 1920 fingerprint_hash, SSH_FP_DEFAULT);
1914 1921
1915 printf("%s:\n", identity_file); 1922 printf("%s:\n", identity_file);
1916 printf(" Type: %s %s certificate\n", key_ssh_name(key), 1923 printf(" Type: %s %s certificate\n", key_ssh_name(key),
@@ -2189,7 +2196,7 @@ usage(void)
2189 " ssh-keygen -e [-m key_format] [-f input_keyfile]\n" 2196 " ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
2190 " ssh-keygen -y [-f input_keyfile]\n" 2197 " ssh-keygen -y [-f input_keyfile]\n"
2191 " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" 2198 " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
2192 " ssh-keygen -l [-f input_keyfile]\n" 2199 " ssh-keygen -l [-E fingerprint_hash] [-f input_keyfile]\n"
2193 " ssh-keygen -B [-f input_keyfile]\n"); 2200 " ssh-keygen -B [-f input_keyfile]\n");
2194#ifdef ENABLE_PKCS11 2201#ifdef ENABLE_PKCS11
2195 fprintf(stderr, 2202 fprintf(stderr,
@@ -2258,9 +2265,10 @@ main(int argc, char **argv)
2258 exit(1); 2265 exit(1);
2259 } 2266 }
2260 2267
2261 /* Remaining characters: EUYdw */ 2268 /* Remaining characters: UYdw */
2262 while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" 2269 while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
2263 "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) { 2270 "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
2271 "a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
2264 switch (opt) { 2272 switch (opt) {
2265 case 'A': 2273 case 'A':
2266 gen_all_hostkeys = 1; 2274 gen_all_hostkeys = 1;
@@ -2271,6 +2279,11 @@ main(int argc, char **argv)
2271 fatal("Bits has bad value %s (%s)", 2279 fatal("Bits has bad value %s (%s)",
2272 optarg, errstr); 2280 optarg, errstr);
2273 break; 2281 break;
2282 case 'E':
2283 fingerprint_hash = ssh_digest_alg_by_name(optarg);
2284 if (fingerprint_hash == -1)
2285 fatal("Invalid hash algorithm \"%s\"", optarg);
2286 break;
2274 case 'F': 2287 case 'F':
2275 find_host = 1; 2288 find_host = 1;
2276 rr_hostname = optarg; 2289 rr_hostname = optarg;
@@ -2702,8 +2715,9 @@ passphrase_again:
2702 fclose(f); 2715 fclose(f);
2703 2716
2704 if (!quiet) { 2717 if (!quiet) {
2705 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); 2718 char *fp = key_fingerprint(public, fingerprint_hash,
2706 char *ra = key_fingerprint(public, SSH_FP_MD5, 2719 SSH_FP_DEFAULT);
2720 char *ra = key_fingerprint(public, fingerprint_hash,
2707 SSH_FP_RANDOMART); 2721 SSH_FP_RANDOMART);
2708 printf("Your public key has been saved in %s.\n", 2722 printf("Your public key has been saved in %s.\n",
2709 identity_file); 2723 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 @@
1/* $OpenBSD: ssh-keysign.c,v 1.43 2014/10/08 22:20:25 djm Exp $ */ 1/* $OpenBSD: ssh-keysign.c,v 1.44 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 2002 Markus Friedl. All rights reserved.
4 * 4 *
@@ -246,7 +246,8 @@ main(int argc, char **argv)
246 } 246 }
247 } 247 }
248 if (!found) { 248 if (!found) {
249 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 249 fp = key_fingerprint(key, options.fingerprint_hash,
250 SSH_FP_DEFAULT);
250 fatal("no matching hostkey found for key %s %s", 251 fatal("no matching hostkey found for key %s %s",
251 key_type(key), fp); 252 key_type(key), fp);
252 } 253 }
diff --git a/ssh.1 b/ssh.1
index 51201861b..d489047ce 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh.1,v 1.351 2014/10/09 06:21:31 jmc Exp $ 36.\" $OpenBSD: ssh.1,v 1.352 2014/12/21 22:27:56 djm Exp $
37.Dd $Mdocdate: October 9 2014 $ 37.Dd $Mdocdate: December 21 2014 $
38.Dt SSH 1 38.Dt SSH 1
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -1091,7 +1091,7 @@ Fingerprints can be determined using
1091If the fingerprint is already known, it can be matched 1091If the fingerprint is already known, it can be matched
1092and the key can be accepted or rejected. 1092and the key can be accepted or rejected.
1093Because of the difficulty of comparing host keys 1093Because of the difficulty of comparing host keys
1094just by looking at hex strings, 1094just by looking at fingerprint strings,
1095there is also support to compare host keys visually, 1095there is also support to compare host keys visually,
1096using 1096using
1097.Em random art . 1097.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 @@
1/* $OpenBSD: sshconnect.c,v 1.253 2014/12/11 08:20:09 djm Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.254 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -918,9 +918,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
918 "key for IP address '%.128s' to the list " 918 "key for IP address '%.128s' to the list "
919 "of known hosts.", type, ip); 919 "of known hosts.", type, ip);
920 } else if (options.visual_host_key) { 920 } else if (options.visual_host_key) {
921 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 921 fp = key_fingerprint(host_key,
922 ra = key_fingerprint(host_key, SSH_FP_MD5, 922 options.fingerprint_hash, SSH_FP_DEFAULT);
923 SSH_FP_RANDOMART); 923 ra = key_fingerprint(host_key,
924 options.fingerprint_hash, SSH_FP_RANDOMART);
924 logit("Host key fingerprint is %s\n%s\n", fp, ra); 925 logit("Host key fingerprint is %s\n%s\n", fp, ra);
925 free(ra); 926 free(ra);
926 free(fp); 927 free(fp);
@@ -959,9 +960,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
959 else 960 else
960 snprintf(msg1, sizeof(msg1), "."); 961 snprintf(msg1, sizeof(msg1), ".");
961 /* The default */ 962 /* The default */
962 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 963 fp = key_fingerprint(host_key,
963 ra = key_fingerprint(host_key, SSH_FP_MD5, 964 options.fingerprint_hash, SSH_FP_DEFAULT);
964 SSH_FP_RANDOMART); 965 ra = key_fingerprint(host_key,
966 options.fingerprint_hash, SSH_FP_RANDOMART);
965 msg2[0] = '\0'; 967 msg2[0] = '\0';
966 if (options.verify_host_key_dns) { 968 if (options.verify_host_key_dns) {
967 if (matching_host_key_dns) 969 if (matching_host_key_dns)
@@ -1226,7 +1228,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1226 struct sshkey *plain = NULL; 1228 struct sshkey *plain = NULL;
1227 1229
1228 if ((fp = sshkey_fingerprint(host_key, 1230 if ((fp = sshkey_fingerprint(host_key,
1229 SSH_FP_MD5, SSH_FP_HEX)) == NULL) { 1231 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
1230 error("%s: fingerprint host key: %s", __func__, ssh_err(r)); 1232 error("%s: fingerprint host key: %s", __func__, ssh_err(r));
1231 r = -1; 1233 r = -1;
1232 goto out; 1234 goto out;
@@ -1387,8 +1389,10 @@ show_other_keys(struct hostkeys *hostkeys, Key *key)
1387 continue; 1389 continue;
1388 if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) 1390 if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
1389 continue; 1391 continue;
1390 fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); 1392 fp = key_fingerprint(found->key,
1391 ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); 1393 options.fingerprint_hash, SSH_FP_DEFAULT);
1394 ra = key_fingerprint(found->key,
1395 options.fingerprint_hash, SSH_FP_RANDOMART);
1392 logit("WARNING: %s key found for host %s\n" 1396 logit("WARNING: %s key found for host %s\n"
1393 "in %s:%lu\n" 1397 "in %s:%lu\n"
1394 "%s key fingerprint %s.", 1398 "%s key fingerprint %s.",
@@ -1409,7 +1413,8 @@ warn_changed_key(Key *host_key)
1409{ 1413{
1410 char *fp; 1414 char *fp;
1411 1415
1412 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 1416 fp = key_fingerprint(host_key, options.fingerprint_hash,
1417 SSH_FP_DEFAULT);
1413 1418
1414 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1419 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1415 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); 1420 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 @@
1/* $OpenBSD: sshconnect2.c,v 1.211 2014/12/11 05:13:28 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.212 2014/12/21 22:27:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -582,7 +582,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
582 key->type, pktype); 582 key->type, pktype);
583 goto done; 583 goto done;
584 } 584 }
585 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 585 fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
586 debug2("input_userauth_pk_ok: fp %s", fp); 586 debug2("input_userauth_pk_ok: fp %s", fp);
587 free(fp); 587 free(fp);
588 588
@@ -991,7 +991,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
991 int have_sig = 1; 991 int have_sig = 1;
992 char *fp; 992 char *fp;
993 993
994 fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); 994 fp = key_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT);
995 debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); 995 debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
996 free(fp); 996 free(fp);
997 997
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 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.182 2014/12/12 00:02:17 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.183 2014/12/21 22:27:55 djm Exp $
37.Dd $Mdocdate: December 12 2014 $ 37.Dd $Mdocdate: December 21 2014 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -485,6 +485,15 @@ and finally
485See PATTERNS in 485See PATTERNS in
486.Xr ssh_config 5 486.Xr ssh_config 5
487for more information on patterns. 487for more information on patterns.
488.It Cm FingerprintHash
489Specifies the hash algorithm used when logging key fingerprints.
490Valid options are:
491.Dq md5
492and
493.Dq sha256 .
494The default is
495.Dq sha256 .
496.Pp
488.It Cm ForceCommand 497.It Cm ForceCommand
489Forces the execution of the command specified by 498Forces the execution of the command specified by
490.Cm ForceCommand , 499.Cm ForceCommand ,
diff --git a/sshkey.c b/sshkey.c
index cf126626e..a32bd36cc 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.6 2014/12/10 01:24:09 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.7 2014/12/21 22:27:55 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -29,6 +29,7 @@
29 29
30#include <sys/param.h> 30#include <sys/param.h>
31#include <sys/types.h> 31#include <sys/types.h>
32#include <netinet/in.h>
32 33
33#include <openssl/evp.h> 34#include <openssl/evp.h>
34#include <openssl/err.h> 35#include <openssl/err.h>
@@ -852,29 +853,18 @@ sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
852} 853}
853 854
854int 855int
855sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, 856sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
856 u_char **retp, size_t *lenp) 857 u_char **retp, size_t *lenp)
857{ 858{
858 u_char *blob = NULL, *ret = NULL; 859 u_char *blob = NULL, *ret = NULL;
859 size_t blob_len = 0; 860 size_t blob_len = 0;
860 int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR; 861 int r = SSH_ERR_INTERNAL_ERROR;
861 862
862 if (retp != NULL) 863 if (retp != NULL)
863 *retp = NULL; 864 *retp = NULL;
864 if (lenp != NULL) 865 if (lenp != NULL)
865 *lenp = 0; 866 *lenp = 0;
866 867 if (ssh_digest_bytes(dgst_alg) == 0) {
867 switch (dgst_type) {
868 case SSH_FP_MD5:
869 hash_alg = SSH_DIGEST_MD5;
870 break;
871 case SSH_FP_SHA1:
872 hash_alg = SSH_DIGEST_SHA1;
873 break;
874 case SSH_FP_SHA256:
875 hash_alg = SSH_DIGEST_SHA256;
876 break;
877 default:
878 r = SSH_ERR_INVALID_ARGUMENT; 868 r = SSH_ERR_INVALID_ARGUMENT;
879 goto out; 869 goto out;
880 } 870 }
@@ -899,7 +889,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
899 r = SSH_ERR_ALLOC_FAIL; 889 r = SSH_ERR_ALLOC_FAIL;
900 goto out; 890 goto out;
901 } 891 }
902 if ((r = ssh_digest_memory(hash_alg, blob, blob_len, 892 if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
903 ret, SSH_DIGEST_MAX_LENGTH)) != 0) 893 ret, SSH_DIGEST_MAX_LENGTH)) != 0)
904 goto out; 894 goto out;
905 /* success */ 895 /* success */
@@ -908,7 +898,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
908 ret = NULL; 898 ret = NULL;
909 } 899 }
910 if (lenp != NULL) 900 if (lenp != NULL)
911 *lenp = ssh_digest_bytes(hash_alg); 901 *lenp = ssh_digest_bytes(dgst_alg);
912 r = 0; 902 r = 0;
913 out: 903 out:
914 free(ret); 904 free(ret);
@@ -920,21 +910,45 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
920} 910}
921 911
922static char * 912static char *
923fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len) 913fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
924{ 914{
925 char *retval; 915 char *ret;
926 size_t i; 916 size_t plen = strlen(alg) + 1;
917 size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
918 int r;
927 919
928 if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL) 920 if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
921 return NULL;
922 strlcpy(ret, alg, rlen);
923 strlcat(ret, ":", rlen);
924 if (dgst_raw_len == 0)
925 return ret;
926 if ((r = b64_ntop(dgst_raw, dgst_raw_len,
927 ret + plen, rlen - plen)) == -1) {
928 explicit_bzero(ret, rlen);
929 free(ret);
929 return NULL; 930 return NULL;
930 for (i = 0; i < dgst_raw_len; i++) {
931 char hex[4];
932 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
933 strlcat(retval, hex, dgst_raw_len * 3 + 1);
934 } 931 }
932 /* Trim padding characters from end */
933 ret[strcspn(ret, "=")] = '\0';
934 return ret;
935}
935 936
936 /* Remove the trailing ':' character */ 937static char *
937 retval[(dgst_raw_len * 3) - 1] = '\0'; 938fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
939{
940 char *retval, hex[5];
941 size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
942
943 if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
944 return NULL;
945 strlcpy(retval, alg, rlen);
946 strlcat(retval, ":", rlen);
947 for (i = 0; i < dgst_raw_len; i++) {
948 snprintf(hex, sizeof(hex), "%s%02x",
949 i > 0 ? ":" : "", dgst_raw[i]);
950 strlcat(retval, hex, rlen);
951 }
938 return retval; 952 return retval;
939} 953}
940 954
@@ -1020,7 +1034,7 @@ fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
1020#define FLDSIZE_Y (FLDBASE + 1) 1034#define FLDSIZE_Y (FLDBASE + 1)
1021#define FLDSIZE_X (FLDBASE * 2 + 1) 1035#define FLDSIZE_X (FLDBASE * 2 + 1)
1022static char * 1036static char *
1023fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, 1037fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1024 const struct sshkey *k) 1038 const struct sshkey *k)
1025{ 1039{
1026 /* 1040 /*
@@ -1028,9 +1042,9 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1028 * intersects with itself. Matter of taste. 1042 * intersects with itself. Matter of taste.
1029 */ 1043 */
1030 char *augmentation_string = " .o+=*BOX@%&#/^SE"; 1044 char *augmentation_string = " .o+=*BOX@%&#/^SE";
1031 char *retval, *p, title[FLDSIZE_X]; 1045 char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1032 u_char field[FLDSIZE_X][FLDSIZE_Y]; 1046 u_char field[FLDSIZE_X][FLDSIZE_Y];
1033 size_t i, tlen; 1047 size_t i, tlen, hlen;
1034 u_int b; 1048 u_int b;
1035 int x, y, r; 1049 int x, y, r;
1036 size_t len = strlen(augmentation_string) - 1; 1050 size_t len = strlen(augmentation_string) - 1;
@@ -1075,8 +1089,12 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1075 sshkey_type(k), sshkey_size(k)); 1089 sshkey_type(k), sshkey_size(k));
1076 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ 1090 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1077 if (r < 0 || r > (int)sizeof(title)) 1091 if (r < 0 || r > (int)sizeof(title))
1078 snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); 1092 r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1079 tlen = strlen(title); 1093 tlen = (r <= 0) ? 0 : strlen(title);
1094
1095 /* assemble hash ID. */
1096 r = snprintf(hash, sizeof(hash), "[%s]", alg);
1097 hlen = (r <= 0) ? 0 : strlen(hash);
1080 1098
1081 /* output upper border */ 1099 /* output upper border */
1082 p = retval; 1100 p = retval;
@@ -1085,7 +1103,7 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1085 *p++ = '-'; 1103 *p++ = '-';
1086 memcpy(p, title, tlen); 1104 memcpy(p, title, tlen);
1087 p += tlen; 1105 p += tlen;
1088 for (i = p - retval - 1; i < FLDSIZE_X; i++) 1106 for (i += tlen; i < FLDSIZE_X; i++)
1089 *p++ = '-'; 1107 *p++ = '-';
1090 *p++ = '+'; 1108 *p++ = '+';
1091 *p++ = '\n'; 1109 *p++ = '\n';
@@ -1101,7 +1119,11 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1101 1119
1102 /* output lower border */ 1120 /* output lower border */
1103 *p++ = '+'; 1121 *p++ = '+';
1104 for (i = 0; i < FLDSIZE_X; i++) 1122 for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1123 *p++ = '-';
1124 memcpy(p, hash, hlen);
1125 p += hlen;
1126 for (i += hlen; i < FLDSIZE_X; i++)
1105 *p++ = '-'; 1127 *p++ = '-';
1106 *p++ = '+'; 1128 *p++ = '+';
1107 1129
@@ -1109,24 +1131,39 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1109} 1131}
1110 1132
1111char * 1133char *
1112sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type, 1134sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1113 enum sshkey_fp_rep dgst_rep) 1135 enum sshkey_fp_rep dgst_rep)
1114{ 1136{
1115 char *retval = NULL; 1137 char *retval = NULL;
1116 u_char *dgst_raw; 1138 u_char *dgst_raw;
1117 size_t dgst_raw_len; 1139 size_t dgst_raw_len;
1118 1140
1119 if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0) 1141 if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1120 return NULL; 1142 return NULL;
1121 switch (dgst_rep) { 1143 switch (dgst_rep) {
1144 case SSH_FP_DEFAULT:
1145 if (dgst_alg == SSH_DIGEST_MD5) {
1146 retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1147 dgst_raw, dgst_raw_len);
1148 } else {
1149 retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1150 dgst_raw, dgst_raw_len);
1151 }
1152 break;
1122 case SSH_FP_HEX: 1153 case SSH_FP_HEX:
1123 retval = fingerprint_hex(dgst_raw, dgst_raw_len); 1154 retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1155 dgst_raw, dgst_raw_len);
1156 break;
1157 case SSH_FP_BASE64:
1158 retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1159 dgst_raw, dgst_raw_len);
1124 break; 1160 break;
1125 case SSH_FP_BUBBLEBABBLE: 1161 case SSH_FP_BUBBLEBABBLE:
1126 retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); 1162 retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1127 break; 1163 break;
1128 case SSH_FP_RANDOMART: 1164 case SSH_FP_RANDOMART:
1129 retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k); 1165 retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1166 dgst_raw, dgst_raw_len, k);
1130 break; 1167 break;
1131 default: 1168 default:
1132 explicit_bzero(dgst_raw, dgst_raw_len); 1169 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 @@
1/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.2 2014/12/21 22:27:55 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -67,16 +67,14 @@ enum sshkey_types {
67 KEY_UNSPEC 67 KEY_UNSPEC
68}; 68};
69 69
70/* Fingerprint hash algorithms */ 70/* Default fingerprint hash */
71enum sshkey_fp_type { 71#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256
72 SSH_FP_SHA1,
73 SSH_FP_MD5,
74 SSH_FP_SHA256
75};
76 72
77/* Fingerprint representation formats */ 73/* Fingerprint representation formats */
78enum sshkey_fp_rep { 74enum sshkey_fp_rep {
75 SSH_FP_DEFAULT = 0,
79 SSH_FP_HEX, 76 SSH_FP_HEX,
77 SSH_FP_BASE64,
80 SSH_FP_BUBBLEBABBLE, 78 SSH_FP_BUBBLEBABBLE,
81 SSH_FP_RANDOMART 79 SSH_FP_RANDOMART
82}; 80};
@@ -124,9 +122,9 @@ int sshkey_equal_public(const struct sshkey *,
124 const struct sshkey *); 122 const struct sshkey *);
125int sshkey_equal(const struct sshkey *, const struct sshkey *); 123int sshkey_equal(const struct sshkey *, const struct sshkey *);
126char *sshkey_fingerprint(const struct sshkey *, 124char *sshkey_fingerprint(const struct sshkey *,
127 enum sshkey_fp_type, enum sshkey_fp_rep); 125 int, enum sshkey_fp_rep);
128int sshkey_fingerprint_raw(const struct sshkey *k, 126int sshkey_fingerprint_raw(const struct sshkey *k,
129 enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp); 127 int, u_char **retp, size_t *lenp);
130const char *sshkey_type(const struct sshkey *); 128const char *sshkey_type(const struct sshkey *);
131const char *sshkey_cert_type(const struct sshkey *); 129const char *sshkey_cert_type(const struct sshkey *);
132int sshkey_write(const struct sshkey *, FILE *); 130int sshkey_write(const struct sshkey *, FILE *);