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