Blame SOURCES/0042-intg-require-SC-tests.patch

71e593
From 0c56f4aee8115081cf0ee32cceb8c1dc56945e6f Mon Sep 17 00:00:00 2001
71e593
From: Sumit Bose <sbose@redhat.com>
71e593
Date: Wed, 26 Sep 2018 11:48:37 +0200
71e593
Subject: [PATCH 42/47] intg: require SC tests
71e593
71e593
Integration test for the new try_cert_auth and require_cert_auth option
71e593
for pam_sss.
71e593
71e593
Related to https://pagure.io/SSSD/sssd/issue/3650
71e593
71e593
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
71e593
(cherry picked from commit 5cdb6968f407c7bcaba69f4892f51fd6426dddb2)
71e593
---
71e593
 src/tests/intg/Makefile.am           |  16 ++-
71e593
 src/tests/intg/test_pam_responder.py | 188 +++++++++++++++++++++++++++++++----
71e593
 2 files changed, 182 insertions(+), 22 deletions(-)
71e593
71e593
diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
71e593
index bb3a7f01ae4f79fa05cd661993e8f9872ecd0450..44fb6353ad031fc9edac291ce70aa7557999509d 100644
71e593
--- a/src/tests/intg/Makefile.am
71e593
+++ b/src/tests/intg/Makefile.am
71e593
@@ -113,6 +113,20 @@ pam_sss_service:
71e593
 	echo "password required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
 	echo "session  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
 
71e593
+pam_sss_sc_required:
71e593
+	$(MKDIR_P) $(PAM_SERVICE_DIR)
71e593
+	echo "auth     required       $(DESTDIR)$(pammoddir)/pam_sss.so require_cert_auth retry=1"  > $(PAM_SERVICE_DIR)/$@
71e593
+	echo "account  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+	echo "password required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+	echo "session  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+
71e593
+pam_sss_try_sc:
71e593
+	$(MKDIR_P) $(PAM_SERVICE_DIR)
71e593
+	echo "auth     required       $(DESTDIR)$(pammoddir)/pam_sss.so try_cert_auth"  > $(PAM_SERVICE_DIR)/$@
71e593
+	echo "account  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+	echo "password required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+	echo "session  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
71e593
+
71e593
 CLEANFILES=config.py config.pyc passwd group
71e593
 
71e593
 clean-local:
71e593
@@ -127,7 +141,7 @@ PAM_CERT_DB_PATH="$(abs_builddir)/../test_CA/SSSD_test_CA.pem"
71e593
 SOFTHSM2_CONF="$(abs_builddir)/../test_CA/softhsm2_one.conf"
71e593
 endif
71e593
 
71e593
-intgcheck-installed: config.py passwd group pam_sss_service
71e593
+intgcheck-installed: config.py passwd group pam_sss_service pam_sss_sc_required pam_sss_try_sc
71e593
 	pipepath="$(DESTDIR)$(pipepath)"; \
71e593
 	if test $${#pipepath} -gt 80; then \
71e593
 	    echo "error: Pipe directory path too long," \
71e593
diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py
71e593
index c6d048cd342838fe312287eaffff734e30ba9e1c..06f69a3d82f5502fd5ae1928d81db0287e582e88 100644
71e593
--- a/src/tests/intg/test_pam_responder.py
71e593
+++ b/src/tests/intg/test_pam_responder.py
71e593
@@ -41,6 +41,11 @@ USER1 = dict(name='user1', passwd='x', uid=10001, gid=20001,
71e593
              dir='/home/user1',
71e593
              shell='/bin/bash')
71e593
 
71e593
+USER2 = dict(name='user2', passwd='x', uid=10002, gid=20002,
71e593
+             gecos='User with no Smartcard mapping',
71e593
+             dir='/home/user2',
71e593
+             shell='/bin/bash')
71e593
+
71e593
 
71e593
 def format_pam_cert_auth_conf(config):
71e593
     """Format a basic SSSD configuration"""
71e593
@@ -55,8 +60,11 @@ def format_pam_cert_auth_conf(config):
71e593
 
71e593
         [pam]
71e593
         pam_cert_auth = True
71e593
-        pam_p11_allowed_services = +pam_sss_service
71e593
+        pam_p11_allowed_services = +pam_sss_service, +pam_sss_sc_required, \
71e593
+                                   +pam_sss_try_sc
71e593
         pam_cert_db_path = {config.PAM_CERT_DB_PATH}
71e593
+        p11_child_timeout = 5
71e593
+        p11_wait_for_card_timeout = 5
71e593
         debug_level = 10
71e593
 
71e593
         [domain/auth_only]
71e593
@@ -149,6 +157,15 @@ def create_nssdb():
71e593
     pkcs11_txt.close()
71e593
 
71e593
 
71e593
+def create_nssdb_no_cert():
71e593
+    os.mkdir(config.SYSCONFDIR + "/pki")
71e593
+    os.mkdir(config.SYSCONFDIR + "/pki/nssdb")
71e593
+    if subprocess.call(["certutil", "-N", "-d",
71e593
+                        "sql:" + config.SYSCONFDIR + "/pki/nssdb/",
71e593
+                        "--empty-password"]) != 0:
71e593
+        raise Exception("certutil failed")
71e593
+
71e593
+
71e593
 def cleanup_nssdb():
71e593
     shutil.rmtree(config.SYSCONFDIR + "/pki")
71e593
 
71e593
@@ -158,14 +175,42 @@ def create_nssdb_fixture(request):
71e593
     request.addfinalizer(cleanup_nssdb)
71e593
 
71e593
 
71e593
+def create_nssdb_no_cert_fixture(request):
71e593
+    create_nssdb_no_cert()
71e593
+    request.addfinalizer(cleanup_nssdb)
71e593
+
71e593
+
71e593
 @pytest.fixture
71e593
-def simple_pam_cert_auth(request):
71e593
+def simple_pam_cert_auth(request, passwd_ops_setup):
71e593
     """Setup SSSD with pam_cert_auth=True"""
71e593
     config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH']
71e593
     conf = format_pam_cert_auth_conf(config)
71e593
     create_conf_fixture(request, conf)
71e593
     create_sssd_fixture(request)
71e593
     create_nssdb_fixture(request)
71e593
+    passwd_ops_setup.useradd(**USER1)
71e593
+    passwd_ops_setup.useradd(**USER2)
71e593
+    return None
71e593
+
71e593
+
71e593
+@pytest.fixture
71e593
+def simple_pam_cert_auth_no_cert(request, passwd_ops_setup):
71e593
+    """Setup SSSD with pam_cert_auth=True"""
71e593
+    config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH']
71e593
+
71e593
+    old_softhsm2_conf = os.environ['SOFTHSM2_CONF']
71e593
+    del os.environ['SOFTHSM2_CONF']
71e593
+
71e593
+    conf = format_pam_cert_auth_conf(config)
71e593
+    create_conf_fixture(request, conf)
71e593
+    create_sssd_fixture(request)
71e593
+    create_nssdb_no_cert_fixture(request)
71e593
+
71e593
+    os.environ['SOFTHSM2_CONF'] = old_softhsm2_conf
71e593
+
71e593
+    passwd_ops_setup.useradd(**USER1)
71e593
+    passwd_ops_setup.useradd(**USER2)
71e593
+
71e593
     return None
71e593
 
71e593
 
71e593
@@ -176,26 +221,26 @@ def test_preauth_indicator(simple_pam_cert_auth):
71e593
 
71e593
 
71e593
 @pytest.fixture
71e593
-def pam_wrapper_setup(request):
71e593
+def env_for_sssctl(request):
71e593
     pwrap_runtimedir = os.getenv("PAM_WRAPPER_SERVICE_DIR")
71e593
     if pwrap_runtimedir is None:
71e593
         raise ValueError("The PAM_WRAPPER_SERVICE_DIR variable is unset\n")
71e593
 
71e593
+    env_for_sssctl = os.environ.copy()
71e593
+    env_for_sssctl['PAM_WRAPPER'] = "1"
71e593
+    env_for_sssctl['SSSD_INTG_PEER_UID'] = "0"
71e593
+    env_for_sssctl['SSSD_INTG_PEER_GID'] = "0"
71e593
+    env_for_sssctl['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH']
71e593
 
71e593
-def test_sc_auth_wrong_pin(simple_pam_cert_auth, pam_wrapper_setup,
71e593
-                           passwd_ops_setup):
71e593
+    return env_for_sssctl
71e593
 
71e593
-    passwd_ops_setup.useradd(**USER1)
71e593
-    current_env = os.environ.copy()
71e593
-    current_env['PAM_WRAPPER'] = "1"
71e593
-    current_env['SSSD_INTG_PEER_UID'] = "0"
71e593
-    current_env['SSSD_INTG_PEER_GID'] = "0"
71e593
-    current_env['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH']
71e593
+
71e593
+def test_sc_auth_wrong_pin(simple_pam_cert_auth, env_for_sssctl):
71e593
 
71e593
     sssctl = subprocess.Popen(["sssctl", "user-checks", "user1",
71e593
                                "--action=auth", "--service=pam_sss_service"],
71e593
                               universal_newlines=True,
71e593
-                              env=current_env, stdin=subprocess.PIPE,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
 
71e593
     try:
71e593
@@ -214,19 +259,120 @@ def test_sc_auth_wrong_pin(simple_pam_cert_auth, pam_wrapper_setup,
71e593
                     "Authentication failure") != -1
71e593
 
71e593
 
71e593
-def test_sc_auth(simple_pam_cert_auth, pam_wrapper_setup, passwd_ops_setup):
71e593
-
71e593
-    passwd_ops_setup.useradd(**USER1)
71e593
-    current_env = os.environ.copy()
71e593
-    current_env['PAM_WRAPPER'] = "1"
71e593
-    current_env['SSSD_INTG_PEER_UID'] = "0"
71e593
-    current_env['SSSD_INTG_PEER_GID'] = "0"
71e593
-    current_env['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH']
71e593
+def test_sc_auth(simple_pam_cert_auth, env_for_sssctl):
71e593
 
71e593
     sssctl = subprocess.Popen(["sssctl", "user-checks", "user1",
71e593
                                "--action=auth", "--service=pam_sss_service"],
71e593
                               universal_newlines=True,
71e593
-                              env=current_env, stdin=subprocess.PIPE,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
+                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
+
71e593
+    try:
71e593
+        out, err = sssctl.communicate(input="123456")
71e593
+    except:
71e593
+        sssctl.kill()
71e593
+        out, err = sssctl.communicate()
71e593
+
71e593
+    sssctl.stdin.close()
71e593
+    sssctl.stdout.close()
71e593
+
71e593
+    if sssctl.wait() != 0:
71e593
+        raise Exception("sssctl failed")
71e593
+
71e593
+    assert err.find("pam_authenticate for user [user1]: Success") != -1
71e593
+
71e593
+
71e593
+def test_require_sc_auth(simple_pam_cert_auth, env_for_sssctl):
71e593
+
71e593
+    sssctl = subprocess.Popen(["sssctl", "user-checks", "user1",
71e593
+                               "--action=auth",
71e593
+                               "--service=pam_sss_sc_required"],
71e593
+                              universal_newlines=True,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
+                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
+
71e593
+    try:
71e593
+        out, err = sssctl.communicate(input="123456")
71e593
+    except:
71e593
+        sssctl.kill()
71e593
+        out, err = sssctl.communicate()
71e593
+
71e593
+    sssctl.stdin.close()
71e593
+    sssctl.stdout.close()
71e593
+
71e593
+    if sssctl.wait() != 0:
71e593
+        raise Exception("sssctl failed")
71e593
+
71e593
+    assert err.find("pam_authenticate for user [user1]: Success") != -1
71e593
+
71e593
+
71e593
+def test_require_sc_auth_no_cert(simple_pam_cert_auth_no_cert, env_for_sssctl):
71e593
+
71e593
+    # We have to wait about 20s before the command returns because there will
71e593
+    # be 2 run since retry=1 in the PAM configuration and both
71e593
+    # p11_child_timeout and p11_wait_for_card_timeout are 5s in sssd.conf,
71e593
+    # so 2*(5+5)=20. */
71e593
+    start_time = time.time()
71e593
+    sssctl = subprocess.Popen(["sssctl", "user-checks", "user1",
71e593
+                               "--action=auth",
71e593
+                               "--service=pam_sss_sc_required"],
71e593
+                              universal_newlines=True,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
+                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
+
71e593
+    try:
71e593
+        out, err = sssctl.communicate(input="123456")
71e593
+    except:
71e593
+        sssctl.kill()
71e593
+        out, err = sssctl.communicate()
71e593
+
71e593
+    sssctl.stdin.close()
71e593
+    sssctl.stdout.close()
71e593
+
71e593
+    if sssctl.wait() != 0:
71e593
+        raise Exception("sssctl failed")
71e593
+
71e593
+    end_time = time.time()
71e593
+    assert end_time > start_time and \
71e593
+        (end_time - start_time) >= 20 and \
71e593
+        (end_time - start_time) < 40
71e593
+    assert out.find("Please enter smart card\nPlease enter smart card") != -1
71e593
+    assert err.find("pam_authenticate for user [user1]: Authentication " +
71e593
+                    "service cannot retrieve authentication info") != -1
71e593
+
71e593
+
71e593
+def test_try_sc_auth_no_map(simple_pam_cert_auth, env_for_sssctl):
71e593
+
71e593
+    sssctl = subprocess.Popen(["sssctl", "user-checks", "user2",
71e593
+                               "--action=auth",
71e593
+                               "--service=pam_sss_try_sc"],
71e593
+                              universal_newlines=True,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
+                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
+
71e593
+    try:
71e593
+        out, err = sssctl.communicate(input="123456")
71e593
+    except:
71e593
+        sssctl.kill()
71e593
+        out, err = sssctl.communicate()
71e593
+
71e593
+    sssctl.stdin.close()
71e593
+    sssctl.stdout.close()
71e593
+
71e593
+    if sssctl.wait() != 0:
71e593
+        raise Exception("sssctl failed")
71e593
+
71e593
+    assert err.find("pam_authenticate for user [user2]: Authentication " +
71e593
+                    "service cannot retrieve authentication info") != -1
71e593
+
71e593
+
71e593
+def test_try_sc_auth(simple_pam_cert_auth, env_for_sssctl):
71e593
+
71e593
+    sssctl = subprocess.Popen(["sssctl", "user-checks", "user1",
71e593
+                               "--action=auth",
71e593
+                               "--service=pam_sss_try_sc"],
71e593
+                              universal_newlines=True,
71e593
+                              env=env_for_sssctl, stdin=subprocess.PIPE,
71e593
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
71e593
 
71e593
     try:
71e593
-- 
71e593
2.14.4
71e593