URL: https://github.com/SSSD/sssd/pull/5918
Author: ikerexxe
 Title: #5918: Client ca validation error
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5918/head:pr5918
git checkout pr5918
From 9ae8af9a597acd8ca84bdeadee1edb9011fa0c43 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedr...@redhat.com>
Date: Fri, 10 Dec 2021 14:28:13 +0100
Subject: [PATCH 1/2] man: update ifp options for FindByValidCertificate

Include a reference to ca_db, p11_child_timeout and
certificate_verification in sssd-ifp man page. These options can used be
to control how the certificates are validated with
FindByValidCertificate() API.

Signed-off-by: Iker Pedrosa <ipedr...@redhat.com>
---
 src/man/sssd-ifp.5.xml | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/man/sssd-ifp.5.xml b/src/man/sssd-ifp.5.xml
index c787ef9d4d..d3080537a6 100644
--- a/src/man/sssd-ifp.5.xml
+++ b/src/man/sssd-ifp.5.xml
@@ -38,6 +38,22 @@
             to query information about remote users and groups over the
             system bus.
         </para>
+
+    <refsect2 id='valid_certificate'>
+        <title>FIND BY VALID CERTIFICATE</title>
+        <para>
+            The following options can be used to control how the certificates
+            are validated when using the FindByValidCertificate() API:
+            <itemizedlist>
+                <listitem><para>ca_db</para></listitem>
+                <listitem><para>p11_child_timeout</para></listitem>
+                <listitem><para>certificate_verification</para></listitem>
+            </itemizedlist>
+            For more details about the options see
+            <citerefentry><refentrytitle>sssd.conf</refentrytitle>
+            <manvolnum>5</manvolnum></citerefentry>.
+        </para>
+    </refsect2>
     </refsect1>
 
     <refsect1 id='configuration-options'>

From 51e68dedb5ffd0c1a00aee34e2b76dd03306ad6b Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedr...@redhat.com>
Date: Fri, 10 Dec 2021 11:20:23 +0100
Subject: [PATCH 2/2] ifp: improve FindByValidCertificate() error

Improve the error handling for FindByValidCertificate() by returning a
specific exception ID when the certificate authority file is missing.
Moreover, the log lines have been changed to point to p11_child logs
when an unknown error happens.

Finally, a new test case has been created for the certificate authority
file missing situation.

Resolves: https://github.com/SSSD/sssd/issues/5911

Signed-off-by: Iker Pedrosa <ipedr...@redhat.com>
---
 src/p11_child/p11_child_common.c  |  9 ++++--
 src/p11_child/p11_child_openssl.c | 14 +++++++--
 src/responder/ifp/ifp_users.c     | 15 ++++++++--
 src/sbus/sbus_errors.c            |  1 +
 src/sbus/sbus_errors.h            |  1 +
 src/tests/intg/test_infopipe.py   | 47 ++++++++++++++++++++++++++++++-
 src/util/child_common.h           |  1 -
 src/util/util.h                   |  6 +++-
 src/util/util_errors.c            |  2 ++
 src/util/util_errors.h            |  2 ++
 10 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/src/p11_child/p11_child_common.c b/src/p11_child/p11_child_common.c
index 7c8259479d..4bcaaf6e80 100644
--- a/src/p11_child/p11_child_common.c
+++ b/src/p11_child/p11_child_common.c
@@ -147,7 +147,7 @@ int main(int argc, const char *argv[])
     poptContext pc;
     int debug_fd = -1;
     const char *opt_logger = NULL;
-    errno_t ret;
+    errno_t ret = 0;
     TALLOC_CTX *main_ctx = NULL;
     enum op_mode mode = OP_NONE;
     enum pin_mode pin_mode = PIN_NONE;
@@ -382,5 +382,10 @@ int main(int argc, const char *argv[])
     DEBUG(SSSDBG_CRIT_FAILURE, "p11_child failed!\n");
     close(STDOUT_FILENO);
     talloc_free(main_ctx);
-    return EXIT_FAILURE;
+
+    if (ret == ERR_CA_DB_NOT_FOUND) {
+        return CA_DB_NOT_FOUND_EXIT_CODE;
+    } else {
+        return EXIT_FAILURE;
+    }
 }
diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index de5d583a0e..d4a890a2b4 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -667,9 +667,17 @@ errno_t init_verification(struct p11_ctx *p11_ctx,
 
     if (!X509_LOOKUP_load_file(lookup, p11_ctx->ca_db, X509_FILETYPE_PEM)) {
         err = ERR_get_error();
-        DEBUG(SSSDBG_OP_FAILURE, "X509_LOOKUP_load_file failed [%lu][%s].\n",
-                                 err, ERR_error_string(err, NULL));
-        ret = EIO;
+        DEBUG(SSSDBG_OP_FAILURE,
+              "X509_LOOKUP_load_file [%s] failed [%lu][%s].\n",
+              p11_ctx->ca_db, err, ERR_error_string(err, NULL));
+
+        if (ERR_GET_LIB(err) == ERR_LIB_SYS &&
+            ERR_GET_REASON(err) == ENOENT) {
+            ret = ERR_CA_DB_NOT_FOUND;
+        } else {
+            ret = EIO;
+        }
+
         goto done;
     }
 
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index 8746b25034..ba9ca5ad4a 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -1254,15 +1254,24 @@ ifp_users_find_by_valid_cert_step(int child_status,
     PIPE_FD_CLOSE(state->io->write_to_child_fd);
 
     if (WIFEXITED(child_status)) {
-        if (WEXITSTATUS(child_status) != 0) {
+        if (WEXITSTATUS(child_status) == CA_DB_NOT_FOUND_EXIT_CODE) {
             DEBUG(SSSDBG_OP_FAILURE,
-                  P11_CHILD_PATH " failed with status [%d]\n", child_status);
+                  P11_CHILD_PATH " failed [%d]: [%s].\n",
+                  ERR_CA_DB_NOT_FOUND, sss_strerror(ERR_CA_DB_NOT_FOUND));
+            tevent_req_error(req, ERR_CA_DB_NOT_FOUND);
+            return;
+        } else if (WEXITSTATUS(child_status) != 0) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  P11_CHILD_PATH " failed with status [%d]. Check p11_child"
+                  " logs for more information.\n",
+                  WEXITSTATUS(child_status));
             tevent_req_error(req, ERR_INVALID_CERT);
             return;
         }
     } else if (WIFSIGNALED(child_status)) {
         DEBUG(SSSDBG_OP_FAILURE,
-              P11_CHILD_PATH " was terminated by signal [%d]\n",
+              P11_CHILD_PATH " was terminated by signal [%d]. Check p11_child"
+              " logs for more information.\n",
               WTERMSIG(child_status));
         tevent_req_error(req, ECHILD);
         return;
diff --git a/src/sbus/sbus_errors.c b/src/sbus/sbus_errors.c
index 63c67dd5c9..c6449dd87e 100644
--- a/src/sbus/sbus_errors.c
+++ b/src/sbus/sbus_errors.c
@@ -34,6 +34,7 @@ static const struct {
     { SBUS_ERROR_INTERNAL,          ERR_INTERNAL },
     { SBUS_ERROR_NOT_FOUND,         ENOENT },
     { SBUS_ERROR_KILLED,            ERR_SBUS_KILL_CONNECTION },
+    { SBUS_ERROR_NO_CA,             ERR_CA_DB_NOT_FOUND},
 
     /* D-Bus standard errors. Some errno values may overlap, but when
      * finding its D-Bus pair the first match is returned. */
diff --git a/src/sbus/sbus_errors.h b/src/sbus/sbus_errors.h
index f970be7950..e005f05d12 100644
--- a/src/sbus/sbus_errors.h
+++ b/src/sbus/sbus_errors.h
@@ -31,6 +31,7 @@
 #define SBUS_ERROR_INTERNAL         "sbus.Error.Internal"
 #define SBUS_ERROR_NOT_FOUND        "sbus.Error.NotFound"
 #define SBUS_ERROR_KILLED           "sbus.Error.ConnectionKilled"
+#define SBUS_ERROR_NO_CA            "sbus.Error.NoCA"
 #define SBUS_ERROR_ERRNO            "sbus.Error.Errno"
 
 errno_t sbus_error_to_errno(DBusError *error);
diff --git a/src/tests/intg/test_infopipe.py b/src/tests/intg/test_infopipe.py
index d493a94514..1ca2076b27 100644
--- a/src/tests/intg/test_infopipe.py
+++ b/src/tests/intg/test_infopipe.py
@@ -32,6 +32,7 @@
 import pytest
 import dbus
 import base64
+import shutil
 
 import config
 import ds_openldap
@@ -313,6 +314,34 @@ def create_sssd_fixture(request):
     create_sssd_cleanup(request)
 
 
+def backup_ca_db():
+    """Create backup file for ca db"""
+    src = os.path.dirname(config.PAM_CERT_DB_PATH) + "/SSSD_test_CA.pem"
+    dst = os.path.dirname(config.PAM_CERT_DB_PATH) + "/SSSD_test_CA.pem.bp"
+    shutil.copyfile(src, dst)
+
+
+def restore_ca_db():
+    """Restore backup file for ca db"""
+    src = os.path.dirname(config.PAM_CERT_DB_PATH) + "/SSSD_test_CA.pem.bp"
+    dst = os.path.dirname(config.PAM_CERT_DB_PATH) + "/SSSD_test_CA.pem"
+    shutil.copyfile(src, dst)
+    os.remove(src)
+
+
+def create_restore_ca_db(request):
+    """Add teardown for restoring ca_db"""
+    request.addfinalizer(restore_ca_db)
+
+
+def create_ca_db_fixture(request):
+    """
+    Create backup for ca_db and add teardown for restoring it
+    """
+    backup_ca_db()
+    create_restore_ca_db(request)
+
+
 @pytest.fixture
 def sanity_rfc2307(request, ldap_conn):
     ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
@@ -335,6 +364,7 @@ def sanity_rfc2307(request, ldap_conn):
     conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307, config)
     create_conf_fixture(request, conf)
     create_sssd_fixture(request)
+    create_ca_db_fixture(request)
     return None
 
 
@@ -348,6 +378,7 @@ def simple_rfc2307(request, ldap_conn):
     conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307, config)
     create_conf_fixture(request, conf)
     create_sssd_fixture(request)
+    create_ca_db_fixture(request)
     return None
 
 
@@ -371,6 +402,7 @@ def auto_private_groups_rfc2307(request, ldap_conn):
         """).format(**locals())
     create_conf_fixture(request, conf)
     create_sssd_fixture(request)
+    create_ca_db_fixture(request)
     return None
 
 
@@ -398,6 +430,7 @@ def add_user_with_cert(request, ldap_conn):
     conf = format_certificate_conf(ldap_conn, SCHEMA_RFC2307_BIS, config)
     create_conf_fixture(request, conf)
     create_sssd_fixture(request)
+    create_ca_db_fixture(request)
 
     return None
 
@@ -743,7 +776,6 @@ def test_find_by_valid_certificate(dbus_system_bus,
         assert str(ex) == "sbus.Error.NotFound: No such file or directory"
 
     # Valid certificate from another CA
-    print(os.environ['ABS_SRCDIR'])
     cert_file = os.environ['ABS_SRCDIR'] + \
         "/../test_ECC_CA/SSSD_test_ECC_cert_key_0001.pem"
     with open(cert_file, "r") as f:
@@ -763,3 +795,16 @@ def test_find_by_valid_certificate(dbus_system_bus,
     except dbus.exceptions.DBusException as ex:
         error = "org.freedesktop.DBus.Error.IOError: Input/output error"
         assert str(ex) == error
+
+    # Remove certificate db
+    cert_db = cert_path + "/SSSD_test_CA.pem"
+    os.remove(cert_db)
+    cert_file = cert_path + "/SSSD_test_cert_x509_0002.pem"
+    with open(cert_file, "r") as f:
+        cert = f.read()
+    try:
+        res = users_iface.FindByValidCertificate(cert)
+        assert False, "Previous call should raise an exception"
+    except dbus.exceptions.DBusException as ex:
+        assert str(ex) == \
+            "sbus.Error.NoCA: Certificate authority file not found"
diff --git a/src/util/child_common.h b/src/util/child_common.h
index 92d66a5009..6dab2f5e91 100644
--- a/src/util/child_common.h
+++ b/src/util/child_common.h
@@ -36,7 +36,6 @@
 #define CHILD_MSG_CHUNK     256
 
 #define SIGTERM_TO_SIGKILL_TIME 2
-#define CHILD_TIMEOUT_EXIT_CODE 7
 
 struct response {
     uint8_t *buf;
diff --git a/src/util/util.h b/src/util/util.h
index 6dfd2540cc..2d99a29c2b 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -114,7 +114,11 @@ extern int dbus_activated;
 #define FLAGS_GEN_CONF 0x0008
 #define FLAGS_NO_WATCHDOG 0x0010
 
-#define SSS_WATCHDOG_EXIT_CODE 70 /* to match EX_SOFTWARE in sysexits.h */
+enum sssd_exit_status {
+    CHILD_TIMEOUT_EXIT_CODE = 7,
+    CA_DB_NOT_FOUND_EXIT_CODE = 50,
+    SSS_WATCHDOG_EXIT_CODE = 70 /* to match EX_SOFTWARE in sysexits.h */
+};
 
 #define PIPE_INIT { -1, -1 }
 
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 882c0b4aa3..4132040c48 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -146,6 +146,8 @@ struct err_string error_to_str[] = {
 
     { "TLS handshake was interrupted"}, /* ERR_TLS_HANDSHAKE_INTERRUPTED */
 
+    { "Certificate authority file not found"}, /* ERR_CA_DB_NOT_FOUND */
+
     { "ERR_LAST" } /* ERR_LAST */
 };
 
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index 49d3982cc3..df366e769f 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -167,6 +167,8 @@ enum sssd_errors {
 
     ERR_TLS_HANDSHAKE_INTERRUPTED,
 
+    ERR_CA_DB_NOT_FOUND,
+
     ERR_LAST            /* ALWAYS LAST */
 };
 
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to