From 940be5f7639dd81008abdf86f6b78389f8c39b7b Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 27 May 2015 18:23:49 +0200 Subject: [PATCH 5/8] LDAP/IPA: add user lookup by certificate Related to https://fedorahosted.org/sssd/ticket/2596 --- src/providers/data_provider.h | 6 +++- src/providers/data_provider_be.c | 5 ++++ src/providers/ipa/ipa_subdomains_id.c | 14 +++++++++ src/providers/ldap/ldap_id.c | 55 +++++++++++++++++++++++++++++++---- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index 657d2b798cf28fa59c9f644e343f2a2482609bad..13a700308e9c9d1a80c0310dbb1c17de33607498 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -128,6 +128,7 @@ #define BE_FILTER_ENUM 3 #define BE_FILTER_SECID 4 #define BE_FILTER_UUID 5 +#define BE_FILTER_CERT 6 #define BE_REQ_USER 0x0001 #define BE_REQ_GROUP 0x0002 @@ -140,14 +141,17 @@ #define BE_REQ_HOST 0x0010 #define BE_REQ_BY_SECID 0x0011 #define BE_REQ_USER_AND_GROUP 0x0012 -#define BE_REQ_BY_UUID 0x0013 +#define BE_REQ_BY_UUID 0x0013 +#define BE_REQ_BY_CERT 0x0014 #define BE_REQ_TYPE_MASK 0x00FF #define BE_REQ_FAST 0x1000 #define DP_SEC_ID "secid" +#define DP_CERT "cert" /* sizeof() counts the trailing \0 so we must substract 1 for the string * length */ #define DP_SEC_ID_LEN (sizeof(DP_SEC_ID) - 1) +#define DP_CERT_LEN (sizeof(DP_CERT) - 1) #define EXTRA_NAME_IS_UPN "U" #define EXTRA_INPUT_MAYBE_WITH_VIEW "V" diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c index 34c7b2c766ee4072ee980ad43f1e1d33ee7c8a5a..f5bdfb676011975defa4c5a734d420c8694f3bdd 100644 --- a/src/providers/data_provider_be.c +++ b/src/providers/data_provider_be.c @@ -1199,6 +1199,11 @@ static int be_get_account_info(struct sbus_request *dbus_req, void *user_data) ret = split_name_extended(req, &filter[DP_SEC_ID_LEN + 1], &req->filter_value, &req->extra_value); + } else if (strncmp(filter, DP_CERT"=", DP_CERT_LEN + 1) == 0) { + req->filter_type = BE_FILTER_CERT; + ret = split_name_extended(req, &filter[DP_CERT_LEN + 1], + &req->filter_value, + &req->extra_value); } else if (strcmp(filter, ENUM_INDICATOR) == 0) { req->filter_type = BE_FILTER_ENUM; req->filter_value = NULL; diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index b5c0aa0b531619d34309e12e4cd8084f7beee88a..610b1c58b3b180201cfb5b22f870f8937673e02e 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -934,6 +934,20 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, ret = EOK; goto done; + } 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) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to make request to our cache: [%d]: [%s]\n", + ret, sss_strerror(ret)); + goto done; + } + + *_msg = res->msgs[0]; + + ret = EOK; + goto done; } else if (ar->filter_type == BE_FILTER_IDNUM) { errno = 0; id = strtouint32(ar->filter_value, NULL, 10); diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index d4f46f1dcd69898e5883d21be07f895fd198cf50..ff117d82957b3b23d9cedc5e513255804103f916 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -28,6 +28,7 @@ #include "util/util.h" #include "util/strtonum.h" +#include "util/cert.h" #include "db/sysdb.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" @@ -78,12 +79,13 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, struct tevent_req *req; struct users_get_state *state; const char *attr_name = NULL; - char *clean_name; + char *clean_name = NULL; char *endptr; int ret; uid_t uid; enum idmap_error_code err; char *sid; + char *user_filter = NULL; req = tevent_req_create(memctx, &state, struct users_get_state); if (!req) return NULL; @@ -194,6 +196,23 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, goto done; } break; + case BE_FILTER_CERT: + attr_name = ctx->opts->user_map[SDAP_AT_USER_CERT].name; + if (attr_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Certificate search not configured for this backend.\n"); + ret = EINVAL; + goto done; + } + + ret = sss_cert_derb64_to_ldap_filter(state, name, attr_name, + &user_filter); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_cert_derb64_to_ldap_filter failed.\n"); + goto done; + } + break; default: ret = EINVAL; goto done; @@ -205,29 +224,39 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, goto done; } + if (user_filter == NULL) { + user_filter = talloc_asprintf(state, "(%s=%s)", attr_name, clean_name); + talloc_free(clean_name); + if (user_filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + } + if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { /* When mapping IDs or looking for SIDs, we don't want to limit * ourselves to users with a UID value. But there must be a SID to map * from. */ state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))", - attr_name, clean_name, + "(&%s(objectclass=%s)(%s=*)(%s=*))", + user_filter, ctx->opts->user_map[SDAP_OC_USER].name, ctx->opts->user_map[SDAP_AT_USER_NAME].name, ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); } else { /* When not ID-mapping, make sure there is a non-NULL UID */ state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", - attr_name, clean_name, + "(&%s(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", + user_filter, ctx->opts->user_map[SDAP_OC_USER].name, ctx->opts->user_map[SDAP_AT_USER_NAME].name, ctx->opts->user_map[SDAP_AT_USER_UID].name, ctx->opts->user_map[SDAP_AT_USER_UID].name); } - talloc_zfree(clean_name); + talloc_zfree(user_filter); if (!state->filter) { DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n"); ret = ENOMEM; @@ -1537,6 +1566,16 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, noexist_delete); break; + case BE_REQ_BY_CERT: + subreq = users_get_send(state, be_ctx->ev, id_ctx, + sdom, conn, + ar->filter_value, + ar->filter_type, + ar->extra_value, + ar->attr_type, + noexist_delete); + break; + default: /*fail*/ ret = EINVAL; state->err = "Invalid request type"; @@ -1602,6 +1641,10 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) ret = sdap_get_user_and_group_recv(subreq, &state->dp_error, &state->sdap_ret); break; + case BE_REQ_BY_CERT: + err = "User lookup by certificate failed"; + ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + break; default: /*fail*/ ret = EINVAL; break; -- 2.1.0