security.c revision 1.13 1 1.13 roy /* $NetBSD: security.c,v 1.13 2019/04/24 10:27:49 roy Exp $ */
2 1.12 christos /* $FreeBSD: head/usr.sbin/rpcbind/security.c 262860 2014-03-06 17:33:27Z mav $ */
3 1.1 fvdl
4 1.1 fvdl #include <sys/types.h>
5 1.1 fvdl #include <sys/time.h>
6 1.1 fvdl #include <sys/socket.h>
7 1.1 fvdl #include <netinet/in.h>
8 1.1 fvdl #include <arpa/inet.h>
9 1.1 fvdl #include <rpc/rpc.h>
10 1.1 fvdl #include <rpc/rpcb_prot.h>
11 1.1 fvdl #include <rpc/pmap_prot.h>
12 1.1 fvdl #include <err.h>
13 1.12 christos #include <stdio.h>
14 1.1 fvdl #include <stdlib.h>
15 1.2 thorpej #include <string.h>
16 1.1 fvdl #include <unistd.h>
17 1.1 fvdl #include <util.h>
18 1.1 fvdl #include <syslog.h>
19 1.1 fvdl #include <netdb.h>
20 1.1 fvdl
21 1.1 fvdl /*
22 1.1 fvdl * XXX for special case checks in check_callit.
23 1.1 fvdl */
24 1.1 fvdl #include <rpcsvc/mount.h>
25 1.1 fvdl #include <rpcsvc/rquota.h>
26 1.1 fvdl #include <rpcsvc/nfs_prot.h>
27 1.13 roy
28 1.13 roy #ifdef YP
29 1.1 fvdl #include <rpcsvc/yp.h>
30 1.1 fvdl #include <rpcsvc/ypclnt.h>
31 1.1 fvdl #include <rpcsvc/yppasswd.h>
32 1.13 roy #else
33 1.13 roy /* Define enough to compile. */
34 1.13 roy #define YPBINDPROG ((unsigned long)100007)
35 1.13 roy #define YPBINDPROC_SETDOM ((unsigned long)2)
36 1.13 roy #define YPPROG ((unsigned long)100004)
37 1.13 roy #define YPPROC_FIRST ((unsigned long)4)
38 1.13 roy #define YPPROC_NEXT ((unsigned long)5)
39 1.13 roy #define YPPROC_MATCH ((unsigned long)3)
40 1.13 roy #define YPPROC_ALL ((unsigned long)8)
41 1.13 roy #define YPPASSWDPROG ((unsigned long)100009)
42 1.13 roy #endif
43 1.1 fvdl
44 1.1 fvdl #include "rpcbind.h"
45 1.1 fvdl
46 1.1 fvdl #ifdef LIBWRAP
47 1.1 fvdl # include <tcpd.h>
48 1.1 fvdl #ifndef LIBWRAP_ALLOW_FACILITY
49 1.1 fvdl # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
50 1.1 fvdl #endif
51 1.1 fvdl #ifndef LIBWRAP_ALLOW_SEVERITY
52 1.1 fvdl # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
53 1.1 fvdl #endif
54 1.1 fvdl #ifndef LIBWRAP_DENY_FACILITY
55 1.1 fvdl # define LIBWRAP_DENY_FACILITY LOG_AUTH
56 1.1 fvdl #endif
57 1.1 fvdl #ifndef LIBWRAP_DENY_SEVERITY
58 1.1 fvdl # define LIBWRAP_DENY_SEVERITY LOG_WARNING
59 1.1 fvdl #endif
60 1.1 fvdl int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
61 1.1 fvdl int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
62 1.1 fvdl #endif
63 1.1 fvdl
64 1.1 fvdl #ifndef PORTMAP_LOG_FACILITY
65 1.1 fvdl # define PORTMAP_LOG_FACILITY LOG_AUTH
66 1.1 fvdl #endif
67 1.1 fvdl #ifndef PORTMAP_LOG_SEVERITY
68 1.1 fvdl # define PORTMAP_LOG_SEVERITY LOG_INFO
69 1.1 fvdl #endif
70 1.1 fvdl int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
71 1.1 fvdl
72 1.1 fvdl extern int verboselog;
73 1.1 fvdl
74 1.1 fvdl int
75 1.12 christos check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers)
76 1.1 fvdl {
77 1.1 fvdl struct netbuf *caller = svc_getrpccaller(xprt);
78 1.1 fvdl struct sockaddr *addr = (struct sockaddr *)caller->buf;
79 1.1 fvdl #ifdef LIBWRAP
80 1.1 fvdl struct request_info req;
81 1.1 fvdl #endif
82 1.1 fvdl rpcprog_t prog = 0;
83 1.1 fvdl rpcb *rpcbp;
84 1.1 fvdl struct pmap *pmap;
85 1.1 fvdl
86 1.1 fvdl /*
87 1.1 fvdl * The older PMAP_* equivalents have the same numbers, so
88 1.1 fvdl * they are accounted for here as well.
89 1.1 fvdl */
90 1.1 fvdl switch (proc) {
91 1.1 fvdl case RPCBPROC_GETADDR:
92 1.1 fvdl case RPCBPROC_SET:
93 1.1 fvdl case RPCBPROC_UNSET:
94 1.1 fvdl if (rpcbvers > PMAPVERS) {
95 1.1 fvdl rpcbp = (rpcb *)args;
96 1.1 fvdl prog = rpcbp->r_prog;
97 1.1 fvdl } else {
98 1.1 fvdl pmap = (struct pmap *)args;
99 1.1 fvdl prog = pmap->pm_prog;
100 1.1 fvdl }
101 1.1 fvdl if (proc == RPCBPROC_GETADDR)
102 1.1 fvdl break;
103 1.1 fvdl if (!insecure && !is_loopback(caller)) {
104 1.1 fvdl if (verboselog)
105 1.1 fvdl logit(log_severity, addr, proc, prog,
106 1.1 fvdl " declined (non-loopback sender)");
107 1.1 fvdl return 0;
108 1.1 fvdl }
109 1.1 fvdl break;
110 1.1 fvdl case RPCBPROC_CALLIT:
111 1.1 fvdl case RPCBPROC_INDIRECT:
112 1.1 fvdl case RPCBPROC_DUMP:
113 1.1 fvdl case RPCBPROC_GETTIME:
114 1.1 fvdl case RPCBPROC_UADDR2TADDR:
115 1.1 fvdl case RPCBPROC_TADDR2UADDR:
116 1.1 fvdl case RPCBPROC_GETVERSADDR:
117 1.1 fvdl case RPCBPROC_GETADDRLIST:
118 1.1 fvdl case RPCBPROC_GETSTAT:
119 1.1 fvdl default:
120 1.6 cgd break;
121 1.1 fvdl }
122 1.1 fvdl
123 1.1 fvdl #ifdef LIBWRAP
124 1.12 christos if (libwrap && addr->sa_family != AF_LOCAL) {
125 1.12 christos request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr,
126 1.12 christos 0);
127 1.12 christos sock_methods(&req);
128 1.12 christos if(!hosts_access(&req)) {
129 1.12 christos logit(deny_severity, addr, proc, prog,
130 1.12 christos ": request from unauthorized host");
131 1.12 christos return 0;
132 1.12 christos }
133 1.1 fvdl }
134 1.1 fvdl #endif
135 1.1 fvdl if (verboselog)
136 1.1 fvdl logit(log_severity, addr, proc, prog, "");
137 1.1 fvdl return 1;
138 1.1 fvdl }
139 1.1 fvdl
140 1.1 fvdl int
141 1.1 fvdl is_loopback(struct netbuf *nbuf)
142 1.1 fvdl {
143 1.1 fvdl struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
144 1.1 fvdl struct sockaddr_in *sin;
145 1.1 fvdl #ifdef INET6
146 1.1 fvdl struct sockaddr_in6 *sin6;
147 1.1 fvdl #endif
148 1.1 fvdl
149 1.1 fvdl switch (addr->sa_family) {
150 1.1 fvdl case AF_INET:
151 1.1 fvdl if (!oldstyle_local)
152 1.1 fvdl return 0;
153 1.1 fvdl sin = (struct sockaddr_in *)addr;
154 1.1 fvdl return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
155 1.5 fvdl (ntohs(sin->sin_port) < IPPORT_RESERVED));
156 1.1 fvdl #ifdef INET6
157 1.1 fvdl case AF_INET6:
158 1.1 fvdl if (!oldstyle_local)
159 1.1 fvdl return 0;
160 1.1 fvdl sin6 = (struct sockaddr_in6 *)addr;
161 1.1 fvdl return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
162 1.5 fvdl (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
163 1.1 fvdl #endif
164 1.1 fvdl case AF_LOCAL:
165 1.1 fvdl return 1;
166 1.1 fvdl default:
167 1.6 cgd break;
168 1.1 fvdl }
169 1.1 fvdl
170 1.1 fvdl return 0;
171 1.1 fvdl }
172 1.1 fvdl
173 1.1 fvdl
174 1.1 fvdl /* logit - report events of interest via the syslog daemon */
175 1.1 fvdl void
176 1.1 fvdl logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
177 1.1 fvdl const char *text)
178 1.1 fvdl {
179 1.1 fvdl const char *procname;
180 1.1 fvdl char procbuf[32];
181 1.1 fvdl char *progname;
182 1.1 fvdl char progbuf[32];
183 1.1 fvdl char fromname[NI_MAXHOST];
184 1.1 fvdl struct rpcent *rpc;
185 1.1 fvdl static const char *procmap[] = {
186 1.1 fvdl /* RPCBPROC_NULL */ "null",
187 1.1 fvdl /* RPCBPROC_SET */ "set",
188 1.1 fvdl /* RPCBPROC_UNSET */ "unset",
189 1.1 fvdl /* RPCBPROC_GETADDR */ "getport/addr",
190 1.1 fvdl /* RPCBPROC_DUMP */ "dump",
191 1.1 fvdl /* RPCBPROC_CALLIT */ "callit",
192 1.1 fvdl /* RPCBPROC_GETTIME */ "gettime",
193 1.1 fvdl /* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
194 1.1 fvdl /* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
195 1.1 fvdl /* RPCBPROC_GETVERSADDR */ "getversaddr",
196 1.1 fvdl /* RPCBPROC_INDIRECT */ "indirect",
197 1.1 fvdl /* RPCBPROC_GETADDRLIST */ "getaddrlist",
198 1.1 fvdl /* RPCBPROC_GETSTAT */ "getstat"
199 1.1 fvdl };
200 1.1 fvdl
201 1.1 fvdl /*
202 1.1 fvdl * Fork off a process or the portmap daemon might hang while
203 1.1 fvdl * getrpcbynumber() or syslog() does its thing.
204 1.1 fvdl */
205 1.1 fvdl
206 1.1 fvdl if (fork() == 0) {
207 1.1 fvdl setproctitle("logit");
208 1.1 fvdl
209 1.1 fvdl /* Try to map program number to name. */
210 1.1 fvdl
211 1.1 fvdl if (prognum == 0) {
212 1.9 christos progname = __UNCONST("");
213 1.1 fvdl } else if ((rpc = getrpcbynumber((int) prognum))) {
214 1.1 fvdl progname = rpc->r_name;
215 1.1 fvdl } else {
216 1.1 fvdl snprintf(progname = progbuf, sizeof(progbuf), "%u",
217 1.1 fvdl (unsigned)prognum);
218 1.1 fvdl }
219 1.1 fvdl
220 1.1 fvdl /* Try to map procedure number to name. */
221 1.1 fvdl
222 1.8 elad if (procnum >= (sizeof procmap / sizeof (char *))) {
223 1.1 fvdl snprintf(procbuf, sizeof procbuf, "%u",
224 1.1 fvdl (unsigned)procnum);
225 1.1 fvdl procname = procbuf;
226 1.1 fvdl } else
227 1.1 fvdl procname = procmap[procnum];
228 1.1 fvdl
229 1.1 fvdl /* Write syslog record. */
230 1.1 fvdl
231 1.1 fvdl if (addr->sa_family == AF_LOCAL)
232 1.7 itojun strlcpy(fromname, "local", sizeof(fromname));
233 1.1 fvdl else
234 1.1 fvdl getnameinfo(addr, addr->sa_len, fromname,
235 1.1 fvdl sizeof fromname, NULL, 0, NI_NUMERICHOST);
236 1.1 fvdl
237 1.1 fvdl syslog(severity, "connect from %s to %s(%s)%s",
238 1.1 fvdl fromname, procname, progname, text);
239 1.1 fvdl _exit(0);
240 1.1 fvdl }
241 1.1 fvdl }
242 1.1 fvdl
243 1.1 fvdl int
244 1.12 christos check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum __unused)
245 1.1 fvdl {
246 1.1 fvdl struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
247 1.1 fvdl
248 1.1 fvdl /*
249 1.1 fvdl * Always allow calling NULLPROC
250 1.1 fvdl */
251 1.1 fvdl if (args->rmt_proc == 0)
252 1.1 fvdl return 1;
253 1.1 fvdl
254 1.1 fvdl /*
255 1.1 fvdl * XXX - this special casing sucks.
256 1.1 fvdl */
257 1.1 fvdl switch (args->rmt_prog) {
258 1.1 fvdl case RPCBPROG:
259 1.1 fvdl /*
260 1.1 fvdl * Allow indirect calls to ourselves in insecure mode.
261 1.1 fvdl * The is_loopback checks aren't useful then anyway.
262 1.1 fvdl */
263 1.1 fvdl if (!insecure)
264 1.1 fvdl goto deny;
265 1.1 fvdl break;
266 1.1 fvdl case MOUNTPROG:
267 1.1 fvdl if (args->rmt_proc != MOUNTPROC_MNT &&
268 1.1 fvdl args->rmt_proc != MOUNTPROC_UMNT)
269 1.1 fvdl break;
270 1.1 fvdl goto deny;
271 1.1 fvdl case YPBINDPROG:
272 1.1 fvdl if (args->rmt_proc != YPBINDPROC_SETDOM)
273 1.1 fvdl break;
274 1.1 fvdl /* FALLTHROUGH */
275 1.1 fvdl case YPPASSWDPROG:
276 1.1 fvdl case NFS_PROGRAM:
277 1.1 fvdl case RQUOTAPROG:
278 1.1 fvdl goto deny;
279 1.1 fvdl case YPPROG:
280 1.1 fvdl switch (args->rmt_proc) {
281 1.1 fvdl case YPPROC_ALL:
282 1.1 fvdl case YPPROC_MATCH:
283 1.1 fvdl case YPPROC_FIRST:
284 1.1 fvdl case YPPROC_NEXT:
285 1.1 fvdl goto deny;
286 1.1 fvdl default:
287 1.6 cgd break;
288 1.1 fvdl }
289 1.1 fvdl default:
290 1.6 cgd break;
291 1.1 fvdl }
292 1.1 fvdl
293 1.1 fvdl return 1;
294 1.1 fvdl deny:
295 1.12 christos #ifdef LIBWRAP
296 1.1 fvdl logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
297 1.1 fvdl ": indirect call not allowed");
298 1.12 christos #else
299 1.12 christos logit(0, sa, args->rmt_proc, args->rmt_prog,
300 1.12 christos ": indirect call not allowed");
301 1.12 christos #endif
302 1.1 fvdl return 0;
303 1.1 fvdl }
304