[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [libmicrohttpd] 01/03: add support for digest auth with has
From: |
gnunet |
Subject: |
[GNUnet-SVN] [libmicrohttpd] 01/03: add support for digest auth with hashed password |
Date: |
Sat, 14 Jul 2018 14:41:43 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository libmicrohttpd.
commit 2ed04522e24b801251d7fd1768b7fccfd7b8deac
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Jul 14 11:09:19 2018 +0200
add support for digest auth with hashed password
---
ChangeLog | 5 ++
doc/libmicrohttpd.texi | 15 ++++
src/include/microhttpd.h | 36 +++++++-
src/microhttpd/digestauth.c | 213 +++++++++++++++++++++++++++++++++-----------
4 files changed, 215 insertions(+), 54 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 8f06fb6a..1c4ddd61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index cac5dd29..e4437441 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -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
address@hidden 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}.
+
address@hidden must reference to a zero-terminated string representing the
realm.
+
address@hidden must reference to a zero-terminated string representing the
username,
+it is usually the returned value from MHD_digest_auth_get_username.
+
address@hidden pointer to the binary MD5 sum for the precalculated hash value
``userame:realm:password'' of @code{MHD_MD5_DIGEST_SIZE} bytes.
+
address@hidden 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.
address@hidden 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}.
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index cff084ed..cdbde609 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -294,6 +294,12 @@ _MHD_DEPR_MACRO("Macro MHD_LONG_LONG_PRINTF is deprecated,
use MHD_UNSIGNED_LONG
/**
+ * 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);
/**
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index b0e7ce00..0c5baffb 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -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,
@@ -934,6 +987,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
*
* @param connection The MHD connection structure
--
To stop receiving notification emails like this one, please contact
address@hidden