<xi:include href="xml/gsocketclient.xml"/>
<xi:include href="xml/gsocketconnection.xml"/>
<xi:include href="xml/gunixconnection.xml"/>
+ <xi:include href="xml/gtcpconnection.xml"/>
<xi:include href="xml/gsocketlistener.xml"/>
<xi:include href="xml/gsocketservice.xml"/>
<xi:include href="xml/gthreadedsocketservice.xml"/>
g_socket_get_remote_address
g_socket_get_socket_type
g_socket_speaks_ipv4
+g_socket_get_credentials
<SUBSECTION Standard>
GSocketClass
G_IS_SOCKET
g_socket_connection_get_remote_address
g_socket_connection_get_socket
<SUBSECTION>
-GTcpConnection
-g_tcp_connection_set_graceful_disconnect
-g_tcp_connection_get_graceful_disconnect
-<SUBSECTION>
-GUnixConnection
-g_unix_connection_receive_fd
-g_unix_connection_send_fd
-g_unix_connection_receive_credentials
-g_unix_connection_send_credentials
-<SUBSECTION>
g_socket_connection_factory_create_connection
g_socket_connection_factory_lookup_type
g_socket_connection_factory_register_type
G_SOCKET_CONNECTION_CLASS
G_SOCKET_CONNECTION_GET_CLASS
G_TYPE_SOCKET_CONNECTION
-GTcpConnectionClass
-G_IS_TCP_CONNECTION
-G_IS_TCP_CONNECTION_CLASS
-G_TCP_CONNECTION
-G_TCP_CONNECTION_CLASS
-G_TCP_CONNECTION_GET_CLASS
-G_TYPE_TCP_CONNECTION
<SUBSECTION Private>
GSocketConnectionPrivate
g_socket_connection_get_type
-GTcpConnectionPrivate
-g_tcp_connection_get_type
</SECTION>
<SECTION>
GUnixConnection
g_unix_connection_receive_fd
g_unix_connection_send_fd
+g_unix_connection_receive_credentials
+g_unix_connection_send_credentials
<SUBSECTION Standard>
GUnixConnectionClass
G_IS_UNIX_CONNECTION
</SECTION>
<SECTION>
+<FILE>gtcpconnection</FILE>
+<TITLE>GTcpConnection</TITLE>
+GTcpConnection
+g_tcp_connection_set_graceful_disconnect
+g_tcp_connection_get_graceful_disconnect
+<SUBSECTION Standard>
+GTcpConnectionClass
+G_IS_TCP_CONNECTION
+G_IS_TCP_CONNECTION_CLASS
+G_TYPE_TCP_CONNECTION
+G_TCP_CONNECTION
+G_TCP_CONNECTION_CLASS
+G_TCP_CONNECTION_GET_CLASS
+<SUBSECTION Private>
+GTcpConnectionPrivate
+g_tcp_connection_get_type
+</SECTION>
+
+<SECTION>
<FILE>gsocketcontrolmessage</FILE>
<TITLE>GSocketControlMessage</TITLE>
GSocketControlMessage
<FILE>gcredentials</FILE>
<TITLE>GCredentials</TITLE>
GCredentials
-GCredentialsClass
+GCredentialsType
g_credentials_new
g_credentials_to_string
g_credentials_get_native
#include <stdlib.h>
-#ifdef __linux__
-#define __USE_GNU
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <string.h>
-#endif
-
#include <gobject/gvaluecollector.h>
#include "gcredentials.h"
+#include "gnetworkingprivate.h"
#include "gioerror.h"
#include "glibintl.h"
* @short_description: An object containing credentials
* @include: gio/gio.h
*
- * The #GCredentials type is a reference-counted wrapper for the
- * native credentials type. This information is typically used for
- * identifying, authenticating and authorizing other processes.
+ * The #GCredentials type is a reference-counted wrapper for native
+ * credentials. This information is typically used for identifying,
+ * authenticating and authorizing other processes.
*
* Some operating systems supports looking up the credentials of the
* remote peer of a communication endpoint - see e.g.
* #GUnixCredentialsMessage, g_unix_connection_send_credentials() and
* g_unix_connection_receive_credentials() for details.
*
- * On Linux, the native credential type is a <literal>struct ucred</literal> - see
- * the <literal>unix(7)</literal> man page for details.
+ * On Linux, the native credential type is a <type>struct ucred</type>
+ * - see the
+ * <citerefentry><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ * man page for details. This corresponds to
+ * %G_CREDENTIALS_TYPE_LINUX_UCRED.
*/
-struct _GCredentialsPrivate
+/**
+ * GCredentials:
+ *
+ * The #GCredentials structure contains only private data and
+ * should only be accessed using the provided API.
+ *
+ * Since: 2.26
+ */
+struct _GCredentials
{
+ /*< private >*/
+ GObject parent_instance;
+
#ifdef __linux__
struct ucred native;
#else
#ifdef __GNUC__
#warning Please add GCredentials support for your OS
#endif
- guint foo;
#endif
};
+/**
+ * GCredentialsClass:
+ *
+ * Class structure for #GCredentials.
+ *
+ * Since: 2.26
+ */
+struct _GCredentialsClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+};
+
G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT);
static void
{
GObjectClass *gobject_class;
- g_type_class_add_private (klass, sizeof (GCredentialsPrivate));
-
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_credentials_finalize;
}
static void
g_credentials_init (GCredentials *credentials)
{
- credentials->priv = G_TYPE_INSTANCE_GET_PRIVATE (credentials, G_TYPE_CREDENTIALS, GCredentialsPrivate);
#ifdef __linux__
- credentials->priv->native.pid = getpid ();
- credentials->priv->native.uid = getuid ();
- credentials->priv->native.gid = getgid ();
+ credentials->native.pid = getpid ();
+ credentials->native.uid = getuid ();
+ credentials->native.gid = getgid ();
#endif
}
ret = g_string_new ("GCredentials:");
#ifdef __linux__
- g_string_append (ret, "linux:");
- if (credentials->priv->native.pid != -1)
- g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.pid);
- if (credentials->priv->native.uid != -1)
- g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.uid);
- if (credentials->priv->native.gid != -1)
- g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.gid);
+ g_string_append (ret, "linux-ucred:");
+ if (credentials->native.pid != -1)
+ g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
+ if (credentials->native.uid != -1)
+ g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
+ if (credentials->native.gid != -1)
+ g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
if (ret->str[ret->len - 1] == ',')
ret->str[ret->len - 1] = '\0';
#else
ret = FALSE;
#ifdef __linux__
- if (credentials->priv->native.uid == other_credentials->priv->native.uid)
+ if (credentials->native.uid == other_credentials->native.uid)
ret = TRUE;
#else
g_set_error_literal (error,
/**
* g_credentials_get_native:
* @credentials: A #GCredentials.
+ * @native_type: The type of native credentials to get.
*
- * Gets a pointer to the native credentials structure.
- *
- * Returns: The pointer or %NULL if there is no #GCredentials support
- * for the OS. Do not free the returned data, it is owned by
+ * Gets a pointer to native credentials of type @native_type from
* @credentials.
*
+ * It is a programming error (which will cause an warning to be
+ * logged) to use this method if there is no #GCredentials support for
+ * the OS or if @native_type isn't supported by the OS.
+ *
+ * Returns: The pointer to native credentials or %NULL if the
+ * operation there is no #GCredentials support for the OS or if
+ * @native_type isn't supported by the OS. Do not free the returned
+ * data, it is owned by @credentials.
+ *
* Since: 2.26
*/
gpointer
-g_credentials_get_native (GCredentials *credentials)
+g_credentials_get_native (GCredentials *credentials,
+ GCredentialsType native_type)
{
gpointer ret;
+
g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
+ ret = NULL;
+
#ifdef __linux__
- ret = &credentials->priv->native;
+ if (native_type != G_CREDENTIALS_TYPE_LINUX_UCRED)
+ {
+ g_warning ("g_credentials_get_native: Trying to get credentials of type %d but only "
+ "G_CREDENTIALS_TYPE_LINUX_UCRED is supported.",
+ native_type);
+ }
+ else
+ {
+ ret = &credentials->native;
+ }
#else
- ret = NULL;
+ g_warning ("g_credentials_get_native: Trying to get credentials but GLib has no support "
+ "for the native credentials type. Please add support.");
#endif
return ret;
/**
* g_credentials_set_native:
* @credentials: A #GCredentials.
+ * @native_type: The type of native credentials to set.
* @native: A pointer to native credentials.
*
- * Copies the native credentials from @native into @credentials.
+ * Copies the native credentials of type @native_type from @native
+ * into @credentials.
*
* It is a programming error (which will cause an warning to be
* logged) to use this method if there is no #GCredentials support for
- * the OS.
+ * the OS or if @native_type isn't supported by the OS.
*
* Since: 2.26
*/
void
-g_credentials_set_native (GCredentials *credentials,
- gpointer native)
+g_credentials_set_native (GCredentials *credentials,
+ GCredentialsType native_type,
+ gpointer native)
{
#ifdef __linux__
- memcpy (&credentials->priv->native, native, sizeof (struct ucred));
+ if (native_type != G_CREDENTIALS_TYPE_LINUX_UCRED)
+ {
+ g_warning ("g_credentials_set_native: Trying to set credentials of type %d "
+ "but only G_CREDENTIALS_TYPE_LINUX_UCRED is supported.",
+ native_type);
+ }
+ else
+ {
+ memcpy (&credentials->native, native, sizeof (struct ucred));
+ }
#else
g_warning ("g_credentials_set_native: Trying to set credentials but GLib has no support "
"for the native credentials type. Please add support.");
g_return_val_if_fail (error == NULL || *error == NULL, -1);
#ifdef __linux__
- ret = credentials->priv->native.uid;
+ ret = credentials->native.uid;
#else
ret = -1;
g_set_error_literal (error,
ret = FALSE;
#ifdef __linux__
- credentials->priv->native.uid = uid;
+ credentials->native.uid = uid;
ret = TRUE;
#else
g_set_error_literal (error,
#define G_IS_CREDENTIALS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CREDENTIALS))
typedef struct _GCredentialsClass GCredentialsClass;
-typedef struct _GCredentialsPrivate GCredentialsPrivate;
-
-/**
- * GCredentials:
- *
- * The #GCredentials structure contains only private data and
- * should only be accessed using the provided API.
- *
- * Since: 2.26
- */
-struct _GCredentials
-{
- /*< private >*/
- GObject parent_instance;
- GCredentialsPrivate *priv;
-};
-
-/**
- * GCredentialsClass:
- *
- * Class structure for #GCredentials.
- *
- * Since: 2.26
- */
-struct _GCredentialsClass
-{
- /*< private >*/
- GObjectClass parent_class;
-
- /* Padding for future expansion */
- void (*_g_reserved1) (void);
- void (*_g_reserved2) (void);
- void (*_g_reserved3) (void);
- void (*_g_reserved4) (void);
- void (*_g_reserved5) (void);
- void (*_g_reserved6) (void);
- void (*_g_reserved7) (void);
- void (*_g_reserved8) (void);
-};
GType g_credentials_get_type (void) G_GNUC_CONST;
gchar *g_credentials_to_string (GCredentials *credentials);
-gpointer g_credentials_get_native (GCredentials *credentials);
+gpointer g_credentials_get_native (GCredentials *credentials,
+ GCredentialsType native_type);
+
void g_credentials_set_native (GCredentials *credentials,
+ GCredentialsType native_type,
gpointer native);
gboolean g_credentials_is_same_user (GCredentials *credentials,
g_dbus_server_flags_get_type G_GNUC_CONST
g_dbus_signal_flags_get_type G_GNUC_CONST
g_dbus_send_message_flags_get_type G_GNUC_CONST
+g_credentials_type_get_type G_GNUC_CONST
#endif
#endif
g_socket_set_keepalive
g_socket_set_listen_backlog
g_socket_speaks_ipv4
+g_socket_get_credentials
#endif
#endif
G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL = (1<<0)
} GDBusSendMessageFlags;
+/**
+ * GCredentialsType:
+ * @G_CREDENTIALS_TYPE_INVALID: Indicates an invalid native credential type.
+ * @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a <type>struct ucred</type>.
+ *
+ * Enumeration describing different kinds of native credential types.
+ *
+ * Since: 2.26
+ */
+typedef enum
+{
+ G_CREDENTIALS_TYPE_INVALID,
+ G_CREDENTIALS_TYPE_LINUX_UCRED
+} GCredentialsType;
+
G_END_DECLS
#endif /* __GIO_ENUMS_H__ */
#else /* !G_OS_WIN32 */
+/* need this for struct ucred on Linux */
+#ifdef __linux__
+#define __USE_GNU
+#include <sys/types.h>
+#include <sys/socket.h>
+#undef __USE_GNU
+#endif
+
#include <sys/types.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include "gnetworkingprivate.h"
#include "gsocketaddress.h"
#include "gsocketcontrolmessage.h"
+#include "gcredentials.h"
#include "glibintl.h"
-
/**
* SECTION:gsocket
* @short_description: Low-level socket object
}
#endif
}
+
+/**
+ * g_socket_get_credentials:
+ * @socket: a #GSocket.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Returns the credentials of the foreign process connected to this
+ * socket, if any (e.g. it is only supported for %G_SOCKET_FAMILY_UNIX
+ * sockets).
+ *
+ * If this operation isn't supported on the OS, the method fails with
+ * the %G_IO_ERROR_NOT_SUPPORTED error. On Linux this is implemented
+ * by reading the %SO_PEERCRED option on the underlying socket.
+ *
+ * Other ways to obtain credentials from a foreign peer includes the
+ * #GUnixCredentialsMessage type and
+ * g_unix_connection_send_credentials() /
+ * g_unix_connection_receive_credentials() functions.
+ *
+ * Returns: %NULL if @error is set, otherwise a #GCredentials object
+ * that must be freed with g_object_unref().
+ *
+ * Since: 2.26
+ */
+GCredentials *
+g_socket_get_credentials (GSocket *socket,
+ GError **error)
+{
+ GCredentials *ret;
+
+ g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ ret = NULL;
+
+#ifdef __linux__
+ {
+ struct ucred native_creds;
+ socklen_t optlen;
+ optlen = sizeof (struct ucred);
+ if (getsockopt (socket->priv->fd,
+ SOL_SOCKET,
+ SO_PEERCRED,
+ (void *)&native_creds,
+ &optlen) != 0)
+ {
+ int errsv = get_socket_errno ();
+ g_set_error (error,
+ G_IO_ERROR,
+ socket_io_error_from_errno (errsv),
+ _("Unable to get pending error: %s"),
+ socket_strerror (errsv));
+ }
+ else
+ {
+ ret = g_credentials_new ();
+ g_credentials_set_native (ret,
+ G_CREDENTIALS_TYPE_LINUX_UCRED,
+ &native_creds);
+ }
+ }
+#else
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("g_socket_get_credentials not implemented for this OS"));
+#endif
+
+ return ret;
+}
GIOCondition condition,
GCancellable *cancellable);
gboolean g_socket_speaks_ipv4 (GSocket *socket);
+GCredentials *g_socket_get_credentials (GSocket *socket,
+ GError **error);
G_END_DECLS
/**
* SECTION: gtcpconnection
* @title: GTcpConnection
- * @short_description: a TCP #GSocketConnection
+ * @short_description: a TCP GSocketConnection
* @see_also: #GSocketConnection.
*
* This is the subclass of #GSocketConnection that is created
* for TCP/IP sockets.
*
- * It is currently empty; it offers no additional functionality
- * over its base class.
- *
- * Eventually, some TCP-specific socket stuff will be added.
- *
* Since: 2.22
*/
* byte to the stream, as this is required for credentials passing to
* work on some implementations.
*
+ * Other ways to exchange credentials with a foreign peer includes the
+ * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
+ *
* Note that this function only works on Linux, currently.
*
* Returns: %TRUE on success, %FALSE if @error is set.
* single byte from the stream, as this is required for credentials
* passing to work on some implementations.
*
+ * Other ways to exchange credentials with a foreign peer includes the
+ * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
+ *
* Returns: Received credentials on success (free with
* g_object_unref()), %NULL if @error is set.
*
* 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"
ucred = data;
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:
{
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));
#endif
}
#include <gio/gunixsocketaddress.h>
#include <gio/gunixfdlist.h>
+/* for struct ucred */
+#ifdef __linux__
+#define __USE_GNU
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
#include "gdbus-tests.h"
g_error_free (error);
#endif /* G_OS_UNIX */
+ /* Check that g_socket_get_credentials() work - this really should
+ * be in a GSocket-specific test suite but no such test suite exists
+ * right now.
+ */
+ {
+ GSocket *socket;
+ GCredentials *credentials;
+ socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
+ g_assert (G_IS_SOCKET (socket));
+ error = NULL;
+ credentials = g_socket_get_credentials (socket, &error);
+#ifdef __linux__
+ {
+ struct ucred *native_creds;
+ g_assert_no_error (error);
+ g_assert (G_IS_CREDENTIALS (credentials));
+ native_creds = g_credentials_get_native (credentials, G_CREDENTIALS_TYPE_LINUX_UCRED);
+ g_assert (native_creds != NULL);
+ g_assert (native_creds->uid == getuid ());
+ g_assert (native_creds->gid == getgid ());
+ g_assert (native_creds->pid == getpid ());
+ }
+ g_object_unref (credentials);
+#else
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+ g_assert (credentials == NULL);
+#endif
+ }
+
/* bring up a connection - don't accept it - this should fail
*/