sshdump: add capability to use doas on remote host

This commit is contained in:
Jaap Keuter 2023-02-19 13:41:24 +00:00 committed by Gilbert Ramirez
parent f6e6853dc4
commit 455b9a470f
3 changed files with 142 additions and 33 deletions

View File

@ -26,11 +26,17 @@ sshdump - Provide interfaces to capture from a remote host through SSH using a r
[ *--remote-port*=<TCP port> ]
[ *--remote-username*=<username> ]
[ *--remote-password*=<password> ]
[ *--sshkey*=<public key path> ]
[ *--sshkey*=<private key path> ]
[ *--sshkey-passphrase*=<private key passphrase> ]
[ *--proxycommand*=<SSH proxy command> ]
[ *--remote-interface*=<interface> ]
[ *--remote-capture-command-select*=<capture command selection> ]
[ *--remote-capture-command*=<capture command> ]
[ *--remote-sudo* ]
[ *--remote-priv*=<privilege elevation command selection> ]
[ *--remote-priv-user*=<privileged user name> ]
[ *--remote-noprom* ]
[ *--remote-filter*=<remote capture filter> ]
[ *--remote-count*=<number> ]
[manarg]
*sshdump*
@ -128,6 +134,14 @@ List DLTs of specified interface.
List configuration options of specified interface.
--
--extcap-capture-filter=<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=<SSH private key passphrase>::
+
--
The passphrase for the private key for authentication.
--
--proxycommand=<proxy command>::
+
--
The command to use as proxy for the SSH connection.
--
--remote-interface=<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=<capture filter>::
--remote-priv=<privilege elevation command selection>::
+
--
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=<privileged user name>::
+
--
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=<capture 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=<number>::
+
--
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 -'

View File

@ -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 */
}

View File

@ -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 <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-count <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;
}