Coverage Report

Created: 2025-12-14 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdata/generic/nsec3_50.c
Line
Count
Source
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
19.7k
#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
39
40
static isc_result_t
41
3.14k
fromtext_nsec3(ARGS_FROMTEXT) {
42
3.14k
  isc_token_t token;
43
3.14k
  unsigned int flags;
44
3.14k
  unsigned char hashalg;
45
3.14k
  isc_buffer_t b;
46
3.14k
  unsigned char buf[256];
47
48
3.14k
  REQUIRE(type == dns_rdatatype_nsec3);
49
50
3.14k
  UNUSED(type);
51
3.14k
  UNUSED(rdclass);
52
3.14k
  UNUSED(callbacks);
53
3.14k
  UNUSED(origin);
54
3.14k
  UNUSED(options);
55
56
  /* Hash. */
57
3.14k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
58
3.14k
              false));
59
3.14k
  RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
60
3.08k
  RETERR(uint8_tobuffer(hashalg, target));
61
62
  /* Flags. */
63
3.08k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
64
3.08k
              false));
65
3.07k
  flags = token.value.as_ulong;
66
3.07k
  if (flags > 255U) {
67
52
    RETTOK(ISC_R_RANGE);
68
52
  }
69
3.01k
  RETERR(uint8_tobuffer(flags, target));
70
71
  /* Iterations. */
72
3.01k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
73
3.01k
              false));
74
3.00k
  if (token.value.as_ulong > 0xffffU) {
75
18
    RETTOK(ISC_R_RANGE);
76
18
  }
77
2.99k
  RETERR(uint16_tobuffer(token.value.as_ulong, target));
78
79
  /* salt */
80
2.99k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
81
2.99k
              false));
82
2.95k
  if (token.value.as_textregion.length > (255 * 2)) {
83
2
    RETTOK(DNS_R_TEXTTOOLONG);
84
2
  }
85
2.95k
  if (strcmp(DNS_AS_STR(token), "-") == 0) {
86
940
    RETERR(uint8_tobuffer(0, target));
87
2.01k
  } else {
88
2.01k
    RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
89
2.01k
    RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
90
1.99k
  }
91
92
  /*
93
   * Next hash a single base32hex word.
94
   */
95
2.93k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
96
2.93k
              false));
97
2.92k
  isc_buffer_init(&b, buf, sizeof(buf));
98
2.92k
  RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
99
2.86k
  if (isc_buffer_usedlength(&b) > 0xffU) {
100
2
    RETTOK(ISC_R_RANGE);
101
2
  }
102
2.86k
  RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
103
2.86k
  RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b)));
104
105
2.86k
  return typemap_fromtext(lexer, target, true);
106
2.86k
}
107
108
static isc_result_t
109
4.74k
totext_nsec3(ARGS_TOTEXT) {
110
4.74k
  isc_region_t sr;
111
4.74k
  unsigned int i, j;
112
4.74k
  unsigned char hash;
113
4.74k
  unsigned char flags;
114
4.74k
  char buf[sizeof("TYPE65535")];
115
4.74k
  uint32_t iterations;
116
117
4.74k
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
118
4.74k
  REQUIRE(rdata->length != 0);
119
120
4.74k
  dns_rdata_toregion(rdata, &sr);
121
122
  /* Hash */
123
4.74k
  hash = uint8_fromregion(&sr);
124
4.74k
  isc_region_consume(&sr, 1);
125
4.74k
  snprintf(buf, sizeof(buf), "%u ", hash);
126
4.74k
  RETERR(str_totext(buf, target));
127
128
  /* Flags */
129
4.74k
  flags = uint8_fromregion(&sr);
130
4.74k
  isc_region_consume(&sr, 1);
131
4.74k
  snprintf(buf, sizeof(buf), "%u ", flags);
132
4.74k
  RETERR(str_totext(buf, target));
133
134
  /* Iterations */
135
4.74k
  iterations = uint16_fromregion(&sr);
136
4.74k
  isc_region_consume(&sr, 2);
137
4.74k
  snprintf(buf, sizeof(buf), "%u ", iterations);
138
4.74k
  RETERR(str_totext(buf, target));
139
140
  /* Salt */
141
4.74k
  j = uint8_fromregion(&sr);
142
4.74k
  isc_region_consume(&sr, 1);
143
4.74k
  INSIST(j <= sr.length);
144
145
4.74k
  if (j != 0) {
146
2.36k
    i = sr.length;
147
2.36k
    sr.length = j;
148
2.36k
    RETERR(isc_hex_totext(&sr, 1, "", target));
149
2.36k
    sr.length = i - j;
150
2.37k
  } else {
151
2.37k
    RETERR(str_totext("-", target));
152
2.37k
  }
153
154
4.74k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
155
84
    RETERR(str_totext(" (", target));
156
84
  }
157
4.74k
  RETERR(str_totext(tctx->linebreak, target));
158
159
  /* Next hash */
160
4.74k
  j = uint8_fromregion(&sr);
161
4.74k
  isc_region_consume(&sr, 1);
162
4.74k
  INSIST(j <= sr.length);
163
164
4.74k
  i = sr.length;
165
4.74k
  sr.length = j;
166
4.74k
  RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
167
4.74k
  sr.length = i - j;
168
169
  /*
170
   * Don't leave a trailing space when there's no typemap present.
171
   */
172
4.74k
  if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
173
1.74k
    RETERR(str_totext(" ", target));
174
1.74k
  }
175
4.74k
  RETERR(typemap_totext(&sr, tctx, target));
176
177
4.74k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
178
84
    RETERR(str_totext(" )", target));
179
84
  }
180
181
4.74k
  return ISC_R_SUCCESS;
182
4.74k
}
183
184
static isc_result_t
185
5.37k
fromwire_nsec3(ARGS_FROMWIRE) {
186
5.37k
  isc_region_t sr, rr;
187
5.37k
  unsigned int saltlen, hashlen;
188
189
5.37k
  REQUIRE(type == dns_rdatatype_nsec3);
190
191
5.37k
  UNUSED(type);
192
5.37k
  UNUSED(rdclass);
193
5.37k
  UNUSED(dctx);
194
195
5.37k
  isc_buffer_activeregion(source, &sr);
196
5.37k
  rr = sr;
197
198
  /* hash(1), flags(1), iteration(2), saltlen(1) */
199
5.37k
  if (sr.length < 5U) {
200
15
    RETERR(DNS_R_FORMERR);
201
0
  }
202
5.35k
  saltlen = sr.base[4];
203
5.35k
  isc_region_consume(&sr, 5);
204
205
5.35k
  if (sr.length < saltlen) {
206
12
    RETERR(DNS_R_FORMERR);
207
0
  }
208
5.34k
  isc_region_consume(&sr, saltlen);
209
210
5.34k
  if (sr.length < 1U) {
211
4
    RETERR(DNS_R_FORMERR);
212
0
  }
213
5.34k
  hashlen = sr.base[0];
214
5.34k
  isc_region_consume(&sr, 1);
215
216
5.34k
  if (hashlen < 1 || sr.length < hashlen) {
217
30
    RETERR(DNS_R_FORMERR);
218
0
  }
219
5.31k
  isc_region_consume(&sr, hashlen);
220
221
5.31k
  RETERR(typemap_test(&sr, true));
222
223
5.19k
  RETERR(mem_tobuffer(target, rr.base, rr.length));
224
5.04k
  isc_buffer_forward(source, rr.length);
225
5.04k
  return ISC_R_SUCCESS;
226
5.19k
}
227
228
static isc_result_t
229
2.38k
towire_nsec3(ARGS_TOWIRE) {
230
2.38k
  isc_region_t sr;
231
232
2.38k
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
233
2.38k
  REQUIRE(rdata->length != 0);
234
235
2.38k
  UNUSED(cctx);
236
237
2.38k
  dns_rdata_toregion(rdata, &sr);
238
2.38k
  return mem_tobuffer(target, sr.base, sr.length);
239
2.38k
}
240
241
static int
242
3.62k
compare_nsec3(ARGS_COMPARE) {
243
3.62k
  isc_region_t r1;
244
3.62k
  isc_region_t r2;
245
246
3.62k
  REQUIRE(rdata1->type == rdata2->type);
247
3.62k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
248
3.62k
  REQUIRE(rdata1->type == dns_rdatatype_nsec3);
249
3.62k
  REQUIRE(rdata1->length != 0);
250
3.62k
  REQUIRE(rdata2->length != 0);
251
252
3.62k
  dns_rdata_toregion(rdata1, &r1);
253
3.62k
  dns_rdata_toregion(rdata2, &r2);
254
3.62k
  return isc_region_compare(&r1, &r2);
255
3.62k
}
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
  DNS_RDATACOMMON_INIT(nsec3, rdata->type, rdata->rdclass);
296
297
0
  region.base = rdata->data;
298
0
  region.length = rdata->length;
299
0
  nsec3->hash = uint8_consume_fromregion(&region);
300
0
  nsec3->flags = uint8_consume_fromregion(&region);
301
0
  nsec3->iterations = uint16_consume_fromregion(&region);
302
303
0
  nsec3->salt_length = uint8_consume_fromregion(&region);
304
0
  INSIST(nsec3->salt_length <= region.length);
305
0
  nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
306
0
  isc_region_consume(&region, nsec3->salt_length);
307
308
0
  nsec3->next_length = uint8_consume_fromregion(&region);
309
0
  INSIST(nsec3->next_length <= region.length);
310
0
  nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
311
0
  isc_region_consume(&region, nsec3->next_length);
312
313
0
  nsec3->len = region.length;
314
0
  nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
315
0
  nsec3->mctx = mctx;
316
0
  return ISC_R_SUCCESS;
317
0
}
318
319
static void
320
0
freestruct_nsec3(ARGS_FREESTRUCT) {
321
0
  dns_rdata_nsec3_t *nsec3 = source;
322
323
0
  REQUIRE(nsec3 != NULL);
324
0
  REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3);
325
326
0
  if (nsec3->mctx == NULL) {
327
0
    return;
328
0
  }
329
330
0
  if (nsec3->salt != NULL) {
331
0
    isc_mem_free(nsec3->mctx, nsec3->salt);
332
0
  }
333
0
  if (nsec3->next != NULL) {
334
0
    isc_mem_free(nsec3->mctx, nsec3->next);
335
0
  }
336
0
  if (nsec3->typebits != NULL) {
337
0
    isc_mem_free(nsec3->mctx, nsec3->typebits);
338
0
  }
339
0
  nsec3->mctx = NULL;
340
0
}
341
342
static isc_result_t
343
0
additionaldata_nsec3(ARGS_ADDLDATA) {
344
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
345
346
0
  UNUSED(rdata);
347
0
  UNUSED(owner);
348
0
  UNUSED(add);
349
0
  UNUSED(arg);
350
351
0
  return ISC_R_SUCCESS;
352
0
}
353
354
static isc_result_t
355
0
digest_nsec3(ARGS_DIGEST) {
356
0
  isc_region_t r;
357
358
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
359
360
0
  dns_rdata_toregion(rdata, &r);
361
0
  return (digest)(arg, &r);
362
0
}
363
364
static bool
365
6.00k
checkowner_nsec3(ARGS_CHECKOWNER) {
366
6.00k
  unsigned char owner[NSEC3_MAX_HASH_LENGTH];
367
6.00k
  isc_buffer_t buffer;
368
6.00k
  dns_label_t label;
369
370
6.00k
  REQUIRE(type == dns_rdatatype_nsec3);
371
372
6.00k
  UNUSED(type);
373
6.00k
  UNUSED(rdclass);
374
6.00k
  UNUSED(wildcard);
375
376
  /*
377
   * First label is a base32hex string without padding.
378
   */
379
6.00k
  dns_name_getlabel(name, 0, &label);
380
6.00k
  isc_region_consume(&label, 1);
381
6.00k
  isc_buffer_init(&buffer, owner, sizeof(owner));
382
6.00k
  if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) {
383
5.99k
    return true;
384
5.99k
  }
385
386
16
  return false;
387
6.00k
}
388
389
static bool
390
0
checknames_nsec3(ARGS_CHECKNAMES) {
391
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
392
393
0
  UNUSED(rdata);
394
0
  UNUSED(owner);
395
0
  UNUSED(bad);
396
397
0
  return true;
398
0
}
399
400
static int
401
0
casecompare_nsec3(ARGS_COMPARE) {
402
0
  return compare_nsec3(rdata1, rdata2);
403
0
}
404
405
#endif /* RDATA_GENERIC_NSEC3_50_C */