Coverage Report

Created: 2025-07-18 07:03

/src/bind9/lib/dns/rdata/generic/nsec3_50.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*
15
 * Copyright (C) 2004  Nominet, Ltd.
16
 *
17
 * Permission to use, copy, modify, and distribute this software for any
18
 * purpose with or without fee is hereby granted, provided that the above
19
 * copyright notice and this permission notice appear in all copies.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
22
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
23
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
24
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
26
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27
 * PERFORMANCE OF THIS SOFTWARE.
28
 */
29
30
/* RFC 5155 */
31
32
#ifndef RDATA_GENERIC_NSEC3_50_C
33
#define RDATA_GENERIC_NSEC3_50_C
34
35
#include <isc/base32.h>
36
#include <isc/iterated_hash.h>
37
38
14.5k
#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
39
40
static isc_result_t
41
527
fromtext_nsec3(ARGS_FROMTEXT) {
42
527
  isc_token_t token;
43
527
  unsigned int flags;
44
527
  unsigned char hashalg;
45
527
  isc_buffer_t b;
46
527
  unsigned char buf[256];
47
48
527
  REQUIRE(type == dns_rdatatype_nsec3);
49
50
527
  UNUSED(type);
51
527
  UNUSED(rdclass);
52
527
  UNUSED(callbacks);
53
527
  UNUSED(origin);
54
527
  UNUSED(options);
55
56
  /* Hash. */
57
527
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
58
527
              false));
59
523
  RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
60
477
  RETERR(uint8_tobuffer(hashalg, target));
61
62
  /* Flags. */
63
477
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
64
477
              false));
65
467
  flags = token.value.as_ulong;
66
467
  if (flags > 255U) {
67
45
    RETTOK(ISC_R_RANGE);
68
45
  }
69
422
  RETERR(uint8_tobuffer(flags, target));
70
71
  /* Iterations. */
72
422
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
73
422
              false));
74
412
  if (token.value.as_ulong > 0xffffU) {
75
18
    RETTOK(ISC_R_RANGE);
76
18
  }
77
394
  RETERR(uint16_tobuffer(token.value.as_ulong, target));
78
79
  /* salt */
80
394
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
81
394
              false));
82
369
  if (token.value.as_textregion.length > (255 * 2)) {
83
9
    RETTOK(DNS_R_TEXTTOOLONG);
84
9
  }
85
360
  if (strcmp(DNS_AS_STR(token), "-") == 0) {
86
169
    RETERR(uint8_tobuffer(0, target));
87
191
  } else {
88
191
    RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
89
191
    RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
90
191
  }
91
92
  /*
93
   * Next hash a single base32hex word.
94
   */
95
335
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
96
335
              false));
97
328
  isc_buffer_init(&b, buf, sizeof(buf));
98
328
  RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
99
269
  if (isc_buffer_usedlength(&b) > 0xffU) {
100
1
    RETTOK(ISC_R_RANGE);
101
1
  }
102
268
  RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
103
268
  RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b)));
104
105
268
  return typemap_fromtext(lexer, target, true);
106
268
}
107
108
static isc_result_t
109
4.75k
totext_nsec3(ARGS_TOTEXT) {
110
4.75k
  isc_region_t sr;
111
4.75k
  unsigned int i, j;
112
4.75k
  unsigned char hash;
113
4.75k
  unsigned char flags;
114
4.75k
  char buf[sizeof("TYPE65535")];
115
4.75k
  uint32_t iterations;
116
117
4.75k
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
118
4.75k
  REQUIRE(rdata->length != 0);
119
120
4.75k
  dns_rdata_toregion(rdata, &sr);
121
122
  /* Hash */
123
4.75k
  hash = uint8_fromregion(&sr);
124
4.75k
  isc_region_consume(&sr, 1);
125
4.75k
  snprintf(buf, sizeof(buf), "%u ", hash);
126
4.75k
  RETERR(str_totext(buf, target));
127
128
  /* Flags */
129
4.75k
  flags = uint8_fromregion(&sr);
130
4.75k
  isc_region_consume(&sr, 1);
131
4.75k
  snprintf(buf, sizeof(buf), "%u ", flags);
132
4.75k
  RETERR(str_totext(buf, target));
133
134
  /* Iterations */
135
4.75k
  iterations = uint16_fromregion(&sr);
136
4.75k
  isc_region_consume(&sr, 2);
137
4.75k
  snprintf(buf, sizeof(buf), "%u ", iterations);
138
4.75k
  RETERR(str_totext(buf, target));
139
140
  /* Salt */
141
4.75k
  j = uint8_fromregion(&sr);
142
4.75k
  isc_region_consume(&sr, 1);
143
4.75k
  INSIST(j <= sr.length);
144
145
4.75k
  if (j != 0) {
146
1.86k
    i = sr.length;
147
1.86k
    sr.length = j;
148
1.86k
    RETERR(isc_hex_totext(&sr, 1, "", target));
149
1.86k
    sr.length = i - j;
150
2.89k
  } else {
151
2.89k
    RETERR(str_totext("-", target));
152
2.89k
  }
153
154
4.75k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
155
110
    RETERR(str_totext(" (", target));
156
110
  }
157
4.75k
  RETERR(str_totext(tctx->linebreak, target));
158
159
  /* Next hash */
160
4.75k
  j = uint8_fromregion(&sr);
161
4.75k
  isc_region_consume(&sr, 1);
162
4.75k
  INSIST(j <= sr.length);
163
164
4.75k
  i = sr.length;
165
4.75k
  sr.length = j;
166
4.75k
  RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
167
4.75k
  sr.length = i - j;
168
169
  /*
170
   * Don't leave a trailing space when there's no typemap present.
171
   */
172
4.75k
  if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
173
1.25k
    RETERR(str_totext(" ", target));
174
1.25k
  }
175
4.75k
  RETERR(typemap_totext(&sr, tctx, target));
176
177
4.75k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
178
110
    RETERR(str_totext(" )", target));
179
110
  }
180
181
4.75k
  return ISC_R_SUCCESS;
182
4.75k
}
183
184
static isc_result_t
185
5.92k
fromwire_nsec3(ARGS_FROMWIRE) {
186
5.92k
  isc_region_t sr, rr;
187
5.92k
  unsigned int saltlen, hashlen;
188
189
5.92k
  REQUIRE(type == dns_rdatatype_nsec3);
190
191
5.92k
  UNUSED(type);
192
5.92k
  UNUSED(rdclass);
193
5.92k
  UNUSED(dctx);
194
195
5.92k
  isc_buffer_activeregion(source, &sr);
196
5.92k
  rr = sr;
197
198
  /* hash(1), flags(1), iteration(2), saltlen(1) */
199
5.92k
  if (sr.length < 5U) {
200
16
    RETERR(DNS_R_FORMERR);
201
16
  }
202
5.91k
  saltlen = sr.base[4];
203
5.91k
  isc_region_consume(&sr, 5);
204
205
5.91k
  if (sr.length < saltlen) {
206
12
    RETERR(DNS_R_FORMERR);
207
12
  }
208
5.89k
  isc_region_consume(&sr, saltlen);
209
210
5.89k
  if (sr.length < 1U) {
211
3
    RETERR(DNS_R_FORMERR);
212
3
  }
213
5.89k
  hashlen = sr.base[0];
214
5.89k
  isc_region_consume(&sr, 1);
215
216
5.89k
  if (hashlen < 1 || sr.length < hashlen) {
217
31
    RETERR(DNS_R_FORMERR);
218
31
  }
219
5.86k
  isc_region_consume(&sr, hashlen);
220
221
5.86k
  RETERR(typemap_test(&sr, true));
222
223
5.71k
  RETERR(mem_tobuffer(target, rr.base, rr.length));
224
5.52k
  isc_buffer_forward(source, rr.length);
225
5.52k
  return ISC_R_SUCCESS;
226
5.71k
}
227
228
static isc_result_t
229
2.37k
towire_nsec3(ARGS_TOWIRE) {
230
2.37k
  isc_region_t sr;
231
232
2.37k
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
233
2.37k
  REQUIRE(rdata->length != 0);
234
235
2.37k
  UNUSED(cctx);
236
237
2.37k
  dns_rdata_toregion(rdata, &sr);
238
2.37k
  return mem_tobuffer(target, sr.base, sr.length);
239
2.37k
}
240
241
static int
242
0
compare_nsec3(ARGS_COMPARE) {
243
0
  isc_region_t r1;
244
0
  isc_region_t r2;
245
246
0
  REQUIRE(rdata1->type == rdata2->type);
247
0
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
248
0
  REQUIRE(rdata1->type == dns_rdatatype_nsec3);
249
0
  REQUIRE(rdata1->length != 0);
250
0
  REQUIRE(rdata2->length != 0);
251
252
0
  dns_rdata_toregion(rdata1, &r1);
253
0
  dns_rdata_toregion(rdata2, &r2);
254
0
  return isc_region_compare(&r1, &r2);
255
0
}
256
257
static isc_result_t
258
0
fromstruct_nsec3(ARGS_FROMSTRUCT) {
259
0
  dns_rdata_nsec3_t *nsec3 = source;
260
0
  isc_region_t region;
261
262
0
  REQUIRE(type == dns_rdatatype_nsec3);
263
0
  REQUIRE(nsec3 != NULL);
264
0
  REQUIRE(nsec3->common.rdtype == type);
265
0
  REQUIRE(nsec3->common.rdclass == rdclass);
266
0
  REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
267
0
  REQUIRE(nsec3->hash == dns_hash_sha1);
268
269
0
  UNUSED(type);
270
0
  UNUSED(rdclass);
271
272
0
  RETERR(uint8_tobuffer(nsec3->hash, target));
273
0
  RETERR(uint8_tobuffer(nsec3->flags, target));
274
0
  RETERR(uint16_tobuffer(nsec3->iterations, target));
275
0
  RETERR(uint8_tobuffer(nsec3->salt_length, target));
276
0
  RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
277
0
  RETERR(uint8_tobuffer(nsec3->next_length, target));
278
0
  RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
279
280
0
  region.base = nsec3->typebits;
281
0
  region.length = nsec3->len;
282
0
  RETERR(typemap_test(&region, true));
283
0
  return mem_tobuffer(target, nsec3->typebits, nsec3->len);
284
0
}
285
286
static isc_result_t
287
0
tostruct_nsec3(ARGS_TOSTRUCT) {
288
0
  isc_region_t region;
289
0
  dns_rdata_nsec3_t *nsec3 = target;
290
291
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
292
0
  REQUIRE(nsec3 != NULL);
293
0
  REQUIRE(rdata->length != 0);
294
295
0
  nsec3->common.rdclass = rdata->rdclass;
296
0
  nsec3->common.rdtype = rdata->type;
297
298
0
  region.base = rdata->data;
299
0
  region.length = rdata->length;
300
0
  nsec3->hash = uint8_consume_fromregion(&region);
301
0
  nsec3->flags = uint8_consume_fromregion(&region);
302
0
  nsec3->iterations = uint16_consume_fromregion(&region);
303
304
0
  nsec3->salt_length = uint8_consume_fromregion(&region);
305
0
  INSIST(nsec3->salt_length <= region.length);
306
0
  nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
307
0
  isc_region_consume(&region, nsec3->salt_length);
308
309
0
  nsec3->next_length = uint8_consume_fromregion(&region);
310
0
  INSIST(nsec3->next_length <= region.length);
311
0
  nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
312
0
  isc_region_consume(&region, nsec3->next_length);
313
314
0
  nsec3->len = region.length;
315
0
  nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
316
0
  nsec3->mctx = mctx;
317
0
  return ISC_R_SUCCESS;
318
0
}
319
320
static void
321
0
freestruct_nsec3(ARGS_FREESTRUCT) {
322
0
  dns_rdata_nsec3_t *nsec3 = source;
323
324
0
  REQUIRE(nsec3 != NULL);
325
0
  REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3);
326
327
0
  if (nsec3->mctx == NULL) {
328
0
    return;
329
0
  }
330
331
0
  if (nsec3->salt != NULL) {
332
0
    isc_mem_free(nsec3->mctx, nsec3->salt);
333
0
  }
334
0
  if (nsec3->next != NULL) {
335
0
    isc_mem_free(nsec3->mctx, nsec3->next);
336
0
  }
337
0
  if (nsec3->typebits != NULL) {
338
0
    isc_mem_free(nsec3->mctx, nsec3->typebits);
339
0
  }
340
0
  nsec3->mctx = NULL;
341
0
}
342
343
static isc_result_t
344
0
additionaldata_nsec3(ARGS_ADDLDATA) {
345
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
346
347
0
  UNUSED(rdata);
348
0
  UNUSED(owner);
349
0
  UNUSED(add);
350
0
  UNUSED(arg);
351
352
0
  return ISC_R_SUCCESS;
353
0
}
354
355
static isc_result_t
356
0
digest_nsec3(ARGS_DIGEST) {
357
0
  isc_region_t r;
358
359
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
360
361
0
  dns_rdata_toregion(rdata, &r);
362
0
  return (digest)(arg, &r);
363
0
}
364
365
static bool
366
5.81k
checkowner_nsec3(ARGS_CHECKOWNER) {
367
5.81k
  unsigned char owner[NSEC3_MAX_HASH_LENGTH];
368
5.81k
  isc_buffer_t buffer;
369
5.81k
  dns_label_t label;
370
371
5.81k
  REQUIRE(type == dns_rdatatype_nsec3);
372
373
5.81k
  UNUSED(type);
374
5.81k
  UNUSED(rdclass);
375
5.81k
  UNUSED(wildcard);
376
377
  /*
378
   * First label is a base32hex string without padding.
379
   */
380
5.81k
  dns_name_getlabel(name, 0, &label);
381
5.81k
  isc_region_consume(&label, 1);
382
5.81k
  isc_buffer_init(&buffer, owner, sizeof(owner));
383
5.81k
  if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) {
384
5.78k
    return true;
385
5.78k
  }
386
387
30
  return false;
388
5.81k
}
389
390
static bool
391
0
checknames_nsec3(ARGS_CHECKNAMES) {
392
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
393
394
0
  UNUSED(rdata);
395
0
  UNUSED(owner);
396
0
  UNUSED(bad);
397
398
0
  return true;
399
0
}
400
401
static int
402
0
casecompare_nsec3(ARGS_COMPARE) {
403
0
  return compare_nsec3(rdata1, rdata2);
404
0
}
405
406
#endif /* RDATA_GENERIC_NSEC3_50_C */