tsig.c revision 238104
1238104Sdes/* 2238104Sdes * tsig.c 3238104Sdes * 4238104Sdes * contains the functions needed for TSIG [RFC2845] 5238104Sdes * 6238104Sdes * (c) 2005-2006 NLnet Labs 7238104Sdes * See the file LICENSE for the license 8238104Sdes */ 9238104Sdes 10238104Sdes#include <ldns/config.h> 11238104Sdes 12238104Sdes#include <ldns/ldns.h> 13238104Sdes 14238104Sdes#include <strings.h> 15238104Sdes 16238104Sdes#ifdef HAVE_SSL 17238104Sdes#include <openssl/hmac.h> 18238104Sdes#include <openssl/md5.h> 19238104Sdes#endif /* HAVE_SSL */ 20238104Sdes 21238104Sdeschar * 22238104Sdesldns_tsig_algorithm(ldns_tsig_credentials *tc) 23238104Sdes{ 24238104Sdes return tc->algorithm; 25238104Sdes} 26238104Sdes 27238104Sdeschar * 28238104Sdesldns_tsig_keyname(ldns_tsig_credentials *tc) 29238104Sdes{ 30238104Sdes return tc->keyname; 31238104Sdes} 32238104Sdes 33238104Sdeschar * 34238104Sdesldns_tsig_keydata(ldns_tsig_credentials *tc) 35238104Sdes{ 36238104Sdes return tc->keydata; 37238104Sdes} 38238104Sdes 39238104Sdeschar * 40238104Sdesldns_tsig_keyname_clone(ldns_tsig_credentials *tc) 41238104Sdes{ 42238104Sdes return strdup(tc->keyname); 43238104Sdes} 44238104Sdes 45238104Sdeschar * 46238104Sdesldns_tsig_keydata_clone(ldns_tsig_credentials *tc) 47238104Sdes{ 48238104Sdes return strdup(tc->keydata); 49238104Sdes} 50238104Sdes 51238104Sdes/* 52238104Sdes * Makes an exact copy of the wire, but with the tsig rr removed 53238104Sdes */ 54238104Sdesuint8_t * 55238104Sdesldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len) 56238104Sdes{ 57238104Sdes uint8_t *wire2 = NULL; 58238104Sdes uint16_t qd_count; 59238104Sdes uint16_t an_count; 60238104Sdes uint16_t ns_count; 61238104Sdes uint16_t ar_count; 62238104Sdes ldns_rr *rr; 63238104Sdes 64238104Sdes size_t pos; 65238104Sdes uint16_t i; 66238104Sdes 67238104Sdes ldns_status status; 68238104Sdes 69238104Sdes if(wire_len < LDNS_HEADER_SIZE) { 70238104Sdes return NULL; 71238104Sdes } 72238104Sdes /* fake parse the wire */ 73238104Sdes qd_count = LDNS_QDCOUNT(wire); 74238104Sdes an_count = LDNS_ANCOUNT(wire); 75238104Sdes ns_count = LDNS_NSCOUNT(wire); 76238104Sdes ar_count = LDNS_ARCOUNT(wire); 77238104Sdes 78238104Sdes if (ar_count > 0) { 79238104Sdes ar_count--; 80238104Sdes } else { 81238104Sdes return NULL; 82238104Sdes } 83238104Sdes 84238104Sdes pos = LDNS_HEADER_SIZE; 85238104Sdes 86238104Sdes for (i = 0; i < qd_count; i++) { 87238104Sdes status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION); 88238104Sdes if (status != LDNS_STATUS_OK) { 89238104Sdes return NULL; 90238104Sdes } 91238104Sdes ldns_rr_free(rr); 92238104Sdes } 93238104Sdes 94238104Sdes for (i = 0; i < an_count; i++) { 95238104Sdes status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER); 96238104Sdes if (status != LDNS_STATUS_OK) { 97238104Sdes return NULL; 98238104Sdes } 99238104Sdes ldns_rr_free(rr); 100238104Sdes } 101238104Sdes 102238104Sdes for (i = 0; i < ns_count; i++) { 103238104Sdes status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY); 104238104Sdes if (status != LDNS_STATUS_OK) { 105238104Sdes return NULL; 106238104Sdes } 107238104Sdes ldns_rr_free(rr); 108238104Sdes } 109238104Sdes 110238104Sdes for (i = 0; i < ar_count; i++) { 111238104Sdes status = ldns_wire2rr(&rr, wire, wire_len, &pos, 112238104Sdes LDNS_SECTION_ADDITIONAL); 113238104Sdes if (status != LDNS_STATUS_OK) { 114238104Sdes return NULL; 115238104Sdes } 116238104Sdes ldns_rr_free(rr); 117238104Sdes } 118238104Sdes 119238104Sdes *result_len = pos; 120238104Sdes wire2 = LDNS_XMALLOC(uint8_t, *result_len); 121238104Sdes if(!wire2) { 122238104Sdes return NULL; 123238104Sdes } 124238104Sdes memcpy(wire2, wire, *result_len); 125238104Sdes 126238104Sdes ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count); 127238104Sdes 128238104Sdes return wire2; 129238104Sdes} 130238104Sdes 131238104Sdes#ifdef HAVE_SSL 132238104Sdesstatic const EVP_MD * 133238104Sdesldns_digest_function(char *name) 134238104Sdes{ 135238104Sdes /* these are the mandatory algorithms from RFC4635 */ 136238104Sdes /* The optional algorithms are not yet implemented */ 137238104Sdes if (strlen(name) == 12 138238104Sdes && strncasecmp(name, "hmac-sha256.", 11) == 0) { 139238104Sdes#ifdef HAVE_EVP_SHA256 140238104Sdes return EVP_sha256(); 141238104Sdes#else 142238104Sdes return NULL; 143238104Sdes#endif 144238104Sdes } else if (strlen(name) == 10 145238104Sdes && strncasecmp(name, "hmac-sha1.", 9) == 0) { 146238104Sdes return EVP_sha1(); 147238104Sdes } else if (strlen(name) == 25 148238104Sdes && strncasecmp(name, "hmac-md5.sig-alg.reg.int.", 25) 149238104Sdes == 0) { 150238104Sdes return EVP_md5(); 151238104Sdes } else { 152238104Sdes return NULL; 153238104Sdes } 154238104Sdes} 155238104Sdes#endif 156238104Sdes 157238104Sdes#ifdef HAVE_SSL 158238104Sdesstatic ldns_status 159238104Sdesldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, 160238104Sdes const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf, 161238104Sdes ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf, 162238104Sdes ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only) 163238104Sdes{ 164238104Sdes ldns_status status; 165238104Sdes char *wireformat; 166238104Sdes int wiresize; 167238104Sdes unsigned char *mac_bytes = NULL; 168238104Sdes unsigned char *key_bytes = NULL; 169238104Sdes int key_size; 170238104Sdes const EVP_MD *digester; 171238104Sdes char *algorithm_name = NULL; 172238104Sdes unsigned int md_len = EVP_MAX_MD_SIZE; 173238104Sdes ldns_rdf *result = NULL; 174238104Sdes ldns_buffer *data_buffer = NULL; 175238104Sdes ldns_rdf *canonical_key_name_rdf = NULL; 176238104Sdes ldns_rdf *canonical_algorithm_rdf = NULL; 177238104Sdes 178238104Sdes if (key_name_rdf == NULL || algorithm_rdf == NULL) { 179238104Sdes return LDNS_STATUS_NULL; 180238104Sdes } 181238104Sdes canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); 182238104Sdes canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); 183238104Sdes 184238104Sdes if (canonical_key_name_rdf == NULL 185238104Sdes || canonical_algorithm_rdf == NULL) { 186238104Sdes return LDNS_STATUS_MEM_ERR; 187238104Sdes } 188238104Sdes /* 189238104Sdes * prepare the digestable information 190238104Sdes */ 191238104Sdes data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 192238104Sdes if (!data_buffer) { 193238104Sdes status = LDNS_STATUS_MEM_ERR; 194238104Sdes goto clean; 195238104Sdes } 196238104Sdes /* if orig_mac is not NULL, add it too */ 197238104Sdes if (orig_mac_rdf) { 198238104Sdes (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); 199238104Sdes } 200238104Sdes ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); 201238104Sdes if (!tsig_timers_only) { 202238104Sdes ldns_dname2canonical(canonical_key_name_rdf); 203238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, 204238104Sdes canonical_key_name_rdf); 205238104Sdes ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); 206238104Sdes ldns_buffer_write_u32(data_buffer, 0); 207238104Sdes ldns_dname2canonical(canonical_algorithm_rdf); 208238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, 209238104Sdes canonical_algorithm_rdf); 210238104Sdes } 211238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); 212238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); 213238104Sdes if (!tsig_timers_only) { 214238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); 215238104Sdes (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); 216238104Sdes } 217238104Sdes 218238104Sdes wireformat = (char *) data_buffer->_data; 219238104Sdes wiresize = (int) ldns_buffer_position(data_buffer); 220238104Sdes 221238104Sdes algorithm_name = ldns_rdf2str(algorithm_rdf); 222238104Sdes if(!algorithm_name) { 223238104Sdes status = LDNS_STATUS_MEM_ERR; 224238104Sdes goto clean; 225238104Sdes } 226238104Sdes 227238104Sdes /* prepare the key */ 228238104Sdes key_bytes = LDNS_XMALLOC(unsigned char, 229238104Sdes ldns_b64_pton_calculate_size(strlen(key_data))); 230238104Sdes if(!key_bytes) { 231238104Sdes status = LDNS_STATUS_MEM_ERR; 232238104Sdes goto clean; 233238104Sdes } 234238104Sdes key_size = ldns_b64_pton(key_data, key_bytes, 235238104Sdes ldns_b64_pton_calculate_size(strlen(key_data))); 236238104Sdes if (key_size < 0) { 237238104Sdes status = LDNS_STATUS_INVALID_B64; 238238104Sdes goto clean; 239238104Sdes } 240238104Sdes /* hmac it */ 241238104Sdes /* 2 spare bytes for the length */ 242238104Sdes mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); 243238104Sdes if(!mac_bytes) { 244238104Sdes status = LDNS_STATUS_MEM_ERR; 245238104Sdes goto clean; 246238104Sdes } 247238104Sdes memset(mac_bytes, 0, md_len+2); 248238104Sdes 249238104Sdes digester = ldns_digest_function(algorithm_name); 250238104Sdes 251238104Sdes if (digester) { 252238104Sdes (void) HMAC(digester, key_bytes, key_size, (void *)wireformat, 253238104Sdes (size_t) wiresize, mac_bytes + 2, &md_len); 254238104Sdes 255238104Sdes ldns_write_uint16(mac_bytes, md_len); 256238104Sdes result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, 257238104Sdes mac_bytes); 258238104Sdes } else { 259238104Sdes status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 260238104Sdes goto clean; 261238104Sdes } 262238104Sdes *tsig_mac = result; 263238104Sdes status = LDNS_STATUS_OK; 264238104Sdes clean: 265238104Sdes LDNS_FREE(mac_bytes); 266238104Sdes LDNS_FREE(key_bytes); 267238104Sdes LDNS_FREE(algorithm_name); 268238104Sdes ldns_buffer_free(data_buffer); 269238104Sdes ldns_rdf_free(canonical_algorithm_rdf); 270238104Sdes ldns_rdf_free(canonical_key_name_rdf); 271238104Sdes return status; 272238104Sdes} 273238104Sdes#endif /* HAVE_SSL */ 274238104Sdes 275238104Sdes 276238104Sdes#ifdef HAVE_SSL 277238104Sdesbool 278238104Sdesldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name, 279238104Sdes const char *key_data, ldns_rdf *orig_mac_rdf) 280238104Sdes{ 281238104Sdes return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0); 282238104Sdes} 283238104Sdes 284238104Sdesbool 285238104Sdesldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name, 286238104Sdes const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only) 287238104Sdes{ 288238104Sdes ldns_rdf *fudge_rdf; 289238104Sdes ldns_rdf *algorithm_rdf; 290238104Sdes ldns_rdf *time_signed_rdf; 291238104Sdes ldns_rdf *orig_id_rdf; 292238104Sdes ldns_rdf *error_rdf; 293238104Sdes ldns_rdf *other_data_rdf; 294238104Sdes ldns_rdf *pkt_mac_rdf; 295238104Sdes ldns_rdf *my_mac_rdf; 296238104Sdes ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 297238104Sdes uint16_t pkt_id, orig_pkt_id; 298238104Sdes ldns_status status; 299238104Sdes 300238104Sdes uint8_t *prepared_wire = NULL; 301238104Sdes size_t prepared_wire_size = 0; 302238104Sdes 303238104Sdes ldns_rr *orig_tsig = ldns_pkt_tsig(pkt); 304238104Sdes 305238104Sdes if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) { 306238104Sdes ldns_rdf_deep_free(key_name_rdf); 307238104Sdes return false; 308238104Sdes } 309238104Sdes algorithm_rdf = ldns_rr_rdf(orig_tsig, 0); 310238104Sdes time_signed_rdf = ldns_rr_rdf(orig_tsig, 1); 311238104Sdes fudge_rdf = ldns_rr_rdf(orig_tsig, 2); 312238104Sdes pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3); 313238104Sdes orig_id_rdf = ldns_rr_rdf(orig_tsig, 4); 314238104Sdes error_rdf = ldns_rr_rdf(orig_tsig, 5); 315238104Sdes other_data_rdf = ldns_rr_rdf(orig_tsig, 6); 316238104Sdes 317238104Sdes /* remove temporarily */ 318238104Sdes ldns_pkt_set_tsig(pkt, NULL); 319238104Sdes /* temporarily change the id to the original id */ 320238104Sdes pkt_id = ldns_pkt_id(pkt); 321238104Sdes orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf); 322238104Sdes ldns_pkt_set_id(pkt, orig_pkt_id); 323238104Sdes 324238104Sdes prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size); 325238104Sdes 326238104Sdes status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size, 327238104Sdes key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 328238104Sdes time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only); 329238104Sdes 330238104Sdes LDNS_FREE(prepared_wire); 331238104Sdes 332238104Sdes if (status != LDNS_STATUS_OK) { 333238104Sdes ldns_rdf_deep_free(key_name_rdf); 334238104Sdes return false; 335238104Sdes } 336238104Sdes /* Put back the values */ 337238104Sdes ldns_pkt_set_tsig(pkt, orig_tsig); 338238104Sdes ldns_pkt_set_id(pkt, pkt_id); 339238104Sdes 340238104Sdes ldns_rdf_deep_free(key_name_rdf); 341238104Sdes 342238104Sdes if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) { 343238104Sdes ldns_rdf_deep_free(my_mac_rdf); 344238104Sdes return true; 345238104Sdes } else { 346238104Sdes ldns_rdf_deep_free(my_mac_rdf); 347238104Sdes return false; 348238104Sdes } 349238104Sdes} 350238104Sdes#endif /* HAVE_SSL */ 351238104Sdes 352238104Sdes#ifdef HAVE_SSL 353238104Sdesldns_status 354238104Sdesldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, 355238104Sdes uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) 356238104Sdes{ 357238104Sdes return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0); 358238104Sdes} 359238104Sdes 360238104Sdesldns_status 361238104Sdesldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, 362238104Sdes uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only) 363238104Sdes{ 364238104Sdes ldns_rr *tsig_rr; 365238104Sdes ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 366238104Sdes ldns_rdf *fudge_rdf = NULL; 367238104Sdes ldns_rdf *orig_id_rdf = NULL; 368238104Sdes ldns_rdf *algorithm_rdf; 369238104Sdes ldns_rdf *error_rdf = NULL; 370238104Sdes ldns_rdf *mac_rdf = NULL; 371238104Sdes ldns_rdf *other_data_rdf = NULL; 372238104Sdes 373238104Sdes ldns_status status = LDNS_STATUS_OK; 374238104Sdes 375238104Sdes uint8_t *pkt_wire = NULL; 376238104Sdes size_t pkt_wire_len; 377238104Sdes 378238104Sdes struct timeval tv_time_signed; 379238104Sdes uint8_t *time_signed = NULL; 380238104Sdes ldns_rdf *time_signed_rdf = NULL; 381238104Sdes 382238104Sdes algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name); 383238104Sdes if(!key_name_rdf || !algorithm_rdf) { 384238104Sdes status = LDNS_STATUS_MEM_ERR; 385238104Sdes goto clean; 386238104Sdes } 387238104Sdes 388238104Sdes /* eww don't have create tsigtime rdf yet :( */ 389238104Sdes /* bleh :p */ 390238104Sdes if (gettimeofday(&tv_time_signed, NULL) == 0) { 391238104Sdes time_signed = LDNS_XMALLOC(uint8_t, 6); 392238104Sdes if(!time_signed) { 393238104Sdes status = LDNS_STATUS_MEM_ERR; 394238104Sdes goto clean; 395238104Sdes } 396238104Sdes ldns_write_uint64_as_uint48(time_signed, 397238104Sdes (uint64_t)tv_time_signed.tv_sec); 398238104Sdes } else { 399238104Sdes status = LDNS_STATUS_INTERNAL_ERR; 400238104Sdes goto clean; 401238104Sdes } 402238104Sdes 403238104Sdes time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed); 404238104Sdes if(!time_signed_rdf) { 405238104Sdes LDNS_FREE(time_signed); 406238104Sdes status = LDNS_STATUS_MEM_ERR; 407238104Sdes goto clean; 408238104Sdes } 409238104Sdes 410238104Sdes fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge); 411238104Sdes 412238104Sdes orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt)); 413238104Sdes 414238104Sdes error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0); 415238104Sdes 416238104Sdes other_data_rdf = ldns_native2rdf_int16_data(0, NULL); 417238104Sdes 418238104Sdes if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) { 419238104Sdes status = LDNS_STATUS_MEM_ERR; 420238104Sdes goto clean; 421238104Sdes } 422238104Sdes 423238104Sdes if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) { 424238104Sdes status = LDNS_STATUS_ERR; 425238104Sdes goto clean; 426238104Sdes } 427238104Sdes 428238104Sdes status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len, 429238104Sdes key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 430238104Sdes time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only); 431238104Sdes 432238104Sdes if (!mac_rdf) { 433238104Sdes goto clean; 434238104Sdes } 435238104Sdes 436238104Sdes LDNS_FREE(pkt_wire); 437238104Sdes 438238104Sdes /* Create the TSIG RR */ 439238104Sdes tsig_rr = ldns_rr_new(); 440238104Sdes if(!tsig_rr) { 441238104Sdes status = LDNS_STATUS_MEM_ERR; 442238104Sdes goto clean; 443238104Sdes } 444238104Sdes ldns_rr_set_owner(tsig_rr, key_name_rdf); 445238104Sdes ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY); 446238104Sdes ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG); 447238104Sdes ldns_rr_set_ttl(tsig_rr, 0); 448238104Sdes 449238104Sdes ldns_rr_push_rdf(tsig_rr, algorithm_rdf); 450238104Sdes ldns_rr_push_rdf(tsig_rr, time_signed_rdf); 451238104Sdes ldns_rr_push_rdf(tsig_rr, fudge_rdf); 452238104Sdes ldns_rr_push_rdf(tsig_rr, mac_rdf); 453238104Sdes ldns_rr_push_rdf(tsig_rr, orig_id_rdf); 454238104Sdes ldns_rr_push_rdf(tsig_rr, error_rdf); 455238104Sdes ldns_rr_push_rdf(tsig_rr, other_data_rdf); 456238104Sdes 457238104Sdes ldns_pkt_set_tsig(pkt, tsig_rr); 458238104Sdes 459238104Sdes return status; 460238104Sdes 461238104Sdes clean: 462238104Sdes LDNS_FREE(pkt_wire); 463238104Sdes ldns_rdf_free(key_name_rdf); 464238104Sdes ldns_rdf_free(algorithm_rdf); 465238104Sdes ldns_rdf_free(time_signed_rdf); 466238104Sdes ldns_rdf_free(fudge_rdf); 467238104Sdes ldns_rdf_free(orig_id_rdf); 468238104Sdes ldns_rdf_free(error_rdf); 469238104Sdes ldns_rdf_free(other_data_rdf); 470238104Sdes return status; 471238104Sdes} 472238104Sdes#endif /* HAVE_SSL */ 473