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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
28 #include <gobject/gvaluecollector.h>
30 #include "gcredentials.h"
31 #include "gcredentialsprivate.h"
32 #include "gnetworking.h"
34 #include "gioenumtypes.h"
39 * SECTION:gcredentials
40 * @short_description: An object containing credentials
43 * The #GCredentials type is a reference-counted wrapper for native
44 * credentials. This information is typically used for identifying,
45 * authenticating and authorizing other processes.
47 * Some operating systems supports looking up the credentials of the
48 * remote peer of a communication endpoint - see e.g.
49 * g_socket_get_credentials().
51 * Some operating systems supports securely sending and receiving
52 * credentials over a Unix Domain Socket, see
53 * #GUnixCredentialsMessage, g_unix_connection_send_credentials() and
54 * g_unix_connection_receive_credentials() for details.
56 * On Linux, the native credential type is a <type>struct ucred</type>
58 * <citerefentry><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry>
59 * man page for details. This corresponds to
60 * %G_CREDENTIALS_TYPE_LINUX_UCRED.
62 * On FreeBSD, the native credential type is a <type>struct cmsgcred</type>.
63 * This corresponds to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED.
65 * On OpenBSD, the native credential type is a <type>struct sockpeercred</type>.
66 * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
72 * The #GCredentials structure contains only private data and
73 * should only be accessed using the provided API.
80 GObject parent_instance;
82 #if G_CREDENTIALS_USE_LINUX_UCRED
84 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
85 struct cmsgcred native;
86 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
87 struct sockpeercred native;
90 #warning Please add GCredentials support for your OS
98 * Class structure for #GCredentials.
102 struct _GCredentialsClass
105 GObjectClass parent_class;
108 G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT);
111 g_credentials_finalize (GObject *object)
113 G_GNUC_UNUSED GCredentials *credentials = G_CREDENTIALS (object);
115 if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
116 G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
121 g_credentials_class_init (GCredentialsClass *klass)
123 GObjectClass *gobject_class;
125 gobject_class = G_OBJECT_CLASS (klass);
126 gobject_class->finalize = g_credentials_finalize;
130 g_credentials_init (GCredentials *credentials)
132 #if G_CREDENTIALS_USE_LINUX_UCRED
133 credentials->native.pid = getpid ();
134 credentials->native.uid = geteuid ();
135 credentials->native.gid = getegid ();
136 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
137 memset (&credentials->native, 0, sizeof (struct cmsgcred));
138 credentials->native.cmcred_pid = getpid ();
139 credentials->native.cmcred_euid = geteuid ();
140 credentials->native.cmcred_gid = getegid ();
141 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
142 credentials->native.pid = getpid ();
143 credentials->native.uid = geteuid ();
144 credentials->native.gid = getegid ();
148 /* ---------------------------------------------------------------------------------------------------- */
153 * Creates a new #GCredentials object with credentials matching the
154 * the current process.
156 * Returns: A #GCredentials. Free with g_object_unref().
161 g_credentials_new (void)
163 return g_object_new (G_TYPE_CREDENTIALS, NULL);
166 /* ---------------------------------------------------------------------------------------------------- */
169 * g_credentials_to_string:
170 * @credentials: A #GCredentials object.
172 * Creates a human-readable textual representation of @credentials
173 * that can be used in logging and debug messages. The format of the
174 * returned string may change in future GLib release.
176 * Returns: A string that should be freed with g_free().
181 g_credentials_to_string (GCredentials *credentials)
185 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
187 ret = g_string_new ("GCredentials:");
188 #if G_CREDENTIALS_USE_LINUX_UCRED
189 g_string_append (ret, "linux-ucred:");
190 if (credentials->native.pid != -1)
191 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
192 if (credentials->native.uid != -1)
193 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
194 if (credentials->native.gid != -1)
195 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
196 if (ret->str[ret->len - 1] == ',')
197 ret->str[ret->len - 1] = '\0';
198 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
199 g_string_append (ret, "freebsd-cmsgcred:");
200 if (credentials->native.cmcred_pid != -1)
201 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid);
202 if (credentials->native.cmcred_euid != -1)
203 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid);
204 if (credentials->native.cmcred_gid != -1)
205 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid);
206 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
207 g_string_append (ret, "openbsd-sockpeercred:");
208 if (credentials->native.pid != -1)
209 g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid);
210 if (credentials->native.uid != -1)
211 g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid);
212 if (credentials->native.gid != -1)
213 g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
214 if (ret->str[ret->len - 1] == ',')
215 ret->str[ret->len - 1] = '\0';
217 g_string_append (ret, "unknown");
220 return g_string_free (ret, FALSE);
223 /* ---------------------------------------------------------------------------------------------------- */
226 * g_credentials_is_same_user:
227 * @credentials: A #GCredentials.
228 * @other_credentials: A #GCredentials.
229 * @error: Return location for error or %NULL.
231 * Checks if @credentials and @other_credentials is the same user.
233 * This operation can fail if #GCredentials is not supported on the
236 * Returns: %TRUE if @credentials and @other_credentials has the same
237 * user, %FALSE otherwise or if @error is set.
242 g_credentials_is_same_user (GCredentials *credentials,
243 GCredentials *other_credentials,
248 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
249 g_return_val_if_fail (G_IS_CREDENTIALS (other_credentials), FALSE);
250 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
253 #if G_CREDENTIALS_USE_LINUX_UCRED
254 if (credentials->native.uid == other_credentials->native.uid)
256 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
257 if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
259 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
260 if (credentials->native.uid == other_credentials->native.uid)
263 g_set_error_literal (error,
265 G_IO_ERROR_NOT_SUPPORTED,
266 _("GCredentials is not implemented on this OS"));
273 credentials_native_type_check (GCredentialsType requested_type,
276 GEnumClass *enum_class;
277 GEnumValue *requested;
278 #if G_CREDENTIALS_SUPPORTED
279 GEnumValue *supported;
282 #if G_CREDENTIALS_SUPPORTED
283 if (requested_type == G_CREDENTIALS_NATIVE_TYPE)
287 enum_class = g_type_class_ref (g_credentials_type_get_type ());
288 requested = g_enum_get_value (enum_class, requested_type);
290 #if G_CREDENTIALS_SUPPORTED
291 supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE);
292 g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
293 "but only %s is supported on this platform.",
295 requested ? requested->value_name : "(unknown)",
296 supported->value_name);
298 g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s "
299 "but there is no support for GCredentials on this platform.",
301 requested ? requested->value_name : "(unknown)");
304 g_type_class_unref (enum_class);
309 * g_credentials_get_native: (skip)
310 * @credentials: A #GCredentials.
311 * @native_type: The type of native credentials to get.
313 * Gets a pointer to native credentials of type @native_type from
316 * It is a programming error (which will cause an warning to be
317 * logged) to use this method if there is no #GCredentials support for
318 * the OS or if @native_type isn't supported by the OS.
320 * Returns: The pointer to native credentials or %NULL if the
321 * operation there is no #GCredentials support for the OS or if
322 * @native_type isn't supported by the OS. Do not free the returned
323 * data, it is owned by @credentials.
328 g_credentials_get_native (GCredentials *credentials,
329 GCredentialsType native_type)
331 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL);
333 if (!credentials_native_type_check (native_type, "get"))
336 #if G_CREDENTIALS_SUPPORTED
337 return &credentials->native;
339 g_assert_not_reached ();
344 * g_credentials_set_native:
345 * @credentials: A #GCredentials.
346 * @native_type: The type of native credentials to set.
347 * @native: A pointer to native credentials.
349 * Copies the native credentials of type @native_type from @native
352 * It is a programming error (which will cause an warning to be
353 * logged) to use this method if there is no #GCredentials support for
354 * the OS or if @native_type isn't supported by the OS.
359 g_credentials_set_native (GCredentials *credentials,
360 GCredentialsType native_type,
363 if (!credentials_native_type_check (native_type, "set"))
366 #if G_CREDENTIALS_SUPPORTED
367 memcpy (&credentials->native, native, sizeof (credentials->native));
369 g_assert_not_reached ();
373 /* ---------------------------------------------------------------------------------------------------- */
377 * g_credentials_get_unix_user:
378 * @credentials: A #GCredentials
379 * @error: Return location for error or %NULL.
381 * Tries to get the UNIX user identifier from @credentials. This
382 * method is only available on UNIX platforms.
384 * This operation can fail if #GCredentials is not supported on the
385 * OS or if the native credentials type does not contain information
386 * about the UNIX user.
388 * Returns: The UNIX user identifier or -1 if @error is set.
393 g_credentials_get_unix_user (GCredentials *credentials,
398 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
399 g_return_val_if_fail (error == NULL || *error == NULL, -1);
401 #if G_CREDENTIALS_USE_LINUX_UCRED
402 ret = credentials->native.uid;
403 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
404 ret = credentials->native.cmcred_euid;
405 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
406 ret = credentials->native.uid;
409 g_set_error_literal (error,
411 G_IO_ERROR_NOT_SUPPORTED,
412 _("There is no GCredentials support for your platform"));
419 * g_credentials_get_unix_pid:
420 * @credentials: A #GCredentials
421 * @error: Return location for error or %NULL.
423 * Tries to get the UNIX process identifier from @credentials. This
424 * method is only available on UNIX platforms.
426 * This operation can fail if #GCredentials is not supported on the
427 * OS or if the native credentials type does not contain information
428 * about the UNIX process ID.
430 * Returns: The UNIX process ID, or -1 if @error is set.
435 g_credentials_get_unix_pid (GCredentials *credentials,
440 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1);
441 g_return_val_if_fail (error == NULL || *error == NULL, -1);
443 #if G_CREDENTIALS_USE_LINUX_UCRED
444 ret = credentials->native.pid;
445 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
446 ret = credentials->native.cmcred_pid;
447 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
448 ret = credentials->native.pid;
451 g_set_error_literal (error,
453 G_IO_ERROR_NOT_SUPPORTED,
454 _("GCredentials does not contain a process ID on this OS"));
461 * g_credentials_set_unix_user:
462 * @credentials: A #GCredentials.
463 * @uid: The UNIX user identifier to set.
464 * @error: Return location for error or %NULL.
466 * Tries to set the UNIX user identifier on @credentials. This method
467 * is only available on UNIX platforms.
469 * This operation can fail if #GCredentials is not supported on the
470 * OS or if the native credentials type does not contain information
471 * about the UNIX user.
473 * Returns: %TRUE if @uid was set, %FALSE if error is set.
478 g_credentials_set_unix_user (GCredentials *credentials,
484 g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE);
485 g_return_val_if_fail (uid != -1, FALSE);
486 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
489 #if G_CREDENTIALS_USE_LINUX_UCRED
490 credentials->native.uid = uid;
492 #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
493 credentials->native.cmcred_euid = uid;
495 #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
496 credentials->native.uid = uid;
499 g_set_error_literal (error,
501 G_IO_ERROR_NOT_SUPPORTED,
502 _("GCredentials is not implemented on this OS"));
508 #endif /* G_OS_UNIX */