]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/misc/tcpwrapper.c
Only hash on IP address and Program number. Including the Procedure
[nfs-utils.git] / support / misc / tcpwrapper.c
index f7fd3a9cd2d1bfe5dc13051e00bbd42c7771262c..a9cd9088ef7854365d24bcd4eeb3407f6705ad72 100644 (file)
 #include <sys/types.h>
 #include <sys/signal.h>
 #include <sys/queue.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "xlog.h"
+
 #ifdef SYSV40
 #include <netinet/in.h>
 #include <rpc/rpcent.h>
@@ -53,6 +58,8 @@
 static void logit(int severity, struct sockaddr_in *addr,
                  u_long procnum, u_long prognum, char *text);
 static void toggle_verboselog(int sig);
+static int check_files(void);
+
 int     verboselog = 0;
 int     allow_severity = LOG_INFO;
 int     deny_severity = LOG_WARNING;
@@ -101,8 +108,8 @@ typedef struct _hash_head {
        TAILQ_HEAD(host_list, _haccess_t) h_head;
 } hash_head;
 hash_head haccess_tbl[HASH_TABLE_SIZE];
-static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long, u_long);
-static void haccess_add(struct sockaddr_in *addr, u_long, u_long, int);
+static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long);
+static void haccess_add(struct sockaddr_in *addr, u_long, int);
 
 inline unsigned int strtoint(char *str)
 {
@@ -115,15 +122,14 @@ inline unsigned int strtoint(char *str)
 
        return n;
 }
-inline int hashint(unsigned int num)
+static inline int hashint(unsigned int num)
 {
        return num % HASH_TABLE_SIZE;
 }
-#define HASH(_addr, _proc, _prog) \
-       hashint((strtoint((_addr))+(_proc)+(_prog)))
+#define HASH(_addr, _prog) \
+       hashint((strtoint((_addr))+(_prog)))
 
-void haccess_add(struct sockaddr_in *addr, u_long proc, 
-       u_long prog, int access)
+void haccess_add(struct sockaddr_in *addr, u_long prog, int access)
 {
        hash_head *head;
        haccess_t *hptr;
@@ -133,7 +139,7 @@ void haccess_add(struct sockaddr_in *addr, u_long proc,
        if (hptr == NULL)
                return;
 
-       hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
+       hash = HASH(inet_ntoa(addr->sin_addr), prog);
        head = &(haccess_tbl[hash]);
 
        hptr->access = access;
@@ -144,13 +150,13 @@ void haccess_add(struct sockaddr_in *addr, u_long proc,
        else
                TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
 }
-haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long proc, u_long prog)
+haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long prog)
 {
        hash_head *head;
        haccess_t *hptr;
        int hash;
 
-       hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
+       hash = HASH(inet_ntoa(addr->sin_addr), prog);
        head = &(haccess_tbl[hash]);
 
        TAILQ_FOREACH(hptr, &head->h_head, list) {
@@ -176,17 +182,27 @@ struct sockaddr_in *addr;
        /* Now do the hostname lookup */
        hp = gethostbyaddr ((const char *) &(addr->sin_addr),
                sizeof (addr->sin_addr), AF_INET);
-       if (!hp)
+       if (!hp) {
+               xlog(L_WARNING, 
+                       "Warning: Client IP address '%s' not found in host lookup",
+                       inet_ntoa(addr->sin_addr));
                return DENY; /* never heard of it. misconfigured DNS? */
+       }
 
        /* Make sure the hostent is authorative. */
        tmpname = strdup(hp->h_name);
-       if (!tmpname)
+       if (!tmpname) {
+               xlog(L_WARNING, "Warning: No memory for Host access check");
                return DENY;
+       }
        hp = gethostbyname(tmpname);
-       free(tmpname);
-       if (!hp)
+       if (!hp) {
+               xlog(L_WARNING, 
+                       "Warning: Client hostname '%s' not found in host lookup", tmpname);
+               free(tmpname);
                return DENY; /* never heard of it. misconfigured DNS? */
+       }
+       free(tmpname);
 
        /* Now make sure the address is on the list */
        for (sp = hp->h_addr_list ; *sp ; sp++) {
@@ -246,6 +262,33 @@ void    check_startup(void)
     (void) signal(SIGINT, toggle_verboselog);
 }
 
+/* check_files - check to see if either access files have changed */
+
+static int check_files()
+{
+       static time_t allow_mtime, deny_mtime;
+       struct stat astat, dstat;
+       int changed = 0;
+
+       if (stat("/etc/hosts.allow", &astat) < 0)
+               astat.st_mtime = 0;
+       if (stat("/etc/hosts.deny", &dstat) < 0)
+               dstat.st_mtime = 0;
+
+       if(!astat.st_mtime || !dstat.st_mtime)
+               return changed;
+
+       if (astat.st_mtime != allow_mtime)
+               changed = 1;
+       else if (dstat.st_mtime != deny_mtime)
+               changed = 1;
+
+       allow_mtime = astat.st_mtime;
+       deny_mtime = dstat.st_mtime;
+
+       return changed;
+}
+
 /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
 
 int
@@ -256,20 +299,27 @@ u_long  proc;
 u_long  prog;
 {
        haccess_t *acc = NULL;
+       int changed = check_files();
 
-       acc = haccess_lookup(addr, proc, prog);
-       if (acc)
+       acc = haccess_lookup(addr, prog);
+       if (acc && changed == 0)
                return (acc->access);
 
        if (!(from_local(addr) || good_client(daemon, addr))) {
                log_bad_host(addr, proc, prog);
-               haccess_add(addr, proc, prog, FALSE);
+               if (acc)
+                       acc->access = FALSE;
+               else 
+                       haccess_add(addr, prog, FALSE);
                return (FALSE);
        }
        if (verboselog)
                log_client(addr, proc, prog);
 
-       haccess_add(addr, proc, prog, TRUE);
+       if (acc)
+               acc->access = TRUE;
+       else 
+               haccess_add(addr, prog, TRUE);
     return (TRUE);
 }