xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/ipseckey_45.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: ipseckey_45.c,v 1.11 2025/01/26 16:25:31 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
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
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, 0, 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
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 	dctx = dns_decompress_setpermitted(dctx, false);
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, 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
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
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
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
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 	ipseckey->common.rdclass = rdata->rdclass;
359 	ipseckey->common.rdtype = rdata->type;
360 	ISC_LINK_INIT(&ipseckey->common, link);
361 
362 	dns_name_init(&name, NULL);
363 	dns_rdata_toregion(rdata, &region);
364 
365 	ipseckey->precedence = uint8_fromregion(&region);
366 	isc_region_consume(&region, 1);
367 
368 	ipseckey->gateway_type = uint8_fromregion(&region);
369 	isc_region_consume(&region, 1);
370 
371 	ipseckey->algorithm = uint8_fromregion(&region);
372 	isc_region_consume(&region, 1);
373 
374 	switch (ipseckey->gateway_type) {
375 	case 0:
376 		break;
377 
378 	case 1:
379 		n = uint32_fromregion(&region);
380 		ipseckey->in_addr.s_addr = htonl(n);
381 		isc_region_consume(&region, 4);
382 		break;
383 
384 	case 2:
385 		INSIST(region.length >= 16U);
386 		memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
387 		isc_region_consume(&region, 16);
388 		break;
389 
390 	case 3:
391 		dns_name_init(&ipseckey->gateway, NULL);
392 		dns_name_fromregion(&name, &region);
393 		name_duporclone(&name, mctx, &ipseckey->gateway);
394 		isc_region_consume(&region, name_length(&name));
395 		break;
396 	}
397 
398 	ipseckey->keylength = region.length;
399 	if (ipseckey->keylength != 0U) {
400 		ipseckey->key = mem_maybedup(mctx, region.base,
401 					     ipseckey->keylength);
402 	} else {
403 		ipseckey->key = NULL;
404 	}
405 
406 	ipseckey->mctx = mctx;
407 	return ISC_R_SUCCESS;
408 }
409 
410 static void
411 freestruct_ipseckey(ARGS_FREESTRUCT) {
412 	dns_rdata_ipseckey_t *ipseckey = source;
413 
414 	REQUIRE(ipseckey != NULL);
415 	REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
416 
417 	if (ipseckey->mctx == NULL) {
418 		return;
419 	}
420 
421 	if (ipseckey->gateway_type == 3) {
422 		dns_name_free(&ipseckey->gateway, ipseckey->mctx);
423 	}
424 
425 	if (ipseckey->key != NULL) {
426 		isc_mem_free(ipseckey->mctx, ipseckey->key);
427 	}
428 
429 	ipseckey->mctx = NULL;
430 }
431 
432 static isc_result_t
433 additionaldata_ipseckey(ARGS_ADDLDATA) {
434 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
435 
436 	UNUSED(rdata);
437 	UNUSED(owner);
438 	UNUSED(add);
439 	UNUSED(arg);
440 
441 	return ISC_R_SUCCESS;
442 }
443 
444 static isc_result_t
445 digest_ipseckey(ARGS_DIGEST) {
446 	isc_region_t region;
447 
448 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
449 
450 	dns_rdata_toregion(rdata, &region);
451 	return (digest)(arg, &region);
452 }
453 
454 static bool
455 checkowner_ipseckey(ARGS_CHECKOWNER) {
456 	REQUIRE(type == dns_rdatatype_ipseckey);
457 
458 	UNUSED(name);
459 	UNUSED(type);
460 	UNUSED(rdclass);
461 	UNUSED(wildcard);
462 
463 	return true;
464 }
465 
466 static bool
467 checknames_ipseckey(ARGS_CHECKNAMES) {
468 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
469 
470 	UNUSED(rdata);
471 	UNUSED(owner);
472 	UNUSED(bad);
473 
474 	return true;
475 }
476 
477 static int
478 casecompare_ipseckey(ARGS_COMPARE) {
479 	isc_region_t region1;
480 	isc_region_t region2;
481 	dns_name_t name1;
482 	dns_name_t name2;
483 	int order;
484 
485 	REQUIRE(rdata1->type == rdata2->type);
486 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
487 	REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
488 	REQUIRE(rdata1->length >= 3);
489 	REQUIRE(rdata2->length >= 3);
490 
491 	dns_rdata_toregion(rdata1, &region1);
492 	dns_rdata_toregion(rdata2, &region2);
493 
494 	if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
495 	{
496 		return isc_region_compare(&region1, &region2);
497 	}
498 
499 	dns_name_init(&name1, NULL);
500 	dns_name_init(&name2, NULL);
501 
502 	isc_region_consume(&region1, 3);
503 	isc_region_consume(&region2, 3);
504 
505 	dns_name_fromregion(&name1, &region1);
506 	dns_name_fromregion(&name2, &region2);
507 
508 	order = dns_name_rdatacompare(&name1, &name2);
509 	if (order != 0) {
510 		return order;
511 	}
512 
513 	isc_region_consume(&region1, name_length(&name1));
514 	isc_region_consume(&region2, name_length(&name2));
515 
516 	return isc_region_compare(&region1, &region2);
517 }
518 
519 #endif /* RDATA_GENERIC_IPSECKEY_45_C */
520