summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-11-11 21:52:09 -0500
committerStephen Gallagher <sgallagh@redhat.com>2009-11-18 17:35:07 -0500
commitb6dd30c7f8cce8800ef4c35f13d6574e796ffca2 (patch)
treeefc2aeda57f7216325780bc0ecfabb38769f65b9
parent39462f9afb7512d3d8109e17b78a303b20c557ab (diff)
downloadsssd-b6dd30c7f8cce8800ef4c35f13d6574e796ffca2.tar.gz
sssd-b6dd30c7f8cce8800ef4c35f13d6574e796ffca2.tar.xz
sssd-b6dd30c7f8cce8800ef4c35f13d6574e796ffca2.zip
Change initgroups code to use and check the cache
We were previously always ending up contacting the backend because we had no way to know if an initgroups call for the same user had ever been called. Add attribute to hold this information and rely on backends to update it. If they don't we fallback to the previous behvior of asking the backend.
-rw-r--r--server/db/sysdb.h33
-rw-r--r--server/responder/nss/nsssrv_cmd.c294
2 files changed, 109 insertions, 218 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 4c92c3777..a32998590 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -66,6 +66,7 @@
#define SYSDB_LAST_UPDATE "lastUpdate"
#define SYSDB_CACHE_EXPIRE "dataExpireTimestamp"
+#define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp"
#define SYSDB_CACHEDPWD "cachedPassword"
@@ -101,41 +102,29 @@
#define SYSDB_GETCACHED_FILTER "(&"SYSDB_UC")("SYSDB_LAST_LOGIN">=%lu))"
+#define SYSDB_DEFAULT_ATTRS SYSDB_LAST_UPDATE, \
+ SYSDB_CACHE_EXPIRE, \
+ SYSDB_INITGR_EXPIRE, \
+ "objectClass"
+
#define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
SYSDB_GIDNUM, SYSDB_GECOS, \
SYSDB_HOMEDIR, SYSDB_SHELL, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- "objectClass", \
+ SYSDB_DEFAULT_ATTRS, \
NULL}
-#define SYSDB_USER_ATTRS {SYSDB_DEFAULTGROUP, \
- SYSDB_GECOS, \
- SYSDB_HOMEDIR, \
- SYSDB_SHELL, \
- SYSDB_FULLNAME, \
- SYSDB_LOCALE, \
- SYSDB_KEYBOARD, \
- SYSDB_SESSION, \
- SYSDB_LAST_LOGIN, \
- SYSDB_USERPIC, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- NULL}
#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- "objectClass", \
+ SYSDB_DEFAULT_ATTRS, \
NULL}
#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- "objectClass", \
+ SYSDB_DEFAULT_ATTRS, \
NULL}
#define SYSDB_GRENT_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, SYSDB_MEMBEROF, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- "objectClass", \
+ SYSDB_DEFAULT_ATTRS, \
NULL}
#define SYSDB_INITGR_ATTR SYSDB_MEMBEROF
#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, \
- SYSDB_LAST_UPDATE, SYSDB_CACHE_EXPIRE, \
- "objectClass", \
+ SYSDB_DEFAULT_ATTRS, \
NULL}
#define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index b2a2035c7..a029baf46 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -280,7 +280,7 @@ static errno_t check_cache(struct nss_dom_ctx *dctx,
int timeout;
time_t now;
uint64_t lastUpdate;
- uint64_t cacheExpire;
+ uint64_t cacheExpire = 0;
uint64_t midpoint_refresh;
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
@@ -305,8 +305,14 @@ static errno_t check_cache(struct nss_dom_ctx *dctx,
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
SYSDB_LAST_UPDATE, 0);
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
+ if (req_type == SSS_DP_INITGROUPS) {
+ cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
+ SYSDB_INITGR_EXPIRE, 1);
+ }
+ if (cacheExpire == 0) {
+ cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
+ SYSDB_CACHE_EXPIRE, 0);
+ }
midpoint_refresh = 0;
if(nctx->cache_refresh_percent) {
@@ -2780,147 +2786,47 @@ done:
return EOK;
}
-static void nss_cmd_initgr_callback(void *ptr, int status,
- struct ldb_result *res)
+static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
{
- struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
- struct cli_ctx *cctx = cmdctx->cctx;
uint8_t *body;
size_t blen;
- uint32_t gid;
- uint32_t num;
- int ret, i;
+ gid_t gid;
+ int ret, i, num;
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
+ if (res->count == 0) {
+ return ENOENT;
}
- if (status != LDB_SUCCESS) {
- sss_packet_set_error(cctx->creq->out, status);
- goto done;
- }
+ /* one less, the first one is the user entry */
+ num = res->count -1;
- num = res->count;
- ret = sss_packet_grow(cctx->creq->out, (2 + num) * sizeof(uint32_t));
+ ret = sss_packet_grow(packet, (2 + res->count) * sizeof(uint32_t));
if (ret != EOK) {
- sss_packet_set_error(cctx->creq->out, ret);
- goto done;
+ return ret;
}
- sss_packet_get_body(cctx->creq->out, &body, &blen);
+ sss_packet_get_body(packet, &body, &blen);
+ /* skip first entry, it's the user entry */
for (i = 0; i < num; i++) {
- gid = ldb_msg_find_attr_as_uint64(res->msgs[i], SYSDB_GIDNUM, 0);
+ gid = ldb_msg_find_attr_as_uint64(res->msgs[i + 1], SYSDB_GIDNUM, 0);
if (!gid) {
DEBUG(1, ("Incomplete group object for initgroups! Aborting\n"));
- sss_packet_set_error(cctx->creq->out, EIO);
- num = 0;
- goto done;
+ return EFAULT;
}
- ((uint32_t *)body)[2+i] = gid;
+ ((uint32_t *)body)[2 + i] = gid;
}
((uint32_t *)body)[0] = num; /* num results */
((uint32_t *)body)[1] = 0; /* reserved */
-done:
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min,
- 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;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "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));
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_initgroups(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_initgr_callback, cmdctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
+ return EOK;
}
-static void nss_cmd_getinit_callback(void *ptr, int status,
- struct ldb_result *res);
-
-static void nss_cmd_getinitnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- 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;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "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_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinit_callback, dctx);
+static void nss_cmd_getinitgr_dp_callback(uint16_t err_maj, uint32_t err_min,
+ const char *err_msg, void *ptr);
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static void nss_cmd_getinit_callback(void *ptr, int status,
- struct ldb_result *res)
+static void nss_cmd_getinitgr_callback(void *ptr, int status,
+ struct ldb_result *res)
{
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
@@ -2928,11 +2834,8 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
struct sss_domain_info *dom;
struct sysdb_ctx *sysdb;
struct nss_ctx *nctx;
- int timeout;
- uint64_t cacheExpire;
uint8_t *body;
size_t blen;
- bool call_provider = false;
bool neghit = false;
int ncret;
int ret;
@@ -2949,55 +2852,15 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
}
if (dctx->check_provider) {
- switch (res->count) {
- case 0:
- call_provider = true;
- break;
-
- case 1:
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
- if (cacheExpire < time(NULL)) {
- call_provider = true;
- }
- break;
-
- default:
- DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
- }
-
- 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 = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_getinitnam_dp_callback, dctx,
- timeout, dctx->domain->name, SSS_DP_USER,
- cmdctx->name, 0);
+ ret = check_cache(dctx, nctx, res,
+ SSS_DP_INITGROUPS, cmdctx->name, 0,
+ nss_cmd_getinitgr_dp_callback);
if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
+ /* Anything but EOK means we should reenter the mainloop
+ * because we may be refreshing the cache
+ */
+ return;
}
- return;
}
switch (res->count) {
@@ -3047,9 +2910,9 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
NSS_CMD_FATAL_ERROR(cctx);
}
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinit_callback, dctx);
+ ret = sysdb_initgroups(cmdctx, sysdb,
+ dctx->domain, cmdctx->name,
+ nss_cmd_getinitgr_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
}
@@ -3081,35 +2944,74 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
((uint32_t *)body)[1] = 0; /* reserved */
break;
- case 1:
+ default:
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_getinitgr_callback, dctx,
- timeout, dctx->domain->name,
- SSS_DP_INITGROUPS,
- cmdctx->name, 0);
+ DEBUG(6, ("Returning initgr for user [%s]\n", cmdctx->name));
+
+ ret = sss_packet_new(cctx->creq, 0,
+ sss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ ret = fill_initgr(cctx->creq->out, res);
+ if (ret == ENOENT) {
+ ret = fill_empty(cctx->creq->out);
+ }
+ sss_packet_set_error(cctx->creq->out, ret);
+ }
+
+ sss_cmd_done(cctx, cmdctx);
+}
+
+static void nss_cmd_getinitgr_dp_callback(uint16_t err_maj, uint32_t err_min,
+ 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;
+ struct cli_ctx *cctx = cmdctx->cctx;
+ struct sysdb_ctx *sysdb;
+ int ret;
+
+ if (err_maj) {
+ DEBUG(2, ("Unable to get information from Data Provider\n"
+ "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;
}
- sss_cmd_done(cctx, cmdctx);
}
+ nss_cmd_getinitgr_callback(dctx, LDB_SUCCESS, dctx->res);
return;
+ }
- default:
- DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
+ ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
+ dctx->domain, &sysdb);
+ if (ret != EOK) {
+ DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ ret = sysdb_initgroups(cmdctx, sysdb,
+ dctx->domain, cmdctx->name,
+ nss_cmd_getinitgr_callback, dctx);
+
+done:
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to make request to our cache!\n"));
+
+ ret = nss_cmd_send_error(cmdctx, ret);
if (ret != EOK) {
NSS_CMD_FATAL_ERROR(cctx);
}
+ sss_cmd_done(cctx, cmdctx);
}
-
- sss_cmd_done(cctx, cmdctx);
}
/* for now, if we are online, try to always query the backend */
@@ -3227,9 +3129,9 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
ret = EFAULT;
goto done;
}
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinit_callback, dctx);
+ ret = sysdb_initgroups(cmdctx, sysdb,
+ dctx->domain, cmdctx->name,
+ nss_cmd_getinitgr_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
}