*/
/**
- * SECTION: gunixcredentialsmessage
+ * SECTION:gunixcredentialsmessage
* @title: GUnixCredentialsMessage
* @short_description: A GSocketControlMessage containing credentials
* @include: gio/gunixcredentialsmessage.h
* 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 <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"
-#include "gioalias.h"
struct _GUnixCredentialsMessagePrivate
{
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);
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
+ return G_CREDENTIALS_NATIVE_SIZE;
#else
return 0;
#endif
static int
g_unix_credentials_message_get_level (GSocketControlMessage *message)
{
+#if G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
return SOL_SOCKET;
+#else
+ return 0;
+#endif
}
static int
g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
{
-#ifdef __linux__
+#if G_CREDENTIALS_USE_LINUX_UCRED
return SCM_CREDENTIALS;
+#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
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, ucred);
- 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), sizeof (struct ucred));
+
+ memcpy (data,
+ g_credentials_get_native (message->priv->credentials,
+ G_CREDENTIALS_NATIVE_TYPE),
+ G_CREDENTIALS_NATIVE_SIZE);
#endif
}
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
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;
/**
* 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
*
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
}
/* ---------------------------------------------------------------------------------------------------- */
*
* 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
*/
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"