diff options
Diffstat (limited to 'tests/client/torture_auth.c')
-rw-r--r-- | tests/client/torture_auth.c | 712 |
1 files changed, 546 insertions, 166 deletions
diff --git a/tests/client/torture_auth.c b/tests/client/torture_auth.c index 24ecc507..77b7bd1f 100644 --- a/tests/client/torture_auth.c +++ b/tests/client/torture_auth.c @@ -32,8 +32,7 @@ #include <sys/types.h> #include <pwd.h> -/* agent_is_running */ -#include "agent.c" +#include "torture_auth_common.c" static int sshd_setup(void **state) { @@ -112,7 +111,7 @@ static int agent_setup(void **state) char ssh_agent_cmd[4096]; char ssh_agent_sock[1024]; char ssh_agent_pidfile[1024]; - char bob_ssh_key[1024]; + char ssh_key_add[1024]; struct passwd *pwd; int rc; @@ -149,38 +148,12 @@ static int agent_setup(void **state) setenv("SSH_AUTH_SOCK", ssh_agent_sock, 1); setenv("TORTURE_SSH_AGENT_PIDFILE", ssh_agent_pidfile, 1); - snprintf(bob_ssh_key, - sizeof(bob_ssh_key), + snprintf(ssh_key_add, + sizeof(ssh_key_add), "ssh-add %s/.ssh/id_rsa", pwd->pw_dir); - rc = system(bob_ssh_key); - assert_return_code(rc, errno); - - return 0; -} - -static int agent_cert_setup(void **state) -{ - char bob_alt_ssh_key[1024]; - struct passwd *pwd; - int rc; - - rc = agent_setup(state); - if (rc != 0) { - return rc; - } - - pwd = getpwnam("bob"); - assert_non_null(pwd); - - /* remove all keys, load alternative key + cert */ - snprintf(bob_alt_ssh_key, - sizeof(bob_alt_ssh_key), - "ssh-add -D && ssh-add %s/.ssh_cert/id_rsa", - pwd->pw_dir); - - rc = system(bob_alt_ssh_key); + rc = system(ssh_key_add); assert_return_code(rc, errno); return 0; @@ -257,6 +230,143 @@ static void torture_auth_none_nonblocking(void **state) { } +/* Setting MaxAuthTries 0 makes libssh hang. The option is not practical, + * but simulates setting low value and requiring multiple authentication + * methods to succeed (T233) + */ +static void torture_auth_none_max_tries(void **state) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; + const char *sshd_config = "MaxAuthTries 0"; + + torture_update_sshd_config(state, sshd_config); + + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); + assert_int_equal(rc, SSH_OK); + + rc = ssh_connect(session); + assert_int_equal(rc, SSH_OK); + + rc = ssh_userauth_none(session,NULL); + assert_int_equal(rc, SSH_AUTH_DENIED); + + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + } + + /* Reset config back to defaults */ + torture_update_sshd_config(state, ""); +} + + +static void torture_auth_pubkey(void **state) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + char bob_ssh_key[1024]; + ssh_key privkey = NULL; + struct passwd *pwd = NULL; + int rc; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + snprintf(bob_ssh_key, + sizeof(bob_ssh_key), + "%s/.ssh/id_rsa", + pwd->pw_dir); + + /* Authenticate as alice with bob his pubkey */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); + assert_int_equal(rc, SSH_OK); + + rc = ssh_connect(session); + assert_int_equal(rc, SSH_OK); + + rc = ssh_userauth_none(session, NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + } + + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); + assert_int_equal(rc, SSH_OK); + + /* negative tests */ + rc = ssh_userauth_try_publickey(NULL, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_ERROR); + rc = ssh_userauth_try_publickey(session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_ERROR); + + rc = ssh_userauth_try_publickey(session, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + /* negative tests */ + rc = ssh_userauth_publickey(NULL, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_ERROR); + rc = ssh_userauth_publickey(session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_ERROR); + + rc = ssh_userauth_publickey(session, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + SSH_KEY_FREE(privkey); +} + +static void torture_auth_pubkey_nonblocking(void **state) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + char bob_ssh_key[1024]; + ssh_key privkey = NULL; + struct passwd *pwd = NULL; + int rc; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + snprintf(bob_ssh_key, + sizeof(bob_ssh_key), + "%s/.ssh/id_rsa", + pwd->pw_dir); + + /* Authenticate as alice with bob his pubkey */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); + assert_int_equal(rc, SSH_OK); + + rc = ssh_connect(session); + assert_int_equal(rc, SSH_OK); + + ssh_set_blocking(session, 0); + + do { + rc = ssh_userauth_none(session,NULL); + } while (rc == SSH_AUTH_AGAIN); + assert_int_equal(rc, SSH_AUTH_DENIED); + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); + assert_int_equal(rc, SSH_OK); + + do { + rc = ssh_userauth_try_publickey(session, NULL, privkey); + } while (rc == SSH_AUTH_AGAIN); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + do { + rc = ssh_userauth_publickey(session, NULL, privkey); + } while (rc == SSH_AUTH_AGAIN); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + SSH_KEY_FREE(privkey); +} + static void torture_auth_autopubkey(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; @@ -281,6 +391,96 @@ static void torture_auth_autopubkey(void **state) { assert_int_equal(rc, SSH_AUTH_SUCCESS); } +struct torture_auth_autopubkey_protected_data { + ssh_session session; + int n_calls; +}; + +static int +torture_auth_autopubkey_protected_auth_function (const char *prompt, char *buf, size_t len, + int echo, int verify, void *userdata) +{ + int rc; + char *id, *expected_id; + struct torture_auth_autopubkey_protected_data *data = userdata; + + assert_true(prompt != NULL); + assert_int_equal(echo, 0); + assert_int_equal(verify, 0); + + expected_id = ssh_path_expand_escape(data->session, "%d/id_rsa_protected"); + assert_true(expected_id != NULL); + + rc = ssh_userauth_publickey_auto_get_current_identity(data->session, &id); + assert_int_equal(rc, SSH_OK); + + assert_string_equal(expected_id, id); + + ssh_string_free_char(id); + ssh_string_free_char(expected_id); + + data->n_calls += 1; + strncpy(buf, "secret", len); + return 0; +} + +static void torture_auth_autopubkey_protected(void **state) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + char *id; + int rc; + + struct torture_auth_autopubkey_protected_data data = { + .session = session, + .n_calls = 0 + }; + + struct ssh_callbacks_struct callbacks = { + .userdata = &data, + .auth_function = torture_auth_autopubkey_protected_auth_function + }; + + /* no session pointer */ + rc = ssh_userauth_publickey_auto_get_current_identity(NULL, &id); + assert_int_equal(rc, SSH_ERROR); + + /* no result pointer */ + rc = ssh_userauth_publickey_auto_get_current_identity(session, NULL); + assert_int_equal(rc, SSH_ERROR); + + /* no auto auth going on */ + rc = ssh_userauth_publickey_auto_get_current_identity(session, &id); + assert_int_equal(rc, SSH_ERROR); + + ssh_callbacks_init(&callbacks); + ssh_set_callbacks(session, &callbacks); + + /* Authenticate as alice with bob his pubkey */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); + assert_int_equal(rc, SSH_OK); + + /* Try id_rsa_protected first. + */ + rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "%d/id_rsa_protected"); + assert_int_equal(rc, SSH_OK); + + rc = ssh_connect(session); + assert_int_equal(rc, SSH_OK); + + rc = ssh_userauth_none(session,NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + } + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + rc = ssh_userauth_publickey_auto(session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + assert_int_equal (data.n_calls, 1); +} + static void torture_auth_autopubkey_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; @@ -311,7 +511,11 @@ static void torture_auth_autopubkey_nonblocking(void **state) { assert_int_equal(rc, SSH_AUTH_SUCCESS); } -static void torture_auth_kbdint(void **state) { +static void +torture_auth_kbdint(void **state, + const char *password, + enum ssh_auth_e res) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -334,19 +538,35 @@ static void torture_auth_kbdint(void **state) { assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1); - rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD); + rc = ssh_userauth_kbdint_setanswer(session, 0, password); assert_false(rc < 0); rc = ssh_userauth_kbdint(session, NULL, NULL); /* Sometimes, SSH server send an empty query at the end of exchange */ - if(rc == SSH_AUTH_INFO) { + if (rc == SSH_AUTH_INFO) { assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0); rc = ssh_userauth_kbdint(session, NULL, NULL); } - assert_int_equal(rc, SSH_AUTH_SUCCESS); + assert_int_equal(rc, res); } -static void torture_auth_kbdint_nonblocking(void **state) { +static void +torture_auth_kbdint_good(void **state) +{ + torture_auth_kbdint(state, TORTURE_SSH_USER_BOB_PASSWORD, SSH_AUTH_SUCCESS); +} + +static void +torture_auth_kbdint_bad(void **state) +{ + torture_auth_kbdint(state, "bad password stample", SSH_AUTH_DENIED); +} + +static void +torture_auth_kbdint_nonblocking(void **state, + const char *password, + enum ssh_auth_e res) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -357,9 +577,9 @@ static void torture_auth_kbdint_nonblocking(void **state) { rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); - ssh_set_blocking(session,0); + ssh_set_blocking(session, 0); do { - rc = ssh_userauth_none(session, NULL); + rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ @@ -374,23 +594,41 @@ static void torture_auth_kbdint_nonblocking(void **state) { } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1); - rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD); + rc = ssh_userauth_kbdint_setanswer(session, 0, password); assert_false(rc < 0); do { rc = ssh_userauth_kbdint(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); /* Sometimes, SSH server send an empty query at the end of exchange */ - if(rc == SSH_AUTH_INFO) { + if (rc == SSH_AUTH_INFO) { assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0); do { rc = ssh_userauth_kbdint(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); } - assert_int_equal(rc, SSH_AUTH_SUCCESS); + assert_int_equal(rc, res); +} + +static void +torture_auth_kbdint_nonblocking_good(void **state) +{ + torture_auth_kbdint_nonblocking(state, + TORTURE_SSH_USER_BOB_PASSWORD, + SSH_AUTH_SUCCESS); +} + +static void +torture_auth_kbdint_nonblocking_bad(void **state) +{ + torture_auth_kbdint_nonblocking(state, + "bad password stample", + SSH_AUTH_DENIED); } -static void torture_auth_password(void **state) { +static void +torture_auth_password(void **state, const char *password, enum ssh_auth_e res) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -409,11 +647,29 @@ static void torture_auth_password(void **state) { rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PASSWORD); - rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD); - assert_int_equal(rc, SSH_AUTH_SUCCESS); + rc = ssh_userauth_password(session, NULL, password); + assert_int_equal(rc, res); +} + +static void +torture_auth_password_good(void **state) +{ + torture_auth_password(state, + TORTURE_SSH_USER_BOB_PASSWORD, + SSH_AUTH_SUCCESS); } -static void torture_auth_password_nonblocking(void **state) { +static void +torture_auth_password_bad(void **state) +{ + torture_auth_password(state, "bad password stample", SSH_AUTH_DENIED); +} + +static void +torture_auth_password_nonblocking(void **state, + const char *password, + enum ssh_auth_e res) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; @@ -426,7 +682,7 @@ static void torture_auth_password_nonblocking(void **state) { ssh_set_blocking(session,0); do { - rc = ssh_userauth_none(session, NULL); + rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ @@ -438,16 +694,51 @@ static void torture_auth_password_nonblocking(void **state) { assert_true(rc & SSH_AUTH_METHOD_PASSWORD); do { - rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD); - } while(rc==SSH_AUTH_AGAIN); + rc = ssh_userauth_password(session, NULL, password); + } while (rc == SSH_AUTH_AGAIN); - assert_int_equal(rc, SSH_AUTH_SUCCESS); + assert_int_equal(rc, res); +} + +static void +torture_auth_password_nonblocking_good(void **state) +{ + torture_auth_password_nonblocking(state, + TORTURE_SSH_USER_BOB_PASSWORD, + SSH_AUTH_SUCCESS); +} + +static void +torture_auth_password_nonblocking_bad(void **state) +{ + torture_auth_password_nonblocking(state, + "bad password stample", + SSH_AUTH_DENIED); } -static void torture_auth_agent(void **state) { +/* TODO cover the case: + * * when there is accompanying certificate (identities only + agent) + * * export private key to public key during _auto() authentication. + * this needs to be a encrypted private key in PEM format without + * accompanying public key. + */ +static void torture_auth_agent_identities_only(void **state) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; + char bob_ssh_key[1024]; + struct passwd *pwd = NULL; int rc; + int identities_only = 1; + char *id = NULL; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + snprintf(bob_ssh_key, + sizeof(bob_ssh_key), + "%s/.ssh/id_rsa", + pwd->pw_dir); if (!ssh_agent_is_running(session)){ print_message("*** Agent not running. Test ignored\n"); @@ -456,37 +747,18 @@ static void torture_auth_agent(void **state) { rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); - rc = ssh_connect(session); + rc = ssh_options_set(session, SSH_OPTIONS_IDENTITIES_ONLY, &identities_only); assert_int_equal(rc, SSH_OK); - rc = ssh_userauth_none(session,NULL); - /* This request should return a SSH_REQUEST_DENIED error */ - if (rc == SSH_ERROR) { - assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); - } - rc = ssh_userauth_list(session, NULL); - assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); - - rc = ssh_userauth_agent(session, NULL); - assert_int_equal(rc, SSH_AUTH_SUCCESS); -} - -static void torture_auth_agent_nonblocking(void **state) { - struct torture_state *s = *state; - ssh_session session = s->ssh.session; - int rc; - - if (!ssh_agent_is_running(session)){ - print_message("*** Agent not running. Test ignored\n"); - return; + /* Remove the default identities */ + while ((id = ssh_list_pop_head(char *, session->opts.identity_non_exp)) != NULL) { + SAFE_FREE(id); } - rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); - assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); - rc = ssh_userauth_none(session,NULL); + rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); @@ -494,111 +766,74 @@ static void torture_auth_agent_nonblocking(void **state) { rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); - ssh_set_blocking(session,0); + /* Should fail as key is not in config */ + rc = ssh_userauth_agent(session, NULL); + assert_ssh_return_code_equal(session, rc, SSH_AUTH_DENIED); - do { - rc = ssh_userauth_agent(session, NULL); - } while (rc == SSH_AUTH_AGAIN); - assert_int_equal(rc, SSH_AUTH_SUCCESS); + /* Re-add a key */ + rc = ssh_list_append(session->opts.identity, strdup(bob_ssh_key)); + assert_int_equal(rc, SSH_OK); + + /* Should succeed as key now in config/options */ + rc = ssh_userauth_agent(session, NULL); + assert_ssh_return_code(session, rc); } -static void torture_auth_cert(void **state) { +static void torture_auth_agent_identities_only_protected(void **state) +{ struct torture_state *s = *state; ssh_session session = s->ssh.session; - ssh_key privkey = NULL; - ssh_key cert = NULL; char bob_ssh_key[1024]; - char bob_ssh_cert[2048]; struct passwd *pwd; int rc; + int identities_only = 1; + char *id = NULL; pwd = getpwnam("bob"); assert_non_null(pwd); snprintf(bob_ssh_key, sizeof(bob_ssh_key), - "%s/.ssh_cert/id_rsa", + "%s/.ssh/id_rsa_protected", pwd->pw_dir); - snprintf(bob_ssh_cert, - sizeof(bob_ssh_cert), - "%s-cert.pub", - bob_ssh_key); - /* cert has been signed for login as alice */ + if (!ssh_agent_is_running(session)){ + print_message("*** Agent not running. Test ignored\n"); + return; + } rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); - rc = ssh_connect(session); - assert_int_equal(rc, SSH_OK); - - rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); + rc = ssh_options_set(session, SSH_OPTIONS_IDENTITIES_ONLY, &identities_only); assert_int_equal(rc, SSH_OK); - rc = ssh_pki_import_cert_file(bob_ssh_cert, &cert); - assert_int_equal(rc, SSH_OK); + /* Remove the default identities */ + while ((id = ssh_list_pop_head(char *, session->opts.identity_non_exp)) != NULL) { + SAFE_FREE(id); + } - rc = ssh_pki_copy_cert_to_privkey(cert, privkey); + rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); - rc = ssh_userauth_try_publickey(session, NULL, cert); - assert_int_equal(rc, SSH_AUTH_SUCCESS); - - rc = ssh_userauth_publickey(session, NULL, privkey); - assert_int_equal(rc, SSH_AUTH_SUCCESS); - - SSH_KEY_FREE(privkey); - SSH_KEY_FREE(cert); -} - -static void torture_auth_agent_cert(void **state) -{ - struct torture_state *s = *state; - ssh_session session = s->ssh.session; - int rc; - - /* Skip this test if in FIPS mode. - * - * OpenSSH agent has a bug which makes it to not use SHA2 in signatures when - * using certificates. It always uses SHA1. - * - * This should be removed as soon as OpenSSH agent bug is fixed. - * (see https://gitlab.com/libssh/libssh-mirror/merge_requests/34) */ - if (ssh_fips_mode()) { - skip(); - } else { - /* After the bug is solved, this also should be removed */ - rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, - "ssh-rsa-cert-v01@openssh.com"); - assert_int_equal(rc, SSH_OK); + rc = ssh_userauth_none(session, NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); - /* Setup loads a different key, tests are exactly the same. */ - torture_auth_agent(state); -} - -static void torture_auth_agent_cert_nonblocking(void **state) -{ - struct torture_state *s = *state; - ssh_session session = s->ssh.session; - int rc; + /* Should fail as key is not in config */ + rc = ssh_userauth_agent(session, NULL); + assert_ssh_return_code_equal(session, rc, SSH_AUTH_DENIED); - /* Skip this test if in FIPS mode. - * - * OpenSSH agent has a bug which makes it to not use SHA2 in signatures when - * using certificates. It always uses SHA1. - * - * This should be removed as soon as OpenSSH agent bug is fixed. - * (see https://gitlab.com/libssh/libssh-mirror/merge_requests/34) */ - if (ssh_fips_mode()) { - skip(); - } else { - /* After the bug is solved, this also should be removed */ - rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, - "ssh-rsa-cert-v01@openssh.com"); - assert_int_equal(rc, SSH_OK); - } + /* Re-add a key */ + rc = ssh_list_append(session->opts.identity, strdup(bob_ssh_key)); + assert_int_equal(rc, SSH_OK); - torture_auth_agent_nonblocking(state); + /* Should succeed as key now in config */ + rc = ssh_userauth_agent(session, NULL); + assert_ssh_return_code(session, rc); } static void torture_auth_pubkey_types(void **state) @@ -658,7 +893,7 @@ static void torture_auth_pubkey_types_ecdsa(void **state) rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); - /* We have only the 256b key -- whitelisting only larger should fail */ + /* We have only the 256b key -- allowlisting only larger should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp384"); assert_ssh_return_code(session, rc); @@ -795,7 +1030,7 @@ static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state) ssh_set_blocking(session, 0); do { - rc = ssh_userauth_none(session, NULL); + rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ @@ -806,7 +1041,7 @@ static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state) rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); - /* We have only the 256b key -- whitelisting only larger should fail */ + /* We have only the 256b key -- allowlisting only larger should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp384"); assert_ssh_return_code(session, rc); @@ -892,6 +1127,124 @@ static void torture_auth_pubkey_types_ed25519_nonblocking(void **state) } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); + SSH_KEY_FREE(privkey); +} + +static void torture_auth_pubkey_rsa_key_size(void **state) +{ + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + char bob_ssh_key[1024]; + ssh_key privkey = NULL; + struct passwd *pwd; + int rc; + unsigned int limit = 4096; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + snprintf(bob_ssh_key, + sizeof(bob_ssh_key), + "%s/.ssh/id_rsa", + pwd->pw_dir); + + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); + assert_ssh_return_code(session, rc); + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + rc = ssh_userauth_none(session, NULL); + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + } + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + /* set unreasonable large minimum key size to trigger the condition */ + rc = ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &limit); /* larger than the test key */ + assert_ssh_return_code(session, rc); + + /* Import the RSA private key */ + rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); + assert_int_equal(rc, SSH_OK); + + rc = ssh_userauth_publickey(session, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_DENIED); + + /* revert to default values which should work also in FIPS mode */ + limit = 0; + rc = ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &limit); + assert_ssh_return_code(session, rc); + + rc = ssh_userauth_publickey(session, NULL, privkey); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + SSH_KEY_FREE(privkey); +} + +static void torture_auth_pubkey_rsa_key_size_nonblocking(void **state) +{ + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + char bob_ssh_key[1024]; + ssh_key privkey = NULL; + struct passwd *pwd; + int rc; + unsigned int limit = 4096; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + snprintf(bob_ssh_key, + sizeof(bob_ssh_key), + "%s/.ssh/id_rsa", + pwd->pw_dir); + + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); + assert_ssh_return_code(session, rc); + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + ssh_set_blocking(session, 0); + do { + rc = ssh_userauth_none(session, NULL); + } while (rc == SSH_AUTH_AGAIN); + + /* This request should return a SSH_REQUEST_DENIED error */ + if (rc == SSH_ERROR) { + assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); + } + + rc = ssh_userauth_list(session, NULL); + assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); + + /* set unreasonable large minimum key size to trigger the condition */ + rc = ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &limit); /* larger than the test key */ + assert_ssh_return_code(session, rc); + + /* Import the RSA private key */ + rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); + assert_int_equal(rc, SSH_OK); + + do { + rc = ssh_userauth_publickey(session, NULL, privkey); + } while (rc == SSH_AUTH_AGAIN); + assert_int_equal(rc, SSH_AUTH_DENIED); + + /* revert to default values which should work also in FIPS mode */ + limit = 0; + rc = ssh_options_set(session, SSH_OPTIONS_RSA_MIN_SIZE, &limit); + assert_ssh_return_code(session, rc); + + do { + rc = ssh_userauth_publickey(session, NULL, privkey); + } while (rc == SSH_AUTH_AGAIN); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + + SSH_KEY_FREE(privkey); } int torture_run_tests(void) { @@ -903,21 +1256,45 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_auth_none_nonblocking, session_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_password, + cmocka_unit_test_setup_teardown(torture_auth_none_max_tries, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_password_good, session_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_password_nonblocking, + cmocka_unit_test_setup_teardown(torture_auth_password_nonblocking_good, session_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_kbdint, + cmocka_unit_test_setup_teardown(torture_auth_password_bad, session_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_kbdint_nonblocking, + cmocka_unit_test_setup_teardown(torture_auth_password_nonblocking_bad, session_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_kbdint_good, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_kbdint_nonblocking_good, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_kbdint_bad, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_kbdint_nonblocking_bad, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_pubkey, + pubkey_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_pubkey_nonblocking, + pubkey_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_auth_autopubkey, pubkey_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_autopubkey_protected, + pubkey_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_auth_autopubkey_nonblocking, pubkey_setup, session_teardown), @@ -927,14 +1304,11 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_auth_agent_nonblocking, agent_setup, agent_teardown), - cmocka_unit_test_setup_teardown(torture_auth_cert, - pubkey_setup, - session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_agent_cert, - agent_cert_setup, + cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only, + agent_setup, agent_teardown), - cmocka_unit_test_setup_teardown(torture_auth_agent_cert_nonblocking, - agent_cert_setup, + cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only_protected, + agent_setup, agent_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types, pubkey_setup, @@ -954,6 +1328,12 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519_nonblocking, pubkey_setup, session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_pubkey_rsa_key_size, + pubkey_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_pubkey_rsa_key_size_nonblocking, + pubkey_setup, + session_teardown), }; ssh_init(); |