Date: Sun, 21 Mar 2004 12:09:24 -0800 (PST) From: Dariusz Kulinski <takeda3@netzero.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: ports/64546: [patch] problems with ipv6 connections when running as non-root Message-ID: <200403212009.i2LK9OSh019098@freebsd.takeda.tk> Resent-Message-ID: <200403212010.i2LKAHkE027462@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 64546 >Category: ports >Synopsis: [patch] problems with ipv6 connections when running as non-root >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Sun Mar 21 12:10:17 PST 2004 >Closed-Date: >Last-Modified: >Originator: Dariusz Kulinski >Release: FreeBSD 4.9-RELEASE-p4 i386 >Organization: >Environment: System: FreeBSD freebsd.takeda.tk 4.9-RELEASE-p4 FreeBSD 4.9-RELEASE-p4 #0: Wed Mar 17 22:05:17 PST 2004 root@freebsd.takeda.tk:/usr/obj/usr/src/sys/TUNED i386 >Description: oidentd had problems with connections through ipv6 while was degraded to regular user, new patch was added to fix that issue >How-To-Repeat: >Fix: --- oidentd.patch begins here --- diff -ruN oidentd.bak/files/patch-unprivileged_ipv6 oidentd/files/patch-unprivileged_ipv6 --- oidentd.bak/files/patch-unprivileged_ipv6 Wed Dec 31 16:00:00 1969 +++ oidentd/files/patch-unprivileged_ipv6 Sat Mar 20 20:38:56 2004 @@ -0,0 +1,392 @@ +diff -ru src.old/kernel/freebsd.c src/kernel/freebsd.c +--- src.old/kernel/freebsd.c Sat Mar 20 20:36:51 2004 ++++ src/kernel/freebsd.c Sat Mar 20 20:37:09 2004 +@@ -159,11 +159,11 @@ + + #ifdef _HAVE_OLD_INPCB + +-static struct socket *getlist4( void *arg, ++static struct socket *getlist( void *arg, + in_port_t lport, + in_port_t fport, +- const struct in_addr *laddr, +- const struct in_addr *faddr) ++ const struct sockaddr *laddr, ++ const struct sockaddr *faddr) + { + struct inpcb *pcbp = arg; + struct inpcb *head; +@@ -175,8 +175,8 @@ + + do { + if (opt_enabled(PROXY)) { +- if (faddr->s_addr == SIN4(&proxy)->sin_addr.s_addr && +- laddr->s_addr != SIN4(&proxy)->sin_addr.s_addr && ++ if (SIN4(faddr)->sin_addr.s_addr == SIN4(&proxy)->sin_addr.s_addr && ++ SIN4(laddr)->sin_addr.s_addr != SIN4(&proxy)->sin_addr.s_addr && + pcbp->inp_fport == fport && + pcbp->inp_lport == lport) + { +@@ -184,8 +184,8 @@ + } + } + +- if (pcbp->inp_faddr.s_addr == faddr->s_addr && +- pcbp->inp_laddr.s_addr == laddr->s_addr && ++ if (pcbp->inp_faddr.s_addr == SIN4(faddr)->sin_addr.s_addr && ++ pcbp->inp_laddr.s_addr == SIN4(laddr)->sin_addr.s_addr && + pcbp->inp_fport == fport && + pcbp->inp_lport == lport) + { +@@ -199,16 +199,33 @@ + + #else + +-static struct socket *getlist4( void *arg, ++static struct socket *getlist( void *arg, + in_port_t lport, + in_port_t fport, +- const struct in_addr *laddr, +- const struct in_addr *faddr) ++ const struct sockaddr *local, ++ const struct sockaddr *remote) + { + struct inpcb *head, pcbp; + struct inpcbhead *pcbhead = arg; ++ char *faddr, *laddr, *pfaddr, *pladdr; ++ int alen; + +- (void) laddr; ++ if (remote->sa_family != local->sa_family) ++ return (NULL); ++ switch (remote->sa_family) { ++ case AF_INET: ++ faddr = (char *)&SIN4(remote)->sin_addr; ++ laddr = (char *)&SIN4(local)->sin_addr; ++ break; ++#ifdef INP_IPV6 ++ case AF_INET6: ++ faddr = (char *)&SIN6(remote)->sin6_addr; ++ laddr = (char *)&SIN6(local)->sin6_addr; ++ break; ++#endif ++ default: ++ return (NULL); ++ } + + head = pcbhead->lh_first; + if (head == NULL) +@@ -218,9 +235,9 @@ + if (getbuf((u_long) head, &pcbp, sizeof(struct inpcb)) == -1) + break; + +- if (opt_enabled(PROXY)) { +- if (faddr->s_addr == SIN4(&proxy)->sin_addr.s_addr && +- laddr->s_addr != SIN4(&proxy)->sin_addr.s_addr && ++ if (opt_enabled(PROXY) && remote->sa_family == AF_INET) { ++ if (SIN4(remote)->sin_addr.s_addr == SIN4(&proxy)->sin_addr.s_addr && ++ SIN4(local)->sin_addr.s_addr != SIN4(&proxy)->sin_addr.s_addr && + pcbp.inp_fport == fport && + pcbp.inp_lport == lport) + { +@@ -228,8 +245,32 @@ + } + } + +- if (pcbp.inp_faddr.s_addr == faddr->s_addr && +- pcbp.inp_laddr.s_addr == laddr->s_addr && ++#ifdef INP_IPV6 ++ if (pcbp.inp_vflag & INP_IPV4) ++ { ++ if (remote->sa_family != AF_INET) ++ continue; ++ pfaddr = (char *)&pcbp.inp_faddr; ++ pladdr = (char *)&pcbp.inp_laddr; ++ alen = sizeof(struct in_addr); ++ } ++ else if (pcbp.inp_vflag & INP_IPV6) ++ { ++ if (remote->sa_family != AF_INET6) ++ continue; ++ pfaddr = (char *)&pcbp.in6p_faddr; ++ pladdr = (char *)&pcbp.in6p_laddr; ++ alen = sizeof(struct in6_addr); ++ } ++ else ++ continue; ++#else ++ pfaddr = (char *)&pcbp.inp_faddr; ++ pladdr = (char *)&pcbp.inp_laddr; ++ alen = sizeof(struct in_addr); ++#endif ++ if (memcmp(pfaddr, faddr, alen) == 0 && ++ memcmp(pladdr, laddr, alen) == 0 && + pcbp.inp_fport == fport && + pcbp.inp_lport == lport) + { +@@ -248,7 +289,7 @@ + ** Return the UID of the connection owner + */ + +-int get_user4( in_port_t lport, ++static int get_user( in_port_t lport, + in_port_t fport, + struct sockaddr_storage *laddr, + struct sockaddr_storage *faddr) +@@ -276,8 +317,9 @@ + tcb.inp_prev = (struct inpcb *) kinfo->nl[N_TCB].n_value; + #endif + +- sockp = getlist4(&tcb, lport, fport, +- &SIN4(laddr)->sin_addr, &SIN4(faddr)->sin_addr); ++ sockp = getlist(&tcb, lport, fport, ++ (struct sockaddr *)laddr, ++ (struct sockaddr *)faddr); + + if (sockp == NULL) + return (-1); +@@ -346,6 +388,14 @@ + return (-1); + } + ++int get_user4( in_port_t lport, ++ in_port_t fport, ++ struct sockaddr_storage *laddr, ++ struct sockaddr_storage *faddr) ++{ ++ return (get_user(lport, fport, laddr, faddr)); ++} ++ + #ifdef MASQ_SUPPORT + + /* +@@ -456,36 +506,7 @@ + struct sockaddr_storage *laddr, + struct sockaddr_storage *faddr) + { +- struct ucred ucred; +- struct sockaddr_in6 sin6[2]; +- int len; +- int ret; +- +- len = sizeof(struct ucred); +- +- memset(sin6, 0, sizeof(sin6)); +- +- sin6[0].sin6_len = sizeof(struct sockaddr_in6); +- sin6[0].sin6_family = AF_INET6; +- sin6[0].sin6_port = lport; +- memcpy(&sin6[0].sin6_addr, &SIN6(laddr)->sin6_addr, +- sizeof(sin6[0].sin6_addr)); +- +- sin6[1].sin6_len = sizeof(struct sockaddr_in6); +- sin6[1].sin6_family = AF_INET6; +- sin6[1].sin6_port = fport; +- memcpy(&sin6[1].sin6_addr, &SIN6(faddr)->sin6_addr, +- sizeof(sin6[1].sin6_addr)); +- +- ret = sysctlbyname("net.inet6.tcp6.getcred", +- &ucred, &len, sin6, sizeof(sin6)); +- +- if (ret == -1) { +- debug("sysctlbyname: %s", strerror(errno)); +- return (-1); +- } +- +- return (ucred.cr_uid); ++ return (get_user(lport, fport, laddr, faddr)); + } + + #endif +diff -ru src.old/kernel/freebsd5.c src/kernel/freebsd5.c +--- src.old/kernel/freebsd5.c Sat Mar 20 20:36:51 2004 ++++ src/kernel/freebsd5.c Sat Mar 20 20:37:13 2004 +@@ -160,11 +160,11 @@ + + #ifdef _HAVE_OLD_INPCB + +-static struct socket *getlist4( void *arg, ++static struct socket *getlist( void *arg, + in_port_t lport, + in_port_t fport, +- const struct in_addr *laddr, +- const struct in_addr *faddr) ++ const struct sockaddr *laddr, ++ const struct sockaddr *faddr) + { + struct inpcb *pcbp = arg; + struct inpcb *head; +@@ -176,8 +176,8 @@ + + do { + if (opt_enabled(PROXY)) { +- if (faddr->s_addr == SIN4(&proxy)->sin_addr.s_addr && +- laddr->s_addr != SIN4(&proxy)->sin_addr.s_addr && ++ if (SIN4(faddr)->sin_addr.s_addr == SIN4(&proxy)->sin_addr.s_addr && ++ SIN4(laddr)->sin_addr.s_addr != SIN4(&proxy)->sin_addr.s_addr && + pcbp->inp_fport == fport && + pcbp->inp_lport == lport) + { +@@ -185,8 +185,8 @@ + } + } + +- if (pcbp->inp_faddr.s_addr == faddr->s_addr && +- pcbp->inp_laddr.s_addr == laddr->s_addr && ++ if (pcbp->inp_faddr.s_addr == SIN4(faddr)->sin_addr.s_addr && ++ pcbp->inp_laddr.s_addr == SIN4(laddr)->sin_addr.s_addr && + pcbp->inp_fport == fport && + pcbp->inp_lport == lport) + { +@@ -200,16 +200,31 @@ + + #else + +-static struct socket *getlist4( void *arg, ++static struct socket *getlist( void *arg, + in_port_t lport, + in_port_t fport, +- const struct in_addr *laddr, +- const struct in_addr *faddr) ++ const struct sockaddr *local, ++ const struct sockaddr *remote) + { + struct inpcb *head, pcbp; + struct inpcbhead *pcbhead = arg; ++ char *faddr, *laddr, *pfaddr, *pladdr; ++ int alen; + +- (void) laddr; ++ if (remote->sa_family != local->sa_family) ++ return (NULL); ++ switch (remote->sa_family) { ++ case AF_INET: ++ faddr = (char *)&SIN4(remote)->sin_addr; ++ laddr = (char *)&SIN4(local)->sin_addr; ++ break; ++ case AF_INET6: ++ faddr = (char *)&SIN6(remote)->sin6_addr; ++ laddr = (char *)&SIN6(local)->sin6_addr; ++ break; ++ default: ++ return (NULL); ++ } + + head = pcbhead->lh_first; + if (head == NULL) +@@ -219,9 +234,9 @@ + if (getbuf((u_long) head, &pcbp, sizeof(struct inpcb)) == -1) + break; + +- if (opt_enabled(PROXY)) { +- if (faddr->s_addr == SIN4(&proxy)->sin_addr.s_addr && +- laddr->s_addr != SIN4(&proxy)->sin_addr.s_addr && ++ if (opt_enabled(PROXY) && remote->sa_family == AF_INET) { ++ if (SIN4(remote)->sin_addr.s_addr == SIN4(&proxy)->sin_addr.s_addr && ++ SIN4(local)->sin_addr.s_addr != SIN4(&proxy)->sin_addr.s_addr && + pcbp.inp_fport == fport && + pcbp.inp_lport == lport) + { +@@ -229,8 +244,26 @@ + } + } + +- if (pcbp.inp_faddr.s_addr == faddr->s_addr && +- pcbp.inp_laddr.s_addr == laddr->s_addr && ++ if (pcbp.inp_vflag & INP_IPV4) ++ { ++ if (remote->sa_family != AF_INET) ++ continue; ++ pfaddr = (char *)&pcbp.inp_faddr; ++ pladdr = (char *)&pcbp.inp_laddr; ++ alen = sizeof(struct in_addr); ++ } ++ else if (pcbp.inp_vflag & INP_IPV6) ++ { ++ if (remote->sa_family != AF_INET6) ++ continue; ++ pfaddr = (char *)&pcbp.in6p_faddr; ++ pladdr = (char *)&pcbp.in6p_laddr; ++ alen = sizeof(struct in6_addr); ++ } ++ else ++ continue; ++ if (memcmp(pfaddr, faddr, alen) == 0 && ++ memcmp(pladdr, laddr, alen) == 0 && + pcbp.inp_fport == fport && + pcbp.inp_lport == lport) + { +@@ -249,7 +282,7 @@ + ** Return the UID of the connection owner + */ + +-int get_user4( in_port_t lport, ++static int get_user( in_port_t lport, + in_port_t fport, + struct sockaddr_storage *laddr, + struct sockaddr_storage *faddr) +@@ -276,8 +309,9 @@ + tcb.inp_prev = (struct inpcb *) kinfo->nl[N_TCB].n_value; + #endif + +- sockp = getlist4(&tcb, lport, fport, +- &SIN4(laddr)->sin_addr, &SIN4(faddr)->sin_addr); ++ sockp = getlist(&tcb, lport, fport, ++ (struct sockaddr *)laddr, ++ (struct sockaddr *)faddr); + + if (sockp == NULL) + return (-1); +@@ -338,6 +372,14 @@ + return (-1); + } + ++int get_user4( in_port_t lport, ++ in_port_t fport, ++ struct sockaddr_storage *laddr, ++ struct sockaddr_storage *faddr) ++{ ++ return (get_user(lport, fport, laddr, faddr)); ++} ++ + #ifdef MASQ_SUPPORT + + /* +@@ -448,36 +490,7 @@ + struct sockaddr_storage *laddr, + struct sockaddr_storage *faddr) + { +- struct ucred ucred; +- struct sockaddr_in6 sin6[2]; +- int len; +- int ret; +- +- len = sizeof(struct ucred); +- +- memset(sin6, 0, sizeof(sin6)); +- +- sin6[0].sin6_len = sizeof(struct sockaddr_in6); +- sin6[0].sin6_family = AF_INET6; +- sin6[0].sin6_port = lport; +- memcpy(&sin6[0].sin6_addr, &SIN6(laddr)->sin6_addr, +- sizeof(sin6[0].sin6_addr)); +- +- sin6[1].sin6_len = sizeof(struct sockaddr_in6); +- sin6[1].sin6_family = AF_INET6; +- sin6[1].sin6_port = fport; +- memcpy(&sin6[1].sin6_addr, &SIN6(faddr)->sin6_addr, +- sizeof(sin6[1].sin6_addr)); +- +- ret = sysctlbyname("net.inet6.tcp6.getcred", +- &ucred, &len, sin6, sizeof(sin6)); +- +- if (ret == -1) { +- debug("sysctlbyname: %s", strerror(errno)); +- return (-1); +- } +- +- return (ucred.cr_uid); ++ return (get_user(lport, fport, laddr, faddr)); + } + + #endif --- oidentd.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403212009.i2LK9OSh019098>