mirror of
https://github.com/falk-werner/webfused
synced 2024-10-27 20:44:08 +00:00
Merge pull request #4 from falk-werner/pam
feature: add PAM authenticator
This commit is contained in:
commit
e5aef52fdf
@ -25,6 +25,7 @@ addons:
|
||||
- python3-wheel
|
||||
- ninja-build
|
||||
- libconfig-dev
|
||||
- libpam0g-dev
|
||||
- valgrind
|
||||
|
||||
env:
|
||||
|
@ -3,6 +3,8 @@ project(webfused VERSION 0.1.0 DESCRIPTION "Webfuse daemon")
|
||||
|
||||
option(WITHOUT_TESTS "disable unit tests" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@ -14,6 +16,7 @@ pkg_check_modules(UUID REQUIRED uuid)
|
||||
pkg_check_modules(LIBCONFIG REQUIRED libconfig)
|
||||
pkg_check_modules(OPENSSL REQUIRED openssl)
|
||||
pkg_check_modules(WEBFUSE REQUIRED libwebfuse-adapter)
|
||||
find_package(Pam REQUIRED)
|
||||
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
@ -33,7 +36,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(C_WARNINGS -Wall -Wextra)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(coverage)
|
||||
|
||||
add_library(userdb STATIC
|
||||
@ -58,6 +60,7 @@ add_library(webfused-static STATIC
|
||||
src/webfused/auth/authenticator.c
|
||||
src/webfused/auth/factory.c
|
||||
src/webfused/auth/file_authenticator.c
|
||||
src/webfused/auth/pam_authenticator.c
|
||||
src/webfused/log/log.c
|
||||
src/webfused/log/logger.c
|
||||
src/webfused/log/manager.c
|
||||
@ -76,6 +79,7 @@ target_link_libraries(webfused PUBLIC
|
||||
${OPENSSL_LIBRARIES}
|
||||
${WEBFUSE_LIBRARIES}
|
||||
${UUID_LIBRARIES}
|
||||
${PAM_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_options(webfused PUBLIC ${OPENSSL_CFLAGS_OTHER})
|
||||
@ -119,11 +123,13 @@ add_executable(alltests
|
||||
test/mock_logger.cc
|
||||
test/mock_credentials.cc
|
||||
test/mock_settings.cc
|
||||
test/mock_pam.cc
|
||||
test/test_config_factory.cc
|
||||
test/test_config.cc
|
||||
test/test_settings.cc
|
||||
test/test_auth_factory.cc
|
||||
test/test_file_authenticator.cc
|
||||
test/test_pam_authenticator.cc
|
||||
test/test_mountpoint_factory.cc
|
||||
test/test_log.cc
|
||||
test/test_log_manager.cc
|
||||
@ -160,11 +166,18 @@ target_link_libraries(alltests PRIVATE
|
||||
-Wl,--wrap=wfd_config_set_logger
|
||||
-Wl,--wrap=wfd_config_set_user
|
||||
|
||||
-Wl,--wrap=pam_start
|
||||
-Wl,--wrap=pam_end
|
||||
-Wl,--wrap=pam_strerror
|
||||
-Wl,--wrap=pam_authenticate
|
||||
-Wl,--wrap=pam_acct_mgmt
|
||||
|
||||
webfused-static
|
||||
userdb
|
||||
${LIBCONFIG_LIBRARIES}
|
||||
${WEBFUSE_LIBRARIES}
|
||||
${UUID_LIBRARIES}
|
||||
${PAM_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${GMOCK_LIBRARIES}
|
||||
${GTEST_LIBRARIES}
|
||||
|
23
README.md
23
README.md
@ -39,10 +39,10 @@ server:
|
||||
authentication:
|
||||
(
|
||||
{
|
||||
provider = "file"
|
||||
provider = "pam"
|
||||
settings:
|
||||
{
|
||||
file = "/etc/webfused/passwd"
|
||||
service_name = "webfused"
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -104,9 +104,10 @@ Otherwise, plain websockes without TLS are used.
|
||||
| provider | string | *-required-* | Name of the authentication provider (see below) |
|
||||
| settings | object | *-empty-* | Provider specific settings (see below)
|
||||
|
||||
Currently, only one provider is specified:
|
||||
Currently, the following providers are supported:
|
||||
|
||||
- *file*: file based authentication
|
||||
- *pam*: authentication based on Linux PAM
|
||||
|
||||
### File Authenticaton Provider
|
||||
|
||||
@ -114,7 +115,15 @@ Allows authentication against a file containing username and password.
|
||||
|
||||
| Setting | Type | Default value | Description |
|
||||
| -------- | ------ | ------------- | ------------------------------- |
|
||||
| file | string | *-empty-* | Path to the authentication file |
|
||||
| file | string | *-required-* | Path to the authentication file |
|
||||
|
||||
### PAM Authenticaton Provider
|
||||
|
||||
Allows authentication using Linux PAM.
|
||||
|
||||
| Setting | Type | Default value | Description |
|
||||
| ------------ | ------ | ------------- | ---------------------- |
|
||||
| service_name | string | webfused | PAM service identifier |
|
||||
|
||||
### Filesystems
|
||||
|
||||
@ -180,6 +189,7 @@ switch to *user* and *group* provided in config file.
|
||||
- [jansson](https://github.com/akheron/jansson)
|
||||
- [openssl](https://www.openssl.org/)
|
||||
- [libconfig](https://hyperrealm.github.io/libconfig/)
|
||||
- [linux-pam](http://www.linux-pam.org/)
|
||||
- [Google Test](https://github.com/google/googletest) *(Test only)*
|
||||
|
||||
### Installing dependencies
|
||||
@ -240,6 +250,11 @@ To install libfuse, meson is needed. Please refer to [meson quick guide](https:/
|
||||
sudo apt update
|
||||
sudo apt install libconfig-dev
|
||||
|
||||
#### linux-pam
|
||||
|
||||
sudo apt update
|
||||
sudo apt install libpam0g-dev
|
||||
|
||||
#### GoogleTest
|
||||
|
||||
Installation of GoogleTest is optional webfuse library, but required to compile tests.
|
||||
|
22
cmake/FindPam.cmake
Normal file
22
cmake/FindPam.cmake
Normal file
@ -0,0 +1,22 @@
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_PAM QUIET pam)
|
||||
set(PAM_DEFINITIONS ${PC_PAM_CFLAGS_OTHER})
|
||||
|
||||
find_path(PAM_INCLUDE_DIR security/pam_appl.h
|
||||
HINTS ${PC_PAM_INCLUDEDIR} ${PC_PAM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(PAM_LIBRARY NAMES pam
|
||||
HINTS ${PC_PAM_LIBDIR} ${PC_PAM_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(Pam DEFAULT_MSG
|
||||
PAM_LIBRARY PAM_INCLUDE_DIR
|
||||
)
|
||||
|
||||
mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY)
|
||||
|
||||
set(PAM_LIBRARIES ${PAM_LIBRARY})
|
||||
set(PAM_INCLUDE_DIRS ${PAM_INCLUDE_DIR})
|
@ -25,6 +25,13 @@ authentication:
|
||||
file = "/etc/webfused/passwd"
|
||||
}
|
||||
}
|
||||
# {
|
||||
# provider = "pam"
|
||||
# settings:
|
||||
# {
|
||||
# service_name = "webfused"
|
||||
# }
|
||||
# }
|
||||
)
|
||||
|
||||
filesystems:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "webfused/auth/factory.h"
|
||||
#include "webfused/auth/file_authenticator.h"
|
||||
#include "webfused/auth/pam_authenticator.h"
|
||||
#include "webfused/config/settings.h"
|
||||
#include "webfused/log/log.h"
|
||||
|
||||
@ -16,6 +17,10 @@ wfd_authenticator_create(
|
||||
{
|
||||
result = wfd_file_authenticator_create(settings, authenticator);
|
||||
}
|
||||
else if (0 == strcmp("pam", provider))
|
||||
{
|
||||
result = wfd_pam_authenticator_create(settings, authenticator);
|
||||
}
|
||||
else
|
||||
{
|
||||
WFD_ERROR("failed to create authenticator: unknown type \"%s\"", provider);
|
||||
|
@ -61,7 +61,7 @@ wfd_file_authenticator_get_type(
|
||||
return "username";
|
||||
}
|
||||
|
||||
static struct wfd_authenticator_vtable
|
||||
static struct wfd_authenticator_vtable const
|
||||
wfd_file_authenticator_vtable =
|
||||
{
|
||||
.dispose = &wfd_file_authenticator_dispose,
|
||||
|
174
src/webfused/auth/pam_authenticator.c
Normal file
174
src/webfused/auth/pam_authenticator.c
Normal file
@ -0,0 +1,174 @@
|
||||
#include "webfused/auth/pam_authenticator.h"
|
||||
#include "webfused/auth/authenticator.h"
|
||||
#include "webfused/config/settings.h"
|
||||
#include "webfused/log/log.h"
|
||||
|
||||
#include "webfuse/adapter/credentials.h"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct wfd_pam_authenticator
|
||||
{
|
||||
char * service_name;
|
||||
};
|
||||
|
||||
struct wfd_pam_credentials
|
||||
{
|
||||
char const * username;
|
||||
char const * password;
|
||||
};
|
||||
|
||||
static int
|
||||
wfd_pam_conversation(
|
||||
int count,
|
||||
struct pam_message const ** messages,
|
||||
struct pam_response * * ret_responses,
|
||||
void * user_data)
|
||||
{
|
||||
int result = PAM_SUCCESS;
|
||||
struct pam_response * responses = malloc(count * sizeof(struct pam_response));
|
||||
struct wfd_pam_credentials * creds = user_data;
|
||||
|
||||
for(int i = 0; (PAM_SUCCESS == result) && (i < count); i++)
|
||||
{
|
||||
struct pam_response * response = &responses[i];
|
||||
struct pam_message const * message = messages[i];
|
||||
|
||||
response->resp_retcode = 0;
|
||||
response->resp = NULL;
|
||||
|
||||
switch (message->msg_style)
|
||||
{
|
||||
case PAM_PROMPT_ECHO_ON:
|
||||
response->resp = strdup(creds->username);
|
||||
break;
|
||||
case PAM_PROMPT_ECHO_OFF:
|
||||
response->resp = strdup(creds->password);
|
||||
break;
|
||||
default:
|
||||
free(responses);
|
||||
result = PAM_CONV_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (PAM_SUCCESS == result)
|
||||
{
|
||||
*ret_responses = responses;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
wfd_pam_authenticator_dispose(
|
||||
void * data)
|
||||
{
|
||||
struct wfd_pam_authenticator * authenticator = data;
|
||||
|
||||
free(authenticator->service_name);
|
||||
free(authenticator);
|
||||
}
|
||||
|
||||
static bool
|
||||
wfd_pam_authenticator_authenticate(
|
||||
struct wf_credentials * credentials,
|
||||
void * user_data)
|
||||
{
|
||||
bool result = false;
|
||||
struct wfd_pam_authenticator * authenticator = user_data;
|
||||
|
||||
char const * username = wf_credentials_get(credentials, "username");
|
||||
char const * password = wf_credentials_get(credentials, "password");
|
||||
if ((NULL != username) && (NULL != password))
|
||||
{
|
||||
struct wfd_pam_credentials creds =
|
||||
{
|
||||
.username = username,
|
||||
.password = password
|
||||
};
|
||||
|
||||
struct pam_conv const conversation =
|
||||
{
|
||||
.conv = &wfd_pam_conversation,
|
||||
.appdata_ptr = &creds
|
||||
};
|
||||
|
||||
pam_handle_t * handle = NULL;
|
||||
bool cleanup_handle = false;
|
||||
result = true;
|
||||
{
|
||||
int rc = pam_start(authenticator->service_name, NULL,
|
||||
&conversation, &handle);
|
||||
result = (PAM_SUCCESS == rc);
|
||||
cleanup_handle = result;
|
||||
if (!result)
|
||||
{
|
||||
WFD_ERROR("failed to start pam conversation: %s", pam_strerror(handle, rc));
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
int rc = pam_authenticate(handle, PAM_DISALLOW_NULL_AUTHTOK);
|
||||
result = (PAM_SUCCESS == rc);
|
||||
if (!result)
|
||||
{
|
||||
WFD_INFO("failed to authenticate user \'%s\' (pam_authenticate): %s",
|
||||
username, pam_strerror(handle, rc));
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
int rc = pam_acct_mgmt(handle, PAM_DISALLOW_NULL_AUTHTOK);
|
||||
result = (PAM_SUCCESS == rc);
|
||||
if (!result)
|
||||
{
|
||||
WFD_INFO("failed to authenticate user \'%s\' (pam_acct_mgmt): %s",
|
||||
username, pam_strerror(handle, rc));
|
||||
}
|
||||
}
|
||||
|
||||
if (cleanup_handle)
|
||||
{
|
||||
pam_end(handle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
WFD_INFO("authenticate user \'%s\': %s",
|
||||
(NULL != username) ? username : "<unknown>",
|
||||
result ? "success" : "failure");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char const *
|
||||
wfd_pam_authenticator_get_type(
|
||||
void * data)
|
||||
{
|
||||
(void) data;
|
||||
return "username";
|
||||
}
|
||||
|
||||
static struct wfd_authenticator_vtable const
|
||||
wfd_pam_authenticator_vtable =
|
||||
{
|
||||
.dispose = &wfd_pam_authenticator_dispose,
|
||||
.authenticate = &wfd_pam_authenticator_authenticate,
|
||||
.get_type = &wfd_pam_authenticator_get_type
|
||||
};
|
||||
|
||||
bool
|
||||
wfd_pam_authenticator_create(
|
||||
struct wfd_settings * settings,
|
||||
struct wfd_authenticator * authenticator)
|
||||
{
|
||||
struct wfd_pam_authenticator * data = malloc(sizeof(struct wfd_pam_authenticator));
|
||||
data->service_name = strdup(wfd_settings_get_string_or_default(settings, "service_name", "webfused"));
|
||||
|
||||
authenticator->vtable = &wfd_pam_authenticator_vtable;
|
||||
authenticator->data = data;
|
||||
return true;
|
||||
}
|
25
src/webfused/auth/pam_authenticator.h
Normal file
25
src/webfused/auth/pam_authenticator.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef WFD_AUTH_PAM_AUTHENTICATOR_H
|
||||
#define WFD_AUTH_PAM_AUTHENTICATOR_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct wfd_authenticator;
|
||||
struct wfd_settings;
|
||||
|
||||
extern bool
|
||||
wfd_pam_authenticator_create(
|
||||
struct wfd_settings * settings,
|
||||
struct wfd_authenticator * authenticator);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
99
test/mock_pam.cc
Normal file
99
test/mock_pam.cc
Normal 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
45
test/mock_pam.hpp
Normal 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
|
277
test/test_pam_authenticator.cc
Normal file
277
test/test_pam_authenticator.cc
Normal 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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user