Blame libsoup/soup-connection-auth.c

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
}