summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2015-10-13 15:34:47 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-10-16 16:08:26 +0200
commitd04062511a4862f5a0083ec5353ac7dd46decdd2 (patch)
treeb20878b451c504c50b2b31982b3a1de65f0df6b0
parenta2a80e85982a6acce567528beda489e6c6fea4ce (diff)
downloadsssd-pwrap.zip
sssd-pwrap.tar.gz
sssd-pwrap.tar.xz
WIP: pam_wrapper testspwrap
-rw-r--r--Makefile.am38
-rw-r--r--configure.ac3
-rw-r--r--src/external/cwrap.m418
-rw-r--r--src/tests/cwrap/Makefile.am28
-rwxr-xr-xsrc/tests/cwrap/cwrap_test_setup.sh6
-rw-r--r--src/tests/cwrap/mock_pam_responder.c204
-rw-r--r--src/tests/cwrap/pam_services/test_pam_sss.in4
-rw-r--r--src/tests/cwrap/test_wrapper_pam_sss.c96
8 files changed, 394 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index a9ff93b..2b26f1c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1772,7 +1772,7 @@ responder_socket_access_tests_LDADD = \
$(SSSD_LIBS) \
$(SSSD_INTERNAL_LTLIBS) \
libsss_test_common.la
-endif
+endif # HAVE_CHECK
stress_tests_SOURCES = \
src/tests/stress-tests.c
@@ -2729,6 +2729,40 @@ pam_sss_la_LDFLAGS = \
-avoid-version \
-Wl,--version-script,$(srcdir)/src/sss_client/sss_pam.exports
+if HAVE_PAM_WRAPPER
+if HAVE_LIBPAMTEST
+check_LTLIBRARIES += \
+ pam_test_sss.la \
+ $(NULL)
+
+cwrap_test_modules = pam_test_sss.la
+endif # HAVE_LIBPAMTEST
+endif # HAVE_PAM_WRAPPER
+
+pam_test_sss_la_SOURCES = \
+ $(pam_sss_la_SOURCES) \
+ src/tests/cwrap/mock_pam_responder.c \
+ src/responder/common/responder_packet.c \
+ src/responder/pam/pamsrv_extract.c \
+ src/responder/pam/pamsrv_reply.c \
+ src/responder/pam/pamsrv_p11.c \
+ $(NULL)
+pam_test_sss_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(NULL)
+pam_test_sss_la_LIBADD = \
+ $(pam_sss_la_LIBADD) \
+ libsss_debug.la \
+ libsss_util.la \
+ $(NULL)
+pam_test_sss_la_LDFLAGS = \
+ $(pam_sss_la_LDFLAGS) \
+ -rpath /nowhere \
+ -Wl,-wrap,sss_pam_make_request \
+ -Wl,-wrap,sss_packet_get_body \
+ -Wl,-wrap,sss_parse_name_for_domains \
+ $(NULL)
+
if BUILD_SUDO
libsss_sudo_la_SOURCES = \
@@ -3643,7 +3677,7 @@ endif
CLEANFILES = *.X */*.X */*/*.X
-tests: all $(check_PROGRAMS)
+tests: all $(check_PROGRAMS) $(cwrap_test_modules)
(cd src/tests/cwrap && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1;
diff --git a/configure.ac b/configure.ac
index c6debe2..214f64d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -391,6 +391,8 @@ AM_CONDITIONAL([HAVE_CHECK], [test x$have_check != x])
AM_CHECK_CMOCKA
AM_CHECK_UID_WRAPPER
AM_CHECK_NSS_WRAPPER
+AM_CHECK_PAM_WRAPPER
+AM_CHECK_LIBPAMTEST
SSS_ENABLE_INTGCHECK_REQS
@@ -407,6 +409,7 @@ AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config
src/sysv/sssd src/sysv/gentoo/sssd src/sysv/SUSE/sssd
po/Makefile.in src/man/Makefile src/tests/cwrap/Makefile
src/tests/intg/Makefile
+ src/tests/cwrap/pam_services/test_pam_sss
src/providers/ipa/ipa_hbac.pc src/providers/ipa/ipa_hbac.doxy
src/lib/idmap/sss_idmap.pc src/lib/idmap/sss_idmap.doxy
src/sss_client/sudo/sss_sudo.doxy
diff --git a/src/external/cwrap.m4 b/src/external/cwrap.m4
index b8489cc..f06de87 100644
--- a/src/external/cwrap.m4
+++ b/src/external/cwrap.m4
@@ -28,3 +28,21 @@ AC_DEFUN([AM_CHECK_NSS_WRAPPER],
[
AM_CHECK_WRAPPER(nss_wrapper, HAVE_NSS_WRAPPER)
])
+
+AC_DEFUN([AM_CHECK_PAM_WRAPPER],
+[
+ AM_CHECK_WRAPPER(pam_wrapper, HAVE_PAM_WRAPPER)
+])
+
+dnl A macro to check presence of cmocka on the system
+AC_DEFUN([AM_CHECK_LIBPAMTEST],
+[
+ have_libpamtest="no"
+ PKG_CHECK_EXISTS(libpamtest,
+ dnl PKG_CHECK_EXISTS ACTION-IF-FOUND
+ [PKG_CHECK_MODULES([PAMTEST], [libpamtest], [have_libpamtest="yes"])],
+ dnl PKG_CHECK_EXISTS ACTION-IF-NOT-FOUND
+ [AC_MSG_WARN([No libpamtest library found, some tests will not be built])]
+ )
+ AM_CONDITIONAL([HAVE_LIBPAMTEST], [test x$have_libpamtest = xyes])
+])
diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
index 34b5d8b..9eeb79e 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -53,9 +53,19 @@ check_PROGRAMS += \
$(NULL)
endif # HAVE_UID_WRAPPER
endif # HAVE_NSS_WRAPPER
+
+if HAVE_PAM_WRAPPER
+if HAVE_LIBPAMTEST
+check_PROGRAMS += \
+ pam_sss_wrapper-tests \
+ $(NULL)
+endif # HAVE_LIBPAMTEST
+endif # HAVE_PAM_WRAPPER
+
endif # HAVE_CMOCKA
-TESTS = $(check_PROGRAMS)
+TESTS = $(check_PROGRAMS) \
+ $(NULL)
become_user_tests_SOURCES = \
test_become_user.c \
@@ -167,4 +177,20 @@ responder_common_tests_LDADD = \
$(abs_top_builddir)/libsss_test_common.la \
$(NULL)
+pam_sss_wrapper_tests_SOURCES = \
+ test_wrapper_pam_sss.c \
+ $(NULL)
+pam_sss_wrapper_tests_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(NULL)
+pam_sss_wrapper_tests_LDADD = \
+ $(CMOCKA_LIBS) \
+ $(TALLOC_LIBS) \
+ $(POPT_LIBS) \
+ $(PAM_LIBS) \
+ $(PAMTEST_LIBS) \
+ $(abs_top_builddir)/libsss_debug.la \
+ $(abs_top_builddir)/libsss_test_common.la \
+ $(NULL)
+
tests: $(check_PROGRAMS)
diff --git a/src/tests/cwrap/cwrap_test_setup.sh b/src/tests/cwrap/cwrap_test_setup.sh
index 0d35cb7..0cec62a 100755
--- a/src/tests/cwrap/cwrap_test_setup.sh
+++ b/src/tests/cwrap/cwrap_test_setup.sh
@@ -5,6 +5,7 @@ pkg-config --exists uid_wrapper || exit 1
nss_wrapper=$(pkg-config --libs nss_wrapper)
uid_wrapper=$(pkg-config --libs uid_wrapper)
+pam_wrapper=$(pkg-config --libs pam_wrapper)
if [ -z $nss_wrapper -o -z $uid_wrapper ]; then
echo "Cannot locate cwrap libraries"
exit 2
@@ -15,3 +16,8 @@ export NSS_WRAPPER_PASSWD=$CWRAP_TEST_SRCDIR/passwd
export NSS_WRAPPER_GROUP=$CWRAP_TEST_SRCDIR/group
export UID_WRAPPER=1
export UID_WRAPPER_ROOT=1
+
+if [ ! -z $pam_wrapper ]; then
+ export PAM_WRAPPER=1
+ export PAM_WRAPPER_CONFDIR=$(pwd)/pam_services
+fi
diff --git a/src/tests/cwrap/mock_pam_responder.c b/src/tests/cwrap/mock_pam_responder.c
new file mode 100644
index 0000000..8c057ac
--- /dev/null
+++ b/src/tests/cwrap/mock_pam_responder.c
@@ -0,0 +1,204 @@
+/*
+ Copyright (C) 2015 Red Hat
+
+ SSSD tests: PAM tests
+
+ 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 <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "sss_cli.h"
+
+#include "responder/pam/pamsrv.h"
+#include "responder/common/responder_packet.h"
+#include "providers/data_provider.h"
+
+/* FIXME - move the definition to a private header */
+struct sss_packet {
+ size_t memsize;
+
+ /* Structure of the buffer:
+ * Bytes Content
+ * ---------------------------------
+ * 0-15 packet header
+ * 0-3 packet length (uint32_t)
+ * 4-7 command type (uint32_t)
+ * 8-11 status (uint32_t)
+ * 12-15 reserved
+ * 16+ packet body */
+ uint8_t *buffer;
+
+ /* io pointer */
+ size_t iop;
+};
+
+/* Make linker happy */
+int __wrap_sss_parse_name_for_domains(TALLOC_CTX *memctx,
+ struct sss_domain_info *domains,
+ const char *default_domain,
+ const char *orig,
+ char **domain, char **name)
+{
+ char *atsign;
+
+ atsign = strrchr(orig, '@');
+ if (atsign == NULL) {
+ *domain = NULL;
+ *name = talloc_strdup(memctx, orig);
+ if (*name == NULL) {
+ return ENOMEM;
+ }
+ return EOK;
+ }
+
+ *name = talloc_strndup(memctx, orig, atsign - orig);
+ *domain = talloc_strdup(memctx, atsign+1);
+ if (*name == NULL || *domain == NULL) {
+ return ENOMEM;
+ }
+
+ return EOK;
+}
+
+void __wrap_sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen)
+{
+ *body = packet->buffer;
+ *blen = packet->memsize;
+}
+
+static struct cli_ctx *
+mock_pam_cctx(TALLOC_CTX *mem_ctx,
+ enum sss_cli_command cmd,
+ int cli_protocol_version,
+ struct sss_cli_req_data *rd)
+{
+ struct cli_ctx *cctx = NULL;
+ int ret;
+
+ cctx = talloc_zero(mem_ctx, struct cli_ctx);
+ if (!cctx) goto fail;
+
+ cctx->creq = talloc_zero(cctx, struct cli_request);
+ if (cctx->creq == NULL) goto fail;
+
+ cctx->cli_protocol_version = talloc_zero(cctx,
+ struct cli_protocol_version);
+ if (cctx->cli_protocol_version == NULL) goto fail;
+
+ cctx->cli_protocol_version->version = cli_protocol_version;
+
+ cctx->creq = talloc_zero(cctx, struct cli_request);
+ if (cctx->creq == NULL) goto fail;
+
+ ret = sss_packet_new(cctx->creq, 0, cmd, &cctx->creq->in);
+ if (ret != EOK) goto fail;
+
+ cctx->rctx = talloc_zero(cctx, struct resp_ctx);
+ if (cctx->rctx == NULL) goto fail;
+
+ cctx->creq->in->buffer = discard_const(rd->data);
+ cctx->creq->in->memsize = rd->len;
+
+ return cctx;
+
+fail:
+ talloc_free(cctx);
+ return NULL;
+}
+
+static struct pam_data *
+mock_pam_data(TALLOC_CTX *mem_ctx, enum sss_cli_command cmd)
+{
+ struct pam_data *pd = NULL;
+
+ pd = talloc_zero(mem_ctx, struct pam_data);
+ if (pd == NULL) goto fail;
+
+ pd->cmd = cmd;
+ pd->authtok = sss_authtok_new(pd);
+ pd->newauthtok = sss_authtok_new(pd);
+ if (pd->authtok == NULL || pd->newauthtok == NULL) goto fail;
+
+ return pd;
+
+fail:
+ talloc_free(pd);
+ return NULL;
+}
+
+/* Receives a packed response and returns a mock reply */
+int __wrap_sss_pam_make_request(enum sss_cli_command cmd,
+ struct sss_cli_req_data *rd,
+ uint8_t **repbuf, size_t *replen,
+ int *errnop)
+{
+ errno_t ret;
+ TALLOC_CTX *test_ctx;
+ struct cli_ctx *cctx;
+ struct pam_data *pd;
+
+ test_ctx = talloc_new(NULL);
+ if (test_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ /* The PAM responder functions expect both cctx and pd to be talloc
+ * contexts
+ */
+ cctx = mock_pam_cctx(test_ctx, cmd, 3, rd);
+ pd = mock_pam_data(test_ctx, cmd);
+ if (cctx == NULL || pd == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = pam_forwarder_parse_data(cctx, pd);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (cmd == SSS_PAM_AUTHENTICATE) {
+ if (strcmp(pd->user, "testuser") == 0) {
+ const char *password;
+ size_t pwlen;
+
+ ret = sss_authtok_get_password(pd->authtok, &password, &pwlen);
+ if (ret != EOK) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (strncmp(password, "secret", pwlen) == 0) {
+ pd->pam_status = PAM_SUCCESS;
+ } else {
+ pd->pam_status = PAM_AUTH_ERR;
+ }
+ }
+ }
+
+ ret = pamsrv_reply_packet(cctx->creq, pd, cmd, &cctx->creq->out);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ *repbuf = malloc(cctx->creq->out->memsize);
+ memcpy(*repbuf, cctx->creq->out->buffer, cctx->creq->out->memsize);
+ *replen = cctx->creq->out->memsize;
+
+ ret = EOK;
+done:
+ return ret;
+}
diff --git a/src/tests/cwrap/pam_services/test_pam_sss.in b/src/tests/cwrap/pam_services/test_pam_sss.in
new file mode 100644
index 0000000..8cff061
--- /dev/null
+++ b/src/tests/cwrap/pam_services/test_pam_sss.in
@@ -0,0 +1,4 @@
+auth required @abs_top_builddir@/.libs/pam_test_sss.so
+account required @abs_top_builddir@/.libs/pam_test_sss.so
+password required @abs_top_builddir@/.libs/pam_test_sss.so
+session required @abs_top_builddir@/.libs/pam_test_sss.so
diff --git a/src/tests/cwrap/test_wrapper_pam_sss.c b/src/tests/cwrap/test_wrapper_pam_sss.c
new file mode 100644
index 0000000..c0d1fa5
--- /dev/null
+++ b/src/tests/cwrap/test_wrapper_pam_sss.c
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2015 Red Hat
+
+ SSSD tests: PAM tests
+
+ 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 <popt.h>
+#include <libpamtest.h>
+
+#include "util/util.h"
+#include "tests/cmocka/common_mock.h"
+
+static void test_pam_authenticate(void **state)
+{
+ enum pamtest_err perr;
+ const char *testuser_authtoks[] = {
+ "secret",
+ NULL,
+ };
+ struct pamtest_case tests[] = {
+ { PAMTEST_AUTHENTICATE, PAM_SUCCESS, 0, 0 },
+ { PAMTEST_SENTINEL, 0, 0, 0 },
+ };
+
+ (void) state; /* unused */
+
+ perr = pamtest("test_pam_sss", "testuser", testuser_authtoks, tests);
+ assert_int_equal(perr, PAMTEST_ERR_OK);
+}
+
+static void test_pam_authenticate_err(void **state)
+{
+ enum pamtest_err perr;
+ const char *testuser_authtoks[] = {
+ "wrong_secret",
+ NULL,
+ };
+ struct pamtest_case tests[] = {
+ { PAMTEST_AUTHENTICATE, PAM_AUTH_ERR, 0, 0 },
+ { PAMTEST_SENTINEL, 0, 0, 0 },
+ };
+
+ (void) state; /* unused */
+
+ perr = pamtest("test_pam_sss", "testuser", testuser_authtoks, tests);
+ assert_int_equal(perr, PAMTEST_ERR_OK);
+}
+
+int main(int argc, const char *argv[])
+{
+ poptContext pc;
+ int opt;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ SSSD_DEBUG_OPTS
+ POPT_TABLEEND
+ };
+
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_pam_authenticate),
+ cmocka_unit_test(test_pam_authenticate_err),
+ };
+
+ /* Set debug level to invalid value so we can deside if -d 0 was used. */
+ debug_level = SSSDBG_INVALID;
+
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch(opt) {
+ default:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+ }
+ poptFreeContext(pc);
+
+ DEBUG_CLI_INIT(debug_level);
+ tests_set_cwd();
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}