1 /* $NetBSD: amq_svc.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2014 Erez Zadok 5 * Copyright (c) 1990 Jan-Simon Pendry 6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry at Imperial College, London. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * 38 * File: am-utils/amd/amq_svc.c 39 * 40 */ 41 42 #ifdef HAVE_CONFIG_H 43 # include <config.h> 44 #endif /* HAVE_CONFIG_H */ 45 #include <am_defs.h> 46 #include <amd.h> 47 48 /* typedefs */ 49 typedef char *(*amqsvcproc_t)(voidp, struct svc_req *); 50 51 #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) 52 # ifdef NEED_LIBWRAP_SEVERITY_VARIABLES 53 /* 54 * Some systems that define libwrap already define these two variables 55 * in libwrap, while others don't: so I need to know precisely iff 56 * to define these two severity variables. 57 */ 58 int allow_severity=0, deny_severity=0, rfc931_timeout=0; 59 # endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */ 60 61 /* 62 * check if remote amq is authorized to access this amd. 63 * Returns: 1=allowed, 0=denied. 64 */ 65 static int 66 amqsvc_is_client_allowed(const struct sockaddr_in *addr) 67 { 68 struct request_info req; 69 70 request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0); 71 sock_methods(&req); 72 73 if (hosts_access(&req)) 74 return 1; 75 76 return 0; 77 } 78 #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ 79 80 81 /* 82 * Prepare the parent and child: 83 * 1) Setup IPC pipe. 84 * 2) Set signal masks. 85 * 3) Fork by calling background() so that NumChildren is updated. 86 */ 87 static int 88 amq_fork(opaque_t argp) 89 { 90 #ifdef HAVE_SIGACTION 91 sigset_t new, mask; 92 #else /* not HAVE_SIGACTION */ 93 int mask; 94 #endif /* not HAVE_SIGACTION */ 95 am_node *mp; 96 pid_t pid; 97 98 mp = find_ap(*(char **) argp); 99 if (mp == NULL) { 100 errno = 0; 101 return -1; 102 } 103 104 if (pipe(mp->am_fd) == -1) { 105 mp->am_fd[0] = -1; 106 mp->am_fd[1] = -1; 107 return -1; 108 } 109 110 #ifdef HAVE_SIGACTION 111 sigemptyset(&new); /* initialize signal set we wish to block */ 112 sigaddset(&new, SIGHUP); 113 sigaddset(&new, SIGINT); 114 sigaddset(&new, SIGQUIT); 115 sigaddset(&new, SIGCHLD); 116 sigprocmask(SIG_BLOCK, &new, &mask); 117 #else /* not HAVE_SIGACTION */ 118 mask = 119 sigmask(SIGHUP) | 120 sigmask(SIGINT) | 121 sigmask(SIGQUIT) | 122 sigmask(SIGCHLD); 123 mask = sigblock(mask); 124 #endif /* not HAVE_SIGACTION */ 125 126 switch ((pid = background())) { 127 case -1: /* error */ 128 dlog("amq_fork failed"); 129 return -1; 130 131 case 0: /* child */ 132 close(mp->am_fd[1]); /* close output end of pipe */ 133 mp->am_fd[1] = -1; 134 return 0; 135 136 default: /* parent */ 137 close(mp->am_fd[0]); /* close input end of pipe */ 138 mp->am_fd[0] = -1; 139 140 #ifdef HAVE_SIGACTION 141 sigprocmask(SIG_SETMASK, &mask, NULL); 142 #else /* not HAVE_SIGACTION */ 143 sigsetmask(mask); 144 #endif /* not HAVE_SIGACTION */ 145 return pid; 146 } 147 } 148 149 150 void 151 amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) 152 { 153 union { 154 amq_string amqproc_mnttree_1_arg; 155 amq_string amqproc_umnt_1_arg; 156 amq_setopt amqproc_setopt_1_arg; 157 } argument; 158 char *result; 159 xdrproc_t xdr_argument, xdr_result; 160 amqsvcproc_t local; 161 amqsvcproc_t child; 162 amqsvcproc_t parent; 163 pid_t pid; 164 165 #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) 166 if (gopt.flags & CFM_USE_TCPWRAPPERS) { 167 struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt); 168 char *remote_hostname = inet_ntoa(remote_addr->sin_addr); 169 170 if (!amqsvc_is_client_allowed(remote_addr)) { 171 plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); 172 svcerr_auth(transp, AUTH_FAILED); 173 return; 174 } else { 175 dlog("Amd allowed remote amq service to %s", remote_hostname); 176 } 177 } 178 #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ 179 180 local = NULL; 181 child = NULL; 182 parent = NULL; 183 184 switch (rqstp->rq_proc) { 185 186 case AMQPROC_NULL: 187 xdr_argument = (xdrproc_t) xdr_void; 188 xdr_result = (xdrproc_t) xdr_void; 189 local = (amqsvcproc_t) amqproc_null_1_svc; 190 break; 191 192 case AMQPROC_MNTTREE: 193 xdr_argument = (xdrproc_t) xdr_amq_string; 194 xdr_result = (xdrproc_t) xdr_amq_mount_tree_p; 195 local = (amqsvcproc_t) amqproc_mnttree_1_svc; 196 break; 197 198 case AMQPROC_UMNT: 199 xdr_argument = (xdrproc_t) xdr_amq_string; 200 xdr_result = (xdrproc_t) xdr_void; 201 local = (amqsvcproc_t) amqproc_umnt_1_svc; 202 break; 203 204 case AMQPROC_STATS: 205 xdr_argument = (xdrproc_t) xdr_void; 206 xdr_result = (xdrproc_t) xdr_amq_mount_stats; 207 local = (amqsvcproc_t) amqproc_stats_1_svc; 208 break; 209 210 case AMQPROC_EXPORT: 211 xdr_argument = (xdrproc_t) xdr_void; 212 xdr_result = (xdrproc_t) xdr_amq_mount_tree_list; 213 local = (amqsvcproc_t) amqproc_export_1_svc; 214 break; 215 216 case AMQPROC_SETOPT: 217 xdr_argument = (xdrproc_t) xdr_amq_setopt; 218 xdr_result = (xdrproc_t) xdr_int; 219 local = (amqsvcproc_t) amqproc_setopt_1_svc; 220 break; 221 222 case AMQPROC_GETMNTFS: 223 xdr_argument = (xdrproc_t) xdr_void; 224 xdr_result = (xdrproc_t) xdr_amq_mount_info_qelem; 225 local = (amqsvcproc_t) amqproc_getmntfs_1_svc; 226 break; 227 228 case AMQPROC_GETVERS: 229 xdr_argument = (xdrproc_t) xdr_void; 230 xdr_result = (xdrproc_t) xdr_amq_string; 231 local = (amqsvcproc_t) amqproc_getvers_1_svc; 232 break; 233 234 case AMQPROC_GETPID: 235 xdr_argument = (xdrproc_t) xdr_void; 236 xdr_result = (xdrproc_t) xdr_int; 237 local = (amqsvcproc_t) amqproc_getpid_1_svc; 238 break; 239 240 case AMQPROC_PAWD: 241 xdr_argument = (xdrproc_t) xdr_amq_string; 242 xdr_result = (xdrproc_t) xdr_amq_string; 243 local = (amqsvcproc_t) amqproc_pawd_1_svc; 244 break; 245 246 case AMQPROC_SYNC_UMNT: 247 xdr_argument = (xdrproc_t) xdr_amq_string; 248 xdr_result = (xdrproc_t) xdr_amq_sync_umnt; 249 parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent; 250 child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child; 251 /* used if fork fails */ 252 local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async; 253 break; 254 255 case AMQPROC_GETMAPINFO: 256 xdr_argument = (xdrproc_t) xdr_void; 257 xdr_result = (xdrproc_t) xdr_amq_map_info_qelem; 258 local = (amqsvcproc_t) amqproc_getmapinfo_1_svc; 259 break; 260 261 default: 262 svcerr_noproc(transp); 263 return; 264 } 265 266 memset((char *) &argument, 0, sizeof(argument)); 267 if (!svc_getargs(transp, 268 (XDRPROC_T_TYPE) xdr_argument, 269 (SVC_IN_ARG_TYPE) & argument)) { 270 svcerr_decode(transp); 271 return; 272 } 273 274 pid = -1; 275 result = NULL; 276 277 if (child) { 278 switch ((pid = amq_fork(&argument))) { 279 case -1: /* error */ 280 break; 281 282 case 0: /* child */ 283 result = (*child) (&argument, rqstp); 284 local = NULL; 285 break; 286 287 default: /* parent */ 288 result = (*parent) (&argument, rqstp); 289 local = NULL; 290 break; 291 } 292 } 293 294 if (local) 295 result = (*local) (&argument, rqstp); 296 297 if (result != NULL && !svc_sendreply(transp, 298 (XDRPROC_T_TYPE) xdr_result, 299 result)) { 300 svcerr_systemerr(transp); 301 } 302 303 if (!svc_freeargs(transp, 304 (XDRPROC_T_TYPE) xdr_argument, 305 (SVC_IN_ARG_TYPE) & argument)) { 306 plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1"); 307 going_down(1); 308 } 309 310 if (pid == 0) 311 exit(0); /* the child is done! */ 312 } 313