xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/ipseckey_45.c (revision 122b5006ee1bd67145794b4cde92f4fe4781a5ec)
1 /*	$NetBSD: ipseckey_45.c,v 1.8 2021/02/19 16:42:17 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
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 #ifndef RDATA_GENERIC_IPSECKEY_45_C
15 #define RDATA_GENERIC_IPSECKEY_45_C
16 
17 #include <string.h>
18 
19 #include <isc/net.h>
20 
21 #define RRTYPE_IPSECKEY_ATTRIBUTES (0)
22 
23 static inline isc_result_t
24 fromtext_ipseckey(ARGS_FROMTEXT) {
25 	isc_token_t token;
26 	dns_name_t name;
27 	isc_buffer_t buffer;
28 	unsigned int gateway;
29 	struct in_addr addr;
30 	unsigned char addr6[16];
31 	isc_region_t region;
32 
33 	REQUIRE(type == dns_rdatatype_ipseckey);
34 
35 	UNUSED(type);
36 	UNUSED(rdclass);
37 	UNUSED(callbacks);
38 
39 	/*
40 	 * Precedence.
41 	 */
42 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
43 				      false));
44 	if (token.value.as_ulong > 0xffU) {
45 		RETTOK(ISC_R_RANGE);
46 	}
47 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
48 
49 	/*
50 	 * Gateway type.
51 	 */
52 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
53 				      false));
54 	if (token.value.as_ulong > 0x3U) {
55 		RETTOK(ISC_R_RANGE);
56 	}
57 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
58 	gateway = token.value.as_ulong;
59 
60 	/*
61 	 * Algorithm.
62 	 */
63 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
64 				      false));
65 	if (token.value.as_ulong > 0xffU) {
66 		RETTOK(ISC_R_RANGE);
67 	}
68 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
69 
70 	/*
71 	 * Gateway.
72 	 */
73 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
74 				      false));
75 
76 	switch (gateway) {
77 	case 0:
78 		if (strcmp(DNS_AS_STR(token), ".") != 0) {
79 			RETTOK(DNS_R_SYNTAX);
80 		}
81 		break;
82 
83 	case 1:
84 		if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
85 			RETTOK(DNS_R_BADDOTTEDQUAD);
86 		}
87 		isc_buffer_availableregion(target, &region);
88 		if (region.length < 4) {
89 			return (ISC_R_NOSPACE);
90 		}
91 		memmove(region.base, &addr, 4);
92 		isc_buffer_add(target, 4);
93 		break;
94 
95 	case 2:
96 		if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) {
97 			RETTOK(DNS_R_BADAAAA);
98 		}
99 		isc_buffer_availableregion(target, &region);
100 		if (region.length < 16) {
101 			return (ISC_R_NOSPACE);
102 		}
103 		memmove(region.base, addr6, 16);
104 		isc_buffer_add(target, 16);
105 		break;
106 
107 	case 3:
108 		dns_name_init(&name, NULL);
109 		buffer_fromregion(&buffer, &token.value.as_region);
110 		if (origin == NULL) {
111 			origin = dns_rootname;
112 		}
113 		RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
114 					 target));
115 		break;
116 	}
117 
118 	/*
119 	 * Public key.
120 	 */
121 	return (isc_base64_tobuffer(lexer, target, -2));
122 }
123 
124 static inline isc_result_t
125 totext_ipseckey(ARGS_TOTEXT) {
126 	isc_region_t region;
127 	dns_name_t name;
128 	char buf[sizeof("255 ")];
129 	unsigned short num;
130 	unsigned short gateway;
131 
132 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
133 	REQUIRE(rdata->length >= 3);
134 
135 	dns_name_init(&name, NULL);
136 
137 	if (rdata->data[1] > 3U) {
138 		return (ISC_R_NOTIMPLEMENTED);
139 	}
140 
141 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
142 		RETERR(str_totext("( ", target));
143 	}
144 
145 	/*
146 	 * Precedence.
147 	 */
148 	dns_rdata_toregion(rdata, &region);
149 	num = uint8_fromregion(&region);
150 	isc_region_consume(&region, 1);
151 	snprintf(buf, sizeof(buf), "%u ", num);
152 	RETERR(str_totext(buf, target));
153 
154 	/*
155 	 * Gateway type.
156 	 */
157 	gateway = uint8_fromregion(&region);
158 	isc_region_consume(&region, 1);
159 	snprintf(buf, sizeof(buf), "%u ", gateway);
160 	RETERR(str_totext(buf, target));
161 
162 	/*
163 	 * Algorithm.
164 	 */
165 	num = uint8_fromregion(&region);
166 	isc_region_consume(&region, 1);
167 	snprintf(buf, sizeof(buf), "%u ", num);
168 	RETERR(str_totext(buf, target));
169 
170 	/*
171 	 * Gateway.
172 	 */
173 	switch (gateway) {
174 	case 0:
175 		RETERR(str_totext(".", target));
176 		break;
177 
178 	case 1:
179 		RETERR(inet_totext(AF_INET, tctx->flags, &region, target));
180 		isc_region_consume(&region, 4);
181 		break;
182 
183 	case 2:
184 		RETERR(inet_totext(AF_INET6, tctx->flags, &region, target));
185 		isc_region_consume(&region, 16);
186 		break;
187 
188 	case 3:
189 		dns_name_fromregion(&name, &region);
190 		RETERR(dns_name_totext(&name, false, target));
191 		isc_region_consume(&region, name_length(&name));
192 		break;
193 	}
194 
195 	/*
196 	 * Key.
197 	 */
198 	if (region.length > 0U) {
199 		RETERR(str_totext(tctx->linebreak, target));
200 		if (tctx->width == 0) { /* No splitting */
201 			RETERR(isc_base64_totext(&region, 60, "", target));
202 		} else {
203 			RETERR(isc_base64_totext(&region, tctx->width - 2,
204 						 tctx->linebreak, target));
205 		}
206 	}
207 
208 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
209 		RETERR(str_totext(" )", target));
210 	}
211 	return (ISC_R_SUCCESS);
212 }
213 
214 static inline isc_result_t
215 fromwire_ipseckey(ARGS_FROMWIRE) {
216 	dns_name_t name;
217 	isc_region_t region;
218 
219 	REQUIRE(type == dns_rdatatype_ipseckey);
220 
221 	UNUSED(type);
222 	UNUSED(rdclass);
223 
224 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
225 
226 	dns_name_init(&name, NULL);
227 
228 	isc_buffer_activeregion(source, &region);
229 	if (region.length < 3) {
230 		return (ISC_R_UNEXPECTEDEND);
231 	}
232 
233 	switch (region.base[1]) {
234 	case 0:
235 		if (region.length < 4) {
236 			return (ISC_R_UNEXPECTEDEND);
237 		}
238 		isc_buffer_forward(source, region.length);
239 		return (mem_tobuffer(target, region.base, region.length));
240 
241 	case 1:
242 		if (region.length < 8) {
243 			return (ISC_R_UNEXPECTEDEND);
244 		}
245 		isc_buffer_forward(source, region.length);
246 		return (mem_tobuffer(target, region.base, region.length));
247 
248 	case 2:
249 		if (region.length < 20) {
250 			return (ISC_R_UNEXPECTEDEND);
251 		}
252 		isc_buffer_forward(source, region.length);
253 		return (mem_tobuffer(target, region.base, region.length));
254 
255 	case 3:
256 		RETERR(mem_tobuffer(target, region.base, 3));
257 		isc_buffer_forward(source, 3);
258 		RETERR(dns_name_fromwire(&name, source, dctx, options, target));
259 		isc_buffer_activeregion(source, &region);
260 		isc_buffer_forward(source, region.length);
261 		if (region.length < 1) {
262 			return (ISC_R_UNEXPECTEDEND);
263 		}
264 		return (mem_tobuffer(target, region.base, region.length));
265 
266 	default:
267 		return (ISC_R_NOTIMPLEMENTED);
268 	}
269 }
270 
271 static inline isc_result_t
272 towire_ipseckey(ARGS_TOWIRE) {
273 	isc_region_t region;
274 
275 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
276 	REQUIRE(rdata->length != 0);
277 
278 	UNUSED(cctx);
279 
280 	dns_rdata_toregion(rdata, &region);
281 	return (mem_tobuffer(target, region.base, region.length));
282 }
283 
284 static inline int
285 compare_ipseckey(ARGS_COMPARE) {
286 	isc_region_t region1;
287 	isc_region_t region2;
288 
289 	REQUIRE(rdata1->type == rdata2->type);
290 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
291 	REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
292 	REQUIRE(rdata1->length >= 3);
293 	REQUIRE(rdata2->length >= 3);
294 
295 	dns_rdata_toregion(rdata1, &region1);
296 	dns_rdata_toregion(rdata2, &region2);
297 
298 	return (isc_region_compare(&region1, &region2));
299 }
300 
301 static inline isc_result_t
302 fromstruct_ipseckey(ARGS_FROMSTRUCT) {
303 	dns_rdata_ipseckey_t *ipseckey = source;
304 	isc_region_t region;
305 	uint32_t n;
306 
307 	REQUIRE(type == dns_rdatatype_ipseckey);
308 	REQUIRE(ipseckey != NULL);
309 	REQUIRE(ipseckey->common.rdtype == type);
310 	REQUIRE(ipseckey->common.rdclass == rdclass);
311 
312 	UNUSED(type);
313 	UNUSED(rdclass);
314 
315 	if (ipseckey->gateway_type > 3U) {
316 		return (ISC_R_NOTIMPLEMENTED);
317 	}
318 
319 	RETERR(uint8_tobuffer(ipseckey->precedence, target));
320 	RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
321 	RETERR(uint8_tobuffer(ipseckey->algorithm, target));
322 
323 	switch (ipseckey->gateway_type) {
324 	case 0:
325 		break;
326 
327 	case 1:
328 		n = ntohl(ipseckey->in_addr.s_addr);
329 		RETERR(uint32_tobuffer(n, target));
330 		break;
331 
332 	case 2:
333 		RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
334 		break;
335 
336 	case 3:
337 		dns_name_toregion(&ipseckey->gateway, &region);
338 		RETERR(isc_buffer_copyregion(target, &region));
339 		break;
340 	}
341 
342 	return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
343 }
344 
345 static inline isc_result_t
346 tostruct_ipseckey(ARGS_TOSTRUCT) {
347 	isc_region_t region;
348 	dns_rdata_ipseckey_t *ipseckey = target;
349 	dns_name_t name;
350 	uint32_t n;
351 
352 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
353 	REQUIRE(ipseckey != NULL);
354 	REQUIRE(rdata->length >= 3);
355 
356 	if (rdata->data[1] > 3U) {
357 		return (ISC_R_NOTIMPLEMENTED);
358 	}
359 
360 	ipseckey->common.rdclass = rdata->rdclass;
361 	ipseckey->common.rdtype = rdata->type;
362 	ISC_LINK_INIT(&ipseckey->common, link);
363 
364 	dns_name_init(&name, NULL);
365 	dns_rdata_toregion(rdata, &region);
366 
367 	ipseckey->precedence = uint8_fromregion(&region);
368 	isc_region_consume(&region, 1);
369 
370 	ipseckey->gateway_type = uint8_fromregion(&region);
371 	isc_region_consume(&region, 1);
372 
373 	ipseckey->algorithm = uint8_fromregion(&region);
374 	isc_region_consume(&region, 1);
375 
376 	switch (ipseckey->gateway_type) {
377 	case 0:
378 		break;
379 
380 	case 1:
381 		n = uint32_fromregion(&region);
382 		ipseckey->in_addr.s_addr = htonl(n);
383 		isc_region_consume(&region, 4);
384 		break;
385 
386 	case 2:
387 		memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
388 		isc_region_consume(&region, 16);
389 		break;
390 
391 	case 3:
392 		dns_name_init(&ipseckey->gateway, NULL);
393 		dns_name_fromregion(&name, &region);
394 		RETERR(name_duporclone(&name, mctx, &ipseckey->gateway));
395 		isc_region_consume(&region, name_length(&name));
396 		break;
397 	}
398 
399 	ipseckey->keylength = region.length;
400 	if (ipseckey->keylength != 0U) {
401 		ipseckey->key = mem_maybedup(mctx, region.base,
402 					     ipseckey->keylength);
403 		if (ipseckey->key == NULL) {
404 			if (ipseckey->gateway_type == 3) {
405 				dns_name_free(&ipseckey->gateway,
406 					      ipseckey->mctx);
407 			}
408 			return (ISC_R_NOMEMORY);
409 		}
410 	} else {
411 		ipseckey->key = NULL;
412 	}
413 
414 	ipseckey->mctx = mctx;
415 	return (ISC_R_SUCCESS);
416 }
417 
418 static inline void
419 freestruct_ipseckey(ARGS_FREESTRUCT) {
420 	dns_rdata_ipseckey_t *ipseckey = source;
421 
422 	REQUIRE(ipseckey != NULL);
423 	REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
424 
425 	if (ipseckey->mctx == NULL) {
426 		return;
427 	}
428 
429 	if (ipseckey->gateway_type == 3) {
430 		dns_name_free(&ipseckey->gateway, ipseckey->mctx);
431 	}
432 
433 	if (ipseckey->key != NULL) {
434 		isc_mem_free(ipseckey->mctx, ipseckey->key);
435 	}
436 
437 	ipseckey->mctx = NULL;
438 }
439 
440 static inline isc_result_t
441 additionaldata_ipseckey(ARGS_ADDLDATA) {
442 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
443 
444 	UNUSED(rdata);
445 	UNUSED(add);
446 	UNUSED(arg);
447 
448 	return (ISC_R_SUCCESS);
449 }
450 
451 static inline isc_result_t
452 digest_ipseckey(ARGS_DIGEST) {
453 	isc_region_t region;
454 
455 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
456 
457 	dns_rdata_toregion(rdata, &region);
458 	return ((digest)(arg, &region));
459 }
460 
461 static inline bool
462 checkowner_ipseckey(ARGS_CHECKOWNER) {
463 	REQUIRE(type == dns_rdatatype_ipseckey);
464 
465 	UNUSED(name);
466 	UNUSED(type);
467 	UNUSED(rdclass);
468 	UNUSED(wildcard);
469 
470 	return (true);
471 }
472 
473 static inline bool
474 checknames_ipseckey(ARGS_CHECKNAMES) {
475 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
476 
477 	UNUSED(rdata);
478 	UNUSED(owner);
479 	UNUSED(bad);
480 
481 	return (true);
482 }
483 
484 static inline int
485 casecompare_ipseckey(ARGS_COMPARE) {
486 	isc_region_t region1;
487 	isc_region_t region2;
488 	dns_name_t name1;
489 	dns_name_t name2;
490 	int order;
491 
492 	REQUIRE(rdata1->type == rdata2->type);
493 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
494 	REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
495 	REQUIRE(rdata1->length >= 3);
496 	REQUIRE(rdata2->length >= 3);
497 
498 	dns_rdata_toregion(rdata1, &region1);
499 	dns_rdata_toregion(rdata2, &region2);
500 
501 	if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
502 	{
503 		return (isc_region_compare(&region1, &region2));
504 	}
505 
506 	dns_name_init(&name1, NULL);
507 	dns_name_init(&name2, NULL);
508 
509 	isc_region_consume(&region1, 3);
510 	isc_region_consume(&region2, 3);
511 
512 	dns_name_fromregion(&name1, &region1);
513 	dns_name_fromregion(&name2, &region2);
514 
515 	order = dns_name_rdatacompare(&name1, &name2);
516 	if (order != 0) {
517 		return (order);
518 	}
519 
520 	isc_region_consume(&region1, name_length(&name1));
521 	isc_region_consume(&region2, name_length(&name2));
522 
523 	return (isc_region_compare(&region1, &region2));
524 }
525 
526 #endif /* RDATA_GENERIC_IPSECKEY_45_C */
527