git.fiddlerwoaroof.com
conversation_test.cc
01c00cfe
 #include <vector>
 #include <algorithm>
 #include <string>
2fade7af
 #include <algorithm>
 #include <memory>
 #include <cstring>
0b6e39a6
 #include <security/pam_modules.h>
 
2fade7af
 #include <iostream>
 
 #include "request.h"
0b6e39a6
 #include "conversation.h"
 #include "test_util.h"
01c00cfe
 #include "pam.h"
0b6e39a6
 
2fade7af
 struct conversation_data {
     std::vector<pam_message> expected_prompts;
     std::vector<pam_response> responses;
     int return_value;
01c00cfe
 };
 
2fade7af
 bool same_prompts (const std::vector<pam_message> &expected,
                    int num_prompts, const pam_message **actual)
cdf7fd74
 {
2fade7af
     if (expected.size() != num_prompts) {
         return false;
cdf7fd74
     }
1bbd05bc
 
2fade7af
     for (int i=0; i< num_prompts; ++i) {
         if (expected[i].msg_style != actual[i]->msg_style) {
             return false;
12570d65
         }
b017a4d2
 
2fade7af
         if (std::strcmp (expected[i].msg, actual[i]->msg)) {
             return false;
f9c4622b
         }
cdf7fd74
     }
f9c4622b
 
2fade7af
     return true;
 }
f9c4622b
 
2fade7af
 template<class T>
 T *address_of (T &t)
cdf7fd74
 {
2fade7af
     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<conversation_data *>
                               (appdata_ptr);
b017a4d2
 
2fade7af
     if (data->return_value != PAM_SUCCESS) {
         return data->return_value;
cdf7fd74
     }
c9d7e817
 
2fade7af
     if (!same_prompts (data->expected_prompts, num_msg, msg)) {
         throw std::string ("unexpected prompts");
     }
 
     std::vector<pam_response> &responses = data->responses;
     std::transform (responses.begin(), responses.end(), resp,
                     address_of<pam_response>);
     return data->return_value;
 }
c9d7e817
 
2fade7af
 class fake_pam : public pam_ifc
cdf7fd74
 {
 private:
2fade7af
     pam_handle *expected_handle_;
     conversation_data conversation_data_;
     pam_conv conv_;
cdf7fd74
 public:
2fade7af
     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)
cdf7fd74
     {
2fade7af
         if (expected_handle_ != handle) {
             throw std::string("unexpected handle");
01c00cfe
         }
2fade7af
         conv_.appdata_ptr = reinterpret_cast<void *>(&conversation_data_);
         conv_.conv = fake_conv;
         *out = &conv_;
         return PAM_SUCCESS;
cdf7fd74
     }
0b6e39a6
 
2fade7af
 };
0b6e39a6
 
2fade7af
 template<class T>
 std::shared_ptr<T> share (T *t) {
     return std::shared_ptr<T>(t);
0b6e39a6
 }
 
2fade7af
 bool uses_pam_correctly()
cdf7fd74
 {
9e6b6179
 
2fade7af
     // given
     pam_handle *handle = reinterpret_cast<pam_handle *> (29039);
     std::string user ("user");
     std::string token ("token");
     pam_message prompt;
     prompt.msg_style = PAM_PROMPT_ECHO_OFF;
     prompt.msg = const_cast<char *>("Dual control token: ");
     pam_response response;
     response.resp_retcode = 0;
     std::string response_text(user + ":" + token);
     response.resp = const_cast<char *>(response_text.c_str());
     conversation_data conversation_data = {
         std::vector<pam_message>(&prompt, &prompt + 1),
         std::vector<pam_response>(&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");
be7b0e04
 
     succeed();
 }
 
2fade7af
 RESET_VARS_START
 RESET_VARS_END
0b6e39a6
 
2fade7af
 int run_tests()
cdf7fd74
 {
2fade7af
     test (uses_pam_correctly);
26830ef5
     succeed();
 }
 
2fade7af
 int main (int argc, char **argv)
cdf7fd74
 {
2fade7af
     return !run_tests();
231e2d6e
 }
 
2fade7af
 /*
  * 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()
cdf7fd74
 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()
2fade7af
 */
0b6e39a6