1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-07-20 18:02:58 +03:00

Add new options

Pair-Programmed-With: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Aris Adamantiadis
2014-08-03 22:29:49 +02:00
committed by Andreas Schneider
parent 094aa5eb02
commit f818e63f8f
9 changed files with 343 additions and 19 deletions

View File

@ -351,6 +351,11 @@ enum ssh_options_e {
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
SSH_OPTIONS_HMAC_C_S, SSH_OPTIONS_HMAC_C_S,
SSH_OPTIONS_HMAC_S_C, SSH_OPTIONS_HMAC_S_C,
SSH_OPTIONS_PASSWORD_AUTH,
SSH_OPTIONS_PUBKEY_AUTH,
SSH_OPTIONS_KBDINT_AUTH,
SSH_OPTIONS_GSSAPI_AUTH,
SSH_OPTIONS_GLOBAL_KNOWNHOSTS
}; };
enum { enum {

View File

@ -79,6 +79,13 @@ enum ssh_pending_call_e {
/* Don't block at all */ /* Don't block at all */
#define SSH_TIMEOUT_NONBLOCKING 0 #define SSH_TIMEOUT_NONBLOCKING 0
/* options flags */
/* Authentication with *** allowed */
#define SSH_OPT_FLAG_PASSWORD_AUTH 0x1
#define SSH_OPT_FLAG_PUBKEY_AUTH 0x2
#define SSH_OPT_FLAG_KBDINT_AUTH 0x4
#define SSH_OPT_FLAG_GSSAPI_AUTH 0x8
/* members that are common to ssh_session and ssh_bind */ /* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct { struct ssh_common_struct {
struct error_struct error; struct error_struct error;
@ -182,6 +189,7 @@ struct ssh_session_struct {
char *bindaddr; /* bind the client to an ip addr */ char *bindaddr; /* bind the client to an ip addr */
char *sshdir; char *sshdir;
char *knownhosts; char *knownhosts;
char *global_knownhosts;
char *wanted_methods[10]; char *wanted_methods[10];
char *ProxyCommand; char *ProxyCommand;
char *custombanner; char *custombanner;
@ -196,6 +204,7 @@ struct ssh_session_struct {
char *gss_server_identity; char *gss_server_identity;
char *gss_client_identity; char *gss_client_identity;
int gss_delegate_creds; int gss_delegate_creds;
int flags;
} opts; } opts;
/* counters */ /* counters */
ssh_counter socket_counter; ssh_counter socket_counter;

View File

@ -921,7 +921,10 @@ int ssh_userauth_publickey_auto(ssh_session session,
if (session == NULL) { if (session == NULL) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if (! (session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH)) {
session->auth_methods &= ~SSH_AUTH_METHOD_PUBLICKEY;
return SSH_AUTH_DENIED;
}
if (session->common.callbacks) { if (session->common.callbacks) {
auth_fn = session->common.callbacks->auth_function; auth_fn = session->common.callbacks->auth_function;
auth_data = session->common.callbacks->userdata; auth_data = session->common.callbacks->userdata;

View File

@ -36,8 +36,14 @@
#define MAX_LINE_SIZE 1024 #define MAX_LINE_SIZE 1024
enum ssh_config_opcode_e { enum ssh_config_opcode_e {
/* Unknown opcode */
SOC_UNKNOWN = -3,
/* Known and not applicable to libssh */
SOC_NA = -2,
/* Known but not supported by current libssh version */
SOC_UNSUPPORTED = -1, SOC_UNSUPPORTED = -1,
SOC_HOST, SOC_HOST,
SOC_MATCH,
SOC_HOSTNAME, SOC_HOSTNAME,
SOC_PORT, SOC_PORT,
SOC_USERNAME, SOC_USERNAME,
@ -53,6 +59,17 @@ enum ssh_config_opcode_e {
SOC_GSSAPICLIENTIDENTITY, SOC_GSSAPICLIENTIDENTITY,
SOC_GSSAPIDELEGATECREDENTIALS, SOC_GSSAPIDELEGATECREDENTIALS,
SOC_INCLUDE, SOC_INCLUDE,
SOC_BINDADDRESS,
SOC_CONNECTTIMEOUT,
SOC_GLOBALKNOWNHOSTSFILE,
SOC_LOGLEVEL,
SOC_HOSTKEYALGORITHMS,
SOC_KEXALGORITHMS,
SOC_MAC,
SOC_GSSAPIAUTHENTICATION,
SOC_KBDINTERACTIVEAUTHENTICATION,
SOC_PASSWORDAUTHENTICATION,
SOC_PUBKEYAUTHENTICATION,
SOC_END /* Keep this one last in the list */ SOC_END /* Keep this one last in the list */
}; };
@ -64,6 +81,7 @@ struct ssh_config_keyword_table_s {
static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = { static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "host", SOC_HOST }, { "host", SOC_HOST },
{ "match", SOC_MATCH },
{ "hostname", SOC_HOSTNAME }, { "hostname", SOC_HOSTNAME },
{ "port", SOC_PORT }, { "port", SOC_PORT },
{ "user", SOC_USERNAME }, { "user", SOC_USERNAME },
@ -79,7 +97,76 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "gssapiserveridentity", SOC_GSSAPICLIENTIDENTITY }, { "gssapiserveridentity", SOC_GSSAPICLIENTIDENTITY },
{ "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS }, { "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS },
{ "include", SOC_INCLUDE }, { "include", SOC_INCLUDE },
{ NULL, SOC_UNSUPPORTED } { "bindaddress", SOC_BINDADDRESS},
{ "connecttimeout", SOC_CONNECTTIMEOUT},
{ "globalknownhostsfile", SOC_GLOBALKNOWNHOSTSFILE},
{ "loglevel", SOC_LOGLEVEL},
{ "hostkeyalgorithms", SOC_HOSTKEYALGORITHMS},
{ "kexalgorithms", SOC_KEXALGORITHMS},
{ "mac", SOC_MAC},
{ "gssapiauthentication", SOC_GSSAPIAUTHENTICATION},
{ "kbdinteractiveauthentication", SOC_KBDINTERACTIVEAUTHENTICATION},
{ "passwordauthentication", SOC_PASSWORDAUTHENTICATION},
{ "pubkeyauthentication", SOC_PUBKEYAUTHENTICATION},
{ "addressfamily", SOC_UNSUPPORTED},
{ "batchmode", SOC_UNSUPPORTED},
{ "canonicaldomains", SOC_UNSUPPORTED},
{ "canonicalizefallbacklocal", SOC_UNSUPPORTED},
{ "canonicalizehostname", SOC_UNSUPPORTED},
{ "canonicalizemaxdots", SOC_UNSUPPORTED},
{ "canonicalizepermittedcnames", SOC_UNSUPPORTED},
{ "challengeresponseauthentication", SOC_UNSUPPORTED},
{ "checkhostip", SOC_UNSUPPORTED},
{ "cipher", SOC_UNSUPPORTED},
{ "compressionlevel", SOC_UNSUPPORTED},
{ "connectionattempts", SOC_UNSUPPORTED},
{ "enablesshkeysign", SOC_UNSUPPORTED},
{ "forwardagent", SOC_UNSUPPORTED},
{ "gssapikeyexchange", SOC_UNSUPPORTED},
{ "gssapirenewalforcesrekey", SOC_UNSUPPORTED},
{ "gssapitrustdns", SOC_UNSUPPORTED},
{ "hashknownhosts", SOC_UNSUPPORTED},
{ "hostbasedauthentication", SOC_UNSUPPORTED},
{ "hostkeyalias", SOC_UNSUPPORTED},
{ "identitiesonly", SOC_UNSUPPORTED},
{ "ipqos", SOC_UNSUPPORTED},
{ "kbdinteractivedevices", SOC_UNSUPPORTED},
{ "nohostauthenticationforlocalhost", SOC_UNSUPPORTED},
{ "numberofpasswordprompts", SOC_UNSUPPORTED},
{ "pkcs11provider", SOC_UNSUPPORTED},
{ "preferredauthentications", SOC_UNSUPPORTED},
{ "proxyusefdpass", SOC_UNSUPPORTED},
{ "rekeylimit", SOC_UNSUPPORTED},
{ "rhostsrsaauthentication", SOC_UNSUPPORTED},
{ "rsaauthentication", SOC_UNSUPPORTED},
{ "serveralivecountmax", SOC_UNSUPPORTED},
{ "serveraliveinterval", SOC_UNSUPPORTED},
{ "tcpkeepalive", SOC_UNSUPPORTED},
{ "useprivilegedport", 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},
{ NULL, SOC_UNKNOWN }
}; };
static int ssh_config_parse_line(ssh_session session, const char *line, static int ssh_config_parse_line(ssh_session session, const char *line,
@ -94,7 +181,7 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
} }
} }
return SOC_UNSUPPORTED; return SOC_UNKNOWN;
} }
static char *ssh_config_get_cmd(char **str) { static char *ssh_config_get_cmd(char **str) {
@ -297,13 +384,11 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
break; break;
case SOC_PORT: case SOC_PORT:
if (session->opts.port == 0) { p = ssh_config_get_str_tok(&s, NULL);
p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) {
if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p); }
} break;
}
break;
case SOC_USERNAME: case SOC_USERNAME:
if (session->opts.username == NULL) { if (session->opts.username == NULL) {
p = ssh_config_get_str_tok(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
@ -408,10 +493,101 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i); ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i);
} }
break; break;
case SOC_BINDADDRESS:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_BINDADDR, p);
}
break;
case SOC_CONNECTTIMEOUT:
i = ssh_config_get_int(&s, 0);
if (i >= 0 && *parsing) {
long t = i;
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &t);
}
break;
case SOC_GLOBALKNOWNHOSTSFILE:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *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) {
if (strcasecmp(p, "quiet") == 0) {
ssh_set_log_level(SSH_LOG_NONE);
} else if (strcasecmp(p, "fatal") == 0 ||
strcasecmp(p, "error")== 0 ||
strcasecmp(p, "info") == 0) {
ssh_set_log_level(SSH_LOG_WARN);
} else if (strcasecmp(p, "verbose") == 0) {
ssh_set_log_level(SSH_LOG_INFO);
} else if (strcasecmp(p, "DEBUG") == 0 ||
strcasecmp(p, "DEBUG1") == 0) {
ssh_set_log_level(SSH_LOG_DEBUG);
} else if (strcasecmp(p, "DEBUG2") == 0 ||
strcasecmp(p, "DEBUG3") == 0) {
ssh_set_log_level(SSH_LOG_TRACE);
}
}
break;
case SOC_HOSTKEYALGORITHMS:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p);
}
break;
case SOC_KEXALGORITHMS:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, p);
}
break;
case SOC_MAC:
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);
}
break;
case SOC_GSSAPIAUTHENTICATION:
case SOC_KBDINTERACTIVEAUTHENTICATION:
case SOC_PASSWORDAUTHENTICATION:
case SOC_PUBKEYAUTHENTICATION:
i = ssh_config_get_yesno(&s, 0);
if (i>=0 && *parsing) {
switch(opcode){
case SOC_GSSAPIAUTHENTICATION:
ssh_options_set(session, SSH_OPTIONS_GSSAPI_AUTH, &i);
break;
case SOC_KBDINTERACTIVEAUTHENTICATION:
ssh_options_set(session, SSH_OPTIONS_KBDINT_AUTH, &i);
break;
case SOC_PASSWORDAUTHENTICATION:
ssh_options_set(session, SSH_OPTIONS_PASSWORD_AUTH, &i);
break;
case SOC_PUBKEYAUTHENTICATION:
ssh_options_set(session, SSH_OPTIONS_PUBKEY_AUTH, &i);
break;
/* make gcc happy */
default:
break;
}
}
break;
case SOC_NA:
SSH_LOG(SSH_LOG_INFO, "Unapplicable option: %s, line: %d\n",
keyword, count);
break;
case SOC_UNSUPPORTED: case SOC_UNSUPPORTED:
SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d", SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d",
keyword, count); keyword, count);
break; break;
case SOC_UNKNOWN:
SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d\n",
keyword, count);
break;
default: default:
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d", ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d",
opcode); opcode);

View File

@ -410,6 +410,8 @@ int ssh_is_server_known(ssh_session session) {
char *hostport; char *hostport;
const char *type; const char *type;
int match; int match;
int i=0;
char * files[3];
int ret = SSH_SERVER_NOT_KNOWN; int ret = SSH_SERVER_NOT_KNOWN;
if (session->opts.knownhosts == NULL) { if (session->opts.knownhosts == NULL) {
@ -444,14 +446,27 @@ int ssh_is_server_known(ssh_session session) {
return SSH_SERVER_ERROR; return SSH_SERVER_ERROR;
} }
/* set the list of known hosts */
i = 0;
if (session->opts.global_knownhosts != NULL){
files[i++]=session->opts.global_knownhosts;
}
files[i++] = session->opts.knownhosts;
files[i] = NULL;
i = 0;
do { do {
tokens = ssh_get_knownhost_line(&file, tokens = ssh_get_knownhost_line(&file,
session->opts.knownhosts, files[i],
&type); &type);
/* End of file, return the current state */ /* End of file, return the current state or use next file */
if (tokens == NULL) { if (tokens == NULL) {
break; ++i;
if(files[i] == NULL)
break;
else
continue;
} }
match = match_hashed_host(host, tokens[0]); match = match_hashed_host(host, tokens[0]);
if (match == 0){ if (match == 0){
@ -694,7 +709,8 @@ char **ssh_knownhosts_algorithms(ssh_session session) {
const char *type; const char *type;
int match; int match;
char **array; char **array;
int i=0, j; char *files[3] = { NULL };
int i=0, j, k;
if (session->opts.knownhosts == NULL) { if (session->opts.knownhosts == NULL) {
if (ssh_options_apply(session) < 0) { if (ssh_options_apply(session) < 0) {
@ -720,13 +736,26 @@ char **ssh_knownhosts_algorithms(ssh_session session) {
return NULL; return NULL;
} }
/* set the list of known hosts */
if (session->opts.global_knownhosts != NULL){
files[i++]=session->opts.global_knownhosts;
}
files[i++] = session->opts.knownhosts;
files[i] = NULL;
k = 0;
i = 0;
do { do {
tokens = ssh_get_knownhost_line(&file, tokens = ssh_get_knownhost_line(&file, files[k], &type);
session->opts.knownhosts, &type);
/* End of file, return the current state */ /* End of file, return the current state */
if (tokens == NULL) { if (tokens == NULL) {
break; ++k;
if (files[k] == NULL) {
break;
} else {
continue;
}
} }
match = match_hashed_host(host, tokens[0]); match = match_hashed_host(host, tokens[0]);
if (match == 0){ if (match == 0){

View File

@ -681,6 +681,17 @@ char *ssh_path_expand_tilde(const char *d) {
return r; return r;
} }
/** @internal
* @brief expands a string in function of session options
* @param[in] s Format string to expand. Known parameters:
* %d SSH configuration directory (~/.ssh)
* %h target host name
* %u local username
* %l local hostname
* %r remote username
* %p remote port
* @returns Expanded string.
*/
char *ssh_path_expand_escape(ssh_session session, const char *s) { char *ssh_path_expand_escape(ssh_session session, const char *s) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
char buf[MAX_BUF_SIZE]; char buf[MAX_BUF_SIZE];
@ -971,7 +982,7 @@ int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
* -2 means user-defined timeout as available in * -2 means user-defined timeout as available in
* session->timeout, session->timeout_usec. * session->timeout, session->timeout_usec.
*/ */
fprintf(stderr, "ssh_timeout_elapsed called with -2. this needs to " SSH_LOG(SSH_LOG_WARN, "ssh_timeout_elapsed called with -2. this needs to "
"be fixed. please set a breakpoint on %s:%d and " "be fixed. please set a breakpoint on %s:%d and "
"fix the caller\n", __FILE__, __LINE__); "fix the caller\n", __FILE__, __LINE__);
return 0; return 0;

View File

@ -374,6 +374,28 @@ int ssh_options_set_algo(ssh_session session,
* Set it to specify that GSSAPI should delegate credentials * Set it to specify that GSSAPI should delegate credentials
* to the server (int, 0 = false). * to the server (int, 0 = false).
* *
* - SSH_OPTIONS_PASSWORD_AUTH
* Set it if password authentication should be used
* in ssh_userauth_auto_pubkey(). (int, 0=false).
* Currently without effect (ssh_userauth_auto_pubkey doesn't use
* password authentication).
*
* - SSH_OPTIONS_PUBKEY_AUTH
* Set it if pubkey authentication should be used
* in ssh_userauth_auto_pubkey(). (int, 0=false).
*
* - SSH_OPTIONS_KBDINT_AUTH
* Set it if keyboard-interactive authentication should be used
* in ssh_userauth_auto_pubkey(). (int, 0=false).
* Currently without effect (ssh_userauth_auto_pubkey doesn't use
* keyboard-interactive authentication).
*
* - SSH_OPTIONS_GSSAPI_AUTH
* Set it if gssapi authentication should be used
* in ssh_userauth_auto_pubkey(). (int, 0=false).
* Currently without effect (ssh_userauth_auto_pubkey doesn't use
* gssapi authentication).
*
* @param value The value to set. This is a generic pointer and the * @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the * datatype which is used should be set according to the
* type set. * type set.
@ -385,6 +407,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
const char *v; const char *v;
char *p, *q; char *p, *q;
long int i; long int i;
unsigned int u;
int rc; int rc;
if (session == NULL) { if (session == NULL) {
@ -574,6 +597,20 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
} }
} }
break; break;
case SSH_OPTIONS_GLOBAL_KNOWNHOSTS:
v = value;
SAFE_FREE(session->opts.global_knownhosts);
if (v == NULL || v[0] == '\0') {
ssh_set_error_invalid(session);
return -1;
} else {
session->opts.global_knownhosts = strdup(v);
if (session->opts.global_knownhosts == NULL) {
ssh_set_error_oom(session);
return -1;
}
}
break;
case SSH_OPTIONS_TIMEOUT: case SSH_OPTIONS_TIMEOUT:
if (value == NULL) { if (value == NULL) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
@ -858,6 +895,30 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->opts.gss_delegate_creds = (x & 0xff); session->opts.gss_delegate_creds = (x & 0xff);
} }
break; break;
case SSH_OPTIONS_PASSWORD_AUTH:
case SSH_OPTIONS_PUBKEY_AUTH:
case SSH_OPTIONS_KBDINT_AUTH:
case SSH_OPTIONS_GSSAPI_AUTH:
u = 0;
if (value == NULL) {
ssh_set_error_invalid(session);
return -1;
} else {
int x = *(int *)value;
u = type == SSH_OPTIONS_PASSWORD_AUTH ?
SSH_OPT_FLAG_PASSWORD_AUTH:
type == SSH_OPTIONS_PUBKEY_AUTH ?
SSH_OPT_FLAG_PUBKEY_AUTH:
type == SSH_OPTIONS_KBDINT_AUTH ?
SSH_OPT_FLAG_KBDINT_AUTH:
SSH_OPT_FLAG_GSSAPI_AUTH;
if (x != 0){
session->opts.flags |= u;
} else {
session->opts.flags &= ~u;
}
}
break;
default: default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);

View File

@ -112,7 +112,8 @@ ssh_session ssh_new(void) {
#else #else
session->opts.ssh1 = 0; session->opts.ssh1 = 0;
#endif #endif
session->opts.flags = SSH_OPT_FLAG_PASSWORD_AUTH | SSH_OPT_FLAG_PUBKEY_AUTH |
SSH_OPT_FLAG_KBDINT_AUTH | SSH_OPT_FLAG_GSSAPI_AUTH;
session->opts.identity = ssh_list_new(); session->opts.identity = ssh_list_new();
if (session->opts.identity == NULL) { if (session->opts.identity == NULL) {
goto err; goto err;

View File

@ -239,6 +239,34 @@ static void torture_options_proxycommand(void **state) {
assert_null(session->opts.ProxyCommand); assert_null(session->opts.ProxyCommand);
} }
static void torture_options_config_host(void **state) {
ssh_session session = *state;
FILE *config = NULL;
/* create a new config file */
config = fopen("test_config", "w");
assert_non_null(config);
fputs("Host testhost1\nPort 42\nHost testhost2,testhost3\nPort 43\n", config);
fclose(config);
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1");
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 42);
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost2");
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 43);
session->opts.port = 0;
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost3");
ssh_options_parse_config(session, "test_config");
assert_int_equal(session->opts.port, 43);
unlink("test_config");
}
#ifdef WITH_SERVER #ifdef WITH_SERVER
/* sshbind options */ /* sshbind options */
@ -304,6 +332,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown)
}; };
#ifdef WITH_SERVER #ifdef WITH_SERVER