diff --git a/doc/sshdump.adoc b/doc/sshdump.adoc index 66dfdf0eb4..5165aefb91 100644 --- a/doc/sshdump.adoc +++ b/doc/sshdump.adoc @@ -28,6 +28,7 @@ sshdump - Provide interfaces to capture from a remote host through SSH using a r [ *--remote-password*= ] [ *--sshkey*= ] [ *--remote-interface*= ] +[ *--remote-capture-command-select*= ] [ *--remote-capture-command*= ] [ *--remote-sudo* ] @@ -154,7 +155,7 @@ The SSH port of the remote host. --remote-username=:: + -- -The username for ssh authentication. +The username for SSH authentication. -- --remote-password=:: @@ -177,6 +178,17 @@ The path to a private key for authentication. NOTE: Only OPENSSH key/value pair The remote network interface to capture from. -- +--remote-capture-command-select=:: ++ +-- +The selection of the build-in support for remote capture commands. Either *dumpcap* for a remote +capture command using dumpcap, *tcpdump* for a remote capture command using tcpdump, or *other*, +where the remote capture command is to be given with the *--remote-capture-command* option. + +Note that selecting dumpcap allows for specifying multiple capture interfaces as a whitespace +seperated list, while tcpdump does not. +-- + --remote-capture-command=:: + -- @@ -240,27 +252,37 @@ To see interface configuration options: arg {number=3}{call=--remote-password}{display=Remote SSH server password}{type=password} {tooltip=The SSH password, used when other methods (SSH agent or key files) are unavailable.}{group=Authentication} arg {number=4}{call=--sshkey}{display=Path to SSH private key}{type=fileselect} - {tooltip=The path on the local filesystem of the private ssh key}{group=Authentication} + {tooltip=The path on the local filesystem of the private SSH key (OpenSSH format)}{mustexist=true}{group=Authentication} arg {number=5}{call=--sshkey-passphrase}{display=SSH key passphrase}{type=password} - {tooltip=Passphrase to unlock the SSH private key}{group=Authentication (OPENSSH format)} + {tooltip=Passphrase to unlock the SSH private key}{group=Authentication} arg {number=6}{call=--proxycommand}{display=ProxyCommand}{type=string} {tooltip=The command to use as proxy for the SSH connection}{group=Authentication} arg {number=7}{call=--remote-interface}{display=Remote interface}{type=string} {tooltip=The remote network interface used for capture}{group=Capture} - arg {number=8}{call=--remote-capture-command}{display=Remote capture command}{type=string} + arg {number=8}{call=--remote-capture-command-select}{display=Remote capture command selection}{type=radio} + {tooltip=The remote capture command to build a command line for}{group=Capture} + value {arg=8}{value=dumpcap}{display=dumpcap} + value {arg=8}{value=tcpdump}{display=tcpdump}{default=true} + 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=9}{call=--remote-sudo}{display=Use sudo on the remote machine}{type=boolean} + 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=10}{call=--remote-noprom}{display=No promiscuous mode}{type=boolflag} + arg {number=11}{call=--remote-noprom}{display=No promiscuous mode}{type=boolflag} {tooltip=Don't use promiscuous mode on the remote machine}{group=Capture} - arg {number=11}{call=--remote-filter}{display=Remote capture filter}{type=string} + arg {number=12}{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=12}{call=--remote-count}{display=Packets to capture}{type=unsigned}{default=0} + arg {number=13}{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=13}{call=--debug}{display=Run in debug mode}{type=boolflag}{default=false} - {tooltip=Print debug messages}{required=false}{group=Debug} - arg {number=14}{call=--debug-file}{display=Use a file for debug}{type=string} - {tooltip=Set a file where the debug messages are written}{required=false}{group=Debug} + arg {number=14}{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} + {tooltip=Set a file where log messages are written}{required=false}{group=Debug} + To capture: diff --git a/extcap/sshdump.c b/extcap/sshdump.c index f9b4d9e292..298aa8c1f9 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 "0" +#define SSHDUMP_VERSION_MINOR "1" #define SSHDUMP_VERSION_RELEASE "0" #define SSH_READ_BLOCK_SIZE 256 @@ -51,6 +51,7 @@ enum { OPT_REMOTE_USERNAME, OPT_REMOTE_PASSWORD, OPT_REMOTE_INTERFACE, + OPT_REMOTE_CAPTURE_COMMAND_SELECT, OPT_REMOTE_CAPTURE_COMMAND, OPT_REMOTE_FILTER, OPT_SSHKEY, @@ -66,6 +67,7 @@ static struct ws_option longopts[] = { { "help", ws_no_argument, NULL, OPT_HELP}, { "version", ws_no_argument, NULL, OPT_VERSION}, 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-noprom", ws_no_argument, NULL, OPT_REMOTE_NOPROM }, @@ -127,11 +129,16 @@ static char* local_interfaces_to_filter(const guint16 remote_port) return filter; } -static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command, const gboolean use_sudo, gboolean noprom, +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* iface, const char* cfilter, const guint32 count) { gchar* cmdline; ssh_channel channel; + char** ifaces_array = NULL; + int ifaces_array_num = 0; + GString *ifaces_string; + gchar *ifaces; char* quoted_iface = NULL; char* quoted_filter = NULL; char* count_str = NULL; @@ -151,11 +158,17 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command ssh_options_get_port(sshs, &remote_port); + if (capture_command_select == NULL || g_strcmp0(capture_command_select, "other")) { + if (capture_command && *capture_command) { + cmdline = g_strdup(capture_command); + ws_debug("Remote capture command has disabled other options"); + } else { + capture_command_select = "tcpdump"; + } + } + /* escape parameters to go save with the shell */ - if (capture_command && *capture_command) { - cmdline = g_strdup(capture_command); - ws_debug("Remote capture command has disabled other options"); - } else { + if (!g_strcmp0(capture_command_select, "tcpdump")) { quoted_iface = iface ? g_shell_quote(iface) : NULL; quoted_filter = g_shell_quote(cfilter ? cfilter : ""); if (count > 0) @@ -168,6 +181,29 @@ static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command noprom ? "-p" : "", count_str ? count_str : "", quoted_filter); + } else if (!g_strcmp0(capture_command_select, "dumpcap")) { + ifaces_array = g_strsplit(iface, " ", -1); + ifaces_string = g_string_new(NULL); + while (ifaces_array[ifaces_array_num]) + { + quoted_iface = g_shell_quote(ifaces_array[ifaces_array_num]); + g_string_append_printf(ifaces_string, "-i %s ", quoted_iface); + ifaces_array_num++; + } + ifaces = g_string_free(ifaces_string, FALSE); + quoted_filter = g_shell_quote(cfilter ? cfilter : ""); + if (count > 0) + count_str = ws_strdup_printf("-c %u", count); + + cmdline = ws_strdup_printf("%s dumpcap %s %s -w - %s %s", + use_sudo ? "sudo" : "", + noprom ? "-p" : "", + *ifaces ? ifaces : "", + count_str ? count_str : "", + quoted_filter); + + g_free(ifaces); + g_strfreev(ifaces_array); } ws_debug("Running: %s", cmdline); @@ -187,7 +223,8 @@ 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, const gboolean use_sudo, gboolean noprom, const guint32 count, const char* fifo) + const char* capture_command_select, const char* capture_command, const gboolean use_sudo, + gboolean noprom, const guint32 count, const char* fifo) { ssh_session sshs = NULL; ssh_channel channel = NULL; @@ -211,7 +248,7 @@ static int ssh_open_remote_connection(const ssh_params_t* params, const char* if goto cleanup; } - channel = run_ssh_command(sshs, capture_command, use_sudo, noprom, iface, cfilter, count); + channel = run_ssh_command(sshs, capture_command_select, capture_command, use_sudo, noprom, iface, cfilter, count); if (!channel) { ws_warning("Can't run ssh command."); @@ -295,7 +332,7 @@ static int list_config(char *interface, unsigned int remote_port) "{type=password}{tooltip=The SSH password, used when other methods (SSH agent " "or key files) are unavailable.}{group=Authentication}\n", inc++); printf("arg {number=%u}{call=--sshkey}{display=Path to SSH private key}" - "{type=fileselect}{tooltip=The path on the local filesystem of the private ssh key (OPENSSH format)}" + "{type=fileselect}{tooltip=The path on the local filesystem of the private SSH key (OpenSSH format)}" "{mustexist=true}{group=Authentication}\n", inc++); printf("arg {number=%u}{call=--sshkey-passphrase}{display=SSH key passphrase}" "{type=password}{tooltip=Passphrase to unlock the SSH private key}{group=Authentication}\n", @@ -306,6 +343,11 @@ static int list_config(char *interface, unsigned int remote_port) printf("arg {number=%u}{call=--remote-interface}{display=Remote interface}" "{type=string}{tooltip=The remote network interface used for capture" "}{group=Capture}\n", inc++); + printf("arg {number=%u}{call=--remote-capture-command-select}{display=Remote capture command selection}" + "{type=radio}{tooltip=The remote capture command to build a command line for}{group=Capture}\n", inc); + printf("value {arg=%u}{value=dumpcap}{display=dumpcap}\n", inc); + printf("value {arg=%u}{value=tcpdump}{display=tcpdump}{default=true}\n", inc); + 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}" @@ -351,6 +393,7 @@ int main(int argc, char *argv[]) int option_idx = 0; ssh_params_t* ssh_params = ssh_params_new(); char* remote_interface = NULL; + char* remote_capture_command_select = NULL; char* remote_capture_command = NULL; char* remote_filter = NULL; guint32 count = 0; @@ -412,15 +455,15 @@ int main(int argc, char *argv[]) extcap_help_add_option(extcap_conf, "--remote-port ", "the remote SSH port"); extcap_help_add_option(extcap_conf, "--remote-username ", "the remote SSH username"); extcap_help_add_option(extcap_conf, "--remote-password ", "the remote SSH password. If not specified, ssh-agent and ssh-key are used"); - extcap_help_add_option(extcap_conf, "--sshkey ", "the path of the ssh key (OPENSSH format)"); - extcap_help_add_option(extcap_conf, "--sshkey-passphrase ", "the passphrase to unlock public ssh"); - extcap_help_add_option(extcap_conf, "--proxycommand ", "the command to use as proxy for the ssh connection"); + extcap_help_add_option(extcap_conf, "--sshkey ", "the path of the SSH key (OpenSSH format)"); + extcap_help_add_option(extcap_conf, "--sshkey-passphrase ", "the passphrase to unlock private SSH key"); + extcap_help_add_option(extcap_conf, "--proxycommand ", "the command to use as proxy for the SSH connection"); 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-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-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"); ws_opterr = 0; @@ -489,6 +532,11 @@ int main(int argc, char *argv[]) remote_interface = g_strdup(ws_optarg); break; + case OPT_REMOTE_CAPTURE_COMMAND_SELECT: + g_free(remote_capture_command_select); + remote_capture_command_select = g_strdup(ws_optarg); + break; + case OPT_REMOTE_CAPTURE_COMMAND: g_free(remote_capture_command); remote_capture_command = g_strdup(ws_optarg); @@ -557,7 +605,8 @@ int main(int argc, char *argv[]) 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, use_sudo, noprom, count, extcap_conf->fifo); + filter, remote_capture_command_select, remote_capture_command, + use_sudo, noprom, count, extcap_conf->fifo); g_free(filter); } else { ws_debug("You should not come here... maybe some parameter missing?"); @@ -567,6 +616,7 @@ int main(int argc, char *argv[]) end: /* clean up stuff */ ssh_params_free(ssh_params); + g_free(remote_capture_command_select); g_free(remote_capture_command); g_free(remote_interface); g_free(remote_filter);