diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | Makefile.common | 7 | ||||
-rw-r--r-- | acinclude.m4 | 31 | ||||
-rw-r--r-- | configure.in | 32 | ||||
-rw-r--r-- | dumpcap.c | 70 |
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" @@ -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 */ |