xref: /netbsd/external/bsd/am-utils/dist/amd/amq_svc.c (revision 31bdb48a)
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
amqsvc_is_client_allowed(const struct sockaddr_in * addr)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
amq_fork(opaque_t argp)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
amq_program_1(struct svc_req * rqstp,SVCXPRT * transp)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