From 8960398a57f69c124ec3105289dc355baa0d5b09 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mar 28 2017 16:21:18 +0000 Subject: extdom: improve cert request Certificates can be assigned to multiple user so the extdom plugin must use sss_nss_getlistbycert() instead of sss_nss_getnamebycert() and return a list of fully-qualified user names. Due to issues on the SSSD side the current version of lookups by certificates didn't work at all and the changes here won't break existing clients. Related to https://pagure.io/freeipa/issue/6826 Reviewed-By: Alexander Bokovoy Reviewed-By: David Kupka --- diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h index 34e2d3c..bc29f06 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h @@ -95,7 +95,8 @@ enum response_types { RESP_USER, RESP_GROUP, RESP_USER_GROUPLIST, - RESP_GROUP_MEMBERS + RESP_GROUP_MEMBERS, + RESP_NAME_LIST }; struct extdom_req { diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c index aa1ff10..fe225fa 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c @@ -698,6 +698,90 @@ done: return ret; } +int pack_ber_name_list(struct extdom_req *req, char **fq_name_list, + struct berval **berval) +{ + BerElement *ber = NULL; + int ret; + char *sep; + size_t c; + size_t len; + size_t name_len; + + /* count the names */ + for (c = 0; fq_name_list[c] != NULL; c++); + if (c == 0) { + set_err_msg(req, "Empty name list"); + return LDAP_NO_SUCH_OBJECT; + } + + ber = ber_alloc_t( LBER_USE_DER ); + if (ber == NULL) { + set_err_msg(req, "BER alloc failed"); + return LDAP_OPERATIONS_ERROR; + } + + + ret = ber_printf(ber,"{e{", RESP_NAME_LIST); + if (ret == -1) { + set_err_msg(req, "BER start failed"); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + for (c = 0; fq_name_list[c] != NULL; c++) { + len = strlen(fq_name_list[c]); + if (len < 3) { + set_err_msg(req, "Fully qualified name too short"); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + sep = strrchr(fq_name_list[c], SSSD_DOMAIN_SEPARATOR); + if (sep == NULL) { + set_err_msg(req, "Failed to split fully qualified name"); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + name_len = sep - fq_name_list[c]; + if (name_len == 0) { + set_err_msg(req, "Missing name."); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + if (name_len + 1 == len) { + set_err_msg(req, "Missing domain."); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_printf(ber,"{oo}", (sep + 1), len - name_len -1, + fq_name_list[c], name_len); + if (ret == -1) { + set_err_msg(req, "BER list item failed"); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + } + + ret = ber_printf(ber,"}}"); + if (ret == -1) { + set_err_msg(req, "BER end failed"); + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_flatten(ber, berval); + ber_free(ber, 1); + if (ret == -1) { + set_err_msg(req, "BER flatten failed"); + return LDAP_OPERATIONS_ERROR; + } + + return LDAP_SUCCESS; +} + int pack_ber_name(const char *domain_name, const char *name, struct berval **berval) { @@ -867,12 +951,56 @@ done: return ret; } -static int handle_sid_or_cert_request(struct ipa_extdom_ctx *ctx, - struct extdom_req *req, - enum request_types request_type, - enum input_types input_type, - const char *input, - struct berval **berval) +static int handle_cert_request(struct ipa_extdom_ctx *ctx, + struct extdom_req *req, + enum request_types request_type, + enum input_types input_type, + const char *input, + struct berval **berval) +{ + int ret; + char **fq_names = NULL; + enum sss_id_type *id_types = NULL; + size_t c; + + if (request_type != REQ_SIMPLE) { + set_err_msg(req, "Only simple request type allowed " + "for lookups by certificate"); + ret = LDAP_PROTOCOL_ERROR; + goto done; + } + + ret = sss_nss_getlistbycert(input, &fq_names, &id_types); + if (ret != 0) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + set_err_msg(req, "Failed to lookup name by certificate"); + ret = LDAP_OPERATIONS_ERROR; + } + goto done; + } + + ret = pack_ber_name_list(req, fq_names, berval); + +done: + if (fq_names != NULL) { + for (c = 0; fq_names[c] != NULL; c++) { + free(fq_names[c]); + } + free(fq_names); + } + free(id_types); + + return ret; +} + +static int handle_sid_request(struct ipa_extdom_ctx *ctx, + struct extdom_req *req, + enum request_types request_type, + enum input_types input_type, + const char *input, + struct berval **berval) { int ret; struct passwd pwd; @@ -886,11 +1014,7 @@ static int handle_sid_or_cert_request(struct ipa_extdom_ctx *ctx, enum sss_id_type id_type; struct sss_nss_kv *kv_list = NULL; - if (input_type == INP_SID) { - ret = sss_nss_getnamebysid(input, &fq_name, &id_type); - } else { - ret = sss_nss_getnamebycert(input, &fq_name, &id_type); - } + ret = sss_nss_getnamebysid(input, &fq_name, &id_type); if (ret != 0) { if (ret == ENOENT) { ret = LDAP_NO_SUCH_OBJECT; @@ -1147,13 +1271,12 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, break; case INP_SID: + ret = handle_sid_request(ctx, req, req->request_type, + req->input_type, req->data.sid, berval); + break; case INP_CERT: - ret = handle_sid_or_cert_request(ctx, req, req->request_type, - req->input_type, - req->input_type == INP_SID ? - req->data.sid : - req->data.cert, - berval); + ret = handle_cert_request(ctx, req, req->request_type, + req->input_type, req->data.cert, berval); break; case INP_NAME: ret = handle_name_request(ctx, req, req->request_type, diff --git a/server.m4 b/server.m4 index a4c9919..5d5333e 100644 --- a/server.m4 +++ b/server.m4 @@ -28,7 +28,7 @@ DIRSRV_CFLAGS="$DIRSRV_CFLAGS $NSPR_CFLAGS" dnl -- sss_idmap is needed by the extdom exop -- PKG_CHECK_MODULES([SSSIDMAP], [sss_idmap]) -PKG_CHECK_MODULES([SSSNSSIDMAP], [sss_nss_idmap >= 1.13.90]) +PKG_CHECK_MODULES([SSSNSSIDMAP], [sss_nss_idmap >= 1.15.2]) dnl -- sss_certmap and certauth.h are needed by the IPA KDB certauth plugin -- PKG_CHECK_EXISTS([sss_certmap],