dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone

Blame SOURCES/0030-ssh-fix-matching-rules-default.patch

0d441c
From 6f7f15691b071cefd4e04a9fee44af580b6c502b Mon Sep 17 00:00:00 2001
0d441c
From: Sumit Bose <sbose@redhat.com>
0d441c
Date: Mon, 9 Mar 2020 13:39:47 +0100
0d441c
Subject: [PATCH] ssh: fix matching rules default
0d441c
MIME-Version: 1.0
0d441c
Content-Type: text/plain; charset=UTF-8
0d441c
Content-Transfer-Encoding: 8bit
0d441c
0d441c
Before the ssh_use_certificate_matching_rules option was added the ssh
0d441c
responder returned ssh keys derived from all valid certificates. Since
0d441c
the default of the ssh_use_certificate_matching_rules option is
0d441c
'all_rules' in a case where no matching rules are defined all
0d441c
certificated will be filtered out and no ssh keys are returned.
0d441c
0d441c
The intention of the default was to allow the same same certificates
0d441c
which are allowed in the PAM responder for authentication. The missing
0d441c
default matching rule which is currently use by the PAM responder if no
0d441c
other rules are available is added by this patch.
0d441c
0d441c
There might still be a small regression in case certificates without the
0d441c
extended key usage (EKU) clientAuth were used for ssh. In this case
0d441c
'ssh_use_certificate_matching_rules = no_rules' or a suitable matching
0d441c
rule must be added to the configuration.
0d441c
0d441c
Related to https://pagure.io/SSSD/sssd/issue/4121
0d441c
0d441c
Reviewed-by: Tomáš Halman <thalman@redhat.com>
0d441c
---
0d441c
 src/man/sssd.conf.5.xml         |  9 ++++-
0d441c
 src/responder/pam/pam_helpers.h |  2 ++
0d441c
 src/responder/pam/pamsrv_p11.c  |  3 +-
0d441c
 src/responder/ssh/ssh_cmd.c     | 30 +++++++++++++----
0d441c
 src/tests/cmocka/test_ssh_srv.c | 58 +++++++++++++++++++++++++++++++++
0d441c
 5 files changed, 93 insertions(+), 9 deletions(-)
0d441c
0d441c
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
0d441c
index 58383579c..a2567f5ac 100644
0d441c
--- a/src/man/sssd.conf.5.xml
0d441c
+++ b/src/man/sssd.conf.5.xml
0d441c
@@ -1766,6 +1766,13 @@ p11_uri = library-description=OpenSC%20smartcard%20framework;slot-id=2
0d441c
                             will be filtered out and ssh keys will be generated
0d441c
                             from all valid certificates.
0d441c
                         </para>
0d441c
+                        <para>
0d441c
+                            If no rules are configured using 'all_rules' will
0d441c
+                            enable a default rule which enables all
0d441c
+                            certificates suitable for client authentication.
0d441c
+                            This is the same behavior as for the PAM responder
0d441c
+                            if certificate authentication is enabled.
0d441c
+                        </para>
0d441c
                         <para>
0d441c
                             A non-existing rule name is considered an error.
0d441c
                             If as a result no rule is selected all certificates
0d441c
@@ -1773,7 +1780,7 @@ p11_uri = library-description=OpenSC%20smartcard%20framework;slot-id=2
0d441c
                         </para>
0d441c
                         <para>
0d441c
                             Default: not set, equivalent to 'all_rules,
0d441c
-                            all found rules are used
0d441c
+                            all found rules or the default rule are used
0d441c
                         </para>
0d441c
                     </listitem>
0d441c
                 </varlistentry>
0d441c
diff --git a/src/responder/pam/pam_helpers.h b/src/responder/pam/pam_helpers.h
0d441c
index 614389706..23fd308bb 100644
0d441c
--- a/src/responder/pam/pam_helpers.h
0d441c
+++ b/src/responder/pam/pam_helpers.h
0d441c
@@ -25,6 +25,8 @@
0d441c
 
0d441c
 #include "util/util.h"
0d441c
 
0d441c
+#define CERT_AUTH_DEFAULT_MATCHING_RULE "KRB5:<EKU>clientAuth"
0d441c
+
0d441c
 errno_t pam_initgr_cache_set(struct tevent_context *ev,
0d441c
                              hash_table_t *id_table,
0d441c
                              char *name,
0d441c
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
0d441c
index 0dc53a826..8e276b200 100644
0d441c
--- a/src/responder/pam/pamsrv_p11.c
0d441c
+++ b/src/responder/pam/pamsrv_p11.c
0d441c
@@ -26,13 +26,12 @@
0d441c
 #include "util/child_common.h"
0d441c
 #include "util/strtonum.h"
0d441c
 #include "responder/pam/pamsrv.h"
0d441c
+#include "responder/pam/pam_helpers.h"
0d441c
 #include "lib/certmap/sss_certmap.h"
0d441c
 #include "util/crypto/sss_crypto.h"
0d441c
 #include "db/sysdb.h"
0d441c
 
0d441c
 
0d441c
-#define CERT_AUTH_DEFAULT_MATCHING_RULE "KRB5:<EKU>clientAuth"
0d441c
-
0d441c
 struct cert_auth_info {
0d441c
     char *cert;
0d441c
     char *token_name;
0d441c
diff --git a/src/responder/ssh/ssh_cmd.c b/src/responder/ssh/ssh_cmd.c
0d441c
index e42e29bfd..a593c904f 100644
0d441c
--- a/src/responder/ssh/ssh_cmd.c
0d441c
+++ b/src/responder/ssh/ssh_cmd.c
0d441c
@@ -29,6 +29,7 @@
0d441c
 #include "responder/common/responder.h"
0d441c
 #include "responder/common/cache_req/cache_req.h"
0d441c
 #include "responder/ssh/ssh_private.h"
0d441c
+#include "responder/pam/pam_helpers.h"
0d441c
 #include "lib/certmap/sss_certmap.h"
0d441c
 
0d441c
 struct ssh_cmd_ctx {
0d441c
@@ -159,6 +160,7 @@ static errno_t ssh_cmd_refresh_certmap_ctx(struct ssh_ctx *ssh_ctx,
0d441c
     bool rule_added;
0d441c
     bool all_rules = false;
0d441c
     bool no_rules = false;
0d441c
+    bool rules_present = false;
0d441c
 
0d441c
     ssh_ctx->cert_rules_error = false;
0d441c
 
0d441c
@@ -195,6 +197,7 @@ static errno_t ssh_cmd_refresh_certmap_ctx(struct ssh_ctx *ssh_ctx,
0d441c
         }
0d441c
 
0d441c
         for (c = 0; certmap_list[c] != NULL; c++) {
0d441c
+            rules_present = true;
0d441c
 
0d441c
             if (!all_rules && !string_in_list(certmap_list[c]->name,
0d441c
                                               ssh_ctx->cert_rules, true)) {
0d441c
@@ -227,12 +230,27 @@ static errno_t ssh_cmd_refresh_certmap_ctx(struct ssh_ctx *ssh_ctx,
0d441c
     }
0d441c
 
0d441c
     if (!rule_added) {
0d441c
-        DEBUG(SSSDBG_CONF_SETTINGS,
0d441c
-              "No matching rule added, please check "
0d441c
-              "ssh_use_certificate_matching_rules option values for typos .\n");
0d441c
-
0d441c
-        ret = EINVAL;
0d441c
-        goto done;
0d441c
+        if (!rules_present) {
0d441c
+            DEBUG(SSSDBG_TRACE_FUNC,
0d441c
+                  "No rules available, trying to add default matching rule.\n");
0d441c
+            ret = sss_certmap_add_rule(sss_certmap_ctx, SSS_CERTMAP_MIN_PRIO,
0d441c
+                                       CERT_AUTH_DEFAULT_MATCHING_RULE,
0d441c
+                                       NULL, NULL);
0d441c
+            if (ret != 0) {
0d441c
+                DEBUG(SSSDBG_OP_FAILURE,
0d441c
+                      "Failed to add default matching rule [%d][%s].\n",
0d441c
+                      ret, sss_strerror(ret));
0d441c
+                goto done;
0d441c
+            }
0d441c
+        } else {
0d441c
+            DEBUG(SSSDBG_CONF_SETTINGS,
0d441c
+                  "No matching rule added, please check "
0d441c
+                  "ssh_use_certificate_matching_rules option values for "
0d441c
+                  "typos.\n");
0d441c
+
0d441c
+            ret = EINVAL;
0d441c
+            goto done;
0d441c
+        }
0d441c
     }
0d441c
 
0d441c
     ret = EOK;
0d441c
diff --git a/src/tests/cmocka/test_ssh_srv.c b/src/tests/cmocka/test_ssh_srv.c
0d441c
index fc43663a7..a48013416 100644
0d441c
--- a/src/tests/cmocka/test_ssh_srv.c
0d441c
+++ b/src/tests/cmocka/test_ssh_srv.c
0d441c
@@ -769,6 +769,62 @@ void test_ssh_user_pubkey_cert_with_all_rules(void **state)
0d441c
     assert_int_equal(ret, EOK);
0d441c
 }
0d441c
 
0d441c
+void test_ssh_user_pubkey_cert_with_all_rules_but_no_rules_present(void **state)
0d441c
+{
0d441c
+    int ret;
0d441c
+    struct sysdb_attrs *attrs;
0d441c
+    /* Both rules are enabled, both certificates should be handled. */
0d441c
+    const char *rule_list[] = { "all_rules", NULL };
0d441c
+
0d441c
+    attrs = sysdb_new_attrs(ssh_test_ctx);
0d441c
+    assert_non_null(attrs);
0d441c
+    ret = sysdb_attrs_add_string(attrs, SYSDB_SSH_PUBKEY, TEST_SSH_PUBKEY);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+    ret = sysdb_attrs_add_base64_blob(attrs, SYSDB_USER_CERT,
0d441c
+                                      SSSD_TEST_CERT_0001);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+    ret = sysdb_attrs_add_base64_blob(attrs, SYSDB_USER_CERT,
0d441c
+                                      SSSD_TEST_CERT_0002);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+
0d441c
+    ret = sysdb_set_user_attr(ssh_test_ctx->tctx->dom,
0d441c
+                              ssh_test_ctx->ssh_user_fqdn,
0d441c
+                              attrs,
0d441c
+                              LDB_FLAG_MOD_ADD);
0d441c
+    talloc_free(attrs);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+
0d441c
+    mock_input_user(ssh_test_ctx, ssh_test_ctx->ssh_user_fqdn);
0d441c
+    will_return(__wrap_sss_packet_get_cmd, SSS_SSH_GET_USER_PUBKEYS);
0d441c
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
0d441c
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
0d441c
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
0d441c
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
0d441c
+
0d441c
+    /* Enable certificate support */
0d441c
+    ssh_test_ctx->ssh_ctx->use_cert_keys = true;
0d441c
+    ssh_test_ctx->ssh_ctx->rctx->domains->certmaps = NULL;
0d441c
+    ssh_test_ctx->ssh_ctx->certmap_last_read = 0;
0d441c
+    ssh_test_ctx->ssh_ctx->rctx->get_domains_last_call.tv_sec = 1;
0d441c
+    ssh_test_ctx->ssh_ctx->cert_rules = discard_const(rule_list);
0d441c
+#ifdef HAVE_NSS
0d441c
+    ssh_test_ctx->ssh_ctx->ca_db = discard_const("sql:" ABS_BUILD_DIR
0d441c
+                                                "/src/tests/test_CA/p11_nssdb");
0d441c
+#else
0d441c
+    ssh_test_ctx->ssh_ctx->ca_db = discard_const(ABS_BUILD_DIR
0d441c
+                                                "/src/tests/test_CA/SSSD_test_CA.pem");
0d441c
+#endif
0d441c
+
0d441c
+    set_cmd_cb(test_ssh_user_pubkey_cert_check);
0d441c
+    ret = sss_cmd_execute(ssh_test_ctx->cctx, SSS_SSH_GET_USER_PUBKEYS,
0d441c
+                          ssh_test_ctx->ssh_cmds);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+
0d441c
+    /* Wait until the test finishes with EOK */
0d441c
+    ret = test_ev_loop(ssh_test_ctx->tctx);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+}
0d441c
+
0d441c
 void test_ssh_user_pubkey_cert_with_no_rules(void **state)
0d441c
 {
0d441c
     int ret;
0d441c
@@ -966,6 +1022,8 @@ int main(int argc, const char *argv[])
0d441c
                                         ssh_test_setup, ssh_test_teardown),
0d441c
         cmocka_unit_test_setup_teardown(test_ssh_user_pubkey_cert_with_all_rules,
0d441c
                                         ssh_test_setup, ssh_test_teardown),
0d441c
+        cmocka_unit_test_setup_teardown(test_ssh_user_pubkey_cert_with_all_rules_but_no_rules_present,
0d441c
+                                        ssh_test_setup, ssh_test_teardown),
0d441c
         cmocka_unit_test_setup_teardown(test_ssh_user_pubkey_cert_with_no_rules,
0d441c
                                         ssh_test_setup, ssh_test_teardown),
0d441c
         cmocka_unit_test_setup_teardown(test_ssh_user_pubkey_cert_with_unknow_rule_name,
0d441c
-- 
0d441c
2.21.1
0d441c