#include #include #include #include #include "conversation.h" #include "test_util.h" #include "pam.h" class fake_pam_conversation : public pam_conversation { private: pam_response response_; std::string answer_; public: fake_pam_conversation (const std::string &answer) : answer_ (answer) {} int conv (const std::vector &prompts, std::vector &answers) { if (prompts.size() != 1) { throw std::string ("test only supports one prompt"); } response_.resp_retcode = 0; response_.resp = const_cast (answer_.c_str()); answers.resize (1); answers[0] = &response_; return 0; } }; class fake_failing_conversation: public pam_conversation { public: int conv (const std::vector &prompts, std::vector &answers) { return 1; } }; class fake_failing_answer_conversation: public pam_conversation { private: pam_response response_; std::string answer_; public: fake_failing_answer_conversation() : answer_ ("ok:1") {} int conv (const std::vector &prompts, std::vector &answers) { if (prompts.size() != 1) { throw std::string ("test only supports one prompt"); } response_.resp_retcode = 13; response_.resp = const_cast (answer_.c_str()); answers.resize (1); answers[0] = &response_; return 0; } }; class match_prompt_text_conversation : public pam_conversation { private: pam_response response_; std::string answer_; std::string prompt_; public: match_prompt_text_conversation (const std::string &prompt) : prompt_ (prompt), answer_ ("ok:123") {} int conv (const std::vector &prompts, std::vector &answers) { if (prompt_ != prompts[0]->msg) { throw std::string ("prompt does not match"); } response_.resp_retcode = 0; response_.resp = const_cast (answer_.c_str()); answers.resize (1); answers[0] = &response_; return 0; } }; class match_prompt_style_conversation : public pam_conversation { private: pam_response response_; std::string answer_; int style_; public: match_prompt_style_conversation (int style) : style_ (style), answer_ ("ok:123") {} int conv (const std::vector &prompts, std::vector &answers) { if (style_ != prompts[0]->msg_style) { throw std::string ("style does not match"); } response_.resp_retcode = 0; response_.resp = const_cast (answer_.c_str()); answers.resize (1); answers[0] = &response_; return 0; } }; class fake_pam : public pam { private: std::shared_ptr conversation_; public: fake_pam (std::shared_ptr conversation) : conversation_ (conversation) {} fake_pam() {} int get_conversation (pam_handle_t *pamh, std::shared_ptr &conversation) { if (conversation_) { conversation = conversation_; return 0; } return 12; } }; int returns_correct_token() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation ("user:code"); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.token() == "code", "returned incorrect token"); succeed(); } int returns_correct_user_name() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation ("sally:token"); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "sally", "returned incorrect user name"); succeed(); } int returns_empty_user_and_token_when_no_colon() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation ("sally"); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } int returns_empty_user_and_token_when_empty_answer() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation (""); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } int returns_empty_token_when_colon_end() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation ("sally:"); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "sally", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } int returns_empty_user_when_colon_begin() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation (":token"); pam_p pam = (pam_p)new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "token", "did not return empty token"); succeed(); } int returns_empty_user_and_token_when_pam_cant_create_conversation() { // given pam_handle_t *pamh; pam_p pam = (pam_p)new fake_pam; //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } int prompts_user_with_correct_text() { // given pam_handle_t *pamh; pam_conversation_p match_conversation = (pam_conversation_p) new match_prompt_text_conversation ("Dual control token: "); pam_p pam = (pam_p)new fake_pam (match_conversation); // when / then try { pam_token_conversation conversation (pamh, pam); succeed(); } catch (const std::string &x) { fail(); } } int prompts_user_with_correct_style() { // given pam_handle_t *pamh; pam_conversation_p match_conversation = (pam_conversation_p) new match_prompt_style_conversation (PAM_PROMPT_ECHO_OFF); pam_p pam = (pam_p)new fake_pam (match_conversation); // when / then try { pam_token_conversation conversation (pamh, pam); succeed(); } catch (const std::string &x) { fail(); } } int returns_empty_user_and_token_when_conversation_fails() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_failing_conversation; pam_p pam = (pam_p) new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } int returns_empty_user_and_token_when_conversation_answer_fails() { //given pam_handle_t *pamh; pam_conversation_p fake_conversation = (pam_conversation_p) new fake_failing_answer_conversation; pam_p pam = (pam_p) new fake_pam (fake_conversation); //when pam_token_conversation conversation (pamh, pam); //then check (conversation.user_name() == "", "did not return empty user name"); check (conversation.token() == "", "did not return empty token"); succeed(); } RESET_VARS_START RESET_VARS_END int run_tests() { test (returns_correct_token); test (returns_correct_user_name); test (returns_empty_user_and_token_when_no_colon); test (returns_empty_token_when_colon_end); test (returns_empty_user_when_colon_begin); test (returns_empty_user_and_token_when_empty_answer); test (returns_empty_user_and_token_when_pam_cant_create_conversation); test (prompts_user_with_correct_text); test (prompts_user_with_correct_style); test (returns_empty_user_and_token_when_conversation_fails); test (returns_empty_user_and_token_when_conversation_answer_fails); succeed(); } int main (int argc, char *args[]) { return !run_tests(); }