mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-19 00:48:43 +09:00
Support new '-o' option parsing to client
Signed-off-by: abdallah elhdad <abdallahselhdad@gmail.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
committed by
Jakub Jelen
parent
1833ce86f9
commit
ecea5b6052
@@ -86,22 +86,24 @@ static void add_cmd(char *cmd)
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage : ssh [options] [login@]hostname\n"
|
||||
"sample client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -r : use RSA to verify host public key\n"
|
||||
" -F file : parse configuration file instead of default one\n"
|
||||
fprintf(
|
||||
stderr,
|
||||
"Usage : ssh [options] [login@]hostname\n"
|
||||
"sample client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -o option : set configuration option (e.g., -o Compression=yes)\n"
|
||||
" -r : use RSA to verify host public key\n"
|
||||
" -F file : parse configuration file instead of default one\n"
|
||||
#ifdef WITH_PCAP
|
||||
" -P file : create a pcap debugging file\n"
|
||||
" -P file : create a pcap debugging file\n"
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
" -T proxycommand : command to execute as a socket proxy\n"
|
||||
" -T proxycommand : command to execute as a socket proxy\n"
|
||||
#endif
|
||||
"\n",
|
||||
ssh_version(0));
|
||||
"\n",
|
||||
ssh_version(0));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef LIBSSH_CONFIG_H_
|
||||
#define LIBSSH_CONFIG_H_
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
|
||||
enum ssh_config_opcode_e {
|
||||
/* Unknown opcode */
|
||||
@@ -70,4 +71,7 @@ enum ssh_config_opcode_e {
|
||||
|
||||
SOC_MAX /* Keep this one last in the list */
|
||||
};
|
||||
enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword);
|
||||
int ssh_config_parse_line_cli(ssh_session session, const char *line);
|
||||
|
||||
#endif /* LIBSSH_CONFIG_H_ */
|
||||
|
||||
484
src/config.c
484
src/config.c
@@ -60,101 +60,102 @@
|
||||
struct ssh_config_keyword_table_s {
|
||||
const char *name;
|
||||
enum ssh_config_opcode_e opcode;
|
||||
bool cli_supported;
|
||||
};
|
||||
|
||||
static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ "host", SOC_HOST },
|
||||
{ "match", SOC_MATCH },
|
||||
{ "hostname", SOC_HOSTNAME },
|
||||
{ "port", SOC_PORT },
|
||||
{ "user", SOC_USERNAME },
|
||||
{ "identityfile", SOC_IDENTITY },
|
||||
{ "ciphers", SOC_CIPHERS },
|
||||
{ "macs", SOC_MACS },
|
||||
{ "compression", SOC_COMPRESSION },
|
||||
{ "connecttimeout", SOC_TIMEOUT },
|
||||
{ "stricthostkeychecking", SOC_STRICTHOSTKEYCHECK },
|
||||
{ "userknownhostsfile", SOC_KNOWNHOSTS },
|
||||
{ "proxycommand", SOC_PROXYCOMMAND },
|
||||
{ "gssapiserveridentity", SOC_GSSAPISERVERIDENTITY },
|
||||
{ "gssapiclientidentity", SOC_GSSAPICLIENTIDENTITY },
|
||||
{ "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS },
|
||||
{ "include", SOC_INCLUDE },
|
||||
{ "bindaddress", SOC_BINDADDRESS},
|
||||
{ "globalknownhostsfile", SOC_GLOBALKNOWNHOSTSFILE},
|
||||
{ "loglevel", SOC_LOGLEVEL},
|
||||
{ "hostkeyalgorithms", SOC_HOSTKEYALGORITHMS},
|
||||
{ "kexalgorithms", SOC_KEXALGORITHMS},
|
||||
{ "gssapiauthentication", SOC_GSSAPIAUTHENTICATION},
|
||||
{ "kbdinteractiveauthentication", SOC_KBDINTERACTIVEAUTHENTICATION},
|
||||
{ "passwordauthentication", SOC_PASSWORDAUTHENTICATION},
|
||||
{ "pubkeyauthentication", SOC_PUBKEYAUTHENTICATION},
|
||||
{ "addkeystoagent", SOC_UNSUPPORTED},
|
||||
{ "addressfamily", SOC_UNSUPPORTED},
|
||||
{ "batchmode", SOC_UNSUPPORTED},
|
||||
{ "canonicaldomains", SOC_UNSUPPORTED},
|
||||
{ "canonicalizefallbacklocal", SOC_UNSUPPORTED},
|
||||
{ "canonicalizehostname", SOC_UNSUPPORTED},
|
||||
{ "canonicalizemaxdots", SOC_UNSUPPORTED},
|
||||
{ "canonicalizepermittedcnames", SOC_UNSUPPORTED},
|
||||
{ "certificatefile", SOC_CERTIFICATE},
|
||||
{ "kbdinteractiveauthentication", SOC_UNSUPPORTED},
|
||||
{ "checkhostip", SOC_UNSUPPORTED},
|
||||
{ "connectionattempts", SOC_UNSUPPORTED},
|
||||
{ "enablesshkeysign", SOC_UNSUPPORTED},
|
||||
{ "fingerprinthash", SOC_UNSUPPORTED},
|
||||
{ "forwardagent", SOC_UNSUPPORTED},
|
||||
{ "hashknownhosts", SOC_UNSUPPORTED},
|
||||
{ "hostbasedauthentication", SOC_UNSUPPORTED},
|
||||
{ "hostbasedacceptedalgorithms", SOC_UNSUPPORTED},
|
||||
{ "hostkeyalias", SOC_UNSUPPORTED},
|
||||
{ "identitiesonly", SOC_IDENTITIESONLY},
|
||||
{ "identityagent", SOC_IDENTITYAGENT},
|
||||
{ "ipqos", SOC_UNSUPPORTED},
|
||||
{ "kbdinteractivedevices", SOC_UNSUPPORTED},
|
||||
{ "nohostauthenticationforlocalhost", SOC_UNSUPPORTED},
|
||||
{ "numberofpasswordprompts", SOC_UNSUPPORTED},
|
||||
{ "pkcs11provider", SOC_UNSUPPORTED},
|
||||
{ "preferredauthentications", SOC_UNSUPPORTED},
|
||||
{ "proxyjump", SOC_PROXYJUMP},
|
||||
{ "proxyusefdpass", SOC_UNSUPPORTED},
|
||||
{ "pubkeyacceptedalgorithms", SOC_PUBKEYACCEPTEDKEYTYPES},
|
||||
{ "rekeylimit", SOC_REKEYLIMIT},
|
||||
{ "remotecommand", SOC_UNSUPPORTED},
|
||||
{ "revokedhostkeys", SOC_UNSUPPORTED},
|
||||
{ "serveralivecountmax", SOC_UNSUPPORTED},
|
||||
{ "serveraliveinterval", SOC_UNSUPPORTED},
|
||||
{ "streamlocalbindmask", SOC_UNSUPPORTED},
|
||||
{ "streamlocalbindunlink", SOC_UNSUPPORTED},
|
||||
{ "syslogfacility", SOC_UNSUPPORTED},
|
||||
{ "tcpkeepalive", SOC_UNSUPPORTED},
|
||||
{ "updatehostkeys", SOC_UNSUPPORTED},
|
||||
{ "verifyhostkeydns", SOC_UNSUPPORTED},
|
||||
{ "visualhostkey", SOC_UNSUPPORTED},
|
||||
{ "clearallforwardings", SOC_NA},
|
||||
{ "controlmaster", SOC_NA},
|
||||
{ "controlpersist", SOC_NA},
|
||||
{ "controlpath", SOC_NA},
|
||||
{ "dynamicforward", SOC_NA},
|
||||
{ "escapechar", SOC_NA},
|
||||
{ "exitonforwardfailure", SOC_NA},
|
||||
{ "forwardx11", SOC_NA},
|
||||
{ "forwardx11timeout", SOC_NA},
|
||||
{ "forwardx11trusted", SOC_NA},
|
||||
{ "gatewayports", SOC_NA},
|
||||
{ "ignoreunknown", SOC_NA},
|
||||
{ "localcommand", SOC_NA},
|
||||
{ "localforward", SOC_NA},
|
||||
{ "permitlocalcommand", SOC_NA},
|
||||
{ "remoteforward", SOC_NA},
|
||||
{ "requesttty", SOC_NA},
|
||||
{ "sendenv", SOC_NA},
|
||||
{ "tunnel", SOC_NA},
|
||||
{ "tunneldevice", SOC_NA},
|
||||
{ "xauthlocation", SOC_NA},
|
||||
{ "pubkeyacceptedkeytypes", SOC_PUBKEYACCEPTEDKEYTYPES},
|
||||
{ "requiredrsasize", SOC_REQUIRED_RSA_SIZE},
|
||||
{ NULL, SOC_UNKNOWN }
|
||||
{"host", SOC_HOST, true},
|
||||
{"match", SOC_MATCH, false},
|
||||
{"hostname", SOC_HOSTNAME, true},
|
||||
{"port", SOC_PORT, true},
|
||||
{"user", SOC_USERNAME, true},
|
||||
{"identityfile", SOC_IDENTITY, true},
|
||||
{"ciphers", SOC_CIPHERS, true},
|
||||
{"macs", SOC_MACS, true},
|
||||
{"compression", SOC_COMPRESSION, true},
|
||||
{"connecttimeout", SOC_TIMEOUT, true},
|
||||
{"stricthostkeychecking", SOC_STRICTHOSTKEYCHECK, true},
|
||||
{"userknownhostsfile", SOC_KNOWNHOSTS, true},
|
||||
{"proxycommand", SOC_PROXYCOMMAND, true},
|
||||
{"gssapiserveridentity", SOC_GSSAPISERVERIDENTITY, false},
|
||||
{"gssapiclientidentity", SOC_GSSAPICLIENTIDENTITY, false},
|
||||
{"gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS, true},
|
||||
{"include", SOC_INCLUDE, true},
|
||||
{"bindaddress", SOC_BINDADDRESS, true},
|
||||
{"globalknownhostsfile", SOC_GLOBALKNOWNHOSTSFILE, true},
|
||||
{"loglevel", SOC_LOGLEVEL, true},
|
||||
{"hostkeyalgorithms", SOC_HOSTKEYALGORITHMS, true},
|
||||
{"kexalgorithms", SOC_KEXALGORITHMS, true},
|
||||
{"gssapiauthentication", SOC_GSSAPIAUTHENTICATION, true},
|
||||
{"kbdinteractiveauthentication", SOC_KBDINTERACTIVEAUTHENTICATION, true},
|
||||
{"passwordauthentication", SOC_PASSWORDAUTHENTICATION, true},
|
||||
{"pubkeyauthentication", SOC_PUBKEYAUTHENTICATION, true},
|
||||
{"addkeystoagent", SOC_UNSUPPORTED, true},
|
||||
{"addressfamily", SOC_UNSUPPORTED, true},
|
||||
{"batchmode", SOC_UNSUPPORTED, true},
|
||||
{"canonicaldomains", SOC_UNSUPPORTED, true},
|
||||
{"canonicalizefallbacklocal", SOC_UNSUPPORTED, true},
|
||||
{"canonicalizehostname", SOC_UNSUPPORTED, true},
|
||||
{"canonicalizemaxdots", SOC_UNSUPPORTED, true},
|
||||
{"canonicalizepermittedcnames", SOC_UNSUPPORTED, true},
|
||||
{"certificatefile", SOC_CERTIFICATE, true},
|
||||
{"kbdinteractiveauthentication", SOC_UNSUPPORTED, true},
|
||||
{"checkhostip", SOC_UNSUPPORTED, true},
|
||||
{"connectionattempts", SOC_UNSUPPORTED, true},
|
||||
{"enablesshkeysign", SOC_UNSUPPORTED, true},
|
||||
{"fingerprinthash", SOC_UNSUPPORTED, true},
|
||||
{"forwardagent", SOC_UNSUPPORTED, true},
|
||||
{"hashknownhosts", SOC_UNSUPPORTED, true},
|
||||
{"hostbasedauthentication", SOC_UNSUPPORTED, true},
|
||||
{"hostbasedacceptedalgorithms", SOC_UNSUPPORTED, true},
|
||||
{"hostkeyalias", SOC_UNSUPPORTED, true},
|
||||
{"identitiesonly", SOC_IDENTITIESONLY, true},
|
||||
{"identityagent", SOC_IDENTITYAGENT, true},
|
||||
{"ipqos", SOC_UNSUPPORTED, true},
|
||||
{"kbdinteractivedevices", SOC_UNSUPPORTED, true},
|
||||
{"nohostauthenticationforlocalhost", SOC_UNSUPPORTED, true},
|
||||
{"numberofpasswordprompts", SOC_UNSUPPORTED, true},
|
||||
{"pkcs11provider", SOC_UNSUPPORTED, true},
|
||||
{"preferredauthentications", SOC_UNSUPPORTED, true},
|
||||
{"proxyjump", SOC_PROXYJUMP, true},
|
||||
{"proxyusefdpass", SOC_UNSUPPORTED, true},
|
||||
{"pubkeyacceptedalgorithms", SOC_PUBKEYACCEPTEDKEYTYPES, true},
|
||||
{"rekeylimit", SOC_REKEYLIMIT, true},
|
||||
{"remotecommand", SOC_UNSUPPORTED, true},
|
||||
{"revokedhostkeys", SOC_UNSUPPORTED, true},
|
||||
{"serveralivecountmax", SOC_UNSUPPORTED, true},
|
||||
{"serveraliveinterval", SOC_UNSUPPORTED, true},
|
||||
{"streamlocalbindmask", SOC_UNSUPPORTED, true},
|
||||
{"streamlocalbindunlink", SOC_UNSUPPORTED, true},
|
||||
{"syslogfacility", SOC_UNSUPPORTED, true},
|
||||
{"tcpkeepalive", SOC_UNSUPPORTED, true},
|
||||
{"updatehostkeys", SOC_UNSUPPORTED, true},
|
||||
{"verifyhostkeydns", SOC_UNSUPPORTED, true},
|
||||
{"visualhostkey", SOC_UNSUPPORTED, true},
|
||||
{"clearallforwardings", SOC_NA, true},
|
||||
{"controlmaster", SOC_NA, true},
|
||||
{"controlpersist", SOC_NA, true},
|
||||
{"controlpath", SOC_NA, true},
|
||||
{"dynamicforward", SOC_NA, true},
|
||||
{"escapechar", SOC_NA, true},
|
||||
{"exitonforwardfailure", SOC_NA, true},
|
||||
{"forwardx11", SOC_NA, true},
|
||||
{"forwardx11timeout", SOC_NA, true},
|
||||
{"forwardx11trusted", SOC_NA, true},
|
||||
{"gatewayports", SOC_NA, true},
|
||||
{"ignoreunknown", SOC_NA, true},
|
||||
{"localcommand", SOC_NA, true},
|
||||
{"localforward", SOC_NA, true},
|
||||
{"permitlocalcommand", SOC_NA, true},
|
||||
{"remoteforward", SOC_NA, true},
|
||||
{"requesttty", SOC_NA, true},
|
||||
{"sendenv", SOC_NA, true},
|
||||
{"tunnel", SOC_NA, true},
|
||||
{"tunneldevice", SOC_NA, true},
|
||||
{"xauthlocation", SOC_NA, true},
|
||||
{"pubkeyacceptedkeytypes", SOC_PUBKEYACCEPTEDKEYTYPES, true},
|
||||
{"requiredrsasize", SOC_REQUIRED_RSA_SIZE, true},
|
||||
{NULL, SOC_UNKNOWN, false},
|
||||
};
|
||||
|
||||
enum ssh_config_match_e {
|
||||
@@ -189,19 +190,48 @@ static struct ssh_config_match_keyword_table_s
|
||||
{NULL, MATCH_UNKNOWN},
|
||||
};
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, unsigned int depth, bool global);
|
||||
int ssh_config_parse_line(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing,
|
||||
unsigned int depth,
|
||||
bool global);
|
||||
|
||||
static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
|
||||
int i;
|
||||
static int ssh_config_parse_line_internal(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing,
|
||||
unsigned int depth,
|
||||
bool global,
|
||||
bool is_cli,
|
||||
bool fail_on_unknown);
|
||||
|
||||
for (i = 0; ssh_config_keyword_table[i].name != NULL; i++) {
|
||||
if (strcasecmp(keyword, ssh_config_keyword_table[i].name) == 0) {
|
||||
return ssh_config_keyword_table[i].opcode;
|
||||
int ssh_config_parse_line_cli(ssh_session session, const char *line);
|
||||
|
||||
enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ssh_config_keyword_table[i].name != NULL; i++) {
|
||||
if (strcasecmp(keyword, ssh_config_keyword_table[i].name) == 0) {
|
||||
return ssh_config_keyword_table[i].opcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SOC_UNKNOWN;
|
||||
return SOC_UNKNOWN;
|
||||
}
|
||||
|
||||
static bool ssh_config_is_cli_supported(enum ssh_config_opcode_e opcode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ssh_config_keyword_table[i].name != NULL; i++) {
|
||||
if (opcode == ssh_config_keyword_table[i].opcode) {
|
||||
return ssh_config_keyword_table[i].cli_supported;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define LIBSSH_CONF_MAX_DEPTH 16
|
||||
@@ -735,8 +765,6 @@ ssh_match_localnetwork(const char *addrlist, bool negate)
|
||||
}
|
||||
#endif /* HAVE_IFADDRS_H */
|
||||
|
||||
|
||||
|
||||
static enum ssh_options_e
|
||||
ssh_config_get_auth_option(enum ssh_config_opcode_e opcode)
|
||||
{
|
||||
@@ -778,13 +806,37 @@ ssh_config_get_auth_option(enum ssh_config_opcode_e opcode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_config_parse_line(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing,
|
||||
unsigned int depth,
|
||||
bool global)
|
||||
#define CHECK_COND_OR_FAIL(cond, error_message) \
|
||||
do { \
|
||||
if ((cond)) { \
|
||||
SSH_LOG(SSH_LOG_DEBUG, \
|
||||
"line %d: %s: %s", \
|
||||
count, \
|
||||
error_message, \
|
||||
keyword); \
|
||||
if (fail_on_unknown) { \
|
||||
ssh_set_error(session, \
|
||||
SSH_FATAL, \
|
||||
is_cli ? "%s '%s' value on CLI" \
|
||||
: "%s '%s' value at line %d", \
|
||||
error_message, \
|
||||
keyword, \
|
||||
is_cli ? 0 : count); \
|
||||
SAFE_FREE(x); \
|
||||
return SSH_ERROR; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int ssh_config_parse_line_internal(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing,
|
||||
unsigned int depth,
|
||||
bool global,
|
||||
bool is_cli,
|
||||
bool fail_on_unknown)
|
||||
{
|
||||
enum ssh_config_opcode_e opcode;
|
||||
const char *p = NULL, *p2 = NULL;
|
||||
@@ -799,6 +851,9 @@ ssh_config_parse_line(ssh_session session,
|
||||
|
||||
/* Ignore empty lines */
|
||||
if (line == NULL || *line == '\0') {
|
||||
if (is_cli) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -824,6 +879,16 @@ ssh_config_parse_line(ssh_session session,
|
||||
}
|
||||
|
||||
opcode = ssh_config_get_opcode(keyword);
|
||||
if (is_cli && !ssh_config_is_cli_supported(opcode)) {
|
||||
ssh_set_error(
|
||||
session,
|
||||
SSH_FATAL,
|
||||
"Option '%s' is not supported in command-line configuration",
|
||||
keyword);
|
||||
SAFE_FREE(x);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (*parsing == 1 &&
|
||||
opcode != SOC_HOST &&
|
||||
opcode != SOC_MATCH &&
|
||||
@@ -1094,82 +1159,93 @@ ssh_config_parse_line(ssh_session session,
|
||||
}
|
||||
case SOC_HOSTNAME:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
char *z = ssh_path_expand_escape(session, p);
|
||||
if (z == NULL) {
|
||||
z = strdup(p);
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, z);
|
||||
free(z);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
char *z = ssh_path_expand_escape(session, p);
|
||||
if (z == NULL) {
|
||||
z = strdup(p);
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, z);
|
||||
free(z);
|
||||
}
|
||||
break;
|
||||
case SOC_PORT:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
|
||||
}
|
||||
break;
|
||||
case SOC_USERNAME:
|
||||
if (session->opts.username == NULL) {
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
||||
}
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOC_IDENTITY:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
|
||||
}
|
||||
break;
|
||||
case SOC_CIPHERS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
|
||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
|
||||
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
|
||||
}
|
||||
break;
|
||||
case SOC_MACS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, p);
|
||||
ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, p);
|
||||
ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, p);
|
||||
}
|
||||
break;
|
||||
case SOC_COMPRESSION:
|
||||
i = ssh_config_get_yesno(&s, -1);
|
||||
if (i >= 0 && *parsing) {
|
||||
if (i) {
|
||||
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes");
|
||||
} else {
|
||||
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "no");
|
||||
}
|
||||
CHECK_COND_OR_FAIL(i < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
if (i) {
|
||||
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes");
|
||||
} else {
|
||||
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "no");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOC_TIMEOUT:
|
||||
l = ssh_config_get_long(&s, -1);
|
||||
if (l >= 0 && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &l);
|
||||
CHECK_COND_OR_FAIL(l < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &l);
|
||||
}
|
||||
break;
|
||||
case SOC_STRICTHOSTKEYCHECK:
|
||||
i = ssh_config_get_yesno(&s, -1);
|
||||
if (i >= 0 && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &i);
|
||||
CHECK_COND_OR_FAIL(i < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &i);
|
||||
}
|
||||
break;
|
||||
case SOC_KNOWNHOSTS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p);
|
||||
}
|
||||
break;
|
||||
case SOC_PROXYCOMMAND:
|
||||
p = ssh_config_get_cmd(&s);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
/* We share the seen value with the ProxyJump */
|
||||
if (p && *parsing && !seen[SOC_PROXYJUMP]) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
||||
if (*parsing && !seen[SOC_PROXYJUMP]) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
|
||||
}
|
||||
break;
|
||||
case SOC_PROXYJUMP:
|
||||
@@ -1189,37 +1265,43 @@ ssh_config_parse_line(ssh_session session,
|
||||
break;
|
||||
case SOC_GSSAPISERVERIDENTITY:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_SERVER_IDENTITY, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_SERVER_IDENTITY, p);
|
||||
}
|
||||
break;
|
||||
case SOC_GSSAPICLIENTIDENTITY:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY, p);
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY, p);
|
||||
}
|
||||
break;
|
||||
case SOC_GSSAPIDELEGATECREDENTIALS:
|
||||
i = ssh_config_get_yesno(&s, -1);
|
||||
if (i >=0 && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i);
|
||||
CHECK_COND_OR_FAIL(i < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i);
|
||||
}
|
||||
break;
|
||||
case SOC_BINDADDRESS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_BINDADDR, p);
|
||||
}
|
||||
break;
|
||||
case SOC_GLOBALKNOWNHOSTSFILE:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, p);
|
||||
}
|
||||
break;
|
||||
case SOC_LOGLEVEL:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
int value = -1;
|
||||
|
||||
if (strcasecmp(p, "quiet") == 0) {
|
||||
@@ -1237,6 +1319,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
strcasecmp(p, "DEBUG3") == 0) {
|
||||
value = SSH_LOG_TRACE;
|
||||
}
|
||||
CHECK_COND_OR_FAIL(value == -1, "Invalid value");
|
||||
if (value != -1) {
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &value);
|
||||
}
|
||||
@@ -1244,19 +1327,22 @@ ssh_config_parse_line(ssh_session session,
|
||||
break;
|
||||
case SOC_HOSTKEYALGORITHMS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p);
|
||||
}
|
||||
break;
|
||||
case SOC_PUBKEYACCEPTEDKEYTYPES:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, p);
|
||||
}
|
||||
break;
|
||||
case SOC_KEXALGORITHMS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, p);
|
||||
}
|
||||
break;
|
||||
@@ -1264,6 +1350,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
/* Parse the data limit */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL) {
|
||||
CHECK_COND_OR_FAIL(1, "Missing data limit");
|
||||
break;
|
||||
} else if (strcmp(p, "default") == 0) {
|
||||
/* Default rekey limits enforced automatically */
|
||||
@@ -1272,8 +1359,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
char *endp = NULL;
|
||||
ll = strtoll(p, &endp, 10);
|
||||
if (p == endp || ll < 0) {
|
||||
/* No number or negative */
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid argument to rekey limit");
|
||||
CHECK_COND_OR_FAIL(1, "Invalid data limit");
|
||||
break;
|
||||
}
|
||||
switch (*endp) {
|
||||
@@ -1311,19 +1397,19 @@ ssh_config_parse_line(ssh_session session,
|
||||
break;
|
||||
}
|
||||
if (*endp != ' ' && *endp != '\0') {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid trailing characters after the rekey limit: %s",
|
||||
endp);
|
||||
CHECK_COND_OR_FAIL(1, "Invalid trailing characters");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ll > -1 && *parsing) {
|
||||
CHECK_COND_OR_FAIL(ll < 0, "Invalid data limit");
|
||||
if (*parsing) {
|
||||
uint64_t v = (uint64_t)ll;
|
||||
ssh_options_set(session, SSH_OPTIONS_REKEY_DATA, &v);
|
||||
}
|
||||
/* Parse the time limit */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL) {
|
||||
CHECK_COND_OR_FAIL(1, "Missing time limit");
|
||||
break;
|
||||
} else if (strcmp(p, "none") == 0) {
|
||||
ll = 0;
|
||||
@@ -1332,7 +1418,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
ll = strtoll(p, &endp, 10);
|
||||
if (p == endp || ll < 0) {
|
||||
/* No number or negative */
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid argument to rekey limit");
|
||||
CHECK_COND_OR_FAIL(1, "Invalid time limit");
|
||||
break;
|
||||
}
|
||||
switch (*endp) {
|
||||
@@ -1385,11 +1471,11 @@ ssh_config_parse_line(ssh_session session,
|
||||
break;
|
||||
}
|
||||
if (*endp != '\0') {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid trailing characters after the"
|
||||
" rekey limit: %s", endp);
|
||||
CHECK_COND_OR_FAIL(1, "Invalid trailing characters");
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK_COND_OR_FAIL(ll < 0, "Invalid time limit");
|
||||
if (ll > -1 && *parsing) {
|
||||
uint32_t v = (uint32_t)ll;
|
||||
ssh_options_set(session, SSH_OPTIONS_REKEY_TIME, &v);
|
||||
@@ -1402,39 +1488,40 @@ ssh_config_parse_line(ssh_session session,
|
||||
enum ssh_options_e option = ssh_config_get_auth_option(opcode);
|
||||
i = ssh_config_get_yesno(&s, 0);
|
||||
|
||||
if (i >= 0 && *parsing) {
|
||||
CHECK_COND_OR_FAIL(i < 0, "Authentication option");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, option, &i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOC_NA:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unapplicable option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
CHECK_COND_OR_FAIL(1, "Unapplicable option");
|
||||
break;
|
||||
case SOC_UNSUPPORTED:
|
||||
SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
CHECK_COND_OR_FAIL(1, "Unsupported option");
|
||||
break;
|
||||
case SOC_UNKNOWN:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
CHECK_COND_OR_FAIL(1, "Unknown option");
|
||||
break;
|
||||
case SOC_IDENTITYAGENT:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_IDENTITY_AGENT, p);
|
||||
}
|
||||
break;
|
||||
case SOC_IDENTITIESONLY:
|
||||
i = ssh_config_get_yesno(&s, -1);
|
||||
if (i >= 0 && *parsing) {
|
||||
bool b = i;
|
||||
ssh_options_set(session, SSH_OPTIONS_IDENTITIES_ONLY, &b);
|
||||
CHECK_COND_OR_FAIL(i < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
bool b = i;
|
||||
ssh_options_set(session, SSH_OPTIONS_IDENTITIES_ONLY, &b);
|
||||
}
|
||||
break;
|
||||
case SOC_CONTROLMASTER:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "ControlMaster");
|
||||
if (*parsing) {
|
||||
int value = -1;
|
||||
|
||||
if (strcasecmp(p, "auto") == 0) {
|
||||
@@ -1449,6 +1536,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
value = SSH_CONTROL_MASTER_ASK;
|
||||
}
|
||||
|
||||
CHECK_COND_OR_FAIL(value == -1, "Invalid argument");
|
||||
if (value != -1) {
|
||||
ssh_options_set(session, SSH_OPTIONS_CONTROL_MASTER, &value);
|
||||
}
|
||||
@@ -1466,13 +1554,15 @@ ssh_config_parse_line(ssh_session session,
|
||||
break;
|
||||
case SOC_CERTIFICATE:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
CHECK_COND_OR_FAIL(p == NULL, "Missing argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_CERTIFICATE, p);
|
||||
}
|
||||
break;
|
||||
case SOC_REQUIRED_RSA_SIZE:
|
||||
l = ssh_config_get_long(&s, -1);
|
||||
if (l >= 0 && *parsing) {
|
||||
CHECK_COND_OR_FAIL(l < 0, "Invalid argument");
|
||||
if (*parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &l);
|
||||
}
|
||||
break;
|
||||
@@ -1488,6 +1578,38 @@ ssh_config_parse_line(ssh_session session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef SSH_PARSE_OR_FAIL
|
||||
|
||||
int ssh_config_parse_line(ssh_session session,
|
||||
const char *line,
|
||||
unsigned int count,
|
||||
int *parsing,
|
||||
unsigned int depth,
|
||||
bool global)
|
||||
{
|
||||
return ssh_config_parse_line_internal(session,
|
||||
line,
|
||||
count,
|
||||
parsing,
|
||||
depth,
|
||||
global,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
int ssh_config_parse_line_cli(ssh_session session, const char *line)
|
||||
{
|
||||
int parsing = 1;
|
||||
return ssh_config_parse_line_internal(session,
|
||||
line,
|
||||
0,
|
||||
&parsing,
|
||||
0,
|
||||
false,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
|
||||
/* @brief Parse configuration from a file pointer
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include "libssh/config.h"
|
||||
#include "libssh/config_parser.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/options.h"
|
||||
@@ -1698,6 +1699,7 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
int compress = 0;
|
||||
int cont = 1;
|
||||
size_t current = 0;
|
||||
int opt_rc = 0;
|
||||
int saveoptind = optind; /* need to save 'em */
|
||||
int saveopterr = opterr;
|
||||
int opt;
|
||||
@@ -1708,7 +1710,7 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
}
|
||||
|
||||
opterr = 0; /* shut up getopt */
|
||||
while((opt = getopt(argc, argv, "c:i:Cl:p:vb:r12")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "c:i:o:Cl:p:vb:r12")) != -1) {
|
||||
switch(opt) {
|
||||
case 'l':
|
||||
user = optarg;
|
||||
@@ -1731,6 +1733,9 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
case 'C':
|
||||
compress++;
|
||||
break;
|
||||
case 'o':
|
||||
opt_rc = ssh_config_parse_line_cli(session, optarg);
|
||||
break;
|
||||
case '2':
|
||||
break;
|
||||
case '1':
|
||||
@@ -1762,6 +1767,9 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
if (opt_rc == SSH_ERROR) {
|
||||
break;
|
||||
}
|
||||
} /* while */
|
||||
opterr = saveopterr;
|
||||
tmp = realloc(save, (current + (argc - optind)) * sizeof(char*));
|
||||
@@ -1786,6 +1794,11 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
|
||||
optind = saveoptind;
|
||||
|
||||
if (opt_rc == SSH_ERROR) {
|
||||
SAFE_FREE(save);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if(!cont) {
|
||||
SAFE_FREE(save);
|
||||
return -1;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "torture.h"
|
||||
#include "torture_key.h"
|
||||
#include <errno.h>
|
||||
#include <libssh/config.h>
|
||||
#include <libssh/misc.h>
|
||||
#include <libssh/options.h>
|
||||
#include <libssh/pki.h>
|
||||
@@ -1615,6 +1616,108 @@ static void torture_options_getopt(void **state)
|
||||
#endif /* _NSC_VER */
|
||||
}
|
||||
|
||||
static void torture_options_getopt_o_option(void **state)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
ssh_session session = *state;
|
||||
int rc;
|
||||
enum ssh_config_opcode_e opcode =
|
||||
ssh_config_get_opcode((char *)"compression");
|
||||
const char *argv[6] = {EXECUTABLE_NAME, "-o", "Compression nah", NULL};
|
||||
int argc = 3;
|
||||
|
||||
// Test: -o with invalid value (e.g., "-o Compression nah")
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
||||
|
||||
session->opts.options_seen[opcode] = 0;
|
||||
|
||||
// Test: -o with valid value (e.g., "-o Compression yes")
|
||||
argv[1] = "-o";
|
||||
argv[2] = "compression yes";
|
||||
argv[3] = NULL;
|
||||
argc = 3;
|
||||
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code(session, rc);
|
||||
assert_int_equal(session->opts.options_seen[opcode], 1);
|
||||
|
||||
#ifdef WITH_ZLIB
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S],
|
||||
"zlib@openssh.com,none");
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C],
|
||||
"zlib@openssh.com,none");
|
||||
#else
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "none");
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], "none");
|
||||
#endif
|
||||
|
||||
// Test: -o with missing value (e.g., "-o =")
|
||||
argv[1] = "-o";
|
||||
argv[2] = "=";
|
||||
argv[3] = NULL;
|
||||
argc = 3;
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
// Test: -o with only option name, no value (e.g., "-o Compression")
|
||||
session->opts.options_seen[opcode] = 0;
|
||||
argv[1] = "-o";
|
||||
argv[2] = "Compression";
|
||||
argv[3] = NULL;
|
||||
argc = 3;
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
||||
|
||||
// Test: -o with empty string (e.g., "-o ")
|
||||
argv[1] = "-o";
|
||||
argv[2] = "";
|
||||
argv[3] = NULL;
|
||||
argc = 3;
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
||||
|
||||
// Test: -o with unsupported option on the cli
|
||||
argv[1] = "-o";
|
||||
argv[2] = "match *";
|
||||
argv[3] = NULL;
|
||||
argc = 3;
|
||||
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
||||
|
||||
// Test: multiple -o options together, one invalid
|
||||
session->opts.options_seen[opcode] = 0;
|
||||
argv[1] = "-o";
|
||||
argv[2] = "compression yes";
|
||||
argv[3] = "-o";
|
||||
argv[4] = "enablesshkeysign yes";
|
||||
argv[5] = NULL;
|
||||
argc = 5;
|
||||
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
||||
|
||||
// Test: multiple -o options together, all valid
|
||||
session->opts.options_seen[opcode] = 0;
|
||||
argv[1] = "-o";
|
||||
argv[2] = "compression no";
|
||||
argv[3] = "-o";
|
||||
argv[4] = "rekeylimit 1G 1h";
|
||||
argv[5] = NULL;
|
||||
argc = 5;
|
||||
|
||||
rc = ssh_options_getopt(session, &argc, (char **)argv);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
opcode = ssh_config_get_opcode((char *)"compression");
|
||||
assert_int_equal(session->opts.options_seen[opcode], 1);
|
||||
|
||||
opcode = ssh_config_get_opcode((char *)"rekeylimit");
|
||||
assert_int_equal(session->opts.options_seen[opcode], 1);
|
||||
#endif /* _MSC_VER */
|
||||
}
|
||||
|
||||
static void torture_options_plus_sign(void **state)
|
||||
{
|
||||
ssh_session session = *state;
|
||||
@@ -3026,6 +3129,9 @@ torture_run_tests(void)
|
||||
cmocka_unit_test_setup_teardown(torture_options_getopt,
|
||||
setup,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_getopt_o_option,
|
||||
setup,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_plus_sign,
|
||||
setup,
|
||||
teardown),
|
||||
|
||||
Reference in New Issue
Block a user