svn commit: r365378 - head/usr.sbin/traceroute6
Oliver Pinter
oliver.pntr at gmail.com
Sun Sep 6 18:32:48 UTC 2020
On Sunday, September 6, 2020, Mariusz Zaborski <oshogbo at 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 <shubh at 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-head at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-head
> To unsubscribe, send any mail to "svn-src-head-unsubscribe at freebsd.org"
>
More information about the svn-src-all
mailing list