summaryrefslogtreecommitdiffstats
path: root/src/responder/common
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2016-05-15 20:48:13 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-06-20 14:48:47 +0200
commit83a79d93035c2d75a1941f3b54426119174044a0 (patch)
treeca7d8ae7fe618c4b1798b22ffbf4cc8368156b2d /src/responder/common
parentdea636af4d1902a081ee891f1b19ee2f8729d759 (diff)
downloadsssd-83a79d93035c2d75a1941f3b54426119174044a0.tar.gz
sssd-83a79d93035c2d75a1941f3b54426119174044a0.tar.xz
sssd-83a79d93035c2d75a1941f3b54426119174044a0.zip
RESPONDER: New interface for client registration
This is just a beginning of new responder interface to data provider and it is just to make the client registration work. It needs further improvement. The idea is to take the existing interface and make it work better with further extensions of data provider. The current interface has several disadvantages such as it is originally build only for account requests and doesn't take different set of output parameters. It also doesn't work well with integration into tevent-made responders. Reviewed-by: Sumit Bose <sbose@redhat.com> Reviewed-by: Jakub Hrozek <jhrozek@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src/responder/common')
-rw-r--r--src/responder/common/data_provider/rdp.h60
-rw-r--r--src/responder/common/data_provider/rdp_client.c55
-rw-r--r--src/responder/common/data_provider/rdp_message.c243
-rw-r--r--src/responder/common/responder.h1
-rw-r--r--src/responder/common/responder_common.c4
5 files changed, 360 insertions, 3 deletions
diff --git a/src/responder/common/data_provider/rdp.h b/src/responder/common/data_provider/rdp.h
new file mode 100644
index 000000000..8a3ec803d
--- /dev/null
+++ b/src/responder/common/data_provider/rdp.h
@@ -0,0 +1,60 @@
+/*
+ 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/>.
+*/
+
+#ifndef _RDP_H_
+#define _RDP_H_
+
+#include "responder/common/responder.h"
+#include "providers/data_provider/dp_iface_generated.h"
+#include "providers/data_provider/dp_iface.h"
+#include "sbus/sssd_dbus.h"
+#include "util/util.h"
+
+struct be_conn;
+struct resp_ctx;
+
+struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ ...);
+
+#define rdp_message_send(mem_ctx, rctx, domain, path, iface, \
+ method, ...) \
+ _rdp_message_send(mem_ctx, rctx, domain, path, iface, method, \
+ ##__VA_ARGS__, DBUS_TYPE_INVALID)
+
+/* D-Bus reply message is freed with tevent request. Since all output data
+ * point inside D-Bus reply do not call talloc_free(req) unless
+ * you are not accessing the data any longer. */
+errno_t _rdp_message_recv(struct tevent_req *req,
+ int first_arg_type,
+ ...);
+
+#define rdp_message_recv(req, ...) \
+ _rdp_message_recv(req, ##__VA_ARGS__, DBUS_TYPE_INVALID)
+
+errno_t rdp_register_client(struct be_conn *be_conn,
+ const char *client_name);
+
+#endif /* _RDP_CALLS_H_ */
diff --git a/src/responder/common/data_provider/rdp_client.c b/src/responder/common/data_provider/rdp_client.c
new file mode 100644
index 000000000..d0b8357a9
--- /dev/null
+++ b/src/responder/common/data_provider/rdp_client.c
@@ -0,0 +1,55 @@
+/*
+ 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 "responder/common/data_provider/rdp.h"
+#include "util/util.h"
+
+static void rdp_register_client_done(struct tevent_req *req);
+
+errno_t rdp_register_client(struct be_conn *be_conn,
+ const char *client_name)
+{
+ struct tevent_req *req;
+
+ req = rdp_message_send(be_conn, be_conn->rctx, be_conn->domain,
+ DP_PATH, IFACE_DP_CLIENT, IFACE_DP_CLIENT_REGISTER,
+ DBUS_TYPE_STRING, &client_name);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, rdp_register_client_done, NULL);
+
+ return EOK;
+}
+
+static void rdp_register_client_done(struct tevent_req *req)
+{
+ errno_t ret;
+
+ ret = rdp_message_recv(req);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register client with DP\n");
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Client is registered with DP\n");
+}
diff --git a/src/responder/common/data_provider/rdp_message.c b/src/responder/common/data_provider/rdp_message.c
new file mode 100644
index 000000000..78af6f896
--- /dev/null
+++ b/src/responder/common/data_provider/rdp_message.c
@@ -0,0 +1,243 @@
+/*
+ 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 <tevent.h>
+
+#include "responder/common/data_provider/rdp.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_errors.h"
+#include "util/util.h"
+
+static errno_t rdp_error_to_errno(DBusError *error)
+{
+ static struct {
+ const char *name;
+ errno_t ret;
+ } list[] = {{SBUS_ERROR_INTERNAL, ERR_INTERNAL},
+ {SBUS_ERROR_NOT_FOUND, ENOENT},
+ {SBUS_ERROR_DP_FATAL, ERR_TERMINATED},
+ {SBUS_ERROR_DP_OFFLINE, ERR_OFFLINE},
+ {SBUS_ERROR_DP_NOTSUP, ENOTSUP},
+ {NULL, ERR_INTERNAL}
+ };
+ int i;
+
+ if (!dbus_error_is_set(error)) {
+ return EOK;
+ }
+
+ for (i = 0; list[i].name != NULL; i ++) {
+ if (dbus_error_has_name(error, list[i].name)) {
+ return list[i].ret;
+ }
+ }
+
+ return EIO;
+}
+
+struct rdp_message_state {
+ struct DBusMessage *reply;
+};
+
+static int rdp_message_state_destructor(struct rdp_message_state *state)
+{
+ if (state->reply != NULL) {
+ dbus_message_unref(state->reply);
+ }
+
+ return 0;
+}
+
+static void rdp_message_done(DBusPendingCall *pending, void *ptr);
+
+struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *path,
+ const char *iface,
+ const char *method,
+ int first_arg_type,
+ ...)
+{
+ struct rdp_message_state *state;
+ struct be_conn *be_conn;
+ struct tevent_req *req;
+ DBusMessage *msg;
+ dbus_bool_t bret;
+ errno_t ret;
+ va_list va;
+
+ req = tevent_req_create(mem_ctx, &state, struct rdp_message_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ talloc_set_destructor(state, rdp_message_state_destructor);
+
+ ret = sss_dp_get_domain_conn(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);
+ ret = ERR_INTERNAL;
+ goto immediately;
+ }
+
+ msg = dbus_message_new_method_call(NULL, path, iface, method);
+ if (msg == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create message\n");
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ va_start(va, first_arg_type);
+ bret = dbus_message_append_args_valist(msg, first_arg_type, va);
+ va_end(va);
+ if (!bret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n");
+ ret = EIO;
+ goto immediately;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "DP Request: %s %s.%s\n", path, iface, method);
+
+ ret = sbus_conn_send(be_conn->conn, msg, 30000,
+ rdp_message_done, req, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto immediately;
+ }
+
+ return req;
+
+immediately:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, rctx->ev);
+
+ return req;
+}
+
+static void rdp_message_done(DBusPendingCall *pending, void *ptr)
+{
+ struct rdp_message_state *state;
+ DBusMessage *reply = NULL;
+ struct tevent_req *req;
+ DBusError error;
+ dbus_bool_t bret;
+ errno_t ret;
+
+ req = talloc_get_type(ptr, struct tevent_req);
+ state = tevent_req_data(req, struct rdp_message_state);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+ if (reply == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Severe error. A reply callback was "
+ "called but no reply was received and no timeout occurred\n");
+ ret = EFAULT;
+ goto done;
+ }
+
+ switch (dbus_message_get_type(reply)) {
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ DEBUG(SSSDBG_TRACE_FUNC, "DP Success\n");
+ state->reply = reply;
+ ret = EOK;
+ goto done;
+
+ case DBUS_MESSAGE_TYPE_ERROR:
+ bret = dbus_set_error_from_message(&error, reply);
+ if (bret == false) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read error from message\n");
+ ret = EIO;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "DP Error [%s]: %s\n",
+ error.name, (error.message == NULL ? "(null)" : error.message));
+ ret = rdp_error_to_errno(&error);
+ goto done;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected type?\n");
+ ret = ERR_INTERNAL;
+ goto done;
+ }
+
+ ret = ERR_INTERNAL;
+
+done:
+ dbus_pending_call_unref(pending);
+ dbus_error_free(&error);
+
+ if (ret == EOK) {
+ tevent_req_done(req);
+ return;
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+ tevent_req_error(req, ret);
+}
+
+errno_t _rdp_message_recv(struct tevent_req *req,
+ int first_arg_type,
+ ...)
+{
+ struct rdp_message_state *state;
+ DBusError error;
+ dbus_bool_t bret;
+ errno_t ret;
+ va_list va;
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ state = tevent_req_data(req, struct rdp_message_state);
+ dbus_error_init(&error);
+
+ va_start(va, first_arg_type);
+ bret = dbus_message_get_args_valist(state->reply, &error, first_arg_type, va);
+ va_end(va);
+
+ if (bret == false) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse reply\n");
+ ret = EIO;
+ goto done;
+ }
+
+ ret = rdp_error_to_errno(&error);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse message [%s]: %s\n",
+ error.name, error.message);
+ goto done;
+ }
+
+done:
+ dbus_error_free(&error);
+ return ret;
+}
+
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 7fc277024..2b5b05412 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -33,6 +33,7 @@
#include <ldb.h>
#include <dhash.h>
+#include "data_provider/rdp.h"
#include "sbus/sssd_dbus.h"
#include "responder/common/negcache.h"
#include "sss_client/sss_cli.h"
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index f0ddde9c0..352c413be 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -571,9 +571,7 @@ static int sss_dp_init(struct resp_ctx *rctx,
DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
/* Identify ourselves to the DP */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- cli_name);
+ ret = rdp_register_client(be_conn, cli_name);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "Failed to identify to the DP!\n");
return ret;