If libcap is present, have dumpcap use it to drop privileges while
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 20 Nov 2007 16:53:01 +0000 (16:53 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 20 Nov 2007 16:53:01 +0000 (16:53 +0000)
retaining CAP_NET_ADMIN and CAP_NET_RAW.  Update some Makefile
dependencies for dumpcap.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@23511 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.am
Makefile.common
acinclude.m4
configure.in
dumpcap.c

index 22f73d24177b2a2a643c4bc28a800de90aee9485..048f8665706ef88b97c53d290e35d8206d2f612c 100644 (file)
@@ -387,7 +387,8 @@ dumpcap_LDADD = \
        @INET_NTOP_LO@                  \
        @GLIB_LIBS@                     \
        @PCAP_LIBS@ @SOCKET_LIBS@ @NSL_LIBS@ @FRAMEWORKS@ \
-       @LIBGCRYPT_LIBS@
+       @LIBGCRYPT_LIBS@                \
+       @LIBCAP_LIBS@
 
 # Common headers
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/wiretap \
index 3ce45aeb0e45b6ee4f097b4089cae30a5a9735c2..9156b6b6b4cf2795d3563b45d9f069a632481215 100644 (file)
@@ -233,7 +233,8 @@ dumpcap_SOURCES =   \
        sync_pipe_write.c       \
        tempfile.c      \
        version_info.c  \
-       epan/unicode-utils.c
+       epan/unicode-utils.c    \
+       epan/privileges.c
 
 # corresponding headers
 dumpcap_INCLUDES = \
@@ -241,7 +242,9 @@ dumpcap_INCLUDES = \
        capture_stop_conditions.h       \
        conditions.h    \
        pcapio.h        \
-       ringbuffer.h
+       ringbuffer.h    \
+       epan/unicode-utils.h    \
+       epan/privileges.h
 
 # this target needed for distribution only
 noinst_HEADERS =       \
index ba7c65e305cb96a80162116476727a0e86df176c..ff9c31fba92edc4c34bb6622c9946271977f82f3 100644 (file)
@@ -1236,6 +1236,37 @@ AC_DEFUN([AC_WIRESHARK_ADNS_CHECK],
 ])
 
 
+#
+# AC_WIRESHARK_LIBCAP_CHECK
+#
+AC_DEFUN([AC_WIRESHARK_LIBCAP_CHECK],
+[
+       want_libcap=defaultyes
+
+       if test "x$want_libcap" = "xdefaultyes"; then
+               want_libcap=yes
+               if test "x$ac_cv_enable_usr_local" = "xyes" ; then
+                       withval=/usr/local
+                       if test -d "$withval"; then
+                               AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
+                       fi
+               fi
+       fi
+
+       if test "x$want_libcap" = "xyes"; then
+               AC_CHECK_LIB(cap, cap_set_flag,
+                 [
+                   LIBCAP_LIBS=-lcap
+               AC_DEFINE(HAVE_LIBCAP, 1, [Define to use the libcap library])
+               have_good_libcap=yes
+                 ],,
+               )
+       else
+               AC_MSG_RESULT(not required)
+       fi
+])
+
+
 #
 # AC_WIRESHARK_KRB5_CHECK
 #
index dc8dbfdcc4cedb94f1eae7f531d2862124b3900a..9cdce37e6941e6b9159dbca05ca1026f7efb0622 100644 (file)
@@ -1067,6 +1067,31 @@ fi
 
 AM_CONDITIONAL(SETUID_INSTALL, test x$enable_setuid_install = xyes)
 
+dnl libcap (not libpcap) check
+LIBCAP_LIBS=''
+AC_MSG_CHECKING(whether to use the libcap capabilities library)
+
+AC_ARG_WITH(libcap,
+  AC_HELP_STRING( [--with-libcap@<:@=DIR@:>@],
+                  [use libcap (located in directory DIR, if supplied) for POSIX.1e capabilities management.   @<:@default=yes, if present@:>@]),
+[
+if   test "x$withval" = "xno";  then
+       want_libcap=no
+elif test "x$withval" = "xyes"; then
+       want_libcap=yes
+elif test -d "$withval"; then
+       want_libcap=yes
+       AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
+fi
+])
+if test "x$with_libcap" = "xno" ; then
+       AC_MSG_RESULT(no)
+else
+       AC_MSG_RESULT(yes)
+       AC_WIRESHARK_LIBCAP_CHECK
+fi
+AC_SUBST(LIBCAP_LIBS)
+
 dnl Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS(direct.h dirent.h fcntl.h grp.h netdb.h pwd.h stdarg.h stddef.h unistd.h)
@@ -1649,6 +1674,12 @@ else
        adns_message="no"
 fi
 
+if test "x$have_good_libcap" = "xyes" ; then
+       libcap_message="yes"
+else
+       libcap_message="no"
+fi
+
 echo ""
 echo "The Wireshark package has been configured with the following options."
 echo "                    Build wireshark : $enable_wireshark"
@@ -1681,3 +1712,4 @@ echo "             Use GNU crypto library : $gcrypt_message"
 echo "             Use SSL crypto library : $ssl_message"
 echo "           Use IPv6 name resolution : $enable_ipv6"
 echo "                 Use gnutls library : $tls_message"
+echo "                 Use libcap library : $libcap_message"
index 3bdcf3ce445088afec3aa7e34b1dd06a7206b7c0..26ac7a481179984cef841cc4aab45238dd99f60e 100644 (file)
--- a/dumpcap.c
+++ b/dumpcap.c
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_LIBCAP
+# include <sys/prctl.h>
+# include <sys/capability.h>
+# include <stdio.h>
+#endif
+
 #include "ringbuffer.h"
 #include "clopts_common.h"
 #include "cmdarg_err.h"
 #include "epan/unicode-utils.h"
 #endif
 
+#ifdef HAVE_LIBCAP
+#include "epan/privileges.h"
+#endif
+
 #include "sync_pipe.h"
 
 #include "capture.h"
@@ -238,6 +248,62 @@ void exit_main(int status)
   exit(status);
 }
 
+#ifdef HAVE_LIBCAP
+/*
+ * If we were linked with libcap (not libpcap), make sure we have
+ * CAP_NET_ADMIN and CAP_NET_RAW, then relinquish our permissions.
+ */
+
+void
+#if 0 /* Set to enable capability debugging */
+print_caps(char *pfx) {
+    cap_t caps = cap_get_proc();
+    fprintf(stderr, "%s: EUID: %d  Capabilities: %s\n", pfx,
+            geteuid(), cap_to_text(caps, NULL));
+    cap_free(caps);
+#else
+print_caps(char *pfx _U_) {
+#endif
+}
+
+void
+relinquish_privs_except_capture(void)
+{
+    /* CAP_NET_ADMIN: Promiscuous mode and a truckload of other
+     *                stuff we don't need (and shouldn't have).
+     * CAP_NET_RAW:   Packet capture (raw sockets).
+     */
+    cap_value_t cap_list[2] = { CAP_NET_ADMIN, CAP_NET_RAW };
+    cap_t caps = cap_init();
+    int cl_len = sizeof(cap_list) / sizeof(cap_value_t);
+
+    if (started_with_special_privs()) {
+        print_caps("Pre drop, pre set");
+        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
+            perror("prctl()");
+        }
+
+        cap_set_flag(caps, CAP_PERMITTED,   cl_len, cap_list, CAP_SET);
+        cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET);
+
+        if (cap_set_proc(caps)) {
+            perror("capset()");
+        }
+        print_caps("Pre drop, post set");
+    }
+
+    relinquish_special_privs_perm();
+
+    print_caps("Post drop, pre set");
+    cap_set_flag(caps, CAP_EFFECTIVE,   cl_len, cap_list, CAP_SET);
+    if (cap_set_proc(caps)) {
+        perror("capset()");
+    }
+    print_caps("Post drop, post set");
+    cap_free(caps);
+}
+#endif /* HAVE_LIBCAP */
+
 
 /* And now our feature presentation... [ fade to music ] */
 int
@@ -287,6 +353,10 @@ main(int argc, char *argv[])
   SetConsoleCtrlHandler(&ConsoleCtrlHandlerRoutine, TRUE);
 #endif  /* _WIN32 */
 
+#ifdef HAVE_LIBCAP
+  get_credential_info();
+  relinquish_privs_except_capture();
+#endif
 
   /* the default_log_handler will use stdout, which makes trouble in */
   /* capture child mode, as it uses stdout for it's sync_pipe */