static void torture_pubkey_generate_from_privkey(void **state) { ssh_session session = *state; ssh_private_key privkey = NULL; ssh_public_key pubkey = NULL; ssh_string pubkey_orig = NULL; ssh_string pubkey_new = NULL; char pubkey_line_orig[512] = {0}; char pubkey_line_new[512] = {0}; int type_orig = 0; int type_new = 0; int rc; /* read the publickey */ rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey_orig, &type_orig); assert_true(rc == 0); assert_true(pubkey_orig != NULL); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_orig, sizeof(pubkey_line_orig)); assert_true(rc == 0); /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_RSA_TESTKEY ".pub"); privkey = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL); assert_true(privkey != NULL); pubkey = publickey_from_privatekey(privkey); assert_true(pubkey != NULL); type_new = privkey->type; privatekey_free(privkey); pubkey_new = publickey_to_string(pubkey); publickey_free(pubkey); assert_true(pubkey_new != NULL); assert_true(ssh_string_len(pubkey_orig) == ssh_string_len(pubkey_new)); assert_memory_equal(ssh_string_data(pubkey_orig), ssh_string_data(pubkey_new), ssh_string_len(pubkey_orig)); rc = ssh_publickey_to_file(session, LIBSSH_RSA_TESTKEY ".pub", pubkey_new, type_new); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_new, sizeof(pubkey_line_new)); assert_true(rc == 0); assert_string_equal(pubkey_line_orig, pubkey_line_new); ssh_string_free(pubkey_orig); ssh_string_free(pubkey_new); }
/** * @brief Tries to automaticaly authenticate with public key and "none" * * It may fail, for instance it doesn't ask for a password and uses a default * asker for passphrases (in case the private key is encrypted). * * @param session The ssh session to authenticate with. * * @param passphrase Use this passphrase to unlock the privatekey. Use NULL * if you don't want to use a passphrase or the user * should be asked. * * @returns SSH_AUTH_ERROR: A serious error happened\n * SSH_AUTH_DENIED: Authentication failed: use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success * * @see ssh_userauth_kbdint() * @see ssh_userauth_password() */ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { struct ssh_iterator *it; ssh_private_key privkey; ssh_public_key pubkey; ssh_string pubkey_string; int type = 0; int rc; enter_function(); /* Always test none authentication */ rc = ssh_userauth_none(session, NULL); if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_SUCCESS) { leave_function(); return rc; } /* Try authentication with ssh-agent first */ #ifndef _WIN32 if (agent_is_running(session)) { char *privkey_file = NULL; ssh_log(session, SSH_LOG_RARE, "Trying to authenticate with SSH agent keys as user: %s", session->username); for (pubkey = agent_get_first_ident(session, &privkey_file); pubkey != NULL; pubkey = agent_get_next_ident(session, &privkey_file)) { ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file); pubkey_string = publickey_to_string(pubkey); if (pubkey_string) { rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string); string_free(pubkey_string); if (rc == SSH_AUTH_ERROR) { SAFE_FREE(privkey_file); publickey_free(pubkey); leave_function(); return rc; } else if (rc != SSH_AUTH_SUCCESS) { ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server"); SAFE_FREE(privkey_file); publickey_free(pubkey); continue; } ssh_log(session, SSH_LOG_RARE, "Public key accepted"); /* pubkey accepted by server ! */ rc = ssh_userauth_agent_pubkey(session, NULL, pubkey); if (rc == SSH_AUTH_ERROR) { SAFE_FREE(privkey_file); publickey_free(pubkey); leave_function(); return rc; } else if (rc != SSH_AUTH_SUCCESS) { ssh_log(session, SSH_LOG_RARE, "Server accepted public key but refused the signature ;" " It might be a bug of libssh"); SAFE_FREE(privkey_file); publickey_free(pubkey); continue; } /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success", privkey_file); SAFE_FREE(privkey_file); publickey_free(pubkey); leave_function(); return SSH_AUTH_SUCCESS; } /* if pubkey */ SAFE_FREE(privkey_file); publickey_free(pubkey); } /* for each privkey */ } /* if agent is running */ #endif for (it = ssh_list_get_iterator(session->identity); it != NULL; it = it->next) { const char *privkey_file = it->data; int privkey_open = 0; privkey = NULL; ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file); rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type); if (rc == 1) { char *publickey_file; size_t len; privkey = privatekey_from_file(session, privkey_file, type, passphrase); if (privkey == NULL) { ssh_log(session, SSH_LOG_RARE, "Reading private key %s failed (bad passphrase ?)", privkey_file); leave_function(); return SSH_AUTH_ERROR; } privkey_open = 1; pubkey = publickey_from_privatekey(privkey); if (pubkey == NULL) { privatekey_free(privkey); ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; } pubkey_string = publickey_to_string(pubkey); type = pubkey->type; publickey_free(pubkey); if (pubkey_string == NULL) { ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; } len = strlen(privkey_file) + 5; publickey_file = malloc(len); if (publickey_file == NULL) { ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; } snprintf(publickey_file, len, "%s.pub", privkey_file); rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type); if (rc < 0) { ssh_log(session, SSH_LOG_PACKET, "Could not write public key to file: %s", publickey_file); } SAFE_FREE(publickey_file); } else if (rc < 0) { continue; } rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string); if (rc == SSH_AUTH_ERROR){ string_free(pubkey_string); ssh_log(session, SSH_LOG_RARE, "Publickey authentication error"); leave_function(); return rc; } else { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server"); string_free(pubkey_string); continue; } } /* Public key accepted by server! */ if (!privkey_open) { ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file); privkey = privatekey_from_file(session, privkey_file, type, passphrase); if (privkey == NULL) { ssh_log(session, SSH_LOG_RARE, "Reading private key %s failed (bad passphrase ?)", privkey_file); string_free(pubkey_string); continue; /* continue the loop with other pubkey */ } } rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey); if (rc == SSH_AUTH_ERROR) { string_free(pubkey_string); privatekey_free(privkey); leave_function(); return rc; } else { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_FUNCTIONS, "The server accepted the public key but refused the signature"); string_free(pubkey_string); privatekey_free(privkey); continue; } } /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Successfully authenticated using %s", privkey_file); string_free(pubkey_string); privatekey_free(privkey); leave_function(); return SSH_AUTH_SUCCESS; } /* at this point, pubkey is NULL and so is privkeyfile */ ssh_log(session, SSH_LOG_FUNCTIONS, "Tried every public key, none matched"); ssh_set_error(session,SSH_NO_ERROR,"No public key matched"); leave_function(); return SSH_AUTH_DENIED; }