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