[SSSD] [PATCHES] nss: use negative cache for sid-by-id requests

Sumit Bose sbose at redhat.com
Fri Jul 24 13:26:33 UTC 2015


Hi,

the attached two patches should fix
https://fedorahosted.org/sssd/ticket/2731 . If an object is looked up by
a POSIX UID or GID we always assume a multi-domain search and only have
a global, i.e. for all domains, negative cache.

Doing a multi-domain search makes sense because there is no such thing
as a fully-qualified UID and using fixed ranges for every domain might
not be possible in the general case, e.g. in AD forests where the POSIX
IDs are managed by AD. We might want to use some information we have in
the IPA case, but I think this way some backend data would leak into the
responders and there are better ways to fix the general case.

For the typical POSIX calls like getpwuid() and getgrgid() there already
is no issue because if a matching object is found it is added to the
memory cache and for some time no searches hit the responders.

For other calls, especially the SID-by-ID calls which is exposed by
libwbclient-sssd to samba and used regularly here, where there is no
memory cache (yet) the current processing is pretty expensive. Because
if the ID was not found in the cache of the first domain SSSD will ask
the backend of the first domain which causes an LDAP request. If the ID
was not found the second domain (or sub-domain) is checked first in the
cache and if not found via the backend. If sooner or later a matching ID
is found it is save in the cache of the corresponding domain. But the
next request for the same ID would cause the same sequence again because
we call the backend before checking the caches of the other domains.

The proper solution would be a memory cache for the SID related requests
which is tracked https://fedorahosted.org/sssd/ticket/2727 . As a short
term fix I made the negative cache for UIDs and GIDs domain aware. Now a
second request which comes shortly after the first will see the ID on
the negative cache of the other domain and will find the cached entry of
the right domain without calling the backends. 

bye,
Sumit
-------------- next part --------------
From cb6fc2521aae3c2aa4ab3e7e6e158b2848bc4f2c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 22 Jul 2015 14:21:52 +0200
Subject: [PATCH 1/2] negcache: allow domain name for UID and GID

Related to https://fedorahosted.org/sssd/ticket/2731
---
 src/responder/common/negcache.c             | 40 +++++++++++++++++++++++------
 src/responder/common/negcache.h             | 12 ++++++---
 src/responder/common/responder_cache_req.c  |  8 +++---
 src/responder/nss/nsssrv_cmd.c              | 19 ++++++++------
 src/tests/cmocka/test_negcache.c            | 40 ++++++++++++++---------------
 src/tests/cmocka/test_nss_srv.c             |  8 +++---
 src/tests/cmocka/test_responder_cache_req.c |  4 +--
 7 files changed, 82 insertions(+), 49 deletions(-)

diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
index 64270f4672f81fcd71f60acb83728d82dd4a1965..fc482c4110927af4b4d0c75afb9d6cc7932c8f78 100644
--- a/src/responder/common/negcache.c
+++ b/src/responder/common/negcache.c
@@ -376,12 +376,18 @@ int sss_ncache_check_service_port(struct sss_nc_ctx *ctx, int ttl,
 
 
 
-int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid)
+int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
+                         struct sss_domain_info *dom, uid_t uid)
 {
     char *str;
     int ret;
 
-    str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
+    if (dom != NULL) {
+        str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
+                              uid);
+    } else {
+        str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
+    }
     if (!str) return ENOMEM;
 
     ret = sss_ncache_check_str(ctx, str, ttl);
@@ -390,12 +396,18 @@ int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid)
     return ret;
 }
 
-int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl, gid_t gid)
+int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl,
+                         struct sss_domain_info *dom, gid_t gid)
 {
     char *str;
     int ret;
 
-    str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
+    if (dom != NULL) {
+        str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
+                              gid);
+    } else {
+        str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
+    }
     if (!str) return ENOMEM;
 
     ret = sss_ncache_check_str(ctx, str, ttl);
@@ -522,12 +534,18 @@ int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
     return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_netgr_int);
 }
 
-int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, uid_t uid)
+int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
+                       struct sss_domain_info *dom, uid_t uid)
 {
     char *str;
     int ret;
 
-    str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
+    if (dom != NULL) {
+        str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
+                              uid);
+    } else {
+        str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
+    }
     if (!str) return ENOMEM;
 
     ret = sss_ncache_set_str(ctx, str, permanent);
@@ -536,12 +554,18 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, uid_t uid)
     return ret;
 }
 
-int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, gid_t gid)
+int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
+                       struct sss_domain_info *dom, gid_t gid)
 {
     char *str;
     int ret;
 
-    str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
+    if (dom != NULL) {
+        str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
+                              gid);
+    } else {
+        str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
+    }
     if (!str) return ENOMEM;
 
     ret = sss_ncache_set_str(ctx, str, permanent);
diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h
index e7cbfe11451399a639d8e77b3479e74968e72921..46e66d503e45da0ee61735a17e88cbb84bd4ea49 100644
--- a/src/responder/common/negcache.h
+++ b/src/responder/common/negcache.h
@@ -34,8 +34,10 @@ int sss_ncache_check_group(struct sss_nc_ctx *ctx, int ttl,
                            struct sss_domain_info *dom, const char *name);
 int sss_ncache_check_netgr(struct sss_nc_ctx *ctx, int ttl,
                            struct sss_domain_info *dom, const char *name);
-int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid);
-int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl, gid_t gid);
+int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
+                         struct sss_domain_info *dom, uid_t uid);
+int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl,
+                         struct sss_domain_info *dom, gid_t gid);
 int sss_ncache_check_sid(struct sss_nc_ctx *ctx, int ttl, const char *sid);
 int sss_ncache_check_cert(struct sss_nc_ctx *ctx, int ttl, const char *cert);
 
@@ -58,8 +60,10 @@ int sss_ncache_set_group(struct sss_nc_ctx *ctx, bool permanent,
                          struct sss_domain_info *dom, const char *name);
 int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
                          struct sss_domain_info *dom, const char *name);
-int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, uid_t uid);
-int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, gid_t gid);
+int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
+                       struct sss_domain_info *dom, uid_t uid);
+int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
+                       struct sss_domain_info *dom, gid_t gid);
 int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid);
 int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
                         const char *cert);
diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c
index e7099f171d7ef39af7b146a524dadc38a9165e22..d0a90d2c94b7f990a46af488a08dd386854384e0 100644
--- a/src/responder/common/responder_cache_req.c
+++ b/src/responder/common/responder_cache_req.c
@@ -303,10 +303,10 @@ static errno_t cache_req_check_ncache(struct cache_req_input *input,
                                      input->domain, input->dom_objname);
         break;
     case CACHE_REQ_USER_BY_ID:
-        ret = sss_ncache_check_uid(ncache, neg_timeout, input->id);
+        ret = sss_ncache_check_uid(ncache, neg_timeout, NULL, input->id);
         break;
     case CACHE_REQ_GROUP_BY_ID:
-        ret = sss_ncache_check_gid(ncache, neg_timeout, input->id);
+        ret = sss_ncache_check_gid(ncache, neg_timeout, NULL, input->id);
         break;
     case CACHE_REQ_USER_BY_CERT:
         ret = sss_ncache_check_cert(ncache, neg_timeout, input->cert);
@@ -382,10 +382,10 @@ static void cache_req_add_to_ncache_global(struct cache_req_input *input,
         ret = EOK;
         break;
     case CACHE_REQ_USER_BY_ID:
-        ret = sss_ncache_set_uid(ncache, false, input->id);
+        ret = sss_ncache_set_uid(ncache, false, NULL, input->id);
         break;
     case CACHE_REQ_GROUP_BY_ID:
-        ret = sss_ncache_set_gid(ncache, false, input->id);
+        ret = sss_ncache_set_gid(ncache, false, NULL, input->id);
         break;
     case CACHE_REQ_USER_BY_CERT:
         ret = sss_ncache_set_cert(ncache, false, input->cert);
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index b3998015fa621cad8e06a126a674f94d26158dda..93c9bb81da0fd33576592258d55dbcbdac1a369c 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1710,7 +1710,7 @@ static int nss_cmd_getpwuid_search(struct nss_dom_ctx *dctx)
 done:
     if (ret == ENOENT) {
         /* The entry was not found, need to set result in negative cache */
-        err = sss_ncache_set_uid(nctx->ncache, false, cmdctx->id);
+        err = sss_ncache_set_uid(nctx->ncache, false, NULL, cmdctx->id);
         if (err != EOK) {
             DEBUG(SSSDBG_MINOR_FAILURE,
                 "Cannot set negative cache for UID %"PRIu32"\n", cmdctx->id);
@@ -1779,7 +1779,8 @@ static int nss_cmd_getbyid(enum sss_cli_command cmd, struct cli_ctx *cctx)
 
     switch(dctx->cmdctx->cmd) {
     case SSS_NSS_GETPWUID:
-        ret = sss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, cmdctx->id);
+        ret = sss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, NULL,
+                                   cmdctx->id);
         if (ret == EEXIST) {
             DEBUG(SSSDBG_TRACE_FUNC,
                   "Uid [%"PRIu32"] does not exist! (negative cache)\n",
@@ -1789,7 +1790,8 @@ static int nss_cmd_getbyid(enum sss_cli_command cmd, struct cli_ctx *cctx)
         }
         break;
     case SSS_NSS_GETGRGID:
-        ret = sss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, cmdctx->id);
+        ret = sss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, NULL,
+                                   cmdctx->id);
         if (ret == EEXIST) {
             DEBUG(SSSDBG_TRACE_FUNC,
                   "Gid [%"PRIu32"] does not exist! (negative cache)\n",
@@ -1799,10 +1801,11 @@ static int nss_cmd_getbyid(enum sss_cli_command cmd, struct cli_ctx *cctx)
         }
         break;
     case SSS_NSS_GETSIDBYID:
-        ret = sss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, cmdctx->id);
+        ret = sss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, NULL,
+                                   cmdctx->id);
         if (ret != EEXIST) {
             ret = sss_ncache_check_gid(nctx->ncache, nctx->neg_timeout,
-                                       cmdctx->id);
+                                       NULL, cmdctx->id);
         }
         if (ret == EEXIST) {
             DEBUG(SSSDBG_TRACE_FUNC,
@@ -3288,7 +3291,7 @@ static int nss_cmd_getgrgid_search(struct nss_dom_ctx *dctx)
 done:
     if (ret == ENOENT) {
         /* The entry was not found, need to set result in negative cache */
-        err = sss_ncache_set_gid(nctx->ncache, false, cmdctx->id);
+        err = sss_ncache_set_gid(nctx->ncache, false, NULL, cmdctx->id);
         if (err != EOK) {
             DEBUG(SSSDBG_MINOR_FAILURE,
                 "Cannot set negative cache for GID %"PRIu32"\n", cmdctx->id);
@@ -4592,13 +4595,13 @@ done:
         if (cmdctx->cmd == SSS_NSS_GETSIDBYID) {
             DEBUG(SSSDBG_MINOR_FAILURE,
                 "No matching domain found for [%"PRIu32"], fail!\n", cmdctx->id);
-            err = sss_ncache_set_uid(nctx->ncache, false, cmdctx->id);
+            err = sss_ncache_set_uid(nctx->ncache, false, NULL, cmdctx->id);
             if (err != EOK) {
                 DEBUG(SSSDBG_MINOR_FAILURE,
                     "Cannot set negative cache for UID %"PRIu32"\n", cmdctx->id);
             }
 
-            err = sss_ncache_set_gid(nctx->ncache, false, cmdctx->id);
+            err = sss_ncache_set_gid(nctx->ncache, false, NULL, cmdctx->id);
             if (err != EOK) {
                 DEBUG(SSSDBG_MINOR_FAILURE,
                     "Cannot set negative cache for GID %"PRIu32"\n", cmdctx->id);
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
index fa07ea2481e2040e3e83eecfb5c69dbec17e26fa..a1f9471854ff9fe9c5e265dd4b74a590ece1aa45 100644
--- a/src/tests/cmocka/test_negcache.c
+++ b/src/tests/cmocka/test_negcache.c
@@ -188,7 +188,7 @@ static void test_sss_ncache_uid(void **state)
     ts = talloc_get_type_abort(*state, struct test_state);
 
     /* test when uid not present in database */
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, ENOENT);
 
     /* test when uid is present in database */
@@ -197,43 +197,43 @@ static void test_sss_ncache_uid(void **state)
     ret = sss_ncache_reset_permanent(ts->ctx);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_set_uid(ts->ctx, permanent, uid);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, uid);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, EEXIST);
 
     ttl = SHORTSPAN;
-    ret = sss_ncache_set_uid(ts->ctx, permanent, uid);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, uid);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, EEXIST);
 
     sleep(SHORTSPAN + 1);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, EEXIST);
 
     permanent = false;
 
-    ret = sss_ncache_set_uid(ts->ctx, permanent, uid);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, uid);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, EEXIST);
 
     sleep(SHORTSPAN + 1);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, ENOENT);
 
-    ret = sss_ncache_set_uid(ts->ctx, permanent, uid);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, uid);
     assert_int_equal(ret, EOK);
 
     /* test when ttl is -1 with uid present in database*/
     ttl = -1;
-    ret = sss_ncache_check_uid(ts->ctx, ttl, uid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, uid);
     assert_int_equal(ret, EEXIST);
 }
 
@@ -253,27 +253,27 @@ static void test_sss_ncache_gid(void **state)
     ts = talloc_get_type_abort(*state, struct test_state);
 
     /* test when gid is not present in database */
-    ret = sss_ncache_check_gid(ts->ctx, ttl, gid);
+    ret = sss_ncache_check_gid(ts->ctx, ttl, NULL, gid);
     assert_int_equal(ret, ENOENT);
 
     /* test when gid is present in database */
     permanent = true;
-    ret = sss_ncache_set_gid(ts->ctx, permanent, gid);
+    ret = sss_ncache_set_gid(ts->ctx, permanent, NULL, gid);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_gid(ts->ctx, ttl, gid);
+    ret = sss_ncache_check_gid(ts->ctx, ttl, NULL, gid);
     assert_int_equal(ret, EEXIST);
 
     permanent = false;
-    ret = sss_ncache_set_uid(ts->ctx, permanent, gid);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, gid);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, ttl, gid);
+    ret = sss_ncache_check_uid(ts->ctx, ttl, NULL, gid);
     assert_int_equal(ret, EEXIST);
 
     /* test when ttl is -1 with gid present in database*/
     ttl = -1;
-    ret = sss_ncache_check_gid(ts->ctx, ttl, gid);
+    ret = sss_ncache_check_gid(ts->ctx, ttl, NULL, gid);
     assert_int_equal(ret, EEXIST);
 }
 
@@ -608,16 +608,16 @@ static void test_sss_ncache_reset_permanent(void **state)
 
     ts = talloc_get_type_abort(*state, struct test_state);
 
-    ret = sss_ncache_set_uid(ts->ctx, permanent, 0);
+    ret = sss_ncache_set_uid(ts->ctx, permanent, NULL, 0);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, 0, 0);
+    ret = sss_ncache_check_uid(ts->ctx, 0, NULL, 0);
     assert_int_equal(ret, EEXIST);
 
     ret = sss_ncache_reset_permanent(ts->ctx);
     assert_int_equal(ret, EOK);
 
-    ret = sss_ncache_check_uid(ts->ctx, 0, 0);
+    ret = sss_ncache_check_uid(ts->ctx, 0, NULL, 0);
     assert_int_equal(ret, ENOENT);
 }
 
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 84d3413be70bc0af433b7fd23cf7d78b4b9298f1..2d4fb2204544a2b371f389545a461f3d526f2c0a 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -166,13 +166,15 @@ int __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
     return ret;
 }
 
-int __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid);
+int __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
+                                struct sss_domain_info *dom, uid_t uid);
 
-int __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid)
+int __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
+                                struct sss_domain_info *dom, uid_t uid)
 {
     int ret;
 
-    ret = __real_sss_ncache_check_uid(ctx, ttl, uid);
+    ret = __real_sss_ncache_check_uid(ctx, ttl, dom, uid);
     if (ret == EEXIST) {
         nss_test_ctx->ncache_hits++;
     }
diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c
index 31b6694668607815652f45bc93210554fd2ac918..032fe429ac88b8cc9113976329ea04837f287276 100644
--- a/src/tests/cmocka/test_responder_cache_req.c
+++ b/src/tests/cmocka/test_responder_cache_req.c
@@ -873,7 +873,7 @@ void test_user_by_id_ncache(void **state)
 
     test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
 
-    ret = sss_ncache_set_uid(test_ctx->ncache, false, uid);
+    ret = sss_ncache_set_uid(test_ctx->ncache, false, NULL, uid);
     assert_int_equal(ret, EOK);
 
     req_mem_ctx = talloc_new(global_talloc_context);
@@ -1601,7 +1601,7 @@ void test_group_by_id_ncache(void **state)
 
     test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
 
-    ret = sss_ncache_set_gid(test_ctx->ncache, false, gid);
+    ret = sss_ncache_set_gid(test_ctx->ncache, false, NULL, gid);
     assert_int_equal(ret, EOK);
 
     req_mem_ctx = talloc_new(global_talloc_context);
-- 
2.1.0

-------------- next part --------------
From bead55a14c9e1bed8bf3cb6f123800bb71445c27 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 22 Jul 2015 15:34:32 +0200
Subject: [PATCH 2/2] nss: use negative cache for sid-by-id requests

Resolves https://fedorahosted.org/sssd/ticket/2731
---
 src/responder/nss/nsssrv_cmd.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 93c9bb81da0fd33576592258d55dbcbdac1a369c..4505f2a990d8711aa880e20f9cf5c982a773921d 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1087,6 +1087,7 @@ static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min,
     struct cli_ctx *cctx = cmdctx->cctx;
     int ret;
     bool check_subdomains;
+    struct nss_ctx *nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
     if (err_maj) {
         DEBUG(SSSDBG_OP_FAILURE,
@@ -1135,8 +1136,40 @@ static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min,
          * here. */
         switch (dctx->cmdctx->cmd) {
         case SSS_NSS_GETPWUID:
+            ret = sss_ncache_set_uid(nctx->ncache, false, dctx->domain,
+                                     cmdctx->id);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      "Cannot set negative cache for UID %"PRIu32"\n",
+                      cmdctx->id);
+            }
+            check_subdomains = true;
+            break;
         case SSS_NSS_GETGRGID:
+            ret = sss_ncache_set_gid(nctx->ncache, false, dctx->domain,
+                                     cmdctx->id);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      "Cannot set negative cache for GID %"PRIu32"\n",
+                      cmdctx->id);
+            }
+            check_subdomains = true;
+            break;
         case SSS_NSS_GETSIDBYID:
+            ret = sss_ncache_set_uid(nctx->ncache, false, dctx->domain,
+                                     cmdctx->id);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      "Cannot set negative cache for UID %"PRIu32"\n",
+                       cmdctx->id);
+            }
+            ret = sss_ncache_set_gid(nctx->ncache, false, dctx->domain,
+                                     cmdctx->id);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      "Cannot set negative cache for GID %"PRIu32"\n",
+                      cmdctx->id);
+            }
             check_subdomains = true;
             break;
         default:
@@ -4358,6 +4391,28 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
         if (cmdctx->cmd == SSS_NSS_GETSIDBYID) {
             DEBUG(SSSDBG_TRACE_FUNC, "Requesting info for [%"PRIu32"@%s]\n",
                                       cmdctx->id, dom->name);
+
+            ret = sss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, dom,
+                                       cmdctx->id);
+            if (ret == EEXIST) {
+                ret = sss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, dom,
+                                           cmdctx->id);
+                if (ret == EEXIST) {
+                    DEBUG(SSSDBG_TRACE_FUNC,
+                          "ID [%"PRIu32"] does not exist in [%s]! (negative cache)\n",
+                           cmdctx->id, dom->name);
+                    /* if a multidomain search, try with next, including
+                     * sub-domains */
+                    if (cmdctx->check_next) {
+                        dom = get_next_domain(dom, true);
+                        continue;
+                    }
+                    /* There are no further domains. */
+                    ret = ENOENT;
+                    goto done;
+                }
+            }
+
         } else {
             talloc_free(name);
             talloc_zfree(sysdb_name);
-- 
2.1.0



More information about the sssd-devel mailing list