aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.common7
-rw-r--r--acinclude.m431
-rw-r--r--configure.in32
-rw-r--r--dumpcap.c70
5 files changed, 140 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 22f73d2417..048f866570 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/Makefile.common b/Makefile.common
index 3ce45aeb0e..9156b6b6b4 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -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 = \
diff --git a/acinclude.m4 b/acinclude.m4
index ba7c65e305..ff9c31fba9 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1237,6 +1237,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
#
AC_DEFUN([AC_WIRESHARK_KRB5_CHECK],
diff --git a/configure.in b/configure.in
index dc8dbfdcc4..9cdce37e69 100644
--- a/configure.in
+++ b/configure.in
@@ -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"
diff --git a/dumpcap.c b/dumpcap.c
index 3bdcf3ce44..26ac7a4811 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -43,6 +43,12 @@
#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"
@@ -59,6 +65,10 @@
#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 */