Imported Upstream version 2.67.2
[platform/upstream/glib.git] / gio / gcredentials.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <gobject/gvaluecollector.h>
27
28 #include "gcredentials.h"
29 #include "gcredentialsprivate.h"
30 #include "gnetworking.h"
31 #include "gioerror.h"
32 #include "gioenumtypes.h"
33
34 #include "glibintl.h"
35
36 /**
37  * SECTION:gcredentials
38  * @short_description: An object containing credentials
39  * @include: gio/gio.h
40  *
41  * The #GCredentials type is a reference-counted wrapper for native
42  * credentials. This information is typically used for identifying,
43  * authenticating and authorizing other processes.
44  *
45  * Some operating systems supports looking up the credentials of the
46  * remote peer of a communication endpoint - see e.g.
47  * g_socket_get_credentials().
48  *
49  * Some operating systems supports securely sending and receiving
50  * credentials over a Unix Domain Socket, see
51  * #GUnixCredentialsMessage, g_unix_connection_send_credentials() and
52  * g_unix_connection_receive_credentials() for details.
53  *
54  * On Linux, the native credential type is a `struct ucred` - see the
55  * unix(7) man page for details. This corresponds to
56  * %G_CREDENTIALS_TYPE_LINUX_UCRED.
57  *
58  * On Apple operating systems (including iOS, tvOS, and macOS),
59  * the native credential type is a `struct xucred`.
60  * This corresponds to %G_CREDENTIALS_TYPE_APPLE_XUCRED.
61  *
62  * On FreeBSD, Debian GNU/kFreeBSD, and GNU/Hurd, the native
63  * credential type is a `struct cmsgcred`. This corresponds
64  * to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED.
65  *
66  * On NetBSD, the native credential type is a `struct unpcbid`.
67  * This corresponds to %G_CREDENTIALS_TYPE_NETBSD_UNPCBID.
68  *
69  * On OpenBSD, the native credential type is a `struct sockpeercred`.
70  * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
71  *
72  * On Solaris (including OpenSolaris and its derivatives), the native
73  * credential type is a `ucred_t`. This corresponds to
74  * %G_CREDENTIALS_TYPE_SOLARIS_UCRED.
75  */
76
77 /**
78  * GCredentials:
79  *
80  * The #GCredentials structure contains only private data and
81  * should only be accessed using the provided API.
82  *
83  * Since: 2.26
84  */
85 struct _GCredentials
86 {
87   /*< private >*/
88   GObject parent_instance;
89
90 #if G_CREDENTIALS_USE_LINUX_UCRED
91   struct ucred native;
92 #elif G_CREDENTIALS_USE_APPLE_XUCRED
93   struct xucred native;
94 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
95   struct cmsgcred native;
96 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
97   struct unpcbid native;
98 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
99   struct sockpeercred native;
100 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
101   ucred_t *native;
102 #else
103   #ifdef __GNUC__
104   #pragma GCC diagnostic push
105   #pragma GCC diagnostic warning "-Wcpp"
106   #warning Please add GCredentials support for your OS
107   #pragma GCC diagnostic pop
108   #endif
109 #endif
110 };
111
112 /**
113  * GCredentialsClass:
114  *
115  * Class structure for #GCredentials.
116  *
117  * Since: 2.26
118  */
119 struct _GCredentialsClass
120 {
121   /*< private >*/
122   GObjectClass parent_class;
123 };
124
125 G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT)
126
127 static void
128 g_credentials_finalize (GObject *object)
129 {
130 #if G_CREDENTIALS_USE_SOLARIS_UCRED
131   GCredentials *credentials = G_CREDENTIALS (object);
132
133   ucred_free (credentials->native);
134 #endif
135
136   if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
137     G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
138 }
139
140
141 static void
142 g_credentials_class_init (GCredentialsClass *klass)
143 {
144   GObjectClass *gobject_class;
145
146   gobject_class = G_OBJECT_CLASS (klass);
147   gobject_class->finalize = g_credentials_finalize;
148 }
149
150 static void
151 g_credentials_init (GCredentials *credentials)
152 {
153 #if G_CREDENTIALS_USE_LINUX_UCRED
154   credentials->native.pid = getpid ();
155   credentials->native.uid = geteuid ();
156   credentials->native.gid = getegid ();
157 #elif G_CREDENTIALS_USE_APPLE_XUCRED
158   gsize i;
159
160   credentials->native.cr_version = XUCRED_VERSION;
161   credentials->native.cr_uid = geteuid ();
162   credentials->native.cr_ngroups = 1;
163   credentials->native.cr_groups[0] = getegid ();
164
165   /* FIXME: In principle this could use getgroups() to fill in the rest
166    * of cr_groups, but then we'd have to handle the case where a process
167    * can have more than NGROUPS groups, if that's even possible. A macOS
168    * user would have to develop and test this.
169    *
170    * For now we fill it with -1 (meaning "no data"). */
171   for (i = 1; i < NGROUPS; i++)
172     credentials->native.cr_groups[i] = -1;
173 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
174   memset (&credentials->native, 0, sizeof (struct cmsgcred));
175   credentials->native.cmcred_pid  = getpid ();
176   credentials->native.cmcred_euid = geteuid ();
177   credentials->native.cmcred_gid  = getegid ();
178 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
179   credentials->native.unp_pid = getpid ();
180   credentials->native.unp_euid = geteuid ();
181   credentials->native.unp_egid = getegid ();
182 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
183   credentials->native.pid = getpid ();
184   credentials->native.uid = geteuid ();
185   credentials->native.gid = getegid ();
186 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
187   credentials->native = ucred_get (P_MYID);
188 #endif
189 }
190
191 /* ---------------------------------------------------------------------------------------------------- */
192
193 /**
194  * g_credentials_new:
195  *
196  * Creates a new #GCredentials object with credentials matching the
197  * the current process.
198  *
199  * Returns: (transfer full): A #GCredentials. Free with g_object_unref().
200  *
201  * Since: 2.26
202  */
203 GCredentials *
204 g_credentials_new (void)
205 {
206   return g_object_new (G_TYPE_CREDENTIALS, NULL);
207 }
208
209 /* ---------------------------------------------------------------------------------------------------- */
210
211 /**
212  * g_credentials_to_string:
213  * @credentials: A #GCredentials object.
214  *
215  * Creates a human-readable textual representation of @credentials
216  * that can be used in logging and debug messages. The format of the
217  * returned string may change in future GLib release.
218  *
219  * Returns: (transfer full): A string that should be freed with g_free().
220  *
221  * Since: 2.26
222  */
223 gchar *
224 g_credentials_to_string (GCredentials *credentials)
225 {
226   GString *ret;
227 #if G_CREDENTIALS_USE_APPLE_XUCRED
228   glib_typeof (credentials->native.cr_ngroups) i;
229 #endif
230
231   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
232
233   ret = g_string_new ("GCredentials:");
234 #if G_CREDENTIALS_USE_LINUX_UCRED
235   g_string_append (ret, "linux-ucred:");
236   if (credentials->native.pid != (pid_t) -1)
237     g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
238   if (credentials->native.uid != (uid_t) -1)
239     g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
240   if (credentials->native.gid != (gid_t) -1)
241     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
242   if (ret->str[ret->len - 1] == ',')
243     ret->str[ret->len - 1] = '\0';
244 #elif G_CREDENTIALS_USE_APPLE_XUCRED
245   g_string_append (ret, "apple-xucred:");
246   g_string_append_printf (ret, "version=%u,", credentials->native.cr_version);
247   if (credentials->native.cr_uid != (uid_t) -1)
248     g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_uid);
249   for (i = 0; i < credentials->native.cr_ngroups; i++)
250     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_groups[i]);
251   if (ret->str[ret->len - 1] == ',')
252     ret->str[ret->len - 1] = '\0';
253 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
254   g_string_append (ret, "freebsd-cmsgcred:");
255   if (credentials->native.cmcred_pid != (pid_t) -1)
256     g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid);
257   if (credentials->native.cmcred_euid != (uid_t) -1)
258     g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid);
259   if (credentials->native.cmcred_gid != (gid_t) -1)
260     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid);
261 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
262   g_string_append (ret, "netbsd-unpcbid:");
263   if (credentials->native.unp_pid != (pid_t) -1)
264     g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_pid);
265   if (credentials->native.unp_euid != (uid_t) -1)
266     g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_euid);
267   if (credentials->native.unp_egid != (gid_t) -1)
268     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_egid);
269   ret->str[ret->len - 1] = '\0';
270 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
271   g_string_append (ret, "openbsd-sockpeercred:");
272   if (credentials->native.pid != (pid_t) -1)
273     g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
274   if (credentials->native.uid != (uid_t) -1)
275     g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
276   if (credentials->native.gid != (gid_t) -1)
277     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
278   if (ret->str[ret->len - 1] == ',')
279     ret->str[ret->len - 1] = '\0';
280 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
281   g_string_append (ret, "solaris-ucred:");
282   {
283     id_t id;
284     if ((id = ucred_getpid (credentials->native)) != (id_t) -1)
285       g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id);
286     if ((id = ucred_geteuid (credentials->native)) != (id_t) -1)
287       g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id);
288     if ((id = ucred_getegid (credentials->native)) != (id_t) -1)
289       g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id);
290     if (ret->str[ret->len - 1] == ',')
291       ret->str[ret->len - 1] = '\0';
292   }
293 #else
294   g_string_append (ret, "unknown");
295 #endif
296
297   return g_string_free (ret, FALSE);
298 }
299
300 /* ---------------------------------------------------------------------------------------------------- */
301
302 #if G_CREDENTIALS_USE_LINUX_UCRED
303 /*
304  * Check whether @native contains invalid data. If getsockopt SO_PEERCRED
305  * is used on a TCP socket, it succeeds but yields a credentials structure
306  * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a
307  * receiving Unix socket when the sending socket did not also enable
308  * SO_PASSCRED, it can succeed but yield a credentials structure with
309  * pid 0, uid /proc/sys/kernel/overflowuid and gid
310  * /proc/sys/kernel/overflowgid.
311  */
312 static gboolean
313 linux_ucred_check_valid (struct ucred  *native,
314                          GError       **error)
315 {
316   if (native->pid == 0
317       || native->uid == -1
318       || native->gid == -1)
319     {
320       g_set_error_literal (error,
321                            G_IO_ERROR,
322                            G_IO_ERROR_INVALID_DATA,
323                            _("GCredentials contains invalid data"));
324       return FALSE;
325     }
326
327   return TRUE;
328 }
329 #endif
330
331 /**
332  * g_credentials_is_same_user:
333  * @credentials: A #GCredentials.
334  * @other_credentials: A #GCredentials.
335  * @error: Return location for error or %NULL.
336  *
337  * Checks if @credentials and @other_credentials is the same user.
338  *
339  * This operation can fail if #GCredentials is not supported on the
340  * the OS.
341  *
342  * Returns: %TRUE if @credentials and @other_credentials has the same
343  * user, %FALSE otherwise or if @error is set.
344  *
345  * Since: 2.26
346  */
347 gboolean
348 g_credentials_is_same_user (GCredentials  *credentials,
349                             GCredentials  *other_credentials,
350                             GError       **error)
351 {
352   gboolean ret;
353
354   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
355   g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE);
356   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
357
358   ret = FALSE;
359 #if G_CREDENTIALS_USE_LINUX_UCRED
360   if (linux_ucred_check_valid (&credentials->native, NULL)
361       && credentials->native.uid == other_credentials->native.uid)
362     ret = TRUE;
363 #elif G_CREDENTIALS_USE_APPLE_XUCRED
364   if (credentials->native.cr_version == other_credentials->native.cr_version &&
365       credentials->native.cr_uid == other_credentials->native.cr_uid)
366     ret = TRUE;
367 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
368   if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
369     ret = TRUE;
370 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
371   if (credentials->native.unp_euid == other_credentials->native.unp_euid)
372     ret = TRUE;
373 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
374   if (credentials->native.uid == other_credentials->native.uid)
375     ret = TRUE;
376 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
377   if (ucred_geteuid (credentials->native) == ucred_geteuid (other_credentials->native))
378     ret = TRUE;
379 #else
380   g_set_error_literal (error,
381                        G_IO_ERROR,
382                        G_IO_ERROR_NOT_SUPPORTED,
383                        _("GCredentials is not implemented on this OS"));
384 #endif
385
386   return ret;
387 }
388
389 static gboolean
390 credentials_native_type_check (GCredentialsType  requested_type,
391                                const char       *op)
392 {
393   GEnumClass *enum_class;
394   GEnumValue *requested;
395 #if G_CREDENTIALS_SUPPORTED
396   GEnumValue *supported;
397 #endif
398
399 #if G_CREDENTIALS_SUPPORTED
400   if (requested_type == G_CREDENTIALS_NATIVE_TYPE)
401     return TRUE;
402 #endif
403
404   enum_class = g_type_class_ref (g_credentials_type_get_type ());
405   requested = g_enum_get_value (enum_class, requested_type);
406
407 #if G_CREDENTIALS_SUPPORTED
408   supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE);
409   g_assert (supported);
410   g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
411              "but only %s is supported on this platform.",
412              op, op,
413              requested ? requested->value_name : "(unknown)",
414              supported->value_name);
415 #else
416   g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
417              "but there is no support for GCredentials on this platform.",
418              op, op,
419              requested ? requested->value_name : "(unknown)");
420 #endif
421
422   g_type_class_unref (enum_class);
423   return FALSE;
424 }
425
426 /**
427  * g_credentials_get_native: (skip)
428  * @credentials: A #GCredentials.
429  * @native_type: The type of native credentials to get.
430  *
431  * Gets a pointer to native credentials of type @native_type from
432  * @credentials.
433  *
434  * It is a programming error (which will cause a warning to be
435  * logged) to use this method if there is no #GCredentials support for
436  * the OS or if @native_type isn't supported by the OS.
437  *
438  * Returns: (transfer none) (nullable): The pointer to native credentials or
439  *     %NULL if there is no #GCredentials support for the OS or if @native_type
440  *     isn't supported by the OS. Do not free the returned data, it is owned
441  *     by @credentials.
442  *
443  * Since: 2.26
444  */
445 gpointer
446 g_credentials_get_native (GCredentials     *credentials,
447                           GCredentialsType  native_type)
448 {
449   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
450
451   if (!credentials_native_type_check (native_type, "get"))
452     return NULL;
453
454 #if G_CREDENTIALS_USE_SOLARIS_UCRED
455   return credentials->native;
456 #elif G_CREDENTIALS_SUPPORTED
457   return &credentials->native;
458 #else
459   g_assert_not_reached ();
460 #endif
461 }
462
463 /**
464  * g_credentials_set_native:
465  * @credentials: A #GCredentials.
466  * @native_type: The type of native credentials to set.
467  * @native: (not nullable): A pointer to native credentials.
468  *
469  * Copies the native credentials of type @native_type from @native
470  * into @credentials.
471  *
472  * It is a programming error (which will cause a warning to be
473  * logged) to use this method if there is no #GCredentials support for
474  * the OS or if @native_type isn't supported by the OS.
475  *
476  * Since: 2.26
477  */
478 void
479 g_credentials_set_native (GCredentials     *credentials,
480                           GCredentialsType  native_type,
481                           gpointer          native)
482 {
483   if (!credentials_native_type_check (native_type, "set"))
484     return;
485
486 #if G_CREDENTIALS_USE_SOLARIS_UCRED
487   memcpy (credentials->native, native, ucred_size ());
488 #elif G_CREDENTIALS_SUPPORTED
489   memcpy (&credentials->native, native, sizeof (credentials->native));
490 #else
491   g_assert_not_reached ();
492 #endif
493 }
494
495 /* ---------------------------------------------------------------------------------------------------- */
496
497 #ifdef G_OS_UNIX
498 /**
499  * g_credentials_get_unix_user:
500  * @credentials: A #GCredentials
501  * @error: Return location for error or %NULL.
502  *
503  * Tries to get the UNIX user identifier from @credentials. This
504  * method is only available on UNIX platforms.
505  *
506  * This operation can fail if #GCredentials is not supported on the
507  * OS or if the native credentials type does not contain information
508  * about the UNIX user.
509  *
510  * Returns: The UNIX user identifier or `-1` if @error is set.
511  *
512  * Since: 2.26
513  */
514 uid_t
515 g_credentials_get_unix_user (GCredentials    *credentials,
516                              GError         **error)
517 {
518   uid_t ret;
519
520   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
521   g_return_val_if_fail (error == NULL || *error == NULL, -1);
522
523 #if G_CREDENTIALS_USE_LINUX_UCRED
524   if (linux_ucred_check_valid (&credentials->native, error))
525     ret = credentials->native.uid;
526   else
527     ret = -1;
528 #elif G_CREDENTIALS_USE_APPLE_XUCRED
529   if (credentials->native.cr_version == XUCRED_VERSION)
530     {
531       ret = credentials->native.cr_uid;
532     }
533   else
534     {
535       g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
536                    /* No point in translating the part in parentheses... */
537                    "%s (struct xucred cr_version %u != %u)",
538                    _("There is no GCredentials support for your platform"),
539                    credentials->native.cr_version,
540                    XUCRED_VERSION);
541       ret = -1;
542     }
543 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
544   ret = credentials->native.cmcred_euid;
545 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
546   ret = credentials->native.unp_euid;
547 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
548   ret = credentials->native.uid;
549 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
550   ret = ucred_geteuid (credentials->native);
551 #else
552   ret = -1;
553   g_set_error_literal (error,
554                        G_IO_ERROR,
555                        G_IO_ERROR_NOT_SUPPORTED,
556                        _("There is no GCredentials support for your platform"));
557 #endif
558
559   return ret;
560 }
561
562 /**
563  * g_credentials_get_unix_pid:
564  * @credentials: A #GCredentials
565  * @error: Return location for error or %NULL.
566  *
567  * Tries to get the UNIX process identifier from @credentials. This
568  * method is only available on UNIX platforms.
569  *
570  * This operation can fail if #GCredentials is not supported on the
571  * OS or if the native credentials type does not contain information
572  * about the UNIX process ID (for example this is the case for
573  * %G_CREDENTIALS_TYPE_APPLE_XUCRED).
574  *
575  * Returns: The UNIX process ID, or `-1` if @error is set.
576  *
577  * Since: 2.36
578  */
579 pid_t
580 g_credentials_get_unix_pid (GCredentials    *credentials,
581                             GError         **error)
582 {
583   pid_t ret;
584
585   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
586   g_return_val_if_fail (error == NULL || *error == NULL, -1);
587
588 #if G_CREDENTIALS_USE_LINUX_UCRED
589   if (linux_ucred_check_valid (&credentials->native, error))
590     ret = credentials->native.pid;
591   else
592     ret = -1;
593 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
594   ret = credentials->native.cmcred_pid;
595 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
596   ret = credentials->native.unp_pid;
597 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
598   ret = credentials->native.pid;
599 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
600   ret = ucred_getpid (credentials->native);
601 #else
602   /* this case includes G_CREDENTIALS_USE_APPLE_XUCRED */
603   ret = -1;
604   g_set_error_literal (error,
605                        G_IO_ERROR,
606                        G_IO_ERROR_NOT_SUPPORTED,
607                        _("GCredentials does not contain a process ID on this OS"));
608 #endif
609
610   return ret;
611 }
612
613 /**
614  * g_credentials_set_unix_user:
615  * @credentials: A #GCredentials.
616  * @uid: The UNIX user identifier to set.
617  * @error: Return location for error or %NULL.
618  *
619  * Tries to set the UNIX user identifier on @credentials. This method
620  * is only available on UNIX platforms.
621  *
622  * This operation can fail if #GCredentials is not supported on the
623  * OS or if the native credentials type does not contain information
624  * about the UNIX user. It can also fail if the OS does not allow the
625  * use of "spoofed" credentials.
626  *
627  * Returns: %TRUE if @uid was set, %FALSE if error is set.
628  *
629  * Since: 2.26
630  */
631 gboolean
632 g_credentials_set_unix_user (GCredentials    *credentials,
633                              uid_t            uid,
634                              GError         **error)
635 {
636   gboolean ret = FALSE;
637
638   g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
639   g_return_val_if_fail (uid != -1, FALSE);
640   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
641
642 #if G_CREDENTIALS_USE_LINUX_UCRED
643   credentials->native.uid = uid;
644   ret = TRUE;
645 #elif G_CREDENTIALS_USE_APPLE_XUCRED
646   credentials->native.cr_uid = uid;
647   ret = TRUE;
648 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
649   credentials->native.cmcred_euid = uid;
650   ret = TRUE;
651 #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
652   credentials->native.unp_euid = uid;
653   ret = TRUE;
654 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
655   credentials->native.uid = uid;
656   ret = TRUE;
657 #elif !G_CREDENTIALS_SPOOFING_SUPPORTED
658   g_set_error_literal (error,
659                        G_IO_ERROR,
660                        G_IO_ERROR_PERMISSION_DENIED,
661                        _("Credentials spoofing is not possible on this OS"));
662   ret = FALSE;
663 #else
664   g_set_error_literal (error,
665                        G_IO_ERROR,
666                        G_IO_ERROR_NOT_SUPPORTED,
667                        _("GCredentials is not implemented on this OS"));
668   ret = FALSE;
669 #endif
670
671   return ret;
672 }
673
674 #endif /* G_OS_UNIX */