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