1*a0ee8cc6SDag-Erling Smørgrav /* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 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> 37*a0ee8cc6SDag-Erling Smørgrav #include <stdarg.h> 38*a0ee8cc6SDag-Erling Smørgrav #include <stdlib.h> 39d95e11bfSDag-Erling Smørgrav 40d95e11bfSDag-Erling Smørgrav #include "xmalloc.h" 41d95e11bfSDag-Erling Smørgrav #include "key.h" 42d95e11bfSDag-Erling Smørgrav #include "dns.h" 43d95e11bfSDag-Erling Smørgrav #include "log.h" 44d95e11bfSDag-Erling Smørgrav 45d95e11bfSDag-Erling Smørgrav static const char *errset_text[] = { 46d95e11bfSDag-Erling Smørgrav "success", /* 0 ERRSET_SUCCESS */ 47d95e11bfSDag-Erling Smørgrav "out of memory", /* 1 ERRSET_NOMEMORY */ 48d95e11bfSDag-Erling Smørgrav "general failure", /* 2 ERRSET_FAIL */ 49d95e11bfSDag-Erling Smørgrav "invalid parameter", /* 3 ERRSET_INVAL */ 50d95e11bfSDag-Erling Smørgrav "name does not exist", /* 4 ERRSET_NONAME */ 51d95e11bfSDag-Erling Smørgrav "data does not exist", /* 5 ERRSET_NODATA */ 52d95e11bfSDag-Erling Smørgrav }; 53d95e11bfSDag-Erling Smørgrav 54d95e11bfSDag-Erling Smørgrav static const char * 55d74d50a8SDag-Erling Smørgrav dns_result_totext(unsigned int res) 56d95e11bfSDag-Erling Smørgrav { 57d74d50a8SDag-Erling Smørgrav switch (res) { 58d95e11bfSDag-Erling Smørgrav case ERRSET_SUCCESS: 59d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_SUCCESS]; 60d95e11bfSDag-Erling Smørgrav case ERRSET_NOMEMORY: 61d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NOMEMORY]; 62d95e11bfSDag-Erling Smørgrav case ERRSET_FAIL: 63d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_FAIL]; 64d95e11bfSDag-Erling Smørgrav case ERRSET_INVAL: 65d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_INVAL]; 66d95e11bfSDag-Erling Smørgrav case ERRSET_NONAME: 67d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NONAME]; 68d95e11bfSDag-Erling Smørgrav case ERRSET_NODATA: 69d95e11bfSDag-Erling Smørgrav return errset_text[ERRSET_NODATA]; 70d95e11bfSDag-Erling Smørgrav default: 71d95e11bfSDag-Erling Smørgrav return "unknown error"; 72d95e11bfSDag-Erling Smørgrav } 73d95e11bfSDag-Erling Smørgrav } 74d95e11bfSDag-Erling Smørgrav 75d95e11bfSDag-Erling Smørgrav /* 76d95e11bfSDag-Erling Smørgrav * Read SSHFP parameters from key buffer. 77d95e11bfSDag-Erling Smørgrav */ 78d95e11bfSDag-Erling Smørgrav static int 79d95e11bfSDag-Erling Smørgrav dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, 80b15c8340SDag-Erling Smørgrav u_char **digest, u_int *digest_len, Key *key) 81d95e11bfSDag-Erling Smørgrav { 82d95e11bfSDag-Erling Smørgrav int success = 0; 83462c32cbSDag-Erling Smørgrav enum fp_type fp_type = 0; 84d95e11bfSDag-Erling Smørgrav 85d95e11bfSDag-Erling Smørgrav switch (key->type) { 86d95e11bfSDag-Erling Smørgrav case KEY_RSA: 87d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RSA; 88462c32cbSDag-Erling Smørgrav if (!*digest_type) 89462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA1; 90d95e11bfSDag-Erling Smørgrav break; 91d95e11bfSDag-Erling Smørgrav case KEY_DSA: 92d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_DSA; 93462c32cbSDag-Erling Smørgrav if (!*digest_type) 94462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA1; 95d95e11bfSDag-Erling Smørgrav break; 96462c32cbSDag-Erling Smørgrav case KEY_ECDSA: 97462c32cbSDag-Erling Smørgrav *algorithm = SSHFP_KEY_ECDSA; 98462c32cbSDag-Erling Smørgrav if (!*digest_type) 99462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA256; 100462c32cbSDag-Erling Smørgrav break; 101*a0ee8cc6SDag-Erling Smørgrav case KEY_ED25519: 102*a0ee8cc6SDag-Erling Smørgrav *algorithm = SSHFP_KEY_ED25519; 103*a0ee8cc6SDag-Erling Smørgrav if (!*digest_type) 104*a0ee8cc6SDag-Erling Smørgrav *digest_type = SSHFP_HASH_SHA256; 105*a0ee8cc6SDag-Erling Smørgrav break; 106d95e11bfSDag-Erling Smørgrav default: 107021d409fSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RESERVED; /* 0 */ 108462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 109d95e11bfSDag-Erling Smørgrav } 110d95e11bfSDag-Erling Smørgrav 111462c32cbSDag-Erling Smørgrav switch (*digest_type) { 112462c32cbSDag-Erling Smørgrav case SSHFP_HASH_SHA1: 113462c32cbSDag-Erling Smørgrav fp_type = SSH_FP_SHA1; 114462c32cbSDag-Erling Smørgrav break; 115462c32cbSDag-Erling Smørgrav case SSHFP_HASH_SHA256: 116462c32cbSDag-Erling Smørgrav fp_type = SSH_FP_SHA256; 117462c32cbSDag-Erling Smørgrav break; 118462c32cbSDag-Erling Smørgrav default: 119462c32cbSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 120462c32cbSDag-Erling Smørgrav } 121462c32cbSDag-Erling Smørgrav 122462c32cbSDag-Erling Smørgrav if (*algorithm && *digest_type) { 123462c32cbSDag-Erling Smørgrav *digest = key_fingerprint_raw(key, fp_type, digest_len); 124021d409fSDag-Erling Smørgrav if (*digest == NULL) 125021d409fSDag-Erling Smørgrav fatal("dns_read_key: null from key_fingerprint_raw()"); 126d95e11bfSDag-Erling Smørgrav success = 1; 127d95e11bfSDag-Erling Smørgrav } else { 128d95e11bfSDag-Erling Smørgrav *digest = NULL; 129d95e11bfSDag-Erling Smørgrav *digest_len = 0; 130d95e11bfSDag-Erling Smørgrav success = 0; 131d95e11bfSDag-Erling Smørgrav } 132d95e11bfSDag-Erling Smørgrav 133d95e11bfSDag-Erling Smørgrav return success; 134d95e11bfSDag-Erling Smørgrav } 135d95e11bfSDag-Erling Smørgrav 136d95e11bfSDag-Erling Smørgrav /* 137d95e11bfSDag-Erling Smørgrav * Read SSHFP parameters from rdata buffer. 138d95e11bfSDag-Erling Smørgrav */ 139d95e11bfSDag-Erling Smørgrav static int 140d95e11bfSDag-Erling Smørgrav dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type, 141d95e11bfSDag-Erling Smørgrav u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len) 142d95e11bfSDag-Erling Smørgrav { 143d95e11bfSDag-Erling Smørgrav int success = 0; 144d95e11bfSDag-Erling Smørgrav 145d95e11bfSDag-Erling Smørgrav *algorithm = SSHFP_KEY_RESERVED; 146d95e11bfSDag-Erling Smørgrav *digest_type = SSHFP_HASH_RESERVED; 147d95e11bfSDag-Erling Smørgrav 148d95e11bfSDag-Erling Smørgrav if (rdata_len >= 2) { 149d95e11bfSDag-Erling Smørgrav *algorithm = rdata[0]; 150d95e11bfSDag-Erling Smørgrav *digest_type = rdata[1]; 151d95e11bfSDag-Erling Smørgrav *digest_len = rdata_len - 2; 152d95e11bfSDag-Erling Smørgrav 153d95e11bfSDag-Erling Smørgrav if (*digest_len > 0) { 154d95e11bfSDag-Erling Smørgrav *digest = (u_char *) xmalloc(*digest_len); 155d95e11bfSDag-Erling Smørgrav memcpy(*digest, rdata + 2, *digest_len); 156d95e11bfSDag-Erling Smørgrav } else { 157761efaa7SDag-Erling Smørgrav *digest = (u_char *)xstrdup(""); 158d95e11bfSDag-Erling Smørgrav } 159d95e11bfSDag-Erling Smørgrav 160d95e11bfSDag-Erling Smørgrav success = 1; 161d95e11bfSDag-Erling Smørgrav } 162d95e11bfSDag-Erling Smørgrav 163d95e11bfSDag-Erling Smørgrav return success; 164d95e11bfSDag-Erling Smørgrav } 165d95e11bfSDag-Erling Smørgrav 166043840dfSDag-Erling Smørgrav /* 167043840dfSDag-Erling Smørgrav * Check if hostname is numerical. 168043840dfSDag-Erling Smørgrav * Returns -1 if hostname is numeric, 0 otherwise 169043840dfSDag-Erling Smørgrav */ 170043840dfSDag-Erling Smørgrav static int 171043840dfSDag-Erling Smørgrav is_numeric_hostname(const char *hostname) 172043840dfSDag-Erling Smørgrav { 173043840dfSDag-Erling Smørgrav struct addrinfo hints, *ai; 174043840dfSDag-Erling Smørgrav 175d4af9e69SDag-Erling Smørgrav /* 176d4af9e69SDag-Erling Smørgrav * We shouldn't ever get a null host but if we do then log an error 177d4af9e69SDag-Erling Smørgrav * and return -1 which stops DNS key fingerprint processing. 178d4af9e69SDag-Erling Smørgrav */ 179d4af9e69SDag-Erling Smørgrav if (hostname == NULL) { 180d4af9e69SDag-Erling Smørgrav error("is_numeric_hostname called with NULL hostname"); 181d4af9e69SDag-Erling Smørgrav return -1; 182d4af9e69SDag-Erling Smørgrav } 183d4af9e69SDag-Erling Smørgrav 184043840dfSDag-Erling Smørgrav memset(&hints, 0, sizeof(hints)); 185043840dfSDag-Erling Smørgrav hints.ai_socktype = SOCK_DGRAM; 186043840dfSDag-Erling Smørgrav hints.ai_flags = AI_NUMERICHOST; 187043840dfSDag-Erling Smørgrav 188d4af9e69SDag-Erling Smørgrav if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { 189043840dfSDag-Erling Smørgrav freeaddrinfo(ai); 190043840dfSDag-Erling Smørgrav return -1; 191043840dfSDag-Erling Smørgrav } 192043840dfSDag-Erling Smørgrav 193043840dfSDag-Erling Smørgrav return 0; 194043840dfSDag-Erling Smørgrav } 195d95e11bfSDag-Erling Smørgrav 196d95e11bfSDag-Erling Smørgrav /* 197d95e11bfSDag-Erling Smørgrav * Verify the given hostname, address and host key using DNS. 198efcad6b7SDag-Erling Smørgrav * Returns 0 if lookup succeeds, -1 otherwise 199d95e11bfSDag-Erling Smørgrav */ 200d95e11bfSDag-Erling Smørgrav int 201d95e11bfSDag-Erling Smørgrav verify_host_key_dns(const char *hostname, struct sockaddr *address, 202b15c8340SDag-Erling Smørgrav Key *hostkey, int *flags) 203d95e11bfSDag-Erling Smørgrav { 204043840dfSDag-Erling Smørgrav u_int counter; 205d95e11bfSDag-Erling Smørgrav int result; 206d95e11bfSDag-Erling Smørgrav struct rrsetinfo *fingerprints = NULL; 207d95e11bfSDag-Erling Smørgrav 208d95e11bfSDag-Erling Smørgrav u_int8_t hostkey_algorithm; 209462c32cbSDag-Erling Smørgrav u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED; 210d95e11bfSDag-Erling Smørgrav u_char *hostkey_digest; 211d95e11bfSDag-Erling Smørgrav u_int hostkey_digest_len; 212d95e11bfSDag-Erling Smørgrav 213d95e11bfSDag-Erling Smørgrav u_int8_t dnskey_algorithm; 214d95e11bfSDag-Erling Smørgrav u_int8_t dnskey_digest_type; 215d95e11bfSDag-Erling Smørgrav u_char *dnskey_digest; 216d95e11bfSDag-Erling Smørgrav u_int dnskey_digest_len; 217d95e11bfSDag-Erling Smørgrav 218efcad6b7SDag-Erling Smørgrav *flags = 0; 219d95e11bfSDag-Erling Smørgrav 220021d409fSDag-Erling Smørgrav debug3("verify_host_key_dns"); 221d95e11bfSDag-Erling Smørgrav if (hostkey == NULL) 222d95e11bfSDag-Erling Smørgrav fatal("No key to look up!"); 223d95e11bfSDag-Erling Smørgrav 224043840dfSDag-Erling Smørgrav if (is_numeric_hostname(hostname)) { 225043840dfSDag-Erling Smørgrav debug("skipped DNS lookup for numerical hostname"); 226043840dfSDag-Erling Smørgrav return -1; 227043840dfSDag-Erling Smørgrav } 228043840dfSDag-Erling Smørgrav 229d95e11bfSDag-Erling Smørgrav result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, 230d95e11bfSDag-Erling Smørgrav DNS_RDATATYPE_SSHFP, 0, &fingerprints); 231d95e11bfSDag-Erling Smørgrav if (result) { 232d95e11bfSDag-Erling Smørgrav verbose("DNS lookup error: %s", dns_result_totext(result)); 233efcad6b7SDag-Erling Smørgrav return -1; 234d95e11bfSDag-Erling Smørgrav } 235d95e11bfSDag-Erling Smørgrav 236efcad6b7SDag-Erling Smørgrav if (fingerprints->rri_flags & RRSET_VALIDATED) { 237efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_SECURE; 238efcad6b7SDag-Erling Smørgrav debug("found %d secure fingerprints in DNS", 239efcad6b7SDag-Erling Smørgrav fingerprints->rri_nrdatas); 240efcad6b7SDag-Erling Smørgrav } else { 241efcad6b7SDag-Erling Smørgrav debug("found %d insecure fingerprints in DNS", 242efcad6b7SDag-Erling Smørgrav fingerprints->rri_nrdatas); 243d95e11bfSDag-Erling Smørgrav } 244d95e11bfSDag-Erling Smørgrav 245462c32cbSDag-Erling Smørgrav /* Initialize default host key parameters */ 246d95e11bfSDag-Erling Smørgrav if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, 247d95e11bfSDag-Erling Smørgrav &hostkey_digest, &hostkey_digest_len, hostkey)) { 248d95e11bfSDag-Erling Smørgrav error("Error calculating host key fingerprint."); 249d95e11bfSDag-Erling Smørgrav freerrset(fingerprints); 250efcad6b7SDag-Erling Smørgrav return -1; 251d95e11bfSDag-Erling Smørgrav } 252d95e11bfSDag-Erling Smørgrav 253efcad6b7SDag-Erling Smørgrav if (fingerprints->rri_nrdatas) 254efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_FOUND; 255efcad6b7SDag-Erling Smørgrav 256d95e11bfSDag-Erling Smørgrav for (counter = 0; counter < fingerprints->rri_nrdatas; counter++) { 257d95e11bfSDag-Erling Smørgrav /* 258d95e11bfSDag-Erling Smørgrav * Extract the key from the answer. Ignore any badly 259d95e11bfSDag-Erling Smørgrav * formatted fingerprints. 260d95e11bfSDag-Erling Smørgrav */ 261d95e11bfSDag-Erling Smørgrav if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type, 262d95e11bfSDag-Erling Smørgrav &dnskey_digest, &dnskey_digest_len, 263d95e11bfSDag-Erling Smørgrav fingerprints->rri_rdatas[counter].rdi_data, 264d95e11bfSDag-Erling Smørgrav fingerprints->rri_rdatas[counter].rdi_length)) { 265d95e11bfSDag-Erling Smørgrav verbose("Error parsing fingerprint from DNS."); 266d95e11bfSDag-Erling Smørgrav continue; 267d95e11bfSDag-Erling Smørgrav } 268d95e11bfSDag-Erling Smørgrav 269462c32cbSDag-Erling Smørgrav if (hostkey_digest_type != dnskey_digest_type) { 270462c32cbSDag-Erling Smørgrav hostkey_digest_type = dnskey_digest_type; 271e4a9863fSDag-Erling Smørgrav free(hostkey_digest); 272462c32cbSDag-Erling Smørgrav 273462c32cbSDag-Erling Smørgrav /* Initialize host key parameters */ 274462c32cbSDag-Erling Smørgrav if (!dns_read_key(&hostkey_algorithm, 275462c32cbSDag-Erling Smørgrav &hostkey_digest_type, &hostkey_digest, 276462c32cbSDag-Erling Smørgrav &hostkey_digest_len, hostkey)) { 277462c32cbSDag-Erling Smørgrav error("Error calculating key fingerprint."); 278462c32cbSDag-Erling Smørgrav freerrset(fingerprints); 279462c32cbSDag-Erling Smørgrav return -1; 280462c32cbSDag-Erling Smørgrav } 281462c32cbSDag-Erling Smørgrav } 282462c32cbSDag-Erling Smørgrav 283d95e11bfSDag-Erling Smørgrav /* Check if the current key is the same as the given key */ 284d95e11bfSDag-Erling Smørgrav if (hostkey_algorithm == dnskey_algorithm && 285d95e11bfSDag-Erling Smørgrav hostkey_digest_type == dnskey_digest_type) { 286d95e11bfSDag-Erling Smørgrav if (hostkey_digest_len == dnskey_digest_len && 287462c32cbSDag-Erling Smørgrav timingsafe_bcmp(hostkey_digest, dnskey_digest, 288462c32cbSDag-Erling Smørgrav hostkey_digest_len) == 0) 289efcad6b7SDag-Erling Smørgrav *flags |= DNS_VERIFY_MATCH; 290efcad6b7SDag-Erling Smørgrav } 291e4a9863fSDag-Erling Smørgrav free(dnskey_digest); 292efcad6b7SDag-Erling Smørgrav } 293efcad6b7SDag-Erling Smørgrav 294e4a9863fSDag-Erling Smørgrav free(hostkey_digest); /* from key_fingerprint_raw() */ 295d95e11bfSDag-Erling Smørgrav freerrset(fingerprints); 296efcad6b7SDag-Erling Smørgrav 297efcad6b7SDag-Erling Smørgrav if (*flags & DNS_VERIFY_FOUND) 298efcad6b7SDag-Erling Smørgrav if (*flags & DNS_VERIFY_MATCH) 299d95e11bfSDag-Erling Smørgrav debug("matching host key fingerprint found in DNS"); 300efcad6b7SDag-Erling Smørgrav else 301efcad6b7SDag-Erling Smørgrav debug("mismatching host key fingerprint found in DNS"); 302efcad6b7SDag-Erling Smørgrav else 303efcad6b7SDag-Erling Smørgrav debug("no host key fingerprint found in DNS"); 304d95e11bfSDag-Erling Smørgrav 305efcad6b7SDag-Erling Smørgrav return 0; 306d95e11bfSDag-Erling Smørgrav } 307d95e11bfSDag-Erling Smørgrav 308d95e11bfSDag-Erling Smørgrav /* 309d95e11bfSDag-Erling Smørgrav * Export the fingerprint of a key as a DNS resource record 310d95e11bfSDag-Erling Smørgrav */ 311d95e11bfSDag-Erling Smørgrav int 312b15c8340SDag-Erling Smørgrav export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) 313d95e11bfSDag-Erling Smørgrav { 314d95e11bfSDag-Erling Smørgrav u_int8_t rdata_pubkey_algorithm = 0; 315462c32cbSDag-Erling Smørgrav u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED; 316462c32cbSDag-Erling Smørgrav u_int8_t dtype; 317d95e11bfSDag-Erling Smørgrav u_char *rdata_digest; 318462c32cbSDag-Erling Smørgrav u_int i, rdata_digest_len; 319d95e11bfSDag-Erling Smørgrav int success = 0; 320d95e11bfSDag-Erling Smørgrav 321462c32cbSDag-Erling Smørgrav for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) { 322462c32cbSDag-Erling Smørgrav rdata_digest_type = dtype; 323d95e11bfSDag-Erling Smørgrav if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, 324d95e11bfSDag-Erling Smørgrav &rdata_digest, &rdata_digest_len, key)) { 325462c32cbSDag-Erling Smørgrav if (generic) { 326462c32cbSDag-Erling Smørgrav fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", 327462c32cbSDag-Erling Smørgrav hostname, DNS_RDATATYPE_SSHFP, 328462c32cbSDag-Erling Smørgrav 2 + rdata_digest_len, 329d95e11bfSDag-Erling Smørgrav rdata_pubkey_algorithm, rdata_digest_type); 330462c32cbSDag-Erling Smørgrav } else { 331d95e11bfSDag-Erling Smørgrav fprintf(f, "%s IN SSHFP %d %d ", hostname, 332d95e11bfSDag-Erling Smørgrav rdata_pubkey_algorithm, rdata_digest_type); 333462c32cbSDag-Erling Smørgrav } 334d95e11bfSDag-Erling Smørgrav for (i = 0; i < rdata_digest_len; i++) 335d95e11bfSDag-Erling Smørgrav fprintf(f, "%02x", rdata_digest[i]); 336d95e11bfSDag-Erling Smørgrav fprintf(f, "\n"); 337e4a9863fSDag-Erling Smørgrav free(rdata_digest); /* from key_fingerprint_raw() */ 338d95e11bfSDag-Erling Smørgrav success = 1; 339462c32cbSDag-Erling Smørgrav } 340462c32cbSDag-Erling Smørgrav } 341462c32cbSDag-Erling Smørgrav 342462c32cbSDag-Erling Smørgrav /* No SSHFP record was generated at all */ 343462c32cbSDag-Erling Smørgrav if (success == 0) { 344462c32cbSDag-Erling Smørgrav error("%s: unsupported algorithm and/or digest_type", __func__); 345d95e11bfSDag-Erling Smørgrav } 346d95e11bfSDag-Erling Smørgrav 347d95e11bfSDag-Erling Smørgrav return success; 348d95e11bfSDag-Erling Smørgrav } 349