aboutsummaryrefslogtreecommitdiffstats
path: root/extcap/sshdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'extcap/sshdump.c')
-rw-r--r--extcap/sshdump.c206
1 files changed, 159 insertions, 47 deletions
diff --git a/extcap/sshdump.c b/extcap/sshdump.c
index e7390ee3e5..15adec4b6a 100644
--- a/extcap/sshdump.c
+++ b/extcap/sshdump.c
@@ -29,7 +29,7 @@
#include <cli_main.h>
-static gchar* sshdump_extcap_interface;
+static char* sshdump_extcap_interface;
#ifdef _WIN32
#define DEFAULT_SSHDUMP_EXTCAP_INTERFACE "sshdump.exe"
#else
@@ -37,7 +37,7 @@ static gchar* sshdump_extcap_interface;
#endif
#define SSHDUMP_VERSION_MAJOR "1"
-#define SSHDUMP_VERSION_MINOR "0"
+#define SSHDUMP_VERSION_MINOR "2"
#define SSHDUMP_VERSION_RELEASE "0"
#define SSH_READ_BLOCK_SIZE 256
@@ -51,13 +51,17 @@ enum {
OPT_REMOTE_USERNAME,
OPT_REMOTE_PASSWORD,
OPT_REMOTE_INTERFACE,
+ OPT_REMOTE_CAPTURE_COMMAND_SELECT,
OPT_REMOTE_CAPTURE_COMMAND,
OPT_REMOTE_FILTER,
OPT_SSHKEY,
OPT_SSHKEY_PASSPHRASE,
OPT_PROXYCOMMAND,
+ OPT_SSH_SHA1,
OPT_REMOTE_COUNT,
- OPT_REMOTE_SUDO,
+ OPT_REMOTE_SUDO, // Deprecated
+ OPT_REMOTE_PRIV,
+ OPT_REMOTE_PRIV_USER,
OPT_REMOTE_NOPROM
};
@@ -66,8 +70,11 @@ 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-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}
};
@@ -90,7 +97,7 @@ static int ssh_loop_read(ssh_channel channel, FILE* fp)
if (nbytes == 0) {
break;
}
- if (fwrite(buffer, 1, nbytes, fp) != (guint)nbytes) {
+ if (fwrite(buffer, 1, nbytes, fp) != (unsigned)nbytes) {
ws_warning("Error writing to fifo");
ret = EXIT_FAILURE;
goto end;
@@ -105,7 +112,7 @@ static int ssh_loop_read(ssh_channel channel, FILE* fp)
ws_warning("Error reading from channel");
goto end;
}
- if (fwrite(buffer, 1, nbytes, stderr) != (guint)nbytes) {
+ if (fwrite(buffer, 1, nbytes, stderr) != (unsigned)nbytes) {
ws_warning("Error writing to stderr");
break;
}
@@ -119,7 +126,7 @@ end:
return ret;
}
-static char* local_interfaces_to_filter(const guint16 remote_port)
+static char* local_interfaces_to_filter(const uint16_t remote_port)
{
GSList* interfaces = local_interfaces_to_list();
char* filter = interfaces_list_to_filter(interfaces, remote_port);
@@ -127,11 +134,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,
- const char* iface, const char* cfilter, const guint32 count)
+static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_command_select,
+ const char* capture_command, const char* privilege, bool noprom,
+ const char* iface, const char* cfilter, const uint32_t count)
{
- gchar* cmdline;
+ char* cmdline = NULL;
ssh_channel channel;
+ char** ifaces_array = NULL;
+ int ifaces_array_num = 0;
+ GString *ifaces_string;
+ char *ifaces = NULL;
char* quoted_iface = NULL;
char* quoted_filter = NULL;
char* count_str = NULL;
@@ -151,23 +163,54 @@ 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)
- count_str = g_strdup_printf("-c %u", count);
+ count_str = ws_strdup_printf("-c %u", count);
- cmdline = g_strdup_printf("%s tcpdump -U %s%s %s -w - %s %s",
- use_sudo ? "sudo" : "",
+ cmdline = ws_strdup_printf("%s tcpdump -U %s%s %s -w - %s %s",
+ privilege,
quoted_iface ? "-i " : "",
quoted_iface ? quoted_iface : "",
noprom ? "-p" : "",
count_str ? count_str : "",
quoted_filter);
+ } else if (!g_strcmp0(capture_command_select, "dumpcap")) {
+ if (iface) {
+ 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 -f %s",
+ privilege,
+ noprom ? "-p" : "",
+ ifaces ? ifaces : "",
+ count_str ? count_str : "",
+ quoted_filter);
+
+ g_free(ifaces);
+ g_strfreev(ifaces_array);
}
ws_debug("Running: %s", cmdline);
@@ -187,7 +230,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 char* privilege,
+ bool noprom, const uint32_t count, const char* fifo)
{
ssh_session sshs = NULL;
ssh_channel channel = NULL;
@@ -211,7 +255,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, privilege, noprom, iface, cfilter, count);
if (!channel) {
ws_warning("Can't run ssh command.");
@@ -262,7 +306,7 @@ static char* interfaces_list_to_filter(GSList* interfaces, unsigned int remote_p
}
g_string_append_printf(filter, ") and port %u)", remote_port);
}
- return g_string_free(filter, FALSE);
+ return g_string_free(filter, false);
}
static int list_config(char *interface, unsigned int remote_port)
@@ -286,7 +330,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, "
@@ -295,7 +339,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}"
+ "{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",
@@ -303,13 +347,31 @@ static int list_config(char *interface, unsigned int remote_port)
printf("arg {number=%u}{call=--proxycommand}{display=ProxyCommand}"
"{type=string}{tooltip=The command to use as proxy for the SSH connection}"
"{group=Authentication}\n", inc++);
+ printf("arg {number=%u}{call=--ssh-sha1}{display=Support SHA-1 keys (deprecated)}"
+ "{type=boolflag}{tooltip=Support keys and key exchange algorithms using SHA-1 (deprecated)}{group=Authentication}"
+ "\n", inc++);
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}"
- "{type=boolean}{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}"
@@ -341,7 +403,7 @@ static char* concat_filters(const char* extcap_filter, const char* remote_filter
if (!remote_filter && !extcap_filter)
return NULL;
- return g_strdup_printf("(%s) and (%s)", extcap_filter, remote_filter);
+ return ws_strdup_printf("(%s) and (%s)", extcap_filter, remote_filter);
}
int main(int argc, char *argv[])
@@ -351,22 +413,21 @@ 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;
+ uint32_t count = 0;
int ret = EXIT_FAILURE;
extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1);
char* help_url;
char* help_header = NULL;
- gboolean use_sudo = FALSE;
- gboolean noprom = FALSE;
- gchar* interface_description = g_strdup("SSH remote capture");
+ char* priv = NULL;
+ char* priv_user = NULL;
+ bool noprom = false;
+ char* interface_description = g_strdup("SSH remote capture");
/* Initialize log handler early so we can have proper logging during startup. */
- ws_log_init("sshdump", NULL);
-
- /* Early logging command-line initialization. */
- ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
+ extcap_log_init("sshdump");
sshdump_extcap_interface = g_path_get_basename(argv[0]);
@@ -379,7 +440,7 @@ int main(int argc, char *argv[])
* Attempt to get the pathname of the directory containing the
* executable file.
*/
- err_msg = init_progfile_dir(argv[0]);
+ err_msg = configuration_init(argv[0], NULL);
if (err_msg != NULL) {
ws_warning("Can't get pathname of directory containing the extcap program: %s.",
err_msg);
@@ -392,14 +453,14 @@ int main(int argc, char *argv[])
g_free(help_url);
add_libssh_info(extcap_conf);
if (g_strcmp0(sshdump_extcap_interface, DEFAULT_SSHDUMP_EXTCAP_INTERFACE)) {
- gchar* temp = interface_description;
- interface_description = g_strdup_printf("%s, custom version", interface_description);
+ char* temp = interface_description;
+ interface_description = ws_strdup_printf("%s, custom version", interface_description);
g_free(temp);
}
extcap_base_register_interface(extcap_conf, sshdump_extcap_interface, interface_description, 147, "Remote capture dependent DLT");
g_free(interface_description);
- help_header = g_strdup_printf(
+ help_header = ws_strdup_printf(
" %s --extcap-interfaces\n"
" %s --extcap-interface=%s --extcap-dlts\n"
" %s --extcap-interface=%s --extcap-config\n"
@@ -415,15 +476,18 @@ int main(int argc, char *argv[])
extcap_help_add_option(extcap_conf, "--remote-port <port>", "the remote SSH port");
extcap_help_add_option(extcap_conf, "--remote-username <username>", "the remote SSH username");
extcap_help_add_option(extcap_conf, "--remote-password <password>", "the remote SSH password. If not specified, ssh-agent and ssh-key are used");
- extcap_help_add_option(extcap_conf, "--sshkey <public key path>", "the path of the ssh key");
- extcap_help_add_option(extcap_conf, "--sshkey-passphrase <public key passphrase>", "the passphrase to unlock public ssh");
- extcap_help_add_option(extcap_conf, "--proxycommand <proxy command>", "the command to use as proxy the the ssh connection");
+ extcap_help_add_option(extcap_conf, "--sshkey <private key path>", "the path of the SSH key (OpenSSH format)");
+ extcap_help_add_option(extcap_conf, "--sshkey-passphrase <private key passphrase>", "the passphrase to unlock private SSH key");
+ extcap_help_add_option(extcap_conf, "--proxycommand <proxy command>", "the command to use as proxy for the SSH connection");
+ extcap_help_add_option(extcap_conf, "--ssh-sha1", "support keys and key exchange using SHA-1 (deprecated)");
extcap_help_add_option(extcap_conf, "--remote-interface <iface>", "the remote capture interface");
+ extcap_help_add_option(extcap_conf, "--remote-capture-command-select <selection>", "dumpcap, tcpdump or other remote capture command");
extcap_help_add_option(extcap_conf, "--remote-capture-command <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 <selection>", "none, sudo or doas");
+ extcap_help_add_option(extcap_conf, "--remote-priv-user <username>", "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 <filter>", "a filter for remote capture (default: don't "
- "listen on local interfaces IPs)");
+ extcap_help_add_option(extcap_conf, "--remote-filter <filter>", "a filter for remote capture (default: don't listen on local interfaces IPs)");
extcap_help_add_option(extcap_conf, "--remote-count <count>", "the number of packets to capture");
ws_opterr = 0;
@@ -487,18 +551,39 @@ int main(int argc, char *argv[])
ssh_params->proxycommand = g_strdup(ws_optarg);
break;
+ case OPT_SSH_SHA1:
+ ssh_params->ssh_sha1 = true;
+ break;
+
case OPT_REMOTE_INTERFACE:
g_free(remote_interface);
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);
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:
@@ -514,7 +599,7 @@ int main(int argc, char *argv[])
break;
case OPT_REMOTE_NOPROM:
- noprom = TRUE;
+ noprom = true;
break;
case ':':
@@ -552,16 +637,40 @@ 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("");
+ }
+
+ // This may result in the use of a different port number than was given in
+ // the default filter string, as presented in the config dialog. The default
+ // given is always using the default SSH port since there's no remote SSH port
+ // given on the command line to get the extcap arguments.
+ // However the remote SSH port used here is the one given on the command line
+ // when the capture us started, which is the indended one.
+ // And this is only happening when no remote filter is specified on the command
+ // line to start the capture.
+ if (remote_filter == NULL)
+ remote_filter = local_interfaces_to_filter(ssh_params->port);
filter = concat_filters(extcap_conf->capture_filter, remote_filter);
- ssh_params->debug = extcap_conf->debug;
+ ssh_params_set_log_level(ssh_params, 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,
+ 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;
@@ -570,9 +679,12 @@ 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);
+ g_free(priv);
+ g_free(priv_user);
extcap_base_cleanup(&extcap_conf);
return ret;
}