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.
37 #include <tcpwrapper.h>
41 #include <rpc/pmap_prot.h>
45 #include <sys/types.h>
46 #include <sys/signal.h>
48 #include <netinet/in.h>
49 #include <rpc/rpcent.h>
53 static void toggle_verboselog();
55 int allow_severity = LOG_INFO;
56 int deny_severity = LOG_WARNING;
58 /* A handful of macros for "readability". */
61 /* coming from libwrap.a (tcp_wrappers) */
62 extern int hosts_ctl(char *daemon, char *name, char *addr, char *user);
64 int hosts_ctl(char *daemon, char *name, char *addr, char *user)
70 #define legal_port(a,p) \
71 (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
73 #define log_bad_port(addr, proc, prog) \
74 logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
76 #define log_bad_host(addr, proc, prog) \
77 logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
79 #define log_bad_owner(addr, proc, prog) \
80 logit(deny_severity, addr, proc, prog, ": request from non-local host")
82 #define log_no_forward(addr, proc, prog) \
83 logit(deny_severity, addr, proc, prog, ": request not forwarded")
85 #define log_client(addr, proc, prog) \
86 logit(allow_severity, addr, proc, prog, "")
89 good_client(daemon, addr)
91 struct sockaddr_in *addr;
97 /* Check the IP address first. */
98 if (hosts_ctl(daemon, "", inet_ntoa(addr->sin_addr), ""))
101 /* Check the hostname. */
102 hp = gethostbyaddr ((const char *) &(addr->sin_addr),
103 sizeof (addr->sin_addr), AF_INET);
108 /* must make sure the hostent is authorative. */
109 tmpname = alloca (strlen (hp->h_name) + 1);
110 strcpy (tmpname, hp->h_name);
111 hp = gethostbyname(tmpname);
113 /* now make sure the "addr->sin_addr" is on the list */
114 for (sp = hp->h_addr_list ; *sp ; sp++) {
115 if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0)
123 /* never heard of it. misconfigured DNS? */
126 /* Check the official name first. */
127 if (hosts_ctl(daemon, "", hp->h_name, ""))
131 for (sp = hp->h_aliases; *sp ; sp++) {
132 if (hosts_ctl(daemon, "", *sp, ""))
140 /* check_startup - additional startup code */
146 * Give up root privileges so that we can never allocate a privileged
147 * port when forwarding an rpc request.
149 * Fix 8/3/00 Philipp Knirsch: First lookup our rpc user. If we find it,
150 * switch to that uid, otherwise simply resue the old bin user and print
151 * out a warning in syslog.
154 struct passwd *pwent;
156 pwent = getpwnam("rpc");
158 syslog(LOG_WARNING, "user rpc not found, reverting to user bin");
159 if (setuid(1) == -1) {
160 syslog(LOG_ERR, "setuid(1) failed: %m");
165 if (setuid(pwent->pw_uid) == -1) {
166 syslog(LOG_WARNING, "setuid() to rpc user failed: %m");
167 if (setuid(1) == -1) {
168 syslog(LOG_ERR, "setuid(1) failed: %m");
174 (void) signal(SIGINT, toggle_verboselog);
177 /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
180 check_default(daemon, addr, proc, prog)
182 struct sockaddr_in *addr;
186 if (!(from_local(addr) || good_client(daemon, addr))) {
187 log_bad_host(addr, proc, prog);
191 log_client(addr, proc, prog);
195 /* check_privileged_port - additional checks for privileged-port updates */
197 check_privileged_port(addr, proc, prog, port)
198 struct sockaddr_in *addr;
204 if (!legal_port(addr, port)) {
205 log_bad_port(addr, proc, prog);
212 /* toggle_verboselog - toggle verbose logging flag */
214 static void toggle_verboselog(sig)
217 (void) signal(sig, toggle_verboselog);
218 verboselog = !verboselog;
221 /* logit - report events of interest via the syslog daemon */
223 static void logit(severity, addr, procnum, prognum, text)
225 struct sockaddr_in *addr;
231 char procbuf[16 + 4 * sizeof(u_long)];
233 char progbuf[16 + 4 * sizeof(u_long)];
237 * Fork off a process or the portmap daemon might hang while
238 * getrpcbynumber() or syslog() does its thing.
240 * Don't forget to wait for the children, too...
245 /* Try to map program number to name. */
249 } else if ((rpc = getrpcbynumber((int) prognum))) {
250 progname = rpc->r_name;
252 snprintf(progname = progbuf, sizeof (progbuf),
253 "prog (%lu)", prognum);
256 /* Try to map procedure number to name. */
258 snprintf(procname = procbuf, sizeof (procbuf),
259 "proc (%lu)", (u_long) procnum);
261 /* Write syslog record. */
263 syslog(severity, "connect from %s to %s in %s%s",
264 inet_ntoa(addr->sin_addr), procname, progname, text);