X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fmisc%2Ftcpwrapper.c;h=06b0a463019ad08f7de34d3dad4bbaaf2ed8c93c;hp=af626adc5b5cdb430f20c92549a0c02a813823f4;hb=9bb85c5e8d2285f82367c75df5530a71a9a5a5f2;hpb=4bc0dbaed1ba2f58beea2cdb0595b461e0c88b8e diff --git a/support/misc/tcpwrapper.c b/support/misc/tcpwrapper.c index af626ad..06b0a46 100644 --- a/support/misc/tcpwrapper.c +++ b/support/misc/tcpwrapper.c @@ -34,13 +34,12 @@ #ifdef HAVE_CONFIG_H #include #endif + #ifdef HAVE_LIBWRAP -#include #include #include #include #include -#include #include #include #include @@ -49,108 +48,146 @@ #include #include +#include "sockaddr.h" +#include "tcpwrapper.h" #include "xlog.h" #ifdef SYSV40 #include #include -#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 */