From 8ddfdffdd892f3ab3fb42c10ff5abd6653f7c166 Mon Sep 17 00:00:00 2001 From: ian Date: Sat, 29 Aug 1998 21:22:23 +0000 Subject: [PATCH] Initial checkin. --- .cvsignore | 4 ++ Makefile | 19 +++++++ authbind.c | 38 ++++++++++++++ debian/.cvsignore | 3 ++ debian/changelog | 9 ++++ debian/control | 13 +++++ debian/copyright | 1 + debian/rules | 75 ++++++++++++++++++++++++++ debian/shlibs | 1 + debian/shlibs.alpha | 1 + helper.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ libauthbind.c | 97 ++++++++++++++++++++++++++++++++++ 12 files changed, 386 insertions(+) create mode 100644 .cvsignore create mode 100644 Makefile create mode 100644 authbind.c create mode 100644 debian/.cvsignore create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100755 debian/rules create mode 100644 debian/shlibs create mode 100644 debian/shlibs.alpha create mode 100644 helper.c create mode 100644 libauthbind.c diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..5f1941a --- /dev/null +++ b/.cvsignore @@ -0,0 +1,4 @@ +authbind +helper +libauthbind.o +libauthbind.so.0.1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5618a5f --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +# +OPTIMISE= -O2 +CFLAGS= -g $(OPTIMISE) \ + -Wall -Wwrite-strings -Wpointer-arith -Wimplicit \ + -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes + +TARGETS= authbind helper libauthbind.so.0.1 + +all: $(TARGETS) + +libauthbind.o: libauthbind.c + gcc -D_REENTRANT -g $(CFLAGS) -c -o libauthbind.o -fPIC libauthbind.c + +libauthbind.so.0.1: libauthbind.o + gcc -g -shared -Wl,-soname,libauthbind.so.0.1 -o libauthbind.so.0.1 libauthbind.o -ldl -lc + +clean distclean: + rm -f $(TARGETS) *.o *~ ./#*# *.bak debian/*~ + rm -f core libauthbind.so* diff --git a/authbind.c b/authbind.c new file mode 100644 index 0000000..6d957ae --- /dev/null +++ b/authbind.c @@ -0,0 +1,38 @@ +/**/ + +#include +#include +#include +#include + +#define LD_PRELOAD "LD_PRELOAD" +#define AUTHBINDLIB "AUTHBIND_LIB" +#define LIBAUTHBIND "/usr/lib/authbind/libauthbind.so.0" + +int main(int argc, char *const *argv) { + const char *expreload, *authbindlib, *preload; + char *newpreload; + + authbindlib= getenv(AUTHBINDLIB); + if (!authbindlib) { + if (setenv(AUTHBINDLIB,LIBAUTHBIND,0)) { + perror("authbind: setenv " AUTHBINDLIB); + exit(-1); + } + authbindlib= LIBAUTHBIND; + } + + if ((expreload= getenv(LD_PRELOAD))) { + newpreload= malloc(strlen(expreload)+strlen(authbindlib)+2); + strcpy(newpreload,expreload); + strcat(newpreload,":"); + strcat(newpreload,authbindlib); + preload= newpreload; + } else { + preload= authbindlib; + } + if (setenv(LD_PRELOAD,preload,1)) { perror("authbind: setenv"); exit(-1); } + + execvp(argv[1],argv+1); + perror(argv[1]); exit(-1); +} diff --git a/debian/.cvsignore b/debian/.cvsignore new file mode 100644 index 0000000..db09c07 --- /dev/null +++ b/debian/.cvsignore @@ -0,0 +1,3 @@ +files +substvars +tmp diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..3ac61d6 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,9 @@ +authbind (0.1-1) experimental; urgency=low + + * Initial release. + + -- Ian Jackson Sat, 29 Aug 1998 20:10:37 +0100 + +Local variables: +mode: debian-changelog +End: diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..261df18 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: authbind +Section: utils +Priority: extra +Maintainer: Ian Jackson +Standards-Version: 2.1.1.0 + +Package: authbind +Architecture: any +Depends: ${shlibs:Depends} +Description: Allows non-root programs to bind() to low ports + This package allows a package to be started as non-root but + still bind to low ports. The ports allowed to who are in + /etc/authbind/ - make it executable to allow. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..220317d --- /dev/null +++ b/debian/copyright @@ -0,0 +1 @@ +GNU copyleft joost witteveen, . diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..b6fc00b --- /dev/null +++ b/debian/rules @@ -0,0 +1,75 @@ +#! /usr/bin/make -f +# -*- mode: makefile; -*- +# +# Modified by Ian Jackson for authbind. +# Then last updated: Sat Dec 17 10:52:20 EST 1994 by imurdock. +# +# To make the binary distribution package, the ``Debianized'' source package +# and the context diff to the original package, type `./debian.rules dist'. +# Make sure that `debian.rules' is executable before the final distribution +# is made. +# +# Invoke each target with `./debian.rules '. All targets should be +# invoked with the package root as the current directory. +# +# The `binary' target must be run as root, as it needs to install files with +# specific ownerships. The `diff' target assumes that you have the original +# source package available, unpacked, in ../$(p)-$(v).orig, or that you have +# the previous revision of the ``Debianized'' source package and context diff +# in the parent directory. + +CC = gcc + +package=authbind +major=0 +minor=1 + +arch = $(shell dpkg --print-architecture) + +build: + $(MAKE) + +clean: + rm -rf debian/{files,substvars,tmp} build + $(MAKE) distclean + +binary-indep: checkroot build + $(checkdir) +# There are no architecture-independent files to be uploaded +# generated by this package. If there were any they would be +# made here. + +lab=libauthbind.so.$(major).$(minor) + +binary-arch: checkroot build + rm -rf debian/tmp + install -d -g root -m 755 -o root debian/tmp/DEBIAN \ + debian/tmp/usr/{bin,lib/$(package),doc/$(package)} \ + debian/tmp/etc/authbind/{byport,byname,byuid} + install -s -g root -o root -m 755 authbind debian/tmp/usr/bin/. + install -s -g root -o root -m 4755 helper debian/tmp/usr/lib/authbind/. + install -s -g root -o root -m 755 $(lab) debian/tmp/usr/lib/authbind/. + ln -s $(lab) debian/tmp/usr/lib/authbind/libauthbind.so.$(major) + strip --strip-unneeded debian/tmp/usr/lib/authbind/$(lab) + install -g root -o root -m 644 debian/copyright debian/tmp/usr/doc/$(package)/ + install -g root -o root -m 644 debian/changelog \ + debian/tmp/usr/doc/$(package)/changelog.Debian + gzip -9 debian/tmp/usr/doc/$(package)/* +ifneq ($(arch),alpha) + install -g root -o root -m 644 debian/shlibs debian/tmp/DEBIAN +else + install -g root -o root -m 644 debian/shlibs.alpha debian/tmp/DEBIAN/shlibs +endif + dpkg-shlibdeps ./authbind + dpkg-gencontrol + chown -R root.root debian/tmp + chmod -R g-ws debian/tmp + #/bin/bash #-c "ls debian/tmp" + #bash -c "dpkg --build debian/tmp .." + dpkg --build debian/tmp .. + +binary: binary-indep binary-arch + +checkroot: + $(checkdir) + test root = "`whoami`" diff --git a/debian/shlibs b/debian/shlibs new file mode 100644 index 0000000..ae3640e --- /dev/null +++ b/debian/shlibs @@ -0,0 +1 @@ +/usr/lib/libfakeroot/libfakeroot 0 libc6 diff --git a/debian/shlibs.alpha b/debian/shlibs.alpha new file mode 100644 index 0000000..00dfeef --- /dev/null +++ b/debian/shlibs.alpha @@ -0,0 +1 @@ +/usr/lib/libfakeroot/libfakeroot 0 libc6.1 diff --git a/helper.c b/helper.c new file mode 100644 index 0000000..e086e9e --- /dev/null +++ b/helper.c @@ -0,0 +1,125 @@ +/* + * setuid. Invoked with socket on stdin. + * Usage: helper + * both are hex strings, padded to the right length. + * they are pairs of hex digits for each byte (network byte order) + * + * If /etc/authbind cannot be chdir'd into, is an error. + * + * First, check /etc/authbind/byport/ with access(2,X_OK). + * If OK, then authorised. + * If ENOENT then keep looking. + * Otherwise, not authorised, errno=whatever + * + * Then check /etc/authbind/byboth/: likewise. + * + * Then try to read /etc/authbind/byuid/ (with superuser privs!) + * If ENOENT, then not authorised, errno=EPERM + * If cannot open, then not authorised, errno=whatever + * If it contains a line of the form + * /:, + * then authorised, otherwise not authorised, errno=ENOENT + * If read error then is an error + * + * In each case, + * is dotted quad + * is decimal in host order + * is prefix length (so 0.0.0.0/32 matches any) + * is decimal unsigned + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIGDIR "/etc/authbind" + +static void exiterrno(int e) { + exit(e>0 && e<128 ? e : ENOSYS); +} + +static void perrorfail(const char *m) { + int e; + e= errno; + fprintf(stderr,"libauthbind's helper: %s: %s\n",m,strerror(e)); + exiterrno(e); +} + +static void badusage(void) { + fputs("libauthbind's helper: bad usage\n",stderr); + exit(ENOSYS); +} + +static struct sockaddr_in saddr; + +static void authorised(void) { + if (bind(0,&saddr,sizeof(saddr))) exiterrno(errno); + else _exit(0); +} + +int main(int argc, const char *const *argv) { + uid_t uid; + char fnbuf[100]; + char *ep; + const char *np; + unsigned long addr, port, haddr, thaddr, thmask; + unsigned int hport, a1,a2,a3,a4, 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(); + + 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; + hport= htons(port); + + 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 (!access(fnbuf,X_OK)) authorised(); + if (errno != ENOENT) exiterrno(errno); + + uid= getuid(); if (uid==(uid_t)-1) perrorfail("getuid"); + snprintf(fnbuf,sizeof(fnbuf)-1,"byuid/%lu",(unsigned long)uid); + + file= fopen(fnbuf,"r"); + if (!file) exiterrno(errno==ENOENT ? EPERM : errno); + + haddr= ntohl(addr); + + while (fgets(fnbuf,sizeof(fnbuf)-1,file)) { + 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) + continue; + + if (hportpmax) continue; + + thaddr= (a1<<24)|(a2<<16)|(a3<<8)|(a4); + thmask= 0x0ffffffffUL<<(32-alen); + if ((haddr&thmask) != thaddr) continue; + authorised(); + } + if (ferror(file)) perrorfail("read per-uid file"); + _exit(ENOENT); +} diff --git a/libauthbind.c b/libauthbind.c new file mode 100644 index 0000000..d7b3f89 --- /dev/null +++ b/libauthbind.c @@ -0,0 +1,97 @@ +/* + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AUTHBIND_NESTED "AUTHBIND_NESTED" +#define HELPER "/usr/lib/authbind/helper" + +typedef void anyfn_type(void); +typedef int bindfn_type(int fd, const struct sockaddr *addr, socklen_t addrlen); + +#define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1) +#define STDERRSTR_STRING(m) write(2,m,strlen(m)) + +static int find_any(const char *name, anyfn_type **keep) { + static const char *dlerr; + anyfn_type *kv; + + if (*keep) return 0; + kv= dlsym(RTLD_NEXT,name); + if (kv) { *keep= kv; return 0; } + dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason"; + STDERRSTR_CONST("libauthbind: error finding original version of "); + STDERRSTR_STRING(name); + STDERRSTR_CONST(": "); + STDERRSTR_STRING(dlerr); + STDERRSTR_STRING("\n"); + errno= ENOSYS; + return -1; +} + +static bindfn_type find_bind, *old_bind= find_bind; + +int find_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { + anyfn_type *anyfn; + if (find_any("bind",&anyfn)) return -1; + old_bind= (bindfn_type*)anyfn; + return old_bind(fd,addr,addrlen); +} + +static int exiterrno(int e) { + _exit(e>0 && e<128 ? e : -1); +} + +int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { + pid_t child, rchild; + char portarg[5], addrarg[9]; + int status; + + if (addr->sa_family != AF_INET || addrlen != sizeof(struct sockaddr_in) || + ntohs(((struct sockaddr_in*)addr)->sin_port) >= 1024 || !geteuid()) + return old_bind(fd,addr,addrlen); + + if (getenv(AUTHBIND_NESTED)) { + STDERRSTR_CONST("libauthbind: possible installation problem - " + "nested invocation, perhaps helper is not setuid\n"); + return old_bind(fd,addr,addrlen); + } + + 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); + + child= fork(); if (child==-1) return -1; + + if (!child) { + if (dup2(fd,0)) exiterrno(errno); + if (setenv(AUTHBIND_NESTED,"1",1)) exiterrno(errno); + execl(HELPER,HELPER,addrarg,portarg,(char*)0); + status= errno; + STDERRSTR_CONST("libauthbind: possible installation problem - " + "could not invoke " HELPER "\n"); + exiterrno(status); + } + + rchild= waitpid(child,&status,0); + if (rchild==-1) return -1; + if (rchild!=child) { errno= ECHILD; return -1; } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) { errno= WEXITSTATUS(status); return -1; } + return 0; + } else { + errno= ENOSYS; + return -1; + } +} -- 2.30.2