11 #include <sys/socket.h>
13 #include <netinet/in.h>
15 #define AUTHBIND_NESTED "AUTHBIND_NESTED"
16 #define HELPER "/usr/lib/authbind/helper"
18 typedef void anyfn_type(void);
19 typedef int bindfn_type(int fd, const struct sockaddr *addr, socklen_t addrlen);
21 #define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1)
22 #define STDERRSTR_STRING(m) write(2,m,strlen(m))
24 static int find_any(const char *name, anyfn_type **keep) {
25 static const char *dlerr;
29 kv= dlsym(RTLD_NEXT,name);
30 if (kv) { *keep= kv; return 0; }
31 dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason";
32 STDERRSTR_CONST("libauthbind: error finding original version of ");
33 STDERRSTR_STRING(name);
34 STDERRSTR_CONST(": ");
35 STDERRSTR_STRING(dlerr);
36 STDERRSTR_STRING("\n");
41 static bindfn_type find_bind, *old_bind= find_bind;
43 int find_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
45 if (find_any("bind",&anyfn)) return -1;
46 old_bind= (bindfn_type*)anyfn;
47 return old_bind(fd,addr,addrlen);
50 static int exiterrno(int e) {
51 _exit(e>0 && e<128 ? e : -1);
54 int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
56 char portarg[5], addrarg[9];
59 if (addr->sa_family != AF_INET || addrlen != sizeof(struct sockaddr_in) ||
60 ntohs(((struct sockaddr_in*)addr)->sin_port) >= 1024 || !geteuid())
61 return old_bind(fd,addr,addrlen);
63 if (getenv(AUTHBIND_NESTED)) {
64 STDERRSTR_CONST("libauthbind: possible installation problem - "
65 "nested invocation, perhaps helper is not setuid\n");
66 return old_bind(fd,addr,addrlen);
69 sprintf(addrarg,"%08lx",
70 ((unsigned long)(((struct sockaddr_in*)addr)->sin_addr.s_addr))&0x0ffffffffUL);
71 sprintf(portarg,"%04x",
72 ((unsigned int)(((struct sockaddr_in*)addr)->sin_port))&0x0ffff);
74 child= fork(); if (child==-1) return -1;
77 if (dup2(fd,0)) exiterrno(errno);
78 if (setenv(AUTHBIND_NESTED,"1",1)) exiterrno(errno);
79 execl(HELPER,HELPER,addrarg,portarg,(char*)0);
81 STDERRSTR_CONST("libauthbind: possible installation problem - "
82 "could not invoke " HELPER "\n");
86 rchild= waitpid(child,&status,0);
87 if (rchild==-1) return -1;
88 if (rchild!=child) { errno= ECHILD; return -1; }
90 if (WIFEXITED(status)) {
91 if (WEXITSTATUS(status)) { errno= WEXITSTATUS(status); return -1; }