From 865332b74b1a83f2dc5b2d6db6e1526f55ba5946 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Sun, 22 Apr 2012 15:14:22 -0400
Subject: [PATCH 13/20] LDAP: Allow looking up ID-mapped groups by name

---
 src/providers/ldap/ldap_id.c           |   31 +++++---
 src/providers/ldap/sdap_async_groups.c |  127 +++++++++++++++++++++++++++-----
 2 files changed, 127 insertions(+), 31 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index ac08fd071449fdc5d9d8e7c73f3957b8c1daefb3..397ac33cfea245c7d5eda2b49ec91168fb7767e2 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -336,6 +336,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
     const char *attr_name;
     char *clean_name;
     int ret;
+    bool use_id_mapping = dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING);
 
     req = tevent_req_create(memctx, &state, struct groups_get_state);
     if (!req) return NULL;
@@ -368,18 +369,26 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    ret = sss_filter_sanitize(state, name, &clean_name);
-    if (ret != EOK) {
-        goto fail;
+
+    if (use_id_mapping) {
+        /* When mapping IDs, we don't want to limit ourselves
+         * to groups with a GID value
+         */
+
+        state->filter = talloc_asprintf(state,
+                                        "(&(%s=%s)(objectclass=%s)(%s=*))",
+                                        attr_name, clean_name,
+                                        ctx->opts->group_map[SDAP_OC_GROUP].name,
+                                        ctx->opts->group_map[SDAP_AT_GROUP_NAME].name);
+    } else {
+        state->filter = talloc_asprintf(state,
+                                        "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))",
+                                        attr_name, clean_name,
+                                        ctx->opts->group_map[SDAP_OC_GROUP].name,
+                                        ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
+                                        ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
+                                        ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
     }
-
-    state->filter = talloc_asprintf(state,
-                                    "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))",
-                                    attr_name, clean_name,
-                                    ctx->opts->group_map[SDAP_OC_GROUP].name,
-                                    ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
-                                    ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
-                                    ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
     talloc_zfree(clean_name);
     if (!state->filter) {
         DEBUG(2, ("Failed to build filter\n"));
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index d6877a37484c8a4d1149230786dccd004416cec0..89882be04b826f9436f87409579b4ab73212d41c 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -25,6 +25,7 @@
 #include "db/sysdb.h"
 #include "providers/ldap/sdap_async_private.h"
 #include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_idmap.h"
 
 /* ==Group-Parsing Routines=============================================== */
 
@@ -196,6 +197,11 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     char *usn_value = NULL;
     TALLOC_CTX *tmpctx = NULL;
     bool posix_group;
+    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
+    struct dom_sid *dom_sid;
+    char *sid_str;
+    char *dom_sid_str;
+    enum idmap_error_code err;
 
     tmpctx = talloc_new(memctx);
     if (!tmpctx) {
@@ -217,27 +223,108 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group);
-    if (ret == ENOENT) {
+    if (use_id_mapping) {
         posix_group = true;
-    } else if (ret != EOK) {
-        goto fail;
-    }
-
-    DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not"));
-    ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group);
-    if (ret != EOK) {
-        goto fail;
-    }
-
-    ret = sysdb_attrs_get_uint32_t(attrs,
-                                   opts->group_map[SDAP_AT_GROUP_GID].sys_name,
-                                   &gid);
-    if (ret != EOK) {
-        DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
-                  name, dom->name));
-        ret = EINVAL;
-        goto fail;
+
+        DEBUG(SSSDBG_TRACE_LIBS,
+              ("Mapping group [%s] objectSID to unix ID\n", name));
+
+        ret = sysdb_attrs_get_el(attrs,
+                                 opts->group_map[SDAP_AT_GROUP_OBJECTSID].sys_name,
+                                 &el);
+        if (ret != EOK || el->num_values != 1) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("No [%s] attribute for group [%s] while id-mapping\n",
+                   opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
+                   name));
+            goto fail;
+        }
+
+        ret = binary_to_dom_sid(tmpctx,
+                                el->values[0].data,
+                                el->values[0].length,
+                                &dom_sid);
+        if (ret != EOK) goto fail;
+
+        ret = dom_sid_to_string(tmpctx, dom_sid, &sid_str);
+        talloc_zfree(dom_sid);
+        if (ret != EOK) goto fail;
+
+        /* Add string representation to the cache for easier
+         * debugging
+         */
+        ret = sysdb_attrs_add_string(group_attrs, SYSDB_SID_STR, sid_str);
+        if (ret != EOK) goto fail;
+
+        /* Convert the SID into a UNIX group ID */
+        err = sss_idmap_sid_to_unix(opts->idmap_ctx->map,
+                                    sid_str,
+                                    (uint32_t *)&gid);
+        if (err != IDMAP_SUCCESS && err != IDMAP_NO_DOMAIN) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Could not convert objectSID [%s] to a UNIX ID\n",
+                   sid_str));
+            ret = EIO;
+            goto fail;
+        } else if (err == IDMAP_NO_DOMAIN) {
+            /* This is the first time we've seen this domain
+             * Create a new domain for it. We'll use the dom-sid
+             * as the domain name for now, since we don't have
+             * any way to get the real name.
+             */
+            ret = sdap_idmap_get_dom_sid_from_object(tmpctx, sid_str,
+                                                     &dom_sid_str);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Could not parse domain SID from [%s]\n", sid_str));
+                goto fail;
+            }
+
+            ret = sdap_idmap_add_domain(opts->idmap_ctx,
+                                        dom_sid_str, dom_sid_str,
+                                        -1);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Could not add new domain for sid [%s]\n", sid_str));
+                goto fail;
+            }
+
+            /* Now try converting to a UNIX ID again */
+            err = sss_idmap_sid_to_unix(opts->idmap_ctx->map,
+                                        sid_str,
+                                        (uint32_t *)&gid);
+            if (err != IDMAP_SUCCESS) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Could not convert objectSID [%s] to a UNIX ID\n",
+                       sid_str));
+                ret = EIO;
+                goto fail;
+            }
+        }
+
+    } else {
+        ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group);
+        if (ret == ENOENT) {
+            posix_group = true;
+        } else if (ret != EOK) {
+            goto fail;
+        }
+
+        DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not"));
+        ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group);
+        if (ret != EOK) {
+            goto fail;
+        }
+
+        ret = sysdb_attrs_get_uint32_t(attrs,
+                                       opts->group_map[SDAP_AT_GROUP_GID].sys_name,
+                                       &gid);
+        if (ret != EOK) {
+            DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
+                      name, dom->name));
+            ret = EINVAL;
+            goto fail;
+        }
     }
 
     /* check that the gid is valid for this domain */
-- 
1.7.10

