From 537e057ef3bd140e418381f2ce74397ab8c34a73 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 24 Mar 2017 15:40:41 +0100
Subject: [PATCH 59/60] IPA: lookup AD users by certificates on IPA clients
Get a list of users mapped to a certificate back from the IPA server,
look them up and store them together with the certificate used for the
search as mapped attribute to the cache.
Related to https://pagure.io/SSSD/sssd/issue/3050
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/providers/ipa/ipa_s2n_exop.c | 109 +++++++++++++++++++++++++++++++++++++--
1 file changed, 105 insertions(+), 4 deletions(-)
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 05c32a24d61947e62884f460069083fb81f40fe0..8a3391b4093f1547d84fe44a0f24b1d063d1e28c 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -52,7 +52,8 @@ enum response_types {
RESP_USER,
RESP_GROUP,
RESP_USER_GROUPLIST,
- RESP_GROUP_MEMBERS
+ RESP_GROUP_MEMBERS,
+ RESP_NAME_LIST
};
/* ==Sid2Name Extended Operation============================================= */
@@ -366,8 +367,8 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
break;
case BE_REQ_BY_CERT:
if (req_input->type == REQ_INP_CERT) {
- ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
- req_input->inp.cert);
+ ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
+ req_input->inp.cert);
} else {
DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
req_input->type);
@@ -463,6 +464,11 @@ done:
* GroupMemberList ::= SEQUENCE OF OCTET STRING
*/
+struct name_list {
+ char *domain_name;
+ char *name;
+};
+
struct resp_attrs {
enum response_types response_type;
char *domain_name;
@@ -475,6 +481,7 @@ struct resp_attrs {
size_t ngroups;
char **groups;
struct sysdb_attrs *sysdb_attrs;
+ char **name_list;
};
static errno_t get_extra_attrs(BerElement *ber, struct resp_attrs *resp_attrs)
@@ -782,6 +789,9 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
struct resp_attrs *attrs = NULL;
char *sid_str;
bool is_v1 = false;
+ char **name_list = NULL;
+ ber_len_t ber_len;
+ char *fq_name = NULL;
if (retoid == NULL || retdata == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Missing OID or data.\n");
@@ -947,6 +957,53 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
goto done;
}
break;
+ case RESP_NAME_LIST:
+ tag = ber_scanf(ber, "{");
+ if (tag == LBER_ERROR) {
+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ while (ber_peek_tag(ber, &ber_len) == LBER_SEQUENCE) {
+ tag = ber_scanf(ber, "{aa}", &domain_name, &name);
+ if (tag == LBER_ERROR) {
+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ fq_name = sss_create_internal_fqname(attrs, name, domain_name);
+ if (fq_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sss_create_internal_fqname failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_ALL, "[%s][%s][%s].\n", domain_name, name,
+ fq_name);
+
+ ret = add_string_to_list(attrs, fq_name, &name_list);
+ ber_memfree(domain_name);
+ ber_memfree(name);
+ talloc_free(fq_name);
+ domain_name = NULL;
+ name = NULL;
+ fq_name = NULL;
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "add_to_name_list failed.\n");
+ goto done;
+ }
+ }
+
+ tag = ber_scanf(ber, "}}");
+ if (tag == LBER_ERROR) {
+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+ ret = EINVAL;
+ goto done;
+ }
+ attrs->name_list = name_list;
+ break;
default:
DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
type);
@@ -955,7 +1012,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
}
attrs->response_type = type;
- if (type != RESP_SID) {
+ if (type != RESP_SID && type != RESP_NAME_LIST) {
attrs->domain_name = talloc_strdup(attrs, domain_name);
if (attrs->domain_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
@@ -969,6 +1026,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
done:
ber_memfree(domain_name);
ber_memfree(name);
+ talloc_free(fq_name);
ber_free(ber, 1);
if (ret == EOK) {
@@ -1332,6 +1390,7 @@ struct ipa_s2n_get_user_state {
struct resp_attrs *attrs;
struct resp_attrs *simple_attrs;
struct sysdb_attrs *override_attrs;
+ struct sysdb_attrs *mapped_attrs;
int exop_timeout;
};
@@ -1384,6 +1443,11 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
goto fail;
}
+ if (entry_type == BE_REQ_BY_CERT) {
+ /* Only REQ_SIMPLE is supported for BE_REQ_BY_CERT */
+ state->request_type = REQ_SIMPLE;
+ }
+
ret = s2n_encode_request(state, dom->name, entry_type, state->request_type,
req_input, &bv_req);
if (ret != EOK) {
@@ -1785,6 +1849,43 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
+ if (state->simple_attrs->response_type == RESP_NAME_LIST
+ && state->req_input->type == REQ_INP_CERT) {
+ state->mapped_attrs = sysdb_new_attrs(state);
+ if (state->mapped_attrs == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_base64_blob(state->mapped_attrs,
+ SYSDB_USER_MAPPED_CERT,
+ state->req_input->inp.cert);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n");
+ goto done;
+ }
+
+ subreq = ipa_s2n_get_list_send(state, state->ev,
+ state->ipa_ctx, state->dom,
+ state->sh, state->exop_timeout,
+ BE_REQ_USER,
+ REQ_FULL_WITH_MEMBERS,
+ REQ_INP_NAME,
+ state->simple_attrs->name_list,
+ state->mapped_attrs);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "ipa_s2n_get_list_send failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(subreq, ipa_s2n_get_list_done,
+ req);
+
+ return;
+ }
+
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n");
--
2.9.3