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