From ccab999170cf87ef98fe315e7197f0b2e54ebd62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Mon, 9 Sep 2013 15:52:03 +0200
Subject: [PATCH 05/12] ad: shortcut if possible during get object by ID or
 SID

When getByID or getBySID comes from responder, the request doesn't
necessarily have to contain correct domain, since responder iterates
over all domains until it finds a match.

Every domain has its own ID range, so we can simply shortcut if
domain does not match and avoid LDAP round trip. Responder will
continue with next domain until it finds the correct one.
---
 src/providers/ad/ad_id.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 9ee639a75c386045d7e80d8a80b1237b1383417e..446b60154403f9e2d571517400b5d5cc3df452b4 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -20,10 +20,12 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "util/util.h"
+#include "util/strtonum.h"
 #include "providers/ad/ad_common.h"
 #include "providers/ad/ad_id.h"
 #include "providers/ad/ad_domain_info.h"
 #include "providers/ldap/sdap_async_enum.h"
+#include "providers/ldap/sdap_idmap.h"
 
 struct ad_handle_acct_info_state {
     struct be_req *breq;
@@ -219,6 +221,9 @@ ad_account_info_handler(struct be_req *be_req)
     struct sss_domain_info *dom;
     struct sdap_domain *sdom;
     struct sdap_id_conn_ctx **clist;
+    enum idmap_error_code map_err;
+    uint32_t id;
+    char *sid = NULL;
     errno_t ret;
 
     ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
@@ -230,6 +235,44 @@ ad_account_info_handler(struct be_req *be_req)
         return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
     }
 
+    /* Try to shortcut if this is ID or SID search and it belongs to
+     * other domain range than is in ar->domain. */
+    if (ar->filter_type == BE_FILTER_IDNUM
+            || ar->filter_type == BE_FILTER_SECID) {
+        if (ar->filter_type == BE_FILTER_IDNUM) {
+            id = strtouint32(ar->filter_value, NULL, 10);
+            if (errno != EOK) {
+                ret = EINVAL;
+                goto fail;
+            }
+
+            /* Convert the ID to its objectSID */
+            map_err = sss_idmap_unix_to_sid(sdap_id_ctx->opts->idmap_ctx->map,
+                                            id, &sid);
+            if (map_err != IDMAP_SUCCESS) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Mapping ID [%s] to SID failed: [%s]\n",
+                       ar->filter_value, idmap_error_string(map_err)));
+                ret = EIO;
+                goto fail;
+            }
+        } else {
+            sid = ar->filter_value;
+        }
+
+        dom = find_subdomain_by_sid(be_ctx->domain, sid);
+        if (dom == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, ("Invalid domain\n"));
+            ret = EINVAL;
+            goto fail;
+        }
+
+        if (strcasecmp(dom->name, ar->domain) != 0) {
+            be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
+            return;
+        }
+    }
+
     dom = be_ctx->domain;
     if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
         /* Subdomain request, verify subdomain */
-- 
1.7.11.7

