|
|
9f2ebf |
From 426dd731fe7c804c4b9d96c62d1a60a9022dcb09 Mon Sep 17 00:00:00 2001
|
|
|
9f2ebf |
From: Sumit Bose <sbose@redhat.com>
|
|
|
9f2ebf |
Date: Tue, 17 Jan 2017 15:55:18 +0100
|
|
|
9f2ebf |
Subject: [PATCH 36/46] p11_child: return multiple certs
|
|
|
9f2ebf |
MIME-Version: 1.0
|
|
|
9f2ebf |
Content-Type: text/plain; charset=UTF-8
|
|
|
9f2ebf |
Content-Transfer-Encoding: 8bit
|
|
|
9f2ebf |
|
|
|
9f2ebf |
This patch refactors the handling of certificates in p11_child. Not only
|
|
|
9f2ebf |
the first but all certificates suitable for authentication are returned.
|
|
|
9f2ebf |
The PAM responder component calling p11_child is refactored to handle
|
|
|
9f2ebf |
multiple certificate returned by p11_child but so far only returns the
|
|
|
9f2ebf |
first one to its callers.
|
|
|
9f2ebf |
|
|
|
9f2ebf |
Related to https://pagure.io/SSSD/sssd/issue/3560
|
|
|
9f2ebf |
|
|
|
9f2ebf |
Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
|
|
|
9f2ebf |
Tested-by: Scott Poore <spoore@redhat.com>
|
|
|
9f2ebf |
(cherry picked from commit 39fd336e4390ece3a8465714735ef4203f329e54)
|
|
|
9f2ebf |
---
|
|
|
9f2ebf |
src/p11_child/p11_child_nss.c | 131 +++++++++++++---------
|
|
|
9f2ebf |
src/responder/pam/pamsrv.h | 2 +
|
|
|
9f2ebf |
src/responder/pam/pamsrv_p11.c | 242 +++++++++++++++++++++++------------------
|
|
|
9f2ebf |
3 files changed, 219 insertions(+), 156 deletions(-)
|
|
|
9f2ebf |
|
|
|
9f2ebf |
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
|
|
|
9f2ebf |
index b0ec69be321c4b4186ce851c07bfcc3e1afe9694..50bde2f4f91f6c00260b0db383d0962112686ebc 100644
|
|
|
9f2ebf |
--- a/src/p11_child/p11_child_nss.c
|
|
|
9f2ebf |
+++ b/src/p11_child/p11_child_nss.c
|
|
|
9f2ebf |
@@ -72,8 +72,7 @@ static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
|
9f2ebf |
int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
enum op_mode mode, const char *pin,
|
|
|
9f2ebf |
struct cert_verify_opts *cert_verify_opts,
|
|
|
9f2ebf |
- char **cert, char **token_name_out, char **module_name_out,
|
|
|
9f2ebf |
- char **key_id_out)
|
|
|
9f2ebf |
+ char **_multi)
|
|
|
9f2ebf |
{
|
|
|
9f2ebf |
int ret;
|
|
|
9f2ebf |
SECStatus rv;
|
|
|
9f2ebf |
@@ -110,7 +109,10 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
PK11SlotListElement *le;
|
|
|
9f2ebf |
SECItem *key_id = NULL;
|
|
|
9f2ebf |
char *key_id_str = NULL;
|
|
|
9f2ebf |
-
|
|
|
9f2ebf |
+ CERTCertList *valid_certs = NULL;
|
|
|
9f2ebf |
+ char *cert_b64 = NULL;
|
|
|
9f2ebf |
+ char *multi = NULL;
|
|
|
9f2ebf |
+ PRCList *node;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, ¶meters, flags);
|
|
|
9f2ebf |
if (nss_ctx == NULL) {
|
|
|
9f2ebf |
@@ -303,6 +305,14 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
found_cert = NULL;
|
|
|
9f2ebf |
+ valid_certs = CERT_NewCertList();
|
|
|
9f2ebf |
+ if (valid_certs == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewCertList failed [%d].\n",
|
|
|
9f2ebf |
+ PR_GetError());
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n");
|
|
|
9f2ebf |
for (cert_list_node = CERT_LIST_HEAD(cert_list);
|
|
|
9f2ebf |
!CERT_LIST_END(cert_list_node, cert_list);
|
|
|
9f2ebf |
@@ -326,6 +336,13 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+ rv = CERT_AddCertToListTail(valid_certs, cert_list_node->cert);
|
|
|
9f2ebf |
+ if (rv != SECSuccess) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "CERT_AddCertToListTail failed [%d].\n", PR_GetError());
|
|
|
9f2ebf |
+ ret = EIO;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (found_cert == NULL) {
|
|
|
9f2ebf |
found_cert = cert_list_node->cert;
|
|
|
9f2ebf |
@@ -352,9 +369,7 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (found_cert == NULL) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
|
|
|
9f2ebf |
- *cert = NULL;
|
|
|
9f2ebf |
- *token_name_out = NULL;
|
|
|
9f2ebf |
- *module_name_out = NULL;
|
|
|
9f2ebf |
+ *_multi = NULL;
|
|
|
9f2ebf |
ret = EOK;
|
|
|
9f2ebf |
goto done;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
@@ -421,51 +436,55 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
|
|
|
9f2ebf |
"Certificate verified and validated.\n");
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- key_id = PK11_GetLowLevelKeyIDForCert(slot, found_cert, NULL);
|
|
|
9f2ebf |
- if (key_id == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
|
|
|
9f2ebf |
- PR_GetError());
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
-
|
|
|
9f2ebf |
- key_id_str = CERT_Hexify(key_id, PR_FALSE);
|
|
|
9f2ebf |
- if (key_id_str == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n", PR_GetError());
|
|
|
9f2ebf |
+ multi = talloc_strdup(mem_ctx, "");
|
|
|
9f2ebf |
+ if (multi == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create output string.\n");
|
|
|
9f2ebf |
ret = ENOMEM;
|
|
|
9f2ebf |
goto done;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n", key_id_str);
|
|
|
9f2ebf |
+ for (cert_list_node = CERT_LIST_HEAD(valid_certs);
|
|
|
9f2ebf |
+ !CERT_LIST_END(cert_list_node, valid_certs);
|
|
|
9f2ebf |
+ cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- *key_id_out = talloc_strdup(mem_ctx, key_id_str);
|
|
|
9f2ebf |
- if (*key_id_out == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy key id.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ found_cert = cert_list_node->cert;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- *cert = sss_base64_encode(mem_ctx, found_cert->derCert.data,
|
|
|
9f2ebf |
- found_cert->derCert.len);
|
|
|
9f2ebf |
- if (*cert == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ SECITEM_FreeItem(key_id, PR_TRUE);
|
|
|
9f2ebf |
+ PORT_Free(key_id_str);
|
|
|
9f2ebf |
+ key_id = PK11_GetLowLevelKeyIDForCert(slot, found_cert, NULL);
|
|
|
9f2ebf |
+ if (key_id == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
|
|
|
9f2ebf |
+ PR_GetError());
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- *token_name_out = talloc_strdup(mem_ctx, token_name);
|
|
|
9f2ebf |
- if (*token_name_out == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy slot name.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ key_id_str = CERT_Hexify(key_id, PR_FALSE);
|
|
|
9f2ebf |
+ if (key_id_str == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n",
|
|
|
9f2ebf |
+ PR_GetError());
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- *module_name_out = talloc_strdup(mem_ctx, module_name);
|
|
|
9f2ebf |
- if (*module_name_out == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy module_name_out name.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
+ talloc_free(cert_b64);
|
|
|
9f2ebf |
+ cert_b64 = sss_base64_encode(mem_ctx, found_cert->derCert.data,
|
|
|
9f2ebf |
+ found_cert->derCert.len);
|
|
|
9f2ebf |
+ if (cert_b64 == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
|
|
|
9f2ebf |
+ key_id_str);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ multi = talloc_asprintf_append(multi, "%s\n%s\n%s\n%s\n",
|
|
|
9f2ebf |
+ token_name, module_name, key_id_str,
|
|
|
9f2ebf |
+ cert_b64);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
+ *_multi = multi;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
ret = EOK;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
@@ -474,6 +493,18 @@ done:
|
|
|
9f2ebf |
PK11_FreeSlot(slot);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+ if (valid_certs != NULL) {
|
|
|
9f2ebf |
+ /* The certificates can be found in valid_certs and cert_list and
|
|
|
9f2ebf |
+ * CERT_DestroyCertList() will free the certificates as well. To avoid
|
|
|
9f2ebf |
+ * a double free the nodes from valid_certs are removed first because
|
|
|
9f2ebf |
+ * valid_certs will only have a sub-set of the certificates. */
|
|
|
9f2ebf |
+ while (!PR_CLIST_IS_EMPTY(&valid_certs->list)) {
|
|
|
9f2ebf |
+ node = PR_LIST_HEAD(&valid_certs->list);
|
|
|
9f2ebf |
+ PR_REMOVE_LINK(node);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ CERT_DestroyCertList(valid_certs);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
if (cert_list != NULL) {
|
|
|
9f2ebf |
CERT_DestroyCertList(cert_list);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
@@ -483,6 +514,8 @@ done:
|
|
|
9f2ebf |
|
|
|
9f2ebf |
PORT_Free(signed_random_value.data);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+ talloc_free(cert_b64);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
rv = NSS_ShutdownContext(nss_ctx);
|
|
|
9f2ebf |
if (rv != SECSuccess) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",
|
|
|
9f2ebf |
@@ -540,17 +573,14 @@ int main(int argc, const char *argv[])
|
|
|
9f2ebf |
const char *opt_logger = NULL;
|
|
|
9f2ebf |
errno_t ret;
|
|
|
9f2ebf |
TALLOC_CTX *main_ctx = NULL;
|
|
|
9f2ebf |
- char *cert;
|
|
|
9f2ebf |
enum op_mode mode = OP_NONE;
|
|
|
9f2ebf |
enum pin_mode pin_mode = PIN_NONE;
|
|
|
9f2ebf |
char *pin = NULL;
|
|
|
9f2ebf |
char *slot_name_in = NULL;
|
|
|
9f2ebf |
- char *token_name_out = NULL;
|
|
|
9f2ebf |
- char *module_name_out = NULL;
|
|
|
9f2ebf |
- char *key_id_out = NULL;
|
|
|
9f2ebf |
char *nss_db = NULL;
|
|
|
9f2ebf |
struct cert_verify_opts *cert_verify_opts;
|
|
|
9f2ebf |
char *verify_opts = NULL;
|
|
|
9f2ebf |
+ char *multi = NULL;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
struct poptOption long_options[] = {
|
|
|
9f2ebf |
POPT_AUTOHELP
|
|
|
9f2ebf |
@@ -715,17 +745,14 @@ int main(int argc, const char *argv[])
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, cert_verify_opts,
|
|
|
9f2ebf |
- &cert, &token_name_out, &module_name_out, &key_id_out);
|
|
|
9f2ebf |
+ &multi);
|
|
|
9f2ebf |
if (ret != EOK) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
|
|
|
9f2ebf |
goto fail;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- if (cert != NULL) {
|
|
|
9f2ebf |
- fprintf(stdout, "%s\n", token_name_out);
|
|
|
9f2ebf |
- fprintf(stdout, "%s\n", module_name_out);
|
|
|
9f2ebf |
- fprintf(stdout, "%s\n", key_id_out);
|
|
|
9f2ebf |
- fprintf(stdout, "%s\n", cert);
|
|
|
9f2ebf |
+ if (multi != NULL) {
|
|
|
9f2ebf |
+ fprintf(stdout, "%s", multi);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
talloc_free(main_ctx);
|
|
|
9f2ebf |
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
|
|
|
9f2ebf |
index 57a37b72594f030995f5e22255eb7a8fcd63d10e..896f71befbc9947a53b5eb20cba0bb3d104c4cf2 100644
|
|
|
9f2ebf |
--- a/src/responder/pam/pamsrv.h
|
|
|
9f2ebf |
+++ b/src/responder/pam/pamsrv.h
|
|
|
9f2ebf |
@@ -88,6 +88,8 @@ int LOCAL_pam_handler(struct pam_auth_req *preq);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
errno_t p11_child_init(struct pam_ctx *pctx);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+struct cert_auth_info;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
struct tevent_context *ev,
|
|
|
9f2ebf |
int child_debug_fd,
|
|
|
9f2ebf |
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
|
|
|
9f2ebf |
index 4dce43800c3c6b026c545df35c846269cbb49610..ff32d1e726808caa36ca7cca557220866ef1a9ab 100644
|
|
|
9f2ebf |
--- a/src/responder/pam/pamsrv_p11.c
|
|
|
9f2ebf |
+++ b/src/responder/pam/pamsrv_p11.c
|
|
|
9f2ebf |
@@ -35,6 +35,15 @@
|
|
|
9f2ebf |
#define P11_CHILD_LOG_FILE "p11_child"
|
|
|
9f2ebf |
#define P11_CHILD_PATH SSSD_LIBEXEC_PATH"/p11_child"
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+struct cert_auth_info {
|
|
|
9f2ebf |
+ char *cert;
|
|
|
9f2ebf |
+ char *token_name;
|
|
|
9f2ebf |
+ char *module_name;
|
|
|
9f2ebf |
+ char *key_id;
|
|
|
9f2ebf |
+ struct cert_auth_info *prev;
|
|
|
9f2ebf |
+ struct cert_auth_info *next;
|
|
|
9f2ebf |
+};
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
errno_t p11_child_init(struct pam_ctx *pctx)
|
|
|
9f2ebf |
{
|
|
|
9f2ebf |
return child_debug_init(P11_CHILD_LOG_FILE, &pctx->p11_child_debug_fd);
|
|
|
9f2ebf |
@@ -132,18 +141,15 @@ static errno_t get_p11_child_write_buffer(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
|
|
|
9f2ebf |
- ssize_t buf_len, char **_cert,
|
|
|
9f2ebf |
- char **_token_name, char **_module_name,
|
|
|
9f2ebf |
- char **_key_id)
|
|
|
9f2ebf |
+ ssize_t buf_len,
|
|
|
9f2ebf |
+ struct cert_auth_info **_cert_list)
|
|
|
9f2ebf |
{
|
|
|
9f2ebf |
int ret;
|
|
|
9f2ebf |
TALLOC_CTX *tmp_ctx = NULL;
|
|
|
9f2ebf |
uint8_t *p;
|
|
|
9f2ebf |
uint8_t *pn;
|
|
|
9f2ebf |
- char *cert = NULL;
|
|
|
9f2ebf |
- char *token_name = NULL;
|
|
|
9f2ebf |
- char *module_name = NULL;
|
|
|
9f2ebf |
- char *key_id = NULL;
|
|
|
9f2ebf |
+ struct cert_auth_info *cert_list = NULL;
|
|
|
9f2ebf |
+ struct cert_auth_info *cert_auth_info;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (buf_len < 0) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
9f2ebf |
@@ -157,108 +163,132 @@ static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
|
|
|
9f2ebf |
goto done;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- p = memchr(buf, '\n', buf_len);
|
|
|
9f2ebf |
- if (p == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
- return EINVAL;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
- if (p == buf) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "Missing counter in p11_child response.\n");
|
|
|
9f2ebf |
- return EINVAL;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
-
|
|
|
9f2ebf |
tmp_ctx = talloc_new(NULL);
|
|
|
9f2ebf |
if (tmp_ctx == NULL) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
|
|
|
9f2ebf |
return ENOMEM;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- token_name = talloc_strndup(tmp_ctx, (char*) buf, (p - buf));
|
|
|
9f2ebf |
- if (token_name == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ p = buf;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- p++;
|
|
|
9f2ebf |
- pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
- if (pn == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
- "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ do {
|
|
|
9f2ebf |
+ cert_auth_info = talloc_zero(tmp_ctx, struct cert_auth_info);
|
|
|
9f2ebf |
+ if (cert_auth_info == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- if (pn == p) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
- "Missing module name in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
+ if (pn == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
+ return EINVAL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ if (pn == p) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing counter in p11_child response.\n");
|
|
|
9f2ebf |
+ return EINVAL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- module_name = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
|
|
|
9f2ebf |
- if (module_name == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
- DEBUG(SSSDBG_TRACE_ALL, "Found module name [%s].\n", module_name);
|
|
|
9f2ebf |
+ cert_auth_info->token_name = talloc_strndup(cert_auth_info, (char *)p,
|
|
|
9f2ebf |
+ (pn - p));
|
|
|
9f2ebf |
+ if (cert_auth_info->token_name == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_ALL, "Found token name [%s].\n",
|
|
|
9f2ebf |
+ cert_auth_info->token_name);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- p = ++pn;
|
|
|
9f2ebf |
- pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
- if (pn == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
- "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ p = ++pn;
|
|
|
9f2ebf |
+ pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
+ if (pn == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- if (pn == p) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
- "Missing key id in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ if (pn == p) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing module name in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- key_id = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
|
|
|
9f2ebf |
- if (key_id == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
- DEBUG(SSSDBG_TRACE_ALL, "Found key id [%s].\n", key_id);
|
|
|
9f2ebf |
+ cert_auth_info->module_name = talloc_strndup(cert_auth_info, (char *)p,
|
|
|
9f2ebf |
+ (pn - p));
|
|
|
9f2ebf |
+ if (cert_auth_info->module_name == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_ALL, "Found module name [%s].\n",
|
|
|
9f2ebf |
+ cert_auth_info->module_name);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- p = pn + 1;
|
|
|
9f2ebf |
- pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
- if (pn == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
- "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ p = ++pn;
|
|
|
9f2ebf |
+ pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
+ if (pn == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- if (pn == p) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n");
|
|
|
9f2ebf |
- ret = EINVAL;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
+ if (pn == p) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing key id in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- cert = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
|
|
|
9f2ebf |
- if(cert == NULL) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
- ret = ENOMEM;
|
|
|
9f2ebf |
- goto done;
|
|
|
9f2ebf |
- }
|
|
|
9f2ebf |
- DEBUG(SSSDBG_TRACE_ALL, "Found cert [%s].\n", cert);
|
|
|
9f2ebf |
+ cert_auth_info->key_id = talloc_strndup(cert_auth_info, (char *)p,
|
|
|
9f2ebf |
+ (pn - p));
|
|
|
9f2ebf |
+ if (cert_auth_info->key_id == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_ALL, "Found key id [%s].\n", cert_auth_info->key_id);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ p = ++pn;
|
|
|
9f2ebf |
+ pn = memchr(p, '\n', buf_len - (p - buf));
|
|
|
9f2ebf |
+ if (pn == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Missing new-line in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (pn == p) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n");
|
|
|
9f2ebf |
+ ret = EINVAL;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ cert_auth_info->cert = talloc_strndup(cert_auth_info, (char *)p,
|
|
|
9f2ebf |
+ (pn - p));
|
|
|
9f2ebf |
+ if (cert_auth_info->cert == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_ALL, "Found cert [%s].\n", cert_auth_info->cert);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ DLIST_ADD(cert_list, cert_auth_info);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ p = ++pn;
|
|
|
9f2ebf |
+ } while ((pn - buf) < buf_len);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
ret = EOK;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
done:
|
|
|
9f2ebf |
if (ret == EOK) {
|
|
|
9f2ebf |
- *_token_name = talloc_steal(mem_ctx, token_name);
|
|
|
9f2ebf |
- *_cert = talloc_steal(mem_ctx, cert);
|
|
|
9f2ebf |
- *_module_name = talloc_steal(mem_ctx, module_name);
|
|
|
9f2ebf |
- *_key_id = talloc_steal(mem_ctx, key_id);
|
|
|
9f2ebf |
+ DLIST_FOR_EACH(cert_auth_info, cert_list) {
|
|
|
9f2ebf |
+ talloc_steal(mem_ctx, cert_auth_info);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ *_cert_list = cert_list;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
talloc_free(tmp_ctx);
|
|
|
9f2ebf |
@@ -273,10 +303,8 @@ struct pam_check_cert_state {
|
|
|
9f2ebf |
struct tevent_context *ev;
|
|
|
9f2ebf |
|
|
|
9f2ebf |
struct child_io_fds *io;
|
|
|
9f2ebf |
- char *cert;
|
|
|
9f2ebf |
- char *token_name;
|
|
|
9f2ebf |
- char *module_name;
|
|
|
9f2ebf |
- char *key_id;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ struct cert_auth_info *cert_list;
|
|
|
9f2ebf |
};
|
|
|
9f2ebf |
|
|
|
9f2ebf |
static void p11_child_write_done(struct tevent_req *subreq);
|
|
|
9f2ebf |
@@ -349,9 +377,6 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
|
|
|
9f2ebf |
state->ev = ev;
|
|
|
9f2ebf |
state->child_status = EFAULT;
|
|
|
9f2ebf |
- state->cert = NULL;
|
|
|
9f2ebf |
- state->token_name = NULL;
|
|
|
9f2ebf |
- state->module_name = NULL;
|
|
|
9f2ebf |
state->io = talloc(state, struct child_io_fds);
|
|
|
9f2ebf |
if (state->io == NULL) {
|
|
|
9f2ebf |
DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
|
|
|
9f2ebf |
@@ -514,11 +539,9 @@ static void p11_child_done(struct tevent_req *subreq)
|
|
|
9f2ebf |
|
|
|
9f2ebf |
PIPE_FD_CLOSE(state->io->read_from_child_fd);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
- ret = parse_p11_child_response(state, buf, buf_len, &state->cert,
|
|
|
9f2ebf |
- &state->token_name, &state->module_name,
|
|
|
9f2ebf |
- &state->key_id);
|
|
|
9f2ebf |
+ ret = parse_p11_child_response(state, buf, buf_len, &state->cert_list);
|
|
|
9f2ebf |
if (ret != EOK) {
|
|
|
9f2ebf |
- DEBUG(SSSDBG_OP_FAILURE, "parse_p11_child_respose failed.\n");
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "parse_p11_child_response failed.\n");
|
|
|
9f2ebf |
tevent_req_error(req, ret);
|
|
|
9f2ebf |
return;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
@@ -551,20 +574,31 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
|
|
|
9f2ebf |
TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+ if (state->cert_list == NULL) {
|
|
|
9f2ebf |
+ *token_name = NULL;
|
|
|
9f2ebf |
+ *cert = NULL;
|
|
|
9f2ebf |
+ *module_name = NULL;
|
|
|
9f2ebf |
+ *key_id = NULL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
if (cert != NULL) {
|
|
|
9f2ebf |
- *cert = talloc_steal(mem_ctx, state->cert);
|
|
|
9f2ebf |
+ *cert = (state->cert_list == NULL) ? NULL
|
|
|
9f2ebf |
+ : talloc_steal(mem_ctx, state->cert_list->cert);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (token_name != NULL) {
|
|
|
9f2ebf |
- *token_name = talloc_steal(mem_ctx, state->token_name);
|
|
|
9f2ebf |
+ *token_name = (state->cert_list == NULL) ? NULL
|
|
|
9f2ebf |
+ : talloc_steal(mem_ctx, state->cert_list->token_name);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (module_name != NULL) {
|
|
|
9f2ebf |
- *module_name = talloc_steal(mem_ctx, state->module_name);
|
|
|
9f2ebf |
+ *module_name = (state->cert_list == NULL) ? NULL
|
|
|
9f2ebf |
+ : talloc_steal(mem_ctx, state->cert_list->module_name);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
if (key_id != NULL) {
|
|
|
9f2ebf |
- *key_id = talloc_steal(mem_ctx, state->key_id);
|
|
|
9f2ebf |
+ *key_id = (state->cert_list == NULL) ? NULL
|
|
|
9f2ebf |
+ : talloc_steal(mem_ctx, state->cert_list->key_id);
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
return EOK;
|
|
|
9f2ebf |
--
|
|
|
9f2ebf |
2.13.6
|
|
|
9f2ebf |
|