sss_cache.c revision 1330390c698ca0802200725df43356557aa633a2
beaad6ac31022179c44d88536811e9ccd9425696nd/*
beaad6ac31022179c44d88536811e9ccd9425696nd SSSD
beaad6ac31022179c44d88536811e9ccd9425696nd
db878466c5e95073429dda0bdd001f45e9486e16fielding sss_cache
db878466c5e95073429dda0bdd001f45e9486e16fielding
db878466c5e95073429dda0bdd001f45e9486e16fielding Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2011
db878466c5e95073429dda0bdd001f45e9486e16fielding
db878466c5e95073429dda0bdd001f45e9486e16fielding This program is free software; you can redistribute it and/or modify
db878466c5e95073429dda0bdd001f45e9486e16fielding it under the terms of the GNU General Public License as published by
beaad6ac31022179c44d88536811e9ccd9425696nd the Free Software Foundation; either version 3 of the License, or
beaad6ac31022179c44d88536811e9ccd9425696nd (at your option) any later version.
beaad6ac31022179c44d88536811e9ccd9425696nd
beaad6ac31022179c44d88536811e9ccd9425696nd This program is distributed in the hope that it will be useful,
beaad6ac31022179c44d88536811e9ccd9425696nd but WITHOUT ANY WARRANTY; without even the implied warranty of
beaad6ac31022179c44d88536811e9ccd9425696nd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
beaad6ac31022179c44d88536811e9ccd9425696nd GNU General Public License for more details.
beaad6ac31022179c44d88536811e9ccd9425696nd
beaad6ac31022179c44d88536811e9ccd9425696nd You should have received a copy of the GNU General Public License
beaad6ac31022179c44d88536811e9ccd9425696nd along with this program. If not, see <http://www.gnu.org/licenses/>.
01c674544bd4c211141bcd9fb09b96ffc18c6c3dnd*/
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
01c674544bd4c211141bcd9fb09b96ffc18c6c3dnd#include <stdio.h>
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include <stdlib.h>
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include <talloc.h>
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include <popt.h>
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include <sys/types.h>
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
a8bc9b37495d26276b0e506d644a07f32ad95626rbowen#include "util/util.h"
a8bc9b37495d26276b0e506d644a07f32ad95626rbowen#include "tools/sss_sync_ops.h"
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#include "db/sysdb.h"
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#include "db/sysdb_services.h"
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include "db/sysdb_autofs.h"
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#include "db/sysdb_ssh.h"
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#include "db/sysdb_sudo.h"
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#define INVALIDATE_NONE 0
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_USERS 1
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#define INVALIDATE_GROUPS 2
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_NETGROUPS 4
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#define INVALIDATE_SERVICES 8
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_AUTOFSMAPS 16
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_SSH_HOSTS 32
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_SUDO_RULES 64
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#ifdef BUILD_AUTOFS
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#ifdef BUILD_SSH
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#define INVALIDATE_EVERYTHING (INVALIDATE_USERS | INVALIDATE_GROUPS | \
7e68fce3cbd2246164e045a51ecd77f9f26680ednd INVALIDATE_NETGROUPS | INVALIDATE_SERVICES | \
7e68fce3cbd2246164e045a51ecd77f9f26680ednd INVALIDATE_AUTOFSMAPS | INVALIDATE_SSH_HOSTS )
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#else /* BUILD_SSH */
66e48875fca2df6669dab4f2690ee36c6913c0ffnd#define INVALIDATE_EVERYTHING (INVALIDATE_USERS | INVALIDATE_GROUPS | \
7e68fce3cbd2246164e045a51ecd77f9f26680ednd INVALIDATE_NETGROUPS | INVALIDATE_SERVICES | \
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd INVALIDATE_AUTOFSMAPS )
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#endif /* BUILD_SSH */
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#else /* BUILD_AUTOFS */
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#ifdef BUILD_SSH
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd#define INVALIDATE_EVERYTHING (INVALIDATE_USERS | INVALIDATE_GROUPS | \
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd INVALIDATE_NETGROUPS | INVALIDATE_SERVICES | \
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd INVALIDATE_SSH_HOSTS )
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#else /* BUILD_SSH */
7e68fce3cbd2246164e045a51ecd77f9f26680ednd#define INVALIDATE_EVERYTHING (INVALIDATE_USERS | INVALIDATE_GROUPS | \
7e68fce3cbd2246164e045a51ecd77f9f26680ednd INVALIDATE_NETGROUPS | INVALIDATE_SERVICES )
f5f948a91315652103ddae08be22d76f63ba96d4nd#endif /* BUILD_SSH */
8cfbcde8e416fd60132dd4324c42a5098da156cfnd#endif /* BUILD_AUTOFS */
8cfbcde8e416fd60132dd4324c42a5098da156cfnd
7e68fce3cbd2246164e045a51ecd77f9f26680edndenum sss_cache_entry {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_USER=0,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_GROUP,
f5f948a91315652103ddae08be22d76f63ba96d4nd TYPE_NETGROUP,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_SERVICE,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_AUTOFSMAP,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_SSH_HOST,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd TYPE_SUDO_RULE
7e68fce3cbd2246164e045a51ecd77f9f26680ednd};
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic errno_t search_autofsmaps(TALLOC_CTX *mem_ctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *domain,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd const char *sub_filter, const char **attrs,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd size_t *msgs_count, struct ldb_message ***msgs);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680edndstruct input_values {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *domain;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *group;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *map;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *netgroup;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *service;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *ssh_host;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *sudo_rule;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *user;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd};
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680edndstruct cache_tool_ctx {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct confdb_ctx *confdb;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *domains;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *user_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *group_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *netgroup_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *service_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *autofs_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *ssh_host_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *sudo_rule_filter;
f5f948a91315652103ddae08be22d76f63ba96d4nd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *user_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *group_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *netgroup_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *service_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *autofs_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd char *ssh_host_name;
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd char *sudo_rule_name;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_user_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_group_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_netgroup_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_service_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_autofs_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_ssh_host_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool update_sudo_rule_filter;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd};
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic void free_input_values(struct input_values *values);
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic bool is_filter_valid(struct cache_tool_ctx *ctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct input_values *values, int idb);
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic errno_t init_domains(struct cache_tool_ctx *ctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd const char *domain);
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic errno_t init_context(int argc, const char *argv[],
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct cache_tool_ctx **tctx);
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic errno_t invalidate_entry(TALLOC_CTX *ctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *domain,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd const char *name, int entry_type);
7e68fce3cbd2246164e045a51ecd77f9f26680edndstatic bool invalidate_entries(TALLOC_CTX *ctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *dinfo,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd enum sss_cache_entry entry_type,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd const char *filter, const char *name);
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26ndstatic errno_t update_all_filters(struct cache_tool_ctx *tctx,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *dinfo);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680edndint main(int argc, const char *argv[])
7e68fce3cbd2246164e045a51ecd77f9f26680ednd{
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd errno_t ret;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct cache_tool_ctx *tctx = NULL;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sysdb_ctx *sysdb;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd bool skipped = true;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd struct sss_domain_info *dinfo;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd ret = init_context(argc, argv, &tctx);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd if (ret != EOK) {
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd DEBUG(SSSDBG_CRIT_FAILURE,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd "Error initializing context for the application\n");
7e68fce3cbd2246164e045a51ecd77f9f26680ednd goto done;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd for (dinfo = tctx->domains; dinfo;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd dinfo = get_next_domain(dinfo, SSS_GND_DESCEND)) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd if (!IS_SUBDOMAIN(dinfo)) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd /* Update list of subdomains for this domain */
7e68fce3cbd2246164e045a51ecd77f9f26680ednd ret = sysdb_update_subdomains(dinfo);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd if (ret != EOK) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd DEBUG(SSSDBG_MINOR_FAILURE,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd "Failed to update subdomains for domain %s.\n", dinfo->name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd sysdb = dinfo->sysdb;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd /* Update filters for each domain */
66e48875fca2df6669dab4f2690ee36c6913c0ffnd ret = update_all_filters(tctx, dinfo);
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd if (ret != EOK) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd DEBUG(SSSDBG_CRIT_FAILURE, "Failed to update filters.\n");
7e68fce3cbd2246164e045a51ecd77f9f26680ednd goto done;
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
66e48875fca2df6669dab4f2690ee36c6913c0ffnd ret = sysdb_transaction_start(sysdb);
bdbf46e4950b6f633073f803486962e82c2f086and if (ret != EOK) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd DEBUG(SSSDBG_CRIT_FAILURE,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd "Could not start the transaction!\n");
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd goto done;
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd skipped &= !invalidate_entries(tctx, dinfo, TYPE_USER,
b51bf223f42d43ca6b1b33c95124edcfa5a871a4nd tctx->user_filter,
f36af6370d0850bf789703e852778d8e8ceefd20nd tctx->user_name);
b51bf223f42d43ca6b1b33c95124edcfa5a871a4nd skipped &= !invalidate_entries(tctx, dinfo, TYPE_GROUP,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->group_filter,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->group_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd skipped &= !invalidate_entries(tctx, dinfo, TYPE_NETGROUP,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->netgroup_filter,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->netgroup_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd skipped &= !invalidate_entries(tctx, dinfo, TYPE_SERVICE,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->service_filter,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->service_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd skipped &= !invalidate_entries(tctx, dinfo, TYPE_AUTOFSMAP,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->autofs_filter,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->autofs_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd skipped &= !invalidate_entries(tctx, dinfo, TYPE_SSH_HOST,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->ssh_host_filter,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->ssh_host_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd skipped &= !invalidate_entries(tctx, dinfo, TYPE_SUDO_RULE,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd tctx->sudo_rule_filter,
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd tctx->sudo_rule_name);
7e68fce3cbd2246164e045a51ecd77f9f26680ednd
7e68fce3cbd2246164e045a51ecd77f9f26680ednd ret = sysdb_transaction_commit(sysdb);
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd if (ret != EOK) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd DEBUG(SSSDBG_CRIT_FAILURE,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd "Could not commit the transaction!\n");
7e68fce3cbd2246164e045a51ecd77f9f26680ednd ret = sysdb_transaction_cancel(sysdb);
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd if (ret != EOK) {
7e68fce3cbd2246164e045a51ecd77f9f26680ednd DEBUG(SSSDBG_CRIT_FAILURE,
7e68fce3cbd2246164e045a51ecd77f9f26680ednd "Failed to cancel transaction\n");
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
7e68fce3cbd2246164e045a51ecd77f9f26680ednd }
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd
29fb68cf24dbdb4985cbb4734cb6074ea4bbab26nd if (skipped == true) {
ERROR("No cache object matched the specified search\n");
ret = ENOENT;
goto done;
} else {
ret = sss_memcache_clear_all();
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to clear memory cache.\n");
goto done;
}
}
ret = EOK;
done:
if (tctx) talloc_free(tctx);
return ret;
}
static void free_input_values(struct input_values *values)
{
free(values->domain);
free(values->group);
free(values->map);
free(values->netgroup);
free(values->service);
free(values->ssh_host);
free(values->sudo_rule);
free(values->user);
}
static errno_t update_filter(struct cache_tool_ctx *tctx,
struct sss_domain_info *dinfo,
char *name, bool update, const char *fmt,
enum sss_cache_entry entry_type,
bool force_case_sensitivity,
char **_filter)
{
errno_t ret;
char *parsed_domain = NULL;
char *parsed_name = NULL;
TALLOC_CTX *tmp_ctx = NULL;
char *use_name = NULL;
char *filter;
char *sanitized;
char *lc_sanitized;
if (!name || !update) {
/* Nothing to do */
return EOK;
}
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
return ENOMEM;
}
ret = sss_parse_name(tmp_ctx, dinfo->names, name,
&parsed_domain, &parsed_name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_name failed\n");
goto done;
}
if (parsed_domain != NULL && strcasecmp(dinfo->name, parsed_domain) != 0) {
/* We were able to parse the domain from given fqdn, but it
* does not match with currently processed domain. */
filter = NULL;
ret = EOK;
goto done;
}
if (!dinfo->case_sensitive && !force_case_sensitivity) {
use_name = sss_tc_utf8_str_tolower(tmp_ctx, parsed_name);
if (!use_name) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
ret = ENOMEM;
goto done;
}
} else {
use_name = parsed_name;
}
switch (entry_type) {
case TYPE_USER:
case TYPE_GROUP:
use_name = sss_create_internal_fqname(tmp_ctx, use_name, dinfo->name);
default:
break;
}
if (!use_name) {
ret = ENOMEM;
goto done;
}
ret = sss_filter_sanitize_for_dom(tmp_ctx, use_name, dinfo,
&sanitized, &lc_sanitized);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to sanitize the given name.\n");
goto done;
}
if (fmt) {
if (!dinfo->case_sensitive && !force_case_sensitivity) {
filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)(%s=%s))",
SYSDB_NAME_ALIAS, lc_sanitized,
SYSDB_NAME_ALIAS, sanitized);
} else {
filter = talloc_asprintf(tmp_ctx, fmt, SYSDB_NAME, sanitized);
}
} else {
filter = talloc_strdup(tmp_ctx, sanitized);
}
if (filter == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
ret = ENOMEM;
goto done;
}
ret = EOK;
done:
if (ret == EOK) {
talloc_free(*_filter);
*_filter = talloc_steal(tctx, filter);
}
talloc_free(tmp_ctx);
return ret;
}
/* This function updates all filters for specified domain using this
* domains regex to parse string into domain and name (if exists). */
static errno_t update_all_filters(struct cache_tool_ctx *tctx,
struct sss_domain_info *dinfo)
{
errno_t ret;
/* Update user filter */
ret = update_filter(tctx, dinfo, tctx->user_name,
tctx->update_user_filter, "(%s=%s)",
TYPE_USER, false,
&tctx->user_filter);
if (ret != EOK) {
return ret;
}
/* Update group filter */
ret = update_filter(tctx, dinfo, tctx->group_name,
tctx->update_group_filter, "(%s=%s)",
TYPE_GROUP, false,
&tctx->group_filter);
if (ret != EOK) {
return ret;
}
/* Update netgroup filter */
ret = update_filter(tctx, dinfo, tctx->netgroup_name,
tctx->update_netgroup_filter, "(%s=%s)",
TYPE_NETGROUP, false,
&tctx->netgroup_filter);
if (ret != EOK) {
return ret;
}
/* Update service filter */
ret = update_filter(tctx, dinfo, tctx->service_name,
tctx->update_service_filter, "(%s=%s)",
TYPE_SERVICE, false,
&tctx->service_filter);
if (ret != EOK) {
return ret;
}
/* Update autofs filter */
ret = update_filter(tctx, dinfo, tctx->autofs_name,
tctx->update_autofs_filter,
"(&(objectclass="SYSDB_AUTOFS_MAP_OC")(%s=%s))",
TYPE_AUTOFSMAP, true,
&tctx->autofs_filter);
if (ret != EOK) {
return ret;
}
/* Update ssh host filter */
ret = update_filter(tctx, dinfo, tctx->ssh_host_name,
tctx->update_ssh_host_filter, "(%s=%s)",
TYPE_SSH_HOST, false,
&tctx->ssh_host_filter);
if (ret != EOK) {
return ret;
}
/* Update sudo rule filter */
ret = update_filter(tctx, dinfo, tctx->sudo_rule_name,
tctx->update_sudo_rule_filter,
"(%s=%s)", TYPE_SUDO_RULE, false,
&tctx->sudo_rule_filter);
if (ret != EOK) {
return ret;
}
return EOK;
}
static bool invalidate_entries(TALLOC_CTX *ctx,
struct sss_domain_info *dinfo,
enum sss_cache_entry entry_type,
const char *filter, const char *name)
{
const char *attrs[] = {SYSDB_NAME, NULL};
size_t msg_count;
struct ldb_message **msgs;
const char *type_string = "unknown";
errno_t ret = EINVAL;
int i;
const char *c_name;
bool iret;
if (!filter) return false;
switch (entry_type) {
case TYPE_USER:
type_string = "user";
ret = sysdb_search_users(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
break;
case TYPE_GROUP:
type_string = "group";
ret = sysdb_search_groups(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
break;
case TYPE_NETGROUP:
type_string = "netgroup";
ret = sysdb_search_netgroups(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
break;
case TYPE_SERVICE:
type_string = "service";
ret = sysdb_search_services(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
break;
case TYPE_AUTOFSMAP:
type_string = "autofs map";
ret = search_autofsmaps(ctx, dinfo, filter, attrs, &msg_count, &msgs);
break;
case TYPE_SSH_HOST:
type_string = "ssh_host";
#ifdef BUILD_SSH
ret = sysdb_search_ssh_hosts(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
#else /* BUILD_SSH */
ret = ENOSYS;
#endif /* BUILD_SSH */
break;
case TYPE_SUDO_RULE:
type_string = "sudo_rule";
#ifdef BUILD_SUDO
ret = sysdb_search_sudo_rules(ctx, dinfo,
filter, attrs, &msg_count, &msgs);
#else /* BUILD_SUDO */
ret = ENOSYS;
#endif /* BUILD_SUDO */
break;
}
if (ret != EOK) {
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_FUNC, "'%s' %s: Not found in domain '%s'\n",
type_string, name ? name : "", dinfo->name);
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Searching for %s in domain %s with filter %s failed\n",
type_string, dinfo->name, filter);
}
return false;
}
iret = true;
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(SSSDBG_MINOR_FAILURE,
"Something bad happened, can't find attribute %s\n",
SYSDB_NAME);
ERROR("Couldn't invalidate %1$s\n", type_string);
iret = false;
} else {
ret = invalidate_entry(ctx, dinfo, c_name, entry_type);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Couldn't invalidate %s %s\n", type_string, c_name);
ERROR("Couldn't invalidate %1$s %2$s\n", type_string, c_name);
iret = false;
}
}
}
talloc_zfree(msgs);
return iret;
}
static errno_t invalidate_entry(TALLOC_CTX *ctx,
struct sss_domain_info *domain,
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:
/* For users, we also need to reset the initgroups
* cache expiry */
ret = sysdb_attrs_add_time_t(sys_attrs,
SYSDB_INITGR_EXPIRE, 1);
if (ret != EOK) return ret;
ret = sysdb_set_user_attr(domain, name, sys_attrs,
SYSDB_MOD_REP);
break;
case TYPE_GROUP:
ret = sysdb_set_group_attr(domain, name, sys_attrs,
SYSDB_MOD_REP);
break;
case TYPE_NETGROUP:
ret = sysdb_set_netgroup_attr(domain, name, sys_attrs,
SYSDB_MOD_REP);
break;
case TYPE_SERVICE:
ret = sysdb_set_service_attr(domain, name,
sys_attrs, SYSDB_MOD_REP);
break;
case TYPE_AUTOFSMAP:
ret = sysdb_set_autofsmap_attr(domain, name,
sys_attrs, SYSDB_MOD_REP);
break;
case TYPE_SSH_HOST:
#ifdef BUILD_SSH
ret = sysdb_set_ssh_host_attr(domain, name,
sys_attrs, SYSDB_MOD_REP);
#else /* BUILD_SSH */
ret = ENOSYS;
#endif /* BUILD_SSH */
break;
case TYPE_SUDO_RULE:
#ifdef BUILD_SUDO
ret = sysdb_set_sudo_rule_attr(domain, name,
sys_attrs, SYSDB_MOD_REP);
#else /* BUILD_SUDO */
ret = ENOSYS;
#endif /* BUILD_SUDO */
break;
default:
return EINVAL;
}
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not set entry attributes\n");
}
} else {
DEBUG(SSSDBG_MINOR_FAILURE,
"Could not add expiration time to attributes\n");
}
talloc_zfree(sys_attrs);
} else {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not create sysdb attributes\n");
ret = ENOMEM;
}
return ret;
}
static errno_t init_domains(struct cache_tool_ctx *ctx,
const char *domain)
{
char *confdb_path;
int ret;
struct sss_domain_info *dinfo;
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(SSSDBG_CRIT_FAILURE,
"Could not initialize connection to the confdb\n");
return ret;
}
if (domain) {
ret = sssd_domain_init(ctx, ctx->confdb,
domain, DB_PATH, &ctx->domains);
if (ret != EOK) {
SYSDB_VERSION_ERROR(ret);
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not initialize connection to the sysdb\n");
return ret;
}
} else {
ret = confdb_get_domains(ctx->confdb, &ctx->domains);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not initialize domains\n");
return ret;
}
ret = sysdb_init(ctx, ctx->domains);
SYSDB_VERSION_ERROR(ret);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not initialize connection to the sysdb\n");
return ret;
}
}
for (dinfo = ctx->domains; dinfo; dinfo = get_next_domain(dinfo, 0)) {
ret = sss_names_init(ctx, ctx->confdb, dinfo->name, &dinfo->names);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_names_init() failed\n");
return ret;
}
}
return EOK;
}
static errno_t init_context(int argc, const char *argv[],
struct cache_tool_ctx **tctx)
{
struct cache_tool_ctx *ctx = NULL;
int idb = INVALIDATE_NONE;
struct input_values values = { 0 };
int debug = SSSDBG_DEFAULT;
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 },
{ "everything", 'E', POPT_ARG_NONE, NULL, 'e',
_("Invalidate all cached entries"), NULL },
{ "user", 'u', POPT_ARG_STRING, &(values.user), 0,
_("Invalidate particular user"), NULL },
{ "users", 'U', POPT_ARG_NONE, NULL, 'u',
_("Invalidate all users"), NULL },
{ "group", 'g', POPT_ARG_STRING, &(values.group), 0,
_("Invalidate particular group"), NULL },
{ "groups", 'G', POPT_ARG_NONE, NULL, 'g',
_("Invalidate all groups"), NULL },
{ "netgroup", 'n', POPT_ARG_STRING, &(values.netgroup), 0,
_("Invalidate particular netgroup"), NULL },
{ "netgroups", 'N', POPT_ARG_NONE, NULL, 'n',
_("Invalidate all netgroups"), NULL },
{ "service", 's', POPT_ARG_STRING, &(values.service), 0,
_("Invalidate particular service"), NULL },
{ "services", 'S', POPT_ARG_NONE, NULL, 's',
_("Invalidate all services"), NULL },
#ifdef BUILD_AUTOFS
{ "autofs-map", 'a', POPT_ARG_STRING, &(values.map), 0,
_("Invalidate particular autofs map"), NULL },
{ "autofs-maps", 'A', POPT_ARG_NONE, NULL, 'a',
_("Invalidate all autofs maps"), NULL },
#endif /* BUILD_AUTOFS */
#ifdef BUILD_SSH
{ "ssh-host", 'h', POPT_ARG_STRING, &(values.ssh_host), 0,
_("Invalidate particular SSH host"), NULL },
{ "ssh-hosts", 'H', POPT_ARG_NONE, NULL, 'h',
_("Invalidate all SSH hosts"), NULL },
#endif /* BUILD_SSH */
#ifdef BUILD_SUDO
{ "sudo-rule", 'r', POPT_ARG_STRING, &(values.sudo_rule), 0,
_("Invalidate particular sudo rule"), NULL },
{ "sudo-rules", 'R', POPT_ARG_NONE, NULL, 'r',
_("Invalidate all cached sudo rules"), NULL },
#endif /* BUILD_SUDO */
{ "domain", 'd', POPT_ARG_STRING, &(values.domain), 0,
_("Only invalidate entries from a particular domain"), NULL },
POPT_TABLEEND
};
ret = set_locale();
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"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;
case 's':
idb |= INVALIDATE_SERVICES;
break;
case 'a':
idb |= INVALIDATE_AUTOFSMAPS;
break;
case 'h':
idb |= INVALIDATE_SSH_HOSTS;
break;
case 'r':
idb |= INVALIDATE_SUDO_RULES;
break;
case 'e':
idb = INVALIDATE_EVERYTHING;
#ifdef BUILD_SUDO
idb |= INVALIDATE_SUDO_RULES;
#endif /* BUILD_SUDO */
break;
}
}
DEBUG_CLI_INIT(debug);
debug_prg_name = argv[0];
if (ret != -1) {
BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
}
if (poptGetArg(pc)) {
BAD_POPT_PARAMS(pc,
_("Unexpected argument(s) provided, options that "
"invalidate a single object only accept a single "
"provided argument.\n"),
ret, fini);
}
if (idb == INVALIDATE_NONE && !values.user && !values.group &&
!values.netgroup && !values.service && !values.map &&
!values.ssh_host && !values.sudo_rule) {
BAD_POPT_PARAMS(pc,
_("Please select at least one object to invalidate\n"),
ret, fini);
}
CHECK_ROOT(ret, debug_prg_name);
ctx = talloc_zero(NULL, struct cache_tool_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"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);
ctx->update_user_filter = false;
} else if (values.user) {
ctx->user_name = talloc_strdup(ctx, values.user);
ctx->update_user_filter = true;
}
if (idb & INVALIDATE_GROUPS) {
ctx->group_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
ctx->update_group_filter = false;
} else if (values.group) {
ctx->group_name = talloc_strdup(ctx, values.group);
ctx->update_group_filter = true;
}
if (idb & INVALIDATE_NETGROUPS) {
ctx->netgroup_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
ctx->update_netgroup_filter = false;
} else if (values.netgroup) {
ctx->netgroup_name = talloc_strdup(ctx, values.netgroup);
ctx->update_netgroup_filter = true;
}
if (idb & INVALIDATE_SERVICES) {
ctx->service_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
ctx->update_service_filter = false;
} else if (values.service) {
ctx->service_name = talloc_strdup(ctx, values.service);
ctx->update_service_filter = true;
}
if (idb & INVALIDATE_AUTOFSMAPS) {
ctx->autofs_filter = talloc_asprintf(ctx, "(&(objectclass=%s)(%s=*))",
SYSDB_AUTOFS_MAP_OC, SYSDB_NAME);
ctx->update_autofs_filter = false;
} else if (values.map) {
ctx->autofs_name = talloc_strdup(ctx, values.map);
ctx->update_autofs_filter = true;
}
if (idb & INVALIDATE_SSH_HOSTS) {
ctx->ssh_host_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
ctx->update_ssh_host_filter = false;
} else if (values.ssh_host) {
ctx->ssh_host_name = talloc_strdup(ctx, values.ssh_host);
ctx->update_ssh_host_filter = true;
}
if (idb & INVALIDATE_SUDO_RULES) {
ctx->sudo_rule_filter = talloc_asprintf(ctx, "(%s=*)", SYSDB_NAME);
ctx->update_sudo_rule_filter = false;
} else if (values.sudo_rule) {
ctx->sudo_rule_name = talloc_strdup(ctx, values.sudo_rule);
ctx->update_sudo_rule_filter = true;
}
if (is_filter_valid(ctx, &values, idb) == false) {
DEBUG(SSSDBG_CRIT_FAILURE, "Construction of filters failed\n");
ret = ENOMEM;
goto fini;
}
ret = init_domains(ctx, values.domain);
if (ret != EOK) {
if (values.domain) {
ERROR("Could not open domain %1$s. If the domain is a subdomain "
"(trusted domain), use fully qualified name instead of "
"--domain/-d parameter.\n", values.domain);
} else {
ERROR("Could not open available domains\n");
}
DEBUG(SSSDBG_OP_FAILURE,
"Initialization of sysdb connections failed\n");
goto fini;
}
ret = EOK;
fini:
poptFreeContext(pc);
free_input_values(&values);
if (ret != EOK && ctx) {
talloc_zfree(ctx);
}
if (ret == EOK) {
*tctx = ctx;
}
return ret;
}
static bool is_filter_valid(struct cache_tool_ctx *ctx,
struct input_values *values, int idb)
{
if ((idb & INVALIDATE_USERS) && ctx->user_filter == NULL) {
return false;
}
if ((idb & INVALIDATE_GROUPS) && ctx->group_filter == NULL) {
return false;
}
if ((idb & INVALIDATE_NETGROUPS) && ctx->netgroup_filter == NULL) {
return false;
}
if ((idb & INVALIDATE_SERVICES) && ctx->service_filter == NULL) {
return false;
}
if ((idb & INVALIDATE_AUTOFSMAPS) && ctx->autofs_filter == NULL) {
return false;
}
if ((idb & INVALIDATE_SSH_HOSTS) && ctx->ssh_host_filter == NULL) {
return false;
}
if (values->user && ctx->user_name == NULL) {
return false;
}
if (values->group && ctx->group_name == NULL) {
return false;
}
if (values->netgroup && ctx->netgroup_name == NULL) {
return false;
}
if (values->service && ctx->service_name == NULL) {
return false;
}
if (values->map && ctx->autofs_name == NULL) {
return false;
}
if (values->ssh_host && ctx->ssh_host_name == NULL) {
return false;
}
if (values->sudo_rule && ctx->sudo_rule_name == NULL) {
return false;
}
return true;
}
static errno_t
search_autofsmaps(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *sub_filter, const char **attrs,
size_t *msgs_count, struct ldb_message ***msgs)
{
#ifdef BUILD_AUTOFS
return sysdb_search_custom(mem_ctx, domain, sub_filter,
AUTOFS_MAP_SUBDIR, attrs,
msgs_count, msgs);
#else
return ENOSYS;
#endif /* BUILD_AUTOFS */
}