diff options
author | Joe Orton <jorton@redhat.com> | 2022-07-04 10:18:28 +0100 |
---|---|---|
committer | Joe Orton <jorton@apache.org> | 2022-07-11 08:10:31 +0100 |
commit | 93faea82fe49bfcf22d99c0e9f954ae714315de5 (patch) | |
tree | eef64605fd048097864ae81b251126f8fe949af9 | |
parent | 9924d4d31525f8b61e37076b18004c603fd01761 (diff) | |
download | neon-git-93faea82fe49bfcf22d99c0e9f954ae714315de5.tar.gz |
Relax strictness of usernames allowed with Digest without requiring
userhash/ext-param quoting (closes #78):
* src/ne_auth.c (unsafe_username): New function.
(get_digest_h_urp): Use it, rather than ne_strparam() to
determine whether the passed username is safe to use quoted.
* test/auth.c (digest_username_star): Test for @ in usernames.
-rw-r--r-- | src/ne_auth.c | 50 | ||||
-rw-r--r-- | test/auth.c | 1 |
2 files changed, 45 insertions, 6 deletions
diff --git a/src/ne_auth.c b/src/ne_auth.c index 2a31084..9284fa4 100644 --- a/src/ne_auth.c +++ b/src/ne_auth.c @@ -885,6 +885,47 @@ static int ntlm_challenge(auth_session *sess, int attempt, } #endif /* HAVE_NTLM */ +/* Username safety lookup table; "SF" for characters which are safe to + * include in 2617-style username parameter values, else "NS" for + * non-safe characters. Determined from RFC7230§3.2.6 - everything in + * qdtext EXCEPT obs-text (which is "non-ASCII") is treated as safe to + * include in a quoted username. */ +#define SF 0 +#define NS 1 +static const signed char safe_username_table[256] = { +/* 0xXX x0 x2 x4 x6 x8 xA xC xE */ +/* 0x */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* 1x */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* 2x */ NS, SF, NS, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, +/* 3x */ SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, +/* 4x */ SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, +/* 5x */ SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, NS, SF, SF, SF, +/* 4x */ SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, +/* 7x */ SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, SF, NS, +/* 8x */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* 9x */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Ax */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Bx */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Cx */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Dx */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Ex */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, +/* Fx */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS +}; +#undef NS +#undef SF + +/* Returns non-zero if 'username' is unsafe to use without quoting. */ +static int unsafe_username(const char *username) +{ + const char *p; + int rv = 0; + + for (p = username; *p; p++) + rv |= safe_username_table[(const unsigned char)*p]; + + return rv; +} + /* Returns the H(username:realm:password) used in the Digest H(A1) * calculation. */ static char *get_digest_h_urp(auth_session *sess, ne_buffer **errmsg, @@ -911,19 +952,16 @@ static char *get_digest_h_urp(auth_session *sess, ne_buffer **errmsg, * caller has indicated the username really is UTF-8; or * else b) the challenge is an error since the username * cannot be sent safely. */ - char *esc = ne_strparam("UTF-8", NULL, (unsigned char *)sess->username); - - if (esc) { + if (unsafe_username(sess->username)) { if (parms->userhash == userhash_none || parms->handler->new_creds == NULL) { - ne_free(esc); challenge_error(errmsg, _("could not handle non-ASCII " "username in Digest challenge")); ne__strzero(password, sizeof password); return NULL; } - sess->username_star = esc; - NE_DEBUG(NE_DBG_HTTPAUTH, "auth: Using username* => %s\n", esc); + sess->username_star = ne_strparam("UTF-8", NULL, (unsigned char *)sess->username); + NE_DEBUG(NE_DBG_HTTPAUTH, "auth: Using username* => %s\n", sess->username_star); } } diff --git a/test/auth.c b/test/auth.c index c9b3c63..e985703 100644 --- a/test/auth.c +++ b/test/auth.c @@ -1030,6 +1030,7 @@ static int digest_username_star(void) const char *username_raw, *username_star; } ts[] = { { "Aladdin", NULL }, + { "aladdin@cave.example.com", NULL }, { "Ałâddín", "UTF-8''A%c5%82%c3%a2dd%c3%adn" }, { "Jäsøn Doe", "UTF-8''J%c3%a4s%c3%b8n%20Doe" }, { "foo bar", "UTF-8''foo%20bar"}, |