summaryrefslogtreecommitdiffstats
path: root/src/responder
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder')
-rw-r--r--src/responder/autofs/autofssrv.c4
-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
-rw-r--r--src/responder/ifp/ifpsrv.c4
-rw-r--r--src/responder/nss/nsssrv.c4
-rw-r--r--src/responder/pac/pacsrv.c4
-rw-r--r--src/responder/pam/pamsrv.c4
-rw-r--r--src/responder/ssh/sshsrv.c4
-rw-r--r--src/responder/sudo/sudosrv.c4
12 files changed, 367 insertions, 24 deletions
diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
index eee7594ed..9647c3473 100644
--- a/src/responder/autofs/autofssrv.c
+++ b/src/responder/autofs/autofssrv.c
@@ -79,9 +79,7 @@ autofs_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_TRACE_FUNC, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "autofs");
+ ret = rdp_register_client(be_conn, "autofs");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
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;
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index 879e00c8e..fdb11f650 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -90,9 +90,7 @@ static void ifp_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_TRACE_FUNC, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "InfoPipe");
+ ret = rdp_register_client(be_conn, "InfoPipe");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 2cc934c45..d01884789 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -380,9 +380,7 @@ static void nss_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_CRIT_FAILURE, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "NSS");
+ ret = rdp_register_client(be_conn, "NSS");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
index b4b033b68..8e919780a 100644
--- a/src/responder/pac/pacsrv.c
+++ b/src/responder/pac/pacsrv.c
@@ -84,9 +84,7 @@ static void pac_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_OP_FAILURE, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "PAC");
+ ret = rdp_register_client(be_conn, "PAC");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index 6596ccd75..7e037b403 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -87,9 +87,7 @@ static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void
DEBUG(SSSDBG_CRIT_FAILURE, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "PAM");
+ ret = rdp_register_client(be_conn, "PAM");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
index d4e202d87..2be7d4bf2 100644
--- a/src/responder/ssh/sshsrv.c
+++ b/src/responder/ssh/sshsrv.c
@@ -63,9 +63,7 @@ static void ssh_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_TRACE_FUNC, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "SSH");
+ ret = rdp_register_client(be_conn, "SSH");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);
diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
index 73c91b1f8..e93ec75b4 100644
--- a/src/responder/sudo/sudosrv.c
+++ b/src/responder/sudo/sudosrv.c
@@ -65,9 +65,7 @@ static void sudo_dp_reconnect_init(struct sbus_connection *conn,
DEBUG(SSSDBG_TRACE_FUNC, "Reconnected to the Data Provider.\n");
/* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "SUDO");
+ ret = rdp_register_client(be_conn, "SUDO");
/* all fine */
if (ret == EOK) {
handle_requests_after_reconnect(be_conn->rctx);