1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2009 Codethink Limited
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * See the included COPYING file for more information.
14 * Authors: Ryan Lortie <desrt@desrt.ca>
19 #include "gunixconnection.h"
20 #include "gnetworking.h"
22 #include "gsocketcontrolmessage.h"
23 #include "gunixcredentialsmessage.h"
24 #include "gunixfdmessage.h"
34 * SECTION:gunixconnection
35 * @title: GUnixConnection
36 * @short_description: A UNIX domain GSocketConnection
37 * @include: gio/gunixconnection.h
38 * @see_also: #GSocketConnection.
40 * This is the subclass of #GSocketConnection that is created
41 * for UNIX domain sockets.
43 * It contains functions to do some of the UNIX socket specific
44 * functionality like passing file descriptors.
46 * Since GLib 2.72, #GUnixConnection is available on all platforms. It requires
47 * underlying system support (such as Windows 10 with `AF_UNIX`) at run time.
49 * Before GLib 2.72, `<gio/gunixconnection.h>` belonged to the UNIX-specific GIO
50 * interfaces, thus you had to use the `gio-unix-2.0.pc` pkg-config file when
51 * using it. This is no longer necessary since GLib 2.72.
59 * #GUnixConnection is an opaque data structure and can only be accessed
60 * using the following functions.
63 G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection,
64 G_TYPE_SOCKET_CONNECTION,
65 g_socket_connection_factory_register_type (g_define_type_id,
68 G_SOCKET_PROTOCOL_DEFAULT);
72 * g_unix_connection_send_fd:
73 * @connection: a #GUnixConnection
74 * @fd: a file descriptor
75 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
76 * @error: (nullable): #GError for error reporting, or %NULL to ignore.
78 * Passes a file descriptor to the receiving side of the
79 * connection. The receiving end has to call g_unix_connection_receive_fd()
80 * to accept the file descriptor.
82 * As well as sending the fd this also writes a single byte to the
83 * stream, as this is required for fd passing to work on some
86 * Returns: a %TRUE on success, %NULL on error.
91 g_unix_connection_send_fd (GUnixConnection *connection,
93 GCancellable *cancellable,
97 GSocketControlMessage *scm;
100 g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
101 g_return_val_if_fail (fd >= 0, FALSE);
103 scm = g_unix_fd_message_new ();
105 if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (scm), fd, error))
107 g_object_unref (scm);
111 g_object_get (connection, "socket", &socket, NULL);
112 if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1)
113 /* XXX could it 'fail' with zero? */
115 g_object_unref (socket);
116 g_object_unref (scm);
121 g_object_unref (socket);
122 g_object_unref (scm);
126 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
127 _("Sending FD is not supported"));
133 * g_unix_connection_receive_fd:
134 * @connection: a #GUnixConnection
135 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
136 * @error: (nullable): #GError for error reporting, or %NULL to ignore
138 * Receives a file descriptor from the sending end of the connection.
139 * The sending end has to call g_unix_connection_send_fd() for this
142 * As well as reading the fd this also reads a single byte from the
143 * stream, as this is required for fd passing to work on some
146 * Returns: a file descriptor on success, -1 on error.
151 g_unix_connection_receive_fd (GUnixConnection *connection,
152 GCancellable *cancellable,
156 GSocketControlMessage **scms;
157 gint *fds, nfd, fd, nscm;
158 GUnixFDMessage *fdmsg;
161 g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1);
163 g_object_get (connection, "socket", &socket, NULL);
164 if (g_socket_receive_message (socket, NULL, NULL, 0,
165 &scms, &nscm, NULL, cancellable, error) != 1)
166 /* XXX it _could_ 'fail' with zero. */
168 g_object_unref (socket);
173 g_object_unref (socket);
179 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
181 "Expecting 1 control message, got %d",
182 "Expecting 1 control message, got %d",
186 for (i = 0; i < nscm; i++)
187 g_object_unref (scms[i]);
194 if (!G_IS_UNIX_FD_MESSAGE (scms[0]))
196 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
197 _("Unexpected type of ancillary data"));
198 g_object_unref (scms[0]);
204 fdmsg = G_UNIX_FD_MESSAGE (scms[0]);
207 fds = g_unix_fd_message_steal_fds (fdmsg, &nfd);
208 g_object_unref (fdmsg);
214 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
216 "Expecting one fd, but got %d\n",
217 "Expecting one fd, but got %d\n",
221 for (i = 0; i < nfd; i++)
234 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
235 _("Received invalid fd"));
241 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
242 _("Receiving FD is not supported"));
248 g_unix_connection_init (GUnixConnection *connection)
253 g_unix_connection_class_init (GUnixConnectionClass *class)
257 /* TODO: Other stuff we might want to add are:
258 void g_unix_connection_send_fd_async (GUnixConnection *connection,
262 GAsyncReadyCallback callback,
264 gboolean g_unix_connection_send_fd_finish (GUnixConnection *connection,
267 gboolean g_unix_connection_send_fds (GUnixConnection *connection,
271 void g_unix_connection_send_fds_async (GUnixConnection *connection,
275 GAsyncReadyCallback callback,
277 gboolean g_unix_connection_send_fds_finish (GUnixConnection *connection,
280 void g_unix_connection_receive_fd_async (GUnixConnection *connection,
282 GAsyncReadyCallback callback,
284 gint g_unix_connection_receive_fd_finish (GUnixConnection *connection,
288 gboolean g_unix_connection_send_fake_credentials (GUnixConnection *connection,
293 void g_unix_connection_send_fake_credentials_async (GUnixConnection *connection,
298 GAsyncReadyCallback callback,
300 gboolean g_unix_connection_send_fake_credentials_finish (GUnixConnection *connection,
303 gboolean g_unix_connection_create_pair (GUnixConnection **one,
304 GUnixConnection **two,
310 * g_unix_connection_send_credentials:
311 * @connection: A #GUnixConnection.
312 * @cancellable: (nullable): A #GCancellable or %NULL.
313 * @error: Return location for error or %NULL.
315 * Passes the credentials of the current user the receiving side
316 * of the connection. The receiving end has to call
317 * g_unix_connection_receive_credentials() (or similar) to accept the
320 * As well as sending the credentials this also writes a single NUL
321 * byte to the stream, as this is required for credentials passing to
322 * work on some implementations.
324 * This method can be expected to be available on the following platforms:
326 * - Linux since GLib 2.26
327 * - FreeBSD since GLib 2.26
328 * - GNU/kFreeBSD since GLib 2.36
329 * - Solaris, Illumos and OpenSolaris since GLib 2.40
330 * - GNU/Hurd since GLib 2.40
332 * Other ways to exchange credentials with a foreign peer includes the
333 * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
335 * Returns: %TRUE on success, %FALSE if @error is set.
340 g_unix_connection_send_credentials (GUnixConnection *connection,
341 GCancellable *cancellable,
344 GCredentials *credentials;
345 GSocketControlMessage *scm;
348 GOutputVector vector;
349 guchar nul_byte[1] = {'\0'};
352 g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
353 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
357 credentials = g_credentials_new ();
359 vector.buffer = &nul_byte;
362 if (g_unix_credentials_message_is_supported ())
364 scm = g_unix_credentials_message_new_with_credentials (credentials);
373 g_object_get (connection, "socket", &socket, NULL);
374 if (g_socket_send_message (socket,
384 g_prefix_error (error, _("Error sending credentials: "));
391 g_object_unref (socket);
393 g_object_unref (scm);
394 g_object_unref (credentials);
399 send_credentials_async_thread (GTask *task,
400 gpointer source_object,
402 GCancellable *cancellable)
404 GError *error = NULL;
406 if (g_unix_connection_send_credentials (G_UNIX_CONNECTION (source_object),
409 g_task_return_boolean (task, TRUE);
411 g_task_return_error (task, error);
412 g_object_unref (task);
416 * g_unix_connection_send_credentials_async:
417 * @connection: A #GUnixConnection.
418 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
419 * @callback: (scope async): a #GAsyncReadyCallback
420 * to call when the request is satisfied
421 * @user_data: the data to pass to callback function
423 * Asynchronously send credentials.
425 * For more details, see g_unix_connection_send_credentials() which is
426 * the synchronous version of this call.
428 * When the operation is finished, @callback will be called. You can then call
429 * g_unix_connection_send_credentials_finish() to get the result of the operation.
434 g_unix_connection_send_credentials_async (GUnixConnection *connection,
435 GCancellable *cancellable,
436 GAsyncReadyCallback callback,
441 task = g_task_new (connection, cancellable, callback, user_data);
442 g_task_set_source_tag (task, g_unix_connection_send_credentials_async);
443 g_task_run_in_thread (task, send_credentials_async_thread);
447 * g_unix_connection_send_credentials_finish:
448 * @connection: A #GUnixConnection.
449 * @result: a #GAsyncResult.
450 * @error: a #GError, or %NULL
452 * Finishes an asynchronous send credentials operation started with
453 * g_unix_connection_send_credentials_async().
455 * Returns: %TRUE if the operation was successful, otherwise %FALSE.
460 g_unix_connection_send_credentials_finish (GUnixConnection *connection,
461 GAsyncResult *result,
464 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
466 return g_task_propagate_boolean (G_TASK (result), error);
470 * g_unix_connection_receive_credentials:
471 * @connection: A #GUnixConnection.
472 * @cancellable: (nullable): A #GCancellable or %NULL.
473 * @error: Return location for error or %NULL.
475 * Receives credentials from the sending end of the connection. The
476 * sending end has to call g_unix_connection_send_credentials() (or
477 * similar) for this to work.
479 * As well as reading the credentials this also reads (and discards) a
480 * single byte from the stream, as this is required for credentials
481 * passing to work on some implementations.
483 * This method can be expected to be available on the following platforms:
485 * - Linux since GLib 2.26
486 * - FreeBSD since GLib 2.26
487 * - GNU/kFreeBSD since GLib 2.36
488 * - Solaris, Illumos and OpenSolaris since GLib 2.40
489 * - GNU/Hurd since GLib 2.40
491 * Other ways to exchange credentials with a foreign peer includes the
492 * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
494 * Returns: (transfer full): Received credentials on success (free with
495 * g_object_unref()), %NULL if @error is set.
500 g_unix_connection_receive_credentials (GUnixConnection *connection,
501 GCancellable *cancellable,
505 GSocketControlMessage **scms;
509 gssize num_bytes_read;
511 gboolean turn_off_so_passcreds;
514 g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL);
515 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
520 g_object_get (connection, "socket", &socket, NULL);
522 /* On Linux, we need to turn on SO_PASSCRED if it isn't enabled
523 * already. We also need to turn it off when we're done. See
524 * #617483 for more discussion.
530 turn_off_so_passcreds = FALSE;
532 if (!g_socket_get_option (socket,
541 g_io_error_from_errno (errsv),
542 _("Error checking if SO_PASSCRED is enabled for socket: %s"),
548 if (!g_socket_set_option (socket,
557 g_io_error_from_errno (errsv),
558 _("Error enabling SO_PASSCRED: %s"),
562 turn_off_so_passcreds = TRUE;
567 g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE);
568 num_bytes_read = g_socket_receive_message (socket,
569 NULL, /* GSocketAddress **address */
577 if (num_bytes_read != 1)
579 /* Handle situation where g_socket_receive_message() returns
580 * 0 bytes and not setting @error
582 if (num_bytes_read == 0 && error != NULL && *error == NULL)
584 g_set_error_literal (error,
587 _("Expecting to read a single byte for receiving credentials but read zero bytes"));
592 if (g_unix_credentials_message_is_supported () &&
593 /* Fall back on get_credentials if the other side didn't send the credentials */
602 "Expecting 1 control message, got %d",
603 "Expecting 1 control message, got %d",
609 if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0]))
611 g_set_error_literal (error,
614 _("Unexpected type of ancillary data"));
618 ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0]));
628 _("Not expecting control message, but got %d"),
634 ret = g_socket_get_credentials (socket, error);
641 if (turn_off_so_passcreds)
643 if (!g_socket_set_option (socket,
652 g_io_error_from_errno (errsv),
653 _("Error while disabling SO_PASSCRED: %s"),
662 for (n = 0; n < nscm; n++)
663 g_object_unref (scms[n]);
666 g_object_unref (socket);
671 receive_credentials_async_thread (GTask *task,
672 gpointer source_object,
674 GCancellable *cancellable)
677 GError *error = NULL;
679 creds = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (source_object),
683 g_task_return_pointer (task, creds, g_object_unref);
685 g_task_return_error (task, error);
686 g_object_unref (task);
690 * g_unix_connection_receive_credentials_async:
691 * @connection: A #GUnixConnection.
692 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
693 * @callback: (scope async): a #GAsyncReadyCallback
694 * to call when the request is satisfied
695 * @user_data: the data to pass to callback function
697 * Asynchronously receive credentials.
699 * For more details, see g_unix_connection_receive_credentials() which is
700 * the synchronous version of this call.
702 * When the operation is finished, @callback will be called. You can then call
703 * g_unix_connection_receive_credentials_finish() to get the result of the operation.
708 g_unix_connection_receive_credentials_async (GUnixConnection *connection,
709 GCancellable *cancellable,
710 GAsyncReadyCallback callback,
715 task = g_task_new (connection, cancellable, callback, user_data);
716 g_task_set_source_tag (task, g_unix_connection_receive_credentials_async);
717 g_task_run_in_thread (task, receive_credentials_async_thread);
721 * g_unix_connection_receive_credentials_finish:
722 * @connection: A #GUnixConnection.
723 * @result: a #GAsyncResult.
724 * @error: a #GError, or %NULL
726 * Finishes an asynchronous receive credentials operation started with
727 * g_unix_connection_receive_credentials_async().
729 * Returns: (transfer full): a #GCredentials, or %NULL on error.
730 * Free the returned object with g_object_unref().
735 g_unix_connection_receive_credentials_finish (GUnixConnection *connection,
736 GAsyncResult *result,
739 g_return_val_if_fail (g_task_is_valid (result, connection), NULL);
741 return g_task_propagate_pointer (G_TASK (result), error);