|
|
@@ -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);
|
|
|
}
|
|
|
}
|
|
|
|