diff options
Diffstat (limited to 'amd/amq_svc.c')
-rw-r--r-- | amd/amq_svc.c | 175 |
1 files changed, 128 insertions, 47 deletions
diff --git a/amd/amq_svc.c b/amd/amq_svc.c index 6fadb160c121..1f2b3d6ff8d9 100644 --- a/amd/amq_svc.c +++ b/amd/amq_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -57,7 +53,7 @@ typedef char *(*amqsvcproc_t)(voidp, struct svc_req *); * in libwrap, while others don't: so I need to know precisely iff * to define these two severity variables. */ -int allow_severity=0, deny_severity=0; +int allow_severity=0, deny_severity=0, rfc931_timeout=0; # endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */ /* @@ -65,49 +61,88 @@ int allow_severity=0, deny_severity=0; * Returns: 1=allowed, 0=denied. */ static int -amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote) +amqsvc_is_client_allowed(const struct sockaddr_in *addr) { - struct hostent *h; - char *name = NULL, **ad; - int ret = 0; /* default is 0==denied */ - - /* Check IP address */ - if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) { - ret = 1; - goto out; + struct request_info req; + + request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0); + sock_methods(&req); + + if (hosts_access(&req)) + return 1; + + return 0; +} +#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ + + +/* + * Prepare the parent and child: + * 1) Setup IPC pipe. + * 2) Set signal masks. + * 3) Fork by calling background() so that NumChildren is updated. + */ +static int +amq_fork(opaque_t argp) +{ +#ifdef HAVE_SIGACTION + sigset_t new, mask; +#else /* not HAVE_SIGACTION */ + int mask; +#endif /* not HAVE_SIGACTION */ + am_node *mp; + pid_t pid; + + mp = find_ap(*(char **) argp); + if (mp == NULL) { + errno = 0; + return -1; } - /* Get address */ - if (!(h = gethostbyaddr((const char *)&(addr->sin_addr), - sizeof(addr->sin_addr), - AF_INET))) - goto out; - if (!(name = strdup(h->h_name))) - goto out; - /* Paranoia check */ - if (!(h = gethostbyname(name))) - goto out; - for (ad = h->h_addr_list; *ad; ad++) - if (!memcmp(*ad, &(addr->sin_addr), h->h_length)) - break; - if (!*ad) - goto out; - if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) { - return 1; - goto out; + + if (pipe(mp->am_fd) == -1) { + mp->am_fd[0] = -1; + mp->am_fd[1] = -1; + return -1; } - /* Check aliases */ - for (ad = h->h_aliases; *ad; ad++) - if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) { - return 1; - goto out; - } - out: - if (name) - XFREE(name); - return ret; +#ifdef HAVE_SIGACTION + sigemptyset(&new); /* initialize signal set we wish to block */ + sigaddset(&new, SIGHUP); + sigaddset(&new, SIGINT); + sigaddset(&new, SIGQUIT); + sigaddset(&new, SIGCHLD); + sigprocmask(SIG_BLOCK, &new, &mask); +#else /* not HAVE_SIGACTION */ + mask = + sigmask(SIGHUP) | + sigmask(SIGINT) | + sigmask(SIGQUIT) | + sigmask(SIGCHLD); + mask = sigblock(mask); +#endif /* not HAVE_SIGACTION */ + + switch ((pid = background())) { + case -1: /* error */ + dlog("amq_fork failed"); + return -1; + + case 0: /* child */ + close(mp->am_fd[1]); /* close output end of pipe */ + mp->am_fd[1] = -1; + return 0; + + default: /* parent */ + close(mp->am_fd[0]); /* close input end of pipe */ + mp->am_fd[0] = -1; + +#ifdef HAVE_SIGACTION + sigprocmask(SIG_SETMASK, &mask, NULL); +#else /* not HAVE_SIGACTION */ + sigsetmask(mask); +#endif /* not HAVE_SIGACTION */ + return pid; + } } -#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ void @@ -121,13 +156,16 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) char *result; xdrproc_t xdr_argument, xdr_result; amqsvcproc_t local; + amqsvcproc_t child; + amqsvcproc_t parent; + pid_t pid; #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) if (gopt.flags & CFM_USE_TCPWRAPPERS) { struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt); char *remote_hostname = inet_ntoa(remote_addr->sin_addr); - if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) { + if (!amqsvc_is_client_allowed(remote_addr)) { plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); svcerr_auth(transp, AUTH_FAILED); return; @@ -137,6 +175,10 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) } #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ + local = NULL; + child = NULL; + parent = NULL; + switch (rqstp->rq_proc) { case AMQPROC_NULL: @@ -199,6 +241,21 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) local = (amqsvcproc_t) amqproc_pawd_1_svc; break; + case AMQPROC_SYNC_UMNT: + xdr_argument = (xdrproc_t) xdr_amq_string; + xdr_result = (xdrproc_t) xdr_amq_sync_umnt; + parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent; + child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child; + /* used if fork fails */ + local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async; + break; + + case AMQPROC_GETMAPINFO: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_amq_map_info_qelem; + local = (amqsvcproc_t) amqproc_getmapinfo_1_svc; + break; + default: svcerr_noproc(transp); return; @@ -212,7 +269,28 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) return; } - result = (*local) (&argument, rqstp); + pid = -1; + result = NULL; + + if (child) { + switch ((pid = amq_fork(&argument))) { + case -1: /* error */ + break; + + case 0: /* child */ + result = (*child) (&argument, rqstp); + local = NULL; + break; + + default: /* parent */ + result = (*parent) (&argument, rqstp); + local = NULL; + break; + } + } + + if (local) + result = (*local) (&argument, rqstp); if (result != NULL && !svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, @@ -226,4 +304,7 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1"); going_down(1); } + + if (pid == 0) + exit(0); /* the child is done! */ } |