(root)/
glib-2.79.0/
gio/
gdbusauthobserver.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 "gdbusauthobserver.h"
      26  #include "gcredentials.h"
      27  #include "gioenumtypes.h"
      28  #include "giostream.h"
      29  #include "gdbusprivate.h"
      30  
      31  #include "glibintl.h"
      32  #include "gmarshal-internal.h"
      33  
      34  /**
      35   * GDBusAuthObserver:
      36   *
      37   * `GDBusAuthObserver` provides a mechanism for participating
      38   * in how a [class@Gio.DBusServer] (or a [class@Gio.DBusConnection])
      39   * authenticates remote peers.
      40   *
      41   * Simply instantiate a `GDBusAuthObserver` and connect to the
      42   * signals you are interested in. Note that new signals may be added
      43   * in the future.
      44   *
      45   * ## Controlling Authentication Mechanisms
      46   *
      47   * By default, a `GDBusServer` or server-side `GDBusConnection` will allow
      48   * any authentication mechanism to be used. If you only want to allow D-Bus
      49   * connections with the `EXTERNAL` mechanism, which makes use of credentials
      50   * passing and is the recommended mechanism for modern Unix platforms such
      51   * as Linux and the BSD family, you would use a signal handler like this:
      52   *
      53   * ```c
      54   * static gboolean
      55   * on_allow_mechanism (GDBusAuthObserver *observer,
      56   *                     const gchar       *mechanism,
      57   *                     gpointer           user_data)
      58   * {
      59   *   if (g_strcmp0 (mechanism, "EXTERNAL") == 0)
      60   *     {
      61   *       return TRUE;
      62   *     }
      63   *
      64   *   return FALSE;
      65   * }
      66   * ```
      67   *
      68   * ## Controlling Authorization
      69   *
      70   * By default, a `GDBusServer` or server-side `GDBusConnection` will accept
      71   * connections from any successfully authenticated user (but not from
      72   * anonymous connections using the `ANONYMOUS` mechanism). If you only
      73   * want to allow D-Bus connections from processes owned by the same uid
      74   * as the server, since GLib 2.68, you should use the
      75   * `G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER` flag. It’s equivalent
      76   * to the following signal handler:
      77   *
      78   * ```c
      79   * static gboolean
      80   * on_authorize_authenticated_peer (GDBusAuthObserver *observer,
      81   *                                  GIOStream         *stream,
      82   *                                  GCredentials      *credentials,
      83   *                                  gpointer           user_data)
      84   * {
      85   *   gboolean authorized;
      86   *
      87   *   authorized = FALSE;
      88   *   if (credentials != NULL)
      89   *     {
      90   *       GCredentials *own_credentials;
      91   *       own_credentials = g_credentials_new ();
      92   *       if (g_credentials_is_same_user (credentials, own_credentials, NULL))
      93   *         authorized = TRUE;
      94   *       g_object_unref (own_credentials);
      95   *     }
      96   *
      97   *   return authorized;
      98   * }
      99   * ```
     100   *
     101   * Since: 2.26
     102   */
     103  
     104  typedef struct _GDBusAuthObserverClass GDBusAuthObserverClass;
     105  
     106  /**
     107   * GDBusAuthObserverClass:
     108   * @authorize_authenticated_peer: Signal class handler for the #GDBusAuthObserver::authorize-authenticated-peer signal.
     109   *
     110   * Class structure for #GDBusAuthObserverClass.
     111   *
     112   * Since: 2.26
     113   */
     114  struct _GDBusAuthObserverClass
     115  {
     116    /*< private >*/
     117    GObjectClass parent_class;
     118  
     119    /*< public >*/
     120  
     121    /* Signals */
     122    gboolean (*authorize_authenticated_peer) (GDBusAuthObserver  *observer,
     123                                              GIOStream          *stream,
     124                                              GCredentials       *credentials);
     125  
     126    gboolean (*allow_mechanism) (GDBusAuthObserver  *observer,
     127                                 const gchar        *mechanism);
     128  };
     129  
     130  struct _GDBusAuthObserver
     131  {
     132    GObject parent_instance;
     133  };
     134  
     135  enum
     136  {
     137    AUTHORIZE_AUTHENTICATED_PEER_SIGNAL,
     138    ALLOW_MECHANISM_SIGNAL,
     139    LAST_SIGNAL,
     140  };
     141  
     142  static guint signals[LAST_SIGNAL] = { 0 };
     143  
     144  G_DEFINE_TYPE (GDBusAuthObserver, g_dbus_auth_observer, G_TYPE_OBJECT)
     145  
     146  /* ---------------------------------------------------------------------------------------------------- */
     147  
     148  static void
     149  g_dbus_auth_observer_finalize (GObject *object)
     150  {
     151    G_OBJECT_CLASS (g_dbus_auth_observer_parent_class)->finalize (object);
     152  }
     153  
     154  static gboolean
     155  g_dbus_auth_observer_authorize_authenticated_peer_real (GDBusAuthObserver  *observer,
     156                                                          GIOStream          *stream,
     157                                                          GCredentials       *credentials)
     158  {
     159    return TRUE;
     160  }
     161  
     162  static gboolean
     163  g_dbus_auth_observer_allow_mechanism_real (GDBusAuthObserver  *observer,
     164                                             const gchar        *mechanism)
     165  {
     166    return TRUE;
     167  }
     168  
     169  static void
     170  g_dbus_auth_observer_class_init (GDBusAuthObserverClass *klass)
     171  {
     172    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     173  
     174    gobject_class->finalize = g_dbus_auth_observer_finalize;
     175  
     176    klass->authorize_authenticated_peer = g_dbus_auth_observer_authorize_authenticated_peer_real;
     177    klass->allow_mechanism = g_dbus_auth_observer_allow_mechanism_real;
     178  
     179    /**
     180     * GDBusAuthObserver::authorize-authenticated-peer:
     181     * @observer: The #GDBusAuthObserver emitting the signal.
     182     * @stream: A #GIOStream for the #GDBusConnection.
     183     * @credentials: (nullable): Credentials received from the peer or %NULL.
     184     *
     185     * Emitted to check if a peer that is successfully authenticated
     186     * is authorized.
     187     *
     188     * Returns: %TRUE if the peer is authorized, %FALSE if not.
     189     *
     190     * Since: 2.26
     191     */
     192    signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL] =
     193      g_signal_new (I_("authorize-authenticated-peer"),
     194                    G_TYPE_DBUS_AUTH_OBSERVER,
     195                    G_SIGNAL_RUN_LAST,
     196                    G_STRUCT_OFFSET (GDBusAuthObserverClass, authorize_authenticated_peer),
     197                    _g_signal_accumulator_false_handled,
     198                    NULL, /* accu_data */
     199                    _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECT,
     200                    G_TYPE_BOOLEAN,
     201                    2,
     202                    G_TYPE_IO_STREAM,
     203                    G_TYPE_CREDENTIALS);
     204    g_signal_set_va_marshaller (signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL],
     205                                G_TYPE_FROM_CLASS (klass),
     206                                _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECTv);
     207  
     208    /**
     209     * GDBusAuthObserver::allow-mechanism:
     210     * @observer: The #GDBusAuthObserver emitting the signal.
     211     * @mechanism: The name of the mechanism, e.g. `DBUS_COOKIE_SHA1`.
     212     *
     213     * Emitted to check if @mechanism is allowed to be used.
     214     *
     215     * Returns: %TRUE if @mechanism can be used to authenticate the other peer, %FALSE if not.
     216     *
     217     * Since: 2.34
     218     */
     219    signals[ALLOW_MECHANISM_SIGNAL] =
     220      g_signal_new (I_("allow-mechanism"),
     221                    G_TYPE_DBUS_AUTH_OBSERVER,
     222                    G_SIGNAL_RUN_LAST,
     223                    G_STRUCT_OFFSET (GDBusAuthObserverClass, allow_mechanism),
     224                    _g_signal_accumulator_false_handled,
     225                    NULL, /* accu_data */
     226                    _g_cclosure_marshal_BOOLEAN__STRING,
     227                    G_TYPE_BOOLEAN,
     228                    1,
     229                    G_TYPE_STRING);
     230    g_signal_set_va_marshaller (signals[ALLOW_MECHANISM_SIGNAL],
     231                                G_TYPE_FROM_CLASS (klass),
     232                                _g_cclosure_marshal_BOOLEAN__STRINGv);
     233  }
     234  
     235  static void
     236  g_dbus_auth_observer_init (GDBusAuthObserver *observer)
     237  {
     238  }
     239  
     240  /**
     241   * g_dbus_auth_observer_new:
     242   *
     243   * Creates a new #GDBusAuthObserver object.
     244   *
     245   * Returns: A #GDBusAuthObserver. Free with g_object_unref().
     246   *
     247   * Since: 2.26
     248   */
     249  GDBusAuthObserver *
     250  g_dbus_auth_observer_new (void)
     251  {
     252    return g_object_new (G_TYPE_DBUS_AUTH_OBSERVER, NULL);
     253  }
     254  
     255  /* ---------------------------------------------------------------------------------------------------- */
     256  
     257  /**
     258   * g_dbus_auth_observer_authorize_authenticated_peer:
     259   * @observer: A #GDBusAuthObserver.
     260   * @stream: A #GIOStream for the #GDBusConnection.
     261   * @credentials: (nullable): Credentials received from the peer or %NULL.
     262   *
     263   * Emits the #GDBusAuthObserver::authorize-authenticated-peer signal on @observer.
     264   *
     265   * Returns: %TRUE if the peer is authorized, %FALSE if not.
     266   *
     267   * Since: 2.26
     268   */
     269  gboolean
     270  g_dbus_auth_observer_authorize_authenticated_peer (GDBusAuthObserver  *observer,
     271                                                     GIOStream          *stream,
     272                                                     GCredentials       *credentials)
     273  {
     274    gboolean denied;
     275  
     276    denied = FALSE;
     277    g_signal_emit (observer,
     278                   signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL],
     279                   0,
     280                   stream,
     281                   credentials,
     282                   &denied);
     283    return denied;
     284  }
     285  
     286  /**
     287   * g_dbus_auth_observer_allow_mechanism:
     288   * @observer: A #GDBusAuthObserver.
     289   * @mechanism: The name of the mechanism, e.g. `DBUS_COOKIE_SHA1`.
     290   *
     291   * Emits the #GDBusAuthObserver::allow-mechanism signal on @observer.
     292   *
     293   * Returns: %TRUE if @mechanism can be used to authenticate the other peer, %FALSE if not.
     294   *
     295   * Since: 2.34
     296   */
     297  gboolean
     298  g_dbus_auth_observer_allow_mechanism (GDBusAuthObserver  *observer,
     299                                        const gchar        *mechanism)
     300  {
     301    gboolean ret;
     302  
     303    ret = FALSE;
     304    g_signal_emit (observer,
     305                   signals[ALLOW_MECHANISM_SIGNAL],
     306                   0,
     307                   mechanism,
     308                   &ret);
     309    return ret;
     310  }