proposed patch to rpcbind to provide finer-grained security controls than offered by the -i option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

The current rpcbind -i option seems to relax 3 different security requirements.
If the user wants to allow any one of the three, he is forced to allow
all 3.

The attached patch introduces 3 new options (-c, -r, and -u) to break this
down to give the user control of which security requirements to relax.

This patch compiles, but has not been tested yet.  If there is any
interest in accepting this, I will of course test it. :-)  But it's fairly
basic, so I thought I'd gauge the interest level first.  Steve
Dickson from Redhat suggested that I post here to discuss this issue
regarding https://bugzilla.redhat.com/show_bug.cgi?id=481422

Thank you for considering this.  I do not follow this list, so apologize
in advance if this email violates any conventions or protocols.

Regards,
Andy
diff -up rpcbind-0.2.0/src/rpcbind.c.orig rpcbind-0.2.0/src/rpcbind.c
--- rpcbind-0.2.0/src/rpcbind.c.orig	2009-05-29 09:38:22.000000000 -0400
+++ rpcbind-0.2.0/src/rpcbind.c	2010-12-09 15:39:14.459781896 -0500
@@ -92,8 +92,9 @@ char *rpcbinduser = NULL;
 #define RPCBINDDLOCK "/var/run/rpcbind.lock"
 
 int runasdaemon = 0;
-int insecure = 0;
-int oldstyle_local = 0;
+int allow_remote = 0;
+int allow_unprivileged = 0;
+int allow_callit = 0;
 int verboselog = 0;
 
 char **hosts = NULL;
@@ -730,13 +731,15 @@ static void
 parseargs(int argc, char *argv[])
 {
 	int c;
-	oldstyle_local = 1;
-	while ((c = getopt(argc, argv, "dwah:ils")) != -1) {
+	while ((c = getopt(argc, argv, "acdh:ilrsuw")) != -1) {
 		switch (c) {
 		case 'a':
 			doabort = 1;	/* when debugging, do an abort on */
 			break;		/* errors; for rpcbind developers */
 					/* only! */
+		case 'c':
+			allow_callit = 1;
+			break;
 		case 'd':
 			debugging = 1;
 			break;
@@ -750,21 +753,27 @@ parseargs(int argc, char *argv[])
 				errx(1, "Out of memory");
 			break;
 		case 'i':
-			insecure = 1;
+			allow_remote = allow_unprivileged = allow_callit = 1;
 			break;
 		case 'l':
 			verboselog = 1;
 			break;
+		case 'r':
+			allow_remote = 1;
+			break;
 		case 's':
 			runasdaemon = 1;
 			break;
+		case 'u':
+			allow_unprivileged = 1;
+			break;
 #ifdef WARMSTART
 		case 'w':
 			warmstart = 1;
 			break;
 #endif
 		default:	/* error */
-			fprintf(stderr,	"usage: rpcbind [-Idwils]\n");
+			fprintf(stderr,	"usage: rpcbind [-acdhilrsuw]\n");
 			exit (1);
 		}
 	}
diff -up rpcbind-0.2.0/src/rpcbind.h.orig rpcbind-0.2.0/src/rpcbind.h
--- rpcbind-0.2.0/src/rpcbind.h.orig	2009-05-29 09:38:22.000000000 -0400
+++ rpcbind-0.2.0/src/rpcbind.h	2010-12-09 15:37:47.340843901 -0500
@@ -67,8 +67,9 @@ struct r_rmtcall_args {
 extern int debugging;
 extern int doabort;
 extern int verboselog;
-extern int insecure;
-extern int oldstyle_local;
+extern int allow_remote;
+extern int allow_unprivileged;
+extern int allow_callit;
 extern rpcblist_ptr list_rbl;	/* A list of version 3 & 4 rpcbind services */
 
 #ifdef PORTMAP
@@ -123,6 +124,7 @@ int check_access(SVCXPRT *, rpcproc_t, v
 int check_callit(SVCXPRT *, struct r_rmtcall_args *, int);
 void logit(int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *);
 int is_loopback(struct netbuf *);
+int is_privileged(struct netbuf *);
 int is_localroot(struct netbuf *);
 
 #ifdef PORTMAP
diff -up rpcbind-0.2.0/src/security.c.orig rpcbind-0.2.0/src/security.c
--- rpcbind-0.2.0/src/security.c.orig	2009-05-29 09:38:22.000000000 -0400
+++ rpcbind-0.2.0/src/security.c	2010-12-09 15:37:57.152719027 -0500
@@ -90,7 +90,7 @@ check_access(SVCXPRT *xprt, rpcproc_t pr
 		}
 		if (proc == RPCBPROC_GETADDR)
 			break;
-		if (!insecure && !is_loopback(caller)) {
+		if (!allow_remote && !is_loopback(caller)) {
 #ifdef RPCBIND_DEBUG
 			  if (debugging)
 			    fprintf(stderr, " declined (non-loopback sender) \n");
@@ -100,6 +100,16 @@ check_access(SVCXPRT *xprt, rpcproc_t pr
 				    " declined (non-loopback sender)");
 			return 0;
 		}
+		if (!allow_unprivileged && !is_privileged(caller)) {
+#ifdef RPCBIND_DEBUG
+			  if (debugging)
+			    fprintf(stderr, " declined (non-privileged sender) \n");
+#endif
+			if (verboselog)
+				logit(log_severity, addr, proc, prog,
+				    " declined (non-privileged sender)");
+			return 0;
+		}
 		break;
 	case RPCBPROC_CALLIT:
 	case RPCBPROC_INDIRECT:
@@ -141,32 +151,65 @@ is_loopback(struct netbuf *nbuf)
 
 	switch (addr->sa_family) {
 	case AF_INET:
-		if (!oldstyle_local)
-			return 0;
 		sin = (struct sockaddr_in *)addr;
 #ifdef RPCBIND_DEBUG
 		if (debugging)
 			  fprintf(stderr,
-				  "Checking caller's adress (port = %d)\n",
+				  "Checking caller's address (port = %d)\n",
 				  ntohs(sin->sin_port));
 #endif
-	       	return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
-		    (ntohs(sin->sin_port) < IPPORT_RESERVED));
+	       	return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
 #ifdef INET6
 	case AF_INET6:
-		if (!oldstyle_local)
-			return 0;
 		sin6 = (struct sockaddr_in6 *)addr;
 #ifdef RPCBIND_DEBUG
 		if (debugging)
 			  fprintf(stderr,
-				  "Checking caller's adress (port = %d)\n",
+				  "Checking caller's address (port = %d)\n",
 				  ntohs(sin6->sin6_port));
 #endif
-		return ((IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
-			 (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
-			  sin6->sin6_addr.s6_addr32[3] == htonl(INADDR_LOOPBACK))) &&
-		        (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
+		return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
+			(IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
+			 sin6->sin6_addr.s6_addr32[3] == htonl(INADDR_LOOPBACK)));
+#endif
+	case AF_LOCAL:
+		return 1;
+	default:
+		break;
+	}
+	
+	return 0;
+}
+
+int
+is_privileged(struct netbuf *nbuf)
+{
+	struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
+	struct sockaddr_in *sin;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)addr;
+#ifdef RPCBIND_DEBUG
+		if (debugging)
+			  fprintf(stderr,
+				  "Checking caller's port (%d)\n",
+				  ntohs(sin->sin_port));
+#endif
+	       	return (ntohs(sin->sin_port) < IPPORT_RESERVED);
+#ifdef INET6
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)addr;
+#ifdef RPCBIND_DEBUG
+		if (debugging)
+			  fprintf(stderr,
+				  "Checking caller's port (%d)\n",
+				  ntohs(sin6->sin6_port));
+#endif
+		return (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED);
 #endif
 	case AF_LOCAL:
 		return 1;
@@ -192,15 +235,11 @@ is_localroot(struct netbuf *nbuf)
 
 	switch (addr->sa_family) {
 	case AF_INET:
-		if (!oldstyle_local)
-			return 0;
 		sin = (struct sockaddr_in *)addr;
 		return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
 		    (ntohs(sin->sin_port) < IPPORT_RESERVED));
 #ifdef INET6
 	case AF_INET6:
-		if (!oldstyle_local)
-			return 0;
 		sin6 = (struct sockaddr_in6 *)addr;
 		return ((IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
 			 (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
@@ -310,11 +349,7 @@ check_callit(SVCXPRT *xprt, struct r_rmt
 	 */
 	switch (args->rmt_prog) {
 	case RPCBPROG:
-		/*
-		 * Allow indirect calls to ourselves in insecure mode.
-		 * The is_loopback checks aren't useful then anyway.
-		 */
-		if (!insecure)
+		if (!allow_callit)
 			goto deny;
 		break;
 	case MOUNTPROG:

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux