[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 02/04: digestauth: fixed wrong results of client data ch
From: |
gnunet |
Subject: |
[libmicrohttpd] 02/04: digestauth: fixed wrong results of client data check |
Date: |
Fri, 13 May 2022 14:19:53 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 58d1aef753d9d049354aff18c9fdf50cd738d23d
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Thu May 12 19:13:08 2022 +0300
digestauth: fixed wrong results of client data check
Stale 'nonce' from client was reported as either 'INVALID_NONCE' or just
as 'MHD_NO'. Now it is always reported as 'INVALID_NONCE".
Unfortunately wrong 'nonce' is reported as 'INVALID_NONCE' as well and
it cannot be fixed with current API.
---
src/include/microhttpd.h | 8 +--
src/microhttpd/digestauth.c | 172 +++++++++++++++++++++++++++++++-------------
2 files changed, 128 insertions(+), 52 deletions(-)
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index f209587b..b18c11a4 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -4374,7 +4374,7 @@ enum MHD_DigestAuthAlgorithm
* invalid in seconds
* @param algo digest algorithms allowed for verification
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @note Available since #MHD_VERSION 0x00096200
* @ingroup authentication
*/
@@ -4401,7 +4401,7 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @ingroup authentication
* @deprecated use MHD_digest_auth_check2()
*/
@@ -4427,7 +4427,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
* invalid in seconds
* @param algo digest algorithms allowed for verification
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @note Available since #MHD_VERSION 0x00096200
* @ingroup authentication
*/
@@ -4455,7 +4455,7 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection
*connection,
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @note Available since #MHD_VERSION 0x00096000
* @ingroup authentication
* @deprecated use #MHD_digest_auth_check_digest2()
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index a92d99ed..d870902e 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -147,6 +147,63 @@
*/
#define _MHD_SESS_TOKEN "-sess"
+
+/**
+ * The result of digest authentication of the client.
+ */
+enum MHD_DigestAuthResult
+{
+ /**
+ * Authentication OK
+ */
+ MHD_DAUTH_OK = 1,
+
+ /**
+ * General error, like "out of memory"
+ */
+ MHD_DAUTH_ERROR = 0,
+
+ /**
+ * No "Authorization" header or wrong format of the header.
+ */
+ MHD_DAUTH_WRONG_HEADER = -1,
+
+ /**
+ * Wrong 'username'.
+ */
+ MHD_DAUTH_WRONG_USERNAME = -2,
+
+ /**
+ * Wrong 'realm'.
+ */
+ MHD_DAUTH_WRONG_REALM = -3,
+
+ /**
+ * Wrong 'URI' (or URI parameters).
+ */
+ MHD_DAUTH_WRONG_URI = -4,
+
+ /* The different form of naming is intentionally used for the results below,
+ * as they are more important */
+
+ /**
+ * The 'nonce' is too old. Suggest the client to retry with the same
+ * username and password to get the fresh 'nonce'.
+ * The validity of the 'nonce' may not be checked.
+ */
+ MHD_DAUTH_NONCE_STALE = -16,
+
+ /**
+ * The 'nonce' is wrong. May indicate an attack attempt.
+ */
+ MHD_DAUTH_NONCE_WRONG = -32,
+
+ /**
+ * The 'response' is wrong. May indicate an attack attempt.
+ */
+ MHD_DAUTH_RESPONSE_WRONG = -33,
+};
+
/**
* Context passed to functions that need to calculate
* a digest but are orthogonal to the specific
@@ -1129,11 +1186,11 @@ check_argument_match (struct MHD_Connection *connection,
* (must contain "da->digest_size" bytes or be NULL)
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
- * @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * @return #MHD_DAUTH_OK if authenticated,
+ * error code otherwise.
* @ingroup authentication
*/
-static int
+static enum MHD_DigestAuthResult
digest_auth_check_all (struct MHD_Connection *connection,
struct DigestAlgorithm *da,
const char *realm,
@@ -1169,14 +1226,15 @@ digest_auth_check_all (struct MHD_Connection
*connection,
MHD_HTTP_HEADER_AUTHORIZATION),
&header,
NULL))
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
if (0 != strncmp (header,
_BASE,
MHD_STATICSTR_LEN_ (_BASE)))
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
header += MHD_STATICSTR_LEN_ (_BASE);
left = strlen (header);
+ if (1)
{
char un[MAX_USERNAME_LENGTH];
@@ -1184,13 +1242,15 @@ digest_auth_check_all (struct MHD_Connection
*connection,
sizeof (un),
header,
"username");
- if ( (0 == len) ||
- (0 != strcmp (username,
- un)) )
- return MHD_NO;
+ if (0 == len)
+ return MHD_DAUTH_WRONG_HEADER;
+ if (0 != strcmp (username,
+ un))
+ return MHD_DAUTH_WRONG_USERNAME;
left -= strlen ("username") + len;
}
+ if (1)
{
char r[MAX_REALM_LENGTH];
@@ -1198,10 +1258,11 @@ digest_auth_check_all (struct MHD_Connection
*connection,
sizeof (r),
header,
"realm");
- if ( (0 == len) ||
- (0 != strcmp (realm,
- r)) )
- return MHD_NO;
+ if (0 == len)
+ return MHD_DAUTH_WRONG_HEADER;
+ if (0 != strcmp (realm,
+ r))
+ return MHD_DAUTH_WRONG_REALM;
left -= strlen ("realm") + len;
}
@@ -1209,7 +1270,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
sizeof (nonce),
header,
"nonce")))
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
nonce_len = len;
left -= strlen ("nonce") + len;
if (left > 32 * 1024)
@@ -1221,7 +1282,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
#MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large
and would thus permit sending a >32k authorization
header value. */
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
}
if (! get_nonce_timestamp (nonce, nonce_len, &nonce_time))
{
@@ -1229,7 +1290,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
MHD_DLOG (daemon,
_ ("Authentication failed, invalid timestamp format.\n"));
#endif
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
}
t = MHD_monotonic_msec_counter ();
@@ -1241,7 +1302,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
if (TRIM_TO_TIMESTAMP (t - nonce_time) > (nonce_timeout * 1000))
{
/* too old */
- return MHD_INVALID_NONCE;
+ return MHD_DAUTH_NONCE_STALE;
}
calculate_nonce (nonce_time,
@@ -1264,7 +1325,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
if (0 != strcmp (nonce,
noncehashexp))
{
- return MHD_INVALID_NONCE;
+ return MHD_DAUTH_NONCE_WRONG;
}
if ( (0 == lookup_sub_value (cnonce,
sizeof (cnonce),
@@ -1291,7 +1352,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
MHD_DLOG (daemon,
_ ("Authentication failed, invalid format.\n"));
#endif
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
}
if (len != MHD_strx_to_uint64_n_ (nc,
len,
@@ -1301,7 +1362,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
MHD_DLOG (daemon,
_ ("Authentication failed, invalid nc format.\n"));
#endif
- return MHD_NO; /* invalid nonce format */
+ return MHD_DAUTH_WRONG_HEADER; /* invalid nonce format */
}
if (0 == nci)
{
@@ -1309,7 +1370,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
MHD_DLOG (daemon,
_ ("Authentication failed, invalid 'nc' value.\n"));
#endif
- return MHD_NO; /* invalid nc value */
+ return MHD_DAUTH_WRONG_HEADER; /* invalid nc value */
}
/*
@@ -1322,9 +1383,10 @@ digest_auth_check_all (struct MHD_Connection *connection,
nonce_len,
nci))
{
- return MHD_NO;
+ return MHD_DAUTH_NONCE_STALE;
}
+ if (1)
{
char *uri;
@@ -1335,7 +1397,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
MHD_DLOG (daemon,
_ ("Failed to allocate memory for auth header processing.\n"));
#endif /* HAVE_MESSAGES */
- return MHD_NO;
+ return MHD_DAUTH_ERROR;
}
if (0 == lookup_sub_value (uri,
left + 1,
@@ -1343,7 +1405,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
"uri"))
{
free (uri);
- return MHD_NO;
+ return MHD_DAUTH_WRONG_HEADER;
}
if (NULL != digest)
{
@@ -1396,9 +1458,10 @@ digest_auth_check_all (struct MHD_Connection *connection,
_ ("Authentication failed, URI does not match.\n"));
#endif
free (uri);
- return MHD_NO;
+ return MHD_DAUTH_WRONG_URI;
}
+ if (1)
{
const char *args = qmark;
@@ -1415,15 +1478,15 @@ digest_auth_check_all (struct MHD_Connection
*connection,
_ ("Authentication failed, arguments do not match.\n"));
#endif
free (uri);
- return MHD_NO;
+ return MHD_DAUTH_WRONG_URI;
}
}
free (uri);
- return (0 == strcmp (response,
- da->sessionkey))
- ? MHD_YES
- : MHD_NO;
}
+ return (0 == strcmp (response,
+ da->sessionkey))
+ ? MHD_DAUTH_OK
+ : MHD_DAUTH_RESPONSE_WRONG;
}
@@ -1441,7 +1504,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @ingroup authentication
*/
_MHD_EXTERN int
@@ -1520,7 +1583,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
* invalid in seconds
* @param algo digest algorithms allowed for verification
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @ingroup authentication
*/
_MHD_EXTERN int
@@ -1531,18 +1594,25 @@ MHD_digest_auth_check2 (struct MHD_Connection
*connection,
unsigned int nonce_timeout,
enum MHD_DigestAuthAlgorithm algo)
{
+ enum MHD_DigestAuthResult res;
SETUP_DA (algo, da);
mhd_assert (NULL != password);
if (0 == da.digest_size)
MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
- return digest_auth_check_all (connection,
- &da,
- realm,
- username,
- password,
- NULL,
- nonce_timeout);
+ res = digest_auth_check_all (connection,
+ &da,
+ realm,
+ username,
+ password,
+ NULL,
+ nonce_timeout);
+ if (MHD_DAUTH_OK == res)
+ return MHD_YES;
+ else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
+ return MHD_INVALID_NONCE;
+ return MHD_NO;
+
}
@@ -1560,7 +1630,7 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
* invalid in seconds
* @param algo digest algorithms allowed for verification
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @ingroup authentication
*/
_MHD_EXTERN int
@@ -1572,18 +1642,24 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection
*connection,
unsigned int nonce_timeout,
enum MHD_DigestAuthAlgorithm algo)
{
+ enum MHD_DigestAuthResult res;
SETUP_DA (algo, da);
mhd_assert (NULL != digest);
if ((da.digest_size != digest_size) || (0 == digest_size))
MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */
- return digest_auth_check_all (connection,
- &da,
- realm,
- username,
- NULL,
- digest,
- nonce_timeout);
+ res = digest_auth_check_all (connection,
+ &da,
+ realm,
+ username,
+ NULL,
+ digest,
+ nonce_timeout);
+ if (MHD_DAUTH_OK == res)
+ return MHD_YES;
+ else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
+ return MHD_INVALID_NONCE;
+ return MHD_NO;
}
@@ -1601,7 +1677,7 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection
*connection,
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
* @return #MHD_YES if authenticated, #MHD_NO if not,
- * #MHD_INVALID_NONCE if nonce is invalid
+ * #MHD_INVALID_NONCE if nonce is invalid or stale
* @ingroup authentication
*/
_MHD_EXTERN int
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.