1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-connection-auth.c: Abstract base class for hacky Microsoft
4 * connection-based auth mechanisms (NTLM and Negotiate)
6 * Copyright (C) 2010 Red Hat, Inc.
16 #include "soup-connection-auth.h"
18 #include "soup-connection.h"
19 #include "soup-message-private.h"
21 G_DEFINE_ABSTRACT_TYPE (SoupConnectionAuth, soup_connection_auth, SOUP_TYPE_AUTH)
23 struct SoupConnectionAuthPrivate {
28 soup_connection_auth_init (SoupConnectionAuth *auth)
30 auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthPrivate);
32 auth->priv->conns = g_hash_table_new (NULL, NULL);
35 static void connection_disconnected (SoupConnection *conn, gpointer user_data);
38 soup_connection_auth_free_connection_state (SoupConnectionAuth *auth,
42 g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_disconnected), auth);
43 SOUP_CONNECTION_AUTH_GET_CLASS (auth)->free_connection_state (auth, state);
47 connection_disconnected (SoupConnection *conn, gpointer user_data)
49 SoupConnectionAuth *auth = user_data;
52 state = g_hash_table_lookup (auth->priv->conns, conn);
53 g_hash_table_remove (auth->priv->conns, conn);
54 soup_connection_auth_free_connection_state (auth, conn, state);
58 soup_connection_auth_finalize (GObject *object)
60 SoupConnectionAuth *auth = SOUP_CONNECTION_AUTH (object);
64 g_hash_table_iter_init (&iter, auth->priv->conns);
65 while (g_hash_table_iter_next (&iter, &conn, &state)) {
66 soup_connection_auth_free_connection_state (auth, conn, state);
67 g_hash_table_iter_remove (&iter);
69 g_hash_table_destroy (auth->priv->conns);
71 G_OBJECT_CLASS (soup_connection_auth_parent_class)->finalize (object);
75 get_connection_state_for_message (SoupConnectionAuth *auth, SoupMessage *msg)
80 conn = soup_message_get_connection (msg);
81 state = g_hash_table_lookup (auth->priv->conns, conn);
85 state = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->create_connection_state (auth);
87 g_signal_connect (conn, "disconnected",
88 G_CALLBACK (connection_disconnected), auth);
91 g_hash_table_insert (auth->priv->conns, conn, state);
96 soup_connection_auth_update (SoupAuth *auth,
98 GHashTable *auth_params)
100 SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
101 gpointer conn = get_connection_state_for_message (cauth, msg);
103 GString *auth_header;
107 /* Recreate @auth_header out of @auth_params. If the
108 * base64 data ended with 1 or more "="s, then it
109 * will have been parsed as key=value. Otherwise
110 * it will all have been parsed as key, and value
113 auth_header = g_string_new (soup_auth_get_scheme_name (auth));
114 g_hash_table_iter_init (&iter, auth_params);
115 if (g_hash_table_iter_next (&iter, &key, &value)) {
117 g_string_append_printf (auth_header, " %s=%s",
121 g_string_append_printf (auth_header, " %s",
125 if (g_hash_table_iter_next (&iter, &key, &value)) {
126 g_string_free (auth_header, TRUE);
131 result = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
132 update_connection (cauth, msg, auth_header->str, conn);
134 g_string_free (auth_header, TRUE);
139 soup_connection_auth_get_authorization (SoupAuth *auth,
142 SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
143 gpointer conn = get_connection_state_for_message (cauth, msg);
145 return SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
146 get_connection_authorization (cauth, msg, conn);
150 soup_connection_auth_is_ready (SoupAuth *auth,
153 SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth);
154 gpointer conn = get_connection_state_for_message (cauth, msg);
156 return SOUP_CONNECTION_AUTH_GET_CLASS (auth)->
157 is_connection_ready (SOUP_CONNECTION_AUTH (auth), msg, conn);
161 soup_connection_auth_class_init (SoupConnectionAuthClass *connauth_class)
163 SoupAuthClass *auth_class = SOUP_AUTH_CLASS (connauth_class);
164 GObjectClass *object_class = G_OBJECT_CLASS (connauth_class);
166 g_type_class_add_private (connauth_class, sizeof (SoupConnectionAuthPrivate));
168 auth_class->update = soup_connection_auth_update;
169 auth_class->get_authorization = soup_connection_auth_get_authorization;
170 auth_class->is_ready = soup_connection_auth_is_ready;
172 object_class->finalize = soup_connection_auth_finalize;