diff options
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | src/providers/data_provider.h | 2 | ||||
-rw-r--r-- | src/providers/dp_auth_util.c | 36 | ||||
-rw-r--r-- | src/responder/autofs/autofssrv.c | 4 | ||||
-rw-r--r-- | src/responder/common/data_provider/rdp.h | 60 | ||||
-rw-r--r-- | src/responder/common/data_provider/rdp_client.c | 55 | ||||
-rw-r--r-- | src/responder/common/data_provider/rdp_message.c | 243 | ||||
-rw-r--r-- | src/responder/common/responder.h | 1 | ||||
-rw-r--r-- | src/responder/common/responder_common.c | 4 | ||||
-rw-r--r-- | src/responder/ifp/ifpsrv.c | 4 | ||||
-rw-r--r-- | src/responder/nss/nsssrv.c | 4 | ||||
-rw-r--r-- | src/responder/pac/pacsrv.c | 4 | ||||
-rw-r--r-- | src/responder/pam/pamsrv.c | 4 | ||||
-rw-r--r-- | src/responder/ssh/sshsrv.c | 4 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv.c | 4 | ||||
-rw-r--r-- | src/tests/cwrap/Makefile.am | 4 |
16 files changed, 379 insertions, 63 deletions
diff --git a/Makefile.am b/Makefile.am index 0100b6bfe..12586abbf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -469,6 +469,8 @@ SSSD_RESPONDER_OBJ = \ src/responder/common/responder_get_domains.c \ src/responder/common/responder_utils.c \ src/responder/common/responder_cache_req.c \ + src/responder/common/data_provider/rdp_message.c \ + src/responder/common/data_provider/rdp_client.c \ src/monitor/monitor_iface_generated.c \ src/providers/data_provider_iface_generated.c \ src/providers/data_provider_req.c @@ -578,6 +580,7 @@ dist_noinst_HEADERS = \ src/responder/common/responder_packet.h \ src/responder/common/responder_sbus.h \ src/responder/common/responder_cache_req.h \ + src/responder/common/data_provider/rdp.h \ src/responder/pam/pamsrv.h \ src/responder/pam/pam_helpers.h \ src/responder/nss/nsssrv.h \ @@ -1902,7 +1905,9 @@ responder_socket_access_tests_SOURCES = \ src/responder/common/negcache.c \ src/responder/common/responder_common.c \ src/responder/common/responder_packet.c \ - src/responder/common/responder_cmd.c + src/responder/common/responder_cmd.c \ + src/responder/common/data_provider/rdp_message.c \ + src/responder/common/data_provider/rdp_client.c responder_socket_access_tests_CFLAGS = \ $(AM_CFLAGS) \ $(CHECK_CFLAGS) @@ -1999,6 +2004,8 @@ TEST_MOCK_RESP_OBJ = \ src/responder/common/negcache_files.c \ src/responder/common/negcache.c \ src/responder/common/responder_common.c \ + src/responder/common/data_provider/rdp_message.c \ + src/responder/common/data_provider/rdp_client.c \ src/responder/common/responder_cache_req.c TEST_MOCK_PROVIDER_OBJ = \ diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index f52295ae4..b0b6876d9 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -227,8 +227,6 @@ bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd); bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error); -int dp_common_send_id(struct sbus_connection *conn, uint16_t version, - const char *name); void dp_id_callback(DBusPendingCall *pending, void *ptr); /* from dp_sbus.c */ diff --git a/src/providers/dp_auth_util.c b/src/providers/dp_auth_util.c index 8e261ef5e..8c09299b1 100644 --- a/src/providers/dp_auth_util.c +++ b/src/providers/dp_auth_util.c @@ -385,39 +385,3 @@ done: dbus_pending_call_unref(pending); dbus_message_unref(reply); } - -int dp_common_send_id(struct sbus_connection *conn, uint16_t version, - const char *name) -{ - DBusMessage *msg; - dbus_bool_t ret; - int retval; - - /* create the message */ - msg = dbus_message_new_method_call(NULL, - DP_PATH, - DATA_PROVIDER_IFACE, - DATA_PROVIDER_IFACE_REGISTERSERVICE); - if (msg == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?!\n"); - return ENOMEM; - } - - DEBUG(SSSDBG_CONF_SETTINGS, "Sending ID to DP: (%d,%s)\n", - version, name); - - ret = dbus_message_append_args(msg, - DBUS_TYPE_UINT16, &version, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - if (!ret) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n"); - return EIO; - } - - retval = sbus_conn_send(conn, msg, 30000, dp_id_callback, NULL, NULL); - - dbus_message_unref(msg); - return retval; -} - 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); diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am index 84d8df4b7..8005d9974 100644 --- a/src/tests/cwrap/Makefile.am +++ b/src/tests/cwrap/Makefile.am @@ -46,6 +46,8 @@ SSSD_RESPONDER_OBJ = \ ../../../src/responder/common/responder_get_domains.c \ ../../../src/responder/common/responder_utils.c \ ../../../src/responder/common/responder_cache_req.c \ + ../../../src/responder/common/data_provider/rdp_message.c \ + ../../../src/responder/common/data_provider/rdp_client.c \ ../../../src/monitor/monitor_iface_generated.c \ ../../../src/providers/data_provider_iface_generated.c \ ../../../src/providers/data_provider_req.c @@ -130,6 +132,8 @@ responder_common_tests_SOURCES =\ test_responder_common.c \ ../../../src/responder/common/negcache_files.c \ ../../../src/responder/common/negcache.c \ + ../../../src/responder/common/data_provider/rdp_message.c \ + ../../../src/responder/common/data_provider/rdp_client.c \ ../../../src/responder/common/responder_common.c \ ../../../src/responder/common/responder_packet.c \ ../../../src/responder/common/responder_cmd.c \ |