Home | History | Annotate | Line # | Download | only in amd
      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