From 92802883a6ec5192b9df1ab7b3d4d8069b46f841 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Thu, 30 Aug 2007 00:24:40 +0000 Subject: [PATCH] Change the "--enable-setuid-install" option to install dumpcap and TShark setuid instead of Wireshark. Remove the "DANGEROUS" notices, but leave it disabled by default. Whine if the user runs Wireshark or TShark as root. Add a preference to disable the whining. Add a "setuid-root" script that can be used to switch dumpcap and TShark's setuid-ness on and off for development and testing. Update the release notes and README.packaging. svn path=/trunk/; revision=22733 --- Makefile.am | 1 + capture_loop.c | 3 + capture_opts.c | 4 ++ capture_opts.h | 4 ++ configure.in | 19 +++--- doc/README.packaging | 6 +- docbook/release-notes.xml | 17 +++++ epan/libwireshark.def | 3 + epan/privileges.c | 133 +++++++++++++++++++++++++++++++++++++- epan/privileges.h | 30 ++++++++- gtk/capture_dlg.c | 4 ++ gtk/drag_and_drop.c | 32 +++++---- gtk/gsm_map_summary.c | 4 ++ gtk/main.c | 42 +++++++++--- gtk/mtp3_summary.c | 6 +- gtk/packet_win.c | 4 ++ gtk/recent.c | 21 +++++- gtk/recent.h | 5 +- gtk/summary_dlg.c | 14 ++-- summary.c | 4 ++ tools/Makefile.am | 9 +++ tshark.c | 21 ++++++ 22 files changed, 336 insertions(+), 50 deletions(-) diff --git a/Makefile.am b/Makefile.am index ab4cc50766..c7e35093bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -679,6 +679,7 @@ EXTRA_DIST = \ packaging/u3/win32/u3util.c \ services \ tools/idl2wrs.sh.in \ + tools/setuid-root.in \ wka.tmpl if SETUID_INSTALL diff --git a/capture_loop.c b/capture_loop.c index cd4f905cbe..15f85d0144 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -1191,6 +1191,9 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, capture_opts->save_file = capfile_name; /* capture_opts.save_file is "g_free"ed later, which is equivalent to "g_free(capfile_name)". */ +#ifndef _WIN32 + fchown(*save_file_fd, capture_opts->owner, capture_opts->group); +#endif return TRUE; } diff --git a/capture_opts.c b/capture_opts.c index bb46ac4162..2c63ca0dc1 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -124,6 +124,10 @@ capture_opts_init(capture_options *capture_opts, void *cfile) #endif capture_opts->state = CAPTURE_STOPPED; capture_opts->output_to_pipe = FALSE; +#ifndef _WIN32 + capture_opts->owner = getuid(); + capture_opts->group = getgid(); +#endif } diff --git a/capture_opts.h b/capture_opts.h index 2f96886d90..c47519329d 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -104,6 +104,10 @@ typedef struct capture_options_tag { #endif capture_state state; /**< current state of the capture engine */ gboolean output_to_pipe; /**< save_file is a pipe (named or stdout) */ +#ifndef _WIN32 + uid_t owner; /**< owner of the cfile */ + gid_t group; /**< group of the cfile */ +#endif } capture_options; /* initialize the capture_options with some reasonable values */ diff --git a/configure.in b/configure.in index 4091926af1..46c949d916 100644 --- a/configure.in +++ b/configure.in @@ -193,7 +193,7 @@ AC_ARG_ENABLE(extra-gcc-checks, AC_WIRESHARK_GCC_CFLAGS_CHECK(-Wmissing-declarations) #Temporarily put cast-align here waiting eradication of 'cast #increases required alignment of target type' on the Solaris - #slave. + #slave. AC_WIRESHARK_GCC_CFLAGS_CHECK(-Wcast-align) fi ],) @@ -216,13 +216,13 @@ else fi # -# If we're running gcc, will enable a barrier "stop on warning". +# If we're running gcc, will enable a barrier "stop on warning". # This barrier is set for a very large part of the code. However, it is # typically not set for "generated" code (lex, ans2wrs, idl2wrs, ...) # AC_MSG_CHECKING(whether we should treat compiler warnings as errors) AC_ARG_ENABLE(warnings-as-errors, - AC_HELP_STRING( [--enable-warnings-as-errors], + AC_HELP_STRING( [--enable-warnings-as-errors], [Treat warnings as errors (only for gcc). @<:@default=yes@:>@]), [ if test "x$GCC" = "xyes" -a "x$enableval" == "xyes" -a "x$wireshark_extra_gcc_flags" != "xyes"; then @@ -453,7 +453,7 @@ if test "$HAVE_GNU_SED" = no ; then AC_MSG_CHECKING(whether one of /usr/bin/sed or /bin/sed or /usr/ucb/sed will be used) case `which sed` in /bin/sed|/usr/bin/sed|/usr/ucb/sed) - AC_MSG_RESULT(yes) + AC_MSG_RESULT(yes) AC_MSG_ERROR([change your path to search /usr/xpg4/bin or directory containing GNU sed before /usr/bin (and /bin and /usr/ucb)]) ;; @@ -1045,10 +1045,10 @@ fi dnl Check if wireshark should be installed setuid AC_ARG_ENABLE(setuid-install, AC_HELP_STRING( [--enable-setuid-install], - [install wireshark as setuid. DANGEROUS!!! @<:@default=no@:>@]), + [install tshark and dumpcap as setuid @<:@default=no@:>@]), enable_setuid_install=$enableval,enable_setuid_install=no) -AC_MSG_CHECKING(whether to install wireshark setuid) +AC_MSG_CHECKING(whether to install tshark and dumpcap setuid) if test "x$enable_setuid_install" = "xno" ; then AC_MSG_RESULT(no) else @@ -1063,7 +1063,7 @@ AM_CONDITIONAL(SETUID_INSTALL, test x$enable_setuid_install = xyes) dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(direct.h dirent.h fcntl.h netdb.h stdarg.h stddef.h unistd.h) +AC_CHECK_HEADERS(direct.h dirent.h fcntl.h grp.h netdb.h pwd.h stdarg.h stddef.h unistd.h) AC_CHECK_HEADERS(sys/ioctl.h sys/param.h sys/socket.h sys/sockio.h sys/stat.h sys/time.h sys/types.h sys/utsname.h sys/wait.h) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(arpa/inet.h arpa/nameser.h) @@ -1465,7 +1465,7 @@ AC_ARG_WITH(plugins, have_plugins=no elif test "x$have_plugins" = "xno"; then AC_MSG_ERROR([GLib on this platform doesn't support loadable modules, so you can't enable plugins.]) - if test "x$withval" != "xyes"; then + if test "x$withval" != "xyes"; then plugindir="$withval" fi fi @@ -1562,12 +1562,13 @@ AC_OUTPUT( tools/idl2wrs.sh tools/lemon/Makefile ,) +dnl AC_CONFIG_FILES([tools/setuid-root.pl], [chmod +x tools/setuid-root.pl]) # Pretty messages if test "x$enable_setuid_install" = "xyes" ; then - setuid_message="yes (DANGEROUS!!!)" + setuid_message="yes" else setuid_message="no" fi diff --git a/doc/README.packaging b/doc/README.packaging index 53d22a19ad..8404aee722 100644 --- a/doc/README.packaging +++ b/doc/README.packaging @@ -35,11 +35,15 @@ your package complies with this license, or we send in the marmots. In versions up to and including 0.99.6, it was necessary to run Wireshark with elevated privileges in order to be able to capture traffic. With version 0.99.7, all function calls that require elevated -privliges have been moved out of the GUI. +privliges have been moved out of the GUI to dumpcap. WIRESHARK CONTAINS OVER ONE POINT FIVE MILLION LINES OF SOURCE CODE. DO NOT RUN THEM AS ROOT. +If desired, you can use the configure option "--enable-setuid-install=yes" +to install dumpcap and TShark setuid root. This will allow normal users +to capture traffic. + 4. Customization. Custom version information can be added by creating a file called diff --git a/docbook/release-notes.xml b/docbook/release-notes.xml index cb35a12d93..5245a29c00 100644 --- a/docbook/release-notes.xml +++ b/docbook/release-notes.xml @@ -64,6 +64,23 @@ Wireshark Info The following features are new (or have been significantly updated) since the last release: + + + + + Most of the capture code has been moved out of the GUI, which + means that Wireshark no longer needs to be run as root. + + + + + + You can now filter directly on SNMP OIDs. + + + + + diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 936de36e73..edda89a3b6 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -412,6 +412,8 @@ get_column_longest_string get_column_title get_column_width_string get_credential_info +get_cur_groupname +get_cur_username get_datafile_path get_datafile_dir get_dirname @@ -734,6 +736,7 @@ rtp_free_hash_dyn_payload rtp_payload_type_vals DATA rtp_payload_type_short_vals DATA running_in_build_directory +running_with_special_privs rval_to_str sccp_message_type_acro_values DATA scsi_mmc_vals DATA diff --git a/epan/privileges.c b/epan/privileges.c index f4e740b692..4f0073e7de 100644 --- a/epan/privileges.c +++ b/epan/privileges.c @@ -29,6 +29,7 @@ #include #include "privileges.h" +#include "emem.h" #ifdef _WIN32 @@ -53,6 +54,18 @@ started_with_special_privs(void) return FALSE; } +/* + * For now, we say the program isn't running with special privileges. + * There are ways of running programs with credentials other than those + * for the session in which it's run, but I don't know whether that'd be + * done with Wireshark/TShark or not. + */ +gboolean +running_with_special_privs(void) +{ + return FALSE; +} + /* * For now, we don't do anything when asked to relinquish special privileges. */ @@ -61,6 +74,26 @@ relinquish_special_privs_perm(void) { } +/* + * Get the current username. String must be g_free()d after use. + */ +gchar * +get_cur_username(void) { + gchar *username; + username = g_strdup("UNKNOWN"); + return username; +} + +/* + * Get the current group. String must be g_free()d after use. + */ +gchar * +get_cur_groupname(void) { + gchar *groupname; + groupname = g_strdup("UNKNOWN"); + return groupname; +} + #else /* _WIN32 */ #ifdef HAVE_SYS_TYPES_H @@ -71,6 +104,18 @@ relinquish_special_privs_perm(void) #include #endif +#ifdef HAVE_PWD_H +#include +#endif + +#ifdef HAVE_GRP_H +#include +#endif + +#include +#include +#include + static uid_t ruid, euid; static gid_t rgid, egid; @@ -89,7 +134,8 @@ get_credential_info(void) } /* - * "Started with special privileges" means "started out set-UID or set-GID". + * "Started with special privileges" means "started out set-UID or set-GID", + * or run as the root user or group. */ gboolean started_with_special_privs(void) @@ -97,20 +143,101 @@ started_with_special_privs(void) #ifdef HAVE_ISSETUGID return issetugid(); #else - return (ruid != euid || rgid != egid); + return (ruid != euid || rgid != egid || ruid == 0 || rgid == 0); #endif } +/* + * Return TRUE if the real, effective, or saved (if we can check it) user + * ID or group are 0. + */ +gboolean +running_with_special_privs(void) +{ +#ifdef HAVE_SETRESUID + uid_t ru, eu, su; +#endif +#ifdef HAVE_SETRESGID + gid_t rg, eg, sg; +#endif + +#ifdef HAVE_SETRESUID + getresuid(&ru, &eu, &su); + if (ru == 0 || eu == 0 || su == 0) + return TRUE; +#else + if (getuid() == 0 || geteuid() == 0) + return TRUE; +#endif +#ifdef HAVE_SETRESGID + getresgid(&rg, &eg, &sg); + if (rg == 0 || eg == 0 || sg == 0) + return TRUE; +#else + if (getgid() == 0 || getegid() == 0) + return TRUE; +#endif + return FALSE; +} + /* * Permanently relinquish set-UID and set-GID privileges. * Ignore errors for now - if we have the privileges, we should * be able to relinquish them. */ + void relinquish_special_privs_perm(void) { - setuid(ruid); + /* If we're running setuid, switch to the calling user */ +#ifdef HAVE_SETRESGID + setresgid(rgid, rgid, rgid); +#else setgid(rgid); + setegid(rgid); +#endif + +#ifdef HAVE_SETRESUID + setresuid(ruid, ruid, ruid); +#else + setuid(ruid); + seteuid(ruid); +#endif + +} + +/* + * Get the current username. String must be g_free()d after use. + */ +gchar * +get_cur_username(void) { + gchar *username; + struct passwd *pw = getpwuid(getuid()); + + if (pw) { + username = g_strdup(pw->pw_name); + } else { + username = g_strdup("UNKNOWN"); + } + endpwent(); + return username; +} + +/* + * Get the current group. String must be g_free()d after use. + */ +gchar * +get_cur_groupname(void) { + gchar *groupname; + struct group *gr = getgrgid(getgid()); + + if (gr) { + groupname = g_strdup(gr->gr_name); + } else { + groupname = g_strdup("UNKNOWN"); + } + endgrent(); + return groupname; } #endif /* _WIN32 */ diff --git a/epan/privileges.h b/epan/privileges.h index 3e82c8d813..a3612e4936 100644 --- a/epan/privileges.h +++ b/epan/privileges.h @@ -22,18 +22,42 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* +/** * Called when the program starts, to save whatever credential information * we'll need later. */ extern void get_credential_info(void); -/* +/** * Was this program started with special privileges? + * @return TRUE if the program was started with special privileges, + * FALSE otherwise. */ extern gboolean started_with_special_privs(void); -/* +/** + * Is this program running with special privileges? + * @return TRUE if the program is running with special privileges, + * FALSE otherwise. + */ +extern gboolean running_with_special_privs(void); + +/** * Permanently relinquish special privileges. */ extern void relinquish_special_privs_perm(void); + +/** + * Get the current username. String must be g_free()d after use. + * @return A freshly g_alloc()ed string containing the username, + * or "UNKNOWN" on failure. + */ +extern gchar *get_cur_username(void); + +/** + * Get the current group. String must be g_free()d after use. + * @return A freshly g_alloc()ed string containing the group, + * or "UNKNOWN" on failure. + */ +extern gchar *get_cur_groupname(void); + diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index b7f9bae0f1..42e1ebd662 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -28,6 +28,10 @@ #ifdef HAVE_LIBPCAP +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include #include /* menu.h needs FILE */ diff --git a/gtk/drag_and_drop.c b/gtk/drag_and_drop.c index 623372b92a..7939f3ccb4 100644 --- a/gtk/drag_and_drop.c +++ b/gtk/drag_and_drop.c @@ -26,6 +26,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include "globals.h" @@ -82,7 +86,7 @@ dnd_uri2filename(gchar *cf_name) * * On UNIX (at least GNOME Nautilus 2.8.2), this prefix looks like: * file:///dir1/dir2/capture-file.cap - */ + */ if (strncmp("file:", cf_name, 5) == 0) { /* now becoming: /dir1/dir2/capture-file.cap or ///dir1/dir2/capture-file.cap */ cf_name += 5; @@ -91,14 +95,14 @@ dnd_uri2filename(gchar *cf_name) } #endif - /* + /* * unescape the escaped URI characters (spaces, ...) * - * we have to replace escaped chars to their equivalents, + * we have to replace escaped chars to their equivalents, * e.g. %20 (always a two digit hexstring) -> ' ' * the percent character '%' is escaped be a double one "%%" * - * we do this conversation "in place" as the result is always + * we do this conversation "in place" as the result is always * equal or smaller in size. */ src = cf_name; @@ -202,10 +206,10 @@ dnd_open_file_cmd(gchar *cf_names_freeme) int files_work; char **in_filenames; - + /* DND_TARGET_URL on Win32: * The cf_name_freeme is a single string, containing one or more URI's, - * seperated by CR/NL chars. The length of the whole field can be found + * seperated by CR/NL chars. The length of the whole field can be found * in the selection_data->length field. If it contains one file, simply open it, * If it contains more than one file, ask to merge these files. */ @@ -253,7 +257,7 @@ dnd_open_file_cmd(gchar *cf_names_freeme) default: /* build and show the info dialog */ dialog_text = g_string_sized_new(200); - g_string_append(dialog_text, PRIMARY_TEXT_START + g_string_append(dialog_text, PRIMARY_TEXT_START "Merging the following files:" PRIMARY_TEXT_END "\n\n"); for(files_work = 0; files_work < in_files; files_work++) { g_string_append(dialog_text, in_filenames[files_work]); @@ -274,7 +278,7 @@ dnd_open_file_cmd(gchar *cf_names_freeme) } /* ask the user to save current unsaved file, before opening the dnd file */ -static void +static void dnd_save_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data) { switch(btn) { @@ -296,17 +300,17 @@ dnd_save_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data) /* we have received some drag and drop data */ /* (as we only registered to "text/uri-list", we will only get a file list here) */ -static void -dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_, +static void +dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_, GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_) { gpointer dialog; gchar *cf_names_freeme; if (info == DND_TARGET_URL) { - /* Usually we block incoming events by disabling the corresponding menu/toolbar items. - * This is the only place where an incoming event won't be blocked in such a way, - * so we have to take care of NOT loading a new file while a different process + /* Usually we block incoming events by disabling the corresponding menu/toolbar items. + * This is the only place where an incoming event won't be blocked in such a way, + * so we have to take care of NOT loading a new file while a different process * (e.g. capture/load/...) is still in progress. */ #ifdef HAVE_LIBPCAP @@ -351,7 +355,7 @@ GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_) } /* init the drag and drop functionality */ -void +void dnd_init(GtkWidget *w) { /* we are only interested in the URI list containing filenames */ diff --git a/gtk/gsm_map_summary.c b/gtk/gsm_map_summary.c index 8a7f984752..df150edd2c 100644 --- a/gtk/gsm_map_summary.c +++ b/gtk/gsm_map_summary.c @@ -31,6 +31,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include diff --git a/gtk/main.c b/gtk/main.c index e6f69cae9b..ed9b470054 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -207,6 +207,7 @@ static GtkWidget *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2; static GtkWidget *main_first_pane, *main_second_pane; static GtkWidget *status_pane; static GtkWidget *menubar, *main_vbox, *main_tb, *stat_hbox, *filter_tb; +static GtkWidget *priv_warning_dialog; #ifdef HAVE_AIRPCAP GtkWidget *airpcap_tb; @@ -214,7 +215,7 @@ static GtkWidget *driver_warning_dialog; static int airpcap_dll_ret_val = -1; #endif -static GtkWidget *info_bar; +static GtkWidget *info_bar; static GtkWidget *packets_bar = NULL; static GtkWidget *welcome_pane; static guint main_ctx, file_ctx, help_ctx; @@ -1468,6 +1469,12 @@ set_display_filename(capture_file *cf) GtkWidget *close_dlg = NULL; +static void +priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_) +{ + recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog); +} + static void main_cf_cb_file_closing(capture_file *cf) { @@ -2135,6 +2142,7 @@ main(int argc, char *argv[]) guint go_to_packet = 0; int optind_initial; int status; + gchar *cur_user, *cur_group; #ifdef HAVE_AIRPCAP char *err_str; @@ -2152,16 +2160,13 @@ main(int argc, char *argv[]) char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] = OPTSTRING_INIT OPTSTRING_WIN32; -#ifdef HAVE_AIRPDCAP - /* Davide Schiera (2006-11-18): init AirPDcap context */ - AirPDcapInitContext(&airpdcap_ctx); - /* Davide Schiera (2006-11-18) ------------------------------------------- */ -#endif - /* - * Get credential information for later use. + * Get credential information for later use, and drop privileges + * before doing anything else. + * Let the user know if anything happened. */ get_credential_info(); + relinquish_special_privs_perm(); /* * Attempt to get the pathname of the executable file. @@ -2171,6 +2176,12 @@ main(int argc, char *argv[]) /* initialize the funnel mini-api */ initialize_funnel_ops(); +#ifdef HAVE_AIRPDCAP + /* Davide Schiera (2006-11-18): init AirPDcap context */ + AirPDcapInitContext(&airpdcap_ctx); + /* Davide Schiera (2006-11-18) ------------------------------------------- */ +#endif + #ifdef _WIN32 /* Load wpcap if possible. Do this before collecting the run-time version information */ load_wpcap(); @@ -2911,6 +2922,19 @@ main(int argc, char *argv[]) /* the window can be sized only, if it's not already shown, so do it now! */ main_load_window_geometry(top_level); + /* Tell the user not to run as root. */ + if (running_with_special_privs() && recent.privs_warn_if_elevated) { + cur_user = get_cur_username(); + cur_group = get_cur_groupname(); + priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, + "Running as user \"%s\" and group \"%s\".\n" + "This could be dangerous.", cur_user, cur_group); + g_free(cur_user); + g_free(cur_group); + simple_dialog_check_set(priv_warning_dialog, "Don't show this message again."); + simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL); + } + /* If we were given the name of a capture file, read it in now; we defer it until now, so that, if we can't open it, and pop up an alert box, the alert box is more likely to come up on @@ -4822,7 +4846,7 @@ show_main_window(gboolean doing_work) "does not support driver-level decryption. Please\n" "download a more recent version from\n" "http://www.cacetech.com/support/downloads.htm \n"); simple_dialog_check_set(driver_warning_dialog,"Don't show this message again."); - simple_dialog_set_cb(driver_warning_dialog, driver_warning_dialog_cb, (gpointer) driver_warning_dialog); + simple_dialog_set_cb(driver_warning_dialog, driver_warning_dialog_cb, NULL); } break; diff --git a/gtk/mtp3_summary.c b/gtk/mtp3_summary.c index 0c4995cf78..e10a6805df 100644 --- a/gtk/mtp3_summary.c +++ b/gtk/mtp3_summary.c @@ -31,6 +31,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include @@ -216,7 +220,7 @@ mtp3_sum_draw( entries[1] = g_strdup_printf("%u", num_msus); entries[2] = (seconds) ? g_strdup_printf("%.2f", num_msus/seconds) : "N/A"; - + entries[3] = g_strdup_printf("%.0f", num_bytes); entries[4] = (num_msus) ? g_strdup_printf("%.2f", num_bytes/num_msus) : "N/A"; diff --git a/gtk/packet_win.c b/gtk/packet_win.c index ffd8faf105..6ffd70f8f8 100644 --- a/gtk/packet_win.c +++ b/gtk/packet_win.c @@ -35,6 +35,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include diff --git a/gtk/recent.c b/gtk/recent.c index 929c65558b..7b78d11294 100644 --- a/gtk/recent.c +++ b/gtk/recent.c @@ -51,8 +51,8 @@ #define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show" #define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show" -#define RECENT_KEY_AIRPCAP_TOOLBAR_SHOW "gui.airpcap_toolbar_show" -#define RECENT_KEY_DRIVER_CHECK_SHOW "gui.airpcap_driver_check_show" +#define RECENT_KEY_AIRPCAP_TOOLBAR_SHOW "gui.airpcap_toolbar_show" +#define RECENT_KEY_DRIVER_CHECK_SHOW "gui.airpcap_driver_check_show" #define RECENT_KEY_PACKET_LIST_SHOW "gui.packet_list_show" #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show" #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show" @@ -70,7 +70,8 @@ #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane" #define RECENT_GUI_GEOMETRY_STATUS_PANE "gui.geometry_status_pane" #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir" -#define RECENT_GUI_GEOMETRY "gui.geom." +#define RECENT_GUI_GEOMETRY "gui.geom." +#define RECENT_KEY_PRIVS_WARN_IF_ELEVATED "privs.warn_if_elevated" #define RECENT_FILE_NAME "recent" @@ -258,6 +259,11 @@ write_recent(void) recent.gui_geometry_status_pane); } + fprintf(rf, "\n# Warn if running with elevated permissions (e.g. as root).\n"); + fprintf(rf, "# TRUE or FALSE (case-insensitive).\n"); + fprintf(rf, RECENT_KEY_PRIVS_WARN_IF_ELEVATED ": %s\n", + recent.privs_warn_if_elevated == TRUE ? "TRUE" : "FALSE"); + if (get_last_open_dir() != NULL) { fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n"); @@ -452,6 +458,13 @@ read_set_recent_pair_static(gchar *key, gchar *value, void *private_data _U_) sub_key++; window_geom_recent_read_pair(win, sub_key, value); } + } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_ELEVATED) == 0) { + if (strcasecmp(value, "true") == 0) { + recent.privs_warn_if_elevated = TRUE; + } + else { + recent.privs_warn_if_elevated = FALSE; + } } return PREFS_SET_OK; @@ -564,6 +577,8 @@ recent_read_static(char **rf_path_return, int *rf_errno_return) recent.has_gui_geometry_status_pane = FALSE; #endif + recent.privs_warn_if_elevated = TRUE; + /* Construct the pathname of the user's recent file. */ rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE); diff --git a/gtk/recent.h b/gtk/recent.h index f1a003c918..a5dc1937e1 100644 --- a/gtk/recent.h +++ b/gtk/recent.h @@ -43,8 +43,8 @@ typedef struct recent_settings_tag { gboolean main_toolbar_show; gboolean filter_toolbar_show; - gboolean airpcap_toolbar_show; - gboolean airpcap_driver_check_show; + gboolean airpcap_toolbar_show; + gboolean airpcap_driver_check_show; gboolean packet_list_show; gboolean tree_view_show; gboolean byte_view_show; @@ -67,6 +67,7 @@ typedef struct recent_settings_tag { gint gui_geometry_main_lower_pane; /* this is autodetected in GTK2 only */ gboolean has_gui_geometry_status_pane; /* gui_geometry_status_pane is valid */ gint gui_geometry_status_pane; /* this is autodetected in GTK2 only */ + gboolean privs_warn_if_elevated; } recent_settings_t; /** Global recent settings. */ diff --git a/gtk/summary_dlg.c b/gtk/summary_dlg.c index d749048989..d4b3e3e058 100644 --- a/gtk/summary_dlg.c +++ b/gtk/summary_dlg.c @@ -26,6 +26,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include @@ -191,10 +195,10 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_) /* elapsed seconds */ elapsed_time = (unsigned int)summary.elapsed_time; if(elapsed_time/86400) { - g_snprintf(string_buff, SUM_STR_MAX, "%02u days %02u:%02u:%02u", + g_snprintf(string_buff, SUM_STR_MAX, "%02u days %02u:%02u:%02u", elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60); } else { - g_snprintf(string_buff, SUM_STR_MAX, "%02u:%02u:%02u", + g_snprintf(string_buff, SUM_STR_MAX, "%02u:%02u:%02u", elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60); } add_string_to_table(table, &row, "Elapsed:", string_buff); @@ -254,7 +258,7 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_) str_work = g_strdup(&str_dup[offset]); snip++; } - + add_string_to_table(table, &row, (snip == 0) ? "Display filter:" : "", str_work); g_free(str_work); g_free(str_dup); @@ -351,7 +355,7 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_) strcpy(string_buff, ""); } if (summary.dfilter && disp_seconds > 0){ - g_snprintf(string_buff2, SUM_STR_MAX, "%.3f", + g_snprintf(string_buff2, SUM_STR_MAX, "%.3f", /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */ ((gint64) summary.filtered_bytes) * 8.0 / (disp_seconds * 1000.0 * 1000.0)); } else { @@ -359,7 +363,7 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_) } add_string_to_list(list, "Avg. MBit/sec", string_buff, string_buff2); - + /* Button row. */ if(topic_available(HELP_STATS_SUMMARY_DIALOG)) { bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL); diff --git a/summary.c b/summary.c index 0ac1b8a5f1..528bbfc556 100644 --- a/summary.c +++ b/summary.c @@ -26,6 +26,10 @@ # include "config.h" #endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include "cfile.h" #include "summary.h" diff --git a/tools/Makefile.am b/tools/Makefile.am index 4bb4a22458..847a06a621 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -103,6 +103,15 @@ EXTRA_DIST = \ wireshark_gen.py \ yacc.py +noinst_SCRIPTS = setuid-root.pl +setuid-root.pl: setuid-root.pl.in Makefile + sed \ + -e 's,@BIN_PREFIX\@,$(bindir),' \ + -e 's,@TSHARK_BIN\@,$(tshark_bin)$(EEXT),' \ + -e 's,@DUMPCAP_BIN\@,$(dumpcap_bin)$(EEXT),' \ + < setuid-root.pl.in > setuid-root.pl + chmod +x setuid-root.pl + MAINTAINERCLEANFILES = \ Makefile.in diff --git a/tshark.c b/tshark.c index 4b73dbef06..e9931a3beb 100644 --- a/tshark.c +++ b/tshark.c @@ -669,6 +669,25 @@ output_file_description(const char *fname) return save_file_string; } +static void +print_current_user() { + gchar *cur_user, *cur_group; + if (started_with_special_privs()) { + cur_user = get_cur_username(); + cur_group = get_cur_groupname(); + fprintf(stderr, "Running as user \"%s\" and group \"%s\".", + cur_user, cur_group); + g_free(cur_user); + g_free(cur_group); + if (running_with_special_privs()) { + fprintf(stderr, " This could be dangerous."); + } + fprintf(stderr, "\n"); + } +} + + + int main(int argc, char *argv[]) { @@ -1452,6 +1471,7 @@ main(int argc, char *argv[]) * can't open. */ relinquish_special_privs_perm(); + print_current_user(); if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) { epan_cleanup(); @@ -1631,6 +1651,7 @@ capture(void) * not special privileges. */ relinquish_special_privs_perm(); + print_current_user(); /* init the input filter from the network interface (capture pipe will do nothing) */ switch (capture_loop_init_filter(ld.pcap_h, ld.from_cap_pipe, capture_opts.iface, capture_opts.cfilter)) {