From a2df8df20853e3575fd9c8f39dc7efdb5170105d Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 16 Feb 2017 13:20:20 +0100 Subject: PAM: allow muliple users mapped to a certificate --- src/providers/ipa/ipa_subdomains_id.c | 3 +- src/responder/pam/pamsrv.h | 2 +- src/responder/pam/pamsrv_cmd.c | 134 +++++++++++++++++++--------------- 3 files changed, 80 insertions(+), 59 deletions(-) diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index 0d74e203d..c2560b8b2 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -1001,7 +1001,8 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, } else if (ar->filter_type == BE_FILTER_CERT) { ret = sysdb_search_object_by_cert(mem_ctx, dom, ar->filter_value, attrs, &res); - if (ret != EOK) { + /* TODO: make extdom/ipa_subdom aware of multiple certificate matches */ + if (ret != EOK || res->count != 1) { DEBUG(SSSDBG_OP_FAILURE, "Failed to make request to our cache: [%d]: [%s]\n", ret, sss_strerror(ret)); diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h index 7860a99a8..e26d90c0a 100644 --- a/src/responder/pam/pamsrv.h +++ b/src/responder/pam/pamsrv.h @@ -69,7 +69,7 @@ struct pam_auth_req { struct pam_auth_dp_req *dpreq_spy; struct ldb_message *user_obj; - struct ldb_message *cert_user_obj; + struct ldb_result *cert_user_objs; char *token_name; char *module_name; char *key_id; diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index e788a75a4..43632049d 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -1464,7 +1464,7 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) preq->domain = result->domain; } - preq->cert_user_obj = talloc_steal(preq, result->msgs[0]); + preq->cert_user_objs = talloc_steal(preq, result->ldb_result); if (preq->pd->logon_name == NULL) { if (preq->pd->cmd != SSS_PAM_PREAUTH) { @@ -1473,8 +1473,17 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) ret = ENOENT; goto done; } - cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, - SYSDB_NAME, NULL); + + if (preq->cert_user_objs->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "More than one user mapped to certificate."); + /* TODO: send pam response to ask for a user name */ + ret = EINVAL; + goto done; + } + cert_user = ldb_msg_find_attr_as_string( + preq->cert_user_objs->msgs[0], + SYSDB_NAME, NULL); if (cert_user == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Certificate user object has not name.\n"); @@ -1981,6 +1990,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) struct pam_ctx *pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); const char *cert_user; + size_t c; if (!preq->pd->domain) { preq->pd->domain = preq->domain->name; @@ -2017,74 +2027,84 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) return; } - if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_obj != NULL) { + if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_objs != NULL) { /* Check if user matches certificate user */ - cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, SYSDB_NAME, - NULL); - if (cert_user == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Certificate user object has no name.\n"); - preq->pd->pam_status = PAM_USER_UNKNOWN; - pam_reply(preq); - return; - } + for (c = 0; c < preq->cert_user_objs->count; c++) { + cert_user = ldb_msg_find_attr_as_string( + preq->cert_user_objs->msgs[c], + SYSDB_NAME, + NULL); + if (cert_user == NULL) { + /* Even if there might be other users mapped to the + * certificate a missing SYSDB_NAME indicates some critical + * condition which justifies that the whole request is aborted + * */ + DEBUG(SSSDBG_CRIT_FAILURE, + "Certificate user object has no name.\n"); + preq->pd->pam_status = PAM_USER_UNKNOWN; + pam_reply(preq); + return; + } - /* pam_check_user_search() calls pd_set_primary_name() is the search - * was successful, so pd->user contains the canonical sysdb name - * as well */ - if (ldb_dn_compare(preq->cert_user_obj->dn, preq->user_obj->dn) == 0) { - - if (preq->pd->cmd == SSS_PAM_PREAUTH) { - ret = sss_authtok_set_sc(preq->pd->authtok, - SSS_AUTHTOK_TYPE_SC_PIN, NULL, 0, - preq->token_name, 0, - preq->module_name, 0, - preq->key_id, 0); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_set_sc failed, " - "Smartcard authentication " - "detection might fail in the " - "backend.\n"); + /* pam_check_user_search() calls pd_set_primary_name() is the search + * was successful, so pd->user contains the canonical sysdb name + * as well */ + if (ldb_dn_compare(preq->cert_user_objs->msgs[c]->dn, + preq->user_obj->dn) == 0) { + + //preq->pd->pam_status = PAM_SUCCESS; + + if (preq->pd->cmd == SSS_PAM_PREAUTH) { + ret = sss_authtok_set_sc(preq->pd->authtok, + SSS_AUTHTOK_TYPE_SC_PIN, NULL, 0, + preq->token_name, 0, + preq->module_name, 0, + preq->key_id, 0); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_set_sc failed, " + "Smartcard authentication " + "detection might fail in the " + "backend.\n"); + } + + ret = add_pam_cert_response(preq->pd, cert_user, + preq->token_name, + preq->module_name, + preq->key_id); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n"); + preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL; + } } - ret = add_pam_cert_response(preq->pd, cert_user, - preq->token_name, - preq->module_name, - preq->key_id); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n"); - preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL; + /* We are done if we do not have to call the backend */ + if (preq->pd->cmd == SSS_PAM_AUTHENTICATE + && preq->cert_auth_local) { + preq->pd->pam_status = PAM_SUCCESS; + preq->callback = pam_reply; + pam_reply(preq); + return; } } + } - /* We are done if we do not have to call the backend */ - if (preq->pd->cmd == SSS_PAM_AUTHENTICATE - && preq->cert_auth_local) { - preq->pd->pam_status = PAM_SUCCESS; - preq->callback = pam_reply; - pam_reply(preq); - return; - } + if (preq->pd->cmd == SSS_PAM_PREAUTH) { + DEBUG(SSSDBG_TRACE_FUNC, + "User and certificate user do not match, " \ + "continue with other authentication methods.\n"); } else { - if (preq->pd->cmd == SSS_PAM_PREAUTH) { - DEBUG(SSSDBG_TRACE_FUNC, - "User and certificate user do not match, " \ - "continue with other authentication methods.\n"); - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - "User and certificate user do not match.\n"); - preq->pd->pam_status = PAM_AUTH_ERR; - pam_reply(preq); - return; - } + DEBUG(SSSDBG_CRIT_FAILURE, + "User and certificate user do not match.\n"); + preq->pd->pam_status = PAM_AUTH_ERR; + pam_reply(preq); + return; } } if (!NEED_CHECK_PROVIDER(preq->domain->provider) ) { preq->callback = pam_reply; ret = LOCAL_pam_handler(preq); - } - else { + } else { preq->callback = pam_reply; ret = pam_dp_send_req(preq, SSS_CLI_SOCKET_TIMEOUT/2); DEBUG(SSSDBG_CONF_SETTINGS, "pam_dp_send_req returned %d\n", ret); -- cgit