2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2013 The FreeBSD Foundation
7 * This software was developed by Pawel Jakub Dawidek under sponsorship from
8 * the FreeBSD Foundation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/capsicum.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
50 #include <libcasper.h>
52 #include <casper/cap_dns.h>
56 #define CHECK(expr) do { \
58 printf("ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
60 printf("not ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
64 #define CHECKX(expr) do { \
66 printf("ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
68 printf("not ok %d # %s:%u\n", ntest, __FILE__, __LINE__); \
75 #define GETHOSTBYNAME 0x01
76 #define GETHOSTBYNAME2_AF_INET 0x02
77 #define GETHOSTBYNAME2_AF_INET6 0x04
78 #define GETHOSTBYADDR_AF_INET 0x08
79 #define GETHOSTBYADDR_AF_INET6 0x10
80 #define GETADDRINFO_AF_UNSPEC 0x20
81 #define GETADDRINFO_AF_INET 0x40
82 #define GETADDRINFO_AF_INET6 0x80
85 addrinfo_compare(struct addrinfo *ai0, struct addrinfo *ai1)
87 struct addrinfo *at0, *at1;
89 if (ai0 == NULL && ai1 == NULL)
91 if (ai0 == NULL || ai1 == NULL)
97 if ((at0->ai_flags == at1->ai_flags) &&
98 (at0->ai_family == at1->ai_family) &&
99 (at0->ai_socktype == at1->ai_socktype) &&
100 (at0->ai_protocol == at1->ai_protocol) &&
101 (at0->ai_addrlen == at1->ai_addrlen) &&
102 (memcmp(at0->ai_addr, at1->ai_addr,
103 at0->ai_addrlen) == 0)) {
104 if (at0->ai_canonname != NULL &&
105 at1->ai_canonname != NULL) {
106 if (strcmp(at0->ai_canonname,
107 at1->ai_canonname) != 0) {
112 if (at0->ai_canonname == NULL &&
113 at1->ai_canonname != NULL) {
116 if (at0->ai_canonname != NULL &&
117 at1->ai_canonname == NULL) {
121 if (at0->ai_next == NULL && at1->ai_next == NULL)
123 if (at0->ai_next == NULL || at1->ai_next == NULL)
134 fprintf(stderr, "Dead code reached in addrinfo_compare()\n");
139 hostent_aliases_compare(char **aliases0, char **aliases1)
143 if (aliases0 == NULL && aliases1 == NULL)
145 if (aliases0 == NULL || aliases1 == NULL)
148 for (i0 = 0; aliases0[i0] != NULL; i0++) {
149 for (i1 = 0; aliases1[i1] != NULL; i1++) {
150 if (strcmp(aliases0[i0], aliases1[i1]) == 0)
153 if (aliases1[i1] == NULL)
161 hostent_addr_list_compare(char **addr_list0, char **addr_list1, int length)
165 if (addr_list0 == NULL && addr_list1 == NULL)
167 if (addr_list0 == NULL || addr_list1 == NULL)
170 for (i0 = 0; addr_list0[i0] != NULL; i0++) {
171 for (i1 = 0; addr_list1[i1] != NULL; i1++) {
172 if (memcmp(addr_list0[i0], addr_list1[i1], length) == 0)
175 if (addr_list1[i1] == NULL)
183 hostent_compare(const struct hostent *hp0, const struct hostent *hp1)
186 if (hp0 == NULL && hp1 != NULL)
189 if (hp0 == NULL || hp1 == NULL)
192 if (hp0->h_name != NULL || hp1->h_name != NULL) {
193 if (hp0->h_name == NULL || hp1->h_name == NULL)
195 if (strcmp(hp0->h_name, hp1->h_name) != 0)
199 if (!hostent_aliases_compare(hp0->h_aliases, hp1->h_aliases))
201 if (!hostent_aliases_compare(hp1->h_aliases, hp0->h_aliases))
204 if (hp0->h_addrtype != hp1->h_addrtype)
207 if (hp0->h_length != hp1->h_length)
210 if (!hostent_addr_list_compare(hp0->h_addr_list, hp1->h_addr_list,
214 if (!hostent_addr_list_compare(hp1->h_addr_list, hp0->h_addr_list,
223 runtest(cap_channel_t *capdns)
226 struct addrinfo *ais, *aic, hints, *hintsp;
227 struct hostent *hps, *hpc;
233 hps = gethostbyname("example.com");
235 fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com");
236 hpc = cap_gethostbyname(capdns, "example.com");
237 if (hostent_compare(hps, hpc))
238 result |= GETHOSTBYNAME;
240 hps = gethostbyname2("example.com", AF_INET);
242 fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com");
243 hpc = cap_gethostbyname2(capdns, "example.com", AF_INET);
244 if (hostent_compare(hps, hpc))
245 result |= GETHOSTBYNAME2_AF_INET;
247 hps = gethostbyname2("example.com", AF_INET6);
249 fprintf(stderr, "Unable to resolve %s IPv6.\n", "example.com");
250 hpc = cap_gethostbyname2(capdns, "example.com", AF_INET6);
251 if (hostent_compare(hps, hpc))
252 result |= GETHOSTBYNAME2_AF_INET6;
255 hints.ai_family = AF_UNSPEC;
256 hints.ai_socktype = 0;
257 hints.ai_protocol = 0;
258 hints.ai_addrlen = 0;
259 hints.ai_addr = NULL;
260 hints.ai_canonname = NULL;
261 hints.ai_next = NULL;
265 if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) {
267 "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n",
268 gai_strerror(errno));
270 if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) {
271 if (addrinfo_compare(ais, aic))
272 result |= GETADDRINFO_AF_UNSPEC;
277 hints.ai_family = AF_INET;
278 if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) {
280 "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n",
281 gai_strerror(errno));
283 if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) {
284 if (addrinfo_compare(ais, aic))
285 result |= GETADDRINFO_AF_INET;
290 hints.ai_family = AF_INET6;
291 if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) {
293 "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n",
294 gai_strerror(errno));
296 if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) {
297 if (addrinfo_compare(ais, aic))
298 result |= GETADDRINFO_AF_INET6;
303 /* XXX: hardcoded addresses for "google-public-dns-a.google.com". */
304 #define GOOGLE_DNS_IPV4 "8.8.8.8"
305 #define GOOGLE_DNS_IPV6 "2001:4860:4860::8888"
307 inet_pton(AF_INET, GOOGLE_DNS_IPV4, &ip4);
308 hps = gethostbyaddr(&ip4, sizeof(ip4), AF_INET);
310 fprintf(stderr, "Unable to resolve %s.\n", GOOGLE_DNS_IPV4);
311 hpc = cap_gethostbyaddr(capdns, &ip4, sizeof(ip4), AF_INET);
312 if (hostent_compare(hps, hpc))
313 result |= GETHOSTBYADDR_AF_INET;
315 inet_pton(AF_INET6, GOOGLE_DNS_IPV6, &ip6);
316 hps = gethostbyaddr(&ip6, sizeof(ip6), AF_INET6);
318 fprintf(stderr, "Unable to resolve %s.\n", GOOGLE_DNS_IPV6);
320 hpc = cap_gethostbyaddr(capdns, &ip6, sizeof(ip6), AF_INET6);
321 if (hostent_compare(hps, hpc))
322 result |= GETHOSTBYADDR_AF_INET6;
329 cap_channel_t *capcas, *capdns, *origcapdns;
330 const char *types[2];
337 CHECKX(capcas != NULL);
339 origcapdns = capdns = cap_service_open(capcas, "system.dns");
340 CHECKX(capdns != NULL);
346 CHECK(runtest(capdns) ==
347 (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 |
348 GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 |
349 GETADDRINFO_AF_UNSPEC | GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6));
354 * family: AF_INET, AF_INET6
357 capdns = cap_clone(origcapdns);
358 CHECK(capdns != NULL);
362 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
363 families[0] = AF_INET;
364 families[1] = AF_INET6;
365 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
367 CHECK(runtest(capdns) ==
368 (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 |
369 GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 |
370 GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6));
377 * family: AF_INET, AF_INET6
380 capdns = cap_clone(origcapdns);
381 CHECK(capdns != NULL);
384 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
386 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
387 errno == ENOTCAPABLE);
389 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
390 errno == ENOTCAPABLE);
391 families[0] = AF_INET;
392 families[1] = AF_INET6;
393 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
395 CHECK(runtest(capdns) ==
396 (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 |
397 GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6));
404 * family: AF_INET, AF_INET6
407 capdns = cap_clone(origcapdns);
408 CHECK(capdns != NULL);
411 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
413 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
414 errno == ENOTCAPABLE);
416 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
417 errno == ENOTCAPABLE);
418 families[0] = AF_INET;
419 families[1] = AF_INET6;
420 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
422 CHECK(runtest(capdns) ==
423 (GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6));
432 capdns = cap_clone(origcapdns);
433 CHECK(capdns != NULL);
437 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
438 families[0] = AF_INET;
439 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
440 families[1] = AF_INET6;
441 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
442 errno == ENOTCAPABLE);
443 families[0] = AF_INET6;
444 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
445 errno == ENOTCAPABLE);
447 CHECK(runtest(capdns) ==
448 (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYADDR_AF_INET |
449 GETADDRINFO_AF_INET));
459 capdns = cap_clone(origcapdns);
460 CHECK(capdns != NULL);
464 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
465 families[0] = AF_INET6;
466 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
467 families[1] = AF_INET;
468 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
469 errno == ENOTCAPABLE);
470 families[0] = AF_INET;
471 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
472 errno == ENOTCAPABLE);
474 CHECK(runtest(capdns) ==
475 (GETHOSTBYNAME2_AF_INET6 | GETHOSTBYADDR_AF_INET6 |
476 GETADDRINFO_AF_INET6));
480 /* Below we also test further limiting capability. */
488 capdns = cap_clone(origcapdns);
489 CHECK(capdns != NULL);
493 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
494 families[0] = AF_INET;
495 families[1] = AF_INET6;
496 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
498 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
500 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
501 errno == ENOTCAPABLE);
503 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
504 errno == ENOTCAPABLE);
505 families[0] = AF_INET;
506 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
507 families[1] = AF_INET6;
508 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
509 errno == ENOTCAPABLE);
510 families[0] = AF_INET6;
511 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
512 errno == ENOTCAPABLE);
514 CHECK(runtest(capdns) ==
515 (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETADDRINFO_AF_INET));
525 capdns = cap_clone(origcapdns);
526 CHECK(capdns != NULL);
530 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
531 families[0] = AF_INET;
532 families[1] = AF_INET6;
533 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
535 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
537 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
538 errno == ENOTCAPABLE);
540 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
541 errno == ENOTCAPABLE);
542 families[0] = AF_INET6;
543 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
544 families[1] = AF_INET;
545 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
546 errno == ENOTCAPABLE);
547 families[0] = AF_INET;
548 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
549 errno == ENOTCAPABLE);
551 CHECK(runtest(capdns) ==
552 (GETHOSTBYNAME2_AF_INET6 | GETADDRINFO_AF_INET6));
562 capdns = cap_clone(origcapdns);
563 CHECK(capdns != NULL);
567 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
568 families[0] = AF_INET;
569 families[1] = AF_INET6;
570 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
572 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
574 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
575 errno == ENOTCAPABLE);
577 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
578 errno == ENOTCAPABLE);
579 families[0] = AF_INET;
580 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
581 families[1] = AF_INET6;
582 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
583 errno == ENOTCAPABLE);
584 families[0] = AF_INET6;
585 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
586 errno == ENOTCAPABLE);
588 CHECK(runtest(capdns) == GETHOSTBYADDR_AF_INET);
598 capdns = cap_clone(origcapdns);
599 CHECK(capdns != NULL);
603 CHECK(cap_dns_type_limit(capdns, types, 2) == 0);
604 families[0] = AF_INET;
605 families[1] = AF_INET6;
606 CHECK(cap_dns_family_limit(capdns, families, 2) == 0);
608 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
610 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
611 errno == ENOTCAPABLE);
613 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
614 errno == ENOTCAPABLE);
615 families[0] = AF_INET6;
616 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
617 families[1] = AF_INET;
618 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
619 errno == ENOTCAPABLE);
620 families[0] = AF_INET;
621 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
622 errno == ENOTCAPABLE);
624 CHECK(runtest(capdns) == GETHOSTBYADDR_AF_INET6);
628 /* Trying to rise the limits. */
630 capdns = cap_clone(origcapdns);
631 CHECK(capdns != NULL);
634 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
635 families[0] = AF_INET;
636 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
640 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
641 errno == ENOTCAPABLE);
642 families[0] = AF_INET;
643 families[1] = AF_INET6;
644 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
645 errno == ENOTCAPABLE);
648 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
649 errno == ENOTCAPABLE);
650 families[0] = AF_INET6;
651 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
652 errno == ENOTCAPABLE);
654 CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 &&
655 errno == ENOTCAPABLE);
656 CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 &&
657 errno == ENOTCAPABLE);
659 /* Do the limits still hold? */
660 CHECK(runtest(capdns) == (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET |
661 GETADDRINFO_AF_INET));
665 capdns = cap_clone(origcapdns);
666 CHECK(capdns != NULL);
669 CHECK(cap_dns_type_limit(capdns, types, 1) == 0);
670 families[0] = AF_INET6;
671 CHECK(cap_dns_family_limit(capdns, families, 1) == 0);
675 CHECK(cap_dns_type_limit(capdns, types, 2) == -1 &&
676 errno == ENOTCAPABLE);
677 families[0] = AF_INET;
678 families[1] = AF_INET6;
679 CHECK(cap_dns_family_limit(capdns, families, 2) == -1 &&
680 errno == ENOTCAPABLE);
683 CHECK(cap_dns_type_limit(capdns, types, 1) == -1 &&
684 errno == ENOTCAPABLE);
685 families[0] = AF_INET;
686 CHECK(cap_dns_family_limit(capdns, families, 1) == -1 &&
687 errno == ENOTCAPABLE);
689 CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 &&
690 errno == ENOTCAPABLE);
691 CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 &&
692 errno == ENOTCAPABLE);
694 /* Do the limits still hold? */
695 CHECK(runtest(capdns) == GETHOSTBYADDR_AF_INET6);
699 cap_close(origcapdns);