diff options
author | David Zeuthen <davidz@redhat.com> | 2010-05-06 15:31:45 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-05-06 15:31:45 -0400 |
commit | c490c14f4e3fbbe8c74b26e6cacac31b0e744c92 (patch) | |
tree | df9113881a866c54b5ef870900e2bd0ae581257b /gio | |
parent | d0a14469d09d5fe23de219ba293fd4a266b02ced (diff) | |
download | glib-c490c14f4e3fbbe8c74b26e6cacac31b0e744c92.tar.gz |
Set up gtk-doc for GDBus
Also move send_credentials() and receive_credentials() to
GUnixConnection. This code might change, discussion is still ongoing
in
https://bugzilla.gnome.org/show_bug.cgi?id=617483.
Diffstat (limited to 'gio')
-rw-r--r-- | gio/gcredentials.c | 4 | ||||
-rw-r--r-- | gio/gdbusaddress.c | 2 | ||||
-rw-r--r-- | gio/gdbusauth.c | 189 | ||||
-rw-r--r-- | gio/gdbusauthobserver.c | 2 | ||||
-rw-r--r-- | gio/gdbusconnection.c | 8 | ||||
-rw-r--r-- | gio/gdbuserror.c | 2 | ||||
-rw-r--r-- | gio/gdbusintrospection.c | 2 | ||||
-rw-r--r-- | gio/gdbusmessage.c | 2 | ||||
-rw-r--r-- | gio/gdbusmethodinvocation.c | 2 | ||||
-rw-r--r-- | gio/gdbusnameowning.c | 4 | ||||
-rw-r--r-- | gio/gdbusnamewatching.c | 4 | ||||
-rw-r--r-- | gio/gdbusproxy.c | 2 | ||||
-rw-r--r-- | gio/gdbusproxywatching.c | 4 | ||||
-rw-r--r-- | gio/gdbusserver.c | 4 | ||||
-rw-r--r-- | gio/gdbusutils.c | 2 | ||||
-rw-r--r-- | gio/gunixconnection.c | 258 | ||||
-rw-r--r-- | gio/gunixconnection.h | 10 |
17 files changed, 290 insertions, 211 deletions
diff --git a/gio/gcredentials.c b/gio/gcredentials.c index e1712fe61..1ca25432b 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -36,8 +36,8 @@ /** * SECTION:gcredentials - * @short_description: Credentials - * @include: gdbus/gdbus.h + * @short_description: An object containing credentials + * @include: gio/gio.h * * The #GCredentials type is used for storing information that can be * used for identifying, authenticating and authorizing processes. diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index e50e73781..6cfa5f951 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -40,7 +40,7 @@ * SECTION:gdbusaddress * @title: D-Bus Addresses * @short_description: D-Bus connection endpoints - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Routines for working with D-Bus addresses. */ diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index 850db9aa6..2d47060cd 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -78,195 +78,6 @@ debug_print (const gchar *message, ...) #endif } - -/* ---------------------------------------------------------------------------------------------------- */ -/* TODO: move to gio */ - -/** - * g_unix_connection_send_credentials: - * @connection: A #GUnixConnection. - * @credentials: A #GCredentials to send. - * @cancellable: A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Passes the credentials stored in @credentials to the recieving side - * of the connection. The recieving end has to call - * g_unix_connection_receive_credentials() (or similar) to accept the - * credentials. - * - * The credentials which the sender specifies are checked by the - * kernel. A process with effective user ID 0 is allowed to specify - * values that do not match its own. This means that the credentials - * can be used to authenticate other connections. - * - * As well as sending the credentials this also writes a single NUL - * byte to the stream, as this is required for credentials passing to - * work on some implementations. - * - * Returns: %TRUE on success, %FALSE if @error is set. - * - * Since: 2.26 - */ -static gboolean -g_unix_connection_send_credentials (GUnixConnection *connection, - GCredentials *credentials, - GCancellable *cancellable, - GError **error) -{ - GSocketControlMessage *scm; - GSocket *socket; - gboolean ret; - GOutputVector vector; - guchar nul_byte[1] = {'\0'}; - - g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE); - g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - ret = FALSE; - - vector.buffer = &nul_byte; - vector.size = 1; - scm = g_unix_credentials_message_new_with_credentials (credentials); - g_object_get (connection, "socket", &socket, NULL); - if (g_socket_send_message (socket, - NULL, /* address */ - &vector, - 1, - &scm, - 1, - G_SOCKET_MSG_NONE, - cancellable, - error) != 1) - { - g_prefix_error (error, _("Error sending credentials: ")); - goto out; - } - - ret = TRUE; - - out: - g_object_unref (socket); - g_object_unref (scm); - return ret; -} - -/** - * g_unix_connection_receive_credentials: - * @connection: A #GUnixConnection. - * @cancellable: A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Receives credentials from the sending end of the connection. The - * sending end has to call g_unix_connection_send_credentials() (or - * similar) for this to work. - * - * As well as reading the credentials this also reads (and discards) a - * single byte from the stream, as this is required for credentials - * passing to work on some implementations. - * - * Returns: Received credentials on success (free with - * g_object_unref()), %NULL if @error is set. - * - * Since: 2.26 - */ -static GCredentials * -g_unix_connection_receive_credentials (GUnixConnection *connection, - GCancellable *cancellable, - GError **error) -{ - GCredentials *ret; - GSocketControlMessage **scms; - gint nscm; - GSocket *socket; - gint n; - volatile GType credentials_message_gtype; - gssize num_bytes_read; - - g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - ret = NULL; - scms = NULL; - - g_object_get (connection, "socket", &socket, NULL); - -#if 1 - /* TODO: Move this to gsocket.c... */ - { - int opt_val = 1; - if (setsockopt (g_socket_get_fd (socket), - SOL_SOCKET, - SO_PASSCRED, - &opt_val, - sizeof opt_val) != 0) - { - g_warning ("boo, error setting SO_PASSCRED: %m"); - } - } -#endif - - /* ensure the type of GUnixCredentialsMessage has been registered with the type system */ - credentials_message_gtype = G_TYPE_UNIX_CREDENTIALS_MESSAGE; - num_bytes_read = g_socket_receive_message (socket, - NULL, /* GSocketAddress **address */ - NULL, - 0, - &scms, - &nscm, - NULL, - cancellable, - error); - if (num_bytes_read != 1) - { - /* Handle situation where g_socket_receive_message() returns - * 0 bytes and not setting @error - */ - if (num_bytes_read == 0 && error != NULL && *error == NULL) - { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Expecting to read a single byte for receiving credentials but read zero bytes")); - } - goto out; - } - - if (nscm != 1) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Expecting 1 control message, got %d"), - nscm); - goto out; - } - - if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0])) - { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Unexpected type of ancillary data")); - goto out; - } - - ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0])); - g_object_ref (ret); - - out: - if (scms != NULL) - { - for (n = 0; n < nscm; n++) - g_object_unref (scms[n]); - g_free (scms); - } - g_object_unref (socket); - return ret; -} - -/* ---------------------------------------------------------------------------------------------------- */ - typedef struct { const gchar *name; diff --git a/gio/gdbusauthobserver.c b/gio/gdbusauthobserver.c index f0411aba8..4de672283 100644 --- a/gio/gdbusauthobserver.c +++ b/gio/gdbusauthobserver.c @@ -33,7 +33,7 @@ /** * SECTION:gdbusauthobserver * @short_description: Object used for authenticating connections - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * The #GDBusAuthObserver type provides a mechanism for participating * in how a #GDBusServer (or a #GDBusConnection) authenticates remote diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index 0bcd58f89..fdcb6ed29 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -78,7 +78,7 @@ /** * SECTION:gdbusconnection * @short_description: D-Bus Connections - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * <para><note> * This class is rarely used directly in D-Bus clients. If you are @@ -89,11 +89,11 @@ * The #GDBusConnection type is used for D-Bus connections to remote * peers such as a message buses. * - * <example id="gdbus-server"><title>D-Bus server example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-server"><title>D-Bus server example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> * - * <example id="gdbus-subtree-server"><title>D-Bus subtree example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-subtree.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-subtree-server"><title>D-Bus subtree example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-subtree.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> * - * <example id="gdbus-unix-fd-client"><title>D-Bus UNIX File Descriptor example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-unix-fd-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-unix-fd-client"><title>D-Bus UNIX File Descriptor example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-unix-fd-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> */ /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/gdbuserror.c b/gio/gdbuserror.c index 3b0e080fc..5bc9c69ca 100644 --- a/gio/gdbuserror.c +++ b/gio/gdbuserror.c @@ -36,7 +36,7 @@ * SECTION:gdbuserror * @title: GDBusError * @short_description: Mapping D-Bus errors to and from #GError - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * All facilities that return errors from remote methods (such as * g_dbus_connection_invoke_method_sync()) use #GError to represent diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index 63b945e0e..c76af4eb8 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -32,7 +32,7 @@ * SECTION:gdbusintrospection * @title: Introspection XML * @short_description: Parse and Generate Introspection XML - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Various data structures and convenience routines to parse and * generate D-Bus introspection XML. diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c index 668b1c856..d1929ae3c 100644 --- a/gio/gdbusmessage.c +++ b/gio/gdbusmessage.c @@ -48,7 +48,7 @@ /** * SECTION:gdbusmessage * @short_description: D-Bus Message - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * A type for representing D-Bus messages that can be sent or received * on a #GDBusConnection. diff --git a/gio/gdbusmethodinvocation.c b/gio/gdbusmethodinvocation.c index dc6950bea..5885abcec 100644 --- a/gio/gdbusmethodinvocation.c +++ b/gio/gdbusmethodinvocation.c @@ -36,7 +36,7 @@ /** * SECTION:gdbusmethodinvocation * @short_description: Object for handling remote calls - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Instances of the #GDBusMethodInvocation class are used when * handling D-Bus method calls. It provides a way to asynchronously diff --git a/gio/gdbusnameowning.c b/gio/gdbusnameowning.c index 30901651f..e840353f8 100644 --- a/gio/gdbusnameowning.c +++ b/gio/gdbusnameowning.c @@ -36,11 +36,11 @@ * SECTION:gdbusnameowning * @title: Owning Bus Names * @short_description: Simple API for owning bus names - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Convenience API for owning bus names. * - * <example id="gdbus-owning-names"><title>Simple application owning a name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-own-name.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-owning-names"><title>Simple application owning a name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-own-name.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> */ G_LOCK_DEFINE_STATIC (lock); diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c index 92e04cc18..6ae4754da 100644 --- a/gio/gdbusnamewatching.c +++ b/gio/gdbusnamewatching.c @@ -36,11 +36,11 @@ * SECTION:gdbusnamewatching * @title: Watching Bus Names * @short_description: Simple API for watching bus names - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Convenience API for watching bus names. * - * <example id="gdbus-watching-names"><title>Simple application watching a name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-watch-name.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-watching-names"><title>Simple application watching a name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-watch-name.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> */ G_LOCK_DEFINE_STATIC (lock); diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c index 39094d0b4..89aced924 100644 --- a/gio/gdbusproxy.c +++ b/gio/gdbusproxy.c @@ -42,7 +42,7 @@ /** * SECTION:gdbusproxy * @short_description: Base class for proxies - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * #GDBusProxy is a base class used for proxies to access a D-Bus * interface on a remote object. A #GDBusProxy can only be constructed diff --git a/gio/gdbusproxywatching.c b/gio/gdbusproxywatching.c index 4f85c1de5..4025e1f92 100644 --- a/gio/gdbusproxywatching.c +++ b/gio/gdbusproxywatching.c @@ -39,11 +39,11 @@ * SECTION:gdbusproxywatching * @title: Watching Proxies * @short_description: Simple API for watching proxies - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Convenience API for watching bus proxies. * - * <example id="gdbus-watching-proxy"><title>Simple application watching a proxy</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-watch-proxy.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-watching-proxy"><title>Simple application watching a proxy</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-watch-proxy.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> */ /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/gdbusserver.c b/gio/gdbusserver.c index 0d0deeaa2..99e7701a2 100644 --- a/gio/gdbusserver.c +++ b/gio/gdbusserver.c @@ -44,12 +44,12 @@ /** * SECTION:gdbusserver * @short_description: Helper for accepting connections - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * #GDBusServer is a helper for listening to and accepting D-Bus * connections. * - * <example id="gdbus-peer-to-peer"><title>D-Bus peer-to-peer example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../../gio/tests/gdbus-example-peer.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * <example id="gdbus-peer-to-peer"><title>D-Bus peer-to-peer example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-peer.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> */ struct _GDBusServerPrivate diff --git a/gio/gdbusutils.c b/gio/gdbusutils.c index b1ec0ea1c..00529168a 100644 --- a/gio/gdbusutils.c +++ b/gio/gdbusutils.c @@ -33,7 +33,7 @@ * SECTION:gdbusutils * @title: D-Bus Utilities * @short_description: Various utilities related to D-Bus. - * @include: gdbus/gdbus.h + * @include: gio/gio.h * * Various utility routines related to D-Bus. */ diff --git a/gio/gunixconnection.c b/gio/gunixconnection.c index 92ad246f8..8b618cb0a 100644 --- a/gio/gunixconnection.c +++ b/gio/gunixconnection.c @@ -36,6 +36,14 @@ #include <gio/gsocket.h> #include <unistd.h> +#ifdef __linux__ +/* for getsockopt() and setsockopt() */ +#include <sys/types.h> /* See NOTES */ +#include <sys/socket.h> +#include <errno.h> +#include <string.h> +#endif + #include "gioalias.h" G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection, @@ -287,5 +295,255 @@ gboolean g_unix_connection_create_pair (GUnixCo GError **error); */ + +/** + * g_unix_connection_send_credentials: + * @connection: A #GUnixConnection. + * @credentials: A #GCredentials to send. + * @cancellable: A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Passes the credentials stored in @credentials to the recieving side + * of the connection. The recieving end has to call + * g_unix_connection_receive_credentials() (or similar) to accept the + * credentials. + * + * The credentials which the sender specifies are checked by the + * kernel. A process with effective user ID 0 is allowed to specify + * values that do not match its own. This means that the credentials + * can be used to authenticate other connections. + * + * As well as sending the credentials this also writes a single NUL + * byte to the stream, as this is required for credentials passing to + * work on some implementations. + * + * Returns: %TRUE on success, %FALSE if @error is set. + * + * Since: 2.26 + */ +gboolean +g_unix_connection_send_credentials (GUnixConnection *connection, + GCredentials *credentials, + GCancellable *cancellable, + GError **error) +{ + GSocketControlMessage *scm; + GSocket *socket; + gboolean ret; + GOutputVector vector; + guchar nul_byte[1] = {'\0'}; + + g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE); + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + ret = FALSE; + + vector.buffer = &nul_byte; + vector.size = 1; + scm = g_unix_credentials_message_new_with_credentials (credentials); + g_object_get (connection, "socket", &socket, NULL); + if (g_socket_send_message (socket, + NULL, /* address */ + &vector, + 1, + &scm, + 1, + G_SOCKET_MSG_NONE, + cancellable, + error) != 1) + { + g_prefix_error (error, _("Error sending credentials: ")); + goto out; + } + + ret = TRUE; + + out: + g_object_unref (socket); + g_object_unref (scm); + return ret; +} + +/** + * g_unix_connection_receive_credentials: + * @connection: A #GUnixConnection. + * @cancellable: A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Receives credentials from the sending end of the connection. The + * sending end has to call g_unix_connection_send_credentials() (or + * similar) for this to work. + * + * As well as reading the credentials this also reads (and discards) a + * single byte from the stream, as this is required for credentials + * passing to work on some implementations. + * + * Returns: Received credentials on success (free with + * g_object_unref()), %NULL if @error is set. + * + * Since: 2.26 + */ +GCredentials * +g_unix_connection_receive_credentials (GUnixConnection *connection, + GCancellable *cancellable, + GError **error) +{ + GCredentials *ret; + GSocketControlMessage **scms; + gint nscm; + GSocket *socket; + gint n; + volatile GType credentials_message_gtype; + gssize num_bytes_read; +#ifdef __linux__ + gboolean turn_off_so_passcreds; +#endif + + g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + ret = NULL; + scms = NULL; + + g_object_get (connection, "socket", &socket, NULL); + + /* On Linux, we need to turn on SO_PASSCRED if it isn't enabled + * already. We also need to turn it off when we're done. See + * #617483 for more discussion. + */ +#ifdef __linux__ + { + gint opt_val; + socklen_t opt_len; + + turn_off_so_passcreds = FALSE; + opt_val = 0; + opt_len = sizeof (gint); + if (getsockopt (g_socket_get_fd (socket), + SOL_SOCKET, + SO_PASSCRED, + &opt_val, + &opt_len) != 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + _("Error checking if SO_PASSCRED is enabled for socket: %s"), + strerror (errno)); + goto out; + } + if (opt_len != sizeof (gint)) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Unexpected option length while checking if SO_PASSCRED is enabled for socket. " + "Expected %d bytes, got %d"), + (gint) sizeof (gint), (gint) opt_len); + goto out; + } + if (opt_val == 0) + { + opt_val = 1; + if (setsockopt (g_socket_get_fd (socket), + SOL_SOCKET, + SO_PASSCRED, + &opt_val, + sizeof opt_val) != 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + _("Error enabling SO_PASSCRED: %s"), + strerror (errno)); + goto out; + } + turn_off_so_passcreds = TRUE; + } + } +#endif + + /* ensure the type of GUnixCredentialsMessage has been registered with the type system */ + credentials_message_gtype = G_TYPE_UNIX_CREDENTIALS_MESSAGE; + num_bytes_read = g_socket_receive_message (socket, + NULL, /* GSocketAddress **address */ + NULL, + 0, + &scms, + &nscm, + NULL, + cancellable, + error); + if (num_bytes_read != 1) + { + /* Handle situation where g_socket_receive_message() returns + * 0 bytes and not setting @error + */ + if (num_bytes_read == 0 && error != NULL && *error == NULL) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Expecting to read a single byte for receiving credentials but read zero bytes")); + } + goto out; + } + + if (nscm != 1) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Expecting 1 control message, got %d"), + nscm); + goto out; + } + + if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0])) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Unexpected type of ancillary data")); + goto out; + } + + ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0])); + g_object_ref (ret); + + out: + +#ifdef __linux__ + if (turn_off_so_passcreds) + { + gint opt_val; + opt_val = 0; + if (setsockopt (g_socket_get_fd (socket), + SOL_SOCKET, + SO_PASSCRED, + &opt_val, + sizeof opt_val) != 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + _("Error while disabling SO_PASSCRED: %s"), + strerror (errno)); + goto out; + } + } +#endif + + if (scms != NULL) + { + for (n = 0; n < nscm; n++) + g_object_unref (scms[n]); + g_free (scms); + } + g_object_unref (socket); + return ret; +} + #define __G_UNIX_CONNECTION_C__ #include "gioaliasdef.c" diff --git a/gio/gunixconnection.h b/gio/gunixconnection.h index 7435e9742..9c691ea0d 100644 --- a/gio/gunixconnection.h +++ b/gio/gunixconnection.h @@ -71,6 +71,16 @@ gint g_unix_connection_receive_fd (GUnixCo GCancellable *cancellable, GError **error); +gboolean g_unix_connection_send_credentials (GUnixConnection *connection, + GCredentials *credentials, + GCancellable *cancellable, + GError **error); + +GCredentials *g_unix_connection_receive_credentials (GUnixConnection *connection, + GCancellable *cancellable, + GError **error); + + G_END_DECLS #endif /* __G_UNIX_CONNECTION_H__ */ |