1238106Sdes/*
2238106Sdes * validator/val_kentry.c - validator key entry definition.
3238106Sdes *
4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved.
5238106Sdes *
6238106Sdes * This software is open source.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes *
12238106Sdes * Redistributions of source code must retain the above copyright notice,
13238106Sdes * this list of conditions and the following disclaimer.
14238106Sdes *
15238106Sdes * Redistributions in binary form must reproduce the above copyright notice,
16238106Sdes * this list of conditions and the following disclaimer in the documentation
17238106Sdes * and/or other materials provided with the distribution.
18238106Sdes *
19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20238106Sdes * be used to endorse or promote products derived from this software without
21238106Sdes * specific prior written permission.
22238106Sdes *
23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34238106Sdes */
35238106Sdes
36238106Sdes/**
37238106Sdes * \file
38238106Sdes *
39238106Sdes * This file contains functions for dealing with validator key entries.
40238106Sdes */
41238106Sdes#include "config.h"
42238106Sdes#include "validator/val_kentry.h"
43238106Sdes#include "util/data/packed_rrset.h"
44238106Sdes#include "util/data/dname.h"
45238106Sdes#include "util/storage/lookup3.h"
46238106Sdes#include "util/regional.h"
47238106Sdes#include "util/net_help.h"
48287917Sdes#include "sldns/rrdef.h"
49287917Sdes#include "sldns/keyraw.h"
50238106Sdes
51238106Sdessize_t
52238106Sdeskey_entry_sizefunc(void* key, void* data)
53238106Sdes{
54238106Sdes	struct key_entry_key* kk = (struct key_entry_key*)key;
55238106Sdes	struct key_entry_data* kd = (struct key_entry_data*)data;
56238106Sdes	size_t s = sizeof(*kk) + kk->namelen;
57238106Sdes	s += sizeof(*kd) + lock_get_mem(&kk->entry.lock);
58238106Sdes	if(kd->rrset_data)
59238106Sdes		s += packed_rrset_sizeof(kd->rrset_data);
60238106Sdes	if(kd->reason)
61238106Sdes		s += strlen(kd->reason)+1;
62238106Sdes	if(kd->algo)
63238106Sdes		s += strlen((char*)kd->algo)+1;
64238106Sdes	return s;
65238106Sdes}
66238106Sdes
67238106Sdesint
68238106Sdeskey_entry_compfunc(void* k1, void* k2)
69238106Sdes{
70238106Sdes	struct key_entry_key* n1 = (struct key_entry_key*)k1;
71238106Sdes	struct key_entry_key* n2 = (struct key_entry_key*)k2;
72238106Sdes	if(n1->key_class != n2->key_class) {
73238106Sdes		if(n1->key_class < n2->key_class)
74238106Sdes			return -1;
75238106Sdes		return 1;
76238106Sdes	}
77238106Sdes	return query_dname_compare(n1->name, n2->name);
78238106Sdes}
79238106Sdes
80238106Sdesvoid
81238106Sdeskey_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg))
82238106Sdes{
83238106Sdes	struct key_entry_key* kk = (struct key_entry_key*)key;
84238106Sdes	if(!key)
85238106Sdes		return;
86238106Sdes	lock_rw_destroy(&kk->entry.lock);
87238106Sdes	free(kk->name);
88238106Sdes	free(kk);
89238106Sdes}
90238106Sdes
91238106Sdesvoid
92238106Sdeskey_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg))
93238106Sdes{
94238106Sdes	struct key_entry_data* kd = (struct key_entry_data*)data;
95238106Sdes	free(kd->reason);
96238106Sdes	free(kd->rrset_data);
97238106Sdes	free(kd->algo);
98238106Sdes	free(kd);
99238106Sdes}
100238106Sdes
101238106Sdesvoid
102238106Sdeskey_entry_hash(struct key_entry_key* kk)
103238106Sdes{
104238106Sdes	kk->entry.hash = 0x654;
105238106Sdes	kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class),
106238106Sdes		kk->entry.hash);
107238106Sdes	kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash);
108238106Sdes}
109238106Sdes
110238106Sdesstruct key_entry_key*
111238106Sdeskey_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region)
112238106Sdes{
113238106Sdes	struct key_entry_key* newk;
114238106Sdes	newk = regional_alloc_init(region, kkey, sizeof(*kkey));
115238106Sdes	if(!newk)
116238106Sdes		return NULL;
117238106Sdes	newk->name = regional_alloc_init(region, kkey->name, kkey->namelen);
118238106Sdes	if(!newk->name)
119238106Sdes		return NULL;
120238106Sdes	newk->entry.key = newk;
121238106Sdes	if(newk->entry.data) {
122238106Sdes		/* copy data element */
123238106Sdes		struct key_entry_data *d = (struct key_entry_data*)
124238106Sdes			kkey->entry.data;
125238106Sdes		struct key_entry_data *newd;
126238106Sdes		newd = regional_alloc_init(region, d, sizeof(*d));
127238106Sdes		if(!newd)
128238106Sdes			return NULL;
129238106Sdes		/* copy rrset */
130238106Sdes		if(d->rrset_data) {
131238106Sdes			newd->rrset_data = regional_alloc_init(region,
132238106Sdes				d->rrset_data,
133238106Sdes				packed_rrset_sizeof(d->rrset_data));
134238106Sdes			if(!newd->rrset_data)
135238106Sdes				return NULL;
136238106Sdes			packed_rrset_ptr_fixup(newd->rrset_data);
137238106Sdes		}
138238106Sdes		if(d->reason) {
139238106Sdes			newd->reason = regional_strdup(region, d->reason);
140238106Sdes			if(!newd->reason)
141238106Sdes				return NULL;
142238106Sdes		}
143238106Sdes		if(d->algo) {
144238106Sdes			newd->algo = (uint8_t*)regional_strdup(region,
145238106Sdes				(char*)d->algo);
146238106Sdes			if(!newd->algo)
147238106Sdes				return NULL;
148238106Sdes		}
149238106Sdes		newk->entry.data = newd;
150238106Sdes	}
151238106Sdes	return newk;
152238106Sdes}
153238106Sdes
154238106Sdesstruct key_entry_key*
155238106Sdeskey_entry_copy(struct key_entry_key* kkey)
156238106Sdes{
157238106Sdes	struct key_entry_key* newk;
158238106Sdes	if(!kkey)
159238106Sdes		return NULL;
160238106Sdes	newk = memdup(kkey, sizeof(*kkey));
161238106Sdes	if(!newk)
162238106Sdes		return NULL;
163238106Sdes	newk->name = memdup(kkey->name, kkey->namelen);
164238106Sdes	if(!newk->name) {
165238106Sdes		free(newk);
166238106Sdes		return NULL;
167238106Sdes	}
168238106Sdes	lock_rw_init(&newk->entry.lock);
169238106Sdes	newk->entry.key = newk;
170238106Sdes	if(newk->entry.data) {
171238106Sdes		/* copy data element */
172238106Sdes		struct key_entry_data *d = (struct key_entry_data*)
173238106Sdes			kkey->entry.data;
174238106Sdes		struct key_entry_data *newd;
175238106Sdes		newd = memdup(d, sizeof(*d));
176238106Sdes		if(!newd) {
177238106Sdes			free(newk->name);
178238106Sdes			free(newk);
179238106Sdes			return NULL;
180238106Sdes		}
181238106Sdes		/* copy rrset */
182238106Sdes		if(d->rrset_data) {
183238106Sdes			newd->rrset_data = memdup(d->rrset_data,
184238106Sdes				packed_rrset_sizeof(d->rrset_data));
185238106Sdes			if(!newd->rrset_data) {
186238106Sdes				free(newd);
187238106Sdes				free(newk->name);
188238106Sdes				free(newk);
189238106Sdes				return NULL;
190238106Sdes			}
191238106Sdes			packed_rrset_ptr_fixup(newd->rrset_data);
192238106Sdes		}
193238106Sdes		if(d->reason) {
194238106Sdes			newd->reason = strdup(d->reason);
195238106Sdes			if(!newd->reason) {
196238106Sdes				free(newd->rrset_data);
197238106Sdes				free(newd);
198238106Sdes				free(newk->name);
199238106Sdes				free(newk);
200238106Sdes				return NULL;
201238106Sdes			}
202238106Sdes		}
203238106Sdes		if(d->algo) {
204238106Sdes			newd->algo = (uint8_t*)strdup((char*)d->algo);
205238106Sdes			if(!newd->algo) {
206238106Sdes				free(newd->rrset_data);
207238106Sdes				free(newd->reason);
208238106Sdes				free(newd);
209238106Sdes				free(newk->name);
210238106Sdes				free(newk);
211238106Sdes				return NULL;
212238106Sdes			}
213238106Sdes		}
214238106Sdes		newk->entry.data = newd;
215238106Sdes	}
216238106Sdes	return newk;
217238106Sdes}
218238106Sdes
219238106Sdesint
220238106Sdeskey_entry_isnull(struct key_entry_key* kkey)
221238106Sdes{
222238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
223238106Sdes	return (!d->isbad && d->rrset_data == NULL);
224238106Sdes}
225238106Sdes
226238106Sdesint
227238106Sdeskey_entry_isgood(struct key_entry_key* kkey)
228238106Sdes{
229238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
230238106Sdes	return (!d->isbad && d->rrset_data != NULL);
231238106Sdes}
232238106Sdes
233238106Sdesint
234238106Sdeskey_entry_isbad(struct key_entry_key* kkey)
235238106Sdes{
236238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
237238106Sdes	return (int)(d->isbad);
238238106Sdes}
239238106Sdes
240238106Sdesvoid
241238106Sdeskey_entry_set_reason(struct key_entry_key* kkey, char* reason)
242238106Sdes{
243238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
244238106Sdes	d->reason = reason;
245238106Sdes}
246238106Sdes
247238106Sdeschar*
248238106Sdeskey_entry_get_reason(struct key_entry_key* kkey)
249238106Sdes{
250238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
251238106Sdes	return d->reason;
252238106Sdes}
253238106Sdes
254238106Sdes/** setup key entry in region */
255238106Sdesstatic int
256238106Sdeskey_entry_setup(struct regional* region,
257238106Sdes	uint8_t* name, size_t namelen, uint16_t dclass,
258238106Sdes	struct key_entry_key** k, struct key_entry_data** d)
259238106Sdes{
260238106Sdes	*k = regional_alloc(region, sizeof(**k));
261238106Sdes	if(!*k)
262238106Sdes		return 0;
263238106Sdes	memset(*k, 0, sizeof(**k));
264238106Sdes	(*k)->entry.key = *k;
265238106Sdes	(*k)->name = regional_alloc_init(region, name, namelen);
266238106Sdes	if(!(*k)->name)
267238106Sdes		return 0;
268238106Sdes	(*k)->namelen = namelen;
269238106Sdes	(*k)->key_class = dclass;
270238106Sdes	*d = regional_alloc(region, sizeof(**d));
271238106Sdes	if(!*d)
272238106Sdes		return 0;
273238106Sdes	(*k)->entry.data = *d;
274238106Sdes	return 1;
275238106Sdes}
276238106Sdes
277238106Sdesstruct key_entry_key*
278238106Sdeskey_entry_create_null(struct regional* region,
279266114Sdes	uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
280266114Sdes	time_t now)
281238106Sdes{
282238106Sdes	struct key_entry_key* k;
283238106Sdes	struct key_entry_data* d;
284238106Sdes	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
285238106Sdes		return NULL;
286238106Sdes	d->ttl = now + ttl;
287238106Sdes	d->isbad = 0;
288238106Sdes	d->reason = NULL;
289238106Sdes	d->rrset_type = LDNS_RR_TYPE_DNSKEY;
290238106Sdes	d->rrset_data = NULL;
291238106Sdes	d->algo = NULL;
292238106Sdes	return k;
293238106Sdes}
294238106Sdes
295238106Sdesstruct key_entry_key*
296238106Sdeskey_entry_create_rrset(struct regional* region,
297238106Sdes	uint8_t* name, size_t namelen, uint16_t dclass,
298266114Sdes	struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now)
299238106Sdes{
300238106Sdes	struct key_entry_key* k;
301238106Sdes	struct key_entry_data* d;
302238106Sdes	struct packed_rrset_data* rd = (struct packed_rrset_data*)
303238106Sdes		rrset->entry.data;
304238106Sdes	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
305238106Sdes		return NULL;
306238106Sdes	d->ttl = rd->ttl + now;
307238106Sdes	d->isbad = 0;
308238106Sdes	d->reason = NULL;
309238106Sdes	d->rrset_type = ntohs(rrset->rk.type);
310238106Sdes	d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
311238106Sdes		rd, packed_rrset_sizeof(rd));
312238106Sdes	if(!d->rrset_data)
313238106Sdes		return NULL;
314238106Sdes	if(sigalg) {
315238106Sdes		d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
316238106Sdes		if(!d->algo)
317238106Sdes			return NULL;
318238106Sdes	} else d->algo = NULL;
319238106Sdes	packed_rrset_ptr_fixup(d->rrset_data);
320238106Sdes	return k;
321238106Sdes}
322238106Sdes
323238106Sdesstruct key_entry_key*
324238106Sdeskey_entry_create_bad(struct regional* region,
325266114Sdes	uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
326266114Sdes	time_t now)
327238106Sdes{
328238106Sdes	struct key_entry_key* k;
329238106Sdes	struct key_entry_data* d;
330238106Sdes	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
331238106Sdes		return NULL;
332238106Sdes	d->ttl = now + ttl;
333238106Sdes	d->isbad = 1;
334238106Sdes	d->reason = NULL;
335238106Sdes	d->rrset_type = LDNS_RR_TYPE_DNSKEY;
336238106Sdes	d->rrset_data = NULL;
337238106Sdes	d->algo = NULL;
338238106Sdes	return k;
339238106Sdes}
340238106Sdes
341238106Sdesstruct ub_packed_rrset_key*
342238106Sdeskey_entry_get_rrset(struct key_entry_key* kkey, struct regional* region)
343238106Sdes{
344238106Sdes	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
345238106Sdes	struct ub_packed_rrset_key* rrk;
346238106Sdes	struct packed_rrset_data* rrd;
347238106Sdes	if(!d || !d->rrset_data)
348238106Sdes		return NULL;
349238106Sdes	rrk = regional_alloc(region, sizeof(*rrk));
350238106Sdes	if(!rrk)
351238106Sdes		return NULL;
352238106Sdes	memset(rrk, 0, sizeof(*rrk));
353238106Sdes	rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen);
354238106Sdes	if(!rrk->rk.dname)
355238106Sdes		return NULL;
356238106Sdes	rrk->rk.dname_len = kkey->namelen;
357238106Sdes	rrk->rk.type = htons(d->rrset_type);
358238106Sdes	rrk->rk.rrset_class = htons(kkey->key_class);
359238106Sdes	rrk->entry.key = rrk;
360238106Sdes	rrd = regional_alloc_init(region, d->rrset_data,
361238106Sdes		packed_rrset_sizeof(d->rrset_data));
362238106Sdes	if(!rrd)
363238106Sdes		return NULL;
364238106Sdes	rrk->entry.data = rrd;
365238106Sdes	packed_rrset_ptr_fixup(rrd);
366238106Sdes	return rrk;
367238106Sdes}
368238106Sdes
369238106Sdes/** Get size of key in keyset */
370238106Sdesstatic size_t
371238106Sdesdnskey_get_keysize(struct packed_rrset_data* data, size_t idx)
372238106Sdes{
373238106Sdes	unsigned char* pk;
374238106Sdes	unsigned int pklen = 0;
375238106Sdes	int algo;
376238106Sdes	if(data->rr_len[idx] < 2+5)
377238106Sdes		return 0;
378238106Sdes	algo = (int)data->rr_data[idx][2+3];
379238106Sdes	pk = (unsigned char*)data->rr_data[idx]+2+4;
380238106Sdes	pklen = (unsigned)data->rr_len[idx]-2-4;
381266114Sdes	return sldns_rr_dnskey_key_size_raw(pk, pklen, algo);
382238106Sdes}
383238106Sdes
384238106Sdes/** get dnskey flags from data */
385238106Sdesstatic uint16_t
386238106Sdeskd_get_flags(struct packed_rrset_data* data, size_t idx)
387238106Sdes{
388238106Sdes	uint16_t f;
389238106Sdes	if(data->rr_len[idx] < 2+2)
390238106Sdes		return 0;
391238106Sdes	memmove(&f, data->rr_data[idx]+2, 2);
392238106Sdes	f = ntohs(f);
393238106Sdes	return f;
394238106Sdes}
395238106Sdes
396238106Sdessize_t
397238106Sdeskey_entry_keysize(struct key_entry_key* kkey)
398238106Sdes{
399238106Sdes	struct packed_rrset_data* d;
400238106Sdes	/* compute size of smallest ZSK key in the rrset */
401238106Sdes	size_t i;
402238106Sdes	size_t bits = 0;
403238106Sdes	if(!key_entry_isgood(kkey))
404238106Sdes		return 0;
405238106Sdes	d = ((struct key_entry_data*)kkey->entry.data)->rrset_data;
406238106Sdes	for(i=0; i<d->count; i++) {
407238106Sdes		if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK))
408238106Sdes			continue;
409238106Sdes		if(i==0 || dnskey_get_keysize(d, i) < bits)
410238106Sdes			bits = dnskey_get_keysize(d, i);
411238106Sdes	}
412238106Sdes	return bits;
413238106Sdes}
414