diff options
author | Patrick Griffis <pgriffis@igalia.com> | 2021-10-08 07:38:46 -0500 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2021-10-08 09:17:41 -0500 |
commit | f9a972791965e05e540766751da4a13241051fbb (patch) | |
tree | 764ee9f6eae4d861187af891b328f4829a2f8695 | |
parent | 9af7d0fc751f7afcd8b03bc827a4d3af0c4556f8 (diff) | |
download | libsoup-pgriffis/digest-sha256.tar.gz |
WIP: auth: Add Digest support for SHA-256pgriffis/digest-sha256
-rw-r--r-- | libsoup/auth/soup-auth-digest-private.h | 37 | ||||
-rw-r--r-- | libsoup/auth/soup-auth-digest.c | 179 | ||||
-rw-r--r-- | libsoup/server/soup-auth-domain-digest.c | 43 |
3 files changed, 153 insertions, 106 deletions
diff --git a/libsoup/auth/soup-auth-digest-private.h b/libsoup/auth/soup-auth-digest-private.h index bb251ad0..c5c9e29b 100644 --- a/libsoup/auth/soup-auth-digest-private.h +++ b/libsoup/auth/soup-auth-digest-private.h @@ -8,7 +8,9 @@ typedef enum { SOUP_AUTH_DIGEST_ALGORITHM_NONE, SOUP_AUTH_DIGEST_ALGORITHM_MD5, - SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS + SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS, + SOUP_AUTH_DIGEST_ALGORITHM_SHA256, + SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS, } SoupAuthDigestAlgorithm; typedef enum { @@ -22,20 +24,19 @@ char *soup_auth_digest_get_algorithm (SoupAuthDigestAlgorit SoupAuthDigestQop soup_auth_digest_parse_qop (const char *qop); char *soup_auth_digest_get_qop (SoupAuthDigestQop qop); -void soup_auth_digest_compute_hex_urp (const char *username, - const char *realm, - const char *password, - char hex_urp[33]); -void soup_auth_digest_compute_hex_a1 (const char *hex_urp, - SoupAuthDigestAlgorithm algorithm, - const char *nonce, - const char *cnonce, - char hex_a1[33]); -void soup_auth_digest_compute_response (const char *method, - const char *uri, - const char *hex_a1, - SoupAuthDigestQop qop, - const char *nonce, - const char *cnonce, - int nc, - char response[33]); +char *soup_auth_digest_compute_hex_urp (SoupAuthDigestAlgorithm algorithm, + const char *username, + const char *realm, + const char *password); +char *soup_auth_digest_compute_hex_a1 (const char *hex_urp, + SoupAuthDigestAlgorithm algorithm, + const char *nonce, + const char *cnonce); +char *soup_auth_digest_compute_response (SoupAuthDigestAlgorithm algorithm, + const char *method, + const char *uri, + const char *hex_a1, + SoupAuthDigestQop qop, + const char *nonce, + const char *cnonce, + int nc); diff --git a/libsoup/auth/soup-auth-digest.c b/libsoup/auth/soup-auth-digest.c index 13b6cc16..7583d0ab 100644 --- a/libsoup/auth/soup-auth-digest.c +++ b/libsoup/auth/soup-auth-digest.c @@ -27,8 +27,8 @@ struct _SoupAuthDigest { typedef struct { char *user; - char hex_urp[33]; - char hex_a1[33]; + char *hex_urp; + char *hex_a1; /* These are provided by the server */ char *nonce; @@ -71,9 +71,8 @@ soup_auth_digest_finalize (GObject *object) g_free (priv->nonce); g_free (priv->domain); g_free (priv->cnonce); - - memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); - memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + g_free (priv->hex_urp); + g_free (priv->hex_a1); G_OBJECT_CLASS (soup_auth_digest_parent_class)->finalize (object); } @@ -85,6 +84,10 @@ soup_auth_digest_parse_algorithm (const char *algorithm) return SOUP_AUTH_DIGEST_ALGORITHM_MD5; else if (!g_ascii_strcasecmp (algorithm, "MD5-sess")) return SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS; + else if (!g_ascii_strcasecmp (algorithm, "SHA256")) + return SOUP_AUTH_DIGEST_ALGORITHM_SHA256; + else if (!g_ascii_strcasecmp (algorithm, "SHA256-sess")) + return SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS; else return -1; } @@ -96,6 +99,10 @@ soup_auth_digest_get_algorithm (SoupAuthDigestAlgorithm algorithm) return g_strdup ("MD5"); else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS) return g_strdup ("MD5-sess"); + if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_SHA256) + return g_strdup ("SHA-256"); + else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS) + return g_strdup ("SHA-256-sess"); else return NULL; } @@ -172,15 +179,13 @@ soup_auth_digest_update (SoupAuth *auth, SoupMessage *msg, ok = FALSE; stale = g_hash_table_lookup (auth_params, "stale"); - if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp) + if (stale && !g_ascii_strcasecmp (stale, "TRUE") && priv->hex_urp) recompute_hex_a1 (priv); else { - g_free (priv->user); - priv->user = NULL; - g_free (priv->cnonce); - priv->cnonce = NULL; - memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); - memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + g_clear_pointer (&priv->user, g_free); + g_clear_pointer (&priv->cnonce, g_free); + g_clear_pointer (&priv->hex_urp, g_free); + g_clear_pointer (&priv->hex_a1, g_free); } return ok; @@ -234,13 +239,27 @@ soup_auth_digest_get_protection_space (SoupAuth *auth, GUri *source_uri) return space; } -void -soup_auth_digest_compute_hex_urp (const char *username, +char * +soup_auth_digest_compute_hex_urp (SoupAuthDigestAlgorithm algorithm, + const char *username, const char *realm, - const char *password, - char hex_urp[33]) + const char *password) { GChecksum *checksum; + GChecksumType type; + char *ret; + + switch (algorithm) { + case SOUP_AUTH_DIGEST_ALGORITHM_NONE: + case SOUP_AUTH_DIGEST_ALGORITHM_MD5: + case SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS: + type = G_CHECKSUM_MD5; + break; + case SOUP_AUTH_DIGEST_ALGORITHM_SHA256: + case SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS: + type = G_CHECKSUM_SHA256; + break; + } checksum = g_checksum_new (G_CHECKSUM_MD5); g_checksum_update (checksum, (guchar *)username, strlen (username)); @@ -248,49 +267,55 @@ soup_auth_digest_compute_hex_urp (const char *username, g_checksum_update (checksum, (guchar *)realm, strlen (realm)); g_checksum_update (checksum, (guchar *)":", 1); g_checksum_update (checksum, (guchar *)password, strlen (password)); - g_strlcpy (hex_urp, g_checksum_get_string (checksum), 33); + g_message ("LEN: %zu", g_checksum_type_get_length (type)); + + ret = g_strdup (g_checksum_get_string (checksum)); g_checksum_free (checksum); + + return ret; } -void +char * soup_auth_digest_compute_hex_a1 (const char *hex_urp, SoupAuthDigestAlgorithm algorithm, const char *nonce, - const char *cnonce, - char hex_a1[33]) + const char *cnonce) { - if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) { - /* In MD5, A1 is just user:realm:password, so hex_A1 - * is just hex_urp. - */ - /* You'd think you could say "sizeof (hex_a1)" here, - * but you'd be wrong. - */ - memcpy (hex_a1, hex_urp, 33); - } else { - GChecksum *checksum; - - /* In MD5-sess, A1 is hex_urp:nonce:cnonce */ + GChecksum *checksum; + GChecksumType type; + char *ret; + + /* In non-sess digests, A1 is just user:realm:password, so hex_A1 + * is just hex_urp. */ + if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5 || + algorithm == SOUP_AUTH_DIGEST_ALGORITHM_SHA256) { + return g_strdup (hex_urp); + } - checksum = g_checksum_new (G_CHECKSUM_MD5); - g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp)); - g_checksum_update (checksum, (guchar *)":", 1); - g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); - g_checksum_update (checksum, (guchar *)":", 1); - g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); - g_strlcpy (hex_a1, g_checksum_get_string (checksum), 33); - g_checksum_free (checksum); - } + if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS) + type = G_CHECKSUM_SHA256; + else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS) + type = G_CHECKSUM_MD5; + + checksum = g_checksum_new (type); + g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); + g_checksum_update (checksum, (guchar *)":", 1); + g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); + ret = g_strdup (g_checksum_get_string (checksum)); + g_checksum_free (checksum); + + return ret; } static void recompute_hex_a1 (SoupAuthDigestPrivate *priv) { - soup_auth_digest_compute_hex_a1 (priv->hex_urp, - priv->algorithm, - priv->nonce, - priv->cnonce, - priv->hex_a1); + priv->hex_a1 = soup_auth_digest_compute_hex_a1 (priv->hex_urp, + priv->algorithm, + priv->nonce, + priv->cnonce); } static void @@ -315,9 +340,10 @@ soup_auth_digest_authenticate (SoupAuth *auth, const char *username, priv->user = g_strdup (username); /* compute "URP" (user:realm:password) */ - soup_auth_digest_compute_hex_urp (username, soup_auth_get_realm (auth), - password ? password : "", - priv->hex_urp); + priv->hex_urp = soup_auth_digest_compute_hex_urp (priv->algorithm, + priv->user, + soup_auth_get_realm (auth), + password ? password : ""); /* And compute A1 from that */ recompute_hex_a1 (priv); @@ -331,29 +357,42 @@ soup_auth_digest_is_authenticated (SoupAuth *auth) return priv->cnonce != NULL; } -void -soup_auth_digest_compute_response (const char *method, - const char *uri, - const char *hex_a1, - SoupAuthDigestQop qop, - const char *nonce, - const char *cnonce, - int nc, - char response[33]) +char * +soup_auth_digest_compute_response (SoupAuthDigestAlgorithm algorithm, + const char *method, + const char *uri, + const char *hex_a1, + SoupAuthDigestQop qop, + const char *nonce, + const char *cnonce, + int nc) { - char hex_a2[33]; + char *hex_a2, *response; GChecksum *checksum; + GChecksumType checksum_type; + + switch (algorithm) { + case SOUP_AUTH_DIGEST_ALGORITHM_NONE: + case SOUP_AUTH_DIGEST_ALGORITHM_MD5: + case SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS: + checksum_type = G_CHECKSUM_MD5; + break; + case SOUP_AUTH_DIGEST_ALGORITHM_SHA256: + case SOUP_AUTH_DIGEST_ALGORITHM_SHA256_SESS: + checksum_type = G_CHECKSUM_SHA256; + break; + } /* compute A2 */ - checksum = g_checksum_new (G_CHECKSUM_MD5); + checksum = g_checksum_new (checksum_type); g_checksum_update (checksum, (guchar *)method, strlen (method)); g_checksum_update (checksum, (guchar *)":", 1); g_checksum_update (checksum, (guchar *)uri, strlen (uri)); - memcpy (hex_a2, g_checksum_get_string (checksum), sizeof (char) * 33); + hex_a2 = g_strdup (g_checksum_get_string (checksum)); g_checksum_free (checksum); /* compute KD */ - checksum = g_checksum_new (G_CHECKSUM_MD5); + checksum = g_checksum_new (checksum_type); g_checksum_update (checksum, (guchar *)hex_a1, strlen (hex_a1)); g_checksum_update (checksum, (guchar *)":", 1); g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); @@ -374,9 +413,11 @@ soup_auth_digest_compute_response (const char *method, g_checksum_update (checksum, (guchar *)":", 1); } - g_checksum_update (checksum, (guchar *)hex_a2, 32); - memcpy (response, g_checksum_get_string (checksum), sizeof (char) * 33); + g_checksum_update (checksum, (guchar *)hex_a2, strlen (hex_a2)); + response = g_strdup (g_checksum_get_string (checksum)); g_checksum_free (checksum); + g_free (hex_a2); + return response; } static void @@ -416,7 +457,7 @@ soup_auth_digest_get_authorization (SoupAuth *auth, SoupMessage *msg) { SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); - char response[33], *token; + char *response, *token; char *url, *algorithm; GString *out; GUri *uri; @@ -425,10 +466,10 @@ soup_auth_digest_get_authorization (SoupAuth *auth, SoupMessage *msg) g_return_val_if_fail (uri != NULL, NULL); url = soup_uri_get_path_and_query (uri); - soup_auth_digest_compute_response (soup_message_get_method (msg), url, priv->hex_a1, - priv->qop, priv->nonce, - priv->cnonce, priv->nc, - response); + response = soup_auth_digest_compute_response (priv->algorithm, + soup_message_get_method (msg), url, priv->hex_a1, + priv->qop, priv->nonce, + priv->cnonce, priv->nc); out = g_string_new ("Digest "); diff --git a/libsoup/server/soup-auth-domain-digest.c b/libsoup/server/soup-auth-domain-digest.c index 4011babf..acc8607c 100644 --- a/libsoup/server/soup-auth-domain-digest.c +++ b/libsoup/server/soup-auth-domain-digest.c @@ -209,8 +209,9 @@ check_hex_urp (SoupAuthDomain *domain, { const char *uri, *qop, *realm, *msg_username; const char *nonce, *nc, *cnonce, *response; - char hex_a1[33], computed_response[33]; + char *hex_a1, *computed_response; int nonce_count; + gboolean ret; GUri *dig_uri, *req_uri; msg_username = g_hash_table_lookup (params, "username"); @@ -272,16 +273,21 @@ check_hex_urp (SoupAuthDomain *domain, if (!response) return FALSE; - soup_auth_digest_compute_hex_a1 (hex_urp, - SOUP_AUTH_DIGEST_ALGORITHM_MD5, - nonce, cnonce, hex_a1); - soup_auth_digest_compute_response (soup_server_message_get_method (msg), - uri, - hex_a1, - SOUP_AUTH_DIGEST_QOP_AUTH, - nonce, cnonce, nonce_count, - computed_response); - return strcmp (response, computed_response) == 0; + // FIXME algo + + hex_a1 = soup_auth_digest_compute_hex_a1 (hex_urp, + SOUP_AUTH_DIGEST_ALGORITHM_MD5, + nonce, cnonce); + computed_response = soup_auth_digest_compute_response (SOUP_AUTH_DIGEST_ALGORITHM_MD5, + soup_server_message_get_method (msg), + uri, + hex_a1, + SOUP_AUTH_DIGEST_QOP_AUTH, + nonce, cnonce, nonce_count); + ret = strcmp (response, computed_response) == 0; + g_free (hex_a1); + g_free (computed_response); + return ret; } static char * @@ -374,10 +380,7 @@ soup_auth_domain_digest_encode_password (const char *username, const char *realm, const char *password) { - char hex_urp[33]; - - soup_auth_digest_compute_hex_urp (username, realm, password, hex_urp); - return g_strdup (hex_urp); + return soup_auth_digest_compute_hex_urp (SOUP_AUTH_DIGEST_ALGORITHM_MD5, username, realm, password); } static gboolean @@ -389,7 +392,7 @@ soup_auth_domain_digest_check_password (SoupAuthDomain *domain, const char *header; GHashTable *params; const char *msg_username; - char hex_urp[33]; + char *hex_urp; gboolean accept; header = soup_message_headers_get_one_common (soup_server_message_get_request_headers (msg), @@ -407,10 +410,12 @@ soup_auth_domain_digest_check_password (SoupAuthDomain *domain, return FALSE; } - soup_auth_digest_compute_hex_urp (username, - soup_auth_domain_get_realm (domain), - password, hex_urp); + hex_urp = soup_auth_digest_compute_hex_urp (SOUP_AUTH_DIGEST_ALGORITHM_MD5, + username, + soup_auth_domain_get_realm (domain), + password); accept = check_hex_urp (domain, msg, params, username, hex_urp); + g_free (hex_urp); soup_header_free_param_list (params); return accept; } |