diff --git a/examples/ssh_client.c b/examples/ssh_client.c index 1b516830..c95e7394 100644 --- a/examples/ssh_client.c +++ b/examples/ssh_client.c @@ -337,6 +337,7 @@ static void batch_shell(ssh_session session) static int client(ssh_session session) { int auth = 0; + int authenticated = 0; char *banner = NULL; int state; @@ -369,16 +370,28 @@ static int client(ssh_session session) return -1; } - ssh_userauth_none(session, NULL); banner = ssh_get_issue_banner(session); if (banner) { printf("%s\n", banner); free(banner); } - auth = authenticate_console(session); - if (auth != SSH_AUTH_SUCCESS) { + auth = ssh_userauth_none(session, NULL); + if (auth == SSH_AUTH_SUCCESS) { + authenticated = 1; + } else if (auth == SSH_AUTH_ERROR) { + fprintf(stderr, + "Authentication error during none auth: %s\n", + ssh_get_error(session)); return -1; } + + if (!authenticated) { + auth = authenticate_console(session); + if (auth != SSH_AUTH_SUCCESS) { + return -1; + } + } + if (cmds[0] == NULL) { shell(session); } else { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cf1adf56..68cbf1bf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -419,6 +419,9 @@ if (CLIENT_TESTING OR SERVER_TESTING) file(READ keys/pkcs11/id_pkcs11_ecdsa_256_openssh.pub CONTENTS) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}") + # Create home directory for noneuser (for "none" authentication test) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/home/noneuser/.ssh) + file(READ keys/pkcs11/id_pkcs11_ecdsa_384_openssh.pub CONTENTS) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}") diff --git a/tests/client/torture_auth.c b/tests/client/torture_auth.c index 99d59b94..7a5d0ced 100644 --- a/tests/client/torture_auth.c +++ b/tests/client/torture_auth.c @@ -228,6 +228,44 @@ static void torture_auth_none_max_tries(void **state) { torture_update_sshd_config(state, ""); } +static void torture_auth_none_success(void **state) +{ + struct torture_state *s = *state; + const char *additional_config = "PermitEmptyPasswords yes\n" + "PasswordAuthentication yes\n" + "KbdInteractiveAuthentication no\n" + "PubkeyAuthentication no\n" + "AuthenticationMethods none\n"; + + ssh_session session = s->ssh.session; + int rc; + + torture_update_sshd_config(state, additional_config); + + /* Use noneuser which has an empty password set in shadow.in + * When PermitEmptyPasswords is yes and PasswordAuthentication is yes, + * OpenSSH's userauth_none() internally calls mm_auth_password() with + * an empty password, which succeeds for users with empty passwords. + */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_NONEUSER); + if (rc != SSH_OK) { + goto cleanup; + } + + rc = ssh_connect(session); + if (rc != SSH_OK) { + goto cleanup; + } + + rc = ssh_userauth_none(session, NULL); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + +cleanup: + torture_update_sshd_config(state, ""); + if (rc != SSH_OK && rc != SSH_AUTH_SUCCESS) { + assert_int_equal(rc, SSH_OK); + } +} static void torture_auth_pubkey(void **state) { struct torture_state *s = *state; @@ -1373,6 +1411,9 @@ 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_none_success, + session_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_auth_none_max_tries, session_setup, session_teardown), @@ -1424,9 +1465,10 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only, agent_setup, agent_teardown), - cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only_protected, - agent_setup, - agent_teardown), + 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, session_teardown), @@ -1436,15 +1478,17 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa, pubkey_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking, - pubkey_setup, - session_teardown), + cmocka_unit_test_setup_teardown( + torture_auth_pubkey_types_ecdsa_nonblocking, + pubkey_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519, pubkey_setup, session_teardown), - cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519_nonblocking, - pubkey_setup, - session_teardown), + cmocka_unit_test_setup_teardown( + torture_auth_pubkey_types_ed25519_nonblocking, + pubkey_setup, + session_teardown), #ifdef WITH_FIDO2 cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_sk_ecdsa, pubkey_setup, @@ -1456,9 +1500,10 @@ int torture_run_tests(void) { 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), + cmocka_unit_test_setup_teardown( + torture_auth_pubkey_rsa_key_size_nonblocking, + pubkey_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_skip_none, pubkey_setup, session_teardown), diff --git a/tests/etc/pam_matrix_passdb.in b/tests/etc/pam_matrix_passdb.in index 9404bc0e..234bad70 100644 --- a/tests/etc/pam_matrix_passdb.in +++ b/tests/etc/pam_matrix_passdb.in @@ -2,3 +2,4 @@ bob:secret:sshd alice:secret:sshd charlie:secret:sshd doe:secret:sshd +noneuser::sshd diff --git a/tests/etc/passwd.in b/tests/etc/passwd.in index fff78780..aaac4c79 100644 --- a/tests/etc/passwd.in +++ b/tests/etc/passwd.in @@ -3,6 +3,7 @@ alice:x:5001:9000:alice gecos:@HOMEDIR@/alice:/bin/sh charlie:x:5002:9000:charlie gecos:@HOMEDIR@/charlie:/bin/sh doe:x:5003:9000:doe gecos:@HOMEDIR@/doe:/bin/sh frank:x:5003:9000:doe gecos:@HOMEDIR@/frank:/bin/sh +noneuser:x:5004:9000:noneuser gecos:@HOMEDIR@/noneuser:/bin/sh sshd:x:65530:65531:sshd:@HOMEDIR@:/sbin/nologin nobody:x:65533:65534:nobody gecos:@HOMEDIR@:/bin/false root:x:0:0:root gecos:@HOMEDIR@:/bin/false diff --git a/tests/etc/shadow.in b/tests/etc/shadow.in index 0f03b149..c3b61ae5 100644 --- a/tests/etc/shadow.in +++ b/tests/etc/shadow.in @@ -2,3 +2,4 @@ alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFl bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0::::: charlie:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0::::: doe:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0::::: +noneuser:::0::::: diff --git a/tests/torture.h b/tests/torture.h index 0120bd6f..443e709b 100644 --- a/tests/torture.h +++ b/tests/torture.h @@ -51,6 +51,7 @@ #define TORTURE_SSH_USER_ALICE "alice" #define TORTURE_SSH_USER_CHARLIE "charlie" +#define TORTURE_SSH_USER_NONEUSER "noneuser" /* Used by main to communicate with parse_opt. */ struct argument_s {