mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-10 10:26:47 +09:00
connect: Support AddressFamily option
* allow parsing of AddressFamily in config and cli * supports options "any", "inet" and "inet6" * introduce SSH_OPTIONS_ADDRESS_FAMILY Signed-off-by: Samir Benmendil <me@rmz.io> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
@@ -68,6 +68,7 @@ enum ssh_config_opcode_e {
|
|||||||
SOC_CONTROLPATH,
|
SOC_CONTROLPATH,
|
||||||
SOC_CERTIFICATE,
|
SOC_CERTIFICATE,
|
||||||
SOC_REQUIRED_RSA_SIZE,
|
SOC_REQUIRED_RSA_SIZE,
|
||||||
|
SOC_ADDRESSFAMILY,
|
||||||
|
|
||||||
SOC_MAX /* Keep this one last in the list */
|
SOC_MAX /* Keep this one last in the list */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -371,6 +371,12 @@ enum ssh_control_master_options_e {
|
|||||||
SSH_CONTROL_MASTER_AUTOASK
|
SSH_CONTROL_MASTER_AUTOASK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ssh_address_family_options_e {
|
||||||
|
SSH_ADDRESS_FAMILY_ANY,
|
||||||
|
SSH_ADDRESS_FAMILY_INET,
|
||||||
|
SSH_ADDRESS_FAMILY_INET6
|
||||||
|
};
|
||||||
|
|
||||||
enum ssh_options_e {
|
enum ssh_options_e {
|
||||||
SSH_OPTIONS_HOST,
|
SSH_OPTIONS_HOST,
|
||||||
SSH_OPTIONS_PORT,
|
SSH_OPTIONS_PORT,
|
||||||
@@ -422,6 +428,7 @@ enum ssh_options_e {
|
|||||||
SSH_OPTIONS_PROXYJUMP,
|
SSH_OPTIONS_PROXYJUMP,
|
||||||
SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND,
|
SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND,
|
||||||
SSH_OPTIONS_PKI_CONTEXT,
|
SSH_OPTIONS_PKI_CONTEXT,
|
||||||
|
SSH_OPTIONS_ADDRESS_FAMILY,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -277,6 +277,7 @@ struct ssh_session_struct {
|
|||||||
bool identities_only;
|
bool identities_only;
|
||||||
int control_master;
|
int control_master;
|
||||||
char *control_path;
|
char *control_path;
|
||||||
|
int address_family;
|
||||||
} opts;
|
} opts;
|
||||||
|
|
||||||
/* server options */
|
/* server options */
|
||||||
|
|||||||
31
src/config.c
31
src/config.c
@@ -91,7 +91,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
|||||||
{"passwordauthentication", SOC_PASSWORDAUTHENTICATION, true},
|
{"passwordauthentication", SOC_PASSWORDAUTHENTICATION, true},
|
||||||
{"pubkeyauthentication", SOC_PUBKEYAUTHENTICATION, true},
|
{"pubkeyauthentication", SOC_PUBKEYAUTHENTICATION, true},
|
||||||
{"addkeystoagent", SOC_UNSUPPORTED, true},
|
{"addkeystoagent", SOC_UNSUPPORTED, true},
|
||||||
{"addressfamily", SOC_UNSUPPORTED, true},
|
{"addressfamily", SOC_ADDRESSFAMILY, true},
|
||||||
{"batchmode", SOC_UNSUPPORTED, true},
|
{"batchmode", SOC_UNSUPPORTED, true},
|
||||||
{"canonicaldomains", SOC_UNSUPPORTED, true},
|
{"canonicaldomains", SOC_UNSUPPORTED, true},
|
||||||
{"canonicalizefallbacklocal", SOC_UNSUPPORTED, true},
|
{"canonicalizefallbacklocal", SOC_UNSUPPORTED, true},
|
||||||
@@ -1564,6 +1564,35 @@ static int ssh_config_parse_line_internal(ssh_session session,
|
|||||||
ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &l);
|
ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &l);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SOC_ADDRESSFAMILY:
|
||||||
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
|
if (p == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_WARNING,
|
||||||
|
"line %d: no argument after keyword \"addressfamily\"",
|
||||||
|
count);
|
||||||
|
SAFE_FREE(x);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if (*parsing) {
|
||||||
|
int value = -1;
|
||||||
|
|
||||||
|
if (strcasecmp(p, "any") == 0) {
|
||||||
|
value = SSH_ADDRESS_FAMILY_ANY;
|
||||||
|
} else if (strcasecmp(p, "inet") == 0) {
|
||||||
|
value = SSH_ADDRESS_FAMILY_INET;
|
||||||
|
} else if (strcasecmp(p, "inet6") == 0) {
|
||||||
|
value = SSH_ADDRESS_FAMILY_INET6;
|
||||||
|
} else {
|
||||||
|
SSH_LOG(SSH_LOG_WARNING,
|
||||||
|
"line %d: invalid argument \"%s\"",
|
||||||
|
count,
|
||||||
|
p);
|
||||||
|
SAFE_FREE(x);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_ADDRESS_FAMILY, &value);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ static int ssh_connect_socket_close(socket_t s)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getai(const char *host, int port, struct addrinfo **ai)
|
static int
|
||||||
|
getai(const char *host, int port, int ai_family, struct addrinfo **ai)
|
||||||
{
|
{
|
||||||
const char *service = NULL;
|
const char *service = NULL;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
@@ -118,7 +119,7 @@ static int getai(const char *host, int port, struct addrinfo **ai)
|
|||||||
ZERO_STRUCT(hints);
|
ZERO_STRUCT(hints);
|
||||||
|
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
hints.ai_family = PF_UNSPEC;
|
hints.ai_family = ai_family;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
@@ -165,16 +166,39 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|||||||
{
|
{
|
||||||
socket_t s = -1, first = -1;
|
socket_t s = -1, first = -1;
|
||||||
int rc;
|
int rc;
|
||||||
|
int ai_family;
|
||||||
|
static const char *ai_family_str = NULL;
|
||||||
struct addrinfo *ai = NULL;
|
struct addrinfo *ai = NULL;
|
||||||
struct addrinfo *itr = NULL;
|
struct addrinfo *itr = NULL;
|
||||||
char addrname[NI_MAXHOST], portname[NI_MAXSERV];
|
char addrname[NI_MAXHOST], portname[NI_MAXSERV];
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Resolve target hostname %s port %d", host, port);
|
switch (session->opts.address_family) {
|
||||||
rc = getai(host, port, &ai);
|
case SSH_ADDRESS_FAMILY_INET:
|
||||||
|
ai_family = PF_INET;
|
||||||
|
ai_family_str = "inet";
|
||||||
|
break;
|
||||||
|
case SSH_ADDRESS_FAMILY_INET6:
|
||||||
|
ai_family = PF_INET6;
|
||||||
|
ai_family_str = "inet6";
|
||||||
|
break;
|
||||||
|
case SSH_ADDRESS_FAMILY_ANY:
|
||||||
|
default:
|
||||||
|
ai_family = PF_UNSPEC;
|
||||||
|
ai_family_str = "any";
|
||||||
|
}
|
||||||
|
SSH_LOG(SSH_LOG_PACKET,
|
||||||
|
"Resolve target hostname %s port %d (%s)",
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
ai_family_str);
|
||||||
|
rc = getai(host, port, ai_family, &ai);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session,
|
||||||
"Failed to resolve hostname %s (%s)",
|
SSH_FATAL,
|
||||||
host, gai_strerror(rc));
|
"Failed to resolve hostname %s (%s): %s",
|
||||||
|
host,
|
||||||
|
ai_family_str,
|
||||||
|
gai_strerror(rc));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -194,13 +218,18 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|||||||
struct addrinfo *bind_ai = NULL;
|
struct addrinfo *bind_ai = NULL;
|
||||||
struct addrinfo *bind_itr = NULL;
|
struct addrinfo *bind_itr = NULL;
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Resolving bind address %s", bind_addr);
|
SSH_LOG(SSH_LOG_PACKET,
|
||||||
|
"Resolving bind address %s (%s)",
|
||||||
rc = getai(bind_addr, 0, &bind_ai);
|
|
||||||
if (rc != 0) {
|
|
||||||
ssh_set_error(session, SSH_FATAL,
|
|
||||||
"Failed to resolve bind address %s (%s)",
|
|
||||||
bind_addr,
|
bind_addr,
|
||||||
|
ai_family_str);
|
||||||
|
|
||||||
|
rc = getai(bind_addr, 0, ai_family, &bind_ai);
|
||||||
|
if (rc != 0) {
|
||||||
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Failed to resolve bind address %s (%s): %s",
|
||||||
|
bind_addr,
|
||||||
|
ai_family_str,
|
||||||
gai_strerror(rc));
|
gai_strerror(rc));
|
||||||
ssh_connect_socket_close(s);
|
ssh_connect_socket_close(s);
|
||||||
s = -1;
|
s = -1;
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
|
|||||||
new->opts.nodelay = src->opts.nodelay;
|
new->opts.nodelay = src->opts.nodelay;
|
||||||
new->opts.config_processed = src->opts.config_processed;
|
new->opts.config_processed = src->opts.config_processed;
|
||||||
new->opts.control_master = src->opts.control_master;
|
new->opts.control_master = src->opts.control_master;
|
||||||
|
new->opts.address_family = src->opts.address_family;
|
||||||
new->common.log_verbosity = src->common.log_verbosity;
|
new->common.log_verbosity = src->common.log_verbosity;
|
||||||
new->common.callbacks = src->common.callbacks;
|
new->common.callbacks = src->common.callbacks;
|
||||||
|
|
||||||
@@ -650,6 +651,13 @@ int ssh_options_set_algo(ssh_session session,
|
|||||||
* context and can free it after this call.
|
* context and can free it after this call.
|
||||||
* (ssh_pki_ctx)
|
* (ssh_pki_ctx)
|
||||||
*
|
*
|
||||||
|
* - SSH_OPTIONS_ADDRESS_FAMILY
|
||||||
|
* Specify which address family to use when connecting.
|
||||||
|
*
|
||||||
|
* Possible options:
|
||||||
|
* - SSH_ADDRESS_FAMILY_ANY: use any address family
|
||||||
|
* - SSH_ADDRESS_FAMILY_INET: IPv4 only
|
||||||
|
* - SSH_ADDRESS_FAMILY_INET6: IPv6 only
|
||||||
*
|
*
|
||||||
* @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
|
||||||
@@ -1393,6 +1401,20 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSH_OPTIONS_ADDRESS_FAMILY:
|
||||||
|
if (value == NULL) {
|
||||||
|
ssh_set_error_invalid(session);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
int *x = (int *)value;
|
||||||
|
if (*x < SSH_ADDRESS_FAMILY_ANY ||
|
||||||
|
*x > SSH_ADDRESS_FAMILY_INET6) {
|
||||||
|
ssh_set_error_invalid(session);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
session->opts.address_family = *x;
|
||||||
|
}
|
||||||
|
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);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "torture_cmocka.h"
|
||||||
|
|
||||||
#define LIBSSH_STATIC
|
#define LIBSSH_STATIC
|
||||||
|
|
||||||
@@ -143,6 +144,48 @@ static void torture_connect_ipv6(void **state) {
|
|||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_connect_addrfamily(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
ssh_session session = s->ssh.session;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct aftest {
|
||||||
|
enum ssh_address_family_options_e family;
|
||||||
|
char const *host;
|
||||||
|
int return_code;
|
||||||
|
};
|
||||||
|
static struct aftest aftests[] = {
|
||||||
|
{SSH_ADDRESS_FAMILY_ANY, "afboth", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET, "afboth", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET6, "afboth", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_ANY, "afinet", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET, "afinet", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET6, "afinet", SSH_ERROR},
|
||||||
|
{SSH_ADDRESS_FAMILY_ANY, "afinet6", SSH_OK},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET, "afinet6", SSH_ERROR},
|
||||||
|
{SSH_ADDRESS_FAMILY_INET6, "afinet6", SSH_OK},
|
||||||
|
};
|
||||||
|
|
||||||
|
int aftest_count = sizeof(aftests) / sizeof(aftests[0]);
|
||||||
|
for (int i = 0; i < aftest_count; ++i) {
|
||||||
|
struct aftest const *t = &aftests[i];
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_ADDRESS_FAMILY, &t->family);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_HOST, t->host);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
} while (rc == SSH_AGAIN);
|
||||||
|
|
||||||
|
assert_ssh_return_code_equal(session, rc, t->return_code);
|
||||||
|
ssh_disconnect(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0 /* This does not work with socket_wrapper */
|
#if 0 /* This does not work with socket_wrapper */
|
||||||
static void torture_connect_timeout(void **state) {
|
static void torture_connect_timeout(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -329,6 +372,9 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_connect_ipv6,
|
cmocka_unit_test_setup_teardown(torture_connect_ipv6,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_connect_addrfamily,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_connect_double,
|
cmocka_unit_test_setup_teardown(torture_connect_double,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
|||||||
@@ -5,3 +5,8 @@
|
|||||||
|
|
||||||
123.0.0.11 testing
|
123.0.0.11 testing
|
||||||
fd00::5357:5f0a testing
|
fd00::5357:5f0a testing
|
||||||
|
|
||||||
|
127.0.0.10 afboth
|
||||||
|
fd00::5357:5f0a afboth
|
||||||
|
127.0.0.10 afinet
|
||||||
|
fd00::5357:5f0a afinet6
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
#define LIBSSH_TESTCONFIG15 "libssh_testconfig15.tmp"
|
#define LIBSSH_TESTCONFIG15 "libssh_testconfig15.tmp"
|
||||||
#define LIBSSH_TESTCONFIG16 "libssh_testconfig16.tmp"
|
#define LIBSSH_TESTCONFIG16 "libssh_testconfig16.tmp"
|
||||||
#define LIBSSH_TESTCONFIG17 "libssh_testconfig17.tmp"
|
#define LIBSSH_TESTCONFIG17 "libssh_testconfig17.tmp"
|
||||||
|
#define LIBSSH_TESTCONFIG18 "libssh_testconfig18.tmp"
|
||||||
#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
|
#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
|
||||||
#define LIBSSH_TEST_PUBKEYTYPES "libssh_test_PubkeyAcceptedKeyTypes.tmp"
|
#define LIBSSH_TEST_PUBKEYTYPES "libssh_test_PubkeyAcceptedKeyTypes.tmp"
|
||||||
#define LIBSSH_TEST_PUBKEYALGORITHMS "libssh_test_PubkeyAcceptedAlgorithms.tmp"
|
#define LIBSSH_TEST_PUBKEYALGORITHMS "libssh_test_PubkeyAcceptedAlgorithms.tmp"
|
||||||
@@ -222,6 +223,15 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
"\tControlMaster yes\n" \
|
"\tControlMaster yes\n" \
|
||||||
"\tControlPath none\n"
|
"\tControlPath none\n"
|
||||||
|
|
||||||
|
#define LIBSSH_TESTCONFIG_STRING18 \
|
||||||
|
"Host simple\n" \
|
||||||
|
"Host af\n" \
|
||||||
|
"\tAddressFamily any\n" \
|
||||||
|
"Host af4\n" \
|
||||||
|
"\tAddressFamily inet\n" \
|
||||||
|
"Host af6\n" \
|
||||||
|
"\tAddressFamily inet6\n"
|
||||||
|
|
||||||
#define LIBSSH_TEST_PUBKEYTYPES_STRING \
|
#define LIBSSH_TEST_PUBKEYTYPES_STRING \
|
||||||
"PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n"
|
"PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n"
|
||||||
|
|
||||||
@@ -292,6 +302,7 @@ static int setup_config_files(void **state)
|
|||||||
unlink(LIBSSH_TESTCONFIG15);
|
unlink(LIBSSH_TESTCONFIG15);
|
||||||
unlink(LIBSSH_TESTCONFIG16);
|
unlink(LIBSSH_TESTCONFIG16);
|
||||||
unlink(LIBSSH_TESTCONFIG17);
|
unlink(LIBSSH_TESTCONFIG17);
|
||||||
|
unlink(LIBSSH_TESTCONFIG18);
|
||||||
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
||||||
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
||||||
unlink(LIBSSH_TEST_NONEWLINEEND);
|
unlink(LIBSSH_TEST_NONEWLINEEND);
|
||||||
@@ -350,6 +361,8 @@ static int setup_config_files(void **state)
|
|||||||
LIBSSH_TESTCONFIG_STRING16);
|
LIBSSH_TESTCONFIG_STRING16);
|
||||||
torture_write_file(LIBSSH_TESTCONFIG17,
|
torture_write_file(LIBSSH_TESTCONFIG17,
|
||||||
LIBSSH_TESTCONFIG_STRING17);
|
LIBSSH_TESTCONFIG_STRING17);
|
||||||
|
torture_write_file(LIBSSH_TESTCONFIG18,
|
||||||
|
LIBSSH_TESTCONFIG_STRING18);
|
||||||
|
|
||||||
torture_write_file(LIBSSH_TEST_PUBKEYTYPES,
|
torture_write_file(LIBSSH_TEST_PUBKEYTYPES,
|
||||||
LIBSSH_TEST_PUBKEYTYPES_STRING);
|
LIBSSH_TEST_PUBKEYTYPES_STRING);
|
||||||
@@ -392,6 +405,7 @@ static int teardown_config_files(void **state)
|
|||||||
unlink(LIBSSH_TESTCONFIG15);
|
unlink(LIBSSH_TESTCONFIG15);
|
||||||
unlink(LIBSSH_TESTCONFIG16);
|
unlink(LIBSSH_TESTCONFIG16);
|
||||||
unlink(LIBSSH_TESTCONFIG17);
|
unlink(LIBSSH_TESTCONFIG17);
|
||||||
|
unlink(LIBSSH_TESTCONFIG18);
|
||||||
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
||||||
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
||||||
unlink(LIBSSH_TEST_NONEWLINEEND);
|
unlink(LIBSSH_TEST_NONEWLINEEND);
|
||||||
@@ -1520,6 +1534,79 @@ static void torture_config_control_master_file(void **state)
|
|||||||
torture_config_control_master(state, LIBSSH_TESTCONFIG17, NULL);
|
torture_config_control_master(state, LIBSSH_TESTCONFIG17, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify we can parse AdressFamily configuration option
|
||||||
|
*/
|
||||||
|
static void torture_config_address_family(void **state,
|
||||||
|
const char *file,
|
||||||
|
const char *string)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
|
||||||
|
const char *config;
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "simple");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
assert_int_equal(session->opts.address_family, SSH_ADDRESS_FAMILY_ANY);
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "af");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
assert_int_equal(session->opts.address_family, SSH_ADDRESS_FAMILY_ANY);
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "af4");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
assert_int_equal(session->opts.address_family, SSH_ADDRESS_FAMILY_INET);
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "af6");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
assert_int_equal(session->opts.address_family, SSH_ADDRESS_FAMILY_INET6);
|
||||||
|
|
||||||
|
/* test for parsing failures */
|
||||||
|
config = "Host afmissing\n"
|
||||||
|
"\tAddressFamily\n";
|
||||||
|
if (file != NULL) {
|
||||||
|
torture_write_file(file, config);
|
||||||
|
} else {
|
||||||
|
string = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "afmissing");
|
||||||
|
_parse_config(session, file, string, SSH_ERROR);
|
||||||
|
|
||||||
|
config = "Host afinvalid\n"
|
||||||
|
"\tAddressFamily wurstkäse\n";
|
||||||
|
if (file != NULL) {
|
||||||
|
torture_write_file(file, config);
|
||||||
|
} else {
|
||||||
|
string = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "afinvalid");
|
||||||
|
_parse_config(session, file, string, SSH_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify we can parse AdressFamily configuration option from string
|
||||||
|
*/
|
||||||
|
static void torture_config_address_family_string(void **state)
|
||||||
|
{
|
||||||
|
torture_config_address_family(state, NULL, LIBSSH_TESTCONFIG_STRING18);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify we can parse AdressFamily configuration option from file
|
||||||
|
*/
|
||||||
|
static void torture_config_address_family_file(void **state)
|
||||||
|
{
|
||||||
|
torture_config_address_family(state, LIBSSH_TESTCONFIG18, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Verify the configuration parser handles all the possible
|
* @brief Verify the configuration parser handles all the possible
|
||||||
* versions of RekeyLimit configuration option.
|
* versions of RekeyLimit configuration option.
|
||||||
@@ -2707,6 +2794,12 @@ int torture_run_tests(void)
|
|||||||
cmocka_unit_test_setup_teardown(torture_config_control_master_string,
|
cmocka_unit_test_setup_teardown(torture_config_control_master_string,
|
||||||
setup,
|
setup,
|
||||||
teardown),
|
teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_address_family_file,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_address_family_string,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_config_rekey_file,
|
cmocka_unit_test_setup_teardown(torture_config_rekey_file,
|
||||||
setup,
|
setup,
|
||||||
teardown),
|
teardown),
|
||||||
|
|||||||
@@ -1352,6 +1352,7 @@ static void torture_options_copy(void **state)
|
|||||||
"GSSAPIDelegateCredentials yes\n"
|
"GSSAPIDelegateCredentials yes\n"
|
||||||
"PubkeyAuthentication yes\n" /* sets flags */
|
"PubkeyAuthentication yes\n" /* sets flags */
|
||||||
"GSSAPIAuthentication no\n" /* sets flags */
|
"GSSAPIAuthentication no\n" /* sets flags */
|
||||||
|
"AddressFamily inet6\n"
|
||||||
"",
|
"",
|
||||||
config);
|
config);
|
||||||
fclose(config);
|
fclose(config);
|
||||||
@@ -1428,6 +1429,7 @@ static void torture_options_copy(void **state)
|
|||||||
assert_true(session->opts.config_processed == new->opts.config_processed);
|
assert_true(session->opts.config_processed == new->opts.config_processed);
|
||||||
assert_memory_equal(session->opts.options_seen, new->opts.options_seen,
|
assert_memory_equal(session->opts.options_seen, new->opts.options_seen,
|
||||||
sizeof(session->opts.options_seen));
|
sizeof(session->opts.options_seen));
|
||||||
|
assert_int_equal(session->opts.address_family, new->opts.address_family);
|
||||||
|
|
||||||
ssh_free(new);
|
ssh_free(new);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user