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