]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/misc/tcpwrapper.c
libexport.a: Refactor client_init()
[nfs-utils.git] / support / misc / tcpwrapper.c
index af626adc5b5cdb430f20c92549a0c02a813823f4..06b0a463019ad08f7de34d3dad4bbaaf2ed8c93c 100644 (file)
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
+
 #ifdef HAVE_LIBWRAP
-#include <tcpwrapper.h>
 #include <unistd.h>
 #include <string.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
-#include <syslog.h>
 #include <netdb.h>
 #include <pwd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <tcpd.h>
 
+#include "sockaddr.h"
+#include "tcpwrapper.h"
 #include "xlog.h"
 
 #ifdef SYSV40
 #include <netinet/in.h>
 #include <rpc/rpcent.h>
-#endif
+#endif /* SYSV40 */
 
-static void logit(int severity, struct sockaddr_in *addr,
-                 u_long procnum, u_long prognum, char *text);
-static int check_files(void);
+#define ALLOW 1
+#define DENY 0
 
-/*
- * These need to exist since they are externed 
- * public header files.
- */
-int     verboselog = 0;
-int     allow_severity = LOG_INFO;
-int     deny_severity = LOG_WARNING;
+#ifdef IPV6_SUPPORTED
+static void
+present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+       const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+       const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
+       socklen_t len = (socklen_t)buflen;
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               if (inet_ntop(AF_INET, &sin->sin_addr, buf, len) != 0)
+                       return;
+       case AF_INET6:
+               if (inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len) != 0)
+                       return;
+       }
 
-#define log_bad_host(addr, proc, prog) \
-  logit(deny_severity, addr, proc, prog, "request from unauthorized host")
+       memset(buf, 0, buflen);
+       strncpy(buf, "unrecognized caller", buflen);
+}
+#else  /* !IPV6_SUPPORTED */
+static void
+present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+       const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+       socklen_t len = (socklen_t)buflen;
 
-#define ALLOW 1
-#define DENY 0
+       if (sap->sa_family == AF_INET)
+               if (inet_ntop(AF_INET, &sin->sin_addr, buf, len) != 0)
+                       return;
+
+       memset(buf, 0, buflen);
+       strncpy(buf, "unrecognized caller", (size_t)buflen);
+}
+#endif /* !IPV6_SUPPORTED */
 
 typedef struct _haccess_t {
-       TAILQ_ENTRY(_haccess_t) list;
-       int access;
-    struct in_addr addr;
+       TAILQ_ENTRY(_haccess_t) list;
+       int                     allowed;
+       union nfs_sockaddr      address;
 } haccess_t;
 
 #define HASH_TABLE_SIZE 1021
 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);
-static void haccess_add(struct sockaddr_in *addr, u_long, int);
 
-inline unsigned int strtoint(char *str)
+static hash_head haccess_tbl[HASH_TABLE_SIZE];
+
+static unsigned long
+strtoint(const char *str)
 {
-       unsigned int n = 0;
-       int len = strlen(str);
-       int i;
+       unsigned long i, n = 0;
+       size_t len = strlen(str);
 
-       for (i=0; i < len; i++)
-               n+=((int)str[i])*i;
+       for (i = 0; i < len; i++)
+               n += (unsigned char)str[i] * i;
 
        return n;
 }
-static inline int hashint(unsigned int num)
+
+static unsigned int
+hashint(const unsigned long num)
 {
-       return num % HASH_TABLE_SIZE;
+       return (unsigned int)(num % HASH_TABLE_SIZE);
 }
-#define HASH(_addr, _prog) \
-       hashint((strtoint((_addr))+(_prog)))
 
-void haccess_add(struct sockaddr_in *addr, u_long prog, int access)
+static unsigned int
+HASH(const char *addr, const unsigned long program)
+{
+       return hashint(strtoint(addr) + program);
+}
+
+static void
+haccess_add(const struct sockaddr *sap, const char *address,
+               const unsigned long program, const int allowed)
 {
        hash_head *head;
-       haccess_t *hptr;
-       int hash;
+       haccess_t *hptr;
+       unsigned int hash;
 
        hptr = (haccess_t *)malloc(sizeof(haccess_t));
        if (hptr == NULL)
                return;
 
-       hash = HASH(inet_ntoa(addr->sin_addr), prog);
+       hash = HASH(address, program);
        head = &(haccess_tbl[hash]);
 
-       hptr->access = access;
-       hptr->addr.s_addr = addr->sin_addr.s_addr;
+       hptr->allowed = allowed;
+       memcpy(&hptr->address, sap, (size_t)nfs_sockaddr_length(sap));
 
        if (TAILQ_EMPTY(&head->h_head))
                TAILQ_INSERT_HEAD(&head->h_head, hptr, list);
        else
                TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
 }
-haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long prog)
+
+static haccess_t *
+haccess_lookup(const struct sockaddr *sap, const char *address,
+               const unsigned long program)
 {
        hash_head *head;
-       haccess_t *hptr;
-       int hash;
+       haccess_t *hptr;
+       unsigned int hash;
 
-       hash = HASH(inet_ntoa(addr->sin_addr), prog);
+       hash = HASH(address, program);
        head = &(haccess_tbl[hash]);
 
        TAILQ_FOREACH(hptr, &head->h_head, list) {
-               if (hptr->addr.s_addr == addr->sin_addr.s_addr)
+               if (nfs_compare_sockaddr(&hptr->address.sa, sap))
                        return hptr;
        }
        return NULL;
 }
 
-int
-good_client(daemon, addr)
-char *daemon;
-struct sockaddr_in *addr;
+static void
+logit(const char *address)
+{
+       xlog_warn("connect from %s denied: request from unauthorized host",
+                       address);
+}
+
+static int
+good_client(char *name, struct sockaddr *sap)
 {
        struct request_info req;
 
-       request_init(&req, RQ_DAEMON, daemon, RQ_CLIENT_SIN, addr, 0);
+       request_init(&req, RQ_DAEMON, name, RQ_CLIENT_SIN, sap, 0);
        sock_methods(&req);
 
        if (hosts_access(&req)) 
@@ -159,9 +196,8 @@ struct sockaddr_in *addr;
        return DENY;
 }
 
-/* check_files - check to see if either access files have changed */
-
-static int check_files()
+static int
+check_files(void)
 {
        static time_t allow_mtime, deny_mtime;
        struct stat astat, dstat;
@@ -186,45 +222,48 @@ static int check_files()
        return changed;
 }
 
-/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
-
+/**
+ * check_default - additional checks for NULL, DUMP, GETPORT and unknown
+ * @name: pointer to '\0'-terminated ASCII string containing name of the
+ *             daemon requesting the access check
+ * @sap: pointer to sockaddr containing network address of caller
+ * @program: RPC program number caller is attempting to access
+ *
+ * Returns TRUE if the caller is allowed access; otherwise FALSE is returned.
+ */
 int
-check_default(daemon, addr, proc, prog)
-char *daemon;
-struct sockaddr_in *addr;
-u_long  proc;
-u_long  prog;
+check_default(char *name, struct sockaddr *sap, const unsigned long program)
 {
        haccess_t *acc = NULL;
        int changed = check_files();
+       char buf[INET6_ADDRSTRLEN];
+
+       present_address(sap, buf, sizeof(buf));
 
-       acc = haccess_lookup(addr, prog);
-       if (acc && changed == 0)
-               return (acc->access);
+       acc = haccess_lookup(sap, buf, program);
+       if (acc != NULL && changed == 0) {
+               xlog(D_GENERAL, "%s: access by %s %s (cached)", __func__,
+                       buf, acc->allowed ? "ALLOWED" : "DENIED");
+               return acc->allowed;
+       }
 
-       if (!(from_local((struct sockaddr *)addr) || good_client(daemon, addr))) {
-               log_bad_host(addr, proc, prog);
-               if (acc)
-                       acc->access = FALSE;
-               else 
-                       haccess_add(addr, prog, FALSE);
+       if (!(from_local(sap) || good_client(name, sap))) {
+               logit(buf);
+               if (acc != NULL)
+                       acc->allowed = FALSE;
+               else
+                       haccess_add(sap, buf, program, FALSE);
+               xlog(D_GENERAL, "%s: access by %s DENIED", __func__, buf);
                return (FALSE);
        }
 
-       if (acc)
-               acc->access = TRUE;
-       else 
-               haccess_add(addr, prog, TRUE);
+       if (acc != NULL)
+               acc->allowed = TRUE;
+       else
+               haccess_add(sap, buf, program, TRUE);
+       xlog(D_GENERAL, "%s: access by %s ALLOWED", __func__, buf);
 
-    return (TRUE);
+       return (TRUE);
 }
 
-/* logit - report events of interest via the syslog daemon */
-
-static void logit(int severity, struct sockaddr_in *addr,
-                 u_long procnum, u_long prognum, char *text)
-{
-       syslog(severity, "connect from %s denied: %s",
-              inet_ntoa(addr->sin_addr), text);
-}
-#endif
+#endif /* HAVE_LIBWRAP */