1*e4a9863fSDag-Erling Smørgrav /* $OpenBSD: dns.c,v 1.29 2013/05/17 00:13:13 djm Exp $ */ 2d95e11bfSDag-Erling Smørgrav 3d95e11bfSDag-Erling Smørgrav /* 4d95e11bfSDag-Erling Smørgrav * Copyright (c) 2003 Wesley Griffin. All rights reserved. 5d95e11bfSDag-Erling Smørgrav * Copyright (c) 2003 Jakob Schlyter. All rights reserved. 6d95e11bfSDag-Erling Smørgrav * 7d95e11bfSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 8d95e11bfSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 9d95e11bfSDag-Erling Smørgrav * are met: 10d95e11bfSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 11d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 12d95e11bfSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 13d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 14d95e11bfSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 15d95e11bfSDag-Erling Smørgrav * 16d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17d95e11bfSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18d95e11bfSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19d95e11bfSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20d95e11bfSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21d95e11bfSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22d95e11bfSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23d95e11bfSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24d95e11bfSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26d95e11bfSDag-Erling Smørgrav */ 27d95e11bfSDag-Erling Smørgrav 28d95e11bfSDag-Erling Smørgrav #include "includes.h" 29761efaa7SDag-Erling Smørgrav 30761efaa7SDag-Erling Smørgrav #include <sys/types.h> 31761efaa7SDag-Erling Smørgrav #include <sys/socket.h> 32d95e11bfSDag-Erling Smørgrav 33d95e11bfSDag-Erling Smørgrav #include <netdb.h> 34761efaa7SDag-Erling Smørgrav #include <stdarg.h> 35761efaa7SDag-Erling Smørgrav #include <stdio.h> 36761efaa7SDag-Erling Smørgrav #include <string.h> 37d95e11bfSDag-Erling Smørgrav 38d95e11bfSDag-Erling Smørgrav #include "xmalloc.h" 39d95e11bfSDag-Erling Smørgrav #include "key.h" 40d95e11bfSDag-Erling Smørgrav #include "dns.h" 41d95e11bfSDag-Erling Smørgrav #include "log.h" 42d95e11bfSDag-Erling Smørgrav 43d95e11bfSDag-Erling Smørgrav static const char *errset_text[] = { 44d95e11bfSDag-Erling Smørgrav "success", /* 0 ERRSET_SUCCESS */ 45d95e11bfSDag-Erling Smørgrav "out of memory", /* 1 ERRSET_NOMEMORY */ 46d95e11bfSDag-Erling Smørgrav "general failure", /* 2 ERRSET_FAIL */ 47d95e11bfSDag-Erling Smørgrav "invalid parameter", /* 3 ERRSET_INVAL */ 48d95e11bfSDag-Erling Smørgrav "name does not exist", /* 4 ERRSET_NONAME */ 49d95e11bfSDag-Erling Smørgrav "data does not exist", /* 5 ERRSET_NODATA */ 50d95e11bfSDag-Erling Smørgrav }; 51d95e11bfSDag-Erling Smørgrav 52d95e11bfSDag-Erling Smørgrav static const char * 53d74d50a8SDag-Erling Smørgrav dns_result_totext(unsigned int res) 54d95e11bfSDag-Erling Smørgrav { 55d74d50a8SDag-Erling Smørgrav switch (res) { 56d95e11bfSDag-Erling Smørgrav case ERRSET_SUCCESS: 57d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_SUCCESS]; 58d95e11bfSDag-Erling Smørgrav case ERRSET_NOMEMORY: 59d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NOMEMORY]; 60d95e11bfSDag-Erling Smørgrav case ERRSET_FAIL: 61d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_FAIL]; 62d95e11bfSDag-Erling Smørgrav case ERRSET_INVAL: 63d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_INVAL]; 64d95e11bfSDag-Erling Smørgrav case ERRSET_NONAME: 65d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NONAME]; 66d95e11bfSDag-Erling Smørgrav case ERRSET_NODATA: 67d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NODATA]; 68d95e11bfSDag-Erling Smørgrav default: 69d95e11bfSDag-Erling Smørgrav return "unknown error"; 70d95e11bfSDag-Erling Smørgrav } 71d95e11bfSDag-Erling Smørgrav } 72d95e11bfSDag-Erling Smørgrav 73d95e11bfSDag-Erling Smørgrav /* 74d95e11bfSDag-Erling Smørgrav * Read SSHFP parameters from key buffer. 75d95e11bfSDag-Erling Smørgrav */ 76d95e11bfSDag-Erling Smørgrav static int 77d95e11bfSDag-Erling Smørgrav dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, 78b15c8340SDag-Erling Smørgrav u_char **digest, u_int *digest_len, Key *key) 79d95e11bfSDag-Erling Smørgrav { 80d95e11bfSDag-Erling Smørgrav int success = 0; 81462c32cbSDag-Erling Smørgrav enum fp_type fp_type = 0; 82d95e11bfSDag-Erling Smørgrav 83d95e11bfSDag-Erling Smørgrav switch (key->type) { 84d95e11bfSDag-Erling Smørgrav case KEY_RSA: 85d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RSA; 86462c32cbSDag-Erling Smørgrav if (!*digest_type) 87462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA1; 88d95e11bfSDag-Erling Smørgrav break; 89d95e11bfSDag-Erling Smørgrav case KEY_DSA: 90d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_DSA; 91462c32cbSDag-Erling Smørgrav if (!*digest_type) 92462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA1; 93d95e11bfSDag-Erling Smørgrav break; 94462c32cbSDag-Erling Smørgrav case KEY_ECDSA: 95462c32cbSDag-Erling Smørgrav *algorithm = SSHFP_KEY_ECDSA; 96462c32cbSDag-Erling Smørgrav if (!*digest_type) 97462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA256; 98462c32cbSDag-Erling Smørgrav break; 99d95e11bfSDag-Erling Smørgrav default: 100021d409fSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RESERVED; /* 0 */ 101462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 102d95e11bfSDag-Erling Smørgrav } 103d95e11bfSDag-Erling Smørgrav 104462c32cbSDag-Erling Smørgrav switch (*digest_type) { 105462c32cbSDag-Erling Smørgrav case SSHFP_HASH_SHA1: 106462c32cbSDag-Erling Smørgrav fp_type = SSH_FP_SHA1; 107462c32cbSDag-Erling Smørgrav break; 108462c32cbSDag-Erling Smørgrav case SSHFP_HASH_SHA256: 109462c32cbSDag-Erling Smørgrav fp_type = SSH_FP_SHA256; 110462c32cbSDag-Erling Smørgrav break; 111462c32cbSDag-Erling Smørgrav default: 112462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 113462c32cbSDag-Erling Smørgrav } 114462c32cbSDag-Erling Smørgrav 115462c32cbSDag-Erling Smørgrav if (*algorithm && *digest_type) { 116462c32cbSDag-Erling Smørgrav *digest = key_fingerprint_raw(key, fp_type, digest_len); 117021d409fSDag-Erling Smørgrav if (*digest == NULL) 118021d409fSDag-Erling Smørgrav fatal("dns_read_key: null from key_fingerprint_raw()"); 119d95e11bfSDag-Erling Smørgrav success = 1; 120d95e11bfSDag-Erling Smørgrav } else { 121d95e11bfSDag-Erling Smørgrav *digest = NULL; 122d95e11bfSDag-Erling Smørgrav *digest_len = 0; 123d95e11bfSDag-Erling Smørgrav success = 0; 124d95e11bfSDag-Erling Smørgrav } 125d95e11bfSDag-Erling Smørgrav 126d95e11bfSDag-Erling Smørgrav return success; 127d95e11bfSDag-Erling Smørgrav } 128d95e11bfSDag-Erling Smørgrav 129d95e11bfSDag-Erling Smørgrav /* 130d95e11bfSDag-Erling Smørgrav * Read SSHFP parameters from rdata buffer. 131d95e11bfSDag-Erling Smørgrav */ 132d95e11bfSDag-Erling Smørgrav static int 133d95e11bfSDag-Erling Smørgrav dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type, 134d95e11bfSDag-Erling Smørgrav u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len) 135d95e11bfSDag-Erling Smørgrav { 136d95e11bfSDag-Erling Smørgrav int success = 0; 137d95e11bfSDag-Erling Smørgrav 138d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RESERVED; 139d95e11bfSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; 140d95e11bfSDag-Erling Smørgrav 141d95e11bfSDag-Erling Smørgrav if (rdata_len >= 2) { 142d95e11bfSDag-Erling Smørgrav *algorithm = rdata[0]; 143d95e11bfSDag-Erling Smørgrav *digest_type = rdata[1]; 144d95e11bfSDag-Erling Smørgrav *digest_len = rdata_len - 2; 145d95e11bfSDag-Erling Smørgrav 146d95e11bfSDag-Erling Smørgrav if (*digest_len > 0) { 147d95e11bfSDag-Erling Smørgrav *digest = (u_char *) xmalloc(*digest_len); 148d95e11bfSDag-Erling Smørgrav memcpy(*digest, rdata + 2, *digest_len); 149d95e11bfSDag-Erling Smørgrav } else { 150761efaa7SDag-Erling Smørgrav *digest = (u_char *)xstrdup(""); 151d95e11bfSDag-Erling Smørgrav } 152d95e11bfSDag-Erling Smørgrav 153d95e11bfSDag-Erling Smørgrav success = 1; 154d95e11bfSDag-Erling Smørgrav } 155d95e11bfSDag-Erling Smørgrav 156d95e11bfSDag-Erling Smørgrav return success; 157d95e11bfSDag-Erling Smørgrav } 158d95e11bfSDag-Erling Smørgrav 159043840dfSDag-Erling Smørgrav /* 160043840dfSDag-Erling Smørgrav * Check if hostname is numerical. 161043840dfSDag-Erling Smørgrav * Returns -1 if hostname is numeric, 0 otherwise 162043840dfSDag-Erling Smørgrav */ 163043840dfSDag-Erling Smørgrav static int 164043840dfSDag-Erling Smørgrav is_numeric_hostname(const char *hostname) 165043840dfSDag-Erling Smørgrav { 166043840dfSDag-Erling Smørgrav struct addrinfo hints, *ai; 167043840dfSDag-Erling Smørgrav 168d4af9e69SDag-Erling Smørgrav /* 169d4af9e69SDag-Erling Smørgrav * We shouldn't ever get a null host but if we do then log an error 170d4af9e69SDag-Erling Smørgrav * and return -1 which stops DNS key fingerprint processing. 171d4af9e69SDag-Erling Smørgrav */ 172d4af9e69SDag-Erling Smørgrav if (hostname == NULL) { 173d4af9e69SDag-Erling Smørgrav error("is_numeric_hostname called with NULL hostname"); 174d4af9e69SDag-Erling Smørgrav return -1; 175d4af9e69SDag-Erling Smørgrav } 176d4af9e69SDag-Erling Smørgrav 177043840dfSDag-Erling Smørgrav memset(&hints, 0, sizeof(hints)); 178043840dfSDag-Erling Smørgrav hints.ai_socktype = SOCK_DGRAM; 179043840dfSDag-Erling Smørgrav hints.ai_flags = AI_NUMERICHOST; 180043840dfSDag-Erling Smørgrav 181d4af9e69SDag-Erling Smørgrav if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { 182043840dfSDag-Erling Smørgrav freeaddrinfo(ai); 183043840dfSDag-Erling Smørgrav return -1; 184043840dfSDag-Erling Smørgrav } 185043840dfSDag-Erling Smørgrav 186043840dfSDag-Erling Smørgrav return 0; 187043840dfSDag-Erling Smørgrav } 188d95e11bfSDag-Erling Smørgrav 189d95e11bfSDag-Erling Smørgrav /* 190d95e11bfSDag-Erling Smørgrav * Verify the given hostname, address and host key using DNS. 191efcad6b7SDag-Erling Smørgrav * Returns 0 if lookup succeeds, -1 otherwise 192d95e11bfSDag-Erling Smørgrav */ 193d95e11bfSDag-Erling Smørgrav int 194d95e11bfSDag-Erling Smørgrav verify_host_key_dns(const char *hostname, struct sockaddr *address, 195b15c8340SDag-Erling Smørgrav Key *hostkey, int *flags) 196d95e11bfSDag-Erling Smørgrav { 197043840dfSDag-Erling Smørgrav u_int counter; 198d95e11bfSDag-Erling Smørgrav int result; 199d95e11bfSDag-Erling Smørgrav struct rrsetinfo *fingerprints = NULL; 200d95e11bfSDag-Erling Smørgrav 201d95e11bfSDag-Erling Smørgrav u_int8_t hostkey_algorithm; 202462c32cbSDag-Erling Smørgrav u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED; 203d95e11bfSDag-Erling Smørgrav u_char *hostkey_digest; 204d95e11bfSDag-Erling Smørgrav u_int hostkey_digest_len; 205d95e11bfSDag-Erling Smørgrav 206d95e11bfSDag-Erling Smørgrav u_int8_t dnskey_algorithm; 207d95e11bfSDag-Erling Smørgrav u_int8_t dnskey_digest_type; 208d95e11bfSDag-Erling Smørgrav u_char *dnskey_digest; 209d95e11bfSDag-Erling Smørgrav u_int dnskey_digest_len; 210d95e11bfSDag-Erling Smørgrav 211efcad6b7SDag-Erling Smørgrav *flags = 0; 212d95e11bfSDag-Erling Smørgrav 213021d409fSDag-Erling Smørgrav debug3("verify_host_key_dns"); 214d95e11bfSDag-Erling Smørgrav if (hostkey == NULL) 215d95e11bfSDag-Erling Smørgrav fatal("No key to look up!"); 216d95e11bfSDag-Erling Smørgrav 217043840dfSDag-Erling Smørgrav if (is_numeric_hostname(hostname)) { 218043840dfSDag-Erling Smørgrav debug("skipped DNS lookup for numerical hostname"); 219043840dfSDag-Erling Smørgrav return -1; 220043840dfSDag-Erling Smørgrav } 221043840dfSDag-Erling Smørgrav 222d95e11bfSDag-Erling Smørgrav result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, 223d95e11bfSDag-Erling Smørgrav DNS_RDATATYPE_SSHFP, 0, &fingerprints); 224d95e11bfSDag-Erling Smørgrav if (result) { 225d95e11bfSDag-Erling Smørgrav verbose("DNS lookup error: %s", dns_result_totext(result)); 226efcad6b7SDag-Erling Smørgrav return -1; 227d95e11bfSDag-Erling Smørgrav } 228d95e11bfSDag-Erling Smørgrav 229efcad6b7SDag-Erling Smørgrav if (fingerprints->rri_flags & RRSET_VALIDATED) { 230efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_SECURE; 231efcad6b7SDag-Erling Smørgrav debug("found %d secure fingerprints in DNS", 232efcad6b7SDag-Erling Smørgrav fingerprints->rri_nrdatas); 233efcad6b7SDag-Erling Smørgrav } else { 234efcad6b7SDag-Erling Smørgrav debug("found %d insecure fingerprints in DNS", 235efcad6b7SDag-Erling Smørgrav fingerprints->rri_nrdatas); 236d95e11bfSDag-Erling Smørgrav } 237d95e11bfSDag-Erling Smørgrav 238462c32cbSDag-Erling Smørgrav /* Initialize default host key parameters */ 239d95e11bfSDag-Erling Smørgrav if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, 240d95e11bfSDag-Erling Smørgrav &hostkey_digest, &hostkey_digest_len, hostkey)) { 241d95e11bfSDag-Erling Smørgrav error("Error calculating host key fingerprint."); 242d95e11bfSDag-Erling Smørgrav freerrset(fingerprints); 243efcad6b7SDag-Erling Smørgrav return -1; 244d95e11bfSDag-Erling Smørgrav } 245d95e11bfSDag-Erling Smørgrav 246efcad6b7SDag-Erling Smørgrav if (fingerprints->rri_nrdatas) 247efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_FOUND; 248efcad6b7SDag-Erling Smørgrav 249d95e11bfSDag-Erling Smørgrav for (counter = 0; counter < fingerprints->rri_nrdatas; counter++) { 250d95e11bfSDag-Erling Smørgrav /* 251d95e11bfSDag-Erling Smørgrav * Extract the key from the answer. Ignore any badly 252d95e11bfSDag-Erling Smørgrav * formatted fingerprints. 253d95e11bfSDag-Erling Smørgrav */ 254d95e11bfSDag-Erling Smørgrav if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type, 255d95e11bfSDag-Erling Smørgrav &dnskey_digest, &dnskey_digest_len, 256d95e11bfSDag-Erling Smørgrav fingerprints->rri_rdatas[counter].rdi_data, 257d95e11bfSDag-Erling Smørgrav fingerprints->rri_rdatas[counter].rdi_length)) { 258d95e11bfSDag-Erling Smørgrav verbose("Error parsing fingerprint from DNS."); 259d95e11bfSDag-Erling Smørgrav continue; 260d95e11bfSDag-Erling Smørgrav } 261d95e11bfSDag-Erling Smørgrav 262462c32cbSDag-Erling Smørgrav if (hostkey_digest_type != dnskey_digest_type) { 263462c32cbSDag-Erling Smørgrav hostkey_digest_type = dnskey_digest_type; 264*e4a9863fSDag-Erling Smørgrav free(hostkey_digest); 265462c32cbSDag-Erling Smørgrav 266462c32cbSDag-Erling Smørgrav /* Initialize host key parameters */ 267462c32cbSDag-Erling Smørgrav if (!dns_read_key(&hostkey_algorithm, 268462c32cbSDag-Erling Smørgrav &hostkey_digest_type, &hostkey_digest, 269462c32cbSDag-Erling Smørgrav &hostkey_digest_len, hostkey)) { 270462c32cbSDag-Erling Smørgrav error("Error calculating key fingerprint."); 271462c32cbSDag-Erling Smørgrav freerrset(fingerprints); 272462c32cbSDag-Erling Smørgrav return -1; 273462c32cbSDag-Erling Smørgrav } 274462c32cbSDag-Erling Smørgrav } 275462c32cbSDag-Erling Smørgrav 276d95e11bfSDag-Erling Smørgrav /* Check if the current key is the same as the given key */ 277d95e11bfSDag-Erling Smørgrav if (hostkey_algorithm == dnskey_algorithm && 278d95e11bfSDag-Erling Smørgrav hostkey_digest_type == dnskey_digest_type) { 279d95e11bfSDag-Erling Smørgrav if (hostkey_digest_len == dnskey_digest_len && 280462c32cbSDag-Erling Smørgrav timingsafe_bcmp(hostkey_digest, dnskey_digest, 281462c32cbSDag-Erling Smørgrav hostkey_digest_len) == 0) 282efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_MATCH; 283efcad6b7SDag-Erling Smørgrav } 284*e4a9863fSDag-Erling Smørgrav free(dnskey_digest); 285efcad6b7SDag-Erling Smørgrav } 286efcad6b7SDag-Erling Smørgrav 287*e4a9863fSDag-Erling Smørgrav free(hostkey_digest); /* from key_fingerprint_raw() */ 288d95e11bfSDag-Erling Smørgrav freerrset(fingerprints); 289efcad6b7SDag-Erling Smørgrav 290efcad6b7SDag-Erling Smørgrav if (*flags & DNS_VERIFY_FOUND) 291efcad6b7SDag-Erling Smørgrav if (*flags & DNS_VERIFY_MATCH) 292d95e11bfSDag-Erling Smørgrav debug("matching host key fingerprint found in DNS"); 293efcad6b7SDag-Erling Smørgrav else 294efcad6b7SDag-Erling Smørgrav debug("mismatching host key fingerprint found in DNS"); 295efcad6b7SDag-Erling Smørgrav else 296efcad6b7SDag-Erling Smørgrav debug("no host key fingerprint found in DNS"); 297d95e11bfSDag-Erling Smørgrav 298efcad6b7SDag-Erling Smørgrav return 0; 299d95e11bfSDag-Erling Smørgrav } 300d95e11bfSDag-Erling Smørgrav 301d95e11bfSDag-Erling Smørgrav /* 302d95e11bfSDag-Erling Smørgrav * Export the fingerprint of a key as a DNS resource record 303d95e11bfSDag-Erling Smørgrav */ 304d95e11bfSDag-Erling Smørgrav int 305b15c8340SDag-Erling Smørgrav export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) 306d95e11bfSDag-Erling Smørgrav { 307d95e11bfSDag-Erling Smørgrav u_int8_t rdata_pubkey_algorithm = 0; 308462c32cbSDag-Erling Smørgrav u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED; 309462c32cbSDag-Erling Smørgrav u_int8_t dtype; 310d95e11bfSDag-Erling Smørgrav u_char *rdata_digest; 311462c32cbSDag-Erling Smørgrav u_int i, rdata_digest_len; 312d95e11bfSDag-Erling Smørgrav int success = 0; 313d95e11bfSDag-Erling Smørgrav 314462c32cbSDag-Erling Smørgrav for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) { 315462c32cbSDag-Erling Smørgrav rdata_digest_type = dtype; 316d95e11bfSDag-Erling Smørgrav if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, 317d95e11bfSDag-Erling Smørgrav &rdata_digest, &rdata_digest_len, key)) { 318462c32cbSDag-Erling Smørgrav if (generic) { 319462c32cbSDag-Erling Smørgrav fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", 320462c32cbSDag-Erling Smørgrav hostname, DNS_RDATATYPE_SSHFP, 321462c32cbSDag-Erling Smørgrav 2 + rdata_digest_len, 322d95e11bfSDag-Erling Smørgrav rdata_pubkey_algorithm, rdata_digest_type); 323462c32cbSDag-Erling Smørgrav } else { 324d95e11bfSDag-Erling Smørgrav fprintf(f, "%s IN SSHFP %d %d ", hostname, 325d95e11bfSDag-Erling Smørgrav rdata_pubkey_algorithm, rdata_digest_type); 326462c32cbSDag-Erling Smørgrav } 327d95e11bfSDag-Erling Smørgrav for (i = 0; i < rdata_digest_len; i++) 328d95e11bfSDag-Erling Smørgrav fprintf(f, "%02x", rdata_digest[i]); 329d95e11bfSDag-Erling Smørgrav fprintf(f, "\n"); 330*e4a9863fSDag-Erling Smørgrav free(rdata_digest); /* from key_fingerprint_raw() */ 331d95e11bfSDag-Erling Smørgrav success = 1; 332462c32cbSDag-Erling Smørgrav } 333462c32cbSDag-Erling Smørgrav } 334462c32cbSDag-Erling Smørgrav 335462c32cbSDag-Erling Smørgrav /* No SSHFP record was generated at all */ 336462c32cbSDag-Erling Smørgrav if (success == 0) { 337462c32cbSDag-Erling Smørgrav error("%s: unsupported algorithm and/or digest_type", __func__); 338d95e11bfSDag-Erling Smørgrav } 339d95e11bfSDag-Erling Smørgrav 340d95e11bfSDag-Erling Smørgrav return success; 341d95e11bfSDag-Erling Smørgrav } 342