xdgmime: plug a small leak
[platform/upstream/glib.git] / gio / gunixcredentialsmessage.c
index 13556e1..7cbbab9 100644 (file)
  */
 
 /**
- * SECTION: gunixcredentialsmessage
+ * SECTION:gunixcredentialsmessage
  * @title: GUnixCredentialsMessage
  * @short_description: A GSocketControlMessage containing credentials
+ * @include: gio/gunixcredentialsmessage.h
  * @see_also: #GUnixConnection, #GSocketControlMessage
  *
  * This #GSocketControlMessage contains a #GCredentials instance.  It
  * may be sent using g_socket_send_message() and received using
  * g_socket_receive_message() over UNIX sockets (ie: sockets in the
- * %G_SOCKET_ADDRESS_UNIX family).
+ * %G_SOCKET_FAMILY_UNIX family).
  *
  * For an easier way to send and receive credentials over
- * stream-oriented UNIX sockets, see g_unix_connection_send_credentials() and
- * g_unix_connection_receive_credentials().
- **/
+ * stream-oriented UNIX sockets, see
+ * g_unix_connection_send_credentials() and
+ * g_unix_connection_receive_credentials(). To receive credentials of
+ * a foreign process connected to a socket, use
+ * g_socket_get_credentials().
+ */
 
 #include "config.h"
 
 /* ---------------------------------------------------------------------------------------------------- */
 #ifdef __linux__
-
-#define _GNU_SOURCE
-#define __USE_GNU
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.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
@@ -57,7 +65,6 @@
 #include "gcredentials.h"
 
 #include "glibintl.h"
-#include "gioalias.h"
 
 struct _GUnixCredentialsMessagePrivate
 {
@@ -77,6 +84,8 @@ g_unix_credentials_message_get_size (GSocketControlMessage *message)
 {
 #ifdef __linux__
   return sizeof (struct ucred);
+#elif defined(__FreeBSD__)
+  return sizeof (struct cmsgcred);
 #else
   return 0;
 #endif
@@ -85,7 +94,13 @@ 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__)
   return SOL_SOCKET;
+#else
+  return 0;
+#endif
 }
 
 static int
@@ -93,6 +108,8 @@ g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
 {
 #ifdef __linux__
   return SCM_CREDENTIALS;
+#elif defined(__FreeBSD__)
+  return SCM_CREDS;
 #else
   return 0;
 #endif
@@ -127,8 +144,42 @@ g_unix_credentials_message_deserialize (gint     level,
 
     ucred = data;
 
+    if (ucred->uid == (uid_t)-1 &&
+       ucred->gid == (gid_t)-1)
+      {
+       /* This happens if the remote side didn't pass the credentials */
+       goto out;
+      }
+
     credentials = g_credentials_new ();
-    g_credentials_set_native (credentials, ucred);
+    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 < 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:
@@ -145,7 +196,16 @@ g_unix_credentials_message_serialize (GSocketControlMessage *_message,
 {
   GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (_message);
 #ifdef __linux__
-  memcpy (data, g_credentials_get_native (message->priv->credentials), sizeof (struct ucred));
+  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));
+
 #endif
 }
 
@@ -157,8 +217,7 @@ g_unix_credentials_message_finalize (GObject *object)
   if (message->priv->credentials != NULL)
     g_object_unref (message->priv->credentials);
 
-  if (G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->finalize != NULL)
-    G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->finalize (object);
+  G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->finalize (object);
 }
 
 static void
@@ -252,8 +311,8 @@ g_unix_credentials_message_class_init (GUnixCredentialsMessageClass *class)
   g_object_class_install_property (gobject_class,
                                    PROP_CREDENTIALS,
                                    g_param_spec_object ("credentials",
-                                                        _("Credentials"),
-                                                        _("The credentials stored in the message"),
+                                                        P_("Credentials"),
+                                                        P_("The credentials stored in the message"),
                                                         G_TYPE_CREDENTIALS,
                                                         G_PARAM_READABLE |
                                                         G_PARAM_WRITABLE |
@@ -269,7 +328,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
  *
@@ -301,7 +360,7 @@ g_unix_credentials_message_new (void)
 }
 
 /**
- * g_unix_credentials_message_new:
+ * g_unix_credentials_message_new_with_credentials:
  * @credentials: A #GCredentials object.
  *
  * Creates a new #GUnixCredentialsMessage holding @credentials.
@@ -326,7 +385,7 @@ g_unix_credentials_message_new_with_credentials (GCredentials *credentials)
  *
  * Gets the credentials stored in @message.
  *
- * Returns: A #GCredentials instance. Do not free, it is owned by @message.
+ * Returns: (transfer none): A #GCredentials instance. Do not free, it is owned by @message.
  *
  * Since: 2.26
  */
@@ -336,7 +395,3 @@ g_unix_credentials_message_get_credentials (GUnixCredentialsMessage *message)
   g_return_val_if_fail (G_IS_UNIX_CREDENTIALS_MESSAGE (message), NULL);
   return message->priv->credentials;
 }
-
-
-#define __G_UNIX_CREDENTIALS_MESSAGE_C__
-#include "gioaliasdef.c"