From 08343a23846c8e7693b8b249f73b51255a865328 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Fri, 15 Apr 2011 10:12:36 +0200
Subject: [PATCH] Add user and group search LDAP filter options

https://fedorahosted.org/sssd/ticket/647
---
 src/man/sssd-ldap.5.xml           |   37 ++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_common.c  |   20 ++++++++++++++++
 src/providers/ldap/ldap_common.h  |    4 +++
 src/providers/ldap/ldap_id.c      |   45 ++++++++++++++++++++++++++----------
 src/providers/ldap/ldap_id_enum.c |   32 +++++++++++++++++++++-----
 5 files changed, 119 insertions(+), 19 deletions(-)

diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 2a39732..9d585e2 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1369,6 +1369,43 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
                         </para>
                     </listitem>
                 </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_user_search_filter (string)</term>
+                    <listitem>
+                        <para>
+                            This option specifies an additional LDAP search
+                            filter criteria that restrict user searches.
+                        </para>
+                        <para>
+                            Default: not set
+                        </para>
+                        <para>
+                            Example:
+                        </para>
+                        <programlisting>
+                            ldap_user_search_filter = (loginShell=/bin/tcsh)
+                        </programlisting>
+                        <para>
+                            This filter would restrict user searches to users
+                            that have their shell set to /bin/tcsh.
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_group_search_filter (string)</term>
+                    <listitem>
+                        <para>
+                            This option specifies an additional LDAP search
+                            filter criteria that restrict group searches.
+                        </para>
+                        <para>
+                            Default: not set
+                        </para>
+                    </listitem>
+                </varlistentry>
+
             </variablelist>
         </para>
     </refsect1>
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 68b8e15..39e9b71 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -1013,3 +1013,23 @@ bool sdap_is_secure_uri(const char *uri)
     }
     return false;
 }
+
+char *sdap_get_id_specific_filter(TALLOC_CTX *mem_ctx,
+                                  char *base_filter,
+                                  char *extra_filter)
+{
+    char *filter = NULL;
+
+    if (!extra_filter) {
+        return talloc_strdup(mem_ctx, base_filter);
+    }
+
+    if (extra_filter[0] == '(') {
+        filter = talloc_asprintf(mem_ctx, "(&%s%s)",
+                                 base_filter, extra_filter);
+    } else {
+        filter = talloc_asprintf(mem_ctx, "(&%s(%s))",
+                                 base_filter, extra_filter);
+    }
+    return filter; /* NULL or not */
+}
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 9146da5..f474680 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -162,4 +162,8 @@ errno_t list_missing_attrs(TALLOC_CTX *mem_ctx,
 
 bool sdap_is_secure_uri(const char *uri);
 
+char *sdap_get_id_specific_filter(TALLOC_CTX *mem_ctx,
+                                  char *base_filter,
+                                  char *extra_filter);
+
 #endif /* _LDAP_COMMON_H_ */
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 776df1a..840ad78 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -65,6 +65,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
     struct users_get_state *state;
     const char *attr_name;
     char *clean_name;
+    char *base_filter;
     int ret;
 
     req = tevent_req_create(memctx, &state, struct users_get_state);
@@ -103,15 +104,24 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
-                                    attr_name, clean_name,
-                                    ctx->opts->user_map[SDAP_OC_USER].name);
+    base_filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
+                                  attr_name, clean_name,
+                                  ctx->opts->user_map[SDAP_OC_USER].name);
+    talloc_zfree(clean_name);
+    if (!base_filter) {
+        DEBUG(2, ("Failed to build the base filter\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    state->filter = sdap_get_id_specific_filter(state, base_filter,
+           dp_opt_get_string(ctx->opts->basic, SDAP_USER_SEARCH_FILTER));
+    talloc_zfree(base_filter);
     if (!state->filter) {
-        DEBUG(2, ("Failed to build filter\n"));
+        DEBUG(2, ("Failed to build user filter\n"));
         ret = ENOMEM;
         goto fail;
     }
-    talloc_zfree(clean_name);
 
     /* TODO: handle attrs_type */
     ret = build_attrs_from_map(state, ctx->opts->user_map,
@@ -297,6 +307,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
     struct groups_get_state *state;
     const char *attr_name;
     char *clean_name;
+    char *base_filter;
     int ret;
 
     req = tevent_req_create(memctx, &state, struct groups_get_state);
@@ -335,18 +346,26 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    state->filter =
-            talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))",
-                            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);
-    if (!state->filter) {
+    base_filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))",
+                                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);
+    talloc_zfree(clean_name);
+    if (!base_filter) {
         DEBUG(2, ("Failed to build filter\n"));
         ret = ENOMEM;
         goto fail;
     }
-    talloc_zfree(clean_name);
+
+    state->filter = sdap_get_id_specific_filter(state, base_filter,
+           dp_opt_get_string(ctx->opts->basic, SDAP_GROUP_SEARCH_FILTER));
+    talloc_zfree(base_filter);
+    if (!state->filter) {
+        DEBUG(2, ("Failed to build group-specific filter\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
 
     /* TODO: handle attrs_type */
     ret = build_attrs_from_map(state, ctx->opts->group_map,
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 6899b87..d7dd33e 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -431,6 +431,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
 {
     struct tevent_req *req, *subreq;
     struct enum_users_state *state;
+    char *base_filter;
     int ret;
 
     req = tevent_req_create(memctx, &state, struct enum_users_state);
@@ -441,7 +442,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
     state->op = op;
 
     if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) {
-        state->filter = talloc_asprintf(
+        base_filter = talloc_asprintf(
                 state,
                 "(&(objectclass=%s)(%s=*)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))",
                 ctx->opts->user_map[SDAP_OC_USER].name,
@@ -453,7 +454,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
                 ctx->opts->user_map[SDAP_AT_USER_USN].name,
                 ctx->srv_opts->max_user_value);
     } else {
-        state->filter = talloc_asprintf(
+        base_filter = talloc_asprintf(
                 state,
                 "(&(objectclass=%s)(%s=*)(%s=*)(%s=*))",
                 ctx->opts->user_map[SDAP_OC_USER].name,
@@ -461,8 +462,17 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
                 ctx->opts->user_map[SDAP_AT_USER_UID].name,
                 ctx->opts->user_map[SDAP_AT_USER_GID].name);
     }
+    if (!base_filter) {
+        DEBUG(2, ("Failed to build base filter\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    state->filter = sdap_get_id_specific_filter(state, base_filter,
+           dp_opt_get_string(ctx->opts->basic, SDAP_USER_SEARCH_FILTER));
+    talloc_zfree(base_filter);
     if (!state->filter) {
-        DEBUG(2, ("Failed to build filter\n"));
+        DEBUG(2, ("Failed to build user filter\n"));
         ret = ENOMEM;
         goto fail;
     }
@@ -542,6 +552,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
 {
     struct tevent_req *req, *subreq;
     struct enum_groups_state *state;
+    char *base_filter;
     int ret;
 
     req = tevent_req_create(memctx, &state, struct enum_groups_state);
@@ -552,7 +563,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
     state->op = op;
 
     if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) {
-        state->filter = talloc_asprintf(
+        base_filter = talloc_asprintf(
                 state,
                 "(&(objectclass=%s)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))",
                 ctx->opts->group_map[SDAP_OC_GROUP].name,
@@ -563,19 +574,28 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
                 ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
                 ctx->srv_opts->max_group_value);
     } else {
-        state->filter = talloc_asprintf(
+        base_filter = talloc_asprintf(
                 state,
                 "(&(objectclass=%s)(%s=*)(%s=*))",
                 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);
     }
-    if (!state->filter) {
+    if (!base_filter) {
         DEBUG(2, ("Failed to build filter\n"));
         ret = ENOMEM;
         goto fail;
     }
 
+    state->filter = sdap_get_id_specific_filter(state, base_filter,
+           dp_opt_get_string(ctx->opts->basic, SDAP_GROUP_SEARCH_FILTER));
+    talloc_zfree(base_filter);
+    if (!state->filter) {
+        DEBUG(2, ("Failed to build group filter\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
     /* TODO: handle attrs_type */
     ret = build_attrs_from_map(state, ctx->opts->group_map,
                                SDAP_OPTS_GROUP, &state->attrs);
-- 
1.7.4.2

