diff -urpN authbind-1.2.0~/authbind.1 authbind-1.2.0/authbind.1 --- authbind-1.2.0~/authbind.1 2003-06-30 03:31:21.000000000 +0530 +++ authbind-1.2.0/authbind.1 2010-09-08 06:54:48.000000000 +0530 @@ -84,8 +84,10 @@ call, usually .RI ( "Permission denied" ). .PP Secondly, if that test fails to resolve the matter, -.BI /etc/authbind/byaddr/ addr : port -is tested, in the same manner as above. +.BI /etc/authbind/byaddr/ ip4addr : port +or +.BI /etc/authbind/byaddr/ [ip6addr] : port +are tested, in the same manner as above. .PP Thirdly, if the question is still unresolved, the file .BI /etc/authbind/byuid/ uid @@ -99,13 +101,14 @@ If the file does exist it will be search .nf .IB addr / length : min\-port , max\-port .fi -matching the request (ie, the initial +matching the request, i.e., where addr is an IPv4 or IPv6 address, and +the initial .I length bits of .I addr match those in the proposed .B bind -call, and the proposed port number lies is in the inclusive range +call, and the proposed port number lies in the inclusive range specified. If such a line is found then the binding is authorised. Otherwise it is not, and .B bind @@ -120,7 +123,7 @@ is the (local) TCP or UDP port number, e integer in the minimal non-zero number of digits, and .TP .I addr -is the (local) IP address, as a dotted quad. +is the (local) IP address, as a dotted quad or an IPv6 address. .PP If a read error occurs, or the directory .B /etc/authbind @@ -178,8 +181,8 @@ the program's stderr, was well as return .BR bind . .SH BUGS .B authbind -currently only supports IPv4 sockets. Programs which open other kinds -of sockets will not benefit from +currently only supports IPv4 and IPv6 sockets. Programs which open +other kinds of sockets will not benefit from .BR authbind , but it won't get in their way. .PP diff -urpN authbind-1.2.0~/libauthbind.c authbind-1.2.0/libauthbind.c --- authbind-1.2.0~/libauthbind.c 2004-04-03 00:24:27.000000000 +0530 +++ authbind-1.2.0/libauthbind.c 2010-09-07 22:57:46.000000000 +0530 @@ -30,6 +30,7 @@ #include #include #include +#include static const char *rcsid="$Id: libauthbind.c,v 1.8 2004/04/02 18:54:27 ian Exp $"; @@ -146,14 +147,22 @@ static const int evilsignals[]= { SIGFPE int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { pid_t child, rchild; - char portarg[5], addrarg[9]; + char portarg[5], addrarg[INET6_ADDRSTRLEN+1]; int r, status; const int *evilsignal; sigset_t block, saved; + unsigned int port = 0; + const char *familyarg; + const void *srcaddr; + + if (addr->sa_family == AF_INET && addrlen == sizeof(struct sockaddr_in)) + port = ntohs(((struct sockaddr_in *)addr)->sin_port); + else if (addr->sa_family == AF_INET6 && + addrlen == sizeof(struct sockaddr_in6)) + port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - if (addr->sa_family != AF_INET || addrlen != sizeof(struct sockaddr_in) || - !geteuid() || ((struct sockaddr_in*)addr)->sin_port == 0 || - ntohs(((struct sockaddr_in*)addr)->sin_port) >= IPPORT_RESERVED/2) + if (!(addr->sa_family == AF_INET || addr->sa_family == AF_INET6) || + !geteuid() || port == 0 || port >= IPPORT_RESERVED/2) return old_bind(fd,addr,addrlen); sigfillset(&block); @@ -162,18 +171,26 @@ int bind(int fd, const struct sockaddr * evilsignal++) sigdelset(&block,*evilsignal); if (sigprocmask(SIG_BLOCK,&block,&saved)) return -1; - - sprintf(addrarg,"%08lx", - ((unsigned long)(((struct sockaddr_in*)addr)->sin_addr.s_addr))&0x0ffffffffUL); - sprintf(portarg,"%04x", - ((unsigned int)(((struct sockaddr_in*)addr)->sin_port))&0x0ffff); + + if (addr->sa_family == AF_INET) { + familyarg = "4"; + srcaddr = &((struct sockaddr_in *)addr)->sin_addr; + } + else /* if (addr->sa_family == AF_INET6) */ { + familyarg = "6"; + srcaddr = &((struct sockaddr_in6 *)addr)->sin6_addr; + } + if (!inet_ntop(addr->sa_family,srcaddr,addrarg,INET6_ADDRSTRLEN)) + goto x_err; + + sprintf(portarg,"%04x",port); child= fork(); if (child==-1) goto x_err; if (!child) { if (dup2(fd,0)) exiterrno(errno); removepreload(); - execl(HELPER,HELPER,addrarg,portarg,(char*)0); + execl(HELPER,HELPER,familyarg,addrarg,portarg,(char*)0); status= errno > 0 && errno < 127 ? errno : 127; STDERRSTR_CONST("libauthbind: possible installation problem - " "could not invoke " HELPER " ("); diff -urpN authbind-1.2.0~/helper.c authbind-1.2.0/helper.c --- authbind-1.2.0~/helper.c 1998-08-31 01:22:38.000000000 +0530 +++ authbind-1.2.0/helper.c 2010-09-08 10:12:28.000000000 +0530 @@ -52,43 +52,67 @@ static void badusage(void) { exit(ENOSYS); } +static struct sockaddr * addr; static struct sockaddr_in saddr; +static struct sockaddr_in6 s6addr; +static int addrlen; static void authorised(void) { - if (bind(0,&saddr,sizeof(saddr))) exiterrno(errno); + if (bind(0,addr,addrlen)) exiterrno(errno); else _exit(0); } int main(int argc, const char *const *argv) { uid_t uid; - char fnbuf[100]; + char fnbuf[100], addrstr[INET6_ADDRSTRLEN]; char *ep; - const char *np; - unsigned long addr, port, haddr, thaddr, thmask; - unsigned int hport, a1,a2,a3,a4, alen,pmin,pmax; + unsigned long port; + unsigned int hport, alen,pmin,pmax; int nchar; FILE *file; - if (argc != 3) badusage(); - addr= strtoul(argv[1],&ep,16); if (*ep || addr&~0x0ffffffffUL) badusage(); - port= strtoul(argv[2],&ep,16); if (*ep || port&~0x0ffffUL) badusage(); - hport= htons(port); - if (hport >= IPPORT_RESERVED/2) _exit(EPERM); + if (argc != 4) badusage(); + + port= strtoul(argv[3],&ep,16); if (*ep || port&~0x0ffffUL) badusage(); + if (port >= IPPORT_RESERVED/2) _exit(EPERM); + hport = port&0x0ffffUL; + + if (!strcmp(argv[1],"4")) { + memset(&saddr,0,sizeof(saddr)); + saddr.sin_family = AF_INET; + if (inet_pton(AF_INET,argv[2],&saddr.sin_addr) <= 0 || + !inet_ntop(AF_INET6,&saddr.sin_addr,addrstr,INET6_ADDRSTRLEN)) + badusage(); + saddr.sin_port = htons(port); + addr = (struct sockaddr *)&saddr; + addrlen = sizeof(saddr); + } + else if (!strcmp(argv[1],"6")) { + memset(&s6addr,0,sizeof(s6addr)); + s6addr.sin6_family = AF_INET6; + if (inet_pton(AF_INET6,argv[2],&s6addr.sin6_addr) <= 0 || + !inet_ntop(AF_INET6,&s6addr.sin6_addr,addrstr,INET6_ADDRSTRLEN)) + badusage(); + s6addr.sin6_port = htons(port); + addr = (struct sockaddr *)&s6addr; + addrlen = sizeof(s6addr); + } + else { + badusage(); + } if (chdir(CONFIGDIR)) perrorfail("chdir " CONFIGDIR); fnbuf[sizeof(fnbuf)-1]= 0; - memset(&saddr,0,sizeof(saddr)); - saddr.sin_family= AF_INET; - saddr.sin_port= port; - saddr.sin_addr.s_addr= addr; snprintf(fnbuf,sizeof(fnbuf)-1,"byport/%u",hport); if (!access(fnbuf,X_OK)) authorised(); if (errno != ENOENT) exiterrno(errno); - np= inet_ntoa(saddr.sin_addr); assert(np); - snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s:%u",np,hport); + if (addr->sa_family == AF_INET) + snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s:%u",addrstr,hport); + else + snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/[%s]:%u",addrstr,hport); if (!access(fnbuf,X_OK)) authorised(); if (errno != ENOENT) exiterrno(errno); @@ -98,22 +122,46 @@ int main(int argc, const char *const *ar file= fopen(fnbuf,"r"); if (!file) exiterrno(errno==ENOENT ? EPERM : errno); - haddr= ntohl(addr); - while (fgets(fnbuf,sizeof(fnbuf)-1,file)) { + unsigned char a[16], *b; + int family = AF_INET, bytes = 0; + char *slash = index(fnbuf,'/'); + if (!slash) + continue; + *slash++ = '\0'; + + memset(a,0,16); + if (index(fnbuf,':')) + family = AF_INET6; + if (addr->sa_family != family || + inet_pton(family,fnbuf,a) <= 0) + continue; + nchar= -1; - sscanf(fnbuf," %u.%u.%u.%u/%u:%u,%u %n", - &a1,&a2,&a3,&a4,&alen,&pmin,&pmax,&nchar); - if (nchar != strlen(fnbuf) || - alen>32 || pmin&~0x0ffff || pmax&~0x0ffff || - a1&~0x0ff || a2&~0xff || a3&~0x0ff || a4&~0x0ff) + sscanf(slash,"%u:%u,%u %n",&alen,&pmin,&pmax,&nchar); + if (nchar != strlen(slash) || + (family == AF_INET && alen > 32) || + (family == AF_INET6 && alen > 128) || + pmin&~0x0ffff || pmax&~0x0ffff) continue; - + if (hportpmax) continue; - thaddr= (a1<<24)|(a2<<16)|(a3<<8)|(a4); - thmask= 0x0ffffffffUL<<(32-alen); - if ((haddr&thmask) != thaddr) continue; + if (addr->sa_family == AF_INET) + b = (void *)&saddr.sin_addr; + else + b = (void *)&s6addr.sin6_addr; + + bytes = alen/8; + if (bytes && memcmp(a,b,bytes)) + continue; + + if (alen%8) { + unsigned char mask = 0xFF<<(8-alen%8); + if ((a[bytes]&mask) != (b[bytes]&mask)) + continue; + } + authorised(); } if (ferror(file)) perrorfail("read per-uid file");