7684972a |
/* 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.
*/
|
dd920112 |
#include <security/pam_modules.h>
|
47f9faed |
#include <string>
|
dd920112 |
|
a71244c0 |
#include "request.h"
|
4a1812fd |
#include "dual_control.h"
|
caf7db60 |
#include "validator.h"
#include "conversation.h"
|
47f9faed |
#include "logger.h"
#include "test_util.h"
|
47142d31 |
#include "session.h"
|
47f9faed |
|
857e33e7 |
template<class T>
|
b017a4d2 |
std::shared_ptr<T> share (T *t)
|
cdf7fd74 |
{
|
b017a4d2 |
return std::shared_ptr<T> (t);
|
857e33e7 |
}
|
b017a4d2 |
void use_validator (dual_control_configuration &config,
validator_ifc *value)
|
cdf7fd74 |
{
|
b017a4d2 |
config.validator = validator (share (value));
|
978f824f |
}
|
f46fb7b6 |
void use_conversation (dual_control_configuration &config,
conversation_ifc *value)
|
cdf7fd74 |
{
|
f46fb7b6 |
config.conversation = conversation (share (value));
|
978f824f |
}
|
b017a4d2 |
void use_logger (dual_control_configuration &config, logger_ifc *value)
|
cdf7fd74 |
{
|
a9690b1d |
config.logger = logger (logger::delegate (value));
|
978f824f |
}
|
47142d31 |
void use_sessions (dual_control_configuration &config, sessions_ifc *value)
{
config.sessions = sessions (sessions::delegate (value));
}
|
706636a4 |
class fake_sessions : public sessions_ifc
{
private:
std::string user_;
public:
fake_sessions (const std::string &user) : user_ (user) {}
std::string user_name (const pam_request &request) const
{
|
47142d31 |
return user_;
}
};
|
cdf7fd74 |
class mock_logger : public logger_ifc
{
private:
int result_;
|
47142d31 |
std::string requester_user_name_;
std::string authorizer_user_name_;
|
cdf7fd74 |
std::string token_;
|
3fc168fa |
std::string reason_;
|
cdf7fd74 |
public:
|
706636a4 |
void log (int result, const std::string &requester_user_name,
const std::string &authorizer_user_name,
|
3fc168fa |
const std::string &token, const std::string &reason) override
|
cdf7fd74 |
{
result_ = result;
|
47142d31 |
requester_user_name_ = requester_user_name;
authorizer_user_name_ = authorizer_user_name;
|
cdf7fd74 |
token_ = token;
|
3fc168fa |
reason_ = reason;
|
cdf7fd74 |
}
int logged_result()
{
return result_;
}
|
47142d31 |
std::string logged_requester()
{
return requester_user_name_;
}
std::string logged_authorizer()
|
cdf7fd74 |
{
|
47142d31 |
return authorizer_user_name_;
|
cdf7fd74 |
}
std::string logged_token()
{
return token_;
}
|
b14fb8c6 |
std::string logged_reason()
{
|
3fc168fa |
return reason_;
}
|
47f9faed |
};
|
caf7db60 |
|
f46fb7b6 |
class fake_conversation : public conversation_ifc
|
cdf7fd74 |
{
private:
std::string user_name_;
std::string token_;
|
3fc168fa |
std::string reason_;
|
cdf7fd74 |
public:
|
f46fb7b6 |
fake_conversation (const std::string &user_name,
|
3fc168fa |
const std::string &token, const std::string &reason) :
|
b14fb8c6 |
user_name_ (user_name), token_ (token), reason_ (reason) {}
|
f46fb7b6 |
conversation_result initiate (const pam_request &request)
|
cdf7fd74 |
{
|
3fc168fa |
return {user_name_, token_, reason_};
|
cdf7fd74 |
}
|
caf7db60 |
};
|
cdf7fd74 |
class fake_validator : public validator_ifc
{
private:
|
47142d31 |
std::string requester_;
std::string authorizer_;
|
cdf7fd74 |
std::string token_;
|
044b2625 |
std::string reason_;
|
cdf7fd74 |
public:
|
47142d31 |
fake_validator (const std::string &requester, const std::string &authorizer,
|
b14fb8c6 |
const std::string &token,
const std::string &reason): requester_ (requester),
authorizer_ (authorizer),
token_ (token), reason_ (reason) {}
|
47142d31 |
bool validate (const std::string &requester, const std::string &authorizer,
|
3fc168fa |
const std::string &token, const std::string &reason) override
|
cdf7fd74 |
{
|
706636a4 |
return requester_ == requester && authorizer_ == authorizer
&& token_ == token;
|
cdf7fd74 |
}
|
caf7db60 |
};
|
a71244c0 |
pam_request req()
{
return pam_request (0, 0, 0, 0);
}
|
cdf7fd74 |
int setcred_returns_success()
{
|
4a1812fd |
//given
|
caf7db60 |
dual_control_configuration configuration;
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
4a1812fd |
//when
|
a71244c0 |
int result = dc.setcred (req());
|
4a1812fd |
//then
|
b017a4d2 |
checkint (PAM_SUCCESS, result, "function return");
|
4a1812fd |
succeed();
}
|
cdf7fd74 |
int authenticate_validates_with_received_token()
{
|
caf7db60 |
// given
dual_control_configuration configuration;
|
706636a4 |
std::string requester ("requester");
std::string authorizer ("authorizer");
std::string token ("token");
|
b14fb8c6 |
std::string reason ("reason");
|
706636a4 |
use_validator (configuration, new fake_validator (requester, authorizer,
|
044b2625 |
token, reason));
|
b14fb8c6 |
use_conversation (configuration, new fake_conversation (authorizer, token,
reason));
|
706636a4 |
use_sessions (configuration, new fake_sessions (requester));
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
b017a4d2 |
pam_handle_t *handle (0);
|
5a49538d |
std::vector<std::string> arguments;
|
caf7db60 |
// when
|
a71244c0 |
int actual = dc.authenticate (req());
|
caf7db60 |
// then
|
b017a4d2 |
check (actual == PAM_SUCCESS, "should be success");
|
b4725468 |
succeed();
}
|
cdf7fd74 |
int authenticate_fails_with_wrong_user()
{
|
b4725468 |
// given
dual_control_configuration configuration;
|
b017a4d2 |
std::string token ("token");
|
b14fb8c6 |
std::string reason ("reason");
|
706636a4 |
use_validator (configuration, new fake_validator ("requester", "user",
|
3fc168fa |
token, reason));
|
f46fb7b6 |
use_conversation (configuration, new fake_conversation ("wrong user",
|
3fc168fa |
token, reason));
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
b4725468 |
// when
|
a71244c0 |
int actual = dc.authenticate (req());
|
b4725468 |
// then
|
b017a4d2 |
check (actual == PAM_AUTH_ERR, "should be auth err");
|
b4725468 |
succeed();
}
|
cdf7fd74 |
int authenticate_fails_with_wrong_token()
{
|
b4725468 |
// given
dual_control_configuration configuration;
|
706636a4 |
std::string requester ("requester");
std::string authorizer ("authorizer");
use_validator (configuration, new fake_validator (requester, authorizer,
|
044b2625 |
"token", "reason"));
|
47142d31 |
use_conversation (configuration, new fake_conversation (authorizer,
|
3fc168fa |
"wrong token", "reason"));
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
b4725468 |
// when
|
a71244c0 |
int actual = dc.authenticate (req());
|
b4725468 |
// then
|
b017a4d2 |
check (actual == PAM_AUTH_ERR, "should be auth err");
|
caf7db60 |
succeed();
}
|
cdf7fd74 |
int logs_authentication()
{
|
47f9faed |
//given
dual_control_configuration configuration;
|
706636a4 |
std::string requester ("requester");
std::string authorizer ("authorizer");
|
b017a4d2 |
std::string token ("token");
|
b14fb8c6 |
std::string reason ("reason");
|
706636a4 |
use_validator (configuration, new fake_validator (requester, authorizer,
|
044b2625 |
token, reason));
|
b14fb8c6 |
use_conversation (configuration, new fake_conversation (authorizer, token,
reason));
|
706636a4 |
use_sessions (configuration, new fake_sessions (requester));
|
978f824f |
mock_logger *test_logger;
|
b017a4d2 |
use_logger (configuration, test_logger = new mock_logger);
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
47f9faed |
//when
|
a71244c0 |
dc.authenticate (req());
|
47f9faed |
//then
|
b017a4d2 |
check (test_logger->logged_result() == PAM_SUCCESS,
"logged result should be success");
|
47142d31 |
check (test_logger->logged_requester() == requester,
|
3fc168fa |
"logged requester should be requester");
|
47142d31 |
check (test_logger->logged_authorizer() == authorizer,
|
3fc168fa |
"logged authorizer should be authorizer");
|
b017a4d2 |
check (test_logger->logged_token() == token,
"logged token should be token");
|
3fc168fa |
check (test_logger->logged_reason() == reason,
|
b14fb8c6 |
"logged reason should be reason");
|
47f9faed |
succeed();
}
|
caf7db60 |
|
cdf7fd74 |
int logs_authentication_failure()
{
|
fa407755 |
//given
dual_control_configuration configuration;
|
706636a4 |
std::string requester ("requester");
std::string authorizer ("authorizer");
std::string token ("token");
|
044b2625 |
std::string reason ("reason");
|
47142d31 |
use_validator (configuration, new fake_validator (requester, authorizer,
|
044b2625 |
"not the received token", reason));
|
b14fb8c6 |
use_conversation (configuration, new fake_conversation (authorizer, token,
reason));
|
706636a4 |
use_sessions (configuration, new fake_sessions (requester));
|
978f824f |
mock_logger *test_logger;
|
b017a4d2 |
use_logger (configuration, test_logger = new mock_logger);
|
58902985 |
dual_control dc (dual_control::create (configuration));
|
4a1812fd |
|
fa407755 |
//when
|
a71244c0 |
dc.authenticate (req());
|
4a1812fd |
|
fa407755 |
//then
|
b017a4d2 |
check (test_logger->logged_result() == PAM_AUTH_ERR,
"logged result should be success");
|
47142d31 |
check (test_logger->logged_requester() == requester,
"logged user name should be user");
check (test_logger->logged_authorizer() == authorizer,
|
b017a4d2 |
"logged user name should be user");
check (test_logger->logged_token() == token,
"logged token should be token");
|
fa407755 |
succeed();
|
4a1812fd |
}
|
cdf7fd74 |
int runtests()
{
|
b017a4d2 |
test (setcred_returns_success);
test (authenticate_validates_with_received_token);
test (authenticate_fails_with_wrong_user);
test (authenticate_fails_with_wrong_token);
test (logs_authentication);
test (logs_authentication_failure);
|
fa407755 |
succeed();
|
b12c1d5d |
}
|
b017a4d2 |
int main (int argc, char *argv[])
|
cdf7fd74 |
{
return !runtests();
|
704ed597 |
}
|
a120158c |
|