summaryrefslogtreecommitdiffstats
path: root/src/responder/common
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-06-16 14:59:49 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-06-17 15:40:13 -0400
commitae5716d87c7b126ab01b0d4fcacd4f519585e5fb (patch)
tree8ebd5855d6cb81f4846107bb55b21132dda1e6cf /src/responder/common
parentde3f8b862f4920c2804529698db86f3057fd3c8a (diff)
downloadsssd-ae5716d87c7b126ab01b0d4fcacd4f519585e5fb.tar.gz
sssd-ae5716d87c7b126ab01b0d4fcacd4f519585e5fb.tar.xz
sssd-ae5716d87c7b126ab01b0d4fcacd4f519585e5fb.zip
Refactor the negative cache
Rename functions from nss_ncache_* to sss_ncache_* Move negative cache to responder/common and rename as negcache.c/h
Diffstat (limited to 'src/responder/common')
-rw-r--r--src/responder/common/negcache.c321
-rw-r--r--src/responder/common/negcache.h51
2 files changed, 372 insertions, 0 deletions
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
new file mode 100644
index 000000000..aef9080a8
--- /dev/null
+++ b/src/responder/common/negcache.c
@@ -0,0 +1,321 @@
+/*
+ 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_ENTRY_PREFIX "NCE/"
+#define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
+#define NC_GROUP_PREFIX NC_ENTRY_PREFIX"GROUP"
+#define NC_UID_PREFIX NC_ENTRY_PREFIX"UID"
+#define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
+
+struct sss_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 sss_ncache_init(TALLOC_CTX *memctx, struct sss_nc_ctx **_ctx)
+{
+ struct sss_nc_ctx *ctx;
+
+ ctx = talloc_zero(memctx, struct sss_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 sss_ncache_check_str(struct sss_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;
+ }
+
+ if (ttl == -1) {
+ /* a negative ttl means: never expires */
+ ret = EEXIST;
+ 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 == 0) {
+ /* a 0 timestamp means this is a permanent entry */
+ ret = EEXIST;
+ 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 sss_ncache_set_str(struct sss_nc_ctx *ctx,
+ char *str, bool permanent)
+{
+ TDB_DATA key;
+ TDB_DATA data;
+ char *timest;
+ int ret;
+
+ ret = string_to_tdb_data(str, &key);
+ if (ret != EOK) return ret;
+
+ if (permanent) {
+ timest = talloc_strdup(ctx, "0");
+ } else {
+ 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]\n",
+ tdb_errorstr(ctx->tdb)));
+ ret = EFAULT;
+ }
+
+done:
+ talloc_free(timest);
+ return ret;
+}
+
+int sss_ncache_check_user(struct sss_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 = sss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_check_group(struct sss_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 = sss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_check_uid(struct sss_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 = sss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_check_gid(struct sss_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 = sss_ncache_check_str(ctx, str, ttl);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_set_user(struct sss_nc_ctx *ctx, bool permanent,
+ 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 = sss_ncache_set_str(ctx, str, permanent);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_set_group(struct sss_nc_ctx *ctx, bool permanent,
+ 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 = sss_ncache_set_str(ctx, str, permanent);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, uid_t uid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
+ if (!str) return ENOMEM;
+
+ ret = sss_ncache_set_str(ctx, str, permanent);
+
+ talloc_free(str);
+ return ret;
+}
+
+int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, gid_t gid)
+{
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
+ if (!str) return ENOMEM;
+
+ ret = sss_ncache_set_str(ctx, str, permanent);
+
+ talloc_free(str);
+ return ret;
+}
+
+static int delete_permanent(struct tdb_context *tdb,
+ TDB_DATA key, TDB_DATA data, void *state)
+{
+ unsigned long long int timestamp;
+ bool remove_key = false;
+ char *ep;
+
+ if (strncmp((char *)key.dptr,
+ NC_ENTRY_PREFIX, sizeof(NC_ENTRY_PREFIX)) != 0) {
+ /* not interested in this key */
+ return 0;
+ }
+
+ errno = 0;
+ timestamp = strtoull((const char *)data.dptr, &ep, 0);
+ if (errno != 0 || *ep != '\0') {
+ /* Malformed entry, remove it */
+ remove_key = true;
+ goto done;
+ }
+
+ if (timestamp == 0) {
+ /* a 0 timestamp means this is a permanent entry */
+ remove_key = true;
+ }
+
+done:
+ if (remove_key) {
+ return tdb_delete(tdb, key);
+ }
+
+ return 0;
+}
+
+int sss_ncache_reset_permament(struct sss_nc_ctx *ctx)
+{
+ int ret;
+
+ ret = tdb_traverse(ctx->tdb, delete_permanent, NULL);
+ if (ret < 0)
+ return EIO;
+
+ return EOK;
+}
diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h
new file mode 100644
index 000000000..d310c9e3d
--- /dev/null
+++ b/src/responder/common/negcache.h
@@ -0,0 +1,51 @@
+/*
+ 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/>.
+*/
+
+#ifndef _NSS_NEG_CACHE_H_
+#define _NSS_NEG_CACHE_H_
+
+struct sss_nc_ctx;
+
+/* init the in memory negative cache */
+int sss_ncache_init(TALLOC_CTX *memctx, struct sss_nc_ctx **_ctx);
+
+/* check if the user is expired according to the passed in time to live */
+int sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
+ const char *domain, const char *name);
+int sss_ncache_check_group(struct sss_nc_ctx *ctx, int ttl,
+ const char *domain, 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);
+
+/* add a new neg-cache entry setting the timestamp to "now" unless
+ * "permanent" is set to true, in which case the timestamps is set to 0
+ * and the negative cache never expires (used to permanently filter out
+ * users and groups) */
+int sss_ncache_set_user(struct sss_nc_ctx *ctx, bool permanent,
+ const char *domain, const char *name);
+int sss_ncache_set_group(struct sss_nc_ctx *ctx, bool permanent,
+ const char *domain, 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_reset_permament(struct sss_nc_ctx *ctx);
+
+#endif /* _NSS_NEG_CACHE_H_ */