home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / security / portmap_3.shar.Z / portmap_3.shar / pmap_check.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  6.6 KB  |  256 lines

  1.  /*
  2.   * pmap_check - additional portmap security.
  3.   * 
  4.   * Always reject non-local requests to update the portmapper tables.
  5.   * 
  6.   * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
  7.   * requests would appear to come from the local system, and nfs export
  8.   * restrictions could be bypassed.
  9.   * 
  10.   * Refuse to forward requests to the nfsd process.
  11.   * 
  12.   * Refuse to forward requests to NIS (YP) daemons; The only exception is the
  13.   * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
  14.   * contact with the NIS server.
  15.   * 
  16.   * Always allocate an unprivileged port when forwarding a request.
  17.   * 
  18.   * If compiled with -DCHECK_PORT, require that requests to register or
  19.   * unregister a privileged port come from a privileged port. This makes it
  20.   * more difficult to replace a critical service by a trojan.
  21.   * 
  22.   * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
  23.   * authorized by the /etc/hosts.{allow,deny} files. The local system is
  24.   * always treated as an authorized host. The access control tables are never
  25.   * consulted for requests from the local system, and are always consulted
  26.   * for requests from other hosts. Access control is based on IP addresses
  27.   * only; attempts to map an address to a host name might cause the
  28.   * portmapper to hang.
  29.   * 
  30.   * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
  31.   * Computing Science, Eindhoven University of Technology, The Netherlands.
  32.   */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#) pmap_check.c 1.6 93/11/21 20:58:59";
  36. #endif
  37.  
  38. #include <rpc/rpc.h>
  39. #include <rpc/pmap_prot.h>
  40. #include <syslog.h>
  41. #include <netdb.h>
  42. #include <sys/signal.h>
  43. #ifdef SYSV40
  44. #include <netinet/in.h>
  45. #include <rpc/rpcent.h>
  46. #endif
  47.  
  48. extern char *inet_ntoa();
  49.  
  50. #include "pmap_check.h"
  51.  
  52. /* Explicit #defines in case the include files are not available. */
  53.  
  54. #define NFSPROG        ((u_long) 100003)
  55. #define MOUNTPROG    ((u_long) 100005)
  56. #define    YPXPROG        ((u_long) 100069)
  57. #define YPPROG          ((u_long) 100004)
  58. #define YPPROC_DOMAIN_NONACK ((u_long) 2)
  59. #define MOUNTPROC_MNT    ((u_long) 1)
  60.  
  61. static void logit();
  62. static void toggle_verboselog();
  63. int     verboselog = 0;
  64. int     allow_severity = LOG_INFO;
  65. int     deny_severity = LOG_WARNING;
  66.  
  67. /* A handful of macros for "readability". */
  68.  
  69. #define    good_client(a) hosts_ctl("portmap", "", inet_ntoa(a->sin_addr), "")
  70.  
  71. #define    legal_port(a,p) \
  72.   (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
  73.  
  74. #define log_bad_port(addr, proc, prog) \
  75.   logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
  76.  
  77. #define log_bad_host(addr, proc, prog) \
  78.   logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
  79.  
  80. #define log_bad_owner(addr, proc, prog) \
  81.   logit(deny_severity, addr, proc, prog, ": request from non-local host")
  82.  
  83. #define    log_no_forward(addr, proc, prog) \
  84.   logit(deny_severity, addr, proc, prog, ": request not forwarded")
  85.  
  86. #define log_client(addr, proc, prog) \
  87.   logit(allow_severity, addr, proc, prog, "")
  88.  
  89. /* check_startup - additional startup code */
  90.  
  91. void    check_startup()
  92. {
  93.  
  94.     /*
  95.      * Give up root privileges so that we can never allocate a privileged
  96.      * port when forwarding an rpc request.
  97.      */
  98.     if (setuid(1) == -1) {
  99.     syslog(LOG_ERR, "setuid(1) failed: %m");
  100.     exit(1);
  101.     }
  102.     (void) signal(SIGINT, toggle_verboselog);
  103. }
  104.  
  105. /* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
  106.  
  107. check_default(addr, proc, prog)
  108. struct sockaddr_in *addr;
  109. u_long  proc;
  110. u_long  prog;
  111. {
  112. #ifdef HOSTS_ACCESS
  113.     if (!(from_local(addr) || good_client(addr))) {
  114.     log_bad_host(addr, proc, prog);
  115.     return (FALSE);
  116.     }
  117. #endif
  118.     if (verboselog)
  119.     log_client(addr, proc, prog);
  120.     return (TRUE);
  121. }
  122.  
  123. /* check_privileged_port - additional checks for privileged-port updates */
  124.  
  125. check_privileged_port(addr, proc, prog, port)
  126. struct sockaddr_in *addr;
  127. u_long  proc;
  128. u_long  prog;
  129. u_long  port;
  130. {
  131. #ifdef CHECK_PORT
  132.     if (!legal_port(addr, port)) {
  133.     log_bad_port(addr, proc, prog);
  134.     return (FALSE);
  135.     }
  136. #endif
  137.     return (TRUE);
  138. }
  139.  
  140. /* check_setunset - additional checks for update requests */
  141.  
  142. check_setunset(addr, proc, prog, port)
  143. struct sockaddr_in *addr;
  144. u_long  proc;
  145. u_long  prog;
  146. u_long  port;
  147. {
  148.     if (!from_local(addr)) {
  149. #ifdef HOSTS_ACCESS
  150.     (void) good_client(addr);        /* because of side effects */
  151. #endif
  152.     log_bad_owner(addr, proc, prog);
  153.     return (FALSE);
  154.     }
  155.     if (port && !check_privileged_port(addr, proc, prog, port))
  156.     return (FALSE);
  157.     if (verboselog)
  158.     log_client(addr, proc, prog);
  159.     return (TRUE);
  160. }
  161.  
  162. /* check_callit - additional checks for forwarded requests */
  163.  
  164. check_callit(addr, proc, prog, aproc)
  165. struct sockaddr_in *addr;
  166. u_long  proc;
  167. u_long  prog;
  168. u_long  aproc;
  169. {
  170. #ifdef HOSTS_ACCESS
  171.     if (!(from_local(addr) || good_client(addr))) {
  172.     log_bad_host(addr, proc, prog);
  173.     return (FALSE);
  174.     }
  175. #endif
  176.     if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
  177.     (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
  178.     (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
  179.     log_no_forward(addr, proc, prog);
  180.     return (FALSE);
  181.     }
  182.     if (verboselog)
  183.     log_client(addr, proc, prog);
  184.     return (TRUE);
  185. }
  186.  
  187. /* toggle_verboselog - toggle verbose logging flag */
  188.  
  189. static void toggle_verboselog(sig)
  190. int     sig;
  191. {
  192.     (void) signal(sig, toggle_verboselog);
  193.     verboselog = !verboselog;
  194. }
  195.  
  196. /* logit - report events of interest via the syslog daemon */
  197.  
  198. static void logit(severity, addr, procnum, prognum, text)
  199. int     severity;
  200. struct sockaddr_in *addr;
  201. u_long  procnum;
  202. u_long  prognum;
  203. char   *text;
  204. {
  205.     char   *procname;
  206.     char    procbuf[4 * sizeof(u_long)];
  207.     char   *progname;
  208.     char    progbuf[4 * sizeof(u_long)];
  209.     struct rpcent *rpc;
  210.     struct proc_map {
  211.     u_long  code;
  212.     char   *proc;
  213.     };
  214.     struct proc_map *procp;
  215.     static struct proc_map procmap[] = {
  216.     PMAPPROC_CALLIT, "callit",
  217.     PMAPPROC_DUMP, "dump",
  218.     PMAPPROC_GETPORT, "getport",
  219.     PMAPPROC_NULL, "null",
  220.     PMAPPROC_SET, "set",
  221.     PMAPPROC_UNSET, "unset",
  222.     0, 0,
  223.     };
  224.  
  225.     /*
  226.      * Fork off a process or the portmap daemon might hang while
  227.      * getrpcbynumber() or syslog() does its thing.
  228.      */
  229.  
  230.     if (fork() == 0) {
  231.  
  232.     /* Try to map program number to name. */
  233.  
  234.     if (prognum == 0) {
  235.         progname = "";
  236.     } else if (rpc = getrpcbynumber((int) prognum)) {
  237.         progname = rpc->r_name;
  238.     } else {
  239.         sprintf(progname = progbuf, "%lu", prognum);
  240.     }
  241.  
  242.     /* Try to map procedure number to name. */
  243.  
  244.     for (procp = procmap; procp->proc && procp->code != procnum; procp++)
  245.          /* void */ ;
  246.     if ((procname = procp->proc) == 0)
  247.         sprintf(procname = procbuf, "%lu", (u_long) procnum);
  248.  
  249.     /* Write syslog record. */
  250.  
  251.     syslog(severity, "connect from %s to %s(%s)%s",
  252.            inet_ntoa(addr->sin_addr), procname, progname, text);
  253.     exit(0);
  254.     }
  255. }
  256.