From bf7ee634e855d15e955d06e7b225d2045abd518a Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 16 Apr 1999 14:45:55 +0000 Subject: [PATCH 1/1] Added interface for tcpd wrapper for access control. --- CHANGELOG | 6 +++ Makefile.in | 8 ++-- client/Makefile.in | 6 +-- comstack/tcpip.c | 28 +++++--------- configure | 108 ++++++++++++++++++++++++++++++++++++++++++++-------- configure.in | 8 +++- include/statserv.h | 10 ++++- server/Makefile.in | 6 +-- server/statserv.c | 35 ++++++++--------- server/tcpdchk.c | 87 ++++++++++++++++++++++++++++++++++++++++++ ztest/Makefile.in | 4 +- 11 files changed, 237 insertions(+), 69 deletions(-) create mode 100644 server/tcpdchk.c diff --git a/CHANGELOG b/CHANGELOG index c929736..d47866e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ Possible compatibility problems with earlier versions marked with '*'. +Added access control facility by interfacing the TCP wrapper library. +YAZ automatically attempts to find the TCP wrapper Library (-lwrap) and +tcpd.h on Unix systems. For the server, option -d specifies the +name of the daemon and enables the access control as specified in +hosts.allow/hosts.deny. Refer to man pages tcpd(8) and hosts_access(5). + Fixed memory leak in ccl_find_str and ccl_qual_rm. Thanks to Hans van den Dool . diff --git a/Makefile.in b/Makefile.in index 70334f3..05a2bf5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Copyright (C) 1995-1998, Index Data +# Copyright (C) 1995-1999, Index Data # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile.in,v 1.5 1998-10-28 15:09:59 adam Exp $ +# $Id: Makefile.in,v 1.6 1999-04-16 14:45:55 adam Exp $ # Uncomment the lines below to enable mOSI communcation. #CDEFS=-DUSE_XTIMOSI @@ -60,7 +60,7 @@ oclean: for i in $(SUBDIR); do (cd $$i; rm -f *.o); done mv lib/libyaz.a .; rm -f lib/*.a; mv libyaz.a lib cd client; strip client - cd server; strip ztest + cd ztest; strip ztest cleanup: rm -f `find $(SUBDIR) -name "*.[oa]" -print` @@ -85,7 +85,7 @@ install.bin: @echo "Installing client -> $(BINDIR)"; \ cp client/client $(BINDIR)/client; chmod 755 $(BINDIR)/client @echo "Installing ztest -> $(BINDIR)"; \ - cp server/ztest $(BINDIR)/ztest; chmod 755 $(BINDIR)/ztest + cp ztest/ztest $(BINDIR)/ztest; chmod 755 $(BINDIR)/ztest install.lib: @if [ ! -d $(LIBDIR) ]; then \ diff --git a/client/Makefile.in b/client/Makefile.in index 9dc4fc9..d25248b 100644 --- a/client/Makefile.in +++ b/client/Makefile.in @@ -1,7 +1,7 @@ -# Copyright (C) 1995-1998, Index Data I/S +# Copyright (C) 1995-1999, Index Data # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile.in,v 1.5 1999-03-31 11:18:24 adam Exp $ +# $Id: Makefile.in,v 1.6 1999-04-16 14:45:55 adam Exp $ SHELL=/bin/sh @@ -33,7 +33,7 @@ alll: $(CC) -c $(DEFS) $(CFLAGS) $< clean: - rm -f *.[oa] test core mon.out gmon.out errlist tst cli $(PROG) + rm -f *.[oa] test core mon.out gmon.out errlist $(PROG) depend: sed '/^#Depend/q' Makefile.tmp diff --git a/comstack/tcpip.c b/comstack/tcpip.c index 94e05c8..62a6a5e 100644 --- a/comstack/tcpip.c +++ b/comstack/tcpip.c @@ -4,7 +4,10 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: tcpip.c,v $ - * Revision 1.28 1999-03-31 11:11:14 adam + * Revision 1.29 1999-04-16 14:45:55 adam + * Added interface for tcpd wrapper for access control. + * + * Revision 1.28 1999/03/31 11:11:14 adam * Function getprotobyname only called once. Minor change in tcpip_get * to handle multi-threaded conditions. * @@ -169,6 +172,7 @@ #include #include +#include /* Chas added the following, so we get the definition of completeBER */ #include @@ -412,6 +416,7 @@ int tcpip_bind(COMSTACK h, void *address, int mode) unsigned long one = 1; #endif + logf (LOG_LOG, "tcpip_bind"); TRC(fprintf(stderr, "tcpip_bind\n")); if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one)) < 0) @@ -433,19 +438,6 @@ int tcpip_bind(COMSTACK h, void *address, int mode) return 0; } -#if 0 -void tcpip_get_ip(COMSTACK h, char *ip_buf) -{ - struct tcpip_state *sp = (tcpip_state *)h->cprivate; - const char *ip_addr = (const char *) (&sp->addr->sin_addr.s_addr); - int i; - - for (i = 0; i<4; i++) - TRC (fprintf (stderr, "%u ", ip_addr[i])); - TRC (fprintf (stderr, "\n")); -} -#endif - int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, int (*check_ip)(void *cd, const char *a, int len, int type), void *cd) @@ -476,14 +468,14 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in)); else if (addrlen) *addrlen = 0; - if (check_ip && (*check_ip)(cd, (const char *) &addr.sin_addr, - sizeof(addr.sin_addr), AF_INET)) + if (check_ip && (*check_ip)(cd, (const char *) &addr, + sizeof(addr), AF_INET)) { h->cerrno = CSDENY; #ifdef WIN32 - closesocket(h->iofile); + closesocket(h->newfd); #else - close(h->iofile); + close(h->newfd); #endif return -1; } diff --git a/configure b/configure index 5466d78..246ec9b 100755 --- a/configure +++ b/configure @@ -1233,13 +1233,89 @@ fi done fi +echo $ac_n "checking for main in -lwrap""... $ac_c" 1>&6 +echo "configure:1238: checking for main in -lwrap" >&5 +ac_lib_var=`echo wrap'_'main | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lwrap $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lwrap" +else + echo "$ac_t""no" 1>&6 +fi + +for ac_hdr in tcpd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1277: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1238: checking for ANSI C header files" >&5 +echo "configure:1314: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1247,7 +1323,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1327: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1264,7 +1340,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1282,7 +1358,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1303,7 +1379,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1314,7 +1390,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:1318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : else @@ -1353,17 +1429,17 @@ if test "$threads_ok" = "yes"; then do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1357: checking for $ac_hdr" >&5 +echo "configure:1433: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1367: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1443: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1390,12 +1466,12 @@ fi done echo $ac_n "checking for pthread_mutex_lock""... $ac_c" 1>&6 -echo "configure:1394: checking for pthread_mutex_lock" >&5 +echo "configure:1470: checking for pthread_mutex_lock" >&5 if eval "test \"`echo '$''{'ac_cv_func_pthread_mutex_lock'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1498: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_pthread_mutex_lock=yes" else @@ -1439,7 +1515,7 @@ fi if test "$ac_cv_func_pthread_mutex_lock" = "no"; then echo $ac_n "checking for main in -lpthread""... $ac_c" 1>&6 -echo "configure:1443: checking for main in -lpthread" >&5 +echo "configure:1519: checking for main in -lpthread" >&5 ac_lib_var=`echo pthread'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1447,14 +1523,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1534: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else diff --git a/configure.in b/configure.in index 342eb41..c2a5bbf 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl YAZ Toolkit -dnl (c) Index Data 1994-1998 +dnl (c) Index Data 1994-1999 dnl See the file LICENSE for details. -dnl $Id: configure.in,v 1.6 1999-03-11 11:12:07 adam Exp $ +dnl $Id: configure.in,v 1.7 1999-04-16 14:45:55 adam Exp $ AC_INIT(include/yaz-version.h) dnl dnl ------ Checking programs @@ -50,6 +50,10 @@ if test "$ac_cv_lib_readline_readline" = "yes"; then AC_CHECK_HEADERS(readline/readline.h readline/history.h) fi dnl +dnl ------ tcpd +AC_CHECK_LIB(wrap, main, [LIBS="$LIBS -lwrap"]) +AC_CHECK_HEADERS(tcpd.h) +dnl dnl ------ Headers AC_STDC_HEADERS if test "$ac_cv_header_stdc" = "no"; then diff --git a/include/statserv.h b/include/statserv.h index e4669f3..0326a3b 100644 --- a/include/statserv.h +++ b/include/statserv.h @@ -24,7 +24,10 @@ * OF THIS SOFTWARE. * * $Log: statserv.h,v $ - * Revision 1.14 1999-02-02 13:57:32 adam + * Revision 1.15 1999-04-16 14:45:55 adam + * Added interface for tcpd wrapper for access control. + * + * Revision 1.14 1999/02/02 13:57:32 adam * Uses preprocessor define WIN32 instead of WINDOWS to build code * for Microsoft WIN32. * @@ -81,6 +84,7 @@ #define STATSERVER_H #include +#include #include #ifdef __cplusplus @@ -101,6 +105,8 @@ typedef struct statserv_options_block char setuid[ODR_MAXNAME+1]; /* setuid to this user after binding */ void (*pre_init)(struct statserv_options_block *p); int (*options_func)(int argc, char **argv); + int (*check_ip)(void *cd, const char *addr, int len, int type); + char daemon_name[128]; int inetd; /* Do we use the inet deamon or not */ #ifdef WIN32 @@ -119,6 +125,8 @@ void statserv_closedown(void); statserv_options_block *statserv_getcontrol(void); void statserv_setcontrol(statserv_options_block *block); +int check_ip_tcpd(void *cd, const char *addr, int len, int type); + #ifdef __cplusplus } #endif diff --git a/server/Makefile.in b/server/Makefile.in index fac9db8..c2b5859 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -1,7 +1,7 @@ -# Copyright (C) 1995-1998, Index Data +# Copyright (C) 1995-1999, Index Data # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile.in,v 1.3 1998-10-28 15:10:11 adam Exp $ +# $Id: Makefile.in,v 1.4 1999-04-16 14:45:55 adam Exp $ SHELL=/bin/sh @@ -19,7 +19,7 @@ INCLUDE=-I../z39.50 -I../include -I. -I../../xtimosi/src LIBINCLUDE=-L$(LIBDIR) DEFS=$(INCLUDE) $(CDEFS) LIB=$(LIBDIR)/libserver.a -PO = eventl.o seshigh.o statserv.o requestq.o +PO = eventl.o seshigh.o statserv.o requestq.o tcpdchk.o all: $(LIB) diff --git a/server/statserv.c b/server/statserv.c index b7759f3..6bfee93 100644 --- a/server/statserv.c +++ b/server/statserv.c @@ -7,7 +7,10 @@ * Chas Woodfield, Fretwell Downing Datasystems. * * $Log: statserv.c,v $ - * Revision 1.53 1999-02-02 13:57:39 adam + * Revision 1.54 1999-04-16 14:45:55 adam + * Added interface for tcpd wrapper for access control. + * + * Revision 1.53 1999/02/02 13:57:39 adam * Uses preprocessor define WIN32 instead of WINDOWS to build code * for Microsoft WIN32. * @@ -187,7 +190,6 @@ * */ -#include #include #include #ifdef WIN32 @@ -203,9 +205,9 @@ #include #include -#include #include #include +#include #ifdef USE_XTIMOSI #include #endif @@ -234,6 +236,8 @@ statserv_options_block control_block = { "", /* set user id */ NULL, /* pre init handler */ check_options, /* Default routine, for checking the run-time arguments */ + check_ip_tcpd, + "", 0 /* default value for inet deamon */ #ifdef WIN32 @@ -509,19 +513,6 @@ void statserv_closedown() iochan_destroy(p); } -static int check_ip(void *cd, const char *addr, int len, int type) -{ - const unsigned char *ip = (const unsigned char *) addr; - int i; - char str[64]; - - sprintf (str, "%u", *ip); - for (i = 1; i<4; i++) - sprintf (str + strlen(str), ".%u", ip[i]); - logf (LOG_DEBUG, "ip %s", str); - return 0; -} - static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); @@ -589,7 +580,8 @@ static void listener(IOCHAN h, int event) return; } } - if ((res = cs_listen_check(line, 0, 0, check_ip, 0)) < 0) + if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, + control_block.daemon_name)) < 0) { logf(LOG_WARN, "cs_listen failed"); return; @@ -855,7 +847,7 @@ int check_options(int argc, char **argv) int ret = 0, r; char *arg; - while ((ret = options("a:iszSl:v:u:c:w:t:k:", argv, argc, &arg)) != -2) + while ((ret = options("a:iszSl:v:u:c:w:t:k:d:", argv, argc, &arg)) != -2) { switch (ret) { @@ -888,6 +880,9 @@ int check_options(int argc, char **argv) case 'c': strcpy(control_block.configname, arg ? arg : ""); break; + case 'd': + strcpy(control_block.daemon_name, arg ? arg : ""); + break; case 't': if (!arg || !(r = atoi(arg))) { @@ -899,7 +894,7 @@ int check_options(int argc, char **argv) case 'k': if (!arg || !(r = atoi(arg))) { - fprintf(stderr, "%s: Specify positive timeout for -t.\n", me); + fprintf(stderr, "%s: Specify positive size for -k.\n", me); return(1); } control_block.maxrecordsize = r * 1024; @@ -917,7 +912,7 @@ int check_options(int argc, char **argv) default: fprintf(stderr, "Usage: %s [ -i -a -v " " -l -u -c -t " - " -k " + " -k -d " " -zsS -w ... ]\n", me); return(1); } diff --git a/server/tcpdchk.c b/server/tcpdchk.c new file mode 100644 index 0000000..a5d3d64 --- /dev/null +++ b/server/tcpdchk.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1995-1999, Index Data + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: tcpdchk.c,v $ + * Revision 1.1 1999-04-16 14:45:55 adam + * Added interface for tcpd wrapper for access control. + * + */ + +#include +#include + +#if HAVE_TCPD_H +#include +#include + +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; + +#ifdef LOG_DEBUG +#undef LOG_DEBUG +#endif +#ifdef LOG_WARN +#undef LOG_WARN +#endif + +#endif + +#ifdef WIN32 +#include +#else +#include +#endif + +#include +#include +#include + +int check_ip_tcpd(void *cd, const char *addr, int len, int type) +{ + const char *daemon_name = cd; + + if (type == AF_INET) + { + if (daemon_name && *daemon_name) + { +#if HAVE_TCPD_H + struct request_info request_info; +#endif + int i; + char *host_name = 0, *host_addr = 0; + struct hostent *host; + + struct sockaddr_in *addr_in = (struct sockaddr_in *) addr; + + if ((host = gethostbyaddr((char*)&addr_in->sin_addr, + sizeof(addr_in->sin_addr), + AF_INET))) + host_name = (char*) host->h_name; + host_addr = inet_ntoa(addr_in->sin_addr); +#if HAVE_TCPD_H + if (host_addr) + request_init(&request_info, RQ_DAEMON, daemon_name, + RQ_CLIENT_NAME, host_name, + RQ_CLIENT_SIN, addr_in, + RQ_CLIENT_ADDR, host_addr, 0); + else + request_init(&request_info, RQ_DAEMON, daemon_name, + RQ_CLIENT_SIN, addr_in, + RQ_CLIENT_ADDR, host_addr, 0); + i = hosts_access(&request_info); + if (!i) + { + logf (LOG_DEBUG, "access denied from %s", + host_name ? host_name : host_addr); + return 1; + } + logf (LOG_DEBUG, "access granted from %s", + host_name ? host_name : host_addr); +#endif + } + } + return 0; +} + diff --git a/ztest/Makefile.in b/ztest/Makefile.in index 98a5b0a..b7854ca 100644 --- a/ztest/Makefile.in +++ b/ztest/Makefile.in @@ -1,7 +1,7 @@ -# Copyright (C) 1995-1998, Index Data I/S +# Copyright (C) 1995-1999, Index Data # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile.in,v 1.4 1998-10-28 15:10:14 adam Exp $ +# $Id: Makefile.in,v 1.5 1999-04-16 14:45:55 adam Exp $ SHELL=/bin/sh -- 1.7.10.4