1
0
mirror of https://github.com/falk-werner/webfused synced 2026-03-02 04:09:19 +00:00

added pam authenticator

This commit is contained in:
Falk Werner
2020-03-19 21:53:49 +01:00
parent b53e002de0
commit ca348795f3
13 changed files with 669 additions and 21 deletions

99
test/mock_pam.cc Normal file
View File

@@ -0,0 +1,99 @@
#include "mock_pam.hpp"
extern "C"
{
static webfused_test::IPam * wfd_MockPam = nullptr;
extern int __real_pam_start(
char const * service_name,
char const * user,
struct pam_conv const * conversation,
pam_handle_t * * handle);
extern int __real_pam_end(pam_handle_t * handle, int status);
extern int __real_pam_authenticate(pam_handle_t * handle, int flags);
extern int __real_pam_acct_mgmt(pam_handle_t * handle, int flags);
extern char const * __real_pam_strerror(pam_handle_t * handle, int errnum);
int __wrap_pam_start(
char const * service_name,
char const * user,
struct pam_conv const * conversation,
pam_handle_t * * handle)
{
if (nullptr == wfd_MockPam)
{
return __real_pam_start(service_name, user, conversation, handle);
}
else
{
return wfd_MockPam->start(service_name, user, conversation, handle);
}
}
int __wrap_pam_end(pam_handle_t * handle, int status)
{
if (nullptr == wfd_MockPam)
{
return __real_pam_end(handle, status);
}
else
{
return wfd_MockPam->end(handle, status);
}
}
int __wrap_pam_authenticate(pam_handle_t * handle, int flags)
{
if (nullptr == wfd_MockPam)
{
return __real_pam_authenticate(handle, flags);
}
else
{
return wfd_MockPam->authenticate(handle, flags);
}
}
int __wrap_pam_acct_mgmt(pam_handle_t * handle, int flags)
{
if (nullptr == wfd_MockPam)
{
return __real_pam_acct_mgmt(handle, flags);
}
else
{
return wfd_MockPam->acct_mgmt(handle, flags);
}
}
char const * __wrap_pam_strerror(pam_handle_t * handle, int errnum)
{
if (nullptr == wfd_MockPam)
{
return __real_pam_strerror(handle, errnum);
}
else
{
return wfd_MockPam->strerror(handle, errnum);
}
}
}
namespace webfused_test
{
MockPam::MockPam()
{
wfd_MockPam = this;
}
MockPam::~MockPam()
{
wfd_MockPam = nullptr;
}
}

45
test/mock_pam.hpp Normal file
View File

@@ -0,0 +1,45 @@
#ifndef WFD_MOCK_PAM_HPP
#define WFD_MOCK_PAM_HPP
#include <security/pam_appl.h>
#include <gmock/gmock.h>
namespace webfused_test
{
class IPam
{
public:
virtual ~IPam() = default;
virtual int start(
char const * service_name,
char const * user,
struct pam_conv const * conversation,
pam_handle_t * * handle) = 0;
virtual int end(pam_handle_t * handle, int status) = 0;
virtual int authenticate(pam_handle_t * handle, int flags) = 0;
virtual int acct_mgmt(pam_handle_t * handle, int flags) = 0;
virtual char const * strerror(pam_handle_t * handle, int errnum) = 0;
};
class MockPam: public IPam
{
public:
MockPam();
~MockPam() override;
MOCK_METHOD4(start, int (
char const * service_name,
char const * user,
struct pam_conv const * conversation,
pam_handle_t * * handle));
MOCK_METHOD2(end, int(pam_handle_t * handle, int status));
MOCK_METHOD2(authenticate, int(pam_handle_t * handle, int flags));
MOCK_METHOD2(acct_mgmt, int (pam_handle_t * handle, int flags));
MOCK_METHOD2(strerror, char const * (pam_handle_t * handle, int errnum));
};
}
#endif

View File

@@ -1,13 +0,0 @@
#include <security/pam_appl.h>
#include <gtest/gtest.h>
TEST(pam, start)
{
pam_handle_t * handle = nullptr;
struct pam_conv conv = { nullptr, nullptr };
int rc = pam_start("test", nullptr, &conv, &handle);
if (PAM_SUCCESS == rc)
{
pam_end(handle, 0);
}
}

View File

@@ -0,0 +1,277 @@
#include "webfused/auth/pam_authenticator.h"
#include "webfused/auth/authenticator.h"
#include "webfused/config/settings.h"
#include "webfused/auth/factory.h"
#include "mock_credentials.hpp"
#include "mock_settings.hpp"
#include "mock_pam.hpp"
#include <gtest/gtest.h>
using ::webfused_test::MockSettings;
using ::webfused_test::MockCredentials;
using ::webfused_test::MockPam;
using ::testing::_;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::Invoke;
using ::testing::StrictMock;
TEST(pam_authenticator, create)
{
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, create_via_factory)
{
wfd_authenticator authenticator;
bool success = wfd_authenticator_create("pam", nullptr, &authenticator);
ASSERT_TRUE(success);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, get_type)
{
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
ASSERT_STREQ("username", wfd_authenticator_get_type(authenticator));
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("webfused"), nullptr, _, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, authenticate(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, acct_mgmt(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, end(_, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_TRUE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate_with_custom_service_name)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("brummni"), nullptr, _, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, authenticate(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, acct_mgmt(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, end(_, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
MockSettings settings;
EXPECT_CALL(settings, getStringOrDefault(StrEq("service_name"), StrEq("webfused")))
.Times(1).WillOnce(Return("brummni"));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_TRUE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
namespace
{
int valid_conversation(
char const * service_name,
char const * user,
struct pam_conv const * conv,
pam_handle_t * * handle)
{
(void) service_name;
(void) user;
(void) handle;
pam_message request_username = {PAM_PROMPT_ECHO_ON, "username"};
pam_message request_password = {PAM_PROMPT_ECHO_OFF, "password"};
pam_message const * messages[2] =
{
&request_username,
&request_password
};
pam_response * responses;
int rc = conv->conv(2, messages, &responses, conv->appdata_ptr);
if (PAM_SUCCESS == rc)
{
free(responses);
}
return rc;
}
}
TEST(pam_authenticator, conversation_with_valid_messages)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("webfused"), nullptr, _, _))
.Times(1).WillOnce(Invoke(&valid_conversation));
EXPECT_CALL(pam, authenticate(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, acct_mgmt(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, end(_, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_TRUE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
namespace
{
int invalid_conversation(
char const * service_name,
char const * user,
struct pam_conv const * conv,
pam_handle_t * * handle)
{
(void) service_name;
(void) user;
(void) handle;
pam_message invalid_request = {-1, "invalid"};
pam_message const * messages[2] =
{
&invalid_request
};
pam_response * responses;
int rc = conv->conv(1, messages, &responses, conv->appdata_ptr);
return rc;
}
}
TEST(pam_authenticator, conversation_with_invalid_messages)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("webfused"), nullptr, _, _))
.Times(1).WillOnce(Invoke(&invalid_conversation));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_FALSE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate_fail_authenticate)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("webfused"), nullptr, _, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, authenticate(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(-1));
EXPECT_CALL(pam, end(_, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_FALSE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate_fail_acct_mgmt)
{
MockPam pam;
EXPECT_CALL(pam, start(StrEq("webfused"), nullptr, _, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, authenticate(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(PAM_SUCCESS));
EXPECT_CALL(pam, acct_mgmt(_, PAM_DISALLOW_NULL_AUTHTOK)).Times(1).WillOnce(Return(-1));
EXPECT_CALL(pam, end(_, _)).Times(1).WillOnce(Return(PAM_SUCCESS));
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_FALSE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate_fail_missing_username)
{
StrictMock<MockPam> pam;
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return(nullptr));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret"));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_FALSE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}
TEST(pam_authenticator, authenticate_fail_missing_password)
{
StrictMock<MockPam> pam;
wfd_authenticator authenticator;
bool success = wfd_pam_authenticator_create(nullptr, &authenticator);
ASSERT_TRUE(success);
MockCredentials creds;
EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob"));
EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return(nullptr));
bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr);
ASSERT_FALSE(is_authenticated);
wfd_authenticator_dispose(authenticator);
}

View File

@@ -21,7 +21,13 @@ TEST(stderr_logger, init_via_manager)
TEST(stderr_logger, log)
{
ASSERT_TRUE(wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL));
WFD_INFO("some information");
WFD_FATAL("webfused test");
WFD_ERROR("webfused test");
WFD_WARN ("webfused test");
WFD_INFO ("webfused test");
WFD_DEBUG("webfused test");
wfd_log(-1, "webfused test");
wfd_logger_close();
}

View File

@@ -39,7 +39,13 @@ TEST(syslog_logger, init_via_manager)
TEST(syslog_logger, log)
{
ASSERT_TRUE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, NULL));
WFD_INFO("some information");
WFD_FATAL("webfused test");
WFD_ERROR("webfused test");
WFD_WARN ("webfused test");
WFD_INFO ("webfused test");
WFD_DEBUG("webfused test");
wfd_log(-1, "webfused test");
wfd_logger_close();
}