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

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