diff --git a/include/libssh/gssapi.h b/include/libssh/gssapi.h index a3e24922..578ec1d6 100644 --- a/include/libssh/gssapi.h +++ b/include/libssh/gssapi.h @@ -89,6 +89,8 @@ OM_uint32 ssh_gssapi_init_ctx(struct ssh_gssapi_struct *gssapi, char *ssh_gssapi_oid_hash(ssh_string oid); char *ssh_gssapi_kex_mechs(ssh_session session, const char *gss_algs); int ssh_gssapi_check_client_config(ssh_session session); +ssh_buffer ssh_gssapi_build_mic(ssh_session session, const char *context); +int ssh_gssapi_auth_keyex_mic(ssh_session session, gss_buffer_desc *mic_token_buf); #ifdef __cplusplus } diff --git a/include/libssh/kex.h b/include/libssh/kex.h index a3f972ec..02b5c56e 100644 --- a/include/libssh/kex.h +++ b/include/libssh/kex.h @@ -31,6 +31,8 @@ struct ssh_kex_struct { char *methods[SSH_KEX_METHODS]; }; +#include "libssh/crypto.h" + #ifdef __cplusplus extern "C" { #endif @@ -64,6 +66,7 @@ int ssh_make_sessionid(ssh_session session); int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie); int ssh_hashbufout_add_cookie(ssh_session session); int ssh_generate_session_keys(ssh_session session); +bool ssh_kex_is_gss(struct ssh_crypto_struct *crypto); #ifdef __cplusplus } diff --git a/include/libssh/server.h b/include/libssh/server.h index 47860ca3..ee800567 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -247,6 +247,7 @@ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o); * SSH_AUTH_METHOD_HOSTBASED * SSH_AUTH_METHOD_INTERACTIVE * SSH_AUTH_METHOD_GSSAPI_MIC + * SSH_AUTH_METHOD_GSSAPI_KEYEX */ LIBSSH_API void ssh_set_auth_methods(ssh_session session, int auth_methods); diff --git a/src/auth.c b/src/auth.c index 5e9834fe..931f1220 100644 --- a/src/auth.c +++ b/src/auth.c @@ -2473,9 +2473,7 @@ int ssh_userauth_gssapi_keyex(ssh_session session) { int rc = SSH_AUTH_DENIED; #ifdef WITH_GSSAPI - ssh_buffer buf = ssh_buffer_new(); - gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; - OM_uint32 maj_stat, min_stat; + OM_uint32 min_stat; gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER; switch(session->pending_call_state) { @@ -2492,15 +2490,11 @@ int ssh_userauth_gssapi_keyex(ssh_session session) } /* Check if GSSAPI Key exchange was performed */ - switch (session->current_crypto->kex_type) { - case SSH_GSS_KEX_DH_GROUP14_SHA256: - case SSH_GSS_KEX_DH_GROUP16_SHA512: - break; - default: - ssh_set_error(session, - SSH_FATAL, - "Attempt to authenticate with \"gssapi-keyex\" without doing GSSAPI Key exchange."); - return SSH_ERROR; + if (!ssh_kex_is_gss(session->current_crypto)) { + ssh_set_error(session, + SSH_FATAL, + "Attempt to authenticate with \"gssapi-keyex\" without doing GSSAPI Key exchange."); + return SSH_ERROR; } rc = ssh_userauth_request_service(session); @@ -2515,38 +2509,14 @@ int ssh_userauth_gssapi_keyex(ssh_session session) session->auth.state = SSH_AUTH_STATE_NONE; session->pending_call_state = SSH_PENDING_CALL_AUTH_GSSAPI_KEYEX; - rc = ssh_buffer_pack(buf, - "dPbsss", - session->current_crypto->session_id_len, - session->current_crypto->session_id_len, - session->current_crypto->session_id, - SSH2_MSG_USERAUTH_REQUEST, - session->opts.username, - "ssh-connection", - "gssapi-keyex"); + session->gssapi->user = strdup(session->opts.username); + rc = ssh_gssapi_auth_keyex_mic(session, &mic_token_buf); if (rc != SSH_OK) { - ssh_set_error_oom(session); session->auth.state = SSH_AUTH_STATE_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE; return rc; } - mic_buf.length = ssh_buffer_get_len(buf); - mic_buf.value = ssh_buffer_get(buf); - - maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, - &mic_buf, &mic_token_buf); - if (GSS_ERROR(maj_stat)) { - ssh_gssapi_log_error(SSH_LOG_DEBUG, - "generating MIC", - maj_stat, - min_stat); - session->auth.state = SSH_AUTH_STATE_NONE; - session->pending_call_state = SSH_PENDING_CALL_NONE; - return SSH_ERROR; - } - SSH_BUFFER_FREE(buf); - rc = ssh_buffer_pack(session->out_buffer, "bsssdP", SSH2_MSG_USERAUTH_REQUEST, diff --git a/src/gssapi.c b/src/gssapi.c index f4addd64..d3d41205 100644 --- a/src/gssapi.c +++ b/src/gssapi.c @@ -457,7 +457,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server) #endif /* WITH_SERVER */ -static ssh_buffer ssh_gssapi_build_mic(ssh_session session) +ssh_buffer ssh_gssapi_build_mic(ssh_session session, const char *context) { struct ssh_crypto_struct *crypto = NULL; ssh_buffer mic_buffer = NULL; @@ -481,7 +481,7 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session) SSH2_MSG_USERAUTH_REQUEST, session->gssapi->user, "ssh-connection", - "gssapi-with-mic"); + context); if (rc != SSH_OK) { ssh_set_error_oom(session); SSH_BUFFER_FREE(mic_buffer); @@ -516,7 +516,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic) goto error; } - mic_buffer = ssh_gssapi_build_mic(session); + mic_buffer = ssh_gssapi_build_mic(session, "gssapi-with-mic"); if (mic_buffer == NULL) { ssh_set_error_oom(session); goto error; @@ -1166,6 +1166,40 @@ out: return SSH_AUTH_ERROR; } +/** + * @brief Get the MIC for "gssapi-keyex" authentication. + * @returns SSH_ERROR: A serious error happened\n + * SSH_OK: MIC token is stored in mic_token_buf + */ +int ssh_gssapi_auth_keyex_mic(ssh_session session, gss_buffer_desc *mic_token_buf) { + ssh_buffer buf = NULL; + gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; + OM_uint32 maj_stat, min_stat; + + buf = ssh_gssapi_build_mic(session, "gssapi-keyex"); + if (buf == NULL) { + ssh_set_error_oom(session); + return SSH_ERROR; + } + + mic_buf.length = ssh_buffer_get_len(buf); + mic_buf.value = ssh_buffer_get(buf); + + maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, + &mic_buf, mic_token_buf); + if (GSS_ERROR(maj_stat)) { + ssh_gssapi_log_error(SSH_LOG_DEBUG, + "generating MIC", + maj_stat, + min_stat); + SSH_BUFFER_FREE(buf); + return SSH_ERROR; + } + SSH_BUFFER_FREE(buf); + + return SSH_OK; +} + static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s) { gss_OID ret = NULL; @@ -1275,7 +1309,7 @@ static int ssh_gssapi_send_mic(ssh_session session) SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC"); - mic_buffer = ssh_gssapi_build_mic(session); + mic_buffer = ssh_gssapi_build_mic(session, "gssapi-with-mic"); if (mic_buffer == NULL) { ssh_set_error_oom(session); return SSH_ERROR; diff --git a/src/kex.c b/src/kex.c index 9fe8ffd5..1ccc4636 100644 --- a/src/kex.c +++ b/src/kex.c @@ -1480,14 +1480,9 @@ int ssh_make_sessionid(ssh_session session) } if (session->server) { - switch (session->next_crypto->kex_type) { - case SSH_GSS_KEX_DH_GROUP14_SHA256: - case SSH_GSS_KEX_DH_GROUP16_SHA512: + if (ssh_kex_is_gss(session->next_crypto)) { ssh_string_free(server_pubkey_blob); server_pubkey_blob = ssh_string_new(0); - break; - default: - break; } } @@ -2020,3 +2015,21 @@ error: return rc; } + +/** @internal + * @brief Check if a given crypto context has a GSSAPI KEX set + * + * @param[in] crypto The SSH crypto context + * @return true if the KEX of the context is a GSSAPI KEX, false otherwise + */ +bool +ssh_kex_is_gss(struct ssh_crypto_struct *crypto) +{ + switch (crypto->kex_type) { + case SSH_GSS_KEX_DH_GROUP14_SHA256: + case SSH_GSS_KEX_DH_GROUP16_SHA512: + return true; + default: + return false; + } +} diff --git a/src/messages.c b/src/messages.c index 011c75c0..9d55a5ec 100644 --- a/src/messages.c +++ b/src/messages.c @@ -1145,6 +1145,67 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request) SAFE_FREE(method); SSH_MESSAGE_FREE(msg); + return SSH_PACKET_USED; + } + if (strcmp(method, "gssapi-keyex") == 0) { + gss_buffer_desc received_mic = GSS_C_EMPTY_BUFFER; + gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; + ssh_string mic_token_string = NULL; + OM_uint32 maj_stat, min_stat; + ssh_buffer buf = NULL; + + if (!ssh_kex_is_gss(session->current_crypto)) { + ssh_set_error(session, + SSH_FATAL, + "Attempt to authenticate with \"gssapi-keyex\" without doing GSSAPI Key Exchange"); + ssh_auth_reply_default(session, 0); + goto error; + } + + rc = ssh_buffer_unpack(packet, "S", &mic_token_string); + if (rc != SSH_OK){ + ssh_auth_reply_default(session, 0); + goto error; + } + received_mic.length = ssh_string_len(mic_token_string); + received_mic.value = ssh_string_data(mic_token_string); + + session->gssapi->user = strdup(msg->auth_request.username); + buf = ssh_gssapi_build_mic(session, "gssapi-keyex"); + if (buf == NULL) { + ssh_set_error_oom(session); + SSH_STRING_FREE(mic_token_string); + ssh_auth_reply_default(session, 0); + goto error; + } + + mic_buf.length = ssh_buffer_get_len(buf); + mic_buf.value = ssh_buffer_get(buf); + + maj_stat = gss_verify_mic(&min_stat, + session->gssapi->ctx, + &mic_buf, + &received_mic, + NULL); + if (maj_stat != GSS_S_COMPLETE) { + ssh_set_error(session, + SSH_FATAL, + "Failed to verify MIC for \"gssapi-keyex\" auth"); + SSH_BUFFER_FREE(buf); + SSH_STRING_FREE(mic_token_string); + ssh_auth_reply_default(session, 0); + goto error; + } + + ssh_auth_reply_success(session, 0); + + /* bypass the message queue thing */ + SAFE_FREE(service); + SAFE_FREE(method); + SSH_BUFFER_FREE(buf); + SSH_MESSAGE_FREE(msg); + SSH_STRING_FREE(mic_token_string); + return SSH_PACKET_USED; } #endif diff --git a/src/server.c b/src/server.c index 09e4d213..c454c1a6 100644 --- a/src/server.c +++ b/src/server.c @@ -699,6 +699,12 @@ int ssh_auth_reply_default(ssh_session session,int partial) { strncat(methods_c,"gssapi-with-mic,", sizeof(methods_c) - strlen(methods_c) - 1); } + /* Check if GSSAPI Key exchange was performed */ + if (session->auth.supported_methods & SSH_AUTH_METHOD_GSSAPI_KEYEX) { + if (ssh_kex_is_gss(session->current_crypto)) { + strncat(methods_c, "gssapi-keyex,", sizeof(methods_c) - strlen(methods_c) - 1); + } + } if (session->auth.supported_methods & SSH_AUTH_METHOD_INTERACTIVE) { strncat(methods_c, "keyboard-interactive,", sizeof(methods_c) - strlen(methods_c) - 1); diff --git a/tests/client/torture_gssapi_key_exchange.c b/tests/client/torture_gssapi_key_exchange.c index d859f2e0..60609832 100644 --- a/tests/client/torture_gssapi_key_exchange.c +++ b/tests/client/torture_gssapi_key_exchange.c @@ -226,6 +226,38 @@ torture_gssapi_key_exchange_auth(void **state) torture_teardown_kdc_server(state); } +static void +torture_gssapi_key_exchange_no_auth(void **state) +{ + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; + bool f = false; + + /* Valid */ + 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"); + + /* Don't do GSSAPI Key Exchange */ + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &f); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(session); + assert_int_equal(rc, 0); + + /* Still try to do "gssapi-keyex" auth */ + rc = ssh_userauth_gssapi_keyex(session); + assert_int_equal(rc, SSH_AUTH_ERROR); + + torture_teardown_kdc_server(state); +} + int torture_run_tests(void) { @@ -246,6 +278,9 @@ torture_run_tests(void) cmocka_unit_test_setup_teardown(torture_gssapi_key_exchange_auth, session_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_key_exchange_no_auth, + session_setup, + session_teardown), }; ssh_init(); diff --git a/tests/server/test_server/main.c b/tests/server/test_server/main.c index 8c9f79f2..e47ae231 100644 --- a/tests/server/test_server/main.c +++ b/tests/server/test_server/main.c @@ -115,6 +115,9 @@ static void print_auth_methods(int auth_methods) if (auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { printf("\tSSH_AUTH_METHOD_GSSAPI_MIC\n"); } + if (auth_methods & SSH_AUTH_METHOD_GSSAPI_KEYEX) { + printf("\tSSH_AUTH_METHOD_GSSAPI_KEYEX\n"); + } } static void print_verbosity(int verbosity) diff --git a/tests/server/torture_gssapi_server_key_exchange.c b/tests/server/torture_gssapi_server_key_exchange.c index ed255ac4..981e7634 100644 --- a/tests/server/torture_gssapi_server_key_exchange.c +++ b/tests/server/torture_gssapi_server_key_exchange.c @@ -8,14 +8,13 @@ #include #include "libssh/libssh.h" +#include "libssh/crypto.h" #include "torture.h" #include "torture_key.h" #include "test_server.h" #include "default_cb.h" -#define TORTURE_KNOWN_HOSTS_FILE "libssh_torture_knownhosts" - struct test_server_st { struct torture_state *state; struct server_state_st *ss; @@ -119,7 +118,7 @@ setup_config(void **state) ss->verbosity = torture_libssh_verbosity(); ss->log_file = strdup(log_file); - ss->auth_methods = SSH_AUTH_METHOD_GSSAPI_MIC; + ss->auth_methods = SSH_AUTH_METHOD_GSSAPI_KEYEX; #ifdef WITH_PCAP ss->with_pcap = 1; @@ -154,7 +153,7 @@ 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]; + char pid_str[1024] = {0}; pid_t pid; int rc; @@ -217,7 +216,7 @@ static int session_setup(void **state) { struct test_server_st *tss = *state; - struct torture_state *s; + struct torture_state *s = NULL; int verbosity = torture_libssh_verbosity(); char *cwd = NULL; bool b = false; @@ -258,7 +257,7 @@ static int session_teardown(void **state) { struct test_server_st *tss = *state; - struct torture_state *s; + struct torture_state *s = NULL; int rc = 0; assert_non_null(tss); @@ -282,7 +281,7 @@ static void torture_gssapi_server_key_exchange(void **state) { struct test_server_st *tss = *state; - struct torture_state *s; + struct torture_state *s = NULL; ssh_session session; int rc; bool t = true; @@ -308,12 +307,211 @@ torture_gssapi_server_key_exchange(void **state) 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_int_equal(rc, SSH_OK); + + torture_teardown_kdc_server((void **)&s); +} + +static void +torture_gssapi_server_key_exchange_no_tgt(void **state) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session; + int rc; + bool t = true; + + assert_non_null(tss); + + s = tss->state; + assert_non_null(s); + + session = s->ssh.session; + assert_non_null(session); + + /* Don't run kinit */ + 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", + + /* No TGT */ + ""); + + 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_int_equal(rc, 0); + + 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); + + torture_teardown_kdc_server((void **)&s); +} + +static void +torture_gssapi_server_key_exchange_gss_group14_sha256(void **state) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session; + int rc; + bool t = true; + + 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_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, "gss-group14-sha256-"); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(session); + assert_int_equal(rc, 0); + + assert_int_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP14_SHA256); + + torture_teardown_kdc_server((void **)&s); +} + +static void +torture_gssapi_server_key_exchange_gss_group16_sha512(void **state) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session; + int rc; + bool t = true; + + 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_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, "gss-group16-sha512-"); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_connect(session); - fprintf(stderr, "%s", ssh_get_error(session)); + assert_int_equal(rc, 0); + + assert_int_equal(session->current_crypto->kex_type, SSH_GSS_KEX_DH_GROUP16_SHA512); + + torture_teardown_kdc_server((void **)&s); +} + +static void +torture_gssapi_server_key_exchange_auth(void **state) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session; + int rc; + bool t = true; + + 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_int_equal(rc, SSH_OK); + + rc = ssh_userauth_gssapi_keyex(session); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + torture_teardown_kdc_server((void **)&s); +} + +static void +torture_gssapi_server_key_exchange_no_auth(void **state) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session = NULL; + int rc; + bool f = false; + + 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"); + + /* Don't do GSSAPI Key Exchange */ + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &f); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(session); + assert_int_equal(rc, SSH_OK); + + /* Still try to do "gssapi-keyex" auth */ + rc = ssh_userauth_gssapi_keyex(session); + assert_int_equal(rc, SSH_AUTH_ERROR); + torture_teardown_kdc_server((void **)&s); } @@ -325,6 +523,21 @@ torture_run_tests(void) cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange, session_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_no_tgt, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_gss_group14_sha256, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_gss_group16_sha512, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_auth, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_no_auth, + session_setup, + session_teardown), }; ssh_init();