gsocket: add getsockopt/setsockopt wrappers
[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 <filename>&lt;gio/gunixconnection.h&gt;</filename> belongs to
43  * the UNIX-specific GIO interfaces, thus you have to use the
44  * <filename>gio-unix-2.0.pc</filename> 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                    _("Expecting 1 control message, got %d"), nscm);
160
161       for (i = 0; i < nscm; i++)
162         g_object_unref (scms[i]);
163
164       g_free (scms);
165
166       return -1;
167     }
168
169   if (!G_IS_UNIX_FD_MESSAGE (scms[0]))
170     {
171       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
172                            _("Unexpected type of ancillary data"));
173       g_object_unref (scms[0]);
174       g_free (scms);
175
176       return -1;
177     }
178
179   fdmsg = G_UNIX_FD_MESSAGE (scms[0]);
180   g_free (scms);
181
182   fds = g_unix_fd_message_steal_fds (fdmsg, &nfd);
183   g_object_unref (fdmsg);
184
185   if (nfd != 1)
186     {
187       gint i;
188
189       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
190                    _("Expecting one fd, but got %d\n"), nfd);
191
192       for (i = 0; i < nfd; i++)
193         close (fds[i]);
194
195       g_free (fds);
196
197       return -1;
198     }
199
200   fd = *fds;
201   g_free (fds);
202
203   if (fd < 0)
204     {
205       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
206                            _("Received invalid fd"));
207       fd = -1;
208     }
209
210   return fd;
211 }
212
213 static void
214 g_unix_connection_init (GUnixConnection *connection)
215 {
216 }
217
218 static void
219 g_unix_connection_class_init (GUnixConnectionClass *class)
220 {
221 }
222
223 /* TODO: Other stuff we might want to add are:
224 void                    g_unix_connection_send_fd_async                 (GUnixConnection      *connection,
225                                                                          gint                  fd,
226                                                                          gboolean              close,
227                                                                          gint                  io_priority,
228                                                                          GAsyncReadyCallback   callback,
229                                                                          gpointer              user_data);
230 gboolean                g_unix_connection_send_fd_finish                (GUnixConnection      *connection,
231                                                                          GError              **error);
232
233 gboolean                g_unix_connection_send_fds                      (GUnixConnection      *connection,
234                                                                          gint                 *fds,
235                                                                          gint                  nfds,
236                                                                          GError              **error);
237 void                    g_unix_connection_send_fds_async                (GUnixConnection      *connection,
238                                                                          gint                 *fds,
239                                                                          gint                  nfds,
240                                                                          gint                  io_priority,
241                                                                          GAsyncReadyCallback   callback,
242                                                                          gpointer              user_data);
243 gboolean                g_unix_connection_send_fds_finish               (GUnixConnection      *connection,
244                                                                          GError              **error);
245
246 void                    g_unix_connection_receive_fd_async              (GUnixConnection      *connection,
247                                                                          gint                  io_priority,
248                                                                          GAsyncReadyCallback   callback,
249                                                                          gpointer              user_data);
250 gint                    g_unix_connection_receive_fd_finish             (GUnixConnection      *connection,
251                                                                          GError              **error);
252
253
254 gboolean                g_unix_connection_send_fake_credentials         (GUnixConnection      *connection,
255                                                                          guint64               pid,
256                                                                          guint64               uid,
257                                                                          guint64               gid,
258                                                                          GError              **error);
259 void                    g_unix_connection_send_fake_credentials_async   (GUnixConnection      *connection,
260                                                                          guint64               pid,
261                                                                          guint64               uid,
262                                                                          guint64               gid,
263                                                                          gint                  io_priority,
264                                                                          GAsyncReadyCallback   callback,
265                                                                          gpointer              user_data);
266 gboolean                g_unix_connection_send_fake_credentials_finish  (GUnixConnection      *connection,
267                                                                          GError              **error);
268
269 gboolean                g_unix_connection_create_pair                   (GUnixConnection     **one,
270                                                                          GUnixConnection     **two,
271                                                                          GError              **error);
272 */
273
274
275 /**
276  * g_unix_connection_send_credentials:
277  * @connection: A #GUnixConnection.
278  * @cancellable: (allow-none): A #GCancellable or %NULL.
279  * @error: Return location for error or %NULL.
280  *
281  * Passes the credentials of the current user the receiving side
282  * of the connection. The receiving end has to call
283  * g_unix_connection_receive_credentials() (or similar) to accept the
284  * credentials.
285  *
286  * As well as sending the credentials this also writes a single NUL
287  * byte to the stream, as this is required for credentials passing to
288  * work on some implementations.
289  *
290  * Other ways to exchange credentials with a foreign peer includes the
291  * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
292  *
293  * Returns: %TRUE on success, %FALSE if @error is set.
294  *
295  * Since: 2.26
296  */
297 gboolean
298 g_unix_connection_send_credentials (GUnixConnection      *connection,
299                                     GCancellable         *cancellable,
300                                     GError              **error)
301 {
302   GCredentials *credentials;
303   GSocketControlMessage *scm;
304   GSocket *socket;
305   gboolean ret;
306   GOutputVector vector;
307   guchar nul_byte[1] = {'\0'};
308   gint num_messages;
309
310   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
311   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
312
313   ret = FALSE;
314
315   credentials = g_credentials_new ();
316
317   vector.buffer = &nul_byte;
318   vector.size = 1;
319
320   if (g_unix_credentials_message_is_supported ())
321     {
322       scm = g_unix_credentials_message_new_with_credentials (credentials);
323       num_messages = 1;
324     }
325   else
326     {
327       scm = NULL;
328       num_messages = 0;
329     }
330
331   g_object_get (connection, "socket", &socket, NULL);
332   if (g_socket_send_message (socket,
333                              NULL, /* address */
334                              &vector,
335                              1,
336                              &scm,
337                              num_messages,
338                              G_SOCKET_MSG_NONE,
339                              cancellable,
340                              error) != 1)
341     {
342       g_prefix_error (error, _("Error sending credentials: "));
343       goto out;
344     }
345
346   ret = TRUE;
347
348  out:
349   g_object_unref (socket);
350   if (scm != NULL)
351     g_object_unref (scm);
352   g_object_unref (credentials);
353   return ret;
354 }
355
356 static void
357 send_credentials_async_thread (GTask         *task,
358                                gpointer       source_object,
359                                gpointer       task_data,
360                                GCancellable  *cancellable)
361 {
362   GError *error = NULL;
363
364   if (g_unix_connection_send_credentials (G_UNIX_CONNECTION (source_object),
365                                           cancellable,
366                                           &error))
367     g_task_return_boolean (task, TRUE);
368   else
369     g_task_return_error (task, error);
370   g_object_unref (task);
371 }
372
373 /**
374  * g_unix_connection_send_credentials_async:
375  * @connection: A #GUnixConnection.
376  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
377  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
378  * @user_data: (closure): the data to pass to callback function
379  *
380  * Asynchronously send credentials.
381  *
382  * For more details, see g_unix_connection_send_credentials() which is
383  * the synchronous version of this call.
384  *
385  * When the operation is finished, @callback will be called. You can then call
386  * g_unix_connection_send_credentials_finish() to get the result of the operation.
387  *
388  * Since: 2.32
389  **/
390 void
391 g_unix_connection_send_credentials_async (GUnixConnection      *connection,
392                                           GCancellable         *cancellable,
393                                           GAsyncReadyCallback   callback,
394                                           gpointer              user_data)
395 {
396   GTask *task;
397
398   task = g_task_new (connection, cancellable, callback, user_data);
399
400   g_task_run_in_thread (task, send_credentials_async_thread);
401 }
402
403 /**
404  * g_unix_connection_send_credentials_finish:
405  * @connection: A #GUnixConnection.
406  * @result: a #GAsyncResult.
407  * @error: a #GError, or %NULL
408  *
409  * Finishes an asynchronous send credentials operation started with
410  * g_unix_connection_send_credentials_async().
411  *
412  * Returns: %TRUE if the operation was successful, otherwise %FALSE.
413  *
414  * Since: 2.32
415  **/
416 gboolean
417 g_unix_connection_send_credentials_finish (GUnixConnection *connection,
418                                            GAsyncResult    *result,
419                                            GError         **error)
420 {
421   g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
422
423   return g_task_propagate_boolean (G_TASK (result), error);
424 }
425
426 /**
427  * g_unix_connection_receive_credentials:
428  * @connection: A #GUnixConnection.
429  * @cancellable: (allow-none): A #GCancellable or %NULL.
430  * @error: Return location for error or %NULL.
431  *
432  * Receives credentials from the sending end of the connection.  The
433  * sending end has to call g_unix_connection_send_credentials() (or
434  * similar) for this to work.
435  *
436  * As well as reading the credentials this also reads (and discards) a
437  * single byte from the stream, as this is required for credentials
438  * passing to work on some implementations.
439  *
440  * Other ways to exchange credentials with a foreign peer includes the
441  * #GUnixCredentialsMessage type and g_socket_get_credentials() function.
442  *
443  * Returns: (transfer full): Received credentials on success (free with
444  * g_object_unref()), %NULL if @error is set.
445  *
446  * Since: 2.26
447  */
448 GCredentials *
449 g_unix_connection_receive_credentials (GUnixConnection      *connection,
450                                        GCancellable         *cancellable,
451                                        GError              **error)
452 {
453   GCredentials *ret;
454   GSocketControlMessage **scms;
455   gint nscm;
456   GSocket *socket;
457   gint n;
458   gssize num_bytes_read;
459 #ifdef __linux__
460   gboolean turn_off_so_passcreds;
461 #endif
462
463   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL);
464   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
465
466   ret = NULL;
467   scms = NULL;
468
469   g_object_get (connection, "socket", &socket, NULL);
470
471   /* On Linux, we need to turn on SO_PASSCRED if it isn't enabled
472    * already. We also need to turn it off when we're done.  See
473    * #617483 for more discussion.
474    */
475 #ifdef __linux__
476   {
477     gint opt_val;
478
479     turn_off_so_passcreds = FALSE;
480     opt_val = 0;
481     if (!g_socket_get_option (socket,
482                               SOL_SOCKET,
483                               SO_PASSCRED,
484                               &opt_val,
485                               NULL))
486       {
487         g_set_error (error,
488                      G_IO_ERROR,
489                      g_io_error_from_errno (errno),
490                      _("Error checking if SO_PASSCRED is enabled for socket: %s"),
491                      strerror (errno));
492         goto out;
493       }
494     if (opt_val == 0)
495       {
496         if (!g_socket_set_option (socket,
497                                   SOL_SOCKET,
498                                   SO_PASSCRED,
499                                   TRUE,
500                                   NULL))
501           {
502             g_set_error (error,
503                          G_IO_ERROR,
504                          g_io_error_from_errno (errno),
505                          _("Error enabling SO_PASSCRED: %s"),
506                          strerror (errno));
507             goto out;
508           }
509         turn_off_so_passcreds = TRUE;
510       }
511   }
512 #endif
513
514   g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE);
515   num_bytes_read = g_socket_receive_message (socket,
516                                              NULL, /* GSocketAddress **address */
517                                              NULL,
518                                              0,
519                                              &scms,
520                                              &nscm,
521                                              NULL,
522                                              cancellable,
523                                              error);
524   if (num_bytes_read != 1)
525     {
526       /* Handle situation where g_socket_receive_message() returns
527        * 0 bytes and not setting @error
528        */
529       if (num_bytes_read == 0 && error != NULL && *error == NULL)
530         {
531           g_set_error_literal (error,
532                                G_IO_ERROR,
533                                G_IO_ERROR_FAILED,
534                                _("Expecting to read a single byte for receiving credentials but read zero bytes"));
535         }
536       goto out;
537     }
538
539   if (g_unix_credentials_message_is_supported () &&
540       /* Fall back on get_credentials if the other side didn't send the credentials */
541       nscm > 0)
542     {
543       if (nscm != 1)
544         {
545           g_set_error (error,
546                        G_IO_ERROR,
547                        G_IO_ERROR_FAILED,
548                        _("Expecting 1 control message, got %d"),
549                        nscm);
550           goto out;
551         }
552
553       if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0]))
554         {
555           g_set_error_literal (error,
556                                G_IO_ERROR,
557                                G_IO_ERROR_FAILED,
558                                _("Unexpected type of ancillary data"));
559           goto out;
560         }
561
562       ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0]));
563       g_object_ref (ret);
564     }
565   else
566     {
567       if (nscm != 0)
568         {
569           g_set_error (error,
570                        G_IO_ERROR,
571                        G_IO_ERROR_FAILED,
572                        _("Not expecting control message, but got %d"),
573                        nscm);
574           goto out;
575         }
576       else
577         {
578           ret = g_socket_get_credentials (socket, error);
579         }
580     }
581
582  out:
583
584 #ifdef __linux__
585   if (turn_off_so_passcreds)
586     {
587       if (!g_socket_set_option (socket,
588                                 SOL_SOCKET,
589                                 SO_PASSCRED,
590                                 FALSE,
591                                 NULL))
592         {
593           g_set_error (error,
594                        G_IO_ERROR,
595                        g_io_error_from_errno (errno),
596                        _("Error while disabling SO_PASSCRED: %s"),
597                        strerror (errno));
598           goto out;
599         }
600     }
601 #endif
602
603   if (scms != NULL)
604     {
605       for (n = 0; n < nscm; n++)
606         g_object_unref (scms[n]);
607       g_free (scms);
608     }
609   g_object_unref (socket);
610   return ret;
611 }
612
613 static void
614 receive_credentials_async_thread (GTask         *task,
615                                   gpointer       source_object,
616                                   gpointer       task_data,
617                                   GCancellable  *cancellable)
618 {
619   GCredentials *creds;
620   GError *error = NULL;
621
622   creds = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (source_object),
623                                                  cancellable,
624                                                  &error);
625   if (creds)
626     g_task_return_pointer (task, creds, g_object_unref);
627   else
628     g_task_return_error (task, error);
629   g_object_unref (task);
630 }
631
632 /**
633  * g_unix_connection_receive_credentials_async:
634  * @connection: A #GUnixConnection.
635  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
636  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
637  * @user_data: (closure): the data to pass to callback function
638  *
639  * Asynchronously receive credentials.
640  *
641  * For more details, see g_unix_connection_receive_credentials() which is
642  * the synchronous version of this call.
643  *
644  * When the operation is finished, @callback will be called. You can then call
645  * g_unix_connection_receive_credentials_finish() to get the result of the operation.
646  *
647  * Since: 2.32
648  **/
649 void
650 g_unix_connection_receive_credentials_async (GUnixConnection      *connection,
651                                               GCancellable         *cancellable,
652                                               GAsyncReadyCallback   callback,
653                                               gpointer              user_data)
654 {
655   GTask *task;
656
657   task = g_task_new (connection, cancellable, callback, user_data);
658
659   g_task_run_in_thread (task, receive_credentials_async_thread);
660 }
661
662 /**
663  * g_unix_connection_receive_credentials_finish:
664  * @connection: A #GUnixConnection.
665  * @result: a #GAsyncResult.
666  * @error: a #GError, or %NULL
667  *
668  * Finishes an asynchronous receive credentials operation started with
669  * g_unix_connection_receive_credentials_async().
670  *
671  * Returns: (transfer full): a #GCredentials, or %NULL on error.
672  *     Free the returned object with g_object_unref().
673  *
674  * Since: 2.32
675  **/
676 GCredentials *
677 g_unix_connection_receive_credentials_finish (GUnixConnection *connection,
678                                               GAsyncResult    *result,
679                                               GError         **error)
680 {
681   g_return_val_if_fail (g_task_is_valid (result, connection), NULL);
682
683   return g_task_propagate_pointer (G_TASK (result), error);
684 }