mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
7eba41346e
- Make GCredentials instance and class structures private so it can't be subclassed and we don't have to worry about ABI compat issues. This also allows us to get rid of the GCredentialsPrivate struct. - Add a GCredentialsType enumeration that is used whenever exchanging pointers with the user. This allows us to support OSes with multiple native credential types. In particular, it allows supporting OSes where the native credential evolves or even changes over time. - Add g_socket_get_credentials() method. - Add tests for g_socket_get_credentials(). Right now this is in the GDBus peer-to-peer test case but we can change that later. - Move GTcpConnection into a separate gtk-doc page as was already half-done with GUnixConnection. Also finish the GUnixConnection move and ensure send_credentials() and receive_credentials() methods are in the docs. Also nuke comment about GTcpConnection being empty compared to its superclass. Signed-off-by: David Zeuthen <davidz@redhat.com>
347 lines
10 KiB
C
347 lines
10 KiB
C
/* GIO - GLib Input, Output and Streaming Library
|
|
*
|
|
* Copyright (C) 2010 Red Hat, Inc.
|
|
* Copyright (C) 2009 Codethink Limited
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; either version 2 of the licence or (at
|
|
* your option) any later version.
|
|
*
|
|
* See the included COPYING file for more information.
|
|
*
|
|
* Authors: David Zeuthen <davidz@redhat.com>
|
|
*/
|
|
|
|
/**
|
|
* 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_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(). To receive credentials of
|
|
* a foreign process connected to a socket, use
|
|
* g_socket_get_credentials().
|
|
*/
|
|
|
|
#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
|
|
|
|
#else
|
|
/* TODO: please add support for your UNIX flavor */
|
|
#define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 0
|
|
#endif
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "gunixcredentialsmessage.h"
|
|
#include "gcredentials.h"
|
|
|
|
#include "glibintl.h"
|
|
|
|
struct _GUnixCredentialsMessagePrivate
|
|
{
|
|
GCredentials *credentials;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_CREDENTIALS
|
|
};
|
|
|
|
G_DEFINE_TYPE (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);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
g_unix_credentials_message_get_level (GSocketControlMessage *message)
|
|
{
|
|
#ifdef __linux__
|
|
return SOL_SOCKET;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
|
|
{
|
|
#ifdef __linux__
|
|
return SCM_CREDENTIALS;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static GSocketControlMessage *
|
|
g_unix_credentials_message_deserialize (gint level,
|
|
gint type,
|
|
gsize size,
|
|
gpointer data)
|
|
{
|
|
GSocketControlMessage *message;
|
|
|
|
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:
|
|
;
|
|
}
|
|
#endif
|
|
|
|
return message;
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_serialize (GSocketControlMessage *_message,
|
|
gpointer data)
|
|
{
|
|
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));
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_finalize (GObject *object)
|
|
{
|
|
GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (object);
|
|
|
|
if (message->priv->credentials != NULL)
|
|
g_object_unref (message->priv->credentials);
|
|
|
|
G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_init (GUnixCredentialsMessage *message)
|
|
{
|
|
message->priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
|
|
G_TYPE_UNIX_CREDENTIALS_MESSAGE,
|
|
GUnixCredentialsMessagePrivate);
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CREDENTIALS:
|
|
g_value_set_object (value, message->priv->credentials);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CREDENTIALS:
|
|
message->priv->credentials = g_value_dup_object (value);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
g_unix_credentials_message_constructed (GObject *object)
|
|
{
|
|
GUnixCredentialsMessage *message = G_UNIX_CREDENTIALS_MESSAGE (object);
|
|
|
|
if (message->priv->credentials == NULL)
|
|
message->priv->credentials = g_credentials_new ();
|
|
|
|
if (G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->constructed != NULL)
|
|
G_OBJECT_CLASS (g_unix_credentials_message_parent_class)->constructed (object);
|
|
}
|
|
|
|
static void
|
|
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;
|
|
gobject_class->finalize = g_unix_credentials_message_finalize;
|
|
gobject_class->constructed = g_unix_credentials_message_constructed;
|
|
|
|
scm_class = G_SOCKET_CONTROL_MESSAGE_CLASS (class);
|
|
scm_class->get_size = g_unix_credentials_message_get_size;
|
|
scm_class->get_level = g_unix_credentials_message_get_level;
|
|
scm_class->get_type = g_unix_credentials_message_get_msg_type;
|
|
scm_class->serialize = g_unix_credentials_message_serialize;
|
|
scm_class->deserialize = g_unix_credentials_message_deserialize;
|
|
|
|
/**
|
|
* GUnixCredentialsMessage:credentials:
|
|
*
|
|
* The credentials stored in the message.
|
|
*
|
|
* Since: 2.26
|
|
*/
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_CREDENTIALS,
|
|
g_param_spec_object ("credentials",
|
|
P_("Credentials"),
|
|
P_("The credentials stored in the message"),
|
|
G_TYPE_CREDENTIALS,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_WRITABLE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_NAME |
|
|
G_PARAM_STATIC_BLURB |
|
|
G_PARAM_STATIC_NICK));
|
|
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* g_unix_credentials_message_is_supported:
|
|
*
|
|
* Checks if passing a #GCredential on a #GSocket is supported on this platform.
|
|
*
|
|
* Returns: %TRUE if supported, %FALSE otherwise
|
|
*
|
|
* Since: 2.26
|
|
*/
|
|
gboolean
|
|
g_unix_credentials_message_is_supported (void)
|
|
{
|
|
return G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* g_unix_credentials_message_new:
|
|
*
|
|
* Creates a new #GUnixCredentialsMessage with credentials matching the current processes.
|
|
*
|
|
* Returns: a new #GUnixCredentialsMessage
|
|
*
|
|
* Since: 2.26
|
|
*/
|
|
GSocketControlMessage *
|
|
g_unix_credentials_message_new (void)
|
|
{
|
|
g_return_val_if_fail (g_unix_credentials_message_is_supported (), NULL);
|
|
return g_object_new (G_TYPE_UNIX_CREDENTIALS_MESSAGE,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* g_unix_credentials_message_new_with_credentials:
|
|
* @credentials: A #GCredentials object.
|
|
*
|
|
* Creates a new #GUnixCredentialsMessage holding @credentials.
|
|
*
|
|
* Returns: a new #GUnixCredentialsMessage
|
|
*
|
|
* Since: 2.26
|
|
*/
|
|
GSocketControlMessage *
|
|
g_unix_credentials_message_new_with_credentials (GCredentials *credentials)
|
|
{
|
|
g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
|
|
g_return_val_if_fail (g_unix_credentials_message_is_supported (), NULL);
|
|
return g_object_new (G_TYPE_UNIX_CREDENTIALS_MESSAGE,
|
|
"credentials", credentials,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* g_unix_credentials_message_get_credentials:
|
|
* @message: A #GUnixCredentialsMessage.
|
|
*
|
|
* Gets the credentials stored in @message.
|
|
*
|
|
* Returns: A #GCredentials instance. Do not free, it is owned by @message.
|
|
*
|
|
* Since: 2.26
|
|
*/
|
|
GCredentials *
|
|
g_unix_credentials_message_get_credentials (GUnixCredentialsMessage *message)
|
|
{
|
|
g_return_val_if_fail (G_IS_UNIX_CREDENTIALS_MESSAGE (message), NULL);
|
|
return message->priv->credentials;
|
|
}
|