summaryrefslogtreecommitdiffstats
path: root/support/misc
diff options
context:
space:
mode:
authorhjl <hjl>2000-08-25 23:10:40 +0000
committerhjl <hjl>2000-08-25 23:10:40 +0000
commit764e46f5c5fe1a6e376f4cd350424f33afc9e838 (patch)
tree29248c861c97d8be3f44e162b062808dca306988 /support/misc
parent25f30caad17b6379a462d567b242e961082e1485 (diff)
downloadnfs-utils-764e46f5c5fe1a6e376f4cd350424f33afc9e838.tar.gz
nfs-utils-764e46f5c5fe1a6e376f4cd350424f33afc9e838.tar.xz
nfs-utils-764e46f5c5fe1a6e376f4cd350424f33afc9e838.zip
2000-08-25 H.J. Lu <hjl@lucon.org>
* support/include/tcpwrapper.h: New for the tcp wrapper support. * support/misc/Makefile: Likewise. * support/misc/from_local.c: Likewise. * support/misc/tcpwrapper.c: Likewise. * aclocal.m4 (AC_TCP_WRAPPER): New. * configure.in: Use it. Substitute LIBWRAP. * configure: Rebuilt. * config.mk.in (LIBNSL): New. (LIBWRAP): Likewise. * support/Makefile (SUBDIRS): Add misc. * support/lib/Makefile (LIBS): Add libmisc.a. * utils/rquotad/Makefile (LIBS): Add -lmisc $(LIBWRAP) $(LIBNSL) * utils/statd/Makefile (LIBS): Likewise. * utils/rquotad/rquota_svc.c: Include "tcpwrapper.h" if HAVE_TCP_WRAPPER is defined. (rquotaprog_1): Call check_default () if HAVE_TCP_WRAPPER is defined. Reject an RPC call if check_default () fails. * utils/statd/statd.c: Include "tcpwrapper.h" if HAVE_TCP_WRAPPER is defined. (sm_prog_1_wrapper): New. A wrapper for sm_prog_1. Call check_default () before calling sm_prog_1 (). Define it as sm_prog_1_wrapper if HAVE_TCP_WRAPPER is defined.
Diffstat (limited to 'support/misc')
-rw-r--r--support/misc/Makefile11
-rw-r--r--support/misc/from_local.c188
-rw-r--r--support/misc/tcpwrapper.c256
3 files changed, 455 insertions, 0 deletions
diff --git a/support/misc/Makefile b/support/misc/Makefile
new file mode 100644
index 0000000..b2f73f8
--- /dev/null
+++ b/support/misc/Makefile
@@ -0,0 +1,11 @@
+#
+# linux-nfs/support/misc/Makefile
+#
+
+LIBNAME = libmisc.a
+OBJS = tcpwrapper.o from_local.o
+
+include $(TOP)rules.mk
+
+install::
+ @:
diff --git a/support/misc/from_local.c b/support/misc/from_local.c
new file mode 100644
index 0000000..56478d7
--- /dev/null
+++ b/support/misc/from_local.c
@@ -0,0 +1,188 @@
+ /*
+ * Check if an address belongs to the local system. Adapted from:
+ *
+ * @(#)pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc.
+ * @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#) from_local.c 1.3 96/05/31 15:52:57";
+#endif
+
+#ifdef TEST
+#undef perror
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+ /*
+ * With virtual hosting, each hardware network interface can have multiple
+ * network addresses. On such machines the number of machine addresses can
+ * be surprisingly large.
+ */
+static int num_local;
+static int num_addrs;
+static struct in_addr *addrs;
+
+/* grow_addrs - extend list of local interface addresses */
+
+static int grow_addrs()
+{
+ struct in_addr *new_addrs;
+ int new_num;
+
+ /*
+ * Keep the previous result if we run out of memory. The system would
+ * really get hosed if we simply give up.
+ */
+ new_num = (addrs == 0) ? 1 : num_addrs + num_addrs;
+ new_addrs = (struct in_addr *) malloc(sizeof(*addrs) * new_num);
+ if (new_addrs == 0) {
+ perror("portmap: out of memory");
+ return (0);
+ } else {
+ if (addrs != 0) {
+ memcpy((char *) new_addrs, (char *) addrs,
+ sizeof(*addrs) * num_addrs);
+ free((char *) addrs);
+ }
+ num_addrs = new_num;
+ addrs = new_addrs;
+ return (1);
+ }
+}
+
+/* find_local - find all IP addresses for this host */
+static int
+find_local()
+{
+ struct ifconf ifc;
+ struct ifreq ifreq;
+ struct ifreq *ifr;
+ struct ifreq *the_end;
+ int sock;
+ char buf[BUFSIZ];
+
+ /*
+ * Get list of network interfaces. We use a huge buffer to allow for the
+ * presence of non-IP interfaces.
+ */
+
+ if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return (0);
+ }
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
+ perror("SIOCGIFCONF");
+ (void) close(sock);
+ return (0);
+ }
+ /* Get IP address of each active IP network interface. */
+
+ the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ num_local = 0;
+ for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
+ if (ifr->ifr_addr.sa_family == AF_INET) { /* IP net interface */
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+ perror("SIOCGIFFLAGS");
+ } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */
+ if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
+ perror("SIOCGIFADDR");
+ } else {
+ if (num_local >= num_addrs)
+ if (grow_addrs() == 0)
+ break;
+ addrs[num_local++] = ((struct sockaddr_in *)
+ & ifreq.ifr_addr)->sin_addr;
+ }
+ }
+ }
+ /* Support for variable-length addresses. */
+#ifdef HAS_SA_LEN
+ ifr = (struct ifreq *) ((caddr_t) ifr
+ + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
+#endif
+ }
+ (void) close(sock);
+ return (num_local);
+}
+
+/* from_local - determine whether request comes from the local system */
+int
+from_local(addr)
+struct sockaddr_in *addr;
+{
+ int i;
+
+ if (addrs == 0 && find_local() == 0)
+ syslog(LOG_ERR, "cannot find any active local network interfaces");
+
+ for (i = 0; i < num_local; i++) {
+ if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
+ sizeof(struct in_addr)) == 0)
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#ifdef TEST
+
+main()
+{
+ char *inet_ntoa();
+ int i;
+
+ find_local();
+ for (i = 0; i < num_local; i++)
+ printf("%s\n", inet_ntoa(addrs[i]));
+}
+
+#endif
diff --git a/support/misc/tcpwrapper.c b/support/misc/tcpwrapper.c
new file mode 100644
index 0000000..498a829
--- /dev/null
+++ b/support/misc/tcpwrapper.c
@@ -0,0 +1,256 @@
+/* This is copied from portmap 4.0-29 in RedHat. */
+
+ /*
+ * pmap_check - additional portmap security.
+ *
+ * Always reject non-local requests to update the portmapper tables.
+ *
+ * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
+ * requests would appear to come from the local system, and nfs export
+ * restrictions could be bypassed.
+ *
+ * Refuse to forward requests to the nfsd process.
+ *
+ * Refuse to forward requests to NIS (YP) daemons; The only exception is the
+ * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
+ * contact with the NIS server.
+ *
+ * Always allocate an unprivileged port when forwarding a request.
+ *
+ * If compiled with -DCHECK_PORT, require that requests to register or
+ * unregister a privileged port come from a privileged port. This makes it
+ * more difficult to replace a critical service by a trojan.
+ *
+ * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
+ * authorized by the /etc/hosts.{allow,deny} files. The local system is
+ * always treated as an authorized host. The access control tables are never
+ * consulted for requests from the local system, and are always consulted
+ * for requests from other hosts. Access control is based on IP addresses
+ * only; attempts to map an address to a host name might cause the
+ * portmapper to hang.
+ *
+ * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+ * Computing Science, Eindhoven University of Technology, The Netherlands.
+ */
+
+#include "tcpwrapper.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#endif
+
+static void logit();
+static void toggle_verboselog();
+int verboselog = 0;
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+
+/* A handful of macros for "readability". */
+
+/* coming from libwrap.a (tcp_wrappers) */
+extern int hosts_ctl(char *daemon, char *name, char *addr, char *user);
+
+#define legal_port(a,p) \
+ (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
+
+#define log_bad_port(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
+
+#define log_bad_host(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
+
+#define log_bad_owner(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from non-local host")
+
+#define log_no_forward(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request not forwarded")
+
+#define log_client(addr, proc, prog) \
+ logit(allow_severity, addr, proc, prog, "")
+
+int
+good_client(daemon, addr)
+char *daemon;
+struct sockaddr_in *addr;
+{
+ struct hostent *hp;
+ char **sp;
+ char *tmpname;
+
+ /* Check the IP address first. */
+ if (hosts_ctl(daemon, "", inet_ntoa(addr->sin_addr), ""))
+ return 1;
+
+ /* Check the hostname. */
+ hp = gethostbyaddr ((const char *) &(addr->sin_addr),
+ sizeof (addr->sin_addr), AF_INET);
+
+ if (!hp)
+ return 0;
+
+ /* must make sure the hostent is authorative. */
+ tmpname = alloca (strlen (hp->h_name) + 1);
+ strcpy (tmpname, hp->h_name);
+ hp = gethostbyname(tmpname);
+ if (hp) {
+ /* now make sure the "addr->sin_addr" is on the list */
+ for (sp = hp->h_addr_list ; *sp ; sp++) {
+ if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0)
+ break;
+ }
+ if (!*sp)
+ /* it was a FAKE. */
+ return 0;
+ }
+ else
+ /* never heard of it. misconfigured DNS? */
+ return 0;
+
+ /* Check the official name first. */
+ if (hosts_ctl(daemon, "", hp->h_name, ""))
+ return 1;
+
+ /* Check aliases. */
+ for (sp = hp->h_aliases; *sp ; sp++) {
+ if (hosts_ctl(daemon, "", *sp, ""))
+ return 1;
+ }
+
+ /* No match */
+ return 0;
+}
+
+/* check_startup - additional startup code */
+
+void check_startup()
+{
+
+ /*
+ * Give up root privileges so that we can never allocate a privileged
+ * port when forwarding an rpc request.
+ *
+ * Fix 8/3/00 Philipp Knirsch: First lookup our rpc user. If we find it,
+ * switch to that uid, otherwise simply resue the old bin user and print
+ * out a warning in syslog.
+ */
+
+ struct passwd *pwent;
+
+ pwent = getpwnam("rpc");
+ if (pwent == NULL) {
+ syslog(LOG_WARNING, "user rpc not found, reverting to user bin");
+ if (setuid(1) == -1) {
+ syslog(LOG_ERR, "setuid(1) failed: %m");
+ exit(1);
+ }
+ }
+ else {
+ if (setuid(pwent->pw_uid) == -1) {
+ syslog(LOG_WARNING, "setuid() to rpc user failed: %m");
+ if (setuid(1) == -1) {
+ syslog(LOG_ERR, "setuid(1) failed: %m");
+ exit(1);
+ }
+ }
+ }
+
+ (void) signal(SIGINT, toggle_verboselog);
+}
+
+/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
+
+int
+check_default(daemon, addr, proc, prog)
+char *daemon;
+struct sockaddr_in *addr;
+u_long proc;
+u_long prog;
+{
+ if (!(from_local(addr) || good_client(daemon, addr))) {
+ log_bad_host(addr, proc, prog);
+ return (FALSE);
+ }
+ if (verboselog)
+ log_client(addr, proc, prog);
+ return (TRUE);
+}
+
+/* check_privileged_port - additional checks for privileged-port updates */
+int
+check_privileged_port(addr, proc, prog, port)
+struct sockaddr_in *addr;
+u_long proc;
+u_long prog;
+u_long port;
+{
+#ifdef CHECK_PORT
+ if (!legal_port(addr, port)) {
+ log_bad_port(addr, proc, prog);
+ return (FALSE);
+ }
+#endif
+ return (TRUE);
+}
+
+/* toggle_verboselog - toggle verbose logging flag */
+
+static void toggle_verboselog(sig)
+int sig;
+{
+ (void) signal(sig, toggle_verboselog);
+ verboselog = !verboselog;
+}
+
+/* logit - report events of interest via the syslog daemon */
+
+static void logit(severity, addr, procnum, prognum, text)
+int severity;
+struct sockaddr_in *addr;
+u_long procnum;
+u_long prognum;
+char *text;
+{
+ char *procname;
+ char procbuf[4 * sizeof(u_long)];
+ char *progname;
+ char progbuf[4 * sizeof(u_long)];
+ struct rpcent *rpc;
+
+ /*
+ * Fork off a process or the portmap daemon might hang while
+ * getrpcbynumber() or syslog() does its thing.
+ */
+
+ if (fork() == 0) {
+
+ /* Try to map program number to name. */
+
+ if (prognum == 0) {
+ progname = "";
+ } else if ((rpc = getrpcbynumber((int) prognum))) {
+ progname = rpc->r_name;
+ } else {
+ sprintf(progname = progbuf, "%lu", prognum);
+ }
+
+ /* Try to map procedure number to name. */
+
+ sprintf(procname = procbuf, "%lu", (u_long) procnum);
+
+ /* Write syslog record. */
+
+ syslog(severity, "connect from %s to %s(%s)%s",
+ inet_ntoa(addr->sin_addr), procname, progname, text);
+ exit(0);
+ }
+}