summaryrefslogtreecommitdiff
path: root/server/responder/nss/nsssrv_nc.c
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-03-12 22:59:31 -0400
committerSimo Sorce <ssorce@redhat.com>2009-03-13 13:47:38 -0400
commitdd4d867835a1443cb5a10b7a678d1d12400690d6 (patch)
treea78b211c0ae56369ba22a8dc7add0de3f13c7a77 /server/responder/nss/nsssrv_nc.c
parent063ef0f15dfc32d15d2e9bdcba819906aa99b948 (diff)
downloadsssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.tar.gz
sssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.tar.bz2
sssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.zip
Implement Negative cache for NSS
As for positive caches, negative caches are implement for all queries except enumerations. Also set the correct requires in sssd.spec as we now depend directly on tdb as well.
Diffstat (limited to 'server/responder/nss/nsssrv_nc.c')
-rw-r--r--server/responder/nss/nsssrv_nc.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/server/responder/nss/nsssrv_nc.c b/server/responder/nss/nsssrv_nc.c
new file mode 100644
index 00000000..74f8369b
--- /dev/null
+++ b/server/responder/nss/nsssrv_nc.c
@@ -0,0 +1,258 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include <fcntl.h>
+#include <time.h>
+#include "tdb.h"
+
+#define NC_USER_PREFIX "NCUSER"
+#define NC_GROUP_PREFIX "NCGROUP"
+#define NC_UID_PREFIX "NCUID"
+#define NC_GID_PREFIX "NCGID"
+
+struct nss_nc_ctx {
+ struct tdb_context *tdb;
+};
+
+static int string_to_tdb_data(char *str, TDB_DATA *ret)
+{
+ if (!str || !ret) return EINVAL;
+
+ ret->dptr = (uint8_t *)str;
+ ret->dsize = strlen(str)+1;
+
+ return EOK;
+}
+
+int nss_ncache_init(TALLOC_CTX *memctx, struct nss_nc_ctx **_ctx)
+{
+ struct nss_nc_ctx *ctx;
+
+ ctx = talloc_zero(memctx, struct nss_nc_ctx);
+ if (!ctx) return ENOMEM;
+
+ errno = 0;
+ /* open a memory only tdb with default hash size */
+ ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
+ if (!ctx->tdb) return errno;
+
+ *_ctx = ctx;
+ return EOK;
+};
+
+static int nss_ncache_check_str(struct nss_nc_ctx *ctx, char *str, int ttl)
+{
+ TDB_DATA key;
+ TDB_DATA data;
+ unsigned long long int timestamp;
+ bool expired = false;
+ char *ep;
+ int ret;
+
+ ret = string_to_tdb_data(str, &key);
+ if (ret != EOK) goto done;
+
+ data = tdb_fetch(ctx->tdb, key);
+
+ if (!data.dptr) {
+ ret = ENOENT;
+ goto done;
+ }
+
+ errno = 0;
+ timestamp = strtoull((const char *)data.dptr, &ep, 0);
+ if (errno != 0 || *ep != '\0') {
+ /* Malformed entry, remove it and return no entry */
+ expired = true;
+ goto done;
+ }
+
+ if (timestamp + ttl > time(NULL)) {
+ /* still valid */
+ ret = EEXIST;
+ goto done;
+ }
+
+ expired = true;
+
+done:
+ if (expired) {
+ /* expired, remove and return no entry */
+ tdb_delete(ctx->tdb, key);
+ ret = ENOENT;
+ }
+
+ return ret;
+}
+
+static int nss_ncache_set_str(struct nss_nc_ctx *ctx, char *str)
+{
+ TDB_DATA key;
+ TDB_DATA data;
+ char *timest;
+ int ret;
+
+ ret = string_to_tdb_data(str, &key);
+ if (ret != EOK) return ret;
+
+ timest = talloc_asprintf(ctx, "%llu", (unsigned long long int)time(NULL));
+ if (!timest) return ENOMEM;
+
+ ret = string_to_tdb_data(timest, &data);
+ if (ret != EOK) goto done;
+
+ ret = tdb_store(ctx->tdb, key, data, TDB_REPLACE);
+ if (ret != 0) {
+ DEBUG(1, ("Negative cache failed to set entry: [%s]",
+ tdb_errorstr(ctx->tdb)));
+ ret = EFAULT;
+ }
+
+done:
+ talloc_free(timest);
+ return ret;
+}
+
+int nss_ncache_check_user(struct nss_nc_ctx *ctx, int ttl,
+ const char *domain, const char *name)
+{
+ char *str;
+ int ret;
+
+ if (!name || !*name) return EINVAL;
+
+ str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_check_group(struct nss_nc_ctx *ctx, int ttl,
+ const char *domain, const char *name)
+{
+ char *str;
+ int ret;
+
+ if (!name || !*name) return EINVAL;
+
+ str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_check_uid(struct nss_nc_ctx *ctx, int ttl, uid_t uid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_check_gid(struct nss_nc_ctx *ctx, int ttl, gid_t gid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_set_user(struct nss_nc_ctx *ctx,
+ const char *domain, const char *name)
+{
+ char *str;
+ int ret;
+
+ if (!name || !*name) return EINVAL;
+
+ str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_set_str(ctx, str);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_set_group(struct nss_nc_ctx *ctx,
+ const char *domain, const char *name)
+{
+ char *str;
+ int ret;
+
+ if (!name || !*name) return EINVAL;
+
+ str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_set_str(ctx, str);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_set_uid(struct nss_nc_ctx *ctx, uid_t uid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_set_str(ctx, str);
+
+ talloc_free(str);
+ return ret;
+}
+
+int nss_ncache_set_gid(struct nss_nc_ctx *ctx, gid_t gid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
+ if (!str) return ENOMEM;
+
+ ret = nss_ncache_set_str(ctx, str);
+
+ talloc_free(str);
+ return ret;
+}
+