aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2014-08-03 22:29:49 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2015-01-21 16:24:52 +0100
commitf7f11b39108edf4cddf975f5ed9349ee33d443ac (patch)
treedd1dbfc10815cd7e58d0eb3265f88aad78ab8b76
parentb235c380f29b22ab08421dd18e225acdaa21c555 (diff)
downloadlibssh-f7f11b39108edf4cddf975f5ed9349ee33d443ac.tar.gz
libssh-f7f11b39108edf4cddf975f5ed9349ee33d443ac.tar.xz
libssh-f7f11b39108edf4cddf975f5ed9349ee33d443ac.zip
Add new optionsoptions
-rw-r--r--include/libssh/libssh.h5
-rw-r--r--include/libssh/session.h9
-rw-r--r--src/auth.c5
-rw-r--r--src/config.c192
-rw-r--r--src/known_hosts.c41
-rw-r--r--src/match.c1
-rw-r--r--src/misc.c14
-rw-r--r--src/options.c61
-rw-r--r--src/session.c3
-rw-r--r--tests/unittests/torture_options.c29
10 files changed, 343 insertions, 17 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index f4e4fe93..afe32977 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -345,6 +345,11 @@ enum ssh_options_e {
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
SSH_OPTIONS_HMAC_C_S,
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 {
diff --git a/include/libssh/session.h b/include/libssh/session.h
index 29bdd60b..72c588e1 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -79,6 +79,13 @@ enum ssh_pending_call_e {
/* Don't block at all */
#define SSH_TIMEOUT_NONBLOCKING 0
+/* options flags */
+/* Authentication with *** allowed */
+#define SSH_OPT_FLAG_PASSWORD_AUTH 1
+#define SSH_OPT_FLAG_PUBKEY_AUTH 2
+#define SSH_OPT_FLAG_KBDINT_AUTH 4
+#define SSH_OPT_FLAG_GSSAPI_AUTH 8
+
/* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {
struct error_struct error;
@@ -182,6 +189,7 @@ struct ssh_session_struct {
char *bindaddr; /* bind the client to an ip addr */
char *sshdir;
char *knownhosts;
+ char *global_knownhosts;
char *wanted_methods[10];
char *ProxyCommand;
char *custombanner;
@@ -196,6 +204,7 @@ struct ssh_session_struct {
char *gss_server_identity;
char *gss_client_identity;
int gss_delegate_creds;
+ int flags;
} opts;
/* counters */
ssh_counter socket_counter;
diff --git a/src/auth.c b/src/auth.c
index d56111d2..5133bd70 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -897,7 +897,10 @@ int ssh_userauth_publickey_auto(ssh_session session,
if (session == NULL) {
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) {
auth_fn = session->common.callbacks->auth_function;
auth_data = session->common.callbacks->userdata;
diff --git a/src/config.c b/src/config.c
index 0d44c215..a26ee47f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -34,8 +34,14 @@
#include "libssh/options.h"
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_HOST,
+ SOC_MATCH,
SOC_HOSTNAME,
SOC_PORT,
SOC_USERNAME,
@@ -50,6 +56,17 @@ enum ssh_config_opcode_e {
SOC_GSSAPISERVERIDENTITY,
SOC_GSSAPICLIENTIDENTITY,
SOC_GSSAPIDELEGATECREDENTIALS,
+ SOC_BINDADDRESS,
+ SOC_CONNECTTIMEOUT,
+ SOC_GLOBALKNOWNHOSTSFILE,
+ SOC_LOGLEVEL,
+ SOC_HOSTKEYALGORITHMS,
+ SOC_KEXALGORITHMS,
+ SOC_MAC,
+ SOC_GSSAPIAUTHENTICATION,
+ SOC_KBDINTERACTIVEAUTHENTICATION,
+ SOC_PASSWORDAUTHENTICATION,
+ SOC_PUBKEYAUTHENTICATION,
};
struct ssh_config_keyword_table_s {
@@ -59,6 +76,7 @@ struct ssh_config_keyword_table_s {
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 },
@@ -73,7 +91,76 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "gssapiserveridentity", SOC_GSSAPISERVERIDENTITY },
{ "gssapiserveridentity", SOC_GSSAPICLIENTIDENTITY },
{ "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS },
- { 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 enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
@@ -85,7 +172,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) {
@@ -245,12 +332,10 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
}
break;
case SOC_PORT:
- if (session->opts.port == 0) {
- p = ssh_config_get_str_tok(&s, NULL);
- if (p && *parsing) {
- ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
- }
- }
+ p = ssh_config_get_str_tok(&s, NULL);
+ if (p && *parsing) {
+ ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
+ }
break;
case SOC_USERNAME:
if (session->opts.username == NULL) {
@@ -356,10 +441,101 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
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) {
+ 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:
SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
keyword, count);
break;
+ case SOC_UNKNOWN:
+ SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d\n",
+ keyword, count);
+ break;
default:
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d\n",
opcode);
diff --git a/src/known_hosts.c b/src/known_hosts.c
index f7828d5f..1e8de54a 100644
--- a/src/known_hosts.c
+++ b/src/known_hosts.c
@@ -410,6 +410,8 @@ int ssh_is_server_known(ssh_session session) {
char *hostport;
const char *type;
int match;
+ int i=0;
+ char * files[3];
int ret = SSH_SERVER_NOT_KNOWN;
if (session->opts.knownhosts == NULL) {
@@ -444,14 +446,27 @@ int ssh_is_server_known(ssh_session session) {
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 {
tokens = ssh_get_knownhost_line(&file,
- session->opts.knownhosts,
+ files[i],
&type);
- /* End of file, return the current state */
+ /* End of file, return the current state or use next file */
if (tokens == NULL) {
- break;
+ ++i;
+ if(files[i] == NULL)
+ break;
+ else
+ continue;
}
match = match_hashed_host(host, tokens[0]);
if (match == 0){
@@ -667,7 +682,8 @@ char **ssh_knownhosts_algorithms(ssh_session session) {
const char *type;
int match;
char **array;
- int i=0, j;
+ char *files[3];
+ int i=0, j, k;
if (session->opts.knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
@@ -693,13 +709,26 @@ char **ssh_knownhosts_algorithms(ssh_session session) {
return NULL;
}
+ /* 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;
+ k = 0;
+
do {
tokens = ssh_get_knownhost_line(&file,
- session->opts.knownhosts, &type);
+ files[k], &type);
/* End of file, return the current state */
if (tokens == NULL) {
- break;
+ ++k;
+ if(files[k] == NULL)
+ break;
+ else
+ continue;
}
match = match_hashed_host(host, tokens[0]);
if (match == 0){
diff --git a/src/match.c b/src/match.c
index 53620bdd..36cc922a 100644
--- a/src/match.c
+++ b/src/match.c
@@ -109,6 +109,7 @@ static int match_pattern(const char *s, const char *pattern) {
}
/* NOTREACHED */
+ return 0;
}
/*
diff --git a/src/misc.c b/src/misc.c
index 6daf60ab..6afc81d2 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -696,6 +696,17 @@ char *ssh_path_expand_tilde(const char *d) {
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 host[NI_MAXHOST];
char buf[MAX_BUF_SIZE];
@@ -967,9 +978,10 @@ int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
* -2 means user-defined timeout as available in
* 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 "
"fix the caller\n", __FILE__, __LINE__);
+ return 0;
case -1: /* -1 means infinite timeout */
return 0;
case 0: /* 0 means no timeout */
diff --git a/src/options.c b/src/options.c
index 2b8abb48..16fcc7aa 100644
--- a/src/options.c
+++ b/src/options.c
@@ -379,6 +379,28 @@ int ssh_options_set_algo(ssh_session session, int algo,
* Set it to specify that GSSAPI should delegate credentials
* 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
* datatype which is used should be set according to the
* type set.
@@ -390,6 +412,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
const char *v;
char *p, *q;
long int i;
+ unsigned int u;
int rc;
if (session == NULL) {
@@ -579,6 +602,20 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
}
}
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:
if (value == NULL) {
ssh_set_error_invalid(session);
@@ -863,6 +900,30 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->opts.gss_delegate_creds = (x & 0xff);
}
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:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
diff --git a/src/session.c b/src/session.c
index 63364c51..d2a9ef29 100644
--- a/src/session.c
+++ b/src/session.c
@@ -109,7 +109,8 @@ ssh_session ssh_new(void) {
#else
session->opts.ssh1 = 0;
#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();
if (session->opts.identity == NULL) {
goto err;
diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c
index 6f5df1bb..471c387a 100644
--- a/tests/unittests/torture_options.c
+++ b/tests/unittests/torture_options.c
@@ -193,6 +193,34 @@ static void torture_options_proxycommand(void **state) {
assert_null(session->opts.ProxyCommand);
}
+static void torture_options_config_host(void **state) {
+ ssh_session session = *state;
+ FILE *config;
+ int rc;
+
+ /* 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);
+
+}
+
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
@@ -206,6 +234,7 @@ int torture_run_tests(void) {
unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
unit_test_setup_teardown(torture_options_get_identity, setup, teardown),
unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
+ unit_test_setup_teardown(torture_options_config_host, setup, teardown)
};
ssh_init();