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@
This commit is contained in:
djm@openbsd.org 2014-12-21 22:27:55 +00:00 committed by Damien Miller
parent 058f839fe1
commit 56d1c83cdd
28 changed files with 374 additions and 149 deletions

View File

@ -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 <ylo@cs.hut.fi>
* 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,
"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);

5
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.107 2014/12/04 02:24:32 djm Exp $ */
/* $OpenBSD: auth.c,v 1.108 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -679,7 +679,8 @@ auth_key_is_revoked(Key *key)
if (options.revoked_keys_file == NULL)
return 0;
if ((fp = sshkey_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX)) == NULL) {
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
error("%s: fingerprint key: %s", __func__, ssh_err(r));
goto out;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
/* $OpenBSD: auth2-hostbased.c,v 1.19 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -208,13 +208,14 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
options.fingerprint_hash, SSH_FP_DEFAULT);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
key_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.42 2014/12/04 02:24:32 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -213,7 +213,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
options.fingerprint_hash, SSH_FP_DEFAULT);
auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
key_type(key), key->cert->key_id,
(unsigned long long)key->cert->serial,
@ -221,7 +221,8 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
} else {
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
@ -365,8 +366,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
continue;
if (!key_is_cert_authority)
continue;
fp = key_fingerprint(found, SSH_FP_MD5,
SSH_FP_HEX);
fp = key_fingerprint(found, options.fingerprint_hash,
SSH_FP_DEFAULT);
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, key_type(found), fp);
/*
@ -406,7 +407,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
if (key_is_cert_authority)
continue;
found_key = 1;
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(found, options.fingerprint_hash,
SSH_FP_DEFAULT);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(found), fp);
free(fp);
@ -432,7 +434,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
return 0;
ca_fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
options.fingerprint_hash, SSH_FP_DEFAULT);
if (sshkey_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1, 0) != 0) {

View File

@ -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 <djm@mindrot.org>
* 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)
{

View File

@ -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 <djm@mindrot.org>
*
@ -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)
{

View File

@ -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 <djm@mindrot.org>
*
@ -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);

11
dns.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */
/* $OpenBSD: dns.c,v 1.32 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -41,6 +41,7 @@
#include "key.h"
#include "dns.h"
#include "log.h"
#include "digest.h"
static const char *errset_text[] = {
"success", /* 0 ERRSET_SUCCESS */
@ -80,7 +81,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
u_char **digest, u_int *digest_len, Key *key)
{
int success = 0;
enum fp_type fp_type = 0;
int fp_alg = -1;
switch (key->type) {
case KEY_RSA:
@ -110,17 +111,17 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
switch (*digest_type) {
case SSHFP_HASH_SHA1:
fp_type = SSH_FP_SHA1;
fp_alg = SSH_DIGEST_SHA1;
break;
case SSHFP_HASH_SHA256:
fp_type = SSH_FP_SHA256;
fp_alg = SSH_DIGEST_SHA256;
break;
default:
*digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
if (*algorithm && *digest_type) {
*digest = key_fingerprint_raw(key, fp_type, digest_len);
*digest = key_fingerprint_raw(key, fp_alg, digest_len);
if (*digest == NULL)
fatal("dns_read_key: null from key_fingerprint_raw()");
success = 1;

7
key.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.c,v 1.123 2014/12/04 20:47:36 djm Exp $ */
/* $OpenBSD: key.c,v 1.124 2014/12/21 22:27:56 djm Exp $ */
/*
* placed in the public domain
*/
@ -40,8 +40,7 @@ key_new_private(int type)
}
u_char*
key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
u_int *dgst_raw_length)
key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length)
{
u_char *ret = NULL;
size_t dlen;
@ -49,7 +48,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
if (dgst_raw_length != NULL)
*dgst_raw_length = 0;
if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0)
if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if (dlen > INT_MAX)
fatal("%s: giant len %zu", __func__, dlen);

4
key.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.h,v 1.43 2014/12/04 20:47:36 djm Exp $ */
/* $OpenBSD: key.h,v 1.44 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -67,7 +67,7 @@ void key_add_private(Key *);
Key *key_new_private(int);
void key_free(Key *);
Key *key_demote(const Key *);
u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
u_char *key_fingerprint_raw(const Key *, int, u_int *);
int key_write(const Key *, FILE *);
int key_read(Key *, char **);

8
krl.c
View File

@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: krl.c,v 1.20 2014/12/04 01:49:59 djm Exp $ */
/* $OpenBSD: krl.c,v 1.21 2014/12/21 22:27:56 djm Exp $ */
#include "includes.h"
@ -36,6 +36,7 @@
#include "misc.h"
#include "log.h"
#include "ssherr.h"
#include "digest.h"
#include "krl.h"
@ -411,7 +412,8 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key)
int r;
debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key));
if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0)
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
&blob, &len)) != 0)
return r;
return revoke_blob(&krl->revoked_sha1s, blob, len);
}
@ -1151,7 +1153,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
/* Check explicitly revoked hashes first */
memset(&rb, 0, sizeof(rb));
if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1,
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
&rb.blob, &rb.len)) != 0)
return r;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.223 2014/12/04 02:24:32 djm Exp $ */
/* $OpenBSD: readconf.c,v 1.224 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -60,6 +60,7 @@
#include "mac.h"
#include "uidswap.h"
#include "myproposal.h"
#include "digest.h"
/* Format of the configuration file:
@ -155,6 +156,7 @@ typedef enum {
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash,
oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@ -270,6 +272,7 @@ static struct {
{ "streamlocalbindmask", oStreamLocalBindMask },
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
{ "revokedhostkeys", oRevokedHostKeys },
{ "fingerprinthash", oFingerprintHash },
{ "ignoreunknown", oIgnoreUnknown },
{ NULL, oBadOption }
@ -1460,6 +1463,18 @@ parse_int:
charptr = &options->revoked_host_keys;
goto parse_string;
case oFingerprintHash:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
if (*activep)
options->fingerprint_hash = value;
break;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@ -1637,6 +1652,7 @@ initialize_options(Options * options)
options->canonicalize_fallback_local = -1;
options->canonicalize_hostname = -1;
options->revoked_host_keys = NULL;
options->fingerprint_hash = -1;
}
/*
@ -1814,6 +1830,9 @@ fill_default_options(Options * options)
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
#define CLEAR_ON_NONE(v) \
do { \
if (option_clear_or_none(v)) { \
@ -2071,6 +2090,8 @@ fmt_intarg(OpCodes code, int val)
return fmt_multistate_int(val, multistate_requesttty);
case oCanonicalizeHostname:
return fmt_multistate_int(val, multistate_canonicalizehostname);
case oFingerprintHash:
return ssh_digest_alg_name(val);
case oProtocol:
switch (val) {
case SSH_PROTO_1:
@ -2205,6 +2226,7 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oControlMaster, o->control_master);
dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(oForwardAgent, o->forward_agent);
dump_cfg_fmtint(oForwardX11, o->forward_x11);
dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.104 2014/12/04 02:24:32 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.105 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -146,6 +146,8 @@ typedef struct {
char *revoked_host_keys;
int fingerprint_hash;
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.255 2014/11/24 03:39:22 jsg Exp $ */
/* $OpenBSD: servconf.c,v 1.256 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -55,6 +55,7 @@
#include "hostfile.h"
#include "auth.h"
#include "myproposal.h"
#include "digest.h"
static void add_listen_addr(ServerOptions *, char *, int);
static void add_one_listen_addr(ServerOptions *, char *, int);
@ -158,6 +159,7 @@ initialize_server_options(ServerOptions *options)
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
}
void
@ -313,6 +315,8 @@ fill_default_server_options(ServerOptions *options)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Turn privilege separation on by default */
if (use_privsep == -1)
use_privsep = PRIVSEP_NOSANDBOX;
@ -362,7 +366,7 @@ typedef enum {
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding,
sAllowStreamLocalForwarding, sFingerprintHash,
sDeprecated, sUnsupported
} ServerOpCodes;
@ -493,6 +497,7 @@ static struct {
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@ -1670,6 +1675,18 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case sFingerprintHash:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
if (*activep)
options->fingerprint_hash = value;
break;
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@ -1912,6 +1929,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sFingerprintHash:
return ssh_digest_alg_name(val);
case sProtocol:
switch (val) {
case SSH_PROTO_1:
@ -2073,6 +2092,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);

View File

@ -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 <ylo@cs.hut.fi>
@ -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 */

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.60 2014/08/30 15:33:50 sobrado Exp $
.\" $OpenBSD: ssh-add.1,v 1.61 2014/12/21 22:27:56 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: August 30 2014 $
.Dd $Mdocdate: December 21 2014 $
.Dt SSH-ADD 1
.Os
.Sh NAME
@ -44,6 +44,7 @@
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl cDdkLlXx
.Op Fl E Ar fingerprint_hash
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
@ -108,6 +109,14 @@ If no public key is found at a given path,
will append
.Pa .pub
and retry.
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.It Fl e Ar pkcs11
Remove keys provided by the PKCS#11 shared library
.Ar pkcs11 .

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.114 2014/11/26 18:34:51 millert Exp $ */
/* $OpenBSD: ssh-add.c,v 1.115 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -63,6 +63,7 @@
#include "pathnames.h"
#include "misc.h"
#include "ssherr.h"
#include "digest.h"
/* argv0 */
extern char *__progname;
@ -79,6 +80,8 @@ static char *default_files[] = {
NULL
};
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Default lifetime (0 == forever) */
static int lifetime = 0;
@ -340,8 +343,8 @@ list_identities(AuthenticationConnection *ac, int do_fp)
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
fp = key_fingerprint(key, SSH_FP_MD5,
SSH_FP_HEX);
fp = key_fingerprint(key, fingerprint_hash,
SSH_FP_DEFAULT);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment, key_type(key));
free(fp);
@ -408,6 +411,7 @@ usage(void)
fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -l List fingerprints of all identities.\n");
fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n");
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -k Load only keys and not certificates.\n");
fprintf(stderr, " -c Require confirmation to sign using identities\n");
@ -428,6 +432,7 @@ main(int argc, char **argv)
AuthenticationConnection *ac = NULL;
char *pkcs11provider = NULL;
int i, ch, deleting = 0, ret = 0, key_only = 0;
int xflag = 0, lflag = 0, Dflag = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@ -446,21 +451,28 @@ main(int argc, char **argv)
"Could not open a connection to your authentication agent.\n");
exit(2);
}
while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) {
while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'k':
key_only = 1;
break;
case 'l':
case 'L':
if (list_identities(ac, ch == 'l' ? 1 : 0) == -1)
ret = 1;
goto done;
if (lflag != 0)
fatal("-%c flag already specified", lflag);
lflag = ch;
break;
case 'x':
case 'X':
if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
if (xflag != 0)
fatal("-%c flag already specified", xflag);
xflag = ch;
break;
case 'c':
confirm = 1;
break;
@ -468,9 +480,8 @@ main(int argc, char **argv)
deleting = 1;
break;
case 'D':
if (delete_all(ac) == -1)
ret = 1;
goto done;
Dflag = 1;
break;
case 's':
pkcs11provider = optarg;
break;
@ -491,6 +502,23 @@ main(int argc, char **argv)
goto done;
}
}
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
fatal("Invalid combination of actions");
else if (xflag) {
if (lock_agent(ac, xflag == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
} else if (lflag) {
if (list_identities(ac, lflag == 'l' ? 1 : 0) == -1)
ret = 1;
goto done;
} else if (Dflag) {
if (delete_all(ac) == -1)
ret = 1;
goto done;
}
argc -= optind;
argv += optind;
if (pkcs11provider != NULL) {

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-agent.1,v 1.56 2014/08/30 15:33:50 sobrado Exp $
.\" $OpenBSD: ssh-agent.1,v 1.57 2014/12/21 22:27:56 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: August 30 2014 $
.Dd $Mdocdate: December 21 2014 $
.Dt SSH-AGENT 1
.Os
.Sh NAME
@ -45,6 +45,7 @@
.Op Fl c | s
.Op Fl d
.Op Fl a Ar bind_address
.Op Fl E Ar fingerprint_hash
.Op Fl t Ar life
.Op Ar command Op Ar arg ...
.Nm ssh-agent
@ -96,6 +97,14 @@ Debug mode.
When this option is specified
.Nm
will not fork.
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.It Fl k
Kill the current agent (given by the
.Ev SSH_AGENT_PID

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.191 2014/11/18 20:54:28 krw Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.192 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -142,6 +142,8 @@ extern char *__progname;
/* Default lifetime in seconds (0 == forever) */
static long lifetime = 0;
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
static void
close_socket(SocketEntry *e)
{
@ -203,7 +205,7 @@ confirm_key(Identity *id)
char *p;
int ret = -1;
p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
p = key_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
id->comment, p))
ret = 0;
@ -1026,7 +1028,7 @@ usage(void)
{
fprintf(stderr,
"usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n"
" [command [arg ...]]\n"
" [-E fingerprint_hash] [command [arg ...]]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
}
@ -1069,8 +1071,13 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
seed_rng();
while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'c':
if (s_flag)
usage();

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.123 2014/08/30 15:33:50 sobrado Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.124 2014/12/21 22:27:56 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: August 30 2014 $
.Dd $Mdocdate: December 21 2014 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@ -73,6 +73,7 @@
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl l
.Op Fl E Ar fingerprint_hash
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl B
@ -269,6 +270,14 @@ When used in combination with
this option indicates that a CA key resides in a PKCS#11 token (see the
.Sx CERTIFICATES
section for details).
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.It Fl e
This option will read a private or public OpenSSH key file and
print to stdout the key in one of the formats specified by the

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keygen.c,v 1.250 2014/08/21 01:08:52 doug Exp $ */
/* $OpenBSD: ssh-keygen.c,v 1.251 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -53,6 +53,7 @@
#include "ssh-pkcs11.h"
#include "atomicio.h"
#include "krl.h"
#include "digest.h"
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
#define DEFAULT_BITS 2048
@ -90,6 +91,9 @@ int show_cert = 0;
int print_fingerprint = 0;
int print_bubblebabble = 0;
/* Hash algorithm to use for fingerprints. */
int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* The identity file name, given on the command line or entered by the user. */
char identity_file[1024];
int have_identity = 0;
@ -749,11 +753,11 @@ do_download(struct passwd *pw)
Key **keys = NULL;
int i, nkeys;
enum fp_rep rep;
enum fp_type fptype;
int fptype;
char *fp, *ra;
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
pkcs11_init(0);
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
@ -762,7 +766,7 @@ do_download(struct passwd *pw)
for (i = 0; i < nkeys; i++) {
if (print_fingerprint) {
fp = key_fingerprint(keys[i], fptype, rep);
ra = key_fingerprint(keys[i], SSH_FP_MD5,
ra = key_fingerprint(keys[i], fingerprint_hash,
SSH_FP_RANDOMART);
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
fp, key_type(keys[i]));
@ -792,12 +796,11 @@ do_fingerprint(struct passwd *pw)
char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
int i, skip = 0, num = 0, invalid = 1;
enum fp_rep rep;
enum fp_type fptype;
int fptype;
struct stat st;
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
@ -807,7 +810,8 @@ do_fingerprint(struct passwd *pw)
public = key_load_public(identity_file, &comment);
if (public != NULL) {
fp = key_fingerprint(public, fptype, rep);
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
ra = key_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, comment,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@ -873,7 +877,8 @@ do_fingerprint(struct passwd *pw)
}
comment = *cp ? cp : comment;
fp = key_fingerprint(public, fptype, rep);
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
ra = key_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp,
comment ? comment : "no comment", key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@ -993,13 +998,15 @@ printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash)
{
if (print_fingerprint) {
enum fp_rep rep;
enum fp_type fptype;
int fptype;
char *fp, *ra;
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
fptype = print_bubblebabble ?
SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
fp = key_fingerprint(public, fptype, rep);
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
ra = key_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, name,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@ -1908,9 +1915,9 @@ do_show_cert(struct passwd *pw)
fatal("%s is not a certificate", identity_file);
v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
key_fp = key_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
ca_fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
fingerprint_hash, SSH_FP_DEFAULT);
printf("%s:\n", identity_file);
printf(" Type: %s %s certificate\n", key_ssh_name(key),
@ -2189,7 +2196,7 @@ usage(void)
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
" ssh-keygen -y [-f input_keyfile]\n"
" ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
" ssh-keygen -l [-f input_keyfile]\n"
" ssh-keygen -l [-E fingerprint_hash] [-f input_keyfile]\n"
" ssh-keygen -B [-f input_keyfile]\n");
#ifdef ENABLE_PKCS11
fprintf(stderr,
@ -2258,9 +2265,10 @@ main(int argc, char **argv)
exit(1);
}
/* Remaining characters: EUYdw */
/* Remaining characters: UYdw */
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
"C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
"C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
"a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
@ -2271,6 +2279,11 @@ main(int argc, char **argv)
fatal("Bits has bad value %s (%s)",
optarg, errstr);
break;
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'F':
find_host = 1;
rr_hostname = optarg;
@ -2702,8 +2715,9 @@ passphrase_again:
fclose(f);
if (!quiet) {
char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
char *ra = key_fingerprint(public, SSH_FP_MD5,
char *fp = key_fingerprint(public, fingerprint_hash,
SSH_FP_DEFAULT);
char *ra = key_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keysign.c,v 1.43 2014/10/08 22:20:25 djm Exp $ */
/* $OpenBSD: ssh-keysign.c,v 1.44 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@ -246,7 +246,8 @@ main(int argc, char **argv)
}
}
if (!found) {
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
fatal("no matching hostkey found for key %s %s",
key_type(key), fp);
}

6
ssh.1
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh.1,v 1.351 2014/10/09 06:21:31 jmc Exp $
.Dd $Mdocdate: October 9 2014 $
.\" $OpenBSD: ssh.1,v 1.352 2014/12/21 22:27:56 djm Exp $
.Dd $Mdocdate: December 21 2014 $
.Dt SSH 1
.Os
.Sh NAME
@ -1091,7 +1091,7 @@ Fingerprints can be determined using
If the fingerprint is already known, it can be matched
and the key can be accepted or rejected.
Because of the difficulty of comparing host keys
just by looking at hex strings,
just by looking at fingerprint strings,
there is also support to compare host keys visually,
using
.Em random art .

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.253 2014/12/11 08:20:09 djm Exp $ */
/* $OpenBSD: sshconnect.c,v 1.254 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* 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,
"key for IP address '%.128s' to the list "
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
ra = key_fingerprint(host_key, SSH_FP_MD5,
SSH_FP_RANDOMART);
fp = key_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = key_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
logit("Host key fingerprint is %s\n%s\n", fp, ra);
free(ra);
free(fp);
@ -959,9 +960,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
ra = key_fingerprint(host_key, SSH_FP_MD5,
SSH_FP_RANDOMART);
fp = key_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = key_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@ -1226,7 +1228,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
struct sshkey *plain = NULL;
if ((fp = sshkey_fingerprint(host_key,
SSH_FP_MD5, SSH_FP_HEX)) == NULL) {
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
error("%s: fingerprint host key: %s", __func__, ssh_err(r));
r = -1;
goto out;
@ -1387,8 +1389,10 @@ show_other_keys(struct hostkeys *hostkeys, Key *key)
continue;
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
continue;
fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
fp = key_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = key_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
@ -1409,7 +1413,8 @@ warn_changed_key(Key *host_key)
{
char *fp;
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(host_key, options.fingerprint_hash,
SSH_FP_DEFAULT);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.211 2014/12/11 05:13:28 djm Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.212 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -582,7 +582,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
key->type, pktype);
goto done;
}
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
debug2("input_userauth_pk_ok: fp %s", fp);
free(fp);
@ -991,7 +991,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
int have_sig = 1;
char *fp;
fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
fp = key_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT);
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
free(fp);

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd_config.5,v 1.182 2014/12/12 00:02:17 djm Exp $
.Dd $Mdocdate: December 12 2014 $
.\" $OpenBSD: sshd_config.5,v 1.183 2014/12/21 22:27:55 djm Exp $
.Dd $Mdocdate: December 21 2014 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -485,6 +485,15 @@ and finally
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
.It Cm FingerprintHash
Specifies the hash algorithm used when logging key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.Pp
.It Cm ForceCommand
Forces the execution of the command specified by
.Cm ForceCommand ,

113
sshkey.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshkey.c,v 1.6 2014/12/10 01:24:09 djm Exp $ */
/* $OpenBSD: sshkey.c,v 1.7 2014/12/21 22:27:55 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@ -29,6 +29,7 @@
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <openssl/evp.h>
#include <openssl/err.h>
@ -852,29 +853,18 @@ sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
}
int
sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
u_char **retp, size_t *lenp)
{
u_char *blob = NULL, *ret = NULL;
size_t blob_len = 0;
int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR;
int r = SSH_ERR_INTERNAL_ERROR;
if (retp != NULL)
*retp = NULL;
if (lenp != NULL)
*lenp = 0;
switch (dgst_type) {
case SSH_FP_MD5:
hash_alg = SSH_DIGEST_MD5;
break;
case SSH_FP_SHA1:
hash_alg = SSH_DIGEST_SHA1;
break;
case SSH_FP_SHA256:
hash_alg = SSH_DIGEST_SHA256;
break;
default:
if (ssh_digest_bytes(dgst_alg) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
@ -899,7 +889,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = ssh_digest_memory(hash_alg, blob, blob_len,
if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
ret, SSH_DIGEST_MAX_LENGTH)) != 0)
goto out;
/* success */
@ -908,7 +898,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
ret = NULL;
}
if (lenp != NULL)
*lenp = ssh_digest_bytes(hash_alg);
*lenp = ssh_digest_bytes(dgst_alg);
r = 0;
out:
free(ret);
@ -920,21 +910,45 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
}
static char *
fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len)
fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
{
char *retval;
size_t i;
char *ret;
size_t plen = strlen(alg) + 1;
size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
int r;
if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL)
if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
return NULL;
strlcpy(ret, alg, rlen);
strlcat(ret, ":", rlen);
if (dgst_raw_len == 0)
return ret;
if ((r = b64_ntop(dgst_raw, dgst_raw_len,
ret + plen, rlen - plen)) == -1) {
explicit_bzero(ret, rlen);
free(ret);
return NULL;
for (i = 0; i < dgst_raw_len; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
strlcat(retval, hex, dgst_raw_len * 3 + 1);
}
/* Trim padding characters from end */
ret[strcspn(ret, "=")] = '\0';
return ret;
}
/* Remove the trailing ':' character */
retval[(dgst_raw_len * 3) - 1] = '\0';
static char *
fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
{
char *retval, hex[5];
size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
return NULL;
strlcpy(retval, alg, rlen);
strlcat(retval, ":", rlen);
for (i = 0; i < dgst_raw_len; i++) {
snprintf(hex, sizeof(hex), "%s%02x",
i > 0 ? ":" : "", dgst_raw[i]);
strlcat(retval, hex, rlen);
}
return retval;
}
@ -1020,7 +1034,7 @@ fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
#define FLDSIZE_Y (FLDBASE + 1)
#define FLDSIZE_X (FLDBASE * 2 + 1)
static char *
fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
const struct sshkey *k)
{
/*
@ -1028,9 +1042,9 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
* intersects with itself. Matter of taste.
*/
char *augmentation_string = " .o+=*BOX@%&#/^SE";
char *retval, *p, title[FLDSIZE_X];
char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
u_char field[FLDSIZE_X][FLDSIZE_Y];
size_t i, tlen;
size_t i, tlen, hlen;
u_int b;
int x, y, r;
size_t len = strlen(augmentation_string) - 1;
@ -1075,8 +1089,12 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
sshkey_type(k), sshkey_size(k));
/* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
if (r < 0 || r > (int)sizeof(title))
snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
tlen = strlen(title);
r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
tlen = (r <= 0) ? 0 : strlen(title);
/* assemble hash ID. */
r = snprintf(hash, sizeof(hash), "[%s]", alg);
hlen = (r <= 0) ? 0 : strlen(hash);
/* output upper border */
p = retval;
@ -1085,7 +1103,7 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
*p++ = '-';
memcpy(p, title, tlen);
p += tlen;
for (i = p - retval - 1; i < FLDSIZE_X; i++)
for (i += tlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
*p++ = '\n';
@ -1101,7 +1119,11 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
/* output lower border */
*p++ = '+';
for (i = 0; i < FLDSIZE_X; i++)
for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
*p++ = '-';
memcpy(p, hash, hlen);
p += hlen;
for (i += hlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
@ -1109,24 +1131,39 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
}
char *
sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type,
sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
enum sshkey_fp_rep dgst_rep)
{
char *retval = NULL;
u_char *dgst_raw;
size_t dgst_raw_len;
if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0)
if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
return NULL;
switch (dgst_rep) {
case SSH_FP_DEFAULT:
if (dgst_alg == SSH_DIGEST_MD5) {
retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
} else {
retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
}
break;
case SSH_FP_HEX:
retval = fingerprint_hex(dgst_raw, dgst_raw_len);
retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
break;
case SSH_FP_BASE64:
retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
break;
case SSH_FP_BUBBLEBABBLE:
retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
break;
case SSH_FP_RANDOMART:
retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k);
retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len, k);
break;
default:
explicit_bzero(dgst_raw, dgst_raw_len);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */
/* $OpenBSD: sshkey.h,v 1.2 2014/12/21 22:27:55 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -67,16 +67,14 @@ enum sshkey_types {
KEY_UNSPEC
};
/* Fingerprint hash algorithms */
enum sshkey_fp_type {
SSH_FP_SHA1,
SSH_FP_MD5,
SSH_FP_SHA256
};
/* Default fingerprint hash */
#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256
/* Fingerprint representation formats */
enum sshkey_fp_rep {
SSH_FP_DEFAULT = 0,
SSH_FP_HEX,
SSH_FP_BASE64,
SSH_FP_BUBBLEBABBLE,
SSH_FP_RANDOMART
};
@ -124,9 +122,9 @@ int sshkey_equal_public(const struct sshkey *,
const struct sshkey *);
int sshkey_equal(const struct sshkey *, const struct sshkey *);
char *sshkey_fingerprint(const struct sshkey *,
enum sshkey_fp_type, enum sshkey_fp_rep);
int, enum sshkey_fp_rep);
int sshkey_fingerprint_raw(const struct sshkey *k,
enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp);
int, u_char **retp, size_t *lenp);
const char *sshkey_type(const struct sshkey *);
const char *sshkey_cert_type(const struct sshkey *);
int sshkey_write(const struct sshkey *, FILE *);