1 /* This is copied from portmap 4.0-29 in RedHat. */
4 * pmap_check - additional portmap security.
6 * Always reject non-local requests to update the portmapper tables.
8 * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
9 * requests would appear to come from the local system, and nfs export
10 * restrictions could be bypassed.
12 * Refuse to forward requests to the nfsd process.
14 * Refuse to forward requests to NIS (YP) daemons; The only exception is the
15 * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
16 * contact with the NIS server.
18 * Always allocate an unprivileged port when forwarding a request.
20 * If compiled with -DCHECK_PORT, require that requests to register or
21 * unregister a privileged port come from a privileged port. This makes it
22 * more difficult to replace a critical service by a trojan.
24 * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
25 * authorized by the /etc/hosts.{allow,deny} files. The local system is
26 * always treated as an authorized host. The access control tables are never
27 * consulted for requests from the local system, and are always consulted
28 * for requests from other hosts.
30 * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
31 * Computing Science, Eindhoven University of Technology, The Netherlands.
38 #include <tcpwrapper.h>
42 #include <rpc/pmap_prot.h>
46 #include <sys/types.h>
47 #include <sys/signal.h>
48 #include <sys/queue.h>
55 #include <netinet/in.h>
56 #include <rpc/rpcent.h>
59 static void logit(int severity, struct sockaddr_in *addr,
60 u_long procnum, u_long prognum, char *text);
61 static int check_files(void);
64 * These need to exist since they are externed
65 * public header files.
68 int allow_severity = LOG_INFO;
69 int deny_severity = LOG_WARNING;
71 #define log_bad_host(addr, proc, prog) \
72 logit(deny_severity, addr, proc, prog, "request from unauthorized host")
77 typedef struct _haccess_t {
78 TAILQ_ENTRY(_haccess_t) list;
83 #define HASH_TABLE_SIZE 1021
84 typedef struct _hash_head {
85 TAILQ_HEAD(host_list, _haccess_t) h_head;
87 hash_head haccess_tbl[HASH_TABLE_SIZE];
88 static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long);
89 static void haccess_add(struct sockaddr_in *addr, u_long, int);
91 inline unsigned int strtoint(char *str)
94 int len = strlen(str);
97 for (i=0; i < len; i++)
102 static inline int hashint(unsigned int num)
104 return num % HASH_TABLE_SIZE;
106 #define HASH(_addr, _prog) \
107 hashint((strtoint((_addr))+(_prog)))
109 void haccess_add(struct sockaddr_in *addr, u_long prog, int access)
115 hptr = (haccess_t *)malloc(sizeof(haccess_t));
119 hash = HASH(inet_ntoa(addr->sin_addr), prog);
120 head = &(haccess_tbl[hash]);
122 hptr->access = access;
123 hptr->addr.s_addr = addr->sin_addr.s_addr;
125 if (TAILQ_EMPTY(&head->h_head))
126 TAILQ_INSERT_HEAD(&head->h_head, hptr, list);
128 TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
130 haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long prog)
136 hash = HASH(inet_ntoa(addr->sin_addr), prog);
137 head = &(haccess_tbl[hash]);
139 TAILQ_FOREACH(hptr, &head->h_head, list) {
140 if (hptr->addr.s_addr == addr->sin_addr.s_addr)
147 good_client(daemon, addr)
149 struct sockaddr_in *addr;
151 struct request_info req;
153 request_init(&req, RQ_DAEMON, daemon, RQ_CLIENT_SIN, addr, 0);
156 if (hosts_access(&req))
162 /* check_files - check to see if either access files have changed */
164 static int check_files()
166 static time_t allow_mtime, deny_mtime;
167 struct stat astat, dstat;
170 if (stat("/etc/hosts.allow", &astat) < 0)
172 if (stat("/etc/hosts.deny", &dstat) < 0)
175 if(!astat.st_mtime || !dstat.st_mtime)
178 if (astat.st_mtime != allow_mtime)
180 else if (dstat.st_mtime != deny_mtime)
183 allow_mtime = astat.st_mtime;
184 deny_mtime = dstat.st_mtime;
189 /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
192 check_default(daemon, addr, proc, prog)
194 struct sockaddr_in *addr;
198 haccess_t *acc = NULL;
199 int changed = check_files();
201 acc = haccess_lookup(addr, prog);
202 if (acc && changed == 0)
203 return (acc->access);
205 if (!(from_local(addr) || good_client(daemon, addr))) {
206 log_bad_host(addr, proc, prog);
210 haccess_add(addr, prog, FALSE);
217 haccess_add(addr, prog, TRUE);
222 /* logit - report events of interest via the syslog daemon */
224 static void logit(int severity, struct sockaddr_in *addr,
225 u_long procnum, u_long prognum, char *text)
227 syslog(severity, "connect from %s denied: %s",
228 inet_ntoa(addr->sin_addr), text);