Blob Blame History Raw
From 52514960f5b0609cd9f31f3c4455b61fbe4c04c5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 26 Apr 2017 17:16:19 +0200
Subject: [PATCH 121/121] PAM: check matching certificates from all domains

Although the cache_req lookup found matching in multiple domains only
the results from the first domain were used. With this patch the results
from all domains are checked.

Resolves https://pagure.io/SSSD/sssd/issue/3385

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 92d8b072f8c521e1b4effe109b5caedabd36ed6f)
---
 src/responder/pam/pamsrv_cmd.c | 69 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 63 insertions(+), 6 deletions(-)

diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index f2b3c74b483e527932dda42279d14a9ac184b475..10a178f839ec011c09a6da4575efbb026f3f7700 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1352,15 +1352,71 @@ done:
     pam_check_user_done(preq, ret);
 }
 
+static errno_t get_results_from_all_domains(TALLOC_CTX *mem_ctx,
+                                            struct cache_req_result **results,
+                                            struct ldb_result **ldb_results)
+{
+    int ret;
+    size_t count = 0;
+    size_t c;
+    size_t d;
+    size_t r = 0;
+    struct ldb_result *res;
+
+    for (d = 0; results != NULL && results[d] != NULL; d++) {
+        count += results[d]->count;
+    }
+
+    res = talloc_zero(mem_ctx, struct ldb_result);
+    if (res == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+        return ENOMEM;
+    }
+
+    if (count == 0) {
+        *ldb_results = res;
+        return EOK;
+    }
+
+    res->msgs = talloc_zero_array(res, struct ldb_message *, count);
+    if (res->msgs == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n");
+        return ENOMEM;
+    }
+    res->count = count;
+
+    for (d = 0; results != NULL && results[d] != NULL; d++) {
+        for (c = 0; c < results[d]->count; c++) {
+            if (r >= count) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "More results found then counted before.\n");
+                ret = EINVAL;
+                goto done;
+            }
+            res->msgs[r++] = talloc_steal(res->msgs, results[d]->msgs[c]);
+        }
+    }
+
+    *ldb_results = res;
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        talloc_free(res);
+    }
+
+    return ret;
+}
+
 static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
 {
     int ret;
-    struct cache_req_result *result;
+    struct cache_req_result **results;
     struct pam_auth_req *preq = tevent_req_callback_data(req,
                                                          struct pam_auth_req);
     const char *cert_user;
 
-    ret = cache_req_user_by_cert_recv(preq, req, &result);
+    ret = cache_req_recv(preq, req, &results);
     talloc_zfree(req);
     if (ret != EOK && ret != ENOENT) {
         DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n");
@@ -1368,12 +1424,13 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
     }
 
     if (ret == EOK) {
-        if (preq->domain == NULL) {
-            preq->domain = result->domain;
+        ret = get_results_from_all_domains(preq, results,
+                                           &preq->cert_user_objs);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "get_results_from_all_domains failed.\n");
+            goto done;
         }
 
-        preq->cert_user_objs = talloc_steal(preq, result->ldb_result);
-
         if (preq->pd->logon_name == NULL) {
             if (preq->pd->cmd != SSS_PAM_PREAUTH) {
                 DEBUG(SSSDBG_CRIT_FAILURE,
-- 
2.9.3