1 1.1 christos /* $NetBSD: dns_message_checksig.c,v 1.3 2025/01/26 16:25:20 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <inttypes.h> 17 1.1 christos #include <stdbool.h> 18 1.1 christos #include <stdlib.h> 19 1.1 christos #include <unistd.h> 20 1.1 christos 21 1.1 christos #include <isc/buffer.h> 22 1.1 christos #include <isc/commandline.h> 23 1.1 christos #include <isc/file.h> 24 1.1 christos #include <isc/mem.h> 25 1.1 christos #include <isc/result.h> 26 1.1 christos #include <isc/string.h> 27 1.3 christos #include <isc/tid.h> 28 1.1 christos #include <isc/util.h> 29 1.1 christos 30 1.1 christos #include <dns/fixedname.h> 31 1.1 christos #include <dns/message.h> 32 1.1 christos #include <dns/name.h> 33 1.1 christos #include <dns/rcode.h> 34 1.1 christos #include <dns/tsig.h> 35 1.1 christos #include <dns/view.h> 36 1.1 christos #include <dns/zone.h> 37 1.1 christos 38 1.1 christos #include "fuzz.h" 39 1.1 christos 40 1.1 christos bool debug = false; 41 1.1 christos 42 1.1 christos static isc_mem_t *mctx = NULL; 43 1.1 christos 44 1.1 christos /* 45 1.1 christos * Packet dumps of validily signed request ./IN/SOA 46 1.1 christos * requests. 47 1.1 christos * 48 1.1 christos * TSIG: 49 1.1 christos * 50 1.1 christos * 0x0000: 600b 0900 006a 1140 0000 0000 0000 0000 51 1.1 christos * 0x0010: 0000 0000 0000 0001 0000 0000 0000 0000 52 1.1 christos * 0x0020: 0000 0000 0000 0001 cc88 0035 006a 007d 53 1.1 christos * 0x0030: 1dfa 0000 0001 0000 0000 0001 0000 0600 54 1.1 christos * 0x0040: 0108 7473 6967 2d6b 6579 0000 fa00 ff00 55 1.1 christos * 0x0050: 0000 0000 3d0b 686d 6163 2d73 6861 3235 56 1.1 christos * 0x0060: 3600 0000 622a cce1 012c 0020 224d 5807 57 1.1 christos * 0x0070: 648d 1400 9d8e fc1c d049 55e9 cc90 2187 58 1.1 christos * 0x0080: 3b5f af5c 8899 dc27 c8df b34b 1dfa 0000 59 1.1 christos * 0x0090: 0000 60 1.1 christos * 61 1.1 christos * SIG(0): 62 1.1 christos * 63 1.1 christos * 0x0000: 6004 0e00 013f 1140 0000 0000 0000 0000 64 1.1 christos * 0x0010: 0000 0000 0000 0001 0000 0000 0000 0000 65 1.1 christos * 0x0020: 0000 0000 0000 0001 c0a7 0035 013f 0152 66 1.1 christos * 0x0030: 0000 0000 0001 0000 0000 0001 0000 0600 67 1.1 christos * 0x0040: 0100 0018 00ff 0000 0000 011b 0000 0800 68 1.1 christos * 0x0050: 0000 0000 622a ce0d 622a cbb5 da71 0773 69 1.1 christos * 0x0060: 6967 306b 6579 0068 988b 27bf 5c89 5270 70 1.1 christos * 0x0070: c5ba ea8b 2e10 0512 9b44 48d3 69de b7ec 71 1.1 christos * 0x0080: 7c67 15f3 6bc7 b0dc 277b e8f1 6979 4c89 72 1.1 christos * 0x0090: 149a 0203 30a1 c0b7 a711 ee8a 8d90 ebb9 73 1.1 christos * 0x00a0: 9e33 dd65 33d5 5d1d 90db cf9c bb6a b346 74 1.1 christos * 0x00b0: 568f a399 71d7 c877 616d 2fb7 0f86 963f 75 1.1 christos * 0x00c0: aa00 850d 180a 9f83 cd4b d115 c79f 64c9 76 1.1 christos * 0x00d0: ff05 e751 6810 28b3 2249 c4ba 2d8d 57ba 77 1.1 christos * 0x00e0: 9aad f1fc b34e c237 9465 04fd fe4d 19c9 78 1.1 christos * 0x00f0: 2368 ec8e 7097 eaea e067 2b9c 06eb c383 79 1.1 christos * 0x0100: e901 a11e 606b 4cce c12a 0e57 8c09 b7cb 80 1.1 christos * 0x0110: 23bb ec05 b68b 1852 9288 b665 fe89 cf62 81 1.1 christos * 0x0120: 0a41 5e5a acbe 6903 cbb7 e7b6 cab4 e4a2 82 1.1 christos * 0x0130: b98f 884f c09d 5b39 c695 c84c 9a92 f110 83 1.1 christos * 0x0140: ccc3 f2ee 313f a2a1 1cda 5aa2 faec d593 84 1.1 christos * 0x0150: 4514 724a 868f 94b9 0547 4dc9 7b73 c85e 85 1.1 christos * 0x0160: 544c 73d4 e892 f9 86 1.1 christos */ 87 1.1 christos 88 1.1 christos #define HMACSHA256 "\x0bhmac-sha256" 89 1.1 christos 90 1.1 christos static isc_stdtime_t fuzztime = 0x622acce1; 91 1.3 christos static isc_loopmgr_t *loopmgr = NULL; 92 1.1 christos static dns_view_t *view = NULL; 93 1.1 christos static dns_tsigkey_t *tsigkey = NULL; 94 1.3 christos static dns_tsigkeyring_t *ring = NULL; 95 1.3 christos static dns_tsigkeyring_t *emptyring = NULL; 96 1.1 christos static char *wd = NULL; 97 1.1 christos static char template[] = "/tmp/dns-message-checksig-XXXXXX"; 98 1.1 christos 99 1.1 christos static char f1[] = "Ksig0key.+008+55921.key"; 100 1.1 christos static char c1[] = "sig0key. IN KEY 512 3 8 " 101 1.1 christos "AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 " 102 1.1 christos "uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs " 103 1.1 christos "bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti " 104 1.1 christos "e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA " 105 1.1 christos "TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk " 106 1.1 christos "ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw " 107 1.1 christos "sY32nxzjDbs=\n"; 108 1.1 christos 109 1.1 christos static char f2[] = "Ksig0key.+008+55921.private"; 110 1.1 christos static char c2[] = "Private-key-format: v1.3\n\ 111 1.1 christos Algorithm: 8 (RSASHA256)\n\ 112 1.1 christos Modulus: rbaWAeLW8BtC+7kRN1OubYfyvCBr22/IxrosWJIPJ68u9K/RSjm69+tefFot20Ey2zp7UvLamJIf0lFs4Yw2Js4rgRdaFYCfwwgjhJaBACxsXC2LPgfI+fbBJytRB2jwOhwqJAkFqd6yvu8M7x90DpGDV7TIC1J422J7xq/Hjr8clroIWzcKgTSx/qg4VLEz3ngCAIFNc4Y0G3U23cGF+q3arIBMsWKLkrWMsNNkNWSiLINcvUzvBxPAp/0wROCPV5CYfcYaVEz84n+PzGRmIUZsvdyKlZ2IfjzTfWOJXaGVz3aYqfxhrR30A3pzjimLNr8lIXJ1lfCxjfafHOMNuw==\n\ 113 1.1 christos PublicExponent: AQAB\n\ 114 1.1 christos PrivateExponent: GDfclFkR5ToFGH9rMTRMnP73Q5dzjLgkx4vyHcuzKtxcvAans4+hNj+NazckAy2E+mpzV2j95TJ4wZjSM2RvB5xLwBIc4Dg6oyAHL6Ikoae6gw64cHFOaYb808n8CyqWqfX+QWAz9sRSVZXnTuPViX3A+svR7ejVak9Bzr1NTDm0DFlrhaKVCYA++dKVZerfuNiXT/jQvrc4wMCa7WWsfLsFO8aTNkEhqUnmS9c5VYgr7MkCV4ENDBcISpQc9wElI0hl12QPaSj8iSdk9liYp+HTiOxOyp6BGGuecKAoQijMwrZy4qExdOxvowptll8+nZLtwGRn/un/xvIZY5OLAQ==\n\ 115 1.1 christos Prime1: ww3C6jwnrLQik/zxSgC0KuqgHq68cCjiRjwK2/euzs7NkMevFpXvV0cWO8x1/wKC1mszVLsUaKTvH6fzRsXfz5MPihzNzUYFwvobKVLserSxEwHNk+FKUU+q07Kf8WWnCqX5nX9QzVG1q4J8Q44N49I5S480jHLGYbyLZrEYMQE=\n\ 116 1.1 christos Prime2: 4/3Ozq/8vRgcO4bieFs4CbZR7C98HiTi65SiLBIKY09mDfCleZI0uurAYBluZJgHS5AC5cdyHFuJr3uKxvD+Mgdlru40U6cSCEdK7HAhyUGZUndWl28wyMEB6Kke1/owxVn0S4RKLPOgFI2668H6JObaqXf0wyY89RdVQP6VQrs=\n\ 117 1.1 christos Exponent1: Tbr9MyVX1j5PDVSev5P6OKQZvUB7PeM9ESo6VaCl3CqTxx+cic6ke86LcLcxSrewdkxwP1LydiVMWfwvOcP/RhRf+/Uwmp5OC35qNpSiQuAhNObiCw2b9T1fYU/s52FQKTEtgXNMOxZV5IxyguVoaaLMTG08TsAqiKZ/kyP99QE=\n\ 118 1.1 christos Exponent2: Q4qSNKrwLbixzHS2LL+hR0dK17RtiaSV0QKUVIf3qdoAusp6yxwkIOegnBeMm6JqLtl38kh2pq37iRAJWcxVEc8dMYiB2fJZpjgwmwDREYUsfcC611vqUN7UyO8pIwSMZDq045ZKPyzhVJV0NZmemEYHq0LNMO7oCheiewGwiDc=\n\ 119 1.1 christos Coefficient: T2u/J4NgyO+OqoLpXBIpTBzqrvDk8tb0feYgsp5d16hHvbXxNkMUR8cI07RdbI9HnEldtmhAnbQ6SvFiy2YYjpw/1Fz2WwdxRqLaDV7UlhrT+CqltvU9d/N/xThBNKDa23Wf5Vat+HRiLHSgzsY1PseVCWN+g4azuK2D8+DLeHE=\n\ 120 1.1 christos Created: 20220311073606\n\ 121 1.1 christos Publish: 20220311073606\n\ 122 1.1 christos Activate: 20220311073606\n"; 123 1.1 christos 124 1.1 christos static char f3[] = "sig0key.db"; 125 1.1 christos static char c3[] = "sig0key. 0 IN SOA . . 0 0 0 0 0\n\ 126 1.1 christos sig0key. 0 IN NS .\n\ 127 1.1 christos sig0key. 0 IN KEY 512 3 8 AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw sY32nxzjDbs=\n"; 128 1.1 christos 129 1.1 christos static bool destroy_dst = false; 130 1.1 christos 131 1.1 christos int 132 1.3 christos LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) { 133 1.1 christos isc_result_t result; 134 1.1 christos dns_fixedname_t fixed; 135 1.1 christos dns_name_t *name = dns_fixedname_initname(&fixed); 136 1.1 christos unsigned char secret[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 137 1.1 christos 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 138 1.1 christos 0xff, 0xff, 0xff, 0xff }; 139 1.1 christos dns_zone_t *zone = NULL; 140 1.1 christos char pathbuf[PATH_MAX]; 141 1.1 christos FILE *fd; 142 1.1 christos 143 1.1 christos wd = mkdtemp(template); 144 1.1 christos if (wd == NULL) { 145 1.1 christos fprintf(stderr, "mkdtemp failed\n"); 146 1.3 christos return 1; 147 1.1 christos } 148 1.1 christos 149 1.1 christos snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f1); 150 1.1 christos fd = fopen(pathbuf, "w"); 151 1.1 christos if (fd == NULL) { 152 1.1 christos fprintf(stderr, "fopen(%s) failed\n", pathbuf); 153 1.3 christos return 1; 154 1.1 christos } 155 1.1 christos fputs(c1, fd); 156 1.1 christos fclose(fd); 157 1.1 christos 158 1.1 christos snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f2); 159 1.1 christos fd = fopen(pathbuf, "w"); 160 1.1 christos if (fd == NULL) { 161 1.1 christos fprintf(stderr, "fopen(%s) failed\n", pathbuf); 162 1.3 christos return 1; 163 1.1 christos } 164 1.1 christos fputs(c2, fd); 165 1.1 christos fclose(fd); 166 1.1 christos 167 1.1 christos snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f3); 168 1.1 christos fd = fopen(pathbuf, "w"); 169 1.1 christos if (fd == NULL) { 170 1.1 christos fprintf(stderr, "fopen(%s) failed\n", pathbuf); 171 1.3 christos return 1; 172 1.1 christos } 173 1.1 christos fputs(c3, fd); 174 1.1 christos fclose(fd); 175 1.1 christos 176 1.1 christos isc_mem_create(&mctx); 177 1.1 christos 178 1.1 christos result = dst_lib_init(mctx, NULL); 179 1.1 christos if (result != ISC_R_SUCCESS) { 180 1.1 christos fprintf(stderr, "dst_lib_init failed: %s\n", 181 1.1 christos isc_result_totext(result)); 182 1.3 christos return 1; 183 1.1 christos } 184 1.1 christos destroy_dst = true; 185 1.1 christos 186 1.3 christos isc_loopmgr_create(mctx, 1, &loopmgr); 187 1.3 christos 188 1.3 christos result = dns_view_create(mctx, loopmgr, NULL, dns_rdataclass_in, "view", 189 1.3 christos &view); 190 1.1 christos if (result != ISC_R_SUCCESS) { 191 1.1 christos fprintf(stderr, "dns_view_create failed: %s\n", 192 1.1 christos isc_result_totext(result)); 193 1.3 christos return 1; 194 1.1 christos } 195 1.1 christos 196 1.3 christos dns_tsigkeyring_create(mctx, &ring); 197 1.3 christos dns_tsigkeyring_create(mctx, &emptyring); 198 1.1 christos 199 1.3 christos result = dns_name_fromstring(name, "tsig-key", dns_rootname, 0, NULL); 200 1.1 christos if (result != ISC_R_SUCCESS) { 201 1.3 christos fprintf(stderr, "dns_name_fromstring failed: %s\n", 202 1.1 christos isc_result_totext(result)); 203 1.3 christos return 1; 204 1.1 christos } 205 1.1 christos 206 1.3 christos result = dns_tsigkey_create(name, DST_ALG_HMACSHA256, secret, 207 1.3 christos sizeof(secret), mctx, &tsigkey); 208 1.1 christos if (result != ISC_R_SUCCESS) { 209 1.3 christos fprintf(stderr, "dns_tsigkey_create failed: %s\n", 210 1.1 christos isc_result_totext(result)); 211 1.3 christos return 1; 212 1.1 christos } 213 1.3 christos result = dns_tsigkeyring_add(ring, tsigkey); 214 1.1 christos if (result != ISC_R_SUCCESS) { 215 1.3 christos fprintf(stderr, "dns_tsigkeyring_add failed: %s\n", 216 1.1 christos isc_result_totext(result)); 217 1.3 christos return 1; 218 1.1 christos } 219 1.1 christos 220 1.3 christos result = dns_name_fromstring(name, "sig0key", dns_rootname, 0, NULL); 221 1.1 christos if (result != ISC_R_SUCCESS) { 222 1.1 christos fprintf(stderr, "dns_name_fromstring failed: %s\n", 223 1.1 christos isc_result_totext(result)); 224 1.3 christos return 1; 225 1.1 christos } 226 1.1 christos 227 1.3 christos dns_zone_create(&zone, mctx, 0); 228 1.1 christos 229 1.1 christos result = dns_zone_setorigin(zone, name); 230 1.1 christos if (result != ISC_R_SUCCESS) { 231 1.1 christos fprintf(stderr, "dns_zone_setorigin failed: %s\n", 232 1.1 christos isc_result_totext(result)); 233 1.3 christos return 1; 234 1.1 christos } 235 1.1 christos 236 1.1 christos dns_zone_setclass(zone, view->rdclass); 237 1.1 christos dns_zone_settype(zone, dns_zone_primary); 238 1.1 christos 239 1.1 christos result = dns_zone_setkeydirectory(zone, wd); 240 1.1 christos if (result != ISC_R_SUCCESS) { 241 1.1 christos fprintf(stderr, "dns_zone_setkeydirectory failed: %s\n", 242 1.1 christos isc_result_totext(result)); 243 1.3 christos return 1; 244 1.1 christos } 245 1.1 christos 246 1.1 christos result = dns_zone_setfile(zone, pathbuf, dns_masterformat_text, 247 1.1 christos &dns_master_style_default); 248 1.1 christos if (result != ISC_R_SUCCESS) { 249 1.1 christos fprintf(stderr, "dns_zone_setfile failed: %s\n", 250 1.1 christos isc_result_totext(result)); 251 1.3 christos return 1; 252 1.1 christos } 253 1.1 christos 254 1.1 christos result = dns_zone_load(zone, false); 255 1.1 christos if (result != ISC_R_SUCCESS) { 256 1.1 christos fprintf(stderr, "dns_zone_load failed: %s\n", 257 1.1 christos isc_result_totext(result)); 258 1.3 christos return 1; 259 1.1 christos } 260 1.1 christos 261 1.1 christos result = dns_view_addzone(view, zone); 262 1.1 christos if (result != ISC_R_SUCCESS) { 263 1.1 christos fprintf(stderr, "dns_view_addzone failed: %s\n", 264 1.1 christos isc_result_totext(result)); 265 1.3 christos return 1; 266 1.1 christos } 267 1.1 christos 268 1.3 christos dns_zone_setview(zone, view); 269 1.1 christos dns_view_freeze(view); 270 1.1 christos 271 1.1 christos dns_zone_detach(&zone); 272 1.1 christos 273 1.3 christos return 0; 274 1.1 christos } 275 1.1 christos 276 1.1 christos static isc_result_t 277 1.1 christos create_message(dns_message_t **messagep, const uint8_t *data, size_t size, 278 1.1 christos bool addasig, bool addtsig) { 279 1.1 christos isc_result_t result; 280 1.1 christos dns_message_t *message = NULL; 281 1.1 christos isc_buffer_t b; 282 1.1 christos static unsigned char buf[65535]; 283 1.1 christos 284 1.1 christos isc_buffer_init(&b, buf, sizeof(buf)); 285 1.1 christos 286 1.1 christos /* Message ID */ 287 1.1 christos isc_buffer_putuint16(&b, 0); 288 1.1 christos 289 1.1 christos /* QR, Opcode, other flags = 0, rcode = 0 */ 290 1.1 christos isc_buffer_putuint16(&b, (*data & 0x1f) << 11); 291 1.1 christos /* Counts */ 292 1.1 christos isc_buffer_putuint16(&b, 1); 293 1.1 christos isc_buffer_putuint16(&b, 0); 294 1.1 christos isc_buffer_putuint16(&b, 0); 295 1.1 christos isc_buffer_putuint16(&b, addasig ? 1 : 0); 296 1.1 christos 297 1.1 christos /* Question ./IN/SOA */ 298 1.1 christos isc_buffer_putuint8(&b, 0); 299 1.1 christos isc_buffer_putuint16(&b, 6); 300 1.1 christos isc_buffer_putuint16(&b, 1); 301 1.1 christos 302 1.1 christos if (addasig) { 303 1.1 christos /* Signature */ 304 1.1 christos if (addtsig) { 305 1.1 christos const unsigned char keyname[] = "\x08tsig-key"; 306 1.1 christos isc_buffer_putmem(&b, keyname, sizeof(keyname)); 307 1.1 christos isc_buffer_putuint16(&b, dns_rdatatype_tsig); 308 1.1 christos isc_buffer_putuint16(&b, dns_rdataclass_any); 309 1.1 christos } else { 310 1.1 christos isc_buffer_putuint8(&b, 0); /* '.' */ 311 1.1 christos isc_buffer_putuint16(&b, dns_rdatatype_sig); 312 1.1 christos isc_buffer_putuint16(&b, dns_rdataclass_in); 313 1.1 christos } 314 1.1 christos isc_buffer_putuint32(&b, 0); /* ttl */ 315 1.1 christos data++; 316 1.1 christos size--; 317 1.1 christos if (size > isc_buffer_availablelength(&b) - 2) { 318 1.1 christos size = isc_buffer_availablelength(&b) - 2; 319 1.1 christos } 320 1.1 christos isc_buffer_putuint16(&b, size); 321 1.1 christos isc_buffer_putmem(&b, data, size); 322 1.1 christos } 323 1.1 christos 324 1.3 christos dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message); 325 1.1 christos 326 1.1 christos result = dns_message_parse(message, &b, 0); 327 1.1 christos if (debug) { 328 1.1 christos fprintf(stderr, "dns_message_parse => %s\n", 329 1.1 christos isc_result_totext(result)); 330 1.1 christos } 331 1.1 christos if (result != ISC_R_SUCCESS) { 332 1.1 christos dns_message_detach(&message); 333 1.1 christos } else { 334 1.1 christos if (debug) { 335 1.1 christos char text[200000]; 336 1.1 christos isc_buffer_init(&b, text, sizeof(text)); 337 1.1 christos 338 1.1 christos result = dns_message_totext( 339 1.1 christos message, &dns_master_style_debug, 0, &b); 340 1.1 christos if (result == ISC_R_SUCCESS) { 341 1.1 christos fprintf(stderr, "%.*s", (int)b.used, text); 342 1.1 christos } else { 343 1.1 christos fprintf(stderr, "dns_message_totext => %s\n", 344 1.1 christos isc_result_totext(result)); 345 1.1 christos } 346 1.1 christos } 347 1.1 christos *messagep = message; 348 1.1 christos } 349 1.3 christos return result; 350 1.1 christos } 351 1.1 christos 352 1.1 christos int 353 1.1 christos LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 354 1.1 christos isc_result_t result; 355 1.1 christos dns_message_t *message = NULL; 356 1.1 christos unsigned char query_tsig[23 + 32 + 6] = { 0 }; 357 1.1 christos bool addasig = false; 358 1.1 christos bool addtime = false; 359 1.1 christos bool addtsig = false; 360 1.1 christos bool setquerytsig = false; 361 1.1 christos bool settsigkey = false; 362 1.1 christos bool subtime = false; 363 1.1 christos bool withring = false; 364 1.1 christos bool withview = false; 365 1.1 christos 366 1.1 christos /* 367 1.1 christos * The first 2 octets affect setup. 368 1.1 christos * Octet 1 determines whether a signature is added and which type 369 1.1 christos * (addasig, addtsig), whether time should be adjusted (addtime, 370 1.1 christos * subtime), whether dns_message_setquerytsig and dns_message_settsigkey 371 1.1 christos * have been called, whether there is a keyring available with the 372 1.1 christos * TSIG key or a view is defined. 373 1.1 christos * 374 1.1 christos * The second octet defines if the message is a response and the 375 1.1 christos * opcode. 376 1.1 christos */ 377 1.1 christos if (size > 65535 || size < 2) { 378 1.3 christos return 0; 379 1.1 christos } 380 1.1 christos 381 1.1 christos addasig = (*data & 0x80) != 0; 382 1.1 christos addtime = (*data & 0x40) != 0; 383 1.1 christos addtsig = (*data & 0x20) != 0; 384 1.1 christos setquerytsig = (*data & 0x10) != 0; 385 1.1 christos settsigkey = (*data & 0x08) != 0; 386 1.1 christos subtime = (*data & 0x04) != 0; 387 1.1 christos withring = (*data & 0x02) != 0; 388 1.1 christos withview = (*data & 0x01) != 0; 389 1.1 christos 390 1.1 christos data++; 391 1.1 christos size--; 392 1.1 christos 393 1.1 christos if (debug) { 394 1.1 christos fprintf(stderr, 395 1.1 christos "addasig=%u addtime=%u addtsig=%u setquerytsig=%u " 396 1.1 christos "settsigkey=%u subtime=%u withring=%u\nwithview=%u\n", 397 1.1 christos addasig, addtime, addtsig, setquerytsig, settsigkey, 398 1.1 christos subtime, withring, withview); 399 1.1 christos } 400 1.1 christos 401 1.1 christos result = create_message(&message, data, size, addasig, addtsig); 402 1.1 christos if (result != ISC_R_SUCCESS) { 403 1.3 christos return 0; 404 1.1 christos } 405 1.1 christos 406 1.1 christos /* 407 1.1 christos * Make time calculations consistent. 408 1.1 christos */ 409 1.1 christos message->fuzzing = 1; 410 1.1 christos message->fuzztime = fuzztime; 411 1.1 christos if (addtime) { 412 1.1 christos message->fuzztime += 1200; 413 1.1 christos } 414 1.1 christos if (subtime) { 415 1.1 christos message->fuzztime -= 1200; 416 1.1 christos } 417 1.1 christos 418 1.1 christos if ((message->flags & DNS_MESSAGEFLAG_QR) != 0) { 419 1.1 christos if (setquerytsig) { 420 1.1 christos isc_buffer_t b; 421 1.1 christos unsigned char hmacname[] = HMACSHA256; 422 1.1 christos unsigned char hmacvalue[32] = { 423 1.1 christos 0x22, 0x4d, 0x58, 0x07, 0x64, 0x8d, 0x14, 0x00, 424 1.1 christos 0x9d, 0x8e, 0xfc, 0x1c, 0xd0, 0x49, 0x55, 0xe9, 425 1.1 christos 0xcc, 0x90, 0x21, 0x87, 0x3b, 0x5f, 0xaf, 0x5c, 426 1.1 christos 0x88, 0x99, 0xdc, 0x27, 0xc8, 0xdf, 0xb3, 0x4b 427 1.1 christos }; 428 1.1 christos 429 1.1 christos /* 430 1.1 christos * Valid TSIG rdata for tsig-key over a plain 431 1.1 christos * DNS QUERY for ./SOA/IN with no flags set. 432 1.1 christos */ 433 1.1 christos isc_buffer_init(&b, query_tsig, sizeof(query_tsig)); 434 1.1 christos isc_buffer_putmem(&b, hmacname, sizeof(hmacname)); 435 1.1 christos isc_buffer_putuint16(&b, 0); /* time high */ 436 1.1 christos isc_buffer_putuint32(&b, 0x622abec0); /* time low */ 437 1.1 christos isc_buffer_putuint16(&b, 300); /* Fudge */ 438 1.1 christos isc_buffer_putuint16(&b, 32); /* Mac Length */ 439 1.1 christos /* Mac */ 440 1.1 christos isc_buffer_putmem(&b, hmacvalue, 32); 441 1.1 christos isc_buffer_putuint16(&b, 7674); /* Original Id */ 442 1.1 christos isc_buffer_putuint16(&b, 0); /* Error */ 443 1.1 christos isc_buffer_putuint16(&b, 0); /* Other len */ 444 1.1 christos 445 1.1 christos dns_message_setquerytsig(message, &b); 446 1.1 christos } 447 1.1 christos } 448 1.1 christos 449 1.1 christos if (settsigkey) { 450 1.1 christos result = dns_message_settsigkey(message, tsigkey); 451 1.1 christos if (debug) { 452 1.1 christos fprintf(stderr, "dns_message_settsigkey => %s\n", 453 1.1 christos isc_result_totext(result)); 454 1.1 christos } 455 1.1 christos } 456 1.1 christos 457 1.1 christos dns_view_setkeyring(view, withring ? ring : emptyring); 458 1.1 christos 459 1.1 christos result = dns_message_checksig(message, withview ? view : NULL); 460 1.1 christos if (debug) { 461 1.1 christos char textbuf[64]; 462 1.1 christos isc_buffer_t b; 463 1.1 christos 464 1.1 christos fprintf(stderr, "dns_message_checksig => %s\n", 465 1.1 christos isc_result_totext(result)); 466 1.1 christos isc_buffer_init(&b, textbuf, sizeof(textbuf)); 467 1.1 christos dns_tsigrcode_totext(message->tsigstatus, &b); 468 1.1 christos fprintf(stderr, "tsigstatus=%.*s\n", (int)b.used, textbuf); 469 1.1 christos isc_buffer_init(&b, textbuf, sizeof(textbuf)); 470 1.1 christos dns_tsigrcode_totext(message->sig0status, &b); 471 1.1 christos fprintf(stderr, "sig0status=%.*s\n", (int)b.used, textbuf); 472 1.1 christos } 473 1.1 christos if (result != ISC_R_SUCCESS) { 474 1.1 christos goto cleanup; 475 1.1 christos } 476 1.1 christos 477 1.1 christos cleanup: 478 1.1 christos if (message != NULL) { 479 1.1 christos dns_message_detach(&message); 480 1.1 christos } 481 1.1 christos 482 1.3 christos return 0; 483 1.1 christos } 484