45d60a
diff -up dhcp-4.2.2b1/client/dhclient.8.capability dhcp-4.2.2b1/client/dhclient.8
45d60a
--- dhcp-4.2.2b1/client/dhclient.8.capability	2011-07-01 15:09:06.603784531 +0200
45d60a
+++ dhcp-4.2.2b1/client/dhclient.8	2011-07-01 15:09:06.663783913 +0200
45d60a
@@ -118,6 +118,9 @@ dhclient - Dynamic Host Configuration Pr
45d60a
 .B -w
45d60a
 ]
45d60a
 [
45d60a
+.B -nc
45d60a
+]
45d60a
+[
45d60a
 .B -B
45d60a
 ]
45d60a
 [
45d60a
@@ -296,6 +299,32 @@ has been added or removed, so that the c
45d60a
 address on that interface.
45d60a
 
45d60a
 .TP
45d60a
+.BI \-nc
45d60a
+Do not drop capabilities.
45d60a
+
45d60a
+Normally, if
45d60a
+.B dhclient
45d60a
+was compiled with libcap-ng support,
45d60a
+.B dhclient
45d60a
+drops most capabilities immediately upon startup.  While more secure,
45d60a
+this greatly restricts the additional actions that hooks in
45d60a
+.B dhclient-script (8)
45d60a
+can take.  (For example, any daemons that 
45d60a
+.B dhclient-script (8)
45d60a
+starts or restarts will inherit the restricted capabilities as well,
45d60a
+which may interfere with their correct operation.)  Thus, the
45d60a
+.BI \-nc
45d60a
+option can be used to prevent
45d60a
+.B dhclient
45d60a
+from dropping capabilities.
45d60a
+
45d60a
+The
45d60a
+.BI \-nc
45d60a
+option is ignored if
45d60a
+.B dhclient
45d60a
+was not compiled with libcap-ng support.
45d60a
+
45d60a
+.TP
45d60a
 .BI \-B
45d60a
 Set the BOOTP broadcast flag in request packets so servers will always
45d60a
 broadcast replies.
45d60a
diff -up dhcp-4.2.2b1/client/dhclient.c.capability dhcp-4.2.2b1/client/dhclient.c
45d60a
--- dhcp-4.2.2b1/client/dhclient.c.capability	2011-07-01 15:09:06.644784107 +0200
45d60a
+++ dhcp-4.2.2b1/client/dhclient.c	2011-07-01 15:09:06.664783903 +0200
45d60a
@@ -39,6 +39,10 @@
45d60a
 #include <limits.h>
45d60a
 #include <dns/result.h>
45d60a
 
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+#include <cap-ng.h>
45d60a
+#endif
45d60a
+
45d60a
 /*
45d60a
  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
45d60a
  * that when building ISC code.
45d60a
@@ -141,6 +145,9 @@ main(int argc, char **argv) {
45d60a
 	int timeout_arg = 0;
45d60a
 	char *arg_conf = NULL;
45d60a
 	int arg_conf_len = 0;
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+	int keep_capabilities = 0;
45d60a
+#endif
45d60a
 
45d60a
 	/* Initialize client globals. */
45d60a
 	memset(&default_duid, 0, sizeof(default_duid));
45d60a
@@ -410,6 +417,10 @@ main(int argc, char **argv) {
45d60a
 			}
45d60a
 
45d60a
 			dhclient_request_options = argv[i];
45d60a
+		} else if (!strcmp(argv[i], "-nc")) {
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+			keep_capabilities = 1;
45d60a
+#endif
45d60a
 		} else if (argv[i][0] == '-') {
45d60a
 		    usage();
45d60a
 		} else if (interfaces_requested < 0) {
45d60a
@@ -458,6 +469,19 @@ main(int argc, char **argv) {
45d60a
 		path_dhclient_script = s;
45d60a
 	}
45d60a
 
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+	/* Drop capabilities */
45d60a
+	if (!keep_capabilities) {
45d60a
+		capng_clear(CAPNG_SELECT_CAPS);
45d60a
+		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
45d60a
+				CAP_DAC_OVERRIDE); // Drop this someday
45d60a
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
45d60a
+				CAP_NET_ADMIN, CAP_NET_RAW,
45d60a
+				CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
45d60a
+		capng_apply(CAPNG_SELECT_CAPS);
45d60a
+	}
45d60a
+#endif
45d60a
+
45d60a
 	/* Set up the initial dhcp option universe. */
45d60a
 	initialize_common_option_spaces();
45d60a
 
45d60a
diff -up dhcp-4.2.2b1/client/dhclient-script.8.capability dhcp-4.2.2b1/client/dhclient-script.8
45d60a
--- dhcp-4.2.2b1/client/dhclient-script.8.capability	2011-07-01 15:09:06.604784521 +0200
45d60a
+++ dhcp-4.2.2b1/client/dhclient-script.8	2011-07-01 15:09:06.666783883 +0200
45d60a
@@ -239,6 +239,16 @@ repeatedly initialized to the values pro
45d60a
 the other.   Assuming the information provided by both servers is
45d60a
 valid, this shouldn't cause any real problems, but it could be
45d60a
 confusing.
45d60a
+.PP
45d60a
+Normally, if dhclient was compiled with libcap-ng support,
45d60a
+dhclient drops most capabilities immediately upon startup.
45d60a
+While more secure, this greatly restricts the additional actions that
45d60a
+hooks in dhclient-script can take. For example, any daemons that
45d60a
+dhclient-script starts or restarts will inherit the restricted
45d60a
+capabilities as well, which may interfere with their correct operation.
45d60a
+Thus, the
45d60a
+.BI \-nc
45d60a
+option can be used to prevent dhclient from dropping capabilities.
45d60a
 .SH SEE ALSO
45d60a
 dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
45d60a
 dhclient.leases(5).
45d60a
diff -up dhcp-4.2.2b1/client/Makefile.am.capability dhcp-4.2.2b1/client/Makefile.am
45d60a
--- dhcp-4.2.2b1/client/Makefile.am.capability	2011-07-01 15:09:06.526785327 +0200
45d60a
+++ dhcp-4.2.2b1/client/Makefile.am	2011-07-01 15:09:06.667783873 +0200
45d60a
@@ -5,7 +5,7 @@ dhclient_SOURCES = clparse.c dhclient.c 
45d60a
 		   scripts/netbsd scripts/nextstep scripts/openbsd \
45d60a
 		   scripts/solaris scripts/openwrt
45d60a
 dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
45d60a
-		 $(BIND9_LIBDIR) -ldns-export -lisc-export
45d60a
+		 $(BIND9_LIBDIR) -ldns-export -lisc-export $(CAPNG_LDADD)
45d60a
 man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
45d60a
 EXTRA_DIST = $(man_MANS)
45d60a
 
45d60a
diff -up dhcp-4.2.2b1/configure.ac.capability dhcp-4.2.2b1/configure.ac
45d60a
--- dhcp-4.2.2b1/configure.ac.capability	2011-07-01 15:09:06.527785317 +0200
45d60a
+++ dhcp-4.2.2b1/configure.ac	2011-07-01 15:09:06.667783873 +0200
45d60a
@@ -449,6 +449,41 @@ AC_TRY_LINK(
45d60a
 # Look for optional headers.
45d60a
 AC_CHECK_HEADERS(sys/socket.h net/if_dl.h net/if6.h regex.h)
45d60a
 
45d60a
+# look for capabilities library
45d60a
+AC_ARG_WITH(libcap-ng,
45d60a
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
45d60a
+    with_libcap_ng=auto)
45d60a
+
45d60a
+# Check for Libcap-ng API
45d60a
+#
45d60a
+# libcap-ng detection
45d60a
+if test x$with_libcap_ng = xno ; then
45d60a
+    have_libcap_ng=no;
45d60a
+else
45d60a
+    # Start by checking for header file
45d60a
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
45d60a
+
45d60a
+    # See if we have libcap-ng library
45d60a
+    AC_CHECK_LIB(cap-ng, capng_clear,
45d60a
+                 CAPNG_LDADD=-lcap-ng,)
45d60a
+
45d60a
+    # Check results are usable
45d60a
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
45d60a
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
45d60a
+    fi
45d60a
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
45d60a
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
45d60a
+    fi
45d60a
+fi
45d60a
+AC_SUBST(CAPNG_LDADD)
45d60a
+AC_MSG_CHECKING(whether to use libcap-ng)
45d60a
+if test x$CAPNG_LDADD != x ; then
45d60a
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
45d60a
+    AC_MSG_RESULT(yes)
45d60a
+else
45d60a
+    AC_MSG_RESULT(no)
45d60a
+fi
45d60a
+
45d60a
 # Solaris needs some libraries for functions
45d60a
 AC_SEARCH_LIBS(socket, [socket])
45d60a
 AC_SEARCH_LIBS(inet_ntoa, [nsl])
45d60a
diff -up dhcp-4.2.2b1/relay/dhcrelay.c.capability dhcp-4.2.2b1/relay/dhcrelay.c
45d60a
--- dhcp-4.2.2b1/relay/dhcrelay.c.capability	2011-07-01 15:09:06.626784295 +0200
45d60a
+++ dhcp-4.2.2b1/relay/dhcrelay.c	2011-07-01 15:12:05.362223794 +0200
45d60a
@@ -36,6 +36,11 @@
45d60a
 #include <syslog.h>
45d60a
 #include <sys/time.h>
45d60a
 
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+#  include <cap-ng.h>
45d60a
+   int keep_capabilities = 0;
45d60a
+#endif
45d60a
+
45d60a
 TIME default_lease_time = 43200; /* 12 hours... */
45d60a
 TIME max_lease_time = 86400; /* 24 hours... */
45d60a
 struct tree_cache *global_options[256];
45d60a
@@ -356,6 +361,10 @@ main(int argc, char **argv) {
45d60a
 			sl->next = upstreams;
45d60a
 			upstreams = sl;
45d60a
 #endif
45d60a
+		} else if (!strcmp(argv[i], "-nc")) {
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+			keep_capabilities = 1;
45d60a
+#endif
45d60a
 		} else if (!strcmp(argv[i], "-pf")) {
45d60a
 			if (++i == argc)
45d60a
 				usage();
45d60a
@@ -426,6 +435,17 @@ main(int argc, char **argv) {
45d60a
 #endif
45d60a
 	}
45d60a
 
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+	/* Drop capabilities */
45d60a
+	if (!keep_capabilities) {
45d60a
+		capng_clear(CAPNG_SELECT_BOTH);
45d60a
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
45d60a
+				CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
45d60a
+		capng_apply(CAPNG_SELECT_BOTH);
45d60a
+		log_info ("Dropped all unnecessary capabilities.");
45d60a
+	}
45d60a
+#endif
45d60a
+
45d60a
 	if (!quiet) {
45d60a
 		log_info("%s %s", message, PACKAGE_VERSION);
45d60a
 		log_info(copyright);
45d60a
@@ -573,6 +593,15 @@ main(int argc, char **argv) {
45d60a
 		dhcpv6_packet_handler = do_packet6;
45d60a
 #endif
45d60a
 
45d60a
+#ifdef HAVE_LIBCAP_NG
45d60a
+	/* Drop all capabilities */
45d60a
+	if (!keep_capabilities) {
45d60a
+		capng_clear(CAPNG_SELECT_BOTH);
45d60a
+		capng_apply(CAPNG_SELECT_BOTH);
45d60a
+		log_info ("Dropped all capabilities.");
45d60a
+	}
45d60a
+#endif
45d60a
+
45d60a
 	/* Start dispatching packets and timeouts... */
45d60a
 	dispatch();
45d60a
 
45d60a
diff -up dhcp-4.2.2b1/relay/Makefile.am.capability dhcp-4.2.2b1/relay/Makefile.am
45d60a
--- dhcp-4.2.2b1/relay/Makefile.am.capability	2011-07-01 15:09:06.546785121 +0200
45d60a
+++ dhcp-4.2.2b1/relay/Makefile.am	2011-07-01 15:09:06.670783841 +0200
45d60a
@@ -3,7 +3,7 @@ AM_CPPFLAGS = -DLOCALSTATEDIR='"@localst
45d60a
 sbin_PROGRAMS = dhcrelay
45d60a
 dhcrelay_SOURCES = dhcrelay.c
45d60a
 dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
45d60a
-		 $(BIND9_LIBDIR) -ldns-export -lisc-export
45d60a
+		 $(BIND9_LIBDIR) -ldns-export -lisc-export $(CAPNG_LDADD)
45d60a
 man_MANS = dhcrelay.8
45d60a
 EXTRA_DIST = $(man_MANS)
45d60a