>From 3bc78051e26983e5741c02d7fce82d4b683cc722 Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce@redhat.com>
Date: Wed, 18 Nov 2009 12:05:27 -0500
Subject: [PATCH] Filter by id range before actually storing entries.

This way we do not need to check for id ranges on every search.
---
 server/providers/ldap/sdap_async_accounts.c |   18 +++++
 server/providers/proxy.c                    |  101 +++++++++++++++++++++++----
 server/responder/nss/nsssrv_cmd.c           |   16 ----
 3 files changed, 104 insertions(+), 31 deletions(-)

diff --git a/server/providers/ldap/sdap_async_accounts.c b/server/providers/ldap/sdap_async_accounts.c
index 292c85f..741ed80 100644
--- a/server/providers/ldap/sdap_async_accounts.c
+++ b/server/providers/ldap/sdap_async_accounts.c
@@ -128,6 +128,15 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx,
     }
     uid = l;
 
+    /* check that the uid is valid for this domain */
+    if ((dom->id_min && (uid < dom->id_min)) ||
+        (dom->id_max && (uid > dom->id_max))) {
+            DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
+                      state->name));
+        ret = EINVAL;
+        goto fail;
+    }
+
     ret = sysdb_attrs_get_el(state->attrs,
                              opts->user_map[SDAP_AT_USER_GID].sys_name, &el);
     if (ret) goto fail;
@@ -903,6 +912,15 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx,
     }
     gid = l;
 
+    /* check that the gid is valid for this domain */
+    if ((dom->id_min && (gid < dom->id_min)) ||
+        (dom->id_max && (gid > dom->id_max))) {
+            DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
+                      state->name));
+        ret = EINVAL;
+        goto fail;
+    }
+
     group_attrs = sysdb_new_attrs(state);
     if (!group_attrs) {
         ret = ENOMEM;
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index 0a37344..0d4b25b 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -369,6 +369,7 @@ static void get_pw_name_process(struct tevent_req *subreq)
     struct proxy_state *state = tevent_req_data(req,
                                                 struct proxy_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     size_t buflen;
@@ -416,7 +417,16 @@ static void get_pw_name_process(struct tevent_req *subreq)
                   state->pwd->pw_uid, state->pwd->pw_gid));
 
         /* uid=0 or gid=0 are invalid values */
-        if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->pwd->pw_uid == 0) ||
+            ((dom->id_min && (state->pwd->pw_uid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_uid > dom->id_max))) ||
+            (state->pwd->pw_gid == 0) ||
+            ((dom->id_min && (state->pwd->pw_gid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_gid > dom->id_max)))) {
+
+                DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
+                          state->name));
             delete_user = true;
             break;
         }
@@ -561,6 +571,7 @@ static void get_pw_uid_process(struct tevent_req *subreq)
     struct proxy_state *state = tevent_req_data(req,
                                                 struct proxy_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     size_t buflen;
@@ -609,7 +620,16 @@ static void get_pw_uid_process(struct tevent_req *subreq)
                   state->pwd->pw_uid, state->pwd->pw_gid));
 
         /* uid=0 or gid=0 are invalid values */
-        if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->pwd->pw_uid == 0) ||
+            ((dom->id_min && (state->pwd->pw_uid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_uid > dom->id_max))) ||
+            (state->pwd->pw_gid == 0) ||
+            ((dom->id_min && (state->pwd->pw_gid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_gid > dom->id_max)))) {
+
+                DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
+                          state->name));
             delete_user = true;
             break;
         }
@@ -764,6 +784,7 @@ static void enum_users_process(struct tevent_req *subreq)
     struct enum_users_state *state = tevent_req_data(req,
                                                 struct enum_users_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *newbuf;
     int ret;
@@ -832,7 +853,17 @@ again:
                   state->pwd->pw_uid, state->pwd->pw_gid));
 
         /* uid=0 or gid=0 are invalid values */
-        if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->pwd->pw_uid == 0) ||
+            ((dom->id_min && (state->pwd->pw_uid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_uid > dom->id_max))) ||
+            (state->pwd->pw_gid == 0) ||
+            ((dom->id_min && (state->pwd->pw_gid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_gid > dom->id_max)))) {
+
+                DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
+                          state->pwd->pw_name));
+
             goto again; /* skip */
         }
 
@@ -931,6 +962,7 @@ static void get_gr_name_process(struct tevent_req *subreq)
     struct proxy_state *state = tevent_req_data(req,
                                                 struct proxy_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     char *newbuf;
@@ -999,7 +1031,13 @@ again:
                   state->grp->gr_name, state->grp->gr_gid));
 
         /* gid=0 is an invalid value */
-        if (state->grp->gr_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->grp->gr_gid == 0) ||
+            ((dom->id_min && (state->grp->gr_gid < dom->id_min)) ||
+             (dom->id_max && (state->grp->gr_gid > dom->id_max)))) {
+
+                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
+                          state->name));
             delete_group = true;
             break;
         }
@@ -1148,6 +1186,7 @@ static void get_gr_gid_process(struct tevent_req *subreq)
     struct proxy_state *state = tevent_req_data(req,
                                                 struct proxy_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     char *newbuf;
@@ -1214,7 +1253,13 @@ again:
                   state->grp->gr_name, state->grp->gr_gid));
 
         /* gid=0 is an invalid value */
-        if (state->grp->gr_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->grp->gr_gid == 0) ||
+            ((dom->id_min && (state->grp->gr_gid < dom->id_min)) ||
+             (dom->id_max && (state->grp->gr_gid > dom->id_max)))) {
+
+                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
+                          state->grp->gr_name));
             delete_group = true;
             break;
         }
@@ -1374,6 +1419,7 @@ static void enum_groups_process(struct tevent_req *subreq)
     struct enum_groups_state *state = tevent_req_data(req,
                                                 struct enum_groups_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     const char **members;
     char *newbuf;
@@ -1439,14 +1485,22 @@ again:
         return;
 
     case NSS_STATUS_SUCCESS:
-        /* gid=0 is an invalid value */
-        if (state->grp->gr_gid == 0) {
-            goto again; /* skip */
-        }
 
         DEBUG(7, ("Group found (%s, %d)\n",
                   state->grp->gr_name, state->grp->gr_gid));
 
+        /* gid=0 is an invalid value */
+        /* also check that the id is in the valid range for this domain */
+        if ((state->grp->gr_gid == 0) ||
+            ((dom->id_min && (state->grp->gr_gid < dom->id_min)) ||
+             (dom->id_max && (state->grp->gr_gid > dom->id_max)))) {
+
+                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
+                          state->grp->gr_name));
+
+            goto again; /* skip */
+        }
+
         DEBUG_GR_MEM(7, state);
 
         if (state->grp->gr_mem && state->grp->gr_mem[0]) {
@@ -1547,6 +1601,7 @@ static void get_initgr_process(struct tevent_req *subreq)
     struct proxy_state *state = tevent_req_data(req,
                                                 struct proxy_state);
     struct proxy_ctx *ctx = state->ctx;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     size_t buflen;
@@ -1587,7 +1642,16 @@ static void get_initgr_process(struct tevent_req *subreq)
     case NSS_STATUS_SUCCESS:
 
         /* uid=0 or gid=0 are invalid values */
-        if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
+        /* also check that the id is in the valid range for this domain */
+        if ((state->pwd->pw_uid == 0) ||
+            ((dom->id_min && (state->pwd->pw_uid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_uid > dom->id_max))) ||
+            (state->pwd->pw_gid == 0) ||
+            ((dom->id_min && (state->pwd->pw_gid < dom->id_min)) ||
+             (dom->id_max && (state->pwd->pw_gid > dom->id_max)))) {
+
+                DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
+                          state->name));
             delete_user = true;
             break;
         }
@@ -1833,11 +1897,12 @@ static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx,
 {
     struct tevent_req *req, *subreq;
     struct proxy_state *state;
+    struct sss_domain_info *dom = ctx->be->domain;
     enum nss_status status;
     char *buffer;
     char *newbuf;
     size_t buflen;
-    bool delete_user = false;
+    bool delete_group = false;
     int ret;
 
     req = tevent_req_create(mem_ctx, &state, struct proxy_state);
@@ -1890,14 +1955,20 @@ again:
 
     case NSS_STATUS_NOTFOUND:
 
-        delete_user = true;
+        delete_group = true;
         break;
 
     case NSS_STATUS_SUCCESS:
 
         /* gid=0 is an invalid value */
-        if (state->grp->gr_gid == 0) {
-            delete_user = true;
+        /* also check that the id is in the valid range for this domain */
+        if ((state->grp->gr_gid == 0) ||
+            ((dom->id_min && (state->grp->gr_gid < dom->id_min)) ||
+             (dom->id_max && (state->grp->gr_gid > dom->id_max)))) {
+
+                DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
+                          state->grp->gr_name));
+            delete_group = true;
             break;
         }
 
@@ -1927,7 +1998,7 @@ again:
         goto fail;
     }
 
-    if (delete_user) {
+    if (delete_group) {
         subreq = sysdb_delete_group_send(state, state->ev,
                                          NULL, state->handle,
                                          state->domain,
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 707c3d1..3c8b9fd 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -174,14 +174,6 @@ static int fill_pwent(struct sss_packet *packet,
             }
         }
 
-        /* check that the uid is valid for this domain */
-        if ((dom->id_min && (uid < dom->id_min)) ||
-            (dom->id_max && (uid > dom->id_max))) {
-                DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n",
-                          name, domain));
-            continue;
-        }
-
         if (!packet_initialized) {
             /* first 2 fields (len and reserved), filled up later */
             ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
@@ -1554,14 +1546,6 @@ static int fill_grent(struct sss_packet *packet,
             }
         }
 
-        /* check that the gid is valid for this domain */
-        if ((dom->id_min && (gid < dom->id_min)) ||
-            (dom->id_max && (gid > dom->id_max))) {
-                DEBUG(4, ("Group [%s@%s] filtered out! (id out of range)\n",
-                          name, domain));
-            continue;
-        }
-
         nsize = strlen(name) + 1; /* includes terminating \0 */
         if (add_domain) nsize += delim + dom_len;
 
-- 
1.6.2.5

