#include #include #include #include #include #include #include #include #include "request.h" #include "conversation.h" #include "test_util.h" #include "pam.h" struct conversation_data { std::vector expected_prompts; std::vector responses; int return_value; }; bool same_prompts (const std::vector &expected, int num_prompts, const pam_message **actual) { if (expected.size() != num_prompts) { return false; } for (int i=0; i< num_prompts; ++i) { if (expected[i].msg_style != actual[i]->msg_style) { return false; } if (std::strcmp (expected[i].msg, actual[i]->msg)) { return false; } } return true; } template T *address_of (T &t) { return &t; } int fake_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { conversation_data *data = reinterpret_cast (appdata_ptr); if (data->return_value != PAM_SUCCESS) { return data->return_value; } if (!same_prompts (data->expected_prompts, num_msg, msg)) { throw std::string ("unexpected prompts"); } std::vector &responses = data->responses; std::transform (responses.begin(), responses.end(), resp, address_of); return data->return_value; } class fake_pam : public pam_ifc { private: pam_handle *expected_handle_; conversation_data conversation_data_; pam_conv conv_; public: fake_pam(pam_handle* expected_handle, const conversation_data &conversation_data) : expected_handle_(expected_handle), conversation_data_(conversation_data) {} int get_conv (pam_handle *handle, const pam_conv **out) { if (expected_handle_ != handle) { throw std::string("unexpected handle"); } conv_.appdata_ptr = reinterpret_cast(&conversation_data_); conv_.conv = fake_conv; *out = &conv_; return PAM_SUCCESS; } }; template std::shared_ptr share (T *t) { return std::shared_ptr(t); } bool uses_pam_correctly() { // given pam_handle *handle = reinterpret_cast (29039); std::string user ("user"); std::string token ("token"); pam_message prompt; prompt.msg_style = PAM_PROMPT_ECHO_OFF; prompt.msg = const_cast("Dual control token: "); pam_response response; response.resp_retcode = 0; std::string response_text(user + ":" + token); response.resp = const_cast(response_text.c_str()); conversation_data conversation_data = { std::vector(&prompt, &prompt + 1), std::vector(&response, &response + 1), PAM_SUCCESS }; pam pam (share (new fake_pam (handle, conversation_data))); pam_request request (handle, 0, 0, 0); conversation conversation (create_conversation (pam)); // when conversation_result actual = conversation.initiate (request); // then check(actual.user_name == user, "user name does not match"); check(actual.token == token, "token does not match"); succeed(); } RESET_VARS_START RESET_VARS_END int run_tests() { test (uses_pam_correctly); succeed(); } int main (int argc, char **argv) { return !run_tests(); } /* * int returns_correct_token() int returns_correct_user_name() int returns_empty_user_and_token_when_no_colon() int returns_empty_user_and_token_when_empty_answer() int returns_empty_token_when_colon_end() int returns_empty_user_when_colon_begin() int returns_empty_user_and_token_when_pam_cant_create_conversation() int prompts_user_with_correct_text() int prompts_user_with_correct_style() int returns_empty_user_and_token_when_conversation_fails() int returns_empty_user_and_token_when_conversation_answer_fails() */