gnunet-svn
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]