git.fiddlerwoaroof.com
Raw Blame History
/* Copyright (C) CJ Affiliate
 *
 * You may use, distribute and modify this code under  the
 * terms of the  GNU General Public License  version 2  or
 * later.
 *
 * You should have received a copy of the license with this
 * file. If not, you will find a copy in the "LICENSE" file
 * at https://github.com/cjdev/dual-control.
 */

#include <security/pam_modules.h>
#include <algorithm>
#include <vector>
#include <string>

#include "conversation.h"

namespace
{
conversation_result err = {"",""};
class impl : public conversation_ifc
{
private:
    pam pam_;
public:
    impl (pam &pam) : pam_ (pam) {}
    conversation_result initiate (const pam_request &request)
    {
        const pam_conv *conv;
        int get_conv_result = pam_.get_conv (request.handle(), &conv);

        if (get_conv_result != PAM_SUCCESS) {
            return err;
        }

        pam_message msg;
        msg.msg = const_cast<char *> ("Dual control token: ");
        msg.msg_style = PAM_PROMPT_ECHO_OFF;
        std::vector<const pam_message *> messages;
        messages.push_back (&msg);
        std::vector<pam_response *> responses (1);
        int conv_result = conv->conv (1, messages.data(), responses.data(),
                                      conv->appdata_ptr);

        if (conv_result != PAM_SUCCESS) {
            return err;
        }

        if (responses[0]->resp_retcode != 0) {
            return err;
        }

        std::string answer (responses[0]->resp);
        std::string::iterator delim = std::find (answer.begin(), answer.end(), ':');

        if (delim == answer.end()) {
            return err;
        }

        return {
            std::string (answer.begin(), delim),
            std::string (delim + 1, answer.end())
        };

    }
};
}

conversation create_conversation (pam &pam)
{
    return conversation (std::shared_ptr<conversation_ifc> (new impl (pam)));
}

/*
int (*conv)(int num_msg, const struct pam_message **msg,
                struct pam_response **resp, void *appdata_ptr)
   */

/*
pam_token_conversation::pam_token_conversation (pam_handle_t *pamh,
        const pam_p pam)
{
    pam_conversation_p pam_conversation;
    int get_conversation_result = pam->get_conversation (pamh,
                                  pam_conversation);

    if (get_conversation_result != 0) {
        return;
    }

    struct pam_message prompt;

    std::string message ("Dual control token: ");

    prompt.msg = const_cast<char *> (message.c_str());

    prompt.msg_style = PAM_PROMPT_ECHO_OFF;

    std::vector<const struct pam_message *> prompts (1);

    prompts[0] = &prompt;

    std::vector<struct pam_response *> answers (1);

    int conversation_result = pam_conversation->conv (prompts, answers);

    if (conversation_result) {
        return;
    }

    if (answers[0]->resp_retcode) {
        return;
    }

    std::string answer (answers[0]->resp);
    std::string::iterator delim = std::find (answer.begin(), answer.end(), ':');

    if (delim == answer.end()) {
        return;
    }

    std::string user_name (answer.begin(), delim);
    std::string token (delim + 1, answer.end());
    user_ = user_name;
    token_ = token;
}

std::string pam_token_conversation::token()
{
    return token_;
}

std::string pam_token_conversation::user_name()
{
    return user_;
}
*/