URL: https://github.com/freeipa/freeipa/pull/644
Author: sumit-bose
 Title: #644: extdom: improve certificate request
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/644/head:pr644
git checkout pr644
From 90e000fbccf8be924520f7cb480ce115ed74c983 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 17 Mar 2017 14:10:52 +0100
Subject: [PATCH 1/2] extdom: do reverse search for domain separator

To avoid issues which @-signs in the short user or group names it is
better to search for the domain separator starting at the end of the
fully-qualified name.
---
 daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

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 e629247..aa1ff10 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
@@ -515,7 +515,7 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
     char *short_user_name = NULL;
 
     short_user_name = strdup(user_name);
-    if ((locat = strchr(short_user_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
+    if ((locat = strrchr(short_user_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
         if (strcasecmp(locat+1, domain_name) == 0  ) {
             locat[0] = '\0';
         } else {
@@ -626,7 +626,7 @@ int pack_ber_group(enum response_types response_type,
     char *short_group_name = NULL;
 
     short_group_name = strdup(group_name);
-    if ((locat = strchr(short_group_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
+    if ((locat = strrchr(short_group_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
         if (strcasecmp(locat+1, domain_name) == 0  ) {
             locat[0] = '\0';
         } else {
@@ -901,7 +901,7 @@ static int handle_sid_or_cert_request(struct ipa_extdom_ctx *ctx,
         goto done;
     }
 
-    sep = strchr(fq_name, SSSD_DOMAIN_SEPARATOR);
+    sep = strrchr(fq_name, SSSD_DOMAIN_SEPARATOR);
     if (sep == NULL) {
         set_err_msg(req, "Failed to split fully qualified name");
         ret = LDAP_OPERATIONS_ERROR;

From ed8703fa99fd31997d6a0fcfcf10e5fe487a0f7a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 17 Mar 2017 14:48:50 +0100
Subject: [PATCH 2/2] 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/6646
---
 .../ipa-extdom-extop/ipa_extdom.h                  |   3 +-
 .../ipa-extdom-extop/ipa_extdom_common.c           | 157 ++++++++++++++++++---
 server.m4                                          |   2 +-
 3 files changed, 143 insertions(+), 19 deletions(-)

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 @@ int pack_ber_group(enum response_types response_type,
     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 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
     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 92b5cdd..d6f233e 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 ---------------------------------------------------------------------------
 dnl - Check for KRB5 krad
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to