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