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