Evgeny Grin (Karlson2k) 1 год назад
Родитель
Сommit
1e424c985c

+ 66 - 65
configure.ac

@@ -5376,99 +5376,100 @@ AM_CONDITIONAL([USE_UPGRADE_TLS_TESTS], [[test "x${mhd_cv_gnutls_mthread_broken}
 
 # optional: HTTP Basic Auth support. Enabled by default
 AC_MSG_CHECKING([[whether to support HTTP Basic authentication]])
-AC_ARG_ENABLE([bauth],
-  [AS_HELP_STRING([--disable-bauth],[disable HTTP Basic Authentication support])],
+AC_ARG_ENABLE([basic-auth],
+  [AS_HELP_STRING([--disable-basic-auth],[disable HTTP Basic Authentication support])],
   [],
-  [enable_bauth="yes"]
+  [enable_basic_auth="yes"]
 )
-AS_IF([[test "x$enable_bauth" != "xno"]],
+AS_IF([[test "x$enable_basic_auth" != "xno"]],
   [
-    enable_bauth="yes"
-    AC_DEFINE([MHD_ENABLE_BAUTH],[1],[Define to '1' if libmicrohttpd should be compiled with Basic Auth support.])
+    enable_basic_auth="yes"
+    AC_DEFINE([MHD_SUPPORT_AUTH_BASIC],[1],[Define to '1' if libmicrohttpd should be compiled with Basic Auth support.])
   ]
 )
-AM_CONDITIONAL([MHD_ENABLE_BAUTH], [test "x$enable_bauth" = "xyes"])
-AC_MSG_RESULT([[$enable_bauth]])
+AM_CONDITIONAL([MHD_SUPPORT_AUTH_BASIC], [test "x$enable_basic_auth" = "xyes"])
+AC_MSG_RESULT([[$enable_basic_auth]])
 
 # optional: HTTP Digest Auth support. Enabled by default
 AC_MSG_CHECKING([[whether to support HTTP Digest authentication]])
-AC_ARG_ENABLE([dauth],
-		[AS_HELP_STRING([--disable-dauth], [disable HTTP Digest Authentication support])],
-		[enable_dauth="${enableval}"],
-		[enable_dauth="yes"])
-AS_IF([[test "x$enable_dauth" != "xno"]],
-  [ enable_dauth=yes
-    AC_DEFINE([DAUTH_SUPPORT],[1],[Define to 1 if libmicrohttpd is compiled with Digest Auth support.]) ])
-AM_CONDITIONAL([ENABLE_DAUTH], [test "x$enable_dauth" != "xno"])
-AC_MSG_RESULT([[$enable_dauth]])
-
-AS_VAR_IF([enable_dauth], ["yes"],
+AC_ARG_ENABLE([digest-auth],
+  [AS_HELP_STRING([--disable-digest-auth], [disable HTTP Digest Authentication support])],
+  [],
+  [enable_digest_auth="yes"]
+)
+AS_IF([[test "x$enable_digest_auth" != "xno"]],
+  [ enable_digest_auth=yes
+    AC_DEFINE([MHD_SUPPORT_AUTH_DIGEST],[1],[Define to 1 if libmicrohttpd is compiled with Digest Auth support.]) ])
+AM_CONDITIONAL([MHD_SUPPORT_AUTH_DIGEST], [test "x$enable_digest_auth" != "xno"])
+AC_MSG_RESULT([[$enable_digest_auth]])
+
+AS_VAR_IF([enable_digest_auth], ["yes"],
   [
     AC_MSG_CHECKING([[for Digest Authentication default nonce timeout value]])
-    AC_ARG_ENABLE([dauth-def-timeout],
-      [AS_HELP_STRING([--enable-dauth-def-timeout=NNN],
+    AC_ARG_ENABLE([digest-auth-def-timeout],
+      [AS_HELP_STRING([--enable-digest-auth-def-timeout=NNN],
                       [set default Digest Auth nonce validity time to NNN seconds])],
-      [enable_dauth_def_timeout="${enableval}"],
-      [enable_dauth_def_timeout=""]
+      [],
+      [enable_digest_auth_def_timeout=""]
     )
-    AS_VAR_IF([enable_dauth_def_timeout], ["no"],
+    AS_VAR_IF([enable_digest_auth_def_timeout], ["no"],
       [
-        AC_MSG_WARN([Default Diget Auth nonce validity time cannot be disabled, --disable-dauth-def-timeout parameter is ignored])
-        enable_dauth_def_timeout=""
+        AC_MSG_WARN([Default Diget Auth nonce validity time cannot be disabled, --disable-digest-auth-def-timeout parameter is ignored])
+        enable_digest_auth_def_timeout=""
       ]
     )
-    AS_IF([test -z "${enable_dauth_def_timeout}"],
+    AS_IF([test -z "${enable_digest_auth_def_timeout}"],
       [
-        enable_dauth_def_timeout="90"
-        enable_dauth_def_timeout_MSG="${enable_dauth_def_timeout} seconds (default)"
+        enable_digest_auth_def_timeout="90"
+        enable_dauth_def_timeout_MSG="${enable_digest_auth_def_timeout} seconds (default)"
       ],
       [
-        AS_IF([[test "x${enable_dauth_def_timeout}" = "x`echo ${enable_dauth_def_timeout}|${SED-sed} 's/[^0-9]//g'`" && \
-                test "${enable_dauth_def_timeout}" -ge "0" 2>/dev/null ]],[:],
-          [AC_MSG_ERROR([Invalid parameter --enable-dauth-def-timeout=${enable_dauth_def_timeout}. Timeout value must be a positive integer.])
+        AS_IF([[test "x${enable_digest_auth_def_timeout}" = "x`echo ${enable_digest_auth_def_timeout}|${SED-sed} 's/[^0-9]//g'`" && \
+                test "${enable_digest_auth_def_timeout}" -ge "0" 2>/dev/null ]],[:],
+          [AC_MSG_ERROR([Invalid parameter --enable-digest-auth-def-timeout=${enable_digest_auth_def_timeout}. Timeout value must be a positive integer.])
           ]
         )
         AC_COMPILE_IFELSE(
           [
             AC_LANG_PROGRAM([],
               [[
-  static int arr[((int) 2) - 4 * (int)(${enable_dauth_def_timeout} != ((unsigned int)${enable_dauth_def_timeout}))];
+  static int arr[((int) 2) - 4 * (int)(${enable_digest_auth_def_timeout} != ((unsigned int)${enable_digest_auth_def_timeout}))];
   (void) arr;
               ]]
             )
           ],
           [],
-          [AC_MSG_ERROR([The value specified by --enable-dauth-def-timeout=${enable_dauth_def_timeout} is too large.])]
+          [AC_MSG_ERROR([The value specified by --enable-digest-auth-def-timeout=${enable_digest_auth_def_timeout} is too large.])]
         )
-        enable_dauth_def_timeout_MSG="${enable_dauth_def_timeout} seconds (set by parameter)"
+        enable_dauth_def_timeout_MSG="${enable_digest_auth_def_timeout} seconds (set by parameter)"
       ]
     )
-    AC_DEFINE_UNQUOTED([MHD_DAUTH_DEF_TIMEOUT_],[${enable_dauth_def_timeout}],
+    AC_DEFINE_UNQUOTED([MHD_AUTH_DIGEST_DEF_TIMEOUT],[${enable_digest_auth_def_timeout}],
         [The default HTTP Digest Auth default nonce timeout value (in seconds)])
     AC_MSG_RESULT([[${enable_dauth_def_timeout_MSG}]])
 
     AC_MSG_CHECKING([[for Digest Authentication default maximum nc value]])
-    AC_ARG_ENABLE([dauth-def-max-nc],
-      [AS_HELP_STRING([--enable-dauth-def-max-nc=NNN],
+    AC_ARG_ENABLE([digest-auth-def-max-nc],
+      [AS_HELP_STRING([--enable-digest-auth-def-max-nc=NNN],
                       [set default Digest Auth maximum nc (nonce count) value to NNN])],
-      [enable_dauth_def_max_nc="${enableval}"],
-      [enable_dauth_def_max_nc=""]
+      [],
+      [enable_digest_auth_def_max_nc=""]
     )
-    AS_VAR_IF([enable_dauth_def_max_nc], ["no"],
+    AS_VAR_IF([enable_digest_auth_def_max_nc], ["no"],
       [
-        AC_MSG_WARN([Default Diget Auth maximum nc cannot be disabled, --disable-dauth-def-max-nc parameter is ignored])
-        enable_dauth_def_max_nc=""
+        AC_MSG_WARN([Default Diget Auth maximum nc cannot be disabled, --disable-digest-auth-def-max-nc parameter is ignored])
+        enable_digest_auth_def_max_nc=""
       ]
     )
-    AS_IF([test -z "${enable_dauth_def_max_nc}"],
+    AS_IF([test -z "${enable_digest_auth_def_max_nc}"],
       [
-        enable_dauth_def_max_nc="1000"
-        enable_dauth_def_max_nc_MSG="${enable_dauth_def_max_nc} (default)"
+        enable_digest_auth_def_max_nc="1000"
+        enable_dauth_def_max_nc_MSG="${enable_digest_auth_def_max_nc} (default)"
       ],
       [
-        AS_IF([[test "x${enable_dauth_def_max_nc}" = "x`echo ${enable_dauth_def_max_nc}|${SED-sed} 's/[^0-9]//g'`" && \
-                test "${enable_dauth_def_max_nc}" -ge "0" 2>/dev/null ]],[:],
-          [AC_MSG_ERROR([Invalid parameter --enable-dauth-def-max-nc=${enable_dauth_def_max_nc}. The value must be a positive integer.])
+        AS_IF([[test "x${enable_digest_auth_def_max_nc}" = "x`echo ${enable_digest_auth_def_max_nc}|${SED-sed} 's/[^0-9]//g'`" && \
+                test "${enable_digest_auth_def_max_nc}" -ge "0" 2>/dev/null ]],[:],
+          [AC_MSG_ERROR([Invalid parameter --enable-digest-auth-def-max-nc=${enable_digest_auth_def_max_nc}. The value must be a positive integer.])
           ]
         )
         AC_COMPILE_IFELSE(
@@ -5478,18 +5479,18 @@ AS_VAR_IF([enable_dauth], ["yes"],
 #include <stdint.h>
               ]],
               [[
-  static int arr[((int) 2) - 4 * (int)(${enable_dauth_def_max_nc} != ((uint_fast32_t)${enable_dauth_def_max_nc}))];
+  static int arr[((int) 2) - 4 * (int)(${enable_digest_auth_def_max_nc} != ((uint_fast32_t)${enable_digest_auth_def_max_nc}))];
   (void) arr;
               ]]
             )
           ],
           [],
-          [AC_MSG_ERROR([The value specified by --enable-dauth-def-max-nc=${enable_dauth_def_max_nc} is too large.])]
+          [AC_MSG_ERROR([The value specified by --enable-digest-auth-def-max-nc=${enable_digest_auth_def_max_nc} is too large.])]
         )
-        enable_dauth_def_max_nc_MSG="${enable_dauth_def_max_nc} (set by parameter)"
+        enable_dauth_def_max_nc_MSG="${enable_digest_auth_def_max_nc} (set by parameter)"
       ]
     )
-    AC_DEFINE_UNQUOTED([MHD_DAUTH_DEF_MAX_NC_],[${enable_dauth_def_max_nc}],
+    AC_DEFINE_UNQUOTED([MHD_AUTH_DIGEST_DEF_MAX_NC],[${enable_digest_auth_def_max_nc}],
         [The default HTTP Digest Auth default maximum nc (nonce count) value])
     AC_MSG_RESULT([[${enable_dauth_def_max_nc_MSG}]])
 
@@ -5500,7 +5501,7 @@ AS_VAR_IF([enable_dauth], ["yes"],
   ]
 )
 
-AM_CONDITIONAL([HAVE_ANYAUTH],[test "x$enable_bauth" != "xno" || test "x$enable_dauth" != "xno"])
+AM_CONDITIONAL([MHD_SUPPORT_AUTH],[test "x$enable_basic_auth" != "xno" || test "x$enable_digest_auth" != "xno"])
 
 # optional: HTTP "Upgrade" support. Enabled by default
 AC_MSG_CHECKING([[whether to support HTTP "Upgrade"]])
@@ -5533,7 +5534,7 @@ AC_ARG_ENABLE([[md5]],
   [
     AS_VAR_IF([enable_md5],["internal"],[enable_md5='builtin'])
     AS_VAR_IF([enable_md5],["built-in"],[enable_md5='builtin'])
-    AS_VAR_IF([enable_dauth],["yes"],[],
+    AS_VAR_IF([enable_digest_auth],["yes"],[],
       [
         AS_VAR_IF([enable_md5],["no"],[],
           [
@@ -5543,7 +5544,7 @@ AC_ARG_ENABLE([[md5]],
         )
       ]
     )
-  ], [[enable_md5="${enable_dauth}"]]
+  ], [[enable_md5="${enable_digest_auth}"]]
 )
 AS_CASE([${enable_md5}],[yes|tlslib],
   [
@@ -5655,7 +5656,7 @@ AC_ARG_ENABLE([[sha256]],
   [
     AS_VAR_IF([enable_sha256],["internal"],[enable_sha256='builtin'])
     AS_VAR_IF([enable_sha256],["built-in"],[enable_sha256='builtin'])
-    AS_VAR_IF([enable_dauth],["yes"],[],
+    AS_VAR_IF([enable_digest_auth],["yes"],[],
       [
         AS_VAR_IF([enable_sha256],["no"],[],
           [
@@ -5665,7 +5666,7 @@ AC_ARG_ENABLE([[sha256]],
         )
       ]
     )
-  ], [[enable_sha256="${enable_dauth}"]]
+  ], [[enable_sha256="${enable_digest_auth}"]]
 )
 AS_CASE([${enable_sha256}],[yes|tlslib],
   [
@@ -5777,7 +5778,7 @@ AC_ARG_ENABLE([[sha512-256]],
   [
     AS_VAR_IF([[enable_sha512_256]],[["yes"]],
       [
-        AS_VAR_IF([enable_dauth],["yes"],[],
+        AS_VAR_IF([enable_digest_auth],["yes"],[],
           [
             AC_MSG_WARN([The parameter --enable-sha512-256 is ignored as Digest Authentication is disabled])
             enable_sha512_256='no'
@@ -5785,7 +5786,7 @@ AC_ARG_ENABLE([[sha512-256]],
         )
       ],[[enable_sha512_256='no']]
     )
-  ], [[enable_sha512_256="${enable_dauth}"]]
+  ], [[enable_sha512_256="${enable_digest_auth}"]]
 )
 AC_MSG_CHECKING([[whether to support SHA-512/256]])
 AS_UNSET([enable_sha512_256_MSG])
@@ -5803,7 +5804,7 @@ AS_VAR_IF([[enable_sha512_256]],[["yes"]],
 AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
 AC_MSG_RESULT([[${enable_sha512_256_MSG}]])
 
-AS_IF([test "x$enable_dauth" != "xno"],
+AS_IF([test "x$enable_digest_auth" != "xno"],
   [
     AS_IF([test "x${enable_md5}" = "xno" &&  test "x${enable_sha256}" = "xno" && test "x${enable_sha512_256}" != "xyes"],
       [AC_MSG_ERROR([At least one hashing algorithm must be enabled if Digest Auth is enabled])]
@@ -7447,8 +7448,8 @@ AC_MSG_NOTICE([[GNU libmicrohttpd ${PACKAGE_VERSION} Configuration Summary:
   TLS backends     : ${MSG_TLS_BACKENDS}
   Cookie parser    : ${enable_cookie}
   POST parser      : ${enable_postparser}
-  Basic auth.      : ${enable_bauth}
-  Digest auth.     : ${enable_dauth}
+  Basic auth.      : ${enable_basic_auth}
+  Digest auth.     : ${enable_digest_auth}
   Digest auth. defaults: ${dauth_defs_MSG}
   MD5              : ${enable_md5_MSG}
   SHA-256          : ${enable_sha256_MSG}
@@ -7495,8 +7496,8 @@ AC_MSG_NOTICE([[
   Library licence  : ${licence_descr}
 ]])
 
-AS_IF([test "x$enable_bauth" != "xyes" || \
-   test "x$enable_dauth" != "xyes" || \
+AS_IF([test "x$enable_basic_auth" != "xyes" || \
+   test "x$enable_digest_auth" != "xyes" || \
    test "x${enable_md5}" = "xno" || \
    test "x${enable_sha256}" = "xno" || \
    test "x${enable_sha512_256}" != "xyes" || \

+ 1 - 1
doc/examples/Makefile.am

@@ -25,7 +25,7 @@ noinst_PROGRAMS = \
   logging \
   responseheaders
   
-if MHD_ENABLE_BAUTH
+if MHD_SUPPORT_AUTH_BASIC
 noinst_PROGRAMS += \
   basicauthentication
 if MHD_ENABLE_HTTPS

+ 6 - 6
src/incl_priv/mhd_sys_options.h

@@ -584,12 +584,12 @@
 #  endif /* 0 != HAVE_DECL_CPU_SETSIZE */
 #endif /* HAVE_DECL_CPU_SETSIZE */
 
-#ifndef MHD_DAUTH_DEF_TIMEOUT_
-#  define MHD_DAUTH_DEF_TIMEOUT_ 90
-#endif /* ! MHD_DAUTH_DEF_TIMEOUT_ */
-#ifndef MHD_DAUTH_DEF_MAX_NC_
-#  define MHD_DAUTH_DEF_MAX_NC_ 1000
-#endif /* ! MHD_DAUTH_DEF_MAX_NC_ */
+#ifndef MHD_AUTH_DIGEST_DEF_TIMEOUT
+#  define MHD_AUTH_DIGEST_DEF_TIMEOUT 90
+#endif /* ! MHD_AUTH_DIGEST_DEF_TIMEOUT */
+#ifndef MHD_AUTH_DIGEST_DEF_MAX_NC
+#  define MHD_AUTH_DIGEST_DEF_MAX_NC 1000
+#endif /* ! MHD_AUTH_DIGEST_DEF_MAX_NC */
 
 /* Eclipse parse compatibility */
 #ifdef __CDT_PARSER__

+ 126 - 85
src/include/microhttpd2.h

@@ -462,6 +462,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_APPLICATION_DATA_GENERATION_FINISHED = 20001
   ,
+  /**
+   * The request does not contain a particular type of Authentication
+   * credentials
+   */
+  MHD_SC_AUTH_ABSENT = 20060
+  ,
 
   /* 30000-level status codes indicate transient failures
      that might go away if the client tries again. */
@@ -555,6 +561,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_CONNECTION_POOL_NO_MEM_COOKIE = 30132
   ,
+  /**
+   * Failed to allocate memory from connection memory pool to store
+   * parsed Authentication data.
+   */
+  MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA = 30133
+  ,
   /**
    * Detected jump back of system clock
    */
@@ -753,6 +765,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_REQ_POST_PARSE_FAILED_INVALID_POST_FORMAT = 40290
   ,
+  /**
+   * The data in Auth request header has invalid format.
+   * For example, for Basic Authentication base64 decoding failed.
+   */
+  MHD_SC_REQ_AUTH_DATA_BROKEN = 40320
+  ,
   /**
    * The request cannot be processed. Sending error reply.
    */
@@ -1372,115 +1390,122 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
   /* 60000-level errors are because the application
      logic did something wrong or generated an error. */
 
+  /**
+   * The application called function too early.
+   * For example, a header value was requested before the headers
+   * had been received.
+   */
+  MHD_SC_TOO_EARLY = 60000
+  ,
+  /**
+   * The application called this function too late.
+   * For example, MHD has already started sending reply.
+   */
+  MHD_SC_TOO_LATE = 60001
+  ,
   /**
    * MHD does not support the requested combination of
    * the sockets polling syscall and the work mode.
    */
-  MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID = 60000
+  MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID = 60010
   ,
   /**
    * MHD does not support quiescing if ITC was disabled
    * and threads are used.
    */
-  MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 60001
+  MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 60011
   ,
   /**
    * MHD is closing a connection because the application
    * logic to generate the response data failed.
    */
-  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 60005
+  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 60015
   ,
   /**
    * MHD is closing a connection because the application
    * callback told it to do so.
    */
-  MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION = 60006
+  MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION = 60016
   ,
   /**
    * Application only partially processed upload and did
    * not suspend connection. This may result in a hung
    * connection.
    */
-  MHD_SC_APPLICATION_HUNG_CONNECTION = 60007
+  MHD_SC_APPLICATION_HUNG_CONNECTION = 60017
   ,
   /**
    * Application only partially processed upload and did
    * not suspend connection and the read buffer was maxxed
    * out, so MHD closed the connection.
    */
-  MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED = 60008
-  ,
-  /**
-   * Application called function too late, for example because
-   * MHD already changed state.
-   */
-  MHD_SC_TOO_LATE = 60009
+  MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED = 60018
   ,
   /**
    * Attempted to set an option that conflicts with another option
    * already set.
    */
-  MHD_SC_OPTIONS_CONFLICT = 60010
+  MHD_SC_OPTIONS_CONFLICT = 60020
   ,
   /**
    * Attempted to set an option that not recognised by MHD.
    */
-  MHD_SC_OPTION_UNKNOWN = 60011
+  MHD_SC_OPTION_UNKNOWN = 60021
   ,
   /**
    * Parameter specified unknown work mode.
    */
-  MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60012
+  MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60022
   ,
   /**
    * Parameter specified unknown socket poll syscall.
    */
-  MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60013
+  MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60023
   ,
   /**
    * The size of the provided sockaddr does not match address family.
    */
-  MHD_SC_CONFIGURATION_WRONG_SA_SIZE = 60014
+  MHD_SC_CONFIGURATION_WRONG_SA_SIZE = 60024
   ,
   /**
    * The number set by #MHD_D_O_FD_NUMBER_LIMIT is too strict to run
    * the daemon
    */
-  MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT = 60015
+  MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT = 60025
   ,
   /**
    * The number set by #MHD_D_O_GLOBAL_CONNECTION_LIMIT is too for the daemon
    * configuration
    */
-  MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60016
+  MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60026
   ,
   /**
    * The application requested an unsupported TLS backend to be used.
    */
-  MHD_SC_TLS_BACKEND_UNSUPPORTED = 60020
+  MHD_SC_TLS_BACKEND_UNSUPPORTED = 60030
   ,
   /**
    * The application attempted to setup TLS parameters before
    * enabling TLS.
    */
-  MHD_SC_TLS_BACKEND_UNINITIALIZED = 60021
+  MHD_SC_TLS_BACKEND_UNINITIALIZED = 60031
   ,
   /**
    * The application requested a TLS backend which cannot be used due
    * to missing TLS dynamic library or backend initialisation problem.
    */
-  MHD_SC_TLS_BACKEND_UNAVAILABLE = 60022
+  MHD_SC_TLS_BACKEND_UNAVAILABLE = 60032
   ,
   /**
    * Provided TLS certificate and/or private key are incorrect
    */
-  MHD_SC_TLS_CONF_BAD_CERT = 60023
+  MHD_SC_TLS_CONF_BAD_CERT = 60033
   ,
   /**
    * The application requested a daemon setting that cannot be used with
    * selected TLS backend
    */
-  MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS = 60024
+  MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS = 60034
   ,
   /**
    * The response header name has forbidden characters or token
@@ -1570,12 +1595,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
   /**
    * The requested type of information is not recognised.
    */
-  MHD_SC_INFO_TYPE_UNKNOWN = 60200
-  ,
-  /**
-   * The requested type of information is not recognised.
-   */
-  MHD_SC_INFO_GET_INFO_TYPE_UNKNOWN = 60200
+  MHD_SC_INFO_GET_TYPE_UNKNOWN = 60200
   ,
   /**
    * The information of the requested type is too large to fit into
@@ -7973,26 +7993,6 @@ MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_NONNULL_ (5);
  */
 #define MHD_INVALID_NONCE -1
 
-
-/**
- * Information decoded from Basic Authentication client's header.
- *
- * @see #MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO
- */
-struct MHD_BasicAuthInfo
-{
-  /**
-   * The username
-   */
-  struct MHD_String username;
-
-  /**
-   * The password, string pointer may be NULL if password is not encoded
-   * by the client.
-   */
-  struct MHD_StringNullable password;
-};
-
 /**
  * Add Basic Authentication "challenge" to the response.
  *
@@ -8053,6 +8053,11 @@ MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_CSTR_ (2);
  *
  * See RFC 7617, section-2 for details.
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -8061,10 +8066,6 @@ MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_CSTR_ (2);
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @param abort_if_failed if set to #MHD_NO the response will be used even if
  *                        failed to add Basic Authentication "challenge",
  *                        if not set to #MHD_NO the request will be aborted
@@ -8082,9 +8083,9 @@ MHD_FN_PAR_NONNULL_ (1)
 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
 const struct MHD_Action *
 MHD_action_basic_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
-                                 struct MHD_Response *MHD_RESTRICT response,
                                  const char *MHD_RESTRICT realm,
                                  enum MHD_Bool prefer_utf8,
+                                 struct MHD_Response *MHD_RESTRICT response,
                                  enum MHD_Bool abort_if_failed)
 {
   if ((MHD_SC_OK !=
@@ -8109,6 +8110,11 @@ MHD_STATIC_INLINE_END_
  * If the @a response object cannot be extended with the "challenge",
  * the @a response will be used to reply without the "challenge".
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -8117,10 +8123,6 @@ MHD_STATIC_INLINE_END_
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @return pointer to the action, the action must be consumed
  *         otherwise response object may leak;
  *         NULL if failed or if any action has been already created for
@@ -8129,9 +8131,9 @@ MHD_STATIC_INLINE_END_
  *         to be "destroyed"
  * @ingroup authentication
  */
-#define MHD_action_basic_auth_challenge_p(request,response,realm,prefer_utf8) \
-        MHD_action_basic_auth_challenge ((request), (response), (realm), \
-                                         (prefer_utf8), MHD_NO)
+#define MHD_action_basic_auth_challenge_p(request,realm,prefer_utf8,response) \
+        MHD_action_basic_auth_challenge ((request), (realm), (prefer_utf8), \
+                                         (response), MHD_NO)
 
 /**
  * Create action to reply with Basic Authentication "challenge".
@@ -8139,8 +8141,13 @@ MHD_STATIC_INLINE_END_
  * The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
  *
  * If the @a response object cannot be extended with the "challenge",
- * the @a response will be used to reply without the "challenge".
+ * the request will be aborted.
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -8149,10 +8156,6 @@ MHD_STATIC_INLINE_END_
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @return pointer to the action, the action must be consumed
  *         otherwise response object may leak;
  *         NULL if failed or if any action has been already created for
@@ -8161,12 +8164,32 @@ MHD_STATIC_INLINE_END_
  *         to be "destroyed"
  * @ingroup authentication
  */
-#define MHD_action_basic_auth_challenge_a(request,response,realm,prefer_utf8) \
-        MHD_action_basic_auth_challenge ((request), (response), (realm), \
-                                         (prefer_utf8), MHD_YES)
+#define MHD_action_basic_auth_challenge_a(request,realm,prefer_utf8,response) \
+        MHD_action_basic_auth_challenge ((request), (realm), (prefer_utf8), \
+                                         (response), MHD_YES)
 
 #endif /* ! MHD_NO_STATIC_INLINE */
 
+
+/**
+ * Information decoded from Basic Authentication client's header.
+ *
+ * @see #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS
+ */
+struct MHD_BasicAuthInfo
+{
+  /**
+   * The username
+   */
+  struct MHD_String username;
+
+  /**
+   * The password, string pointer may be NULL if password is not encoded
+   * by the client.
+   */
+  struct MHD_StringNullable password;
+};
+
 /* ********************** (f) Introspection ********************** */
 
 
@@ -8242,7 +8265,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed
   /**
    * Get whether HTTP Basic authorization is supported. If supported
    * then functions #MHD_action_basic_auth_required_response ()
-   * and #MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO can be used.
+   * and #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS can be used.
    * The result is placed in @a v_bool member.
    */
   MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH = 20
@@ -9664,14 +9687,13 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType
   MHD_REQUEST_INFO_DYNAMIC_DAUTH_REQ_INFO = 42
   ,
   /**
-   * Returns pointer to information about basic auth in client request.
-   * The resulting pointer is NULL if no basic auth header is set by
-   * the client or the format of the basic auth header is broken.
-   * Pointers in the returned structure (if any) are valid until response
-   * is provided for the request.
-   * The result is placed in @a v_bauth_info member.
+   * Returns information about Basic Authentication credentials in the request.
+   * Pointers in the returned structure (if any) are valid until any MHD_Action
+   * or MHD_UploadAction is provided. If the data is needed beyond this point,
+   * it should be copied.
+   * The result is placed in @a v_auth_basic_creds member.
    */
-  MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO = 51
+  MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS = 51
   ,
   /* * Sentinel * */
   /**
@@ -9713,17 +9735,17 @@ union MHD_RequestInfoDynamicData
   /**
    * The information about client provided username for digest auth
    */
-  struct MHD_DigestAuthUsernameInfo *v_dauth_username;
+  const struct MHD_DigestAuthUsernameInfo *v_dauth_username;
 
   /**
    * The information about client's digest auth
    */
-  struct MHD_DigestAuthInfo *v_dauth_info;
+  const struct MHD_DigestAuthInfo *v_dauth_info;
 
   /**
    * The information about client's basic auth
    */
-  struct MHD_BasicAuthInfo *v_bauth_info;
+  const struct MHD_BasicAuthInfo *v_auth_basic_creds;
 };
 
 
@@ -9732,6 +9754,10 @@ union MHD_RequestInfoDynamicData
  * This information may be changed during the lifetime of the request.
  * The wrapper macro #MHD_request_get_info_dynamic() could be more convenient.
  *
+ * Any pointers in the returned data are valid until any MHD_Action or
+ * MHD_UploadAction is provided. If the data is needed beyond this point,
+ * it should be copied.
+ *
  * @param request the request to get information about
  * @param info_type the type of information requested
  * @param[out] return_value pointer to union where requested information will
@@ -9739,7 +9765,22 @@ union MHD_RequestInfoDynamicData
  * @param return_value_size the size of the memory area pointed
  *                          by @a return_data, in bytes
  * @return #MHD_SC_OK if succeed,
- *         error code otherwise
+ *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a return_value_size is too small,
+ *         #MHD_SC_TOO_LATE if request is already being closed or the response
+ *                          is being sent
+ *         #MHD_SC_TOO_EARLY if requested data is not yet ready (for example,
+ *                           headers are not yet received),
+ *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is
+ *                                       not recognized by MHD,
+ *         #MHD_SC_FEATURE_DISABLED if requested functionality is not supported
+ *                                  by this MHD build,
+ *         #MHD_SC_AUTH_ABSENT if request does not have particular Auth data,
+ *         #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool
+ *                                                  has no space to put decoded
+ *                                                  authentication data,
+ *         #MHD_SC_REQ_AUTH_DATA_BROKEN if format of authentication data is
+ *                                      incorrect or broken,
+ *         other error code otherwise
  * @ingroup specialized
  */
 MHD_EXTERN_ enum MHD_StatusCode
@@ -9749,8 +9790,7 @@ MHD_request_get_info_dynamic_sz (
   union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value,
   size_t return_value_size)
 MHD_FN_PAR_NONNULL_ (1)
-MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3)
-MHD_FN_PURE_;
+MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
 
 
 /**
@@ -9766,7 +9806,8 @@ MHD_FN_PURE_;
  * @ingroup specialized
  */
 #define MHD_request_get_info_dynamic(request,info_type,return_value) \
-        MHD_request_get_info_dynamic_sz ((request), (info_type), (return_value), \
+        MHD_request_get_info_dynamic_sz ((request), (info_type), \
+                                         (return_value), \
                                          sizeof(*(return_value)))
 
 /**

+ 76 - 55
src/include/microhttpd2_main.h.in

@@ -3411,26 +3411,6 @@ MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_NONNULL_ (5);
  */
 #define MHD_INVALID_NONCE -1
 
-
-/**
- * Information decoded from Basic Authentication client's header.
- *
- * @see #MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO
- */
-struct MHD_BasicAuthInfo
-{
-  /**
-   * The username
-   */
-  struct MHD_String username;
-
-  /**
-   * The password, string pointer may be NULL if password is not encoded
-   * by the client.
-   */
-  struct MHD_StringNullable password;
-};
-
 /**
  * Add Basic Authentication "challenge" to the response.
  *
@@ -3491,6 +3471,11 @@ MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_CSTR_ (2);
  *
  * See RFC 7617, section-2 for details.
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -3499,10 +3484,6 @@ MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_CSTR_ (2);
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @param abort_if_failed if set to #MHD_NO the response will be used even if
  *                        failed to add Basic Authentication "challenge",
  *                        if not set to #MHD_NO the request will be aborted
@@ -3520,9 +3501,9 @@ MHD_FN_PAR_NONNULL_ (1)
 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
 const struct MHD_Action *
 MHD_action_basic_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
-                                 struct MHD_Response *MHD_RESTRICT response,
                                  const char *MHD_RESTRICT realm,
                                  enum MHD_Bool prefer_utf8,
+                                 struct MHD_Response *MHD_RESTRICT response,
                                  enum MHD_Bool abort_if_failed)
 {
   if ((MHD_SC_OK !=
@@ -3547,6 +3528,11 @@ MHD_STATIC_INLINE_END_
  * If the @a response object cannot be extended with the "challenge",
  * the @a response will be used to reply without the "challenge".
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -3555,10 +3541,6 @@ MHD_STATIC_INLINE_END_
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @return pointer to the action, the action must be consumed
  *         otherwise response object may leak;
  *         NULL if failed or if any action has been already created for
@@ -3567,9 +3549,9 @@ MHD_STATIC_INLINE_END_
  *         to be "destroyed"
  * @ingroup authentication
  */
-#define MHD_action_basic_auth_challenge_p(request,response,realm,prefer_utf8) \
-        MHD_action_basic_auth_challenge ((request), (response), (realm), \
-                                         (prefer_utf8), MHD_NO)
+#define MHD_action_basic_auth_challenge_p(request,realm,prefer_utf8,response) \
+        MHD_action_basic_auth_challenge ((request), (realm), (prefer_utf8), \
+                                         (response), MHD_NO)
 
 /**
  * Create action to reply with Basic Authentication "challenge".
@@ -3577,8 +3559,13 @@ MHD_STATIC_INLINE_END_
  * The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
  *
  * If the @a response object cannot be extended with the "challenge",
- * the @a response will be used to reply without the "challenge".
+ * the request will be aborted.
  *
+ * @param request the request to create the action for
+ * @param realm the realm presented to the client
+ * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
+ *                    be added, indicating for client that UTF-8 encoding
+ *                    is preferred
  * @param response the reply to send; should contain the "access denied"
  *                 body;
  *                 note: this function adds the "WWW Authenticate" header in
@@ -3587,10 +3574,6 @@ MHD_STATIC_INLINE_END_
  *                 code;
  *                 the NULL is tolerated (the result is
  *                 #MHD_action_abort_request())
- * @param realm the realm presented to the client
- * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
- *                    be added, indicating for client that UTF-8 encoding
- *                    is preferred
  * @return pointer to the action, the action must be consumed
  *         otherwise response object may leak;
  *         NULL if failed or if any action has been already created for
@@ -3599,12 +3582,32 @@ MHD_STATIC_INLINE_END_
  *         to be "destroyed"
  * @ingroup authentication
  */
-#define MHD_action_basic_auth_challenge_a(request,response,realm,prefer_utf8) \
-        MHD_action_basic_auth_challenge ((request), (response), (realm), \
-                                         (prefer_utf8), MHD_YES)
+#define MHD_action_basic_auth_challenge_a(request,realm,prefer_utf8,response) \
+        MHD_action_basic_auth_challenge ((request), (realm), (prefer_utf8), \
+                                         (response), MHD_YES)
 
 #endif /* ! MHD_NO_STATIC_INLINE */
 
+
+/**
+ * Information decoded from Basic Authentication client's header.
+ *
+ * @see #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS
+ */
+struct MHD_BasicAuthInfo
+{
+  /**
+   * The username
+   */
+  struct MHD_String username;
+
+  /**
+   * The password, string pointer may be NULL if password is not encoded
+   * by the client.
+   */
+  struct MHD_StringNullable password;
+};
+
 /* ********************** (f) Introspection ********************** */
 
 
@@ -3680,7 +3683,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed
   /**
    * Get whether HTTP Basic authorization is supported. If supported
    * then functions #MHD_action_basic_auth_required_response ()
-   * and #MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO can be used.
+   * and #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS can be used.
    * The result is placed in @a v_bool member.
    */
   MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH = 20
@@ -5102,14 +5105,13 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType
   MHD_REQUEST_INFO_DYNAMIC_DAUTH_REQ_INFO = 42
   ,
   /**
-   * Returns pointer to information about basic auth in client request.
-   * The resulting pointer is NULL if no basic auth header is set by
-   * the client or the format of the basic auth header is broken.
-   * Pointers in the returned structure (if any) are valid until response
-   * is provided for the request.
-   * The result is placed in @a v_bauth_info member.
+   * Returns information about Basic Authentication credentials in the request.
+   * Pointers in the returned structure (if any) are valid until any MHD_Action
+   * or MHD_UploadAction is provided. If the data is needed beyond this point,
+   * it should be copied.
+   * The result is placed in @a v_auth_basic_creds member.
    */
-  MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO = 51
+  MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS = 51
   ,
   /* * Sentinel * */
   /**
@@ -5151,17 +5153,17 @@ union MHD_RequestInfoDynamicData
   /**
    * The information about client provided username for digest auth
    */
-  struct MHD_DigestAuthUsernameInfo *v_dauth_username;
+  const struct MHD_DigestAuthUsernameInfo *v_dauth_username;
 
   /**
    * The information about client's digest auth
    */
-  struct MHD_DigestAuthInfo *v_dauth_info;
+  const struct MHD_DigestAuthInfo *v_dauth_info;
 
   /**
    * The information about client's basic auth
    */
-  struct MHD_BasicAuthInfo *v_bauth_info;
+  const struct MHD_BasicAuthInfo *v_auth_basic_creds;
 };
 
 
@@ -5170,6 +5172,10 @@ union MHD_RequestInfoDynamicData
  * This information may be changed during the lifetime of the request.
  * The wrapper macro #MHD_request_get_info_dynamic() could be more convenient.
  *
+ * Any pointers in the returned data are valid until any MHD_Action or
+ * MHD_UploadAction is provided. If the data is needed beyond this point,
+ * it should be copied.
+ *
  * @param request the request to get information about
  * @param info_type the type of information requested
  * @param[out] return_value pointer to union where requested information will
@@ -5177,7 +5183,22 @@ union MHD_RequestInfoDynamicData
  * @param return_value_size the size of the memory area pointed
  *                          by @a return_data, in bytes
  * @return #MHD_SC_OK if succeed,
- *         error code otherwise
+ *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a return_value_size is too small,
+ *         #MHD_SC_TOO_LATE if request is already being closed or the response
+ *                          is being sent
+ *         #MHD_SC_TOO_EARLY if requested data is not yet ready (for example,
+ *                           headers are not yet received),
+ *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is
+ *                                       not recognized by MHD,
+ *         #MHD_SC_FEATURE_DISABLED if requested functionality is not supported
+ *                                  by this MHD build,
+ *         #MHD_SC_AUTH_ABSENT if request does not have particular Auth data,
+ *         #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool
+ *                                                  has no space to put decoded
+ *                                                  authentication data,
+ *         #MHD_SC_REQ_AUTH_DATA_BROKEN if format of authentication data is
+ *                                      incorrect or broken,
+ *         other error code otherwise
  * @ingroup specialized
  */
 MHD_EXTERN_ enum MHD_StatusCode
@@ -5187,8 +5208,7 @@ MHD_request_get_info_dynamic_sz (
   union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value,
   size_t return_value_size)
 MHD_FN_PAR_NONNULL_ (1)
-MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3)
-MHD_FN_PURE_;
+MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
 
 
 /**
@@ -5204,7 +5224,8 @@ MHD_FN_PURE_;
  * @ingroup specialized
  */
 #define MHD_request_get_info_dynamic(request,info_type,return_value) \
-        MHD_request_get_info_dynamic_sz ((request), (info_type), (return_value), \
+        MHD_request_get_info_dynamic_sz ((request), (info_type), \
+                                         (return_value), \
                                          sizeof(*(return_value)))
 
 /**

+ 50 - 30
src/include/microhttpd2_preamble.h.in

@@ -462,6 +462,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_APPLICATION_DATA_GENERATION_FINISHED = 20001
   ,
+  /**
+   * The request does not contain a particular type of Authentication
+   * credentials
+   */
+  MHD_SC_AUTH_ABSENT = 20060
+  ,
 
   /* 30000-level status codes indicate transient failures
      that might go away if the client tries again. */
@@ -555,6 +561,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_CONNECTION_POOL_NO_MEM_COOKIE = 30132
   ,
+  /**
+   * Failed to allocate memory from connection memory pool to store
+   * parsed Authentication data.
+   */
+  MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA = 30133
+  ,
   /**
    * Detected jump back of system clock
    */
@@ -753,6 +765,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
    */
   MHD_SC_REQ_POST_PARSE_FAILED_INVALID_POST_FORMAT = 40290
   ,
+  /**
+   * The data in Auth request header has invalid format.
+   * For example, for Basic Authentication base64 decoding failed.
+   */
+  MHD_SC_REQ_AUTH_DATA_BROKEN = 40320
+  ,
   /**
    * The request cannot be processed. Sending error reply.
    */
@@ -1372,115 +1390,122 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
   /* 60000-level errors are because the application
      logic did something wrong or generated an error. */
 
+  /**
+   * The application called function too early.
+   * For example, a header value was requested before the headers
+   * had been received.
+   */
+  MHD_SC_TOO_EARLY = 60000
+  ,
+  /**
+   * The application called this function too late.
+   * For example, MHD has already started sending reply.
+   */
+  MHD_SC_TOO_LATE = 60001
+  ,
   /**
    * MHD does not support the requested combination of
    * the sockets polling syscall and the work mode.
    */
-  MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID = 60000
+  MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID = 60010
   ,
   /**
    * MHD does not support quiescing if ITC was disabled
    * and threads are used.
    */
-  MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 60001
+  MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 60011
   ,
   /**
    * MHD is closing a connection because the application
    * logic to generate the response data failed.
    */
-  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 60005
+  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 60015
   ,
   /**
    * MHD is closing a connection because the application
    * callback told it to do so.
    */
-  MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION = 60006
+  MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION = 60016
   ,
   /**
    * Application only partially processed upload and did
    * not suspend connection. This may result in a hung
    * connection.
    */
-  MHD_SC_APPLICATION_HUNG_CONNECTION = 60007
+  MHD_SC_APPLICATION_HUNG_CONNECTION = 60017
   ,
   /**
    * Application only partially processed upload and did
    * not suspend connection and the read buffer was maxxed
    * out, so MHD closed the connection.
    */
-  MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED = 60008
-  ,
-  /**
-   * Application called function too late, for example because
-   * MHD already changed state.
-   */
-  MHD_SC_TOO_LATE = 60009
+  MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED = 60018
   ,
   /**
    * Attempted to set an option that conflicts with another option
    * already set.
    */
-  MHD_SC_OPTIONS_CONFLICT = 60010
+  MHD_SC_OPTIONS_CONFLICT = 60020
   ,
   /**
    * Attempted to set an option that not recognised by MHD.
    */
-  MHD_SC_OPTION_UNKNOWN = 60011
+  MHD_SC_OPTION_UNKNOWN = 60021
   ,
   /**
    * Parameter specified unknown work mode.
    */
-  MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60012
+  MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60022
   ,
   /**
    * Parameter specified unknown socket poll syscall.
    */
-  MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60013
+  MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60023
   ,
   /**
    * The size of the provided sockaddr does not match address family.
    */
-  MHD_SC_CONFIGURATION_WRONG_SA_SIZE = 60014
+  MHD_SC_CONFIGURATION_WRONG_SA_SIZE = 60024
   ,
   /**
    * The number set by #MHD_D_O_FD_NUMBER_LIMIT is too strict to run
    * the daemon
    */
-  MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT = 60015
+  MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT = 60025
   ,
   /**
    * The number set by #MHD_D_O_GLOBAL_CONNECTION_LIMIT is too for the daemon
    * configuration
    */
-  MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60016
+  MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60026
   ,
   /**
    * The application requested an unsupported TLS backend to be used.
    */
-  MHD_SC_TLS_BACKEND_UNSUPPORTED = 60020
+  MHD_SC_TLS_BACKEND_UNSUPPORTED = 60030
   ,
   /**
    * The application attempted to setup TLS parameters before
    * enabling TLS.
    */
-  MHD_SC_TLS_BACKEND_UNINITIALIZED = 60021
+  MHD_SC_TLS_BACKEND_UNINITIALIZED = 60031
   ,
   /**
    * The application requested a TLS backend which cannot be used due
    * to missing TLS dynamic library or backend initialisation problem.
    */
-  MHD_SC_TLS_BACKEND_UNAVAILABLE = 60022
+  MHD_SC_TLS_BACKEND_UNAVAILABLE = 60032
   ,
   /**
    * Provided TLS certificate and/or private key are incorrect
    */
-  MHD_SC_TLS_CONF_BAD_CERT = 60023
+  MHD_SC_TLS_CONF_BAD_CERT = 60033
   ,
   /**
    * The application requested a daemon setting that cannot be used with
    * selected TLS backend
    */
-  MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS = 60024
+  MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS = 60034
   ,
   /**
    * The response header name has forbidden characters or token
@@ -1570,12 +1595,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
   /**
    * The requested type of information is not recognised.
    */
-  MHD_SC_INFO_TYPE_UNKNOWN = 60200
-  ,
-  /**
-   * The requested type of information is not recognised.
-   */
-  MHD_SC_INFO_GET_INFO_TYPE_UNKNOWN = 60200
+  MHD_SC_INFO_GET_TYPE_UNKNOWN = 60200
   ,
   /**
    * The information of the requested type is too large to fit into

+ 14 - 4
src/mhd2/Makefile.am

@@ -103,8 +103,12 @@ post_parser_files = \
   mhd_post_parser.h         mhd_post_result.h         mhd_postfield_int.h \
   post_parser_funcs.c       post_parser_funcs.h
 
-basic_auth_sources = \
-  response_add_bauth.c
+auth_sources = \
+  request_auth_get.c        request_auth_get.h
+
+auth_basic_sources = \
+  auth_basic.c              auth_basic.h \
+  response_auth_basic.c
 
 upgrade_files = \
   mhd_upgrade.h \
@@ -134,8 +138,12 @@ if HAVE_POST_PARSER
   libmicrohttpd2_la_SOURCES += $(post_parser_files)
 endif
 
-if MHD_ENABLE_BAUTH
-  libmicrohttpd2_la_SOURCES += $(basic_auth_sources)
+if MHD_SUPPORT_AUTH
+  libmicrohttpd2_la_SOURCES += $(auth_sources)
+endif
+
+if MHD_SUPPORT_AUTH_BASIC
+  libmicrohttpd2_la_SOURCES += $(auth_basic_sources)
 endif
 
 if MHD_UPGRADE_SUPPORT
@@ -241,6 +249,8 @@ check-sources-missing:
 	echo " done" ; \
 	test -z "$$res" || echo "The following sources are missing in Makefile.am:$${res}"
 
+check-missing-sources: check-sources-missing
+
 .PHONY: update-po-POTFILES.in check-sources-missing
 
 .NOTPARALLEL: $(srcdir)/daemon_options.h $(srcdir)/daemon_set_options.c $(srcdir)/response_options.h $(srcdir)/response_set_options.c

+ 139 - 0
src/mhd2/auth_basic.c

@@ -0,0 +1,139 @@
+/*
+  This file is part of GNU libmicrohttpd
+  Copyright (C) 2024 Evgeny Grin (Karlson2k)
+
+  GNU libmicrohttpd 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.
+
+  GNU libmicrohttpd 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 src/mhd2/auth_basic.c
+ * @brief  The implementation of the Basic Authorization header parser
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+#include "sys_base_types.h"
+
+#include <string.h>
+
+#include "mhd_cntnr_ptr.h"
+
+#include "mhd_assert.h"
+
+#include "mhd_str_types.h"
+#include "mhd_connection.h"
+
+#include "mhd_str.h"
+#include "stream_funcs.h"
+#include "request_auth_get.h"
+
+#include "auth_basic.h"
+
+static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
+enum MHD_StatusCode
+find_and_parse_auth_basic (struct MHD_Request *restrict req)
+{
+  struct MHD_String token68;
+  size_t alloc_size;
+  size_t dec_size;
+  char *dec_buf;
+  char *colon_ptr;
+
+  mhd_assert (NULL == req->auth.basic.intr.username.cstr);
+
+  if (! mhd_request_get_auth_header_value (req,
+                                           mhd_AUTH_HDR_BASIC,
+                                           &token68))
+    return MHD_SC_AUTH_ABSENT;
+
+  mhd_assert (NULL != token68.cstr);
+
+  if (0 == token68.len)
+  {
+    /* Zero-length token68 */
+    req->auth.basic.intr.username.cstr = token68.cstr;
+    mhd_assert (0 == req->auth.basic.intr.username.len);
+    mhd_assert (NULL == req->auth.basic.intr.password.cstr);
+    mhd_assert (0 == req->auth.basic.intr.password.len);
+    return MHD_SC_OK;
+  }
+
+  alloc_size = mhd_base64_max_dec_size (token68.len) + 1;
+  dec_buf = (char *)
+            mhd_stream_alloc_memory (mhd_CNTNR_PTR (req, \
+                                                    struct MHD_Connection, \
+                                                    rq),
+                                     alloc_size);
+  if (NULL == dec_buf)
+    return MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA;
+
+  /* The 'dec_buf' remains allocated until start of sending reply or until
+     end of the request processing. */
+
+  dec_size = mhd_base64_to_bin_n (token68.cstr,
+                                  token68.len,
+                                  dec_buf,
+                                  alloc_size);
+  if (0 == dec_size)
+    return MHD_SC_REQ_AUTH_DATA_BROKEN;
+
+  dec_buf[dec_size] = 0; /* Zero-terminate the result */
+  req->auth.basic.intr.username.cstr = dec_buf;
+  colon_ptr = memchr (dec_buf, ':', dec_size);
+  if (NULL == colon_ptr)
+  {
+    /* No password provided. Only username. */
+    req->auth.basic.intr.username.len = dec_size;
+    mhd_assert (NULL == req->auth.basic.intr.password.cstr);
+    mhd_assert (0 == req->auth.basic.intr.password.len);
+    return MHD_SC_OK;
+  }
+  *colon_ptr = 0; /* Zero-terminate the username */
+  req->auth.basic.intr.username.len = (size_t) (colon_ptr - dec_buf);
+  req->auth.basic.intr.password.cstr = colon_ptr + 1;
+  mhd_assert ((req->auth.basic.intr.username.len + 1) <= dec_size);
+  req->auth.basic.intr.password.len =
+    dec_size - (req->auth.basic.intr.username.len + 1);
+  return MHD_SC_OK;
+}
+
+
+MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
+MHD_FN_PAR_OUT_ (2) enum MHD_StatusCode
+mhd_request_get_auth_basic_creds (
+  struct MHD_Request *restrict req,
+  const struct MHD_BasicAuthInfo **restrict v_auth_basic_creds)
+{
+  enum MHD_StatusCode res;
+  mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED <=
+              mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
+  mhd_assert (mhd_HTTP_STAGE_REQ_RECV_FINISHED >=
+              mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
+
+  if (NULL != req->auth.basic.intr.username.cstr)
+    res = MHD_SC_OK;
+  else
+    res = find_and_parse_auth_basic (req);
+
+  if (MHD_SC_OK != res)
+    return res; /* Failure exit point */
+
+  *v_auth_basic_creds = &(req->auth.basic.extr);
+
+  return MHD_SC_OK; /* Success exit point */
+}

+ 51 - 0
src/mhd2/auth_basic.h

@@ -0,0 +1,51 @@
+/*
+  This file is part of GNU libmicrohttpd
+  Copyright (C) 2024 Evgeny Grin (Karlson2k)
+
+  GNU libmicrohttpd 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.
+
+  GNU libmicrohttpd 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 src/mhd2/auth_basic.h
+ * @brief  The declaration of the Basic Authorization header parser
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_AUTH_BASIC_H
+#define MHD_AUTH_BASIC_H 1
+
+#include "mhd_sys_options.h"
+
+#if ! defined(MHD_SUPPORT_AUTH_BASIC)
+#error Basic Authorization must be enabled
+#endif
+
+#include "mhd_public_api.h"
+
+/**
+ * Find in request and parse Basic Authentication information
+ * @param req the request to use
+ * @param[out] v_auth_basic_creds the pointer to set to the found data
+ * @return #MHD_SC_OK on success,
+ *         error code otherwise
+ */
+MHD_INTERNAL enum MHD_StatusCode
+mhd_request_get_auth_basic_creds (
+  struct MHD_Request *restrict req,
+  const struct MHD_BasicAuthInfo **restrict v_auth_basic_creds)
+MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2);
+
+#endif /* ! MHD_AUTH_BASIC_H */

+ 1 - 1
src/mhd2/daemon_get_info.c

@@ -83,5 +83,5 @@ MHD_daemon_get_info_fixed_sz (struct MHD_Daemon *daemon,
   default:
     break;
   }
-  return MHD_SC_INFO_TYPE_UNKNOWN;
+  return MHD_SC_INFO_GET_TYPE_UNKNOWN;
 }

+ 12 - 2
src/mhd2/lib_get_info.c

@@ -116,7 +116,17 @@ MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type,
   case MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER:
   case MHD_LIB_INFO_FIXED_HAS_POST_PARSER:
   case MHD_LIB_INFO_FIXED_HAS_UPGRADE:
+    mhd_assert (0 && "Not implemented yet");
+    break;
   case MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH:
+    if (sizeof(return_data->v_bool) > return_data_size)
+      return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
+#ifdef MHD_SUPPORT_AUTH_BASIC
+    return_data->v_bool = MHD_YES;
+#else
+    return_data->v_bool = MHD_NO;
+#endif
+    return MHD_SC_OK;
   case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH:
   case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_RFC2069:
   case MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_MD5:
@@ -167,7 +177,7 @@ MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type,
   default:
     break;
   }
-  return MHD_SC_INFO_TYPE_UNKNOWN;
+  return MHD_SC_INFO_GET_TYPE_UNKNOWN;
 }
 
 
@@ -215,5 +225,5 @@ MHD_lib_get_info_dynamic_sz (enum MHD_LibInfoDynamic info_type,
   default:
     break;
   }
-  return MHD_SC_INFO_TYPE_UNKNOWN;
+  return MHD_SC_INFO_GET_TYPE_UNKNOWN;
 }

+ 22 - 4
src/mhd2/mhd_cntnr_ptr.h

@@ -20,7 +20,7 @@
 
 /**
  * @file src/mhd2/mhd_cntnr_ptr.h
- * @brief  The definition of mhd_CNTNR_PTR() macro.
+ * @brief  The definition of mhd_CNTNR_PTR() and mhd_CNTNR_CPTR() macros.
  * @author Karlson2k (Evgeny Grin)
  */
 
@@ -45,10 +45,28 @@
  * @param membr_name the name of the member pointed by @a membr_ptr
  * @return the pointer to the outer structure
  */
-#define mhd_CNTNR_PTR(membr_ptr,cntnr_type,membr_name)      \
-        ((cntnr_type*) (void*)                              \
-         (((char*) (0 ?                                     \
+#define mhd_CNTNR_PTR(membr_ptr,cntnr_type,membr_name)   \
+        ((cntnr_type*) (void*)                            \
+         (((char*) (0 ?                                    \
                     (&(((cntnr_type*) NULL)->membr_name)) : \
                     (membr_ptr))) - offsetof (cntnr_type,membr_name)))
 
+/**
+ * Get the const pointer to the outer @a cntnr_type structure
+ * containing @a membr_name member by the @a membr_ptr pointer to the member.
+ *
+ * This macro checks at compile time whether pointer to the @a membr_name in
+ * the @a cntnr_type is compatible with the provided @a membr_ptr pointer.
+ *
+ * @param membr_ptr the pointer to the member
+ * @param cntnr_type the type of the container with the @a membr_name member
+ * @param membr_name the name of the member pointed by @a membr_ptr
+ * @return the pointer to the outer structure
+ */
+#define mhd_CNTNR_CPTR(membr_ptr,cntnr_type,membr_name)        \
+        ((const cntnr_type*) (const void*)                      \
+         (((const char*) (0 ?                                    \
+                          (&(((cntnr_type*) NULL)->membr_name)) : \
+                          (membr_ptr))) - offsetof (cntnr_type,membr_name)))
+
 #endif /* ! MHD_CNTNR_PTR_H */

+ 68 - 0
src/mhd2/mhd_request.h

@@ -283,6 +283,67 @@ union mhd_ReqContentParsingData
   // TODO: move "raw" upload processing data here
 };
 
+
+#ifdef MHD_SUPPORT_AUTH_BASIC
+/**
+ * Request Basic Auth internal data
+ * The same format as struct MHD_BasicAuthInfo, but wiht nullable username.
+ * Keep in sync with MHD_BasicAuthInfo!
+ */
+struct mhd_ReqAuthBasicInternalData
+{
+  /**
+   * The user name
+   */
+  struct MHD_StringNullable username;
+  /**
+   * The user password
+   */
+  struct MHD_StringNullable password;
+};
+
+/**
+ * Request Basic Auth data
+ */
+union mhd_ReqAuthBasicData
+{
+  /**
+   * The internal representation of the Basic Auth data
+   */
+  struct mhd_ReqAuthBasicInternalData intr;
+
+  /**
+   * The external (application) Basic Auth data
+   */
+  struct MHD_BasicAuthInfo extr;
+};
+
+#endif /* MHD_SUPPORT_AUTH_BASIC */
+
+#if defined(MHD_SUPPORT_AUTH_BASIC)
+/**
+ * Defined if any Authentication scheme is supported
+ */
+#  define mhd_SUPPORT_AUTH      1
+#endif /* MHD_SUPPORT_AUTH_BASIC */
+
+
+#ifdef mhd_SUPPORT_AUTH
+/**
+ * Request Basic Auth data
+ */
+struct mhd_ReqAuthData
+{
+#ifdef MHD_SUPPORT_AUTH_BASIC
+  /**
+   * Request Basic Auth data
+   */
+  union mhd_ReqAuthBasicData basic;
+#endif /* MHD_SUPPORT_AUTH_BASIC */
+};
+
+#endif /* mhd_SUPPORT_AUTH */
+
 /**
  * Request-specific values.
  *
@@ -327,6 +388,13 @@ struct MHD_Request
    */
   bool have_expect_100;
 
+#ifdef mhd_SUPPORT_AUTH
+  /**
+   * Request Basic Auth data
+   */
+  struct mhd_ReqAuthData auth;
+#endif /* mhd_SUPPORT_AUTH */
+
   /**
    * HTTP version string (i.e. http/1.1).  Allocated
    * in pool.

+ 2 - 2
src/mhd2/mhd_response.h

@@ -265,12 +265,12 @@ struct mhd_ResponseConfiguration
    */
   bool int_err_resp;
 
-#ifdef MHD_ENABLE_BAUTH
+#ifdef MHD_SUPPORT_AUTH_BASIC
   /**
    * Response has Basic Auth "challenge" header
    */
   bool has_bauth;
-#endif /* MHD_ENABLE_BAUTH */
+#endif /* MHD_SUPPORT_AUTH_BASIC */
 };
 
 /**

+ 8 - 8
src/mhd2/mhd_str.c

@@ -1944,7 +1944,7 @@ mhd_str_pct_decode_in_place_lenient (char *restrict str,
 }
 
 
-#ifdef DAUTH_SUPPORT
+#ifdef MHD_SUPPORT_AUTH_DIGEST
 MHD_INTERNAL bool
 mhd_str_equal_quoted_bin_n (const char *quoted,
                             size_t quoted_len,
@@ -2005,9 +2005,9 @@ mhd_str_equal_caseless_quoted_bin_n (const char *quoted,
 }
 
 
-#endif /* DAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_DIGEST */
 
-#if defined(DAUTH_SUPPORT) || defined(HAVE_POST_PARSER)
+#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(HAVE_POST_PARSER)
 
 MHD_INTERNAL size_t
 mhd_str_unquote (const char *quoted,
@@ -2034,9 +2034,9 @@ mhd_str_unquote (const char *quoted,
 }
 
 
-#endif /* DAUTH_SUPPORT HAVE_POST_PARSER */
+#endif /* MHD_SUPPORT_AUTH_DIGEST HAVE_POST_PARSER */
 
-#if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT)
+#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC)
 
 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
 MHD_FN_PAR_IN_SIZE_ (1,2)
@@ -2097,9 +2097,9 @@ mhd_str_quote (const char *unquoted,
 }
 
 
-#endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_AUTH_BASIC */
 
-#ifdef BAUTH_SUPPORT
+#ifdef MHD_SUPPORT_AUTH_BASIC
 
 /*
  * MHD_BASE64_FUNC_VERSION
@@ -2333,7 +2333,7 @@ MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
 
 #undef mhd_base64_map_type
 
-#endif /* BAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_BASIC */
 
 
 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool

+ 8 - 8
src/mhd2/mhd_str.h

@@ -598,7 +598,7 @@ MHD_INTERNAL size_t
 mhd_str_pct_decode_in_place_lenient (char *restrict str,
                                      bool *restrict broken_encoding);
 
-#ifdef DAUTH_SUPPORT
+#ifdef MHD_SUPPORT_AUTH_DIGEST
 /**
  * Check two strings for equality, "unquoting" the first string from quoted
  * form as specified by RFC7230#section-3.2.6 and RFC7694#quoted.strings.
@@ -689,9 +689,9 @@ mhd_str_equal_caseless_quoted_bin_n (const char *quoted,
 #define mhd_str_equal_caseless_quoted_s_bin_n(q,l,u) \
         mhd_str_equal_caseless_quoted_bin_n (q,l,u,mhd_SSTR_LEN (u))
 
-#endif /* DAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_DIGEST */
 
-#if defined(DAUTH_SUPPORT) || defined(HAVE_POST_PARSER)
+#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(HAVE_POST_PARSER)
 
 /**
  * Convert string from quoted to unquoted form as specified by
@@ -713,9 +713,9 @@ mhd_str_unquote (const char *quoted,
                  size_t quoted_len,
                  char *result);
 
-#endif /* DAUTH_SUPPORT HAVE_POST_PARSER */
+#endif /* MHD_SUPPORT_AUTH_DIGEST HAVE_POST_PARSER */
 
-#if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT)
+#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC)
 
 /**
  * Convert string from unquoted to quoted form as specified by
@@ -739,9 +739,9 @@ mhd_str_quote (const char *unquoted,
                size_t buf_size)
 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4);
 
-#endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_AUTH_BASIC */
 
-#ifdef BAUTH_SUPPORT
+#ifdef MHD_SUPPORT_AUTH_BASIC
 
 /**
  * Returns the maximum possible size of the Base64 decoded data.
@@ -776,7 +776,7 @@ mhd_base64_to_bin_n (const char *base64,
                      void *bin,
                      size_t bin_size);
 
-#endif /* BAUTH_SUPPORT */
+#endif /* MHD_SUPPORT_AUTH_BASIC */
 
 
 /**

+ 138 - 0
src/mhd2/request_auth_get.c

@@ -0,0 +1,138 @@
+/*
+  This file is part of GNU libmicrohttpd
+  Copyright (C) 2022-2024 Evgeny Grin (Karlson2k)
+
+  GNU libmicrohttpd 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.
+
+  GNU libmicrohttpd 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 src/mhd2/request_auth_get.c
+ * @brief  The implementation of the request Authorization header parsing helper
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+#include "sys_base_types.h"
+
+#include "mhd_assert.h"
+#include "mhd_unreachable.h"
+#include "mhd_cntnr_ptr.h"
+#include "mhd_str_macros.h"
+
+#include "mhd_str_types.h"
+#include "mhd_request.h"
+#include "mhd_connection.h"
+#include "mhd_daemon.h"
+
+#include "mhd_str.h"
+
+#include "request_auth_get.h"
+
+MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
+MHD_FN_PAR_OUT_ (3) bool
+mhd_request_get_auth_header_value (struct MHD_Request *restrict request,
+                                   enum mhd_AuthHeaderKind auth_type,
+                                   struct MHD_String *restrict header_value)
+{
+  static const struct MHD_String hdr_name = mhd_MSTR_INIT ("Authorization");
+#ifdef MHD_SUPPORT_AUTH_BASIC
+  static const struct MHD_String prefix_basic = mhd_MSTR_INIT ("Basic");
+#endif
+  const int strict_lvl =
+    mhd_CNTNR_PTR (request, \
+                   struct MHD_Connection, rq)->daemon->req_cfg.strictness;
+  const bool allow_tab_as_sep = (-2 >= strict_lvl);
+  const char *prefix_str;
+  size_t prefix_len;
+  struct mhd_RequestField *f;
+  size_t p_start;
+
+  mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED <= \
+              mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage);
+
+  switch (auth_type)
+  {
+#ifdef MHD_SUPPORT_AUTH_BASIC
+  case mhd_AUTH_HDR_BASIC:
+    prefix_str = prefix_basic.cstr;
+    prefix_len = prefix_basic.len;
+    break;
+#endif
+#ifdef MHD_ENUMS_NEED_TRAILING_VALUE
+  case mhd_AUTH_HDR_KIND_SENTINEL:
+#endif
+  default:
+    mhd_UNREACHABLE ();
+    return false;
+  }
+
+  for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f;
+       f = mhd_DLINKEDL_GET_NEXT (f, fields))
+  {
+    if (hdr_name.len != f->field.nv.name.len)
+      continue;
+    if (MHD_VK_HEADER != f->field.kind)
+      continue;
+    if (prefix_len > f->field.nv.name.len)
+      continue;
+    if (! mhd_str_equal_caseless_bin_n (hdr_name.cstr,
+                                        f->field.nv.name.cstr,
+                                        hdr_name.len))
+      continue;
+    if (! mhd_str_equal_caseless_bin_n (prefix_str,
+                                        f->field.nv.value.cstr,
+                                        prefix_len))
+      continue;
+    /* Match only if the search token string is the full header value or
+       the search token is followed by space */
+    if (prefix_len == f->field.nv.name.len)
+    {
+      header_value->cstr = f->field.nv.value.cstr + f->field.nv.name.len;
+      header_value->len = 0;
+      return true; /* Success exit point */
+    }
+    if (' ' == f->field.nv.value.cstr[prefix_len])
+      break;
+    /* Note: RFC 7235 (Section 2.1) only allows the space character.
+       However, as a slight violation of the specifications, a tab character
+       is also recognised here for additional flexibility and
+       uniformity (tabs are supported as separators between parameters). */
+    if (allow_tab_as_sep &&
+        ('\t' == f->field.nv.value.cstr[prefix_len]))
+      break;
+  }
+  if (NULL == f)
+    return false; /* Failure exit point */
+
+  mhd_assert (prefix_len + 1 <= f->field.nv.name.len);
+  /* Skip leading whitespaces */
+  for (p_start = prefix_len + 1; p_start < f->field.nv.name.len; ++p_start)
+  {
+    if ((' ' != f->field.nv.value.cstr[p_start]) &&
+        ('\t' != f->field.nv.value.cstr[p_start]))
+      break;
+  }
+  header_value->cstr = f->field.nv.value.cstr + p_start;
+  header_value->len = f->field.nv.value.len - p_start;
+
+  mhd_assert (0 == header_value->cstr[header_value->len]);
+  mhd_assert ((0 != header_value->len) && \
+              "Trailing header whitespaces must be already stripped");
+
+  return true; /* Success exit point */
+}

+ 76 - 0
src/mhd2/request_auth_get.h

@@ -0,0 +1,76 @@
+/*
+  This file is part of GNU libmicrohttpd
+  Copyright (C) 2024 Evgeny Grin (Karlson2k)
+
+  GNU libmicrohttpd 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.
+
+  GNU libmicrohttpd 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 src/mhd2/request_auth_get.h
+ * @brief  The declaration of the request Authorization header parsing helper
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_REQUEST_AUTH_GET_H
+#define MHD_REQUEST_AUTH_GET_H 1
+
+#include "mhd_sys_options.h"
+
+#if ! defined(MHD_SUPPORT_AUTH_BASIC) && ! defined(MHD_SUPPORT_AUTH_DIGEST)
+#error Authorization header parsing must be enabled
+#endif
+
+#include "sys_bool_type.h"
+
+struct MHD_String;      /* forward declaration */
+struct MHD_Request;     /* forward declaration */
+
+/**
+ * The type of Authorization header to look for
+ */
+enum MHD_FIXED_ENUM_ mhd_AuthHeaderKind
+{
+#ifdef MHD_SUPPORT_AUTH_BASIC
+  mhd_AUTH_HDR_BASIC,
+#endif
+#ifdef MHD_ENUMS_NEED_TRAILING_VALUE
+  mhd_AUTH_HDR_KIND_SENTINEL
+#endif
+};
+
+
+/**
+ * Get value of the specific Authorization header
+ *
+ * This function supports multiple types of the Authorization headers in
+ * one request, but does not parse each header for several types of
+ * Authorization. This should not be a limitation as RFC 7235 (section 4.2)
+ * allows only one type of Authorization in each request.
+ *
+ * @param request the request to use
+ * @param auth_type the type of Authorization to get
+ * @param[out] header_value the value of the Authorization header, excluding
+ *                          the prefix (type) and initial whitespaces
+ * @return 'true' if requested header found,
+ *         'false' otherwise (@a header_value not set)
+ */
+MHD_INTERNAL bool
+mhd_request_get_auth_header_value (struct MHD_Request *restrict request,
+                                   enum mhd_AuthHeaderKind auth_type,
+                                   struct MHD_String *restrict header_value)
+MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (3);
+
+#endif /* ! MHD_REQUEST_AUTH_GET_H */

+ 29 - 8
src/mhd2/request_get_info.c

@@ -36,6 +36,10 @@
 #include "mhd_request.h"
 #include "mhd_connection.h"
 
+#ifdef MHD_SUPPORT_AUTH_BASIC
+#  include "auth_basic.h"
+#endif
+
 #include "mhd_public_api.h"
 
 MHD_EXTERN_
@@ -80,30 +84,39 @@ MHD_request_get_info_fixed_sz (
   default:
   }
 
-  return MHD_SC_INFO_TYPE_UNKNOWN;
+  return MHD_SC_INFO_GET_TYPE_UNKNOWN;
 }
 
 
 MHD_EXTERN_
 MHD_FN_PAR_NONNULL_ (1)
-MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3)
-MHD_FN_PURE_ enum MHD_StatusCode
+MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode
 MHD_request_get_info_dynamic_sz (
   struct MHD_Request *MHD_RESTRICT request,
   enum MHD_RequestInfoDynamicType info_type,
   union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value,
   size_t return_value_size)
 {
+  if (mhd_HTTP_STAGE_REQ_RECV_FINISHED <
+      mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage)
+    return MHD_SC_TOO_LATE;
+  if ((mhd_HTTP_STAGE_HEADERS_PROCESSED >
+       mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage) &&
+      (MHD_REQUEST_INFO_DYNAMIC_NUMBER_GET_PARAMS < info_type))
+    return MHD_SC_TOO_EARLY;
   switch (info_type)
   {
   case MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR:
-    /* TODO: check stage */
+    mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVED <= \
+                mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage);
     if (sizeof(return_value->v_str) > return_value_size)
       return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
     return_value->v_str = request->method;
     return MHD_SC_OK;
   case MHD_REQUEST_INFO_DYNAMIC_URI:
-    /* TODO: check stage */
+    if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED <
+        mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage)
+      return MHD_SC_TOO_EARLY;
     if (sizeof(return_value->v_str) > return_value_size)
       return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
     return_value->v_str.cstr = request->url;
@@ -121,7 +134,6 @@ MHD_request_get_info_dynamic_sz (
     mhd_assert (0 && "Not implemented yet");
     break;
   case MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE:
-    /* TODO: check stage */
     if (sizeof(return_value->v_sizet) > return_value_size)
       return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
     return_value->v_sizet = request->header_size;
@@ -133,12 +145,21 @@ MHD_request_get_info_dynamic_sz (
   case MHD_REQUEST_INFO_DYNAMIC_DAUTH_REQ_INFO:
     mhd_assert (0 && "Not implemented yet");
     break;
-  case MHD_REQUEST_INFO_DYNAMIC_BAUTH_REQ_INFO:
+  case MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS:
+#ifdef MHD_SUPPORT_AUTH_BASIC
+    if (sizeof(return_value->v_auth_basic_creds) > return_value_size)
+      return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
+    return mhd_request_get_auth_basic_creds (request,
+                                             &(return_value->
+                                               v_auth_basic_creds));
+#else  /* MHD_SUPPORT_AUTH_BASIC */
+    return MHD_SC_FEATURE_DISABLED;
+#endif /* MHD_SUPPORT_AUTH_BASIC */
     mhd_assert (0 && "Not implemented yet");
     break;
   case MHD_REQUEST_INFO_DYNAMIC_SENTINEL:
   default:
   }
 
-  return MHD_SC_INFO_TYPE_UNKNOWN;
+  return MHD_SC_INFO_GET_TYPE_UNKNOWN;
 }

+ 27 - 26
src/mhd2/response_add_bauth.c → src/mhd2/response_auth_basic.c

@@ -19,7 +19,7 @@
 */
 
 /**
- * @file src/mhd2/response_add_bauth.c
+ * @file src/mhd2/response_auth_basic.c
  * @brief  The definitions of MHD_response_add_basic_auth_challenge() function
  * @author Karlson2k (Evgeny Grin)
  */
@@ -28,6 +28,7 @@
 
 #include "mhd_response.h"
 #include "mhd_locks.h"
+#include "mhd_str_types.h"
 
 #include <string.h>
 #include "sys_malloc.h"
@@ -43,12 +44,12 @@ response_add_basic_auth_challenge_int (struct MHD_Response *restrict response,
                                        const char *restrict realm,
                                        enum MHD_Bool prefer_utf8)
 {
-  static const char hdr_name[] =        MHD_HTTP_HEADER_WWW_AUTHENTICATE;
-  static const size_t hdr_name_len =    mhd_SSTR_LEN (hdr_name);
-  static const char prefix[] =          "Basic realm=\"";
-  static const size_t prefix_len =      mhd_SSTR_LEN (prefix);
-  static const char add_charset[] =     ", charset=\"UTF-8\"";
-  static const size_t add_charset_len = mhd_SSTR_LEN (add_charset);
+  static const struct MHD_String hdr_name =
+    mhd_MSTR_INIT (MHD_HTTP_HEADER_WWW_AUTHENTICATE);
+  static const struct MHD_String prefix =
+    mhd_MSTR_INIT ("Basic realm=\"");
+  static const struct MHD_String add_charset =
+    mhd_MSTR_INIT (", charset=\"UTF-8\"");
   const size_t realm_len = strlen (realm);
   char *val_str;
   size_t hval_maxlen;
@@ -65,29 +66,29 @@ response_add_basic_auth_challenge_int (struct MHD_Response *restrict response,
 
   suffix_len = 1; /* for (closing) quote char */
   if (MHD_NO != prefer_utf8)
-    suffix_len += add_charset_len;
-  hval_maxlen = prefix_len + realm_len * 2 + suffix_len;
+    suffix_len += add_charset.len;
+  hval_maxlen = prefix.len + realm_len * 2 + suffix_len;
 
   new_hdr = (struct mhd_ResponseHeader *)
             malloc (sizeof(struct mhd_ResponseHeader)
-                    + hdr_name_len + 1 + hval_maxlen + 1);
+                    + hdr_name.len + 1 + hval_maxlen + 1);
 
   if (NULL == new_hdr)
     return MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED;
 
   /* Set the name of the header */
   memcpy ((char *) (new_hdr + 1),
-          hdr_name,
-          hdr_name_len + 1);
+          hdr_name.cstr,
+          hdr_name.len + 1);
 
   /* Set the value of the header */
-  val_str = ((char *) (new_hdr + 1)) + hdr_name_len + 1;
-  memcpy (val_str, prefix, prefix_len);
-  pos = prefix_len;
+  val_str = ((char *) (new_hdr + 1)) + hdr_name.len + 1;
+  memcpy (val_str, prefix.cstr, prefix.len);
+  pos = prefix.len;
   realm_quoted_len = mhd_str_quote (realm,
                                     realm_len,
                                     val_str + pos,
-                                    hval_maxlen - prefix_len - suffix_len);
+                                    hval_maxlen - prefix.len - suffix_len);
   mhd_assert (0 != realm_quoted_len);
   pos += realm_quoted_len;
   val_str[pos++] = '\"';
@@ -95,9 +96,9 @@ response_add_basic_auth_challenge_int (struct MHD_Response *restrict response,
 
   if (MHD_NO != prefer_utf8)
   {
-    mhd_assert (pos + add_charset_len <= hval_maxlen);
-    memcpy (val_str + pos, add_charset, add_charset_len);
-    pos += add_charset_len;
+    mhd_assert (pos + add_charset.len <= hval_maxlen);
+    memcpy (val_str + pos, add_charset.cstr, add_charset.len);
+    pos += add_charset.len;
   }
   val_str[pos] = 0; /* Zero terminate the result */
   mhd_assert (pos <= hval_maxlen);
@@ -107,23 +108,23 @@ response_add_basic_auth_challenge_int (struct MHD_Response *restrict response,
     void *new_ptr;
     new_ptr = realloc (new_hdr,
                        sizeof(struct mhd_ResponseHeader)
-                       + hdr_name_len + 1 + pos + 1);
+                       + hdr_name.len + 1 + pos + 1);
     /* Just use the old pointer if realloc() failed */
     if (NULL != new_ptr)
       new_hdr = (struct mhd_ResponseHeader *) new_ptr;
   }
 
   new_hdr->name.cstr = (char *) (new_hdr + 1);
-  new_hdr->name.len = hdr_name_len;
-  mhd_assert (0 == memcmp (hdr_name, \
+  new_hdr->name.len = hdr_name.len;
+  mhd_assert (0 == memcmp (hdr_name.cstr, \
                            new_hdr->name.cstr, \
                            new_hdr->name.len + 1));
 
-  new_hdr->value.cstr = ((char *) (new_hdr + 1)) + hdr_name_len + 1;
+  new_hdr->value.cstr = ((char *) (new_hdr + 1)) + hdr_name.len + 1;
   new_hdr->value.len = pos;
-  mhd_assert (0 == memcmp (prefix, \
+  mhd_assert (0 == memcmp (prefix.cstr, \
                            new_hdr->value.cstr, \
-                           prefix_len));
+                           prefix.len));
   mhd_assert (0 == new_hdr->value.cstr[new_hdr->value.len]);
 
   mhd_DLINKEDL_INIT_LINKS (new_hdr, headers);
@@ -150,7 +151,7 @@ MHD_response_add_basic_auth_challenge (
     return MHD_SC_RESP_POINTER_NULL;
   if (response->frozen)
     return MHD_SC_TOO_LATE;
-  if (MHD_HTTP_STATUS_FORBIDDEN != response->sc)
+  if (MHD_HTTP_STATUS_UNAUTHORIZED != response->sc)
     return MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE;
 
   if (response->reuse.reusable)