aboutsummaryrefslogtreecommitdiffstats
path: root/dumpcap.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2007-11-20 16:53:01 +0000
committerGerald Combs <gerald@wireshark.org>2007-11-20 16:53:01 +0000
commit58914b5248b3f4e09be4394ac47f297fbd226877 (patch)
tree28d99d540514df3932aa6671c77e3df03602b6c4 /dumpcap.c
parentbe81aa150ebf189120bbfbdf1d9609c70d0b787a (diff)
If libcap is present, have dumpcap use it to drop privileges while
retaining CAP_NET_ADMIN and CAP_NET_RAW. Update some Makefile dependencies for dumpcap. svn path=/trunk/; revision=23511
Diffstat (limited to 'dumpcap.c')
-rw-r--r--dumpcap.c70
1 files changed, 70 insertions, 0 deletions
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 */