diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 31b2cfb0..3c3d33f2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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$" ############################################################################### diff --git a/src/auth.c b/src/auth.c index 931f1220..3882b435 100644 --- a/src/auth.c +++ b/src/auth.c @@ -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; diff --git a/src/bind.c b/src/bind.c index 7afcd9cc..5b419e46 100644 --- a/src/bind.c +++ b/src/bind.c @@ -245,8 +245,13 @@ int ssh_bind_listen(ssh_bind sshbind) sshbind->ecdsa == NULL && sshbind->ed25519 == NULL) { rc = ssh_bind_import_keys(sshbind); - if (rc != SSH_OK) { - return SSH_ERROR; + 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"); } } @@ -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,8 +525,13 @@ 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) { - return SSH_ERROR; + 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"); } } diff --git a/src/dh-gss.c b/src/dh-gss.c index 9ababd82..c890d99e 100644 --- a/src/dh-gss.c +++ b/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,32 +346,39 @@ 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; } - rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); - if (rc != SSH_OK) { - goto error; - } - rc = ssh_buffer_pack(session->out_buffer, - "bS", - SSH2_MSG_KEXGSS_HOSTKEY, - server_pubkey_blob); - if(rc != SSH_OK) { - ssh_set_error_oom(session); - ssh_buffer_reinit(session->out_buffer); - 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; + } + rc = ssh_buffer_pack(session->out_buffer, + "bS", + SSH2_MSG_KEXGSS_HOSTKEY, + server_pubkey_blob); + if(rc != SSH_OK) { + ssh_set_error_oom(session); + ssh_buffer_reinit(session->out_buffer); + goto error; + } - rc = ssh_packet_send(session); - if (rc == SSH_ERROR) { - goto error; + rc = ssh_packet_send(session); + if (rc == SSH_ERROR) { + goto error; + } + SSH_LOG(SSH_LOG_DEBUG, "Sent SSH2_MSG_KEXGSS_HOSTKEY"); + SSH_STRING_FREE(server_pubkey_blob); } - 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); diff --git a/src/gssapi.c b/src/gssapi.c index d3d41205..2c1bdb0f 100644 --- a/src/gssapi.c +++ b/src/gssapi.c @@ -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: diff --git a/src/kex.c b/src/kex.c index da7767c7..d7dfac35 100644 --- a/src/kex.c +++ b/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); - server_pubkey_blob = ssh_string_new(0); - } - - if (session->server) { - if (server_pubkey_blob == NULL && ssh_kex_is_gss(session->next_crypto)) { - 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; + } } } diff --git a/src/options.c b/src/options.c index fec3676a..932becbc 100644 --- a/src/options.c +++ b/src/options.c @@ -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; diff --git a/src/server.c b/src/server.c index c454c1a6..d984b79c 100644 --- a/src/server.c +++ b/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,33 +151,34 @@ int server_set_kex(ssh_session session) } } - /* It is expected for the list of allowed hostkeys to be ordered by - * preference */ - kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys, - allowed); - if (kept == NULL) { - /* Nothing was allowed */ - return -1; - } + 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, + allowed); + if (kept == NULL) { + /* Nothing was allowed */ + return -1; + } - rc = ssh_options_set_algo(session, - SSH_HOSTKEYS, - kept, - &session->opts.wanted_methods[SSH_HOSTKEYS]); - SAFE_FREE(kept); - if (rc < 0) { - return -1; + rc = ssh_options_set_algo(session, + SSH_HOSTKEYS, + kept, + &session->opts.wanted_methods[SSH_HOSTKEYS]); + SAFE_FREE(kept); + 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 */ diff --git a/src/session.c b/src/session.c index 7b48a562..3c22bf47 100644 --- a/src/session.c +++ b/src/session.c @@ -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; diff --git a/tests/client/torture_gssapi_auth.c b/tests/client/torture_gssapi_auth.c index 20f35419..d40d7a62 100644 --- a/tests/client/torture_gssapi_auth.c +++ b/tests/client/torture_gssapi_auth.c @@ -272,5 +272,11 @@ torture_run_tests(void) rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); - return 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); } diff --git a/tests/client/torture_gssapi_key_exchange.c b/tests/client/torture_gssapi_key_exchange.c index 60609832..80f5934e 100644 --- a/tests/client/torture_gssapi_key_exchange.c +++ b/tests/client/torture_gssapi_key_exchange.c @@ -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); } diff --git a/tests/client/torture_gssapi_key_exchange_null.c b/tests/client/torture_gssapi_key_exchange_null.c index 874a85e8..f6e24a86 100644 --- a/tests/client/torture_gssapi_key_exchange_null.c +++ b/tests/client/torture_gssapi_key_exchange_null.c @@ -19,21 +19,23 @@ sshd_setup(void **state) s = *state; s->disable_hostkeys = true; - /* Temporary kerberos server */ - torture_setup_kdc_server( - state, - "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", + if (!ssh_fips_mode()) { + /* Temporary kerberos server */ + torture_setup_kdc_server( + state, + "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"); + "echo bar | kinit alice"); - torture_update_sshd_config(state, - "GSSAPIAuthentication yes\n" - "GSSAPIKeyExchange yes\n"); + torture_update_sshd_config(state, + "GSSAPIAuthentication yes\n" + "GSSAPIKeyExchange yes\n"); - torture_teardown_kdc_server(state); + 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); } diff --git a/tests/server/CMakeLists.txt b/tests/server/CMakeLists.txt index d6c14952..89de495f 100644 --- a/tests/server/CMakeLists.txt +++ b/tests/server/CMakeLists.txt @@ -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 diff --git a/tests/server/test_server/test_server.c b/tests/server/test_server/test_server.c index bf215a57..69b6dac2 100644 --- a/tests/server/test_server/test_server.c +++ b/tests/server/test_server/test_server.c @@ -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; } diff --git a/tests/server/torture_gssapi_server_auth.c b/tests/server/torture_gssapi_server_auth.c index 8058d4d0..a1ed351a 100644 --- a/tests/server/torture_gssapi_server_auth.c +++ b/tests/server/torture_gssapi_server_auth.c @@ -452,5 +452,11 @@ torture_run_tests(void) teardown_default_server); ssh_finalize(); - return 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); } diff --git a/tests/server/torture_gssapi_server_auth_cb.c b/tests/server/torture_gssapi_server_auth_cb.c index 381af800..abafdd61 100644 --- a/tests/server/torture_gssapi_server_auth_cb.c +++ b/tests/server/torture_gssapi_server_auth_cb.c @@ -476,5 +476,11 @@ torture_run_tests(void) teardown_default_server); ssh_finalize(); - return 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); } diff --git a/tests/server/torture_gssapi_server_delegation.c b/tests/server/torture_gssapi_server_delegation.c index dd3ad335..a14a53c3 100644 --- a/tests/server/torture_gssapi_server_delegation.c +++ b/tests/server/torture_gssapi_server_delegation.c @@ -372,5 +372,11 @@ torture_run_tests(void) teardown_default_server); ssh_finalize(); - return 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); } diff --git a/tests/server/torture_gssapi_server_key_exchange.c b/tests/server/torture_gssapi_server_key_exchange.c index 981e7634..7139a65b 100644 --- a/tests/server/torture_gssapi_server_key_exchange.c +++ b/tests/server/torture_gssapi_server_key_exchange.c @@ -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); } diff --git a/tests/server/torture_gssapi_server_key_exchange_null.c b/tests/server/torture_gssapi_server_key_exchange_null.c new file mode 100644 index 00000000..01f962f1 --- /dev/null +++ b/tests/server/torture_gssapi_server_key_exchange_null.c @@ -0,0 +1,305 @@ +#include "config.h" + +#define LIBSSH_STATIC + +#include +#include +#include +#include + +#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); +} diff --git a/tests/ssh_ping.c b/tests/ssh_ping.c index 9b53c7b3..31bb64b4 100644 --- a/tests/ssh_ping.c +++ b/tests/ssh_ping.c @@ -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) { diff --git a/tests/torture.c b/tests/torture.c index a474fcce..6b32d329 100644 --- a/tests/torture.c +++ b/tests/torture.c @@ -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,