gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] branch master updated (b1fff186 -> 435cd008)


From: gnunet
Subject: [libmicrohttpd] branch master updated (b1fff186 -> 435cd008)
Date: Sat, 28 May 2022 18:56:32 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from b1fff186 I'm trying to use libmicrohttpd on a platform where fcntl(fd, 
O_NONBLOCK) doesn't work for sockets. This shouldn't be a problem, as far as I 
understand, except in epoll mode, which I'm not using, because epoll() isn't 
available either.
     new 223013b2 Created basicauth.h header
     new efaa0a62 Created digestauth.h header
     new 664d8ca9 MHD_str_unquote(): added new internal function
     new 4a4d659b connection_alloc_memory_(): made function non-static
     new d73c6d20 digestauth: reworked support for multiple digest algorithms
     new 435cd008 test_basicauth: added new test

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/microhttpd/Makefile.am                         |   4 +-
 src/microhttpd/basicauth.c                         |  14 +-
 src/microhttpd/basicauth.h                         |  38 ++
 src/microhttpd/connection.c                        |  18 +-
 src/microhttpd/connection.h                        |  14 +
 src/microhttpd/digestauth.c                        | 658 ++++++++++++---------
 src/microhttpd/digestauth.h                        |  38 ++
 src/microhttpd/md5.c                               |  16 +-
 src/microhttpd/md5.h                               |  12 +-
 src/microhttpd/mhd_str.c                           |  25 +
 src/microhttpd/mhd_str.h                           |  19 +
 src/microhttpd/sha256.c                            |  17 +-
 src/microhttpd/sha256.h                            |  14 +-
 src/microhttpd/test_sha256.c                       |  18 +-
 src/testcurl/Makefile.am                           |   8 +
 .../{test_digestauth.c => test_basicauth.c}        | 401 ++++++++-----
 w32/common/libmicrohttpd-files.vcxproj             |   2 +
 w32/common/libmicrohttpd-filters.vcxproj           |   6 +
 18 files changed, 854 insertions(+), 468 deletions(-)
 create mode 100644 src/microhttpd/basicauth.h
 create mode 100644 src/microhttpd/digestauth.h
 copy src/testcurl/{test_digestauth.c => test_basicauth.c} (60%)

diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 8db55a9a..20e29c66 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -163,7 +163,7 @@ endif
 
 if ENABLE_DAUTH
 libmicrohttpd_la_SOURCES += \
-  digestauth.c \
+  digestauth.c digestauth.h \
   mhd_bithelpers.h mhd_byteorder.h mhd_align.h \
   md5.c md5.h \
   sha256.c sha256.h
@@ -171,7 +171,7 @@ endif
 
 if ENABLE_BAUTH
 libmicrohttpd_la_SOURCES += \
-  basicauth.c \
+  basicauth.c basicauth.h \
   base64.c base64.h
 endif
 
diff --git a/src/microhttpd/basicauth.c b/src/microhttpd/basicauth.c
index b739652e..9ef26dca 100644
--- a/src/microhttpd/basicauth.c
+++ b/src/microhttpd/basicauth.c
@@ -1,6 +1,7 @@
 /*
      This file is part of libmicrohttpd
      Copyright (C) 2010, 2011, 2012 Daniel Pittman and Christian Grothoff
+     Copyright (C) 2014-2022 Evgeny Grin (Karlson2k)
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -21,18 +22,15 @@
  * @brief Implements HTTP basic authentication methods
  * @author Amr Ali
  * @author Matthieu Speder
+ * @author Karlson2k (Evgeny Grin)
  */
+#include "basicauth.h"
 #include "platform.h"
 #include "mhd_limits.h"
 #include "internal.h"
 #include "base64.h"
 #include "mhd_compat.h"
 
-/**
- * Beginning string for any valid Basic authentication header.
- */
-#define _BASIC_BASE   "Basic "
-
 
 /**
  * Get the username and password from the basic authorization header sent by 
the client
@@ -60,10 +58,10 @@ MHD_basic_auth_get_username_password (struct MHD_Connection 
*connection,
                                                  &header,
                                                  NULL)) ||
        (0 != strncmp (header,
-                      _BASIC_BASE,
-                      MHD_STATICSTR_LEN_ (_BASIC_BASE))) )
+                      _MHD_AUTH_BASIC_BASE,
+                      MHD_STATICSTR_LEN_ (_MHD_AUTH_BASIC_BASE))) )
     return NULL;
-  header += MHD_STATICSTR_LEN_ (_BASIC_BASE);
+  header += MHD_STATICSTR_LEN_ (_MHD_AUTH_BASIC_BASE);
   if (NULL == (decode = BASE64Decode (header)))
   {
 #ifdef HAVE_MESSAGES
diff --git a/src/microhttpd/basicauth.h b/src/microhttpd/basicauth.h
new file mode 100644
index 00000000..c3ba4a4b
--- /dev/null
+++ b/src/microhttpd/basicauth.h
@@ -0,0 +1,38 @@
+/*
+     This file is part of libmicrohttpd
+     Copyright (C) 2010, 2011, 2012 Daniel Pittman and Christian Grothoff
+     Copyright (C) 2014-2022 Evgeny Grin (Karlson2k)
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This library is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 
 USA
+*/
+/**
+ * @file basicauth.c
+ * @brief Implements HTTP basic authentication methods
+ * @author Amr Ali
+ * @author Matthieu Speder
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_BASICAUTH_H
+#define MHD_BASICAUTH_H 1
+
+/**
+ * Beginning string for any valid Basic authentication header.
+ */
+#define _MHD_AUTH_BASIC_BASE   "Basic "
+
+#endif /* ! MHD_BASICAUTH_H */
+
+/* end of basicauth.h */
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index a260933c..f178f44e 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -242,9 +242,9 @@ str_conn_error_ (ssize_t mhd_err_code)
  * @return pointer to allocated memory region in the pool or
  *         NULL if no memory is available
  */
-static void *
-connection_alloc_memory (struct MHD_Connection *connection,
-                         size_t size)
+void *
+MHD_connection_alloc_memory_ (struct MHD_Connection *connection,
+                              size_t size)
 {
   struct MHD_Connection *const c = connection; /* a short alias */
   struct MemoryPool *const pool = c->pool;     /* a short alias */
@@ -482,8 +482,8 @@ MHD_set_connection_value_n_nocheck_ (struct MHD_Connection 
*connection,
 {
   struct MHD_HTTP_Req_Header *pos;
 
-  pos = connection_alloc_memory (connection,
-                                 sizeof (struct MHD_HTTP_Res_Header));
+  pos = MHD_connection_alloc_memory_ (connection,
+                                      sizeof (struct MHD_HTTP_Res_Header));
   if (NULL == pos)
     return MHD_NO;
   pos->header = key;
@@ -1033,8 +1033,8 @@ try_ready_normal_body (struct MHD_Connection *connection)
     if (NULL != connection->resp_iov.iov)
       return MHD_YES;
     copy_size = response->data_iovcnt * sizeof(MHD_iovec_);
-    connection->resp_iov.iov = connection_alloc_memory (connection,
-                                                        copy_size);
+    connection->resp_iov.iov = MHD_connection_alloc_memory_ (connection,
+                                                             copy_size);
     if (NULL == connection->resp_iov.iov)
     {
       MHD_mutex_unlock_chk_ (&response->mutex);
@@ -3103,8 +3103,8 @@ parse_cookie_header (struct MHD_Connection *connection)
   if (0 == hdr_len)
     return MHD_PARSE_COOKIE_OK;
 
-  cpy = connection_alloc_memory (connection,
-                                 hdr_len + 1);
+  cpy = MHD_connection_alloc_memory_ (connection,
+                                      hdr_len + 1);
   if (NULL == cpy)
     return MHD_PARSE_COOKIE_NO_MEMORY;
 
diff --git a/src/microhttpd/connection.h b/src/microhttpd/connection.h
index 9f1a0ffb..693e26fc 100644
--- a/src/microhttpd/connection.h
+++ b/src/microhttpd/connection.h
@@ -190,4 +190,18 @@ MHD_connection_epoll_update_ (struct MHD_Connection 
*connection);
 void
 MHD_update_last_activity_ (struct MHD_Connection *connection);
 
+
+/**
+ * Allocate memory from connection's memory pool.
+ * If memory pool doesn't have enough free memory but read or write buffer
+ * have some unused memory, the size of the buffer will be reduced as needed.
+ * @param connection the connection to use
+ * @param size the size of allocated memory area
+ * @return pointer to allocated memory region in the pool or
+ *         NULL if no memory is available
+ */
+void *
+MHD_connection_alloc_memory_ (struct MHD_Connection *connection,
+                              size_t size);
+
 #endif
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index cda8b478..7ac5ad8b 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -25,6 +25,7 @@
  * @author Christian Grothoff (RFC 7616 support)
  * @author Karlson2k (Evgeny Grin)
  */
+#include "digestauth.h"
 #include "platform.h"
 #include "mhd_limits.h"
 #include "internal.h"
@@ -119,12 +120,6 @@
 #define VLA_CHECK_LEN_DIGEST(n) \
   do { if ((n) > MAX_DIGEST) MHD_PANIC (_ ("VLA too big.\n")); } while (0)
 
-
-/**
- * Beginning string for any valid Digest authentication header.
- */
-#define _BASE   "Digest "
-
 /**
  * Maximum length of a username for digest authentication.
  */
@@ -180,74 +175,261 @@ enum MHD_CheckNonceNC_
 
 
 /**
- * Context passed to functions that need to calculate
- * a digest but are orthogonal to the specific
- * algorithm.
+ * Digest context data
  */
-struct DigestAlgorithm
+union DigestCtx
 {
-  /**
-   * Size of the final digest returned by @e digest.
-   */
-  unsigned int digest_size;
+  struct MD5Context md5_ctx;
+  struct Sha256Ctx sha256_ctx;
+};
 
+/**
+ * Digest printed as hex digits.
+ */
+union DigestHex
+{
+  char md5[MD5_DIGEST_STRING_LENGTH];
+  char sha256[SHA256_DIGEST_STRING_SIZE];
+};
+
+/**
+ * Digest in binary form.
+ */
+union DigestBin
+{
+  uint8_t md5[MD5_DIGEST_SIZE];
+  uint8_t sha256[SHA256_DIGEST_SIZE];
+};
+
+/**
+ * The digest calculation structure.
+ */
+struct DigestAlgorithm
+{
   /**
    * A context for the digest algorithm, already initialized to be
    * useful for @e init, @e update and @e digest.
    */
-  void *ctx;
+  union DigestCtx ctx;
 
   /**
-   * Name of the algorithm, "MD5" or "SHA-256".
-   * @sa #_MHD_MD5_TOKEN, #_MHD_SHA256_TOKEN
+   * Digest in binary form.
    */
-  const char *alg;
-
+  union DigestBin digest;
   /**
-   * Buffer of @e digest_size * 2 + 1 bytes.
+   * The digest algorithm.
    */
-  char *sessionkey;
+  enum MHD_DigestAuthAlgorithm algo;
 
   /**
-   * Call to initialize @e ctx.
+   * Buffer for hex-print of the final digest.
    */
-  void
-  (*init)(void *ctx);
+  union DigestHex digest_hex;
+#if _DEBUG
+  bool setup; /**< The structure was set-up */
+  bool inited; /**< The calculation was initialised */
+  bool digest_calculated; /**< The digest was calculated */
+#endif /* _DEBUG */
+};
 
-  /**
-   * Feed more data into the digest function.
-   *
-   * @param ctx context to feed
-   * @param length number of bytes in @a data
-   * @param data data to add
-   */
-  void
-  (*update)(void *ctx,
-            const uint8_t *data,
-            size_t length);
 
-  /**
-   * Compute final @a digest.
-   *
-   * @param ctx context to use
-   * @param[out] digest where to write the result,
-   *        must be @e digest_length bytes long
-   */
-  void
-  (*digest)(void *ctx,
-            uint8_t *digest);
-};
+/**
+ * Return name of the algorithm as a string.
+ * @param da the digest calculation structure to identify
+ * @return the name of the @a algo as a string.
+ */
+_MHD_static_inline const char *
+digest_get_algo_name (struct DigestAlgorithm *da)
+{
+  mhd_assert (da->setup);
+  if (MHD_DIGEST_ALG_MD5 == da->algo)
+    return _MHD_MD5_TOKEN;
+  if (MHD_DIGEST_ALG_SHA256 == da->algo)
+    return _MHD_SHA256_TOKEN;
+  mhd_assert (0); /* May not happen */
+  return "";
+}
+
+
+/**
+ * Return the size of the digest.
+ * @param da the digest calculation structure to identify
+ * @return the size of the digest.
+ */
+_MHD_static_inline unsigned int
+digest_get_size (struct DigestAlgorithm *da)
+{
+  mhd_assert (da->setup);
+  if (MHD_DIGEST_ALG_MD5 == da->algo)
+    return MD5_DIGEST_SIZE;
+  if (MHD_DIGEST_ALG_SHA256 == da->algo)
+    return SHA256_DIGEST_SIZE;
+  mhd_assert (0); /* May not happen */
+  return 0;
+}
+
+
+/**
+ * Set-up the digest calculation structure.
+ * @param da the structure to set-up
+ * @param algo the algorithm to use for digest calculation
+ * @return boolean 'true' if successfully set-up,
+ *         false otherwise.
+ */
+_MHD_static_inline bool
+digest_setup (struct DigestAlgorithm *da,
+              enum MHD_DigestAuthAlgorithm algo)
+{
+#ifdef _DEBUG
+  da->setup = false;
+  da->inited = false;
+  da->digest_calculated = false;
+#endif /* _DEBUG */
+  if (MHD_DIGEST_ALG_AUTO == algo)
+    algo = MHD_DIGEST_ALG_SHA256;
+
+  if ((MHD_DIGEST_ALG_MD5 == algo) ||
+      (MHD_DIGEST_ALG_SHA256 == algo))
+  {
+    da->algo = algo;
+#ifdef _DEBUG
+    da->setup = true;
+#endif /* _DEBUG */
+    return true;
+  }
+  mhd_assert (0); /* Bad parameter */
+  return false;
+}
+
+
+/**
+ * Initialise/reset the digest calculation structure.
+ * @param da the structure to initialise/reset
+ */
+_MHD_static_inline void
+digest_init (struct DigestAlgorithm *da)
+{
+  mhd_assert (da->setup);
+#ifdef _DEBUG
+  da->digest_calculated = false;
+#endif
+  if (MHD_DIGEST_ALG_MD5 == da->algo)
+  {
+    MHD_MD5Init (&da->ctx.md5_ctx);
+#ifdef _DEBUG
+    da->inited = true;
+#endif
+  }
+  else if (MHD_DIGEST_ALG_SHA256 == da->algo)
+  {
+    MHD_SHA256_init (&da->ctx.sha256_ctx);
+#ifdef _DEBUG
+    da->inited = true;
+#endif
+  }
+  else
+  {
+#ifdef _DEBUG
+    da->inited = false;
+#endif
+    mhd_assert (0); /* Bad algorithm */
+  }
+}
+
+
+/**
+ * Feed digest calculation with more data.
+ * @param da the digest calculation
+ * @param data the data to process
+ * @param length the size of the @a data in bytes
+ */
+_MHD_static_inline void
+digest_update (struct DigestAlgorithm *da,
+               const uint8_t *data,
+               size_t length)
+{
+  mhd_assert (da->inited);
+  mhd_assert (! da->digest_calculated);
+  if (MHD_DIGEST_ALG_MD5 == da->algo)
+    MHD_MD5Update (&da->ctx.md5_ctx, data, length);
+  else if (MHD_DIGEST_ALG_SHA256 == da->algo)
+    MHD_SHA256_update (&da->ctx.sha256_ctx, data, length);
+  else
+    mhd_assert (0); /* May not happen */
+}
+
+
+/**
+ * Finally calculate hash (the digest).
+ * @param da the digest calculation
+ */
+_MHD_static_inline void
+digest_calc_hash (struct DigestAlgorithm *da)
+{
+  mhd_assert (da->inited);
+  mhd_assert (! da->digest_calculated);
+  if (MHD_DIGEST_ALG_MD5 == da->algo)
+    MHD_MD5Final (&da->ctx.md5_ctx, da->digest.md5);
+  else if (MHD_DIGEST_ALG_SHA256 == da->algo)
+    MHD_SHA256_finish (&da->ctx.sha256_ctx, da->digest.sha256);
+  else
+    mhd_assert (0); /* May not happen */
+#ifdef _DEBUG
+  da->digest_calculated = true;
+#endif
+}
+
+
+/**
+ * Get pointer to the calculated digest in binary form.
+ * @param da the digest calculation
+ * @return the pointer to the calculated digest
+ */
+_MHD_static_inline const uint8_t *
+digest_get_bin (struct DigestAlgorithm *da)
+{
+  mhd_assert (da->inited);
+  mhd_assert (da->digest_calculated);
+  mhd_assert (da->digest.md5 == da->digest.sha256);
+  return da->digest.sha256;
+}
+
+
+/**
+ * Get pointer to the buffer for the printed digest.
+ * @param da the digest calculation
+ * @return the pointer to the buffer
+ */
+_MHD_static_inline char *
+digest_get_hex_buffer (struct DigestAlgorithm *da)
+{
+  return da->digest_hex.sha256;
+}
+
+
+/**
+ * Put calculated digest to the buffer as hex digits.
+ * @param da the digest calculation
+ * @return the pointer to the calculated digest
+ */
+_MHD_static_inline void
+digest_make_hex (struct DigestAlgorithm *da)
+{
+  MHD_bin_to_hex (digest_get_bin (da),
+                  digest_get_size (da),
+                  digest_get_hex_buffer (da));
+}
 
 
 /**
  * calculate H(A1) from given hash as per RFC2617 spec
- * and store the * result in 'sessionkey'.
+ * and store the result in 'digest_hex'.
  *
  * @param alg The hash algorithm used, can be "MD5" or "MD5-sess"
  *            or "SHA-256" or "SHA-256-sess"
  *    Note that the rest of the code does not support the the "-sess" variants!
  * @param[in,out] da digest implementation, must match @a alg; the
- *          da->sessionkey will be initialized to the digest in HEX
+ *          da->digest_hex will be initialized to the digest in HEX
  * @param digest An `unsigned char *' pointer to the binary MD5 sum
  *      for the precalculated hash value "username:realm:password"
  *      of #MHD_MD5_DIGEST_SIZE or #SHA256_DIGEST_SIZE bytes
@@ -261,49 +443,43 @@ digest_calc_ha1_from_digest (const char *alg,
                              const char *nonce,
                              const char *cnonce)
 {
-  const unsigned int digest_size = da->digest_size;
+  /* TODO: disable unsupported code paths */
   if ( (MHD_str_equal_caseless_ (alg,
                                  _MHD_MD5_TOKEN _MHD_SESS_TOKEN)) ||
        (MHD_str_equal_caseless_ (alg,
                                  _MHD_SHA256_TOKEN _MHD_SESS_TOKEN)) )
   {
-    uint8_t dig[VLA_ARRAY_LEN_DIGEST (digest_size)];
-
-    VLA_CHECK_LEN_DIGEST (digest_size);
-    da->init (da->ctx);
-    da->update (da->ctx,
-                digest,
-                MHD_MD5_DIGEST_SIZE);
-    da->update (da->ctx,
-                (const unsigned char *) ":",
-                1);
-    da->update (da->ctx,
-                (const unsigned char *) nonce,
-                strlen (nonce));
-    da->update (da->ctx,
-                (const unsigned char *) ":",
-                1);
-    da->update (da->ctx,
-                (const unsigned char *) cnonce,
-                strlen (cnonce));
-    da->digest (da->ctx,
-                dig);
-    MHD_bin_to_hex (dig,
-                    digest_size,
-                    da->sessionkey);
+    digest_init (da);
+    digest_update (da,
+                   digest,
+                   digest_get_size (da));
+    digest_update (da,
+                   (const unsigned char *) ":",
+                   1);
+    digest_update (da,
+                   (const unsigned char *) nonce,
+                   strlen (nonce));
+    digest_update (da,
+                   (const unsigned char *) ":",
+                   1);
+    digest_update (da,
+                   (const unsigned char *) cnonce,
+                   strlen (cnonce));
+    digest_calc_hash (da);
+    digest_make_hex (da);
   }
   else
   {
     MHD_bin_to_hex (digest,
-                    digest_size,
-                    da->sessionkey);
+                    digest_get_size (da),
+                    digest_get_hex_buffer (da));
   }
 }
 
 
 /**
  * calculate H(A1) from username, realm and password as per RFC2617 spec
- * and store the result in 'sessionkey'.
+ * and store the result in 'digest_hex'.
  *
  * @param alg The hash algorithm used, can be "MD5" or "MD5-sess"
  *             or "SHA-256" or "SHA-256-sess"
@@ -324,30 +500,26 @@ digest_calc_ha1_from_user (const char *alg,
                            const char *cnonce,
                            struct DigestAlgorithm *da)
 {
-  unsigned char ha1[VLA_ARRAY_LEN_DIGEST (da->digest_size)];
-
-  VLA_CHECK_LEN_DIGEST (da->digest_size);
-  da->init (da->ctx);
-  da->update (da->ctx,
-              (const unsigned char *) username,
-              strlen (username));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) realm,
-              strlen (realm));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) password,
-              strlen (password));
-  da->digest (da->ctx,
-              ha1);
+  digest_init (da);
+  digest_update (da,
+                 (const unsigned char *) username,
+                 strlen (username));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) realm,
+                 strlen (realm));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) password,
+                 strlen (password));
+  digest_calc_hash (da);
   digest_calc_ha1_from_digest (alg,
                                da,
-                               ha1,
+                               digest_get_bin (da),
                                nonce,
                                cnonce);
 }
@@ -380,85 +552,78 @@ digest_calc_response (const char *ha1,
                       const char *hentity,
                       struct DigestAlgorithm *da)
 {
-  const unsigned int digest_size = da->digest_size;
-  unsigned char ha2[VLA_ARRAY_LEN_DIGEST (digest_size)];
-  unsigned char resphash[VLA_ARRAY_LEN_DIGEST (digest_size)];
   (void) hentity; /* Unused. Silence compiler warning. */
 
-  VLA_CHECK_LEN_DIGEST (digest_size);
-  da->init (da->ctx);
-  da->update (da->ctx,
-              (const unsigned char *) method,
-              strlen (method));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) uri,
-              strlen (uri));
+  /* Calculate h(a2) */
+  digest_init (da);
+  digest_update (da,
+                 (const unsigned char *) method,
+                 strlen (method));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) uri,
+                 strlen (uri));
 #if 0
   if (0 == strcasecmp (qop,
                        "auth-int"))
   {
     /* This is dead code since the rest of this module does
  not support auth-int. */
-    da->update (da->ctx,
-                ":",
-                1);
+    digest_update (da,
+                   ":",
+                   1);
     if (NULL != hentity)
       da->update (da->ctx,
                   hentity,
                   strlen (hentity));
   }
 #endif
-  da->digest (da->ctx,
-              ha2);
-  MHD_bin_to_hex (ha2,
-                  digest_size,
-                  da->sessionkey);
-  da->init (da->ctx);
+  digest_calc_hash (da);
+  digest_make_hex (da);
+
   /* calculate response */
-  da->update (da->ctx,
-              (const unsigned char *) ha1,
-              digest_size * 2);
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) nonce,
-              strlen (nonce));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
+  digest_init (da);
+  digest_update (da,
+                 (const unsigned char *) ha1,
+                 digest_get_size (da) * 2);
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) nonce,
+                 strlen (nonce));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
   if ('\0' != *qop)
   {
-    da->update (da->ctx,
-                (const unsigned char *) noncecount,
-                strlen (noncecount));
-    da->update (da->ctx,
-                (const unsigned char *) ":",
-                1);
-    da->update (da->ctx,
-                (const unsigned char *) cnonce,
-                strlen (cnonce));
-    da->update (da->ctx,
-                (const unsigned char *) ":",
-                1);
-    da->update (da->ctx,
-                (const unsigned char *) qop,
-                strlen (qop));
-    da->update (da->ctx,
-                (const unsigned char *) ":",
-                1);
+    digest_update (da,
+                   (const unsigned char *) noncecount,
+                   strlen (noncecount));
+    digest_update (da,
+                   (const unsigned char *) ":",
+                   1);
+    digest_update (da,
+                   (const unsigned char *) cnonce,
+                   strlen (cnonce));
+    digest_update (da,
+                   (const unsigned char *) ":",
+                   1);
+    digest_update (da,
+                   (const unsigned char *) qop,
+                   strlen (qop));
+    digest_update (da,
+                   (const unsigned char *) ":",
+                   1);
   }
-  da->update (da->ctx,
-              (const unsigned char *) da->sessionkey,
-              digest_size * 2);
-  da->digest (da->ctx,
-              resphash);
-  MHD_bin_to_hex (resphash,
-                  digest_size,
-                  da->sessionkey);
+  digest_update (da,
+                 (const unsigned char *) digest_get_hex_buffer (da),
+                 digest_get_size (da) * 2);
+
+  digest_calc_hash (da);
+  digest_make_hex (da);
 }
 
 
@@ -794,10 +959,10 @@ MHD_digest_auth_get_username (struct MHD_Connection 
*connection)
                                                NULL))
     return NULL;
   if (0 != strncmp (header,
-                    _BASE,
-                    MHD_STATICSTR_LEN_ (_BASE)))
+                    _MHD_AUTH_DIGEST_BASE,
+                    MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE)))
     return NULL;
-  header += MHD_STATICSTR_LEN_ (_BASE);
+  header += MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE);
   if (0 == lookup_sub_value (user,
                              sizeof (user),
                              header,
@@ -833,13 +998,8 @@ calculate_nonce (uint64_t nonce_time,
                  char *nonce)
 {
   uint8_t timestamp[TIMESTAMP_BIN_SIZE];
-  const unsigned int digest_size = da->digest_size;
-  char tmpnonce[VLA_ARRAY_LEN_DIGEST (digest_size)];
 
-  mhd_assert (0 == (digest_size % 2));
-  mhd_assert (0 != digest_size);
-  VLA_CHECK_LEN_DIGEST (digest_size);
-  da->init (da->ctx);
+  digest_init (da);
   /* If the nonce_time is milliseconds, then the same 48 bit value will repeat
    * every 8 925 years, which is more than enough to mitigate a replay attack 
*/
 #if TIMESTAMP_BIN_SIZE != 6
@@ -851,42 +1011,41 @@ calculate_nonce (uint64_t nonce_time,
   timestamp[3] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 3)));
   timestamp[4] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 4)));
   timestamp[5] = (uint8_t) (nonce_time >> (8 * (TIMESTAMP_BIN_SIZE - 1 - 5)));
-  da->update (da->ctx,
-              timestamp,
-              sizeof (timestamp));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) method,
-              strlen (method));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
+  digest_update (da,
+                 timestamp,
+                 sizeof (timestamp));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) method,
+                 strlen (method));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
   if (rnd_size > 0)
-    da->update (da->ctx,
-                (const unsigned char *) rnd,
-                rnd_size);
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) uri,
-              strlen (uri));
-  da->update (da->ctx,
-              (const unsigned char *) ":",
-              1);
-  da->update (da->ctx,
-              (const unsigned char *) realm,
-              strlen (realm));
-  da->digest (da->ctx,
-              (uint8_t *) tmpnonce);
-  MHD_bin_to_hex (tmpnonce,
-                  digest_size,
+    digest_update (da,
+                   (const unsigned char *) rnd,
+                   rnd_size);
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) uri,
+                 strlen (uri));
+  digest_update (da,
+                 (const unsigned char *) ":",
+                 1);
+  digest_update (da,
+                 (const unsigned char *) realm,
+                 strlen (realm));
+  digest_calc_hash (da);
+  MHD_bin_to_hex (digest_get_bin (da),
+                  digest_get_size (da),
                   nonce);
   MHD_bin_to_hex (timestamp,
                   sizeof (timestamp),
-                  nonce + digest_size * 2);
+                  nonce + digest_get_size (da) * 2);
 }
 
 
@@ -970,7 +1129,7 @@ calculate_add_nonce (struct MHD_Connection *const 
connection,
 {
   struct MHD_Daemon *const daemon = MHD_get_master (connection->daemon);
   struct MHD_NonceNc *nn;
-  const size_t nonce_size = NONCE_STD_LEN (da->digest_size);
+  const size_t nonce_size = NONCE_STD_LEN (digest_get_size (da));
   bool ret;
 
   mhd_assert (MAX_NONCE_LENGTH >= nonce_size);
@@ -1038,7 +1197,7 @@ calculate_add_nonce_with_retry (struct MHD_Connection 
*const connection,
      * 2. Another nonce uses the same slot, and this nonce never has been
      * used by the client and this nonce is still fresh enough.
      */
-    const size_t digest_size = da->digest_size;
+    const size_t digest_size = digest_get_size (da);
     char nonce2[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_size)) + 1];
     uint64_t timestamp2;
     if (0 == MHD_get_master (connection->daemon)->nonce_nc_size)
@@ -1221,7 +1380,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
   char nonce[MAX_NONCE_LENGTH];
   size_t nonce_len;
   char cnonce[MAX_NONCE_LENGTH];
-  const unsigned int digest_size = da->digest_size;
+  const unsigned int digest_size = digest_get_size (da);
   char ha1[VLA_ARRAY_LEN_DIGEST (digest_size) * 2 + 1];
   char qop[15]; /* auth,auth-int */
   char nc[20];
@@ -1244,10 +1403,10 @@ digest_auth_check_all (struct MHD_Connection 
*connection,
                                                NULL))
     return MHD_DAUTH_WRONG_HEADER;
   if (0 != strncmp (header,
-                    _BASE,
-                    MHD_STATICSTR_LEN_ (_BASE)))
+                    _MHD_AUTH_DIGEST_BASE,
+                    MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE)))
     return MHD_DAUTH_WRONG_HEADER;
-  header += MHD_STATICSTR_LEN_ (_BASE);
+  header += MHD_STATICSTR_LEN_ (_MHD_AUTH_DIGEST_BASE);
   left = strlen (header);
 
   if (1)
@@ -1446,8 +1605,8 @@ digest_auth_check_all (struct MHD_Connection *connection,
     }
     if (NULL != digest)
     {
-      /* This will initialize da->sessionkey (ha1) */
-      digest_calc_ha1_from_digest (da->alg,
+      /* This will initialize da->digest_hex (ha1) */
+      digest_calc_ha1_from_digest (digest_get_algo_name (da),
                                    da,
                                    digest,
                                    nonce,
@@ -1455,9 +1614,9 @@ digest_auth_check_all (struct MHD_Connection *connection,
     }
     else
     {
-      /* This will initialize da->sessionkey (ha1) */
+      /* This will initialize da->digest_hex (ha1) */
       mhd_assert (NULL != password);   /* NULL == digest => password != NULL */
-      digest_calc_ha1_from_user (da->alg,
+      digest_calc_ha1_from_user (digest_get_algo_name (da),
                                  username,
                                  realm,
                                  password,
@@ -1466,7 +1625,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
                                  da);
     }
     memcpy (ha1,
-            da->sessionkey,
+            digest_get_hex_buffer (da),
             digest_size * 2 + 1);
     /* This will initialize da->sessionkey (respexp) */
     digest_calc_response (ha1,
@@ -1521,7 +1680,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
     free (uri);
   }
   return (0 == strcmp (response,
-                       da->sessionkey))
+                       digest_get_hex_buffer (da)))
          ? MHD_DAUTH_OK
          : MHD_DAUTH_RESPONSE_WRONG;
 }
@@ -1561,55 +1720,6 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
 }
 
 
-/**
- * Setup digest authentication data structures (on the
- * stack, hence must be done inline!).  Initializes a
- * "struct DigestAlgorithm da" for algorithm @a algo.
- *
- * @param algo digest algorithm to provide
- * @param da data structure to setup
- */
-#define SETUP_DA(algo,da)                         \
-  union {                                         \
-    struct MD5Context md5;                        \
-    struct sha256_ctx sha256;                     \
-  } ctx;                                          \
-  union {                                         \
-    char md5[MD5_DIGEST_SIZE * 2 + 1];            \
-    char sha256[SHA256_DIGEST_SIZE * 2 + 1];      \
-  } skey;                                         \
-  struct DigestAlgorithm da;                      \
-                                                  \
-  do {                                            \
-    switch (algo) {                                 \
-    case MHD_DIGEST_ALG_MD5:                        \
-      da.digest_size = MD5_DIGEST_SIZE;             \
-      da.ctx = &ctx.md5;                            \
-      da.alg = _MHD_MD5_TOKEN;                               \
-      da.sessionkey = skey.md5;                     \
-      da.init = &MHD_MD5Init;                           \
-      da.update = &MHD_MD5Update;                       \
-      da.digest = &MHD_MD5Final;                        \
-      break;                                        \
-    case MHD_DIGEST_ALG_AUTO:                             \
-  /* auto == SHA256, fall-though thus intentional! */ \
-    case MHD_DIGEST_ALG_SHA256:                           \
-      da.digest_size = SHA256_DIGEST_SIZE;                \
-      da.ctx = &ctx.sha256;                               \
-      da.alg = _MHD_SHA256_TOKEN;                                 \
-      da.sessionkey = skey.sha256;                        \
-      da.init = &MHD_SHA256_init;                             \
-      da.update = &MHD_SHA256_update;                         \
-      da.digest = &MHD_SHA256_finish;                         \
-      break;                                              \
-    default:                                              \
-      da.digest_size = 0;                                 \
-      mhd_assert (false);                                 \
-      break;                                              \
-    }                                                     \
-  } while (0)
-
-
 /**
  * Authenticates the authorization header sent by the client.
  *
@@ -1632,10 +1742,11 @@ MHD_digest_auth_check3 (struct MHD_Connection 
*connection,
                         unsigned int nonce_timeout,
                         enum MHD_DigestAuthAlgorithm algo)
 {
-  SETUP_DA (algo, da);
+  struct DigestAlgorithm da;
 
   mhd_assert (NULL != password);
-  if (0 == da.digest_size)
+
+  if (! digest_setup (&da, algo))
     MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
 
   return digest_auth_check_all (connection,
@@ -1674,10 +1785,13 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection 
*connection,
                                unsigned int nonce_timeout,
                                enum MHD_DigestAuthAlgorithm algo)
 {
-  SETUP_DA (algo, da);
+  struct DigestAlgorithm da;
 
   mhd_assert (NULL != digest);
-  if ((da.digest_size != digest_size) || (0 == digest_size))
+  if (! digest_setup (&da, algo))
+    MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
+
+  if (digest_get_size (&da) != digest_size)
     MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */
 
   return digest_auth_check_all (connection,
@@ -1837,9 +1951,10 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
 {
   int ret;
   int hlen;
-  SETUP_DA (algo, da);
 
-  if (0 == da.digest_size)
+  struct DigestAlgorithm da;
+
+  if (! digest_setup (&da, algo))
     MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
 
   if (NULL == response)
@@ -1856,9 +1971,10 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
 
   if (1)
   {
-    char nonce[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (da.digest_size)) + 1];
+    char nonce[NONCE_STD_LEN (VLA_ARRAY_LEN_DIGEST (digest_get_size (&da)))
+               + 1];
 
-    VLA_CHECK_LEN_DIGEST (da.digest_size);
+    VLA_CHECK_LEN_DIGEST (digest_get_size (&da));
     if (! calculate_add_nonce_with_retry (connection, realm, &da, nonce))
     {
 #ifdef HAVE_MESSAGES
@@ -1877,7 +1993,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
                           realm,
                           nonce,
                           opaque,
-                          da.alg,
+                          digest_get_algo_name (&da),
                           signal_stale
                           ? ",stale=\"true\""
                           : "");
@@ -1902,7 +2018,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
                          realm,
                          nonce,
                          opaque,
-                         da.alg,
+                         digest_get_algo_name (&da),
                          signal_stale
                          ? ",stale=\"true\""
                          : "") == hlen)
diff --git a/src/microhttpd/digestauth.h b/src/microhttpd/digestauth.h
new file mode 100644
index 00000000..689c0487
--- /dev/null
+++ b/src/microhttpd/digestauth.h
@@ -0,0 +1,38 @@
+/*
+     This file is part of libmicrohttpd
+     Copyright (C) 2010, 2011, 2012, 2015, 2018 Daniel Pittman and Christian 
Grothoff
+     Copyright (C) 2014-2022 Evgeny Grin (Karlson2k)
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This library is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 
 USA
+*/
+/**
+ * @file digestauth.c
+ * @brief Implements HTTP digest authentication
+ * @author Amr Ali
+ * @author Matthieu Speder
+ * @author Christian Grothoff (RFC 7616 support)
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_DIGESTAUTH_H
+#define MHD_DIGESTAUTH_H 1
+/**
+ * Beginning string for any valid Digest authentication header.
+ */
+#define _MHD_AUTH_DIGEST_BASE   "Digest "
+
+#endif /* ! MHD_DIGESTAUTH_H */
+
+/* end of digestauth.h */
diff --git a/src/microhttpd/md5.c b/src/microhttpd/md5.c
index a467ccac..ada6fd31 100644
--- a/src/microhttpd/md5.c
+++ b/src/microhttpd/md5.c
@@ -37,13 +37,11 @@
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MHD_MD5Init (void *ctx_)
+MHD_MD5Init (struct MD5Context *ctx)
 {
-  struct MD5Context *ctx = ctx_;
-
   mhd_assert (ctx != NULL);
   ctx->count = 0;
   ctx->state[0] = UINT32_C (0x67452301);
@@ -61,13 +59,12 @@ MD5Transform (uint32_t state[4],
 /**
  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MHD_MD5Final (void *ctx_,
+MHD_MD5Final (struct MD5Context *ctx,
               uint8_t digest[MD5_DIGEST_SIZE])
 {
-  struct MD5Context *ctx = ctx_;
   uint64_t count_bits;
   size_t have_bytes;
 
@@ -267,16 +264,15 @@ MD5Transform (uint32_t state[4],
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  * @param input bytes to add to hash
  * @param len the number of bytes in @a data
  */
 void
-MHD_MD5Update (void *ctx_,
+MHD_MD5Update (struct MD5Context *ctx,
                const uint8_t *input,
                size_t len)
 {
-  struct MD5Context *ctx = ctx_;
   size_t have, need;
 
   mhd_assert (ctx != NULL);
diff --git a/src/microhttpd/md5.h b/src/microhttpd/md5.h
index 239cf664..bdfc031c 100644
--- a/src/microhttpd/md5.h
+++ b/src/microhttpd/md5.h
@@ -40,22 +40,22 @@ struct MD5Context
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MHD_MD5Init (void *ctx_);
+MHD_MD5Init (struct MD5Context *ctx);
 
 
 /**
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  * @param input bytes to add to hash
  * @param len the number of bytes in @a data
  */
 void
-MHD_MD5Update (void *ctx_,
+MHD_MD5Update (struct MD5Context *ctx,
                const uint8_t *input,
                size_t len);
 
@@ -63,10 +63,10 @@ MHD_MD5Update (void *ctx_,
 /**
  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
  *
- * @param ctx_ must be a `struct MD5Context *`
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MHD_MD5Final (void *ctx_,
+MHD_MD5Final (struct MD5Context *ctx,
               uint8_t digest[MD5_DIGEST_SIZE]);
 
 
diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c
index da60b18d..484de105 100644
--- a/src/microhttpd/mhd_str.c
+++ b/src/microhttpd/mhd_str.c
@@ -1375,3 +1375,28 @@ MHD_bin_to_hex (const void *bin,
   hex[i * 2] = 0;
   return i;
 }
+
+
+size_t
+MHD_str_unquote (const char *quoted,
+                 size_t quoted_len,
+                 char *result)
+{
+  size_t r;
+  size_t w;
+
+  r = 0;
+  w = 0;
+
+  while (quoted_len > r)
+  {
+    if ('\\' == quoted[r])
+    {
+      ++r;
+      if (quoted_len == r)
+        return 0; /* Last backslash is not followed by char to unescape */
+    }
+    result[w++] = quoted[r++];
+  }
+  return w;
+}
diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h
index cdf92067..851fabb7 100644
--- a/src/microhttpd/mhd_str.h
+++ b/src/microhttpd/mhd_str.h
@@ -471,4 +471,23 @@ MHD_bin_to_hex (const void *bin,
                 size_t size,
                 char *hex);
 
+/**
+ * Convert string from quoted to unquoted form as specified by
+ * RFC7230#section-3.2.6 and RFC7694#quoted.strings.
+ *
+ * @param quoted the quoted string, must NOT include leading and closing
+ *               DQUOTE chars, does not need to be zero-terminated
+ * @param size the size in chars of the @a quited string
+ * @param[out] result the pointer to the buffer to put the result, must
+ *                    be at least @a size character long. The result is NOT
+ *                    zero-terminated.
+ * @return The number of characters written to the output buffer,
+ *         zero if last backslash is not followed by any character (or
+ *         @a size is zero).
+ */
+size_t
+MHD_str_unquote (const char *quoted,
+                 size_t quoted_len,
+                 char *result);
+
 #endif /* MHD_STR_H */
diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
index 825b80b3..f62b4ba1 100644
--- a/src/microhttpd/sha256.c
+++ b/src/microhttpd/sha256.c
@@ -35,12 +35,11 @@
 /**
  * Initialise structure for SHA256 calculation.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx must be a `struct Sha256Ctx *`
  */
 void
-MHD_SHA256_init (void *ctx_)
+MHD_SHA256_init (struct Sha256Ctx *ctx)
 {
-  struct sha256_ctx *const ctx = ctx_;
   /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.3 */
   /* First thirty-two bits of the fractional parts of the square
    * roots of the first eight prime numbers: 2, 3, 5, 7, 11, 13,
@@ -306,16 +305,15 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
 /**
  * Process portion of bytes.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx_ must be a `struct Sha256Ctx *`
  * @param data bytes to add to hash
  * @param length number of bytes in @a data
  */
 void
-MHD_SHA256_update (void *ctx_,
+MHD_SHA256_update (struct Sha256Ctx *ctx,
                    const uint8_t *data,
                    size_t length)
 {
-  struct sha256_ctx *const ctx = ctx_;
   unsigned bytes_have; /**< Number of bytes in buffer */
 
   mhd_assert ((data != NULL) || (length == 0));
@@ -369,14 +367,13 @@ MHD_SHA256_update (void *ctx_,
 /**
  * Finalise SHA256 calculation, return digest.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx_ must be a `struct Sha256Ctx *`
  * @param[out] digest set to the hash, must be #SHA256_DIGEST_SIZE bytes
  */
 void
-MHD_SHA256_finish (void *ctx_,
+MHD_SHA256_finish (struct Sha256Ctx *ctx,
                    uint8_t digest[SHA256_DIGEST_SIZE])
 {
-  struct sha256_ctx *const ctx = ctx_;
   uint64_t num_bits;   /**< Number of processed bits */
   unsigned bytes_have; /**< Number of bytes in buffer */
 
@@ -448,5 +445,5 @@ MHD_SHA256_finish (void *ctx_,
   }
 
   /* Erase potentially sensitive data. */
-  memset (ctx, 0, sizeof(struct sha256_ctx));
+  memset (ctx, 0, sizeof(struct Sha256Ctx));
 }
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
index cac3cb28..8feb52fe 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -70,7 +70,7 @@
 #define SHA256_BLOCK_SIZE (SHA256_BLOCK_SIZE_BITS / 8)
 
 
-struct sha256_ctx
+struct Sha256Ctx
 {
   uint32_t H[_SHA256_DIGEST_LENGTH];    /**< Intermediate hash value / digest 
at end of calculation */
   uint8_t buffer[SHA256_BLOCK_SIZE];    /**< SHA256 input data buffer */
@@ -80,21 +80,21 @@ struct sha256_ctx
 /**
  * Initialise structure for SHA256 calculation.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx must be a `struct Sha256Ctx *`
  */
 void
-MHD_SHA256_init (void *ctx_);
+MHD_SHA256_init (struct Sha256Ctx *ctx);
 
 
 /**
  * Process portion of bytes.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx must be a `struct Sha256Ctx *`
  * @param data bytes to add to hash
  * @param length number of bytes in @a data
  */
 void
-MHD_SHA256_update (void *ctx_,
+MHD_SHA256_update (struct Sha256Ctx *ctx,
                    const uint8_t *data,
                    size_t length);
 
@@ -102,11 +102,11 @@ MHD_SHA256_update (void *ctx_,
 /**
  * Finalise SHA256 calculation, return digest.
  *
- * @param ctx_ must be a `struct sha256_ctx *`
+ * @param ctx must be a `struct Sha256Ctx *`
  * @param[out] digest set to the hash, must be #SHA256_DIGEST_SIZE bytes
  */
 void
-MHD_SHA256_finish (void *ctx_,
+MHD_SHA256_finish (struct Sha256Ctx *ctx,
                    uint8_t digest[SHA256_DIGEST_SIZE]);
 
 #endif /* MHD_SHA256_H */
diff --git a/src/microhttpd/test_sha256.c b/src/microhttpd/test_sha256.c
index 91b28af2..74061cfb 100644
--- a/src/microhttpd/test_sha256.c
+++ b/src/microhttpd/test_sha256.c
@@ -332,11 +332,11 @@ test1_str (void)
 
   for (i = 0; i < units1_num; i++)
   {
-    struct sha256_ctx ctx;
+    struct Sha256Ctx ctx;
     uint8_t digest[SHA256_DIGEST_SIZE];
 
     MHD_SHA256_init (&ctx);
-    MHD_SHA256_update (&ctx, (const uint8_t*) data_units1[i].str_l.str,
+    MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
                        data_units1[i].str_l.len);
     MHD_SHA256_finish (&ctx, digest);
     num_failed += check_result (__FUNCTION__, i, digest,
@@ -354,7 +354,7 @@ test1_bin (void)
 
   for (i = 0; i < units2_num; i++)
   {
-    struct sha256_ctx ctx;
+    struct Sha256Ctx ctx;
     uint8_t digest[SHA256_DIGEST_SIZE];
 
     MHD_SHA256_init (&ctx);
@@ -377,13 +377,15 @@ test2_str (void)
 
   for (i = 0; i < units1_num; i++)
   {
-    struct sha256_ctx ctx;
+    struct Sha256Ctx ctx;
     uint8_t digest[SHA256_DIGEST_SIZE];
     size_t part_s = data_units1[i].str_l.len / 4;
 
     MHD_SHA256_init (&ctx);
-    MHD_SHA256_update (&ctx, (const uint8_t*) data_units1[i].str_l.str, 
part_s);
-    MHD_SHA256_update (&ctx, (const uint8_t*) data_units1[i].str_l.str + 
part_s,
+    MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
+                       part_s);
+    MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str
+                       + part_s,
                        data_units1[i].str_l.len - part_s);
     MHD_SHA256_finish (&ctx, digest);
     num_failed += check_result (__FUNCTION__, i, digest,
@@ -401,7 +403,7 @@ test2_bin (void)
 
   for (i = 0; i < units2_num; i++)
   {
-    struct sha256_ctx ctx;
+    struct Sha256Ctx ctx;
     uint8_t digest[SHA256_DIGEST_SIZE];
     size_t part_s = data_units2[i].bin_l.len * 2 / 3;
 
@@ -438,7 +440,7 @@ test_unaligned (void)
 
   for (offset = MAX_OFFSET; offset >= 1; --offset)
   {
-    struct sha256_ctx ctx;
+    struct Sha256Ctx ctx;
     uint8_t *unaligned_digest;
     uint8_t *unaligned_buf;
 
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index 4b0c3d1c..ed585527 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -151,6 +151,11 @@ check_PROGRAMS += \
   perf_get
 endif
 
+if ENABLE_BAUTH
+check_PROGRAMS += \
+  test_basicauth
+endif
+
 if HAVE_POSTPROCESSOR
  check_PROGRAMS += \
   test_post \
@@ -228,6 +233,9 @@ perf_get_concurrent11_CFLAGS = \
 perf_get_concurrent11_LDADD = \
   $(PTHREAD_LIBS) $(LDADD)
 
+test_basicauth_SOURCES = \
+  test_basicauth.c
+
 test_digestauth_SOURCES = \
   test_digestauth.c
 test_digestauth_LDADD = \
diff --git a/src/testcurl/test_digestauth.c b/src/testcurl/test_basicauth.c
similarity index 60%
copy from src/testcurl/test_digestauth.c
copy to src/testcurl/test_basicauth.c
index 6f22c1f2..1b84ac15 100644
--- a/src/testcurl/test_digestauth.c
+++ b/src/testcurl/test_basicauth.c
@@ -20,8 +20,8 @@
 */
 
 /**
- * @file daemontest_digestauth.c
- * @brief  Testcase for libmicrohttpd Digest Auth
+ * @file test_basicauth.c
+ * @brief  Testcase for libmicrohttpd concurrent Basic Authorisation
  * @author Amr Ali
  * @author Karlson2k (Evgeny Grin)
  */
@@ -33,11 +33,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#ifdef MHD_HTTPS_REQUIRE_GRYPT
-#ifdef HAVE_GCRYPT_H
-#include <gcrypt.h>
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GRYPT */
 
 #ifndef WINDOWS
 #include <sys/socket.h>
@@ -46,6 +41,15 @@
 #include <wincrypt.h>
 #endif
 
+#include "mhd_has_param.h"
+
+#ifndef MHD_STATICSTR_LEN_
+/**
+ * Determine length of static string / macro strings at compile time.
+ */
+#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
+#endif /* ! MHD_STATICSTR_LEN_ */
+
 #ifndef CURL_VERSION_BITS
 #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #endif /* ! CURL_VERSION_BITS */
@@ -132,6 +136,7 @@ _externalErrorExit_func (const char *errDesc, const char 
*funcName, int lineNum)
 }
 
 
+/* Not actually used in this test */
 static char libcurl_errbuf[CURL_ERROR_SIZE] = "";
 
 _MHD_NORETURN static void
@@ -184,6 +189,8 @@ _mhdErrorExit_func (const char *errDesc, const char 
*funcName, int lineNum)
 }
 
 
+#if 0
+/* Function unused in this test */
 static void
 _checkCURLE_OK_func (CURLcode code, const char *curlFunc,
                      const char *funcName, int lineNum)
@@ -213,18 +220,26 @@ _checkCURLE_OK_func (CURLcode code, const char *curlFunc,
 }
 
 
+#endif
+
+
 /* Could be increased to facilitate debugging */
-#define TIMEOUTS_VAL 5
+#define TIMEOUTS_VAL 10
 
 #define MHD_URI_BASE_PATH "/bar%20foo%3Fkey%3Dvalue"
 
+#define REALM "TestRealm"
+#define USERNAME "Aladdin"
+#define PASSWORD "open sesame"
+
+
 #define PAGE \
-  "<html><head><title>libmicrohttpd demo</title></head><body>Access 
granted</body></html>"
+  "<html><head><title>libmicrohttpd demo page</title>" \
+  "</head><body>Access granted</body></html>"
 
 #define DENIED \
-  "<html><head><title>libmicrohttpd demo</title></head><body>Access 
denied</body></html>"
-
-#define MY_OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
+  "<html><head><title>libmicrohttpd - Access denied</title>" \
+  "</head><body>Access denied</body></html>"
 
 struct CBC
 {
@@ -233,6 +248,7 @@ struct CBC
   size_t size;
 };
 
+static int verbose;
 
 static size_t
 copyBuffer (void *ptr,
@@ -262,14 +278,12 @@ ahc_echo (void *cls,
 {
   struct MHD_Response *response;
   char *username;
-  const char *password = "testpass";
-  const char *realm = "test@example.com";
+  char *password;
   enum MHD_Result ret;
-  enum MHD_DigestAuthResult ret_e;
   static int already_called_marker;
-  (void) cls; (void) url;                         /* Unused. Silent compiler 
warning. */
+  (void) cls; (void) url;         /* Unused. Silent compiler warning. */
   (void) method; (void) version; (void) upload_data; /* Unused. Silent 
compiler warning. */
-  (void) upload_data_size; (void) req_cls;        /* Unused. Silent compiler 
warning. */
+  (void) upload_data_size;        /* Unused. Silent compiler warning. */
 
   if (&already_called_marker != *req_cls)
   { /* Called for the first time, request not fully read yet */
@@ -278,66 +292,57 @@ ahc_echo (void *cls,
     return MHD_YES;
   }
 
-  username = MHD_digest_auth_get_username (connection);
-  if ( (username == NULL) ||
-       (0 != strcmp (username, "testuser")) )
+  if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+    mhdErrorExitDesc ("Unexpected HTTP method");
+
+  /* require: USERNAME with password PASSWORD */
+  password = NULL;
+  username = MHD_basic_auth_get_username_password (connection,
+                                                   &password);
+  if (NULL != username)
   {
-    response = MHD_create_response_from_buffer_static (strlen (DENIED),
-                                                       DENIED);
+    if (0 != strcmp (username, USERNAME))
+    {
+      fprintf (stderr, "'username' does not match.\n"
+               "Expected: '%s'\tRecieved: '%s'. ", USERNAME, username);
+      mhdErrorExitDesc ("Wrong 'username'");
+    }
+    if (NULL == password)
+      mhdErrorExitDesc ("The password pointer is NULL");
+    if (0 != strcmp (password, PASSWORD))
+      fprintf (stderr, "'password' does not match.\n"
+               "Expected: '%s'\tRecieved: '%s'. ", PASSWORD, password);
+    response =
+      MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (PAGE),
+                                              (const void *) PAGE);
     if (NULL == response)
-      mhdErrorExitDesc ("MHD_create_response_from_buffer failed");
-    ret = MHD_queue_auth_fail_response2 (connection,
-                                         realm,
-                                         MY_OPAQUE,
-                                         response,
-                                         MHD_NO,
-                                         MHD_DIGEST_ALG_MD5);
+      mhdErrorExitDesc ("Response creation failed");
+    ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     if (MHD_YES != ret)
-      mhdErrorExitDesc ("MHD_queue_auth_fail_response2 failed");
-    MHD_destroy_response (response);
-    return ret;
+      mhdErrorExitDesc ("'MHD_queue_response()' failed");
   }
-  ret_e = MHD_digest_auth_check3 (connection,
-                                  realm,
-                                  username,
-                                  password,
-                                  300,
-                                  MHD_DIGEST_ALG_MD5);
-  MHD_free (username);
-  if (ret_e != MHD_DAUTH_OK)
+  else
   {
-    response = MHD_create_response_from_buffer_static (strlen (DENIED),
-                                                       DENIED);
-    if (NULL == response)
-      mhdErrorExitDesc ("MHD_create_response_from_buffer() failed");
-    ret = MHD_queue_auth_fail_response2 (connection,
-                                         realm,
-                                         MY_OPAQUE,
-                                         response,
-                                         (MHD_DAUTH_NONCE_STALE == ret_e) ?
-                                         MHD_YES : MHD_NO,
-                                         MHD_DIGEST_ALG_MD5);
-    if (MHD_YES != ret)
-      mhdErrorExitDesc ("MHD_queue_auth_fail_response2() failed");
-    MHD_destroy_response (response);
-    return ret;
+    if (NULL != password)
+      mhdErrorExitDesc ("The password pointer is NOT NULL");
+    response =
+      MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (DENIED),
+                                              (const void *) DENIED);
+    ret = MHD_queue_basic_auth_fail_response (connection, REALM,
+                                              response);
   }
-  response = MHD_create_response_from_buffer_static (strlen (PAGE),
-                                                     PAGE);
-  if (NULL == response)
-    mhdErrorExitDesc ("MHD_create_response_from_buffer() failed");
-  ret = MHD_queue_response (connection,
-                            MHD_HTTP_OK,
-                            response);
-  if (MHD_YES != ret)
-    mhdErrorExitDesc ("MHD_queue_auth_fail_response2() failed");
+
+  if (NULL != username)
+    MHD_free (username);
+  if (NULL != password)
+    MHD_free (password);
   MHD_destroy_response (response);
   return ret;
 }
 
 
 static CURL *
-setupCURL (void *cbc, int port)
+setupCURL (void *cbc, int port, char *errbuf)
 {
   CURL *c;
   char url[512];
@@ -346,7 +351,7 @@ setupCURL (void *cbc, int port)
   {
     int res;
     /* A workaround for some old libcurl versions, which ignore the specified
-     * port by CURLOPT_PORT when digest authorisation is used. */
+     * port by CURLOPT_PORT when authorisation is used. */
     res = snprintf (url, (sizeof(url) / sizeof(url[0])),
                     "http://127.0.0.1:%d%s";, port, MHD_URI_BASE_PATH);
     if ((0 >= res) || ((sizeof(url) / sizeof(url[0])) <= (size_t) res))
@@ -359,7 +364,7 @@ setupCURL (void *cbc, int port)
 
   if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)) ||
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_ERRORBUFFER,
-                                     libcurl_errbuf)) ||
+                                     errbuf)) ||
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEFUNCTION,
                                      &copyBuffer)) ||
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc)) ||
@@ -379,76 +384,174 @@ setupCURL (void *cbc, int port)
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_PORT, ((long) port))) ||
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_URL, url)))
     libcurlErrorExitDesc ("curl_easy_setopt() failed");
-  if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST)) ||
+  if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_BASIC)) ||
       (CURLE_OK != curl_easy_setopt (c, CURLOPT_USERPWD,
-                                     "testuser:testpass")))
+                                     USERNAME ":" PASSWORD)))
     libcurlErrorExitDesc ("curl_easy_setopt() authorization options failed");
   return c;
 }
 
 
-static int
-testDigestAuth ()
+static CURLcode
+performQueryExternal (struct MHD_Daemon *d, CURL *c)
+{
+  CURLM *multi;
+  time_t start;
+  struct timeval tv;
+  CURLcode ret;
+
+  ret = CURLE_FAILED_INIT; /* will be replaced with real result */
+  multi = NULL;
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    libcurlErrorExitDesc ("curl_multi_init() failed");
+  if (CURLM_OK != curl_multi_add_handle (multi, c))
+    libcurlErrorExitDesc ("curl_multi_add_handle() failed");
+
+  start = time (NULL);
+  while (time (NULL) - start <= TIMEOUTS_VAL)
+  {
+    fd_set rs;
+    fd_set ws;
+    fd_set es;
+    MHD_socket maxMhdSk;
+    int maxCurlSk;
+    int running;
+
+    maxMhdSk = MHD_INVALID_SOCKET;
+    maxCurlSk = -1;
+    FD_ZERO (&rs);
+    FD_ZERO (&ws);
+    FD_ZERO (&es);
+    if (NULL != multi)
+    {
+      curl_multi_perform (multi, &running);
+      if (0 == running)
+      {
+        struct CURLMsg *msg;
+        int msgLeft;
+        int totalMsgs = 0;
+        do
+        {
+          msg = curl_multi_info_read (multi, &msgLeft);
+          if (NULL == msg)
+            libcurlErrorExitDesc ("curl_multi_info_read() failed");
+          totalMsgs++;
+          if (CURLMSG_DONE == msg->msg)
+            ret = msg->data.result;
+        } while (msgLeft > 0);
+        if (1 != totalMsgs)
+        {
+          fprintf (stderr,
+                   "curl_multi_info_read returned wrong "
+                   "number of results (%d).\n",
+                   totalMsgs);
+          externalErrorExit ();
+        }
+        curl_multi_remove_handle (multi, c);
+        curl_multi_cleanup (multi);
+        multi = NULL;
+      }
+      else
+      {
+        if (CURLM_OK != curl_multi_fdset (multi, &rs, &ws, &es, &maxCurlSk))
+          libcurlErrorExitDesc ("curl_multi_fdset() failed");
+      }
+    }
+    if (NULL == multi)
+    { /* libcurl has finished, check whether MHD still needs to perform 
cleanup */
+      if (0 != MHD_get_timeout64s (d))
+        break; /* MHD finished as well */
+    }
+    if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxMhdSk))
+      mhdErrorExitDesc ("MHD_get_fdset() failed");
+    tv.tv_sec = 0;
+    tv.tv_usec = 200000;
+#ifdef MHD_POSIX_SOCKETS
+    if (maxMhdSk > maxCurlSk)
+      maxCurlSk = maxMhdSk;
+#endif /* MHD_POSIX_SOCKETS */
+    if (-1 == select (maxCurlSk + 1, &rs, &ws, &es, &tv))
+    {
+#ifdef MHD_POSIX_SOCKETS
+      if (EINTR != errno)
+        externalErrorExitDesc ("Unexpected select() error");
+#else
+      if ((WSAEINVAL != WSAGetLastError ()) ||
+          (0 != rs.fd_count) || (0 != ws.fd_count) || (0 != es.fd_count) )
+        externalErrorExitDesc ("Unexpected select() error");
+      Sleep (200);
+#endif
+    }
+    if (MHD_YES != MHD_run_from_select (d, &rs, &ws, &es))
+      mhdErrorExitDesc ("MHD_run_from_select() failed");
+  }
+
+  return ret;
+}
+
+
+/**
+ * Check request result
+ * @param curl_code the CURL easy return code
+ * @param pcbc the pointer struct CBC
+ * @return non-zero if success, zero if failed
+ */
+static unsigned int
+check_result (CURLcode curl_code, struct CBC *pcbc)
+{
+  if (CURLE_OK != curl_code)
+  {
+    fflush (stdout);
+    if (0 != libcurl_errbuf[0])
+      fprintf (stderr, "First request failed. "
+               "libcurl error: '%s'.\n"
+               "libcurl error description: '%s'.\n",
+               curl_easy_strerror (curl_code),
+               libcurl_errbuf);
+    else
+      fprintf (stderr, "First request failed. "
+               "libcurl error: '%s'.\n",
+               curl_easy_strerror (curl_code));
+    fflush (stderr);
+    return 0;
+  }
+
+  if (pcbc->pos != strlen (PAGE))
+  {
+    fprintf (stderr, "Got %u bytes ('%.*s'), expected %u bytes. ",
+             (unsigned) pcbc->pos, (int) pcbc->pos, pcbc->buf,
+             (unsigned) strlen (PAGE));
+    mhdErrorExitDesc ("Wrong returned data length");
+  }
+  if (0 != memcmp (PAGE, pcbc->buf, pcbc->pos))
+  {
+    fprintf (stderr, "Got invalid response '%.*s'. ",
+             (int) pcbc->pos, pcbc->buf);
+    mhdErrorExitDesc ("Wrong returned data");
+  }
+  return 1;
+}
+
+
+static unsigned int
+testBasicAuth (void)
 {
-  CURL *c;
   struct MHD_Daemon *d;
+  uint16_t port;
   struct CBC cbc;
   char buf[2048];
-  char rnd[8];
-  int port;
-#ifndef WINDOWS
-  int fd;
-  size_t len;
-  size_t off = 0;
-#endif /* ! WINDOWS */
+  CURL *c;
+  int failed = 0;
 
   if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
     port = 0;
   else
-    port = 1165;
+    port = 4210;
 
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-#ifndef WINDOWS
-  fd = open ("/dev/urandom",
-             O_RDONLY);
-  if (-1 == fd)
-    externalErrorExitDesc ("Failed to open '/dev/urandom'");
-
-  while (off < 8)
-  {
-    len = read (fd,
-                rnd + off,
-                8 - off);
-    if (len == (size_t) -1)
-      externalErrorExitDesc ("Failed to read '/dev/urandom'");
-    off += len;
-  }
-  (void) close (fd);
-#else
-  {
-    HCRYPTPROV cc;
-    BOOL b;
-
-    b = CryptAcquireContext (&cc,
-                             NULL,
-                             NULL,
-                             PROV_RSA_FULL,
-                             CRYPT_VERIFYCONTEXT);
-    if (b == 0)
-      externalErrorExitDesc ("CryptAcquireContext() failed");
-    b = CryptGenRandom (cc, 8, (BYTE *) rnd);
-    if (b == 0)
-      externalErrorExitDesc ("CryptGenRandom() failed");
-    CryptReleaseContext (cc, 0);
-  }
-#endif
-  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
+  d = MHD_start_daemon (MHD_USE_ERROR_LOG,
                         port, NULL, NULL,
-                        &ahc_echo, PAGE,
-                        MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof (rnd), rnd,
-                        MHD_OPTION_NONCE_NC_SIZE, 300,
+                        &ahc_echo, NULL,
                         MHD_OPTION_END);
   if (d == NULL)
     return 1;
@@ -461,27 +564,46 @@ testDigestAuth ()
     if ( (NULL == dinfo) ||
          (0 == dinfo->port) )
       mhdErrorExitDesc ("MHD_get_daemon_info() failed");
-    port = (int) dinfo->port;
+    port = (uint16_t) dinfo->port;
   }
-  c = setupCURL (&cbc, port);
-
-  checkCURLE_OK (curl_easy_perform (c));
 
+  /* First request */
+  cbc.buf = buf;
+  cbc.size = sizeof (buf);
+  cbc.pos = 0;
+  memset (cbc.buf, 0, cbc.size);
+  c = setupCURL (&cbc, port, libcurl_errbuf);
+  if (check_result (performQueryExternal (d, c), &cbc))
+  {
+    if (verbose)
+      printf ("First request successful.\n");
+  }
+  else
+  {
+    fprintf (stderr, "First request FAILED.\n");
+    failed = 1;
+  }
   curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen (PAGE))
+
+  /* Second request */
+  cbc.buf = buf;
+  cbc.size = sizeof (buf);
+  cbc.pos = 0;
+  memset (cbc.buf, 0, cbc.size);
+  c = setupCURL (&cbc, port, libcurl_errbuf);
+  if (check_result (performQueryExternal (d, c), &cbc))
   {
-    fprintf (stderr, "Got %u bytes ('%.*s'), expected %u bytes. ",
-             (unsigned) cbc.pos, (int) cbc.pos, cbc.buf,
-             (unsigned) strlen (MHD_URI_BASE_PATH));
-    mhdErrorExitDesc ("Wrong returned data length");
+    if (verbose)
+      printf ("Second request successful.\n");
   }
-  if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE)))
+  else
   {
-    fprintf (stderr, "Got invalid response '%.*s'. ", (int) cbc.pos, cbc.buf);
-    mhdErrorExitDesc ("Wrong returned data");
+    fprintf (stderr, "Second request FAILED.\n");
+    failed = 1;
   }
-  return 0;
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return failed ? 1 : 0;
 }
 
 
@@ -491,7 +613,12 @@ main (int argc, char *const *argv)
   unsigned int errorCount = 0;
   (void) argc; (void) argv; /* Unused. Silent compiler warning. */
 
-#ifdef MHD_HTTPS_REQUIRE_GRYPT
+  verbose = ! (has_param (argc, argv, "-q") ||
+               has_param (argc, argv, "--quiet") ||
+               has_param (argc, argv, "-s") ||
+               has_param (argc, argv, "--silent"));
+
+  #ifdef MHD_HTTPS_REQUIRE_GRYPT
 #ifdef HAVE_GCRYPT_H
   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
 #ifdef GCRYCTL_INITIALIZATION_FINISHED
@@ -501,7 +628,7 @@ main (int argc, char *const *argv)
 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
     return 2;
-  errorCount += testDigestAuth ();
+  errorCount += testBasicAuth ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);
   curl_global_cleanup ();
diff --git a/w32/common/libmicrohttpd-files.vcxproj 
b/w32/common/libmicrohttpd-files.vcxproj
index e4b6eb14..2fa2debc 100644
--- a/w32/common/libmicrohttpd-files.vcxproj
+++ b/w32/common/libmicrohttpd-files.vcxproj
@@ -32,7 +32,9 @@
     <ClInclude Include="$(MhdSrc)include\mhd_options.h" />
     <ClInclude Include="$(MhdSrc)include\platform.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\base64.h" />
+    <ClInclude Include="$(MhdSrc)microhttpd\basicauth.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\connection.h" />
+    <ClInclude Include="$(MhdSrc)microhttpd\digestauth.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\internal.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\md5.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\sha256.h" />
diff --git a/w32/common/libmicrohttpd-filters.vcxproj 
b/w32/common/libmicrohttpd-filters.vcxproj
index fd19a0b0..684f8beb 100644
--- a/w32/common/libmicrohttpd-filters.vcxproj
+++ b/w32/common/libmicrohttpd-filters.vcxproj
@@ -43,9 +43,15 @@
     <ClInclude Include="$(MhdSrc)microhttpd\base64.h">
       <Filter>Internal Headers</Filter>
     </ClInclude>
+    <ClInclude Include="$(MhdSrc)microhttpd\basicauth.h">
+      <Filter>Internal Headers</Filter>
+    </ClInclude>
     <ClInclude Include="$(MhdSrc)microhttpd\connection.h">
       <Filter>Internal Headers</Filter>
     </ClInclude>
+    <ClInclude Include="$(MhdSrc)microhttpd\digestauth.h">
+      <Filter>Internal Headers</Filter>
+    </ClInclude>
     <ClInclude Include="$(MhdSrc)microhttpd\internal.h">
       <Filter>Internal Headers</Filter>
     </ClInclude>

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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