summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am10
-rw-r--r--contrib/sssd.spec.in1
-rw-r--r--src/tools/sss_cache.c360
3 files changed, 370 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index d8eb28d3..014293df 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,8 @@ sbin_PROGRAMS = \
sss_groupdel \
sss_usermod \
sss_groupmod \
- sss_groupshow
+ sss_groupshow \
+ sss_cache
sssdlibexec_PROGRAMS = \
sssd_nss \
@@ -476,6 +477,13 @@ sss_groupshow_SOURCES = \
sss_groupshow_LDADD = \
$(TOOLS_LIBS)
+sss_cache_SOURCES = \
+ src/tools/sss_cache.c \
+ $(SSSD_UTIL_OBJ) \
+ $(SSSD_TOOLS_OBJ)
+sss_cache_LDADD = \
+ $(TOOLS_LIBS)
+
#################
# Feature Tests #
#################
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 338151dd..56e36f4d 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -249,6 +249,7 @@ rm -rf $RPM_BUILD_ROOT
%{_sbindir}/sss_groupmod
%{_sbindir}/sss_groupshow
%{_sbindir}/sss_obfuscate
+%{_sbindir}/sss_cache
%{_mandir}/man8/sss_groupadd.8*
%{_mandir}/man8/sss_groupdel.8*
%{_mandir}/man8/sss_groupmod.8*
diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c
new file mode 100644
index 00000000..9eefca45
--- /dev/null
+++ b/src/tools/sss_cache.c
@@ -0,0 +1,360 @@
+/*
+ SSSD
+
+ sss_cache
+
+ Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2011
+
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <talloc.h>
+#include <popt.h>
+#include <sys/types.h>
+
+#include "util/util.h"
+#include "tools/sss_sync_ops.h"
+#include "db/sysdb.h"
+
+#define INVALIDATE_NONE 0
+#define INVALIDATE_USERS 1
+#define INVALIDATE_GROUPS 2
+#define INVALIDATE_NETGROUPS 4
+
+#define TYPE_USER 0
+#define TYPE_GROUP 1
+#define TYPE_NETGROUP 2
+struct entry_type_t {
+ const char *type_string;
+ int (* search_fn)(TALLOC_CTX *, struct sysdb_ctx *, struct sss_domain_info *,
+ const char *, const char **, size_t *, struct ldb_message ***);
+};
+static struct entry_type_t entry_types[] = {
+ {"user", sysdb_search_users},
+ {"group", sysdb_search_groups},
+ {"netgroup", sysdb_search_netgroups}
+};
+
+struct cache_tool_ctx {
+ struct confdb_ctx *confdb;
+ struct sss_domain_info *domains;
+ struct sysdb_ctx_list *sysdb_list;
+
+ char *user_filter;
+ char *group_filter;
+ char *netgroup_filter;
+};
+
+errno_t init_domains(struct cache_tool_ctx *ctx, const char *domain);
+errno_t init_context(int argc, const char *argv[], struct cache_tool_ctx **tctx);
+errno_t invalidate_entry(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb,
+ const char *name, int entry_type);
+void invalidate_entries(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb,
+ int entry_type, const char *filter);
+
+int main(int argc, const char *argv[])
+{
+ errno_t ret;
+ struct cache_tool_ctx *tctx = NULL;
+ struct sysdb_ctx *sysdb;
+ int i;
+
+ ret = init_context(argc, argv, &tctx);
+ if (ret != EOK) {
+ DEBUG(2, ("Error initializing context for the application\n"));
+ goto done;
+ }
+
+ for (i = 0; i < tctx->sysdb_list->num_dbs; i++) {
+ sysdb = tctx->sysdb_list->dbs[i];
+ ret = sysdb_transaction_start(sysdb);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not start the transaction!\n"));
+ goto done;
+ }
+
+ invalidate_entries(tctx, sysdb, TYPE_USER, tctx->user_filter);
+ invalidate_entries(tctx, sysdb, TYPE_GROUP, tctx->group_filter);
+ invalidate_entries(tctx, sysdb, TYPE_NETGROUP, tctx->netgroup_filter);
+
+ ret = sysdb_transaction_commit(sysdb);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not commit the transaction!\n"));
+ sysdb_transaction_cancel(sysdb);
+ }
+ }
+
+done:
+ if (tctx) talloc_free(tctx);
+ return ret;
+}
+
+
+void invalidate_entries(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb,
+ int entry_type, const char *filter)
+{
+ const char *attrs[] = {SYSDB_NAME, NULL};
+ size_t msg_count;
+ struct ldb_message **msgs;
+ struct entry_type_t type_rec;
+ errno_t ret;
+ int i;
+ const char *c_name;
+
+ type_rec = entry_types[entry_type];
+ if (filter) {
+ ret = type_rec.search_fn(ctx, sysdb, NULL, filter, attrs,
+ &msg_count, &msgs);
+ if (ret != EOK) {
+ DEBUG(3, ("Searching for %s with filter %s failed\n",
+ type_rec.type_string, filter));
+ return;
+ }
+
+ for (i = 0; i < msg_count; i++) {
+ c_name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
+ if (c_name == NULL) {
+ DEBUG(3, ("Something bad happened, can't find attribute %s",
+ SYSDB_NAME));
+ ERROR("Couldn't invalidate %s", type_rec.type_string);
+ } else {
+ ret = invalidate_entry(ctx, sysdb, c_name, entry_type);
+ if (ret != EOK) {
+ DEBUG(3, ("Couldn't invalidate %s %s", type_rec.type_string,
+ c_name));
+ ERROR("Couldn't invalidate %s %s", type_rec.type_string,
+ c_name);
+ }
+ }
+ }
+ talloc_zfree(msgs);
+ }
+}
+
+errno_t invalidate_entry(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb,
+ const char *name, int entry_type)
+{
+ struct sysdb_attrs *sys_attrs = NULL;
+ errno_t ret;
+
+ sys_attrs = sysdb_new_attrs(ctx);
+ if (sys_attrs) {
+ ret = sysdb_attrs_add_time_t(sys_attrs,
+ SYSDB_CACHE_EXPIRE, 1);
+ if (ret == EOK) {
+ switch (entry_type) {
+ case TYPE_USER:
+ ret = sysdb_set_user_attr(ctx, sysdb, NULL, name,
+ sys_attrs, SYSDB_MOD_REP);
+ break;
+ case TYPE_GROUP:
+ ret = sysdb_set_group_attr(ctx, sysdb, NULL, name,
+ sys_attrs, SYSDB_MOD_REP);
+ break;
+ case TYPE_NETGROUP:
+ ret = sysdb_set_netgroup_attr(sysdb, NULL, name,
+ sys_attrs, SYSDB_MOD_REP);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (ret != EOK) {
+ DEBUG(3, ("Could not set entry attributes\n"));
+ }
+ } else {
+ DEBUG(3, ("Could not add expiration time to attributes\n"));
+ }
+ talloc_zfree(sys_attrs);
+ } else {
+ DEBUG(3, ("Could not create sysdb attributes\n"));
+ }
+ return ret;
+}
+
+errno_t init_domains(struct cache_tool_ctx *ctx, const char *domain) {
+ char *confdb_path;
+ int ret;
+ struct sysdb_ctx *db_ctx = NULL;
+
+ confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
+ if (confdb_path == NULL) {
+ return ENOMEM;
+ }
+
+ /* Connect to the conf db */
+ ret = confdb_init(ctx, &ctx->confdb, confdb_path);
+ talloc_free(confdb_path);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not initialize connection to the confdb\n"));
+ return ret;
+ }
+
+ if (domain) {
+ ret = confdb_get_domain(ctx->confdb, domain, &ctx->domains);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not get '%s' domain: [%d] [%s]\n",
+ domain, ret, strerror(ret)));
+ goto fail;
+ }
+
+ ret = sysdb_domain_init(ctx, ctx->domains, DB_PATH, &db_ctx);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not initialize connection to the sysdb\n"));
+ goto fail;
+ }
+
+ ret = sysdb_list_init(ctx, DB_PATH, db_ctx, &ctx->sysdb_list);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not initialize the list of connections\n"));
+ goto fail;
+ }
+ } else {
+ ret = sysdb_init(ctx, ctx->confdb, NULL, false, &ctx->sysdb_list);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not initialize connection to the sysdb\n"));
+ goto fail;
+ }
+ }
+
+ return EOK;
+fail:
+ if (ctx->confdb) talloc_zfree(ctx->confdb);
+ if (ctx->domains) talloc_zfree(ctx->domains);
+ if (ctx->sysdb_list) {
+ talloc_zfree(ctx->sysdb_list);
+ } else {
+ if (db_ctx) talloc_free(db_ctx);
+ }
+ return ret;
+}
+
+errno_t init_context(int argc, const char *argv[], struct cache_tool_ctx **tctx)
+{
+ struct cache_tool_ctx *ctx = NULL;
+ int idb = INVALIDATE_NONE;
+ char *user = NULL;
+ char *group = NULL;
+ char *netgroup = NULL;
+ char *domain = NULL;
+ int debug = 0;
+ errno_t ret = EOK;
+
+ poptContext pc = NULL;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &debug,
+ 0, _("The debug level to run with"), NULL },
+ { "user", 'u', POPT_ARG_STRING, &user, 0,
+ _("Invalidate particular user"), NULL },
+ { "users", 'U', POPT_ARG_NONE, NULL, 'u',
+ _("Invalidate all users"), NULL },
+ { "group", 'g', POPT_ARG_STRING, &group, 0,
+ _("Invalidate particular group"), NULL },
+ { "groups", 'G', POPT_ARG_NONE, NULL, 'g',
+ _("Invalidate all groups"), NULL },
+ { "netgroup", 'n', POPT_ARG_STRING, &netgroup, 0,
+ _("Invalidate particular netgroup"), NULL },
+ { "netgroups", 'N', POPT_ARG_NONE, NULL, 'n',
+ _("Invalidate all netgroups"), NULL },
+ { "domain", 'd', POPT_ARG_STRING, &domain, 0,
+ _("Only invalidate entries from a particular domain"), NULL },
+ POPT_TABLEEND
+ };
+
+ ret = set_locale();
+ if (ret != EOK) {
+ DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret)));
+ ERROR("Error setting the locale\n");
+ goto fini;
+ }
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ while ((ret = poptGetNextOpt(pc)) > 0) {
+ switch (ret) {
+ case 'u':
+ idb |= INVALIDATE_USERS;
+ break;
+ case 'g':
+ idb |= INVALIDATE_GROUPS;
+ break;
+ case 'n':
+ idb |= INVALIDATE_NETGROUPS;
+ break;
+ }
+ }
+ if (ret != -1) {
+ BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
+ }
+
+ debug_level = debug;
+ debug_prg_name = argv[0];
+ CHECK_ROOT(ret, debug_prg_name);
+
+ ctx = talloc_zero(NULL, struct cache_tool_ctx);
+ if (ctx == NULL) {
+ DEBUG(1, ("Could not allocate memory for tools context\n"));
+ ret = ENOMEM;
+ goto fini;
+ }
+
+ if (idb & INVALIDATE_USERS) {
+ ctx->user_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
+ } else if (user) {
+ ctx->user_filter = talloc_asprintf(ctx, "(%s=%s)", SYSDB_NAME, user);
+ }
+
+ if (idb & INVALIDATE_GROUPS) {
+ ctx->group_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
+ } else if (group) {
+ ctx->group_filter = talloc_asprintf(ctx, "(%s=%s)", SYSDB_NAME, group);
+ }
+
+ if (idb & INVALIDATE_NETGROUPS) {
+ ctx->netgroup_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
+ } else if (netgroup) {
+ ctx->netgroup_filter = talloc_asprintf(ctx, "(%s=%s)", SYSDB_NAME,
+ netgroup);
+ }
+ if (((idb & INVALIDATE_USERS || user) && !ctx->user_filter) ||
+ ((idb & INVALIDATE_GROUPS || group) && !ctx->group_filter) ||
+ ((idb & INVALIDATE_NETGROUPS || netgroup) && !ctx->netgroup_filter)) {
+ DEBUG(1, ("Construction of filters failed\n"));
+ ret = ENOMEM;
+ goto fini;
+ }
+
+ ret = init_domains(ctx, domain);
+ if (ret != EOK) {
+ DEBUG(3, ("Initialization of sysdb connections failed\n"));
+ goto fini;
+ }
+
+ ret = EOK;
+
+fini:
+ poptFreeContext(pc);
+ free(user);
+ free(group);
+ free(netgroup);
+ free(domain);
+ if (ret != EOK && ctx) {
+ talloc_zfree(ctx);
+ }
+ if (ret == EOK) {
+ *tctx = ctx;
+ }
+ return ret;
+}