| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright © 2009 Codethink Limited | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-05-18 09:12:45 +01:00
										 |  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-05-27 18:21:30 +02:00
										 |  |  |  * This library 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.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See the included COPYING file for more information. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Authors: Ryan Lortie <desrt@desrt.ca> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | #include "gunixconnection.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | #include "gnetworking.h"
 | 
					
						
							|  |  |  | #include "gsocket.h"
 | 
					
						
							|  |  |  | #include "gsocketcontrolmessage.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-14 15:30:33 +02:00
										 |  |  | #include "gunixcredentialsmessage.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | #include "gunixfdmessage.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | #include "glibintl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #ifdef HAVE_UNISTD_H
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2023-11-02 16:26:25 +00:00
										 |  |  |  * GUnixConnection: | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2023-11-02 16:26:25 +00:00
										 |  |  |  * This is the subclass of [class@Gio.SocketConnection] that is created | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * for UNIX domain sockets. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-08 23:28:17 -04:00
										 |  |  |  * It contains functions to do some of the UNIX socket specific | 
					
						
							|  |  |  |  * functionality like passing file descriptors. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2023-11-02 16:26:25 +00:00
										 |  |  |  * Since GLib 2.72, `GUnixConnection` is available on all platforms. It requires | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  |  * underlying system support (such as Windows 10 with `AF_UNIX`) at run time. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Before GLib 2.72, `<gio/gunixconnection.h>` belonged to the UNIX-specific GIO | 
					
						
							|  |  |  |  * interfaces, thus you had to use the `gio-unix-2.0.pc` pkg-config file when | 
					
						
							|  |  |  |  * using it. This is no longer necessary since GLib 2.72. | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection, | 
					
						
							|  |  |  | 			 G_TYPE_SOCKET_CONNECTION, | 
					
						
							|  |  |  |   g_socket_connection_factory_register_type (g_define_type_id, | 
					
						
							|  |  |  | 					     G_SOCKET_FAMILY_UNIX, | 
					
						
							|  |  |  | 					     G_SOCKET_TYPE_STREAM, | 
					
						
							| 
									
										
										
										
											2009-05-20 12:01:29 +02:00
										 |  |  | 					     G_SOCKET_PROTOCOL_DEFAULT); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 			 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_send_fd: | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  * @connection: a #GUnixConnection | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * @fd: a file descriptor | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. | 
					
						
							|  |  |  |  * @error: (nullable): #GError for error reporting, or %NULL to ignore. | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-04-20 19:08:06 +02:00
										 |  |  |  * Passes a file descriptor to the receiving side of the | 
					
						
							|  |  |  |  * connection. The receiving end has to call g_unix_connection_receive_fd() | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * to accept the file descriptor. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * As well as sending the fd this also writes a single byte to the | 
					
						
							|  |  |  |  * stream, as this is required for fd passing to work on some | 
					
						
							|  |  |  |  * implementations. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: a %TRUE on success, %NULL on error. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | gboolean | 
					
						
							|  |  |  | g_unix_connection_send_fd (GUnixConnection  *connection, | 
					
						
							|  |  |  |                            gint              fd, | 
					
						
							|  |  |  |                            GCancellable     *cancellable, | 
					
						
							|  |  |  |                            GError          **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #ifdef G_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   GSocketControlMessage *scm; | 
					
						
							|  |  |  |   GSocket *socket; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE); | 
					
						
							|  |  |  |   g_return_val_if_fail (fd >= 0, FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   scm = g_unix_fd_message_new (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (scm), fd, error)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_object_unref (scm); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_get (connection, "socket", &socket, NULL); | 
					
						
							| 
									
										
										
										
											2009-06-23 17:42:01 -04:00
										 |  |  |   if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1) | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |     /* XXX could it 'fail' with zero? */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_object_unref (socket); | 
					
						
							|  |  |  |       g_object_unref (scm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_unref (socket); | 
					
						
							|  |  |  |   g_object_unref (scm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, | 
					
						
							|  |  |  |                        _("Sending FD is not supported")); | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_receive_fd: | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  * @connection: a #GUnixConnection | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore | 
					
						
							|  |  |  |  * @error: (nullable): #GError for error reporting, or %NULL to ignore | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  * Receives a file descriptor from the sending end of the connection. | 
					
						
							|  |  |  |  * The sending end has to call g_unix_connection_send_fd() for this | 
					
						
							|  |  |  |  * to work. | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * As well as reading the fd this also reads a single byte from the | 
					
						
							|  |  |  |  * stream, as this is required for fd passing to work on some | 
					
						
							|  |  |  |  * implementations. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: a file descriptor on success, -1 on error. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2010-07-12 18:30:14 -04:00
										 |  |  |  **/ | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | gint | 
					
						
							|  |  |  | g_unix_connection_receive_fd (GUnixConnection  *connection, | 
					
						
							|  |  |  |                               GCancellable     *cancellable, | 
					
						
							|  |  |  |                               GError          **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #ifdef G_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   GSocketControlMessage **scms; | 
					
						
							|  |  |  |   gint *fds, nfd, fd, nscm; | 
					
						
							|  |  |  |   GUnixFDMessage *fdmsg; | 
					
						
							|  |  |  |   GSocket *socket; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_get (connection, "socket", &socket, NULL); | 
					
						
							| 
									
										
										
										
											2009-06-23 17:42:01 -04:00
										 |  |  |   if (g_socket_receive_message (socket, NULL, NULL, 0, | 
					
						
							|  |  |  |                                 &scms, &nscm, NULL, cancellable, error) != 1) | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |     /* XXX it _could_ 'fail' with zero. */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_object_unref (socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_unref (socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (nscm != 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       gint i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 23:21:58 -04:00
										 |  |  |       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							| 
									
										
										
										
											2023-04-25 23:25:38 -04:00
										 |  |  |                    g_dngettext (NULL, | 
					
						
							|  |  |  |                                 "Expecting 1 control message, got %d", | 
					
						
							|  |  |  |                                 "Expecting 1 control message, got %d", | 
					
						
							|  |  |  |                                 nscm), | 
					
						
							|  |  |  |                    nscm); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for (i = 0; i < nscm; i++) | 
					
						
							|  |  |  |         g_object_unref (scms[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_free (scms); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!G_IS_UNIX_FD_MESSAGE (scms[0])) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							|  |  |  | 			   _("Unexpected type of ancillary data")); | 
					
						
							|  |  |  |       g_object_unref (scms[0]); | 
					
						
							|  |  |  |       g_free (scms); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fdmsg = G_UNIX_FD_MESSAGE (scms[0]); | 
					
						
							|  |  |  |   g_free (scms); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fds = g_unix_fd_message_steal_fds (fdmsg, &nfd); | 
					
						
							|  |  |  |   g_object_unref (fdmsg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (nfd != 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       gint i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 23:21:58 -04:00
										 |  |  |       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							| 
									
										
										
										
											2023-04-25 23:25:38 -04:00
										 |  |  |                    g_dngettext (NULL, | 
					
						
							|  |  |  |                                 "Expecting one fd, but got %d\n", | 
					
						
							|  |  |  |                                 "Expecting one fd, but got %d\n", | 
					
						
							|  |  |  |                                 nfd), | 
					
						
							| 
									
										
										
										
											2023-04-25 23:21:58 -04:00
										 |  |  |                    nfd); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for (i = 0; i < nfd; i++) | 
					
						
							|  |  |  |         close (fds[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_free (fds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fd = *fds; | 
					
						
							|  |  |  |   g_free (fds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fd < 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-05-19 15:03:14 +02:00
										 |  |  |       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							|  |  |  |                            _("Received invalid fd")); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |       fd = -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return fd; | 
					
						
							| 
									
										
										
										
											2022-01-19 15:52:15 +04:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, | 
					
						
							|  |  |  |                        _("Receiving FD is not supported")); | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_unix_connection_init (GUnixConnection *connection) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_unix_connection_class_init (GUnixConnectionClass *class) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO: Other stuff we might want to add are:
 | 
					
						
							|  |  |  | void                    g_unix_connection_send_fd_async                 (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          gint                  fd, | 
					
						
							|  |  |  |                                                                          gboolean              close, | 
					
						
							|  |  |  |                                                                          gint                  io_priority, | 
					
						
							|  |  |  |                                                                          GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                                          gpointer              user_data); | 
					
						
							|  |  |  | gboolean                g_unix_connection_send_fd_finish                (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gboolean                g_unix_connection_send_fds                      (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          gint                 *fds, | 
					
						
							|  |  |  |                                                                          gint                  nfds, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | void                    g_unix_connection_send_fds_async                (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          gint                 *fds, | 
					
						
							|  |  |  |                                                                          gint                  nfds, | 
					
						
							|  |  |  |                                                                          gint                  io_priority, | 
					
						
							|  |  |  |                                                                          GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                                          gpointer              user_data); | 
					
						
							|  |  |  | gboolean                g_unix_connection_send_fds_finish               (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void                    g_unix_connection_receive_fd_async              (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          gint                  io_priority, | 
					
						
							|  |  |  |                                                                          GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                                          gpointer              user_data); | 
					
						
							|  |  |  | gint                    g_unix_connection_receive_fd_finish             (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gboolean                g_unix_connection_send_fake_credentials         (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          guint64               pid, | 
					
						
							|  |  |  |                                                                          guint64               uid, | 
					
						
							|  |  |  |                                                                          guint64               gid, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | void                    g_unix_connection_send_fake_credentials_async   (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          guint64               pid, | 
					
						
							|  |  |  |                                                                          guint64               uid, | 
					
						
							|  |  |  |                                                                          guint64               gid, | 
					
						
							|  |  |  |                                                                          gint                  io_priority, | 
					
						
							|  |  |  |                                                                          GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                                          gpointer              user_data); | 
					
						
							|  |  |  | gboolean                g_unix_connection_send_fake_credentials_finish  (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gboolean                g_unix_connection_create_pair                   (GUnixConnection     **one, | 
					
						
							|  |  |  |                                                                          GUnixConnection     **two, | 
					
						
							|  |  |  |                                                                          GError              **error); | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_send_credentials: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): A #GCancellable or %NULL. | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |  * @error: Return location for error or %NULL. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-13 14:25:29 -04:00
										 |  |  |  * Passes the credentials of the current user the receiving side | 
					
						
							| 
									
										
										
										
											2011-04-20 19:08:06 +02:00
										 |  |  |  * of the connection. The receiving end has to call | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |  * g_unix_connection_receive_credentials() (or similar) to accept the | 
					
						
							|  |  |  |  * credentials. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-06-05 10:51:30 +01:00
										 |  |  |  * This method can be expected to be available on the following platforms: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Linux since GLib 2.26 | 
					
						
							|  |  |  |  * - FreeBSD since GLib 2.26 | 
					
						
							|  |  |  |  * - GNU/kFreeBSD since GLib 2.36 | 
					
						
							|  |  |  |  * - Solaris, Illumos and OpenSolaris since GLib 2.40 | 
					
						
							|  |  |  |  * - GNU/Hurd since GLib 2.40 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-07-20 14:02:14 -04:00
										 |  |  |  * Other ways to exchange credentials with a foreign peer includes the | 
					
						
							|  |  |  |  * #GUnixCredentialsMessage type and g_socket_get_credentials() function. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |  * Returns: %TRUE on success, %FALSE if @error is set. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.26 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | gboolean | 
					
						
							|  |  |  | g_unix_connection_send_credentials (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                     GCancellable         *cancellable, | 
					
						
							|  |  |  |                                     GError              **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-13 14:25:29 -04:00
										 |  |  |   GCredentials *credentials; | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |   GSocketControlMessage *scm; | 
					
						
							|  |  |  |   GSocket *socket; | 
					
						
							|  |  |  |   gboolean ret; | 
					
						
							|  |  |  |   GOutputVector vector; | 
					
						
							|  |  |  |   guchar nul_byte[1] = {'\0'}; | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |   gint num_messages; | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE); | 
					
						
							|  |  |  |   g_return_val_if_fail (error == NULL || *error == NULL, FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-13 14:25:29 -04:00
										 |  |  |   credentials = g_credentials_new (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |   vector.buffer = &nul_byte; | 
					
						
							|  |  |  |   vector.size = 1; | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (g_unix_credentials_message_is_supported ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       scm = g_unix_credentials_message_new_with_credentials (credentials); | 
					
						
							|  |  |  |       num_messages = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       scm = NULL; | 
					
						
							|  |  |  |       num_messages = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |   g_object_get (connection, "socket", &socket, NULL); | 
					
						
							|  |  |  |   if (g_socket_send_message (socket, | 
					
						
							|  |  |  |                              NULL, /* address */ | 
					
						
							|  |  |  |                              &vector, | 
					
						
							|  |  |  |                              1, | 
					
						
							|  |  |  |                              &scm, | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |                              num_messages, | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |                              G_SOCKET_MSG_NONE, | 
					
						
							|  |  |  |                              cancellable, | 
					
						
							|  |  |  |                              error) != 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_prefix_error (error, _("Error sending credentials: ")); | 
					
						
							|  |  |  |       goto out; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							|  |  |  |   g_object_unref (socket); | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |   if (scm != NULL) | 
					
						
							|  |  |  |     g_object_unref (scm); | 
					
						
							| 
									
										
										
										
											2010-05-13 14:25:29 -04:00
										 |  |  |   g_object_unref (credentials); | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | send_credentials_async_thread (GTask         *task, | 
					
						
							|  |  |  | 			       gpointer       source_object, | 
					
						
							|  |  |  | 			       gpointer       task_data, | 
					
						
							|  |  |  | 			       GCancellable  *cancellable) | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   if (g_unix_connection_send_credentials (G_UNIX_CONNECTION (source_object), | 
					
						
							|  |  |  | 					  cancellable, | 
					
						
							|  |  |  | 					  &error)) | 
					
						
							|  |  |  |     g_task_return_boolean (task, TRUE); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     g_task_return_error (task, error); | 
					
						
							|  |  |  |   g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_send_credentials_async: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. | 
					
						
							| 
									
										
										
										
											2023-02-20 14:43:02 -06:00
										 |  |  |  * @callback: (scope async): a #GAsyncReadyCallback | 
					
						
							|  |  |  |  *   to call when the request is satisfied | 
					
						
							|  |  |  |  * @user_data: the data to pass to callback function | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Asynchronously send credentials. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * For more details, see g_unix_connection_send_credentials() which is | 
					
						
							|  |  |  |  * the synchronous version of this call. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When the operation is finished, @callback will be called. You can then call | 
					
						
							|  |  |  |  * g_unix_connection_send_credentials_finish() to get the result of the operation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.32 | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | g_unix_connection_send_credentials_async (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                           GCancellable         *cancellable, | 
					
						
							|  |  |  |                                           GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                           gpointer              user_data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   GTask *task; | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   task = g_task_new (connection, cancellable, callback, user_data); | 
					
						
							| 
									
										
										
										
											2016-06-16 19:39:38 -04:00
										 |  |  |   g_task_set_source_tag (task, g_unix_connection_send_credentials_async); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   g_task_run_in_thread (task, send_credentials_async_thread); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_send_credentials_finish: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							|  |  |  |  * @result: a #GAsyncResult. | 
					
						
							|  |  |  |  * @error: a #GError, or %NULL | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Finishes an asynchronous send credentials operation started with | 
					
						
							|  |  |  |  * g_unix_connection_send_credentials_async(). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: %TRUE if the operation was successful, otherwise %FALSE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.32 | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | gboolean | 
					
						
							|  |  |  | g_unix_connection_send_credentials_finish (GUnixConnection *connection, | 
					
						
							|  |  |  |                                            GAsyncResult    *result, | 
					
						
							|  |  |  |                                            GError         **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   g_return_val_if_fail (g_task_is_valid (result, connection), FALSE); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   return g_task_propagate_boolean (G_TASK (result), error); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_receive_credentials: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): A #GCancellable or %NULL. | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |  * @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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-06-05 10:51:30 +01:00
										 |  |  |  * This method can be expected to be available on the following platforms: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Linux since GLib 2.26 | 
					
						
							|  |  |  |  * - FreeBSD since GLib 2.26 | 
					
						
							|  |  |  |  * - GNU/kFreeBSD since GLib 2.36 | 
					
						
							|  |  |  |  * - Solaris, Illumos and OpenSolaris since GLib 2.40 | 
					
						
							|  |  |  |  * - GNU/Hurd since GLib 2.40 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-07-20 14:02:14 -04:00
										 |  |  |  * Other ways to exchange credentials with a foreign peer includes the | 
					
						
							|  |  |  |  * #GUnixCredentialsMessage type and g_socket_get_credentials() function. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-09-24 18:24:41 -03:00
										 |  |  |  * Returns: (transfer full): Received credentials on success (free with | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |  * 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; | 
					
						
							|  |  |  |   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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     turn_off_so_passcreds = FALSE; | 
					
						
							|  |  |  |     opt_val = 0; | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  |     if (!g_socket_get_option (socket, | 
					
						
							|  |  |  | 			      SOL_SOCKET, | 
					
						
							|  |  |  | 			      SO_PASSCRED, | 
					
						
							|  |  |  | 			      &opt_val, | 
					
						
							|  |  |  | 			      NULL)) | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |         int errsv = errno; | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |         g_set_error (error, | 
					
						
							|  |  |  |                      G_IO_ERROR, | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                      g_io_error_from_errno (errsv), | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |                      _("Error checking if SO_PASSCRED is enabled for socket: %s"), | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                      g_strerror (errsv)); | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |         goto out; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     if (opt_val == 0) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  |         if (!g_socket_set_option (socket, | 
					
						
							|  |  |  | 				  SOL_SOCKET, | 
					
						
							|  |  |  | 				  SO_PASSCRED, | 
					
						
							|  |  |  | 				  TRUE, | 
					
						
							|  |  |  | 				  NULL)) | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |           { | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |             int errsv = errno; | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |             g_set_error (error, | 
					
						
							|  |  |  |                          G_IO_ERROR, | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                          g_io_error_from_errno (errsv), | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |                          _("Error enabling SO_PASSCRED: %s"), | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                          g_strerror (errsv)); | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |             goto out; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         turn_off_so_passcreds = TRUE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-03 14:47:56 -05:00
										 |  |  |   g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE); | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |   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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-12 16:50:20 +02:00
										 |  |  |   if (g_unix_credentials_message_is_supported () && | 
					
						
							|  |  |  |       /* Fall back on get_credentials if the other side didn't send the credentials */ | 
					
						
							|  |  |  |       nscm > 0) | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |       if (nscm != 1) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2023-04-25 23:21:58 -04:00
										 |  |  |           g_set_error (error, | 
					
						
							|  |  |  |                        G_IO_ERROR, | 
					
						
							|  |  |  |                        G_IO_ERROR_FAILED, | 
					
						
							| 
									
										
										
										
											2023-04-25 23:25:38 -04:00
										 |  |  |                        g_dngettext (NULL, | 
					
						
							|  |  |  |                                     "Expecting 1 control message, got %d", | 
					
						
							|  |  |  |                                     "Expecting 1 control message, got %d", | 
					
						
							|  |  |  |                                     nscm), | 
					
						
							| 
									
										
										
										
											2023-04-25 23:21:58 -04:00
										 |  |  |                        nscm); | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |           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; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |       ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0])); | 
					
						
							|  |  |  |       g_object_ref (ret); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-05-27 15:51:08 +02:00
										 |  |  |       if (nscm != 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           g_set_error (error, | 
					
						
							|  |  |  |                        G_IO_ERROR, | 
					
						
							|  |  |  |                        G_IO_ERROR_FAILED, | 
					
						
							|  |  |  |                        _("Not expecting control message, but got %d"), | 
					
						
							|  |  |  |                        nscm); | 
					
						
							|  |  |  |           goto out; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           ret = g_socket_get_credentials (socket, error); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __linux__
 | 
					
						
							|  |  |  |   if (turn_off_so_passcreds) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-02-13 21:12:34 -05:00
										 |  |  |       if (!g_socket_set_option (socket, | 
					
						
							|  |  |  | 				SOL_SOCKET, | 
					
						
							|  |  |  | 				SO_PASSCRED, | 
					
						
							|  |  |  | 				FALSE, | 
					
						
							|  |  |  | 				NULL)) | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |           int errsv = errno; | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |           g_set_error (error, | 
					
						
							|  |  |  |                        G_IO_ERROR, | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                        g_io_error_from_errno (errsv), | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |                        _("Error while disabling SO_PASSCRED: %s"), | 
					
						
							| 
									
										
										
										
											2017-07-31 11:30:55 +01:00
										 |  |  |                        g_strerror (errsv)); | 
					
						
							| 
									
										
										
										
											2010-05-06 15:31:45 -04:00
										 |  |  |           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; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | receive_credentials_async_thread (GTask         *task, | 
					
						
							|  |  |  | 				  gpointer       source_object, | 
					
						
							|  |  |  | 				  gpointer       task_data, | 
					
						
							|  |  |  | 				  GCancellable  *cancellable) | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   GCredentials *creds; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   creds = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (source_object), | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  |                                                  cancellable, | 
					
						
							|  |  |  |                                                  &error); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   if (creds) | 
					
						
							|  |  |  |     g_task_return_pointer (task, creds, g_object_unref); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |     g_task_return_error (task, error); | 
					
						
							|  |  |  |   g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_receive_credentials_async: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							| 
									
										
										
										
											2016-10-28 18:29:02 -07:00
										 |  |  |  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. | 
					
						
							| 
									
										
										
										
											2023-02-20 14:43:02 -06:00
										 |  |  |  * @callback: (scope async): a #GAsyncReadyCallback | 
					
						
							|  |  |  |  *   to call when the request is satisfied | 
					
						
							|  |  |  |  * @user_data: the data to pass to callback function | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Asynchronously receive credentials. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * For more details, see g_unix_connection_receive_credentials() which is | 
					
						
							|  |  |  |  * the synchronous version of this call. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When the operation is finished, @callback will be called. You can then call | 
					
						
							|  |  |  |  * g_unix_connection_receive_credentials_finish() to get the result of the operation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.32 | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | g_unix_connection_receive_credentials_async (GUnixConnection      *connection, | 
					
						
							|  |  |  |                                               GCancellable         *cancellable, | 
					
						
							|  |  |  |                                               GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                               gpointer              user_data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   GTask *task; | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   task = g_task_new (connection, cancellable, callback, user_data); | 
					
						
							| 
									
										
										
										
											2016-06-16 19:39:38 -04:00
										 |  |  |   g_task_set_source_tag (task, g_unix_connection_receive_credentials_async); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   g_task_run_in_thread (task, receive_credentials_async_thread); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_unix_connection_receive_credentials_finish: | 
					
						
							|  |  |  |  * @connection: A #GUnixConnection. | 
					
						
							|  |  |  |  * @result: a #GAsyncResult. | 
					
						
							|  |  |  |  * @error: a #GError, or %NULL | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Finishes an asynchronous receive credentials operation started with | 
					
						
							|  |  |  |  * g_unix_connection_receive_credentials_async(). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: (transfer full): a #GCredentials, or %NULL on error. | 
					
						
							|  |  |  |  *     Free the returned object with g_object_unref(). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.32 | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | GCredentials * | 
					
						
							|  |  |  | g_unix_connection_receive_credentials_finish (GUnixConnection *connection, | 
					
						
							|  |  |  |                                               GAsyncResult    *result, | 
					
						
							|  |  |  |                                               GError         **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   g_return_val_if_fail (g_task_is_valid (result, connection), NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return g_task_propagate_pointer (G_TASK (result), error); | 
					
						
							| 
									
										
										
										
											2012-01-16 14:51:19 +01:00
										 |  |  | } |