From 2005378fa5627ba1ddb6f59f1eb72c1c070b6469 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 18 Jan 2008 14:53:35 +0000 Subject: [PATCH] add a new generic auth callback that can be used with any subclass to do * libsoup/soup-auth-domain.c (soup_auth_domain_set_generic_auth_callback): (soup_auth_domain_check_password): add a new generic auth callback that can be used with any subclass to do cleartext password checking against messages. Suggested by Mathias Hasselmann. * libsoup/soup-auth-domain-basic.c: Implement generic auth * libsoup/soup-auth-domain-digest.c: Implement generic auth. (soup_auth_domain_digest_evil_check_password): Gone, use the generic version now. svn path=/trunk/; revision=1048 --- ChangeLog | 14 +++ libsoup/soup-auth-domain-basic.c | 86 +++++++++++---- libsoup/soup-auth-domain-digest.c | 213 ++++++++++++++++++-------------------- libsoup/soup-auth-domain-digest.h | 7 -- libsoup/soup-auth-domain.c | 151 ++++++++++++++++++++++++++- libsoup/soup-auth-domain.h | 40 +++++-- 6 files changed, 359 insertions(+), 152 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83c6001..e41c718 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-01-18 Dan Winship + + * libsoup/soup-auth-domain.c + (soup_auth_domain_set_generic_auth_callback): + (soup_auth_domain_check_password): add a new generic auth callback + that can be used with any subclass to do cleartext password + checking against messages. Suggested by Mathias Hasselmann. + + * libsoup/soup-auth-domain-basic.c: Implement generic auth + + * libsoup/soup-auth-domain-digest.c: Implement generic auth. + (soup_auth_domain_digest_evil_check_password): Gone, use the + generic version now. + 2008-01-17 Dan Winship * libsoup/soup-auth-digest.c (soup_auth_digest_compute_hex_urp) diff --git a/libsoup/soup-auth-domain-basic.c b/libsoup/soup-auth-domain-basic.c index c3c64e2..b8b8fc5 100644 --- a/libsoup/soup-auth-domain-basic.c +++ b/libsoup/soup-auth-domain-basic.c @@ -42,11 +42,15 @@ typedef struct { G_DEFINE_TYPE (SoupAuthDomainBasic, soup_auth_domain_basic, SOUP_TYPE_AUTH_DOMAIN) -static char *accepts (SoupAuthDomain *domain, - SoupMessage *msg, - const char *header); -static char *challenge (SoupAuthDomain *domain, - SoupMessage *msg); +static char *accepts (SoupAuthDomain *domain, + SoupMessage *msg, + const char *header); +static char *challenge (SoupAuthDomain *domain, + SoupMessage *msg); +static gboolean check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); @@ -79,8 +83,9 @@ soup_auth_domain_basic_class_init (SoupAuthDomainBasicClass *basic_class) g_type_class_add_private (basic_class, sizeof (SoupAuthDomainBasicPrivate)); - auth_domain_class->accepts = accepts; - auth_domain_class->challenge = challenge; + auth_domain_class->accepts = accepts; + auth_domain_class->challenge = challenge; + auth_domain_class->check_password = check_password; object_class->finalize = finalize; object_class->set_property = set_property; @@ -241,40 +246,53 @@ pw_free (char *pw) g_free (pw); } -static char * -accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) +static gboolean +parse_basic (SoupMessage *msg, const char *header, + char **username, char **password) { - SoupAuthDomainBasicPrivate *priv = - SOUP_AUTH_DOMAIN_BASIC_GET_PRIVATE (domain); char *decoded, *colon; gsize len, plen; - char *username, *password; - gboolean ok = FALSE; - - if (!priv->auth_callback) - return NULL; if (strncmp (header, "Basic ", 6) != 0) - return NULL; + return FALSE; decoded = (char *)g_base64_decode (header + 6, &len); if (!decoded) - return NULL; + return FALSE; colon = memchr (decoded, ':', len); if (!colon) { pw_free (decoded); - return NULL; + return FALSE; } *colon = '\0'; plen = len - (colon - decoded) - 1; - password = g_strndup (colon + 1, plen); + *password = g_strndup (colon + 1, plen); memset (colon + 1, 0, plen); - username = decoded; + *username = decoded; + return TRUE; +} + +static char * +accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) +{ + SoupAuthDomainBasicPrivate *priv = + SOUP_AUTH_DOMAIN_BASIC_GET_PRIVATE (domain); + char *username, *password; + gboolean ok = FALSE; + + if (!parse_basic (msg, header, &username, &password)) + return NULL; + + if (priv->auth_callback) { + ok = priv->auth_callback (domain, msg, username, password, + priv->auth_data); + } else { + ok = soup_auth_domain_try_generic_auth_callback ( + domain, msg, username); + } - ok = priv->auth_callback (domain, msg, username, password, - priv->auth_data); pw_free (password); if (ok) @@ -292,3 +310,25 @@ challenge (SoupAuthDomain *domain, SoupMessage *msg) return g_strdup_printf ("Basic realm=\"%s\"", soup_auth_domain_get_realm (domain)); } + +static gboolean +check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) +{ + const char *header; + char *msg_username, *msg_password; + gboolean ok; + + header = soup_message_headers_get (msg->request_headers, "Authorization"); + if (!parse_basic (msg, header, &msg_username, &msg_password)) + return FALSE; + + ok = (!strcmp (username, msg_username) && + !strcmp (password, msg_password)); + g_free (msg_username); + pw_free (msg_password); + + return ok; +} diff --git a/libsoup/soup-auth-domain-digest.c b/libsoup/soup-auth-domain-digest.c index b303ce8..a98bf74 100644 --- a/libsoup/soup-auth-domain-digest.c +++ b/libsoup/soup-auth-domain-digest.c @@ -47,11 +47,15 @@ typedef struct { G_DEFINE_TYPE (SoupAuthDomainDigest, soup_auth_domain_digest, SOUP_TYPE_AUTH_DOMAIN) -static char *accepts (SoupAuthDomain *domain, - SoupMessage *msg, - const char *header); -static char *challenge (SoupAuthDomain *domain, - SoupMessage *msg); +static char *accepts (SoupAuthDomain *domain, + SoupMessage *msg, + const char *header); +static char *challenge (SoupAuthDomain *domain, + SoupMessage *msg); +static gboolean check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); @@ -84,8 +88,9 @@ soup_auth_domain_digest_class_init (SoupAuthDomainDigestClass *digest_class) g_type_class_add_private (digest_class, sizeof (SoupAuthDomainDigestPrivate)); - auth_domain_class->accepts = accepts; - auth_domain_class->challenge = challenge; + auth_domain_class->accepts = accepts; + auth_domain_class->challenge = challenge; + auth_domain_class->check_password = check_password; object_class->finalize = finalize; object_class->set_property = set_property; @@ -229,40 +234,32 @@ soup_auth_domain_digest_set_auth_callback (SoupAuthDomain *domain, g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_DIGEST_AUTH_DATA); } -static char * -accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) +static gboolean +check_hex_urp (SoupAuthDomain *domain, SoupMessage *msg, + GHashTable *params, const char *username, + const char *hex_urp) { - SoupAuthDomainDigestPrivate *priv = - SOUP_AUTH_DOMAIN_DIGEST_GET_PRIVATE (domain); - GHashTable *params; - const char *uri, *qop, *realm, *username; + const char *uri, *qop, *realm, *msg_username; const char *nonce, *nc, *cnonce, *response; - char *hex_urp, hex_a1[33], computed_response[33], *ret_user; + char hex_a1[33], computed_response[33]; int nonce_count; SoupURI *dig_uri, *req_uri; - gboolean accept = FALSE; - - if (!priv->auth_callback) - return NULL; - - if (strncmp (header, "Digest ", 7) != 0) - return NULL; - params = soup_header_parse_param_list (header + 7); - if (!params) - return NULL; + msg_username = g_hash_table_lookup (params, "username"); + if (!msg_username || strcmp (msg_username, username) != 0) + return FALSE; /* Check uri */ uri = g_hash_table_lookup (params, "uri"); if (!uri) - goto DONE; + return FALSE; req_uri = soup_message_get_uri (msg); dig_uri = soup_uri_new (uri); if (dig_uri) { if (!soup_uri_equal (dig_uri, req_uri)) { soup_uri_free (dig_uri); - goto DONE; + return FALSE; } soup_uri_free (dig_uri); } else { @@ -271,7 +268,7 @@ accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) req_path = soup_uri_to_string (req_uri, TRUE); if (strcmp (uri, req_path) != 0) { g_free (req_path); - goto DONE; + return FALSE; } g_free (req_path); } @@ -279,46 +276,75 @@ accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) /* Check qop; we only support "auth" for now */ qop = g_hash_table_lookup (params, "qop"); if (!qop || strcmp (qop, "auth") != 0) - goto DONE; + return FALSE; /* Check realm */ realm = g_hash_table_lookup (params, "realm"); if (!realm || strcmp (realm, soup_auth_domain_get_realm (domain)) != 0) - goto DONE; + return FALSE; - username = g_hash_table_lookup (params, "username"); - if (!username) - goto DONE; nonce = g_hash_table_lookup (params, "nonce"); if (!nonce) - goto DONE; + return FALSE; nc = g_hash_table_lookup (params, "nc"); if (!nc) - goto DONE; + return FALSE; nonce_count = atoi (nc); if (nonce_count <= 0) - goto DONE; + return FALSE; cnonce = g_hash_table_lookup (params, "cnonce"); if (!cnonce) - goto DONE; + return FALSE; response = g_hash_table_lookup (params, "response"); if (!response) - goto DONE; + return FALSE; + + soup_auth_digest_compute_hex_a1 (hex_urp, + SOUP_AUTH_DIGEST_ALGORITHM_MD5, + nonce, cnonce, hex_a1); + soup_auth_digest_compute_response (msg->method, uri, + hex_a1, + SOUP_AUTH_DIGEST_QOP_AUTH, + nonce, cnonce, nonce_count, + computed_response); + return strcmp (response, computed_response) == 0; +} + +static char * +accepts (SoupAuthDomain *domain, SoupMessage *msg, const char *header) +{ + SoupAuthDomainDigestPrivate *priv = + SOUP_AUTH_DOMAIN_DIGEST_GET_PRIVATE (domain); + GHashTable *params; + const char *username; + gboolean accept = FALSE; + char *ret_user; + + if (strncmp (header, "Digest ", 7) != 0) + return NULL; + + params = soup_header_parse_param_list (header + 7); + if (!params) + return NULL; + + username = g_hash_table_lookup (params, "username"); + if (!username) { + soup_header_free_param_list (params); + return NULL; + } - hex_urp = priv->auth_callback (domain, msg, username, priv->auth_data); - if (hex_urp) { - soup_auth_digest_compute_hex_a1 (hex_urp, - SOUP_AUTH_DIGEST_ALGORITHM_MD5, - nonce, cnonce, hex_a1); + if (priv->auth_callback) { + char *hex_urp; + + hex_urp = priv->auth_callback (domain, msg, username, + priv->auth_data); + accept = check_hex_urp (domain, msg, params, username, hex_urp); g_free (hex_urp); - soup_auth_digest_compute_response (msg->method, uri, hex_a1, - SOUP_AUTH_DIGEST_QOP_AUTH, - nonce, cnonce, nonce_count, - computed_response); - accept = (strcmp (response, computed_response) == 0); + } else { + accept = soup_auth_domain_try_generic_auth_callback ( + domain, msg, username); } - DONE: ret_user = accept ? g_strdup (username) : NULL; soup_header_free_param_list (params); return ret_user; @@ -378,77 +404,36 @@ soup_auth_domain_digest_encode_password (const char *username, return g_strdup (hex_urp); } -static char * -evil_auth_callback (SoupAuthDomain *domain, SoupMessage *msg, - const char *username, gpointer encoded_password) -{ - return g_strdup (encoded_password); -} - -/** - * soup_auth_domain_digest_evil_check_password: - * @domain: the auth domain - * @msg: the possibly-authenticated request - * @username: the username to check @msg against - * @password: the password to check @msg against - * - * Checks if @msg correctly authenticates @username via @password in - * @domain. - * - * Don't use this method; it's evil. It requires you to have a - * cleartext password database, which means that if your server is - * compromised, the attackers will have access to all of your users' - * passwords, which may also be their passwords on other servers. It - * is much better to store the passwords encoded in some format (eg, - * via soup_auth_domain_digest_encode_password() when using Digest - * authentication), so that if the server is compromised, the - * attackers won't be able to use the encoded passwords elsewhere. - * - * At any rate, even if you do have a cleartext password database, you - * still don't need to use this method, as you can just call - * soup_auth_domain_digest_encode_password() on the cleartext password - * from the #SoupAuthDomainDigestAuthCallback anyway. This method - * really only exists so as not to break certain libraries written - * against libsoup 2.2 whose public APIs depend on the existence of a - * "check this password against this request" method. - * - * Return value: %TRUE if @msg matches @username and @password, - * %FALSE if not. - **/ -gboolean -soup_auth_domain_digest_evil_check_password (SoupAuthDomain *domain, - SoupMessage *msg, - const char *username, - const char *password) +static gboolean +check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) { - SoupAuthDomainDigestPrivate *priv = - SOUP_AUTH_DOMAIN_DIGEST_GET_PRIVATE (domain); - char *encoded_password; const char *header; - SoupAuthDomainDigestAuthCallback old_callback; - gpointer old_data; - char *matched_username; - - encoded_password = soup_auth_domain_digest_encode_password ( - username, soup_auth_domain_get_realm (domain), password); - - old_callback = priv->auth_callback; - old_data = priv->auth_data; - - priv->auth_callback = evil_auth_callback; - priv->auth_data = encoded_password; + GHashTable *params; + const char *msg_username; + char hex_urp[33]; + gboolean accept; header = soup_message_headers_get (msg->request_headers, "Authorization"); - matched_username = accepts (domain, msg, header); - - priv->auth_callback = old_callback; - priv->auth_data = old_data; + if (strncmp (header, "Digest ", 7) != 0) + return FALSE; - g_free (encoded_password); + params = soup_header_parse_param_list (header + 7); + if (!params) + return FALSE; - if (matched_username) { - g_free (matched_username); - return TRUE; - } else + msg_username = g_hash_table_lookup (params, "username"); + if (!msg_username || strcmp (msg_username, username) != 0) { + soup_header_free_param_list (params); return FALSE; + } + + soup_auth_digest_compute_hex_urp (username, + soup_auth_domain_get_realm (domain), + password, hex_urp); + accept = check_hex_urp (domain, msg, params, username, hex_urp); + soup_header_free_param_list (params); + return accept; } diff --git a/libsoup/soup-auth-domain-digest.h b/libsoup/soup-auth-domain-digest.h index 8f8ae10..0a9a36e 100644 --- a/libsoup/soup-auth-domain-digest.h +++ b/libsoup/soup-auth-domain-digest.h @@ -52,11 +52,4 @@ char *soup_auth_domain_digest_encode_password (const char *username, const char *realm, const char *password); - -gboolean soup_auth_domain_digest_evil_check_password (SoupAuthDomain *domain, - SoupMessage *msg, - const char *username, - const char *password); - - #endif /* SOUP_AUTH_DOMAIN_DIGEST_H */ diff --git a/libsoup/soup-auth-domain.c b/libsoup/soup-auth-domain.c index 8ff77bb..04ee1c4 100644 --- a/libsoup/soup-auth-domain.c +++ b/libsoup/soup-auth-domain.c @@ -47,6 +47,8 @@ enum { PROP_REMOVE_PATH, PROP_FILTER, PROP_FILTER_DATA, + PROP_GENERIC_AUTH_CALLBACK, + PROP_GENERIC_AUTH_DATA, LAST_PROP }; @@ -54,10 +56,16 @@ enum { typedef struct { char *realm; gboolean proxy; + SoupPathMap *paths; + SoupAuthDomainFilter filter; gpointer filter_data; GDestroyNotify filter_dnotify; - SoupPathMap *paths; + + SoupAuthDomainGenericAuthCallback auth_callback; + gpointer auth_data; + GDestroyNotify auth_dnotify; + } SoupAuthDomainPrivate; #define SOUP_AUTH_DOMAIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_DOMAIN, SoupAuthDomainPrivate)) @@ -87,6 +95,8 @@ finalize (GObject *object) if (priv->filter_dnotify) priv->filter_dnotify (priv->filter_data); + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); G_OBJECT_CLASS (soup_auth_domain_parent_class)->finalize (object); } @@ -142,6 +152,18 @@ soup_auth_domain_class_init (SoupAuthDomainClass *auth_domain_class) "Filter data", "Data to pass to filter", G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, PROP_GENERIC_AUTH_CALLBACK, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK, + "Generic authentication callback", + "An authentication callback that can be used with any SoupAuthDomain subclass", + G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, PROP_GENERIC_AUTH_DATA, + g_param_spec_pointer (SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA, + "Authentication callback data", + "Data to pass to auth callback", + G_PARAM_READWRITE)); } static void @@ -177,6 +199,16 @@ set_property (GObject *object, guint prop_id, } priv->filter_data = g_value_get_pointer (value); break; + case PROP_GENERIC_AUTH_CALLBACK: + priv->auth_callback = g_value_get_pointer (value); + break; + case PROP_GENERIC_AUTH_DATA: + if (priv->auth_dnotify) { + priv->auth_dnotify (priv->auth_data); + priv->auth_dnotify = NULL; + } + priv->auth_data = g_value_get_pointer (value); + break; default: break; } @@ -201,6 +233,12 @@ get_property (GObject *object, guint prop_id, case PROP_FILTER_DATA: g_value_set_pointer (value, priv->filter_data); break; + case PROP_GENERIC_AUTH_CALLBACK: + g_value_set_pointer (value, priv->auth_callback); + break; + case PROP_GENERIC_AUTH_DATA: + g_value_set_pointer (value, priv->auth_data); + break; default: break; } @@ -256,6 +294,18 @@ soup_auth_domain_remove_path (SoupAuthDomain *domain, const char *path) } /** + * SoupAuthDomainFilter: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * @user_data: the data passed to soup_auth_domain_set_filter() + * + * The prototype for a #SoupAuthDomain filter; see + * soup_auth_domain_set_filter() for details. + * + * Return value: %TRUE if @msg requires authentication, %FALSE if not. + **/ + +/** * soup_auth_domain_set_filter: * @domain: a #SoupAuthDomain * @filter: the auth filter for @domain @@ -324,6 +374,105 @@ soup_auth_domain_get_realm (SoupAuthDomain *domain) } /** + * SoupAuthDomainGenericAuthCallback: + * @domain: a #SoupAuthDomain + * @msg: the #SoupMessage being authenticated + * @username: the username from @msg + * @user_data: the data passed to + * soup_auth_domain_set_generic_auth_callback() + * + * The prototype for a #SoupAuthDomain generic authentication callback. + * + * The callback should look up the user's password, call + * soup_auth_domain_check_password(), and use the return value from + * that method as its own return value. + * + * In general, for security reasons, it is preferable to use the + * auth-domain-specific auth callbacks (eg, + * #SoupAuthDomainBasicAuthCallback and + * #SoupAuthDomainDigestAuthCallback), because they don't require + * keeping a cleartext password database. Most users will use the same + * password for many different sites, meaning if any site with a + * cleartext password database is compromised, accounts on other + * servers might be compromised as well. For many of the cases where + * #SoupServer is used, this is not really relevant, but it may still + * be worth considering. + * + * Return value: %TRUE if @msg is authenticated, %FALSE if not. + **/ + +/** + * soup_auth_domain_set_generic_auth_callback: + * @domain: a #SoupAuthDomain + * @auth_callback: the auth callback + * @auth_data: data to pass to @auth_callback + * @dnotify: destroy notifier to free @auth_data when @domain + * is destroyed + * + * Sets @auth_callback as an authentication-handling callback for + * @domain. Whenever a request comes in to @domain which cannot be + * authenticated via a domain-specific auth callback (eg, + * #SoupAuthDomainDigestAuthCallback), the generic auth callback + * will be invoked. See #SoupAuthDomainGenericAuthCallback for information + * on what the callback should do. + **/ +void +soup_auth_domain_set_generic_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainGenericAuthCallback auth_callback, + gpointer auth_data, + GDestroyNotify dnotify) +{ + SoupAuthDomainPrivate *priv = SOUP_AUTH_DOMAIN_GET_PRIVATE (domain); + + if (priv->auth_dnotify) + priv->auth_dnotify (priv->auth_data); + + priv->auth_callback = auth_callback; + priv->auth_data = auth_data; + priv->auth_dnotify = dnotify; + + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK); + g_object_notify (G_OBJECT (domain), SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA); +} + +gboolean +soup_auth_domain_try_generic_auth_callback (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username) +{ + SoupAuthDomainPrivate *priv = SOUP_AUTH_DOMAIN_GET_PRIVATE (domain); + + if (priv->auth_callback) + return priv->auth_callback (domain, msg, username, priv->auth_data); + else + return FALSE; +} + +/** + * soup_auth_domain_check_password: + * @domain: a #SoupAuthDomain + * @msg: a #SoupMessage + * @username: a username + * @password: a password + * + * Checks if @msg authenticates to @domain via @username and + * @password. This would normally be called from a + * #SoupAuthDomainGenericAuthCallback. + * + * Return value: whether or not the message is authenticated + **/ +gboolean +soup_auth_domain_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password) +{ + return SOUP_AUTH_DOMAIN_GET_CLASS (domain)->check_password (domain, msg, + username, + password); +} + +/** * soup_auth_domain_covers: * @domain: a #SoupAuthDomain * @msg: a #SoupMessage diff --git a/libsoup/soup-auth-domain.h b/libsoup/soup-auth-domain.h index 8b903f7..8b8617b 100644 --- a/libsoup/soup-auth-domain.h +++ b/libsoup/soup-auth-domain.h @@ -23,14 +23,17 @@ struct SoupAuthDomain { typedef struct { GObjectClass parent_class; - char * (*accepts) (SoupAuthDomain *domain, - SoupMessage *msg, - const char *header); - char * (*challenge) (SoupAuthDomain *domain, - SoupMessage *msg); + char * (*accepts) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *header); + char * (*challenge) (SoupAuthDomain *domain, + SoupMessage *msg); + gboolean (*check_password) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); /* Padding for future expansion */ - void (*_libsoup_reserved1) (void); void (*_libsoup_reserved2) (void); void (*_libsoup_reserved3) (void); void (*_libsoup_reserved4) (void); @@ -42,8 +45,17 @@ typedef struct { #define SOUP_AUTH_DOMAIN_REMOVE_PATH "remove-path" #define SOUP_AUTH_DOMAIN_FILTER "filter" #define SOUP_AUTH_DOMAIN_FILTER_DATA "filter-data" +#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_CALLBACK "generic-auth-callback" +#define SOUP_AUTH_DOMAIN_GENERIC_AUTH_DATA "generic-auth-data" -typedef gboolean (*SoupAuthDomainFilter) (SoupAuthDomain *, SoupMessage *, gpointer); +typedef gboolean (*SoupAuthDomainFilter) (SoupAuthDomain *domain, + SoupMessage *msg, + gpointer user_data); + +typedef gboolean (*SoupAuthDomainGenericAuthCallback) (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + gpointer user_data); GType soup_auth_domain_get_type (void); @@ -59,6 +71,15 @@ void soup_auth_domain_set_filter (SoupAuthDomain *domain, const char *soup_auth_domain_get_realm (SoupAuthDomain *domain); +void soup_auth_domain_set_generic_auth_callback (SoupAuthDomain *domain, + SoupAuthDomainGenericAuthCallback auth_callback, + gpointer auth_data, + GDestroyNotify dnotify); +gboolean soup_auth_domain_check_password (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username, + const char *password); + gboolean soup_auth_domain_covers (SoupAuthDomain *domain, SoupMessage *msg); char *soup_auth_domain_accepts (SoupAuthDomain *domain, @@ -66,4 +87,9 @@ char *soup_auth_domain_accepts (SoupAuthDomain *domain, void soup_auth_domain_challenge (SoupAuthDomain *domain, SoupMessage *msg); +/* protected */ +gboolean soup_auth_domain_try_generic_auth_callback (SoupAuthDomain *domain, + SoupMessage *msg, + const char *username); + #endif /* SOUP_AUTH_DOMAIN_H */ -- 2.7.4