chiark / gitweb /
authbind (2.1.1+nmu1) unstable; urgency=medium
authorJohannes Schauer <josch@debian.org>
Sun, 26 Jul 2015 09:23:35 +0000 (10:23 +0100)
committerJohannes Schauer <josch@debian.org>
Sun, 26 Jul 2015 09:23:35 +0000 (10:23 +0100)
  * Non-maintainer upload.
  * Fix mtimes before building binary packages to produce reproducible output
    Based on patch by akira (Closes: #792945)

[dgit import package authbind 2.1.1+nmu1]

14 files changed:
Makefile [new file with mode: 0644]
authbind-helper.8 [new file with mode: 0644]
authbind.1 [new file with mode: 0644]
authbind.c [new file with mode: 0644]
authbind.h [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/postinst [new file with mode: 0644]
debian/postrm [new file with mode: 0755]
debian/prerm [new file with mode: 0644]
debian/rules [new file with mode: 0755]
helper.c [new file with mode: 0644]
libauthbind.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c1eed73
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,89 @@
+# Makefile 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. 
+
+prefix=/usr/local
+
+bin_dir=$(prefix)/bin
+lib_dir=$(prefix)/lib/authbind
+libexec_dir=$(lib_dir)
+
+share_dir=$(prefix)/share
+man_dir=$(share_dir)/man
+man1_dir=$(man_dir)/man1
+man8_dir=$(man_dir)/man8
+
+etc_dir=/etc/authbind
+
+INSTALL_FILE   ?= install -o root -g root -m 644 
+INSTALL_PROGRAM ?= install -o root -g root -m 755 -s
+INSTALL_DIR    ?= install -o root -g root -m 755 -d
+STRIP          ?= strip
+
+OPTIMISE=      -O2
+LDFLAGS=       -g
+LIBS=          -ldl -lc
+CFLAGS=                -g $(OPTIMISE) \
+               -Wall -Wwrite-strings -Wpointer-arith -Wimplicit \
+               -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes
+CPPFLAGS=      -DMAJOR_VER='"$(MAJOR)"' -DMINOR_VER='"$(MINOR)"' \
+               -DLIBAUTHBIND='"$(lib_dir)/$(LIBCANON)"' \
+               -DHELPER='"$(libexec_dir)/$(HELPER)"' -DCONFIGDIR='"$(etc_dir)"' \
+               -D_GNU_SOURCE
+
+MAJOR=1
+MINOR=0
+LIBCANON=      libauthbind.so.$(MAJOR)
+LIBTARGET=     $(LIBCANON).$(MINOR)
+BINTARGETS=    authbind
+HELPER=                helper
+
+TARGETS=               $(BINTARGETS) $(HELPER) $(LIBTARGET)
+MANPAGES_1=            authbind.1
+MANPAGES_8=            authbind-helper.8
+
+all:                   $(TARGETS)
+
+install:               $(TARGETS)
+               $(INSTALL_DIR) $(lib_dir) $(man1_dir) $(man8_dir)
+               $(INSTALL_PROGRAM) $(BINTARGETS) $(bin_dir)/.
+               $(INSTALL_FILE) $(LIBTARGET) $(lib_dir)/.
+               $(STRIP) --strip-unneeded $(lib_dir)/$(LIBTARGET)
+               ln -sf $(LIBTARGET) $(lib_dir)/$(LIBCANON)
+               $(INSTALL_PROGRAM) $(HELPER) $(libexec_dir)/.
+               chmod u+s $(libexec_dir)/$(HELPER)
+               $(INSTALL_DIR) $(etc_dir) \
+                       $(etc_dir)/byport $(etc_dir)/byaddr $(etc_dir)/byuid
+
+install_man:           $(MANPAGES_1) $(MANPAGES_8)
+               $(INSTALL_FILE) $(MANPAGES_1) $(man1_dir)/.
+               $(INSTALL_FILE) $(MANPAGES_8) $(man8_dir)/.
+
+libauthbind.o:         libauthbind.c authbind.h
+               $(CC) -D_REENTRANT $(CFLAGS) $(CPPFLAGS) -c -o $@ -fPIC $<
+
+authbind:              authbind.o
+helper:                        helper.o
+
+helper.o authbind.o:   authbind.h
+
+$(LIBTARGET):          libauthbind.o
+               ld -shared -soname $(LIBCANON) -o $@ $< $(LIBS)
+
+clean distclean:
+               rm -f $(TARGETS) *.o *~ ./#*# *.bak *.new core
+               rm -f libauthbind.so* *.core
diff --git a/authbind-helper.8 b/authbind-helper.8
new file mode 100644 (file)
index 0000000..b9c25e8
--- /dev/null
@@ -0,0 +1,94 @@
+.\" Hey, Emacs!  This is an -*- nroff -*- source file.
+.\" Authors: Ian Jackson
+.\" 
+.\" 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. 
+.\"
+.TH AUTHBIND\-HELPER 8 "30th August 1998" "Debian Project" "Debian Linux manual"
+.br
+.SH NAME 
+authbind\-helper \- helper program to bind sockets to privileged ports without root
+.SH SYNOPSIS
+.BI /usr/lib/authbind/helper " addr4\-hex port\-hex " < socket
+.br
+.BI /usr/lib/authbind/helper " addr6\-hex port\-hex 6 " < socket
+.SH DESCRIPTION
+.B helper
+is the program used by
+.BR libauthbind ,
+which is in turn used by
+.B authbind
+to allow programs which do not or should not run as root to bind to
+low-numbered ports in a controlled way.  See
+.BR authbind (1).
+.PP
+It may also be used standalone, i.e. without assistance from
+.BR authbind .
+Its standard input should be a TCP/IP socket, and it should be passed
+two or three arguments.
+.PP
+The arguments are the address and port number, respectively, to which
+the caller desires that the socket be bound, and the address family
+(ommitted for IPv4; the fixed string
+.B 6
+for IPv6).
+.I addr4-hex
+and
+.I port-hex
+should be hex strings,
+.I without
+leading
+.BR 0x ,
+of exactly the right length (8 and 4 digits, respectively), being
+a pair of hex digits for each byte in the address or port number when
+expressed in host byte order.  For example, the port argument is the
+result of something like
+.B sprintf(arg,
+.B """%04X"",
+.BR sin.sin_port) .
+.I addr6-hex
+should be a string of 32 hex digits, being a pair for each byte in
+the address, in network byte order.
+.SH EXIT STATUS
+.B helper
+will exit with code 0 on success.
+.PP
+If possible,
+.B helper
+will return an appropriate
+.B errno
+value as its exit status.  If this is not possible it may exit with
+status 255 or with an exit status corresponding to
+.B ENOSYS
+.RI ( "Function not implemented" ).
+.SH ACCESS CONTROL
+See
+.BR authbind (1)
+for details of the access control regime implemented by
+.BR helper .
+.SH SEE ALSO
+.BR authbind (1),
+.BR bind (2)
+.SH AUTHOR
+.B authbind
+and this manpage were written by Ian Jackson.  They are
+Copyright (C)1998,2012
+by him and released under the GNU General Public Licence; there is NO
+WARRANTY.  See
+.B /usr/doc/authbind/copyright
+and
+.B /usr/doc/copyright/GPL
+for details.
diff --git a/authbind.1 b/authbind.1
new file mode 100644 (file)
index 0000000..d73e998
--- /dev/null
@@ -0,0 +1,359 @@
+.\" Hey, Emacs!  This is an -*- nroff -*- source file.
+.\" Authors: Ian Jackson
+.\" 
+.\" 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. 
+.\"
+.TH AUTHBIND 1 "30th August 1998" "Debian Project" "Debian Linux manual"
+.SH NAME 
+authbind \- bind sockets to privileged ports without root
+.SH SYNOPSIS
+.BR authbind
+.RI [ options "] " program " [" argument " ...]"
+.SH DESCRIPTION
+.B authbind
+allows a program which does not or should not run as root to bind to
+low-numbered ports in a controlled way.
+.PP
+You must invoke the program using
+.BR authbind ".  " authbind
+will set up some environment variables, including an
+.BR LD_PRELOAD ,
+which will allow the program (including any subprocesses it may run)
+to bind to low-numbered (<512) ports if the system is configured to
+allow this.
+.SH OPTIONS
+.TP
+.B --deep
+Normally,
+.B authbind
+arranges for only the program which it directly invokes to be affected
+by its special version of
+.BR bind (2).
+If you specify
+.B --deep
+then all programs which that program invokes directly or indirectly
+will be affected, so long as they do not unset the environment
+variables set up by
+.BR authbind .
+.TP
+.BI --depth " levels"
+Causes
+.B authbind
+to affect programs which are
+.I levels
+deep in the calling graph.  The default is
+.BR "--depth 1" .
+.SH ACCESS CONTROL
+Access to low numbered ports is controlled by permissions and contents
+of files in a configuration area,
+.BR /etc/authbind .
+.PP
+Firstly,
+.BI /etc/authbind/byport/ port
+is tested.  If this file is accessible for execution to the calling
+user, according to
+.BR access (2),
+then binding to the port is authorised.  If the file can be seen not
+to exist (the existence check returns
+.BR ENOENT )
+then further tests will be used to find authorisation; otherwise,
+binding is not authorised, and the
+.B bind
+call will return with the
+.B errno
+value from the
+.BR access (2)
+call, usually
+.B EACCES
+.RI ( "Permission denied" ).
+.PP
+Secondly, if that test fails to resolve the matter,
+.BI /etc/authbind/byaddr/ addr , port
+(any protocol) or failing that
+.BI /etc/authbind/byaddr/ addr : port
+(IPv4 only)
+is tested, in the same manner as above.  Here
+.I addr
+is as from
+.BR inet_ntop ,
+and
+.I port
+is the (local) TCP or UDP port number, expressed as an unsigned
+integer in the minimal non-zero number of digits.
+.PP
+Thirdly, for IPv6 only: since the textual representation from
+.B inet_ntop
+is complicated to predict, a variant of
+.I addr
+is also tested which does not use the double colon abbreviation:
+each 16-byte chunk expressed in the minimal nonzero number
+of hex digits (i.e. with leading zeroes removed), the chunks
+being separated by colons as is conventional.
+.PP
+Fourthly, if the question is still unresolved, the file
+.BI /etc/authbind/byuid/ uid
+will be opened and read.  If the file does not exist then the binding
+is not authorised and
+.B bind
+will return
+.B EPERM
+.RI ( "Operation not permitted" ", or " "Not owner" ).
+If the file does exist it will be searched for a line of the form
+.nf
+.IR            addrmin [\fB\-\fR addrmax ]\fB,\fR portmin [\fB\-\fR portmax ]
+.IR            addr [\fB/\fR length ]\fB,\fR portmin [\fB\-\fR portmax ]
+.IB            addr4 / length : portmin , portmax
+.fi
+matching the request.
+The first form requires that the address lies in the
+relevant range (inclusive at both ends).
+The second and third forms require that the initial
+.I length
+bits of
+.I addr
+match those in the proposed
+.B bind
+call.  The third form is only available for IPv4 since IPv6 addresses
+contain colons.
+Addresses in the byuid file can
+be in any form acceptable to inet_pton.  In all cases
+the proposed port number must lie is in the inclusive range
+specified.  If such a line is found then the binding is authorised.
+Otherwise it is not, and
+.B bind
+will fail with
+.B ENOENT
+.RI ( "No such file or directory" ).
+.PP
+If a read error occurs, or the directory
+.B /etc/authbind
+cannot be accessed, then not only will
+.B bind
+fail, but an error message will be printed to stderr.  Unrecognised
+lines in
+.BI /etc/authbind/byuid/ uid
+files are silently ignored, as are lines whose
+.I addr
+has non-zero bits more than
+.I length
+from the top or where some
+.I min
+is larger than
+.IR max .
+.SH EXAMPLE
+So for example an attempt by uid 432
+to bind to port 80 of address [2620:106:e002:f00f::21]
+would result in authbind calling
+.I access(2)
+on, in order,
+.RS
+.B /etc/authbind/byport/80
+.br
+.B /etc/authbind/byaddr/2620:106:e002:f00f::21,80
+.br
+.B /etc/authbind/byaddr/2620:106:e002:f00f:0:0:0:21,80
+.RE
+If none of these files exist, authbind will read
+.RS
+.B /etc/authbind/byuid/432
+.RE
+and search for a line to permit
+the relevant access; examples of lines which would do so are:
+.RS
+.B 2620:106:e002:f00f::21,80
+.br
+.B ::/0,80
+.RE
+.SH PORTS 512-1023
+Authorising binding to ports from 512 to 1023 inclusive is
+not recommended.  Some protocols (including some versions of NFS)
+authorise clients by seeing that they are using a port number in this
+range.  So by authorising a program to be a server for such a port,
+you are also authorising it to impersonate the whole host for those
+protocols.
+
+To make sure that this isn't done by accident,
+if the port number requested is in the range 512-1023, authbind
+will expect the permission files to have an additional
+.B !
+at the start of their leafname.
+.SH MECHANISM
+The shared library loaded using
+.B LD_PRELOAD
+overrides the
+.BR bind (2)
+system call.  When a program invoked via
+.B authbind
+calls
+.B bind
+to bind a socket to a low-numbered TCP/IP port, and if the program
+doesn't already have an effective uid of 0, the version of
+.B bind
+supposed by
+.B authbind
+forks and executes a setuid-root helper program.  For non-TCP/IP
+sockets, high-numbered ports, or programs which are already root,
+.B authbind
+passes the call to the original
+.BR bind (2)
+system call, which is found using
+.BR dlsym (3)
+with the handle
+.BR RTLD_NEXT .
+.PP
+.SH ERROR HANDLING
+Usually the normal C error handling mechanisms apply.  If
+.B authbind
+cannot find the program it has been asked to execute it will print a
+message to stderr and exit with code 255.
+.PP
+The helper program usually reports back to the shared library with an
+exit status containing an
+.B errno
+value which encodes whether the
+.B bind
+was permitted and successful.  This will be returned to the calling
+program in the usual way.
+.PP
+In the case of apparent configuration or other serious errors the
+library and/or the helper program may cause messages to be printed to
+the program's stderr, was well as returning -1 from
+.BR bind .
+.SH BUGS
+.B authbind
+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
+The use of
+.B LD_PRELOAD
+makes an
+.B authbind
+installation specific to a particular C library.  This version is for
+GNU/Linux libc6 (glibc2).
+.PP
+.B authbind
+may not operate correctly with multithreaded programs.  It is
+inherently very difficult (if not impossible) to perform the kind of
+trickery that authbind does while preventing all undesirable
+interactions between authbind's activities and those of (say) a
+threading runtime system.
+.PP
+It is quite possible that
+.B authbind
+and other programs and facilities which use
+.B LD_PRELOAD
+may interfere with each other, causing unpredictable behaviour or even
+core dumps.
+.B authbind
+is known sometimes not to work correctly with
+.BR fakeroot ,
+for example (even supposing it could be determined what `correctly'
+means in this context).
+.PP
+.B authbind
+is ineffective with setuid programs, because they do not honour
+.B LD_PRELOAD
+references outside the system directories, for security reasons.  (In
+fact, setuid programs should not honour
+.B LD_PRELOAD
+at all.)
+Of course a setuid-root program does not need
+.BR authbind ,
+but it might be useful to apply it to program which are setuid to
+another user or setgid.  If the author or builder of such a programs
+wishes it to use authbind they could have it load the
+.B libauthbind
+library explicitly rather than via
+.BR LD_PRELOAD .
+.PP
+Some programs may have trouble because
+.B authbind
+spawns a child process `under their feet', causing (for example) a
+.BR fork (2)
+to happen and
+.B SIGCHLD
+signal to be delivered.  Unfortunately the Unix API does not make
+it possible to deal with this problem in a sane way.
+.PP
+The access control configuration scheme is somewhat strange.
+.SH FILES AND ENVIRONMENT VARIABLES
+.TP
+.I /usr/lib/authbind/libauthbind.so.1.0
+The shared library which
+.B authbind
+causes to be loaded using
+.BR LD_PRELOAD ,
+and which actually implements the diversion of
+.BR bind (2)
+to an external program.
+.TP
+.I LD_PRELOAD
+The variable used by the dynamic linker when starting dynamically
+linked programs and deciding which shared libraries to load and
+modifed by the
+.B authbind
+program to allow it to override the usual meaning of
+.BR bind (2) .
+.TP
+.I AUTHBIND_LIB
+If set, forces
+.B authbind
+to use its value as the path to the shared library to put in
+.BR LD_PRELOAD ,
+instead of the compiled-in value.  In any case, unless
+.B --deep
+was specified,
+.B authbind
+will set this variable to the name of the library actually added to
+.BR LD_PRELOAD ,
+so that the library can find and remove the right entry.
+.TP
+.I AUTHBIND_LEVELS
+This variable is set by
+.B authbind
+to the number of levels left from the
+.B --depth
+or
+.B --deep
+option, minus one.  It is decremented during
+.B _init
+by the library on each program call, and the library will remove
+itself from the
+.B LD_PRELOAD
+when it reaches zero.  The special value
+.B y
+means
+.B --deep
+was specified.
+.SH SEE ALSO
+.BR bind (2),
+.BR authbind\-helper (8),
+.BR dlsym (3),
+.BR ld.so (8)
+.SH AUTHOR
+.B authbind
+and this manpage were written by Ian Jackson.  They are
+Copyright (C)1998,2012
+by him and released under the GNU General Public Licence; there is NO
+WARRANTY.  See
+.B /usr/doc/authbind/copyright
+and
+.B /usr/doc/copyright/GPL
+for details.
diff --git a/authbind.c b/authbind.c
new file mode 100644 (file)
index 0000000..8dd8f0c
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  authbind.c - main invoker program
+ *
+ *  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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "authbind.h"
+
+static void printusage(FILE *f) {
+  if (fprintf(f,
+             "usage:       authbind [<options>] <program> <arg> <arg> ...\n"
+             "options:     --deep    --depth <levels>\n")
+      == EOF) { perror("printf usage"); exit(-1); }
+}
+
+static void usageerror(const char *msg) {
+  fprintf(stderr,"usage error: %s\n",msg);
+  printusage(stderr);
+  exit(-1);
+}
+
+static void mustsetenv(const char *var, const char *val) {
+  if (setenv(var,val,1)) { perror("authbind: setenv"); exit(-1); }
+}
+
+int main(int argc, char *const *argv) {
+  const char *expreload, *authbindlib, *preload;
+  char *newpreload, *ep;
+  char buf[50];
+  unsigned long depth;
+
+  depth= 1;
+  while (argc>1 && argv[1][0]=='-') {
+    argc--; argv++;
+    if (!argv[0][1]) break;
+    if (!strcmp("--deep",argv[0])) { depth= 0; }
+    else if (!strcmp("--depth",argv[0])) {
+      if (argc<=1) usageerror("--depth requires a value");
+      argc--; argv++;
+      depth= strtoul(argv[0],&ep,10);
+      if (*ep || depth<=0 || depth>100) usageerror("--depth value is not valid");
+    } else if (!strcmp("--help",argv[0]) || !strcmp("--help",argv[0])) {
+      printusage(stdout);
+      exit(0);
+    }
+  }
+  if (argc<2) usageerror("need program name");
+
+  authbindlib= getenv(AUTHBINDLIB_VAR);
+  if (!authbindlib) {
+    authbindlib= LIBAUTHBIND;
+    mustsetenv(AUTHBINDLIB_VAR,authbindlib);
+  }
+    
+  if ((expreload= getenv(PRELOAD_VAR))) {
+    newpreload= malloc(strlen(expreload)+strlen(authbindlib)+2);
+    strcpy(newpreload,expreload);
+    strcat(newpreload,":");
+    strcat(newpreload,authbindlib);
+    preload= newpreload;
+  } else {
+    preload= authbindlib;
+  }
+  mustsetenv(PRELOAD_VAR,preload);
+
+  if (depth > 1) {
+    sprintf(buf,"%ld",depth-1);
+    mustsetenv(AUTHBIND_LEVELS_VAR,buf);
+  } else if (depth == 0) {
+    mustsetenv(AUTHBIND_LEVELS_VAR,"y");
+  } else {
+    assert(depth==1);
+  }
+
+  execvp(argv[1],argv+1);
+  perror(argv[1]); exit(-1);
+}
diff --git a/authbind.h b/authbind.h
new file mode 100644 (file)
index 0000000..3911c08
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  authbind.h - various definitions
+ *
+ *  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. 
+ * 
+ */
+
+#ifndef AUTHBIND_H
+#define AUTHBIND_H
+
+#ifndef LIBAUTHBIND
+# define LIBAUTHBIND "/usr/local/lib/authbind/libauthbind.so." MAJOR_VER
+#endif
+
+#ifndef HELPER
+# define HELPER "/usr/local/lib/authbind/helper"
+#endif
+
+#define PRELOAD_VAR "LD_PRELOAD"
+#define AUTHBINDLIB_VAR "AUTHBIND_LIB"
+#define AUTHBIND_LEVELS_VAR "AUTHBIND_LEVELS"
+
+#endif
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..531fbbd
--- /dev/null
@@ -0,0 +1,171 @@
+authbind (2.1.1+nmu1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix mtimes before building binary packages to produce reproducible output
+    Based on patch by akira (Closes: #792945)
+
+ -- Johannes Schauer <josch@debian.org>  Sun, 26 Jul 2015 11:23:35 +0200
+
+authbind (2.1.1) unstable; urgency=low
+
+  * Manpage has an example of which files will be checked and read
+    Closes: #676540.
+  * Do not include library version number in usage output from helper; the
+    library and package version numbers are not the same, so this is
+    misleading, and we do not want to introduce new machinery just to
+    plumb the package version number through.  Closes: #676440.
+  * Another minor wording fix in the manpage.x
+
+ -- Ian Jackson <ijackson@chiark.greenend.org.uk>  Sun, 10 Jun 2012 23:17:14 +0100
+
+authbind (2.1.0) unstable; urgency=low
+
+  * Permissions file lines can contain IPv6 mask/length.
+  * Permissions file lines need only contain one port number.
+  * Manpage improvements.
+
+ -- Ian Jackson <ijackson@chiark.greenend.org.uk>  Sun, 03 Jun 2012 12:33:53 +0100
+
+authbind (2.0.1) unstable; urgency=low
+
+  Bugfix:
+  * 0-length ipv4 address masks (ie, 0.0.0.0/0) in byuid files wouldn't
+    work because they would attempt a 32-bit shift.  This was reported
+    against Ubuntu in Launchpad but the but is here too.  LP: #514278.
+
+ -- Ian Jackson <ijackson@chiark.greenend.org.uk>  Sun, 03 Jun 2012 01:50:13 +0100
+
+authbind (2.0.0) unstable; urgency=medium
+
+  Important new functionality:
+  * Support IPv6.  (Closes: #596921.)
+  * Support ports 512-1023 if the user really wants.
+    Explain the problem more clearly in the manpage.  (Closes: 654706.)
+
+  Bugfixes:
+  * Correct manpage description of helper protocol to have
+    actually-implemented byte order convention.  (Closes: #651694.)
+  * Improve wording in BUGS section of manpage about forking.
+
+  Packaging fixes:
+  * Remove shlibs files.  These are not needed because nothing should
+    actually link to libauthbind.
+  * Update Standards-Version.
+  * Upstream repo is now in git.
+  * Change my email address.
+  * Set Priority to optional as in ftpmaster override file.
+
+ -- Ian Jackson <ijackson@chiark.greenend.org.uk>  Sat, 02 Jun 2012 01:56:37 +0100
+
+authbind (1.2.0) unstable; urgency=low
+
+  * Block signals during our child's execution.  Closes: #186439.
+  * manpage: fix subtle error in description of interaction between
+    set-id and LD_PRELOAD.  Closes: #36890.
+  * Say in manpage that we may not work properly with multithreaded
+    programs.  See also Bug#186439.
+  * Make sure we don't try to encode errno's >127 in a status code.
+  * New make variables for improved portability and customisation of
+    locations: LIBS, libexec_dir, HELPER, BINTARGETS.
+  * make clean removes *.core too.
+  * #include <signal.h> in libauthbind.c.
+  * Set SHELL=/bin/bash in debian/rules.  Closes: #374586.
+  * Revert Amaya's accidental change to CC= line in debian/rules.
+  * Debian-native again.  Closes: #393556.
+  * Do not strip if DEB_BUILD_OPTIONS=nostrip (Closes: #436489):
+    - in Makefile, do not set INSTALL_* or STRIP if already set
+    - in rules, export STRIP=: if nostrip
+  * Change my email address in Maintainer: to davenant.
+    
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 23 Sep 2007 20:23:50 +0100
+
+authbind (1.1.5.2-0.2) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Get rid of the /usr/doc link (Closes: #359363).
+  * Revamped packaging a bit:
+    - Get rid of Build-Depends on libc6-dev (build-essential)
+    - spelling-error-in-copyright Debian/GNU Linux Debian GNU/Linux
+    - Not debian-native anymore
+    - Updated ancient-standards-version to 3.7.2, no changes needed.
+
+ -- Amaya Rodrigo Sastre <amaya@debian.org>  Wed, 12 Jul 2006 12:28:12 +0200
+
+authbind (1.1.5.2-0.1) unstable; urgency=low
+
+  * Non-maintainer Upload
+  * Moved man pages to /usr/share/man and docs to
+    /usr/share/doc/authbind. Added a prerm and a postinst script to set
+    the /usr/doc/authbind link. (closes: #91112, #91376, #91387)
+  * Fixed the path to the common licenses in debian/copyright
+  * Added a section and priority field to the changelog
+  * Added support for the `nostrip' and `debug' options in
+    DEB_BUILD_OPTIONS.
+  * Boosted Standards-Version to 3.5.2
+
+ -- Bas Zoetekouw <bas@debian.org>  Sun, 13 May 2001 18:00:52 +0200
+
+authbind (1.1.5.2) frozen unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Makefile: Add -D_GNU_SOURCE, closes: 89944
+
+ -- Stephen Frost <sfrost@debian.org>  Fri, 16 Mar 2001 19:42:05 -0500
+
+authbind (1.1.5.1) frozen unstable; urgency=low
+
+  * Non-maintainer upload.
+  * debian/rules (clean): use tab not spaces, so `debian/rules clean'
+    actually works. [#27360]
+  * debian/rules (binary-arch): don't compress the copyright file.
+  * Makefile: install the shared library non-executable.
+ -- James Troup <james@nocrew.org>  Sun,  3 Jan 1999 21:23:50 +0000
+
+authbind (1.1.5) unstable; urgency=low
+
+  * Fix coredump bug !
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Mon, 31 Aug 1998 15:32:44 +0100
+
+authbind (1.1.4) unstable; urgency=low
+
+  * Allow bind() to port 0 !
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Mon, 31 Aug 1998 15:23:30 +0100
+
+authbind (1.1.3) unstable; urgency=low
+
+  * Make IPPORT_RESERVED check work (oops!).
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 30 Aug 1998 20:52:10 +0100
+
+authbind (1.1.2) unstable; urgency=low
+
+  * Make --deep option actually work (oops).
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 30 Aug 1998 20:09:39 +0100
+
+authbind (1.1.1) unstable; urgency=low
+
+  * Fix Description.
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 30 Aug 1998 16:34:28 +0100
+
+authbind (1.1) experimental; urgency=low
+
+  * Allow control of when the LD_PRELOAD is passed on.
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 30 Aug 1998 16:18:24 +0100
+
+authbind (1.0) experimental; urgency=low
+
+  * Following testing, we can call this 1.0.
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sun, 30 Aug 1998 03:15:21 +0100
+
+authbind (0.1-1) experimental; urgency=low
+
+  * Initial release.
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk>  Sat, 29 Aug 1998 20:10:37 +0100
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..d36c6e3
--- /dev/null
@@ -0,0 +1,12 @@
+Source: authbind
+Section: utils
+Priority: optional
+Maintainer: Ian Jackson <ijackson@chiark.greenend.org.uk>
+Standards-Version: 3.9.1
+
+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, without any changes to the application.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..4d351a2
--- /dev/null
@@ -0,0 +1,26 @@
+This is the Debian GNU/Linux prepackaged version of my `authbind'
+utility for allowing non-root programs to bind to privileged ports,
+subject to configuration by the sysadmin.
+
+This package was put together by me, Ian Jackson
+<ijackson@chiark.greenend.org.uk>, from my git repository.
+
+
+authbind is Copyright (C)1998,2012 Ian Jackson <ian@chiark.greenend.org.uk>.
+
+authbind 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 of the License, 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 with
+your Debian GNU/Linux system, in /usr/share/common-licenses, or with the
+Debian GNU/Linux authbind source package as the file COPYING; if not,
+email me at one of the addresses above.
+
+$Id$
diff --git a/debian/postinst b/debian/postinst
new file mode 100644 (file)
index 0000000..cb07120
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if [ "$1" = "configure" ]; then
+        if [ -d /usr/doc -a -h /usr/doc/authbind -a -d /usr/share/doc/authbind ]; then
+                rm -f /usr/doc/authbind
+        fi
+fi
+
+
diff --git a/debian/postrm b/debian/postrm
new file mode 100755 (executable)
index 0000000..54aa82d
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+if test "$1" = purge
+then
+       rm -rf /etc/authbind
+fi
diff --git a/debian/prerm b/debian/prerm
new file mode 100644 (file)
index 0000000..31beffd
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/authbind ];
+then
+  rm -f /usr/doc/authbind
+fi
+
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..c9091ed
--- /dev/null
@@ -0,0 +1,103 @@
+#! /usr/bin/make -f
+#
+# debian/rules 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. 
+#
+# $Id$
+
+CC= gcc
+SHELL=/bin/bash
+
+package=authbind
+major=1
+minor=0
+
+arch = $(shell dpkg --print-architecture)
+
+export SOURCE_DATE_EPOCH = $(shell date -d "$$(dpkg-parsechangelog --count 1 -SDate)" +%s)
+
+INSTALL = install
+INSTALL_FILE    = $(INSTALL) -p    -o root -g root  -m  644
+INSTALL_PROGRAM = $(INSTALL) -p    -o root -g root  -m  755
+INSTALL_SCRIPT  = $(INSTALL) -p    -o root -g root  -m  755
+INSTALL_DIR     = $(INSTALL) -p -d -o root -g root  -m  755
+
+CFLAGS = -O2 -Wall
+LDFLAGS = 
+
+
+CFLAGS += -g
+LDFLAGS += -g 
+
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+INSTALL_PROGRAM += -s
+STRIP=strip
+else
+STRIP=:
+endif
+
+export CFLAGS
+export LDFLAGS
+export INSTALL
+export INSTALL_FILE
+export INSTALL_PROGRAM
+export INSTALL_SCRIPT
+export INSTALL_DIR
+export STRIP
+
+
+build: 
+       $(MAKE) prefix=/usr
+
+clean: 
+       $(MAKE) distclean
+       rm -rf debian/{files,substvars,tmp} build
+       rm -f debian/*~ debian/#*# debian/core debian/*.bak
+
+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)
+udp=debian/tmp/usr/share/doc/$(package)
+
+binary-arch:   checkroot build
+       rm -rf debian/tmp
+       install -d -g root -m 755 -o root debian/tmp/DEBIAN $(udp) \
+               debian/tmp/usr/{bin,lib/$(package),share/man}
+       $(MAKE) prefix=debian/tmp/usr etc_dir=debian/tmp/etc/authbind \
+               man_dir=debian/tmp/usr/share/man  install install_man
+       $(INSTALL_FILE) debian/changelog $(udp)/changelog
+       gzip -9 debian/tmp/usr/share/man/man*/* $(udp)/*
+       $(INSTALL_FILE) debian/copyright $(udp)/.
+       $(INSTALL_SCRIPT) debian/{postrm,prerm,postinst} debian/tmp/DEBIAN
+       dpkg-shlibdeps ./authbind
+       dpkg-gencontrol -isp
+       chown -R root.root debian/tmp
+       chmod -R g-ws debian/tmp
+       find debian/tmp -newermt "@$$SOURCE_DATE_EPOCH" -print0 | \
+               xargs -0r touch --no-dereference --date="@$$SOURCE_DATE_EPOCH"
+       dpkg --build debian/tmp ..
+
+binary:         binary-indep binary-arch
+
+checkroot:
+       $(checkdir)
+       test root = "`whoami`"
diff --git a/helper.c b/helper.c
new file mode 100644 (file)
index 0000000..a58e7aa
--- /dev/null
+++ b/helper.c
@@ -0,0 +1,269 @@
+/*
+ *  helper.c - setuid helper program 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef CONFIGDIR
+# define CONFIGDIR "/etc/authbind"
+#endif
+
+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) {
+  fprintf(stderr,"libauthbind's helper: bad usage\n");
+  exit(ENOSYS);
+}
+
+static struct sockaddr_in saddr4;
+static struct sockaddr_in6 saddr6;
+
+static struct sockaddr *saddr_any;
+static const void *addr_any;
+static size_t saddrlen_any, addrlen_any;
+
+static void authorised(void) {
+  if (bind(0,saddr_any,saddrlen_any)) exiterrno(errno);
+  else _exit(0);
+}
+
+static void checkexecflagfile(const char *file) {
+  if (!access(file,X_OK)) authorised();
+  if (errno != ENOENT) exiterrno(errno);
+}
+
+static void hex2bytes(const char *string, unsigned char *out, int len) {
+  int i;
+  for (i=0; i<len; i++) {
+    char hex[3], *ep;
+    hex[0]= *string++;  if (!hex[0]) badusage();
+    hex[1]= *string++;  if (!hex[1]) badusage();
+    hex[2]= 0;
+    *out++ = strtoul(hex,&ep,16);
+    if (ep != &hex[2]) badusage();
+  }
+}
+
+int main(int argc, const char *const *argv) {
+  uid_t uid;
+  char fnbuf[300];
+  char *ep;
+  const char *np;
+  const char *tophalfchar="";
+  unsigned long port, addr4=0, haddr4=0;
+  unsigned int hport;
+  int af;
+  FILE *file;
+
+  if (argc == 3) {
+    af= AF_INET;
+    saddr_any= (void*)&saddr4;
+    saddrlen_any= sizeof(saddr4);
+    addr_any= &saddr4.sin_addr.s_addr;
+    addrlen_any= sizeof(saddr4.sin_addr.s_addr);
+    addr4= strtoul(argv[1],&ep,16);
+    if (*ep || addr4&~0x0ffffffffUL) badusage();
+    haddr4= ntohl(addr4);
+  } else if (argc == 4 && !strcmp(argv[3],"6")) {
+    af= AF_INET6;
+    saddr_any= (void*)&saddr6;
+    saddrlen_any= sizeof(saddr6);
+    addr_any= &saddr6.sin6_addr.s6_addr;
+    addrlen_any= sizeof(saddr6.sin6_addr.s6_addr);
+    hex2bytes(argv[1], saddr6.sin6_addr.s6_addr,
+             sizeof(saddr6.sin6_addr.s6_addr));
+  } else {
+    badusage();
+    abort();
+  }
+
+  port= strtoul(argv[2],&ep,16); if (*ep || port&~0x0ffffUL) badusage();
+  hport= htons(port);
+  if (hport >= IPPORT_RESERVED/2) tophalfchar= "!";
+
+  if (chdir(CONFIGDIR)) perrorfail("chdir " CONFIGDIR);
+
+  fnbuf[sizeof(fnbuf)-1]= 0;
+
+  switch (af) {
+  case AF_INET:
+    saddr4.sin_family= af;
+    saddr4.sin_port= port;
+    saddr4.sin_addr.s_addr= addr4;
+    break;
+  case AF_INET6:
+    saddr6.sin6_family= af;
+    saddr6.sin6_port= port;
+    break;
+  default:
+    abort();
+  }
+
+  snprintf(fnbuf,sizeof(fnbuf)-1,"byport/%s%u",tophalfchar,hport);
+  if (!access(fnbuf,X_OK)) authorised();
+  if (errno != ENOENT) exiterrno(errno);
+
+  char npbuf[INET_ADDRSTRLEN + INET6_ADDRSTRLEN];
+  np= inet_ntop(af,addr_any,npbuf,sizeof(npbuf));
+  assert(np);
+
+  if (af == AF_INET) {
+    snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s%s:%u",tophalfchar,np,hport);
+    checkexecflagfile(fnbuf);
+  }
+
+  snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s%s,%u",tophalfchar,np,hport);
+  checkexecflagfile(fnbuf);
+
+  if (af == AF_INET6) {
+    char sbuf[addrlen_any*3+1], *sp = sbuf;
+    const unsigned char *ip = addr_any;
+    int i;
+    for (i=0; i<8; i++) {
+      unsigned val = 0;
+      val |= *ip++;  val <<= 8;
+      val |= *ip++;
+      if (i) *sp++ = ':';
+      sp += sprintf(sp,"%x",val);
+    }
+    snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s%s,%u",tophalfchar,sbuf,hport);
+    checkexecflagfile(fnbuf);
+  }
+
+  uid= getuid(); if (uid==(uid_t)-1) perrorfail("getuid");
+  snprintf(fnbuf,sizeof(fnbuf)-1,"byuid/%s%lu",tophalfchar,(unsigned long)uid);
+
+  file= fopen(fnbuf,"r");
+  if (!file) exiterrno(errno==ENOENT ? EPERM : errno);
+
+  while (fgets(fnbuf,sizeof(fnbuf)-1,file)) {
+    unsigned int a1,a2,a3,a4, alen,pmin,pmax;
+    int nchar;
+
+    if (af == AF_INET &&
+       (nchar = -1,
+        sscanf(fnbuf," %u.%u.%u.%u/%u: %u,%u %n",
+               &a1,&a2,&a3,&a4,&alen,&pmin,&pmax,&nchar),
+        nchar == strlen(fnbuf))) {
+
+      if (alen>32 || pmin&~0x0ffff || pmax&~0x0ffff ||
+         a1&~0x0ff || a2&~0xff || a3&~0x0ff || a4&~0x0ff)
+       continue;
+
+      unsigned long thaddr, thmask;
+      thaddr= (a1<<24)|(a2<<16)|(a3<<8)|(a4);
+      thmask= alen ? 0x0ffffffffUL<<(32-alen) : 0;
+      if ((haddr4&thmask) != thaddr) continue;
+
+    } else {
+
+      char *comma = strchr(fnbuf,',');
+      if (!comma) continue;
+      *comma++ = '\0';
+
+      char *slash = strchr(fnbuf,'/');
+      char *hyphen = strchr(fnbuf,'-');
+
+      if (slash && hyphen)
+       continue;
+
+      if (slash) {
+       int alen;
+       *slash++ = '\0';
+       nchar = -1;
+       sscanf(slash," %u %n",&alen,&nchar);
+       if (nchar != strlen(slash))
+         continue;
+       unsigned char thaddr[addrlen_any];
+       if (inet_pton(af,fnbuf,thaddr) != 1)
+         continue;
+       int pfxlen_remain = alen;
+       int i;
+       for (i=0; i<addrlen_any; i++) {
+         int pfxlen_thisbyte = pfxlen_remain < 8 ? pfxlen_remain : 8;
+         pfxlen_remain -= pfxlen_thisbyte;
+         unsigned mask_thisbyte = 0xff ^ (0xff >> pfxlen_thisbyte);
+         unsigned thaddr_thisbyte = thaddr[i];
+         unsigned addr_thisbyte = ((unsigned char*)addr_any)[i];
+         if ((addr_thisbyte & mask_thisbyte) != thaddr_thisbyte)
+           goto badline;
+       }
+       if (pfxlen_remain) badline: continue;
+       /* hooray */
+      } else {
+       const char *min, *max;
+       if (hyphen) {
+         *hyphen++ = '\0';
+         min = fnbuf;
+         max = hyphen;
+       } else {
+         min = fnbuf;
+         max = fnbuf;
+       }
+       unsigned char minaddr[addrlen_any];
+       unsigned char maxaddr[addrlen_any];
+       if (inet_pton(af,min,minaddr) != 1 ||
+           inet_pton(af,max,maxaddr) != 1)
+         continue;
+       if (memcmp(addr_any,minaddr,addrlen_any) < 0 ||
+           memcmp(addr_any,maxaddr,addrlen_any) > 0)
+         continue;
+      }
+
+      if (nchar = -1,
+         sscanf(comma," %u-%u %n",
+                &pmin,&pmax,&nchar),
+         nchar == strlen(comma)) {
+       /* good */
+      } else if (nchar = -1,
+                sscanf(comma," %u %n",
+                       &pmin,&nchar),
+                nchar == strlen(comma)) {
+       pmax = pmin;
+      } else {
+       continue;
+      }
+
+    }
+    if (hport<pmin || hport>pmax) continue;
+
+    authorised();
+  }
+  if (ferror(file)) perrorfail("read per-uid file");
+  _exit(ENOENT);
+}
diff --git a/libauthbind.c b/libauthbind.c
new file mode 100644 (file)
index 0000000..a685ce3
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *  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 <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+
+#include "authbind.h"
+
+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 anyfn_type *find_any(const char *name) {
+  static const char *dlerr;
+  anyfn_type *kv;
+
+  kv= dlsym(RTLD_NEXT,name); if (kv) return kv;
+  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 0;
+}
+
+static bindfn_type find_bind, *old_bind= find_bind;
+
+int find_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
+  anyfn_type *anyfn;
+  anyfn= find_any("bind"); if (!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);
+}
+
+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;
+}
+
+static const int evilsignals[]= { SIGFPE, SIGILL, SIGSEGV, SIGBUS, 0 };
+
+int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
+  pid_t child, rchild;
+  char portarg[5], addrarg[33];
+  const char *afarg;
+  int i, r, status;
+  const int *evilsignal;
+  sigset_t block, saved;
+  unsigned int portval;
+
+  switch (addr->sa_family) {
+  case AF_INET:
+    portval = ((struct sockaddr_in*)addr)->sin_port;
+    if (addrlen != sizeof(struct sockaddr_in)) goto bail;
+    break;
+  case AF_INET6:
+    portval = ((struct sockaddr_in6*)addr)->sin6_port;
+    if (addrlen != sizeof(struct sockaddr_in6)) goto bail;
+    break;
+  default:
+    goto bail;
+  }
+
+  if (!geteuid() || portval == 0 || ntohs(portval) >= IPPORT_RESERVED) {
+  bail:
+    return old_bind(fd,addr,addrlen);
+  }
+
+  sigfillset(&block);
+  for (evilsignal=evilsignals;
+       *evilsignal;
+       evilsignal++)
+    sigdelset(&block,*evilsignal);
+  if (sigprocmask(SIG_BLOCK,&block,&saved)) return -1;
+
+  switch (addr->sa_family) {
+  case AF_INET:
+    afarg = 0;
+    sprintf(addrarg,"%08lx",
+           ((unsigned long)(((struct sockaddr_in*)addr)->sin_addr.s_addr))
+           &0x0ffffffffUL);
+    break;
+  case AF_INET6:
+    afarg = "6";
+    for (i=0; i<16; i++)
+      sprintf(addrarg+i*2,"%02x",
+             ((struct sockaddr_in6*)addr)->sin6_addr.s6_addr[i]);
+    break;
+  default:
+    abort();
+  }
+  sprintf(portarg,"%04x",
+         portval&0x0ffff);
+
+  child= fork(); if (child==-1) goto x_err;
+
+  if (!child) {
+    if (dup2(fd,0)) exiterrno(errno);
+    removepreload();
+    execl(HELPER,HELPER,addrarg,portarg,afarg,(char*)0);
+    status= errno > 0 && errno < 127 ? errno : 127;
+    STDERRSTR_CONST("libauthbind: possible installation problem - "
+                   "could not invoke " HELPER "\n");
+    exiterrno(status);
+  }
+
+  rchild= waitpid(child,&status,0);
+  if (rchild==-1) goto x_err;
+  if (rchild!=child) { errno= ECHILD; goto x_err; }
+
+  if (WIFEXITED(status)) {
+    if (WEXITSTATUS(status)) {
+      errno= WEXITSTATUS(status);
+      if (errno >= 127) errno= ENXIO;
+      goto x_err;
+    }
+    r= 0;
+    goto x;
+  } else {
+    errno= ENOSYS;
+    goto x_err;
+  }
+
+x_err:
+  r= -1;
+x:
+  if (sigprocmask(SIG_SETMASK,&saved,0)) abort();
+  return r;
+}