mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
add support for digest auth with hashed password
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
Sat Jul 14 11:03:37 CEST 2018
|
||||
Integrate patch for checking digest authentication based on
|
||||
a digest, allowing servers to store passwords only hashed.
|
||||
Adding new function MHD_digest_auth_check_digest(). -CG/FIXME: ack co-author!
|
||||
|
||||
Sat Mar 10 12:15:35 CET 2018
|
||||
Upgrade to gettext-0.19.8.1. Switching to more canonical
|
||||
gettext integration. -CG
|
||||
|
||||
@@ -2393,6 +2393,21 @@ most probably it will be the result of a lookup of the username against a local
|
||||
Most of the time it is sound to specify 300 seconds as its values.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int MHD_digest_auth_check_digest (struct MHD_Connection *connection, const char *realm, const char *username, const unsigned char digest[MHD_MD5_DIGEST_SIZE], unsigned int nonce_timeout)
|
||||
Checks if the provided values in the WWW-Authenticate header are valid
|
||||
and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}.
|
||||
|
||||
@var{realm} must reference to a zero-terminated string representing the realm.
|
||||
|
||||
@var{username} must reference to a zero-terminated string representing the username,
|
||||
it is usually the returned value from MHD_digest_auth_get_username.
|
||||
|
||||
@var{digest} pointer to the binary MD5 sum for the precalculated hash value ``userame:realm:password'' of @code{MHD_MD5_DIGEST_SIZE} bytes.
|
||||
|
||||
@var{nonce_timeout} is the amount of time in seconds for a nonce to be invalid.
|
||||
Most of the time it is sound to specify 300 seconds as its values.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int MHD_queue_auth_fail_response (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
|
||||
Queues a response to request authentication from the client,
|
||||
return @code{MHD_YES} if successful, otherwise @code{MHD_NO}.
|
||||
|
||||
@@ -293,6 +293,12 @@ _MHD_DEPR_MACRO("Macro MHD_LONG_LONG_PRINTF is deprecated, use MHD_UNSIGNED_LONG
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Length of the binary output of the MD5 hash function.
|
||||
*/
|
||||
#define MHD_MD5_DIGEST_SIZE 16
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup httpcode HTTP response codes.
|
||||
* These are the status codes defined for HTTP responses.
|
||||
@@ -3144,10 +3150,32 @@ MHD_free (void *ptr);
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout);
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout);
|
||||
|
||||
/**
|
||||
* Authenticates the authorization header sent by the client
|
||||
*
|
||||
* @param connection The MHD connection structure
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param digest An `unsigned char *' pointer to the binary MD5 sum
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of #MHD_MD5_DIGEST_SIZE bytes
|
||||
* @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
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check_digest (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t digest[MHD_MD5_DIGEST_SIZE],
|
||||
unsigned int nonce_timeout);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+163
-50
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of libmicrohttpd
|
||||
Copyright (C) 2010, 2011, 2012, 2015 Daniel Pittman and Christian Grothoff
|
||||
Copyright (C) 2010, 2011, 2012, 2015, 2018 Daniel Pittman and Christian Grothoff
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <windows.h>
|
||||
#endif /* MHD_W32_MUTEX_ */
|
||||
|
||||
#define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE)
|
||||
#define HASH_MD5_HEX_LEN (2 * MHD_MD5_DIGEST_SIZE)
|
||||
/* 32 bit value is 4 bytes */
|
||||
#define TIMESTAMP_BIN_SIZE 4
|
||||
#define TIMESTAMP_HEX_LEN (2 * TIMESTAMP_BIN_SIZE)
|
||||
@@ -93,8 +93,65 @@ cvthex (const unsigned char *bin,
|
||||
|
||||
|
||||
/**
|
||||
* calculate H(A1) as per RFC2617 spec and store the
|
||||
* result in 'sessionkey'.
|
||||
* calculate H(A1) from given hash as per RFC2617 spec
|
||||
* and store the * result in 'sessionkey'.
|
||||
*
|
||||
* @param alg The hash algorithm used, can be "md5" or "md5-sess"
|
||||
* @param digest An `unsigned char *' pointer to the binary MD5 sum
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of #MHD_MD5_DIGEST_SIZE bytes
|
||||
* @param nonce A `char *' pointer to the nonce value
|
||||
* @param cnonce A `char *' pointer to the cnonce value
|
||||
* @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
|
||||
*/
|
||||
static void
|
||||
digest_calc_ha1_from_digest (const char *alg,
|
||||
const uint8_t digest[MHD_MD5_DIGEST_SIZE],
|
||||
const char *nonce,
|
||||
const char *cnonce,
|
||||
char sessionkey[HASH_MD5_HEX_LEN + 1])
|
||||
{
|
||||
struct MD5Context md5;
|
||||
|
||||
if (MHD_str_equal_caseless_(alg,
|
||||
"md5-sess"))
|
||||
{
|
||||
unsigned char ha1[MHD_MD5_DIGEST_SIZE];
|
||||
|
||||
MD5Init (&md5);
|
||||
MD5Update (&md5,
|
||||
digest,
|
||||
MHD_MD5_DIGEST_SIZE);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) ":",
|
||||
1);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) nonce,
|
||||
strlen (nonce));
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) ":",
|
||||
1);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) cnonce,
|
||||
strlen (cnonce));
|
||||
MD5Final (ha1,
|
||||
&md5);
|
||||
cvthex (ha1,
|
||||
sizeof (ha1),
|
||||
sessionkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvthex (digest,
|
||||
MHD_MD5_DIGEST_SIZE,
|
||||
sessionkey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* calculate H(A1) from username, realm and password as per RFC2617 spec
|
||||
* and store the result in 'sessionkey'.
|
||||
*
|
||||
* @param alg The hash algorithm used, can be "md5" or "md5-sess"
|
||||
* @param username A `char *' pointer to the username value
|
||||
@@ -105,16 +162,16 @@ cvthex (const unsigned char *bin,
|
||||
* @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
|
||||
*/
|
||||
static void
|
||||
digest_calc_ha1 (const char *alg,
|
||||
const char *username,
|
||||
const char *realm,
|
||||
const char *password,
|
||||
const char *nonce,
|
||||
const char *cnonce,
|
||||
char sessionkey[HASH_MD5_HEX_LEN + 1])
|
||||
digest_calc_ha1_from_user (const char *alg,
|
||||
const char *username,
|
||||
const char *realm,
|
||||
const char *password,
|
||||
const char *nonce,
|
||||
const char *cnonce,
|
||||
char sessionkey[HASH_MD5_HEX_LEN + 1])
|
||||
{
|
||||
struct MD5Context md5;
|
||||
unsigned char ha1[MD5_DIGEST_SIZE];
|
||||
unsigned char ha1[MHD_MD5_DIGEST_SIZE];
|
||||
|
||||
MD5Init (&md5);
|
||||
MD5Update (&md5,
|
||||
@@ -134,31 +191,11 @@ digest_calc_ha1 (const char *alg,
|
||||
strlen (password));
|
||||
MD5Final (ha1,
|
||||
&md5);
|
||||
if (MHD_str_equal_caseless_(alg,
|
||||
"md5-sess"))
|
||||
{
|
||||
MD5Init (&md5);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) ha1,
|
||||
sizeof (ha1));
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) ":",
|
||||
1);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) nonce,
|
||||
strlen (nonce));
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) ":",
|
||||
1);
|
||||
MD5Update (&md5,
|
||||
(const unsigned char *) cnonce,
|
||||
strlen (cnonce));
|
||||
MD5Final (ha1,
|
||||
&md5);
|
||||
}
|
||||
cvthex (ha1,
|
||||
sizeof (ha1),
|
||||
sessionkey);
|
||||
digest_calc_ha1_from_digest(alg,
|
||||
ha1,
|
||||
nonce,
|
||||
cnonce,
|
||||
sessionkey);
|
||||
}
|
||||
|
||||
|
||||
@@ -187,8 +224,8 @@ digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 1],
|
||||
char response[HASH_MD5_HEX_LEN + 1])
|
||||
{
|
||||
struct MD5Context md5;
|
||||
unsigned char ha2[MD5_DIGEST_SIZE];
|
||||
unsigned char resphash[MD5_DIGEST_SIZE];
|
||||
unsigned char ha2[MHD_MD5_DIGEST_SIZE];
|
||||
unsigned char resphash[MHD_MD5_DIGEST_SIZE];
|
||||
char ha2hex[HASH_MD5_HEX_LEN + 1];
|
||||
(void)hentity; /* Unused. Silent compiler warning. */
|
||||
|
||||
@@ -220,7 +257,7 @@ digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 1],
|
||||
MD5Final (ha2,
|
||||
&md5);
|
||||
cvthex (ha2,
|
||||
MD5_DIGEST_SIZE,
|
||||
MHD_MD5_DIGEST_SIZE,
|
||||
ha2hex);
|
||||
MD5Init (&md5);
|
||||
/* calculate response */
|
||||
@@ -518,7 +555,7 @@ calculate_nonce (uint32_t nonce_time,
|
||||
{
|
||||
struct MD5Context md5;
|
||||
unsigned char timestamp[TIMESTAMP_BIN_SIZE];
|
||||
unsigned char tmpnonce[MD5_DIGEST_SIZE];
|
||||
unsigned char tmpnonce[MHD_MD5_DIGEST_SIZE];
|
||||
char timestamphex[TIMESTAMP_HEX_LEN + 1];
|
||||
|
||||
MD5Init (&md5);
|
||||
@@ -667,17 +704,21 @@ check_argument_match (struct MHD_Connection *connection,
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param password The password used in the authentication
|
||||
* @param digest An optional `unsigned char *' pointer to the binary MD5 sum
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of #MHD_MD5_DIGEST_SIZE bytes
|
||||
* @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
|
||||
* @ingroup authentication
|
||||
*/
|
||||
int
|
||||
MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
static int
|
||||
digest_auth_check_all (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const uint8_t digest[MHD_MD5_DIGEST_SIZE],
|
||||
unsigned int nonce_timeout)
|
||||
{
|
||||
struct MHD_Daemon *daemon = connection->daemon;
|
||||
@@ -871,13 +912,24 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
digest_calc_ha1 ("md5",
|
||||
username,
|
||||
realm,
|
||||
password,
|
||||
nonce,
|
||||
cnonce,
|
||||
ha1);
|
||||
if (NULL != digest)
|
||||
{
|
||||
digest_calc_ha1_from_digest ("md5",
|
||||
digest,
|
||||
nonce,
|
||||
cnonce,
|
||||
ha1);
|
||||
}
|
||||
else
|
||||
{
|
||||
digest_calc_ha1_from_user ("md5",
|
||||
username,
|
||||
realm,
|
||||
password,
|
||||
nonce,
|
||||
cnonce,
|
||||
ha1);
|
||||
}
|
||||
digest_calc_response (ha1,
|
||||
nonce,
|
||||
nc,
|
||||
@@ -888,6 +940,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
hentity,
|
||||
respexp);
|
||||
|
||||
|
||||
/* Need to unescape URI before comparing with connection->url */
|
||||
daemon->unescape_callback (daemon->unescape_callback_cls,
|
||||
connection,
|
||||
@@ -933,6 +986,66 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Authenticates the authorization header sent by the client
|
||||
*
|
||||
* @param connection The MHD connection structure
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param password The password used in the authentication
|
||||
* @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
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned int nonce_timeout)
|
||||
{
|
||||
return digest_auth_check_all(connection,
|
||||
realm,
|
||||
username,
|
||||
password,
|
||||
NULL,
|
||||
nonce_timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Authenticates the authorization header sent by the client
|
||||
*
|
||||
* @param connection The MHD connection structure
|
||||
* @param realm The realm presented to the client
|
||||
* @param username The username needs to be authenticated
|
||||
* @param digest An `unsigned char *' pointer to the binary MD5 sum
|
||||
* for the precalculated hash value "username:realm:password"
|
||||
* of #MHD_MD5_DIGEST_SIZE bytes
|
||||
* @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
|
||||
* @ingroup authentication
|
||||
*/
|
||||
_MHD_EXTERN int
|
||||
MHD_digest_auth_check_digest (struct MHD_Connection *connection,
|
||||
const char *realm,
|
||||
const char *username,
|
||||
const uint8_t digest[MD5_DIGEST_SIZE],
|
||||
unsigned int nonce_timeout)
|
||||
{
|
||||
return digest_auth_check_all (connection,
|
||||
realm,
|
||||
username,
|
||||
NULL,
|
||||
digest,
|
||||
nonce_timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Queues a response to request authentication from the client
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user