Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gcredentials.c
Line
Count
Source (jump to first uncovered line)
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
0
{
130
#if G_CREDENTIALS_USE_SOLARIS_UCRED
131
  GCredentials *credentials = G_CREDENTIALS (object);
132
133
  ucred_free (credentials->native);
134
#endif
135
136
0
  if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
137
0
    G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
138
0
}
139
140
141
static void
142
g_credentials_class_init (GCredentialsClass *klass)
143
0
{
144
0
  GObjectClass *gobject_class;
145
146
0
  gobject_class = G_OBJECT_CLASS (klass);
147
0
  gobject_class->finalize = g_credentials_finalize;
148
0
}
149
150
static void
151
g_credentials_init (GCredentials *credentials)
152
0
{
153
0
#if G_CREDENTIALS_USE_LINUX_UCRED
154
0
  credentials->native.pid = getpid ();
155
0
  credentials->native.uid = geteuid ();
156
0
  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
0
}
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
0
{
206
0
  return g_object_new (G_TYPE_CREDENTIALS, NULL);
207
0
}
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
0
{
226
0
  GString *ret;
227
#if G_CREDENTIALS_USE_APPLE_XUCRED
228
  glib_typeof (credentials->native.cr_ngroups) i;
229
#endif
230
231
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
232
233
0
  ret = g_string_new ("GCredentials:");
234
0
#if G_CREDENTIALS_USE_LINUX_UCRED
235
0
  g_string_append (ret, "linux-ucred:");
236
0
  if (credentials->native.pid != (pid_t) -1)
237
0
    g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
238
0
  if (credentials->native.uid != (uid_t) -1)
239
0
    g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
240
0
  if (credentials->native.gid != (gid_t) -1)
241
0
    g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
242
0
  if (ret->str[ret->len - 1] == ',')
243
0
    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
0
  return g_string_free (ret, FALSE);
298
0
}
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
0
{
316
0
  if (native->pid == 0
317
0
      || native->uid == (uid_t) -1
318
0
      || native->gid == (gid_t) -1)
319
0
    {
320
0
      g_set_error_literal (error,
321
0
                           G_IO_ERROR,
322
0
                           G_IO_ERROR_INVALID_DATA,
323
0
                           _("GCredentials contains invalid data"));
324
0
      return FALSE;
325
0
    }
326
327
0
  return TRUE;
328
0
}
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
0
{
352
0
  gboolean ret;
353
354
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
355
0
  g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE);
356
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
357
358
0
  ret = FALSE;
359
0
#if G_CREDENTIALS_USE_LINUX_UCRED
360
0
  if (linux_ucred_check_valid (&credentials->native, NULL)
361
0
      && credentials->native.uid == other_credentials->native.uid)
362
0
    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
0
  return ret;
387
0
}
388
389
static gboolean
390
credentials_native_type_check (GCredentialsType  requested_type,
391
                               const char       *op)
392
0
{
393
0
  GEnumClass *enum_class;
394
0
  GEnumValue *requested;
395
0
#if G_CREDENTIALS_SUPPORTED
396
0
  GEnumValue *supported;
397
0
#endif
398
399
0
#if G_CREDENTIALS_SUPPORTED
400
0
  if (requested_type == G_CREDENTIALS_NATIVE_TYPE)
401
0
    return TRUE;
402
0
#endif
403
404
0
  enum_class = g_type_class_ref (g_credentials_type_get_type ());
405
0
  requested = g_enum_get_value (enum_class, requested_type);
406
407
0
#if G_CREDENTIALS_SUPPORTED
408
0
  supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE);
409
0
  g_assert (supported);
410
0
  g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
411
0
             "but only %s is supported on this platform.",
412
0
             op, op,
413
0
             requested ? requested->value_name : "(unknown)",
414
0
             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
0
  g_type_class_unref (enum_class);
423
0
  return FALSE;
424
0
}
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
0
{
449
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
450
451
0
  if (!credentials_native_type_check (native_type, "get"))
452
0
    return NULL;
453
454
#if G_CREDENTIALS_USE_SOLARIS_UCRED
455
  return credentials->native;
456
#elif G_CREDENTIALS_SUPPORTED
457
0
  return &credentials->native;
458
#else
459
  g_assert_not_reached ();
460
#endif
461
0
}
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
0
{
483
0
  if (!credentials_native_type_check (native_type, "set"))
484
0
    return;
485
486
#if G_CREDENTIALS_USE_SOLARIS_UCRED
487
  memcpy (credentials->native, native, ucred_size ());
488
#elif G_CREDENTIALS_SUPPORTED
489
0
  memcpy (&credentials->native, native, sizeof (credentials->native));
490
#else
491
  g_assert_not_reached ();
492
#endif
493
0
}
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
0
{
518
0
  uid_t ret;
519
520
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
521
0
  g_return_val_if_fail (error == NULL || *error == NULL, -1);
522
523
0
#if G_CREDENTIALS_USE_LINUX_UCRED
524
0
  if (linux_ucred_check_valid (&credentials->native, error))
525
0
    ret = credentials->native.uid;
526
0
  else
527
0
    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
0
  return ret;
560
0
}
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
0
{
583
0
  pid_t ret;
584
585
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
586
0
  g_return_val_if_fail (error == NULL || *error == NULL, -1);
587
588
0
#if G_CREDENTIALS_USE_LINUX_UCRED
589
0
  if (linux_ucred_check_valid (&credentials->native, error))
590
0
    ret = credentials->native.pid;
591
0
  else
592
0
    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
0
  return ret;
611
0
}
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
0
{
636
0
  gboolean ret = FALSE;
637
638
0
  g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
639
0
  g_return_val_if_fail (uid != (uid_t) -1, FALSE);
640
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
641
642
0
#if G_CREDENTIALS_USE_LINUX_UCRED
643
0
  credentials->native.uid = uid;
644
0
  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
0
  return ret;
672
0
}
673
674
#endif /* G_OS_UNIX */