Blame gio/gdbusauthmechanismexternal.c

Packit 84794d
/* GDBus - GLib D-Bus Library
Packit 84794d
 *
Packit 84794d
 * Copyright (C) 2008-2010 Red Hat, Inc.
Packit 84794d
 *
Packit 84794d
 * This library is free software; you can redistribute it and/or
Packit 84794d
 * modify it under the terms of the GNU Lesser General Public
Packit 84794d
 * License as published by the Free Software Foundation; either
Packit 84794d
 * version 2.1 of the License, or (at your option) any later version.
Packit 84794d
 *
Packit 84794d
 * This library is distributed in the hope that it will be useful,
Packit 84794d
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 84794d
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 84794d
 * Lesser General Public License for more details.
Packit 84794d
 *
Packit 84794d
 * You should have received a copy of the GNU Lesser General
Packit 84794d
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 84794d
 *
Packit 84794d
 * Author: David Zeuthen <davidz@redhat.com>
Packit 84794d
 */
Packit 84794d
Packit 84794d
#include "config.h"
Packit 84794d
Packit 84794d
#include <string.h>
Packit 84794d
Packit 84794d
#include "gdbusauthmechanismexternal.h"
Packit 84794d
#include "gcredentials.h"
Packit 84794d
#include "gdbuserror.h"
Packit 84794d
#include "gioenumtypes.h"
Packit 84794d
Packit 84794d
#include "glibintl.h"
Packit 84794d
Packit 84794d
struct _GDBusAuthMechanismExternalPrivate
Packit 84794d
{
Packit 84794d
  gboolean is_client;
Packit 84794d
  gboolean is_server;
Packit 84794d
  GDBusAuthMechanismState state;
Packit 84794d
};
Packit 84794d
Packit 84794d
static gint                     mechanism_get_priority              (void);
Packit 84794d
static const gchar             *mechanism_get_name                  (void);
Packit 84794d
Packit 84794d
static gboolean                 mechanism_is_supported              (GDBusAuthMechanism   *mechanism);
Packit 84794d
static gchar                   *mechanism_encode_data               (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     const gchar          *data,
Packit 84794d
                                                                     gsize                 data_len,
Packit 84794d
                                                                     gsize                *out_data_len);
Packit 84794d
static gchar                   *mechanism_decode_data               (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     const gchar          *data,
Packit 84794d
                                                                     gsize                 data_len,
Packit 84794d
                                                                     gsize                *out_data_len);
Packit 84794d
static GDBusAuthMechanismState  mechanism_server_get_state          (GDBusAuthMechanism   *mechanism);
Packit 84794d
static void                     mechanism_server_initiate           (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     const gchar          *initial_response,
Packit 84794d
                                                                     gsize                 initial_response_len);
Packit 84794d
static void                     mechanism_server_data_receive       (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     const gchar          *data,
Packit 84794d
                                                                     gsize                 data_len);
Packit 84794d
static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     gsize                *out_data_len);
Packit 84794d
static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
Packit 84794d
static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
Packit 84794d
static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
Packit 84794d
static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     gsize                *out_initial_response_len);
Packit 84794d
static void                     mechanism_client_data_receive       (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     const gchar          *data,
Packit 84794d
                                                                     gsize                 data_len);
Packit 84794d
static gchar                   *mechanism_client_data_send          (GDBusAuthMechanism   *mechanism,
Packit 84794d
                                                                     gsize                *out_data_len);
Packit 84794d
static void                     mechanism_client_shutdown           (GDBusAuthMechanism   *mechanism);
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */
Packit 84794d
Packit 84794d
G_DEFINE_TYPE_WITH_PRIVATE (GDBusAuthMechanismExternal, _g_dbus_auth_mechanism_external, G_TYPE_DBUS_AUTH_MECHANISM)
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */
Packit 84794d
Packit 84794d
static void
Packit 84794d
_g_dbus_auth_mechanism_external_finalize (GObject *object)
Packit 84794d
{
Packit 84794d
  //GDBusAuthMechanismExternal *mechanism = G_DBUS_AUTH_MECHANISM_EXTERNAL (object);
Packit 84794d
Packit 84794d
  if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize != NULL)
Packit 84794d
    G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize (object);
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
_g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *klass)
Packit 84794d
{
Packit 84794d
  GObjectClass *gobject_class;
Packit 84794d
  GDBusAuthMechanismClass *mechanism_class;
Packit 84794d
Packit 84794d
  gobject_class = G_OBJECT_CLASS (klass);
Packit 84794d
  gobject_class->finalize = _g_dbus_auth_mechanism_external_finalize;
Packit 84794d
Packit 84794d
  mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
Packit 84794d
  mechanism_class->get_name                  = mechanism_get_name;
Packit 84794d
  mechanism_class->get_priority              = mechanism_get_priority;
Packit 84794d
  mechanism_class->is_supported              = mechanism_is_supported;
Packit 84794d
  mechanism_class->encode_data               = mechanism_encode_data;
Packit 84794d
  mechanism_class->decode_data               = mechanism_decode_data;
Packit 84794d
  mechanism_class->server_get_state          = mechanism_server_get_state;
Packit 84794d
  mechanism_class->server_initiate           = mechanism_server_initiate;
Packit 84794d
  mechanism_class->server_data_receive       = mechanism_server_data_receive;
Packit 84794d
  mechanism_class->server_data_send          = mechanism_server_data_send;
Packit 84794d
  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
Packit 84794d
  mechanism_class->server_shutdown           = mechanism_server_shutdown;
Packit 84794d
  mechanism_class->client_get_state          = mechanism_client_get_state;
Packit 84794d
  mechanism_class->client_initiate           = mechanism_client_initiate;
Packit 84794d
  mechanism_class->client_data_receive       = mechanism_client_data_receive;
Packit 84794d
  mechanism_class->client_data_send          = mechanism_client_data_send;
Packit 84794d
  mechanism_class->client_shutdown           = mechanism_client_shutdown;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
_g_dbus_auth_mechanism_external_init (GDBusAuthMechanismExternal *mechanism)
Packit 84794d
{
Packit 84794d
  mechanism->priv = _g_dbus_auth_mechanism_external_get_instance_private (mechanism);
Packit 84794d
}
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
mechanism_is_supported (GDBusAuthMechanism *mechanism)
Packit 84794d
{
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), FALSE);
Packit 84794d
  /* This mechanism is only available if credentials has been exchanged */
Packit 84794d
  if (_g_dbus_auth_mechanism_get_credentials (mechanism) != NULL)
Packit 84794d
    return TRUE;
Packit 84794d
  else
Packit 84794d
    return FALSE;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gint
Packit 84794d
mechanism_get_priority (void)
Packit 84794d
{
Packit 84794d
  /* We prefer EXTERNAL to most other mechanism (DBUS_COOKIE_SHA1 and ANONYMOUS) */
Packit 84794d
  return 100;
Packit 84794d
}
Packit 84794d
Packit 84794d
static const gchar *
Packit 84794d
mechanism_get_name (void)
Packit 84794d
{
Packit 84794d
  return "EXTERNAL";
Packit 84794d
}
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_encode_data (GDBusAuthMechanism   *mechanism,
Packit 84794d
                       const gchar          *data,
Packit 84794d
                       gsize                 data_len,
Packit 84794d
                       gsize                *out_data_len)
Packit 84794d
{
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_decode_data (GDBusAuthMechanism   *mechanism,
Packit 84794d
                       const gchar          *data,
Packit 84794d
                       gsize                 data_len,
Packit 84794d
                       gsize                *out_data_len)
Packit 84794d
{
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */
Packit 84794d
Packit 84794d
static GDBusAuthMechanismState
Packit 84794d
mechanism_server_get_state (GDBusAuthMechanism   *mechanism)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
Packit 84794d
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
Packit 84794d
Packit 84794d
  return m->priv->state;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gboolean
Packit 84794d
data_matches_credentials (const gchar *data,
Packit 84794d
                          GCredentials *credentials)
Packit 84794d
{
Packit 84794d
  gboolean match;
Packit 84794d
Packit 84794d
  match = FALSE;
Packit 84794d
Packit 84794d
  if (credentials == NULL)
Packit 84794d
    goto out;
Packit 84794d
Packit 84794d
  if (data == NULL || strlen (data) == 0)
Packit 84794d
    goto out;
Packit 84794d
Packit 84794d
#if defined(G_OS_UNIX)
Packit 84794d
  {
Packit 84794d
    gint64 alleged_uid;
Packit 84794d
    gchar *endp;
Packit 84794d
Packit 84794d
    /* on UNIX, this is the uid as a string in base 10 */
Packit 84794d
    alleged_uid = g_ascii_strtoll (data, &endp, 10);
Packit 84794d
    if (*endp == '\0')
Packit 84794d
      {
Packit 84794d
        if (g_credentials_get_unix_user (credentials, NULL) == alleged_uid)
Packit 84794d
          {
Packit 84794d
            match = TRUE;
Packit 84794d
          }
Packit 84794d
      }
Packit 84794d
  }
Packit 84794d
#else
Packit 84794d
  /* TODO: Dont know how to compare credentials on this OS. Please implement. */
Packit 84794d
#endif
Packit 84794d
Packit 84794d
 out:
Packit 84794d
  return match;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
Packit 84794d
                           const gchar          *initial_response,
Packit 84794d
                           gsize                 initial_response_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
Packit 84794d
  g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
Packit 84794d
Packit 84794d
  m->priv->is_server = TRUE;
Packit 84794d
Packit 84794d
  if (initial_response != NULL)
Packit 84794d
    {
Packit 84794d
      if (data_matches_credentials (initial_response, _g_dbus_auth_mechanism_get_credentials (mechanism)))
Packit 84794d
        {
Packit 84794d
          m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
Packit 84794d
        }
Packit 84794d
      else
Packit 84794d
        {
Packit 84794d
          m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
Packit 84794d
        }
Packit 84794d
    }
Packit 84794d
  else
Packit 84794d
    {
Packit 84794d
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
Packit 84794d
    }
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
mechanism_server_data_receive (GDBusAuthMechanism   *mechanism,
Packit 84794d
                               const gchar          *data,
Packit 84794d
                               gsize                 data_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
Packit 84794d
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
Packit 84794d
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
Packit 84794d
Packit 84794d
  if (data_matches_credentials (data, _g_dbus_auth_mechanism_get_credentials (mechanism)))
Packit 84794d
    {
Packit 84794d
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
Packit 84794d
    }
Packit 84794d
  else
Packit 84794d
    {
Packit 84794d
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
Packit 84794d
    }
Packit 84794d
}
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
Packit 84794d
                            gsize                *out_data_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
Packit 84794d
Packit 84794d
  /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
Packit 84794d
  g_assert_not_reached ();
Packit 84794d
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
Packit 84794d
Packit 84794d
  /* can never end up here because we are never in the REJECTED state */
Packit 84794d
  g_assert_not_reached ();
Packit 84794d
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
mechanism_server_shutdown (GDBusAuthMechanism   *mechanism)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
Packit 84794d
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
Packit 84794d
Packit 84794d
  m->priv->is_server = FALSE;
Packit 84794d
}
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */
Packit 84794d
Packit 84794d
static GDBusAuthMechanismState
Packit 84794d
mechanism_client_get_state (GDBusAuthMechanism   *mechanism)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
Packit 84794d
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
Packit 84794d
Packit 84794d
  return m->priv->state;
Packit 84794d
}
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
Packit 84794d
                           gsize                *out_initial_response_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
  gchar *initial_response = NULL;
Packit 84794d
  GCredentials *credentials;
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
Packit 84794d
  g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
Packit 84794d
Packit 84794d
  m->priv->is_client = TRUE;
Packit 84794d
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
Packit 84794d
Packit 84794d
  *out_initial_response_len = -1;
Packit 84794d
Packit 84794d
  credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
Packit 84794d
  g_assert (credentials != NULL);
Packit 84794d
Packit 84794d
  /* return the uid */
Packit 84794d
#if defined(G_OS_UNIX)
Packit 84794d
  initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) g_credentials_get_unix_user (credentials, NULL));
Packit 84794d
#elif defined(G_OS_WIN32)
Packit 84794d
#ifdef __GNUC__
Packit 84794d
#warning Dont know how to send credentials on this OS. The EXTERNAL D-Bus authentication mechanism will not work.
Packit 84794d
#endif
Packit 84794d
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
Packit 84794d
#endif
Packit 84794d
  return initial_response;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
Packit 84794d
                               const gchar          *data,
Packit 84794d
                               gsize                 data_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
Packit 84794d
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
Packit 84794d
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
Packit 84794d
Packit 84794d
  /* can never end up here because we are never in the WAITING_FOR_DATA state */
Packit 84794d
  g_assert_not_reached ();
Packit 84794d
}
Packit 84794d
Packit 84794d
static gchar *
Packit 84794d
mechanism_client_data_send (GDBusAuthMechanism   *mechanism,
Packit 84794d
                            gsize                *out_data_len)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
Packit 84794d
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
Packit 84794d
Packit 84794d
  /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
Packit 84794d
  g_assert_not_reached ();
Packit 84794d
Packit 84794d
  return NULL;
Packit 84794d
}
Packit 84794d
Packit 84794d
static void
Packit 84794d
mechanism_client_shutdown (GDBusAuthMechanism   *mechanism)
Packit 84794d
{
Packit 84794d
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
Packit 84794d
Packit 84794d
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
Packit 84794d
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
Packit 84794d
Packit 84794d
  m->priv->is_client = FALSE;
Packit 84794d
}
Packit 84794d
Packit 84794d
/* ---------------------------------------------------------------------------------------------------- */