summaryrefslogtreecommitdiffstats
path: root/server/responder/nss/nsssrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/responder/nss/nsssrv_cmd.c')
-rw-r--r--server/responder/nss/nsssrv_cmd.c259
1 files changed, 256 insertions, 3 deletions
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 4117f9771..ef9dd31d5 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -23,6 +23,7 @@
#include "util/btreemap.h"
#include "responder/common/responder_packet.h"
#include "responder/nss/nsssrv.h"
+#include "responder/nss/nsssrv_nc.h"
#include "db/sysdb.h"
#include <time.h>
#include "confdb/confdb.h"
@@ -54,6 +55,9 @@ struct nss_dom_ctx {
struct sss_domain_info *domain;
bool add_domain;
bool check_provider;
+
+ /* cache results */
+ struct ldb_result *res;
};
struct nss_cmd_table {
@@ -267,7 +271,7 @@ done:
}
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
+ const char *err_msg, void *ptr);
static void nss_cmd_getpwnam_callback(void *ptr, int status,
struct ldb_result *res)
@@ -280,6 +284,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -316,12 +321,38 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_user(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getpwnam call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwnam_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -343,6 +374,15 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
DEBUG(2, ("No results for getpwnam call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_user(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -383,7 +423,7 @@ done:
}
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
+ const char *err_msg, void *ptr)
{
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
@@ -395,13 +435,28 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getpwnam_callback, dctx);
+
+done:
if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
+ DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
+ ret, strerror(ret)));
ret = nss_cmd_send_error(cmdctx, ret);
if (ret != EOK) {
@@ -481,6 +536,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
/* one less to go */
@@ -529,6 +585,27 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_uid(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ cmdctx->id);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getpwuid call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* yet one more call to go */
@@ -538,6 +615,11 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwuid_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -563,6 +645,14 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
DEBUG(2, ("No results for getpwuid call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_uid(cctx->nctx->ncache, cmdctx->id);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -620,11 +710,25 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->id,
nss_cmd_getpwuid_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1249,6 +1353,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -1277,12 +1382,38 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_group(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getgrnam call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrnam_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_GROUP,
@@ -1305,6 +1436,15 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
DEBUG(2, ("No results for getgrnam call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_group(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -1352,11 +1492,25 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getgrnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getgrnam_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1437,6 +1591,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
/* one less to go */
@@ -1476,6 +1631,27 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_gid(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ cmdctx->id);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getgrgid call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* yet one more call to go */
@@ -1485,6 +1661,11 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrgid_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_GROUP,
@@ -1510,6 +1691,14 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
DEBUG(2, ("No results for getgrgid call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_gid(cctx->nctx->ncache, cmdctx->id);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -1561,11 +1750,25 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getgrgid_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->id,
nss_cmd_getgrgid_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2082,11 +2285,25 @@ static void nss_cmd_getinitnam_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getinit_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getinit_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2109,6 +2326,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -2136,12 +2354,38 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_user(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for initgr call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = false;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getinitnam_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -2164,6 +2408,15 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
DEBUG(2, ("No results for initgroups call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_user(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);