diff --git contrib/traceroute/traceroute.c contrib/traceroute/traceroute.c index 63cefa1..02c3c5b 100644 --- contrib/traceroute/traceroute.c +++ contrib/traceroute/traceroute.c @@ -203,6 +203,7 @@ static const char rcsid[] = */ #include +#include #include #include #ifdef HAVE_SYS_SELECT_H @@ -225,6 +226,13 @@ static const char rcsid[] = #include +#if HAVE_LIBCAPSICUM +#include +#include +#include +#include +#endif + #ifdef IPSEC #include #include /* XXX */ @@ -361,6 +369,10 @@ extern int optind; extern int opterr; extern char *optarg; +#if HAVE_LIBCAPSICUM +static cap_channel_t *capdns; +#endif + /* Forwards */ double deltaT(struct timeval *, struct timeval *); void freehostinfo(struct hostinfo *); @@ -486,6 +498,13 @@ main(int argc, char **argv) int requestPort = -1; int sump = 0; int sockerrno; +#ifdef HAVE_LIBCAPSICUM + 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 || @@ -514,20 +533,73 @@ main(int argc, char **argv) exit(1); } +#ifdef HAVE_LIBCAPSICUM + casper = cap_init(); + if (casper == NULL) { + Fprintf(stderr, "unable to contact casperd\n"); + } 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_LIBCAPSICUM */ + #ifdef IPCTL_DEFTTL { int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; size_t sz = sizeof(max_ttl); - if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) { - perror("sysctl(net.inet.ip.ttl)"); - exit(1); - } +# ifdef HAVE_LIBCAPSICUM + /* + * We actually don't need to use casperd here, since we haven't + * entered capability mode yet and sysctl interface is + * accessible for us. But it will make things easier, if in + * future one would like to rise up cap_enter() call. Currently + * it's not possible since there is no way to create sockets in + * capability mode. + */ + cap_channel_t *sysctlloc; + + if (casper != NULL) { + if ((sysctlloc = cap_service_open(casper, + "system.sysctl")) == NULL) { + perror("unable to open system.sysctl service"); + exit(1); + } + if (cap_sysctlbyname(sysctlloc, "net.inet.ip.ttl", + &max_ttl, &sz, NULL, 0) == -1) { + perror("cap_sysctlbyname(net.inet.ip.ttl)"); + exit(1); + } + } else +# endif /* HAVE_LIBCAPSICUM */ + if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) { + perror("sysctl(net.inet.ip.ttl)"); + exit(1); + } } -#else +#else /* !IPCTL_DEFTTL */ max_ttl = 30; #endif +#ifdef HAVE_LIBCAPSICUM + if (casper != NULL) + cap_close(casper); +#endif + if (argv[0] == NULL) prog = "traceroute"; else if ((cp = strrchr(argv[0], '/')) != NULL) @@ -541,12 +613,12 @@ main(int argc, char **argv) case 'a': as_path = 1; break; - + case 'A': as_path = 1; as_server = optarg; break; - + case 'd': options |= SO_DEBUG; break; @@ -931,7 +1003,49 @@ main(int argc, char **argv) as_path = 0; } } - + + 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_LIBCAPSICUM + 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 (cap_sandboxed()) + fprintf(stderr, "capability mode sandbox enabled\n"); + #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) if (setpolicy(sndsock, "in bypass") < 0) errx(1, "%s", ipsec_strerror()); @@ -1219,8 +1333,7 @@ send_probe(int seq, int ttl) } #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", @@ -1581,7 +1694,12 @@ inetname(struct in_addr in) else { cp = strchr(domain, '.'); if (cp == NULL) { - hp = gethostbyname(domain); +#ifdef HAVE_LIBCAPSICUM + if (capdns != NULL) + hp = cap_gethostbyname(capdns, domain); + else +#endif + hp = gethostbyname(domain); if (hp != NULL) cp = strchr(hp->h_name, '.'); } @@ -1595,7 +1713,13 @@ inetname(struct in_addr in) } } if (!nflag && in.s_addr != INADDR_ANY) { - hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); +#ifdef HAVE_LIBCAPSICUM + 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) @@ -1641,7 +1765,12 @@ gethostinfo(register char *hostname) return (hi); } - hp = gethostbyname(hostname); +#ifdef HAVE_LIBCAPSICUM + 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); diff --git usr.sbin/traceroute/Makefile usr.sbin/traceroute/Makefile index 12f9a0b..3c80f5c 100644 --- usr.sbin/traceroute/Makefile +++ usr.sbin/traceroute/Makefile @@ -1,5 +1,8 @@ # $FreeBSD$ +.include +.include + TRACEROUTE_DISTDIR?= ${.CURDIR}/../../contrib/traceroute .PATH: ${TRACEROUTE_DISTDIR} @@ -29,6 +32,12 @@ DPADD= ${LIBIPSEC} LDADD= -lipsec .endif +.if ${MK_CASPER} != "no" +DPADD+= ${LIBCAPSICUM} +LDADD+= -lcapsicum +CFLAGS+=-DHAVE_LIBCAPSICUM +.endif + CFLAGS+= -I${TRACEROUTE_DISTDIR} WARNS?= 3 -- 2.1.0