|
rpm-build |
4f3c61 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
rpm-build |
4f3c61 |
/*
|
|
rpm-build |
4f3c61 |
* soup-connection-auth.c: Abstract base class for hacky Microsoft
|
|
rpm-build |
4f3c61 |
* connection-based auth mechanisms (NTLM and Negotiate)
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Copyright (C) 2010 Red Hat, Inc.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#ifdef HAVE_CONFIG_H
|
|
rpm-build |
4f3c61 |
#include <config.h>
|
|
rpm-build |
4f3c61 |
#endif
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#include <ctype.h>
|
|
rpm-build |
4f3c61 |
#include <string.h>
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#include "soup-connection-auth.h"
|
|
rpm-build |
4f3c61 |
#include "soup.h"
|
|
rpm-build |
4f3c61 |
#include "soup-connection.h"
|
|
rpm-build |
4f3c61 |
#include "soup-message-private.h"
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
struct SoupConnectionAuthPrivate {
|
|
rpm-build |
4f3c61 |
GHashTable *conns;
|
|
rpm-build |
4f3c61 |
};
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SoupConnectionAuth, soup_connection_auth, SOUP_TYPE_AUTH)
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_connection_auth_init (SoupConnectionAuth *auth)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
auth->priv = soup_connection_auth_get_instance_private (auth);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth->priv->conns = g_hash_table_new (NULL, NULL);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void connection_disconnected (SoupConnection *conn, gpointer user_data);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_connection_auth_free_connection_state (SoupConnectionAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupConnection *conn,
|
|
rpm-build |
4f3c61 |
gpointer state)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_disconnected), auth);
|
|
rpm-build |
4f3c61 |
SOUP_CONNECTION_AUTH_GET_CLASS (auth)->free_connection_state (auth, state);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
connection_disconnected (SoupConnection *conn, gpointer user_data)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnectionAuth *auth = user_data;
|
|
rpm-build |
4f3c61 |
gpointer state;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
state = g_hash_table_lookup (auth->priv->conns, conn);
|
|
rpm-build |
4f3c61 |
g_hash_table_remove (auth->priv->conns, conn);
|
|
rpm-build |
4f3c61 |
soup_connection_auth_free_connection_state (auth, conn, state);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_connection_auth_finalize (GObject *object)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnectionAuth *auth = SOUP_CONNECTION_AUTH (object);
|
|
rpm-build |
4f3c61 |
GHashTableIter iter;
|
|
rpm-build |
4f3c61 |
gpointer conn, state;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_hash_table_iter_init (&iter, auth->priv->conns);
|
|
rpm-build |
4f3c61 |
while (g_hash_table_iter_next (&iter, &conn, &state)) {
|
|
rpm-build |
4f3c61 |
soup_connection_auth_free_connection_state (auth, conn, state);
|
|
rpm-build |
4f3c61 |
g_hash_table_iter_remove (&iter);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
g_hash_table_destroy (auth->priv->conns);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
G_OBJECT_CLASS (soup_connection_auth_parent_class)->finalize (object);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* soup_connection_auth_get_connection_state_for_message:
|
|
rpm-build |
4f3c61 |
* @auth: a #SoupConnectionAuth
|
|
rpm-build |
4f3c61 |
* @msg: a #SoupMessage
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Returns an associated connection state object for the given @auth and @msg.
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* This function is only useful from within implementations of SoupConnectionAuth
|
|
rpm-build |
4f3c61 |
* subclasses.
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Return value: (transfer none): the connection state
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Since: 2.58
|
|
rpm-build |
4f3c61 |
**/
|
|
rpm-build |
4f3c61 |
gpointer
|
|
rpm-build |
4f3c61 |
soup_connection_auth_get_connection_state_for_message (SoupConnectionAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnection *conn;
|
|
rpm-build |
4f3c61 |
gpointer state;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_return_val_if_fail (SOUP_IS_CONNECTION_AUTH (auth), NULL);
|
|
rpm-build |
4f3c61 |
g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
conn = soup_message_get_connection (msg);
|
|
rpm-build |
4f3c61 |
state = g_hash_table_lookup (auth->priv->conns, conn);
|
|
rpm-build |
4f3c61 |
if (state)
|
|
rpm-build |
4f3c61 |
return state;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
state = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->create_connection_state (auth);
|
|
rpm-build |
4f3c61 |
if (conn) {
|
|
rpm-build |
4f3c61 |
g_signal_connect (conn, "disconnected",
|
|
rpm-build |
4f3c61 |
G_CALLBACK (connection_disconnected), auth);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_hash_table_insert (auth->priv->conns, conn, state);
|
|
rpm-build |
4f3c61 |
return state;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
soup_connection_auth_update (SoupAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg,
|
|
rpm-build |
4f3c61 |
GHashTable *auth_params)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
|
|
rpm-build |
4f3c61 |
gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg);
|
|
rpm-build |
4f3c61 |
GHashTableIter iter;
|
|
rpm-build |
4f3c61 |
GString *auth_header;
|
|
rpm-build |
4f3c61 |
gpointer key, value;
|
|
rpm-build |
4f3c61 |
gboolean result;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* Recreate @auth_header out of @auth_params. If the
|
|
rpm-build |
4f3c61 |
* base64 data ended with 1 or more "="s, then it
|
|
rpm-build |
4f3c61 |
* will have been parsed as key=value. Otherwise
|
|
rpm-build |
4f3c61 |
* it will all have been parsed as key, and value
|
|
rpm-build |
4f3c61 |
* will be %NULL.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
auth_header = g_string_new (soup_auth_get_scheme_name (auth));
|
|
rpm-build |
4f3c61 |
g_hash_table_iter_init (&iter, auth_params);
|
|
rpm-build |
4f3c61 |
if (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
rpm-build |
4f3c61 |
if (value) {
|
|
rpm-build |
4f3c61 |
g_string_append_printf (auth_header, " %s=%s",
|
|
rpm-build |
4f3c61 |
(char *)key,
|
|
rpm-build |
4f3c61 |
(char *)value);
|
|
rpm-build |
4f3c61 |
} else {
|
|
rpm-build |
4f3c61 |
g_string_append_printf (auth_header, " %s",
|
|
rpm-build |
4f3c61 |
(char *)key);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
rpm-build |
4f3c61 |
g_string_free (auth_header, TRUE);
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
result = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
|
|
rpm-build |
4f3c61 |
update_connection (cauth, msg, auth_header->str, conn);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_string_free (auth_header, TRUE);
|
|
rpm-build |
4f3c61 |
return result;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static char *
|
|
rpm-build |
4f3c61 |
soup_connection_auth_get_authorization (SoupAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
|
|
rpm-build |
4f3c61 |
gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
|
|
rpm-build |
4f3c61 |
get_connection_authorization (cauth, msg, conn);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
soup_connection_auth_is_ready (SoupAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
|
|
rpm-build |
4f3c61 |
gpointer conn = soup_connection_auth_get_connection_state_for_message (cauth, msg);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
|
|
rpm-build |
4f3c61 |
is_connection_ready (SOUP_CONNECTION_AUTH (auth), msg, conn);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_connection_auth_class_init (SoupConnectionAuthClass *connauth_class)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthClass *auth_class = SOUP_AUTH_CLASS (connauth_class);
|
|
rpm-build |
4f3c61 |
GObjectClass *object_class = G_OBJECT_CLASS (connauth_class);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth_class->update = soup_connection_auth_update;
|
|
rpm-build |
4f3c61 |
auth_class->get_authorization = soup_connection_auth_get_authorization;
|
|
rpm-build |
4f3c61 |
auth_class->is_ready = soup_connection_auth_is_ready;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
object_class->finalize = soup_connection_auth_finalize;
|
|
rpm-build |
4f3c61 |
}
|