cleanup
[platform/upstream/glib.git] / gio / gunixconnection.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2009 Codethink Limited
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 2 of the licence or (at
8  * your option) any later version.
9  *
10  * See the included COPYING file for more information.
11  *
12  * Authors: Ryan Lortie <desrt@desrt.ca>
13  */
14
15 #include "config.h"
16
17 #include "gunixconnection.h"
18 #include "gnetworking.h"
19 #include "gsocket.h"
20 #include "gsocketcontrolmessage.h"
21 #include "gunixcredentialsmessage.h"
22 #include "gunixfdmessage.h"
23 #include "glibintl.h"
24
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 /**
30  * SECTION:gunixconnection
31  * @title: GUnixConnection
32  * @short_description: A UNIX domain GSocketConnection
33  * @include: gio/gunixconnection.h
34  * @see_also: #GSocketConnection.
35  *
36  * This is the subclass of #GSocketConnection that is created
37  * for UNIX domain sockets.
38  *
39  * It contains functions to do some of the UNIX socket specific
40  * functionality like passing file descriptors.
41  *
42  * Note that `<gio/gunixconnection.h>` belongs to the UNIX-specific
43  * GIO interfaces, thus you have to use the `gio-unix-2.0.pc`
44  * pkg-config file when using it.
45  *
46  * Since: 2.22
47  */
48
49 G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection,
50                          G_TYPE_SOCKET_CONNECTION,
51   g_socket_connection_factory_register_type (g_define_type_id,
52                                              G_SOCKET_FAMILY_UNIX,
53                                              G_SOCKET_TYPE_STREAM,
54                                              G_SOCKET_PROTOCOL_DEFAULT);
55                          );
56
57 /**
58  * g_unix_connection_send_fd:
59  * @connection: a #GUnixConnection
60  * @fd: a file descriptor
61  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
62  * @error: (allow-none): #GError for error reporting, or %NULL to ignore.
63  *
64  * Passes a file descriptor to the receiving side of the
65  * connection. The receiving end has to call g_unix_connection_receive_fd()
66  * to accept the file descriptor.
67  *
68  * As well as sending the fd this also writes a single byte to the
69  * stream, as this is required for fd passing to work on some
70  * implementations.
71  *
72  * Returns: a %TRUE on success, %NULL on error.
73  *
74  * Since: 2.22
75  */
76 gboolean
77 g_unix_connection_send_fd (GUnixConnection  *connection,
78                            gint              fd,
79                            GCancellable     *cancellable,
80                            GError          **error)
81 {
82   GSocketControlMessage *scm;
83   GSocket *socket;
84
85   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
86   g_return_val_if_fail (fd >= 0, FALSE);
87
88   scm = g_unix_fd_message_new ();
89
90   if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (scm), fd, error))
91     {
92       g_object_unref (scm);
93       return FALSE;
94     }
95
96   g_object_get (connection, "socket", &socket, NULL);
97   if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1)
98     /* XXX could it 'fail' with zero? */
99     {
100       g_object_unref (socket);
101       g_object_unref (scm);
102
103       return FALSE;
104     }
105
106   g_object_unref (socket);
107   g_object_unref (scm);
108
109   return TRUE;
110 }
111
112 /**
113  * g_unix_connection_receive_fd:
114  * @connection: a #GUnixConnection
115  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
116  * @error: (allow-none): #GError for error reporting, or %NULL to ignore
117  *
118  * Receives a file descriptor from the sending end of the connection.
119  * The sending end has to call g_unix_connection_send_fd() for this
120  * to work.
121  *
122  * As well as reading the fd this also reads a single byte from the
123  * stream, as this is required for fd passing to work on some
124  * implementations.
125  *
126  * Returns: a file descriptor on success, -1 on error.
127  *
128  * Since: 2.22
129  **/
130 gint
131 g_unix_connection_receive_fd (GUnixConnection  *connection,
132                               GCancellable     *cancellable,
133                               GError          **error)
134 {
135   GSocketControlMessage **scms;
136   gint *fds, nfd, fd, nscm;
137   GUnixFDMessage *fdmsg;
138   GSocket *socket;
139
140   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1);
141
142   g_object_get (connection, "socket", &socket, NULL);
143   if (g_socket_receive_message (socket, NULL, NULL, 0,
144                                 &scms, &nscm, NULL, cancellable, error) != 1)
145     /* XXX it _could_ 'fail' with zero. */
146     {
147       g_object_unref (socket);
148
149       return -1;
150     }
151
152   g_object_unref (socket);
153
154   if (nscm != 1)
155     {
156       gint i;
157
158       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
159         ngettext("Expecting 1 control message, got %d",
160                  "Expecting 1 control message, got %d",
161                  nscm),
162         nscm);
163
164       for (i = 0; i < nscm; i++)
165         g_object_unref (scms[i]);
166
167       g_free (scms);
168
169       return -1;
170     }
171
172   if (!G_IS_UNIX_FD_MESSAGE (scms[0]))
173     {
174       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
175                            _("Unexpected type of ancillary data"));
176       g_object_unref (scms[0]);
177       g_free (scms);
178
179       return -1;
180     }
181
182   fdmsg = G_UNIX_FD_MESSAGE (scms[0]);
183   g_free (scms);
184
185   fds = g_unix_fd_message_steal_fds (fdmsg, &nfd);
186   g_object_unref (fdmsg);
187
188   if (nfd != 1)
189     {
190       gint i;
191
192       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
193                    ngettext("Expecting one fd, but got %d\n",
194                             "Expecting one fd, but got %d\n",
195                             nfd),
196                    nfd);
197
198       for (i = 0; i < nfd; i++)
199         close (fds[i]);
200
201       g_free (fds);
202
203       return -1;
204     }
205
206   fd = *fds;
207   g_free (fds);
208
209   if (fd < 0)
210     {
211       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
212                            _("Received invalid fd"));
213       fd = -1;
214     }
215
216   return fd;
217 }
218
219 static void
220 g_unix_connection_init (GUnixConnection *connection)
221 {
222 }
223
224 static void
225 g_unix_connection_class_init (GUnixConnectionClass *class)
226 {
227 }
228
229 /* TODO: Other stuff we might want to add are:
230 void                    g_unix_connection_send_fd_async                 (GUnixConnection      *connection,
231                                                                          gint                  fd,
232                                                                          gboolean              close,
233                                                                          gint                  io_priority,
234                                                                          GAsyncReadyCallback   callback,
235                                                                          gpointer              user_data);
236 gboolean                g_unix_connection_send_fd_finish                (GUnixConnection      *connection,
237                                                                          GError              **error);
238
239 gboolean                g_unix_connection_send_fds                      (GUnixConnection      *connection,
240                                                                          gint                 *fds,
241                                                                          gint                  nfds,
242                                                                          GError              **error);
243 void                    g_unix_connection_send_fds_async                (GUnixConnection      *connection,
244                                                                          gint                 *fds,
245                                                                          gint                  nfds,
246                                                                          gint                  io_priority,
247                                                                          GAsyncReadyCallback   callback,
248                                                                          gpointer              user_data);
249 gboolean                g_unix_connection_send_fds_finish               (GUnixConnection      *connection,
250                                                                          GError              **error);
251
252 void                    g_unix_connection_receive_fd_async              (GUnixConnection      *connection,
253                                                                          gint                  io_priority,
254                                                                          GAsyncReadyCallback   callback,
255                                                                          gpointer              user_data);
256 gint                    g_unix_connection_receive_fd_finish             (GUnixConnection      *connection,
257                                                                          GError              **error);
258
259
260 gboolean                g_unix_connection_send_fake_credentials         (GUnixConnection      *connection,
261                                                                          guint64               pid,
262                                                                          guint64               uid,
263                                                                          guint64               gid,
264                                                                          GError              **error);
265 void                    g_unix_connection_send_fake_credentials_async   (GUnixConnection      *connection,
266                                                                          guint64               pid,
267                                                                          guint64               uid,
268                                                                          guint64               gid,
269                                                                          gint                  io_priority,
270                                                                          GAsyncReadyCallback   callback,
271                                                                          gpointer              user_data);
272 gboolean                g_unix_connection_send_fake_credentials_finish  (GUnixConnection      *connection,
273                                                                          GError              **error);
274
275 gboolean                g_unix_connection_create_pair                   (GUnixConnection     **one,
276                                                                          GUnixConnection     **two,
277                                                                          GError              **error);
278 */
279
280
281 /**
282  * g_unix_connection_send_credentials:
283  * @connection: A #GUnixConnection.
284  * @cancellable: (allow-none): A #GCancellable or %NULL.
285  * @error: Return location for error or %NULL.
286  *
287  * Passes the credentials of the current user the receiving side
288  * of the connection. The receiving end has to call
289  * g_unix_connection_receive_credentials() (or similar) to accept the
290  * credentials.
291  *
292  * As well as sending the credentials this also writes a single NUL
293  * byte to the stream, as this is required for credentials passing to
294  * work on some implementations.
295  *
296  * Other ways to exchange credentials with a foreign peer includes the
297  * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
298  *
299  * Returns: %TRUE on success, %FALSE if @error is set.
300  *
301  * Since: 2.26
302  */
303 gboolean
304 g_unix_connection_send_credentials (GUnixConnection      *connection,
305                                     GCancellable         *cancellable,
306                                     GError              **error)
307 {
308   GCredentials *credentials;
309   GSocketControlMessage *scm;
310   GSocket *socket;
311   gboolean ret;
312   GOutputVector vector;
313   guchar nul_byte[1] = {'\0'};
314   gint num_messages;
315
316   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
317   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
318
319   ret = FALSE;
320
321   credentials = g_credentials_new ();
322
323   vector.buffer = &nul_byte;
324   vector.size = 1;
325
326   if (g_unix_credentials_message_is_supported ())
327     {
328       scm = g_unix_credentials_message_new_with_credentials (credentials);
329       num_messages = 1;
330     }
331   else
332     {
333       scm = NULL;
334       num_messages = 0;
335     }
336
337   g_object_get (connection, "socket", &socket, NULL);
338   if (g_socket_send_message (socket,
339                              NULL, /* address */
340                              &vector,
341                              1,
342                              &scm,
343                              num_messages,
344                              G_SOCKET_MSG_NONE,
345                              cancellable,
346                              error) != 1)
347     {
348       g_prefix_error (error, _("Error sending credentials: "));
349       goto out;
350     }
351
352   ret = TRUE;
353
354  out:
355   g_object_unref (socket);
356   if (scm != NULL)
357     g_object_unref (scm);
358   g_object_unref (credentials);
359   return ret;
360 }
361
362 static void
363 send_credentials_async_thread (GTask         *task,
364                                gpointer       source_object,
365                                gpointer       task_data,
366                                GCancellable  *cancellable)
367 {
368   GError *error = NULL;
369
370   if (g_unix_connection_send_credentials (G_UNIX_CONNECTION (source_object),
371                                           cancellable,
372                                           &error))
373     g_task_return_boolean (task, TRUE);
374   else
375     g_task_return_error (task, error);
376   g_object_unref (task);
377 }
378
379 /**
380  * g_unix_connection_send_credentials_async:
381  * @connection: A #GUnixConnection.
382  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
383  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
384  * @user_data: (closure): the data to pass to callback function
385  *
386  * Asynchronously send credentials.
387  *
388  * For more details, see g_unix_connection_send_credentials() which is
389  * the synchronous version of this call.
390  *
391  * When the operation is finished, @callback will be called. You can then call
392  * g_unix_connection_send_credentials_finish() to get the result of the operation.
393  *
394  * Since: 2.32
395  **/
396 void
397 g_unix_connection_send_credentials_async (GUnixConnection      *connection,
398                                           GCancellable         *cancellable,
399                                           GAsyncReadyCallback   callback,
400                                           gpointer              user_data)
401 {
402   GTask *task;
403
404   task = g_task_new (connection, cancellable, callback, user_data);
405
406   g_task_run_in_thread (task, send_credentials_async_thread);
407 }
408
409 /**
410  * g_unix_connection_send_credentials_finish:
411  * @connection: A #GUnixConnection.
412  * @result: a #GAsyncResult.
413  * @error: a #GError, or %NULL
414  *
415  * Finishes an asynchronous send credentials operation started with
416  * g_unix_connection_send_credentials_async().
417  *
418  * Returns: %TRUE if the operation was successful, otherwise %FALSE.
419  *
420  * Since: 2.32
421  **/
422 gboolean
423 g_unix_connection_send_credentials_finish (GUnixConnection *connection,
424                                            GAsyncResult    *result,
425                                            GError         **error)
426 {
427   g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
428
429   return g_task_propagate_boolean (G_TASK (result), error);
430 }
431
432 /**
433  * g_unix_connection_receive_credentials:
434  * @connection: A #GUnixConnection.
435  * @cancellable: (allow-none): A #GCancellable or %NULL.
436  * @error: Return location for error or %NULL.
437  *
438  * Receives credentials from the sending end of the connection.  The
439  * sending end has to call g_unix_connection_send_credentials() (or
440  * similar) for this to work.
441  *
442  * As well as reading the credentials this also reads (and discards) a
443  * single byte from the stream, as this is required for credentials
444  * passing to work on some implementations.
445  *
446  * Other ways to exchange credentials with a foreign peer includes the
447  * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
448  *
449  * Returns: (transfer full): Received credentials on success (free with
450  * g_object_unref()), %NULL if @error is set.
451  *
452  * Since: 2.26
453  */
454 GCredentials *
455 g_unix_connection_receive_credentials (GUnixConnection      *connection,
456                                        GCancellable         *cancellable,
457                                        GError              **error)
458 {
459   GCredentials *ret;
460   GSocketControlMessage **scms;
461   gint nscm;
462   GSocket *socket;
463   gint n;
464   gssize num_bytes_read;
465 #ifdef __linux__
466   gboolean turn_off_so_passcreds;
467 #endif
468
469   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL);
470   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
471
472   ret = NULL;
473   scms = NULL;
474
475   g_object_get (connection, "socket", &socket, NULL);
476
477   /* On Linux, we need to turn on SO_PASSCRED if it isn't enabled
478    * already. We also need to turn it off when we're done.  See
479    * #617483 for more discussion.
480    */
481 #ifdef __linux__
482   {
483     gint opt_val;
484
485     turn_off_so_passcreds = FALSE;
486     opt_val = 0;
487     if (!g_socket_get_option (socket,
488                               SOL_SOCKET,
489                               SO_PASSCRED,
490                               &opt_val,
491                               NULL))
492       {
493         g_set_error (error,
494                      G_IO_ERROR,
495                      g_io_error_from_errno (errno),
496                      _("Error checking if SO_PASSCRED is enabled for socket: %s"),
497                      strerror (errno));
498         goto out;
499       }
500     if (opt_val == 0)
501       {
502         if (!g_socket_set_option (socket,
503                                   SOL_SOCKET,
504                                   SO_PASSCRED,
505                                   TRUE,
506                                   NULL))
507           {
508             g_set_error (error,
509                          G_IO_ERROR,
510                          g_io_error_from_errno (errno),
511                          _("Error enabling SO_PASSCRED: %s"),
512                          strerror (errno));
513             goto out;
514           }
515         turn_off_so_passcreds = TRUE;
516       }
517   }
518 #endif
519
520   g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE);
521   num_bytes_read = g_socket_receive_message (socket,
522                                              NULL, /* GSocketAddress **address */
523                                              NULL,
524                                              0,
525                                              &scms,
526                                              &nscm,
527                                              NULL,
528                                              cancellable,
529                                              error);
530   if (num_bytes_read != 1)
531     {
532       /* Handle situation where g_socket_receive_message() returns
533        * 0 bytes and not setting @error
534        */
535       if (num_bytes_read == 0 && error != NULL && *error == NULL)
536         {
537           g_set_error_literal (error,
538                                G_IO_ERROR,
539                                G_IO_ERROR_FAILED,
540                                _("Expecting to read a single byte for receiving credentials but read zero bytes"));
541         }
542       goto out;
543     }
544
545   if (g_unix_credentials_message_is_supported () &&
546       /* Fall back on get_credentials if the other side didn't send the credentials */
547       nscm > 0)
548     {
549       if (nscm != 1)
550         {
551           g_set_error (error,
552                        G_IO_ERROR,
553                        G_IO_ERROR_FAILED,
554                        ngettext("Expecting 1 control message, got %d",
555                                 "Expecting 1 control message, got %d",
556                                 nscm),
557                        nscm);
558           goto out;
559         }
560
561       if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0]))
562         {
563           g_set_error_literal (error,
564                                G_IO_ERROR,
565                                G_IO_ERROR_FAILED,
566                                _("Unexpected type of ancillary data"));
567           goto out;
568         }
569
570       ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0]));
571       g_object_ref (ret);
572     }
573   else
574     {
575       if (nscm != 0)
576         {
577           g_set_error (error,
578                        G_IO_ERROR,
579                        G_IO_ERROR_FAILED,
580                        _("Not expecting control message, but got %d"),
581                        nscm);
582           goto out;
583         }
584       else
585         {
586           ret = g_socket_get_credentials (socket, error);
587         }
588     }
589
590  out:
591
592 #ifdef __linux__
593   if (turn_off_so_passcreds)
594     {
595       if (!g_socket_set_option (socket,
596                                 SOL_SOCKET,
597                                 SO_PASSCRED,
598                                 FALSE,
599                                 NULL))
600         {
601           g_set_error (error,
602                        G_IO_ERROR,
603                        g_io_error_from_errno (errno),
604                        _("Error while disabling SO_PASSCRED: %s"),
605                        strerror (errno));
606           goto out;
607         }
608     }
609 #endif
610
611   if (scms != NULL)
612     {
613       for (n = 0; n < nscm; n++)
614         g_object_unref (scms[n]);
615       g_free (scms);
616     }
617   g_object_unref (socket);
618   return ret;
619 }
620
621 static void
622 receive_credentials_async_thread (GTask         *task,
623                                   gpointer       source_object,
624                                   gpointer       task_data,
625                                   GCancellable  *cancellable)
626 {
627   GCredentials *creds;
628   GError *error = NULL;
629
630   creds = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (source_object),
631                                                  cancellable,
632                                                  &error);
633   if (creds)
634     g_task_return_pointer (task, creds, g_object_unref);
635   else
636     g_task_return_error (task, error);
637   g_object_unref (task);
638 }
639
640 /**
641  * g_unix_connection_receive_credentials_async:
642  * @connection: A #GUnixConnection.
643  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
644  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
645  * @user_data: (closure): the data to pass to callback function
646  *
647  * Asynchronously receive credentials.
648  *
649  * For more details, see g_unix_connection_receive_credentials() which is
650  * the synchronous version of this call.
651  *
652  * When the operation is finished, @callback will be called. You can then call
653  * g_unix_connection_receive_credentials_finish() to get the result of the operation.
654  *
655  * Since: 2.32
656  **/
657 void
658 g_unix_connection_receive_credentials_async (GUnixConnection      *connection,
659                                               GCancellable         *cancellable,
660                                               GAsyncReadyCallback   callback,
661                                               gpointer              user_data)
662 {
663   GTask *task;
664
665   task = g_task_new (connection, cancellable, callback, user_data);
666
667   g_task_run_in_thread (task, receive_credentials_async_thread);
668 }
669
670 /**
671  * g_unix_connection_receive_credentials_finish:
672  * @connection: A #GUnixConnection.
673  * @result: a #GAsyncResult.
674  * @error: a #GError, or %NULL
675  *
676  * Finishes an asynchronous receive credentials operation started with
677  * g_unix_connection_receive_credentials_async().
678  *
679  * Returns: (transfer full): a #GCredentials, or %NULL on error.
680  *     Free the returned object with g_object_unref().
681  *
682  * Since: 2.32
683  **/
684 GCredentials *
685 g_unix_connection_receive_credentials_finish (GUnixConnection *connection,
686                                               GAsyncResult    *result,
687                                               GError         **error)
688 {
689   g_return_val_if_fail (g_task_is_valid (result, connection), NULL);
690
691   return g_task_propagate_pointer (G_TASK (result), error);
692 }