diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
commit | 74aa0bc6779af38018a03fd2cf4419fe85917904 (patch) | |
tree | 9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/common/cache_req/plugins | |
parent | Initial commit. (diff) | |
download | sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip |
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/responder/common/cache_req/plugins')
31 files changed, 5393 insertions, 0 deletions
diff --git a/src/responder/common/cache_req/plugins/cache_req_autofs_entry_by_name.c b/src/responder/common/cache_req/plugins/cache_req_autofs_entry_by_name.c new file mode 100644 index 0000000..b2b0a06 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_autofs_entry_by_name.c @@ -0,0 +1,161 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2019 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_autofs.h" +#include "util/util.h" +#include "util/sss_chain_id.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_autofs_entry_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "%s:%s", + data->name.name, + data->autofs_entry_name); +} + +static errno_t +cache_req_autofs_entry_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + struct ldb_message *entry; + struct ldb_result *result; + errno_t ret; + + ret = sysdb_get_autofsentry(mem_ctx, domain, data->name.name, + data->autofs_entry_name, &entry); + if (ret != EOK) { + return ret; + } + + result = cache_req_create_ldb_result_from_msg(mem_ctx, entry); + if (result == NULL) { + talloc_free(entry); + return ENOMEM; + } + + *_result = talloc_steal(mem_ctx, result); + return EOK; +} + +static struct tevent_req * +cache_req_autofs_entry_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + struct be_conn *be_conn; + errno_t ret; + + ret = sss_dp_get_domain_conn(cr->rctx, domain->conn_name, &be_conn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "BUG: The Data Provider connection for %s is not available!\n", + domain->name); + return NULL; + } + + return sbus_call_dp_autofs_GetEntry_send(mem_ctx, be_conn->conn, + be_conn->bus_name, SSS_BUS_PATH, + 0, data->name.name, + data->autofs_entry_name, + sss_chain_id_get()); +} + +bool +cache_req_autofs_entry_by_name_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + errno_t ret; + + ret = sbus_call_dp_autofs_GetEntry_recv(subreq); + + if (ret == ERR_MISSING_DP_TARGET || ret == ENOENT) { + ret = EOK; + } + + return ret == EOK; +} + +const struct cache_req_plugin cache_req_autofs_entry_by_name = { + .name = "Get autofs entry", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_autofs_entry_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_autofs_entry_by_name_lookup, + .dp_send_fn = cache_req_autofs_entry_by_name_dp_send, + .dp_recv_fn = cache_req_autofs_entry_by_name_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_autofs_entry_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *mapname, + const char *entryname) +{ + struct cache_req_data *data; + + data = cache_req_data_autofs_entry(mem_ctx, CACHE_REQ_AUTOFS_ENTRY_BY_NAME, + mapname, entryname); + if (data == NULL) { + return NULL; + } + + cache_req_data_set_propogate_offline_status(data, true); + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c b/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c new file mode 100644 index 0000000..23b11b1 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c @@ -0,0 +1,155 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2019 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_autofs.h" +#include "util/util.h" +#include "util/sss_chain_id.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_autofs_map_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.name); +} + +static errno_t +cache_req_autofs_map_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + struct ldb_message *map; + struct ldb_result *result; + errno_t ret; + + ret = sysdb_get_map_byname(mem_ctx, domain, data->name.name, &map); + if (ret != EOK) { + return ret; + } + + result = cache_req_create_ldb_result_from_msg(mem_ctx, map); + if (result == NULL) { + talloc_free(map); + return ENOMEM; + } + + *_result = talloc_steal(mem_ctx, result); + return EOK; +} + +static struct tevent_req * +cache_req_autofs_map_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + struct be_conn *be_conn; + errno_t ret; + + ret = sss_dp_get_domain_conn(cr->rctx, domain->conn_name, &be_conn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "BUG: The Data Provider connection for %s is not available!\n", + domain->name); + return NULL; + } + + return sbus_call_dp_autofs_GetMap_send(mem_ctx, be_conn->conn, + be_conn->bus_name, SSS_BUS_PATH, + 0, data->name.name, + sss_chain_id_get()); +} + +bool +cache_req_autofs_map_by_name_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + errno_t ret; + + ret = sbus_call_dp_autofs_GetMap_recv(subreq); + + if (ret == ERR_MISSING_DP_TARGET || ret == ENOENT) { + ret = EOK; + } + + return ret == EOK; +} + +const struct cache_req_plugin cache_req_autofs_map_by_name = { + .name = "Get autofs map", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_autofs_map_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_autofs_map_by_name_lookup, + .dp_send_fn = cache_req_autofs_map_by_name_dp_send, + .dp_recv_fn = cache_req_autofs_map_by_name_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_autofs_map_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_AUTOFS_MAP_BY_NAME, name); + if (data == NULL) { + return NULL; + } + + cache_req_data_set_propogate_offline_status(data, true); + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_autofs_map_entries.c b/src/responder/common/cache_req/plugins/cache_req_autofs_map_entries.c new file mode 100644 index 0000000..18c08ca --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_autofs_map_entries.c @@ -0,0 +1,187 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2019 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_autofs.h" +#include "util/util.h" +#include "util/sss_chain_id.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_autofs_map_entries_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.name); +} + +static errno_t +cache_req_autofs_map_entries_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_message *map; + struct ldb_message **mounts; + struct ldb_message **msgs; + struct ldb_result *result; + size_t count; + size_t i; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sysdb_get_map_byname(tmp_ctx, domain, data->name.name, &map); + if (ret != EOK) { + goto done; + } + + ret = sysdb_autofs_entries_by_map(tmp_ctx, domain, data->name.name, + &count, &mounts); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + msgs = talloc_zero_array(tmp_ctx, struct ldb_message *, count + 1); + if (msgs == NULL) { + ret = ENOMEM; + goto done; + } + + msgs[0] = talloc_steal(msgs, map); + for (i = 0; i < count; i++) { + msgs[i + 1] = talloc_steal(msgs, mounts[i]); + } + + result = cache_req_create_ldb_result_from_msg_list(tmp_ctx, msgs, count + 1); + if (result == NULL) { + ret = ENOMEM; + goto done; + } + + *_result = talloc_steal(mem_ctx, result); + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +static struct tevent_req * +cache_req_autofs_map_entries_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + struct be_conn *be_conn; + errno_t ret; + + ret = sss_dp_get_domain_conn(cr->rctx, domain->conn_name, &be_conn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "BUG: The Data Provider connection for %s is not available!\n", + domain->name); + return NULL; + } + + return sbus_call_dp_autofs_Enumerate_send(mem_ctx, be_conn->conn, + be_conn->bus_name, SSS_BUS_PATH, + 0, data->name.name, + sss_chain_id_get()); +} + +bool +cache_req_autofs_map_entries_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + errno_t ret; + + ret = sbus_call_dp_autofs_Enumerate_recv(subreq); + + if (ret == ERR_MISSING_DP_TARGET || ret == ENOENT) { + ret = EOK; + } + + return ret == EOK; +} + +const struct cache_req_plugin cache_req_autofs_map_entries = { + .name = "Get autofs entries", + .attr_expiration = SYSDB_ENUM_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_autofs_map_entries_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_autofs_map_entries_lookup, + .dp_send_fn = cache_req_autofs_map_entries_dp_send, + .dp_recv_fn = cache_req_autofs_map_entries_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_autofs_map_entries_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_AUTOFS_MAP_ENTRIES, name); + if (data == NULL) { + return NULL; + } + + cache_req_data_set_propogate_offline_status(data, true); + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_common.c b/src/responder/common/cache_req/plugins/cache_req_common.c new file mode 100644 index 0000000..7eb0921 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_common.c @@ -0,0 +1,192 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +errno_t cache_req_idminmax_check(struct cache_req_data *data, + struct sss_domain_info *domain) +{ + if (((domain->id_min != 0) && (data->id < domain->id_min)) || + ((domain->id_max != 0) && (data->id > domain->id_max))) { + DEBUG(SSSDBG_FUNC_DATA, "id exceeds min/max boundaries\n"); + return ERR_ID_OUTSIDE_RANGE; + } + return EOK; +} + +static struct ldb_message * +cache_req_well_known_sid_msg(TALLOC_CTX *mem_ctx, + const char *sid, + const char *name) +{ + struct ldb_message *msg; + const char *dup_sid; + const char *dup_name; + int ldberr; + + msg = ldb_msg_new(NULL); + if (msg == NULL) { + return NULL; + } + + dup_sid = talloc_strdup(msg, sid); + if (dup_sid == NULL) { + ldberr = LDB_ERR_OTHER; + goto done; + } + + dup_name = talloc_strdup(msg, name); + if (name == NULL) { + ldberr = LDB_ERR_OTHER; + goto done; + } + + ldberr = ldb_msg_add_string(msg, SYSDB_OBJECTCATEGORY, SYSDB_GROUP_CLASS); + if (ldberr != LDB_SUCCESS) { + goto done; + } + + ldberr = ldb_msg_add_string(msg, SYSDB_NAME, dup_name); + if (ldberr != LDB_SUCCESS) { + goto done; + } + + ldberr = ldb_msg_add_string(msg, SYSDB_SID_STR, dup_sid); + if (ldberr != LDB_SUCCESS) { + goto done; + } + +done: + if (ldberr != LDB_SUCCESS) { + talloc_free(msg); + return NULL; + } + + return msg; +} + +struct cache_req_result * +cache_req_well_known_sid_result(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + const char *domname, + const char *sid, + const char *name) +{ + struct cache_req_result *result; + struct sss_domain_info *domain; + struct ldb_message *msg; + + msg = cache_req_well_known_sid_msg(NULL, sid, name); + if (msg == NULL) { + return NULL; + } + + if (domname != NULL) { + domain = find_domain_by_name(cr->rctx->domains, domname, true); + } else { + domain = NULL; + } + + result = cache_req_create_result_from_msg(mem_ctx, domain, msg, + name, domname); + if (result == NULL) { + talloc_free(msg); + } + + return result; +} + +bool +cache_req_common_process_dp_reply(struct cache_req *cr, + errno_t ret, + uint16_t err_maj, + uint32_t err_min, + const char *err_msg) +{ + bool bret; + + if (ret != EOK) { + CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr, + "Could not get account info [%d]: %s\n", + ret, sss_strerror(ret)); + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, + "Due to an error we will return cached data\n"); + + bret = false; + goto done; + } + + if (err_maj) { + CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr, + "Data Provider Error: %u, %u, %s\n", + (unsigned int)err_maj, (unsigned int)err_min, err_msg); + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, + "Due to an error we will return cached data\n"); + + bret = false; + goto done; + } + + bret = true; + +done: + return bret; +} + +bool +cache_req_common_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + const char *err_msg; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + bool bret; + + /* Use subreq as memory context so err_msg is freed with it. */ + ret = sss_dp_get_account_recv(subreq, subreq, &err_maj, &err_min, &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +errno_t +cache_req_common_get_acct_domain_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *subreq, + struct cache_req *cr, + char **_domain) +{ + errno_t ret; + + ret = sss_dp_get_account_domain_recv(mem_ctx, subreq, _domain); + if (ret != EOK) { + CACHE_REQ_DEBUG(SSSDBG_MINOR_FAILURE, cr, + "Could not get account domain [%d]: %s\n", + ret, sss_strerror(ret)); + } + return ret; +} diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_groups.c b/src/responder/common/cache_req/plugins/cache_req_enum_groups.c new file mode 100644 index 0000000..a0d1028 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_enum_groups.c @@ -0,0 +1,93 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_enum_groups_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, "Groups enumeration"); +} + +static errno_t +cache_req_enum_groups_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_enumgrent_with_views(mem_ctx, domain, _result); +} + +static struct tevent_req * +cache_req_enum_groups_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_GROUP, NULL, 0, NULL); +} + +static errno_t +cache_req_enum_groups_ncache_filter(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + const char *name) +{ + return sss_ncache_check_group(ncache, domain, name); +} + +const struct cache_req_plugin cache_req_enum_groups = { + .name = "Enumerate groups", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = true, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_enum_groups_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = cache_req_enum_groups_ncache_filter, + .lookup_fn = cache_req_enum_groups_lookup, + .dp_send_fn = cache_req_enum_groups_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c new file mode 100644 index 0000000..ae468b3 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c @@ -0,0 +1,126 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_iphosts.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_enum_host_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, "IP hosts enumeration"); +} + +static errno_t +cache_req_enum_host_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_enumhostent(mem_ctx, domain, _result); +} + +static struct tevent_req * +cache_req_enum_host_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_HOST, BE_FILTER_ENUM, NULL); +} + +static bool +cache_req_enum_host_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_enum_ip_hosts = { + .name = "Enumerate IP hosts", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = true, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_enum_host_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_enum_host_lookup, + .dp_send_fn = cache_req_enum_host_dp_send, + .dp_recv_fn = cache_req_enum_host_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_enum_ip_hosts_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain) +{ + struct cache_req_data *data; + + data = cache_req_data_enum(mem_ctx, CACHE_REQ_ENUM_HOST); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c new file mode 100644 index 0000000..e03bf6a --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c @@ -0,0 +1,126 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2020 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_ipnetworks.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_enum_ip_networks_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, "IP networks enumeration"); +} + +static errno_t +cache_req_enum_ip_networks_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_enumnetent(mem_ctx, domain, _result); +} + +static struct tevent_req * +cache_req_enum_ip_networks_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_IP_NETWORK, BE_FILTER_ENUM, NULL); +} + +static bool +cache_req_enum_ip_networks_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_enum_ip_networks = { + .name = "Enumerate IP networks", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = true, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_enum_ip_networks_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_enum_ip_networks_lookup, + .dp_send_fn = cache_req_enum_ip_networks_dp_send, + .dp_recv_fn = cache_req_enum_ip_networks_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_enum_ip_networks_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain) +{ + struct cache_req_data *data; + + data = cache_req_data_enum(mem_ctx, CACHE_REQ_ENUM_IP_NETWORK); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c new file mode 100644 index 0000000..282dc1c --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c @@ -0,0 +1,106 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_services.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_enum_svc_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, "Services enumeration"); +} + +static errno_t +cache_req_enum_svc_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_enumservent(mem_ctx, domain, _result); +} + +static struct tevent_req * +cache_req_enum_svc_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_SERVICES, NULL, 0, NULL); +} + +const struct cache_req_plugin cache_req_enum_svc = { + .name = "Enumerate services", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = true, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_enum_svc_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_enum_svc_lookup, + .dp_send_fn = cache_req_enum_svc_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_enum_svc_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain) +{ + struct cache_req_data *data; + + data = cache_req_data_enum(mem_ctx, CACHE_REQ_ENUM_SVC); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_users.c b/src/responder/common/cache_req/plugins/cache_req_enum_users.c new file mode 100644 index 0000000..87da79f --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_enum_users.c @@ -0,0 +1,93 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_enum_users_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, "Users enumeration"); +} + +static errno_t +cache_req_enum_users_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_enumpwent_with_views(mem_ctx, domain, _result); +} + +static struct tevent_req * +cache_req_enum_users_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER, NULL, 0, NULL); +} + +static errno_t +cache_req_enum_users_ncache_filter(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + const char *name) +{ + return sss_ncache_check_user(ncache, domain, name); +} + +const struct cache_req_plugin cache_req_enum_users = { + .name = "Enumerate users", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = true, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_enum_users_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = cache_req_enum_users_ncache_filter, + .lookup_fn = cache_req_enum_users_lookup, + .dp_send_fn = cache_req_enum_users_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c new file mode 100644 index 0000000..1292f18 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c @@ -0,0 +1,171 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_group_by_filter_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_group_by_filter_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_group_by_filter_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + char *recent_filter; + errno_t ret; + + /* The "files" provider updates the record if /etc/passwd or /etc/group + * is touched. It does not perform any per-request update. + * Therefore the last update flag is not updated if no file was touched + * and we cannot use this optimization. + */ + if (is_files_provider(domain)) { + recent_filter = NULL; + } else { + recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", SYSDB_LAST_UPDATE, + cr->req_start); + if (recent_filter == NULL) { + return ENOMEM; + } + } + + ret = sysdb_enumgrent_filter_with_views(mem_ctx, domain, data->name.lookup, + recent_filter, _result); + talloc_free(recent_filter); + + return ret; +} + +static struct tevent_req * +cache_req_group_by_filter_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_WILDCARD_GROUP, + cr->data->name.lookup, cr->data->id, NULL); +} + +const struct cache_req_plugin cache_req_group_by_filter = { + .name = "Group by filter", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_group_by_filter_prepare_domain_data, + .create_debug_name_fn = cache_req_group_by_filter_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_group_by_filter_lookup, + .dp_send_fn = cache_req_group_by_filter_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *filter) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_GROUP_BY_FILTER, filter); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL, + 0, + req_dom_type, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_id.c b/src/responder/common/cache_req/plugins/cache_req_group_by_id.c new file mode 100644 index 0000000..bb72ad9 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_id.c @@ -0,0 +1,246 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_group_by_id_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "GID:%"PRIu32"@%s", data->id, domain->name); +} + +static errno_t +cache_req_group_by_id_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + if (domain != NULL) { + ret = sss_ncache_check_gid(ncache, domain, data->id); + if (ret == EEXIST) { + return ret; + } + } + + return sss_ncache_check_gid(ncache, NULL, data->id); +} + +static errno_t +cache_req_group_by_id_ncache_filter(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + const char *name) +{ + return sss_ncache_check_group(ncache, domain, name); +} + +static errno_t +cache_req_group_by_id_global_ncache_add(struct sss_nc_ctx *ncache, + struct cache_req_data *data) +{ + return sss_ncache_set_gid(ncache, false, NULL, data->id); +} + +static errno_t +cache_req_group_by_id_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_gid(ncache, false, domain, data->id); +} + +static errno_t +cache_req_group_by_id_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + errno_t ret; + + ret = cache_req_idminmax_check(data, domain); + if (ret != EOK) { + return ret; + } + return sysdb_getgrgid_with_views(mem_ctx, domain, data->id, _result); +} + +static errno_t +cache_req_group_by_id_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) +{ + uint32_t id; + + *_id = cr->data->id; + *_string = NULL; + *_flag = NULL; + + if (!DOM_HAS_VIEWS(cr->domain)) { + return EOK; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* If domain has views we will try to use original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_GIDNUM, 0); + if (id == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* Now we have the original name and id. We don't have to search with + * views unless some error occurred. */ + *_id = id; + + return EOK; +} + +static struct tevent_req * +cache_req_group_by_id_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + const char *string; + const char *flag; + uint32_t id; + errno_t ret; + + ret = cache_req_group_by_id_dpreq_params(mem_ctx, cr, result, + &string, &id, &flag); + if (ret != EOK) { + return NULL; + } + + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_GROUP, string, id, flag); +} + +static bool +cache_req_group_by_id_get_domain_check(struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_check_locate_gid(rctx->ncache, domain, data->id); + if (nret == EEXIST) { + return false; + } + + return true; +} + +static struct tevent_req * +cache_req_group_by_id_get_domain_send(TALLOC_CTX *mem_ctx, + struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_set_locate_gid(rctx->ncache, domain, data->id); + if (nret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set negative cache, this might result in performance degradation\n"); + /* Not fatal */ + } + + return sss_dp_get_account_domain_send(mem_ctx, + rctx, + domain, + true, /* fast_reply */ + SSS_DP_GROUP, + data->id, + NULL); +} + +const struct cache_req_plugin cache_req_group_by_id = { + .name = "Group by ID", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_group_by_id_create_debug_name, + .global_ncache_add_fn = cache_req_group_by_id_global_ncache_add, + .ncache_check_fn = cache_req_group_by_id_ncache_check, + .ncache_add_fn = cache_req_group_by_id_ncache_add, + .ncache_filter_fn = cache_req_group_by_id_ncache_filter, + .lookup_fn = cache_req_group_by_id_lookup, + .dp_send_fn = cache_req_group_by_id_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = cache_req_group_by_id_get_domain_check, + .dp_get_domain_send_fn = cache_req_group_by_id_get_domain_send, + .dp_get_domain_recv_fn = cache_req_common_get_acct_domain_recv, +}; + +struct tevent_req * +cache_req_group_by_id_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + gid_t gid) +{ + struct cache_req_data *data; + + data = cache_req_data_id(mem_ctx, CACHE_REQ_GROUP_BY_ID, gid); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c new file mode 100644 index 0000000..3be0d5e --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c @@ -0,0 +1,227 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_group_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_create_internal_fqname(tmp_ctx, name, domain->name); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_group_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_group_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_group(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_group_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_group(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_group_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getgrnam_with_views(mem_ctx, domain, data->name.lookup, + _result); +} + +static errno_t +cache_req_group_by_name_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) +{ + const char *name; + + *_id = 0; + *_string = cr->data->name.lookup; + *_flag = NULL; + + if (!DOM_HAS_VIEWS(cr->domain)) { + return EOK; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* If domain has views we will try to use original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* Now we have the original name and id. We don't have to search with + * views unless some error occurred. */ + *_string = talloc_steal(mem_ctx, name); + + return EOK; +} + +static struct tevent_req * +cache_req_group_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + const char *string; + const char *flag; + uint32_t id; + errno_t ret; + + ret = cache_req_group_by_name_dpreq_params(mem_ctx, cr, result, + &string, &id, &flag); + if (ret != EOK) { + return NULL; + } + + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_GROUP, string, id, flag); +} + +const struct cache_req_plugin cache_req_group_by_name = { + .name = "Group by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_group_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_group_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_group_by_name_ncache_check, + .ncache_add_fn = cache_req_group_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_group_by_name_lookup, + .dp_send_fn = cache_req_group_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + req_dom_type, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c new file mode 100644 index 0000000..c5bea9d --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c @@ -0,0 +1,242 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_initgroups_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_create_internal_fqname(tmp_ctx, name, domain->name); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_initgroups_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_user(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_user(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_initgroups_with_views(mem_ctx, domain, data->name.lookup, + _result); +} + +static errno_t +cache_req_initgroups_by_name_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) +{ + struct ldb_result *user; + const char *name; + errno_t ret; + + *_id = 0; + *_string = cr->data->name.lookup; + *_flag = NULL; + + if (!DOM_HAS_VIEWS(cr->domain)) { + return EOK; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* If domain has views we will try to use original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + ret = sysdb_getpwnam_with_views(NULL, cr->domain, + cr->data->name.lookup, &user); + if (ret != EOK || user == NULL || user->count != 1) { + /* Case where the user is not found has been already handled. If + * this is not OK, it is an error. */ + CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr, + "Unable to match initgroups user [%d]: %s\n", + ret, sss_strerror(ret)); + return ret; + } + + name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME, NULL); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); + talloc_free(user); + return ERR_INTERNAL; + } + + /* Now we have the original name. We don't have to search with + * views unless some error occurred. */ + *_string = talloc_steal(mem_ctx, name); + + talloc_free(user); + + return EOK; +} + +static struct tevent_req * +cache_req_initgroups_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + const char *string; + const char *flag; + uint32_t id; + errno_t ret; + + ret = cache_req_initgroups_by_name_dpreq_params(mem_ctx, cr, result, + &string, &id, &flag); + if (ret != EOK) { + return NULL; + } + + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_INITGROUPS, string, id, flag); +} + +const struct cache_req_plugin cache_req_initgroups_by_name = { + .name = "Initgroups by name", + .attr_expiration = SYSDB_INITGR_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = true, + .upn_equivalent = CACHE_REQ_INITGROUPS_BY_UPN, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_initgroups_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_initgroups_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_initgroups_by_name_ncache_check, + .ncache_add_fn = cache_req_initgroups_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_initgroups_by_name_lookup, + .dp_send_fn = cache_req_initgroups_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_INITGROUPS, name); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + req_dom_type, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_upn.c b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_upn.c new file mode 100644 index 0000000..9bd00f3 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_upn.c @@ -0,0 +1,130 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_initgroups_by_upn_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *name; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed UPN is NULL?\n"); + return ERR_INTERNAL; + } + + /* When looking up UPNs we don't want to reverse-replace spaces, + * just search whatever the user passed in. strdup the name so we + * can safely steal it later. + */ + name = talloc_strdup(data, cr->data->name.name); + if (name == NULL) { + return ENOMEM; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + return EOK; +} + +static const char * +cache_req_initgroups_by_upn_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_upn_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_upn(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_upn_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_upn(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_initgroups_by_upn_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_initgroups_by_upn(mem_ctx, domain, data->name.lookup, + _result); +} + +static struct tevent_req * +cache_req_initgroups_by_upn_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_INITGROUPS, cr->data->name.lookup, + 0, EXTRA_NAME_IS_UPN); +} + +const struct cache_req_plugin cache_req_initgroups_by_upn = { + .name = "Initgroups by UPN", + .attr_expiration = SYSDB_INITGR_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_initgroups_by_upn_prepare_domain_data, + .create_debug_name_fn = cache_req_initgroups_by_upn_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_initgroups_by_upn_ncache_check, + .ncache_add_fn = cache_req_initgroups_by_upn_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_initgroups_by_upn_lookup, + .dp_send_fn = cache_req_initgroups_by_upn_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c new file mode 100644 index 0000000..324d20e --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c @@ -0,0 +1,174 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> +#include <arpa/inet.h> + +#include "db/sysdb.h" +#include "db/sysdb_iphosts.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_ip_host_by_addr_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + char buf[INET6_ADDRSTRLEN]; + const char *addr; + + if (data->addr.len == 0 || data->addr.data == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: address is NULL?\n"); + return ERR_INTERNAL; + } + + if (data->addr.af != AF_INET && data->addr.af != AF_INET6) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bad address family [%d]\n", data->addr.af); + return EAFNOSUPPORT; + } + + addr = inet_ntop(data->addr.af, data->addr.data, buf, INET6_ADDRSTRLEN); + if (addr == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse address: %s\n", + strerror(errno)); + return ERR_INTERNAL; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_strdup(data, addr); + + return EOK; +} + +static const char * +cache_req_ip_host_by_addr_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *addr = NULL; + char buf[INET6_ADDRSTRLEN]; + + addr = inet_ntop(data->addr.af, data->addr.data, buf, INET6_ADDRSTRLEN); + if (addr == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse network address: %s\n", + strerror(errno)); + return NULL; + } + + return talloc_strdup(mem_ctx, addr); +} + +static errno_t +cache_req_ip_host_by_addr_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_gethostbyaddr(mem_ctx, domain, data->name.lookup, + _result); +} + +static struct tevent_req * +cache_req_ip_host_by_addr_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_HOST, BE_FILTER_ADDR, + data->name.lookup); +} + +static bool +cache_req_ip_host_by_addr_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_ip_host_by_addr = { + .name = "IP host by address", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_ip_host_by_addr_prepare_domain_data, + .create_debug_name_fn = cache_req_ip_host_by_addr_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_ip_host_by_addr_lookup, + .dp_send_fn = cache_req_ip_host_by_addr_dp_send, + .dp_recv_fn = cache_req_ip_host_by_addr_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_ip_host_by_addr_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_IP_HOST_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c new file mode 100644 index 0000000..b5f33ee --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c @@ -0,0 +1,170 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_iphosts.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_ip_host_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* Host names always case insensitive */ + name = sss_get_cased_name(tmp_ctx, data->name.name, false); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_ip_host_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *name = data->name.lookup; + + return talloc_asprintf(mem_ctx, "%s@%s", name, domain->name); +} + +static errno_t +cache_req_ip_host_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_gethostbyname(mem_ctx, domain, data->name.lookup, + _result); +} + +static struct tevent_req * +cache_req_ip_host_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_HOST, BE_FILTER_NAME, + data->name.lookup); +} + +static bool +cache_req_ip_host_by_name_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_ip_host_by_name = { + .name = "IP host by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_ip_host_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_ip_host_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_ip_host_by_name_lookup, + .dp_send_fn = cache_req_ip_host_by_name_dp_send, + .dp_recv_fn = cache_req_ip_host_by_name_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_ip_host_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_IP_HOST_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c new file mode 100644 index 0000000..0ad7f61 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c @@ -0,0 +1,174 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2020 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> +#include <arpa/inet.h> + +#include "db/sysdb.h" +#include "db/sysdb_ipnetworks.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_ip_network_by_addr_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + char buf[INET6_ADDRSTRLEN]; + const char *addr; + + if (data->addr.len == 0 || data->addr.data == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: address is NULL?\n"); + return ERR_INTERNAL; + } + + if (data->addr.af != AF_INET && data->addr.af != AF_INET6) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bad address family [%d]\n", data->addr.af); + return EAFNOSUPPORT; + } + + addr = inet_ntop(data->addr.af, data->addr.data, buf, INET6_ADDRSTRLEN); + if (addr == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse address: %s\n", + strerror(errno)); + return ERR_INTERNAL; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_strdup(data, addr); + + return EOK; +} + +static const char * +cache_req_ip_network_by_addr_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *addr = NULL; + char buf[INET6_ADDRSTRLEN]; + + addr = inet_ntop(data->addr.af, data->addr.data, buf, INET6_ADDRSTRLEN); + if (addr == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse network address: %s\n", + strerror(errno)); + return NULL; + } + + return talloc_strdup(mem_ctx, addr); +} + +static errno_t +cache_req_ip_network_by_addr_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getipnetworkbyaddr(mem_ctx, domain, data->name.lookup, + _result); +} + +static struct tevent_req * +cache_req_ip_network_by_addr_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_IP_NETWORK, BE_FILTER_ADDR, + data->name.lookup); +} + +static bool +cache_req_ip_network_by_addr_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_ip_network_by_addr = { + .name = "IP network by address", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_ip_network_by_addr_prepare_domain_data, + .create_debug_name_fn = cache_req_ip_network_by_addr_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_ip_network_by_addr_lookup, + .dp_send_fn = cache_req_ip_network_by_addr_dp_send, + .dp_recv_fn = cache_req_ip_network_by_addr_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_ip_network_by_addr_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_IP_NETWORK_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c new file mode 100644 index 0000000..c02bc06 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c @@ -0,0 +1,170 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2020 SUSE LINUX GmbH, Nuernberg, Germany. + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_ipnetworks.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_ip_network_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* Network names always case insensitive */ + name = sss_get_cased_name(tmp_ctx, data->name.name, false); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_ip_network_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *name = data->name.lookup; + + return talloc_asprintf(mem_ctx, "%s@%s", name, domain->name); +} + +static errno_t +cache_req_ip_network_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getipnetworkbyname(mem_ctx, domain, data->name.lookup, + _result); +} + +static struct tevent_req * +cache_req_ip_network_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_resolver_get_send(mem_ctx, cr->rctx, domain, true, + BE_REQ_IP_NETWORK, BE_FILTER_NAME, + data->name.lookup); +} + +static bool +cache_req_ip_network_by_name_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + bool bret; + uint16_t err_maj; + uint32_t err_min; + errno_t ret; + const char *err_msg; + + ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, + &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_ip_network_by_name = { + .name = "IP network by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_ip_network_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_ip_network_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_ip_network_by_name_lookup, + .dp_send_fn = cache_req_ip_network_by_name_dp_send, + .dp_recv_fn = cache_req_ip_network_by_name_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_ip_network_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_IP_NETWORK_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c new file mode 100644 index 0000000..d370d34 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c @@ -0,0 +1,160 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_netgroup_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_netgroup_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "%s@%s", data->name.lookup, domain->name); +} + +static errno_t +cache_req_netgroup_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_netgr(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_netgroup_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_netgr(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_netgroup_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getnetgr(mem_ctx, domain, data->name.lookup, _result); +} + +static struct tevent_req * +cache_req_netgroup_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_NETGR, cr->data->name.lookup, + 0, NULL); +} + +const struct cache_req_plugin cache_req_netgroup_by_name = { + .name = "Netgroup by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_netgroup_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_netgroup_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_netgroup_by_name_ncache_check, + .ncache_add_fn = cache_req_netgroup_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_netgroup_by_name_lookup, + .dp_send_fn = cache_req_netgroup_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_netgroup_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_NETGROUP_BY_NAME, name); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_id.c b/src/responder/common/cache_req/plugins/cache_req_object_by_id.c new file mode 100644 index 0000000..2bff990 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_object_by_id.c @@ -0,0 +1,236 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_object_by_id_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "ID:%"PRIu32"@%s", data->id, domain->name); +} + +static errno_t +cache_req_object_by_id_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + ret = sss_ncache_check_uid(ncache, domain, data->id); + if (ret == EEXIST) { + ret = sss_ncache_check_gid(ncache, domain, data->id); + } + + return ret; +} + +static errno_t +cache_req_object_by_id_ncache_filter(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + const char *name) +{ + errno_t ret; + + ret = sss_ncache_check_user(ncache, domain, name); + if (ret == EEXIST) { + ret = sss_ncache_check_group(ncache, domain, name); + } + + return ret; +} + +static errno_t +cache_req_object_by_id_global_ncache_add(struct sss_nc_ctx *ncache, + struct cache_req_data *data) +{ + errno_t ret; + + ret = sss_ncache_set_uid(ncache, false, NULL, data->id); + if (ret != EOK) { + return ret; + } + + ret = sss_ncache_set_gid(ncache, false, NULL, data->id); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +static errno_t +cache_req_object_by_id_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + ret = sss_ncache_set_uid(ncache, false, domain, data->id); + if (ret != EOK) { + return ret; + } + + ret = sss_ncache_set_gid(ncache, false, domain, data->id); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +static errno_t +cache_req_object_by_id_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + errno_t ret; + + ret = cache_req_idminmax_check(data, domain); + if (ret != EOK) { + return ret; + } + return sysdb_search_object_by_id(mem_ctx, domain, data->id, + data->attrs, _result); +} + +static struct tevent_req * +cache_req_object_by_id_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER_AND_GROUP, NULL, + cr->data->id, NULL); +} + +static bool +cache_req_object_by_id_get_domain_check(struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_check_locate_uid(rctx->ncache, domain, data->id); + if (nret == EEXIST) { + nret = sss_ncache_check_locate_gid(rctx->ncache, domain, data->id); + if (nret == EEXIST) { + return false; + } + } + + return true; +} + +static struct tevent_req * +cache_req_object_by_id_get_domain_send(TALLOC_CTX *mem_ctx, + struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_set_locate_uid(rctx->ncache, domain, data->id); + if (nret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set negative cache, this might result in " + "performance degradation\n"); + /* Not fatal */ + } + + nret = sss_ncache_set_locate_gid(rctx->ncache, domain, data->id); + if (nret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set negative cache, this might result in " + "performance degradation\n"); + /* Not fatal */ + } + + return sss_dp_get_account_domain_send(mem_ctx, + rctx, + domain, + true, /* fast_reply */ + SSS_DP_USER_AND_GROUP, + data->id, + NULL); +} + +const struct cache_req_plugin cache_req_object_by_id = { + .name = "Object by ID", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_object_by_id_create_debug_name, + .global_ncache_add_fn = cache_req_object_by_id_global_ncache_add, + .ncache_check_fn = cache_req_object_by_id_ncache_check, + .ncache_add_fn = cache_req_object_by_id_ncache_add, + .ncache_filter_fn = cache_req_object_by_id_ncache_filter, + .lookup_fn = cache_req_object_by_id_lookup, + .dp_send_fn = cache_req_object_by_id_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = cache_req_object_by_id_get_domain_check, + .dp_get_domain_send_fn = cache_req_object_by_id_get_domain_send, + .dp_get_domain_recv_fn = cache_req_common_get_acct_domain_recv, +}; + +struct tevent_req * +cache_req_object_by_id_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + uint32_t id, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_id_attrs(mem_ctx, CACHE_REQ_OBJECT_BY_ID, id, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c new file mode 100644 index 0000000..907f1f3 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c @@ -0,0 +1,238 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_object_by_name_well_known(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct cache_req_result **_result) +{ + struct cache_req_result *result; + const char *sid; + char *domname; + char *name; + errno_t ret; + + ret = sss_parse_name(mem_ctx, cr->rctx->global_names, + data->name.input, &domname, &name); + if (ret != EOK) { + CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "Unable to parse name " + "[%d]: %s\n", ret, sss_strerror(ret)); + return ret; + } + + if (domname == NULL || name == NULL) { + CACHE_REQ_DEBUG(SSSDBG_FUNC_DATA, cr, "Unable to split [%s] in " + "name and domain part. Skipping detection of " + "well-known name.\n", data->name.input); + return ENOENT; + } + + ret = name_to_well_known_sid(domname, name, &sid); + if (ret != EOK) { + return ret; + } + + result = cache_req_well_known_sid_result(mem_ctx, cr, domname, sid, name); + talloc_free(domname); + talloc_free(name); + if (result == NULL) { + return ENOMEM; + } + + *_result = result; + + return EOK; +} + +static errno_t +cache_req_object_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_create_internal_fqname(tmp_ctx, name, domain->name); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_object_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_object_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + ret = sss_ncache_check_user(ncache, domain, data->name.lookup); + if (ret == EEXIST) { + ret = sss_ncache_check_group(ncache, domain, data->name.lookup); + } + + return ret; +} + +static errno_t +cache_req_object_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + ret = sss_ncache_set_user(ncache, false, domain, data->name.lookup); + if (ret != EOK) { + return ret; + } + + ret = sss_ncache_set_group(ncache, false, domain, data->name.lookup); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +static errno_t +cache_req_object_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_search_object_by_name(mem_ctx, domain, data->name.lookup, + data->attrs, _result); +} + +static struct tevent_req * +cache_req_object_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER_AND_GROUP, + cr->data->name.lookup, 0, NULL); +} + +const struct cache_req_plugin cache_req_object_by_name = { + .name = "Object by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = true, + .upn_equivalent = CACHE_REQ_USER_BY_UPN, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = cache_req_object_by_name_well_known, + .prepare_domain_data_fn = cache_req_object_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_object_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_object_by_name_ncache_check, + .ncache_add_fn = cache_req_object_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_object_by_name_lookup, + .dp_send_fn = cache_req_object_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_object_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_OBJECT_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c b/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c new file mode 100644 index 0000000..db731b1 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c @@ -0,0 +1,202 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_object_by_sid_well_known(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct cache_req_result **_result) +{ + struct cache_req_result *result; + const char *domname; + const char *name; + errno_t ret; + + ret = well_known_sid_to_name(data->sid, &domname, &name); + if (ret != EOK) { + CACHE_REQ_DEBUG(SSSDBG_TRACE_ALL, cr, + "SID [%s] is not a Well-Known SID.\n", data->sid); + return ret; + } + + result = cache_req_well_known_sid_result(mem_ctx, cr, domname, + data->sid, name); + if (result == NULL) { + return ENOMEM; + } + + *_result = result; + + return EOK; +} + +static const char * +cache_req_object_by_sid_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "SID:%s@%s", data->sid, domain->name); +} + +static errno_t +cache_req_object_by_sid_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_sid(ncache, domain, data->sid); +} + +static errno_t +cache_req_object_by_sid_global_ncache_add(struct sss_nc_ctx *ncache, + struct cache_req_data *data) +{ + return sss_ncache_set_sid(ncache, false, NULL, data->sid); +} + +static errno_t +cache_req_object_by_sid_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_sid(ncache, false, domain, data->sid); +} + +static errno_t +cache_req_object_by_sid_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_search_object_by_sid(mem_ctx, domain, data->sid, data->attrs, + _result); +} + +static struct tevent_req * +cache_req_object_by_sid_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_SECID, cr->data->sid, 0, NULL); +} + +static bool +cache_req_object_by_sid_get_domain_check(struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_check_locate_sid(rctx->ncache, domain, data->sid); + if (nret == EEXIST) { + return false; + } + + return true; +} + +static struct tevent_req * +cache_req_object_by_sid_get_domain_send(TALLOC_CTX *mem_ctx, + struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_set_locate_sid(rctx->ncache, domain, data->sid); + if (nret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set negative cache, this might result in " + "performance degradation\n"); + /* Not fatal */ + } + + return sss_dp_get_account_domain_send(mem_ctx, + rctx, + domain, + true, /* fast_reply */ + SSS_DP_SECID, + 0, + data->sid); +} + + +const struct cache_req_plugin cache_req_object_by_sid = { + .name = "Object by SID", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = cache_req_object_by_sid_well_known, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_object_by_sid_create_debug_name, + .global_ncache_add_fn = cache_req_object_by_sid_global_ncache_add, + .ncache_check_fn = cache_req_object_by_sid_ncache_check, + .ncache_add_fn = cache_req_object_by_sid_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_object_by_sid_lookup, + .dp_send_fn = cache_req_object_by_sid_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = cache_req_object_by_sid_get_domain_check, + .dp_get_domain_send_fn = cache_req_object_by_sid_get_domain_send, + .dp_get_domain_recv_fn = cache_req_common_get_acct_domain_recv, +}; + +struct tevent_req * +cache_req_object_by_sid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *sid, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_sid(mem_ctx, CACHE_REQ_OBJECT_BY_SID, sid, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c new file mode 100644 index 0000000..29f52f1 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c @@ -0,0 +1,164 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb_ssh.h" +#include "util/util.h" +#include "util/sss_chain_id.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_host_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.name); +} + +static errno_t +cache_req_host_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ +#ifdef BUILD_SSH + struct ldb_result *result; + struct ldb_message *msg; + errno_t ret; + + ret = sysdb_get_ssh_host(mem_ctx, domain, data->name.name, + data->attrs, &msg); + if (ret != EOK) { + return ret; + } + + result = cache_req_create_ldb_result_from_msg(mem_ctx, msg); + if (result == NULL) { + return ENOMEM; + } + + *_result = result; + + return EOK; +#else + return ERR_INTERNAL; +#endif /* BUILD_SSH */ +} + +static struct tevent_req * +cache_req_host_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + struct be_conn *be_conn; + errno_t ret; + + ret = sss_dp_get_domain_conn(cr->rctx, domain->conn_name, &be_conn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "BUG: The Data Provider connection for %s is not available!\n", + domain->name); + return NULL; + } + + return sbus_call_dp_dp_hostHandler_send(mem_ctx, be_conn->conn, + be_conn->bus_name, SSS_BUS_PATH, + 0, data->name.name, data->alias, + sss_chain_id_get()); +} + +static bool +cache_req_host_by_name_dp_recv(struct tevent_req *subreq, + struct cache_req *cr) +{ + const char *err_msg; + dbus_uint16_t err_maj; + dbus_uint32_t err_min; + errno_t ret; + bool bret; + + /* Use subreq as memory context so err_msg is freed with it. */ + ret = sbus_call_dp_dp_hostHandler_recv(subreq, subreq, &err_maj, + &err_min, &err_msg); + bret = cache_req_common_process_dp_reply(cr, ret, err_maj, + err_min, err_msg); + + return bret; +} + +const struct cache_req_plugin cache_req_ssh_host_id_by_name = { + .name = "SSH Host ID by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = true, + .bypass_cache = true, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = 0, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_host_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_host_by_name_lookup, + .dp_send_fn = cache_req_host_by_name_dp_send, + .dp_recv_fn = cache_req_host_by_name_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_ssh_host_id_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char *alias, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_ssh_host_id(mem_ctx, CACHE_REQ_SSH_HOST_ID_BY_NAME, + name, alias, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c b/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c new file mode 100644 index 0000000..5485271 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c @@ -0,0 +1,143 @@ +/* + Copyright (C) 2021 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_subid.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_subid_ranges_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_subid_ranges_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_subid_ranges_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + struct ldb_result *result; + struct ldb_message *msg; + errno_t ret; + + ret = sysdb_get_subid_ranges(mem_ctx, domain, data->name.name, + data->attrs, &msg); + if (ret != EOK) { + return ret; + } + + result = cache_req_create_ldb_result_from_msg(mem_ctx, msg); + if (result == NULL) { + return ENOMEM; + } + + *_result = result; + + return EOK; +} + +static struct tevent_req * +cache_req_subid_ranges_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + /* Views aren't yet supported */ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_SUBID_RANGES, cr->data->name.lookup, 0, NULL); +} + +const struct cache_req_plugin cache_req_subid_ranges_by_name = { + .name = "SubID ranges by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_subid_ranges_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_subid_ranges_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_subid_ranges_by_name_lookup, + .dp_send_fn = cache_req_subid_ranges_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c new file mode 100644 index 0000000..5b17051 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c @@ -0,0 +1,185 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_services.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_svc_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + const char *protocol; + errno_t ret; + + if (data->svc.name->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, data->svc.name->name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + if (data->svc.protocol.name == NULL) { + protocol = NULL; + } else { + protocol = sss_get_cased_name(tmp_ctx, data->svc.protocol.name, + domain->case_sensitive); + if (protocol == NULL) { + ret = ENOMEM; + goto done; + } + } + + talloc_zfree(data->svc.name->lookup); + talloc_zfree(data->svc.protocol.lookup); + data->svc.name->lookup = talloc_steal(data, name); + data->svc.protocol.lookup = talloc_steal(data, protocol); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_svc_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *protocol = data->svc.protocol.lookup; + const char *name = data->svc.name->lookup; + + protocol = protocol == NULL ? "<ANY>" : protocol; + + return talloc_asprintf(mem_ctx, "%s %s@%s", protocol, name, domain->name); +} + +static errno_t +cache_req_svc_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_service(ncache, domain, data->svc.name->lookup, + data->svc.protocol.lookup); +} + +static errno_t +cache_req_svc_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_service_name(ncache, false, domain, + data->svc.name->lookup, + data->svc.protocol.lookup); +} + +static errno_t +cache_req_svc_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getservbyname(mem_ctx, domain, data->svc.name->lookup, + data->svc.protocol.lookup, _result); +} + +static struct tevent_req * +cache_req_svc_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_SERVICES, cr->data->svc.name->lookup, + 0, cr->data->svc.protocol.lookup); +} + +const struct cache_req_plugin cache_req_svc_by_name = { + .name = "Service by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_svc_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_svc_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_svc_by_name_ncache_check, + .ncache_add_fn = cache_req_svc_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_svc_by_name_lookup, + .dp_send_fn = cache_req_svc_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_svc_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char *protocol) +{ + struct cache_req_data *data; + + data = cache_req_data_svc(mem_ctx, CACHE_REQ_SVC_BY_NAME, name, protocol, 0); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c new file mode 100644 index 0000000..4c005df --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c @@ -0,0 +1,159 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "db/sysdb_services.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_svc_by_port_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *protocol; + + if (data->svc.protocol.name == NULL) { + return EOK; + } + + protocol = sss_get_cased_name(NULL, data->svc.protocol.name, + domain->case_sensitive); + if (protocol == NULL) { + return ENOMEM; + } + + talloc_zfree(data->svc.protocol.lookup); + data->svc.protocol.lookup = talloc_steal(data, protocol); + + return EOK; +} + +static const char * +cache_req_svc_by_port_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *protocol = data->svc.protocol.lookup; + + protocol = protocol == NULL ? "<ANY>" : protocol; + + return talloc_asprintf(mem_ctx, "%s %u@%s", protocol, + data->svc.port, domain->name); +} + +static errno_t +cache_req_svc_by_port_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_service_port(ncache, domain, data->svc.port, + data->svc.protocol.lookup); +} + +static errno_t +cache_req_svc_by_port_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_service_port(ncache, false, domain, + data->svc.port, + data->svc.protocol.lookup); +} + +static errno_t +cache_req_svc_by_port_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_getservbyport(mem_ctx, domain, data->svc.port, + data->svc.protocol.lookup, _result); +} + +static struct tevent_req * +cache_req_svc_by_port_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_SERVICES, NULL, cr->data->svc.port, + cr->data->svc.protocol.lookup); +} + +const struct cache_req_plugin cache_req_svc_by_port = { + .name = "Service by port", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_svc_by_port_prepare_domain_data, + .create_debug_name_fn = cache_req_svc_by_port_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_svc_by_port_ncache_check, + .ncache_add_fn = cache_req_svc_by_port_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_svc_by_port_lookup, + .dp_send_fn = cache_req_svc_by_port_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_svc_by_port_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + uint16_t port, + const char *protocol) +{ + struct cache_req_data *data; + + data = cache_req_data_svc(mem_ctx, CACHE_REQ_SVC_BY_PORT, + NULL, protocol, port); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c b/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c new file mode 100644 index 0000000..a2dc1fa --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c @@ -0,0 +1,127 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_user_by_cert_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + /* Certificates might be quite long, thus we only use + * the last 10 characters for logging. */ + return talloc_asprintf(mem_ctx, "CERT:%s@%s", + get_last_x_chars(data->cert, 10), domain->name); +} + +static errno_t +cache_req_user_by_cert_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_cert(ncache, data->cert); +} + +static errno_t +cache_req_user_by_cert_global_ncache_add(struct sss_nc_ctx *ncache, + struct cache_req_data *data) +{ + return sss_ncache_set_cert(ncache, false, data->cert); +} + +static errno_t +cache_req_user_by_cert_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + return sysdb_search_user_by_cert_with_views(mem_ctx, domain, data->cert, + _result); +} + +static struct tevent_req * +cache_req_user_by_cert_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_CERT, cr->data->cert, 0, NULL); +} + +const struct cache_req_plugin cache_req_user_by_cert = { + .name = "User by certificate", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = false, + .search_all_domains = true, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_user_by_cert_create_debug_name, + .global_ncache_add_fn = cache_req_user_by_cert_global_ncache_add, + .ncache_check_fn = cache_req_user_by_cert_ncache_check, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_user_by_cert_lookup, + .dp_send_fn = cache_req_user_by_cert_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *pem_cert) +{ + struct cache_req_data *data; + + data = cache_req_data_cert(mem_ctx, CACHE_REQ_USER_BY_CERT, pem_cert); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + req_dom_type, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c new file mode 100644 index 0000000..11ea9ec --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c @@ -0,0 +1,176 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_user_by_filter_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_user_by_filter_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_user_by_filter_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + char *recent_filter; + const char *attr = (data->name.attr == NULL ? SYSDB_NAME : data->name.attr); + errno_t ret; + + /* The "files" provider updates the record if /etc/passwd or /etc/group + * is touched. It does not perform any per-request update. + * Therefore the last update flag is not updated if no file was touched + * and we cannot use this optimization. + * Neither it is possible to use it when asking for a non-"name" attribute + * as it could not be present in the timestamp cache. + */ + if (is_files_provider(domain) || data->name.attr != NULL) { + recent_filter = NULL; + } else { + recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", SYSDB_LAST_UPDATE, + cr->req_start); + if (recent_filter == NULL) { + return ENOMEM; + } + } + + ret = sysdb_enumpwent_filter_with_views(mem_ctx, domain, + attr, data->name.lookup, + recent_filter, _result); + talloc_free(recent_filter); + + return ret; +} + +static struct tevent_req * +cache_req_user_by_filter_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_WILDCARD_USER, cr->data->name.lookup, + cr->data->id, NULL); +} + +const struct cache_req_plugin cache_req_user_by_filter = { + .name = "User by filter", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = true, + .only_one_result = false, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_user_by_filter_prepare_domain_data, + .create_debug_name_fn = cache_req_user_by_filter_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = NULL, + .ncache_add_fn = NULL, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_user_by_filter_lookup, + .dp_send_fn = cache_req_user_by_filter_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *attr, + const char *filter) +{ + struct cache_req_data *data; + + data = cache_req_data_attr(mem_ctx, CACHE_REQ_USER_BY_FILTER, attr, filter); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL, + 0, + req_dom_type, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_id.c b/src/responder/common/cache_req/plugins/cache_req_user_by_id.c new file mode 100644 index 0000000..fee5736 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_id.c @@ -0,0 +1,246 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static const char * +cache_req_user_by_id_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_asprintf(mem_ctx, "UID:%"PRIu32"@%s", data->id, domain->name); +} + +static errno_t +cache_req_user_by_id_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + errno_t ret; + + if (domain != NULL) { + ret = sss_ncache_check_uid(ncache, domain, data->id); + if (ret == EEXIST) { + return ret; + } + } + + return sss_ncache_check_uid(ncache, NULL, data->id); +} + +static errno_t +cache_req_user_by_id_ncache_filter(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + const char *name) +{ + return sss_ncache_check_user(ncache, domain, name); +} + +static errno_t +cache_req_user_by_id_global_ncache_add(struct sss_nc_ctx *ncache, + struct cache_req_data *data) +{ + return sss_ncache_set_uid(ncache, false, NULL, data->id); +} + +static errno_t +cache_req_user_by_id_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_uid(ncache, false, domain, data->id); +} + +static errno_t +cache_req_user_by_id_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + errno_t ret; + ret = cache_req_idminmax_check(data, domain); + if (ret != EOK) { + return ret; + } + return sysdb_getpwuid_with_views(mem_ctx, domain, data->id, _result); +} + +static errno_t +cache_req_user_by_id_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) +{ + uint32_t id; + + *_id = cr->data->id; + *_string = NULL; + *_flag = NULL; + + if (!DOM_HAS_VIEWS(cr->domain)) { + return EOK; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* If domain has views we will try to use original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_UIDNUM, 0); + if (id == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* Now we have the original name and id. We don't have to search with + * views unless some error occurred. */ + *_id = id; + + return EOK; +} + +static struct tevent_req * +cache_req_user_by_id_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + const char *string; + const char *flag; + uint32_t id; + errno_t ret; + + ret = cache_req_user_by_id_dpreq_params(mem_ctx, cr, result, + &string, &id, &flag); + if (ret != EOK) { + return NULL; + } + + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER, string, id, flag); +} + +static bool +cache_req_user_by_id_get_domain_check(struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_check_locate_uid(rctx->ncache, domain, data->id); + if (nret == EEXIST) { + return false; + } + + return true; +} + +static struct tevent_req * +cache_req_user_by_id_get_domain_send(TALLOC_CTX *mem_ctx, + struct resp_ctx *rctx, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + int nret; + + nret = sss_ncache_set_locate_uid(rctx->ncache, domain, data->id); + if (nret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set negative cache, this might result in " + "performance degradation\n"); + /* Not fatal */ + } + + return sss_dp_get_account_domain_send(mem_ctx, + rctx, + domain, + true, /* fast_reply */ + SSS_DP_USER, + data->id, + NULL); +} + +const struct cache_req_plugin cache_req_user_by_id = { + .name = "User by ID", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = NULL, + .create_debug_name_fn = cache_req_user_by_id_create_debug_name, + .global_ncache_add_fn = cache_req_user_by_id_global_ncache_add, + .ncache_check_fn = cache_req_user_by_id_ncache_check, + .ncache_add_fn = cache_req_user_by_id_ncache_add, + .ncache_filter_fn = cache_req_user_by_id_ncache_filter, + .lookup_fn = cache_req_user_by_id_lookup, + .dp_send_fn = cache_req_user_by_id_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = cache_req_user_by_id_get_domain_check, + .dp_get_domain_send_fn = cache_req_user_by_id_get_domain_send, + .dp_get_domain_recv_fn = cache_req_common_get_acct_domain_recv, +}; + +struct tevent_req * +cache_req_user_by_id_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + uid_t uid) +{ + struct cache_req_data *data; + + data = cache_req_data_id(mem_ctx, CACHE_REQ_USER_BY_ID, uid); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c new file mode 100644 index 0000000..d24a222 --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c @@ -0,0 +1,256 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_user_by_name_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + TALLOC_CTX *tmp_ctx; + const char *name; + errno_t ret; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); + return ERR_INTERNAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + name = sss_get_cased_name(tmp_ctx, cr->data->name.name, + domain->case_sensitive); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + name = sss_create_internal_fqname(tmp_ctx, name, domain->name); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static const char * +cache_req_user_by_name_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_user_by_name_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_user(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_user_by_name_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_user(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_user_by_name_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + if (data->attrs == NULL) { + return sysdb_getpwnam_with_views(mem_ctx, domain, data->name.lookup, + _result); + } + + return sysdb_get_user_attr_with_views(mem_ctx, domain, data->name.lookup, + data->attrs, _result); +} + +static errno_t +cache_req_user_by_name_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) +{ + const char *name; + + *_id = 0; + *_string = cr->data->name.lookup; + *_flag = NULL; + + if (!DOM_HAS_VIEWS(cr->domain)) { + return EOK; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* If domain has views we will try to use original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return EOK; + } + + /* Now we have the original name and id. We don't have to search with + * views unless some error occurred. */ + *_string = talloc_steal(mem_ctx, name); + + return EOK; +} + +static struct tevent_req * +cache_req_user_by_name_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + const char *string; + const char *flag; + uint32_t id; + errno_t ret; + + ret = cache_req_user_by_name_dpreq_params(mem_ctx, cr, result, + &string, &id, &flag); + if (ret != EOK) { + return NULL; + } + + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER, string, id, flag); +} + +const struct cache_req_plugin cache_req_user_by_name = { + .name = "User by name", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = true, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = false, + .allow_switch_to_upn = true, + .upn_equivalent = CACHE_REQ_USER_BY_UPN, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_user_by_name_prepare_domain_data, + .create_debug_name_fn = cache_req_user_by_name_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_user_by_name_ncache_check, + .ncache_add_fn = cache_req_user_by_name_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_user_by_name_lookup, + .dp_send_fn = cache_req_user_by_name_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_user_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *name) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_USER_BY_NAME, name); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + req_dom_type, domain, + data); +} + +struct tevent_req * +cache_req_user_by_name_attrs_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + const char *domain, + const char *name, + const char **attrs) +{ + struct cache_req_data *data; + + data = cache_req_data_name_attrs(mem_ctx, CACHE_REQ_USER_BY_NAME, + name, attrs); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + CACHE_REQ_POSIX_DOM, domain, + data); +} diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c new file mode 100644 index 0000000..037994c --- /dev/null +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c @@ -0,0 +1,158 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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 <talloc.h> +#include <ldb.h> + +#include "db/sysdb.h" +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/common/cache_req/cache_req_plugin.h" + +static errno_t +cache_req_user_by_upn_prepare_domain_data(struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + const char *name; + + if (cr->data->name.name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed UPN is NULL?\n"); + return ERR_INTERNAL; + } + + /* When looking up UPNs we don't want to reverse-replace spaces, + * just search whatever the user passed in. strdup the name so we + * can safely steal it later. + */ + name = talloc_strdup(data, cr->data->name.name); + if (name == NULL) { + return ENOMEM; + } + + talloc_zfree(data->name.lookup); + data->name.lookup = talloc_steal(data, name); + + return EOK; +} + +static const char * +cache_req_user_by_upn_create_debug_name(TALLOC_CTX *mem_ctx, + struct cache_req_data *data, + struct sss_domain_info *domain) +{ + return talloc_strdup(mem_ctx, data->name.lookup); +} + +static errno_t +cache_req_user_by_upn_ncache_check(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_check_upn(ncache, domain, data->name.lookup); +} + +static errno_t +cache_req_user_by_upn_ncache_add(struct sss_nc_ctx *ncache, + struct sss_domain_info *domain, + struct cache_req_data *data) +{ + return sss_ncache_set_upn(ncache, false, domain, data->name.lookup); +} + +static errno_t +cache_req_user_by_upn_lookup(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result **_result) +{ + if (data->attrs == NULL) { + return sysdb_getpwupn(mem_ctx, domain, true, data->name.lookup, _result); + } + + return sysdb_search_user_by_upn_res(mem_ctx, domain, true, + data->name.lookup, data->attrs, + _result); +} + +static struct tevent_req * +cache_req_user_by_upn_dp_send(TALLOC_CTX *mem_ctx, + struct cache_req *cr, + struct cache_req_data *data, + struct sss_domain_info *domain, + struct ldb_result *result) +{ + return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, + SSS_DP_USER, cr->data->name.lookup, + 0, EXTRA_NAME_IS_UPN); +} + +const struct cache_req_plugin cache_req_user_by_upn = { + .name = "User by UPN", + .attr_expiration = SYSDB_CACHE_EXPIRE, + .parse_name = false, + .ignore_default_domain = false, + .bypass_cache = false, + .only_one_result = true, + .search_all_domains = false, + .require_enumeration = false, + .allow_missing_fqn = true, + .allow_switch_to_upn = false, + .upn_equivalent = CACHE_REQ_SENTINEL, + .get_next_domain_flags = SSS_GND_DESCEND, + + .is_well_known_fn = NULL, + .prepare_domain_data_fn = cache_req_user_by_upn_prepare_domain_data, + .create_debug_name_fn = cache_req_user_by_upn_create_debug_name, + .global_ncache_add_fn = NULL, + .ncache_check_fn = cache_req_user_by_upn_ncache_check, + .ncache_add_fn = cache_req_user_by_upn_ncache_add, + .ncache_filter_fn = NULL, + .lookup_fn = cache_req_user_by_upn_lookup, + .dp_send_fn = cache_req_user_by_upn_dp_send, + .dp_recv_fn = cache_req_common_dp_recv, + .dp_get_domain_check_fn = NULL, + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, +}; + +struct tevent_req * +cache_req_user_by_upn_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int cache_refresh_percent, + enum cache_req_dom_type req_dom_type, + const char *domain, + const char *upn) +{ + struct cache_req_data *data; + + data = cache_req_data_name(mem_ctx, CACHE_REQ_USER_BY_UPN, upn); + if (data == NULL) { + return NULL; + } + + return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, + cache_refresh_percent, + req_dom_type, domain, + data); +} |