git.fiddlerwoaroof.com
conversation_test.cc
01c00cfe
 #include <vector>
 #include <algorithm>
 #include <string>
0b6e39a6
 #include <security/pam_modules.h>
 
 #include "conversation.h"
 #include "test_util.h"
01c00cfe
 #include "pam.h"
0b6e39a6
 
 
01c00cfe
 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<const struct pam_message *> &prompts, std::vector<struct pam_response *> &answers) {
             if (prompts.size() != 1) {
                 throw std::string("test only supports one prompt");
             }
             response_.resp_retcode = 0;
             response_.resp = const_cast<char *>(answer_.c_str());
             answers.resize(1);
             answers[0] = &response_;
             return 0;
         }
 };
 
1bbd05bc
 class fake_failing_conversation: public pam_conversation {
 
     public:
         int conv(const std::vector<const struct pam_message *> &prompts, std::vector<struct pam_response *> &answers) {
             return 1;
         }
 };
 
12570d65
 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<const struct pam_message *> &prompts, std::vector<struct pam_response *> &answers) {
             if (prompts.size() != 1) {
                 throw std::string("test only supports one prompt");
             }
             response_.resp_retcode = 13;
             response_.resp = const_cast<char *>(answer_.c_str());
             answers.resize(1);
             answers[0] = &response_;
             return 0;
         }
 };
 
c9d7e817
 class match_prompt_text_conversation : public pam_conversation {
f9c4622b
     private:
         pam_response response_;
         std::string answer_;
         std::string prompt_;
     public:
c9d7e817
         match_prompt_text_conversation(const std::string &prompt) : prompt_(prompt), answer_("ok:123") {}
f9c4622b
         int conv(const std::vector<const struct pam_message *> &prompts, std::vector<struct pam_response *> &answers) {
             if (prompt_ != prompts[0]->msg) {
                 throw std::string("prompt does not match");
             }
             response_.resp_retcode = 0;
             response_.resp = const_cast<char *>(answer_.c_str());
             answers.resize(1);
             answers[0] = &response_;
             return 0;
         }
 
 };
 
c9d7e817
 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<const struct pam_message *> &prompts, std::vector<struct pam_response *> &answers) {
             if (style_ != prompts[0]->msg_style) {
                 throw std::string("style does not match");
             }
             response_.resp_retcode = 0;
             response_.resp = const_cast<char *>(answer_.c_str());
             answers.resize(1);
             answers[0] = &response_;
             return 0;
         }
 
 };
 
01c00cfe
 class fake_pam : public pam {
     private:
9e6b6179
         std::shared_ptr<pam_conversation> conversation_;
01c00cfe
     public:
9e6b6179
         fake_pam(std::shared_ptr<pam_conversation> conversation) : conversation_(conversation) {}
662f2d36
         fake_pam() {}
01c00cfe
         int get_conversation(pam_handle_t *pamh, std::shared_ptr<pam_conversation> &conversation) {
662f2d36
             if (conversation_) {
                conversation = conversation_;
                return 0;
             }
             return 12;
01c00cfe
         }
 };
 
9e6b6179
 
0b6e39a6
 int returns_correct_token() {
     //given
     pam_handle_t *pamh;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation("user:code");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
0b6e39a6
 
     //when
01c00cfe
     pam_token_conversation conversation(pamh, pam);
0b6e39a6
 
     //then
01c00cfe
     check(conversation.token() == "code", "returned incorrect token");
0b6e39a6
     succeed();
 }
 
be7b0e04
 int returns_correct_user_name() {
     //given
     pam_handle_t *pamh;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation("sally:token");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
 
be7b0e04
 
     //when
01c00cfe
     pam_token_conversation conversation(pamh, pam);
be7b0e04
 
     //then
01c00cfe
     check(conversation.user_name() == "sally", "returned incorrect user name");
be7b0e04
     succeed();
 }
 
231e2d6e
 int returns_empty_user_and_token_when_no_colon() {
24888e2d
     //given
     pam_handle_t *pamh;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation("sally");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
24888e2d
 
     //when
     pam_token_conversation conversation(pamh, pam);
0b6e39a6
 
24888e2d
     //then
     check(conversation.user_name() == "", "did not return empty user name");
     check(conversation.token() == "", "did not return empty token");
     succeed();
 }
0b6e39a6
 
26830ef5
 int returns_empty_user_and_token_when_empty_answer() {
     //given
     pam_handle_t *pamh;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation("");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
26830ef5
 
     //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();
 }
 
231e2d6e
 int returns_empty_token_when_colon_end() {
     //given
     pam_handle_t *pamh;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation("sally:");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
231e2d6e
 
     //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;
9e6b6179
     pam_conversation_p fake_conversation = (pam_conversation_p) new fake_pam_conversation(":token");
     pam_p pam = (pam_p)new fake_pam(fake_conversation);
231e2d6e
 
     //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();
 }
 
662f2d36
 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();
 
 }
 
f9c4622b
 int prompts_user_with_correct_text() {
     // given
     pam_handle_t *pamh;
c9d7e817
     pam_conversation_p match_conversation = (pam_conversation_p) new match_prompt_text_conversation("Dual control token: ");
f9c4622b
     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();
     }
 
c9d7e817
 }
 
 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);
f9c4622b
 
 
c9d7e817
     // when / then
     try {
       pam_token_conversation conversation(pamh, pam);
       succeed();
     } catch (const std::string &x) {
         fail();
     }
f9c4622b
 }
231e2d6e
 
1bbd05bc
 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);
c9d7e817
 
1bbd05bc
     //then
     check(conversation.user_name() == "", "did not return empty user name");
     check(conversation.token() == "", "did not return empty token");
     succeed();
 }
c9d7e817
 
12570d65
 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();
 }
c9d7e817
 
0b6e39a6
 RESET_VARS_START
 RESET_VARS_END
 
 int run_tests() {
     test(returns_correct_token);
be7b0e04
     test(returns_correct_user_name);
231e2d6e
     test(returns_empty_user_and_token_when_no_colon);
     test(returns_empty_token_when_colon_end);
     test(returns_empty_user_when_colon_begin);
26830ef5
     test(returns_empty_user_and_token_when_empty_answer);
662f2d36
     test(returns_empty_user_and_token_when_pam_cant_create_conversation);
f9c4622b
     test(prompts_user_with_correct_text);
c9d7e817
     test(prompts_user_with_correct_style);
1bbd05bc
     test(returns_empty_user_and_token_when_conversation_fails);
12570d65
     test(returns_empty_user_and_token_when_conversation_answer_fails);
0b6e39a6
     succeed();
 }
 
 int main(int argc, char *args[]) {
     return !run_tests();
 }