summaryrefslogtreecommitdiffstats
path: root/src/responder/common/cache_req/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
commit74aa0bc6779af38018a03fd2cf4419fe85917904 (patch)
tree9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/common/cache_req/plugins
parentInitial commit. (diff)
downloadsssd-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')
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_autofs_entry_by_name.c161
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c155
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_autofs_map_entries.c187
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_common.c192
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_enum_groups.c93
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c126
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c126
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_enum_svc.c106
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_enum_users.c93
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_group_by_filter.c171
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_group_by_id.c246
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_group_by_name.c227
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c242
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_initgroups_by_upn.c130
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c174
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c170
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c174
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c170
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c160
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_object_by_id.c236
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_object_by_name.c238
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_object_by_sid.c202
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c164
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c143
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_svc_by_name.c185
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_svc_by_port.c159
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_user_by_cert.c127
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_user_by_filter.c176
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_user_by_id.c246
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_user_by_name.c256
-rw-r--r--src/responder/common/cache_req/plugins/cache_req_user_by_upn.c158
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);
+}