From 316b1b752a50777e58aae805ad291d08b2f479c3 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Mon, 6 Jan 2014 15:15:40 +0100
Subject: [PATCH 2/2] IFP: Connect to the system bus

Related:
https://fedorahosted.org/sssd/ticket/2072

Adds the possibility for the InfoPipe responder to connect to the system bus.
At the moment, only a dummy method "Ping" is provided. The method only
accepts a single string parameter that has to be 'ping'.
---
 Makefile.am                                        |   9 +-
 contrib/sssd.spec.in                               |   2 +
 src/responder/ifp/ifp_iface.xml                    |  10 ++
 src/responder/ifp/ifp_iface_generated.c            |  25 +++++
 src/responder/ifp/ifp_iface_generated.h            |  49 +++++++++
 src/responder/ifp/ifp_private.h                    |  14 +++
 src/responder/ifp/ifpsrv.c                         | 110 ++++++++++++++++++++-
 src/responder/ifp/ifpsrv_cmd.c                     |  36 +++++++
 .../ifp/org.freedesktop.sssd.infopipe.conf         |  22 +++++
 9 files changed, 275 insertions(+), 2 deletions(-)
 create mode 100644 src/responder/ifp/ifp_iface.xml
 create mode 100644 src/responder/ifp/ifp_iface_generated.c
 create mode 100644 src/responder/ifp/ifp_iface_generated.h
 create mode 100644 src/responder/ifp/org.freedesktop.sssd.infopipe.conf

diff --git a/Makefile.am b/Makefile.am
index 620474f098b20f86e2e26c8dd35689686943f6f8..2cd6b8b40f122b1a75a521bffc2ff65db3cdbbc1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,7 @@ sssdconfdir = $(sysconfdir)/sssd
 sssddatadir = $(datadir)/sssd
 sssdapiplugindir = $(sssddatadir)/sssd.api.d
 dbusintrospectdir = $(datarootdir)/sssd/introspect
+dbuspolicydir = $(sysconfdir)/dbus-1/system.d
 localedir = @localedir@
 nsslibdir = @nsslibdir@
 pamlibdir = @pammoddir@
@@ -685,7 +686,8 @@ include_HEADERS = \
 CODEGEN_XML = \
     $(srcdir)/src/tests/sbus_codegen_tests.xml \
     $(srcdir)/src/monitor/monitor_iface.xml \
-    $(srcdir)/src/providers/data_provider_iface.xml
+    $(srcdir)/src/providers/data_provider_iface.xml \
+    $(srcdir)/src/responder/ifp/ifp_iface.xml
 
 SBUS_CODEGEN = src/sbus/sbus_codegen
 
@@ -807,6 +809,8 @@ if BUILD_IFP
 sssd_ifp_SOURCES = \
     src/responder/ifp/ifpsrv.c \
     src/responder/ifp/ifpsrv_cmd.c \
+    src/responder/ifp/ifp_iface_generated.c \
+    src/responder/ifp/ifp_iface_generated.h \
     $(SSSD_UTIL_OBJ) \
     $(SSSD_RESPONDER_OBJ)
 sssd_ifp_CFLAGS = \
@@ -814,6 +818,8 @@ sssd_ifp_CFLAGS = \
 sssd_ifp_LDADD = \
     $(SSSD_LIBS) \
     $(SSSD_INTERNAL_LTLIBS)
+dist_dbuspolicy_DATA = \
+    src/responder/ifp/org.freedesktop.sssd.infopipe.conf
 endif
 
 sssd_be_SOURCES = \
@@ -2265,6 +2271,7 @@ installsssddirs::
     $(DESTDIR)$(pluginpath) \
     $(DESTDIR)$(libdir)/ldb \
     $(DESTDIR)$(dbusintrospectdir) \
+    $(DESTDIR)$(dbuspolicydir) \
     $(DESTDIR)$(pipepath)/private \
     $(DESTDIR)$(sssdlibdir) \
     $(DESTDIR)$(pkglibdir) \
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 4cf022ac6ee18a6f3e607423a25423f59c043239..ac09b003007ddc8fe4792dbd0b5791b00495a425 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -667,6 +667,8 @@ rm -rf $RPM_BUILD_ROOT
 %doc COPYING
 %{_libexecdir}/%{servicename}/sssd_ifp
 %{_mandir}/man5/sssd-ifp.5*
+# InfoPipe DBus plumbing
+%{_sysconfdir}/dbus-1/system.d/org.freedesktop.sssd.infopipe.conf
 
 %files client -f sssd_client.lang
 %defattr(-,root,root,-)
diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e3221b577b88dc622b4a467f3ae78aa44c84927d
--- /dev/null
+++ b/src/responder/ifp/ifp_iface.xml
@@ -0,0 +1,10 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+    <interface name="org.freedesktop.sssd.infopipe">
+        <annotation value="infopipe_iface" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="Ping">
+            <!-- arguments parsed manually -->
+        </method>
+    </interface>
+</node>
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
new file mode 100644
index 0000000000000000000000000000000000000000..db5e0e545d8d1a956ae052be52a824ed0bf5d273
--- /dev/null
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -0,0 +1,25 @@
+/* The following definitions are auto-generated from ifp_iface.xml */
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
+#include "ifp_iface_generated.h"
+
+/* methods for org.freedesktop.sssd.infopipe */
+const struct sbus_method_meta infopipe_iface__methods[] = {
+    {
+        "Ping", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct infopipe_iface, Ping),
+    },
+    { NULL, }
+};
+
+/* interface info for org.freedesktop.sssd.infopipe */
+const struct sbus_interface_meta infopipe_iface_meta = {
+    "org.freedesktop.sssd.infopipe", /* name */
+    infopipe_iface__methods,
+    NULL, /* no signals */
+    NULL, /* no propetries */
+};
diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h
new file mode 100644
index 0000000000000000000000000000000000000000..8db83fc115d62390560e9be94ac1480ade48296f
--- /dev/null
+++ b/src/responder/ifp/ifp_iface_generated.h
@@ -0,0 +1,49 @@
+/* The following declarations are auto-generated from ifp_iface.xml */
+
+#ifndef __IFP_IFACE_XML__
+#define __IFP_IFACE_XML__
+
+#include "sbus/sssd_dbus.h"
+
+/* ------------------------------------------------------------------------
+ * DBus Constants
+ *
+ * Various constants of interface and method names mostly for use by clients
+ */
+
+/* constants for org.freedesktop.sssd.infopipe */
+#define INFOPIPE_IFACE "org.freedesktop.sssd.infopipe"
+#define INFOPIPE_IFACE_PING "Ping"
+
+/* ------------------------------------------------------------------------
+ * DBus Vtable handler structures
+ *
+ * These structures are filled in by implementors of the different
+ * dbus interfaces to handle method calls.
+ *
+ * Handler functions of type sbus_msg_handler_fn accept raw messages,
+ * other handlers will be typed appropriately. If a handler that is
+ * set to NULL is invoked it will result in a
+ * org.freedesktop.DBus.Error.NotSupported error for the caller.
+ */
+
+/* vtable for org.freedesktop.sssd.infopipe */
+struct infopipe_iface {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    sbus_msg_handler_fn Ping;
+};
+
+/* ------------------------------------------------------------------------
+ * DBus Interface Metadata
+ *
+ * These structure definitions are filled in with the information about
+ * the interfaces, methods, properties and so on.
+ *
+ * The actual definitions are found in the accompanying C file next
+ * to this header.
+ */
+
+/* interface info for org.freedesktop.sssd.infopipe */
+extern const struct sbus_interface_meta infopipe_iface_meta;
+
+#endif /* __IFP_IFACE_XML__ */
diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
index 32c7281ea40e3e12c3e2db9b1439bec713399fea..b97cb8a7d9e55f550a3eda0e9acc034329d4ba17 100644
--- a/src/responder/ifp/ifp_private.h
+++ b/src/responder/ifp/ifp_private.h
@@ -26,10 +26,24 @@
 
 #include "responder/common/responder.h"
 #include "providers/data_provider.h"
+#include "responder/ifp/ifp_iface_generated.h"
+
+#define INFOPIPE_PATH "/org/freedesktop/sssd/infopipe"
+
+struct sysbus_ctx {
+    struct sbus_connection *conn;
+    char *introspect_xml;
+};
 
 struct ifp_ctx {
     struct resp_ctx *rctx;
     struct sss_names_ctx *snctx;
+
+    struct sysbus_ctx *sysbus;
 };
 
+/* This is a throwaway method to ease the review of the patch.
+ * It will be removed later */
+int ifp_ping(struct sbus_request *dbus_req, void *data);
+
 #endif /* _IFPSRV_PRIVATE_H_ */
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index 06434c328359bdbf9e9241252eee0392c3017bce..accf679efe3332aa0fb57162e288ef67eaf54adb 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -61,6 +61,11 @@ static struct data_provider_iface ifp_dp_methods = {
     .getAccountInfo = NULL,
 };
 
+struct infopipe_iface ifp_iface = {
+    { &infopipe_iface_meta, 0 },
+    .Ping = ifp_ping,
+};
+
 struct sss_cmd_table *get_ifp_cmds(void)
 {
     static struct sss_cmd_table ifp_cmds[] = {
@@ -97,6 +102,95 @@ static void ifp_dp_reconnect_init(struct sbus_connection *conn,
                                  be_conn->domain->name);
 }
 
+static errno_t
+sysbus_init(TALLOC_CTX *mem_ctx,
+            struct tevent_context *ev,
+            const char *dbus_name,
+            const char *dbus_path,
+            struct sbus_vtable *iface_vtable,
+            void *pvt,
+            struct sysbus_ctx **sysbus)
+{
+    DBusError dbus_error;
+    DBusConnection *conn = NULL;
+    struct sysbus_ctx *system_bus = NULL;
+    struct sbus_interface *sif;
+    errno_t ret;
+
+    system_bus = talloc_zero(mem_ctx, struct sysbus_ctx);
+    if (system_bus == NULL) {
+        return ENOMEM;
+    }
+
+    dbus_error_init(&dbus_error);
+
+    /* Connect to the well-known system bus */
+    conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
+    if (conn == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Failed to connect to D-BUS system bus.\n"));
+        ret = EIO;
+        goto fail;
+    }
+    dbus_connection_set_exit_on_disconnect(conn, FALSE);
+
+    ret = dbus_bus_request_name(conn, dbus_name,
+                                /* We want exclusive access */
+                                DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                                &dbus_error);
+    if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+        /* We were unable to register on the system bus */
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Unable to request name on the system bus.\n"));
+        ret = EIO;
+        goto fail;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Listening on %s\n", dbus_name);
+
+    /* Integrate with tevent loop */
+    ret = sbus_init_connection(system_bus, ev, conn,
+                               SBUS_CONN_TYPE_SHARED,
+                               &system_bus->conn);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Could not integrate D-BUS into mainloop.\n");
+        goto fail;
+    }
+
+    sif = sbus_new_interface(system_bus->conn,
+                             dbus_path,
+                             iface_vtable,
+                             pvt);
+    if (sif == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Could not add the sbus interface\n");
+        goto fail;
+    }
+
+    ret = sbus_conn_add_interface(system_bus->conn, sif);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Could not add the interface\n");
+        goto fail;
+    }
+
+    *sysbus = system_bus;
+    return EOK;
+
+fail:
+    if (dbus_error_is_set(&dbus_error)) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "DBus error message: %s\n", dbus_error.message);
+        dbus_error_free(&dbus_error);
+    }
+
+    if (conn) dbus_connection_unref(conn);
+
+    talloc_free(system_bus);
+    return ret;
+}
+
 int ifp_process_init(TALLOC_CTX *mem_ctx,
                      struct tevent_context *ev,
                      struct confdb_ctx *cdb)
@@ -158,9 +252,23 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
                             ifp_dp_reconnect_init, iter);
     }
 
+    /* Connect to the D-BUS system bus and set up methods */
+    ret = sysbus_init(ifp_ctx, ifp_ctx->rctx->ev,
+                      INFOPIPE_IFACE,
+                      INFOPIPE_PATH,
+                      &ifp_iface.vtable,
+                      ifp_ctx, &ifp_ctx->sysbus);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Failed to connect to the system message bus\n");
+        talloc_free(ifp_ctx);
+        return EIO;
+    }
+
     ret = schedule_get_domains_task(rctx, rctx->ev, rctx);
     if (ret != EOK) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n");
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "schedule_get_domains_tasks failed.\n");
         goto fail;
     }
 
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index b9641ff605dc777fb3279751b08a995d148b12e5..4f73342dd8a8e5ef34a9061634e8f10c52e59964 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -30,3 +30,39 @@ struct cli_protocol_version *register_cli_protocol_version(void)
 
     return ssh_cli_protocol_version;
 }
+
+/* This is a throwaway method to ease the review of the patch.
+ * It will be removed later */
+int ifp_ping(struct sbus_request *dbus_req, void *data)
+{
+    struct ifp_ctx *ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+    static const char *pong = "PONG";
+    const char *request;
+    DBusError dberr;
+
+    if (ifp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+        return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
+    }
+
+
+    if (!sbus_request_parse_or_finish(dbus_req,
+                                      DBUS_TYPE_STRING, &request,
+                                      DBUS_TYPE_INVALID)) {
+        return EOK; /* handled */
+    }
+
+    DEBUG(SSSDBG_CONF_SETTINGS, "Got request for [%s]\n", request);
+
+    if (strcasecmp(request, "ping") != 0) {
+        dbus_error_init(&dberr);
+        dbus_set_error_const(&dberr,
+                             DBUS_ERROR_INVALID_ARGS,
+                             "Ping() only accepts ping as a param\n");
+        return sbus_request_fail_and_finish(dbus_req, &dberr);
+    }
+
+    return sbus_request_return_and_finish(dbus_req,
+                                          DBUS_TYPE_STRING, &pong,
+                                          DBUS_TYPE_INVALID);
+}
diff --git a/src/responder/ifp/org.freedesktop.sssd.infopipe.conf b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fea847ceed6b3d0f999f4bd747cc7b16df2124a9
--- /dev/null
+++ b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf
@@ -0,0 +1,22 @@
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- This configuration file specifies the required security policies
+       for the SSSD InfoPipe to work. -->
+
+  <!-- Only root can own (provide) the SSSD service -->
+  <policy user="root">
+    <allow own="org.freedesktop.sssd.infopipe"/>
+  </policy>
+
+  <!-- Allow all methods on the interface -->
+  <!-- Right now, this will be handled by a limited ACL
+       within the InfoPipe Daemon. -->
+  <policy context="default">
+    <allow send_interface="org.freedesktop.sssd.infopipe"/>
+  </policy>
+
+</busconfig>
-- 
1.8.5.3

