aboutsummaryrefslogtreecommitdiffstats
path: root/amd/amq_svc.c
diff options
context:
space:
mode:
Diffstat (limited to 'amd/amq_svc.c')
-rw-r--r--amd/amq_svc.c175
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! */
}