])
+#
+# 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
#
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)
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"
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"
#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"
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
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 */