%config(noreplace) not %conf
[moonshot-ui.git] / libmoonshot / libmoonshot-dbus.c
index 20e1a52..df1d46e 100644 (file)
  * Author: Sam Thursfield <samthursfield@codethink.co.uk>
  */
 
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib/gspawn.h>
+
 
 #include "libmoonshot.h"
 #include "libmoonshot-common.h"
 
+/*30 days in ms*/
+#define INFINITE_TIMEOUT 10*24*60*60*1000
+
 #define MOONSHOT_DBUS_NAME "org.janet.Moonshot"
 #define MOONSHOT_DBUS_PATH "/org/janet/moonshot"
 
@@ -56,14 +65,70 @@ void moonshot_free (void *data)
 {
     g_free (data);
 }
+static char *moonshot_launch_argv[] = {
+  MOONSHOT_LAUNCH_SCRIPT, NULL
+};
+
+static DBusGConnection *dbus_launch_moonshot()
+{
+    DBusGConnection *connection = NULL;
+    GError *error = NULL;
+    DBusError dbus_error;
+    GPid child_pid;
+    gint fd_stdin = -1, fd_stdout = -1;
+    ssize_t addresslen;
+    dbus_error_init(&dbus_error);
+    char dbus_address[1024];
+  
+    if (g_spawn_async_with_pipes( NULL /*cwd*/,
+                                 moonshot_launch_argv, NULL /*environ*/,
+                                 0 /*flags*/, NULL /*setup*/, NULL,
+                                 &child_pid, &fd_stdin, &fd_stdout,
+                                 NULL /*stderr*/, NULL /*error*/) == 0 ) {
+      return NULL;
+    }
+
+    addresslen = read( fd_stdout, dbus_address, sizeof dbus_address);
+    close(fd_stdout);
+    /* we require at least 2 octets of address because we trim the newline*/
+    if (addresslen <= 1) {
+    fail: dbus_error_free(&dbus_error);
+      if (connection != NULL)
+       dbus_g_connection_unref(connection);
+      close(fd_stdin);
+      g_spawn_close_pid(child_pid);
+      return NULL;
+    }
+    dbus_address[addresslen-1] = '\0';
+    connection = dbus_g_connection_open(dbus_address, &error);
+    if (error) {
+      g_error_free(error);
+      goto fail;
+    }
+    if (!dbus_bus_register(dbus_g_connection_get_connection(connection),
+                          &dbus_error))
+      goto fail;
+       return connection;
+}
+
+static int is_setid()
+{
+#ifdef HAVE_GETEUID
+  if ((getuid() != geteuid()) || 
+      (getgid() != getegid())) {
+    return 1;
+  }
+#endif
+  return 0;
+}
 
 static DBusGProxy *dbus_connect (MoonshotError **error)
 {
-    DBusConnection  *connection;
+    DBusConnection  *dbconnection;
     DBusError        dbus_error;
-    DBusGConnection *g_connection;
+    DBusGConnection *connection;
     DBusGProxy      *g_proxy;
-    GError          *g_error;
+    GError          *g_error = NULL;
     dbus_bool_t      name_has_owner;
 
     g_return_val_if_fail (*error == NULL, NULL);
@@ -75,17 +140,33 @@ static DBusGProxy *dbus_connect (MoonshotError **error)
      * If/when we move to GDBus this code can become a one-liner.
      */
 
-    connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
-
-    if (dbus_error_is_set (&dbus_error)) {
+    if (is_setid()) {
         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
-                                     "DBus error: %s",
-                                     dbus_error.message);
-        dbus_error_free (&dbus_error);
+                                    "Cannot use IPC while setid");
+        return NULL;
+    }
+
+    connection = dbus_g_bus_get (DBUS_BUS_SESSION, &g_error);
+
+    if (g_error_matches(g_error, DBUS_GERROR, DBUS_GERROR_NOT_SUPPORTED)) {
+      /*Generally this means autolaunch failed because probably DISPLAY is unset*/
+      connection = dbus_launch_moonshot();
+      if (connection != NULL) {
+       g_error_free(g_error);
+       g_error = NULL;
+      }
+    }
+
+    if (g_error != NULL) {
+      *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
+                                  "DBus error: %s",
+                                  g_error->message);
+      g_error_free (g_error);
         return NULL;
     }
 
-    name_has_owner  = dbus_bus_name_has_owner (connection,
+    dbconnection = dbus_g_connection_get_connection(connection);
+    name_has_owner  = dbus_bus_name_has_owner (dbconnection,
                                                MOONSHOT_DBUS_NAME,
                                                &dbus_error);
 
@@ -98,7 +179,7 @@ static DBusGProxy *dbus_connect (MoonshotError **error)
     }
 
     if (! name_has_owner) {
-        dbus_bus_start_service_by_name (connection,
+        dbus_bus_start_service_by_name (dbconnection,
                                         MOONSHOT_DBUS_NAME,
                                         0,
                                         NULL,
@@ -124,17 +205,7 @@ static DBusGProxy *dbus_connect (MoonshotError **error)
     /* Now the service should be running */
     g_error = NULL;
 
-    g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &g_error);
-
-    if (g_error != NULL) {
-        *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
-                                     "DBus error: %s",
-                                     g_error->message);
-        g_error_free (g_error);
-        return NULL;
-    }
-
-    g_proxy = dbus_g_proxy_new_for_name_owner (g_connection,
+    g_proxy = dbus_g_proxy_new_for_name_owner (connection,
                                                MOONSHOT_DBUS_NAME,
                                                MOONSHOT_DBUS_PATH,
                                                MOONSHOT_DBUS_NAME,
@@ -196,9 +267,10 @@ int moonshot_get_identity (const char     *nai,
 
     g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
 
-    dbus_g_proxy_call (dbus_proxy,
+    dbus_g_proxy_call_with_timeout (dbus_proxy,
                        "GetIdentity",
-                       &g_error,
+                                   INFINITE_TIMEOUT,
+                                   &g_error,
                        G_TYPE_STRING, nai,
                        G_TYPE_STRING, password,
                        G_TYPE_STRING, service,
@@ -249,8 +321,9 @@ int moonshot_get_default_identity (char          **nai_out,
 
     g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
 
-    dbus_g_proxy_call (dbus_proxy,
+    dbus_g_proxy_call_with_timeout (dbus_proxy,
                        "GetDefaultIdentity",
+                                   INFINITE_TIMEOUT,
                        &g_error,
                        G_TYPE_INVALID,
                        G_TYPE_STRING, nai_out,
@@ -294,6 +367,7 @@ int moonshot_install_id_card (const char     *display_name,
                               const char     *subject,
                               const char     *subject_alt,
                               const char     *server_cert,
+                              int            force_flat_file_store,
                               MoonshotError **error)
 {
     GError      *g_error = NULL;
@@ -343,6 +417,7 @@ int moonshot_install_id_card (const char     *display_name,
                        G_TYPE_STRING, subject,
                        G_TYPE_STRING, subject_alt,
                        G_TYPE_STRING, server_cert,
+                       G_TYPE_INT, force_flat_file_store,
                        G_TYPE_INVALID,
                        G_TYPE_BOOLEAN, &success,
                        G_TYPE_INVALID);