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