From 52514960f5b0609cd9f31f3c4455b61fbe4c04c5 Mon Sep 17 00:00:00 2001 From: Sumit Bose 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 (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