1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
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 of the License, or (at your option) any later version.
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.
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/>.
18 * Author: David Zeuthen <davidz@redhat.com>
26 #include <gobject/gvaluecollector.h>
28 #include "gcredentials.h"
29 #include "gcredentialsprivate.h"
30 #include "gnetworking.h"
32 #include "gioenumtypes.h"
37 * SECTION:gcredentials
38 * @short_description: An object containing credentials
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.
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().
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.
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.
58 * On FreeBSD, Debian GNU/kFreeBSD, and GNU/Hurd, the native
59 * credential type is a struct cmsgcred. This corresponds
60 * to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED.
62 * On OpenBSD, the native credential type is a struct sockpeercred.
63 * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
65 * On Solaris (including OpenSolaris and its derivatives), the native
66 * credential type is a ucred_t. This corresponds to
67 * %G_CREDENTIALS_TYPE_SOLARIS_UCRED.
73 * The #GCredentials structure contains only private data and
74 * should only be accessed using the provided API.
81 GObject parent_instance;
83 #if G_CREDENTIALS_USE_LINUX_UCRED
85 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
86 struct cmsgcred native;
87 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
88 struct sockpeercred native;
89 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
93 #warning Please add GCredentials support for your OS
101 * Class structure for #GCredentials.
105 struct _GCredentialsClass
108 GObjectClass parent_class;
111 G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT);
114 g_credentials_finalize (GObject *object)
116 #if G_CREDENTIALS_USE_SOLARIS_UCRED
117 GCredentials *credentials = G_CREDENTIALS (object);
119 ucred_free (credentials->native);
122 if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
123 G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
128 g_credentials_class_init (GCredentialsClass *klass)
130 GObjectClass *gobject_class;
132 gobject_class = G_OBJECT_CLASS (klass);
133 gobject_class->finalize = g_credentials_finalize;
137 g_credentials_init (GCredentials *credentials)
139 #if G_CREDENTIALS_USE_LINUX_UCRED
140 credentials->native.pid = getpid ();
141 credentials->native.uid = geteuid ();
142 credentials->native.gid = getegid ();
143 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
144 memset (&credentials->native, 0, sizeof (struct cmsgcred));
145 credentials->native.cmcred_pid = getpid ();
146 credentials->native.cmcred_euid = geteuid ();
147 credentials->native.cmcred_gid = getegid ();
148 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
149 credentials->native.pid = getpid ();
150 credentials->native.uid = geteuid ();
151 credentials->native.gid = getegid ();
152 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
153 credentials->native = ucred_get (P_MYID);
157 /* ---------------------------------------------------------------------------------------------------- */
162 * Creates a new #GCredentials object with credentials matching the
163 * the current process.
165 * Returns: A #GCredentials. Free with g_object_unref().
170 g_credentials_new (void)
172 return g_object_new (G_TYPE_CREDENTIALS, NULL);
175 /* ---------------------------------------------------------------------------------------------------- */
178 * g_credentials_to_string:
179 * @credentials: A #GCredentials object.
181 * Creates a human-readable textual representation of @credentials
182 * that can be used in logging and debug messages. The format of the
183 * returned string may change in future GLib release.
185 * Returns: A string that should be freed with g_free().
190 g_credentials_to_string (GCredentials *credentials)
194 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
196 ret = g_string_new ("GCredentials:");
197 #if G_CREDENTIALS_USE_LINUX_UCRED
198 g_string_append (ret, "linux-ucred:");
199 if (credentials->native.pid != -1)
200 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
201 if (credentials->native.uid != -1)
202 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
203 if (credentials->native.gid != -1)
204 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
205 if (ret->str[ret->len - 1] == ',')
206 ret->str[ret->len - 1] = '\0';
207 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
208 g_string_append (ret, "freebsd-cmsgcred:");
209 if (credentials->native.cmcred_pid != -1)
210 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid);
211 if (credentials->native.cmcred_euid != -1)
212 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid);
213 if (credentials->native.cmcred_gid != -1)
214 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid);
215 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
216 g_string_append (ret, "openbsd-sockpeercred:");
217 if (credentials->native.pid != -1)
218 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
219 if (credentials->native.uid != -1)
220 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
221 if (credentials->native.gid != -1)
222 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
223 if (ret->str[ret->len - 1] == ',')
224 ret->str[ret->len - 1] = '\0';
225 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
226 g_string_append (ret, "solaris-ucred:");
229 if ((id = ucred_getpid (credentials->native)) != -1)
230 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id);
231 if ((id = ucred_geteuid (credentials->native)) != -1)
232 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id);
233 if ((id = ucred_getegid (credentials->native)) != -1)
234 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id);
235 if (ret->str[ret->len - 1] == ',')
236 ret->str[ret->len - 1] = '\0';
239 g_string_append (ret, "unknown");
242 return g_string_free (ret, FALSE);
245 /* ---------------------------------------------------------------------------------------------------- */
248 * g_credentials_is_same_user:
249 * @credentials: A #GCredentials.
250 * @other_credentials: A #GCredentials.
251 * @error: Return location for error or %NULL.
253 * Checks if @credentials and @other_credentials is the same user.
255 * This operation can fail if #GCredentials is not supported on the
258 * Returns: %TRUE if @credentials and @other_credentials has the same
259 * user, %FALSE otherwise or if @error is set.
264 g_credentials_is_same_user (GCredentials *credentials,
265 GCredentials *other_credentials,
270 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
271 g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE);
272 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
275 #if G_CREDENTIALS_USE_LINUX_UCRED
276 if (credentials->native.uid == other_credentials->native.uid)
278 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
279 if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
281 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
282 if (credentials->native.uid == other_credentials->native.uid)
284 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
285 if (ucred_geteuid (credentials->native) == ucred_geteuid (other_credentials->native))
288 g_set_error_literal (error,
290 G_IO_ERROR_NOT_SUPPORTED,
291 _("GCredentials is not implemented on this OS"));
298 credentials_native_type_check (GCredentialsType requested_type,
301 GEnumClass *enum_class;
302 GEnumValue *requested;
303 #if G_CREDENTIALS_SUPPORTED
304 GEnumValue *supported;
307 #if G_CREDENTIALS_SUPPORTED
308 if (requested_type == G_CREDENTIALS_NATIVE_TYPE)
312 enum_class = g_type_class_ref (g_credentials_type_get_type ());
313 requested = g_enum_get_value (enum_class, requested_type);
315 #if G_CREDENTIALS_SUPPORTED
316 supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE);
317 g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
318 "but only %s is supported on this platform.",
320 requested ? requested->value_name : "(unknown)",
321 supported->value_name);
323 g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
324 "but there is no support for GCredentials on this platform.",
326 requested ? requested->value_name : "(unknown)");
329 g_type_class_unref (enum_class);
334 * g_credentials_get_native: (skip)
335 * @credentials: A #GCredentials.
336 * @native_type: The type of native credentials to get.
338 * Gets a pointer to native credentials of type @native_type from
341 * It is a programming error (which will cause an warning to be
342 * logged) to use this method if there is no #GCredentials support for
343 * the OS or if @native_type isn't supported by the OS.
345 * Returns: The pointer to native credentials or %NULL if the
346 * operation there is no #GCredentials support for the OS or if
347 * @native_type isn't supported by the OS. Do not free the returned
348 * data, it is owned by @credentials.
353 g_credentials_get_native (GCredentials *credentials,
354 GCredentialsType native_type)
356 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
358 if (!credentials_native_type_check (native_type, "get"))
361 #if G_CREDENTIALS_USE_SOLARIS_UCRED
362 return credentials->native;
363 #elif G_CREDENTIALS_SUPPORTED
364 return &credentials->native;
366 g_assert_not_reached ();
371 * g_credentials_set_native:
372 * @credentials: A #GCredentials.
373 * @native_type: The type of native credentials to set.
374 * @native: A pointer to native credentials.
376 * Copies the native credentials of type @native_type from @native
379 * It is a programming error (which will cause an warning to be
380 * logged) to use this method if there is no #GCredentials support for
381 * the OS or if @native_type isn't supported by the OS.
386 g_credentials_set_native (GCredentials *credentials,
387 GCredentialsType native_type,
390 if (!credentials_native_type_check (native_type, "set"))
393 #if G_CREDENTIALS_USE_SOLARIS_UCRED
394 memcpy (credentials->native, native, ucred_size ());
395 #elif G_CREDENTIALS_SUPPORTED
396 memcpy (&credentials->native, native, sizeof (credentials->native));
398 g_assert_not_reached ();
402 /* ---------------------------------------------------------------------------------------------------- */
406 * g_credentials_get_unix_user:
407 * @credentials: A #GCredentials
408 * @error: Return location for error or %NULL.
410 * Tries to get the UNIX user identifier from @credentials. This
411 * method is only available on UNIX platforms.
413 * This operation can fail if #GCredentials is not supported on the
414 * OS or if the native credentials type does not contain information
415 * about the UNIX user.
417 * Returns: The UNIX user identifier or -1 if @error is set.
422 g_credentials_get_unix_user (GCredentials *credentials,
427 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
428 g_return_val_if_fail (error == NULL || *error == NULL, -1);
430 #if G_CREDENTIALS_USE_LINUX_UCRED
431 ret = credentials->native.uid;
432 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
433 ret = credentials->native.cmcred_euid;
434 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
435 ret = credentials->native.uid;
436 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
437 ret = ucred_geteuid (credentials->native);
440 g_set_error_literal (error,
442 G_IO_ERROR_NOT_SUPPORTED,
443 _("There is no GCredentials support for your platform"));
450 * g_credentials_get_unix_pid:
451 * @credentials: A #GCredentials
452 * @error: Return location for error or %NULL.
454 * Tries to get the UNIX process identifier from @credentials. This
455 * method is only available on UNIX platforms.
457 * This operation can fail if #GCredentials is not supported on the
458 * OS or if the native credentials type does not contain information
459 * about the UNIX process ID.
461 * Returns: The UNIX process ID, or -1 if @error is set.
466 g_credentials_get_unix_pid (GCredentials *credentials,
471 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
472 g_return_val_if_fail (error == NULL || *error == NULL, -1);
474 #if G_CREDENTIALS_USE_LINUX_UCRED
475 ret = credentials->native.pid;
476 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
477 ret = credentials->native.cmcred_pid;
478 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
479 ret = credentials->native.pid;
480 #elif G_CREDENTIALS_USE_SOLARIS_UCRED
481 ret = ucred_getpid (credentials->native);
484 g_set_error_literal (error,
486 G_IO_ERROR_NOT_SUPPORTED,
487 _("GCredentials does not contain a process ID on this OS"));
494 * g_credentials_set_unix_user:
495 * @credentials: A #GCredentials.
496 * @uid: The UNIX user identifier to set.
497 * @error: Return location for error or %NULL.
499 * Tries to set the UNIX user identifier on @credentials. This method
500 * is only available on UNIX platforms.
502 * This operation can fail if #GCredentials is not supported on the
503 * OS or if the native credentials type does not contain information
504 * about the UNIX user. It can also fail if the OS does not allow the
505 * use of "spoofed" credentials.
507 * Returns: %TRUE if @uid was set, %FALSE if error is set.
512 g_credentials_set_unix_user (GCredentials *credentials,
518 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
519 g_return_val_if_fail (uid != -1, FALSE);
520 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
523 #if G_CREDENTIALS_USE_LINUX_UCRED
524 credentials->native.uid = uid;
526 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
527 credentials->native.cmcred_euid = uid;
529 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
530 credentials->native.uid = uid;
532 #elif !G_CREDENTIALS_SPOOFING_SUPPORTED
533 g_set_error_literal (error,
535 G_IO_ERROR_PERMISSION_DENIED,
536 _("Credentials spoofing is not possible on this OS"));
539 g_set_error_literal (error,
541 G_IO_ERROR_NOT_SUPPORTED,
542 _("GCredentials is not implemented on this OS"));
549 #endif /* G_OS_UNIX */