On Sunday, September 6, 2020, Mariusz Zaborski <osho...@freebsd.org> wrote:
> Author: oshogbo > Date: Sun Sep 6 14:04:02 2020 > New Revision: 365378 > URL: https://svnweb.freebsd.org/changeset/base/365378 > > Log: > traceroute6: capsicumize it > > Submitted by: Shubh Gupta <sh...@freebsd.org> > Sponsored by: Google (GSOC 2020) > Differential Revision: https://reviews.freebsd.org/D25604 > > Modified: > head/usr.sbin/traceroute6/Makefile > head/usr.sbin/traceroute6/traceroute6.c > > Modified: head/usr.sbin/traceroute6/Makefile > ============================================================ > ================== > --- head/usr.sbin/traceroute6/Makefile Sun Sep 6 11:29:06 2020 > (r365377) > +++ head/usr.sbin/traceroute6/Makefile Sun Sep 6 14:04:02 2020 > (r365378) > @@ -13,6 +13,10 @@ > # A PARTICULAR PURPOSE. > # $FreeBSD$ > > +.include <src.opts.mk> > + > +.include <src.opts.mk> Dup > + > TRACEROUTE_DISTDIR?= ${SRCTOP}/contrib/traceroute > .PATH: ${TRACEROUTE_DISTDIR} > > @@ -26,7 +30,13 @@ BINMODE= 4555 > CFLAGS+= -DIPSEC -DHAVE_POLL > CFLAGS+= -I${.CURDIR} -I${TRACEROUTE_DISTDIR} -I. > > -LIBADD= ipsec > +.if ${MK_CASPER} != "no" > +LIBADD+= casper > +LIBADD+= cap_dns > +CFLAGS+= -DWITH_CASPER > +.endif > + > +LIBADD+= ipsec > > .include <bsd.prog.mk> > > > Modified: head/usr.sbin/traceroute6/traceroute6.c > ============================================================ > ================== > --- head/usr.sbin/traceroute6/traceroute6.c Sun Sep 6 11:29:06 2020 > (r365377) > +++ head/usr.sbin/traceroute6/traceroute6.c Sun Sep 6 14:04:02 2020 > (r365378) > @@ -249,6 +249,7 @@ static const char rcsid[] = > */ > > #include <sys/param.h> > +#include <sys/capsicum.h> > #include <sys/time.h> > #include <sys/socket.h> > #include <sys/uio.h> > @@ -260,6 +261,10 @@ static const char rcsid[] = > > #include <arpa/inet.h> > > +#include <libcasper.h> > +#include <casper/cap_dns.h> > +#include <capsicum_helpers.h> > + > #include <netdb.h> > #include <stdio.h> > #include <err.h> > @@ -289,11 +294,6 @@ static const char rcsid[] = > > #define MAXPACKET 65535 /* max ip packet size */ > > -#ifndef HAVE_GETIPNODEBYNAME > -#define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) > -#define freehostent(x) > -#endif > - > static u_char packet[512]; /* last inbound (icmp) packet */ > static char *outpacket; /* last output packet */ > > @@ -304,6 +304,7 @@ int setpolicy(int so, char *policy); > #endif > void send_probe(int, u_long); > void *get_uphdr(struct ip6_hdr *, u_char *); > +void capdns_open(void); > int get_hoplim(struct msghdr *); > double deltaT(struct timeval *, struct timeval *); > const char *pr_type(int); > @@ -312,6 +313,8 @@ void print(struct msghdr *, int); > const char *inetname(struct sockaddr *); > u_int32_t sctp_crc32c(void *, u_int32_t); > u_int16_t in_cksum(u_int16_t *addr, int); > +u_int16_t udp_cksum(struct sockaddr_in6 *, struct sockaddr_in6 *, > + void *, u_int32_t); > u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *, > void *, u_int32_t); > void usage(void); > @@ -335,6 +338,8 @@ static struct cmsghdr *cmsg; > static char *source = NULL; > static char *hostname; > > +static cap_channel_t *capdns; > + > static u_long nprobes = 3; > static u_long first_hop = 1; > static u_long max_hops = 30; > @@ -368,7 +373,10 @@ main(int argc, char *argv[]) > char ipsec_inpolicy[] = "in bypass"; > char ipsec_outpolicy[] = "out bypass"; > #endif > + cap_rights_t rights; > > + capdns_open(); > + > /* > * Receive ICMP > */ > @@ -429,6 +437,7 @@ main(int argc, char *argv[]) > } > break; > case 'g': > + /* XXX use after capability mode is entered */ > hp = getipnodebyname(optarg, AF_INET6, 0, > &h_errno); > if (hp == NULL) { > fprintf(stderr, > @@ -560,8 +569,8 @@ main(int argc, char *argv[]) > sndsock = rcvsock; > break; > case IPPROTO_UDP: > - if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { > - perror("socket(SOCK_DGRAM)"); > + if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)) < > 0) { > + perror("socket(SOCK_RAW)"); > exit(5); > } > break; > @@ -606,7 +615,9 @@ main(int argc, char *argv[]) > hints.ai_socktype = SOCK_RAW; > hints.ai_protocol = IPPROTO_ICMPV6; > hints.ai_flags = AI_CANONNAME; > - error = getaddrinfo(*argv, NULL, &hints, &res); > + > + error = cap_getaddrinfo(capdns, *argv, NULL, &hints, &res); > + > if (error) { > fprintf(stderr, > "traceroute6: %s\n", gai_strerror(error)); > @@ -624,7 +635,7 @@ main(int argc, char *argv[]) > exit(1); > } > if (res->ai_next) { > - if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, > + if (cap_getnameinfo(capdns, res->ai_addr, res->ai_addrlen, > hbuf, > sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) > strlcpy(hbuf, "?", sizeof(hbuf)); > fprintf(stderr, "traceroute6: Warning: %s has multiple " > @@ -803,7 +814,7 @@ main(int argc, char *argv[]) > hints.ai_family = AF_INET6; > hints.ai_socktype = SOCK_DGRAM; /*dummy*/ > hints.ai_flags = AI_NUMERICHOST; > - error = getaddrinfo(source, "0", &hints, &res); > + error = cap_getaddrinfo(capdns, source, "0", &hints, &res); > if (error) { > printf("traceroute6: %s: %s\n", source, > gai_strerror(error)); > @@ -839,7 +850,7 @@ main(int argc, char *argv[]) > perror("getsockname"); > exit(1); > } > - if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, > + if (cap_getnameinfo(capdns, (struct sockaddr *)&Src, > Src.sin6_len, > src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { > fprintf(stderr, "getnameinfo failed for source\n"); > exit(1); > @@ -879,7 +890,7 @@ main(int argc, char *argv[]) > /* > * Message to users > */ > - if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, > + if (cap_getnameinfo(capdns, (struct sockaddr *)&Dst, Dst.sin6_len, > hbuf, > sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) > strlcpy(hbuf, "(invalid)", sizeof(hbuf)); > fprintf(stderr, "traceroute6"); > @@ -894,7 +905,31 @@ main(int argc, char *argv[]) > if (first_hop > 1) > printf("Skipping %lu intermediate hops\n", first_hop - 1); > > + if (connect(sndsock, (struct sockaddr *)&Dst, > + sizeof(Dst)) != 0) { > + fprintf(stderr, "connect: %s\n", strerror(errno)); > + exit(1); > + } > + > /* > + * 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 (caph_enter_casper() < 0) { > + fprintf(stderr, "caph_enter_casper: %s\n", > strerror(errno)); > + exit(1); > + } > + > + cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT); > + if (caph_rights_limit(sndsock, &rights) < 0) { > + fprintf(stderr, "caph_rights_limit sndsock: %s\n", > + strerror(errno)); > + exit(1); > + } > + > + /* > * Main loop > */ > for (hops = first_hop; hops <= max_hops; ++hops) { > @@ -1038,6 +1073,7 @@ send_probe(int seq, u_long hops) > { > struct icmp6_hdr *icp; > struct sctphdr *sctp; > + struct udphdr *outudp; > struct sctp_chunkhdr *chk; > struct sctp_init_chunk *init; > struct sctp_paramhdr *param; > @@ -1063,6 +1099,11 @@ send_probe(int seq, u_long hops) > icp->icmp6_seq = htons(seq); > break; > case IPPROTO_UDP: > + outudp = (struct udphdr *) outpacket; > + outudp->uh_sport = htons(ident); > + outudp->uh_dport = htons(port+seq); > + outudp->uh_ulen = htons(datalen); > + outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen); > break; > case IPPROTO_NONE: > /* No space for anything. No harm as seq/tv32 are > decorative. */ > @@ -1149,12 +1190,11 @@ send_probe(int seq, u_long hops) > fprintf(stderr, "Unknown probe protocol %d.\n", useproto); > exit(1); > } > - > - i = sendto(sndsock, (char *)outpacket, datalen, 0, > - (struct sockaddr *)&Dst, Dst.sin6_len); > + > + i = send(sndsock, (char *)outpacket, datalen, 0); > if (i < 0 || (u_long)i != datalen) { > if (i < 0) > - perror("sendto"); > + perror("send"); > printf("traceroute6: wrote %s %lu chars, ret=%d\n", > hostname, datalen, i); > (void) fflush(stdout); > @@ -1266,7 +1306,7 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, > u_char > hlen = sizeof(struct ip6_hdr); > if (cc < hlen + sizeof(struct icmp6_hdr)) { > if (verbose) { > - if (getnameinfo((struct sockaddr *)from, > from->sin6_len, > + if (cap_getnameinfo(capdns, (struct sockaddr > *)from, from->sin6_len, > hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) > != 0) > strlcpy(hbuf, "invalid", sizeof(hbuf)); > printf("packet too short (%d bytes) from %s\n", cc, > @@ -1279,7 +1319,7 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, > u_char > #else > if (cc < (int)sizeof(struct icmp6_hdr)) { > if (verbose) { > - if (getnameinfo((struct sockaddr *)from, > from->sin6_len, > + if (cap_getnameinfo(capdns, (struct sockaddr > *)from, from->sin6_len, > hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) > != 0) > strlcpy(hbuf, "invalid", sizeof(hbuf)); > printf("data too short (%d bytes) from %s\n", cc, > hbuf); > @@ -1345,7 +1385,7 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, > u_char > break; > case IPPROTO_UDP: > udp = (struct udphdr *)up; > - if (udp->uh_sport == htons(srcport) && > + if (udp->uh_sport == htons(ident) && > udp->uh_dport == htons(port + seq)) > return (1); > break; > @@ -1401,7 +1441,7 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, > u_char > u_int8_t *p; > int i; > > - if (getnameinfo((struct sockaddr *)from, from->sin6_len, > + if (cap_getnameinfo(capdns, (struct sockaddr *)from, > from->sin6_len, > sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) > strlcpy(sbuf, "invalid", sizeof(sbuf)); > printf("\n%d bytes from %s to %s", cc, sbuf, > @@ -1475,12 +1515,33 @@ get_uphdr(struct ip6_hdr *ip6, u_char *lim) > } > > void > +capdns_open() > +{ > + const char *types[] = { "NAME", "ADDR" }; > + int families[1]; > + cap_channel_t *casper; > + > + casper = cap_init(); > + if (casper == NULL) > + errx(1, "unable to create casper process"); > + capdns = cap_service_open(casper, "system.dns"); > + if (capdns == NULL) > + errx(1, "unable to open system.dns service"); > + if (cap_dns_type_limit(capdns, types, nitems(types)) < 0) > + errx(1, "unable to limit access to system.dns service"); > + families[0] = AF_INET6; > + if (cap_dns_family_limit(capdns, families, nitems(families)) < 0) > + errx(1, "unable to limit access to system.dns service"); > + cap_close(casper); > +} > + > +void > print(struct msghdr *mhdr, int cc) > { > struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; > char hbuf[NI_MAXHOST]; > > - if (getnameinfo((struct sockaddr *)from, from->sin6_len, > + if (cap_getnameinfo(capdns, (struct sockaddr *)from, > from->sin6_len, > hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) > strlcpy(hbuf, "invalid", sizeof(hbuf)); > if (as_path) > @@ -1527,7 +1588,7 @@ inetname(struct sockaddr *sa) > } > cp = NULL; > if (!nflag) { > - if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, > 0, > + if (cap_getnameinfo(capdns, sa, sa->sa_len, line, > sizeof(line), NULL, 0, > NI_NAMEREQD) == 0) { > if ((cp = strchr(line, '.')) && > !strcmp(cp + 1, domain)) > @@ -1538,7 +1599,7 @@ inetname(struct sockaddr *sa) > if (cp) > return cp; > > - if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, > + if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), > NULL, 0, > NI_NUMERICHOST) != 0) > strlcpy(line, "invalid", sizeof(line)); > return line; > @@ -1666,6 +1727,33 @@ in_cksum(u_int16_t *addr, int len) > sum += (sum >> 16); /* add carry */ > answer = ~sum; /* truncate to 16 bits */ > return (answer); > +} > + > +u_int16_t > +udp_cksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, > + void *payload, u_int32_t len) > +{ > + struct { > + struct in6_addr src; > + struct in6_addr dst; > + u_int32_t len; > + u_int8_t zero[3]; > + u_int8_t next; > + } pseudo_hdr; > + u_int16_t sum[2]; > + > + pseudo_hdr.src = src->sin6_addr; > + pseudo_hdr.dst = dst->sin6_addr; > + pseudo_hdr.len = htonl(len); > + pseudo_hdr.zero[0] = 0; > + pseudo_hdr.zero[1] = 0; > + pseudo_hdr.zero[2] = 0; > + pseudo_hdr.next = IPPROTO_UDP; > + > + sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr)); > + sum[0] = in_cksum(payload, len); > + > + return (~in_cksum(sum, sizeof(sum))); > } > > u_int16_t > _______________________________________________ > svn-src-h...@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/svn-src-head > To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org" > _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"