summaryrefslogtreecommitdiff
path: root/dns.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2012-06-20 21:51:11 +1000
committerDamien Miller <djm@mindrot.org>2012-06-20 21:51:11 +1000
commit3bde12aeef60c9e1221316aff1fe1aca78eca027 (patch)
tree391e98a1c7a72c4f02afb0407dbcc9a4ef6174aa /dns.c
parentac58ce86e6f4dcb245d5e1aa28a5c7a9f4a56072 (diff)
- 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@
Diffstat (limited to 'dns.c')
-rw-r--r--dns.c103
1 files changed, 69 insertions, 34 deletions
diff --git a/dns.c b/dns.c
index 131cb3d8b..9e3084ba5 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */ 1/* $OpenBSD: dns.c,v 1.28 2012/05/23 03:28:28 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -78,27 +78,46 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
78 u_char **digest, u_int *digest_len, Key *key) 78 u_char **digest, u_int *digest_len, Key *key)
79{ 79{
80 int success = 0; 80 int success = 0;
81 enum fp_type fp_type = 0;
81 82
82 switch (key->type) { 83 switch (key->type) {
83 case KEY_RSA: 84 case KEY_RSA:
84 *algorithm = SSHFP_KEY_RSA; 85 *algorithm = SSHFP_KEY_RSA;
86 if (!*digest_type)
87 *digest_type = SSHFP_HASH_SHA1;
85 break; 88 break;
86 case KEY_DSA: 89 case KEY_DSA:
87 *algorithm = SSHFP_KEY_DSA; 90 *algorithm = SSHFP_KEY_DSA;
91 if (!*digest_type)
92 *digest_type = SSHFP_HASH_SHA1;
93 break;
94 case KEY_ECDSA:
95 *algorithm = SSHFP_KEY_ECDSA;
96 if (!*digest_type)
97 *digest_type = SSHFP_HASH_SHA256;
88 break; 98 break;
89 /* XXX KEY_ECDSA */
90 default: 99 default:
91 *algorithm = SSHFP_KEY_RESERVED; /* 0 */ 100 *algorithm = SSHFP_KEY_RESERVED; /* 0 */
101 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
102 }
103
104 switch (*digest_type) {
105 case SSHFP_HASH_SHA1:
106 fp_type = SSH_FP_SHA1;
107 break;
108 case SSHFP_HASH_SHA256:
109 fp_type = SSH_FP_SHA256;
110 break;
111 default:
112 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
92 } 113 }
93 114
94 if (*algorithm) { 115 if (*algorithm && *digest_type) {
95 *digest_type = SSHFP_HASH_SHA1; 116 *digest = key_fingerprint_raw(key, fp_type, digest_len);
96 *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
97 if (*digest == NULL) 117 if (*digest == NULL)
98 fatal("dns_read_key: null from key_fingerprint_raw()"); 118 fatal("dns_read_key: null from key_fingerprint_raw()");
99 success = 1; 119 success = 1;
100 } else { 120 } else {
101 *digest_type = SSHFP_HASH_RESERVED;
102 *digest = NULL; 121 *digest = NULL;
103 *digest_len = 0; 122 *digest_len = 0;
104 success = 0; 123 success = 0;
@@ -180,7 +199,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
180 struct rrsetinfo *fingerprints = NULL; 199 struct rrsetinfo *fingerprints = NULL;
181 200
182 u_int8_t hostkey_algorithm; 201 u_int8_t hostkey_algorithm;
183 u_int8_t hostkey_digest_type; 202 u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
184 u_char *hostkey_digest; 203 u_char *hostkey_digest;
185 u_int hostkey_digest_len; 204 u_int hostkey_digest_len;
186 205
@@ -216,7 +235,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
216 fingerprints->rri_nrdatas); 235 fingerprints->rri_nrdatas);
217 } 236 }
218 237
219 /* Initialize host key parameters */ 238 /* Initialize default host key parameters */
220 if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, 239 if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
221 &hostkey_digest, &hostkey_digest_len, hostkey)) { 240 &hostkey_digest, &hostkey_digest_len, hostkey)) {
222 error("Error calculating host key fingerprint."); 241 error("Error calculating host key fingerprint.");
@@ -240,16 +259,27 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
240 continue; 259 continue;
241 } 260 }
242 261
262 if (hostkey_digest_type != dnskey_digest_type) {
263 hostkey_digest_type = dnskey_digest_type;
264 xfree(hostkey_digest);
265
266 /* Initialize host key parameters */
267 if (!dns_read_key(&hostkey_algorithm,
268 &hostkey_digest_type, &hostkey_digest,
269 &hostkey_digest_len, hostkey)) {
270 error("Error calculating key fingerprint.");
271 freerrset(fingerprints);
272 return -1;
273 }
274 }
275
243 /* Check if the current key is the same as the given key */ 276 /* Check if the current key is the same as the given key */
244 if (hostkey_algorithm == dnskey_algorithm && 277 if (hostkey_algorithm == dnskey_algorithm &&
245 hostkey_digest_type == dnskey_digest_type) { 278 hostkey_digest_type == dnskey_digest_type) {
246
247 if (hostkey_digest_len == dnskey_digest_len && 279 if (hostkey_digest_len == dnskey_digest_len &&
248 memcmp(hostkey_digest, dnskey_digest, 280 timingsafe_bcmp(hostkey_digest, dnskey_digest,
249 hostkey_digest_len) == 0) { 281 hostkey_digest_len) == 0)
250
251 *flags |= DNS_VERIFY_MATCH; 282 *flags |= DNS_VERIFY_MATCH;
252 }
253 } 283 }
254 xfree(dnskey_digest); 284 xfree(dnskey_digest);
255 } 285 }
@@ -275,31 +305,36 @@ int
275export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) 305export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
276{ 306{
277 u_int8_t rdata_pubkey_algorithm = 0; 307 u_int8_t rdata_pubkey_algorithm = 0;
278 u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; 308 u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
309 u_int8_t dtype;
279 u_char *rdata_digest; 310 u_char *rdata_digest;
280 u_int rdata_digest_len; 311 u_int i, rdata_digest_len;
281
282 u_int i;
283 int success = 0; 312 int success = 0;
284 313
285 if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, 314 for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
286 &rdata_digest, &rdata_digest_len, key)) { 315 rdata_digest_type = dtype;
287 316 if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
288 if (generic) 317 &rdata_digest, &rdata_digest_len, key)) {
289 fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname, 318 if (generic) {
290 DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, 319 fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ",
291 rdata_pubkey_algorithm, rdata_digest_type); 320 hostname, DNS_RDATATYPE_SSHFP,
292 else 321 2 + rdata_digest_len,
293 fprintf(f, "%s IN SSHFP %d %d ", hostname, 322 rdata_pubkey_algorithm, rdata_digest_type);
294 rdata_pubkey_algorithm, rdata_digest_type); 323 } else {
324 fprintf(f, "%s IN SSHFP %d %d ", hostname,
325 rdata_pubkey_algorithm, rdata_digest_type);
326 }
327 for (i = 0; i < rdata_digest_len; i++)
328 fprintf(f, "%02x", rdata_digest[i]);
329 fprintf(f, "\n");
330 xfree(rdata_digest); /* from key_fingerprint_raw() */
331 success = 1;
332 }
333 }
295 334
296 for (i = 0; i < rdata_digest_len; i++) 335 /* No SSHFP record was generated at all */
297 fprintf(f, "%02x", rdata_digest[i]); 336 if (success == 0) {
298 fprintf(f, "\n"); 337 error("%s: unsupported algorithm and/or digest_type", __func__);
299 xfree(rdata_digest); /* from key_fingerprint_raw() */
300 success = 1;
301 } else {
302 error("export_dns_rr: unsupported algorithm");
303 } 338 }
304 339
305 return success; 340 return success;