mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 12:20:42 +09:00
feat: add null hostkey for server
fix: skip gssapi tests in fips mode fix: skip gssapi_key_exchange_null test on ubuntu and tumbleweed fix: return early when rc != 0 to show error tests: replace int asserts by ssh return code asserts fix: add fatal error when hostkeys are not found and gssapi kex is not enabled ci: add comment linking gssapi null kex bug in ubuntu and tumbleweed fix: don't specify hostkeys in config instead of deleting files tests: assert kex method was null refactor: remove redundant include refactor: better error message fix: check null before accessing in gssapi.c fix: allow setting no hostkeys Signed-off-by: Gauravsingh Sisodia <xaerru@gmail.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Jakub Jelen
parent
fd1c3e8878
commit
c1aab9903f
@@ -83,6 +83,11 @@ workflow:
|
||||
.tumbleweed:
|
||||
extends: .tests
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
# torture_gssapi_key_exchange_null is excluded because of a bug (https://issues.redhat.com/browse/RHEL-55740)
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure -E "^torture_gssapi_key_exchange_null$"
|
||||
|
||||
.centos:
|
||||
extends: .tests
|
||||
@@ -504,6 +509,11 @@ fedora/abidiff:
|
||||
ubuntu/openssl_3.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
# torture_gssapi_key_exchange_null is excluded because of a bug (https://issues.redhat.com/browse/RHEL-55740)
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure -E "^torture_gssapi_key_exchange_null$"
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -2456,7 +2456,7 @@ pending:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to authenticate through the "gssapi-with-keyex" method.
|
||||
* @brief Try to authenticate through the "gssapi-keyex" method.
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
@@ -2503,7 +2503,7 @@ int ssh_userauth_gssapi_keyex(ssh_session session)
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Authenticating with gssapi-with-keyex");
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Authenticating with gssapi-keyex");
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_GSSAPI_KEYEX;
|
||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
|
||||
15
src/bind.c
15
src/bind.c
@@ -245,9 +245,14 @@ int ssh_bind_listen(ssh_bind sshbind)
|
||||
sshbind->ecdsa == NULL &&
|
||||
sshbind->ed25519 == NULL) {
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
if (rc == SSH_ERROR) {
|
||||
if (!sshbind->gssapi_key_exchange) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"No hostkeys found");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "No hostkeys found: Using \"null\" hostkey algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
@@ -467,6 +472,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
session->opts.gssapi_key_exchange = sshbind->gssapi_key_exchange;
|
||||
|
||||
if (sshbind->gssapi_key_exchange_algs != NULL) {
|
||||
SAFE_FREE(session->opts.gssapi_key_exchange_algs);
|
||||
session->opts.gssapi_key_exchange_algs = strdup(sshbind->gssapi_key_exchange_algs);
|
||||
if (session->opts.gssapi_key_exchange_algs == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
@@ -519,9 +525,14 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
sshbind->ecdsa == NULL &&
|
||||
sshbind->ed25519 == NULL) {
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
if (rc == SSH_ERROR) {
|
||||
if (!sshbind->gssapi_key_exchange) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"No hostkeys found");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "No hostkeys found: Using \"null\" hostkey algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
|
||||
12
src/dh-gss.c
12
src/dh-gss.c
@@ -338,11 +338,6 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_dh_compute_shared_secret(crypto->dh_ctx,
|
||||
DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR,
|
||||
&crypto->shared_secret);
|
||||
@@ -351,12 +346,18 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Also imports next_crypto->server_pubkey
|
||||
* Can give error when using null hostkey */
|
||||
ssh_get_key_params(session, &privkey, &digest);
|
||||
|
||||
rc = ssh_make_sessionid(session);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (strncmp(crypto->kex_methods[SSH_HOSTKEYS], "null", 4) != 0) {
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
@@ -377,6 +378,7 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Sent SSH2_MSG_KEXGSS_HOSTKEY");
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
}
|
||||
|
||||
rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
|
||||
NULL, &server_pubkey);
|
||||
|
||||
@@ -727,6 +727,10 @@ ssh_gssapi_check_client_config(ssh_session session)
|
||||
|
||||
for (i = 0; i < supported->count; ++i){
|
||||
gssapi = calloc(1, sizeof(struct ssh_gssapi_struct));
|
||||
if (gssapi == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
gssapi->server_creds = GSS_C_NO_CREDENTIAL;
|
||||
gssapi->client_creds = GSS_C_NO_CREDENTIAL;
|
||||
gssapi->ctx = GSS_C_NO_CONTEXT;
|
||||
@@ -786,7 +790,7 @@ ssh_gssapi_check_client_config(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Supported mech %zu: %s", i, ptr);
|
||||
free(ptr);
|
||||
|
||||
/* If any one is configured then return successfully */
|
||||
/* If atleast one mechanism is configured then return successfully */
|
||||
ret = SSH_OK;
|
||||
|
||||
end:
|
||||
|
||||
18
src/kex.c
18
src/kex.c
@@ -811,7 +811,7 @@ int ssh_set_client_kex(ssh_session session)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
if (session->opts.gssapi_key_exchange) {
|
||||
if (session->opts.gssapi_key_exchange && !ssh_fips_mode()) {
|
||||
char *gssapi_algs = NULL;
|
||||
|
||||
ok = ssh_gssapi_init(session);
|
||||
@@ -825,7 +825,7 @@ int ssh_set_client_kex(ssh_session session)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
gssapi_algs = ssh_gssapi_kex_mechs(session, session->opts.gssapi_key_exchange_algs ? session->opts.gssapi_key_exchange_algs : GSSAPI_KEY_EXCHANGE_SUPPORTED);
|
||||
gssapi_algs = ssh_gssapi_kex_mechs(session, session->opts.gssapi_key_exchange_algs);
|
||||
if (gssapi_algs == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -1488,15 +1488,15 @@ int ssh_make_sessionid(ssh_session session)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (server_pubkey_blob == NULL && session->opts.gssapi_key_exchange) {
|
||||
ssh_string_free(server_pubkey_blob);
|
||||
if (server_pubkey_blob == NULL) {
|
||||
if ((session->server && ssh_kex_is_gss(session->next_crypto)) ||
|
||||
session->opts.gssapi_key_exchange) {
|
||||
server_pubkey_blob = ssh_string_new(0);
|
||||
if (server_pubkey_blob == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
rc = SSH_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
if (server_pubkey_blob == NULL && ssh_kex_is_gss(session->next_crypto)) {
|
||||
ssh_string_free(server_pubkey_blob);
|
||||
server_pubkey_blob = ssh_string_new(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -566,7 +566,7 @@ int ssh_options_set_algo(ssh_session session,
|
||||
* to the server (int, 0 = false).
|
||||
*
|
||||
* - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE
|
||||
* Set to true to do GSSAPI key exchange (bool).
|
||||
* Set to true to allow GSSAPI key exchange (bool).
|
||||
*
|
||||
* - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS
|
||||
* Set the GSSAPI key exchange method to be used (const char *,
|
||||
@@ -1285,6 +1285,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
"GSSAPI key exchange algorithms not supported or invalid");
|
||||
return -1;
|
||||
}
|
||||
SAFE_FREE(session->opts.gssapi_key_exchange_algs);
|
||||
session->opts.gssapi_key_exchange_algs = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
15
src/server.c
15
src/server.c
@@ -141,10 +141,6 @@ int server_set_kex(ssh_session session)
|
||||
",%s", ssh_key_type_to_char(keytype));
|
||||
}
|
||||
|
||||
if (strlen(hostkeys) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
|
||||
allowed = session->opts.wanted_methods[SSH_HOSTKEYS];
|
||||
} else {
|
||||
@@ -155,6 +151,7 @@ int server_set_kex(ssh_session session)
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(hostkeys) != 0) {
|
||||
/* It is expected for the list of allowed hostkeys to be ordered by
|
||||
* preference */
|
||||
kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys,
|
||||
@@ -172,16 +169,16 @@ int server_set_kex(ssh_session session)
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
if (session->opts.gssapi_key_exchange) {
|
||||
if (session->opts.gssapi_key_exchange && !ssh_fips_mode()) {
|
||||
ok = ssh_gssapi_init(session);
|
||||
if (ok != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
gssapi_algs = ssh_gssapi_kex_mechs(session, session->opts.gssapi_key_exchange_algs ? session->opts.gssapi_key_exchange_algs : GSSAPI_KEY_EXCHANGE_SUPPORTED);
|
||||
gssapi_algs = ssh_gssapi_kex_mechs(session, session->opts.gssapi_key_exchange_algs);
|
||||
if (gssapi_algs == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -191,6 +188,10 @@ int server_set_kex(ssh_session session)
|
||||
session->opts.wanted_methods[SSH_KEX] =
|
||||
ssh_prefix_without_duplicates(ssh_kex_get_default_methods(SSH_KEX), gssapi_algs);
|
||||
|
||||
if (strlen(hostkeys) == 0) {
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS] = strdup("null");
|
||||
}
|
||||
|
||||
SAFE_FREE(gssapi_algs);
|
||||
}
|
||||
#endif /* WITH_GSSAPI */
|
||||
|
||||
@@ -160,6 +160,13 @@ ssh_session ssh_new(void)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef WITH_GSSAPI
|
||||
session->opts.gssapi_key_exchange_algs = strdup(GSSAPI_KEY_EXCHANGE_SUPPORTED);
|
||||
if (session->opts.gssapi_key_exchange_algs == NULL) {
|
||||
goto err;
|
||||
}
|
||||
#endif /* WITH_GSSAPI */
|
||||
|
||||
id = strdup("%d/id_ed25519");
|
||||
if (id == NULL) {
|
||||
goto err;
|
||||
|
||||
@@ -272,5 +272,11 @@ torture_run_tests(void)
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
ssh_finalize();
|
||||
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,11 @@ torture_gssapi_key_exchange(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -97,7 +102,7 @@ torture_gssapi_key_exchange(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
torture_teardown_kdc_server(state);
|
||||
}
|
||||
|
||||
@@ -109,6 +114,11 @@ torture_gssapi_key_exchange_no_tgt(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Don't run kinit */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -124,7 +134,7 @@ torture_gssapi_key_exchange_no_tgt(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_int_not_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP14_SHA256);
|
||||
assert_int_not_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP16_SHA512);
|
||||
@@ -140,6 +150,11 @@ torture_gssapi_key_exchange_gss_group14_sha256(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -157,7 +172,7 @@ torture_gssapi_key_exchange_gss_group14_sha256(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_int_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP14_SHA256);
|
||||
|
||||
@@ -172,6 +187,11 @@ torture_gssapi_key_exchange_gss_group16_sha512(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -189,7 +209,7 @@ torture_gssapi_key_exchange_gss_group16_sha512(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_true(session->current_crypto->kex_type == SSH_GSS_KEX_DH_GROUP16_SHA512);
|
||||
|
||||
@@ -204,6 +224,11 @@ torture_gssapi_key_exchange_auth(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -218,7 +243,7 @@ torture_gssapi_key_exchange_auth(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_gssapi_keyex(session);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
@@ -234,6 +259,11 @@ torture_gssapi_key_exchange_no_auth(void **state)
|
||||
int rc;
|
||||
bool f = false;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -249,7 +279,7 @@ torture_gssapi_key_exchange_no_auth(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
/* Still try to do "gssapi-keyex" auth */
|
||||
rc = ssh_userauth_gssapi_keyex(session);
|
||||
@@ -289,5 +319,11 @@ torture_run_tests(void)
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
ssh_finalize();
|
||||
|
||||
pthread_exit((void *)&rc);
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ sshd_setup(void **state)
|
||||
s = *state;
|
||||
s->disable_hostkeys = true;
|
||||
|
||||
if (!ssh_fips_mode()) {
|
||||
/* Temporary kerberos server */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -34,6 +35,7 @@ sshd_setup(void **state)
|
||||
"GSSAPIKeyExchange yes\n");
|
||||
|
||||
torture_teardown_kdc_server(state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -98,6 +100,11 @@ torture_gssapi_key_exchange_null(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
state,
|
||||
@@ -112,7 +119,10 @@ torture_gssapi_key_exchange_null(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
assert_string_equal(session->current_crypto->kex_methods[SSH_HOSTKEYS], "null");
|
||||
|
||||
torture_teardown_kdc_server(state);
|
||||
}
|
||||
|
||||
@@ -132,5 +142,11 @@ torture_run_tests(void)
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
ssh_finalize();
|
||||
|
||||
pthread_exit((void *)&rc);
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ if (WITH_GSSAPI AND GSSAPI_FOUND AND GSSAPI_TESTING)
|
||||
torture_gssapi_server_auth
|
||||
torture_gssapi_server_auth_cb
|
||||
torture_gssapi_server_delegation
|
||||
torture_gssapi_server_key_exchange)
|
||||
torture_gssapi_server_key_exchange
|
||||
torture_gssapi_server_key_exchange_null)
|
||||
endif()
|
||||
|
||||
include_directories(${libssh_SOURCE_DIR}/include
|
||||
|
||||
@@ -145,9 +145,8 @@ int run_server(struct server_state_st *state)
|
||||
}
|
||||
|
||||
if (state->host_key == NULL && state->rsa_key == NULL &&
|
||||
state->ecdsa_key == NULL && state->ed25519_key) {
|
||||
state->ecdsa_key == NULL && state->ed25519_key == NULL) {
|
||||
fprintf(stderr, "Missing host key\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sshbind = ssh_bind_new();
|
||||
@@ -211,7 +210,7 @@ int run_server(struct server_state_st *state)
|
||||
state->gssapi_key_exchange_algs);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr,
|
||||
"Error setting GSSAPI key exchange: %s\n",
|
||||
"Error setting GSSAPI key exchange algorithms: %s\n",
|
||||
ssh_get_error(sshbind));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -452,5 +452,11 @@ torture_run_tests(void)
|
||||
teardown_default_server);
|
||||
ssh_finalize();
|
||||
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -476,5 +476,11 @@ torture_run_tests(void)
|
||||
teardown_default_server);
|
||||
ssh_finalize();
|
||||
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -372,5 +372,11 @@ torture_run_tests(void)
|
||||
teardown_default_server);
|
||||
ssh_finalize();
|
||||
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -286,6 +286,11 @@ torture_gssapi_server_key_exchange(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -322,6 +327,11 @@ torture_gssapi_server_key_exchange_no_tgt(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -345,7 +355,7 @@ torture_gssapi_server_key_exchange_no_tgt(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_int_not_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP14_SHA256);
|
||||
assert_int_not_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP16_SHA512);
|
||||
@@ -362,6 +372,11 @@ torture_gssapi_server_key_exchange_gss_group14_sha256(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -387,7 +402,7 @@ torture_gssapi_server_key_exchange_gss_group14_sha256(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_int_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP14_SHA256);
|
||||
|
||||
@@ -403,6 +418,11 @@ torture_gssapi_server_key_exchange_gss_group16_sha512(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -428,7 +448,7 @@ torture_gssapi_server_key_exchange_gss_group16_sha512(void **state)
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
assert_int_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP16_SHA512);
|
||||
|
||||
@@ -444,6 +464,11 @@ torture_gssapi_server_key_exchange_auth(void **state)
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -483,6 +508,11 @@ torture_gssapi_server_key_exchange_no_auth(void **state)
|
||||
int rc;
|
||||
bool f = false;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
@@ -547,5 +577,11 @@ torture_run_tests(void)
|
||||
teardown_default_server);
|
||||
ssh_finalize();
|
||||
|
||||
pthread_exit((void *)&rc);
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
305
tests/server/torture_gssapi_server_key_exchange_null.c
Normal file
305
tests/server/torture_gssapi_server_key_exchange_null.c
Normal file
@@ -0,0 +1,305 @@
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "torture.h"
|
||||
|
||||
#include "test_server.h"
|
||||
#include "default_cb.h"
|
||||
|
||||
struct test_server_st {
|
||||
struct torture_state *state;
|
||||
struct server_state_st *ss;
|
||||
char *cwd;
|
||||
};
|
||||
|
||||
static void
|
||||
free_test_server_state(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
|
||||
torture_free_state(tss->state);
|
||||
SAFE_FREE(tss);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_config(void **state)
|
||||
{
|
||||
struct torture_state *s = NULL;
|
||||
struct server_state_st *ss = NULL;
|
||||
struct test_server_st *tss = NULL;
|
||||
|
||||
char sshd_path[1024];
|
||||
char log_file[1024];
|
||||
char kdc_env[255] = {0};
|
||||
int rc;
|
||||
|
||||
assert_non_null(state);
|
||||
|
||||
tss = (struct test_server_st *)calloc(1, sizeof(struct test_server_st));
|
||||
assert_non_null(tss);
|
||||
|
||||
torture_setup_socket_dir((void **)&s);
|
||||
assert_non_null(s->socket_dir);
|
||||
assert_non_null(s->gss_dir);
|
||||
|
||||
torture_set_kdc_env_str(s->gss_dir, kdc_env, sizeof(kdc_env));
|
||||
torture_set_env_from_str(kdc_env);
|
||||
|
||||
/* Set the default interface for the server */
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
|
||||
setenv("PAM_WRAPPER", "1", 1);
|
||||
|
||||
snprintf(sshd_path, sizeof(sshd_path), "%s/sshd", s->socket_dir);
|
||||
|
||||
rc = mkdir(sshd_path, 0755);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
snprintf(log_file, sizeof(log_file), "%s/sshd/log", s->socket_dir);
|
||||
|
||||
/* Create default server state */
|
||||
ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st));
|
||||
assert_non_null(ss);
|
||||
|
||||
ss->address = strdup("127.0.0.10");
|
||||
assert_non_null(ss->address);
|
||||
|
||||
ss->port = 22;
|
||||
|
||||
/* not to mix up the client and server messages */
|
||||
ss->verbosity = torture_libssh_verbosity();
|
||||
ss->log_file = strdup(log_file);
|
||||
|
||||
ss->auth_methods = SSH_AUTH_METHOD_GSSAPI_KEYEX;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ss->with_pcap = 1;
|
||||
ss->pcap_file = strdup(s->pcap_file);
|
||||
assert_non_null(ss->pcap_file);
|
||||
#endif
|
||||
|
||||
/* TODO make configurable */
|
||||
ss->max_tries = 3;
|
||||
ss->error = 0;
|
||||
|
||||
/* Use the default session handling function */
|
||||
ss->handle_session = default_handle_session_cb;
|
||||
assert_non_null(ss->handle_session);
|
||||
|
||||
/* Do not use global configuration */
|
||||
ss->parse_global_config = false;
|
||||
|
||||
/* Enable GSSAPI key exchange */
|
||||
ss->gssapi_key_exchange = true;
|
||||
ss->gssapi_key_exchange_algs = "gss-group14-sha256-,gss-group16-sha512-";
|
||||
|
||||
tss->state = s;
|
||||
tss->ss = ss;
|
||||
|
||||
*state = tss;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s = NULL;
|
||||
struct server_state_st *ss = NULL;
|
||||
struct test_server_st *tss = NULL;
|
||||
char pid_str[1024] = {0};
|
||||
pid_t pid;
|
||||
/*int rc;*/
|
||||
|
||||
setup_config(state);
|
||||
|
||||
tss = *state;
|
||||
ss = tss->ss;
|
||||
s = tss->state;
|
||||
|
||||
setenv("NSS_WRAPPER_HOSTNAME", "server.libssh.site", 1);
|
||||
/* Start the server using the default values */
|
||||
pid = fork_run_server(ss, free_test_server_state, &tss);
|
||||
if (pid < 0) {
|
||||
fail();
|
||||
}
|
||||
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
||||
|
||||
torture_write_file(s->srv_pidfile, (const char *)pid_str);
|
||||
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
|
||||
unsetenv("PAM_WRAPPER");
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
/*rc = torture_wait_for_daemon(5);*/
|
||||
/*assert_int_equal(rc, 0);*/
|
||||
|
||||
*state = tss;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s = NULL;
|
||||
struct server_state_st *ss = NULL;
|
||||
struct test_server_st *tss = NULL;
|
||||
|
||||
tss = *state;
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
ss = tss->ss;
|
||||
assert_non_null(ss);
|
||||
|
||||
/* This function can be reused */
|
||||
torture_teardown_sshd_server((void **)&s);
|
||||
|
||||
free_server_state(tss->ss);
|
||||
SAFE_FREE(tss->ss);
|
||||
SAFE_FREE(tss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
session_setup(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s = NULL;
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
char *cwd = NULL;
|
||||
bool b = false;
|
||||
int rc;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
/* Make sure we do not test the agent */
|
||||
unsetenv("SSH_AUTH_SOCK");
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tss->cwd = cwd;
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
s->ssh.session = ssh_new();
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
rc = ssh_options_set(s->ssh.session,
|
||||
SSH_OPTIONS_USER,
|
||||
TORTURE_SSH_USER_ALICE);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
/* Make sure no other configuration options from system will get used */
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
session_teardown(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s = NULL;
|
||||
int rc = 0;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
rc = torture_change_dir(tss->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(tss->cwd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
torture_gssapi_server_key_exchange_null(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s = NULL;
|
||||
ssh_session session;
|
||||
int rc;
|
||||
bool t = true;
|
||||
|
||||
/* Skip test if in FIPS mode */
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
session = s->ssh.session;
|
||||
assert_non_null(session);
|
||||
|
||||
/* Valid */
|
||||
torture_setup_kdc_server(
|
||||
(void **)&s,
|
||||
"kadmin.local addprinc -randkey host/server.libssh.site\n"
|
||||
"kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site\n"
|
||||
"kadmin.local addprinc -pw bar alice\n"
|
||||
"kadmin.local list_principals",
|
||||
|
||||
"echo bar | kinit alice");
|
||||
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
assert_string_equal(session->current_crypto->kex_methods[SSH_HOSTKEYS], "null");
|
||||
|
||||
torture_teardown_kdc_server((void **)&s);
|
||||
}
|
||||
|
||||
int
|
||||
torture_run_tests(void)
|
||||
{
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_null,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests,
|
||||
setup_default_server,
|
||||
teardown_default_server);
|
||||
ssh_finalize();
|
||||
|
||||
/* pthread_exit() won't return anything so error should be returned prior */
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Required for freeing memory allocated by GSSAPI */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
@@ -29,6 +29,9 @@ int main(int argc, char **argv)
|
||||
const char *hostkeys = NULL;
|
||||
const char *kex = NULL;
|
||||
int rc = 1;
|
||||
#ifdef WITH_GSSAPI
|
||||
bool t = true;
|
||||
#endif /* WITH_GSSAPI */
|
||||
|
||||
bool process_config = false;
|
||||
|
||||
@@ -75,10 +78,12 @@ int main(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, "gss-group14-sha256-");
|
||||
#ifdef WITH_GSSAPI
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
#endif /* WITH_GSSAPI */
|
||||
|
||||
rc = ssh_connect(session);
|
||||
if (rc != SSH_OK) {
|
||||
|
||||
@@ -819,9 +819,9 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
||||
"Port 22\n"
|
||||
"ListenAddress %s\n"
|
||||
"ListenAddress %s\n"
|
||||
"HostKey %s\n" /* ed25519 HostKey */
|
||||
"HostKey %s\n" /* RSA HostKey */
|
||||
"HostKey %s\n" /* ECDSA HostKey */
|
||||
"%s %s\n" /* ed25519 HostKey */
|
||||
"%s %s\n" /* RSA HostKey */
|
||||
"%s %s\n" /* ECDSA HostKey */
|
||||
"\n"
|
||||
"TrustedUserCAKeys %s\n"
|
||||
"\n"
|
||||
@@ -860,8 +860,8 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
||||
"Port 22\n"
|
||||
"ListenAddress %s\n"
|
||||
"ListenAddress %s\n"
|
||||
"HostKey %s\n" /* RSA HostKey */
|
||||
"HostKey %s\n" /* ECDSA HostKey */
|
||||
"%s %s\n" /* RSA HostKey */
|
||||
"%s %s\n" /* ECDSA HostKey */
|
||||
"\n"
|
||||
"TrustedUserCAKeys %s\n" /* Trusted CA */
|
||||
"\n"
|
||||
@@ -977,16 +977,6 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0));
|
||||
torture_write_file(trusted_ca_pubkey, torture_rsa_certauth_pub);
|
||||
}
|
||||
if (s->disable_hostkeys) {
|
||||
char ss[1000] = {0};
|
||||
rc = snprintf(ss, sizeof(ss), "rm %s/sshd/ssh_host_ecdsa_key %s/sshd/ssh_host_ed25519_key %s/sshd/ssh_host_rsa_key", s->socket_dir, s->socket_dir, s->socket_dir);
|
||||
if (rc < 0 || rc >= (int)sizeof(ss)) {
|
||||
fail_msg("snprintf failed");
|
||||
}
|
||||
|
||||
rc = system(ss);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
sftp_server = getenv("TORTURE_SFTP_SERVER");
|
||||
if (sftp_server == NULL) {
|
||||
@@ -1009,8 +999,22 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
||||
fips_config_string,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV4 : TORTURE_SSHD_SRV_IPV4,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV6 : TORTURE_SSHD_SRV_IPV6,
|
||||
rsa_hostkey,
|
||||
ecdsa_hostkey,
|
||||
"HostKey", rsa_hostkey,
|
||||
"HostKey", ecdsa_hostkey,
|
||||
trusted_ca_pubkey,
|
||||
sftp_server,
|
||||
usepam,
|
||||
additional_config,
|
||||
second_sshd ? s->srv1_pidfile : s->srv_pidfile);
|
||||
} else if (s->disable_hostkeys) {
|
||||
snprintf(sshd_config,
|
||||
sizeof(sshd_config),
|
||||
config_string,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV4 : TORTURE_SSHD_SRV_IPV4,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV6 : TORTURE_SSHD_SRV_IPV6,
|
||||
"", "",
|
||||
"", "",
|
||||
"", "",
|
||||
trusted_ca_pubkey,
|
||||
sftp_server,
|
||||
usepam,
|
||||
@@ -1022,9 +1026,9 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
||||
config_string,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV4 : TORTURE_SSHD_SRV_IPV4,
|
||||
second_sshd ? TORTURE_SSHD_SRV1_IPV6 : TORTURE_SSHD_SRV_IPV6,
|
||||
ed25519_hostkey,
|
||||
rsa_hostkey,
|
||||
ecdsa_hostkey,
|
||||
"HostKey", ed25519_hostkey,
|
||||
"HostKey", rsa_hostkey,
|
||||
"HostKey", ecdsa_hostkey,
|
||||
trusted_ca_pubkey,
|
||||
sftp_server,
|
||||
usepam,
|
||||
|
||||
Reference in New Issue
Block a user