diff options
author | Jakub Hrozek <jakub.hrozek@posteo.se> | 2015-10-20 15:47:48 +0200 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2015-12-10 13:31:19 +0100 |
commit | cdceeaaf6e83001b260d733492c0014f2255982b (patch) | |
tree | 6e9b7b874dc17fd0d18172a9900abd434789f15c | |
parent | be9fbe4bbdcbf6699ed7e549b3a74e0da275fc79 (diff) | |
download | pam_wrapper-cdceeaaf6e83001b260d733492c0014f2255982b.tar.gz pam_wrapper-cdceeaaf6e83001b260d733492c0014f2255982b.tar.xz pam_wrapper-cdceeaaf6e83001b260d733492c0014f2255982b.zip |
pwrap: Add pam_get_items.so and pam_set_items.so
-rw-r--r-- | src/CMakeLists.txt | 26 | ||||
-rw-r--r-- | src/modules/pam_get_items.c | 178 | ||||
-rw-r--r-- | src/modules/pam_set_items.c | 145 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/services/pwrap_get_set.in | 2 | ||||
-rw-r--r-- | tests/test_pam_wrapper.c | 53 |
6 files changed, 394 insertions, 12 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b09a78f..1455bb3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,25 +45,27 @@ install( ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ) -add_library(pam_matrix MODULE modules/pam_matrix.c) -set_property(TARGET pam_matrix PROPERTY PREFIX "") - +set(PAM_MODULES pam_matrix pam_get_items pam_set_items) set(PAM_LIBRARIES pam pam_misc) -target_link_libraries(pam_matrix - ${PAM_LIBRARIES}) - set(PWRAP_PRIVATE_LIBRARIES ${LIB_INSTALL_DIR}/pam_wrapper) -install( - TARGETS - pam_matrix - LIBRARY DESTINATION ${PWRAP_PRIVATE_LIBRARIES} - ARCHIVE DESTINATION ${PWRAP_PRIVATE_LIBRARIES} -) +foreach(_PAM_MODULE ${PAM_MODULES}) + add_library(${_PAM_MODULE} MODULE modules/${_PAM_MODULE}.c) + set_property(TARGET ${_PAM_MODULE} PROPERTY PREFIX "") + + target_link_libraries(${_PAM_MODULE} + ${PAM_LIBRARIES}) + + install( + TARGETS + ${_PAM_MODULE} + LIBRARY DESTINATION ${PWRAP_PRIVATE_LIBRARIES} + ARCHIVE DESTINATION ${PWRAP_PRIVATE_LIBRARIES}) +endforeach() # This needs to be at the end if (POLICY CMP0026) diff --git a/src/modules/pam_get_items.c b/src/modules/pam_get_items.c new file mode 100644 index 0000000..ec9f70f --- /dev/null +++ b/src/modules/pam_get_items.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015 Andreas Schneider <asn@samba.org> + * Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <security/pam_modules.h> +#include <security/pam_appl.h> + +static const char *str_opt(const int opt) +{ + switch (opt) { + case PAM_SERVICE: + return "PAM_SERVICE"; + case PAM_USER: + return "PAM_USER"; + case PAM_USER_PROMPT: + return "PAM_USER_PROMPT"; + case PAM_TTY: + return "PAM_TTY"; + case PAM_RUSER: + return "PAM_RUSER"; + case PAM_RHOST: + return "PAM_RHOST"; + case PAM_AUTHTOK: + return "PAM_AUTHTOK"; + case PAM_OLDAUTHTOK: + return "PAM_OLDAUTHTOK"; + case PAM_XDISPLAY: + return "PAM_XDISPLAY"; + case PAM_AUTHTOK_TYPE: + return "PAM_AUTHTOK_TYPE"; + } + + return NULL; /* Unsupported */ +} + +static int putenv_item(pam_handle_t *pamh, + int item_type) +{ + const char *opt_name; + const char *value = NULL; + char *env_name; + size_t env_len; + int rv; + + rv = pam_get_item(pamh, item_type, (const void **) &value); + if (rv != PAM_SUCCESS) { + return rv; + } + + if (value == NULL) { + return PAM_SUCCESS; + } + + opt_name = str_opt(item_type); + if (opt_name == NULL) { + /* Probably some non-printable value */ + return PAM_BAD_ITEM; + } + + env_len = strlen(value) + strlen(opt_name) + 2; + env_name = malloc(env_len); + if (env_name == NULL) { + return PAM_BUF_ERR; + } + + rv = snprintf(env_name, env_len, "%s=%s", opt_name, value); + if (rv < 0) { + free(env_name); + return PAM_BUF_ERR; + } + + rv = pam_putenv(pamh, env_name); + free(env_name); + + return rv; +} + +/* Get all pam_items and put them into environment */ +static int pam_putitem(pam_handle_t *pamh) +{ + + putenv_item(pamh, PAM_SERVICE); + putenv_item(pamh, PAM_USER); + putenv_item(pamh, PAM_USER_PROMPT); + putenv_item(pamh, PAM_TTY); + putenv_item(pamh, PAM_RUSER); + putenv_item(pamh, PAM_RHOST); + putenv_item(pamh, PAM_AUTHTOK); + putenv_item(pamh, PAM_OLDAUTHTOK); + putenv_item(pamh, PAM_XDISPLAY); + putenv_item(pamh, PAM_AUTHTOK_TYPE); + + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} + +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} + +PAM_EXTERN int +pam_sm_chauthtok(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + return pam_putitem(pamh); +} diff --git a/src/modules/pam_set_items.c b/src/modules/pam_set_items.c new file mode 100644 index 0000000..0fccf4c --- /dev/null +++ b/src/modules/pam_set_items.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015 Andreas Schneider <asn@samba.org> + * Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <security/pam_modules.h> +#include <security/pam_appl.h> + +#define ITEM_FILE_KEY "item_file=" + +static const char *envs[] = { + "PAM_SERVICE", + "PAM_USER", + "PAM_USER_PROMPT", + "PAM_TTY", + "PAM_RUSER", + "PAM_RHOST", + "PAM_AUTHTOK", + "PAM_OLDAUTHTOK", + "PAM_XDISPLAY", + "PAM_AUTHTOK_TYPE", + NULL +}; + +static const int items[] = { + PAM_SERVICE, + PAM_USER, + PAM_USER_PROMPT, + PAM_TTY, + PAM_RUSER, + PAM_RHOST, + PAM_AUTHTOK, + PAM_OLDAUTHTOK, + PAM_XDISPLAY, + PAM_AUTHTOK_TYPE, +}; + +static void pam_setitem_env(pam_handle_t *pamh) +{ + int i; + int rv; + const char *v; + + for (i = 0; envs[i] != NULL; i++) { + v = getenv(envs[i]); + if (v == NULL) { + continue; + } + + rv = pam_set_item(pamh, items[i], v); + if (rv != PAM_SUCCESS) { + continue; + } + } +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_chauthtok(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + (void) flags; /* unused */ + (void) argc; /* unused */ + (void) argv; /* unused */ + + pam_setitem_env(pamh); + return PAM_SUCCESS; +} + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c53090c..59db52b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,8 @@ set(PASSDB_PATH configure_file(passdb_ro ${PASSDB_PATH} @ONLY) configure_file(services/pwrap_pam_opt.in ${CMAKE_CURRENT_BINARY_DIR}/services/pwrap_pam_opt @ONLY) +configure_file(services/pwrap_get_set.in ${CMAKE_CURRENT_BINARY_DIR}/services/pwrap_get_set @ONLY) + if (OSX) set(TEST_ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${PAM_WRAPPER_LOCATION};PAM_WRAPPER=1;PAM_WRAPPER_CONFDIR=${CMAKE_CURRENT_BINARY_DIR}/services}) add_definitions(-DOSX) diff --git a/tests/services/pwrap_get_set.in b/tests/services/pwrap_get_set.in new file mode 100644 index 0000000..48809b9 --- /dev/null +++ b/tests/services/pwrap_get_set.in @@ -0,0 +1,2 @@ +session required @CMAKE_CURRENT_BINARY_DIR@/../src/pam_set_items.so +session required @CMAKE_CURRENT_BINARY_DIR@/../src/pam_get_items.so diff --git a/tests/test_pam_wrapper.c b/tests/test_pam_wrapper.c index d34b097..69d95b6 100644 --- a/tests/test_pam_wrapper.c +++ b/tests/test_pam_wrapper.c @@ -619,6 +619,58 @@ static void test_pam_vsyslog(void **state) pam_syslog(test_ctx->ph, LOG_INFO, "This is pam_wrapper test\n"); } +#define test_setenv(env) setenv(env, "test_"env, 1) + +#define test_getenv(envlist, key) do { \ + const char *__v; \ + __v = string_in_list(envlist, key); \ + assert_non_null(__v); \ + assert_string_equal(__v, "test_"key); \ +} while(0); + +static void test_get_set(void **state) +{ + const char *svc; + enum pamtest_err perr; + struct pamtest_case tests[] = { + { PAMTEST_OPEN_SESSION, PAM_SUCCESS, 0, 0 }, + { PAMTEST_GETENVLIST, PAM_SUCCESS, 0, 0 }, + { PAMTEST_SENTINEL, 0, 0, 0 }, + }; + + (void) state; /* unused */ + + test_setenv("PAM_SERVICE"); + test_setenv("PAM_USER"); + test_setenv("PAM_USER_PROMPT"); + test_setenv("PAM_TTY"); + test_setenv("PAM_RUSER"); + test_setenv("PAM_RHOST"); + test_setenv("PAM_AUTHTOK"); + test_setenv("PAM_OLDAUTHTOK"); + test_setenv("PAM_XDISPLAY"); + test_setenv("PAM_AUTHTOK_TYPE"); + + perr = pamtest("pwrap_get_set", "testuser", NULL, tests); + assert_int_equal(perr, PAMTEST_ERR_OK); + + /* PAM_SERVICE is a special case, libpam lowercases it */ + svc = string_in_list(tests[1].case_out.envlist, "PAM_SERVICE"); + assert_non_null(svc); + assert_string_equal(svc, "test_pam_service"); + + //test_getenv(tests[1].case_out.envlist, "PAM_SERVICE"); + test_getenv(tests[1].case_out.envlist, "PAM_USER"); + test_getenv(tests[1].case_out.envlist, "PAM_USER_PROMPT"); + test_getenv(tests[1].case_out.envlist, "PAM_TTY"); + test_getenv(tests[1].case_out.envlist, "PAM_RUSER"); + test_getenv(tests[1].case_out.envlist, "PAM_RHOST"); + test_getenv(tests[1].case_out.envlist, "PAM_AUTHTOK"); + test_getenv(tests[1].case_out.envlist, "PAM_OLDAUTHTOK"); + test_getenv(tests[1].case_out.envlist, "PAM_XDISPLAY"); + test_getenv(tests[1].case_out.envlist, "PAM_AUTHTOK_TYPE"); +} + int main(void) { int rc; @@ -669,6 +721,7 @@ int main(void) { cmocka_unit_test_setup_teardown(test_pam_vsyslog, setup_noconv, teardown), + cmocka_unit_test(test_get_set), }; rc = cmocka_run_group_tests(init_tests, NULL, NULL); |