philipp / rpms / dhcp

Forked from rpms/dhcp 4 years ago
Clone
26a25c
diff --git a/client/Makefile.am b/client/Makefile.am
26a25c
index b1ecf82..387c097 100644
26a25c
--- a/client/Makefile.am
26a25c
+++ b/client/Makefile.am
26a25c
@@ -15,6 +15,7 @@ dhclient_SOURCES = clparse.c dhclient.c dhc6.c \
26a25c
 		   scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
26a25c
 		   scripts/netbsd scripts/nextstep scripts/openbsd \
26a25c
 		   scripts/solaris scripts/openwrt
26a25c
-dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la $(BIND_LIBS)
26a25c
+dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
26a25c
+		 $(CAPNG_LDADD) $(BIND_LIBS)
26a25c
 man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
26a25c
 EXTRA_DIST = $(man_MANS)
26a25c
diff --git a/client/dhclient-script.8 b/client/dhclient-script.8
26a25c
index 3a3aaf7..fec726c 100644
26a25c
--- a/client/dhclient-script.8
26a25c
+++ b/client/dhclient-script.8
26a25c
@@ -245,6 +245,16 @@ repeatedly initialized to the values provided by one server, and then
26a25c
 the other.   Assuming the information provided by both servers is
26a25c
 valid, this shouldn't cause any real problems, but it could be
26a25c
 confusing.
26a25c
+.PP
26a25c
+Normally, if dhclient was compiled with libcap-ng support,
26a25c
+dhclient drops most capabilities immediately upon startup.
26a25c
+While more secure, this greatly restricts the additional actions that
26a25c
+hooks in dhclient-script can take. For example, any daemons that
26a25c
+dhclient-script starts or restarts will inherit the restricted
26a25c
+capabilities as well, which may interfere with their correct operation.
26a25c
+Thus, the
26a25c
+.BI \-nc
26a25c
+option can be used to prevent dhclient from dropping capabilities.
26a25c
 .SH SEE ALSO
26a25c
 dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
26a25c
 dhclient.leases(5).
26a25c
diff --git a/client/dhclient.8 b/client/dhclient.8
26a25c
index aa2238d..005cda5 100644
26a25c
--- a/client/dhclient.8
26a25c
+++ b/client/dhclient.8
26a25c
@@ -134,6 +134,9 @@ dhclient - Dynamic Host Configuration Protocol Client
26a25c
 .B -w
26a25c
 ]
26a25c
 [
26a25c
+.B -nc
26a25c
+]
26a25c
+[
26a25c
 .B -B
26a25c
 ]
26a25c
 [
26a25c
@@ -320,6 +323,32 @@ not to exit when it doesn't find any such interfaces.  The
26a25c
 program can then be used to notify the client when a network interface
26a25c
 has been added or removed, so that the client can attempt to configure an IP
26a25c
 address on that interface.
26a25c
+.TP
26a25c
+.BI \-nc
26a25c
+Do not drop capabilities.
26a25c
+
26a25c
+Normally, if
26a25c
+.B dhclient
26a25c
+was compiled with libcap-ng support,
26a25c
+.B dhclient
26a25c
+drops most capabilities immediately upon startup.  While more secure,
26a25c
+this greatly restricts the additional actions that hooks in
26a25c
+.B dhclient-script (8)
26a25c
+can take.  (For example, any daemons that 
26a25c
+.B dhclient-script (8)
26a25c
+starts or restarts will inherit the restricted capabilities as well,
26a25c
+which may interfere with their correct operation.)  Thus, the
26a25c
+.BI \-nc
26a25c
+option can be used to prevent
26a25c
+.B dhclient
26a25c
+from dropping capabilities.
26a25c
+
26a25c
+The
26a25c
+.BI \-nc
26a25c
+option is ignored if
26a25c
+.B dhclient
26a25c
+was not compiled with libcap-ng support.
26a25c
+
26a25c
 .TP
26a25c
 .BI \-n
26a25c
 Do not configure any interfaces.  This is most likely to be useful in
26a25c
diff --git a/client/dhclient.c b/client/dhclient.c
26a25c
index 09ae09b..2d564ff 100644
26a25c
--- a/client/dhclient.c
26a25c
+++ b/client/dhclient.c
26a25c
@@ -40,6 +40,10 @@
26a25c
 #include <isc/file.h>
26a25c
 #include <dns/result.h>
26a25c
 
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+#include <cap-ng.h>
26a25c
+#endif
26a25c
+
26a25c
 /*
26a25c
  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
26a25c
  * that when building ISC code.
26a25c
@@ -239,6 +243,9 @@ main(int argc, char **argv) {
26a25c
 	int timeout_arg = 0;
26a25c
 	char *arg_conf = NULL;
26a25c
 	int arg_conf_len = 0;
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+	int keep_capabilities = 0;
26a25c
+#endif
26a25c
 
26a25c
 	/* Initialize client globals. */
26a25c
 	memset(&default_duid, 0, sizeof(default_duid));
26a25c
@@ -548,6 +555,10 @@ main(int argc, char **argv) {
26a25c
 			}
26a25c
 
26a25c
 			dhclient_request_options = argv[i];
26a25c
+		} else if (!strcmp(argv[i], "-nc")) {
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+			keep_capabilities = 1;
26a25c
+#endif
26a25c
 		} else if (argv[i][0] == '-') {
26a25c
 			usage("Unknown command: %s", argv[i]);
26a25c
 		} else if (interfaces_requested < 0) {
26a25c
@@ -608,6 +619,19 @@ main(int argc, char **argv) {
26a25c
 		path_dhclient_script = s;
26a25c
 	}
26a25c
 
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+	/* Drop capabilities */
26a25c
+	if (!keep_capabilities) {
26a25c
+		capng_clear(CAPNG_SELECT_CAPS);
26a25c
+		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
26a25c
+				CAP_DAC_OVERRIDE); // Drop this someday
26a25c
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
26a25c
+				CAP_NET_ADMIN, CAP_NET_RAW,
26a25c
+				CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
26a25c
+		capng_apply(CAPNG_SELECT_CAPS);
26a25c
+	}
26a25c
+#endif
26a25c
+
26a25c
 	/* Set up the initial dhcp option universe. */
26a25c
 	initialize_common_option_spaces();
26a25c
 
26a25c
diff --git a/configure.ac b/configure.ac
26a25c
index adc98a8..8bbe5ca 100644
26a25c
--- a/configure.ac
26a25c
+++ b/configure.ac
26a25c
@@ -592,6 +592,41 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[void foo() __attribute__((noreturn));
26a25c
 # Look for optional headers.
26a25c
 AC_CHECK_HEADERS(sys/socket.h net/if_dl.h net/if6.h regex.h)
26a25c
 
26a25c
+# look for capabilities library
26a25c
+AC_ARG_WITH(libcap-ng,
26a25c
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
26a25c
+    with_libcap_ng=auto)
26a25c
+
26a25c
+# Check for Libcap-ng API
26a25c
+#
26a25c
+# libcap-ng detection
26a25c
+if test x$with_libcap_ng = xno ; then
26a25c
+    have_libcap_ng=no;
26a25c
+else
26a25c
+    # Start by checking for header file
26a25c
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
26a25c
+
26a25c
+    # See if we have libcap-ng library
26a25c
+    AC_CHECK_LIB(cap-ng, capng_clear,
26a25c
+                 CAPNG_LDADD=-lcap-ng,)
26a25c
+
26a25c
+    # Check results are usable
26a25c
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
26a25c
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
26a25c
+    fi
26a25c
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
26a25c
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
26a25c
+    fi
26a25c
+fi
26a25c
+AC_SUBST(CAPNG_LDADD)
26a25c
+AC_MSG_CHECKING(whether to use libcap-ng)
26a25c
+if test x$CAPNG_LDADD != x ; then
26a25c
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
26a25c
+    AC_MSG_RESULT(yes)
26a25c
+else
26a25c
+    AC_MSG_RESULT(no)
26a25c
+fi
26a25c
+
26a25c
 # Solaris needs some libraries for functions
26a25c
 AC_SEARCH_LIBS(socket, [socket])
26a25c
 AC_SEARCH_LIBS(inet_ntoa, [nsl])
26a25c
diff --git a/relay/Makefile.am b/relay/Makefile.am
26a25c
index 316a524..999e543 100644
26a25c
--- a/relay/Makefile.am
26a25c
+++ b/relay/Makefile.am
26a25c
@@ -5,7 +5,7 @@ AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
26a25c
 sbin_PROGRAMS = dhcrelay
26a25c
 dhcrelay_SOURCES = dhcrelay.c
26a25c
 dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
26a25c
-		 $(BIND_LIBS)
26a25c
+		 $(CAPNG_LDADD) $(BIND_LIBS)
26a25c
 man_MANS = dhcrelay.8
26a25c
 EXTRA_DIST = $(man_MANS)
26a25c
 
26a25c
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
26a25c
index eac119c..d2ab448 100644
26a25c
--- a/relay/dhcrelay.c
26a25c
+++ b/relay/dhcrelay.c
26a25c
@@ -32,6 +32,11 @@
26a25c
 #include <sys/time.h>
26a25c
 #include <isc/file.h>
26a25c
 
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+#  include <cap-ng.h>
26a25c
+   int keep_capabilities = 0;
26a25c
+#endif
26a25c
+
26a25c
 TIME default_lease_time = 43200; /* 12 hours... */
26a25c
 TIME max_lease_time = 86400; /* 24 hours... */
26a25c
 struct tree_cache *global_options[256];
26a25c
@@ -472,6 +477,10 @@ main(int argc, char **argv) {
26a25c
 			if (++i == argc)
26a25c
 				usage(use_noarg, argv[i-1]);
26a25c
 			dhcrelay_sub_id = argv[i];
26a25c
+#endif
26a25c
+		} else if (!strcmp(argv[i], "-nc")) {
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+			keep_capabilities = 1;
26a25c
 #endif
26a25c
 		} else if (!strcmp(argv[i], "-pf")) {
26a25c
 			if (++i == argc)
26a25c
@@ -547,6 +556,17 @@ main(int argc, char **argv) {
26a25c
 #endif
26a25c
 	}
26a25c
 
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+	/* Drop capabilities */
26a25c
+	if (!keep_capabilities) {
26a25c
+		capng_clear(CAPNG_SELECT_BOTH);
26a25c
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
26a25c
+				CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
26a25c
+		capng_apply(CAPNG_SELECT_BOTH);
26a25c
+		log_info ("Dropped all unnecessary capabilities.");
26a25c
+	}
26a25c
+#endif
26a25c
+
26a25c
 	if (!quiet) {
26a25c
 		log_info("%s %s", message, PACKAGE_VERSION);
26a25c
 		log_info(copyright);
26a25c
@@ -699,6 +719,15 @@ main(int argc, char **argv) {
26a25c
 	signal(SIGTERM, dhcp_signal_handler);  /* kill */
26a25c
 #endif
26a25c
 
26a25c
+#ifdef HAVE_LIBCAP_NG
26a25c
+	/* Drop all capabilities */
26a25c
+	if (!keep_capabilities) {
26a25c
+		capng_clear(CAPNG_SELECT_BOTH);
26a25c
+		capng_apply(CAPNG_SELECT_BOTH);
26a25c
+		log_info ("Dropped all capabilities.");
26a25c
+	}
26a25c
+#endif
26a25c
+
26a25c
 	/* Start dispatching packets and timeouts... */
26a25c
 	dispatch();
26a25c