/*
+ * libauthbind.c - bind(2)-redirector library for authbind
+ *
+ * authbind is Copyright (C) 1998 Ian Jackson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
*/
#include <dlfcn.h>
#include <sys/wait.h>
#include <netinet/in.h>
-#define AUTHBIND_NESTED "AUTHBIND_NESTED"
-#define HELPER "/usr/lib/authbind/helper"
+static const char *rcsid="$Id$";
+
+#include "authbind.h"
typedef void anyfn_type(void);
typedef int bindfn_type(int fd, const struct sockaddr *addr, socklen_t addrlen);
_exit(e>0 && e<128 ? e : -1);
}
+static void removepreload(void) {
+ const char *myself, *found;
+ char *newval, *preload;
+ int lpreload, lmyself, before, after;
+
+ preload= getenv(PRELOAD_VAR);
+ myself= getenv(AUTHBINDLIB_VAR);
+ if (!myself || !preload) return;
+
+ lpreload= strlen(preload);
+ lmyself= strlen(myself);
+
+ if (lmyself < 1 || lpreload<lmyself) return;
+ if (lpreload==lmyself) {
+ if (!strcmp(preload,myself)) unsetenv(PRELOAD_VAR);
+ return;
+ }
+ if (!memcmp(preload,myself,lmyself) && preload[lmyself]==':') {
+ before= 0; after= lpreload-(lmyself+1);
+ } else if (!memcmp(preload+lpreload-lmyself,myself,lmyself) &&
+ preload[lpreload-(lmyself+1)]==':') {
+ before= lpreload-(lmyself+1); after= 0;
+ } else {
+ if (lpreload<lmyself+2) return;
+ found= preload+1;
+ for (;;) {
+ found= strstr(found,myself); if (!found) return;
+ if (found > preload+lpreload-(lmyself+1)) return;
+ if (found[-1]==':' && found[lmyself]==':') break;
+ found++;
+ }
+ before= found-preload;
+ after= lpreload-(before+lmyself+1);
+ }
+ newval= malloc(before+after+1);
+ if (newval) {
+ memcpy(newval,preload,before);
+ strcpy(newval+before,preload+lpreload-after);
+ if (setenv(PRELOAD_VAR,newval,1)) return;
+ free(newval);
+ }
+ strcpy(preload+before,preload+lpreload-after);
+ return;
+}
+
+int _init(void);
+int _init(void) {
+ char *levels;
+ int levelno;
+
+ /* If AUTHBIND_LEVELS is
+ * unset => always strip from preload
+ * set and starts with `y' => never strip from preload, keep AUTHBIND_LEVELS
+ * set to integer > 1 => do not strip now, subtract one from AUTHBIND_LEVELS
+ * set to integer 1 => do not strip now, unset AUTHBIND_LEVELS
+ * set to empty string or 0 => strip now, unset AUTHBIND_LEVELS
+ */
+ levels= getenv(AUTHBIND_LEVELS_VAR);
+ if (levels) {
+ if (levels[0]=='y') return 0;
+ levelno= atoi(levels);
+ if (levelno > 0) {
+ levelno--;
+ if (levelno > 0) sprintf(levels,"%d",levelno);
+ else unsetenv(AUTHBIND_LEVELS_VAR);
+ return 0;
+ }
+ unsetenv(AUTHBIND_LEVELS_VAR);
+ }
+ removepreload();
+ return 0;
+}
+
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");
+ 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)
return old_bind(fd,addr,addrlen);
- }
sprintf(addrarg,"%08lx",
((unsigned long)(((struct sockaddr_in*)addr)->sin_addr.s_addr))&0x0ffffffffUL);
if (!child) {
if (dup2(fd,0)) exiterrno(errno);
- if (setenv(AUTHBIND_NESTED,"1",1)) exiterrno(errno);
+ removepreload();
execl(HELPER,HELPER,addrarg,portarg,(char*)0);
status= errno;
STDERRSTR_CONST("libauthbind: possible installation problem - "
- "could not invoke " HELPER "\n");
+ "could not invoke " HELPER " (");
+ STDERRSTR_STRING(rcsid);
+ STDERRSTR_CONST(")\n");
exiterrno(status);
}