diff --git a/doc/sshdump.adoc b/doc/sshdump.adoc index 5165aefb91..9b86db4976 100644 --- a/doc/sshdump.adoc +++ b/doc/sshdump.adoc @@ -26,11 +26,17 @@ sshdump - Provide interfaces to capture from a remote host through SSH using a r [ *--remote-port*= ] [ *--remote-username*= ] [ *--remote-password*= ] -[ *--sshkey*= ] +[ *--sshkey*= ] +[ *--sshkey-passphrase*= ] +[ *--proxycommand*= ] [ *--remote-interface*= ] [ *--remote-capture-command-select*= ] [ *--remote-capture-command*= ] -[ *--remote-sudo* ] +[ *--remote-priv*= ] +[ *--remote-priv-user*= ] +[ *--remote-noprom* ] +[ *--remote-filter*= ] +[ *--remote-count*= ] [manarg] *sshdump* @@ -128,6 +134,14 @@ List DLTs of specified interface. List configuration options of specified interface. -- +--extcap-capture-filter=:: ++ +-- +The capture filter. It corresponds to the value provided via the *tshark -f* +option, and the Capture Filter field next to the interfaces list in the +Wireshark interface. +-- + --capture:: + -- @@ -172,6 +186,18 @@ recommended to use keyfiles with a SSH agent. The path to a private key for authentication. NOTE: Only OPENSSH key/value pair format is supported. -- +--sshkey-passphrase=:: ++ +-- +The passphrase for the private key for authentication. +-- + +--proxycommand=:: ++ +-- +The command to use as proxy for the SSH connection. +-- + --remote-interface=:: + -- @@ -204,14 +230,33 @@ When specified, this command will be used as is, options such as the capture filter (*--extcap-capture-filter*) will not be appended. -- ---extcap-capture-filter=:: +--remote-priv=:: + -- -The capture filter. It corresponds to the value provided via the *tshark -f* +The command to use to achieve privilege elevation to capture on the remote host. Either none, sudo or doas. +-- + +--remote-priv-user=:: ++ +-- +If a command is used to achieve privilege elevation to capture on the remote host this may require a user name. +If needed use this option to give that user name. +-- + +--remote-filter=:: ++ +-- +The remote capture filter. It corresponds to the value provided via the *tshark -f* option, and the Capture Filter field next to the interfaces list in the Wireshark interface. -- +--remote-count=:: ++ +-- +The number of packets to capture. +-- + == EXAMPLES To see program arguments: @@ -245,7 +290,7 @@ To see interface configuration options: .Example output arg {number=0}{call=--remote-host}{display=Remote SSH server address}{type=string} {tooltip=The remote SSH host. It can be both an IP address or a hostname}{required=true}{group=Server} - arg {number=1}{call=--remote-port}{display=Remote SSH server port}{type=unsigned} + arg {number=1}{call=--remote-port}{display=Remote SSH server port}{type=unsigned}{default=22} {tooltip=The remote SSH host port (1-65535)}{range=1,65535}{group=Server} arg {number=2}{call=--remote-username}{display=Remote SSH server username}{type=string} {tooltip=The remote SSH username. If not provided, the current user will be used}{group=Authentication} @@ -266,21 +311,26 @@ To see interface configuration options: value {arg=8}{value=other}{display=Other:} arg {number=9}{call=--remote-capture-command}{display=Remote capture command}{type=string} {tooltip=The remote command used to capture}{group=Capture} - arg {number=10}{call=--remote-sudo}{display=Use sudo on the remote machine}{type=boolflag} - {tooltip=Prepend the capture command with sudo on the remote machine}{group=Capture} - arg {number=11}{call=--remote-noprom}{display=No promiscuous mode}{type=boolflag} + arg {number=10}{call=--remote-priv}{display=Gain capture privilege on the remote machine}{type=radio} + {tooltip=Optionally prepend the capture command with sudo or doas on the remote machine}{group=Capture} + value {arg=10}{value=none}{display=none}{default=true} + value {arg=10}{value=sudo}{display=sudo} + value {arg=10}{value=doas -n}{display=doas} + arg {number=11}{call=--remote-priv-user}{display=Privileged user name for sudo or doas}{type=string} + {tooltip=User name of privileged user to execute the capture command on the remote machine}{group=Capture} + arg {number=12}{call=--remote-noprom}{display=No promiscuous mode}{type=boolflag} {tooltip=Don't use promiscuous mode on the remote machine}{group=Capture} - arg {number=12}{call=--remote-filter}{display=Remote capture filter}{type=string} + arg {number=13}{call=--remote-filter}{display=Remote capture filter}{type=string} {tooltip=The remote capture filter}{default=not ((host myhost) and port 22)}{group=Capture} - arg {number=13}{call=--remote-count}{display=Packets to capture}{type=unsigned}{default=0} + arg {number=14}{call=--remote-count}{display=Packets to capture}{type=unsigned}{default=0} {tooltip=The number of remote packets to capture. (Default: inf)}{group=Capture} - arg {number=14}{call=--log-level}{display=Set the log level}{type=selector} + arg {number=15}{call=--log-level}{display=Set the log level}{type=selector} {tooltip=Set the log level}{required=false}{group=Debug} value {arg=14}{value=message}{display=Message}{default=true} value {arg=14}{value=info}{display=Info} value {arg=14}{value=debug}{display=Debug} value {arg=14}{value=noisy}{display=Noisy} - arg {number=15}{call=--log-file}{display=Use a file for logging}{type=fileselect} + arg {number=16}{call=--log-file}{display=Use a file for logging}{type=fileselect} {tooltip=Set a file where log messages are written}{required=false}{group=Debug} @@ -291,6 +341,10 @@ To capture: To use different capture binaries: + sshdump --extcap-interface=sshdump --fifo=/tmp/ssh.pcap --capture --remote-host 192.168.1.10 + --remote-username user --remote-priv sudo --remote-capture-command-select tcpdump + --remote-interface eth0 --remote-noprom + sshdump --extcap-interface=sshdump --fifo=/tmp/ssh.pcap --capture --remote-host 192.168.1.10 --remote-capture-command='dumpcap -i eth0 -P -w -' diff --git a/epan/prefs.c b/epan/prefs.c index ed88801f6b..e34072d6cc 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -6016,16 +6016,27 @@ set_pref(gchar *pref_name, const gchar *value, void *private_data _U_, } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) { pref = prefs_find_preference(nameres_module, "suppress_smi_errors"); } + } else if (strcmp(module->name, "extcap") == 0) { + /* Handle the old "sshdump.remotesudo" preference; map it to the new + "sshdump.remotepriv" preference, and map the boolean values to the + appropriate strings of the new preference. */ + if (strcmp(dotp, "sshdump.remotesudo") == 0) { + pref = prefs_find_preference(module, "sshdump.remotepriv"); + if (g_ascii_strcasecmp(value, "true") == 0) + value = "sudo"; + else + value = "none"; + } } } if (pref == NULL ) { if (strcmp(module->name, "extcap") == 0 && g_list_length(module->prefs) <= 1) { - /* - * Assume that we've skipped extcap preference registration - * and that only extcap.gui_save_on_start is loaded. - */ - return PREFS_SET_OK; - } + /* + * Assume that we've skipped extcap preference registration + * and that only extcap.gui_save_on_start is loaded. + */ + return PREFS_SET_OK; + } return PREFS_SET_NO_SUCH_PREF; /* no such preference */ } diff --git a/extcap/sshdump.c b/extcap/sshdump.c index 9323014125..039ba2b392 100644 --- a/extcap/sshdump.c +++ b/extcap/sshdump.c @@ -37,7 +37,7 @@ static gchar* sshdump_extcap_interface; #endif #define SSHDUMP_VERSION_MAJOR "1" -#define SSHDUMP_VERSION_MINOR "1" +#define SSHDUMP_VERSION_MINOR "2" #define SSHDUMP_VERSION_RELEASE "0" #define SSH_READ_BLOCK_SIZE 256 @@ -58,7 +58,9 @@ enum { OPT_SSHKEY_PASSPHRASE, OPT_PROXYCOMMAND, OPT_REMOTE_COUNT, - OPT_REMOTE_SUDO, + OPT_REMOTE_SUDO, // Deprecated + OPT_REMOTE_PRIV, + OPT_REMOTE_PRIV_USER, OPT_REMOTE_NOPROM }; @@ -69,7 +71,9 @@ static struct ws_option longopts[] = { SSH_BASE_OPTIONS, { "remote-capture-command-select", ws_required_argument, NULL, OPT_REMOTE_CAPTURE_COMMAND_SELECT}, { "remote-capture-command", ws_required_argument, NULL, OPT_REMOTE_CAPTURE_COMMAND}, - { "remote-sudo", ws_no_argument, NULL, OPT_REMOTE_SUDO }, + { "remote-sudo", ws_no_argument, NULL, OPT_REMOTE_SUDO }, // Deprecated + { "remote-priv", ws_required_argument, NULL, OPT_REMOTE_PRIV }, + { "remote-priv-user", ws_required_argument, NULL, OPT_REMOTE_PRIV_USER }, { "remote-noprom", ws_no_argument, NULL, OPT_REMOTE_NOPROM }, { 0, 0, 0, 0} }; @@ -130,7 +134,7 @@ static char* local_interfaces_to_filter(const guint16 remote_port) } static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command_select, - const char* capture_command, const gboolean use_sudo, gboolean noprom, + const char* capture_command, const char* privilege, gboolean noprom, const char* iface, const char* cfilter, const guint32 count) { gchar* cmdline = NULL; @@ -175,7 +179,7 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command count_str = ws_strdup_printf("-c %u", count); cmdline = ws_strdup_printf("%s tcpdump -U %s%s %s -w - %s %s", - use_sudo ? "sudo" : "", + privilege, quoted_iface ? "-i " : "", quoted_iface ? quoted_iface : "", noprom ? "-p" : "", @@ -196,7 +200,7 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command count_str = ws_strdup_printf("-c %u", count); cmdline = ws_strdup_printf("%s dumpcap %s %s -w - %s -f %s", - use_sudo ? "sudo" : "", + privilege, noprom ? "-p" : "", *ifaces ? ifaces : "", count_str ? count_str : "", @@ -223,7 +227,7 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command } static int ssh_open_remote_connection(const ssh_params_t* params, const char* iface, const char* cfilter, - const char* capture_command_select, const char* capture_command, const gboolean use_sudo, + const char* capture_command_select, const char* capture_command, const char* privilege, gboolean noprom, const guint32 count, const char* fifo) { ssh_session sshs = NULL; @@ -248,7 +252,7 @@ static int ssh_open_remote_connection(const ssh_params_t* params, const char* if goto cleanup; } - channel = run_ssh_command(sshs, capture_command_select, capture_command, use_sudo, noprom, iface, cfilter, count); + channel = run_ssh_command(sshs, capture_command_select, capture_command, privilege, noprom, iface, cfilter, count); if (!channel) { ws_warning("Can't run ssh command."); @@ -323,7 +327,7 @@ static int list_config(char *interface, unsigned int remote_port) "{type=string}{tooltip=The remote SSH host. It can be both " "an IP address or a hostname}{required=true}{group=Server}\n", inc++); printf("arg {number=%u}{call=--remote-port}{display=Remote SSH server port}" - "{type=unsigned}{tooltip=The remote SSH host port (1-65535)}" + "{type=unsigned}{default=22}{tooltip=The remote SSH host port (1-65535)}" "{range=1,65535}{group=Server}\n", inc++); printf("arg {number=%u}{call=--remote-username}{display=Remote SSH server username}" "{type=string}{tooltip=The remote SSH username. If not provided, " @@ -350,8 +354,18 @@ static int list_config(char *interface, unsigned int remote_port) printf("value {arg=%u}{value=other}{display=Other:}\n", inc++); printf("arg {number=%u}{call=--remote-capture-command}{display=Remote capture command}" "{type=string}{tooltip=The remote command used to capture}{group=Capture}\n", inc++); - printf("arg {number=%u}{call=--remote-sudo}{display=Use sudo on the remote machine}" - "{type=boolflag}{tooltip=Prepend the capture command with sudo on the remote machine}" + // Deprecated + //printf("arg {number=%u}{call=--remote-sudo}{display=Use sudo on the remote machine}" + // "{type=boolflag}{tooltip=Prepend the capture command with sudo on the remote machine}" + // "{group=Capture}\n", inc++); + printf("arg {number=%u}{call=--remote-priv}{display=Gain capture privilege on the remote machine}" + "{type=radio}{tooltip=Optionally prepend the capture command with sudo or doas on the remote machine}" + "{group=Capture}\n", inc); + printf("value {arg=%u}{value=none}{display=none}{default=true}\n", inc); + printf("value {arg=%u}{value=sudo}{display=sudo}\n", inc); + printf("value {arg=%u}{value=doas -n}{display=doas}\n", inc++); + printf("arg {number=%u}{call=--remote-priv-user}{display=Privileged user name for sudo or doas}" + "{type=string}{tooltip=User name of privileged user to execute the capture command on the remote machine}" "{group=Capture}\n", inc++); printf("arg {number=%u}{call=--remote-noprom}{display=No promiscuous mode}" "{type=boolflag}{tooltip=Don't use promiscuous mode on the remote machine}{group=Capture}" @@ -401,7 +415,8 @@ int main(int argc, char *argv[]) extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1); char* help_url; char* help_header = NULL; - gboolean use_sudo = FALSE; + char* priv = NULL; + char* priv_user = NULL; gboolean noprom = FALSE; gchar* interface_description = g_strdup("SSH remote capture"); @@ -461,7 +476,9 @@ int main(int argc, char *argv[]) extcap_help_add_option(extcap_conf, "--remote-interface ", "the remote capture interface"); extcap_help_add_option(extcap_conf, "--remote-capture-command-select ", "dumpcap, tcpdump or other remote capture command"); extcap_help_add_option(extcap_conf, "--remote-capture-command ", "the remote capture command"); - extcap_help_add_option(extcap_conf, "--remote-sudo", "use sudo on the remote machine to capture"); + //extcap_help_add_option(extcap_conf, "--remote-sudo", "use sudo on the remote machine to capture"); // Deprecated + extcap_help_add_option(extcap_conf, "--remote-priv ", "none, sudo or doas"); + extcap_help_add_option(extcap_conf, "--remote-priv-user ", "privileged user name"); extcap_help_add_option(extcap_conf, "--remote-noprom", "don't use promiscuous mode on the remote machine"); extcap_help_add_option(extcap_conf, "--remote-filter ", "a filter for remote capture (default: don't listen on local interfaces IPs)"); extcap_help_add_option(extcap_conf, "--remote-count ", "the number of packets to capture"); @@ -543,7 +560,19 @@ int main(int argc, char *argv[]) break; case OPT_REMOTE_SUDO: - use_sudo = TRUE; + // Deprecated + g_free(priv); + priv = g_strdup("sudo"); + break; + + case OPT_REMOTE_PRIV: + g_free(priv); + priv = g_strdup(ws_optarg); + break; + + case OPT_REMOTE_PRIV_USER: + g_free(priv_user); + priv_user = g_strdup(ws_optarg); break; case OPT_REMOTE_FILTER: @@ -597,17 +626,30 @@ int main(int argc, char *argv[]) if (extcap_conf->capture) { char* filter; + char* privilege; if (!ssh_params->host) { ws_warning("Missing parameter: --remote-host"); goto end; } + + if ((priv) && g_strcmp0(priv, "none") && strlen(g_strstrip(priv))) { + if ((priv_user) && strlen(g_strstrip(priv_user))) + /* Both sudo and doas use the same command line option */ + privilege = g_strconcat(priv, " -u ", priv_user, NULL); + else + privilege = g_strdup(priv); + } else { + privilege = g_strdup(""); + } + filter = concat_filters(extcap_conf->capture_filter, remote_filter); ssh_params->debug = extcap_conf->debug; ret = ssh_open_remote_connection(ssh_params, remote_interface, filter, remote_capture_command_select, remote_capture_command, - use_sudo, noprom, count, extcap_conf->fifo); + privilege, noprom, count, extcap_conf->fifo); g_free(filter); + g_free(privilege); } else { ws_debug("You should not come here... maybe some parameter missing?"); ret = EXIT_FAILURE; @@ -620,6 +662,8 @@ end: g_free(remote_capture_command); g_free(remote_interface); g_free(remote_filter); + g_free(priv); + g_free(priv_user); extcap_base_cleanup(&extcap_conf); return ret; }