e83fb19
diff -up dhcp-4.3.0a1/client/Makefile.am.capability dhcp-4.3.0a1/client/Makefile.am
e83fb19
--- dhcp-4.3.0a1/client/Makefile.am.capability	2013-12-19 16:15:26.549657115 +0100
e83fb19
+++ dhcp-4.3.0a1/client/Makefile.am	2013-12-19 16:16:04.126133091 +0100
e83fb19
@@ -4,7 +4,7 @@ dhclient_SOURCES = clparse.c dhclient.c
e83fb19
 		   scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
e83fb19
 		   scripts/netbsd scripts/nextstep scripts/openbsd \
e83fb19
 		   scripts/solaris scripts/openwrt
e83fb19
-dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
e83fb19
+dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la $(CAPNG_LDADD) \
e83fb19
 		 $(BIND9_LIBDIR) -lirs-export -ldns-export -lisccfg-export -lisc-export
e83fb19
 man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
e83fb19
 EXTRA_DIST = $(man_MANS)
e83fb19
diff -up dhcp-4.3.0a1/client/dhclient-script.8.capability dhcp-4.3.0a1/client/dhclient-script.8
e83fb19
--- dhcp-4.3.0a1/client/dhclient-script.8.capability	2013-12-19 16:15:26.520657520 +0100
e83fb19
+++ dhcp-4.3.0a1/client/dhclient-script.8	2013-12-19 16:15:26.549657115 +0100
e83fb19
@@ -246,6 +246,16 @@ repeatedly initialized to the values pro
e83fb19
 the other.   Assuming the information provided by both servers is
e83fb19
 valid, this shouldn't cause any real problems, but it could be
e83fb19
 confusing.
e83fb19
+.PP
e83fb19
+Normally, if dhclient was compiled with libcap-ng support,
e83fb19
+dhclient drops most capabilities immediately upon startup.
e83fb19
+While more secure, this greatly restricts the additional actions that
e83fb19
+hooks in dhclient-script can take. For example, any daemons that
e83fb19
+dhclient-script starts or restarts will inherit the restricted
e83fb19
+capabilities as well, which may interfere with their correct operation.
e83fb19
+Thus, the
e83fb19
+.BI \-nc
e83fb19
+option can be used to prevent dhclient from dropping capabilities.
e83fb19
 .SH SEE ALSO
e83fb19
 dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
e83fb19
 dhclient.leases(5).
e83fb19
diff -up dhcp-4.3.0a1/client/dhclient.8.capability dhcp-4.3.0a1/client/dhclient.8
e83fb19
--- dhcp-4.3.0a1/client/dhclient.8.capability	2013-12-19 16:15:26.482658050 +0100
e83fb19
+++ dhcp-4.3.0a1/client/dhclient.8	2013-12-19 16:15:26.550657101 +0100
e83fb19
@@ -124,6 +124,9 @@ dhclient - Dynamic Host Configuration Pr
45c0371
 .B -w
d44b399
 ]
d44b399
 [
d44b399
+.B -nc
d44b399
+]
d44b399
+[
45c0371
 .B -B
d44b399
 ]
d44b399
 [
e83fb19
@@ -300,6 +303,32 @@ has been added or removed, so that the c
45c0371
 address on that interface.
cd8c86f
 
cd8c86f
 .TP
cd8c86f
+.BI \-nc
cd8c86f
+Do not drop capabilities.
cd8c86f
+
cd8c86f
+Normally, if
cd8c86f
+.B dhclient
cd8c86f
+was compiled with libcap-ng support,
cd8c86f
+.B dhclient
cd8c86f
+drops most capabilities immediately upon startup.  While more secure,
cd8c86f
+this greatly restricts the additional actions that hooks in
cd8c86f
+.B dhclient-script (8)
cd8c86f
+can take.  (For example, any daemons that 
cd8c86f
+.B dhclient-script (8)
cd8c86f
+starts or restarts will inherit the restricted capabilities as well,
cd8c86f
+which may interfere with their correct operation.)  Thus, the
cd8c86f
+.BI \-nc
cd8c86f
+option can be used to prevent
cd8c86f
+.B dhclient
cd8c86f
+from dropping capabilities.
cd8c86f
+
cd8c86f
+The
cd8c86f
+.BI \-nc
cd8c86f
+option is ignored if
cd8c86f
+.B dhclient
cd8c86f
+was not compiled with libcap-ng support.
cd8c86f
+
cd8c86f
+.TP
45c0371
 .BI \-B
45c0371
 Set the BOOTP broadcast flag in request packets so servers will always
45c0371
 broadcast replies.
e83fb19
diff -up dhcp-4.3.0a1/client/dhclient.c.capability dhcp-4.3.0a1/client/dhclient.c
e83fb19
--- dhcp-4.3.0a1/client/dhclient.c.capability	2013-12-19 16:15:26.532657352 +0100
e83fb19
+++ dhcp-4.3.0a1/client/dhclient.c	2013-12-19 16:15:26.551657087 +0100
5a3797e
@@ -39,6 +39,10 @@
3b84ae4
 #include <limits.h>
5a3797e
 #include <dns/result.h>
5a3797e
 
3b84ae4
+#ifdef HAVE_LIBCAP_NG
3b84ae4
+#include <cap-ng.h>
3b84ae4
+#endif
5a3797e
+
3b84ae4
 /*
3b84ae4
  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
5a3797e
  * that when building ISC code.
48c3985
@@ -141,6 +145,9 @@ main(int argc, char **argv) {
48c3985
 	int timeout_arg = 0;
48c3985
 	char *arg_conf = NULL;
48c3985
 	int arg_conf_len = 0;
7985996
+#ifdef HAVE_LIBCAP_NG
48c3985
+	int keep_capabilities = 0;
7985996
+#endif
7985996
 
48c3985
 	/* Initialize client globals. */
48c3985
 	memset(&default_duid, 0, sizeof(default_duid));
e83fb19
@@ -413,6 +420,10 @@ main(int argc, char **argv) {
7985996
 			}
7985996
 
7985996
 			dhclient_request_options = argv[i];
7985996
+		} else if (!strcmp(argv[i], "-nc")) {
cd8c86f
+#ifdef HAVE_LIBCAP_NG
7985996
+			keep_capabilities = 1;
7985996
+#endif
7985996
 		} else if (argv[i][0] == '-') {
7985996
 		    usage();
7985996
 		} else if (interfaces_requested < 0) {
e83fb19
@@ -461,6 +472,19 @@ main(int argc, char **argv) {
3b84ae4
 		path_dhclient_script = s;
3b84ae4
 	}
3b84ae4
 
3b84ae4
+#ifdef HAVE_LIBCAP_NG
3b84ae4
+	/* Drop capabilities */
7985996
+	if (!keep_capabilities) {
7985996
+		capng_clear(CAPNG_SELECT_CAPS);
7985996
+		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
7985996
+				CAP_DAC_OVERRIDE); // Drop this someday
7985996
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
7985996
+				CAP_NET_ADMIN, CAP_NET_RAW,
7985996
+				CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
7985996
+		capng_apply(CAPNG_SELECT_CAPS);
7985996
+	}
3b84ae4
+#endif
3b84ae4
+
3b84ae4
 	/* Set up the initial dhcp option universe. */
3b84ae4
 	initialize_common_option_spaces();
3b84ae4
 
e83fb19
diff -up dhcp-4.3.0a1/configure.ac.capability dhcp-4.3.0a1/configure.ac
e83fb19
--- dhcp-4.3.0a1/configure.ac.capability	2013-12-19 16:15:26.475658147 +0100
e83fb19
+++ dhcp-4.3.0a1/configure.ac	2013-12-19 16:15:26.552657074 +0100
e83fb19
@@ -489,6 +489,41 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],
3b84ae4
 # Look for optional headers.
3b84ae4
 AC_CHECK_HEADERS(sys/socket.h net/if_dl.h net/if6.h regex.h)
3b84ae4
 
3b84ae4
+# look for capabilities library
7985996
+AC_ARG_WITH(libcap-ng,
7985996
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
7985996
+    with_libcap_ng=auto)
7985996
+
7985996
+# Check for Libcap-ng API
7985996
+#
7985996
+# libcap-ng detection
7985996
+if test x$with_libcap_ng = xno ; then
7985996
+    have_libcap_ng=no;
7985996
+else
7985996
+    # Start by checking for header file
7985996
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
7985996
+
7985996
+    # See if we have libcap-ng library
7985996
+    AC_CHECK_LIB(cap-ng, capng_clear,
7985996
+                 CAPNG_LDADD=-lcap-ng,)
7985996
+
7985996
+    # Check results are usable
7985996
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
7985996
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
7985996
+    fi
7985996
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
7985996
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
7985996
+    fi
7985996
+fi
7985996
+AC_SUBST(CAPNG_LDADD)
7985996
+AC_MSG_CHECKING(whether to use libcap-ng)
7985996
+if test x$CAPNG_LDADD != x ; then
7985996
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
7985996
+    AC_MSG_RESULT(yes)
7985996
+else
7985996
+    AC_MSG_RESULT(no)
7985996
+fi
3b84ae4
+
45c0371
 # Solaris needs some libraries for functions
45c0371
 AC_SEARCH_LIBS(socket, [socket])
45c0371
 AC_SEARCH_LIBS(inet_ntoa, [nsl])
e83fb19
diff -up dhcp-4.3.0a1/relay/Makefile.am.capability dhcp-4.3.0a1/relay/Makefile.am
e83fb19
--- dhcp-4.3.0a1/relay/Makefile.am.capability	2013-12-19 16:15:26.552657074 +0100
e83fb19
+++ dhcp-4.3.0a1/relay/Makefile.am	2013-12-19 16:16:26.159825841 +0100
e83fb19
@@ -2,7 +2,7 @@ AM_CPPFLAGS = -DLOCALSTATEDIR='"@localst
e83fb19
 
e83fb19
 sbin_PROGRAMS = dhcrelay
e83fb19
 dhcrelay_SOURCES = dhcrelay.c
e83fb19
-dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
e83fb19
+dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.la $(CAPNG_LDADD) \
e83fb19
 		 $(BIND9_LIBDIR) -lirs-export -ldns-export -lisccfg-export -lisc-export
e83fb19
 man_MANS = dhcrelay.8
e83fb19
 EXTRA_DIST = $(man_MANS)
e83fb19
diff -up dhcp-4.3.0a1/relay/dhcrelay.c.capability dhcp-4.3.0a1/relay/dhcrelay.c
e83fb19
--- dhcp-4.3.0a1/relay/dhcrelay.c.capability	2013-12-19 16:15:26.535657311 +0100
e83fb19
+++ dhcp-4.3.0a1/relay/dhcrelay.c	2013-12-19 16:15:26.553657060 +0100
e83fb19
@@ -37,6 +37,11 @@
e83fb19
 #include <signal.h>
48c3985
 #include <sys/time.h>
48c3985
 
48c3985
+#ifdef HAVE_LIBCAP_NG
48c3985
+#  include <cap-ng.h>
48c3985
+   int keep_capabilities = 0;
48c3985
+#endif
48c3985
+
48c3985
 TIME default_lease_time = 43200; /* 12 hours... */
48c3985
 TIME max_lease_time = 86400; /* 24 hours... */
48c3985
 struct tree_cache *global_options[256];
e83fb19
@@ -382,6 +387,10 @@ main(int argc, char **argv) {
e83fb19
 				usage();
e83fb19
 			dhcrelay_sub_id = argv[i];
48c3985
 #endif
48c3985
+		} else if (!strcmp(argv[i], "-nc")) {
48c3985
+#ifdef HAVE_LIBCAP_NG
48c3985
+			keep_capabilities = 1;
48c3985
+#endif
48c3985
 		} else if (!strcmp(argv[i], "-pf")) {
48c3985
 			if (++i == argc)
48c3985
 				usage();
e83fb19
@@ -452,6 +461,17 @@ main(int argc, char **argv) {
48c3985
 #endif
48c3985
 	}
48c3985
 
48c3985
+#ifdef HAVE_LIBCAP_NG
48c3985
+	/* Drop capabilities */
48c3985
+	if (!keep_capabilities) {
48c3985
+		capng_clear(CAPNG_SELECT_BOTH);
48c3985
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
48c3985
+				CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
48c3985
+		capng_apply(CAPNG_SELECT_BOTH);
be9baae
+		log_info ("Dropped all unnecessary capabilities.");
48c3985
+	}
48c3985
+#endif
48c3985
+
48c3985
 	if (!quiet) {
48c3985
 		log_info("%s %s", message, PACKAGE_VERSION);
48c3985
 		log_info(copyright);
e83fb19
@@ -601,6 +621,15 @@ main(int argc, char **argv) {
e83fb19
 	signal(SIGINT, dhcp_signal_handler);   /* control-c */
e83fb19
 	signal(SIGTERM, dhcp_signal_handler);  /* kill */
48c3985
 
48c3985
+#ifdef HAVE_LIBCAP_NG
48c3985
+	/* Drop all capabilities */
48c3985
+	if (!keep_capabilities) {
48c3985
+		capng_clear(CAPNG_SELECT_BOTH);
48c3985
+		capng_apply(CAPNG_SELECT_BOTH);
be9baae
+		log_info ("Dropped all capabilities.");
48c3985
+	}
48c3985
+#endif
48c3985
+
48c3985
 	/* Start dispatching packets and timeouts... */
48c3985
 	dispatch();
48c3985