1dedfbb334
Resolves: upstream#3588 - sssd_nss consumes more memory until restarted or machine swaps Resolves: failure in glibc tests https://sourceware.org/bugzilla/show_bug.cgi?id=22530 Resolves: upstream#3451 - When sssd is configured with id_provider proxy and auth_provider ldap, login fails if the LDAP server is not allowing anonymous binds Resolves: upstream#3285 - SSSD needs restart after incorrect clock is corrected with AD Resolves: upstream#3586 - Give a more detailed debug and system-log message if krb5_init_context() failed Resolves: rhbz#1431153 - SSSD ships a drop-in configuration snippet in /etc/systemd/system Backport few upstream features from 1.16.1
977 lines
38 KiB
Diff
977 lines
38 KiB
Diff
From 5649511243126866c97df0892c51227ab9257347 Mon Sep 17 00:00:00 2001
|
|
From: Sumit Bose <sbose@redhat.com>
|
|
Date: Fri, 25 Aug 2017 12:51:09 +0200
|
|
Subject: [PATCH 43/79] PAM: handled multiple certs in the responder
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
This patch refactors the handling of the certificate and the attributes
|
|
to address the certificate on the Smartcard (module name, token name and
|
|
key id). Instead of using individual variables the values are put into a
|
|
new struct cert_auth_info. Since the new struct can be used as a list
|
|
the PAM responder can now handle multiple certificates on the Smartcard
|
|
and can send the needed data to pam_sss with multiple SSS_PAM_CERT_INFO
|
|
messages.
|
|
|
|
Unit tests are added to confirm the expected behavior.
|
|
|
|
Related to https://pagure.io/SSSD/sssd/issue/3560
|
|
|
|
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
|
|
Tested-by: Scott Poore <spoore@redhat.com>
|
|
---
|
|
src/responder/pam/pamsrv.h | 25 ++--
|
|
src/responder/pam/pamsrv_cmd.c | 257 ++++++++++++++++++++++++++--------------
|
|
src/responder/pam/pamsrv_p11.c | 181 ++++++++++++++++++++--------
|
|
src/tests/cmocka/test_pam_srv.c | 167 +++++++++++++++++++++++++-
|
|
src/tests/whitespace_test | 2 +-
|
|
5 files changed, 483 insertions(+), 149 deletions(-)
|
|
|
|
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
|
|
index 896f71befbc9947a53b5eb20cba0bb3d104c4cf2..f15f7f19f1f38626288416c9f2038371c6f58b47 100644
|
|
--- a/src/responder/pam/pamsrv.h
|
|
+++ b/src/responder/pam/pamsrv.h
|
|
@@ -73,10 +73,8 @@ struct pam_auth_req {
|
|
struct pam_auth_dp_req *dpreq_spy;
|
|
|
|
struct ldb_message *user_obj;
|
|
- struct ldb_result *cert_user_objs;
|
|
- char *token_name;
|
|
- char *module_name;
|
|
- char *key_id;
|
|
+ struct cert_auth_info *cert_list;
|
|
+ struct cert_auth_info *current_cert;
|
|
bool cert_auth_local;
|
|
};
|
|
|
|
@@ -89,6 +87,16 @@ int LOCAL_pam_handler(struct pam_auth_req *preq);
|
|
errno_t p11_child_init(struct pam_ctx *pctx);
|
|
|
|
struct cert_auth_info;
|
|
+const char *sss_cai_get_cert(struct cert_auth_info *i);
|
|
+const char *sss_cai_get_token_name(struct cert_auth_info *i);
|
|
+const char *sss_cai_get_module_name(struct cert_auth_info *i);
|
|
+const char *sss_cai_get_key_id(struct cert_auth_info *i);
|
|
+struct cert_auth_info *sss_cai_get_next(struct cert_auth_info *i);
|
|
+struct ldb_result *sss_cai_get_cert_user_objs(struct cert_auth_info *i);
|
|
+void sss_cai_set_cert_user_objs(struct cert_auth_info *i,
|
|
+ struct ldb_result *cert_user_objs);
|
|
+void sss_cai_check_users(struct cert_auth_info **list, size_t *_cert_count,
|
|
+ size_t *_cert_user_count);
|
|
|
|
struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
|
|
struct tevent_context *ev,
|
|
@@ -98,12 +106,11 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
|
|
const char *verify_opts,
|
|
struct pam_data *pd);
|
|
errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
|
- char **cert, char **token_name, char **module_name,
|
|
- char **key_id);
|
|
+ struct cert_auth_info **cert_list);
|
|
|
|
-errno_t add_pam_cert_response(struct pam_data *pd, const char *user,
|
|
- const char *token_name, const char *module_name,
|
|
- const char *key_id, enum response_type type);
|
|
+errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
|
|
+ struct cert_auth_info *cert_info,
|
|
+ enum response_type type);
|
|
|
|
bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd);
|
|
|
|
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
|
|
index 51d8185650cf823da289a3398b10133065d82ae4..8b2c086e206796ad4c977495be957c56b3255e7f 100644
|
|
--- a/src/responder/pam/pamsrv_cmd.c
|
|
+++ b/src/responder/pam/pamsrv_cmd.c
|
|
@@ -1389,21 +1389,17 @@ done:
|
|
return pam_check_user_done(preq, ret);
|
|
}
|
|
|
|
+static errno_t pam_user_by_cert_step(struct pam_auth_req *preq);
|
|
static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req);
|
|
static void pam_forwarder_cert_cb(struct tevent_req *req)
|
|
{
|
|
struct pam_auth_req *preq = tevent_req_callback_data(req,
|
|
struct pam_auth_req);
|
|
- struct cli_ctx *cctx = preq->cctx;
|
|
struct pam_data *pd;
|
|
errno_t ret = EOK;
|
|
- char *cert;
|
|
- struct pam_ctx *pctx =
|
|
- talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
|
|
+ const char *cert;
|
|
|
|
- ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name,
|
|
- &preq->module_name,
|
|
- &preq->key_id);
|
|
+ ret = pam_check_cert_recv(req, preq, &preq->cert_list);
|
|
talloc_free(req);
|
|
if (ret != EOK) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n");
|
|
@@ -1412,6 +1408,8 @@ static void pam_forwarder_cert_cb(struct tevent_req *req)
|
|
|
|
pd = preq->pd;
|
|
|
|
+ cert = sss_cai_get_cert(preq->cert_list);
|
|
+
|
|
if (cert == NULL) {
|
|
if (pd->logon_name == NULL) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
@@ -1431,21 +1429,42 @@ static void pam_forwarder_cert_cb(struct tevent_req *req)
|
|
goto done;
|
|
}
|
|
|
|
+ preq->current_cert = preq->cert_list;
|
|
+ ret = pam_user_by_cert_step(preq);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "pam_user_by_cert_step failed.\n");
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ return;
|
|
+
|
|
+done:
|
|
+ pam_check_user_done(preq, ret);
|
|
+}
|
|
+
|
|
+static errno_t pam_user_by_cert_step(struct pam_auth_req *preq)
|
|
+{
|
|
+ struct cli_ctx *cctx = preq->cctx;
|
|
+ struct tevent_req *req;
|
|
+ struct pam_ctx *pctx =
|
|
+ talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
|
|
+
|
|
+ if (preq->current_cert == NULL) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing certificate data.\n");
|
|
+ return EINVAL;
|
|
+ }
|
|
|
|
req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx,
|
|
pctx->rctx->ncache, 0,
|
|
preq->req_dom_type, NULL,
|
|
- cert);
|
|
+ sss_cai_get_cert(preq->current_cert));
|
|
if (req == NULL) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n");
|
|
- ret = ENOMEM;
|
|
- goto done;
|
|
+ return ENOMEM;
|
|
}
|
|
+
|
|
tevent_req_set_callback(req, pam_forwarder_lookup_by_cert_done, preq);
|
|
- return;
|
|
-
|
|
-done:
|
|
- pam_check_user_done(preq, ret);
|
|
+ return EOK;
|
|
}
|
|
|
|
static errno_t get_results_from_all_domains(TALLOC_CTX *mem_ctx,
|
|
@@ -1511,6 +1530,9 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
|
|
struct pam_auth_req *preq = tevent_req_callback_data(req,
|
|
struct pam_auth_req);
|
|
const char *cert_user = NULL;
|
|
+ size_t cert_count = 0;
|
|
+ size_t cert_user_count = 0;
|
|
+ struct ldb_result *cert_user_objs;
|
|
|
|
ret = cache_req_recv(preq, req, &results);
|
|
talloc_zfree(req);
|
|
@@ -1521,12 +1543,39 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
|
|
|
|
if (ret == EOK) {
|
|
ret = get_results_from_all_domains(preq, results,
|
|
- &preq->cert_user_objs);
|
|
+ &cert_user_objs);
|
|
if (ret != EOK) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "get_results_from_all_domains failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
+ sss_cai_set_cert_user_objs(preq->current_cert, cert_user_objs);
|
|
+ }
|
|
+
|
|
+ preq->current_cert = sss_cai_get_next(preq->current_cert);
|
|
+ if (preq->current_cert != NULL) {
|
|
+ ret = pam_user_by_cert_step(preq);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "pam_user_by_cert_step failed.\n");
|
|
+ goto done;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ sss_cai_check_users(&preq->cert_list, &cert_count, &cert_user_count);
|
|
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
+ "Found [%zu] certificates and [%zu] related users.\n",
|
|
+ cert_count, cert_user_count);
|
|
+
|
|
+ if (cert_user_count == 0) {
|
|
+ if (preq->pd->logon_name == NULL) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
+ "Missing logon name and no certificate user found.\n");
|
|
+ ret = ENOENT;
|
|
+ goto done;
|
|
+ }
|
|
+ } else {
|
|
+
|
|
if (preq->pd->logon_name == NULL) {
|
|
if (preq->pd->cmd != SSS_PAM_PREAUTH) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
@@ -1535,9 +1584,39 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
|
|
goto done;
|
|
}
|
|
|
|
- if (preq->cert_user_objs->count == 1) {
|
|
+ if (cert_count > 1) {
|
|
+ for (preq->current_cert = preq->cert_list;
|
|
+ preq->current_cert != NULL;
|
|
+ preq->current_cert = sss_cai_get_next(preq->current_cert)) {
|
|
+
|
|
+ ret = add_pam_cert_response(preq->pd, "",
|
|
+ preq->current_cert,
|
|
+ preq->cctx->rctx->domains->user_name_hint
|
|
+ ? SSS_PAM_CERT_INFO_WITH_HINT
|
|
+ : SSS_PAM_CERT_INFO);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
+ "add_pam_cert_response failed.\n");
|
|
+ preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ret = EOK;
|
|
+ preq->pd->pam_status = PAM_SUCCESS;
|
|
+ pam_reply(preq);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (cert_user_count == 1) {
|
|
+ cert_user_objs = sss_cai_get_cert_user_objs(preq->cert_list);
|
|
+ if (cert_user_objs == NULL) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing certificate user.\n");
|
|
+ ret = ENOENT;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
cert_user = ldb_msg_find_attr_as_string(
|
|
- preq->cert_user_objs->msgs[0],
|
|
+ cert_user_objs->msgs[0],
|
|
SYSDB_NAME, NULL);
|
|
if (cert_user == NULL) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
@@ -1564,9 +1643,7 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
|
|
|
|
if (preq->cctx->rctx->domains->user_name_hint) {
|
|
ret = add_pam_cert_response(preq->pd, cert_user,
|
|
- preq->token_name,
|
|
- preq->module_name,
|
|
- preq->key_id,
|
|
+ preq->cert_list,
|
|
SSS_PAM_CERT_INFO_WITH_HINT);
|
|
preq->pd->pam_status = PAM_SUCCESS;
|
|
if (ret != EOK) {
|
|
@@ -1596,13 +1673,6 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
|
|
goto done;
|
|
}
|
|
}
|
|
- } else {
|
|
- if (preq->pd->logon_name == NULL) {
|
|
- DEBUG(SSSDBG_CRIT_FAILURE,
|
|
- "Missing logon name and no certificate user found.\n");
|
|
- ret = ENOENT;
|
|
- goto done;
|
|
- }
|
|
}
|
|
|
|
if (preq->user_obj == NULL) {
|
|
@@ -1884,7 +1954,9 @@ 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;
|
|
+ struct ldb_result *cert_user_objs;
|
|
size_t c;
|
|
+ bool found = false;
|
|
|
|
if (!preq->pd->domain) {
|
|
preq->pd->domain = preq->domain->name;
|
|
@@ -1921,76 +1993,87 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
|
|
return;
|
|
}
|
|
|
|
- if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_objs != NULL) {
|
|
+ if (may_do_cert_auth(pctx, preq->pd) && preq->cert_list != NULL) {
|
|
/* Check if user matches certificate user */
|
|
- 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;
|
|
+ found = false;
|
|
+ for (preq->current_cert = preq->cert_list;
|
|
+ preq->current_cert != NULL;
|
|
+ preq->current_cert = sss_cai_get_next(preq->current_cert)) {
|
|
+
|
|
+ cert_user_objs = sss_cai_get_cert_user_objs(preq->current_cert);
|
|
+ if (cert_user_objs == NULL) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
+ "Unexpteced missing certificate user, "
|
|
+ "trying next certificate.\n");
|
|
+ continue;
|
|
}
|
|
|
|
- /* 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) {
|
|
-
|
|
- 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,
|
|
- SSS_PAM_CERT_INFO);
|
|
- 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;
|
|
+ for (c = 0; c < cert_user_objs->count; c++) {
|
|
+ cert_user = ldb_msg_find_attr_as_string(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;
|
|
}
|
|
+
|
|
+ if (ldb_dn_compare(cert_user_objs->msgs[c]->dn,
|
|
+ preq->user_obj->dn) == 0) {
|
|
+ found = true;
|
|
+ if (preq->pd->cmd == SSS_PAM_PREAUTH) {
|
|
+ ret = sss_authtok_set_sc(preq->pd->authtok,
|
|
+ SSS_AUTHTOK_TYPE_SC_PIN, NULL, 0,
|
|
+ sss_cai_get_token_name(preq->current_cert), 0,
|
|
+ sss_cai_get_module_name(preq->current_cert), 0,
|
|
+ sss_cai_get_key_id(preq->current_cert), 0);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
+ "sss_authtok_set_sc failed, Smartcard "
|
|
+ "authentication detection might fail in "
|
|
+ "the backend.\n");
|
|
+ }
|
|
+
|
|
+ /* FIXME: use the right cert info */
|
|
+ ret = add_pam_cert_response(preq->pd, cert_user,
|
|
+ preq->current_cert,
|
|
+ SSS_PAM_CERT_INFO);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
|
|
+ preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
}
|
|
}
|
|
|
|
- if (preq->pd->cmd == SSS_PAM_PREAUTH) {
|
|
- DEBUG(SSSDBG_TRACE_FUNC,
|
|
- "User and certificate user do not match, "
|
|
- "continue with other authentication methods.\n");
|
|
+ if (found) {
|
|
+ /* 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;
|
|
+ }
|
|
} else {
|
|
- DEBUG(SSSDBG_CRIT_FAILURE,
|
|
- "User and certificate user do not match.\n");
|
|
- preq->pd->pam_status = PAM_AUTH_ERR;
|
|
- 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 {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
+ "User and certificate user do not match.\n");
|
|
+ preq->pd->pam_status = PAM_AUTH_ERR;
|
|
+ pam_reply(preq);
|
|
+ return;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
|
|
index ff32d1e726808caa36ca7cca557220866ef1a9ab..57c8e1e464f4262f2d78f869c52ca48bd469d90a 100644
|
|
--- a/src/responder/pam/pamsrv_p11.c
|
|
+++ b/src/responder/pam/pamsrv_p11.c
|
|
@@ -40,10 +40,80 @@ struct cert_auth_info {
|
|
char *token_name;
|
|
char *module_name;
|
|
char *key_id;
|
|
+ struct ldb_result *cert_user_objs;
|
|
struct cert_auth_info *prev;
|
|
struct cert_auth_info *next;
|
|
};
|
|
|
|
+const char *sss_cai_get_cert(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->cert : NULL;
|
|
+}
|
|
+
|
|
+const char *sss_cai_get_token_name(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->token_name : NULL;
|
|
+}
|
|
+
|
|
+const char *sss_cai_get_module_name(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->module_name : NULL;
|
|
+}
|
|
+
|
|
+const char *sss_cai_get_key_id(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->key_id : NULL;
|
|
+}
|
|
+
|
|
+struct cert_auth_info *sss_cai_get_next(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->next : NULL;
|
|
+}
|
|
+
|
|
+struct ldb_result *sss_cai_get_cert_user_objs(struct cert_auth_info *i)
|
|
+{
|
|
+ return i != NULL ? i->cert_user_objs : NULL;
|
|
+}
|
|
+
|
|
+void sss_cai_set_cert_user_objs(struct cert_auth_info *i,
|
|
+ struct ldb_result *cert_user_objs)
|
|
+{
|
|
+ if (i->cert_user_objs != NULL) {
|
|
+ talloc_free(i->cert_user_objs);
|
|
+ }
|
|
+ i->cert_user_objs = talloc_steal(i, cert_user_objs);
|
|
+}
|
|
+
|
|
+void sss_cai_check_users(struct cert_auth_info **list, size_t *_cert_count,
|
|
+ size_t *_cert_user_count)
|
|
+{
|
|
+ struct cert_auth_info *c;
|
|
+ struct cert_auth_info *tmp;
|
|
+ size_t cert_count = 0;
|
|
+ size_t cert_user_count = 0;
|
|
+ struct ldb_result *user_objs;
|
|
+
|
|
+ DLIST_FOR_EACH_SAFE(c, tmp, *list) {
|
|
+ user_objs = sss_cai_get_cert_user_objs(c);
|
|
+ if (user_objs != NULL) {
|
|
+ cert_count++;
|
|
+ cert_user_count += user_objs->count;
|
|
+ } else {
|
|
+ DLIST_REMOVE(*list, c);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (_cert_count != NULL) {
|
|
+ *_cert_count = cert_count;
|
|
+ }
|
|
+
|
|
+ if (_cert_user_count != NULL) {
|
|
+ *_cert_user_count = cert_user_count;
|
|
+ }
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
errno_t p11_child_init(struct pam_ctx *pctx)
|
|
{
|
|
return child_debug_init(P11_CHILD_LOG_FILE, &pctx->p11_child_debug_fd);
|
|
@@ -566,39 +636,71 @@ static void p11_child_timeout(struct tevent_context *ev,
|
|
}
|
|
|
|
errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
|
- char **cert, char **token_name, char **module_name,
|
|
- char **key_id)
|
|
+ struct cert_auth_info **cert_list)
|
|
{
|
|
+ struct cert_auth_info *tmp_cert_auth_info;
|
|
struct pam_check_cert_state *state =
|
|
tevent_req_data(req, struct pam_check_cert_state);
|
|
|
|
TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
|
- if (state->cert_list == NULL) {
|
|
- *token_name = NULL;
|
|
- *cert = NULL;
|
|
- *module_name = NULL;
|
|
- *key_id = NULL;
|
|
+ if (cert_list != NULL) {
|
|
+ DLIST_FOR_EACH(tmp_cert_auth_info, state->cert_list) {
|
|
+ talloc_steal(mem_ctx, tmp_cert_auth_info);
|
|
+ }
|
|
+
|
|
+ *cert_list = state->cert_list;
|
|
}
|
|
|
|
- if (cert != NULL) {
|
|
- *cert = (state->cert_list == NULL) ? NULL
|
|
- : talloc_steal(mem_ctx, state->cert_list->cert);
|
|
+ return EOK;
|
|
+}
|
|
+
|
|
+static errno_t pack_cert_data(TALLOC_CTX *mem_ctx, const char *sysdb_username,
|
|
+ struct cert_auth_info *cert_info,
|
|
+ uint8_t **_msg, size_t *_msg_len)
|
|
+{
|
|
+ uint8_t *msg = NULL;
|
|
+ size_t msg_len;
|
|
+ const char *token_name;
|
|
+ const char *module_name;
|
|
+ const char *key_id;
|
|
+ size_t user_len;
|
|
+ size_t token_len;
|
|
+ size_t module_len;
|
|
+ size_t key_id_len;
|
|
+ const char *username = "";
|
|
+
|
|
+ if (sysdb_username != NULL) {
|
|
+ username = sysdb_username;
|
|
}
|
|
|
|
- if (token_name != NULL) {
|
|
- *token_name = (state->cert_list == NULL) ? NULL
|
|
- : talloc_steal(mem_ctx, state->cert_list->token_name);
|
|
+ token_name = sss_cai_get_token_name(cert_info);
|
|
+ module_name = sss_cai_get_module_name(cert_info);
|
|
+ key_id = sss_cai_get_key_id(cert_info);
|
|
+
|
|
+ user_len = strlen(username) + 1;
|
|
+ token_len = strlen(token_name) + 1;
|
|
+ module_len = strlen(module_name) + 1;
|
|
+ key_id_len = strlen(key_id) + 1;
|
|
+ msg_len = user_len + token_len + module_len + key_id_len;
|
|
+
|
|
+ msg = talloc_zero_size(mem_ctx, msg_len);
|
|
+ if (msg == NULL) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n");
|
|
+ return ENOMEM;
|
|
}
|
|
|
|
- if (module_name != NULL) {
|
|
- *module_name = (state->cert_list == NULL) ? NULL
|
|
- : talloc_steal(mem_ctx, state->cert_list->module_name);
|
|
+ memcpy(msg, username, user_len);
|
|
+ memcpy(msg + user_len, token_name, token_len);
|
|
+ memcpy(msg + user_len + token_len, module_name, module_len);
|
|
+ memcpy(msg + user_len + token_len + module_len, key_id, key_id_len);
|
|
+
|
|
+ if (_msg != NULL) {
|
|
+ *_msg = msg;
|
|
}
|
|
|
|
- if (key_id != NULL) {
|
|
- *key_id = (state->cert_list == NULL) ? NULL
|
|
- : talloc_steal(mem_ctx, state->cert_list->key_id);
|
|
+ if (_msg_len != NULL) {
|
|
+ *_msg_len = msg_len;
|
|
}
|
|
|
|
return EOK;
|
|
@@ -613,18 +715,13 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
|
#define PKCS11_LOGIN_TOKEN_ENV_NAME "PKCS11_LOGIN_TOKEN_NAME"
|
|
|
|
errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
|
|
- const char *token_name, const char *module_name,
|
|
- const char *key_id, enum response_type type)
|
|
+ struct cert_auth_info *cert_info,
|
|
+ enum response_type type)
|
|
{
|
|
uint8_t *msg = NULL;
|
|
char *env = NULL;
|
|
- size_t user_len;
|
|
size_t msg_len;
|
|
- size_t slot_len;
|
|
- size_t module_len;
|
|
- size_t key_id_len;
|
|
int ret;
|
|
- const char *username = "";
|
|
|
|
if (type != SSS_PAM_CERT_INFO && type != SSS_PAM_CERT_INFO_WITH_HINT) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid response type [%d].\n", type);
|
|
@@ -632,26 +729,14 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
|
|
}
|
|
|
|
if ((type == SSS_PAM_CERT_INFO && sysdb_username == NULL)
|
|
- || token_name == NULL || module_name == NULL || key_id == NULL) {
|
|
+ || cert_info == NULL
|
|
+ || sss_cai_get_token_name(cert_info) == NULL
|
|
+ || sss_cai_get_module_name(cert_info) == NULL
|
|
+ || sss_cai_get_key_id(cert_info) == NULL) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
- if (sysdb_username != NULL) {
|
|
- username = sysdb_username;
|
|
- }
|
|
- user_len = strlen(username) + 1;
|
|
- slot_len = strlen(token_name) + 1;
|
|
- module_len = strlen(module_name) + 1;
|
|
- key_id_len = strlen(key_id) + 1;
|
|
- msg_len = user_len + slot_len + module_len + key_id_len;
|
|
-
|
|
- msg = talloc_zero_size(pd, msg_len);
|
|
- if (msg == NULL) {
|
|
- DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n");
|
|
- return ENOMEM;
|
|
- }
|
|
-
|
|
/* sysdb_username is a fully-qualified name which is used by pam_sss when
|
|
* prompting the user for the PIN and as login name if it wasn't set by
|
|
* the PAM caller but has to be determined based on the inserted
|
|
@@ -659,10 +744,12 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
|
|
* re_expression config option was set in a way that user@domain cannot be
|
|
* handled anymore some more logic has to be added here. But for the time
|
|
* being I think using sysdb_username is fine. */
|
|
- memcpy(msg, username, user_len);
|
|
- memcpy(msg + user_len, token_name, slot_len);
|
|
- memcpy(msg + user_len + slot_len, module_name, module_len);
|
|
- memcpy(msg + user_len + slot_len + module_len, key_id, key_id_len);
|
|
+
|
|
+ ret = pack_cert_data(pd, sysdb_username, cert_info, &msg, &msg_len);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "pack_cert_data failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
|
|
ret = pam_add_response(pd, type, msg_len, msg);
|
|
talloc_free(msg);
|
|
@@ -674,7 +761,7 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
|
|
|
|
if (strcmp(pd->service, "gdm-smartcard") == 0) {
|
|
env = talloc_asprintf(pd, "%s=%s", PKCS11_LOGIN_TOKEN_ENV_NAME,
|
|
- token_name);
|
|
+ sss_cai_get_token_name(cert_info));
|
|
if (env == NULL) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
|
|
return ENOMEM;
|
|
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
|
|
index 351067eb664431cda159f73590de772920504380..6adbc15f580997c41a02819d0d6aa253f2d5a64b 100644
|
|
--- a/src/tests/cmocka/test_pam_srv.c
|
|
+++ b/src/tests/cmocka/test_pam_srv.c
|
|
@@ -47,6 +47,9 @@
|
|
#define NSS_DB_PATH TESTS_PATH
|
|
#define NSS_DB "sql:"NSS_DB_PATH
|
|
|
|
+#define NSS_DB_PATH_2CERTS TESTS_PATH "_2certs"
|
|
+#define NSS_DB_2CERTS "sql:"NSS_DB_PATH_2CERTS
|
|
+
|
|
#define TEST_TOKEN_NAME "SSSD Test Token"
|
|
#define TEST_MODULE_NAME "NSS-Internal"
|
|
#define TEST_KEY_ID "A5EF7DEE625CA5996C8D1BA7D036708161FD49E7"
|
|
@@ -74,6 +77,28 @@
|
|
"8Z+9gqZhCa7FEKJOPNR9RVtJs0qUUutMZrp1zpyx0GTmXQBA7LbgPxy8L68uymEQ" \
|
|
"XyQBwOYRORlnfGyu+Yc9c3E0Wx8Tlznz0lqPR9g="
|
|
|
|
+#define TEST2_KEY_ID "C8D60E009EB195D01A7083EE1D5419251AA87C2C"
|
|
+#define TEST_TOKEN_2ND_CERT \
|
|
+"MIIDazCCAlOgAwIBAgIBBzANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
|
|
+"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA1MjMx" \
|
|
+"NDEzMDFaFw0xODA1MTMxNDEzMDFaMCUxEjAQBgNVBAoMCUlQQS5ERVZFTDEPMA0G" \
|
|
+"A1UEAwwGSVBBIFJBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3abE" \
|
|
+"8LmIc6QN16VVxsMlN/rrCOoZKyyJolSzpP4+K66t+KZUiW/1j1MZogjyYyD39U1F" \
|
|
+"zpa2H+pID74XYrdiqP7sp+uE9/k2XOv/nN3FobXDt+fSINLDriCmxNhUZqpgo2uq" \
|
|
+"Mmka+yx2iJZwkntEoJTcd3aynoa2Sa2ZZbkMBy5p6/pUQKwnD6scOwe6mUDppIBK" \
|
|
+"+ZZRm+u/NDdIRFI5wfKLRR1r/ONaJA9nz1TxSEsgLsjG/1m+Zbb6lGG4pePIFkQ9" \
|
|
+"Iotpi64obBh93oIxzQR29lBG/FMjQVHlPIbx+xuGx11Vtp5pAomgFz0HRrj0leI7" \
|
|
+"bROE+jnC/VGPLQD2aQIDAQABo4GWMIGTMB8GA1UdIwQYMBaAFPci/0Km5D/L5z7Y" \
|
|
+"qwEc7E1/GwgcMEEGCCsGAQUFBwEBBDUwMzAxBggrBgEFBQcwAYYlaHR0cDovL2lw" \
|
|
+"YS1kZXZlbC5pcGEuZGV2ZWw6ODAvY2Evb2NzcDAOBgNVHQ8BAf8EBAMCBPAwHQYD" \
|
|
+"VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBg" \
|
|
+"4Sppx2C3eXPJ4Pd9XElkQPOaBReXf1vV0uk/GlK+rG+aAqAkA2Lryx5PK/iAuzAU" \
|
|
+"M6JUpELuQYgqugoCgBXMgsMlpAO/0C3CFq4ZH3KgIsRlRngKPrt6RG0UPMRD1CE2" \
|
|
+"tSVkwUWvyK83lDiu2BbWDXyMyz5eZOlp7uHusf5BKvob8jEndHj1YzaNTmVSsDM5" \
|
|
+"kiIwf8qgFhsO1HCq08PtAnbVHhqkcvnmIJN98eNWNfTKodDmFVbN8gB0wK+WB5ii" \
|
|
+"WVOw7+3/zF1QgqnYX3t+kPLRryip/wvTZkzXWwMNj/W6UHgjNF/4gWGoBgCHu+u3" \
|
|
+"EvjMmbVSrEkesibpGQS5"
|
|
+
|
|
|
|
static char CACHED_AUTH_TIMEOUT_STR[] = "4";
|
|
static const int CACHED_AUTH_TIMEOUT = 4;
|
|
@@ -111,6 +136,13 @@ static errno_t setup_nss_db(void)
|
|
return ret;
|
|
}
|
|
|
|
+ ret = mkdir(NSS_DB_PATH_2CERTS, 0775);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE,
|
|
+ "Failed to create " NSS_DB_PATH_2CERTS ".\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
child_pid = fork();
|
|
if (child_pid == 0) { /* child */
|
|
ret = execlp("certutil", "certutil", "-N", "--empty-password", "-d",
|
|
@@ -127,6 +159,22 @@ static errno_t setup_nss_db(void)
|
|
return ret;
|
|
}
|
|
|
|
+ child_pid = fork();
|
|
+ if (child_pid == 0) { /* child */
|
|
+ ret = execlp("certutil", "certutil", "-N", "--empty-password", "-d",
|
|
+ NSS_DB_2CERTS, NULL);
|
|
+ if (ret == -1) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "execl() failed.\n");
|
|
+ exit(-1);
|
|
+ }
|
|
+ } else if (child_pid > 0) {
|
|
+ wait(&status);
|
|
+ } else {
|
|
+ ret = errno;
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "fork() failed\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
fp = fopen(NSS_DB_PATH"/pkcs11.txt", "w");
|
|
if (fp == NULL) {
|
|
DEBUG(SSSDBG_FATAL_FAILURE, "fopen() failed.\n");
|
|
@@ -148,6 +196,27 @@ static errno_t setup_nss_db(void)
|
|
return ret;
|
|
}
|
|
|
|
+ fp = fopen(NSS_DB_PATH_2CERTS"/pkcs11.txt", "w");
|
|
+ if (fp == NULL) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "fopen() failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+ ret = fprintf(fp, "library=libsoftokn3.so\nname=soft\n");
|
|
+ if (ret < 0) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+ ret = fprintf(fp, "parameters=configdir='sql:%s/src/tests/cmocka/p11_nssdb_2certs' dbSlotDescription='SSSD Test Slot' dbTokenDescription='SSSD Test Token' secmod='secmod.db' flags=readOnly \n\n", ABS_SRC_DIR);
|
|
+ if (ret < 0) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+ ret = fclose(fp);
|
|
+ if (ret != 0) {
|
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "fclose() failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
return EOK;
|
|
}
|
|
|
|
@@ -174,6 +243,26 @@ static void cleanup_nss_db(void)
|
|
if (ret != EOK) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "Failed to remove " NSS_DB_PATH "\n");
|
|
}
|
|
+
|
|
+ ret = unlink(NSS_DB_PATH_2CERTS"/cert9.db");
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove cert9.db.\n");
|
|
+ }
|
|
+
|
|
+ ret = unlink(NSS_DB_PATH_2CERTS"/key4.db");
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove key4.db.\n");
|
|
+ }
|
|
+
|
|
+ ret = unlink(NSS_DB_PATH_2CERTS"/pkcs11.txt");
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove pkcs11.db.\n");
|
|
+ }
|
|
+
|
|
+ ret = rmdir(NSS_DB_PATH_2CERTS);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove " NSS_DB_PATH "\n");
|
|
+ }
|
|
}
|
|
|
|
struct pam_ctx *mock_pctx(TALLOC_CTX *mem_ctx)
|
|
@@ -749,7 +838,8 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body,
|
|
}
|
|
|
|
static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
|
|
- enum response_type type, const char *name)
|
|
+ enum response_type type, const char *name,
|
|
+ const char *name2)
|
|
{
|
|
size_t rp = 0;
|
|
uint32_t val;
|
|
@@ -763,7 +853,11 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
|
|
if (name == NULL || *name == '\0') {
|
|
assert_int_equal(val, 1);
|
|
} else {
|
|
- assert_int_equal(val, 2);
|
|
+ if (name2 == NULL || *name2 == '\0') {
|
|
+ assert_int_equal(val, 2);
|
|
+ } else {
|
|
+ assert_int_equal(val, 3);
|
|
+ }
|
|
|
|
SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
|
|
assert_int_equal(val, SSS_PAM_DOMAIN_NAME);
|
|
@@ -801,6 +895,33 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
|
|
assert_string_equal(body + rp, TEST_KEY_ID);
|
|
rp += sizeof(TEST_KEY_ID);
|
|
|
|
+ if (name2 != NULL && *name2 != '\0') {
|
|
+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
|
|
+ assert_int_equal(val, type);
|
|
+
|
|
+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
|
|
+ assert_int_equal(val, (strlen(name) + 1
|
|
+ + sizeof(TEST_TOKEN_NAME)
|
|
+ + sizeof(TEST_MODULE_NAME)
|
|
+ + sizeof(TEST2_KEY_ID)));
|
|
+
|
|
+ assert_int_equal(*(body + rp + strlen(name)), 0);
|
|
+ assert_string_equal(body + rp, name);
|
|
+ rp += strlen(name) + 1;
|
|
+
|
|
+ assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0);
|
|
+ assert_string_equal(body + rp, TEST_TOKEN_NAME);
|
|
+ rp += sizeof(TEST_TOKEN_NAME);
|
|
+
|
|
+ assert_int_equal(*(body + rp + sizeof(TEST_MODULE_NAME) - 1), 0);
|
|
+ assert_string_equal(body + rp, TEST_MODULE_NAME);
|
|
+ rp += sizeof(TEST_MODULE_NAME);
|
|
+
|
|
+ assert_int_equal(*(body + rp + sizeof(TEST2_KEY_ID) - 1), 0);
|
|
+ assert_string_equal(body + rp, TEST2_KEY_ID);
|
|
+ rp += sizeof(TEST2_KEY_ID);
|
|
+ }
|
|
+
|
|
assert_int_equal(rp, blen);
|
|
|
|
return EOK;
|
|
@@ -809,7 +930,8 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
|
|
static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen)
|
|
{
|
|
return test_pam_cert_check_ex(status, body, blen,
|
|
- SSS_PAM_CERT_INFO, "pamuser@"TEST_DOM_NAME);
|
|
+ SSS_PAM_CERT_INFO, "pamuser@"TEST_DOM_NAME,
|
|
+ NULL);
|
|
}
|
|
|
|
static int test_pam_cert_check_with_hint(uint32_t status, uint8_t *body,
|
|
@@ -817,14 +939,22 @@ static int test_pam_cert_check_with_hint(uint32_t status, uint8_t *body,
|
|
{
|
|
return test_pam_cert_check_ex(status, body, blen,
|
|
SSS_PAM_CERT_INFO_WITH_HINT,
|
|
- "pamuser@"TEST_DOM_NAME);
|
|
+ "pamuser@"TEST_DOM_NAME, NULL);
|
|
}
|
|
|
|
static int test_pam_cert_check_with_hint_no_user(uint32_t status, uint8_t *body,
|
|
size_t blen)
|
|
{
|
|
return test_pam_cert_check_ex(status, body, blen,
|
|
- SSS_PAM_CERT_INFO_WITH_HINT, "");
|
|
+ SSS_PAM_CERT_INFO_WITH_HINT, "", NULL);
|
|
+}
|
|
+
|
|
+int test_pam_cert_check_2certs(uint32_t status, uint8_t *body,
|
|
+ size_t blen)
|
|
+{
|
|
+ return test_pam_cert_check_ex(status, body, blen,
|
|
+ SSS_PAM_CERT_INFO, "pamuser@"TEST_DOM_NAME,
|
|
+ "pamuser@"TEST_DOM_NAME);
|
|
}
|
|
|
|
static int test_pam_offline_chauthtok_check(uint32_t status,
|
|
@@ -1737,6 +1867,33 @@ static int test_lookup_by_cert_cb(void *pvt)
|
|
|
|
return EOK;
|
|
}
|
|
+int test_lookup_by_cert_cb_2nd_cert_same_user(void *pvt)
|
|
+{
|
|
+ int ret;
|
|
+ struct sysdb_attrs *attrs;
|
|
+ unsigned char *der = NULL;
|
|
+ size_t der_size;
|
|
+
|
|
+ test_lookup_by_cert_cb(pvt);
|
|
+
|
|
+ attrs = sysdb_new_attrs(pam_test_ctx);
|
|
+ assert_non_null(attrs);
|
|
+
|
|
+ der = sss_base64_decode(pam_test_ctx, TEST_TOKEN_2ND_CERT, &der_size);
|
|
+ assert_non_null(der);
|
|
+
|
|
+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size);
|
|
+ talloc_free(der);
|
|
+ assert_int_equal(ret, EOK);
|
|
+
|
|
+ ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom,
|
|
+ pam_test_ctx->pam_user_fqdn,
|
|
+ attrs,
|
|
+ LDB_FLAG_MOD_ADD);
|
|
+ assert_int_equal(ret, EOK);
|
|
+
|
|
+ return EOK;
|
|
+}
|
|
|
|
static int test_lookup_by_cert_double_cb(void *pvt)
|
|
{
|
|
diff --git a/src/tests/whitespace_test b/src/tests/whitespace_test
|
|
index 799e35358b1d5ae4b10c4405068fb507cb234b6f..f055ed4c255db4001194844f45a9df7cda774b38 100755
|
|
--- a/src/tests/whitespace_test
|
|
+++ b/src/tests/whitespace_test
|
|
@@ -39,7 +39,7 @@ fi
|
|
declare found_file=false
|
|
while read file; do
|
|
[[ $file == "src/config/testconfigs/noparse.api.conf" ]] && continue
|
|
- [[ $file =~ ^src/tests/cmocka/p11_nssdb/.*db ]] && continue
|
|
+ [[ $file =~ ^src/tests/cmocka/p11_nssdb.*/.*db ]] && continue
|
|
test `tail -c 1 $ABS_TOP_SRCDIR/$file` && \
|
|
echo "Missing new line at the eof: $file" && \
|
|
found_file=true
|
|
--
|
|
2.15.1
|
|
|