1*8bae5d40Schristos /* $NetBSD: amq_svc.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $ */
2a53f50b9Schristos
3a53f50b9Schristos /*
4*8bae5d40Schristos * Copyright (c) 1997-2014 Erez Zadok
5a53f50b9Schristos * Copyright (c) 1990 Jan-Simon Pendry
6a53f50b9Schristos * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7a53f50b9Schristos * Copyright (c) 1990 The Regents of the University of California.
8a53f50b9Schristos * All rights reserved.
9a53f50b9Schristos *
10a53f50b9Schristos * This code is derived from software contributed to Berkeley by
11a53f50b9Schristos * Jan-Simon Pendry at Imperial College, London.
12a53f50b9Schristos *
13a53f50b9Schristos * Redistribution and use in source and binary forms, with or without
14a53f50b9Schristos * modification, are permitted provided that the following conditions
15a53f50b9Schristos * are met:
16a53f50b9Schristos * 1. Redistributions of source code must retain the above copyright
17a53f50b9Schristos * notice, this list of conditions and the following disclaimer.
18a53f50b9Schristos * 2. Redistributions in binary form must reproduce the above copyright
19a53f50b9Schristos * notice, this list of conditions and the following disclaimer in the
20a53f50b9Schristos * documentation and/or other materials provided with the distribution.
21*8bae5d40Schristos * 3. Neither the name of the University nor the names of its contributors
22a53f50b9Schristos * may be used to endorse or promote products derived from this software
23a53f50b9Schristos * without specific prior written permission.
24a53f50b9Schristos *
25a53f50b9Schristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26a53f50b9Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27a53f50b9Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28a53f50b9Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29a53f50b9Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30a53f50b9Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31a53f50b9Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32a53f50b9Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33a53f50b9Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34a53f50b9Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35a53f50b9Schristos * SUCH DAMAGE.
36a53f50b9Schristos *
37a53f50b9Schristos *
38a53f50b9Schristos * File: am-utils/amd/amq_svc.c
39a53f50b9Schristos *
40a53f50b9Schristos */
41a53f50b9Schristos
42a53f50b9Schristos #ifdef HAVE_CONFIG_H
43a53f50b9Schristos # include <config.h>
44a53f50b9Schristos #endif /* HAVE_CONFIG_H */
45a53f50b9Schristos #include <am_defs.h>
46a53f50b9Schristos #include <amd.h>
47a53f50b9Schristos
48a53f50b9Schristos /* typedefs */
49a53f50b9Schristos typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
50a53f50b9Schristos
51a53f50b9Schristos #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
52a53f50b9Schristos # ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
53a53f50b9Schristos /*
54a53f50b9Schristos * Some systems that define libwrap already define these two variables
55a53f50b9Schristos * in libwrap, while others don't: so I need to know precisely iff
56a53f50b9Schristos * to define these two severity variables.
57a53f50b9Schristos */
58a53f50b9Schristos int allow_severity=0, deny_severity=0, rfc931_timeout=0;
59a53f50b9Schristos # endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
60a53f50b9Schristos
61a53f50b9Schristos /*
62a53f50b9Schristos * check if remote amq is authorized to access this amd.
63a53f50b9Schristos * Returns: 1=allowed, 0=denied.
64a53f50b9Schristos */
65a53f50b9Schristos static int
amqsvc_is_client_allowed(const struct sockaddr_in * addr)66*8bae5d40Schristos amqsvc_is_client_allowed(const struct sockaddr_in *addr)
67a53f50b9Schristos {
68*8bae5d40Schristos struct request_info req;
69a53f50b9Schristos
70*8bae5d40Schristos request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0);
71*8bae5d40Schristos sock_methods(&req);
72a53f50b9Schristos
73*8bae5d40Schristos if (hosts_access(&req))
74*8bae5d40Schristos return 1;
75*8bae5d40Schristos
76*8bae5d40Schristos return 0;
77a53f50b9Schristos }
78a53f50b9Schristos #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
79a53f50b9Schristos
80a53f50b9Schristos
814bcd344eSchristos /*
824bcd344eSchristos * Prepare the parent and child:
834bcd344eSchristos * 1) Setup IPC pipe.
844bcd344eSchristos * 2) Set signal masks.
854bcd344eSchristos * 3) Fork by calling background() so that NumChildren is updated.
864bcd344eSchristos */
874bcd344eSchristos static int
amq_fork(opaque_t argp)884bcd344eSchristos amq_fork(opaque_t argp)
894bcd344eSchristos {
904bcd344eSchristos #ifdef HAVE_SIGACTION
914bcd344eSchristos sigset_t new, mask;
924bcd344eSchristos #else /* not HAVE_SIGACTION */
934bcd344eSchristos int mask;
944bcd344eSchristos #endif /* not HAVE_SIGACTION */
954bcd344eSchristos am_node *mp;
964bcd344eSchristos pid_t pid;
974bcd344eSchristos
984bcd344eSchristos mp = find_ap(*(char **) argp);
994bcd344eSchristos if (mp == NULL) {
1004bcd344eSchristos errno = 0;
1014bcd344eSchristos return -1;
1024bcd344eSchristos }
1034bcd344eSchristos
1044bcd344eSchristos if (pipe(mp->am_fd) == -1) {
1054bcd344eSchristos mp->am_fd[0] = -1;
1064bcd344eSchristos mp->am_fd[1] = -1;
1074bcd344eSchristos return -1;
1084bcd344eSchristos }
1094bcd344eSchristos
1104bcd344eSchristos #ifdef HAVE_SIGACTION
1114bcd344eSchristos sigemptyset(&new); /* initialize signal set we wish to block */
1124bcd344eSchristos sigaddset(&new, SIGHUP);
1134bcd344eSchristos sigaddset(&new, SIGINT);
1144bcd344eSchristos sigaddset(&new, SIGQUIT);
1154bcd344eSchristos sigaddset(&new, SIGCHLD);
1164bcd344eSchristos sigprocmask(SIG_BLOCK, &new, &mask);
1174bcd344eSchristos #else /* not HAVE_SIGACTION */
1184bcd344eSchristos mask =
1194bcd344eSchristos sigmask(SIGHUP) |
1204bcd344eSchristos sigmask(SIGINT) |
1214bcd344eSchristos sigmask(SIGQUIT) |
1224bcd344eSchristos sigmask(SIGCHLD);
1234bcd344eSchristos mask = sigblock(mask);
1244bcd344eSchristos #endif /* not HAVE_SIGACTION */
1254bcd344eSchristos
1264bcd344eSchristos switch ((pid = background())) {
1274bcd344eSchristos case -1: /* error */
1284bcd344eSchristos dlog("amq_fork failed");
1294bcd344eSchristos return -1;
1304bcd344eSchristos
1314bcd344eSchristos case 0: /* child */
1324bcd344eSchristos close(mp->am_fd[1]); /* close output end of pipe */
1334bcd344eSchristos mp->am_fd[1] = -1;
1344bcd344eSchristos return 0;
1354bcd344eSchristos
1364bcd344eSchristos default: /* parent */
1374bcd344eSchristos close(mp->am_fd[0]); /* close input end of pipe */
1384bcd344eSchristos mp->am_fd[0] = -1;
1394bcd344eSchristos
1404bcd344eSchristos #ifdef HAVE_SIGACTION
1414bcd344eSchristos sigprocmask(SIG_SETMASK, &mask, NULL);
1424bcd344eSchristos #else /* not HAVE_SIGACTION */
1434bcd344eSchristos sigsetmask(mask);
1444bcd344eSchristos #endif /* not HAVE_SIGACTION */
1454bcd344eSchristos return pid;
1464bcd344eSchristos }
1474bcd344eSchristos }
1484bcd344eSchristos
1494bcd344eSchristos
150a53f50b9Schristos void
amq_program_1(struct svc_req * rqstp,SVCXPRT * transp)151a53f50b9Schristos amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
152a53f50b9Schristos {
153a53f50b9Schristos union {
154a53f50b9Schristos amq_string amqproc_mnttree_1_arg;
155a53f50b9Schristos amq_string amqproc_umnt_1_arg;
156a53f50b9Schristos amq_setopt amqproc_setopt_1_arg;
157a53f50b9Schristos } argument;
158a53f50b9Schristos char *result;
159a53f50b9Schristos xdrproc_t xdr_argument, xdr_result;
160a53f50b9Schristos amqsvcproc_t local;
1614bcd344eSchristos amqsvcproc_t child;
1624bcd344eSchristos amqsvcproc_t parent;
1634bcd344eSchristos pid_t pid;
164a53f50b9Schristos
165a53f50b9Schristos #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
166a53f50b9Schristos if (gopt.flags & CFM_USE_TCPWRAPPERS) {
167a53f50b9Schristos struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt);
168a53f50b9Schristos char *remote_hostname = inet_ntoa(remote_addr->sin_addr);
169a53f50b9Schristos
170*8bae5d40Schristos if (!amqsvc_is_client_allowed(remote_addr)) {
171a53f50b9Schristos plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
172a53f50b9Schristos svcerr_auth(transp, AUTH_FAILED);
173a53f50b9Schristos return;
174a53f50b9Schristos } else {
175a53f50b9Schristos dlog("Amd allowed remote amq service to %s", remote_hostname);
176a53f50b9Schristos }
177a53f50b9Schristos }
178a53f50b9Schristos #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
179a53f50b9Schristos
1804bcd344eSchristos local = NULL;
1814bcd344eSchristos child = NULL;
1824bcd344eSchristos parent = NULL;
1834bcd344eSchristos
184a53f50b9Schristos switch (rqstp->rq_proc) {
185a53f50b9Schristos
186a53f50b9Schristos case AMQPROC_NULL:
187a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
188a53f50b9Schristos xdr_result = (xdrproc_t) xdr_void;
189a53f50b9Schristos local = (amqsvcproc_t) amqproc_null_1_svc;
190a53f50b9Schristos break;
191a53f50b9Schristos
192a53f50b9Schristos case AMQPROC_MNTTREE:
193a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_amq_string;
194a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_mount_tree_p;
195a53f50b9Schristos local = (amqsvcproc_t) amqproc_mnttree_1_svc;
196a53f50b9Schristos break;
197a53f50b9Schristos
198a53f50b9Schristos case AMQPROC_UMNT:
199a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_amq_string;
200a53f50b9Schristos xdr_result = (xdrproc_t) xdr_void;
201a53f50b9Schristos local = (amqsvcproc_t) amqproc_umnt_1_svc;
202a53f50b9Schristos break;
203a53f50b9Schristos
204a53f50b9Schristos case AMQPROC_STATS:
205a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
206a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_mount_stats;
207a53f50b9Schristos local = (amqsvcproc_t) amqproc_stats_1_svc;
208a53f50b9Schristos break;
209a53f50b9Schristos
210a53f50b9Schristos case AMQPROC_EXPORT:
211a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
212a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_mount_tree_list;
213a53f50b9Schristos local = (amqsvcproc_t) amqproc_export_1_svc;
214a53f50b9Schristos break;
215a53f50b9Schristos
216a53f50b9Schristos case AMQPROC_SETOPT:
217a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_amq_setopt;
218a53f50b9Schristos xdr_result = (xdrproc_t) xdr_int;
219a53f50b9Schristos local = (amqsvcproc_t) amqproc_setopt_1_svc;
220a53f50b9Schristos break;
221a53f50b9Schristos
222a53f50b9Schristos case AMQPROC_GETMNTFS:
223a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
224a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_mount_info_qelem;
225a53f50b9Schristos local = (amqsvcproc_t) amqproc_getmntfs_1_svc;
226a53f50b9Schristos break;
227a53f50b9Schristos
228a53f50b9Schristos case AMQPROC_GETVERS:
229a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
230a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_string;
231a53f50b9Schristos local = (amqsvcproc_t) amqproc_getvers_1_svc;
232a53f50b9Schristos break;
233a53f50b9Schristos
234a53f50b9Schristos case AMQPROC_GETPID:
235a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_void;
236a53f50b9Schristos xdr_result = (xdrproc_t) xdr_int;
237a53f50b9Schristos local = (amqsvcproc_t) amqproc_getpid_1_svc;
238a53f50b9Schristos break;
239a53f50b9Schristos
240a53f50b9Schristos case AMQPROC_PAWD:
241a53f50b9Schristos xdr_argument = (xdrproc_t) xdr_amq_string;
242a53f50b9Schristos xdr_result = (xdrproc_t) xdr_amq_string;
243a53f50b9Schristos local = (amqsvcproc_t) amqproc_pawd_1_svc;
244a53f50b9Schristos break;
245a53f50b9Schristos
2464bcd344eSchristos case AMQPROC_SYNC_UMNT:
2474bcd344eSchristos xdr_argument = (xdrproc_t) xdr_amq_string;
2484bcd344eSchristos xdr_result = (xdrproc_t) xdr_amq_sync_umnt;
2494bcd344eSchristos parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent;
2504bcd344eSchristos child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child;
2514bcd344eSchristos /* used if fork fails */
2524bcd344eSchristos local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async;
2534bcd344eSchristos break;
2544bcd344eSchristos
255*8bae5d40Schristos case AMQPROC_GETMAPINFO:
256*8bae5d40Schristos xdr_argument = (xdrproc_t) xdr_void;
257*8bae5d40Schristos xdr_result = (xdrproc_t) xdr_amq_map_info_qelem;
258*8bae5d40Schristos local = (amqsvcproc_t) amqproc_getmapinfo_1_svc;
259*8bae5d40Schristos break;
260*8bae5d40Schristos
261a53f50b9Schristos default:
262a53f50b9Schristos svcerr_noproc(transp);
263a53f50b9Schristos return;
264a53f50b9Schristos }
265a53f50b9Schristos
266a53f50b9Schristos memset((char *) &argument, 0, sizeof(argument));
267a53f50b9Schristos if (!svc_getargs(transp,
268a53f50b9Schristos (XDRPROC_T_TYPE) xdr_argument,
269a53f50b9Schristos (SVC_IN_ARG_TYPE) & argument)) {
270a53f50b9Schristos svcerr_decode(transp);
271a53f50b9Schristos return;
272a53f50b9Schristos }
273a53f50b9Schristos
2744bcd344eSchristos pid = -1;
2754bcd344eSchristos result = NULL;
2764bcd344eSchristos
2774bcd344eSchristos if (child) {
2784bcd344eSchristos switch ((pid = amq_fork(&argument))) {
2794bcd344eSchristos case -1: /* error */
2804bcd344eSchristos break;
2814bcd344eSchristos
2824bcd344eSchristos case 0: /* child */
2834bcd344eSchristos result = (*child) (&argument, rqstp);
2844bcd344eSchristos local = NULL;
2854bcd344eSchristos break;
2864bcd344eSchristos
2874bcd344eSchristos default: /* parent */
2884bcd344eSchristos result = (*parent) (&argument, rqstp);
2894bcd344eSchristos local = NULL;
2904bcd344eSchristos break;
2914bcd344eSchristos }
2924bcd344eSchristos }
2934bcd344eSchristos
2944bcd344eSchristos if (local)
295a53f50b9Schristos result = (*local) (&argument, rqstp);
296a53f50b9Schristos
297a53f50b9Schristos if (result != NULL && !svc_sendreply(transp,
298a53f50b9Schristos (XDRPROC_T_TYPE) xdr_result,
299a53f50b9Schristos result)) {
300a53f50b9Schristos svcerr_systemerr(transp);
301a53f50b9Schristos }
302a53f50b9Schristos
303a53f50b9Schristos if (!svc_freeargs(transp,
304a53f50b9Schristos (XDRPROC_T_TYPE) xdr_argument,
305a53f50b9Schristos (SVC_IN_ARG_TYPE) & argument)) {
306a53f50b9Schristos plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
307a53f50b9Schristos going_down(1);
308a53f50b9Schristos }
3094bcd344eSchristos
3104bcd344eSchristos if (pid == 0)
3114bcd344eSchristos exit(0); /* the child is done! */
312a53f50b9Schristos }
313