Index: contrib/traceroute/traceroute.c =================================================================== --- contrib/traceroute/traceroute.c +++ contrib/traceroute/traceroute.c @@ -203,6 +203,7 @@ */ #include +#include #include #include #ifdef HAVE_SYS_SELECT_H @@ -226,6 +227,11 @@ #include +#if HAVE_LIBCASPER +#include +#include +#endif + #ifdef IPSEC #include #include /* XXX */ @@ -362,6 +368,10 @@ extern int opterr; extern char *optarg; +#if HAVE_LIBCASPER +static cap_channel_t *capdns; +#endif + /* Forwards */ double deltaT(struct timeval *, struct timeval *); void freehostinfo(struct hostinfo *); @@ -510,6 +520,13 @@ int requestPort = -1; int sump = 0; int sockerrno; +#ifdef HAVE_LIBCASPER + const char *types[2]; + int families[1]; + cap_channel_t *casper; +#endif + cap_rights_t rights; + bool cansandbox; /* Insure the socket fds won't be 0, 1 or 2 */ if (open(devnull, O_RDONLY) < 0 || @@ -538,6 +555,31 @@ exit(1); } +#ifdef HAVE_LIBCASPER + casper = cap_init(); + if (casper == NULL) { + perror(stderr, "unable to create casper process"); + exit(1); + } else { + capdns = cap_service_open(casper, "system.dns"); + if (capdns == NULL) { + perror("unable to open system.dns service"); + exit(1); + } + types[0] = "NAME"; + types[1] = "ADDR"; + if (cap_dns_type_limit(capdns, types, 2) < 0) { + perror("unable to limit access to system.dns service"); + exit(1); + } + families[0] = AF_INET; + if (cap_dns_family_limit(capdns, families, 1) < 0) { + perror("unable to limit access to system.dns service"); + exit(1); + } + } +#endif /* HAVE_LIBCASPER */ + #ifdef IPCTL_DEFTTL { int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; @@ -548,10 +590,15 @@ exit(1); } } -#else +#else /* !IPCTL_DEFTTL */ max_ttl = 30; #endif +#ifdef HAVE_LIBCASPER + if (casper != NULL) + cap_close(casper); +#endif + if (argv[0] == NULL) prog = "traceroute"; else if ((cp = strrchr(argv[0], '/')) != NULL) @@ -964,6 +1011,45 @@ } } + if (connect(sndsock, (struct sockaddr *)&whereto, + sizeof(whereto)) != 0) { + Fprintf(stderr, "%s: connect: %s\n", prog, strerror(errno)); + exit(1); + } + + if (nflag) + cansandbox = true; +#ifdef HAVE_LIBCASPER + else if (capdns != NULL) + cansandbox = true; +#endif + else + cansandbox = false; + + /* + * Here we enter capability mode. Further down access to global + * namespaces (e.g filesystem) is restricted (see capsicum(4)). + * We must connect(2) our socket before this point. + */ + if (cansandbox && cap_enter() < 0 && errno != ENOSYS) { + Fprintf(stderr, "%s: cap_enter: %s\n", prog, strerror(errno)); + exit(1); + } + + cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT); + if (cap_rights_limit(sndsock, &rights) < 0 && errno != ENOSYS) { + Fprintf(stderr, "%s: cap_rights_limit sndsock: %s\n", prog, + strerror(errno)); + exit(1); + } + + cap_rights_init(&rights, CAP_RECV, CAP_EVENT); + if (cap_rights_limit(s, &rights) < 0 && errno != ENOSYS) { + Fprintf(stderr, "%s: cap_rights_limit s: %s\n", prog, + strerror(errno)); + exit(1); + } + #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) if (setpolicy(sndsock, "in bypass") < 0) errx(1, "%s", ipsec_strerror()); @@ -1251,8 +1337,7 @@ } #endif - cc = sendto(sndsock, (char *)outip, - packlen, 0, &whereto, sizeof(whereto)); + cc = send(sndsock, (char *)outip, packlen, 0); if (cc < 0 || cc != packlen) { if (cc < 0) Fprintf(stderr, "%s: sendto: %s\n", @@ -1770,7 +1855,12 @@ else { cp = strchr(domain, '.'); if (cp == NULL) { - hp = gethostbyname(domain); +#ifdef HAVE_LIBCASPER + if (capdns != NULL) + hp = cap_gethostbyname(capdns, domain); + else +#endif + hp = gethostbyname(domain); if (hp != NULL) cp = strchr(hp->h_name, '.'); } @@ -1784,7 +1874,13 @@ } } if (!nflag && in.s_addr != INADDR_ANY) { - hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); +#ifdef HAVE_LIBCASPER + if (capdns != NULL) + hp = cap_gethostbyaddr(capdns, (char *)&in, sizeof(in), + AF_INET); + else +#endif + hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); if (hp != NULL) { if ((cp = strchr(hp->h_name, '.')) != NULL && strcmp(cp + 1, domain) == 0) @@ -1830,7 +1926,12 @@ return (hi); } - hp = gethostbyname(hostname); +#ifdef HAVE_LIBCASPER + if (capdns != NULL) + hp = cap_gethostbyname(capdns, hostname); + else +#endif + hp = gethostbyname(hostname); if (hp == NULL) { Fprintf(stderr, "%s: unknown host %s\n", prog, hostname); exit(1); Index: usr.sbin/traceroute/Makefile =================================================================== --- usr.sbin/traceroute/Makefile +++ usr.sbin/traceroute/Makefile @@ -1,5 +1,8 @@ # $FreeBSD$ +.include +.include + TRACEROUTE_DISTDIR?= ${.CURDIR}/../../contrib/traceroute .PATH: ${TRACEROUTE_DISTDIR} @@ -28,6 +31,13 @@ LIBADD+= ipsec .endif +.if ${MK_CASPER} != "no" +LIBADD+= casper +LIBADD+= cap_dns +LIBADD+= cap_sysctl +CFLAGS+=-DHAVE_LIBCASPER +.endif + CFLAGS+= -I${TRACEROUTE_DISTDIR} WARNS?= 3