(root)/
glib-2.79.0/
gio/
gcredentials.c
       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 */