[Freeipa-devel] [PATCH 130] extdom: add support for new version

Sumit Bose sbose at redhat.com
Tue Sep 23 15:11:01 UTC 2014


Hi,

this patch should fix https://fedorahosted.org/freeipa/ticket/4031 and
with the corresponding SSSD part it would be possible to get the full
list of group memberships with the id command even for user who didn't
log in before.

bye,
Sumit
-------------- next part --------------
From 23ff38cdea85995b211e73f474bcb4b0d7fb8039 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 23 Sep 2014 15:55:43 +0200
Subject: [PATCH] extdom: add support for new version

Currently the extdom plugin is basically used to translate SIDs of AD
users and groups to names and POSIX IDs.

With this patch a new version is added which will return the full member
list for groups and the full list of group memberships for a user.
Additionally the gecos field, the home directory and the login shell of a
user are returned and an optional list of key-value pairs which
currently will contain the SID of the requested object if available.

https://fedorahosted.org/freeipa/ticket/4031
---
 .../ipa-extdom-extop/ipa_extdom.h                  |  29 +-
 .../ipa-extdom-extop/ipa_extdom_common.c           | 850 +++++++++++++++------
 .../ipa-extdom-extop/ipa_extdom_extop.c            |  28 +-
 3 files changed, 640 insertions(+), 267 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 5f834a047a579104cd2589ce417c580c1c5388d3..548ee74f561c474854c049726c4c3e71da5cbbea 100644
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
@@ -64,6 +64,7 @@
 #include <sss_nss_idmap.h>
 
 #define EXOP_EXTDOM_OID "2.16.840.1.113730.3.8.10.4"
+#define EXOP_EXTDOM_V2_OID "2.16.840.1.113730.3.8.10.4.1"
 
 #define IPA_EXTDOM_PLUGIN_NAME   "ipa-extdom-extop"
 #define IPA_EXTDOM_FEATURE_DESC  "IPA trusted domain ID mapper"
@@ -71,6 +72,11 @@
 
 #define IPA_PLUGIN_NAME IPA_EXTDOM_PLUGIN_NAME
 
+enum extdom_version {
+    EXTDOM_V1 = 1,
+    EXTDOM_V2
+};
+
 enum input_types {
     INP_SID = 1,
     INP_NAME,
@@ -80,14 +86,17 @@ enum input_types {
 
 enum request_types {
     REQ_SIMPLE = 1,
-    REQ_FULL
+    REQ_FULL,
+    REQ_FULL_WITH_GROUPS
 };
 
 enum response_types {
     RESP_SID = 1,
     RESP_NAME,
     RESP_USER,
-    RESP_GROUP
+    RESP_GROUP,
+    RESP_USER_GROUPLIST,
+    RESP_GROUP_MEMBERS
 };
 
 struct extdom_req {
@@ -123,11 +132,18 @@ struct extdom_res {
             char *user_name;
             uid_t uid;
             gid_t gid;
+            char *gecos;
+            char *home;
+            char *shell;
+            size_t ngroups;
+            char **groups;
         } user;
         struct {
             char *domain_name;
             char *group_name;
             gid_t gid;
+            size_t nmembers;
+            char **members;
         } group;
     } data;
 };
@@ -150,15 +166,14 @@ struct pwd_grp {
         struct passwd pwd;
         struct group grp;
     } data;
+    int ngroups;
+    gid_t *groups;
 };
 
 int parse_request_data(struct berval *req_val, struct extdom_req **_req);
 void free_req_data(struct extdom_req *req);
+int check_request(struct extdom_req *req, enum extdom_version version);
 int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
-                   struct extdom_res **res);
-int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                    const char *sid_str, enum sss_id_type id_type,
-                    const char *domain_name, struct extdom_res **_res);
-void free_resp_data(struct extdom_res *res);
+                   struct berval **berval);
 int pack_response(struct extdom_res *res, struct berval **ret_val);
 #endif /* _IPA_EXTDOM_H_ */
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 025d37dc5eda05c8db43d4e8176fd7898ed32fe7..5c1ae79c818676c3660d5cd5b8ca5515a4f0f18d 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
@@ -70,6 +70,7 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req)
  *    requestType ENUMERATED {
  *        simple (1),
  *        full (2)
+ *        full_with_groups (3)
  *    },
  *    data InputData
  * }
@@ -179,23 +180,23 @@ void free_req_data(struct extdom_req *req)
     free(req);
 }
 
-int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
-                   struct extdom_res **res)
+int check_request(struct extdom_req *req, enum extdom_version version)
+{
+    if (version == EXTDOM_V1) {
+        if (req->request_type == REQ_FULL_WITH_GROUPS) {
+            return LDAP_PROTOCOL_ERROR;
+        }
+    }
+
+    return LDAP_SUCCESS;
+}
+
+static int get_buffer(size_t *_buf_len, char **_buf)
 {
-    int ret;
-    char *domain_name = NULL;
-    char *sid_str = NULL;
-    size_t buf_len;
-    char *buf = NULL;
     long pw_max;
     long gr_max;
-    struct pwd_grp pg_data;
-    struct passwd *pwd_result = NULL;
-    struct group *grp_result = NULL;
-    enum sss_id_type id_type;
-    char *fq_name = NULL;
-    char *sep;
-
+    size_t buf_len;
+    char *buf;
 
     pw_max = sysconf(_SC_GETPW_R_SIZE_MAX);
     gr_max = sysconf(_SC_GETGR_R_SIZE_MAX);
@@ -211,302 +212,655 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
         return LDAP_OPERATIONS_ERROR;
     }
 
-    switch (req->input_type) {
-    case INP_POSIX_UID:
-        if (req->request_type == REQ_SIMPLE) {
-            ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str,
-                                     &id_type);
+    *_buf_len = buf_len;
+    *_buf = buf;
+
+    return LDAP_SUCCESS;
+}
+
+static int get_user_grouplist(const char *name, gid_t gid,
+                              size_t *_ngroups, gid_t **_groups )
+{
+    int ret;
+    int ngroups;
+    gid_t *groups;
+    gid_t *new_groups;
+
+    ngroups = 128;
+    groups = malloc(ngroups * sizeof(gid_t));
+    if (groups == NULL) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = getgrouplist(name, gid, groups, &ngroups);
+    if (ret == -1) {
+        new_groups = realloc(groups, ngroups);
+        if (new_groups == NULL) {
+            free(groups);
+            return LDAP_OPERATIONS_ERROR;
+        }
+        groups = new_groups;
+
+        ret = getgrouplist(name, gid, groups, &ngroups);
+        if (ret == -1) {
+            free(groups);
+            ret = LDAP_OPERATIONS_ERROR;
+        }
+    }
+
+    *_ngroups = ngroups;
+    *_groups = groups;
+
+    return LDAP_SUCCESS;
+}
+
+static int pack_ber_sid(const char *sid, struct berval **berval)
+{
+    BerElement *ber = NULL;
+    int ret;
+
+    ber = ber_alloc_t( LBER_USE_DER );
+    if (ber == NULL) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_printf(ber,"{es}", RESP_SID, sid);
+    if (ret == -1) {
+        ber_free(ber, 1);
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_flatten(ber, berval);
+    ber_free(ber, 1);
+    if (ret == -1) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    return LDAP_SUCCESS;
+}
+
+#define SSSD_SYSDB_SID_STR "objectSIDString"
+
+static int pack_ber_user(const char *domain_name, const char *user_name,
+                         uid_t uid, gid_t gid,
+                         const char *gecos, const char *homedir,
+                         const char *shell, const char *sid_str,
+                         struct berval **berval)
+{
+    BerElement *ber = NULL;
+    int ret;
+    enum response_types response_type;
+    size_t ngroups;
+    gid_t *groups = NULL;
+    size_t buf_len;
+    char *buf = NULL;
+    struct group grp;
+    struct group *grp_result;
+    size_t c;
+    char *locat;
+    char *short_user_name = NULL;
+    const char *single_value_string_array[] = {NULL, NULL};
+
+    if (gecos == NULL && homedir == NULL && shell == NULL) {
+        response_type = RESP_USER;
+    } else {
+        response_type = RESP_USER_GROUPLIST;
+    }
+
+    short_user_name = strdup(user_name);
+    if ((locat = strchr(short_user_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
+        if (strcasecmp(locat+1, domain_name) == 0  ) {
+            locat[0] = '\0';
         } else {
-            id_type = SSS_ID_TYPE_UID;
-            ret = getpwuid_r(req->data.posix_uid.uid, &pg_data.data.pwd, buf,
-                             buf_len, &pwd_result);
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
         }
+    }
 
-        domain_name = strdup(req->data.posix_uid.domain_name);
-        break;
-    case INP_POSIX_GID:
-        if (req->request_type == REQ_SIMPLE) {
-            ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str,
-                                     &id_type);
+    ber = ber_alloc_t( LBER_USE_DER );
+    if (ber == NULL) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_printf(ber,"{e{ssii", response_type, domain_name, short_user_name,
+                                      uid, gid);
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    if (response_type == RESP_USER_GROUPLIST) {
+        ret = get_user_grouplist(user_name, gid, &ngroups, &groups);
+        if (ret != LDAP_SUCCESS) {
+            goto done;
+        }
+
+        ret = get_buffer(&buf_len, &buf);
+        if (ret != LDAP_SUCCESS) {
+            goto done;
+        }
+
+        ret = ber_printf(ber,"sss", gecos, homedir, shell);
+        if (ret == -1) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+
+        ret = ber_printf(ber,"{");
+        if (ret == -1) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+
+        for (c = 0; c < ngroups; c++) {
+            ret = getgrgid_r(groups[c], &grp, buf, buf_len, &grp_result);
+            if (ret != 0) {
+                ret = LDAP_OPERATIONS_ERROR;
+                goto done;
+            }
+            if (grp_result == NULL) {
+                ret = LDAP_NO_SUCH_OBJECT;
+                goto done;
+            }
+
+            ret = ber_printf(ber, "s", grp.gr_name);
+            if (ret == -1) {
+                ret = LDAP_OPERATIONS_ERROR;
+                goto done;
+            }
+        }
+
+        ret = ber_printf(ber,"}");
+        if (ret == -1) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+
+        single_value_string_array[0] = sid_str;
+        ret = ber_printf(ber,"{{s{v}}}", SSSD_SYSDB_SID_STR,
+                                         single_value_string_array);
+        if (ret == -1) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+    }
+
+    ret = ber_printf(ber,"}}");
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    ret = ber_flatten(ber, berval);
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    ret = LDAP_SUCCESS;
+done:
+    free(short_user_name);
+    free(groups);
+    free(buf);
+    ber_free(ber, 1);
+    return ret;
+}
+
+static int pack_ber_group(const char *domain_name, const char *group_name,
+                          gid_t gid, char **members, const char *sid_str,
+                          struct berval **berval)
+{
+    BerElement *ber = NULL;
+    int ret;
+    size_t c;
+    char *locat;
+    char *short_group_name = NULL;
+    const char *single_value_string_array[] = {NULL, NULL};
+
+    short_group_name = strdup(group_name);
+    if ((locat = strchr(short_group_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
+        if (strcasecmp(locat+1, domain_name) == 0  ) {
+            locat[0] = '\0';
         } else {
-            id_type = SSS_ID_TYPE_GID;
-            ret = getgrgid_r(req->data.posix_gid.gid, &pg_data.data.grp, buf,
-                             buf_len, &grp_result);
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
         }
+    }
 
-        domain_name = strdup(req->data.posix_gid.domain_name);
-        break;
-    case INP_SID:
-        ret = sss_nss_getnamebysid(req->data.sid, &fq_name, &id_type);
-        if (ret != 0) {
+    ber = ber_alloc_t( LBER_USE_DER );
+    if (ber == NULL) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_printf(ber,"{e{ssi", members == NULL ? RESP_GROUP
+                                                    : RESP_GROUP_MEMBERS,
+                                    domain_name, short_group_name, gid);
+    if (ret == -1) {
+        ber_free(ber, 1);
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    if (members != NULL) {
+        ret = ber_printf(ber,"{");
+        if (ret == -1) {
             ret = LDAP_OPERATIONS_ERROR;
             goto done;
         }
 
-        sep = strrchr(fq_name, SSSD_DOMAIN_SEPARATOR);
-        if (sep == NULL) {
+        for (c = 0; members[c] != NULL; c++) {
+            ret = ber_printf(ber, "s", members[c]);
+            if (ret == -1) {
+                ret = LDAP_OPERATIONS_ERROR;
+                goto done;
+            }
+        }
+
+        ret = ber_printf(ber,"}");
+        if (ret == -1) {
             ret = LDAP_OPERATIONS_ERROR;
             goto done;
         }
 
-        ret = asprintf(&domain_name, "%s", sep+1);
+        single_value_string_array[0] = sid_str;
+        ret = ber_printf(ber,"{{s{v}}}", SSSD_SYSDB_SID_STR,
+                                         single_value_string_array);
         if (ret == -1) {
             ret = LDAP_OPERATIONS_ERROR;
-            domain_name = NULL; /* content is undefined according to
-                                   asprintf(3) */
-            goto done;
-        }
-
-        switch(id_type) {
-        case SSS_ID_TYPE_UID:
-        case SSS_ID_TYPE_BOTH:
-            ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len,
-                             &pwd_result);
-            break;
-        case SSS_ID_TYPE_GID:
-            ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len,
-                             &grp_result);
-            break;
-        default:
+            goto done;
+        }
+
+    }
+
+    ret = ber_printf(ber,"}}");
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    ret = ber_flatten(ber, berval);
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    ret = LDAP_SUCCESS;
+
+done:
+    free(short_group_name);
+    ber_free(ber, 1);
+    return ret;
+}
+
+static int pack_ber_name(const char *domain_name, const char *name,
+                         struct berval **berval)
+{
+    BerElement *ber = NULL;
+    int ret;
+
+    ber = ber_alloc_t( LBER_USE_DER );
+    if (ber == NULL) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_printf(ber,"{e{ss}}", RESP_NAME, domain_name, name);
+    if (ret == -1) {
+        ber_free(ber, 1);
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    ret = ber_flatten(ber, berval);
+    ber_free(ber, 1);
+    if (ret == -1) {
+        return LDAP_OPERATIONS_ERROR;
+    }
+
+    return LDAP_SUCCESS;
+}
+
+static int handle_uid_request(enum request_types request_type, uid_t uid,
+                              const char *domain_name, struct berval **berval)
+{
+    int ret;
+    struct passwd pwd;
+    struct passwd *pwd_result = NULL;
+    char *sid_str = NULL;
+    enum sss_id_type id_type;
+    size_t buf_len;
+    char *buf = NULL;
+
+    ret = get_buffer(&buf_len, &buf);
+    if (ret != LDAP_SUCCESS) {
+        return ret;
+    }
+
+    if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) {
+        ret = sss_nss_getsidbyid(uid, &sid_str, &id_type);
+        if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
+                            || id_type == SSS_ID_TYPE_BOTH)) {
+            if (ret == ENOENT) {
+                ret = LDAP_NO_SUCH_OBJECT;
+            } else {
+                ret = LDAP_OPERATIONS_ERROR;
+            }
+            goto done;
+        }
+    }
+
+    if (request_type == REQ_SIMPLE) {
+        ret = pack_ber_sid(sid_str, berval);
+    } else {
+        ret = getpwuid_r(uid, &pwd, buf, buf_len, &pwd_result);
+        if (ret != 0) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+        if (pwd_result == NULL) {
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
+        }
+
+        if (request_type == REQ_FULL) {
+            ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                pwd.pw_gid, NULL, NULL, NULL, NULL, berval);
+        } else  {
+            ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
+                                pwd.pw_shell, sid_str, berval);
+        }
+    }
+
+done:
+    free(sid_str);
+    free(buf);
+    return ret;
+}
+
+static int handle_gid_request(enum request_types request_type, gid_t gid,
+                              const char *domain_name, struct berval **berval)
+{
+    int ret;
+    struct group grp;
+    struct group *grp_result = NULL;
+    char *sid_str = NULL;
+    enum sss_id_type id_type;
+    size_t buf_len;
+    char *buf = NULL;
+
+    ret = get_buffer(&buf_len, &buf);
+    if (ret != LDAP_SUCCESS) {
+        return ret;
+    }
+
+    if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) {
+        ret = sss_nss_getsidbyid(gid, &sid_str, &id_type);
+        if (ret != 0 || !id_type != SSS_ID_TYPE_GID) {
+            if (ret == ENOENT) {
+                ret = LDAP_NO_SUCH_OBJECT;
+            } else {
+                ret = LDAP_OPERATIONS_ERROR;
+            }
+            goto done;
+        }
+    }
+
+    if (request_type == REQ_SIMPLE) {
+        ret = pack_ber_sid(sid_str, berval);
+    } else {
+        ret = getgrgid_r(gid, &grp, buf, buf_len, &grp_result);
+        if (ret != 0) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+        if (grp_result == NULL) {
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
+        }
+
+        if (request_type == REQ_FULL) {
+            ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid, NULL,
+                                 NULL, berval);
+        } else  {
+            ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid,
+                                 grp.gr_mem, sid_str, berval);
+        }
+    }
+
+done:
+    free(sid_str);
+    free(buf);
+    return ret;
+}
+
+static int handle_sid_request(enum request_types request_type, const char *sid,
+                              struct berval **berval)
+{
+    int ret;
+    struct passwd pwd;
+    struct passwd *pwd_result = NULL;
+    struct group grp;
+    struct group *grp_result = NULL;
+    char *domain_name = NULL;
+    char *fq_name = NULL;
+    char *object_name = NULL;
+    char *sep;
+    size_t buf_len;
+    char *buf = NULL;
+    enum sss_id_type id_type;
+
+    ret = sss_nss_getnamebysid(sid, &fq_name, &id_type);
+    if (ret != 0) {
+        if (ret == ENOENT) {
+            ret = LDAP_NO_SUCH_OBJECT;
+        } else {
+            ret = LDAP_OPERATIONS_ERROR;
+        }
+        goto done;
+    }
+
+    sep = strrchr(fq_name, SSSD_DOMAIN_SEPARATOR);
+    if (sep == NULL) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    object_name = strndup(fq_name, (sep - fq_name));
+    domain_name = strdup(sep + 1);
+    if (object_name == NULL || domain_name == NULL) {
+        ret = LDAP_OPERATIONS_ERROR;
+        goto done;
+    }
+
+    if (request_type == REQ_SIMPLE) {
+        ret = pack_ber_name(domain_name, object_name, berval);
+        goto done;
+    }
+
+    ret = get_buffer(&buf_len, &buf);
+    if (ret != LDAP_SUCCESS) {
+        return ret;
+    }
+
+    switch(id_type) {
+    case SSS_ID_TYPE_UID:
+    case SSS_ID_TYPE_BOTH:
+        ret = getpwnam_r(fq_name, &pwd, buf, buf_len, &pwd_result);
+        if (ret != 0) {
             ret = LDAP_OPERATIONS_ERROR;
             goto done;
         }
+
+        if (pwd_result == NULL) {
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
+        }
+
+        if (request_type == REQ_FULL) {
+            ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                pwd.pw_gid, NULL, NULL, NULL, NULL, berval);
+        } else  {
+            ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
+                                pwd.pw_shell, sid, berval);
+        }
         break;
-    case INP_NAME:
-        ret = asprintf(&fq_name, "%s%c%s", req->data.name.object_name,
-                                           SSSD_DOMAIN_SEPARATOR,
-                                           req->data.name.domain_name);
-        if (ret == -1) {
+    case SSS_ID_TYPE_GID:
+        ret = getgrnam_r(fq_name, &grp, buf, buf_len, &grp_result);
+        if (ret != 0) {
             ret = LDAP_OPERATIONS_ERROR;
-            fq_name = NULL; /* content is undefined according to
-                               asprintf(3) */
             goto done;
         }
 
-        if (req->request_type == REQ_SIMPLE) {
-            ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type);
+        if (grp_result == NULL) {
+            ret = LDAP_NO_SUCH_OBJECT;
+            goto done;
+        }
+
+        if (request_type == REQ_FULL) {
+            ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid,
+                                 NULL, NULL, berval);
         } else {
-            id_type = SSS_ID_TYPE_UID;
-            ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len,
-                             &pwd_result);
-            if (ret == 0 && pwd_result == NULL) { /* no user entry found */
-                id_type = SSS_ID_TYPE_GID;
-                ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len,
-                                 &grp_result);
-            }
+            ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid,
+                                 grp.gr_mem, sid, berval);
         }
-        domain_name = strdup(req->data.name.domain_name);
         break;
     default:
-        ret = LDAP_PROTOCOL_ERROR;
-        goto done;
-    }
-
-    if (ret != 0) {
-        ret = LDAP_OPERATIONS_ERROR;
-        goto done;
-    } else if (ret == 0 && pwd_result == NULL && grp_result == NULL &&
-               sid_str == NULL) {
-        ret = LDAP_NO_SUCH_OBJECT;
-        goto done;
-    }
-
-    if (domain_name == NULL) {
-        ret = LDAP_OPERATIONS_ERROR;
-        goto done;
-    }
-
-    ret = create_response(req, &pg_data, sid_str, id_type, domain_name, res);
-    if (ret != 0) {
         ret = LDAP_OPERATIONS_ERROR;
         goto done;
     }
 
-
-    ret = LDAP_SUCCESS;
-
 done:
-    free(buf);
     free(fq_name);
+    free(object_name);
     free(domain_name);
-    free(sid_str);
+    free(buf);
 
     return ret;
 }
 
-int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
-                    const char *sid_str, enum sss_id_type id_type,
-                    const char *domain_name, struct extdom_res **_res)
+static int handle_name_request(enum request_types request_type,
+                               const char *name, const char *domain_name,
+                               struct berval **berval)
 {
-    int ret = EFAULT;
-    char *locat = NULL;
-    struct extdom_res *res;
-
-    res = calloc(1, sizeof(struct extdom_res));
-    if (res == NULL) {
-        return ENOMEM;
+    int ret;
+    char *fq_name = NULL;
+    struct passwd pwd;
+    struct passwd *pwd_result = NULL;
+    struct group grp;
+    struct group *grp_result = NULL;
+    char *sid_str = NULL;
+    enum sss_id_type id_type;
+    size_t buf_len;
+    char *buf = NULL;
+
+    ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR,
+                                       domain_name);
+    if (ret == -1) {
+        ret = LDAP_OPERATIONS_ERROR;
+        fq_name = NULL; /* content is undefined according to
+                           asprintf(3) */
+        goto done;
     }
 
-    switch (req->request_type) {
-        case REQ_SIMPLE:
-            switch (req->input_type) {
-                case INP_SID:
-                    res->response_type = RESP_NAME;
-                    res->data.name.domain_name = strdup(domain_name);
-                    switch(id_type) {
-                    case SSS_ID_TYPE_UID:
-                    case SSS_ID_TYPE_BOTH:
-                        if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                            if (strcasecmp(locat+1, domain_name) == 0  ) {
-                                locat[0] = 0;
-                            } else {
-                                ret = LDAP_NO_SUCH_OBJECT;
-                                goto done;
-                            }
-                        }
-                        res->data.name.object_name =
-                                              strdup(pg_data->data.pwd.pw_name);
-                        break;
-                    case SSS_ID_TYPE_GID:
-                        if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                            if (strcasecmp(locat+1, domain_name) == 0) {
-                                locat[0] = 0;
-                            } else {
-                                ret = LDAP_NO_SUCH_OBJECT;
-                                goto done;
-                            }
-                        }
-                        res->data.name.object_name =
-                                              strdup(pg_data->data.grp.gr_name);
-                        break;
-                    default:
-                        ret = EINVAL;
-                        goto done;
-                    }
-
-                    if (res->data.name.domain_name == NULL
-                            || res->data.name.object_name == NULL) {
-                        ret = ENOMEM;
-                        goto done;
-                    }
-                    break;
-                case INP_NAME:
-                case INP_POSIX_UID:
-                case INP_POSIX_GID:
-                    res->response_type = RESP_SID;
-                    res->data.sid = strdup(sid_str);
-                    if (res->data.sid == NULL) {
-                        ret = ENOMEM;
-                        goto done;
-                    }
-                    break;
-                default:
-                    ret = EINVAL;
-                    goto done;
-            }
-            break;
-        case REQ_FULL:
-            switch (id_type) {
-                case SSS_ID_TYPE_UID:
-                case SSS_ID_TYPE_BOTH:
-                    res->response_type = RESP_USER;
-                    res->data.user.domain_name = strdup(domain_name);
-                    if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                        if (strcasecmp(locat+1, domain_name) == 0) {
-                            locat[0] = 0;
-                        } else {
-                            ret = LDAP_NO_SUCH_OBJECT;
-                            goto done;
-                        }
-                    }
-                    res->data.user.user_name =
-                                              strdup(pg_data->data.pwd.pw_name);
-
-                    if (res->data.user.domain_name == NULL
-                            || res->data.user.user_name == NULL) {
-                        ret = ENOMEM;
-                        goto done;
-                    }
-
-                    res->data.user.uid = pg_data->data.pwd.pw_uid;
-                    res->data.user.gid = pg_data->data.pwd.pw_gid;
-                    break;
-                case SSS_ID_TYPE_GID:
-                    res->response_type = RESP_GROUP;
-                    res->data.group.domain_name = strdup(domain_name);
-                    if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
-                        if (strcasecmp(locat+1, domain_name) == 0) {
-                            locat[0] = 0;
-                        } else {
-                            ret = LDAP_NO_SUCH_OBJECT;
-                            goto done;
-                        }
-                    }
-                    res->data.group.group_name =
-                                              strdup(pg_data->data.grp.gr_name);
-
-                    if (res->data.group.domain_name == NULL
-                            || res->data.group.group_name == NULL) {
-                        ret = ENOMEM;
-                        goto done;
-                    }
-
-                    res->data.group.gid = pg_data->data.grp.gr_gid;
-                    break;
-                default:
-                    ret = EINVAL;
-                    goto done;
+    if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) {
+        ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type);
+        if (ret != 0) {
+            if (ret == ENOENT) {
+                ret = LDAP_NO_SUCH_OBJECT;
+            } else {
+                ret = LDAP_OPERATIONS_ERROR;
             }
-            break;
-        default:
-            ret = EINVAL;
-            goto done;
+           goto done;
+        }
     }
 
-    ret = 0;
-
-done:
-    if (ret == 0) {
-        *_res = res;
+    if (request_type == REQ_SIMPLE) {
+        ret = pack_ber_sid(sid_str, berval);
     } else {
-        free_resp_data(res);
-    }
+        ret = get_buffer(&buf_len, &buf);
+        if (ret != LDAP_SUCCESS) {
+            goto done;
+        }
+
+        ret = getpwnam_r(fq_name, &pwd, buf, buf_len, &pwd_result);
+        if (ret != 0) {
+            ret = LDAP_OPERATIONS_ERROR;
+            goto done;
+        }
+
+        if (pwd_result != NULL) {
+            if (request_type == REQ_FULL) {
+                ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                    pwd.pw_gid, NULL, NULL, NULL, NULL, berval);
+            } else  {
+                ret = pack_ber_user(domain_name, pwd.pw_name, pwd.pw_uid,
+                                    pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
+                                    pwd.pw_shell, sid_str, berval);
+            }
+        } else { /* no user entry found */
+            ret = getgrnam_r(fq_name, &grp, buf, buf_len, &grp_result);
+            if (ret != 0) {
+                ret = LDAP_OPERATIONS_ERROR;
+                goto done;
+            }
 
-    if (locat != NULL) {
-        locat[0] = SSSD_DOMAIN_SEPARATOR;
+            if (grp_result == NULL) {
+                ret = LDAP_NO_SUCH_OBJECT;
+                goto done;
+            }
+
+            if (request_type == REQ_FULL) {
+                ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid,
+                                     NULL, NULL, berval);
+            } else {
+                ret = pack_ber_group(domain_name, grp.gr_name, grp.gr_gid,
+                                     grp.gr_mem, sid_str, berval);
+            }
+        }
     }
 
+done:
+    free(fq_name);
+    free(sid_str);
+    free(buf);
+
     return ret;
 }
 
-void free_resp_data(struct extdom_res *res)
+int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
+                   struct berval **berval)
 {
-    if (res == NULL) {
-        return;
-    }
+    int ret;
+
+    switch (req->input_type) {
+    case INP_POSIX_UID:
+        ret = handle_uid_request(req->request_type, req->data.posix_uid.uid,
+                                 req->data.posix_uid.domain_name, berval);
 
-    switch (res->response_type) {
-    case RESP_SID:
-        free(res->data.sid);
         break;
-    case RESP_NAME:
-        free(res->data.name.domain_name);
-        free(res->data.name.object_name);
+    case INP_POSIX_GID:
+        ret = handle_gid_request(req->request_type, req->data.posix_gid.gid,
+                                 req->data.posix_uid.domain_name, berval);
+
         break;
-    case RESP_USER:
-        free(res->data.user.domain_name);
-        free(res->data.user.user_name);
+    case INP_SID:
+        ret = handle_sid_request(req->request_type, req->data.sid, berval);
         break;
-    case RESP_GROUP:
-        free(res->data.group.domain_name);
-        free(res->data.group.group_name);
+    case INP_NAME:
+        ret = handle_name_request(req->request_type, req->data.name.object_name,
+                                  req->data.name.domain_name, berval);
+
         break;
+    default:
+        ret = LDAP_PROTOCOL_ERROR;
+        goto done;
     }
 
-    free(res);
+
+done:
+
+    return ret;
 }
 
-
 int pack_response(struct extdom_res *res, struct berval **ret_val)
 {
     BerElement *ber = NULL;
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
index 9315da260ee3de660ea8ff708950945110da37e3..24191095d5d23705054bc62a2e861fd02db8807c 100644
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
@@ -49,6 +49,7 @@ Slapi_PluginDesc ipa_extdom_plugin_desc = {
 
 static char *ipa_extdom_oid_list[] = {
     EXOP_EXTDOM_OID,
+    EXOP_EXTDOM_V2_OID,
     NULL
 };
 
@@ -71,8 +72,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
     struct berval *req_val = NULL;
     struct berval *ret_val = NULL;
     struct extdom_req *req = NULL;
-    struct extdom_res *res = NULL;
     struct ipa_extdom_ctx *ctx;
+    enum extdom_version version;
 
     ret = slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid);
     if (ret != 0) {
@@ -82,7 +83,11 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
     }
     LOG("Received extended operation request with OID %s\n", oid);
 
-    if (strcasecmp(oid, EXOP_EXTDOM_OID) != 0) {
+    if (strcasecmp(oid, EXOP_EXTDOM_OID) == 0) {
+        version = EXTDOM_V1;
+    } else if (strcasecmp(oid, EXOP_EXTDOM_V2_OID) == 0) {
+        version = EXTDOM_V2;
+    } else {
         return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED;
     }
 
@@ -107,21 +112,21 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
         goto done;
     }
 
-    ret = handle_request(ctx, req, &res);
+    ret = check_request(req, version);
+    if (ret != LDAP_SUCCESS) {
+        rc = LDAP_UNWILLING_TO_PERFORM;
+        err_msg = "Error in request data.\n";
+        goto done;
+    }
+
+    ret = handle_request(ctx, req, &ret_val);
     if (ret != LDAP_SUCCESS) {
         rc = LDAP_OPERATIONS_ERROR;
         err_msg = "Failed to handle the request.\n";
         goto done;
     }
 
-    ret = pack_response(res, &ret_val);
-    if (ret != LDAP_SUCCESS) {
-        rc = LDAP_OPERATIONS_ERROR;
-        err_msg = "Failed to pack the response.\n";
-        goto done;
-    }
-
-    ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXOP_EXTDOM_OID);
+    ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, oid);
     if (ret != 0) {
         rc = LDAP_OPERATIONS_ERROR;
         err_msg = "Failed to set the OID for the response.\n";
@@ -139,7 +144,6 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
 
 done:
     free_req_data(req);
-    free_resp_data(res);
     if (err_msg != NULL) {
         LOG("%s", err_msg);
     }
-- 
1.8.5.3



More information about the Freeipa-devel mailing list