changeset 2484:4b43ba8b6c11 draft

controlgroup option changes group ownership of the control socket.
author Roy Marples <roy@marples.name>
date Fri, 09 May 2014 12:09:05 +0000
parents ef73d9711718
children 50a9a63ba0fe
files control.c dhcpcd.conf.5.in dhcpcd.h if-options.c
diffstat 4 files changed, 72 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/control.c	Thu May 08 23:55:33 2014 +0000
+++ b/control.c	Fri May 09 12:09:05 2014 +0000
@@ -173,6 +173,9 @@
 	if (bind(ctx->control_fd, (struct sockaddr *)&sun, len) == -1 ||
 	    chmod(ctx->control_sock,
 		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 ||
+	    (ctx->control_group &&
+	        chown(ctx->control_sock,
+		geteuid(), ctx->control_group) == -1) ||
 	    listen(ctx->control_fd, sizeof(ctx->control_fds)) == -1)
 	{
 		close(ctx->control_fd);
--- a/dhcpcd.conf.5.in	Thu May 08 23:55:33 2014 +0000
+++ b/dhcpcd.conf.5.in	Fri May 09 12:09:05 2014 +0000
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 28, 2014
+.Dd May 9, 2014
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -105,6 +105,11 @@
 In most cases,
 .Nm dhcpcd
 will set this automatically.
+.It Ic controlgroup Ar group
+Sets the group ownership of
+.Pa @RUNDIR@/dhcpcd.sock
+so that users other than root can connect to
+.Nm dhcpcd .
 .It Ic debug
 Echo debug messages to the stderr and syslog.
 .It Ic dev Ar value
--- a/dhcpcd.h	Thu May 08 23:55:33 2014 +0000
+++ b/dhcpcd.h	Fri May 09 12:09:05 2014 +0000
@@ -96,6 +96,7 @@
 	int control_fd;
 	struct fd_list *control_fds;
 	char control_sock[sizeof(CONTROLSOCKET) + IF_NAMESIZE];
+	gid_t control_group;
 
 	/* DHCP Enterprise options, RFC3925 */
 	struct dhcp_opt *vivso;
--- a/if-options.c	Thu May 08 23:55:33 2014 +0000
+++ b/if-options.c	Fri May 09 12:09:05 2014 +0000
@@ -36,6 +36,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <getopt.h>
+#include <grp.h>
 #include <limits.h>
 #include <paths.h>
 #include <stdio.h>
@@ -89,6 +90,7 @@
 #define O_DHCP6			O_BASE + 31
 #define O_IPV4			O_BASE + 32
 #define O_IPV6			O_BASE + 33
+#define O_CONTROLGRP		O_BASE + 34
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -172,6 +174,7 @@
 	{"nodhcp",          no_argument,       NULL, O_NODHCP},
 	{"dhcp6",           no_argument,       NULL, O_DHCP6},
 	{"nodhcp6",         no_argument,       NULL, O_NODHCP6},
+	{"controlgroup",    required_argument, NULL, O_CONTROLGRP},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -615,7 +618,8 @@
 parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
     int opt, const char *arg, struct dhcp_opt **ldop, struct dhcp_opt **edop)
 {
-	int i, l, t;
+	int i, t;
+	long l;
 	unsigned long u;
 	char *p = NULL, *fp, *np, **nconf;
 	ssize_t s;
@@ -628,6 +632,11 @@
 	size_t *dop_len, dl;
 	struct vivco *vivco;
 	struct token *token;
+	struct group *grp;
+#ifdef _REENTRANT
+#error foo
+	struct group grpbuf;
+#endif
 #ifdef INET6
 	size_t sl;
 	struct if_ia *ia;
@@ -1774,6 +1783,58 @@
 	case O_NODHCP6:
 		ifo->options &= ~DHCPCD_DHCP6;
 		break;
+	case O_CONTROLGRP:
+#ifdef _REENTRANT
+		l = sysconf(_SC_GETGR_R_SIZE_MAX);
+		if (l == -1)
+			dl = 1024;
+		else
+			dl = (size_t)l;
+		p = malloc(dl);
+		if (p == NULL) {
+			syslog(LOG_ERR, "%s: malloc: %m", __func__);
+			return -1;
+		}
+		while ((i = getgrnam_r(arg, &grpbuf, p, (size_t)l, &grp)) ==
+		    ERANGE)
+		{
+			size_t nl = dl * 2;
+			if (nl < dl) {
+				syslog(LOG_ERR, "control_group: out of buffer");
+				free(p);
+				return -1;
+			}
+			dl = nl;
+			np = realloc(p, dl);
+			if (np == NULL) {
+				syslog(LOG_ERR, "control_group: realloc: %m");
+				free(p);
+				return -1;
+			}
+			p = np;
+		}
+		if (i != 0) {
+			errno = i;
+			syslog(LOG_ERR, "getgrnam_r: %m");
+			free(p);
+			return -1;
+		}
+		if (grp == NULL) {
+			syslog(LOG_ERR, "controlgroup: %s: not found", arg);
+			free(p);
+			return -1;
+		}
+		ctx->control_group = grp->gr_gid;
+		free(p);
+#else
+		grp = getgrnam(arg);
+		if (grp == NULL) {
+			syslog(LOG_ERR, "controlgroup: %s: not found", arg);
+			return -1;
+		}
+		ctx->control_group = grp->gr_gid;
+#endif
+		break;
 	default:
 		return 0;
 	}