1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * tsig.c 3825eb42bSJan Lentfer * 4825eb42bSJan Lentfer * contains the functions needed for TSIG [RFC2845] 5825eb42bSJan Lentfer * 6825eb42bSJan Lentfer * (c) 2005-2006 NLnet Labs 7825eb42bSJan Lentfer * See the file LICENSE for the license 8825eb42bSJan Lentfer */ 9825eb42bSJan Lentfer 10825eb42bSJan Lentfer #include <ldns/config.h> 11825eb42bSJan Lentfer 12825eb42bSJan Lentfer #include <ldns/ldns.h> 13825eb42bSJan Lentfer 14825eb42bSJan Lentfer #include <strings.h> 15825eb42bSJan Lentfer 16825eb42bSJan Lentfer #ifdef HAVE_SSL 17825eb42bSJan Lentfer #include <openssl/hmac.h> 18825eb42bSJan Lentfer #include <openssl/md5.h> 19825eb42bSJan Lentfer #endif /* HAVE_SSL */ 20825eb42bSJan Lentfer 21825eb42bSJan Lentfer char * 22825eb42bSJan Lentfer ldns_tsig_algorithm(ldns_tsig_credentials *tc) 23825eb42bSJan Lentfer { 24825eb42bSJan Lentfer return tc->algorithm; 25825eb42bSJan Lentfer } 26825eb42bSJan Lentfer 27825eb42bSJan Lentfer char * 28825eb42bSJan Lentfer ldns_tsig_keyname(ldns_tsig_credentials *tc) 29825eb42bSJan Lentfer { 30825eb42bSJan Lentfer return tc->keyname; 31825eb42bSJan Lentfer } 32825eb42bSJan Lentfer 33825eb42bSJan Lentfer char * 34825eb42bSJan Lentfer ldns_tsig_keydata(ldns_tsig_credentials *tc) 35825eb42bSJan Lentfer { 36825eb42bSJan Lentfer return tc->keydata; 37825eb42bSJan Lentfer } 38825eb42bSJan Lentfer 39825eb42bSJan Lentfer char * 40825eb42bSJan Lentfer ldns_tsig_keyname_clone(ldns_tsig_credentials *tc) 41825eb42bSJan Lentfer { 42825eb42bSJan Lentfer return strdup(tc->keyname); 43825eb42bSJan Lentfer } 44825eb42bSJan Lentfer 45825eb42bSJan Lentfer char * 46825eb42bSJan Lentfer ldns_tsig_keydata_clone(ldns_tsig_credentials *tc) 47825eb42bSJan Lentfer { 48825eb42bSJan Lentfer return strdup(tc->keydata); 49825eb42bSJan Lentfer } 50825eb42bSJan Lentfer 51825eb42bSJan Lentfer /* 52825eb42bSJan Lentfer * Makes an exact copy of the wire, but with the tsig rr removed 53825eb42bSJan Lentfer */ 54825eb42bSJan Lentfer uint8_t * 55825eb42bSJan Lentfer ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len) 56825eb42bSJan Lentfer { 57825eb42bSJan Lentfer uint8_t *wire2 = NULL; 58825eb42bSJan Lentfer uint16_t qd_count; 59825eb42bSJan Lentfer uint16_t an_count; 60825eb42bSJan Lentfer uint16_t ns_count; 61825eb42bSJan Lentfer uint16_t ar_count; 62825eb42bSJan Lentfer ldns_rr *rr; 63825eb42bSJan Lentfer 64825eb42bSJan Lentfer size_t pos; 65825eb42bSJan Lentfer uint16_t i; 66825eb42bSJan Lentfer 67825eb42bSJan Lentfer ldns_status status; 68825eb42bSJan Lentfer 69fd185f4dSJan Lentfer if(wire_len < LDNS_HEADER_SIZE) { 70fd185f4dSJan Lentfer return NULL; 71fd185f4dSJan Lentfer } 72825eb42bSJan Lentfer /* fake parse the wire */ 73825eb42bSJan Lentfer qd_count = LDNS_QDCOUNT(wire); 74825eb42bSJan Lentfer an_count = LDNS_ANCOUNT(wire); 75825eb42bSJan Lentfer ns_count = LDNS_NSCOUNT(wire); 76825eb42bSJan Lentfer ar_count = LDNS_ARCOUNT(wire); 77825eb42bSJan Lentfer 78825eb42bSJan Lentfer if (ar_count > 0) { 79825eb42bSJan Lentfer ar_count--; 80825eb42bSJan Lentfer } else { 81825eb42bSJan Lentfer return NULL; 82825eb42bSJan Lentfer } 83825eb42bSJan Lentfer 84825eb42bSJan Lentfer pos = LDNS_HEADER_SIZE; 85825eb42bSJan Lentfer 86825eb42bSJan Lentfer for (i = 0; i < qd_count; i++) { 87825eb42bSJan Lentfer status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION); 88825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 89825eb42bSJan Lentfer return NULL; 90825eb42bSJan Lentfer } 91825eb42bSJan Lentfer ldns_rr_free(rr); 92825eb42bSJan Lentfer } 93825eb42bSJan Lentfer 94825eb42bSJan Lentfer for (i = 0; i < an_count; i++) { 95825eb42bSJan Lentfer status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER); 96825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 97825eb42bSJan Lentfer return NULL; 98825eb42bSJan Lentfer } 99825eb42bSJan Lentfer ldns_rr_free(rr); 100825eb42bSJan Lentfer } 101825eb42bSJan Lentfer 102825eb42bSJan Lentfer for (i = 0; i < ns_count; i++) { 103825eb42bSJan Lentfer status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY); 104825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 105825eb42bSJan Lentfer return NULL; 106825eb42bSJan Lentfer } 107825eb42bSJan Lentfer ldns_rr_free(rr); 108825eb42bSJan Lentfer } 109825eb42bSJan Lentfer 110825eb42bSJan Lentfer for (i = 0; i < ar_count; i++) { 111825eb42bSJan Lentfer status = ldns_wire2rr(&rr, wire, wire_len, &pos, 112825eb42bSJan Lentfer LDNS_SECTION_ADDITIONAL); 113825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 114825eb42bSJan Lentfer return NULL; 115825eb42bSJan Lentfer } 116825eb42bSJan Lentfer ldns_rr_free(rr); 117825eb42bSJan Lentfer } 118825eb42bSJan Lentfer 119825eb42bSJan Lentfer *result_len = pos; 120825eb42bSJan Lentfer wire2 = LDNS_XMALLOC(uint8_t, *result_len); 121fd185f4dSJan Lentfer if(!wire2) { 122fd185f4dSJan Lentfer return NULL; 123fd185f4dSJan Lentfer } 124825eb42bSJan Lentfer memcpy(wire2, wire, *result_len); 125825eb42bSJan Lentfer 126825eb42bSJan Lentfer ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count); 127825eb42bSJan Lentfer 128825eb42bSJan Lentfer return wire2; 129825eb42bSJan Lentfer } 130825eb42bSJan Lentfer 131825eb42bSJan Lentfer #ifdef HAVE_SSL 132825eb42bSJan Lentfer static const EVP_MD * 133825eb42bSJan Lentfer ldns_digest_function(char *name) 134825eb42bSJan Lentfer { 135825eb42bSJan Lentfer /* these are the mandatory algorithms from RFC4635 */ 136825eb42bSJan Lentfer /* The optional algorithms are not yet implemented */ 137b5dedccaSJan Lentfer if (strlen(name) == 12 138b5dedccaSJan Lentfer && strncasecmp(name, "hmac-sha256.", 11) == 0) { 139825eb42bSJan Lentfer #ifdef HAVE_EVP_SHA256 140825eb42bSJan Lentfer return EVP_sha256(); 141825eb42bSJan Lentfer #else 142825eb42bSJan Lentfer return NULL; 143825eb42bSJan Lentfer #endif 144b5dedccaSJan Lentfer } else if (strlen(name) == 10 145b5dedccaSJan Lentfer && strncasecmp(name, "hmac-sha1.", 9) == 0) { 146825eb42bSJan Lentfer return EVP_sha1(); 147b5dedccaSJan Lentfer } else if (strlen(name) == 25 148b5dedccaSJan Lentfer && strncasecmp(name, "hmac-md5.sig-alg.reg.int.", 25) 149b5dedccaSJan Lentfer == 0) { 150825eb42bSJan Lentfer return EVP_md5(); 151b5dedccaSJan Lentfer } else { 152825eb42bSJan Lentfer return NULL; 153825eb42bSJan Lentfer } 154b5dedccaSJan Lentfer } 155825eb42bSJan Lentfer #endif 156825eb42bSJan Lentfer 157825eb42bSJan Lentfer #ifdef HAVE_SSL 158825eb42bSJan Lentfer static ldns_status 159825eb42bSJan Lentfer ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, 160825eb42bSJan Lentfer const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf, 161825eb42bSJan Lentfer ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf, 162ac996e71SJan Lentfer ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only) 163825eb42bSJan Lentfer { 164b5dedccaSJan Lentfer ldns_status status; 165825eb42bSJan Lentfer char *wireformat; 166825eb42bSJan Lentfer int wiresize; 167b5dedccaSJan Lentfer unsigned char *mac_bytes = NULL; 168b5dedccaSJan Lentfer unsigned char *key_bytes = NULL; 169825eb42bSJan Lentfer int key_size; 170825eb42bSJan Lentfer const EVP_MD *digester; 171b5dedccaSJan Lentfer char *algorithm_name = NULL; 172825eb42bSJan Lentfer unsigned int md_len = EVP_MAX_MD_SIZE; 173825eb42bSJan Lentfer ldns_rdf *result = NULL; 174825eb42bSJan Lentfer ldns_buffer *data_buffer = NULL; 175b5dedccaSJan Lentfer ldns_rdf *canonical_key_name_rdf = NULL; 176b5dedccaSJan Lentfer ldns_rdf *canonical_algorithm_rdf = NULL; 177825eb42bSJan Lentfer 178b5dedccaSJan Lentfer if (key_name_rdf == NULL || algorithm_rdf == NULL) { 179b5dedccaSJan Lentfer return LDNS_STATUS_NULL; 180b5dedccaSJan Lentfer } 181b5dedccaSJan Lentfer canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); 182*d1b2b5caSJohn Marino if (canonical_key_name_rdf == NULL) { 183*d1b2b5caSJohn Marino return LDNS_STATUS_MEM_ERR; 184*d1b2b5caSJohn Marino } 185b5dedccaSJan Lentfer canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); 186*d1b2b5caSJohn Marino if (canonical_algorithm_rdf == NULL) { 187*d1b2b5caSJohn Marino ldns_rdf_deep_free(canonical_key_name_rdf); 188b5dedccaSJan Lentfer return LDNS_STATUS_MEM_ERR; 189b5dedccaSJan Lentfer } 190825eb42bSJan Lentfer /* 191825eb42bSJan Lentfer * prepare the digestable information 192825eb42bSJan Lentfer */ 193825eb42bSJan Lentfer data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 194ac996e71SJan Lentfer if (!data_buffer) { 195b5dedccaSJan Lentfer status = LDNS_STATUS_MEM_ERR; 196b5dedccaSJan Lentfer goto clean; 197ac996e71SJan Lentfer } 198825eb42bSJan Lentfer /* if orig_mac is not NULL, add it too */ 199825eb42bSJan Lentfer if (orig_mac_rdf) { 200825eb42bSJan Lentfer (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); 201825eb42bSJan Lentfer } 202825eb42bSJan Lentfer ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); 203ac996e71SJan Lentfer if (!tsig_timers_only) { 204b5dedccaSJan Lentfer ldns_dname2canonical(canonical_key_name_rdf); 205b5dedccaSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, 206b5dedccaSJan Lentfer canonical_key_name_rdf); 207825eb42bSJan Lentfer ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); 208825eb42bSJan Lentfer ldns_buffer_write_u32(data_buffer, 0); 209b5dedccaSJan Lentfer ldns_dname2canonical(canonical_algorithm_rdf); 210b5dedccaSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, 211b5dedccaSJan Lentfer canonical_algorithm_rdf); 212ac996e71SJan Lentfer } 213825eb42bSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); 214825eb42bSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); 215ac996e71SJan Lentfer if (!tsig_timers_only) { 216825eb42bSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); 217825eb42bSJan Lentfer (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); 218ac996e71SJan Lentfer } 219825eb42bSJan Lentfer 220825eb42bSJan Lentfer wireformat = (char *) data_buffer->_data; 221825eb42bSJan Lentfer wiresize = (int) ldns_buffer_position(data_buffer); 222825eb42bSJan Lentfer 223825eb42bSJan Lentfer algorithm_name = ldns_rdf2str(algorithm_rdf); 224ac996e71SJan Lentfer if(!algorithm_name) { 225b5dedccaSJan Lentfer status = LDNS_STATUS_MEM_ERR; 226b5dedccaSJan Lentfer goto clean; 227ac996e71SJan Lentfer } 228825eb42bSJan Lentfer 229825eb42bSJan Lentfer /* prepare the key */ 230825eb42bSJan Lentfer key_bytes = LDNS_XMALLOC(unsigned char, 231825eb42bSJan Lentfer ldns_b64_pton_calculate_size(strlen(key_data))); 232ac996e71SJan Lentfer if(!key_bytes) { 233b5dedccaSJan Lentfer status = LDNS_STATUS_MEM_ERR; 234b5dedccaSJan Lentfer goto clean; 235ac996e71SJan Lentfer } 236ac996e71SJan Lentfer key_size = ldns_b64_pton(key_data, key_bytes, 237ac996e71SJan Lentfer ldns_b64_pton_calculate_size(strlen(key_data))); 238825eb42bSJan Lentfer if (key_size < 0) { 239b5dedccaSJan Lentfer status = LDNS_STATUS_INVALID_B64; 240b5dedccaSJan Lentfer goto clean; 241825eb42bSJan Lentfer } 242825eb42bSJan Lentfer /* hmac it */ 243825eb42bSJan Lentfer /* 2 spare bytes for the length */ 244ac996e71SJan Lentfer mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); 245ac996e71SJan Lentfer if(!mac_bytes) { 246b5dedccaSJan Lentfer status = LDNS_STATUS_MEM_ERR; 247b5dedccaSJan Lentfer goto clean; 248ac996e71SJan Lentfer } 249ac996e71SJan Lentfer memset(mac_bytes, 0, md_len+2); 250825eb42bSJan Lentfer 251825eb42bSJan Lentfer digester = ldns_digest_function(algorithm_name); 252825eb42bSJan Lentfer 253825eb42bSJan Lentfer if (digester) { 254825eb42bSJan Lentfer (void) HMAC(digester, key_bytes, key_size, (void *)wireformat, 255825eb42bSJan Lentfer (size_t) wiresize, mac_bytes + 2, &md_len); 256825eb42bSJan Lentfer 257825eb42bSJan Lentfer ldns_write_uint16(mac_bytes, md_len); 258825eb42bSJan Lentfer result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, 259825eb42bSJan Lentfer mac_bytes); 260825eb42bSJan Lentfer } else { 261b5dedccaSJan Lentfer status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 262b5dedccaSJan Lentfer goto clean; 263825eb42bSJan Lentfer } 264b5dedccaSJan Lentfer *tsig_mac = result; 265b5dedccaSJan Lentfer status = LDNS_STATUS_OK; 266b5dedccaSJan Lentfer clean: 267825eb42bSJan Lentfer LDNS_FREE(mac_bytes); 268825eb42bSJan Lentfer LDNS_FREE(key_bytes); 269b5dedccaSJan Lentfer LDNS_FREE(algorithm_name); 270825eb42bSJan Lentfer ldns_buffer_free(data_buffer); 271*d1b2b5caSJohn Marino ldns_rdf_deep_free(canonical_algorithm_rdf); 272*d1b2b5caSJohn Marino ldns_rdf_deep_free(canonical_key_name_rdf); 273b5dedccaSJan Lentfer return status; 274825eb42bSJan Lentfer } 275825eb42bSJan Lentfer #endif /* HAVE_SSL */ 276825eb42bSJan Lentfer 277825eb42bSJan Lentfer 278825eb42bSJan Lentfer #ifdef HAVE_SSL 279825eb42bSJan Lentfer bool 280ac996e71SJan Lentfer ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name, 281ac996e71SJan Lentfer const char *key_data, ldns_rdf *orig_mac_rdf) 282ac996e71SJan Lentfer { 283ac996e71SJan Lentfer return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0); 284ac996e71SJan Lentfer } 285ac996e71SJan Lentfer 286ac996e71SJan Lentfer bool 287ac996e71SJan Lentfer ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name, 288ac996e71SJan Lentfer const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only) 289825eb42bSJan Lentfer { 290825eb42bSJan Lentfer ldns_rdf *fudge_rdf; 291825eb42bSJan Lentfer ldns_rdf *algorithm_rdf; 292825eb42bSJan Lentfer ldns_rdf *time_signed_rdf; 293825eb42bSJan Lentfer ldns_rdf *orig_id_rdf; 294825eb42bSJan Lentfer ldns_rdf *error_rdf; 295825eb42bSJan Lentfer ldns_rdf *other_data_rdf; 296825eb42bSJan Lentfer ldns_rdf *pkt_mac_rdf; 297825eb42bSJan Lentfer ldns_rdf *my_mac_rdf; 298825eb42bSJan Lentfer ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 299825eb42bSJan Lentfer uint16_t pkt_id, orig_pkt_id; 300825eb42bSJan Lentfer ldns_status status; 301825eb42bSJan Lentfer 302825eb42bSJan Lentfer uint8_t *prepared_wire = NULL; 303825eb42bSJan Lentfer size_t prepared_wire_size = 0; 304825eb42bSJan Lentfer 305825eb42bSJan Lentfer ldns_rr *orig_tsig = ldns_pkt_tsig(pkt); 306825eb42bSJan Lentfer 307b5dedccaSJan Lentfer if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) { 308825eb42bSJan Lentfer ldns_rdf_deep_free(key_name_rdf); 309825eb42bSJan Lentfer return false; 310825eb42bSJan Lentfer } 311825eb42bSJan Lentfer algorithm_rdf = ldns_rr_rdf(orig_tsig, 0); 312825eb42bSJan Lentfer time_signed_rdf = ldns_rr_rdf(orig_tsig, 1); 313825eb42bSJan Lentfer fudge_rdf = ldns_rr_rdf(orig_tsig, 2); 314825eb42bSJan Lentfer pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3); 315825eb42bSJan Lentfer orig_id_rdf = ldns_rr_rdf(orig_tsig, 4); 316825eb42bSJan Lentfer error_rdf = ldns_rr_rdf(orig_tsig, 5); 317825eb42bSJan Lentfer other_data_rdf = ldns_rr_rdf(orig_tsig, 6); 318825eb42bSJan Lentfer 319825eb42bSJan Lentfer /* remove temporarily */ 320825eb42bSJan Lentfer ldns_pkt_set_tsig(pkt, NULL); 321825eb42bSJan Lentfer /* temporarily change the id to the original id */ 322825eb42bSJan Lentfer pkt_id = ldns_pkt_id(pkt); 323825eb42bSJan Lentfer orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf); 324825eb42bSJan Lentfer ldns_pkt_set_id(pkt, orig_pkt_id); 325825eb42bSJan Lentfer 326825eb42bSJan Lentfer prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size); 327825eb42bSJan Lentfer 328825eb42bSJan Lentfer status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size, 329825eb42bSJan Lentfer key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 330ac996e71SJan Lentfer time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only); 331825eb42bSJan Lentfer 332825eb42bSJan Lentfer LDNS_FREE(prepared_wire); 333825eb42bSJan Lentfer 334825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 335825eb42bSJan Lentfer ldns_rdf_deep_free(key_name_rdf); 336825eb42bSJan Lentfer return false; 337825eb42bSJan Lentfer } 338825eb42bSJan Lentfer /* Put back the values */ 339825eb42bSJan Lentfer ldns_pkt_set_tsig(pkt, orig_tsig); 340825eb42bSJan Lentfer ldns_pkt_set_id(pkt, pkt_id); 341825eb42bSJan Lentfer 342825eb42bSJan Lentfer ldns_rdf_deep_free(key_name_rdf); 343825eb42bSJan Lentfer 344825eb42bSJan Lentfer if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) { 345825eb42bSJan Lentfer ldns_rdf_deep_free(my_mac_rdf); 346825eb42bSJan Lentfer return true; 347825eb42bSJan Lentfer } else { 348825eb42bSJan Lentfer ldns_rdf_deep_free(my_mac_rdf); 349825eb42bSJan Lentfer return false; 350825eb42bSJan Lentfer } 351825eb42bSJan Lentfer } 352825eb42bSJan Lentfer #endif /* HAVE_SSL */ 353825eb42bSJan Lentfer 354825eb42bSJan Lentfer #ifdef HAVE_SSL 355825eb42bSJan Lentfer ldns_status 356825eb42bSJan Lentfer ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, 357825eb42bSJan Lentfer uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) 358825eb42bSJan Lentfer { 359ac996e71SJan Lentfer return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0); 360ac996e71SJan Lentfer } 361ac996e71SJan Lentfer 362ac996e71SJan Lentfer ldns_status 363ac996e71SJan Lentfer ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, 364ac996e71SJan Lentfer uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only) 365ac996e71SJan Lentfer { 366825eb42bSJan Lentfer ldns_rr *tsig_rr; 367825eb42bSJan Lentfer ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 368825eb42bSJan Lentfer ldns_rdf *fudge_rdf = NULL; 369825eb42bSJan Lentfer ldns_rdf *orig_id_rdf = NULL; 370825eb42bSJan Lentfer ldns_rdf *algorithm_rdf; 371825eb42bSJan Lentfer ldns_rdf *error_rdf = NULL; 372825eb42bSJan Lentfer ldns_rdf *mac_rdf = NULL; 373825eb42bSJan Lentfer ldns_rdf *other_data_rdf = NULL; 374825eb42bSJan Lentfer 375825eb42bSJan Lentfer ldns_status status = LDNS_STATUS_OK; 376825eb42bSJan Lentfer 377825eb42bSJan Lentfer uint8_t *pkt_wire = NULL; 378825eb42bSJan Lentfer size_t pkt_wire_len; 379825eb42bSJan Lentfer 380825eb42bSJan Lentfer struct timeval tv_time_signed; 381825eb42bSJan Lentfer uint8_t *time_signed = NULL; 382825eb42bSJan Lentfer ldns_rdf *time_signed_rdf = NULL; 383825eb42bSJan Lentfer 384825eb42bSJan Lentfer algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name); 385fd185f4dSJan Lentfer if(!key_name_rdf || !algorithm_rdf) { 386fd185f4dSJan Lentfer status = LDNS_STATUS_MEM_ERR; 387fd185f4dSJan Lentfer goto clean; 388fd185f4dSJan Lentfer } 389825eb42bSJan Lentfer 390825eb42bSJan Lentfer /* eww don't have create tsigtime rdf yet :( */ 391825eb42bSJan Lentfer /* bleh :p */ 392825eb42bSJan Lentfer if (gettimeofday(&tv_time_signed, NULL) == 0) { 393825eb42bSJan Lentfer time_signed = LDNS_XMALLOC(uint8_t, 6); 394fd185f4dSJan Lentfer if(!time_signed) { 395fd185f4dSJan Lentfer status = LDNS_STATUS_MEM_ERR; 396fd185f4dSJan Lentfer goto clean; 397fd185f4dSJan Lentfer } 398825eb42bSJan Lentfer ldns_write_uint64_as_uint48(time_signed, 399825eb42bSJan Lentfer (uint64_t)tv_time_signed.tv_sec); 400825eb42bSJan Lentfer } else { 401825eb42bSJan Lentfer status = LDNS_STATUS_INTERNAL_ERR; 402825eb42bSJan Lentfer goto clean; 403825eb42bSJan Lentfer } 404825eb42bSJan Lentfer 405825eb42bSJan Lentfer time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed); 406fd185f4dSJan Lentfer if(!time_signed_rdf) { 407fd185f4dSJan Lentfer LDNS_FREE(time_signed); 408fd185f4dSJan Lentfer status = LDNS_STATUS_MEM_ERR; 409fd185f4dSJan Lentfer goto clean; 410fd185f4dSJan Lentfer } 411825eb42bSJan Lentfer 412825eb42bSJan Lentfer fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge); 413825eb42bSJan Lentfer 414825eb42bSJan Lentfer orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt)); 415825eb42bSJan Lentfer 416825eb42bSJan Lentfer error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0); 417825eb42bSJan Lentfer 418825eb42bSJan Lentfer other_data_rdf = ldns_native2rdf_int16_data(0, NULL); 419825eb42bSJan Lentfer 420fd185f4dSJan Lentfer if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) { 421fd185f4dSJan Lentfer status = LDNS_STATUS_MEM_ERR; 422fd185f4dSJan Lentfer goto clean; 423fd185f4dSJan Lentfer } 424fd185f4dSJan Lentfer 425825eb42bSJan Lentfer if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) { 426825eb42bSJan Lentfer status = LDNS_STATUS_ERR; 427825eb42bSJan Lentfer goto clean; 428825eb42bSJan Lentfer } 429825eb42bSJan Lentfer 430825eb42bSJan Lentfer status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len, 431825eb42bSJan Lentfer key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 432ac996e71SJan Lentfer time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only); 433825eb42bSJan Lentfer 434825eb42bSJan Lentfer if (!mac_rdf) { 435825eb42bSJan Lentfer goto clean; 436825eb42bSJan Lentfer } 437825eb42bSJan Lentfer 438825eb42bSJan Lentfer LDNS_FREE(pkt_wire); 439825eb42bSJan Lentfer 440825eb42bSJan Lentfer /* Create the TSIG RR */ 441825eb42bSJan Lentfer tsig_rr = ldns_rr_new(); 442fd185f4dSJan Lentfer if(!tsig_rr) { 443fd185f4dSJan Lentfer status = LDNS_STATUS_MEM_ERR; 444fd185f4dSJan Lentfer goto clean; 445fd185f4dSJan Lentfer } 446825eb42bSJan Lentfer ldns_rr_set_owner(tsig_rr, key_name_rdf); 447825eb42bSJan Lentfer ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY); 448825eb42bSJan Lentfer ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG); 449825eb42bSJan Lentfer ldns_rr_set_ttl(tsig_rr, 0); 450825eb42bSJan Lentfer 451825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, algorithm_rdf); 452825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, time_signed_rdf); 453825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, fudge_rdf); 454825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, mac_rdf); 455825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, orig_id_rdf); 456825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, error_rdf); 457825eb42bSJan Lentfer ldns_rr_push_rdf(tsig_rr, other_data_rdf); 458825eb42bSJan Lentfer 459825eb42bSJan Lentfer ldns_pkt_set_tsig(pkt, tsig_rr); 460825eb42bSJan Lentfer 461825eb42bSJan Lentfer return status; 462825eb42bSJan Lentfer 463825eb42bSJan Lentfer clean: 464fd185f4dSJan Lentfer LDNS_FREE(pkt_wire); 465825eb42bSJan Lentfer ldns_rdf_free(key_name_rdf); 466825eb42bSJan Lentfer ldns_rdf_free(algorithm_rdf); 467825eb42bSJan Lentfer ldns_rdf_free(time_signed_rdf); 468825eb42bSJan Lentfer ldns_rdf_free(fudge_rdf); 469825eb42bSJan Lentfer ldns_rdf_free(orig_id_rdf); 470825eb42bSJan Lentfer ldns_rdf_free(error_rdf); 471825eb42bSJan Lentfer ldns_rdf_free(other_data_rdf); 472825eb42bSJan Lentfer return status; 473825eb42bSJan Lentfer } 474825eb42bSJan Lentfer #endif /* HAVE_SSL */ 475