Coverage Report

Created: 2026-02-09 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/unbound/validator/val_kentry.c
Line
Count
Source
1
/*
2
 * validator/val_kentry.c - validator key entry definition.
3
 *
4
 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5
 *
6
 * This software is open source.
7
 * 
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 
12
 * Redistributions of source code must retain the above copyright notice,
13
 * this list of conditions and the following disclaimer.
14
 * 
15
 * Redistributions in binary form must reproduce the above copyright notice,
16
 * this list of conditions and the following disclaimer in the documentation
17
 * and/or other materials provided with the distribution.
18
 * 
19
 * Neither the name of the NLNET LABS nor the names of its contributors may
20
 * be used to endorse or promote products derived from this software without
21
 * specific prior written permission.
22
 * 
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 */
35
36
/**
37
 * \file
38
 *
39
 * This file contains functions for dealing with validator key entries.
40
 */
41
#include "config.h"
42
#include "validator/val_kentry.h"
43
#include "util/data/packed_rrset.h"
44
#include "util/data/dname.h"
45
#include "util/storage/lookup3.h"
46
#include "util/regional.h"
47
#include "util/net_help.h"
48
#include "sldns/rrdef.h"
49
#include "sldns/keyraw.h"
50
51
size_t 
52
key_entry_sizefunc(void* key, void* data)
53
0
{
54
0
  struct key_entry_key* kk = (struct key_entry_key*)key;
55
0
  struct key_entry_data* kd = (struct key_entry_data*)data;
56
0
  size_t s = sizeof(*kk) + kk->namelen;
57
0
  s += sizeof(*kd) + lock_get_mem(&kk->entry.lock);
58
0
  if(kd->rrset_data)
59
0
    s += packed_rrset_sizeof(kd->rrset_data);
60
0
  if(kd->reason)
61
0
    s += strlen(kd->reason)+1;
62
0
  if(kd->algo)
63
0
    s += strlen((char*)kd->algo)+1;
64
0
  return s;
65
0
}
66
67
int 
68
key_entry_compfunc(void* k1, void* k2)
69
0
{
70
0
  struct key_entry_key* n1 = (struct key_entry_key*)k1;
71
0
  struct key_entry_key* n2 = (struct key_entry_key*)k2;
72
0
  if(n1->key_class != n2->key_class) {
73
0
    if(n1->key_class < n2->key_class)
74
0
      return -1;
75
0
    return 1;
76
0
  }
77
0
  return query_dname_compare(n1->name, n2->name);
78
0
}
79
80
void 
81
key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg))
82
0
{
83
0
  struct key_entry_key* kk = (struct key_entry_key*)key;
84
0
  if(!key)
85
0
    return;
86
0
  lock_rw_destroy(&kk->entry.lock);
87
0
  free(kk->name);
88
0
  free(kk);
89
0
}
90
91
void 
92
key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg))
93
0
{
94
0
  struct key_entry_data* kd = (struct key_entry_data*)data;
95
0
  free(kd->reason);
96
0
  free(kd->rrset_data);
97
0
  free(kd->algo);
98
0
  free(kd);
99
0
}
100
101
void 
102
key_entry_hash(struct key_entry_key* kk)
103
0
{
104
0
  kk->entry.hash = 0x654;
105
0
  kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), 
106
0
    kk->entry.hash);
107
0
  kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash);
108
0
}
109
110
struct key_entry_key* 
111
key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region)
112
0
{
113
0
  struct key_entry_key* newk;
114
0
  newk = regional_alloc_init(region, kkey, sizeof(*kkey));
115
0
  if(!newk)
116
0
    return NULL;
117
0
  newk->name = regional_alloc_init(region, kkey->name, kkey->namelen);
118
0
  if(!newk->name)
119
0
    return NULL;
120
0
  newk->entry.key = newk;
121
0
  if(newk->entry.data) {
122
    /* copy data element */
123
0
    struct key_entry_data *d = (struct key_entry_data*)
124
0
      kkey->entry.data;
125
0
    struct key_entry_data *newd;
126
0
    newd = regional_alloc_init(region, d, sizeof(*d));
127
0
    if(!newd)
128
0
      return NULL;
129
    /* copy rrset */
130
0
    if(d->rrset_data) {
131
0
      newd->rrset_data = regional_alloc_init(region,
132
0
        d->rrset_data, 
133
0
        packed_rrset_sizeof(d->rrset_data));
134
0
      if(!newd->rrset_data)
135
0
        return NULL;
136
0
      packed_rrset_ptr_fixup(newd->rrset_data);
137
0
    }
138
0
    if(d->reason) {
139
0
      newd->reason = regional_strdup(region, d->reason);
140
0
      if(!newd->reason)
141
0
        return NULL;
142
0
    }
143
0
    if(d->algo) {
144
0
      newd->algo = (uint8_t*)regional_strdup(region,
145
0
        (char*)d->algo);
146
0
      if(!newd->algo)
147
0
        return NULL;
148
0
    }
149
0
    newk->entry.data = newd;
150
0
  }
151
0
  return newk;
152
0
}
153
154
struct key_entry_key* 
155
key_entry_copy(struct key_entry_key* kkey, int copy_reason)
156
0
{
157
0
  struct key_entry_key* newk;
158
0
  if(!kkey)
159
0
    return NULL;
160
0
  newk = memdup(kkey, sizeof(*kkey));
161
0
  if(!newk)
162
0
    return NULL;
163
0
  newk->name = memdup(kkey->name, kkey->namelen);
164
0
  if(!newk->name) {
165
0
    free(newk);
166
0
    return NULL;
167
0
  }
168
0
  lock_rw_init(&newk->entry.lock);
169
0
  newk->entry.key = newk;
170
0
  if(newk->entry.data) {
171
    /* copy data element */
172
0
    struct key_entry_data *d = (struct key_entry_data*)
173
0
      kkey->entry.data;
174
0
    struct key_entry_data *newd;
175
0
    newd = memdup(d, sizeof(*d));
176
0
    if(!newd) {
177
0
      free(newk->name);
178
0
      free(newk);
179
0
      return NULL;
180
0
    }
181
    /* copy rrset */
182
0
    if(d->rrset_data) {
183
0
      newd->rrset_data = memdup(d->rrset_data, 
184
0
        packed_rrset_sizeof(d->rrset_data));
185
0
      if(!newd->rrset_data) {
186
0
        free(newd);
187
0
        free(newk->name);
188
0
        free(newk);
189
0
        return NULL;
190
0
      }
191
0
      packed_rrset_ptr_fixup(newd->rrset_data);
192
0
    }
193
0
    if(copy_reason && d->reason && *d->reason != 0) {
194
0
      newd->reason = strdup(d->reason);
195
0
      if(!newd->reason) {
196
0
        free(newd->rrset_data);
197
0
        free(newd);
198
0
        free(newk->name);
199
0
        free(newk);
200
0
        return NULL;
201
0
      }
202
0
    } else {
203
0
      newd->reason = NULL;
204
0
    }
205
0
    if(d->algo) {
206
0
      newd->algo = (uint8_t*)strdup((char*)d->algo);
207
0
      if(!newd->algo) {
208
0
        free(newd->rrset_data);
209
0
        free(newd->reason);
210
0
        free(newd);
211
0
        free(newk->name);
212
0
        free(newk);
213
0
        return NULL;
214
0
      }
215
0
    }
216
0
    newk->entry.data = newd;
217
0
  }
218
0
  return newk;
219
0
}
220
221
int 
222
key_entry_isnull(struct key_entry_key* kkey)
223
0
{
224
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
225
0
  return (!d->isbad && d->rrset_data == NULL);
226
0
}
227
228
int 
229
key_entry_isgood(struct key_entry_key* kkey)
230
0
{
231
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
232
0
  return (!d->isbad && d->rrset_data != NULL);
233
0
}
234
235
int 
236
key_entry_isbad(struct key_entry_key* kkey)
237
0
{
238
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
239
0
  return (int)(d->isbad);
240
0
}
241
242
char*
243
key_entry_get_reason(struct key_entry_key* kkey)
244
0
{
245
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
246
0
  return d->reason;
247
0
}
248
249
sldns_ede_code
250
key_entry_get_reason_bogus(struct key_entry_key* kkey)
251
0
{
252
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
253
0
  return d->reason_bogus;
254
255
0
}
256
257
/** setup key entry in region */
258
static int
259
key_entry_setup(struct regional* region,
260
  uint8_t* name, size_t namelen, uint16_t dclass, 
261
  struct key_entry_key** k, struct key_entry_data** d)
262
0
{
263
0
  *k = regional_alloc(region, sizeof(**k));
264
0
  if(!*k)
265
0
    return 0;
266
0
  memset(*k, 0, sizeof(**k));
267
0
  (*k)->entry.key = *k;
268
0
  (*k)->name = regional_alloc_init(region, name, namelen);
269
0
  if(!(*k)->name)
270
0
    return 0;
271
0
  (*k)->namelen = namelen;
272
0
  (*k)->key_class = dclass;
273
0
  *d = regional_alloc(region, sizeof(**d));
274
0
  if(!*d)
275
0
    return 0;
276
0
  (*k)->entry.data = *d;
277
0
  return 1;
278
0
}
279
280
struct key_entry_key* 
281
key_entry_create_null(struct regional* region,
282
  uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
283
  sldns_ede_code reason_bogus, const char* reason,
284
  time_t now)
285
0
{
286
0
  struct key_entry_key* k;
287
0
  struct key_entry_data* d;
288
0
  if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
289
0
    return NULL;
290
0
  d->ttl = now + ttl;
291
0
  d->isbad = 0;
292
0
  d->reason = (!reason || *reason == 0)
293
0
    ?NULL :(char*)regional_strdup(region, reason);
294
    /* On allocation error we don't store the reason string */
295
0
  d->reason_bogus = reason_bogus;
296
0
  d->rrset_type = LDNS_RR_TYPE_DNSKEY;
297
0
  d->rrset_data = NULL;
298
0
  d->algo = NULL;
299
0
  return k;
300
0
}
301
302
struct key_entry_key* 
303
key_entry_create_rrset(struct regional* region,
304
  uint8_t* name, size_t namelen, uint16_t dclass,
305
  struct ub_packed_rrset_key* rrset, uint8_t* sigalg,
306
  sldns_ede_code reason_bogus, const char* reason,
307
  time_t now)
308
0
{
309
0
  struct key_entry_key* k;
310
0
  struct key_entry_data* d;
311
0
  struct packed_rrset_data* rd = (struct packed_rrset_data*)
312
0
    rrset->entry.data;
313
0
  if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
314
0
    return NULL;
315
0
  d->ttl = rd->ttl + now;
316
0
  d->isbad = 0;
317
0
  d->reason = (!reason || *reason == 0)
318
0
    ?NULL :(char*)regional_strdup(region, reason);
319
    /* On allocation error we don't store the reason string */
320
0
  d->reason_bogus = reason_bogus;
321
0
  d->rrset_type = ntohs(rrset->rk.type);
322
0
  d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
323
0
    rd, packed_rrset_sizeof(rd));
324
0
  if(!d->rrset_data)
325
0
    return NULL;
326
0
  if(sigalg) {
327
0
    d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
328
0
    if(!d->algo)
329
0
      return NULL;
330
0
  } else d->algo = NULL;
331
0
  packed_rrset_ptr_fixup(d->rrset_data);
332
0
  return k;
333
0
}
334
335
struct key_entry_key* 
336
key_entry_create_bad(struct regional* region,
337
  uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
338
  sldns_ede_code reason_bogus, const char* reason,
339
  time_t now)
340
0
{
341
0
  struct key_entry_key* k;
342
0
  struct key_entry_data* d;
343
0
  if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
344
0
    return NULL;
345
0
  d->ttl = now + ttl;
346
0
  d->isbad = 1;
347
0
  d->reason = (!reason || *reason == 0)
348
0
    ?NULL :(char*)regional_strdup(region, reason);
349
    /* On allocation error we don't store the reason string */
350
0
  d->reason_bogus = reason_bogus;
351
0
  d->rrset_type = LDNS_RR_TYPE_DNSKEY;
352
0
  d->rrset_data = NULL;
353
0
  d->algo = NULL;
354
0
  return k;
355
0
}
356
357
struct ub_packed_rrset_key* 
358
key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region)
359
0
{
360
0
  struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
361
0
  struct ub_packed_rrset_key* rrk;
362
0
  struct packed_rrset_data* rrd;
363
0
  if(!d || !d->rrset_data)
364
0
    return NULL;
365
0
  rrk = regional_alloc(region, sizeof(*rrk));
366
0
  if(!rrk)
367
0
    return NULL;
368
0
  memset(rrk, 0, sizeof(*rrk));
369
0
  rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen);
370
0
  if(!rrk->rk.dname)
371
0
    return NULL;
372
0
  rrk->rk.dname_len = kkey->namelen;
373
0
  rrk->rk.type = htons(d->rrset_type);
374
0
  rrk->rk.rrset_class = htons(kkey->key_class);
375
0
  rrk->entry.key = rrk;
376
0
  rrd = regional_alloc_init(region, d->rrset_data, 
377
0
    packed_rrset_sizeof(d->rrset_data));
378
0
  if(!rrd)
379
0
    return NULL;
380
0
  rrk->entry.data = rrd;
381
0
  packed_rrset_ptr_fixup(rrd);
382
0
  return rrk;
383
0
}
384
385
/** Get size of key in keyset */
386
static size_t
387
dnskey_get_keysize(struct packed_rrset_data* data, size_t idx)
388
0
{
389
0
  unsigned char* pk;
390
0
  unsigned int pklen = 0;
391
0
  int algo;
392
0
  if(data->rr_len[idx] < 2+5)
393
0
    return 0;
394
0
  algo = (int)data->rr_data[idx][2+3];
395
0
  pk = (unsigned char*)data->rr_data[idx]+2+4;
396
0
  pklen = (unsigned)data->rr_len[idx]-2-4;
397
0
  return sldns_rr_dnskey_key_size_raw(pk, pklen, algo);
398
0
}
399
400
/** get dnskey flags from data */
401
static uint16_t
402
kd_get_flags(struct packed_rrset_data* data, size_t idx)
403
0
{
404
0
  uint16_t f;
405
0
  if(data->rr_len[idx] < 2+2)
406
0
    return 0;
407
0
  memmove(&f, data->rr_data[idx]+2, 2);
408
0
  f = ntohs(f);
409
0
  return f;
410
0
}
411
412
size_t 
413
key_entry_keysize(struct key_entry_key* kkey)
414
0
{
415
0
  struct packed_rrset_data* d;
416
  /* compute size of smallest ZSK key in the rrset */
417
0
  size_t i;
418
0
  size_t bits = 0;
419
0
  if(!key_entry_isgood(kkey))
420
0
    return 0;
421
0
  d = ((struct key_entry_data*)kkey->entry.data)->rrset_data;
422
0
  for(i=0; i<d->count; i++) {
423
0
    if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK))
424
0
      continue;
425
0
    if(i==0 || dnskey_get_keysize(d, i) < bits)
426
0
      bits = dnskey_get_keysize(d, i);
427
0
  }
428
0
  return bits;
429
0
}