summaryrefslogtreecommitdiffstats
path: root/src/providers/data_provider/dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/data_provider/dp.c')
-rw-r--r--src/providers/data_provider/dp.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/src/providers/data_provider/dp.c b/src/providers/data_provider/dp.c
new file mode 100644
index 0000000..99f27fc
--- /dev/null
+++ b/src/providers/data_provider/dp.c
@@ -0,0 +1,288 @@
+/*
+ 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 "config.h"
+#include "providers/data_provider/dp.h"
+#include "providers/data_provider/dp_private.h"
+#include "providers/data_provider/dp_iface.h"
+#include "sss_iface/sss_iface_async.h"
+#include "providers/backend.h"
+#include "util/util.h"
+
+static errno_t
+dp_init_interface(struct data_provider *provider)
+{
+ errno_t ret;
+
+ SBUS_INTERFACE(iface_dp_client,
+ sssd_DataProvider_Client,
+ SBUS_METHODS(
+ SBUS_SYNC(METHOD, sssd_DataProvider_Client, Register, dp_client_register, provider)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ SBUS_INTERFACE(iface_dp_backend,
+ sssd_DataProvider_Backend,
+ SBUS_METHODS(
+ SBUS_SYNC(METHOD, sssd_DataProvider_Backend, IsOnline, dp_backend_is_online, provider->be_ctx)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ SBUS_INTERFACE(iface_dp_failover,
+ sssd_DataProvider_Failover,
+ SBUS_METHODS(
+ SBUS_SYNC(METHOD, sssd_DataProvider_Failover, ListServices, dp_failover_list_services, provider->be_ctx),
+ SBUS_SYNC(METHOD, sssd_DataProvider_Failover, ListServers, dp_failover_list_servers, provider->be_ctx),
+ SBUS_SYNC(METHOD, sssd_DataProvider_Failover, ActiveServer, dp_failover_active_server, provider->be_ctx)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ SBUS_INTERFACE(iface_dp_access,
+ sssd_DataProvider_AccessControl,
+ SBUS_METHODS(
+ SBUS_ASYNC(METHOD, sssd_DataProvider_AccessControl, RefreshRules, dp_access_control_refresh_rules_send, dp_access_control_refresh_rules_recv, provider)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ SBUS_INTERFACE(iface_autofs,
+ sssd_DataProvider_Autofs,
+ SBUS_METHODS(
+ SBUS_ASYNC(METHOD, sssd_DataProvider_Autofs, GetMap, dp_autofs_get_map_send, dp_autofs_get_map_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_DataProvider_Autofs, GetEntry, dp_autofs_get_entry_send, dp_autofs_get_entry_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_DataProvider_Autofs, Enumerate, dp_autofs_enumerate_send, dp_autofs_enumerate_recv, provider)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ SBUS_INTERFACE(iface_dp,
+ sssd_dataprovider,
+ SBUS_METHODS(
+ SBUS_ASYNC(METHOD, sssd_dataprovider, pamHandler, dp_pam_handler_send, dp_pam_handler_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, sudoHandler, dp_sudo_handler_send, dp_sudo_handler_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, hostHandler, dp_host_handler_send, dp_host_handler_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, resolverHandler, dp_resolver_handler_send, dp_resolver_handler_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, getDomains, dp_subdomains_handler_send, dp_subdomains_handler_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, getAccountInfo, dp_get_account_info_send, dp_get_account_info_recv, provider),
+ SBUS_ASYNC(METHOD, sssd_dataprovider, getAccountDomain, dp_get_account_domain_send, dp_get_account_domain_recv, provider)
+ ),
+ SBUS_SIGNALS(SBUS_NO_SIGNALS),
+ SBUS_PROPERTIES(SBUS_NO_PROPERTIES)
+ );
+
+ struct sbus_path paths[] = {
+ {SSS_BUS_PATH, &iface_dp_client},
+ {SSS_BUS_PATH, &iface_dp_backend},
+ {SSS_BUS_PATH, &iface_dp_failover},
+ {SSS_BUS_PATH, &iface_dp_access},
+ {SSS_BUS_PATH, &iface_dp},
+ {SSS_BUS_PATH, &iface_autofs},
+ {NULL, NULL}
+ };
+
+ ret = sbus_connection_add_path_map(provider->sbus_conn, paths);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n",
+ ret, sss_strerror(ret));
+ }
+
+ return ret;
+}
+
+static int dp_destructor(struct data_provider *provider)
+{
+ enum dp_clients client;
+
+ provider->terminating = true;
+
+ dp_terminate_active_requests(provider);
+
+ for (client = 0; client != DP_CLIENT_SENTINEL; client++) {
+ talloc_zfree(provider->clients[client]);
+ }
+
+ return 0;
+}
+
+struct dp_init_state {
+ struct be_ctx *be_ctx;
+ struct data_provider *provider;
+};
+
+static void dp_init_done(struct tevent_req *subreq);
+
+struct tevent_req *
+dp_init_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct be_ctx *be_ctx,
+ uid_t uid,
+ gid_t gid,
+ const char *sbus_name)
+{
+ struct dp_init_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ char *sbus_address;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct dp_init_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ sbus_address = sss_iface_domain_address(state, be_ctx->domain);
+ if (sbus_address == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Could not get sbus backend address.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ state->provider = talloc_zero(be_ctx, struct data_provider);
+ if (state->provider == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ state->be_ctx = be_ctx;
+ state->provider->ev = ev;
+ state->provider->uid = uid;
+ state->provider->gid = gid;
+ state->provider->be_ctx = be_ctx;
+
+ /* Initialize data provider bus. Data provider can receive client
+ * registration and other D-Bus methods. However no data provider
+ * request will be executed as long as the modules and targets
+ * are not initialized.
+ */
+ talloc_set_destructor(state->provider, dp_destructor);
+
+ subreq = sbus_server_create_and_connect_send(state->provider, ev,
+ sbus_name, NULL, sbus_address, true, 1000, uid, gid,
+ (sbus_server_on_connection_cb)dp_client_init,
+ (sbus_server_on_connection_data)state->provider);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, dp_init_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void dp_init_done(struct tevent_req *subreq)
+{
+ struct dp_init_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct dp_init_state);
+
+ ret = sbus_server_create_and_connect_recv(state->provider, subreq,
+ &state->provider->sbus_server,
+ &state->provider->sbus_conn);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* be_ctx->provider must be accessible from modules and targets */
+ state->be_ctx->provider = talloc_steal(state->be_ctx, state->provider);
+
+ ret = dp_init_modules(state->provider, &state->provider->modules);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP modules "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = dp_init_targets(state->provider, state->provider->be_ctx,
+ state->provider, state->provider->modules);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP targets "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = dp_init_interface(state->provider);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP interface "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ talloc_zfree(state->be_ctx->provider);
+ tevent_req_error(req, ret);
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t dp_init_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+struct sbus_connection *
+dp_sbus_conn(struct data_provider *provider)
+{
+ if (provider == NULL) {
+ return NULL;
+ }
+
+ return provider->sbus_conn;
+}
+
+struct sbus_server *
+dp_sbus_server(struct data_provider *provider)
+{
+ if (provider == NULL) {
+ return NULL;
+ }
+
+ return provider->sbus_server;
+}