diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8e50494fb6..cae4352ea1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,76 +21,6 @@ jobs: id: matrix run: ./contrib/ci/get-matrix.py --action - intgcheck: - if: github.event_name == 'push' || !contains(github.event.pull_request.labels.*.name, 'Accepted') - needs: [prepare] - strategy: - fail-fast: false - matrix: - tag: ${{ fromJson(needs.prepare.outputs.matrix).intgcheck }} - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@v7 - with: - path: sssd - - - name: Setup containers - uses: SSSD/sssd-ci-containers/actions/setup@master - with: - path: sssd-ci-containers - tag: ${{ matrix.tag }} - limit: dns client - override: | - services: - client: - image: ${REGISTRY}/ci-client-devel:${TAG} - volumes: - - ../sssd:/sssd:rw - - - name: Run integration tests - uses: SSSD/sssd-ci-containers/actions/exec@master - with: - working-directory: /sssd - script: ./contrib/ci/run --moderate - - - name: Print logs - uses: next-actions/print-logs@master - if: always() - with: - working-directory: ./sssd/ci-build-debug - files: | - test-suite.log - ci-make-intgcheck.log - ci-make-distcheck.log - - - name: Upload main artifacts - if: always() - uses: actions/upload-artifact@v7 - with: - if-no-files-found: ignore - name: ${{ matrix.tag }}-intgcheck - path: | - ./sssd/var/log/sssd/*.log - ./sssd/ci-build-debug/ci-*.log - ./sssd/ci-build-debug/config.log - ./sssd/ci-build-debug/test-suite.log - ./sssd/ci-build-debug/ci-mock-result/*.log - ./sssd/ci-build-debug/src/tests/cwrap/test-suite.log - ./sssd/ci-install-deps.log - ./sssd/ci-autoreconf.log - - - name: Upload valgrind artifacts - if: always() - uses: actions/upload-artifact@v7 - with: - if-no-files-found: ignore - name: ${{ matrix.tag }}-intgcheck-valgrind - path: | - ./sssd/ci-build-debug/*.valgrind.log - system: if: github.event_name == 'push' || !contains(github.event.pull_request.labels.*.name, 'Accepted') needs: [prepare] diff --git a/Makefile.am b/Makefile.am index c5c25f68f16..32713972e89 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ if HAVE_MANPAGES SUBDIRS += src/man endif -SUBDIRS += . src/tests/cwrap src/tests/intg src/tests/test_CA \ +SUBDIRS += . src/tests/cwrap src/tests/test_CA \ src/tests/test_ECC_CA src/tools/analyzer # Some old versions of automake don't define builddir @@ -4091,51 +4091,6 @@ test_sssd_krb5_localauth_plugin_LDADD = \ $(NULL) endif -##################### -# Integration tests # -##################### - -intgcheck-prepare: - set -e; \ - rm -Rf intg; \ - $(MKDIR_P) intg/bld; \ - : Use /hopefully/ short prefix to keep D-Bus socket path short; \ - prefix=`mktemp --tmpdir --directory sssd-intg.XXXXXXXX`; \ - $(LN_S) "$$prefix" intg/pfx; \ - cd intg/bld; \ - $(abs_top_srcdir)/configure \ - --prefix="$$prefix" \ - --with-ldb-lib-dir="$$prefix"/lib/ldb \ - --with-pid-path="$$prefix"/run/sssd \ - --enable-intgcheck-reqs \ - --without-selinux \ - --with-session-recording-shell=/bin/false \ - $(INTGCHECK_CONFIGURE_FLAGS) \ - CFLAGS="-O2 -g $$CFLAGS -DINTGCHECK_BUILD"; \ - $(MAKE) $(AM_MAKEFLAGS) ; \ - $(MAKE) $(AM_MAKEFLAGS) test_ssh_client; \ - : Force single-thread install to workaround concurrency issues; \ - $(MAKE) $(AM_MAKEFLAGS) -j1 install; \ - : Remove .la files from LDB module directory to avoid loader warnings; \ - rm "$$prefix"/lib/ldb/*.la; \ - cd ../.. - -intgcheck-run: - set -e; \ - if [ ! -d intg/pfx ]; then $(MAKE) intgcheck-prepare; fi; \ - cd intg/bld; \ - $(MAKE) $(AM_MAKEFLAGS) -C src/tests/intg intgcheck-installed; \ - cd ../.. - -intgcheck-clean: - set -e; \ - prefix=`readlink -e intg/pfx`; \ - rm -Rf "$$prefix" intg - -intgcheck: - $(MAKE) intgcheck-prepare - $(MAKE) intgcheck-run - $(MAKE) intgcheck-clean #################### # Client Libraries # diff --git a/configure.ac b/configure.ac index 39a9ebc91df..8d2fdb313ba 100644 --- a/configure.ac +++ b/configure.ac @@ -235,7 +235,6 @@ m4_include([src/external/sasl.m4]) m4_include([src/external/libnfsidmap.m4]) m4_include([src/external/cwrap.m4]) m4_include([src/external/libresolv.m4]) -m4_include([src/external/intgcheck.m4]) m4_include([src/external/systemtap.m4]) m4_include([src/external/service.m4]) m4_include([src/external/test_ca.m4]) @@ -552,7 +551,7 @@ AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config src/examples/logrotate src/sysv/sssd src/sysv/gentoo/sssd src/sysv/gentoo/sssd-kcm po/Makefile.in src/man/Makefile src/tests/cwrap/Makefile - src/tests/intg/Makefile src/tests/test_CA/Makefile + src/tests/test_CA/Makefile src/tests/test_CA/intermediate_CA/Makefile src/tests/test_ECC_CA/Makefile src/lib/ipa_hbac/ipa_hbac.pc src/lib/ipa_hbac/ipa_hbac.doxy diff --git a/contrib/ci/deps.sh b/contrib/ci/deps.sh index c86f106c8f6..a3c32d6f590 100644 --- a/contrib/ci/deps.sh +++ b/contrib/ci/deps.sh @@ -26,9 +26,6 @@ declare -a DEPS_LIST=( valgrind ) -# "Integration tests dependencies satisfied" flag -declare DEPS_INTGCHECK_SATISFIED=true - if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then declare _DEPS_LIST_SPEC DEPS_LIST+=( @@ -150,7 +147,6 @@ if [[ "$DISTRO_BRANCH" == -debian-* ]]; then libsubid-dev ) - DEPS_INTGCHECK_SATISFIED=true fi declare -a -r DEPS_LIST diff --git a/contrib/ci/get-matrix.py b/contrib/ci/get-matrix.py index b2b79555c8c..07778e31f1f 100755 --- a/contrib/ci/get-matrix.py +++ b/contrib/ci/get-matrix.py @@ -66,7 +66,6 @@ def get_centos_matrix(): centos = sorted(get_centos_matrix()) matrix = { - 'intgcheck': [*fedora, *centos], 'multihost': [*fedora, *centos], } diff --git a/contrib/ci/run b/contrib/ci/run index 43fb60a8c84..49a37656ad9 100755 --- a/contrib/ci/run +++ b/contrib/ci/run @@ -135,7 +135,6 @@ function build_debug() declare -r valgrind_test_pattern+="*/double_semicolon_test)" export CFLAGS="$DEBUG_CFLAGS" declare test_dir - declare intgcheck_configure_args declare status test_dir=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX` @@ -163,18 +162,6 @@ function build_debug() mv "$test_dir" ci-test-dir ((status == 0)) - if "$MODERATE"; then - if "$DEPS_INTGCHECK_SATISFIED"; then - printf -v intgcheck_configure_args " %q" \ - "${CONFIGURE_ARG_LIST[@]}" - stage make-intgcheck make -j $CPU_NUM intgcheck \ - INTGCHECK_CONFIGURE_FLAGS=" \ - $intgcheck_configure_args" - fi - - ((status == 0)) - fi - unset CFLAGS } diff --git a/src/external/intgcheck.m4 b/src/external/intgcheck.m4 deleted file mode 100644 index 1446a7cb4bf..00000000000 --- a/src/external/intgcheck.m4 +++ /dev/null @@ -1,87 +0,0 @@ -AC_CHECK_PROG([HAVE_FAKEROOT], [fakeroot], [yes], [no]) - -dnl Check for variable and fail unless value is "yes" -dnl The second argument will be printed in error message in case of error -dnl Usage: -dnl SSS_INTGCHECK_REQ(variable, message) - -AC_DEFUN([SSS_INTGCHECK_REQ], [ - AS_IF([test x$$1 = xyes], , [ - AC_MSG_ERROR([cannot enable integration tests: $2 not found])]) -]) - -dnl Check for python variable and fail/warn unless value is "yes" -dnl The second argument will be printed in error message in case of error -dnl Any value in 3rd argument will make change error to info -dnl Usage: -dnl SSS_INTGCHECK_PYTHON_REQ(variable, message, [non_fatal]) - -AC_DEFUN([SSS_INTGCHECK_PYTHON_REQ], [ - AS_IF([test x$$1 = xyes], [], - [sss_have_py_intg_deps=no - AS_IF([test -n "$3"], - [AC_MSG_NOTICE([missing python dependency for integration tests: $2 not found])], - [AC_MSG_ERROR([cannot enable integration tests: $2 not found])]) - ]) -]) - -dnl Check for variable and fail unless value is "yes" -dnl The second argument will be printed in error message in case of error -dnl Usage: -dnl SSS_CHECK_PYTHON_INTG_REQ(python_version, [non_fatal]) -AC_DEFUN([SSS_CHECK_PYTHON_INTG_REQ], [ - sss_have_py_intg_deps="no" - - SSS_INTGCHECK_PYTHON_REQ([HAVE_PYTHON$1_BINDINGS], - [sssd python$1 bindings], [$2]) - - AS_IF([test x$HAVE_PYTHON$1_BINDINGS = xyes], - [SSS_CHECK_PYTEST([$PYTHON$1], [PY$1_PYTEST]) - []AM_PYTHON$1_MODULE([ldap]) - []AM_PYTHON$1_MODULE([ldb]) - []AM_PYTHON$1_MODULE([requests]) - []AM_PYTHON$1_MODULE([dbus]) - []AM_PYTHON$1_MODULE([psutil]) - - sss_have_py_intg_deps="yes" - - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1_PYTEST], - [python$1 pytest], [$2]) - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1MOD_LDAP], - [python$1 module ldap], [$2]) - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1MOD_LDB], - [python$1 module ldb], [$2]) - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1MOD_REQUESTS], - [python$1 module requests], [$2]) - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1MOD_DBUS], - [python$1 module dbus], [$2]) - SSS_INTGCHECK_PYTHON_REQ([HAVE_PY$1MOD_PSUTIL], - [python$1 module psutil], [$2])]) - - AS_IF([test "x$sss_have_py_intg_deps" = xyes], - [HAVE_PYTHON_INTG_DEPS=yes - PYTHON_EXEC_INTG=$PYTHON$1 - AC_SUBST(PYTHON_EXEC_INTG)], - [HAVE_PYTHON_INTG_DEPS=no]) - unset sss_have_py_intg_deps -]) - -AC_DEFUN([SSS_ENABLE_INTGCHECK_REQS], [ - AC_ARG_ENABLE(intgcheck-reqs, - [AS_HELP_STRING([--enable-intgcheck-reqs], - [enable checking for integration test requirements [default=no]])], - [enable_intgcheck_reqs="$enableval"], - [enable_intgcheck_reqs="no"]) - if test x"$enable_intgcheck_reqs" = xyes; then - SSS_INTGCHECK_REQ([HAVE_UID_WRAPPER], [uid_wrapper]) - SSS_INTGCHECK_REQ([HAVE_NSS_WRAPPER], [nss_wrapper]) - SSS_INTGCHECK_REQ([HAVE_PAM_WRAPPER], [pam_wrapper]) - SSS_INTGCHECK_REQ([HAVE_SLAPD], [slapd]) - SSS_INTGCHECK_REQ([HAVE_LDAPMODIFY], [ldapmodify]) - SSS_INTGCHECK_REQ([HAVE_FAKEROOT], [fakeroot]) - - SSS_CHECK_PYTHON_INTG_REQ([3]) - fi -]) - -AM_CONDITIONAL([INTG_BUILD], [test x"$enable_intgcheck_reqs" = xyes]) diff --git a/src/tests/intg/.config/screenrc b/src/tests/intg/.config/screenrc deleted file mode 100644 index fe1e4248a63..00000000000 --- a/src/tests/intg/.config/screenrc +++ /dev/null @@ -1,23 +0,0 @@ -autodetach on -defscrollback 1024 -startup_message off -nethack on -vbell off -vbell_msg " -- Bell,Bell!! -- " -multiuser off -msgminwait 0 -msgwait 10 - -defutf8 on -defencoding utf8 - -hardstatus string '%{gk}[ %{G}%H %{g}][%= %{wk}%?%-Lw%?%{=b kR}(%{W}%n*%f %t%?(%u)%?%{=b kR})%{= kw}%?%+Lw%?%?%= %{g}]%{=b C}[ %d/%m %c ]%{W}' -hardstatus alwayslastline - -setenv LD_LIBRARY_PATH "$_LD_LIBRARY_PATH" -setenv LD_PRELOAD "$_LD_PRELOAD" - -screen -t / 0 sh -c 'cd $ROOT_DIR; exec "${SHELL:-sh}"' -screen -t /etc 1 sh -c 'cd $ROOT_DIR/etc; exec "${SHELL:-sh}"' -screen -t sssd_cache 3 sh -c 'cd $ROOT_DIR/var/lib/sss/db; exec "${SHELL:-sh}"' -screen -t sssd_log 2 sh -c 'cd $ROOT_DIR/var/log/sssd; exec "${SHELL:-sh}"' diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am deleted file mode 100644 index 734050a3153..00000000000 --- a/src/tests/intg/Makefile.am +++ /dev/null @@ -1,216 +0,0 @@ -AM_CFLAGS = $(my_CFLAGS) -dist_noinst_DATA = \ - __init__.py \ - config.py.m4 \ - util.py \ - sssd_nss.py \ - sssd_id.py \ - sssd_ldb.py \ - sssd_netgroup.py \ - sssd_passwd.py \ - sssd_group.py \ - ds.py \ - ds_openldap.py \ - ent.py \ - ldap_ent.py \ - util.py \ - files_ops.py \ - kdc.py \ - krb5utils.py \ - data/ad_data.ldif \ - data/ad_schema.ldif \ - data/cert_schema.ldif \ - data/ssh_schema.ldif \ - data/sudo_schema.ldif \ - test_pam_responder.py \ - conftest.py \ - sssd_hosts.py \ - sssd_nets.py \ - $(NULL) - -EXTRA_DIST = data/cwrap-dbus-system.conf.in - -dbussysconfdir = $(sysconfdir)/dbus-1 -dbusservicedir = $(datadir)/dbus-1/system-services - -if INTG_BUILD -lib_LTLIBRARIES = getsockopt_wrapper.la - -getsockopt_wrapper_la_SOURCES = \ - getsockopt_wrapper.c -getsockopt_wrapper_la_CFLAGS = \ - $(AM_CFLAGS) -getsockopt_wrapper_la_LIBADD = \ - $(LIBADD_DL) \ - $(NULL) -getsockopt_wrapper_la_LDFLAGS = \ - -avoid-version \ - -module - -bin_PROGRAMS = sss_netgroup_thread_test - -sss_netgroup_thread_test_SOURCES = \ - sss_netgroup_thread_test.c \ - $(NULL) -sss_netgroup_thread_test_CFLAGS = \ - $(AM_CFLAGS) \ - $(NULL) -sss_netgroup_thread_test_LDADD = \ - -lpthread \ - $(NULL) - -nsslib_LTLIBRARIES = libnss_call.la -libnss_call_la_SOURCES = \ - nss_call.c \ - $(NULL) -libnss_call_la_LDFLAGS = \ - -module \ - -version-info 2:0:0 \ - $(NULL) - -dist_dbussysconf_DATA = cwrap-dbus-system.conf - -install-data-hook: - $(MKDIR_P) $(DESTDIR)$(runstatedir)/dbus - $(MKDIR_P) $(DESTDIR)$(sysconfdir)/session.d - -endif - -if BUILD_KCM_RENEWAL -KCM_RENEW = "enabled" -else -KCM_RENEW = "disabled" -endif - -cwrap-dbus-system.conf: data/cwrap-dbus-system.conf.in Makefile - $(SED) -e "s!@runstatedir[@]!$(runstatedir)!" \ - -e "s!@dbusservicedir[@]!$(dbusservicedir)!" \ - $< > $@ - -config.py: config.py.m4 - m4 -D "prefix=\`$(prefix)'" \ - -D "sysconfdir=\`$(sysconfdir)'" \ - -D "nsslibdir=\`$(nsslibdir)'" \ - -D "dbpath=\`$(dbpath)'" \ - -D "pubconfpath=\`$(pubconfpath)'" \ - -D "pidpath=\`$(pidpath)'" \ - -D "logpath=\`$(logpath)'" \ - -D "mcpath=\`$(mcpath)'" \ - -D "secdbpath=\`$(secdbpath)'" \ - -D "libexecpath=\`$(libexecdir)'" \ - -D "runstatedir=\`$(runstatedir)'" \ - -D "abs_builddir=\`$(abs_builddir)'" \ - -D "session_recording_shell=\`$(session_recording_shell)'" \ - -D "py3execdir=\`$(py3execdir)'" \ - -D "python3dir=\`$(python3dir)'" \ - $< > $@ - -root: - : "Create directory for emulated root's D-Bus cookies." - : "See http://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms" - $(MKDIR_P) -m 0700 root/.dbus-keyrings - -passwd: root - echo "root:x:0:0:root:$(abs_builddir)/root:/bin/bash" > $@ - -group: - echo "root:x:0:" > $@ - -PAM_SERVICE_DIR=pam_service_dir -pam_sss_service: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth required $(DESTDIR)$(pammoddir)/pam_sss.so" > $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -pam_sss_alt_service: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth required $(DESTDIR)$(pammoddir)/pam_sss.so" > $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -pam_sss_sc_required: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth required $(DESTDIR)$(pammoddir)/pam_sss.so require_cert_auth retry=1" > $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -pam_sss_try_sc: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth required $(DESTDIR)$(pammoddir)/pam_sss.so try_cert_auth" > $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -pam_sss_allow_missing_name: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth required $(DESTDIR)$(pammoddir)/pam_sss.so allow_missing_name" > $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -pam_sss_domains: - $(MKDIR_P) $(PAM_SERVICE_DIR) - echo "auth sufficient $(DESTDIR)$(pammoddir)/pam_sss.so forward_pass domains=wrong.dom1" > $(PAM_SERVICE_DIR)/$@ - echo "auth sufficient $(DESTDIR)$(pammoddir)/pam_sss.so forward_pass domains=wrong.dom2" >> $(PAM_SERVICE_DIR)/$@ - echo "auth sufficient $(DESTDIR)$(pammoddir)/pam_sss.so forward_pass domains=wrong.dom3" >> $(PAM_SERVICE_DIR)/$@ - echo "auth sufficient $(DESTDIR)$(pammoddir)/pam_sss.so forward_pass domains=krb5_auth" >> $(PAM_SERVICE_DIR)/$@ - echo "auth required pam_deny.so" >> $(PAM_SERVICE_DIR)/$@ - echo "account required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "password required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - echo "session required $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@ - -CLEANFILES=config.py config.pyc passwd group - -clean-local: - rm -Rf root - rm -f $(builddir)/cwrap-dbus-system.conf - -PAM_CERT_DB_PATH="$(abs_builddir)/../test_CA/SSSD_test_CA.pem" -SOFTHSM2_CONF="$(abs_builddir)/../test_CA/softhsm2_one.conf" -SOFTHSM2_TWO_CONF="$(abs_builddir)/../test_CA/softhsm2_two.conf" - -intgcheck-installed: config.py passwd group pam_sss_service pam_sss_alt_service pam_sss_sc_required pam_sss_try_sc pam_sss_allow_missing_name pam_sss_domains sss_netgroup_thread_test - pipepath="$(DESTDIR)$(pipepath)"; \ - if test $${#pipepath} -gt 80; then \ - echo "error: Pipe directory path too long," \ - "D-Bus won't be able to open sockets" >&2; \ - exit 1; \ - fi - set -e; \ - cd "$(abs_srcdir)"; \ - nss_wrapper=$$(pkg-config --libs nss_wrapper); \ - uid_wrapper=$$(pkg-config --libs uid_wrapper); \ - unset HOME; \ - PATH="$$(dirname -- $(SLAPD)):$$PATH" \ - PATH="$(DESTDIR)$(sbindir):$(DESTDIR)$(bindir):$$PATH" \ - PATH="$$PATH:$(abs_builddir):$(abs_srcdir)" \ - LANG=C \ - PYTHONPATH="$(abs_builddir):$(abs_srcdir)" \ - LDB_MODULES_PATH="$(DESTDIR)$(ldblibdir)" \ - NON_WRAPPED_UID=$$(id -u) \ - LD_PRELOAD="$(libdir)/getsockopt_wrapper.so:$$nss_wrapper:$$uid_wrapper" \ - LD_LIBRARY_PATH="$$LD_LIBRARY_PATH:$(DESTDIR)$(nsslibdir)" \ - NSS_WRAPPER_PASSWD="$(abs_builddir)/passwd" \ - NSS_WRAPPER_GROUP="$(abs_builddir)/group" \ - NSS_WRAPPER_MODULE_SO_PATH="$(DESTDIR)$(nsslibdir)/libnss_sss.so.2" \ - NSS_WRAPPER_MODULE_FN_PREFIX="sss" \ - UID_WRAPPER=1 \ - UID_WRAPPER_ROOT=1 \ - PAM_WRAPPER=0 \ - PAM_WRAPPER_SERVICE_DIR="$(abs_builddir)/$(PAM_SERVICE_DIR)" \ - PAM_WRAPPER_PATH=$$(pkg-config --libs pam_wrapper) \ - PAM_CERT_DB_PATH=$(PAM_CERT_DB_PATH) \ - ABS_SRCDIR=$(abs_srcdir) \ - SOFTHSM2_CONF=$(SOFTHSM2_CONF) \ - SOFTHSM2_TWO_CONF=$(SOFTHSM2_TWO_CONF) \ - KCM_RENEW=$(KCM_RENEW) \ - DBUS_SOCK_DIR="$(DESTDIR)$(runstatedir)/dbus/" \ - DBUS_SESSION_BUS_ADDRESS="unix:path=$$DBUS_SOCK_DIR/fake_socket" \ - DBUS_SYSTEM_BUS_ADDRESS="unix:path=$$DBUS_SOCK_DIR/system_bus_socket" \ - DBUS_SYSTEM_BUS_DEFAULT_ADDRESS="$$DBUS_SYSTEM_BUS_ADDRESS" \ - fakeroot $(PYTHON_EXEC_INTG) -m pytest -v -r a --tb=native $(INTGCHECK_PYTEST_ARGS) . - rm -f $(DESTDIR)$(logpath)/* diff --git a/src/tests/intg/__init__.py b/src/tests/intg/__init__.py deleted file mode 100644 index 882a963146b..00000000000 --- a/src/tests/intg/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -import sys -import config - -LOCAL_PYEXECDIR = config.PY3EXECDIR -LOCAL_PYDIR = config.PY3DIR - -for path in [LOCAL_PYEXECDIR, LOCAL_PYDIR]: - if path not in sys.path: - sys.path.insert(0, path) diff --git a/src/tests/intg/config.py.m4 b/src/tests/intg/config.py.m4 deleted file mode 100644 index d2e0ffeb437..00000000000 --- a/src/tests/intg/config.py.m4 +++ /dev/null @@ -1,23 +0,0 @@ -""" -Build configuration variables. -""" - -PREFIX = "prefix" -SYSCONFDIR = "sysconfdir" -NSS_MODULE_DIR = "nsslibdir" -SSSDCONFDIR = SYSCONFDIR + "/sssd" -CONF_PATH = SSSDCONFDIR + "/sssd.conf" -CONF_SNIPPET_PATH = SSSDCONFDIR + "/conf.d/01.conf" -DB_PATH = "dbpath" -PID_PATH = "pidpath" -PUBCONF_PATH = "pubconfpath" -PIDFILE_PATH = PID_PATH + "/sssd.pid" -LOG_PATH = "logpath" -MCACHE_PATH = "mcpath" -SECDB_PATH = "secdbpath" -LIBEXEC_PATH = "libexecpath" -RUNSTATEDIR = "runstatedir" -ABS_BUILDDIR = "abs_builddir" -SESSION_RECORDING_SHELL = "session_recording_shell" -PY3EXECDIR = "py3execdir" -PY3DIR = "python3dir" diff --git a/src/tests/intg/conftest.py b/src/tests/intg/conftest.py deleted file mode 100644 index f07a410940e..00000000000 --- a/src/tests/intg/conftest.py +++ /dev/null @@ -1 +0,0 @@ -from files_ops import passwd_ops_setup, group_ops_setup # noqa diff --git a/src/tests/intg/data/ad_data.ldif b/src/tests/intg/data/ad_data.ldif deleted file mode 100644 index 0d2ec444c33..00000000000 --- a/src/tests/intg/data/ad_data.ldif +++ /dev/null @@ -1,815 +0,0 @@ -dn: cn=Users,dc=example,dc=com -objectClass: top -objectClass: container -cn: Users -description: Default container for upgraded user accounts -distinguishedName: cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923233930.0Z -whenChanged: 20140923233930.0Z -uSNCreated: 5696 -uSNChanged: 5696 -showInAdvancedViewOnly: FALSE -name: Users -objectGUID:: 6Gd2SrsmeEiT3Hmh/5hTqw== -systemFlags: -1946157056 -objectCategory: cn=Container,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=CHILD1$,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: CHILD1$ -distinguishedName: cn=CHILD1$,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923224256.0Z -whenChanged: 20160423221800.0Z -uSNCreated: 20732 -uSNChanged: 2181674 -name: CHILD1$ -objectGUID:: ACE60RcYu0iZv4CMYPK+eg== -userAccountControl: 2080 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 131059234804699243 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EUAQAAA== -accountExpires: 9223372036854775807 -logonCount: 0 -sAMAccountName: CHILD1$ -sAMAccountType: 805306370 -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=krbtgt,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: krbtgt -description: Key Distribution Center Service Account -distinguishedName: cn=krbtgt,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12324 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12723 -showInAdvancedViewOnly: TRUE -name: krbtgt -objectGUID:: F/Yrx8X81ESM6t14mMxcxA== -userAccountControl: 514 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 130559892182968750 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8E9gEAAA== -adminCount: 1 -accountExpires: 9223372036854775807 -logonCount: 0 -sAMAccountName: krbtgt -sAMAccountType: 805306368 -servicePrincipalName: kadmin/changepw -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Domain Computers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Domain Computers -description: All workstations and servers joined to the domain -distinguishedName: cn=Domain Computers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12330 -uSNChanged: 12332 -name: Domain Computers -objectGUID:: 09VIVs7CDkOMTnLtMkZMUA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EAwIAAA== -sAMAccountName: Domain Computers -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Domain Controllers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Domain Controllers -description: All domain controllers in the domain -distinguishedName: cn=Domain Controllers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12333 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12726 -name: Domain Controllers -objectGUID:: a6OG+FLmnECf3fAe0a8o6w== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EBAIAAA== -adminCount: 1 -sAMAccountName: Domain Controllers -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Schema Admins,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Schema Admins -description: Designated administrators of the schema -member: cn=Administrator,cn=Users,dc=example,dc=com -distinguishedName: cn=Schema Admins,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12336 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12708 -name: Schema Admins -objectGUID:: ONs7cn0OF0uEip0yMnLv2Q== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EBgIAAA== -adminCount: 1 -sAMAccountName: Schema Admins -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Enterprise Admins,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Enterprise Admins -description: Designated administrators of the enterprise -member: cn=Administrator,cn=Users,dc=example,dc=com -distinguishedName: cn=Enterprise Admins,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12339 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -memberOf: cn=Administrators,cn=Builtin,dc=example,dc=com -uSNChanged: 12712 -name: Enterprise Admins -objectGUID:: rD6jEoiL8U6huv7c/OJPwg== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EBwIAAA== -adminCount: 1 -sAMAccountName: Enterprise Admins -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Cert Publishers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Cert Publishers -description: Members of this group are permitted to publish certificates to the directory -member: cn=PLUTO,OU=Domain Controllers,dc=example,dc=com -distinguishedName: cn=Cert Publishers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923191508.0Z -uSNCreated: 12342 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12749 -name: Cert Publishers -objectGUID:: zWTUMdl6tEWA1J0QnPLkRQ== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EBQIAAA== -sAMAccountName: Cert Publishers -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Domain Admins,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Domain Admins -description: Designated administrators of the domain -member: cn=Administrator,cn=Users,dc=example,dc=com -distinguishedName: cn=Domain Admins,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12345 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -memberOf: cn=Administrators,cn=Builtin,dc=example,dc=com -uSNChanged: 12711 -name: Domain Admins -objectGUID:: YxI+YLrC3UeNNsmMnXGTlg== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EAAIAAA== -adminCount: 1 -sAMAccountName: Domain Admins -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Domain Users,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Domain Users -description: All domain users -distinguishedName: cn=Domain Users,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20150202222731.0Z -uSNCreated: 12348 -memberOf: cn=Users,cn=Builtin,dc=example,dc=com -uSNChanged: 213433 -name: Domain Users -objectGUID:: JRHvlJXoU0+LOYXs3vESow== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EAQIAAA== -sAMAccountName: Domain Users -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z -msSFU30NisDomain: example -gidNumber: 100000 - -dn: cn=Domain Guests,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Domain Guests -description: All domain guests -distinguishedName: cn=Domain Guests,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12351 -memberOf: cn=Guests,cn=Builtin,dc=example,dc=com -uSNChanged: 12353 -name: Domain Guests -objectGUID:: Rx/t/vuPwUGOMoprY1KFog== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EAgIAAA== -sAMAccountName: Domain Guests -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Group Policy Creator Owners,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Group Policy Creator Owners -description: Members in this group can modify group policy for the domain -member: cn=Administrator,cn=Users,dc=example,dc=com -distinguishedName: cn=Group Policy Creator Owners,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12354 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12391 -name: Group Policy Creator Owners -objectGUID:: V3HfwcWfZ0yv1br3tRP6bA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ECAIAAA== -sAMAccountName: Group Policy Creator Owners -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=RAS and IAS Servers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: RAS and IAS Servers -description: Servers in this group can access remote access properties of users -distinguishedName: cn=RAS and IAS Servers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12357 -uSNChanged: 12359 -name: RAS and IAS Servers -objectGUID:: PHyDebZK7UKVG9HG+mT8ng== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EKQIAAA== -sAMAccountName: RAS and IAS Servers -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Allowed ROdc Password Replication Group,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Allowed ROdc Password Replication Group -description: Members in this group can have their passwords replicated to all read-only domain controllers in the domain -distinguishedName: cn=Allowed ROdc Password Replication Group,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12402 -uSNChanged: 12404 -name: Allowed ROdc Password Replication Group -objectGUID:: pKN3Txn0SUenHm8Z58ZQYA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EOwIAAA== -sAMAccountName: Allowed ROdc Password Replication Group -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Denied ROdc Password Replication Group -description: Members in this group cannot have their passwords replicated to any read-only domain controllers in the domain -member: cn=Read-only Domain Controllers,cn=Users,dc=example,dc=com -member: cn=Group Policy Creator Owners,cn=Users,dc=example,dc=com -member: cn=Domain Admins,cn=Users,dc=example,dc=com -member: cn=Cert Publishers,cn=Users,dc=example,dc=com -member: cn=Enterprise Admins,cn=Users,dc=example,dc=com -member: cn=Schema Admins,cn=Users,dc=example,dc=com -member: cn=Domain Controllers,cn=Users,dc=example,dc=com -member: cn=krbtgt,cn=Users,dc=example,dc=com -distinguishedName: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12405 -uSNChanged: 12433 -name: Denied ROdc Password Replication Group -objectGUID:: OoOtLxLbXUSdCGKeGvzc7Q== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EPAIAAA== -sAMAccountName: Denied ROdc Password Replication Group -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Read-only Domain Controllers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Read-only Domain Controllers -description: Members of this group are Read-Only Domain Controllers in the domain -distinguishedName: cn=Read-only Domain Controllers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923185530.0Z -uSNCreated: 12419 -memberOf: cn=Denied ROdc Password Replication Group,cn=Users,dc=example,dc=com -uSNChanged: 12725 -name: Read-only Domain Controllers -objectGUID:: GoeeiCJ87UqBN3C9MhqQ3w== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ECQIAAA== -adminCount: 1 -sAMAccountName: Read-only Domain Controllers -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Enterprise Read-only Domain Controllers,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: Enterprise Read-only Domain Controllers -description: Members of this group are Read-Only Domain Controllers in the enterprise -distinguishedName: cn=Enterprise Read-only Domain Controllers,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234018.0Z -whenChanged: 20140923234018.0Z -uSNCreated: 12429 -uSNChanged: 12431 -name: Enterprise Read-only Domain Controllers -objectGUID:: qHRH+tAgFUy7660VnrFpTA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8E8gEAAA== -sAMAccountName: Enterprise Read-only Domain Controllers -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=DnsAdmins,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: DnsAdmins -description: DNS Administrators Group -distinguishedName: cn=DnsAdmins,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234058.0Z -whenChanged: 20140923234058.0Z -uSNCreated: 12459 -uSNChanged: 12461 -name: DnsAdmins -objectGUID:: w4cyv6dWNEGQao3mL5RpTA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ETQQAAA== -sAMAccountName: DnsAdmins -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=DnsUpdateProxy,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: DnsUpdateProxy -description: DNS clients who are permitted to perform dynamic updates on behalf of some other clients (such as DHCP servers). -distinguishedName: cn=DnsUpdateProxy,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923234058.0Z -whenChanged: 20140923234058.0Z -uSNCreated: 12464 -uSNChanged: 12464 -name: DnsUpdateProxy -objectGUID:: LMyHGT2RuEG+IGrGL80qMg== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ETgQAAA== -sAMAccountName: DnsUpdateProxy -sAMAccountType: 268435456 -groupType: -2147483646 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=user1_dom1-19661,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: user1_dom1-19661 -givenName: user1_dom1-19661 -distinguishedName: cn=user1_dom1-19661,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517121016.0Z -whenChanged: 20160517121017.0Z -displayName: user1_dom1-19661 -uSNCreated: 2223663 -memberOf: cn=group1_dom1-19661,cn=Users,dc=example,dc=com -uSNChanged: 2223667 -name: user1_dom1-19661 -objectGUID:: qyJVkvQrRUyig6rpPsXNUw== -userAccountControl: 512 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 131079606172284326 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EeUMBAA== -accountExpires: 0 -logonCount: 0 -sAMAccountName: user1_dom1-19661 -sAMAccountType: 805306368 -userPrincipalName: user1_dom1-19661@example.com -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z -uid: user1_dom1-19661 -msSFU30Name: user1_dom1-19661 - -dn: cn=group1_dom1-19661,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: group1_dom1-19661 -member: cn=user1_dom1-19661,cn=Users,dc=example,dc=com -distinguishedName: cn=group1_dom1-19661,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517121017.0Z -whenChanged: 20160517121018.0Z -uSNCreated: 2223669 -uSNChanged: 2223673 -name: group1_dom1-19661 -objectGUID:: 8BulXIrOCkmlc6HgV+PAvw== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EekMBAA== -sAMAccountName: group1_dom1-19661 -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=user2_dom1-19661,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: user2_dom1-19661 -givenName: user2_dom1-19661 -distinguishedName: cn=user2_dom1-19661,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517121018.0Z -whenChanged: 20160517121019.0Z -displayName: user2_dom1-19661 -uSNCreated: 2223676 -memberOf: cn=group2_dom2-19661,cn=Users,dc=example_tree,dc=com -uSNChanged: 2223680 -name: user2_dom1-19661 -objectGUID:: YSnhUKGpFUC+SqxUvvXugA== -userAccountControl: 512 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 131079606188221826 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8Ee0MBAA== -accountExpires: 0 -logonCount: 0 -sAMAccountName: user2_dom1-19661 -sAMAccountType: 805306368 -userPrincipalName: user2_dom1-19661@example.com -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z -uid: user2_dom1-19661 -msSFU30Name: user2_dom1-19661 - -dn: cn=group3_dom1-19661,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: group3_dom1-19661 -member: cn=user3_dom3-19661,cn=Users,dc=child1,dc=example,dc=com -distinguishedName: cn=group3_dom1-19661,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517121145.0Z -whenChanged: 20160517121146.0Z -uSNCreated: 2223750 -uSNChanged: 2223754 -name: group3_dom1-19661 -objectGUID:: 7bIPzON/JEKmGsVlRmhU3g== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EfEMBAA== -sAMAccountName: group3_dom1-19661 -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=TelnetClients,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: TelnetClients -distinguishedName: cn=TelnetClients,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923184913.0Z -whenChanged: 20140923184913.0Z -uSNCreated: 12704 -uSNChanged: 12706 -name: TelnetClients -objectGUID:: pen22ZTevU2Rb+8+krexQA== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ETwQAAA== -sAMAccountName: TelnetClients -sAMAccountType: 536870912 -groupType: -2147483644 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=SSSDAD_TREE$,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: SSSDAD_TREE$ -distinguishedName: cn=SSSDAD_TREE$,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20141002150546.0Z -whenChanged: 20160504032042.0Z -uSNCreated: 31148 -uSNChanged: 2196300 -name: SSSDAD_TREE$ -objectGUID:: SYm5qEjtH0SySg5aQw6XNA== -userAccountControl: 2080 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 131068056421414345 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8EUQQAAA== -accountExpires: 9223372036854775807 -logonCount: 0 -sAMAccountName: SSSDAD_TREE$ -sAMAccountType: 805306370 -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z - -dn: cn=user1_dom1-17775,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: user1_dom1-17775 -givenName: user1_dom1-17775 -distinguishedName: cn=user1_dom1-17775,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517104141.0Z -whenChanged: 20160517105245.0Z -displayName: user1_dom1-17775 -uSNCreated: 2220148 -memberOf: cn=group1_dom1-17775,cn=Users,dc=example,dc=com -uSNChanged: 2220869 -name: user1_dom1-17775 -objectGUID:: dCwgefPZTEaA5Gq7fuH9eQ== -userAccountControl: 512 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 131079562057827406 -pwdLastSet: 131079557906733656 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ESUMBAA== -accountExpires: 0 -logonCount: 46 -sAMAccountName: user1_dom1-17775 -sAMAccountType: 805306368 -userPrincipalName: user1_dom1-17775@example.com -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z -lastLogonTimestamp: 131079557817046156 -uid: user1_dom1-17775 -msSFU30Name: user1_dom1-17775 - -dn: cn=group1_dom1-17775,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: group1_dom1-17775 -member: cn=user1_dom1-17775,cn=Users,dc=example,dc=com -distinguishedName: cn=group1_dom1-17775,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517104143.0Z -whenChanged: 20160517104143.0Z -uSNCreated: 2220154 -uSNChanged: 2220158 -name: group1_dom1-17775 -objectGUID:: UfJpBGL6gE2d5hqzqNlRGQ== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ESkMBAA== -sAMAccountName: group1_dom1-17775 -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=user2_dom1-17775,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: user2_dom1-17775 -givenName: user2_dom1-17775 -distinguishedName: cn=user2_dom1-17775,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517104143.0Z -whenChanged: 20160517105302.0Z -displayName: user2_dom1-17775 -uSNCreated: 2220161 -memberOf: cn=group2_dom2-17775,cn=Users,dc=example_tree,dc=com -uSNChanged: 2220886 -name: user2_dom1-17775 -objectGUID:: r22lHyI8Y0eMVzeTH2dzoQ== -userAccountControl: 512 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 131079561237671156 -pwdLastSet: 131079553041264906 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ES0MBAA== -accountExpires: 0 -logonCount: 14 -sAMAccountName: user2_dom1-17775 -sAMAccountType: 805306368 -userPrincipalName: user2_dom1-17775@example.com -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z -lastLogonTimestamp: 131079559824702406 -uid: user2_dom1-17775 -msSFU30Name: user2_dom1-17775 - -dn: cn=group3_dom1-17775,cn=Users,dc=example,dc=com -objectClass: top -objectClass: group -cn: group3_dom1-17775 -member: cn=user3_dom3-17775,cn=Users,dc=child1,dc=example,dc=com -distinguishedName: cn=group3_dom1-17775,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20160517104312.0Z -whenChanged: 20160517104312.0Z -uSNCreated: 2220239 -uSNChanged: 2220243 -name: group3_dom1-17775 -objectGUID:: jkkwGJCVb0K4OCjHZVDmdQ== -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8ETEMBAA== -sAMAccountName: group3_dom1-17775 -sAMAccountType: 268435456 -groupType: -2147483640 -objectCategory: cn=Group,cn=Schema,cn=Configuration,dc=example,dc=com -dSCorePropagationData: 16010101000000.0Z - -dn: cn=Administrator,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: Administrator -description: Built-in account for administering the computer/domain -distinguishedName: cn=Administrator,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923233931.0Z -whenChanged: 20160510092815.0Z -uSNCreated: 8196 -memberOf: cn=Group Policy Creator Owners,cn=Users,dc=example,dc=com -memberOf: cn=Domain Admins,cn=Users,dc=example,dc=com -memberOf: cn=Enterprise Admins,cn=Users,dc=example,dc=com -memberOf: cn=Schema Admins,cn=Users,dc=example,dc=com -memberOf: cn=Administrators,cn=Builtin,dc=example,dc=com -uSNChanged: 2204950 -name: Administrator -objectGUID:: QeHMqu/QPEyjJ+KQEqcKFw== -userAccountControl: 66048 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 131074379403763791 -lastLogoff: 0 -lastLogon: 131079606125409326 -logonHours:: //////////////////////////// -pwdLastSet: 130553133586093750 -primaryGroupID: 513 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8E9AEAAA== -adminCount: 1 -accountExpires: 0 -logonCount: 7477 -sAMAccountName: Administrator -sAMAccountType: 805306368 -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 20140923185530.0Z -dSCorePropagationData: 16010101000000.0Z -lastLogonTimestamp: 131073460951421705 - -dn: cn=Guest,cn=Users,dc=example,dc=com -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: Guest -description: Built-in account for guest access to the computer/domain -distinguishedName: cn=Guest,cn=Users,dc=example,dc=com -instanceType: 4 -whenCreated: 20140923233931.0Z -whenChanged: 20140923233931.0Z -uSNCreated: 8197 -memberOf: cn=Guests,cn=Builtin,dc=example,dc=com -uSNChanged: 8197 -name: Guest -objectGUID:: pZVy9Q6Eh02XuYDEXDE9Cg== -userAccountControl: 66082 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 0 -primaryGroupID: 514 -objectSid:: AQUAAAAAAAUVAAAADcfLTVzC66zo0l8E9QEAAA== -accountExpires: 9223372036854775807 -logonCount: 0 -sAMAccountName: Guest -sAMAccountType: 805306368 -objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=example,dc=com -isCriticalSystemObject: TRUE -dSCorePropagationData: 16010101000000.0Z diff --git a/src/tests/intg/data/ad_schema.ldif b/src/tests/intg/data/ad_schema.ldif deleted file mode 100644 index 6ae533a55fa..00000000000 --- a/src/tests/intg/data/ad_schema.ldif +++ /dev/null @@ -1,42 +0,0 @@ -dn: cn=ad,cn=schema,cn=config -objectClass: olcSchemaConfig -cn: ad -structuralObjectClass: olcSchemaConfig -olcAttributeTypes: {0}( 1.2.840.113556.1.4.750 NAME 'groupType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {1}( 1.2.840.113556.1.4.221 NAME 'sAMAccountName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {2}( 1.2.840.113556.1.4.35 NAME 'employeeID' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {3}( 1.2.840.113556.1.2.1 NAME 'instanceType' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {4}( 1.2.840.113556.1.4.782 NAME 'objectCategory' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {5}( 1.2.840.113556.1.2.2 NAME 'whenCreated' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {6}( 1.2.840.113556.1.2.3 NAME 'whenChanged' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {7}( 1.2.840.113556.1.2.19 NAME 'uSNCreated' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {8}( 1.2.840.113556.1.2.120 NAME 'uSNChanged' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {9}( 1.2.840.113556.1.2.169 NAME 'showInAdvancedViewOnly' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) -olcAttributeTypes: {10}( 1.2.840.113556.1.4.2 NAME 'objectGUID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE) -olcAttributeTypes: {11}( 1.2.840.113556.1.4.375 NAME 'systemFlags' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {12}( 1.2.840.113556.1.4.868 NAME 'isCriticalSystemObject' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) -olcAttributeTypes: {13}( 1.2.840.113556.1.4.1357 NAME 'dSCorePropagationData' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -olcAttributeTypes: {14}( 1.2.840.113556.1.4.8 NAME 'userAccountControl' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {15}( 1.2.840.113556.1.4.12 NAME 'badPwdCount' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {16}( 1.2.840.113556.1.4.146 NAME 'objectSid' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE) -olcAttributeTypes: {17}( 1.2.840.113556.1.2.102 NAME 'memberOf' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) -olcAttributeTypes: {18}( 1.2.840.113556.1.4.16 NAME 'codePage' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {19}( 1.2.840.113556.1.4.302 NAME 'sAMAccountType' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {20}( 1.2.840.113556.1.4.150 NAME 'adminCount' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {21}( 1.2.840.113556.1.4.25 NAME 'countryCode' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {22}( 1.2.840.113556.1.4.49 NAME 'badPasswordTime' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {23}( 1.2.840.113556.1.6.18.1.339 NAME 'msSFU30NisDomain' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {24}( 1.2.840.113556.1.4.51 NAME 'lastLogoff' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {25}( 1.2.840.113556.1.4.52 NAME 'lastLogon' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {26}( 1.2.840.113556.1.4.96 NAME 'pwdLastSet' EQUALITY numericStringMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.36' SINGLE-VALUE ) -olcAttributeTypes: {27}( 1.2.840.113556.1.4.64 NAME 'logonHours' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE) -olcAttributeTypes: {28}( 1.2.840.113556.1.4.98 NAME 'primaryGroupID' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {29}( 1.2.840.113556.1.4.159 NAME 'accountExpires' EQUALITY numericStringMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.36' SINGLE-VALUE ) -olcAttributeTypes: {30}( 1.2.840.113556.1.4.169 NAME 'logonCount' EQUALITY integerMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -olcAttributeTypes: {31}( 1.2.840.113556.1.4.771 NAME 'servicePrincipalName' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {31}( 1.2.840.113556.1.4.656 NAME 'userPrincipalName' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {32}( 1.2.840.113556.1.6.18.1.309 NAME 'msSFU30Name' EQUALITY caseExactMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -olcAttributeTypes: {33}( 1.2.840.113556.1.4.1696 NAME 'lastLogonTimestamp' EQUALITY numericStringMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.36' SINGLE-VALUE ) -olcObjectClasses: {1}( 1.2.840.113556.1.5.9 NAME 'user' DESC 'a user' SUP organizationalPerson STRUCTURAL MUST ( cn $ objectSid $ instanceType $ sAMAccountName $ objectCategory ) MAY ( userPassword $ description $ distinguishedName $ name $ userAccountControl $ badPwdCount $ memberOf $ codePage $ sAMAccountType $ adminCount $ countryCode $ dSCorePropagationData $ whenCreated $ whenChanged $ uSNCreated $ uSNChanged $ badPasswordTime $ msSFU30NisDomain $ lastLogoff $ lastLogon $ objectGUID $ pwdLastSet $ logonCount $ logonHours $ primaryGroupID $ accountExpires $ isCriticalSystemObject $ servicePrincipalName $ userPrincipalName $ msSFU30Name $ lastLogonTimestamp $ showInAdvancedViewOnly $ givenName $ displayName $ uid ) ) -olcObjectClasses: {2}( 1.2.840.113556.1.5.8 NAME 'group' DESC 'a group of users' SUP top STRUCTURAL MUST ( groupType $ cn $ objectSid $ instanceType $ sAMAccountName $ objectCategory ) MAY ( member $ description $ distinguishedName $ name $ memberOf $ sAMAccountType $ adminCount $ dSCorePropagationData $ whenCreated $ whenChanged $ uSNCreated $ uSNChanged $ msSFU30NisDomain $ objectGUID $ isCriticalSystemObject $ gidNumber ) ) -olcObjectClasses: {3}( 1.2.840.113556.1.3.23 NAME 'container' DESC 'asdasd' SUP top STRUCTURAL MUST ( cn $ instanceType $ objectCategory ) MAY ( whenCreated $ whenChanged $ uSNCreated $ uSNChanged $ showInAdvancedViewOnly $ objectGUID $ systemFlags $ isCriticalSystemObject $ dSCorePropagationData $ description $ distinguishedName $ name ) ) diff --git a/src/tests/intg/data/cert_schema.ldif b/src/tests/intg/data/cert_schema.ldif deleted file mode 100644 index 0003c662326..00000000000 --- a/src/tests/intg/data/cert_schema.ldif +++ /dev/null @@ -1,11 +0,0 @@ -dn: cn=cert,cn=schema,cn=config -objectClass: olcSchemaConfig -cn: cert -olcAttributeTypes: ( 1.2.840.113556.1.4.645 NAME 'userCert' - DESC 'MANDATORY: X.509 user certificate' - EQUALITY octetStringMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -olcObjectClasses: ( 1.2.840.113556.1.3.46 NAME 'mailRecipient' SUP top AUXILIARY - DESC 'MANDATORY: X.509 objectclass' - MAY ( userCert $ uid ) - ) diff --git a/src/tests/intg/data/cwrap-dbus-system.conf.in b/src/tests/intg/data/cwrap-dbus-system.conf.in deleted file mode 100644 index 7369054e717..00000000000 --- a/src/tests/intg/data/cwrap-dbus-system.conf.in +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - system - - - - - - - - - - - @dbusservicedir@ - - - - @runstatedir@/dbus/messagebus.pid - - - EXTERNAL - - - unix:path=@runstatedir@/dbus/system_bus_socket - - - - - - - - - - - system.d - - - - - /etc/dbus-1/system-local.conf - - contexts/dbus_contexts - - - - - - - diff --git a/src/tests/intg/data/ssh_schema.ldif b/src/tests/intg/data/ssh_schema.ldif deleted file mode 100644 index efe05706b9d..00000000000 --- a/src/tests/intg/data/ssh_schema.ldif +++ /dev/null @@ -1,11 +0,0 @@ -dn: cn=openssh-lpk,cn=schema,cn=config -objectClass: olcSchemaConfig -cn: openssh-lpk -olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' - DESC 'MANDATORY: OpenSSH Public key' - EQUALITY octetStringMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY - DESC 'MANDATORY: OpenSSH LPK objectclass' - MAY ( sshPublicKey $ uid ) - ) diff --git a/src/tests/intg/data/sudo_schema.ldif b/src/tests/intg/data/sudo_schema.ldif deleted file mode 100644 index 8c1f4e3ef76..00000000000 --- a/src/tests/intg/data/sudo_schema.ldif +++ /dev/null @@ -1,11 +0,0 @@ -dn: cn=sudo,cn=schema,cn=config -objectClass: olcSchemaConfig -cn: sudo -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ description ) ) diff --git a/src/tests/intg/ds.py b/src/tests/intg/ds.py deleted file mode 100644 index f4631b28fd0..00000000000 --- a/src/tests/intg/ds.py +++ /dev/null @@ -1,59 +0,0 @@ -# -# Abstract directory server instance class -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Nikolai Kondrashov -# -# 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 . -# - -import ldap - - -class DS(object): - """Abstract directory server instance.""" - - def __init__(self, dir, port, base_dn, admin_rdn, admin_pw): - """ - Initialize the instance. - - Arguments: - dir Path to the root of the filesystem hierarchy to create - the instance under. - port TCP port on localhost to bind the server to. - base_dn Base DN. - admin_rdn Administrator DN, relative to BASE_DN. - admin_pw Administrator password. - """ - self.dir = dir - self.port = port - self.ldap_url = "ldap://localhost:" + str(self.port) - self.base_dn = base_dn - self.admin_rdn = admin_rdn - self.admin_dn = admin_rdn + "," + base_dn - self.admin_pw = admin_pw - - def setup(self): - """Setup the instance""" - raise NotImplementedError() - - def teardown(self): - """Teardown the instance""" - raise NotImplementedError() - - def bind(self): - """Connect to the server and bind as admin, return connection.""" - conn = ldap.initialize(self.ldap_url) - conn.simple_bind_s(self.admin_dn, self.admin_pw) - return conn diff --git a/src/tests/intg/ds_openldap.py b/src/tests/intg/ds_openldap.py deleted file mode 100644 index 158134383aa..00000000000 --- a/src/tests/intg/ds_openldap.py +++ /dev/null @@ -1,398 +0,0 @@ -# -# OpenLDAP directory server instance class -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Nikolai Kondrashov -# Author: Lukas Slebodnik -# -# 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 . -# - -import hashlib -import base64 -import time -import ldap -import os -import errno -import signal -import shutil -import subprocess -from util import unindent, first_dir -from ds import DS - -try: - from urllib import quote as url_quote -except ImportError: - from urllib.parse import quote as url_quote - - -def hash_password(password): - """Generate userPassword value for a password.""" - salt = os.urandom(4) - hash = hashlib.sha1(password.encode('utf-8')) - hash.update(salt) - hash_base64 = base64.standard_b64encode(hash.digest() + salt) - return "{SSHA}" + hash_base64.decode('utf-8') - - -class DSOpenLDAP(DS): - """OpenLDAP directory server instance.""" - - def __init__(self, dir, port, base_dn, admin_rdn, admin_pw): - """ - Initialize the instance. - - Arguments: - dir Path to the root of the filesystem hierarchy to create - the instance under. - port TCP port on localhost to bind the server to. - base_dn Base DN. - admin_rdn Administrator DN, relative to BASE_DN. - admin_pw Administrator password. - """ - DS.__init__(self, dir, port, base_dn, admin_rdn, admin_pw) - self.run_dir = self.dir + "/var/run/ldap" - self.pid_path = self.run_dir + "/slapd.pid" - self.conf_dir = self.dir + "/etc/ldap" - self.conf_slapd_d_dir = self.conf_dir + "/slapd.d" - self.data_dir = self.dir + "/var/lib/ldap" - - def _setup_config(self): - """Setup the instance initial configuration.""" - dist_lib_dir = first_dir("/usr/lib64/openldap", - "/usr/lib/openldap", - "/usr/lib/ldap") - dist_conf_dir = first_dir("/etc/ldap", - "/etc/openldap") - args_file = self.run_dir + "/slapd.args" - admin_pw_hash = hash_password(self.admin_pw) - uid = os.geteuid() - gid = os.getegid() - - # - # Add configuration - # - config = unindent(""" - dn: cn=config - objectClass: olcGlobal - cn: config - olcPidFile: {self.pid_path} - olcArgsFile: {args_file} - # Read slapd.conf(5) for possible values - olcLogLevel: none - - # Frontend settings - dn: olcDatabase={{-1}}frontend,cn=config - objectClass: olcDatabaseConfig - objectClass: olcFrontendConfig - olcDatabase: {{-1}}frontend - # The maximum number of entries that is returned for - # a search operation - olcSizeLimit: 500 - # Allow unlimited access to local connection from the local root - olcAccess: {{0}}to * by dn.exact=gidNumber={gid}+uidNumber={uid}, - cn=peercred,cn=external,cn=auth manage by * break - # Allow unauthenticated read access for schema and - # base DN autodiscovery - olcAccess: {{1}}to dn.exact="" by * read - olcAccess: {{2}}to dn.base="cn=Subschema" by * read - - # Config db settings - dn: olcDatabase=config,cn=config - objectClass: olcDatabaseConfig - olcDatabase: config - # Allow unlimited access to local connection from the local root - olcAccess: to * by dn.exact=gidNumber={gid}+uidNumber={uid}, - cn=peercred,cn=external,cn=auth manage by * break - olcRootDN: {self.admin_rdn},cn=config - olcRootPW: {admin_pw_hash} - - # Load schemas - dn: cn=schema,cn=config - objectClass: olcSchemaConfig - cn: schema - - include: file://{dist_conf_dir}/schema/core.ldif - include: file://{dist_conf_dir}/schema/cosine.ldif - include: file://{dist_conf_dir}/schema/nis.ldif - include: file://{dist_conf_dir}/schema/inetorgperson.ldif - - # Load module - dn: cn=module{{0}},cn=config - objectClass: olcModuleList - cn: module{{0}} - olcModulePath: {dist_lib_dir} - olcModuleLoad: back_mdb - - # Set defaults for the backend - dn: olcBackend=mdb,cn=config - objectClass: olcBackendConfig - olcBackend: mdb - - # The database definition. - dn: olcDatabase=mdb,cn=config - objectClass: olcDatabaseConfig - objectClass: olcMdbConfig - olcDatabase: mdb - olcDbCheckpoint: 512 30 - olcLastMod: TRUE - olcSuffix: {self.base_dn} - olcDbDirectory: {self.data_dir} - olcRootDN: {self.admin_dn} - olcRootPW: {admin_pw_hash} - olcDbIndex: objectClass eq - olcDbIndex: cn,uid eq - olcDbIndex: uidNumber,gidNumber eq - olcDbIndex: member,memberUid eq - olcAccess: to attrs=userPassword,shadowLastChange - by self write - by anonymous auth - by * none - olcAccess: to dn.base="" by * read - olcAccess: to * - by * read - """).format(**locals()) - - slapadd = subprocess.Popen( - ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config"], - stdin=subprocess.PIPE, close_fds=True - ) - slapadd.communicate(config.encode('utf-8')) - if slapadd.returncode != 0: - raise Exception("Failed to add configuration with slapadd") - - # - # Add database config (example from distribution) - # - db_config = unindent(""" - # One 0.25 GB cache - set_cachesize 0 268435456 1 - - # Transaction Log settings - set_lg_regionmax 262144 - set_lg_bsize 2097152 - """) - db_config_file = open(self.data_dir + "/DB_CONFIG", "w") - db_config_file.write(db_config) - db_config_file.close() - - # Import ad schema - subprocess.check_call( - ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config", - "-l", "data/ssh_schema.ldif"], - ) - - # Import sudo schema - subprocess.check_call( - ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config", - "-l", "data/sudo_schema.ldif"], - ) - - # Import cert schema - subprocess.check_call( - ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config", - "-l", "data/cert_schema.ldif"], - ) - - def _start_daemon(self): - """Start the instance.""" - if subprocess.call(["slapd", "-F", self.conf_slapd_d_dir, - "-h", self.url_list]) != 0: - raise Exception("Failed to start slapd") - - # - # Wait until it is available - # - attempt = 0 - while True: - try: - ldap_conn = ldap.initialize(self.ldapi_url) - ldap_conn.simple_bind_s(self.admin_rdn + ",cn=config", - self.admin_pw) - ldap_conn.unbind_s() - ldap_conn = ldap.initialize(self.ldap_url) - ldap_conn.simple_bind_s(self.admin_dn, self.admin_pw) - ldap_conn.unbind_s() - break - except ldap.SERVER_DOWN: - pass - attempt = attempt + 1 - if attempt > 30: - raise Exception("Failed to start slapd") - time.sleep(1) - - def setup(self): - """Setup the instance.""" - ldapi_socket = self.run_dir + "/ldapi" - self.ldapi_url = "ldapi://" + url_quote(ldapi_socket, "") - self.url_list = self.ldapi_url + " " + self.ldap_url - - os.makedirs(self.conf_slapd_d_dir) - os.makedirs(self.run_dir) - os.makedirs(self.data_dir) - - # - # Setup initial configuration - # - self._setup_config() - - self._start_daemon() - - # - # Relax requirement of member attribute presence in groupOfNames - # - modlist = [ - (ldap.MOD_DELETE, "olcObjectClasses", - b"{7}( 2.5.6.9 NAME 'groupOfNames' " - b"DESC 'RFC2256: a group of names (DNs)' SUP top " - b"STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ " - b"seeAlso $ owner $ ou $ o $ description ) )"), - (ldap.MOD_ADD, "olcObjectClasses", - b"{7}( 2.5.6.9 NAME 'groupOfNames' " - b"DESC 'RFC2256: a group of names (DNs)' SUP top " - b"STRUCTURAL MUST ( cn ) MAY ( member $ businessCategory $ " - b"seeAlso $ owner $ ou $ o $ description ) )"), - ] - ldap_conn = ldap.initialize(self.ldapi_url) - ldap_conn.simple_bind_s(self.admin_rdn + ",cn=config", self.admin_pw) - ldap_conn.modify_s("cn={0}core,cn=schema,cn=config", modlist) - ldap_conn.unbind_s() - - # - # Add data - # - ldap_conn = ldap.initialize(self.ldap_url) - ldap_conn.simple_bind_s(self.admin_dn, self.admin_pw) - ldap_conn.add_s(self.base_dn, [ - ("objectClass", [b"dcObject", b"organization"]), - ("o", b"Example Company"), - ]) - ldap_conn.add_s("cn=Manager," + self.base_dn, [ - ("objectClass", b"organizationalRole"), - ]) - for ou in ("Users", "Groups", "Netgroups", "Services", "Policies", - "Hosts", "Networks"): - ldap_conn.add_s("ou=" + ou + "," + self.base_dn, [ - ("objectClass", [b"top", b"organizationalUnit"]), - ]) - ldap_conn.add_s("ou=sudoers," + self.base_dn, [ - ("objectClass", [b"top", b"organizationalUnit"]), - ]) - ldap_conn.add_s("cn=testrule,ou=sudoers," + self.base_dn, [ - ("objectClass", [b"top", b"sudoRole"]), - ("sudoUser", [b"tuser"]), - ]) - ldap_conn.unbind_s() - - def _stop_daemon(self): - """Stop the instance.""" - # Wait for slapd to stop - try: - pid_file = open(self.pid_path, "r") - try: - os.kill(int(pid_file.read()), signal.SIGTERM) - finally: - pid_file.close() - attempt = 0 - while os.path.isfile(self.pid_path): - attempt = attempt + 1 - if attempt > 30: - raise Exception("Failed to stop slapd") - time.sleep(1) - except IOError as e: - if e.errno != errno.ENOENT: - raise - - def teardown(self): - """Teardown the instance.""" - self._stop_daemon() - - for path in (self.conf_slapd_d_dir, self.run_dir, self.data_dir): - shutil.rmtree(path, True) - - -class FakeAD(DSOpenLDAP): - """Fake Active Directory based on OpenLDAP directory server.""" - - def _setup_config(self): - """Setup the instance initial configuration.""" - - # Import ad schema - subprocess.check_call( - ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config", - "-l", "data/ad_schema.ldif"], - ) - - def setup(self): - """Setup the instance.""" - ldapi_socket = self.run_dir + "/ldapi" - self.ldapi_url = "ldapi://" + url_quote(ldapi_socket, "") - self.url_list = self.ldapi_url + " " + self.ldap_url - - os.makedirs(self.conf_slapd_d_dir) - os.makedirs(self.run_dir) - os.makedirs(self.data_dir) - - super(FakeAD, self)._setup_config() - self._setup_config() - - # Start the daemon - super(FakeAD, self)._start_daemon() - - # Relax requirement of surname attribute presence in person - modlist = [ - (ldap.MOD_DELETE, "olcObjectClasses", - b"{4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top " - b"STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ " - b"telephoneNumber $ seeAlso $ description ) )"), - (ldap.MOD_ADD, "olcObjectClasses", - b"{4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top " - b"STRUCTURAL MUST ( cn ) MAY ( sn $ userPassword $ " - b"telephoneNumber $ seeAlso $ description ) )"), - ] - ldap_conn = ldap.initialize(self.ldapi_url) - ldap_conn.simple_bind_s(self.admin_rdn + ",cn=config", self.admin_pw) - ldap_conn.modify_s("cn={0}core,cn=schema,cn=config", modlist) - ldap_conn.unbind_s() - - # restart daemon for reloading schema - super(FakeAD, self)._stop_daemon() - super(FakeAD, self)._start_daemon() - - # Add data - ldap_conn = ldap.initialize(self.ldap_url) - ldap_conn.simple_bind_s(self.admin_dn, self.admin_pw) - ldap_conn.add_s(self.base_dn, [ - ("objectClass", [b"dcObject", b"organization"]), - ("o", b"Example Company"), - ]) - ldap_conn.add_s("cn=Manager," + self.base_dn, [ - ("objectClass", b"organizationalRole"), - ]) - for ou in ("Users", "Groups", "Netgroups", "Services", "Policies"): - ldap_conn.add_s("ou=" + ou + "," + self.base_dn, [ - ("objectClass", [b"top", b"organizationalUnit"]), - ]) - ldap_conn.unbind_s() - - # import data from real AD - subprocess.check_call( - ["ldapadd", "-x", "-w", self.admin_pw, "-D", - self.admin_dn, "-H", self.ldap_url, - "-f", "data/ad_data.ldif"], - ) - - def teardown(self): - """Teardown the instance.""" - super(FakeAD, self).teardown() diff --git a/src/tests/intg/ent.py b/src/tests/intg/ent.py deleted file mode 100644 index d716ae5e656..00000000000 --- a/src/tests/intg/ent.py +++ /dev/null @@ -1,506 +0,0 @@ -# -# Abstract passwd/group entry management -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Nikolai Kondrashov -# -# 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 . -# - -from pprint import pformat -import pwd -import grp - -_PASSWD_LIST_DESC = {None: ("user", {})} -_GROUP_DESC = {"mem": ("member list", {None: ("member", {})})} -_GROUP_LIST_DESC = {None: ("group", _GROUP_DESC)} - - -def _get_desc(desc_map, key): - """ - Get an item description from a container description map. - - Arguments: - desc_map Container description map. - key Item key, None for wildcard description. - """ - assert isinstance(desc_map, dict) - if key in desc_map: - return desc_map[key] - if None in desc_map: - desc = desc_map[None] - if key is not None: - desc = (desc[0] + " " + pformat(key), desc[1]) - return desc - elif key is None: - return ("item", {}) - else: - return (pformat(key), {}) - - -def _diff(ent, pattern, desc_map={}): - """ - Describe difference between an entry and a pattern. - Return None, if none. - - Arguments: - ent Entry. - pattern Pattern. - desc_map Container pattern description map. - - An entry is a value, a list of entries, or a dictionary of entries. - Entries are used to store passwd and group database entries as - dictionaries, in lists and dictionaries. - - A pattern is a value, a tuple, a list, or a dictionary of patterns. - - E.g. 123, "abc", [ 123, "abc" ], { "abc": 123 }, { "abc": ( 123 ) } - - A pattern can be matched against a value, a list, or a dictionary entry. - - A value is considered matching, if it's equal to the pattern. - - E.g. 123 == 123, 123 != 456, "abc" == "abc", "abc" != "def", 123 != "abc" - - A list is considered matching a pattern, if the pattern is a list or a - tuple, where each of pattern list items matches an entry list item and - vice versa, or where each pattern tuple item matches an entry list item, - but not necessarily the other way around. - - E.g. [] != "abc", [] == [], [ "abc", 123 ] == [ 123, "abc" ], - [ "abc" ] != [ 123 ], [ 123 ] != [], - [] == (), [ "abc", 123 ] == ( 123, "abc" ), - [ "abc" ] != ( 123 ), [ 123 ] == (), [ 123, "abc" ] == ( 123 ) - - NOTE: For the sake of readability, it is recommended to use - "contains_only" function to create patterns matching all entry list - items (list patterns), and "contains" function to create patterns - matching a subset of entry list items (tuple patterns). - - A dictionary is considered matching a pattern, if it is also a dictionary, - and all of pattern values match identically-keyed values of the - dictionary. - - E.g. {} == {}, {} != "abc", { "abc": 123, "def": 456 } == { "abc": 123 }, - { "abc": 123 } == {} - - Container pattern description map is a dictionary with keys being item - keys/indices and values being (name, description map) tuples. None key - points to a wildcard description, others to specific item descriptions. - The description map argument is optional, and is used to generate more - readable difference explanations. - """ - assert isinstance(desc_map, dict) - - if isinstance(pattern, dict): - if not isinstance(ent, dict): - return "not a dict, " + str(type(ent)) - - for key, value in pattern.items(): - item_name, item_map = _get_desc(desc_map, key) - d = _diff(ent[key], value, item_map) - if d: - return item_name + " mismatch: " + d - elif isinstance(pattern, tuple): - if not isinstance(ent, list): - return "not a list, " + str(type(ent)) - - pattern_matches = [0 for pv in pattern] - - for ei, ev in enumerate(ent): - for pi, pv in enumerate(pattern): - d = _diff(ev, pv) - if not d: - pattern_matches[pi] += 1 - - unmatched_pattern = [pattern[pi] for pi in range(0, len(pattern)) - if pattern_matches[pi] == 0] - - items = _get_desc(desc_map, None)[0] + "s" - if len(unmatched_pattern) > 0: - return "\nexpected " + items + " not found:\n" + \ - pformat(unmatched_pattern) - elif isinstance(pattern, list): - if not isinstance(ent, list): - return "not a list, " + str(type(ent)) - - pattern_matches = [0 for pv in pattern] - ent_matches = [0 for ev in ent] - - for ei, ev in enumerate(ent): - for pi, pv in enumerate(pattern): - d = _diff(ev, pv) - if not d: - pattern_matches[pi] += 1 - ent_matches[ei] += 1 - - unmatched_pattern = [pattern[pi] for pi in range(0, len(pattern)) - if pattern_matches[pi] == 0] - unmatched_ent = [ent[pi] for pi in range(0, len(ent)) - if ent_matches[pi] == 0] - - items = _get_desc(desc_map, None)[0] + "s" - d = "" - if len(unmatched_pattern) > 0: - d += "\nexpected " + items + " not found:\n" + \ - pformat(unmatched_pattern) - if len(unmatched_ent) != 0: - d += "\nunexpected " + items + " found:\n" + \ - pformat(unmatched_ent) - if len(d) > 0: - return d - else: - if pattern != ent: - return pformat(pattern) + " != " + pformat(ent) - - return None - - -def contains_only(*args): - """ - Produce a pattern matching all list items against arguments. - Use this function instead of constructing bare lists, for readability. - """ - return list(args) - - -def contains(*args): - """ - Produce a pattern matching a subset of list items against arguments. - Use this function instead of constructing bare tuples, for readability. - """ - return args - - -def _convert_passwd(passwd): - """ - Convert a passwd entry returned by pwd module to an entry dictionary. - """ - return dict( - name=passwd.pw_name, - passwd=passwd.pw_passwd, - uid=passwd.pw_uid, - gid=passwd.pw_gid, - gecos=passwd.pw_gecos, - dir=passwd.pw_dir, - shell=passwd.pw_shell - ) - - -def get_passwd_by_name(name): - """Get a passwd database entry by name.""" - return _convert_passwd(pwd.getpwnam(name)) - - -def get_passwd_by_uid(uid): - """Get a passwd database entry by UID.""" - return _convert_passwd(pwd.getpwuid(uid)) - - -def assert_passwd_by_name(name, pattern): - """Assert a passwd entry, retrieved by name, matches a pattern.""" - try: - ent = get_passwd_by_name(name) - except KeyError as err: - assert False, err - d = _diff(ent, pattern) - assert not d, d - - -def assert_passwd_by_uid(uid, pattern): - """Assert a passwd entry, retrieved by UID, matches a pattern.""" - try: - ent = get_passwd_by_uid(uid) - except KeyError as err: - assert False, err - d = _diff(ent, pattern) - assert not d, d - - -def get_passwd_list(): - """Get passwd database entry list with root user removed.""" - passwd_list = pwd.getpwall() - for i, v in enumerate(passwd_list): - if v.pw_name == "root" and v.pw_uid == 0 and v.pw_gid == 0: - del passwd_list[i] - return list(map(_convert_passwd, passwd_list)) - raise Exception("no root user found") - - -def assert_passwd_list(pattern): - """Assert retrieved passwd list matches a pattern.""" - d = _diff(get_passwd_list(), pattern, _PASSWD_LIST_DESC) - assert not d, d - - -def _diff_each_passwd_by_name(pattern_dict): - """ - Describe difference between each pattern_dict value and a passwd entry - retrieved by name being the corresponding key. - """ - try: - ent = dict((k, get_passwd_by_name(k)) for k in pattern_dict.keys()) - except KeyError as err: - return str(err) - return _diff(ent, pattern_dict, _PASSWD_LIST_DESC) - - -def _diff_each_passwd_by_uid(pattern_dict): - """ - Describe difference between each pattern_dict value and a passwd entry - retrieved by UID being the corresponding key. - """ - try: - ent = dict((k, get_passwd_by_uid(k)) for k in pattern_dict.keys()) - except KeyError as err: - return str(err) - return _diff(ent, pattern_dict, _PASSWD_LIST_DESC) - - -def _diff_each_passwd_with_name(pattern_seq): - """ - Describe difference between each pattern in pattern_seq sequence and a - passwd entry retrieved by name being the pattern's "name" value. - """ - return _diff_each_passwd_by_name(dict((p["name"], p) for p in pattern_seq)) - - -def _diff_each_passwd_with_uid(pattern_seq): - """ - Describe difference between each pattern in pattern_seq sequence and a - passwd entry retrieved by UID being the pattern's "uid" value. - """ - return _diff_each_passwd_by_uid(dict((p["uid"], p) for p in pattern_seq)) - - -def assert_each_passwd_by_name(pattern_dict): - """ - Assert each pattern_dict value matches a passwd entry retrieved by - name being the corresponding key. - """ - d = _diff_each_passwd_by_name(pattern_dict) - assert not d, d - - -def assert_each_passwd_by_uid(pattern_dict): - """ - Assert each pattern_dict value matches a passwd entry retrieved by - UID being the corresponding key. - """ - d = _diff_each_passwd_by_uid(pattern_dict) - assert not d, d - - -def assert_each_passwd_with_name(pattern_seq): - """ - Assert each pattern in pattern_seq sequence matches a passwd entry - retrieved by name being the pattern's "name" value. - """ - d = _diff_each_passwd_with_name(pattern_seq) - assert not d, d - - -def assert_each_passwd_with_uid(pattern_seq): - """ - Assert each pattern in pattern_seq sequence matches a passwd entry - retrieved by UID being the pattern's "uid" value. - """ - d = _diff_each_passwd_with_uid(pattern_seq) - assert not d, d - - -def _diff_passwd(pattern): - """ - Describe difference between passwd database and a pattern. - Each pattern entry must have "name" and "uid" attribute. - """ - d = _diff(get_passwd_list(), pattern, _PASSWD_LIST_DESC) - if d: - return "list mismatch: " + d - d = _diff_each_passwd_with_name(pattern) - if d: - return "name retrieval mismatch: " + d - d = _diff_each_passwd_with_uid(pattern) - if d: - return "UID retrieval mismatch: " + d - return None - - -def assert_passwd(pattern): - """ - Assert passwd database matches a pattern. - Each pattern entry must have "name" and "uid" attribute. - """ - d = _diff_passwd(pattern) - assert not d, d - - -def _convert_group(group): - """ - Convert a group entry returned by grp module to an entry dictionary. - """ - return dict( - name=group.gr_name, - passwd=group.gr_passwd, - gid=group.gr_gid, - mem=group.gr_mem - ) - - -def get_group_by_name(name): - """Get a group database entry by name.""" - return _convert_group(grp.getgrnam(name)) - - -def get_group_by_gid(gid): - """Get a group database entry by GID.""" - return _convert_group(grp.getgrgid(gid)) - - -def assert_group_by_name(name, pattern): - """Assert a group entry, retrieved by name, matches a pattern.""" - try: - ent = get_group_by_name(name) - except KeyError as err: - assert False, err - d = _diff(ent, pattern, _GROUP_DESC) - assert not d, d - - -def assert_group_by_gid(gid, pattern): - """Assert a group entry, retrieved by GID, matches a pattern.""" - try: - ent = get_group_by_gid(gid) - except KeyError as err: - assert False, err - d = _diff(ent, pattern, _GROUP_DESC) - assert not d, d - - -def get_group_list(): - """Get group database entry list with root group removed.""" - group_list = grp.getgrall() - for i, v in enumerate(group_list): - if v.gr_name == "root" and v.gr_gid == 0: - del group_list[i] - return list(map(_convert_group, group_list)) - raise Exception("no root group found") - - -def assert_group_list(pattern): - """Assert retrieved group list matches a pattern.""" - d = _diff(get_group_list(), pattern, _GROUP_LIST_DESC) - assert not d, d - - -def _diff_each_group_by_name(pattern_dict): - """ - Describe difference between each pattern_dict value and a group entry - retrieved by name being the corresponding key. - """ - try: - ent = dict((k, get_group_by_name(k)) for k in pattern_dict.keys()) - except KeyError as err: - return str(err) - return _diff(ent, pattern_dict, _GROUP_LIST_DESC) - - -def _diff_each_group_by_gid(pattern_dict): - """ - Describe difference between each pattern_dict value and a group entry - retrieved by GID being the corresponding key. - """ - try: - ent = dict((k, get_group_by_gid(k)) for k in pattern_dict.keys()) - except KeyError as err: - return str(err) - return _diff(ent, pattern_dict, _GROUP_LIST_DESC) - - -def _diff_each_group_with_name(pattern_seq): - """ - Describe difference between each pattern in pattern_seq sequence and a - group entry retrieved name being the pattern's "name" value. - """ - return _diff_each_group_by_name(dict((p["name"], p) for p in pattern_seq)) - - -def _diff_each_group_with_gid(pattern_seq): - """ - Describe difference between each pattern in pattern_seq sequence and a - group entry retrieved by GID being the pattern's "gid" value. - """ - return _diff_each_group_by_gid(dict((p["gid"], p) for p in pattern_seq)) - - -def assert_each_group_by_name(pattern_dict): - """ - Assert each pattern_dict value matches a group entry retrieved by - name being the corresponding key. - """ - d = _diff_each_group_by_name(pattern_dict) - assert not d, d - - -def assert_each_group_by_gid(pattern_dict): - """ - Assert each pattern_dict value matches a group entry retrieved by - GID being the corresponding key. - """ - d = _diff_each_group_by_gid(pattern_dict) - assert not d, d - - -def assert_each_group_with_name(pattern_seq): - """ - Assert each pattern in pattern_seq sequence matches a group entry - retrieved by name being the pattern's "name" value. - """ - d = _diff_each_group_with_name(pattern_seq) - assert not d, d - - -def assert_each_group_with_gid(pattern_seq): - """ - Assert each pattern in pattern_seq sequence matches a group entry - retrieved by GID being the pattern's "gid" value. - """ - d = _diff_each_group_with_gid(pattern_seq) - assert not d, d - - -def _diff_group(pattern): - """ - Describe difference between group database and a pattern. - Each pattern entry must have "name" and "gid" attribute. - """ - d = _diff(get_group_list(), pattern, _GROUP_LIST_DESC) - if d: - return "list mismatch: " + d - d = _diff_each_group_with_name(pattern) - if d: - return "name retrieval mismatch: " + d - d = _diff_each_group_with_gid(pattern) - if d: - return "GID retrieval mismatch: " + d - return None - - -def assert_group(pattern): - """ - Assert group database matches a pattern. - Each pattern entry must have "name" and "gid" attribute. - """ - d = _diff_group(pattern) - assert not d, d diff --git a/src/tests/intg/files_ops.py b/src/tests/intg/files_ops.py deleted file mode 100644 index 57959f5010a..00000000000 --- a/src/tests/intg/files_ops.py +++ /dev/null @@ -1,173 +0,0 @@ -# -# SSSD integration test - operations on UNIX user and group database -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# - -import os -import os.path -import tempfile -import pytest - -import ent -from util import backup_envvar_file, restore_envvar_file - - -@pytest.fixture -def passwd_ops_setup(request): - pwd_file = os.environ["NSS_WRAPPER_PASSWD"] - backup_envvar_file("NSS_WRAPPER_PASSWD") - request.addfinalizer(lambda: restore_envvar_file("NSS_WRAPPER_PASSWD")) - pwd_ops = PasswdOps(pwd_file) - return pwd_ops - - -@pytest.fixture -def group_ops_setup(request): - grp_file = os.environ["NSS_WRAPPER_GROUP"] - backup_envvar_file("NSS_WRAPPER_GROUP") - request.addfinalizer(lambda: restore_envvar_file("NSS_WRAPPER_GROUP")) - grp_ops = GroupOps(grp_file) - return grp_ops - - -@pytest.fixture -def group_db_setup(request): - group = request.param - grp_ops = group_ops_setup(request) - grp_ops.groupadd(**group) - ent.assert_group_by_name(group['name'], group) - return grp_ops - - -class FilesOps(object): - """ - A naive implementation of operations as a basis for user or group - operations. Uses rename to (hopefully) trigger the same fs-level - notifications as shadow-utils would. - """ - def __init__(self, file_name): - self.file_name = file_name - self.tmp_dir = os.path.dirname(self.file_name) - - @staticmethod - def _get_named_line(name, contents): - for num, line in enumerate(contents, 0): - pname = line.split(':')[0] - if name == pname: - return num - raise KeyError("%s not found" % name) - - def _read_contents(self): - with open(self.file_name, "r") as pfile: - contents = pfile.readlines() - return contents - - def _write_contents(self, contents): - tmp_file = tempfile.NamedTemporaryFile(mode='w', dir=self.tmp_dir, - delete=False) - tmp_file.writelines(contents) - tmp_file.flush() - - os.rename(tmp_file.name, self.file_name) - - def _append_line(self, new_line): - contents = self._read_contents() - contents.extend(new_line) - self._write_contents(contents) - - def _subst_line(self, key, line): - contents = self._read_contents() - kindex = self._get_named_line(key, contents) - contents[kindex] = line - self._write_contents(contents) - - def _del_line(self, key): - contents = self._read_contents() - kindex = self._get_named_line(key, contents) - contents.pop(kindex) - self._write_contents(contents) - - contents = self._read_contents() - - def _has_line(self, key): - try: - self._get_named_line(key, self._read_contents()) - return True - except KeyError: - return False - - -class PasswdOps(FilesOps): - """ - A naive implementation of user operations - """ - def __init__(self, file_name): - super(PasswdOps, self).__init__(file_name) - - def _pwd2line(self, name, uid, gid, passwd, gecos, homedir, shell): - pwd_fmt = "{name}:{passwd}:{uid}:{gid}:{gecos}:{homedir}:{shell}\n" - return pwd_fmt.format(name=name, - passwd=passwd, - uid=uid, - gid=gid, - gecos=gecos, - homedir=homedir, - shell=shell) - - def useradd(self, name, uid, gid, passwd='', gecos='', dir='', shell=''): - pwd_line = self._pwd2line(name, uid, gid, passwd, gecos, dir, shell) - self._append_line(pwd_line) - - def usermod(self, name, uid, gid, passwd='', gecos='', dir='', shell=''): - pwd_line = self._pwd2line(name, uid, gid, passwd, gecos, dir, shell) - self._subst_line(name, pwd_line) - - def userdel(self, name): - self._del_line(name) - - def userexist(self, name): - return self._has_line(name) - - -class GroupOps(FilesOps): - """ - A naive implementation of group operations - """ - def __init__(self, file_name): - super(GroupOps, self).__init__(file_name) - - def _grp2line(self, name, gid, mem, passwd): - member_list = ",".join(m for m in mem) - grp_fmt = "{name}:{passwd}:{gid}:{member_list}\n" - return grp_fmt.format(name=name, - passwd=passwd, - gid=gid, - member_list=member_list) - - def groupadd(self, name, gid, mem, passwd="*"): - grp_line = self._grp2line(name, gid, mem, passwd) - self._append_line(grp_line) - - def groupmod(self, old_name, name, gid, mem, passwd="*"): - grp_line = self._grp2line(name, gid, mem, passwd) - self._subst_line(old_name, grp_line) - - def groupdel(self, name): - self._del_line(name) - - def groupexist(self, name): - return self._has_line(name) diff --git a/src/tests/intg/getsockopt_wrapper.c b/src/tests/intg/getsockopt_wrapper.c deleted file mode 100644 index dc378d87a67..00000000000 --- a/src/tests/intg/getsockopt_wrapper.c +++ /dev/null @@ -1,136 +0,0 @@ -/* gcc -Wall -fPIC -shared -o getsockopt_wrapper.so getsockopt_wrapper.c -ldl */ - -/* for RTLD_NEXT */ -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static bool is_dbus_socket(int fd) -{ - int ret; - struct sockaddr_storage addr = { 0 }; - socklen_t addrlen = sizeof(addr); - struct sockaddr_un *unix_socket; - - ret = getsockname(fd, (struct sockaddr *)&addr, &addrlen); - if (ret != 0) return false; - - if (addr.ss_family != AF_UNIX) return false; - - unix_socket = (struct sockaddr_un *)&addr; - - return NULL != strstr(unix_socket->sun_path, "system_bus_socket"); -} - -static bool peer_path_has(int fd, const char *str) -{ - int ret; - struct sockaddr_storage addr = { 0 }; - socklen_t addrlen = sizeof(addr); - struct sockaddr_un *unix_socket; - - ret = getpeername(fd, (struct sockaddr *)&addr, &addrlen); - if (ret != 0) return false; - - if (addr.ss_family != AF_UNIX) return false; - - unix_socket = (struct sockaddr_un *)&addr; - - return NULL != strstr(unix_socket->sun_path, str); -} - -static bool peer_is(const struct ucred *cr, const char *str) -{ - char proc_path[32]; - char cmd_line[255] = { 0 }; - int proc_fd; - int ret; - - if (cr->pid < 0) { - return false; - } - - ret = snprintf(proc_path, sizeof(proc_path), "/proc/%d/cmdline", - (int)cr->pid); - if ((ret < 0) || (ret >= sizeof(proc_path))) { - return false; - } - - proc_fd = open(proc_path, O_RDONLY); - if (proc_fd != -1) { - ret = read(proc_fd, cmd_line, sizeof(cmd_line)-1); - close(proc_fd); - if (ret > 0) { - cmd_line[ret] = 0; - if (strstr(cmd_line, str) != NULL) { - return true; - } - } - } - - return false; -} - -static void fake_peer_uid_gid(uid_t *uid, gid_t *gid) -{ - char *val; - - val = getenv("SSSD_INTG_PEER_UID"); - if (val != NULL) { - *uid = atoi(val); - } else { - *uid = -1; - } - - val = getenv("SSSD_INTG_PEER_GID"); - if (val != NULL) { - *gid = atoi(val); - } else { - *gid = -1; - } -} - -typedef typeof(getsockopt) getsockopt_fn_t; - -static getsockopt_fn_t *orig_getsockopt = NULL; - -int getsockopt(int sockfd, int level, int optname, - void *optval, socklen_t *optlen) -{ - int ret; -#ifdef __OpenBSD__ - struct sockpeercred *cr; -#else - struct ucred *cr; -#endif - - if (orig_getsockopt == NULL) { - orig_getsockopt = (getsockopt_fn_t *)dlsym(RTLD_NEXT, "getsockopt"); - } - - ret = orig_getsockopt(sockfd, level, optname, optval, optlen); - - if (ret == 0 && level == SOL_SOCKET && optname == SO_PEERCRED - && *optlen == sizeof(*cr)) { - cr = optval; - if (cr->uid != 0 && is_dbus_socket(sockfd)) { - cr->uid = 0; - } else if (peer_path_has(sockfd, "pipes/pam") || - peer_path_has(sockfd, "pipes/sudo") || - peer_is(cr, "sssctl") || - peer_is(cr, "sss_sudo_cli")) { - fake_peer_uid_gid(&cr->uid, &cr->gid); - } - } - - return ret; -} diff --git a/src/tests/intg/kdc.py b/src/tests/intg/kdc.py deleted file mode 100644 index a574e1f6775..00000000000 --- a/src/tests/intg/kdc.py +++ /dev/null @@ -1,178 +0,0 @@ -# -# MIT Kerberos server class -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# -import os -import signal -import shutil -import subprocess - -from util import unindent - - -class KDC(object): - """ - MIT Kerberos KDC instance - """ - - def __init__(self, basedir, realm, - includedir=None, - kdc_port=10088, - kadmin_port=10749, - master_key='master'): - self.basedir = basedir - self.realm = realm - self.kdc_port = kdc_port - self.kadmin_port = kadmin_port - self.master_key = master_key - - self.kdc_basedir = self.basedir + "/var/krb5kdc" - self.includedir = includedir or (self.kdc_basedir + "/include") - self.kdc_logdir = self.kdc_basedir + "/log" - self.kdc_conf_path = self.kdc_basedir + "/kdc.conf" - self.krb5_conf_path = self.kdc_basedir + "/krb5.conf" - - self.kdc_pid_file = self.kdc_basedir + "/kdc.pid" - - self.acl_file = self.kdc_basedir + "/kadm5.acl" - - self.admin_princ = "admin/admin@" + self.realm - - def start_kdc(self, extra_args=[]): - args = ["krb5kdc", '-P', self.kdc_pid_file] + extra_args - return self._run_in_env(args, self.get_krb5_env()) - - def stop_kdc(self): - try: - with open(self.kdc_pid_file, "r") as pid_file: - os.kill(int(pid_file.read()), signal.SIGTERM) - except IOError as ioex: - if ioex.errno == 2: - pass - else: - raise ioex - - def teardown(self): - self.stop_kdc() - shutil.rmtree(self.kdc_basedir) - - def set_up(self): - self._create_config() - self._create_acl() - self._create_kdb() - - def get_krb5_env(self): - my_env = os.environ.copy() - my_env['KRB5_CONFIG'] = self.krb5_conf_path - my_env['KRB5_KDC_PROFILE'] = self.kdc_conf_path - return my_env - - def add_config(self, include_files): - for name, contents in include_files.items(): - include_fpath = os.path.join(self.includedir, name) - with open(include_fpath, 'w') as include_file: - include_file.write(contents) - - def add_principal(self, princ, password=None): - args = ["kadmin.local", "-q"] - if password is None: - args += ["addprinc -randkey %s" % (princ)] - else: - args += ["addprinc -pw %s %s" % (password, princ)] - return self._run_in_env(args, self.get_krb5_env()) - - def _run_in_env(self, args, env): - cmd = subprocess.Popen(args, env=env) - out, err = cmd.communicate() - return cmd.returncode, out, err - - def _create_config(self): - try: - os.makedirs(self.kdc_basedir) - os.makedirs(self.kdc_logdir) - os.makedirs(self.includedir) - except OSError as osex: - if osex.errno == 17: - pass - - kdc_conf = self._format_kdc_conf() - with open(self.kdc_conf_path, 'w') as kdc_conf_file: - kdc_conf_file.write(kdc_conf) - - krb5_conf = self._format_krb5_conf() - with open(self.krb5_conf_path, 'w') as krb5_conf_file: - krb5_conf_file.write(krb5_conf) - - def _create_acl(self): - with open(self.acl_file, 'w') as acl_fobject: - acl_fobject.write(self.admin_princ) - - def _create_kdb(self): - self._run_in_env( - ['kdb5_util', 'create', '-W', '-s', '-P', self.master_key], - self.get_krb5_env() - ) - - def _format_kdc_conf(self): - database_path = self.kdc_basedir + "/principal" - key_stash = self.kdc_basedir + "/stash." + self.realm - - kdc_logfile = "FILE:" + self.kdc_logdir + "/krb5kdc.log" - kadmin_logfile = "FILE:" + self.kdc_logdir + "/kadmin.log" - libkrb5_logfile = "FILE:" + self.kdc_logdir + "/libkrb5.log" - - kdc_conf = unindent(""" - [kdcdefaults] - kdc_ports = {self.kdc_port} - kdc_tcp_ports = {self.kdc_port} - - [realms] - {self.realm} = {{ - kadmind_port = {self.kadmin_port} - database_name = {database_path} - key_stash_file = {key_stash} - max_life = 7d - max_renewable_life = 14d - acl_file = {self.acl_file} - }} - - [logging] - kdc = {kdc_logfile} - admin_server = {kadmin_logfile} - default = {libkrb5_logfile} - """).format(**locals()) - return kdc_conf - - def _format_krb5_conf(self): - kdc_uri = "localhost:%d" % self.kdc_port - kadmin_uri = "localhost:%d" % self.kadmin_port - - krb5_conf = unindent(""" - includedir {self.includedir} - - [libdefaults] - default_realm = {self.realm} - dns_lookup_kdc = false - dns_lookup_realm = false - - [realms] - {self.realm} = {{ - kdc = {kdc_uri} - admin_server = {kadmin_uri} - }} - """).format(**locals()) - return krb5_conf diff --git a/src/tests/intg/krb5utils.py b/src/tests/intg/krb5utils.py deleted file mode 100644 index 2d1b79e7688..00000000000 --- a/src/tests/intg/krb5utils.py +++ /dev/null @@ -1,174 +0,0 @@ -# -# MIT Kerberos server class -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# -import os -import subprocess - - -class NoPrincipals(Exception): - def __init__(self): - Exception.__init__(self, 'No principals in the collection') - - -class PrincNotFound(Exception): - def __init__(self, principal): - Exception.__init__(self, 'Principal %s not found' % principal) - - -class Krb5Utils(object): - """ - Helper class to test Kerberos command line utilities - """ - def __init__(self, krb5_conf_path): - self.krb5_conf_path = krb5_conf_path - - def spawn_in_env(self, args, stdin=None, extra_env=None): - my_env = os.environ.copy() - my_env['KRB5_CONFIG'] = self.krb5_conf_path - - if 'KRB5CCNAME' in my_env: - del my_env['KRB5CCNAME'] - if extra_env is not None: - my_env.update(extra_env) - - cmd = subprocess.Popen(args, - env=my_env, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - return cmd - - def _run_in_env(self, args, stdin=None, extra_env=None): - cmd = self.spawn_in_env(args, stdin, extra_env) - out, err = cmd.communicate(stdin) - return cmd.returncode, out.decode('utf-8'), err.decode('utf-8') - - def kinit(self, principal, password, options=None, env=None): - args = ["kinit", principal] - if options: - args.extend(options) - return self._run_in_env(args, password.encode('utf-8'), env) - - def kvno(self, principal, env=None): - args = ["kvno", principal] - return self._run_in_env(args, env) - - def kdestroy(self, all_ccaches=False, env=None): - args = ["kdestroy"] - if all_ccaches is True: - args += ["-A"] - retval, _, _ = self._run_in_env(args, env) - return retval - - def kswitch(self, principal, env=None): - args = ["kswitch", '-p', principal] - retval, _, _ = self._run_in_env(args, env) - return retval - - def _check_klist_l(self, line, exp_principal, exp_cache): - try: - princ, cache = line.split() - except ValueError: - return False - - if exp_cache is not None and cache != exp_cache: - return False - - if exp_principal != princ: - return False - - return True - - def num_princs(self, env=None): - args = ["klist", "-l"] - retval, out, err = self._run_in_env(args, extra_env=env) - if retval != 0: - return 0 - - outlines = [ln for ln in out.split('\n') if len(ln) > 1] - return len(outlines) - 2 - - def list_princs(self, env=None): - args = ["klist", "-l"] - retval, out, err = self._run_in_env(args, extra_env=env) - if retval == 1: - raise NoPrincipals - elif retval != 0: - raise Exception("klist failed: %d: %s\n", retval, err) - - outlines = out.split('\n') - if len(outlines) < 2: - raise Exception("Not enough output from klist -l") - - return [ln for ln in outlines[2:] if len(ln) > 0] - - def list_times(self, env=None): - p = self.spawn_in_env(['klist', '-A']) - output = p.stdout.read().splitlines() - for line in output: - if not line: - continue - - line_str = line.decode("utf-8") - if line_str[0].isdigit(): - return line_str - - def has_principal(self, exp_principal, exp_cache=None, env=None): - try: - princlist = self.list_princs(env) - except NoPrincipals: - return False - - for line in princlist: - matches = self._check_klist_l(line, exp_principal, exp_cache) - if matches is True: - return True - - return False - - def default_principal(self, env=None): - principals = self.list_princs(env) - return principals[0].split()[0] - - def _parse_klist_a(self, out): - dflprinc = None - thisrealm = None - ccache_dict = dict() - - for line in [ln for ln in out.split('\n') if len(ln) > 0]: - if line.startswith("Default principal"): - dflprinc = line.split()[2] - thisrealm = '@' + dflprinc.split('@')[1] - elif thisrealm is not None and line.endswith(thisrealm): - svc = line.split()[-1] - if dflprinc in ccache_dict: - ccache_dict[dflprinc].append(svc) - else: - ccache_dict[dflprinc] = [svc] - - return ccache_dict - - def list_all_princs(self, env=None): - args = ["klist", "-A"] - retval, out, err = self._run_in_env(args, extra_env=env) - if retval == 1: - raise NoPrincipals - elif retval != 0: - raise Exception("klist -A failed: %d: %s\n", retval, err) - - return self._parse_klist_a(out) diff --git a/src/tests/intg/ldap_ent.py b/src/tests/intg/ldap_ent.py deleted file mode 100644 index e5d1af43ac8..00000000000 --- a/src/tests/intg/ldap_ent.py +++ /dev/null @@ -1,258 +0,0 @@ -# -# LDAP modlist generation -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Nikolai Kondrashov -# -# 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 . -# - - -def user(base_dn, uid, uidNumber, gidNumber, - userPassword=None, - gecos=None, - homeDirectory=None, - loginShell=None, - cn=None, - sn=None, - sshPubKey=(), - mail=None): - """ - Generate an RFC2307(bis) user add-modlist for passing to ldap.add* - """ - uidNumber = str(uidNumber).encode('utf-8') - gidNumber = str(gidNumber).encode('utf-8') - user = ( - "uid=" + uid + ",ou=Users," + base_dn, - [ - ('objectClass', [b'top', b'inetOrgPerson', b'mailRecipient', - b'posixAccount', b'ldapPublicKey']), - ('cn', [uidNumber if cn is None else cn.encode('utf-8')]), - ('sn', [b'User' if sn is None else sn.encode('utf-8')]), - ('uidNumber', [uidNumber]), - ('gidNumber', [gidNumber]), - ('userPassword', [b'Password' + uidNumber - if userPassword is None - else userPassword.encode('utf-8')]), - ('homeDirectory', [b'/home/' + uid.encode('utf-8') - if homeDirectory is None - else homeDirectory.encode('utf-8')]), - ('loginShell', [b'/bin/bash' - if loginShell is None - else loginShell.encode('utf-8')]), - ] - ) - if gecos is not None: - user[1].append(('gecos', [gecos.encode('utf-8')])) - if len(sshPubKey) > 0: - pubkeys = [key.encode('utf-8') for key in sshPubKey] - user[1].append(('sshPublicKey', pubkeys)) - if mail is not None: - user[1].append(('mail', [mail.encode('utf-8')])) - return user - - -def group(base_dn, cn, gidNumber, member_uids=()): - """ - Generate an RFC2307 group add-modlist for passing to ldap.add*. - """ - gidNumber = str(gidNumber).encode('utf-8') - attr_list = [ - ('objectClass', [b'top', b'posixGroup']), - ('gidNumber', [gidNumber]) - ] - if len(member_uids) > 0: - mem_uids = [member.encode('utf-8') for member in member_uids] - attr_list.append(('memberUid', mem_uids)) - return ("cn=" + cn + ",ou=Groups," + base_dn, attr_list) - - -def group_bis(base_dn, cn, gidNumber, member_uids=(), member_gids=()): - """ - Generate an RFC2307bis group add-modlist for passing to ldap.add*. - """ - gidNumber = str(gidNumber).encode('utf-8') - attr_list = [ - ('objectClass', [b'top', b'extensibleObject', b'groupOfNames']), - ('gidNumber', [gidNumber]) - ] - member_list = [] - for uid in member_uids: - member_list.append("uid=" + uid + ",ou=Users," + base_dn) - for gid in member_gids: - member_list.append("cn=" + gid + ",ou=Groups," + base_dn) - if len(member_list) > 0: - mem_list = [member.encode('utf-8') for member in member_list] - attr_list.append(('member', mem_list)) - return ("cn=" + cn + ",ou=Groups," + base_dn, attr_list) - - -def netgroup(base_dn, cn, triples=(), members=()): - """ - Generate an RFC2307bis netgroup add-modlist for passing to ldap.add*. - """ - attr_list = [ - ('objectClass', [b'top', b'nisNetgroup']) - ] - if triples: - triples = [triple.encode('utf-8') for triple in triples] - attr_list.append(('nisNetgroupTriple', triples)) - if members: - members = [member.encode('utf-8') for member in members] - attr_list.append(('memberNisNetgroup', members)) - return ("cn=" + cn + ",ou=Netgroups," + base_dn, attr_list) - - -def sudo_rule(base_dn, name, users=(), hosts=(), commands=()): - """ - Generate a sudo rule for passing to ldap.add* - """ - attr_list = [ - ('objectClass', [b'top', b'sudoRole']), - ('cn', [name.encode('utf-8')]) - ] - - if len(users) > 0: - sudo_user_list = [u.encode('utf-8') for u in users] - attr_list.append(('sudoUser', sudo_user_list)) - if len(hosts) > 0: - sudo_host_list = [h.encode('utf-8') for h in hosts] - attr_list.append(('sudoHost', sudo_host_list)) - if len(commands) > 0: - sudo_command_list = [cmd.encode('utf-8') for cmd in commands] - attr_list.append(('sudoCommand', sudo_command_list)) - return ("cn=" + name + ",ou=sudoers," + base_dn, attr_list) - - -def ip_host(base_dn, name, aliases=(), addresses=()): - """ - Generate an RFC2307 ipHost add-modlist for passing to ldap.add*. - """ - attr_list = [ - ('objectClass', [b'top', b'device', b'ipHost']), - ] - if (len(aliases)) > 0: - alias_list = [alias.encode('utf-8') for alias in aliases] - alias_list.insert(0, name.encode('utf-8')) - attr_list.append(('cn', alias_list)) - else: - attr_list.append(('cn', [name.encode('utf-8')])) - if len(addresses) > 0: - addr_list = [addr.encode('utf-8') for addr in addresses] - attr_list.append(('ipHostNumber', addr_list)) - return ("cn=" + name + ",ou=Hosts," + base_dn, attr_list) - - -def ip_net(base_dn, name, address, aliases=()): - """ - Generate an RFC2307 ipNetwork add-modlist for passing to ldap.add*. - """ - attr_list = [ - ('objectClass', [b'top', b'ipNetwork']), - ('ipNetworkNumber', [address.encode('utf-8')]), - ] - if (len(aliases)) > 0: - alias_list = [alias.encode('utf-8') for alias in aliases] - alias_list.insert(0, name.encode('utf-8')) - attr_list.append(('cn', alias_list)) - else: - attr_list.append(('cn', [name.encode('utf-8')])) - return ("cn=" + name + ",ou=Networks," + base_dn, attr_list) - - -def ip_service(base_dn, name, proto, port, aliases=()): - """ - Generate an RFC2307 ipService add-modlist for passing to ldap.add*. - """ - attr_list = [ - ('objectClass', [b'top', b'ipService']), - ('ipServicePort', [str(port).encode('utf-8')]), - ('ipServiceProtocol', [proto.encode('utf-8')]), - ] - if (len(aliases)) > 0: - alias_list = [alias.encode('utf-8') for alias in aliases] - alias_list.insert(0, name.encode('utf-8')) - attr_list.append(('cn', alias_list)) - else: - attr_list.append(('cn', [name.encode('utf-8')])) - return ("cn=" + name + ",ou=Services," + base_dn, attr_list) - - -class List(list): - """LDAP add-modlist list""" - - def __init__(self, base_dn): - self.base_dn = base_dn - - def add_user(self, uid, uidNumber, gidNumber, - base_dn=None, - userPassword=None, - gecos=None, - homeDirectory=None, - loginShell=None, - cn=None, - sn=None, - sshPubKey=(), - mail=None): - """Add an RFC2307(bis) user add-modlist.""" - self.append(user(base_dn or self.base_dn, - uid, uidNumber, gidNumber, - userPassword=userPassword, - gecos=gecos, - homeDirectory=homeDirectory, - loginShell=loginShell, - cn=cn, - sn=sn, - sshPubKey=sshPubKey, - mail=mail)) - - def add_group(self, cn, gidNumber, member_uids=[], - base_dn=None): - """Add an RFC2307 group add-modlist.""" - self.append(group(base_dn or self.base_dn, - cn, gidNumber, member_uids)) - - def add_group_bis(self, cn, gidNumber, - member_uids=[], member_gids=[], - base_dn=None): - """Add an RFC2307bis group add-modlist.""" - self.append(group_bis(base_dn or self.base_dn, - cn, gidNumber, - member_uids, member_gids)) - - def add_netgroup(self, cn, triples=(), members=(), base_dn=None): - """Add an RFC2307bis netgroup add-modlist.""" - self.append(netgroup(base_dn or self.base_dn, - cn, triples, members)) - - def add_sudo_rule(self, name, - users=(), hosts=(), commands=(), - base_dn=None): - self.append(sudo_rule(base_dn or self.base_dn, - name, users, hosts, commands)) - - def add_host(self, name, aliases=[], addresses=[], base_dn=None): - """Add an RFC2307 ipHost add-modlist.""" - self.append(ip_host(base_dn or self.base_dn, - name, aliases, addresses)) - - def add_ipnet(self, name, address, aliases=[], base_dn=None): - """Add an RFC2307 ipNetwork add-modlist.""" - self.append(ip_net(base_dn or self.base_dn, - name, address, aliases)) - - def add_service(self, name, proto, port, aliases=[], base_dn=None): - """Add an RFC2307 ipService add-modlist.""" - self.append(ip_service(base_dn or self.base_dn, - name, proto, port, aliases)) diff --git a/src/tests/intg/nss_call.c b/src/tests/intg/nss_call.c deleted file mode 100644 index a8c7d30f5c7..00000000000 --- a/src/tests/intg/nss_call.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - NSS module which calls glibc's user and group lookup functions again - - DO NOT USE THIS IN /etc/nsswitch.conf, it will cause an infinite loop. - - The main use case is to run proxy provider tests with cwrap's nss-wrapper. - The proxy provider loads the NSS modules directly with dlopen() and is not - using glibc's NSS mechanism. Since nss-wrapper just wraps the standard - glibc calls and does not provide an NSS module on its own we have to use - this workaround to make proxy provider work with nss-wrapper. - - Authors: - Sumit Bose - - Copyright (c) 2023 Red Hat, Inc. - - 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 . -*/ - -#define _DEFAULT_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - - - -#define NSSRET(r) return (((r) == 0) ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND ) - -enum nss_status _nss_call_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop) -{ - struct passwd *res; - int ret = getpwnam_r(name, result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop) -{ - struct passwd *res; - int ret = getpwuid_r(uid, result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_setpwent(void) -{ - setpwent(); - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_call_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, - int *errnop) -{ - struct passwd *res; - int ret = getpwent_r(result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_endpwent(void) -{ - endpwent(); - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_call_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct group *res; - int ret = getgrnam_r(name, result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_getgrgid_r(gid_t gid, struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct group *res; - int ret = getgrgid_r(gid, result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_setgrent(void) -{ - setgrent(); - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_call_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct group *res; - int ret = getgrent_r(result, buffer, buflen, &res); - NSSRET(ret); -} - -enum nss_status _nss_call_endgrent(void) -{ - endgrent(); - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_call_initgroups_dyn(const char *user, gid_t group, - long int *start, long int *size, - gid_t **groups, long int limit, - int *errnop) -{ - int ngroups = 0; - gid_t *grps = NULL; - long int max_ret; - long int i; - int ret; - - ret = getgrouplist(user, group, grps, &ngroups); - if (ret != -1) { - return NSS_STATUS_UNAVAIL; - } - - grps = malloc(ngroups * sizeof(gid_t)); - if (grps == NULL) { - return NSS_STATUS_UNAVAIL; - } - - max_ret = ngroups; - /* check we have enough space in the buffer */ - if ((*size - *start) < ngroups) { - long int newsize; - gid_t *newgroups; - - newsize = *size + ngroups; - if ((limit > 0) && (newsize > limit)) { - newsize = limit; - max_ret = newsize - *start; - } - - newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups)); - if (!newgroups) { - free(grps); - return NSS_STATUS_UNAVAIL; - } - *groups = newgroups; - *size = newsize; - } - - for (i = 0; i < max_ret; i++) { - (*groups)[*start] = grps[i]; - *start += 1; - } - free(grps); - - return NSS_STATUS_SUCCESS; -} diff --git a/src/tests/intg/sss_netgroup_thread_test.c b/src/tests/intg/sss_netgroup_thread_test.c deleted file mode 100644 index d3bee9b3e63..00000000000 --- a/src/tests/intg/sss_netgroup_thread_test.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - Helper program to test if innetgr() is thread-safe - - Authors: - Sumit Bose - - Copyright (c) 2021 Red Hat, Inc. - - 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 . -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - - - -struct data { - const char *group; - const char *host; - const char *user; - const char *domain; - bool *failed; -}; - -static void *full_netgroup(void *arg) -{ - int ret; - size_t c = 0; - struct data *data = arg; - - do { - ret = innetgr(data->group, data->host, data->user, data->domain); - if (ret != 1) { - *(data->failed) = true; - } - c++; - } while (!*(data->failed) && c<100000); - - pthread_exit(NULL); -} - -int main() -{ - pthread_t thread[2]; - bool failed[2] = {false, false}; - - struct data data[3] = {{"ng1", "host1", "user924", "domain1", &failed[0]}, - {"ng2", "host2", "user925", "domain2", &failed[1]}, - {NULL, NULL, NULL, NULL, NULL}}; - - - pthread_create(&thread[0], NULL, full_netgroup, &data[0]); - pthread_create(&thread[1], NULL, full_netgroup, &data[1]); - - pthread_join(thread[1], NULL); - pthread_join(thread[0], NULL); - - if (failed[0] || failed[1]) { - printf ("Test failed.\n"); - return 1; - } - - return 0; -} diff --git a/src/tests/intg/sssd_group.py b/src/tests/intg/sssd_group.py deleted file mode 100644 index b6a37c5014c..00000000000 --- a/src/tests/intg/sssd_group.py +++ /dev/null @@ -1,132 +0,0 @@ -# -# Module for simulation of utility "getent group -s sss" from coreutils -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# - -from ctypes import (c_int, c_char_p, c_ulong, POINTER, Structure, - create_string_buffer) -from sssd_nss import NssReturnCode, SssdNssError, nss_sss_ctypes_loader - -GROUP_BUFLEN = 1024 - - -class Group(Structure): - _fields_ = [("gr_name", c_char_p), - ("gr_passwd", c_char_p), - ("gr_gid", c_int), - ("gr_mem", POINTER(c_char_p))] - - -def getgrnam_r(name, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getgrnam_r(const char *name, - struct group *result, - char *buffer, - size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getgrnam_r") - func.restype = c_int - func.argtypes = [c_char_p, POINTER(Group), - c_char_p, c_ulong, POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - name = name.encode('utf-8') - res = func(c_char_p(name), result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def getgrgid_r(gid, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getgrgid_r(gid_t gid, - struct passwd *result, - char *buffer, - size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getgrgid_r") - func.restype = c_int - func.argtypes = [c_ulong, POINTER(Group), - c_char_p, c_ulong, POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - res = func(gid, result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def set_group_dict(res, result_p): - if res != NssReturnCode.SUCCESS: - return dict() - - group_dict = dict() - group_dict['name'] = result_p[0].gr_name.decode('utf-8') - group_dict['gid'] = result_p[0].gr_gid - group_dict['mem'] = list() - - i = 0 - while result_p[0].gr_mem[i] is not None: - grp_name = result_p[0].gr_mem[i].decode('utf-8') - group_dict['mem'].append(grp_name) - i = i + 1 - - return group_dict - - -def call_sssd_getgrnam(name): - """ - A Python wrapper to retrieve a group by name. Returns: - (res, group_dict) - if res is NssReturnCode.SUCCESS, then group_dict contains the keys - corresponding to the C passwd structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Group() - result_p = POINTER(Group)(result) - buff = create_string_buffer(GROUP_BUFLEN) - - res, errno, result_p = getgrnam_r(name, result_p, buff, GROUP_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getgrnam_r") - - group_dict = set_group_dict(res, result_p) - return res, group_dict - - -def call_sssd_getgrgid(gid): - """ - A Python wrapper to retrieve a group by GID. Returns: - (res, group_dict) - if res is NssReturnCode.SUCCESS, then group_dict contains the keys - corresponding to the C passwd structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Group() - result_p = POINTER(Group)(result) - buff = create_string_buffer(GROUP_BUFLEN) - - res, errno, result_p = getgrgid_r(gid, result_p, buff, GROUP_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getgrgid_r") - - group_dict = set_group_dict(res, result_p) - return res, group_dict diff --git a/src/tests/intg/sssd_hosts.py b/src/tests/intg/sssd_hosts.py deleted file mode 100644 index 14732777dbb..00000000000 --- a/src/tests/intg/sssd_hosts.py +++ /dev/null @@ -1,142 +0,0 @@ -# -# Module for simulation of utility "getent hosts -s sss" from coreutils -# -# Authors: -# Samuel Cabrero -# -# Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. -# -# 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 . - -from ctypes import (c_int, c_char_p, c_ulong, POINTER, - Structure, create_string_buffer) -from sssd_nss import NssReturnCode, SssdNssError, nss_sss_ctypes_loader -import socket -from ipaddress import IPv4Address, IPv6Address - -HOST_BUFLEN = 1024 - - -class Hostent(Structure): - _fields_ = [("h_name", c_char_p), - ("h_aliases", POINTER(c_char_p)), - ("h_addrtype", c_int), - ("h_length", c_int), - ("h_addr_list", POINTER(c_char_p))] - - -def gethostbyname_r(name, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_gethostbyname_r(const char *name, - struct hostent *result, - char *buffer, - size_t buflen, - int *errnop, - int *h_errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_gethostbyname_r") - func.restype = c_int - func.argtypes = [c_char_p, POINTER(Hostent), - c_char_p, c_ulong, POINTER(c_int), POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - h_errno = POINTER(c_int)(c_int(0)) - - name = name.encode('utf-8') - res = func(c_char_p(name), result_p, buffer_p, buflen, errno, h_errno) - - return (int(res), int(errno[0]), int(h_errno[0]), result_p) - - -def gethostbyname2_r(name, af, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_gethostbyname2_r(const char *name, - int af, - struct hostent *result, - char *buffer, - size_t buflen, - int *errnop, - int *h_errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_gethostbyname2_r") - func.restype = c_int - func.argtypes = [c_char_p, c_int, POINTER(Hostent), - c_char_p, c_ulong, POINTER(c_int), POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - h_errno = POINTER(c_int)(c_int(0)) - - name = name.encode('utf-8') - res = func(c_char_p(name), af, result_p, buffer_p, buflen, errno, h_errno) - - return (int(res), int(errno[0]), int(h_errno[0]), result_p) - - -def set_hostent_dict(res, result_p): - if res != NssReturnCode.SUCCESS: - return dict() - - hostent_dict = dict() - hostent_dict['name'] = result_p[0].h_name.decode('utf-8') - hostent_dict['aliases'] = list() - hostent_dict['addrtype'] = result_p[0].h_addrtype - hostent_dict['length'] = result_p[0].h_length - hostent_dict['addresses'] = list() - - i = 0 - while result_p[0].h_aliases[i] is not None: - alias = result_p[0].h_aliases[i].decode('utf-8') - hostent_dict['aliases'].append(alias) - i = i + 1 - - i = 0 - while result_p[0].h_addr_list[i] is not None: - length = result_p[0].h_length - binaddr = result_p[0].h_addr_list[i][:length] - if result_p[0].h_addrtype == socket.AF_INET: - addr = IPv4Address(binaddr) - addr = socket.inet_ntop(socket.AF_INET, addr.packed) - elif result_p[0].h_addrtype == socket.AF_INET6: - addr = IPv6Address(binaddr) - addr = socket.inet_ntop(socket.AF_INET, addr.packed) - else: - raise Exception("Failed to parse IP address") - - hostent_dict['addresses'].append(addr) - i = i + 1 - - return hostent_dict - - -def call_sssd_gethostbyname(name): - """ - A Python wrapper to retrieve a host by name. Returns: - (res, hostent_dict) - if res is NssReturnCode.SUCCESS, then hostent_dict contains the keys - corresponding to the C hostent structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Hostent() - result_p = POINTER(Hostent)(result) - buff = create_string_buffer(HOST_BUFLEN) - - (res, errno, h_errno, result_p) = gethostbyname_r(name, result_p, - buff, HOST_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "gethostbyname_r") - - hostent_dict = set_hostent_dict(res, result_p) - return (res, h_errno, hostent_dict) diff --git a/src/tests/intg/sssd_id.py b/src/tests/intg/sssd_id.py deleted file mode 100644 index 3a45e3b6283..00000000000 --- a/src/tests/intg/sssd_id.py +++ /dev/null @@ -1,129 +0,0 @@ -# -# Module for simulation of utility "id" from coreutils -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Lukas Slebodnik -# -# 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 . -# -import pwd -import grp -from ctypes import (c_int, c_char, c_uint32, c_long, c_char_p, - POINTER, pointer) -from sssd_nss import NssReturnCode, nss_sss_ctypes_loader - - -def call_sssd_initgroups(user, gid): - """ - Function will initialize the supplementary group access list - for given user. It will gather groups only provided by sssd. - - Arguments are the same as for C function initgroups - @param string user name of user - @param int gid the additional gid will be also added to the list. - - @return (int, int, List[int]) (err, errno, gids) - gids should contain user group IDs if err is NssReturnCode.SUCCESS - otherwise errno will contain non-zero value. - """ - func = nss_sss_ctypes_loader('_nss_sss_initgroups_dyn') - - func.restype = c_int - func.argtypes = [POINTER(c_char), c_uint32, POINTER(c_long), - POINTER(c_long), POINTER(POINTER(c_uint32)), c_long, - POINTER(c_int)] - - start = POINTER(c_long)(c_long(0)) - size = POINTER(c_long)(c_long(0)) - groups = POINTER(c_uint32)() - p_groups = pointer(groups) - limit = c_long(-1) - errno = POINTER(c_int)(c_int(0)) - - res = func(c_char_p(user.encode('utf-8)')), c_uint32(gid), start, size, - p_groups, limit, errno) - - gids = [] - if res == NssReturnCode.SUCCESS: - gids_count = size[0] - assert gids_count > 0, "_nss_sss_initgroups_dyn should return " \ - "one gid" - - for i in range(0, gids_count): - gids.append(int(p_groups.contents[i])) - - # add primary group if missing - if gid not in gids: - gids.append(gid) - - return (int(res), errno[0], gids) - - -def get_user_gids(user): - """ - Function will initialize the supplementary group access list - for given user. It will gather groups only provided by sssd. - - Arguments are the same as for C function initgroups - @param string user name of user - - @return (int, int, List[int]) (err, errno, gids) - gids should contain user group IDs if err is NssReturnCode.SUCCESS - otherwise errno will contain non-zero value. - """ - pwd_user = pwd.getpwnam(user) - uid = pwd_user.pw_uid - gid = pwd_user.pw_gid - - user = pwd.getpwuid(uid).pw_name - - return call_sssd_initgroups(user, gid) - - -def gid_to_str(gid): - """ - Function will map numeric GID into names. - If there isn't a group for GID (getgrgid failed) - then the function will return decimal representation of ID. - - @param int gid ID of groups which should be converted to string. - @return string name of group with requested ID or decimal - representation of ID - """ - try: - return grp.getgrgid(gid).gr_name - except KeyError: - return str(gid) - - -def get_user_groups(user): - """ - Function will initialize the supplementary group access list - for given user. It will gather groups only provided by sssd. - - Arguments are the same as for C function initgroups - @param string user name of user - - @return (int, int, List[string]) (err, errno, groups) - groups should contain names of user groups - if err is NssReturnCode.SUCCESS - otherwise errno will contain non-zero value. - """ - (res, errno, gids) = get_user_gids(user) - groups = [] - - if res == NssReturnCode.SUCCESS: - groups = [gid_to_str(gid) for gid in gids] - - return (res, errno, groups) diff --git a/src/tests/intg/sssd_ldb.py b/src/tests/intg/sssd_ldb.py deleted file mode 100644 index 746dbfa19df..00000000000 --- a/src/tests/intg/sssd_ldb.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# SSSD integration test - access the ldb cache -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# - -import os -import ldb -import config - - -class CacheType(object): - sysdb = 1 - timestamps = 2 - - -class TsCacheEntry(object): - user = 1 - group = 2 - - -class SssdLdb(object): - def __init__(self, domain_name): - self._domain_name = domain_name - self._sysdb = self._create_dbconn(CacheType.sysdb, - domain_name) - self._timestamps = self._create_dbconn(CacheType.timestamps, - domain_name) - - def _create_dbconn(self, cache_type, domain_name): - if cache_type == CacheType.sysdb: - db_path = os.path.join(config.DB_PATH, - "cache_%s.ldb" % domain_name) - elif cache_type == CacheType.timestamps: - db_path = os.path.join(config.DB_PATH, - "timestamps_%s.ldb" % domain_name) - else: - raise ValueError("Unknown cache type\n") - - pyldb = ldb.Ldb() - pyldb.connect(db_path) - return pyldb - - def _get_dbconn(self, cache_type): - dbconn = None - if cache_type == CacheType.sysdb: - dbconn = self._sysdb - elif cache_type == CacheType.timestamps: - dbconn = self._timestamps - return dbconn - - def _entry_basedn(self, entry_type): - if entry_type == TsCacheEntry.user: - rdn = "users" - elif entry_type == TsCacheEntry.group: - rdn = "groups" - else: - raise ValueError("Unknown entry type\n") - return "cn=%s,cn=%s,cn=sysdb" % (rdn, self._domain_name) - - def _basedn(self, name, domain, entry_type): - return "name=%s@%s,%s" % (name, domain.lower(), - self._entry_basedn(entry_type)) - - def get_entry_attr(self, cache_type, entry_type, name, domain, attr): - dbconn = self._get_dbconn(cache_type) - basedn = self._basedn(name, domain, entry_type) - - res = dbconn.search(base=basedn, scope=ldb.SCOPE_BASE, attrs=[attr]) - if res.count != 1: - return None - - return res.msgs[0].get(attr).get(0) - - def invalidate_entry(self, name, entry_type, domain): - dbconn = self._get_dbconn(CacheType.timestamps) - - m = ldb.Message() - m.dn = ldb.Dn(dbconn, self._basedn(name, domain, entry_type)) - m["dataExpireTimestamp"] = ldb.MessageElement(str(1), - ldb.FLAG_MOD_REPLACE, - "dataExpireTimestamp") - dbconn.modify(m) diff --git a/src/tests/intg/sssd_netgroup.py b/src/tests/intg/sssd_netgroup.py deleted file mode 100644 index 81d017fa3dc..00000000000 --- a/src/tests/intg/sssd_netgroup.py +++ /dev/null @@ -1,247 +0,0 @@ -# -# Module for simulation of utility "getent netgroup -s sss" from coreutils -# -# Copyright (c) 2016 Red Hat, Inc. -# Author: Lukas Slebodnik -# -# 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 . -# -from ctypes import (c_int, c_char, c_char_p, c_size_t, c_void_p, c_ulong, - POINTER, Structure, Union, create_string_buffer, get_errno) -from sssd_nss import NssReturnCode, nss_sss_ctypes_loader - - -class NetgroupType(object): - """ 'enum' class for type of netgroup """ - TRIPLE_VAL = 0 - GROUP_VAL = 1 - - -class Triple(Structure): - _fields_ = [("host", c_char_p), - ("user", c_char_p), - ("domain", c_char_p)] - - -class Val(Union): - _fields_ = [("triple", Triple), - ("group", c_char_p)] - - -class Idx(Union): - _fields_ = [("cursor", POINTER(c_char)), - ("position", c_ulong)] - - -class NameList(Structure): - pass - - -NameList._fields_ = [("next", POINTER(NameList)), - ("name", POINTER(c_char))] - - -class Netgrent(Structure): - _fields_ = [("type", c_int), - ("val", Val), - ("data", POINTER(c_char)), - ("data_size", c_size_t), - ("idx", Idx), - ("first", c_int), - ("known_groups", POINTER(NameList)), - ("needed_groups", POINTER(NameList)), - ("nip", c_void_p)] - - -class NetgroupRetriever(object): - def __init__(self, name): - self.name = name.encode('utf-8') - self.needed_groups = [] - self.known_groups = [] - self.netgroups = [] - - @staticmethod - def _setnetgrent(netgroup): - """ - This private method is ctypes wrapper for - enum nss_status _nss_sss_setnetgrent(const char *netgroup, - struct __netgrent *result) - - @param string name name of netgroup - - @return (int, POINTER(Netgrent)) (err, result_p) - err is a constant from class NssReturnCode and in case of SUCCESS - result_p will contain POINTER(Netgrent) which can be used in - _getnetgrent_r or _getnetgrent_r. - """ - func = nss_sss_ctypes_loader('_nss_sss_setnetgrent') - func.restype = c_int - func.argtypes = [c_char_p, POINTER(Netgrent)] - - result = Netgrent() - result_p = POINTER(Netgrent)(result) - - res = func(c_char_p(netgroup), result_p) - - return (int(res), result_p) - - @staticmethod - def _getnetgrent_r(result_p, buff, buff_len): - """ - This private method is ctypes wrapper for - enum nss_status _nss_sss_getnetgrent_r(struct __netgrent *result, - char *buffer, size_t buflen, - int *errnop) - @param POINTER(Netgrent) result_p pointer to initialized C structure - struct __netgrent - @param ctypes.c_char_Array buff buffer used by C functions - @param int buff_len size of c_char_Array passed as a parameter buff - - @return (int, int, List[(string, string, string]) - (err, errno, netgroups) - if err is NssReturnCode.SUCCESS netgroups will contain list of - touples. Each touple will consist of 3 elements either string or - """ - func = nss_sss_ctypes_loader('_nss_sss_getnetgrent_r') - func.restype = c_int - func.argtypes = [POINTER(Netgrent), POINTER(c_char), c_size_t, - POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - res = func(result_p, buff, buff_len, errno) - - return (int(res), int(errno[0]), result_p) - - @staticmethod - def _endnetgrent(result_p): - """ - This private method is ctypes wrapper for - enum nss_status _nss_sss_endnetgrent(struct __netgrent *result) - - @param POINTER(Netgrent) result_p pointer to initialized C structure - struct __netgrent - - @return int a constant from class NssReturnCode - """ - func = nss_sss_ctypes_loader('_nss_sss_endnetgrent') - func.restype = c_int - func.argtypes = [POINTER(Netgrent)] - - res = func(result_p) - - return int(res) - - def get_netgroups(self): - """ - Function will return netgroup triplets for given user. All nested - netgroups will be retrieved as part of executions and will content - will be merged with direct triplets. - Missing nested netgroups will not cause failure and are considered - as an empty netgroup without triplets. - - @param string name name of netgroup - - @return (int, int, List[(string, string, string]) - (err, errno, netgroups) - if err is NssReturnCode.SUCCESS netgroups will contain list of - touples. Each touple will consist of 3 elements either string or - None (host, user, domain). - """ - res, errno, result = self._flat_fetch_netgroups(self.name) - if res != NssReturnCode.SUCCESS: - return (res, errno, self.netgroups) - - self.netgroups += result - - while self.needed_groups: - name = self.needed_groups.pop(0) - - nest_res, nest_errno, result = self._flat_fetch_netgroups(name) - # do not fail for missing nested netgroup - if nest_res not in (NssReturnCode.SUCCESS, NssReturnCode.NOTFOUND): - return (nest_res, nest_errno, self.netgroups) - - self.netgroups = result + self.netgroups - - return (res, errno, self.netgroups) - - def _flat_fetch_netgroups(self, name): - """ - Function will return netgroup triplets for given user. The nested - netgroups will not be returned. Missing nested netgroups will be - appended to the array needed_groups - - @param string name name of netgroup - - @return (int, int, List[(string, string, string]) - (err, errno, netgroups) - if err is NssReturnCode.SUCCESS netgroups will contain list of - touples. Each touple will consist of 3 elements either string or - None (host, user, domain). - """ - buff_len = 1024 * 1024 - buff = create_string_buffer(buff_len) - - result = [] - - res, result_p = self._setnetgrent(name) - if res != NssReturnCode.SUCCESS: - return (res, get_errno(), result) - - res, errno, result_p = self._getnetgrent_r(result_p, buff, buff_len) - while res == NssReturnCode.SUCCESS: - if result_p[0].type == NetgroupType.GROUP_VAL: - nested_netgroup = result_p[0].val.group - if nested_netgroup not in self.known_groups: - self.needed_groups.append(nested_netgroup) - self.known_groups.append(nested_netgroup) - - if result_p[0].type == NetgroupType.TRIPLE_VAL: - triple = result_p[0].val.triple - result.append((triple.host and triple.host.decode('utf-8') - or "", - triple.user and triple.user.decode('utf-8') - or "", - triple.domain and triple.domain.decode('utf-8') - or "")) - - res, errno, result_p = self._getnetgrent_r(result_p, buff, - buff_len) - - if res != NssReturnCode.RETURN: - return (res, errno, result) - - res = self._endnetgrent(result_p) - - return (res, errno, result) - - -def get_sssd_netgroups(name): - """ - Function will return netgroup triplets for given user. It will gather - netgroups only provided by sssd. - The equivalent of "getent netgroup -s sss user" - - @param string name name of netgroup - - @return (int, int, List[(string, string, string]) (err, errno, netgroups) - if err is NssReturnCode.SUCCESS netgroups will contain list of touples. - Each touple will consist of 3 elements either string or None - (host, user, domain). - """ - - retriever = NetgroupRetriever(name) - - return retriever.get_netgroups() diff --git a/src/tests/intg/sssd_nets.py b/src/tests/intg/sssd_nets.py deleted file mode 100644 index a64b5adc20e..00000000000 --- a/src/tests/intg/sssd_nets.py +++ /dev/null @@ -1,147 +0,0 @@ -# -# Module for simulation of utility "getent networks -s sss" from coreutils -# -# Authors: -# Samuel Cabrero -# -# Copyright (C) 2020 SUSE LINUX GmbH, Nuernberg, Germany. -# -# 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 . - -from ctypes import (c_int, c_char_p, c_ulong, c_uint32, POINTER, - Structure, create_string_buffer) -from sssd_nss import NssReturnCode, SssdNssError, nss_sss_ctypes_loader -import socket -from ipaddress import IPv4Address -from struct import unpack - -IP_NETWORK_BUFLEN = 1024 - - -class Netent(Structure): - _fields_ = [("n_name", c_char_p), - ("n_aliases", POINTER(c_char_p)), - ("n_addrtype", c_int), - ("n_net", c_uint32)] - - -def getnetbyname_r(name, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getnetbyname_r(const char *name, - struct netent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getnetbyname_r") - func.restype = c_int - func.argtypes = [c_char_p, POINTER(Netent), - c_char_p, c_ulong, POINTER(c_int), POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - h_errno = POINTER(c_int)(c_int(0)) - - name = name.encode('utf-8') - res = func(c_char_p(name), result_p, buffer_p, buflen, errno, h_errno) - - return (int(res), int(errno[0]), int(h_errno[0]), result_p) - - -def getnetbyaddr_r(addr, af, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getnetbyaddr_r(uint32_t addr, int type, - struct netent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getnetbyaddr_r") - func.restype = c_int - func.argtypes = [c_uint32, c_int, POINTER(Netent), - c_char_p, c_ulong, POINTER(c_int), POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - h_errno = POINTER(c_int)(c_int(0)) - - res = func(addr, af, result_p, buffer_p, buflen, errno, h_errno) - - return (int(res), int(errno[0]), int(h_errno[0]), result_p) - - -def set_netent_dict(res, result_p): - if res != NssReturnCode.SUCCESS: - return dict() - - netent_dict = dict() - netent_dict['name'] = result_p[0].n_name.decode('utf-8') - netent_dict['aliases'] = list() - netent_dict['addrtype'] = result_p[0].n_addrtype - netent_dict['address'] = result_p[0].n_net - - i = 0 - while result_p[0].n_aliases[i] is not None: - alias = result_p[0].n_aliases[i].decode('utf-8') - netent_dict['aliases'].append(alias) - i = i + 1 - - return netent_dict - - -def call_sssd_getnetbyname(name): - """ - A Python wrapper to retrieve an IP network by name. Returns: - (res, netent_dict) - if res is NssReturnCode.SUCCESS, then netent_dict contains the keys - corresponding to the C netent structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Netent() - result_p = POINTER(Netent)(result) - buff = create_string_buffer(IP_NETWORK_BUFLEN) - - (res, errno, h_errno, result_p) = getnetbyname_r(name, result_p, - buff, IP_NETWORK_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getnetbyname_r") - - netent_dict = set_netent_dict(res, result_p) - return (res, h_errno, netent_dict) - - -def call_sssd_getnetbyaddr(addrstr, af): - """ - A Python wrapper to retrieve an IP network by address. Returns: - (res, netent_dict) - if res is NssReturnCode.SUCCESS, then netent_dict contains the keys - corresponding to the C netent structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Netent() - result_p = POINTER(Netent)(result) - buff = create_string_buffer(IP_NETWORK_BUFLEN) - - if isinstance(addrstr, bytes): - addrstr = addrstr.decode('utf-8') - addr = IPv4Address(addrstr) - binaddr = unpack('. -# -import config -import ctypes - - -class NssReturnCode(object): - """ 'enum' class for name service switch return code """ - TRYAGAIN = -2, - UNAVAIL = -1 - NOTFOUND = 0 - SUCCESS = 1 - RETURN = 2 - - -class HostError(object): - """ 'enum' class for h_errno (glibc >= 2.19) """ - HOST_NOT_FOUND = 1 - TRY_AGAIN = 2 - NO_RECOVERY = 3 - NO_DATA = 4 - - @classmethod - def tostring(cls, val): - if (val == 1): - return "HOST_NOT_FOUND" - if (val == 2): - return "TRY_AGAIN" - if (val == 3): - return "NO_RECOVERY" - if (val == 4): - return "NO_DATA" - return "UNKNOWN" - - -class SssdNssError(Exception): - """ Raised when one of the NSS operations fail """ - def __init__(self, errno, nssop): - self.errno = errno - self.nssop = nssop - - def __str__(self): - return "NSS operation %s failed %d" % (self.nssop, self.errno) - - -class SssdNssHostError(Exception): - """ Raised when one of the NSS hosts operations fail """ - def __init__(self, h_errno, nssop): - self.h_errno = h_errno - self.nssop = nssop - - def __str__(self): - str_herr = HostError.tostring(self.h_errno) - return "NSS host operation %s failed: %s" % (self.nssop, str_herr) - - -def nss_sss_ctypes_loader(func_name): - libnss_sss_path = config.NSS_MODULE_DIR + "/libnss_sss.so.2" - libnss_sss = ctypes.cdll.LoadLibrary(libnss_sss_path) - func = getattr(libnss_sss, func_name) - return func diff --git a/src/tests/intg/sssd_passwd.py b/src/tests/intg/sssd_passwd.py deleted file mode 100644 index f8c91da7a0b..00000000000 --- a/src/tests/intg/sssd_passwd.py +++ /dev/null @@ -1,210 +0,0 @@ -# -# Module for simulation of utility "getent passwd -s sss" from coreutils -# -# Copyright (c) 2016 Red Hat, Inc. -# -# 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 . -# - -from ctypes import (c_int, c_char_p, c_ulong, POINTER, - Structure, create_string_buffer, get_errno) -from sssd_nss import NssReturnCode, SssdNssError, nss_sss_ctypes_loader - -PASSWD_BUFLEN = 1024 - - -class Passwd(Structure): - _fields_ = [("pw_name", c_char_p), - ("pw_passwd", c_char_p), - ("pw_uid", c_int), - ("pw_gid", c_int), - ("pw_gecos", c_char_p), - ("pw_dir", c_char_p), - ("pw_shell", c_char_p)] - - -def set_user_dict(res, result_p): - if res != NssReturnCode.SUCCESS: - return dict() - - user_dict = dict() - user_dict['name'] = result_p[0].pw_name.decode('utf-8') - user_dict['passwd'] = result_p[0].pw_passwd.decode('utf-8') - user_dict['uid'] = result_p[0].pw_uid - user_dict['gid'] = result_p[0].pw_gid - user_dict['gecos'] = result_p[0].pw_gecos.decode('utf-8') - user_dict['dir'] = result_p[0].pw_dir.decode('utf-8') - user_dict['shell'] = result_p[0].pw_shell.decode('utf-8') - return user_dict - - -def getpwnam_r(name, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getpwnam_r(const char *name, - struct passwd *result, - char *buffer, - size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getpwnam_r") - func.restype = c_int - func.argtypes = [c_char_p, POINTER(Passwd), - c_char_p, c_ulong, POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - name = name.encode('utf-8') - res = func(c_char_p(name), result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def getpwuid_r(uid, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getpwuid_r(uid_t uid, - struct passwd *result, - char *buffer, - size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getpwuid_r") - func.restype = c_int - func.argtypes = [c_ulong, POINTER(Passwd), - c_char_p, c_ulong, POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - res = func(uid, result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def setpwent(): - """ - ctypes wrapper for: - void setpwent(void) - """ - func = nss_sss_ctypes_loader("_nss_sss_setpwent") - func.argtypes = [] - - res = func() - assert res == NssReturnCode.SUCCESS - - errno = get_errno() - if errno != 0: - raise SssdNssError(errno, "setpwent") - - -def endpwent(): - """ - ctypes wrapper for: - void endpwent(void) - """ - func = nss_sss_ctypes_loader("_nss_sss_endpwent") - func.argtypes = [] - - res = func() - assert res == NssReturnCode.SUCCESS - - errno = get_errno() - if errno != 0: - raise SssdNssError(errno, "endpwent") - - -def getpwent_r(result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getpwent_r") - func.restype = c_int - func.argtypes = [POINTER(Passwd), c_char_p, c_ulong, POINTER(c_int)] - - errno = POINTER(c_int)(c_int(0)) - - res = func(result_p, buffer_p, buflen, errno) - return (int(res), int(errno[0]), result_p) - - -def getpwent(): - result = Passwd() - result_p = POINTER(Passwd)(result) - buff = create_string_buffer(PASSWD_BUFLEN) - - res, errno, result_p = getpwent_r(result_p, buff, PASSWD_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getpwent_r") - - user_dict = set_user_dict(res, result_p) - return res, user_dict - - -def call_sssd_getpwnam(name): - """ - A Python wrapper to retrieve a user by name. Returns: - (res, user_dict) - if res is NssReturnCode.SUCCESS, then user_dict contains the keys - corresponding to the C passwd structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Passwd() - result_p = POINTER(Passwd)(result) - buff = create_string_buffer(PASSWD_BUFLEN) - - res, errno, result_p = getpwnam_r(name, result_p, buff, PASSWD_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getpwnam_r") - - user_dict = set_user_dict(res, result_p) - return res, user_dict - - -def call_sssd_getpwuid(uid): - """ - A Python wrapper to retrieve a user by UID. Returns: - (res, user_dict) - if res is NssReturnCode.SUCCESS, then user_dict contains the keys - corresponding to the C passwd structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Passwd() - result_p = POINTER(Passwd)(result) - buff = create_string_buffer(PASSWD_BUFLEN) - - res, errno, result_p = getpwuid_r(uid, result_p, buff, PASSWD_BUFLEN) - if errno != 0: - raise SssdNssError(errno, "getpwuid_r") - - user_dict = set_user_dict(res, result_p) - return res, user_dict - - -def call_sssd_enumeration(): - """ - enumerate users from sssd module only - """ - setpwent() - user_list = [] - - res, user = getpwent() - while res == NssReturnCode.SUCCESS: - user_list.append(user) - res, user = getpwent() - - endpwent() - return user_list diff --git a/src/tests/intg/sssd_services.py b/src/tests/intg/sssd_services.py deleted file mode 100644 index e114cc3766e..00000000000 --- a/src/tests/intg/sssd_services.py +++ /dev/null @@ -1,163 +0,0 @@ -# -# Module for simulation of utility "getent services -s sss" from coreutils -# -# Authors: -# Samuel Cabrero -# -# Copyright (C) 2025 SUSE LINUX GmbH, Nuernberg, Germany. -# -# 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 . - -from ctypes import ( - c_int, - c_char_p, - c_ulong, - POINTER, - Structure, - create_string_buffer, -) -from sssd_nss import NssReturnCode, SssdNssError, nss_sss_ctypes_loader -import socket - -SERVICE_BUFLEN = 1024 - - -# struct servent from netdb.h -class Servent(Structure): - _fields_ = [ - ("s_name", c_char_p), - ("s_aliases", POINTER(c_char_p)), - ("s_port", c_int), - ("s_proto", c_char_p), - ] - - -def getservbyname_r(name, proto, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getservbyname_r(const char *name, - const char *protocol, - struct servent *result, - char *buffer, size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getservbyname_r") - func.restype = c_int - func.argtypes = [ - c_char_p, - c_char_p, - POINTER(Servent), - c_char_p, - c_ulong, - POINTER(c_int), - ] - - errno = POINTER(c_int)(c_int(0)) - - name = name.encode("utf-8") - proto = proto.encode("utf-8") - res = func(c_char_p(name), c_char_p(proto), result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def getservbyport_r(port, proto, result_p, buffer_p, buflen): - """ - ctypes wrapper for: - enum nss_status _nss_sss_getservbyport_r(int port, const char *protocol, - struct servent *result, - char *buffer, size_t buflen, - int *errnop) - """ - func = nss_sss_ctypes_loader("_nss_sss_getservbyport_r") - func.restype = c_int - func.argtypes = [ - c_int, - c_char_p, - POINTER(Servent), - c_char_p, - c_ulong, - POINTER(c_int), - ] - - errno = POINTER(c_int)(c_int(0)) - - port = socket.htons(port) - proto = proto.encode("utf-8") - res = func(port, c_char_p(proto), result_p, buffer_p, buflen, errno) - - return (int(res), int(errno[0]), result_p) - - -def set_servent_dict(res, result_p): - if res != NssReturnCode.SUCCESS: - return dict() - - servent_dict = dict() - servent_dict["name"] = result_p[0].s_name.decode("utf-8") - servent_dict["aliases"] = list() - servent_dict["port"] = result_p[0].s_port - servent_dict["proto"] = result_p[0].s_proto - - i = 0 - while result_p[0].s_aliases[i] is not None: - alias = result_p[0].s_aliases[i].decode("utf-8") - servent_dict["aliases"].append(alias) - i = i + 1 - - return servent_dict - - -def call_sssd_getservbyname(name, proto): - """ - A Python wrapper to retrieve a service by name and protocol. Returns: - (res, servent_dict) - if res is NssReturnCode.SUCCESS, then servent_dict contains the keys - corresponding to the C servent structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Servent() - result_p = POINTER(Servent)(result) - buff = create_string_buffer(SERVICE_BUFLEN) - - (res, errno, result_p) = getservbyname_r( - name, proto, result_p, buff, SERVICE_BUFLEN - ) - if errno != 0: - raise SssdNssError(errno, "getservbyname_r") - - servent_dict = set_servent_dict(res, result_p) - return (res, servent_dict) - - -def call_sssd_getservbyport(port, proto): - """ - A Python wrapper to retrieve a service by port and protocol. Returns: - (res, servent_dict) - if res is NssReturnCode.SUCCESS, then servent_dict contains the keys - corresponding to the C servent structure fields. Otherwise, the dictionary - is empty and errno indicates the error code - """ - result = Servent() - result_p = POINTER(Servent)(result) - buff = create_string_buffer(SERVICE_BUFLEN) - - (res, errno, result_p) = getservbyport_r( - port, proto, result_p, buff, SERVICE_BUFLEN - ) - if errno != 0: - raise SssdNssError(errno, "getservbyport_r") - - servent_dict = set_servent_dict(res, result_p) - return (res, servent_dict) diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py deleted file mode 100644 index cb864523958..00000000000 --- a/src/tests/intg/test_pam_responder.py +++ /dev/null @@ -1,993 +0,0 @@ -# -# Test for the PAM responder -# -# Copyright (c) 2018 Red Hat, Inc. -# Author: Sumit Bose -# -# 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 . -# - -""" -Tests for the PAM responder -""" -import os -import stat -import signal -import errno -import subprocess -import time - -import config -import intg.ds_openldap -import kdc - -import pytest - -from intg.util import unindent - -LDAP_BASE_DN = "dc=example,dc=com" - -def provider_list(): - # The comma is required to indicate a list with the string 'proxy' as - # only item, without it the string 'proxy' will be interpreted as list - # with five letters. - return ('proxy',) - - -class provider_switch: - def __init__(self, p): - if p == 'proxy': - self.p = "id_provider = proxy\nlocal_auth_policy = only\nproxy_lib_name = call\n" - elif p == 'proxy_password': - self.p = "id_provider = proxy\nproxy_lib_name = call\nproxy_pam_target = sssd-shadowutils\n" - elif p == 'proxy_password_with_sc': - self.p = "id_provider = proxy\nlocal_auth_policy = enable:smartcard\nproxy_lib_name = call\nproxy_pam_target = sssd-shadowutils\n" - else: - self.p = none - - -@pytest.fixture(scope="module") -def ad_inst(request): - """Fake AD server instance fixture""" - instance = intg.ds_openldap.FakeAD( - config.PREFIX, 10389, LDAP_BASE_DN, - "cn=admin", "Secret123" - ) - - try: - instance.setup() - except Exception: - instance.teardown() - raise - request.addfinalizer(instance.teardown) - return instance - - -@pytest.fixture(scope="module") -def ldap_conn(request, ad_inst): - """LDAP server connection fixture""" - ldap_conn = ad_inst.bind() - ldap_conn.ad_inst = ad_inst - request.addfinalizer(ldap_conn.unbind_s) - return ldap_conn - - -def format_basic_conf(ldap_conn): - """Format a basic SSSD configuration""" - return unindent("""\ - [sssd] - domains = FakeAD - services = pam, nss - - [nss] - - [pam] - debug_level = 10 - - [domain/FakeAD] - debug_level = 10 - ldap_search_base = {ldap_conn.ad_inst.base_dn} - ldap_referrals = false - - id_provider = ldap - auth_provider = ldap - chpass_provider = ldap - access_provider = ldap - - ldap_uri = {ldap_conn.ad_inst.ldap_url} - ldap_default_bind_dn = {ldap_conn.ad_inst.admin_dn} - ldap_default_authtok_type = password - ldap_default_authtok = {ldap_conn.ad_inst.admin_pw} - - ldap_schema = ad - ldap_id_mapping = true - ldap_idmap_default_domain_sid = S-1-5-21-1305200397-2901131868-73388776 - case_sensitive = False - - [prompting/password] - password_prompt = My global prompt - - [prompting/password/pam_sss_alt_service] - password_prompt = My alt service prompt - """).format(**locals()) - -USER1 = dict(name='user1', passwd='x', uid=10001, gid=20001, - gecos='User for tests', - dir='/home/user1', - shell='/bin/bash') - -USER2 = dict(name='user2', passwd='x', uid=10002, gid=20002, - gecos='User with no Smartcard mapping', - dir='/home/user2', - shell='/bin/bash') - - -def format_pam_cert_auth_conf(config, provider): - """Format a basic SSSD configuration""" - return unindent("""\ - [sssd] - debug_level = 10 - domains = auth_only - services = pam, nss - - [nss] - debug_level = 10 - - [pam] - pam_cert_auth = True - pam_p11_allowed_services = +pam_sss_service, +pam_sss_sc_required, \ - +pam_sss_try_sc, +pam_sss_allow_missing_name - pam_cert_db_path = {config.PAM_CERT_DB_PATH} - p11_uri = pkcs11:manufacturer=SoftHSM%20project; \ - token=SSSD%20Test%20Token - p11_child_timeout = 5 - p11_wait_for_card_timeout = 5 - debug_level = 10 - - [domain/auth_only] - debug_level = 10 - {provider.p} - - [certmap/auth_only/abc] - matchrule = .*CN=SSSD test cert 000[12].* - maprule = LDAPU1:(user1) - """).format(**locals()) - - -def format_pam_cert_auth_conf_name_format(config, provider): - """Format SSSD configuration with full_name_format""" - return unindent("""\ - [sssd] - debug_level = 10 - domains = auth_only - services = pam, nss - - [nss] - debug_level = 10 - - [pam] - pam_cert_auth = True - pam_p11_allowed_services = +pam_sss_service, +pam_sss_sc_required, \ - +pam_sss_try_sc, +pam_sss_allow_missing_name - pam_cert_db_path = {config.PAM_CERT_DB_PATH} - p11_uri = pkcs11:manufacturer=SoftHSM%20project; \ - token=SSSD%20Test%20Token - p11_child_timeout = 5 - p11_wait_for_card_timeout = 5 - debug_level = 10 - - [domain/auth_only] - use_fully_qualified_names = True - full_name_format = %2$s\\%1$s - debug_level = 10 - {provider.p} - - [certmap/auth_only/user1] - matchrule = .*CN=SSSD test cert 000[12].* - """).format(**locals()) - - -def format_pam_krb5_auth(config, kdc_instance): - """Format SSSD configuration for krb5 authentication""" - return unindent("""\ - [sssd] - debug_level = 10 - domains = krb5_auth - services = pam, nss - - [nss] - debug_level = 10 - - [pam] - debug_level = 10 - - [domain/krb5_auth] - debug_level = 10 - id_provider = proxy - proxy_lib_name = call - auth_provider = krb5 - - krb5_realm = PAMKRB5TEST - krb5_server = localhost:{kdc_instance.kdc_port} - """).format(**locals()) - - -def format_pam_krb5_auth_domains(config, kdc_instance): - """Format SSSD configuration for krb5 authentication""" - return unindent("""\ - [sssd] - debug_level = 10 - domains = wrong.dom1, wrong.dom2, krb5_auth, wrong.dom3 - services = pam, nss - - [nss] - debug_level = 10 - - [pam] - debug_level = 10 - - [domain/wrong.dom1] - debug_level = 10 - id_provider = proxy - proxy_lib_name = call - auth_provider = krb5 - - krb5_realm = WRONG1REALM - krb5_server = localhost:{kdc_instance.kdc_port} - - [domain/wrong.dom2] - debug_level = 10 - id_provider = proxy - proxy_lib_name = call - auth_provider = krb5 - - krb5_realm = WRONG2REALM - krb5_server = localhost:{kdc_instance.kdc_port} - - [domain/wrong.dom3] - debug_level = 10 - id_provider = proxy - proxy_lib_name = call - auth_provider = krb5 - - krb5_realm = WRONG3REALM - krb5_server = localhost:{kdc_instance.kdc_port} - - [domain/krb5_auth] - debug_level = 10 - id_provider = proxy - proxy_lib_name = call - auth_provider = krb5 - - krb5_realm = PAMKRB5TEST - krb5_server = localhost:{kdc_instance.kdc_port} - """).format(**locals()) - - -def create_conf_file(contents): - """Create sssd.conf with specified contents""" - conf = open(config.CONF_PATH, "w") - conf.write(contents) - conf.close() - os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR) - - -def create_conf_fixture(request, contents): - """ - Create sssd.conf with specified contents and add teardown for removing it - """ - create_conf_file(contents) - - def cleanup_conf_file(): - """Remove sssd.conf, if it exists""" - if os.path.lexists(config.CONF_PATH): - os.unlink(config.CONF_PATH) - - request.addfinalizer(cleanup_conf_file) - - -def create_sssd_process(krb5_conf_path=None): - """Start the SSSD process""" - my_env = os.environ.copy() - my_env["SSS_FILES_PASSWD"] = os.environ["NSS_WRAPPER_PASSWD"] - my_env["SSS_FILES_GROUP"] = os.environ["NSS_WRAPPER_GROUP"] - my_env['SSSD_INTG_PEER_UID'] = "0" - my_env['SSSD_INTG_PEER_GID'] = "0" - if krb5_conf_path is not None: - my_env['KRB5_CONFIG'] = krb5_conf_path - if subprocess.call(["sssd", "-D", "--logger=files"], env=my_env) != 0: - raise Exception("sssd start failed") - - -def cleanup_sssd_process(): - """Stop the SSSD process and remove its state""" - try: - with open(config.PIDFILE_PATH, "r") as pid_file: - pid = int(pid_file.read()) - os.kill(pid, signal.SIGTERM) - while True: - try: - os.kill(pid, signal.SIGCONT) - except OSError: - break - time.sleep(1) - except OSError: - pass - for path in os.listdir(config.DB_PATH): - os.unlink(config.DB_PATH + "/" + path) - for path in os.listdir(config.MCACHE_PATH): - os.unlink(config.MCACHE_PATH + "/" + path) - - # make sure that the indicator file is removed during shutdown - try: - assert not os.stat(config.PUBCONF_PATH + "/pam_preauth_available") - except OSError as ex: - if ex.errno != errno.ENOENT: - raise ex - - -def create_sssd_fixture(request, krb5_conf_path=None): - """Start SSSD and add teardown for stopping it and removing its state""" - create_sssd_process(krb5_conf_path) - request.addfinalizer(cleanup_sssd_process) - - -@pytest.fixture -def simple_pam_cert_auth(request, passwd_ops_setup): - """Setup SSSD with pam_cert_auth=True""" - config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] - conf = format_pam_cert_auth_conf(config, provider_switch(request.param)) - create_conf_fixture(request, conf) - create_sssd_fixture(request) - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - - return None - - -@pytest.fixture -def simple_pam_cert_auth_no_cert(request, passwd_ops_setup): - """Setup SSSD with pam_cert_auth=True""" - config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] - - old_softhsm2_conf = os.environ['SOFTHSM2_CONF'] - del os.environ['SOFTHSM2_CONF'] - - conf = format_pam_cert_auth_conf(config, provider_switch(request.param)) - create_conf_fixture(request, conf) - create_sssd_fixture(request) - - os.environ['SOFTHSM2_CONF'] = old_softhsm2_conf - - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - - return None - - -@pytest.fixture -def simple_pam_cert_auth_two_certs(request, passwd_ops_setup): - """Setup SSSD with pam_cert_auth=True""" - config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] - - old_softhsm2_conf = os.environ['SOFTHSM2_CONF'] - softhsm2_two_conf = os.environ['SOFTHSM2_TWO_CONF'] - os.environ['SOFTHSM2_CONF'] = softhsm2_two_conf - - conf = format_pam_cert_auth_conf(config, provider_switch(request.param)) - create_conf_fixture(request, conf) - create_sssd_fixture(request) - - os.environ['SOFTHSM2_CONF'] = old_softhsm2_conf - - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - - return None - - -@pytest.fixture -def simple_pam_cert_auth_name_format(request, passwd_ops_setup): - """Setup SSSD with pam_cert_auth=True and full_name_format""" - config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] - conf = format_pam_cert_auth_conf_name_format(config, provider_switch(request.param)) - create_conf_fixture(request, conf) - create_sssd_fixture(request) - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - - return None - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_preauth_indicator(simple_pam_cert_auth): - """Check if preauth indicator file is created""" - statinfo = os.stat(config.PUBCONF_PATH + "/pam_preauth_available") - assert stat.S_ISREG(statinfo.st_mode) - - -@pytest.fixture -def pam_prompting_config(request, ldap_conn): - """Setup SSSD with PAM prompting config""" - conf = format_basic_conf(ldap_conn) - create_conf_fixture(request, conf) - create_sssd_fixture(request) - return None - - -def test_password_prompting_config_global(ldap_conn, pam_prompting_config, - env_for_sssctl): - """Check global change of the password prompt""" - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1_dom1-19661", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="111") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("My global prompt") != -1 - - -def test_password_prompting_config_srv(ldap_conn, pam_prompting_config, - env_for_sssctl): - """Check change of the password prompt for dedicated service""" - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1_dom1-19661", - "--action=auth", - "--service=pam_sss_alt_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="111") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("My alt service prompt") != -1 - - -@pytest.fixture -def env_for_sssctl(request): - pwrap_runtimedir = os.getenv("PAM_WRAPPER_SERVICE_DIR") - if pwrap_runtimedir is None: - raise ValueError("The PAM_WRAPPER_SERVICE_DIR variable is unset\n") - - env_for_sssctl = os.environ.copy() - env_for_sssctl['PAM_WRAPPER'] = "1" - env_for_sssctl['SSSD_INTG_PEER_UID'] = "0" - env_for_sssctl['SSSD_INTG_PEER_GID'] = "0" - env_for_sssctl['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH'] - - return env_for_sssctl - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_sc_auth_wrong_pin(simple_pam_cert_auth, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="111") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: " - "Authentication failure") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_sc_auth(simple_pam_cert_auth, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth_two_certs', provider_list(), indirect=True) -def test_sc_auth_two(simple_pam_cert_auth_two_certs, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="2\n123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth_two_certs', provider_list(), indirect=True) -def test_sc_auth_two_missing_name(simple_pam_cert_auth_two_certs, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "", - "--action=auth", "--service=pam_sss_allow_missing_name"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="2\n123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', ['proxy_password'], indirect=True) -def test_sc_proxy_password_fallback(simple_pam_cert_auth, env_for_sssctl): - """ - Check that there will be a password prompt if another proxy auth module is - configured and Smartcard authentication is not allowed but a Smartcard is - present. - """ - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - assert err.find("Password:") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', ['proxy_password_with_sc'], - indirect=True) -def test_sc_proxy_no_password_fallback(simple_pam_cert_auth, env_for_sssctl): - """ - Use the same environ as for test_sc_proxy_password_fallback but now allow - local Smartcard authentication. Here we expect that there will be a prompt - for the Smartcard PIN and that Smartcard authentication is successful. - """ - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_require_sc_auth(simple_pam_cert_auth, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", - "--service=pam_sss_sc_required"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth_no_cert', provider_list(), indirect=True) -def test_require_sc_auth_no_cert(simple_pam_cert_auth_no_cert, env_for_sssctl): - - # We have to wait about 20s before the command returns because there will - # be 2 run since retry=1 in the PAM configuration and both - # p11_child_timeout and p11_wait_for_card_timeout are 5s in sssd.conf, - # so 2*(5+5)=20. */ - start_time = time.time() - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", - "--service=pam_sss_sc_required"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - end_time = time.time() - assert end_time > start_time and \ - (end_time - start_time) >= 20 and \ - (end_time - start_time) < 40 - assert out.find("Please insert smart card\nPlease insert smart card") != -1 - assert err.find("pam_authenticate for user [user1]: Authentication " - "service cannot retrieve authentication info") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_try_sc_auth_no_map(simple_pam_cert_auth, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user2", - "--action=auth", - "--service=pam_sss_try_sc"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user2]: Authentication " - "service cannot retrieve authentication info") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_try_sc_auth(simple_pam_cert_auth, env_for_sssctl): - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", - "--service=pam_sss_try_sc"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_try_sc_auth_root(simple_pam_cert_auth, env_for_sssctl): - """ - Make sure pam_sss returns PAM_AUTHINFO_UNAVAIL even for root if - try_cert_auth is set. - """ - sssctl = subprocess.Popen(["sssctl", "user-checks", "root", - "--action=auth", - "--service=pam_sss_try_sc"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [root]: Authentication " - "service cannot retrieve authentication info") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_sc_auth_missing_name(simple_pam_cert_auth, env_for_sssctl): - """ - Test pam_sss allow_missing_name feature. - """ - - sssctl = subprocess.Popen(["sssctl", "user-checks", "", - "--action=auth", - "--service=pam_sss_allow_missing_name"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth', provider_list(), indirect=True) -def test_sc_auth_missing_name_whitespace(simple_pam_cert_auth, env_for_sssctl): - """ - Test pam_sss allow_missing_name feature. - """ - - sssctl = subprocess.Popen(["sssctl", "user-checks", " ", - "--action=auth", - "--service=pam_sss_allow_missing_name"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find("pam_authenticate for user [user1]: Success") != -1 - - -@pytest.mark.parametrize('simple_pam_cert_auth_name_format', provider_list(), indirect=True) -def test_sc_auth_name_format(simple_pam_cert_auth_name_format, env_for_sssctl): - """ - Test that full_name_format is respected with pam_sss allow_missing_name - option. - """ - - sssctl = subprocess.Popen(["sssctl", "user-checks", "", - "--action=auth", - "--service=pam_sss_allow_missing_name"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="123456") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find(r"pam_authenticate for user [auth_only\user1]: " - "Success") != -1 - - -@pytest.fixture -def kdc_instance(request): - """Kerberos server instance fixture""" - kdc_instance = kdc.KDC(config.PREFIX, "PAMKRB5TEST") - try: - kdc_instance.set_up() - kdc_instance.start_kdc() - except Exception: - kdc_instance.teardown() - raise - request.addfinalizer(kdc_instance.teardown) - return kdc_instance - - -@pytest.fixture -def setup_krb5(request, kdc_instance, passwd_ops_setup): - """ - Setup SSSD for Kerberos authentication with 2 users with different - passwords - """ - conf = format_pam_krb5_auth(config, kdc_instance) - create_conf_fixture(request, conf) - create_sssd_fixture(request, kdc_instance.krb5_conf_path) - - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - kdc_instance.add_principal("user1", "Secret123User1") - kdc_instance.add_principal("user2", "Secret123User2") - time.sleep(2) # Give KDC time to initialize - return None - - -def test_krb5_auth(setup_krb5, env_for_sssctl): - """ - Test basic Kerberos authentication, check for authentication failure when - a wrong password is used - """ - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", - "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="Secret123User1") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find(r"pam_authenticate for user [user1]: Success") != -1 - - sssctl = subprocess.Popen(["sssctl", "user-checks", "user2", - "--action=auth", - "--service=pam_sss_service"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="Secret123User1") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find(r"pam_authenticate for user [user2]: " - "Authentication failure") != -1 - - -@pytest.fixture -def setup_krb5_domains(request, kdc_instance, passwd_ops_setup): - """ - Setup SSSD for Kerberos authentication with 2 users with different - passwords and multiple domains configured in sssd.conf - """ - conf = format_pam_krb5_auth_domains(config, kdc_instance) - create_conf_fixture(request, conf) - create_sssd_fixture(request, kdc_instance.krb5_conf_path) - - passwd_ops_setup.useradd(**USER1) - passwd_ops_setup.useradd(**USER2) - kdc_instance.add_principal("user1", "Secret123User1") - kdc_instance.add_principal("user2", "Secret123User2") - return None - - -def test_krb5_auth_domains(setup_krb5_domains, env_for_sssctl): - """ - Test basic Kerberos authentication with pam_sss 'domains' option, make - sure not-matching domains are skipped even if the user exists in that - domain - """ - sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", - "--action=auth", - "--service=pam_sss_domains"], - universal_newlines=True, - env=env_for_sssctl, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - try: - out, err = sssctl.communicate(input="Secret123User1") - except Exception: - sssctl.kill() - out, err = sssctl.communicate() - - sssctl.stdin.close() - sssctl.stdout.close() - - if sssctl.wait() != 0: - raise Exception("sssctl failed") - - assert err.find(r"pam_authenticate for user [user1]: Success") != -1 diff --git a/src/tests/intg/util.py b/src/tests/intg/util.py deleted file mode 100644 index 543bfe4892d..00000000000 --- a/src/tests/intg/util.py +++ /dev/null @@ -1,107 +0,0 @@ -# -# Various functions -# -# Copyright (c) 2015 Red Hat, Inc. -# Author: Nikolai Kondrashov -# -# 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 . -# - -import re -import os -import sys -import subprocess -import config -import shutil - -UNINDENT_RE = re.compile("^ +", re.MULTILINE) - - -def unindent(text): - """ - Unindent text by removing at most the number of spaces present in - the first non-empty line from the beginning of every line. - """ - indent_ref = [0] - - def replace(match): - if indent_ref[0] == 0: - indent_ref[0] = len(match.group()) - return match.group()[indent_ref[0]:] - return UNINDENT_RE.sub(replace, text) - - -def run_shell(): - """ - Execute an interactive shell under "screen", preserving environment. - For use as a breakpoint for debugging. - """ - my_env = os.environ.copy() - my_env["ROOT_DIR"] = config.PREFIX - - # screen filter out LD_* evniroment varibles. - # Back-up them and set them later in screenrc - my_env["_LD_LIBRARY_PATH"] = os.getenv("LD_LIBRARY_PATH", "") - my_env["_LD_PRELOAD"] = os.getenv("LD_PRELOAD", "") - - subprocess.call([ - "screen", "-DAm", "-S", "sssd_cwrap_session", "-c", - ".config/screenrc"], - env=my_env - ) - - -def first_dir(*args): - """Return first argument that points to an existing directory.""" - for arg in args: - if os.path.isdir(arg): - return arg - - -def backup_envvar_file(name): - path = os.environ[name] - backup_path = path + ".bak" - shutil.copyfile(path, backup_path) - return path - - -def restore_envvar_file(name): - path = os.environ[name] - backup_path = path + ".bak" - os.rename(backup_path, path) - - -def get_call_output(cmd, stderr_output=subprocess.PIPE, check=False, custom_env=None): - """ - Executes the provided command. - When check is set to True, this function will throw an exception - if the command returns with a non-zero value. - """ - - if (sys.version_info.major < 3 - or (sys.version_info.major == 3 and sys.version_info.minor < 7)): - try: - output = subprocess.check_output(cmd, universal_newlines=True, - stderr=stderr_output, env=custom_env) - except subprocess.CalledProcessError as err: - if (not check): - output = err.output - else: - raise err - return output - - process = subprocess.run(cmd, check=check, text=True, - stdout=subprocess.PIPE, stderr=stderr_output, - env=custom_env) - return process.stdout diff --git a/src/tests/system/tests/test_authentication.py b/src/tests/system/tests/test_authentication.py index 277f1454184..5362039fb05 100644 --- a/src/tests/system/tests/test_authentication.py +++ b/src/tests/system/tests/test_authentication.py @@ -7,11 +7,15 @@ from __future__ import annotations import re +import textwrap +from inspect import cleandoc import pytest from sssd_test_framework.roles.client import Client from sssd_test_framework.roles.generic import GenericProvider +from sssd_test_framework.roles.ipa import IPA from sssd_test_framework.roles.kdc import KDC +from sssd_test_framework.roles.samba import Samba from sssd_test_framework.topology import KnownTopology, KnownTopologyGroup @@ -375,3 +379,142 @@ def test_ensure_localauth_plugin_is_not_configured(client: Client, provider: Gen with pytest.raises(Exception): client.fs.read("/var/lib/sss/pubconf/krb5.include.d/localauth_plugin") + + +@pytest.mark.importance("medium") +@pytest.mark.topology(KnownTopologyGroup.AnyProvider) +@pytest.mark.parametrize( + "prompting_section", + ["prompting/password", "prompting/password/su-l"], + ids=["global_prompt", "service_prompt"], +) +def test_authentication__custom_password_prompt_is_shown_at_login( + client: Client, provider: GenericProvider, prompting_section: str +): + """ + :title: Custom password prompt text is shown at login + :description: + 'su -' uses the 'su-l' PAM service, so the per-service case targets + '[prompting/password/su-l]', not '[prompting/password/su]'. + :setup: + 1. Create user + 2. Set a custom 'password_prompt', either globally or for the 'su -' PAM service ('su-l') + 3. Start SSSD + :steps: + 1. Authenticate as the user via 'su -' + :expectedresults: + 1. The custom prompt text is shown and authentication succeeds + :customerscenario: True + """ + provider.user("user1").add(password="Secret123") + client.sssd.section(prompting_section)["password_prompt"] = "My custom prompt" + client.sssd.start() + + result = client.host.conn.run("su - user1 -c 'su - user1 -c whoami'", input="Secret123") + assert "My custom prompt" in result.stderr, "Custom password prompt was not shown!" + assert "user1" in result.stdout, "'user1' failed to log in!" + + +@pytest.mark.importance("medium") +@pytest.mark.authentication +@pytest.mark.topology(KnownTopology.ALLREALMS) +def test_authentication__pam_sss_domains_skips_non_matching_krb5_domains( + client: Client, samba: Samba, ipa: IPA, kdc: KDC +): + """ + :title: pam_sss.so 'domains' authenticates only against the listed Kerberos realm domain + :description: + Local users may authenticate via Kerberos against one of several configured realms + (Samba, IPA, or a standalone KDC). The same username exists in every realm with a + different password. Each PAM 'domains=' line restricts SSSD to that domain only, so + earlier lines fail with the wrong password and PAM falls through until the matching + domain succeeds (try-and-error via the domains option). + :setup: + 1. Add a local user and create 'user1' in the Samba, IPA, and KDC realms with + different passwords + 2. Configure three SSSD domains (samba, ipa, krb5) with id_provider=proxy/files and + auth_provider=krb5 using each provider's realm + 3. Replace 'su-l' with three 'sufficient' pam_sss.so lines, each limited by 'domains=' + :steps: + 1. Authenticate as the local user via 'su -' using the Samba password and run klist + 2. Authenticate as the local user via 'su -' using the IPA password and run klist + 3. Authenticate as the local user via 'su -' using the KDC password and run klist + :expectedresults: + 1. Authentication succeeds via 'domains=samba' and the TGT realm is the Samba realm + 2. Authentication succeeds via 'domains=ipa' (after Samba fails) and the TGT realm is + the IPA realm + 3. Authentication succeeds via 'domains=krb5' (after Samba and IPA fail) and the TGT + realm is the KDC realm + :customerscenario: True + """ + client.local.user("user1").add(password="LocalSecret123") + samba.user("user1").add(password="SambaSecret123") + ipa.user("user1").add(password="IPASecret123") + kdc.principal("user1").add(password="KDCSecret123") + + client.sssd.fs.write( + "/etc/krb5.conf", + textwrap.dedent(f""" + [libdefaults] + default_realm = {kdc.realm} + dns_lookup_realm = false + dns_lookup_kdc = false + ticket_lifetime = 24h + renew_lifetime = 7d + forwardable = yes + + [realms] + {samba.realm} = {{ + kdc = {samba.host.hostname} + }} + {ipa.realm} = {{ + kdc = {ipa.host.hostname} + }} + {kdc.realm} = {{ + kdc = {kdc.host.hostname}:88 + admin_server = {kdc.host.hostname}:749 + }} + """).lstrip(), + user="root", + group="root", + mode="0644", + ) + + for name, role in (("samba", samba), ("ipa", ipa), ("krb5", kdc)): + client.sssd.dom(name).update( + enabled="true", + id_provider="proxy", + proxy_lib_name="files", + auth_provider="krb5", + krb5_realm=role.realm, + krb5_server=role.host.hostname, + ) + client.sssd.sssd["domains"] = "samba, ipa, krb5" + client.sssd.default_domain = "krb5" + client.sssd.start() + + client.fs.backup("/etc/pam.d/su-l") + client.fs.write( + "/etc/pam.d/su-l", + cleandoc(""" + auth required pam_env.so + auth sufficient pam_sss.so forward_pass domains=samba + auth sufficient pam_sss.so forward_pass domains=ipa + auth sufficient pam_sss.so forward_pass domains=krb5 + auth required pam_deny.so + account required pam_sss.so + password required pam_sss.so + session required pam_sss.so + """), + ) + + for password, realm, domain in ( + ("SambaSecret123", samba.realm, "samba"), + ("IPASecret123", ipa.realm, "ipa"), + ("KDCSecret123", kdc.realm, "krb5"), + ): + result = client.host.conn.run("su - user1 -c klist", input=password, raise_on_error=False) + assert result.rc == 0, f"Authentication with the {domain} password failed!" + assert ( + f"krbtgt/{realm}@{realm}" in result.stdout + ), f"TGT should come from the {domain} realm ({realm}) when authenticating with that realm's password!" diff --git a/src/tests/system/tests/test_smartcard.py b/src/tests/system/tests/test_smartcard.py index 2d7f7e5f60d..41b3fac94a7 100644 --- a/src/tests/system/tests/test_smartcard.py +++ b/src/tests/system/tests/test_smartcard.py @@ -7,7 +7,6 @@ from __future__ import annotations import pytest -from pytest_mh.cli import CLIBuilderArgs from sssd_test_framework.roles.client import Client from sssd_test_framework.roles.ipa import IPA from sssd_test_framework.topology import KnownTopology @@ -337,60 +336,367 @@ def test_smartcard__unlock_console_with_vlock(client: Client): client.local.user(username).add() client.smartcard.setup_local_card(client, username) - cli = client.host.cli - args: CLIBuilderArgs = { - "login": (cli.option.SWITCH, True), - "user": (cli.option.POSITIONAL, username), - } - su_cmd = " ".join(cli.argv("su", args)) - - result = client.host.conn.expect( - rf""" - proc exitmsg {{ msg code }} {{ - catch close - lassign [wait] pid spawnid os_error_flag rc - puts "" - puts "expect result: $msg" - puts "expect exit code: $code" - puts "expect spawn exit code: $rc" - exit $code - }} - - set timeout 60 - spawn {su_cmd} - - expect {{ - "$ " {{ }} - timeout {{exitmsg "No shell prompt after su" 201}} - eof {{exitmsg "Unexpected end of file after su" 202}} - }} - - send "vlock\r" - - expect {{ - "PIN for" {{send "wrongpin\r"}} - timeout {{exitmsg "No PIN prompt from vlock" 201}} - eof {{exitmsg "Unexpected end of file during vlock" 202}} - }} - - expect {{ - "PIN for" {{send "{TOKEN_PIN}\r"}} - "$ " {{exitmsg "vlock unlocked with wrong PIN" 1}} - timeout {{exitmsg "No re-prompt after wrong PIN" 201}} - eof {{exitmsg "Unexpected end of file after wrong PIN" 202}} - }} - - expect {{ - "$ " {{exitmsg "vlock unlock successful" 0}} - timeout {{exitmsg "Timeout after vlock unlock" 201}} - eof {{exitmsg "Unexpected end of file after vlock" 202}} - }} - - exitmsg "Unexpected code path" 203 + assert client.auth.su.vlock_smartcard(username, TOKEN_PIN), "vlock smartcard authentication failed" + + +@pytest.mark.importance("high") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__login_fails_when_wrong_pin_is_entered(client: Client): + """ + :title: Smartcard login fails when the wrong pin is entered. + :setup: + 1. Create a local user and initialize a smart card mapped to the user + :steps: + 1. Authenticate as the user via 'su' with an incorrect PIN + :expectedresults: + 1. Authentication fails + :customerscenario: True + """ + client.local.user("user1").add() + client.smartcard.setup_local_card(client, "user1") + + assert not client.auth.su.smartcard("user1", "000000"), "Authentication should have failed with a wrong PIN!" + + +@pytest.mark.importance("medium") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__login_fails_when_card_is_not_mapped(client: Client): + """ + :title: Smartcard authentication fails when card is not mapped to the user + :setup: + 1. Create two local users and initialize a smart card mapped to only the first user + :steps: + 1. Authenticate as the first user via 'su' with the smart card PIN + 2. Attempt to authenticate as the second user via 'su' with the same smart card PIN + :expectedresults: + 1. Authentication succeeds using the certificate + 2. Authentication fails because the certificate does not map to the second user + :customerscenario: True + """ + client.local.user("user1").add() + client.local.user("user2").add() + client.smartcard.setup_local_card(client, "user1") + + assert client.auth.su.smartcard("user1", TOKEN_PIN), "Smart card authentication failed for the mapped user!" + assert not client.auth.su.smartcard( + "user2", TOKEN_PIN + ), "Authentication should fail for a user the certificate does not map to!" + + +@pytest.mark.importance("high") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.parametrize( + "pam_p11_allowed_services, expect_cert_auth", + [(None, True), ("-su-l", False)], + ids=["su_l_allowed_by_default", "su_l_removed_from_allowed_services"], +) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__certificate_authentication_is_limited_to_allowed_pam_services( + client: Client, pam_p11_allowed_services: str | None, expect_cert_auth: bool +): + """ + :title: Smartcard authentication is only used for PAM services allowed by pam_p11_allowed_services + :setup: + 1. Optionally remove the 'su-l' service (used by ``su -``) from 'pam_p11_allowed_services' + 2. Create a local user and initialize a smart card mapped to the user + :steps: + 1. Authenticate as the user via 'su -' presenting the smart card PIN + :expectedresults: + 1. Authentication uses the certificate when 'su-l' is an allowed service; when it is not, + 'su -' does not prompt for a PIN and the PIN is rejected as a regular password + :customerscenario: True + """ + client.local.user("user1").add() + if pam_p11_allowed_services is not None: + client.sssd.pam["pam_p11_allowed_services"] = pam_p11_allowed_services + client.smartcard.setup_local_card(client, "user1") + + result = client.auth.su.smartcard_with_output("user1", TOKEN_PIN) + if expect_cert_auth: + assert result.rc == 0, "Smart card authentication should have succeeded!" + assert "PIN" in result.stderr, "'su -' should have prompted for a PIN!" + else: + assert "PIN" not in result.stderr, "'su -' should not prompt for a PIN when it is not an allowed service!" + assert result.rc != 0, f"'{TOKEN_PIN}' should not be accepted as user1's login password!" + + +@pytest.mark.importance("high") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__login_succeeds_when_cert_auth_required(client: Client): + """ + :title: Smartcard login succeeds when certificate authentication is required + :setup: + 1. Create a local user and initialize a smart card mapped to the user + 2. Require certificate-based authentication (authselect 'with-smartcard-required') + :steps: + 1. Authenticate as the user via ``sssctl user-checks`` with the ``login`` PAM + service and the smart card PIN + :expectedresults: + 1. Authentication succeeds + :customerscenario: True + """ + client.local.user("user1").add() + client.smartcard.setup_local_card(client, "user1") + client.authselect.select("sssd", ["with-smartcard-required"]) + + result = client.sssctl.user_checks("user1", action="auth", service="login", auth_input=TOKEN_PIN) + assert "pam_authenticate for user [user1]: Success" in result.stderr + + +@pytest.mark.importance("medium") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__login_fails_when_cert_auth_required_without_card(client: Client): + """ + :title: Smartcard login fails when certificate authentication is required and no card is present + :setup: + 1. Create a local user + 2. Reduce the smart card wait timeouts + 3. Initialize a smart card mapped to the user and require certificate-based + authentication (authselect 'with-smartcard-required') + 4. Remove the smart card + :steps: + 1. Attempt to authenticate as the user via ``sssctl user-checks`` with the + ``login`` PAM service + :expectedresults: + 1. Authentication fails because no smart card was inserted before the timeout + :customerscenario: True + """ + client.local.user("user1").add() + client.sssd.pam["p11_child_timeout"] = "1" + client.sssd.pam["p11_wait_for_card_timeout"] = "1" + client.smartcard.setup_local_card(client, "user1") + client.authselect.select("sssd", ["with-smartcard-required"]) + client.smartcard.remove_card() + + result = client.sssctl.user_checks("user1", action="auth", service="login", auth_input=TOKEN_PIN) + assert ( + "Authentication service cannot retrieve authentication info" in result.stderr + ), "Authentication should have failed without a card!" + + +@pytest.mark.importance("critical") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__try_cert_auth_never_used_for_root(client: Client): + """ + :title: try_cert_auth never routes root's own login through certificate authentication + :description: + pam_sss.so unconditionally refuses to handle the 'root' identity. When 'try_cert_auth' + is set, that refusal must surface as PAM_AUTHINFO_UNAVAIL (so the PAM stack falls back + to another module), not as a successful or user-unknown result. This is verified via + 'sssctl user-checks' against a minimal 'auth required pam_sss.so try_cert_auth' service, + since there is no way to originate a fresh authentication attempt for the 'root' identity + itself via 'su'/'ssh' (root already owns the control connection). + :setup: + 1. Create a local user and initialize a smart card mapped to the user + 2. Install a minimal PAM service with 'pam_sss.so try_cert_auth' + :steps: + 1. Run 'sssctl user-checks root' against that service + :expectedresults: + 1. Authentication is reported unavailable, never routed through certificate auth + :customerscenario: True + """ + client.local.user("user1").add() + client.smartcard.setup_local_card(client, "user1") + client.fs.write( + "/etc/pam.d/pam_sss_try_sc", + """ + auth required pam_sss.so try_cert_auth + account required pam_sss.so + password required pam_sss.so + session required pam_sss.so """, - verbose=False, ) + result = client.sssctl.user_checks("root", action="auth", service="pam_sss_try_sc", auth_input=TOKEN_PIN) + assert ( + "pam_authenticate for user [root]: Authentication service cannot retrieve authentication info" in result.stderr + ), f"root should never be routed through certificate authentication! stderr={result.stderr}" + + +@pytest.mark.importance("high") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.parametrize("username_input", ["", " "], ids=["empty_name", "whitespace_only_name"]) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__certificate_owner_resolved_when_username_is_missing(client: Client, username_input: str): + """ + :title: allow_missing_name resolves the certificate owner when no username is given + :setup: + 1. Create a local user and initialize a smart card mapped to the user + :steps: + 1. Authenticate against the 'smartcard-auth' service with an empty or + whitespace-only username and the smart card PIN + :expectedresults: + 1. Authentication succeeds and is resolved to the certificate's mapped user + :customerscenario: True + """ + client.local.user("user1").add() + client.smartcard.setup_local_card(client, "user1") + client.authselect.select("sssd", ["with-smartcard-required"]) + client.sssd.pam["pam_p11_allowed_services"] = "+smartcard-auth" + client.sssd.restart() + + result = client.sssctl.user_checks(username_input, action="auth", service="smartcard-auth", auth_input=TOKEN_PIN) + assert ( + "pam_authenticate for user [user1]: Success" in result.stderr + ), f"Certificate owner was not resolved! stderr={result.stderr}" + + +@pytest.mark.importance("medium") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +def test_smartcard__certificate_owner_resolved_with_full_name_format(client: Client): + """ + :title: allow_missing_name respects full_name_format when resolving the certificate owner + :setup: + 1. Create a local user and initialize a smart card mapped to the user + 2. Enable fully-qualified names with a custom 'full_name_format' + :steps: + 1. Authenticate against the 'smartcard-auth' service with no username and the smart card PIN + :expectedresults: + 1. Authentication succeeds and the resolved user name matches 'full_name_format' + :customerscenario: True + """ + client.local.user("user1").add() + client.smartcard.setup_local_card(client, "user1") + client.authselect.select("sssd", ["with-smartcard-required"]) + client.sssd.pam["pam_p11_allowed_services"] = "+smartcard-auth" + client.sssd.domain["use_fully_qualified_names"] = "True" + client.sssd.domain["full_name_format"] = "%2$s\\%1$s" + client.sssd.restart(clean=True) + + result = client.sssctl.user_checks("", action="auth", service="smartcard-auth", auth_input=TOKEN_PIN) assert ( - result.rc == 0 - ), f"vlock smartcard authentication failed: rc={result.rc}, stdout={result.stdout}, stderr={result.stderr}" + "pam_authenticate for user [local\\user1]: Success" in result.stderr + ), f"Certificate owner was not resolved with full_name_format applied! stderr={result.stderr}" + + +@pytest.mark.importance("medium") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.parametrize("cert_selection", [1, 2]) +def test_smartcard__certificate_owner_resolved_with_two_tokens_and_missing_name(client: Client, cert_selection: int): + """ + :title: allow_missing_name resolves the certificate owner when two tokens are present + :setup: + 1. Create a local user + 2. Reset the certificate CA trust store to a clean state + 3. Initialize two SoftHSM tokens, each holding a certificate mapped to the user, + and trust both certificates in the CA trust store + 4. Configure SSSD for smart card authentication and start services + :steps: + 1. Authenticate against the 'smartcard-auth' service with no username, selecting + each certificate in turn + :expectedresults: + 1. Authentication succeeds and is resolved to the certificate's mapped user for + either certificate selection + :customerscenario: True + """ + username = "user1" + client.local.user(username).add() + client.host.fs.rm("/etc/sssd/pki/sssd_auth_ca_db.pem") + + key1, cert1 = client.smartcard.generate_cert(key_path="/tmp/sc_token1.key", cert_path="/tmp/sc_token1.crt") + client.smartcard.initialize_card(label=TOKEN1_LABEL, user_pin=TOKEN_PIN, reset=True) + client.smartcard.add_key(key1, token_label=TOKEN1_LABEL, label=username) + client.smartcard.add_cert(cert1, token_label=TOKEN1_LABEL, label=username) + key2, cert2 = client.smartcard.generate_cert(key_path="/tmp/sc_token2.key", cert_path="/tmp/sc_token2.crt") + client.smartcard.initialize_card(label=TOKEN2_LABEL, user_pin=TOKEN_PIN, reset=False) + client.smartcard.add_key(key2, token_label=TOKEN2_LABEL, label=username) + client.smartcard.add_cert(cert2, token_label=TOKEN2_LABEL, label=username) + + client.sssd.common.local() + client.sssd.section(f"certmap/local/{username}")["matchrule"] = ".*CN=Test Cert.*" + client.sssd.pam["pam_cert_auth"] = "True" + for cert in (cert1, cert2): + # dedent=False is required here: fs.append() strips trailing whitespace, + # by default which will corrupt the CA bundle. + client.host.fs.append( + "/etc/sssd/pki/sssd_auth_ca_db.pem", client.host.fs.read(cert).strip() + "\n", dedent=False + ) + client.sssd.common.smartcard_with_softhsm(client.smartcard) + client.authselect.select("sssd", ["with-smartcard-required", "with-mkhomedir"]) + client.sssd.pam["pam_p11_allowed_services"] = "+smartcard-auth" + client.sssd.restart() + + result = client.sssctl.user_checks( + "", action="auth", service="smartcard-auth", auth_input=f"{cert_selection}\n{TOKEN_PIN}" + ) + assert ( + f"pam_authenticate for user [{username}]: Success" in result.stderr + ), f"Certificate owner was not resolved! stderr={result.stderr}" + + +@pytest.mark.importance("high") +@pytest.mark.topology(KnownTopology.Client) +@pytest.mark.builtwith(client="virtualsmartcard") +@pytest.mark.parametrize( + "local_auth_policy, auth_input, expected", + [ + (None, None, "Password:"), + ("enable:smartcard", TOKEN_PIN, "pam_authenticate for user [user1]: Success"), + ], + ids=["password_fallback_when_smartcard_not_enabled", "smartcard_when_local_auth_policy_enables_it"], +) +def test_smartcard__proxy_auth_uses_password_or_smartcard_based_on_local_auth_policy( + client: Client, local_auth_policy: str | None, auth_input: str | None, expected: str +): + """ + :title: Proxy domain falls back to password unless local smartcard auth is enabled + :description: + With a smart card present, a proxy domain only offers password auth by default + (``local_auth_policy`` match). Enabling ``enable:smartcard`` switches the prompt + to the smart card PIN and authenticates with the certificate. + :setup: + 1. Create a local user with a password + 2. Enroll a smart card certificate mapped to the user + 3. Install a minimal PAM service that only stacks ``pam_sss.so`` + :steps: + 1. Configure a proxy/files domain with ``pam_cert_auth`` and the parametrized + ``local_auth_policy``, then start SSSD + 2. Authenticate via ``sssctl user-checks`` against that PAM service + :expectedresults: + 1. SSSD starts with the requested local authentication policy + 2. Without smartcard enabled a password prompt is shown; with + ``enable:smartcard`` authentication succeeds with the PIN + :customerscenario: True + :requirement: smartcard_authentication + """ + client.local.user("user1").add(password="Secret123") + + client.host.fs.rm("/etc/sssd/pki/sssd_auth_ca_db.pem") + key, cert = client.smartcard.generate_cert() + client.smartcard.initialize_card() + client.smartcard.add_key(key) + client.smartcard.add_cert(cert) + client.authselect.select("sssd", ["with-smartcard"]) + client.svc.restart("virt_cacard.service") + + client.fs.write( + "/etc/pam.d/pam_sss_service", + """ + auth required pam_sss.so + account required pam_sss.so + password required pam_sss.so + session required pam_sss.so + """, + ) + + client.sssd.common.local() + if local_auth_policy is not None: + client.sssd.dom("local")["local_auth_policy"] = local_auth_policy + client.sssd.section("certmap/local/user1")["matchrule"] = ".*CN=Test Cert.*" + client.sssd.pam["pam_cert_auth"] = "True" + client.sssd.pam["pam_p11_allowed_services"] = "+pam_sss_service" + client.host.fs.append("/etc/sssd/pki/sssd_auth_ca_db.pem", client.host.fs.read(cert), dedent=False) + client.sssd.start() + + result = client.host.conn.exec( + ["sssctl", "user-checks", "user1", "-a", "auth", "-s", "pam_sss_service"], + input=auth_input, + raise_on_error=False, + ) + assert expected in result.stderr, f"Unexpected authentication prompt or result! stderr={result.stderr}" diff --git a/src/tests/test_CA/SSSD_test_cert_0001.config b/src/tests/test_CA/SSSD_test_cert_0001.config index d59023ca665..ce593ae5ea1 100644 --- a/src/tests/test_CA/SSSD_test_cert_0001.config +++ b/src/tests/test_CA/SSSD_test_cert_0001.config @@ -1,7 +1,6 @@ # This certificate is used in # - src/tests/cmocka/test_cert_utils.c # - src/tests/cmocka/test_pam_srv.c -# - src/tests/intg/test_infopipe.py [ req ] distinguished_name = req_distinguished_name prompt = no