]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
- djm@cvs.openbsd.org 2012/05/23 03:28:28
authorDamien Miller <djm@mindrot.org>
Wed, 20 Jun 2012 11:51:11 +0000 (21:51 +1000)
committerDamien Miller <djm@mindrot.org>
Wed, 20 Jun 2012 11:51:11 +0000 (21:51 +1000)
     [dns.c dns.h key.c key.h ssh-keygen.c]
     add support for RFC6594 SSHFP DNS records for ECDSA key types.
     patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@

ChangeLog
dns.c
dns.h
key.c
key.h
ssh-keygen.c

index 419640c2a155df29ac7b330f375e2e304aad92a1..f0356d32e8419c8cea8ab15383685977347e08f0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
      [mux.c]
      fix double-free in new session handler
      NB. Id sync only
+   - djm@cvs.openbsd.org 2012/05/23 03:28:28
+     [dns.c dns.h key.c key.h ssh-keygen.c]
+     add support for RFC6594 SSHFP DNS records for ECDSA key types.
+     patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@
 
 20120519
  - (dtucker) [configure.ac] bz#2010: fix non-portable shell construct.  Patch
diff --git a/dns.c b/dns.c
index 131cb3d8b5d56597d35b9ee07bbbfd4790f1c898..9e3084ba5b3bc89a82beee83735bead5b65c4516 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.28 2012/05/23 03:28:28 djm Exp $ */
 
 /*
  * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -78,27 +78,46 @@ 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;
 
        switch (key->type) {
        case KEY_RSA:
                *algorithm = SSHFP_KEY_RSA;
+               if (!*digest_type)
+                       *digest_type = SSHFP_HASH_SHA1;
                break;
        case KEY_DSA:
                *algorithm = SSHFP_KEY_DSA;
+               if (!*digest_type)
+                       *digest_type = SSHFP_HASH_SHA1;
+               break;
+       case KEY_ECDSA:
+               *algorithm = SSHFP_KEY_ECDSA;
+               if (!*digest_type)
+                       *digest_type = SSHFP_HASH_SHA256;
                break;
-       /* XXX KEY_ECDSA */
        default:
                *algorithm = SSHFP_KEY_RESERVED; /* 0 */
+               *digest_type = SSHFP_HASH_RESERVED; /* 0 */
+       }
+
+       switch (*digest_type) {
+       case SSHFP_HASH_SHA1:
+               fp_type = SSH_FP_SHA1;
+               break;
+       case SSHFP_HASH_SHA256:
+               fp_type = SSH_FP_SHA256;
+               break;
+       default:
+               *digest_type = SSHFP_HASH_RESERVED; /* 0 */
        }
 
-       if (*algorithm) {
-               *digest_type = SSHFP_HASH_SHA1;
-               *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
+       if (*algorithm && *digest_type) {
+               *digest = key_fingerprint_raw(key, fp_type, digest_len);
                if (*digest == NULL)
                        fatal("dns_read_key: null from key_fingerprint_raw()");
                success = 1;
        } else {
-               *digest_type = SSHFP_HASH_RESERVED;
                *digest = NULL;
                *digest_len = 0;
                success = 0;
@@ -180,7 +199,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
        struct rrsetinfo *fingerprints = NULL;
 
        u_int8_t hostkey_algorithm;
-       u_int8_t hostkey_digest_type;
+       u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
        u_char *hostkey_digest;
        u_int hostkey_digest_len;
 
@@ -216,7 +235,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
                    fingerprints->rri_nrdatas);
        }
 
-       /* Initialize host key parameters */
+       /* Initialize default host key parameters */
        if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
            &hostkey_digest, &hostkey_digest_len, hostkey)) {
                error("Error calculating host key fingerprint.");
@@ -240,16 +259,27 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
                        continue;
                }
 
+               if (hostkey_digest_type != dnskey_digest_type) {
+                       hostkey_digest_type = dnskey_digest_type;
+                       xfree(hostkey_digest);
+
+                       /* Initialize host key parameters */
+                       if (!dns_read_key(&hostkey_algorithm,
+                           &hostkey_digest_type, &hostkey_digest,
+                           &hostkey_digest_len, hostkey)) {
+                               error("Error calculating key fingerprint.");
+                               freerrset(fingerprints);
+                               return -1;
+                       }
+               }
+
                /* Check if the current key is the same as the given key */
                if (hostkey_algorithm == dnskey_algorithm &&
                    hostkey_digest_type == dnskey_digest_type) {
-
                        if (hostkey_digest_len == dnskey_digest_len &&
-                           memcmp(hostkey_digest, dnskey_digest,
-                           hostkey_digest_len) == 0) {
-
+                           timingsafe_bcmp(hostkey_digest, dnskey_digest,
+                           hostkey_digest_len) == 0)
                                *flags |= DNS_VERIFY_MATCH;
-                       }
                }
                xfree(dnskey_digest);
        }
@@ -275,31 +305,36 @@ int
 export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
 {
        u_int8_t rdata_pubkey_algorithm = 0;
-       u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
+       u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
+       u_int8_t dtype;
        u_char *rdata_digest;
-       u_int rdata_digest_len;
-
-       u_int i;
+       u_int i, rdata_digest_len;
        int success = 0;
 
-       if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
-           &rdata_digest, &rdata_digest_len, key)) {
-
-               if (generic)
-                       fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
-                           DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
-                           rdata_pubkey_algorithm, rdata_digest_type);
-               else
-                       fprintf(f, "%s IN SSHFP %d %d ", hostname,
-                           rdata_pubkey_algorithm, rdata_digest_type);
+       for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
+               rdata_digest_type = dtype;
+               if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
+                   &rdata_digest, &rdata_digest_len, key)) {
+                       if (generic) {
+                               fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ",
+                                   hostname, DNS_RDATATYPE_SSHFP,
+                                   2 + rdata_digest_len,
+                                   rdata_pubkey_algorithm, rdata_digest_type);
+                       } else {
+                               fprintf(f, "%s IN SSHFP %d %d ", hostname,
+                                   rdata_pubkey_algorithm, rdata_digest_type);
+                       }
+                       for (i = 0; i < rdata_digest_len; i++)
+                               fprintf(f, "%02x", rdata_digest[i]);
+                       fprintf(f, "\n");
+                       xfree(rdata_digest); /* from key_fingerprint_raw() */
+                       success = 1;
+               }
+       }
 
-               for (i = 0; i < rdata_digest_len; i++)
-                       fprintf(f, "%02x", rdata_digest[i]);
-               fprintf(f, "\n");
-               xfree(rdata_digest); /* from key_fingerprint_raw() */
-               success = 1;
-       } else {
-               error("export_dns_rr: unsupported algorithm");
+       /* No SSHFP record was generated at all */
+       if (success == 0) {
+               error("%s: unsupported algorithm and/or digest_type", __func__);
        }
 
        return success;
diff --git a/dns.h b/dns.h
index 90cfd7b92ce2dde48d1350fe5520f76d5a0fe911..d5f428177803883af609f667d62b15c6ddde79a9 100644 (file)
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */
 
 /*
  * Copyright (c) 2003 Wesley Griffin. All rights reserved.
 #define DNS_H
 
 enum sshfp_types {
-       SSHFP_KEY_RESERVED,
-       SSHFP_KEY_RSA,
-       SSHFP_KEY_DSA
+       SSHFP_KEY_RESERVED = 0,
+       SSHFP_KEY_RSA = 1,
+       SSHFP_KEY_DSA = 2,
+       SSHFP_KEY_ECDSA = 3
 };
 
 enum sshfp_hashes {
-       SSHFP_HASH_RESERVED,
-       SSHFP_HASH_SHA1
+       SSHFP_HASH_RESERVED = 0,
+       SSHFP_HASH_SHA1 = 1,
+       SSHFP_HASH_SHA256 = 2,
+       SSHFP_HASH_MAX = 3
 };
 
 #define DNS_RDATACLASS_IN      1
diff --git a/key.c b/key.c
index 5cc4132c011f256d9f78f00b411f990a71881237..8ef0b7e3c96ed0d74137da57404bd1cd7f17ea4d 100644 (file)
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */
+/* $OpenBSD: key.c,v 1.99 2012/05/23 03:28:28 djm Exp $ */
 /*
  * read_bignum():
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -342,6 +342,9 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
        case SSH_FP_SHA1:
                md = EVP_sha1();
                break;
+       case SSH_FP_SHA256:
+               md = EVP_sha256();
+               break;
        default:
                fatal("key_fingerprint_raw: bad digest type %d",
                    dgst_type);
diff --git a/key.h b/key.h
index ec5ac5eb87c14cc70b04899e59693a2b94861570..39e5577f6b4446f862ad7ef1ef08ce4bef61746b 100644 (file)
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 djm Exp $ */
+/* $OpenBSD: key.h,v 1.34 2012/05/23 03:28:28 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -48,7 +48,8 @@ enum types {
 };
 enum fp_type {
        SSH_FP_SHA1,
-       SSH_FP_MD5
+       SSH_FP_MD5,
+       SSH_FP_SHA256
 };
 enum fp_rep {
        SSH_FP_HEX,
index c5130c86e1ad445a57902555216b9d1146a76656..9407321d5ab97307041fa45cf31a1998d311da5d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.213 2012/02/29 11:21:26 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.214 2012/05/23 03:28:28 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2194,6 +2194,8 @@ main(int argc, char **argv)
                            _PATH_HOST_RSA_KEY_FILE, rr_hostname);
                        n += do_print_resource_record(pw,
                            _PATH_HOST_DSA_KEY_FILE, rr_hostname);
+                       n += do_print_resource_record(pw,
+                           _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
 
                        if (n == 0)
                                fatal("no keys found.");