Branch data Line data Source code
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 : 8796 : G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT)
124 : :
125 : : static void
126 : 3656 : 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 : 3656 : if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
135 : 3656 : G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
136 : 3656 : }
137 : :
138 : :
139 : : static void
140 : 100 : g_credentials_class_init (GCredentialsClass *klass)
141 : : {
142 : : GObjectClass *gobject_class;
143 : :
144 : 100 : gobject_class = G_OBJECT_CLASS (klass);
145 : 100 : gobject_class->finalize = g_credentials_finalize;
146 : 100 : }
147 : :
148 : : static void
149 : 3845 : g_credentials_init (GCredentials *credentials)
150 : : {
151 : : #if G_CREDENTIALS_USE_LINUX_UCRED
152 : 3845 : credentials->native.pid = getpid ();
153 : 3845 : credentials->native.uid = geteuid ();
154 : 3845 : 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 : 3845 : }
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 : 3844 : g_credentials_new (void)
207 : : {
208 : 3844 : 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 : 384 : 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 : 384 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
234 : :
235 : 384 : ret = g_string_new ("GCredentials:");
236 : : #if G_CREDENTIALS_USE_LINUX_UCRED
237 : 384 : g_string_append (ret, "linux-ucred:");
238 : 384 : if (credentials->native.pid != (pid_t) -1)
239 : 384 : g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
240 : 384 : if (credentials->native.uid != (uid_t) -1)
241 : 256 : g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
242 : 384 : if (credentials->native.gid != (gid_t) -1)
243 : 256 : g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
244 : 384 : if (ret->str[ret->len - 1] == ',')
245 : 384 : 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 : 384 : 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 : 792 : linux_ucred_check_valid (struct ucred *native,
318 : : GError **error)
319 : : {
320 : 792 : if (native->pid == 0
321 : 646 : || native->uid == (uid_t) -1
322 : 646 : || native->gid == (gid_t) -1)
323 : : {
324 : 146 : g_set_error_literal (error,
325 : : G_IO_ERROR,
326 : : G_IO_ERROR_INVALID_DATA,
327 : : _("GCredentials contains invalid data"));
328 : 146 : return FALSE;
329 : : }
330 : :
331 : 646 : 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 : 24 : g_credentials_is_same_user (GCredentials *credentials,
353 : : GCredentials *other_credentials,
354 : : GError **error)
355 : : {
356 : : gboolean ret;
357 : :
358 : 24 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
359 : 24 : g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE);
360 : 24 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
361 : :
362 : 24 : ret = FALSE;
363 : : #if G_CREDENTIALS_USE_LINUX_UCRED
364 : 24 : if (linux_ucred_check_valid (&credentials->native, NULL)
365 : 24 : && credentials->native.uid == other_credentials->native.uid)
366 : 23 : 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 : 24 : return ret;
391 : : }
392 : :
393 : : static gboolean
394 : 1826 : 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 : 1826 : if (requested_type == G_CREDENTIALS_NATIVE_TYPE)
405 : 1825 : return TRUE;
406 : : #endif
407 : :
408 : 1 : enum_class = g_type_class_ref (g_credentials_type_get_type ());
409 : 1 : requested = g_enum_get_value (enum_class, requested_type);
410 : :
411 : : #if G_CREDENTIALS_SUPPORTED
412 : 1 : supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE);
413 : 1 : g_assert (supported);
414 : 1 : 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 : 1 : g_type_class_unref (enum_class);
427 : 1 : 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 : 1600 : g_credentials_get_native (GCredentials *credentials,
451 : : GCredentialsType native_type)
452 : : {
453 : 1600 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
454 : :
455 : 1600 : if (!credentials_native_type_check (native_type, "get"))
456 : 1 : return NULL;
457 : :
458 : : #if G_CREDENTIALS_USE_SOLARIS_UCRED
459 : : return credentials->native;
460 : : #elif G_CREDENTIALS_SUPPORTED
461 : 1599 : 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 : 226 : g_credentials_set_native (GCredentials *credentials,
484 : : GCredentialsType native_type,
485 : : gpointer native)
486 : : {
487 : 226 : if (!credentials_native_type_check (native_type, "set"))
488 : 0 : return;
489 : :
490 : : #if G_CREDENTIALS_USE_SOLARIS_UCRED
491 : : memcpy (credentials->native, native, ucred_size ());
492 : : #elif G_CREDENTIALS_SUPPORTED
493 : 226 : 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 : 571 : g_credentials_get_unix_user (GCredentials *credentials,
520 : : GError **error)
521 : : {
522 : : uid_t ret;
523 : :
524 : 571 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
525 : 571 : g_return_val_if_fail (error == NULL || *error == NULL, -1);
526 : :
527 : : #if G_CREDENTIALS_USE_LINUX_UCRED
528 : 571 : if (linux_ucred_check_valid (&credentials->native, error))
529 : 488 : ret = credentials->native.uid;
530 : : else
531 : 83 : 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 : 571 : 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 : 197 : g_credentials_get_unix_pid (GCredentials *credentials,
584 : : GError **error)
585 : : {
586 : : pid_t ret;
587 : :
588 : 197 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
589 : 197 : g_return_val_if_fail (error == NULL || *error == NULL, -1);
590 : :
591 : : #if G_CREDENTIALS_USE_LINUX_UCRED
592 : 197 : if (linux_ucred_check_valid (&credentials->native, error))
593 : 134 : ret = credentials->native.pid;
594 : : else
595 : 63 : 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 : 197 : 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 : 2 : g_credentials_set_unix_user (GCredentials *credentials,
644 : : uid_t uid,
645 : : GError **error)
646 : : {
647 : 2 : gboolean ret = FALSE;
648 : :
649 : 2 : g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
650 : 2 : g_return_val_if_fail (uid != (uid_t) -1, FALSE);
651 : 2 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
652 : :
653 : : #if G_CREDENTIALS_USE_LINUX_UCRED
654 : 2 : credentials->native.uid = uid;
655 : 2 : 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 : 2 : 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 */
|