hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gunixcredentialsmessage.c
index a1094be..77612f1 100644 (file)
 #include "config.h"
 
 /* ---------------------------------------------------------------------------------------------------- */
-#ifdef __linux__
 
-#define _GNU_SOURCE
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
 #include <fcntl.h>
-#define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
-
-#elif defined(__FreeBSD__)
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <fcntl.h>
-#define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
-#else
-/* TODO: please add support for your UNIX flavor */
-#define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 0
-#endif
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-#include <string.h>
 #include <errno.h>
+#include <string.h>
+#include <unistd.h>
 
 #include "gunixcredentialsmessage.h"
 #include "gcredentials.h"
+#include "gcredentialsprivate.h"
+#include "gnetworking.h"
 
 #include "glibintl.h"
 
@@ -79,15 +60,13 @@ enum
   PROP_CREDENTIALS
 };
 
-G_DEFINE_TYPE (GUnixCredentialsMessage, g_unix_credentials_message, G_TYPE_SOCKET_CONTROL_MESSAGE);
+G_DEFINE_TYPE_WITH_PRIVATE (GUnixCredentialsMessage, g_unix_credentials_message, G_TYPE_SOCKET_CONTROL_MESSAGE)
 
 static gsize
 g_unix_credentials_message_get_size (GSocketControlMessage *message)
 {
-#ifdef __linux__
-  return sizeof (struct ucred);
-#elif defined(__FreeBSD__)
-  return sizeof (struct cmsgcred);
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
+  return G_CREDENTIALS_NATIVE_SIZE;
 #else
   return 0;
 #endif
@@ -96,9 +75,7 @@ g_unix_credentials_message_get_size (GSocketControlMessage *message)
 static int
 g_unix_credentials_message_get_level (GSocketControlMessage *message)
 {
-#ifdef __linux__
-  return SOL_SOCKET;
-#elif defined(__FreeBSD__)
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
   return SOL_SOCKET;
 #else
   return 0;
@@ -108,10 +85,16 @@ g_unix_credentials_message_get_level (GSocketControlMessage *message)
 static int
 g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
 {
-#ifdef __linux__
+#if G_CREDENTIALS_USE_LINUX_UCRED
   return SCM_CREDENTIALS;
-#elif defined(__FreeBSD__)
+#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
   return SCM_CREDS;
+#elif G_CREDENTIALS_USE_NETBSD_UNPCBID
+  return SCM_CREDS;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+  return SCM_UCRED;
+#elif G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
+  #error "G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED is set but there is no msg_type defined for this platform"
 #else
   return 0;
 #endif
@@ -123,84 +106,53 @@ g_unix_credentials_message_deserialize (gint     level,
                                         gsize    size,
                                         gpointer data)
 {
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
   GSocketControlMessage *message;
+  GCredentials *credentials;
 
-  message = NULL;
-
-#ifdef __linux__
-  {
-    GCredentials *credentials;
-    struct ucred *ucred;
-
-    if (level != SOL_SOCKET || type != SCM_CREDENTIALS)
-      goto out;
-
-    if (size != sizeof (struct ucred))
-      {
-        g_warning ("Expected a struct ucred (%" G_GSIZE_FORMAT " bytes) but "
-                   "got %" G_GSIZE_FORMAT " bytes of data",
-                   sizeof (struct ucred),
-                   size);
-        goto out;
-      }
-
-    ucred = data;
-
-    credentials = g_credentials_new ();
-    g_credentials_set_native (credentials, G_CREDENTIALS_TYPE_LINUX_UCRED, ucred);
-    message = g_unix_credentials_message_new_with_credentials (credentials);
-    g_object_unref (credentials);
- out:
-    ;
-  }
-#elif defined(__FreeBSD__)
-  {
-    GCredentials *credentials;
-    struct cmsgcred *cred;
-
-    if (level != SOL_SOCKET || type != SCM_CREDS)
-      {
-        goto out;
-      }
-    if (size < CMSG_LEN (sizeof *cred))
-      {
-        g_warning ("Expected a struct cmsgcred (%" G_GSIZE_FORMAT " bytes) but "
-                   "got %" G_GSIZE_FORMAT " bytes of data",
-                   CMSG_LEN (sizeof *cred),
-                   size);
-        goto out;
-      }
-
-    cred = data;
-
-    credentials = g_credentials_new ();
-    g_credentials_set_native (credentials, G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED, cred);
-    message = g_unix_credentials_message_new_with_credentials (credentials);
-    g_object_unref (credentials);
- out:
-    ;
-  }
-#endif
+  if (level != SOL_SOCKET || type != g_unix_credentials_message_get_msg_type (NULL))
+    return NULL;
+
+  if (size != G_CREDENTIALS_NATIVE_SIZE)
+    {
+      g_warning ("Expected a credentials struct of %" G_GSIZE_FORMAT " bytes but "
+                 "got %" G_GSIZE_FORMAT " bytes of data",
+                 G_CREDENTIALS_NATIVE_SIZE, size);
+      return NULL;
+    }
+
+  credentials = g_credentials_new ();
+  g_credentials_set_native (credentials, G_CREDENTIALS_NATIVE_TYPE, data);
+
+  if (g_credentials_get_unix_user (credentials, NULL) == (uid_t) -1)
+    {
+      /* This happens on Linux if the remote side didn't pass the credentials */
+      g_object_unref (credentials);
+      return NULL;
+    }
+
+  message = g_unix_credentials_message_new_with_credentials (credentials);
+  g_object_unref (credentials);
 
   return message;
+
+#else /* !G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED */
+
+  return NULL;
+#endif
 }
 
 static void
 g_unix_credentials_message_serialize (GSocketControlMessage *_message,
                                       gpointer               data)
 {
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
   GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (_message);
-#ifdef __linux__
-  memcpy (data,
-          g_credentials_get_native (message->priv->credentials,
-                                    G_CREDENTIALS_TYPE_LINUX_UCRED),
-          sizeof (struct ucred));
-#elif defined(__FreeBSD__)
+
   memcpy (data,
           g_credentials_get_native (message->priv->credentials,
-                                    G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED),
-          sizeof (struct cmsgcred));
-
+                                    G_CREDENTIALS_NATIVE_TYPE),
+          G_CREDENTIALS_NATIVE_SIZE);
 #endif
 }
 
@@ -218,9 +170,7 @@ g_unix_credentials_message_finalize (GObject *object)
 static void
 g_unix_credentials_message_init (GUnixCredentialsMessage *message)
 {
-  message->priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
-                                               G_TYPE_UNIX_CREDENTIALS_MESSAGE,
-                                               GUnixCredentialsMessagePrivate);
+  message->priv = g_unix_credentials_message_get_instance_private (message);
 }
 
 static void
@@ -281,8 +231,6 @@ g_unix_credentials_message_class_init (GUnixCredentialsMessageClass *class)
   GSocketControlMessageClass *scm_class;
   GObjectClass *gobject_class;
 
-  g_type_class_add_private (class, sizeof (GUnixCredentialsMessagePrivate));
-
   gobject_class = G_OBJECT_CLASS (class);
   gobject_class->get_property = g_unix_credentials_message_get_property;
   gobject_class->set_property = g_unix_credentials_message_set_property;
@@ -323,7 +271,7 @@ g_unix_credentials_message_class_init (GUnixCredentialsMessageClass *class)
 /**
  * g_unix_credentials_message_is_supported:
  *
- * Checks if passing a #GCredential on a #GSocket is supported on this platform.
+ * Checks if passing #GCredentials on a #GSocket is supported on this platform.
  *
  * Returns: %TRUE if supported, %FALSE otherwise
  *
@@ -332,7 +280,11 @@ g_unix_credentials_message_class_init (GUnixCredentialsMessageClass *class)
 gboolean
 g_unix_credentials_message_is_supported (void)
 {
-  return G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED;
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
+  return TRUE;
+#else
+  return FALSE;
+#endif
 }
 
 /* ---------------------------------------------------------------------------------------------------- */