keydata_65533.c revision 1.3
1/*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef GENERIC_KEYDATA_65533_C
18#define GENERIC_KEYDATA_65533_C 1
19
20#include <isc/time.h>
21#include <isc/stdtime.h>
22
23#include <dst/dst.h>
24
25#define RRTYPE_KEYDATA_ATTRIBUTES (0)
26
27static inline isc_result_t
28fromtext_keydata(ARGS_FROMTEXT) {
29	isc_result_t result;
30	isc_token_t token;
31	dns_secalg_t alg;
32	dns_secproto_t proto;
33	dns_keyflags_t flags;
34	uint32_t refresh, addhd, removehd;
35
36	REQUIRE(type == dns_rdatatype_keydata);
37
38	UNUSED(type);
39	UNUSED(rdclass);
40	UNUSED(origin);
41	UNUSED(options);
42	UNUSED(callbacks);
43
44	/* refresh timer */
45	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
46				      ISC_FALSE));
47	RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh));
48	RETERR(uint32_tobuffer(refresh, target));
49
50	/* add hold-down */
51	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
52				      ISC_FALSE));
53	RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd));
54	RETERR(uint32_tobuffer(addhd, target));
55
56	/* remove hold-down */
57	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
58				      ISC_FALSE));
59	RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd));
60	RETERR(uint32_tobuffer(removehd, target));
61
62	/* flags */
63	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
64				      ISC_FALSE));
65	RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
66	RETERR(uint16_tobuffer(flags, target));
67
68	/* protocol */
69	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
70				      ISC_FALSE));
71	RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
72	RETERR(mem_tobuffer(target, &proto, 1));
73
74	/* algorithm */
75	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
76				      ISC_FALSE));
77	RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
78	RETERR(mem_tobuffer(target, &alg, 1));
79
80	/* No Key? */
81	if ((flags & 0xc000) == 0xc000)
82		return (ISC_R_SUCCESS);
83
84	result = isc_base64_tobuffer(lexer, target, -1);
85	if (result != ISC_R_SUCCESS)
86		return (result);
87
88	/* Ensure there's at least enough data to compute a key ID for MD5 */
89	if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 19)
90		return (ISC_R_UNEXPECTEDEND);
91
92	return (ISC_R_SUCCESS);
93}
94
95static inline isc_result_t
96totext_keydata(ARGS_TOTEXT) {
97	isc_region_t sr;
98	char buf[sizeof("64000")];
99	unsigned int flags;
100	unsigned char algorithm;
101	unsigned long refresh, add, deltime;
102	char algbuf[DNS_NAME_FORMATSIZE];
103	const char *keyinfo;
104
105	REQUIRE(rdata->type == dns_rdatatype_keydata);
106
107	if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16)
108		return (unknown_totext(rdata, tctx, target));
109
110	dns_rdata_toregion(rdata, &sr);
111
112	/* refresh timer */
113	refresh = uint32_fromregion(&sr);
114	isc_region_consume(&sr, 4);
115	RETERR(dns_time32_totext(refresh, target));
116	RETERR(str_totext(" ", target));
117
118	/* add hold-down */
119	add = uint32_fromregion(&sr);
120	isc_region_consume(&sr, 4);
121	RETERR(dns_time32_totext(add, target));
122	RETERR(str_totext(" ", target));
123
124	/* remove hold-down */
125	deltime = uint32_fromregion(&sr);
126	isc_region_consume(&sr, 4);
127	RETERR(dns_time32_totext(deltime, target));
128	RETERR(str_totext(" ", target));
129
130	/* flags */
131	flags = uint16_fromregion(&sr);
132	isc_region_consume(&sr, 2);
133	snprintf(buf, sizeof(buf), "%u", flags);
134	RETERR(str_totext(buf, target));
135	RETERR(str_totext(" ", target));
136	if ((flags & DNS_KEYFLAG_KSK) != 0) {
137		if (flags & DNS_KEYFLAG_REVOKE)
138			keyinfo = "revoked KSK";
139		else
140			keyinfo = "KSK";
141	} else
142		keyinfo = "ZSK";
143
144	/* protocol */
145	snprintf(buf, sizeof(buf), "%u", sr.base[0]);
146	isc_region_consume(&sr, 1);
147	RETERR(str_totext(buf, target));
148	RETERR(str_totext(" ", target));
149
150	/* algorithm */
151	algorithm = sr.base[0];
152	snprintf(buf, sizeof(buf), "%u", algorithm);
153	isc_region_consume(&sr, 1);
154	RETERR(str_totext(buf, target));
155
156	/* No Key? */
157	if ((flags & 0xc000) == 0xc000)
158		return (ISC_R_SUCCESS);
159
160	/* key */
161	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
162		RETERR(str_totext(" (", target));
163	RETERR(str_totext(tctx->linebreak, target));
164	if (tctx->width == 0)   /* No splitting */
165		RETERR(isc_base64_totext(&sr, 60, "", target));
166	else
167		RETERR(isc_base64_totext(&sr, tctx->width - 2,
168					 tctx->linebreak, target));
169
170	if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0)
171		RETERR(str_totext(tctx->linebreak, target));
172	else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
173		RETERR(str_totext(" ", target));
174
175	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
176		RETERR(str_totext(")", target));
177
178	if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
179		isc_region_t tmpr;
180		char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
181		char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
182		char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
183		struct timespec t;
184
185		RETERR(str_totext(" ; ", target));
186		RETERR(str_totext(keyinfo, target));
187		dns_secalg_format((dns_secalg_t) algorithm, algbuf,
188				  sizeof(algbuf));
189		RETERR(str_totext("; alg = ", target));
190		RETERR(str_totext(algbuf, target));
191		RETERR(str_totext("; key id = ", target));
192		dns_rdata_toregion(rdata, &tmpr);
193		/* Skip over refresh, addhd, and removehd */
194		isc_region_consume(&tmpr, 12);
195		snprintf(buf, sizeof(buf), "%u",
196			 dst_region_computeid(&tmpr, algorithm));
197		RETERR(str_totext(buf, target));
198
199		if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
200			isc_stdtime_t now;
201
202			isc_stdtime_get(&now);
203
204			RETERR(str_totext(tctx->linebreak, target));
205			RETERR(str_totext("; next refresh: ", target));
206			t.tv_sec = refresh;
207			t.tv_nsec = 0;
208			isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf));
209			RETERR(str_totext(rbuf, target));
210
211			if (add == 0U) {
212				RETERR(str_totext(tctx->linebreak, target));
213				RETERR(str_totext("; no trust", target));
214			} else {
215				RETERR(str_totext(tctx->linebreak, target));
216				if (add < now) {
217					RETERR(str_totext("; trusted since: ",
218							  target));
219				} else {
220					RETERR(str_totext("; trust pending: ",
221							  target));
222				}
223				t.tv_sec = add;
224				t.tv_nsec = 0;
225				isc_time_formathttptimestamp(&t, abuf,
226							     sizeof(abuf));
227				RETERR(str_totext(abuf, target));
228			}
229
230			if (deltime != 0U) {
231				RETERR(str_totext(tctx->linebreak, target));
232				RETERR(str_totext("; removal pending: ",
233						  target));
234				t.tv_sec = deltime;
235				t.tv_nsec = 0;
236				isc_time_formathttptimestamp(&t, dbuf,
237							     sizeof(dbuf));
238				RETERR(str_totext(dbuf, target));
239			}
240		}
241
242	}
243	return (ISC_R_SUCCESS);
244}
245
246static inline isc_result_t
247fromwire_keydata(ARGS_FROMWIRE) {
248	isc_region_t sr;
249
250	REQUIRE(type == dns_rdatatype_keydata);
251
252	UNUSED(type);
253	UNUSED(rdclass);
254	UNUSED(dctx);
255	UNUSED(options);
256
257	isc_buffer_activeregion(source, &sr);
258	isc_buffer_forward(source, sr.length);
259	return (mem_tobuffer(target, sr.base, sr.length));
260}
261
262static inline isc_result_t
263towire_keydata(ARGS_TOWIRE) {
264	isc_region_t sr;
265
266	REQUIRE(rdata->type == dns_rdatatype_keydata);
267
268	UNUSED(cctx);
269
270	dns_rdata_toregion(rdata, &sr);
271	return (mem_tobuffer(target, sr.base, sr.length));
272}
273
274static inline int
275compare_keydata(ARGS_COMPARE) {
276	isc_region_t r1;
277	isc_region_t r2;
278
279	REQUIRE(rdata1->type == rdata2->type);
280	REQUIRE(rdata1->rdclass == rdata2->rdclass);
281	REQUIRE(rdata1->type == dns_rdatatype_keydata);
282
283	dns_rdata_toregion(rdata1, &r1);
284	dns_rdata_toregion(rdata2, &r2);
285	return (isc_region_compare(&r1, &r2));
286}
287
288static inline isc_result_t
289fromstruct_keydata(ARGS_FROMSTRUCT) {
290	dns_rdata_keydata_t *keydata = source;
291
292	REQUIRE(type == dns_rdatatype_keydata);
293	REQUIRE(source != NULL);
294	REQUIRE(keydata->common.rdtype == type);
295	REQUIRE(keydata->common.rdclass == rdclass);
296
297	UNUSED(type);
298	UNUSED(rdclass);
299
300	/* Refresh timer */
301	RETERR(uint32_tobuffer(keydata->refresh, target));
302
303	/* Add hold-down */
304	RETERR(uint32_tobuffer(keydata->addhd, target));
305
306	/* Remove hold-down */
307	RETERR(uint32_tobuffer(keydata->removehd, target));
308
309	/* Flags */
310	RETERR(uint16_tobuffer(keydata->flags, target));
311
312	/* Protocol */
313	RETERR(uint8_tobuffer(keydata->protocol, target));
314
315	/* Algorithm */
316	RETERR(uint8_tobuffer(keydata->algorithm, target));
317
318	/* Data */
319	return (mem_tobuffer(target, keydata->data, keydata->datalen));
320}
321
322static inline isc_result_t
323tostruct_keydata(ARGS_TOSTRUCT) {
324	dns_rdata_keydata_t *keydata = target;
325	isc_region_t sr;
326
327	REQUIRE(rdata->type == dns_rdatatype_keydata);
328	REQUIRE(target != NULL);
329
330	keydata->common.rdclass = rdata->rdclass;
331	keydata->common.rdtype = rdata->type;
332	ISC_LINK_INIT(&keydata->common, link);
333
334	dns_rdata_toregion(rdata, &sr);
335
336	/* Refresh timer */
337	if (sr.length < 4)
338		return (ISC_R_UNEXPECTEDEND);
339	keydata->refresh = uint32_fromregion(&sr);
340	isc_region_consume(&sr, 4);
341
342	/* Add hold-down */
343	if (sr.length < 4)
344		return (ISC_R_UNEXPECTEDEND);
345	keydata->addhd = uint32_fromregion(&sr);
346	isc_region_consume(&sr, 4);
347
348	/* Remove hold-down */
349	if (sr.length < 4)
350		return (ISC_R_UNEXPECTEDEND);
351	keydata->removehd = uint32_fromregion(&sr);
352	isc_region_consume(&sr, 4);
353
354	/* Flags */
355	if (sr.length < 2)
356		return (ISC_R_UNEXPECTEDEND);
357	keydata->flags = uint16_fromregion(&sr);
358	isc_region_consume(&sr, 2);
359
360	/* Protocol */
361	if (sr.length < 1)
362		return (ISC_R_UNEXPECTEDEND);
363	keydata->protocol = uint8_fromregion(&sr);
364	isc_region_consume(&sr, 1);
365
366	/* Algorithm */
367	if (sr.length < 1)
368		return (ISC_R_UNEXPECTEDEND);
369	keydata->algorithm = uint8_fromregion(&sr);
370	isc_region_consume(&sr, 1);
371
372	/* Data */
373	keydata->datalen = sr.length;
374	keydata->data = mem_maybedup(sr.base, keydata->datalen);
375	if (keydata->data == NULL)
376		return (ISC_R_NOMEMORY);
377
378	return (ISC_R_SUCCESS);
379}
380
381static inline void
382freestruct_keydata(ARGS_FREESTRUCT) {
383	dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *) source;
384
385	REQUIRE(source != NULL);
386	REQUIRE(keydata->common.rdtype == dns_rdatatype_keydata);
387
388	free(keydata->data);
389}
390
391static inline isc_result_t
392additionaldata_keydata(ARGS_ADDLDATA) {
393	REQUIRE(rdata->type == dns_rdatatype_keydata);
394
395	UNUSED(rdata);
396	UNUSED(add);
397	UNUSED(arg);
398
399	return (ISC_R_SUCCESS);
400}
401
402static inline isc_result_t
403digest_keydata(ARGS_DIGEST) {
404	isc_region_t r;
405
406	REQUIRE(rdata->type == dns_rdatatype_keydata);
407
408	dns_rdata_toregion(rdata, &r);
409
410	return ((digest)(arg, &r));
411}
412
413static inline isc_boolean_t
414checkowner_keydata(ARGS_CHECKOWNER) {
415
416	REQUIRE(type == dns_rdatatype_keydata);
417
418	UNUSED(name);
419	UNUSED(type);
420	UNUSED(rdclass);
421	UNUSED(wildcard);
422
423	return (ISC_TRUE);
424}
425
426static inline isc_boolean_t
427checknames_keydata(ARGS_CHECKNAMES) {
428
429	REQUIRE(rdata->type == dns_rdatatype_keydata);
430
431	UNUSED(rdata);
432	UNUSED(owner);
433	UNUSED(bad);
434
435	return (ISC_TRUE);
436}
437
438static inline int
439casecompare_keydata(ARGS_COMPARE) {
440	return (compare_keydata(rdata1, rdata2));
441}
442
443#endif /* GENERIC_KEYDATA_65533_C */
444