summaryrefslogtreecommitdiffstats
path: root/src/sss_iface/sss_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sss_iface/sss_iface.c')
-rw-r--r--src/sss_iface/sss_iface.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/sss_iface/sss_iface.c b/src/sss_iface/sss_iface.c
new file mode 100644
index 0000000..5711f2d
--- /dev/null
+++ b/src/sss_iface/sss_iface.c
@@ -0,0 +1,193 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2018 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 <unistd.h>
+#include <sys/stat.h>
+
+#include "util/util.h"
+#include "sbus/sbus.h"
+#include "sbus/sbus_opath.h"
+#include "sss_iface/sss_iface_async.h"
+
+char *
+sss_iface_domain_address(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain)
+{
+ struct sss_domain_info *head;
+
+ /* There is only one bus that belongs to the top level domain. */
+ head = get_domains_head(domain);
+
+ return talloc_asprintf(mem_ctx, SSS_BACKEND_ADDRESS, head->name);
+}
+
+char *
+sss_iface_domain_bus(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain)
+{
+ struct sss_domain_info *head;
+ char *safe_name;
+ char *bus_name;
+
+
+ /* There is only one bus that belongs to the top level domain. */
+ head = get_domains_head(domain);
+
+ safe_name = sbus_opath_escape(mem_ctx, head->name);
+ if (safe_name == NULL) {
+ return NULL;
+ }
+
+ /* Parts of bus names must not start with digit thus we concatenate
+ * the name with underscore instead of period. */
+ bus_name = talloc_asprintf(mem_ctx, "sssd.domain_%s", safe_name);
+ talloc_free(safe_name);
+
+ return bus_name;
+}
+
+char *
+sss_iface_proxy_bus(TALLOC_CTX *mem_ctx,
+ uint32_t id)
+{
+ /* Parts of bus names must not start with digit thus we concatenate
+ * the name with underscore instead of period. */
+ return talloc_asprintf(mem_ctx, "sssd.proxy_%"PRIu32, id);
+}
+
+errno_t
+sss_iface_connect_address(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *conn_name,
+ const char *address,
+ time_t *last_request_time,
+ struct sbus_connection **_conn)
+{
+ struct sbus_connection *conn;
+ const char *filename;
+ errno_t ret;
+ uid_t check_uid;
+ gid_t check_gid;
+
+ if (address == NULL) {
+ return EINVAL;
+ }
+
+ filename = strchr(address, '/');
+ if (filename == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unexpected dbus address [%s].\n", address);
+ return EIO;
+ }
+
+ check_uid = geteuid();
+ check_gid = getegid();
+
+ /* Ignore ownership checks when the server runs as root. This is the
+ * case when privileged monitor is setting up sockets for unprivileged
+ * responders */
+ if (check_uid == 0) check_uid = -1;
+ if (check_gid == 0) check_gid = -1;
+
+ ret = check_file(filename, check_uid, check_gid,
+ S_IFSOCK|S_IRUSR|S_IWUSR, 0, NULL, true);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "check_file failed for [%s].\n", filename);
+ return EIO;
+ }
+
+ conn = sbus_connect_private(mem_ctx, ev, address,
+ conn_name, last_request_time);
+ if (conn == NULL) { /* most probably sbus_dbus_connect_address() failed */
+ return EFAULT;
+ }
+
+ *_conn = conn;
+
+ return EOK;
+}
+
+static void
+sss_monitor_service_init_done(struct tevent_req *req);
+
+errno_t
+sss_monitor_service_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *conn_name,
+ const char *svc_name,
+ uint16_t svc_version,
+ uint16_t svc_type,
+ time_t *last_request_time,
+ struct sbus_connection **_conn)
+{
+ struct sbus_connection *conn;
+ struct tevent_req *req;
+ errno_t ret;
+
+ ret = sss_iface_connect_address(mem_ctx, ev, conn_name,
+ SSS_MONITOR_ADDRESS,
+ last_request_time, &conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to monitor sbus server "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ req = sbus_call_monitor_RegisterService_send(conn, conn, SSS_BUS_MONITOR,
+ SSS_BUS_PATH, svc_name,
+ svc_version, svc_type);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(req, sss_monitor_service_init_done, conn);
+
+ *_conn = conn;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(conn);
+ }
+
+ return ret;
+}
+
+static void
+sss_monitor_service_init_done(struct tevent_req *req)
+{
+ uint16_t version;
+ errno_t ret;
+
+ ret = sbus_call_monitor_RegisterService_recv(req, &version);
+ talloc_zfree(req);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register client in monitor "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return;
+ }
+
+ DEBUG(SSSDBG_CONF_SETTINGS, "Got id ack and version (%d) from Monitor\n",
+ version);
+}