]> git.decadent.org.uk Git - nfs-utils.git/blob - support/misc/tcpwrapper.c
General clean up. Removed unused routines. Reworked syslog
[nfs-utils.git] / support / misc / tcpwrapper.c
1 /* This is copied from portmap 4.0-29 in RedHat. */
2
3  /*
4   * pmap_check - additional portmap security.
5   * 
6   * Always reject non-local requests to update the portmapper tables.
7   * 
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.
11   * 
12   * Refuse to forward requests to the nfsd process.
13   * 
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.
17   * 
18   * Always allocate an unprivileged port when forwarding a request.
19   * 
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.
23   * 
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.
29   * 
30   * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
31   * Computing Science, Eindhoven University of Technology, The Netherlands.
32   */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37 #ifdef HAVE_LIBWRAP
38 #include <tcpwrapper.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <rpc/rpc.h>
42 #include <rpc/pmap_prot.h>
43 #include <syslog.h>
44 #include <netdb.h>
45 #include <pwd.h>
46 #include <sys/types.h>
47 #include <sys/signal.h>
48 #include <sys/queue.h>
49 #include <sys/stat.h>
50 #include <tcpd.h>
51
52 #include "xlog.h"
53
54 #ifdef SYSV40
55 #include <netinet/in.h>
56 #include <rpc/rpcent.h>
57 #endif
58
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);
62
63 #define log_bad_host(addr, proc, prog) \
64   logit(LOG_WARNING, addr, proc, prog, "request from unauthorized host")
65
66 #define ALLOW 1
67 #define DENY 0
68
69 typedef struct _haccess_t {
70         TAILQ_ENTRY(_haccess_t) list;
71         int access;
72     struct in_addr addr;
73 } haccess_t;
74
75 #define HASH_TABLE_SIZE 1021
76 typedef struct _hash_head {
77         TAILQ_HEAD(host_list, _haccess_t) h_head;
78 } hash_head;
79 hash_head haccess_tbl[HASH_TABLE_SIZE];
80 static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long);
81 static void haccess_add(struct sockaddr_in *addr, u_long, int);
82
83 inline unsigned int strtoint(char *str)
84 {
85         unsigned int n = 0;
86         int len = strlen(str);
87         int i;
88
89         for (i=0; i < len; i++)
90                 n+=((int)str[i])*i;
91
92         return n;
93 }
94 static inline int hashint(unsigned int num)
95 {
96         return num % HASH_TABLE_SIZE;
97 }
98 #define HASH(_addr, _prog) \
99         hashint((strtoint((_addr))+(_prog)))
100
101 void haccess_add(struct sockaddr_in *addr, u_long prog, int access)
102 {
103         hash_head *head;
104         haccess_t *hptr;
105         int hash;
106
107         hptr = (haccess_t *)malloc(sizeof(haccess_t));
108         if (hptr == NULL)
109                 return;
110
111         hash = HASH(inet_ntoa(addr->sin_addr), prog);
112         head = &(haccess_tbl[hash]);
113
114         hptr->access = access;
115         hptr->addr.s_addr = addr->sin_addr.s_addr;
116
117         if (TAILQ_EMPTY(&head->h_head))
118                 TAILQ_INSERT_HEAD(&head->h_head, hptr, list);
119         else
120                 TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
121 }
122 haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long prog)
123 {
124         hash_head *head;
125         haccess_t *hptr;
126         int hash;
127
128         hash = HASH(inet_ntoa(addr->sin_addr), prog);
129         head = &(haccess_tbl[hash]);
130
131         TAILQ_FOREACH(hptr, &head->h_head, list) {
132                 if (hptr->addr.s_addr == addr->sin_addr.s_addr)
133                         return hptr;
134         }
135         return NULL;
136 }
137
138 int
139 good_client(daemon, addr)
140 char *daemon;
141 struct sockaddr_in *addr;
142 {
143         struct request_info req;
144
145         request_init(&req, RQ_DAEMON, daemon, RQ_CLIENT_SIN, addr, 0);
146         sock_methods(&req);
147
148         if (hosts_access(&req)) 
149                 return ALLOW;
150
151         return DENY;
152 }
153
154 /* check_files - check to see if either access files have changed */
155
156 static int check_files()
157 {
158         static time_t allow_mtime, deny_mtime;
159         struct stat astat, dstat;
160         int changed = 0;
161
162         if (stat("/etc/hosts.allow", &astat) < 0)
163                 astat.st_mtime = 0;
164         if (stat("/etc/hosts.deny", &dstat) < 0)
165                 dstat.st_mtime = 0;
166
167         if(!astat.st_mtime || !dstat.st_mtime)
168                 return changed;
169
170         if (astat.st_mtime != allow_mtime)
171                 changed = 1;
172         else if (dstat.st_mtime != deny_mtime)
173                 changed = 1;
174
175         allow_mtime = astat.st_mtime;
176         deny_mtime = dstat.st_mtime;
177
178         return changed;
179 }
180
181 /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
182
183 int
184 check_default(daemon, addr, proc, prog)
185 char *daemon;
186 struct sockaddr_in *addr;
187 u_long  proc;
188 u_long  prog;
189 {
190         haccess_t *acc = NULL;
191         int changed = check_files();
192
193         acc = haccess_lookup(addr, prog);
194         if (acc && changed == 0)
195                 return (acc->access);
196
197         if (!(from_local(addr) || good_client(daemon, addr))) {
198                 log_bad_host(addr, proc, prog);
199                 if (acc)
200                         acc->access = FALSE;
201                 else 
202                         haccess_add(addr, prog, FALSE);
203                 return (FALSE);
204         }
205
206         if (acc)
207                 acc->access = TRUE;
208         else 
209                 haccess_add(addr, prog, TRUE);
210
211     return (TRUE);
212 }
213
214 /* logit - report events of interest via the syslog daemon */
215
216 static void logit(int severity, struct sockaddr_in *addr,
217                   u_long procnum, u_long prognum, char *text)
218 {
219         syslog(severity, "connect from %s denied: %s",
220                inet_ntoa(addr->sin_addr), text);
221 }
222 #endif