mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
Digest Auth: part one
This commit is contained in:
+10
-10
@@ -5635,18 +5635,18 @@ AS_CASE([${enable_md5}],
|
||||
)
|
||||
AS_IF([test "x${enable_md5}" = "xbuiltin" || test "x${enable_md5}" = "xtlslib" ],
|
||||
[
|
||||
AC_DEFINE([[MHD_MD5_SUPPORT]],[[1]],
|
||||
AC_DEFINE([[MHD_SUPPORT_MD5]],[[1]],
|
||||
[Define to 1 if libmicrohttpd is compiled with MD5 hashing support.])
|
||||
]
|
||||
)
|
||||
AS_IF([test "x${enable_md5}" = "xtlslib" ],
|
||||
[
|
||||
AC_DEFINE([[MHD_MD5_TLSLIB]],[[1]],
|
||||
AC_DEFINE([[MHD_MD5_EXTR]],[[1]],
|
||||
[Define to 1 if libmicrohttpd is compiled with MD5 hashing by TLS library.])
|
||||
]
|
||||
)
|
||||
AM_CONDITIONAL([ENABLE_MD5], [[test "x${enable_md5}" = "xbuiltin" || test "x${enable_md5}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([ENABLE_MD5_EXT], [[test "x${enable_md5}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([MHD_SUPPORT_MD5], [[test "x${enable_md5}" = "xbuiltin" || test "x${enable_md5}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([MHD_MD5_EXTR], [[test "x${enable_md5}" = "xtlslib" ]])
|
||||
AC_MSG_RESULT([[${enable_md5_MSG}]])
|
||||
|
||||
# optional: SHA-256 support for Digest Auth. Enabled by default.
|
||||
@@ -5757,18 +5757,18 @@ AS_CASE([${enable_sha256}],
|
||||
)
|
||||
AS_IF([test "x${enable_sha256}" = "xbuiltin" || test "x${enable_sha256}" = "xtlslib" ],
|
||||
[
|
||||
AC_DEFINE([[MHD_SHA256_SUPPORT]],[[1]],
|
||||
AC_DEFINE([[MHD_SUPPORT_SHA256]],[[1]],
|
||||
[Define to 1 if libmicrohttpd is compiled with SHA-256 hashing support.])
|
||||
]
|
||||
)
|
||||
AS_IF([test "x${enable_sha256}" = "xtlslib" ],
|
||||
[
|
||||
AC_DEFINE([[MHD_SHA256_TLSLIB]],[[1]],
|
||||
AC_DEFINE([[MHD_SHA256_EXTR]],[[1]],
|
||||
[Define to 1 if libmicrohttpd is compiled with SHA-256 hashing by TLS library.])
|
||||
]
|
||||
)
|
||||
AM_CONDITIONAL([ENABLE_SHA256], [[test "x${enable_sha256}" = "xbuiltin" || test "x${enable_sha256}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([ENABLE_SHA256_EXT], [[test "x${enable_sha256}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([MHD_SUPPORT_SHA256], [[test "x${enable_sha256}" = "xbuiltin" || test "x${enable_sha256}" = "xtlslib" ]])
|
||||
AM_CONDITIONAL([MHD_SHA256_EXTR], [[test "x${enable_sha256}" = "xtlslib" ]])
|
||||
AC_MSG_RESULT([[${enable_sha256_MSG}]])
|
||||
|
||||
# optional: SHA-512/256 support for Digest Auth. Enabled by default.
|
||||
@@ -5797,11 +5797,11 @@ AS_CASE([${enable_sha512_256}],
|
||||
)
|
||||
AS_VAR_IF([[enable_sha512_256]],[["yes"]],
|
||||
[
|
||||
AC_DEFINE([[MHD_SHA512_256_SUPPORT]],[[1]],
|
||||
AC_DEFINE([[MHD_SUPPORT_SHA512_256]],[[1]],
|
||||
[Define to 1 if libmicrohttpd is compiled with SHA-512/256 hashing support.])
|
||||
]
|
||||
)
|
||||
AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
|
||||
AM_CONDITIONAL([MHD_SUPPORT_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
|
||||
AC_MSG_RESULT([[${enable_sha512_256_MSG}]])
|
||||
|
||||
AS_IF([test "x$enable_digest_auth" != "xno"],
|
||||
|
||||
+291
-35
@@ -1621,6 +1621,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
* cannot be provided due to some error or other reasons.
|
||||
*/
|
||||
MHD_SC_INFO_GET_TYPE_UNAVAILALBE = 60204
|
||||
,
|
||||
/**
|
||||
* The type of the Digest Auth algorithm is unknown or not supported.
|
||||
*/
|
||||
MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED = 60240
|
||||
,
|
||||
/**
|
||||
* The the Digest Auth QOP value is unknown or not supported.
|
||||
*/
|
||||
MHD_SC_AUTH_DIGEST_QOP_NOT_SUPPORTED = 60241
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -7907,20 +7917,32 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
|
||||
|
||||
/**
|
||||
* Create an action to request authentication from the client
|
||||
* Add Digest Authentication "challenge" to the response.
|
||||
*
|
||||
* If @a mqop allows both RFC 2069 (MHD_DIGEST_AUTH_QOP_NONE) and QOP with
|
||||
* value, then response is formed like if MHD_DIGEST_AUTH_QOP_NONE bit was
|
||||
* not set, because such response should be backward-compatible with RFC 2069.
|
||||
* The response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
|
||||
*
|
||||
* If @a mqop allows both RFC 2069 (#MHD_DIGEST_AUTH_QOP_NONE) and other QOP
|
||||
* values, then the "challenge" is formed like if MHD_DIGEST_AUTH_QOP_NONE bit
|
||||
* was not set, because such "challenge" should be backward-compatible with
|
||||
* RFC 2069.
|
||||
*
|
||||
* If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is
|
||||
* formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no
|
||||
* 'charset'). For better compatibility with clients, it is recommended (but
|
||||
* not required) to set @a domain to NULL in this mode.
|
||||
*
|
||||
* At most one action can be created for any request.
|
||||
* New nonces are generated each time when the resulting response is used.
|
||||
*
|
||||
* @param request the request
|
||||
* See RFC 7616, section 3.3 for details.
|
||||
*
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
@@ -7935,24 +7957,17 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param response the reply to send; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_FORBIDDEN status
|
||||
* code, must not have #MHD_R_O_REUSABLE enabled;
|
||||
* the NULL is tolerated (the result is NULL)
|
||||
* @param signal_stale if set to #MHD_YES then indication of stale nonce used in
|
||||
* the client's request is signalled by adding 'stale=true'
|
||||
* to the authentication header, this instructs the client
|
||||
* to retry immediately with the new nonce and the same
|
||||
* credentials, without asking user for the new password
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then MD5 is preferred (currently, may be changed in next
|
||||
* versions)
|
||||
* @param userhash_support if set to non-zero value (#MHD_YES) then support of
|
||||
* userhash is indicated, allowing client to provide
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
@@ -7964,24 +7979,265 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @return pointer to the action on success,
|
||||
* NULL on failure
|
||||
* @return #MHD_SC_OK if succeed,
|
||||
* #MHD_SC_TOO_LATE if the response has been already "frozen" (used to
|
||||
* create an action),
|
||||
* #MHD_SC_RESP_HEADERS_CONFLICT if Digest Authentication "challenge"
|
||||
* has been added already,
|
||||
* #MHD_SC_RESP_POINTER_NULL if @a response is NULL,
|
||||
* #MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE is response status code is wrong,
|
||||
* #MHD_SC_RESP_HEADER_VALUE_INVALID if @a realm, @a opaque or @a domain
|
||||
* have wrong characters or zero length (for @a realm),
|
||||
* #MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED if memory allocation failed,
|
||||
* or other error code if failed
|
||||
* @ingroup authentication
|
||||
*/
|
||||
MHD_EXTERN_ const struct MHD_Action *
|
||||
MHD_action_digest_auth_required_response (
|
||||
struct MHD_Request *request,
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
const char *domain,
|
||||
struct MHD_Response *response,
|
||||
enum MHD_Bool signal_stale,
|
||||
MHD_EXTERN_ enum MHD_StatusCode
|
||||
MHD_response_add_auth_digest_challenge (
|
||||
struct MHD_Response *MHD_RESTRICT response,
|
||||
const char *MHD_RESTRICT realm,
|
||||
const char *MHD_RESTRICT opaque,
|
||||
const char *MHD_RESTRICT domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo algo,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8)
|
||||
MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_NONNULL_ (5);
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4);
|
||||
|
||||
|
||||
#ifndef MHD_NO_STATIC_INLINE
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
|
||||
*
|
||||
* See RFC 7616, section 3.3 for details.
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* if the "challenge" could not be added.
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
MHD_STATIC_INLINE_
|
||||
MHD_FN_PAR_NONNULL_ (1)
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
const struct MHD_Action *
|
||||
MHD_action_digest_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
|
||||
const char *MHD_RESTRICT realm,
|
||||
const char *MHD_RESTRICT opaque,
|
||||
const char *MHD_RESTRICT domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8,
|
||||
struct MHD_Response *MHD_RESTRICT response,
|
||||
enum MHD_Bool abort_if_failed)
|
||||
{
|
||||
if ((MHD_SC_OK !=
|
||||
MHD_response_add_auth_digest_challenge (response, realm, opaque, domain,
|
||||
indicate_stale, mqop, malgo,
|
||||
userhash_support, prefer_utf8))
|
||||
&& (MHD_NO != abort_if_failed))
|
||||
{
|
||||
MHD_response_destroy (response);
|
||||
return MHD_action_abort_request (request);
|
||||
}
|
||||
return MHD_action_from_response (request, response);
|
||||
}
|
||||
|
||||
|
||||
MHD_STATIC_INLINE_END_
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* 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 is used to reply without the "challenge".
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
#define MHD_action_digest_auth_challenge_p(rq,rlm,opq,dmn,stl,mqop,malgo, \
|
||||
uh,utf,resp) \
|
||||
MHD_action_digest_auth_challenge ((rq),(rlm),(opq),(dmn),(stl),(mqop), \
|
||||
(malgo),(uh),(utf),(resp),MHD_NO)
|
||||
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* 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 is aborted.
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
#define MHD_action_digest_auth_challenge_a(rq,rlm,opq,dmn,stl,mqop,malgo, \
|
||||
uh,utf,resp) \
|
||||
MHD_action_digest_auth_challenge ((rq),(rlm),(opq),(dmn),(stl),(mqop), \
|
||||
(malgo),(uh),(utf),(resp),MHD_YES)
|
||||
|
||||
#endif /* ! MHD_NO_STATIC_INLINE */
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -3325,20 +3325,32 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
|
||||
|
||||
/**
|
||||
* Create an action to request authentication from the client
|
||||
* Add Digest Authentication "challenge" to the response.
|
||||
*
|
||||
* If @a mqop allows both RFC 2069 (MHD_DIGEST_AUTH_QOP_NONE) and QOP with
|
||||
* value, then response is formed like if MHD_DIGEST_AUTH_QOP_NONE bit was
|
||||
* not set, because such response should be backward-compatible with RFC 2069.
|
||||
* The response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
|
||||
*
|
||||
* If @a mqop allows both RFC 2069 (#MHD_DIGEST_AUTH_QOP_NONE) and other QOP
|
||||
* values, then the "challenge" is formed like if MHD_DIGEST_AUTH_QOP_NONE bit
|
||||
* was not set, because such "challenge" should be backward-compatible with
|
||||
* RFC 2069.
|
||||
*
|
||||
* If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is
|
||||
* formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no
|
||||
* 'charset'). For better compatibility with clients, it is recommended (but
|
||||
* not required) to set @a domain to NULL in this mode.
|
||||
*
|
||||
* At most one action can be created for any request.
|
||||
* New nonces are generated each time when the resulting response is used.
|
||||
*
|
||||
* @param request the request
|
||||
* See RFC 7616, section 3.3 for details.
|
||||
*
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
@@ -3353,24 +3365,17 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param response the reply to send; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_FORBIDDEN status
|
||||
* code, must not have #MHD_R_O_REUSABLE enabled;
|
||||
* the NULL is tolerated (the result is NULL)
|
||||
* @param signal_stale if set to #MHD_YES then indication of stale nonce used in
|
||||
* the client's request is signalled by adding 'stale=true'
|
||||
* to the authentication header, this instructs the client
|
||||
* to retry immediately with the new nonce and the same
|
||||
* credentials, without asking user for the new password
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then MD5 is preferred (currently, may be changed in next
|
||||
* versions)
|
||||
* @param userhash_support if set to non-zero value (#MHD_YES) then support of
|
||||
* userhash is indicated, allowing client to provide
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
@@ -3382,24 +3387,265 @@ MHD_FN_PAR_CSTR_ (4);
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @return pointer to the action on success,
|
||||
* NULL on failure
|
||||
* @return #MHD_SC_OK if succeed,
|
||||
* #MHD_SC_TOO_LATE if the response has been already "frozen" (used to
|
||||
* create an action),
|
||||
* #MHD_SC_RESP_HEADERS_CONFLICT if Digest Authentication "challenge"
|
||||
* has been added already,
|
||||
* #MHD_SC_RESP_POINTER_NULL if @a response is NULL,
|
||||
* #MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE is response status code is wrong,
|
||||
* #MHD_SC_RESP_HEADER_VALUE_INVALID if @a realm, @a opaque or @a domain
|
||||
* have wrong characters or zero length (for @a realm),
|
||||
* #MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED if memory allocation failed,
|
||||
* or other error code if failed
|
||||
* @ingroup authentication
|
||||
*/
|
||||
MHD_EXTERN_ const struct MHD_Action *
|
||||
MHD_action_digest_auth_required_response (
|
||||
struct MHD_Request *request,
|
||||
const char *realm,
|
||||
const char *opaque,
|
||||
const char *domain,
|
||||
struct MHD_Response *response,
|
||||
enum MHD_Bool signal_stale,
|
||||
MHD_EXTERN_ enum MHD_StatusCode
|
||||
MHD_response_add_auth_digest_challenge (
|
||||
struct MHD_Response *MHD_RESTRICT response,
|
||||
const char *MHD_RESTRICT realm,
|
||||
const char *MHD_RESTRICT opaque,
|
||||
const char *MHD_RESTRICT domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo algo,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8)
|
||||
MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_NONNULL_ (5);
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4);
|
||||
|
||||
|
||||
#ifndef MHD_NO_STATIC_INLINE
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
|
||||
*
|
||||
* See RFC 7616, section 3.3 for details.
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* if the "challenge" could not be added.
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
MHD_STATIC_INLINE_
|
||||
MHD_FN_PAR_NONNULL_ (1)
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
const struct MHD_Action *
|
||||
MHD_action_digest_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
|
||||
const char *MHD_RESTRICT realm,
|
||||
const char *MHD_RESTRICT opaque,
|
||||
const char *MHD_RESTRICT domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8,
|
||||
struct MHD_Response *MHD_RESTRICT response,
|
||||
enum MHD_Bool abort_if_failed)
|
||||
{
|
||||
if ((MHD_SC_OK !=
|
||||
MHD_response_add_auth_digest_challenge (response, realm, opaque, domain,
|
||||
indicate_stale, mqop, malgo,
|
||||
userhash_support, prefer_utf8))
|
||||
&& (MHD_NO != abort_if_failed))
|
||||
{
|
||||
MHD_response_destroy (response);
|
||||
return MHD_action_abort_request (request);
|
||||
}
|
||||
return MHD_action_from_response (request, response);
|
||||
}
|
||||
|
||||
|
||||
MHD_STATIC_INLINE_END_
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* 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 is used to reply without the "challenge".
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
#define MHD_action_digest_auth_challenge_p(rq,rlm,opq,dmn,stl,mqop,malgo, \
|
||||
uh,utf,resp) \
|
||||
MHD_action_digest_auth_challenge ((rq),(rlm),(opq),(dmn),(stl),(mqop), \
|
||||
(malgo),(uh),(utf),(resp),MHD_NO)
|
||||
|
||||
|
||||
/**
|
||||
* Create action to reply with Digest Authentication "challenge".
|
||||
*
|
||||
* 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 is aborted.
|
||||
*
|
||||
* @param request the request to create the action for
|
||||
* @param realm the realm presented to the client
|
||||
* @param opaque the string for opaque value, can be NULL, but NULL is
|
||||
* not recommended for better compatibility with clients;
|
||||
* the recommended format is hex or Base64 encoded string
|
||||
* @param domain the optional space-separated list of URIs for which the
|
||||
* same authorisation could be used, URIs can be in form
|
||||
* "path-absolute" (the path for the same host with initial slash)
|
||||
* or in form "absolute-URI" (the full path with protocol), in
|
||||
* any case client may assume that URI is in the same "protection
|
||||
* space" if it starts with any of values specified here;
|
||||
* could be NULL (clients typically assume that the same
|
||||
* credentials could be used for any URI on the same host);
|
||||
* this list provides information for the client only and does
|
||||
* not actually restrict anything on the server side
|
||||
* @param indicate_stale if set to #MHD_YES then indication of stale nonce used
|
||||
* in the client's request is indicated by adding
|
||||
* 'stale=true' to the authentication header, this
|
||||
* instructs the client to retry immediately with the new
|
||||
* nonce and the same credentials, without asking user
|
||||
* for the new password
|
||||
* @param mqop the QOP to use
|
||||
* @param algo digest algorithm to use; if several algorithms are allowed
|
||||
* then one challenge for each allowed algorithm is added
|
||||
* @param userhash_support if set to #MHD_YES then support of userhash is
|
||||
* indicated, allowing client to provide
|
||||
* hash("username:realm") instead of the username in
|
||||
* clear text;
|
||||
* note that clients are allowed to provide the username
|
||||
* in cleartext even if this parameter set to non-zero;
|
||||
* when userhash is used, application must be ready to
|
||||
* identify users by provided userhash value instead of
|
||||
* username; see #MHD_digest_auth_calc_userhash() and
|
||||
* #MHD_digest_auth_calc_userhash_hex()
|
||||
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
|
||||
* added, indicating for the client that UTF-8 encoding for
|
||||
* the username is preferred
|
||||
* @param response the response to update; should contain the "access denied"
|
||||
* body;
|
||||
* note: this function sets the "WWW Authenticate" header and
|
||||
* the caller should not set this header;
|
||||
* the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
|
||||
* code;
|
||||
* the NULL is tolerated (the result is
|
||||
* #MHD_SC_RESP_POINTER_NULL)
|
||||
* @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
|
||||
* the @a request;
|
||||
* when failed the response object is consumed and need not
|
||||
* to be "destroyed"
|
||||
* @ingroup authentication
|
||||
*/
|
||||
#define MHD_action_digest_auth_challenge_a(rq,rlm,opq,dmn,stl,mqop,malgo, \
|
||||
uh,utf,resp) \
|
||||
MHD_action_digest_auth_challenge ((rq),(rlm),(opq),(dmn),(stl),(mqop), \
|
||||
(malgo),(uh),(utf),(resp),MHD_YES)
|
||||
|
||||
#endif /* ! MHD_NO_STATIC_INLINE */
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1621,6 +1621,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
* cannot be provided due to some error or other reasons.
|
||||
*/
|
||||
MHD_SC_INFO_GET_TYPE_UNAVAILALBE = 60204
|
||||
,
|
||||
/**
|
||||
* The type of the Digest Auth algorithm is unknown or not supported.
|
||||
*/
|
||||
MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED = 60240
|
||||
,
|
||||
/**
|
||||
* The the Digest Auth QOP value is unknown or not supported.
|
||||
*/
|
||||
MHD_SC_AUTH_DIGEST_QOP_NOT_SUPPORTED = 60241
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,6 +110,10 @@ auth_basic_OPTSOURCES = \
|
||||
auth_basic.c auth_basic.h \
|
||||
response_auth_basic.c
|
||||
|
||||
auth_digest_OPTSOURCES = \
|
||||
mhd_digest_auth_data.h mhd_auth_digest_hdr.h \
|
||||
response_auth_digest.c response_auth_digest.h
|
||||
|
||||
upgrade_OPTSOURCES = \
|
||||
mhd_upgrade.h \
|
||||
upgrade_prep.c upgrade_prep.h \
|
||||
@@ -146,6 +150,10 @@ if MHD_SUPPORT_AUTH_BASIC
|
||||
libmicrohttpd2_la_SOURCES += $(auth_basic_OPTSOURCES)
|
||||
endif
|
||||
|
||||
if MHD_SUPPORT_AUTH_DIGEST
|
||||
libmicrohttpd2_la_SOURCES += $(auth_digest_OPTSOURCES)
|
||||
endif
|
||||
|
||||
if MHD_UPGRADE_SUPPORT
|
||||
libmicrohttpd2_la_SOURCES += $(upgrade_OPTSOURCES)
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
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/mhd_auth_digest_hdr.h
|
||||
* @brief The definition of the Digest Auth response header structure
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#ifndef MHD_AUTH_DIGEST_HDR_H
|
||||
#define MHD_AUTH_DIGEST_HDR_H 1
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
#ifndef MHD_SUPPORT_AUTH_DIGEST
|
||||
#error This header should be used only if Digest Auth is build
|
||||
#endif
|
||||
|
||||
#include "mhd_str_types.h"
|
||||
#include "mhd_dlinked_list.h"
|
||||
|
||||
struct MHD_Response; /* forward declaration */
|
||||
struct mhd_RespAuthDigestHeader; /* forward declaration */
|
||||
|
||||
mhd_DLINKEDL_STRUCTS_DEFS (mhd_RespAuthDigestHeader);
|
||||
|
||||
/**
|
||||
* The Digest Auth response header (the challenge)
|
||||
*/
|
||||
struct mhd_RespAuthDigestHeader
|
||||
{
|
||||
/**
|
||||
* The complete header string, including the name, the colon, the value and
|
||||
* CRLF terminating chars
|
||||
*/
|
||||
struct MHD_String hdr;
|
||||
|
||||
/**
|
||||
* The position of the nonce placeholder in the @a hdr
|
||||
*/
|
||||
size_t nonce_pos;
|
||||
|
||||
/**
|
||||
* The links to the other headers for the same response
|
||||
*/
|
||||
mhd_DLNKDL_LINKS_TYPE (mhd_RespAuthDigestHeader) auth_d_hdrs;
|
||||
};
|
||||
|
||||
#endif /* ! MHD_AUTH_DIGEST_HDR_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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/mhd_digest_auth_data.h
|
||||
* @brief The macros and other data for Digest Auth
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#ifndef MHD_DIGEST_AUTH_DATA_H
|
||||
#define MHD_DIGEST_AUTH_DATA_H 1
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
/**
|
||||
* The name of the Auth scheme
|
||||
*/
|
||||
#define mhd_AUTH_DIGEST_SCHEME "Digest"
|
||||
|
||||
/**
|
||||
* The length of the random part of the nonce (in chars)
|
||||
*/
|
||||
#define mhd_AUTH_DIGEST_NONCE_RAND_LEN 64
|
||||
|
||||
/**
|
||||
* The length of the validity time part of the nonce (in chars)
|
||||
*/
|
||||
#define mhd_AUTH_DIGEST_NONCE_VALD_LEN 8
|
||||
|
||||
/**
|
||||
* The total length of the nonce (in chars)
|
||||
*/
|
||||
#define mhd_AUTH_DIGEST_NONCE_LEN \
|
||||
(mhd_AUTH_DIGEST_NONCE_RAND_LEN + mhd_AUTH_DIGEST_NONCE_VALD_LEN)
|
||||
|
||||
#endif /* ! MHD_DIGEST_AUTH_DATA_H */
|
||||
@@ -36,6 +36,9 @@
|
||||
|
||||
#include "mhd_dlinked_list.h"
|
||||
#include "mhd_str_types.h"
|
||||
#ifdef MHD_SUPPORT_AUTH_DIGEST
|
||||
# include "mhd_auth_digest_hdr.h"
|
||||
#endif
|
||||
|
||||
#include "mhd_iovec.h"
|
||||
|
||||
@@ -356,6 +359,13 @@ struct MHD_Response
|
||||
*/
|
||||
mhd_DLNKDL_LIST (mhd_ResponseHeader,headers);
|
||||
|
||||
#ifdef MHD_SUPPORT_AUTH_DIGEST
|
||||
/**
|
||||
* The double linked list of the Digest Auth response headers
|
||||
*/
|
||||
mhd_DLNKDL_LIST (mhd_RespAuthDigestHeader,auth_d_hdrs);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Special data for internal error responses
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
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/response_auth_digest.c
|
||||
* @brief The definitions of MHD_response_add_auth_basic_challenge() function
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
#include "sys_bool_type.h"
|
||||
|
||||
#include "mhd_unreachable.h"
|
||||
#include "mhd_assert.h"
|
||||
|
||||
#include "mhd_digest_auth_data.h"
|
||||
|
||||
#include "mhd_response.h"
|
||||
#include "mhd_locks.h"
|
||||
#include "mhd_str_types.h"
|
||||
#include <string.h>
|
||||
#include "sys_malloc.h"
|
||||
|
||||
#include "mhd_str_macros.h"
|
||||
#include "mhd_str.h"
|
||||
|
||||
#include "mhd_public_api.h"
|
||||
|
||||
#include "response_auth_digest.h"
|
||||
#include "mhd_auth_digest_hdr.h"
|
||||
|
||||
|
||||
MHD_INTERNAL
|
||||
MHD_FN_PAR_NONNULL_ (1) void
|
||||
mhd_response_remove_auth_digest_headers (struct MHD_Response*response)
|
||||
{
|
||||
struct mhd_RespAuthDigestHeader *hdr_d;
|
||||
|
||||
for (hdr_d = mhd_DLINKEDL_GET_LAST (response, auth_d_hdrs);
|
||||
NULL != hdr_d;
|
||||
hdr_d = mhd_DLINKEDL_GET_LAST (response, auth_d_hdrs))
|
||||
{
|
||||
mhd_DLINKEDL_DEL (response, hdr_d, auth_d_hdrs);
|
||||
free (hdr_d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create and add Digest Auth challenge header with specified algorithm
|
||||
* @param response the response to update
|
||||
* @param rlm the realm to use
|
||||
* @param opq the "opaque" string to use
|
||||
* @param dmn the "domain" string to use
|
||||
* @param indicate_stale whether to indicate "stale" nonce
|
||||
* @param qop_none whether to use RFC 2069 subset only
|
||||
* @param algo the algorithm to use
|
||||
* @param userhash_support whether to indicate support for "userhash"
|
||||
* @param prefer_utf8 whether to indicate UTF-8 support
|
||||
* @return #MHD_SC_OK on success,
|
||||
* error code otherwise
|
||||
*/
|
||||
static MHD_FN_PAR_NONNULL_ALL_ enum MHD_StatusCode
|
||||
response_add_auth_digest_challenge_alg (
|
||||
struct MHD_Response *restrict response,
|
||||
const struct MHD_String *restrict rlm,
|
||||
const struct MHD_StringNullable *restrict opq,
|
||||
const struct MHD_StringNullable *restrict dmn,
|
||||
enum MHD_Bool indicate_stale,
|
||||
bool qop_none,
|
||||
enum MHD_DigestAuthAlgo algo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8)
|
||||
{
|
||||
static const struct MHD_String empty_str =
|
||||
mhd_MSTR_INIT ("");
|
||||
static const struct MHD_String hdr_pref_realm_pref =
|
||||
mhd_MSTR_INIT (MHD_HTTP_HEADER_WWW_AUTHENTICATE ": " \
|
||||
mhd_AUTH_DIGEST_SCHEME " realm=\"");
|
||||
static const struct MHD_String qop_str =
|
||||
mhd_MSTR_INIT (", qop=\"auth\"");
|
||||
#ifdef MHD_SUPPORT_MD5
|
||||
static const struct MHD_String algo_mh5_str =
|
||||
mhd_MSTR_INIT (", algorithm=MD5");
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA256
|
||||
static const struct MHD_String algo_sha256_str =
|
||||
mhd_MSTR_INIT (", algorithm=SHA-256");
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA512_256
|
||||
static const struct MHD_String algo_sha512_256_str =
|
||||
mhd_MSTR_INIT (", algorithm=SHA-512-256");
|
||||
#endif
|
||||
static const struct MHD_String nonce_str =
|
||||
mhd_MSTR_INIT (", nonce=\"" \
|
||||
"00000000000000000000000000000000" \
|
||||
"00000000000000000000000000000000" \
|
||||
"00000000" \
|
||||
"\"");
|
||||
static size_t nonce_off = 9; /* Position of nonce value in the nonce_str */
|
||||
static const struct MHD_String opaque_pref =
|
||||
mhd_MSTR_INIT (", opaque=\"");
|
||||
static const struct MHD_String domain_pref =
|
||||
mhd_MSTR_INIT (", domain=\"");
|
||||
static const struct MHD_String stale_str =
|
||||
mhd_MSTR_INIT (", stale=true");
|
||||
static const struct MHD_String charset_str =
|
||||
mhd_MSTR_INIT (", charset=UTF-8");
|
||||
static const struct MHD_String userhash_str =
|
||||
mhd_MSTR_INIT (", userhash=true");
|
||||
|
||||
/* Header content:
|
||||
+ Scheme name and space;
|
||||
+ realm, quoted;
|
||||
+ qop="auth", quoted (optional);
|
||||
+ algorithm, NOT quoted (optional);
|
||||
+ nonce (placeholder), quoted;
|
||||
+ opaque, quoted (optional);
|
||||
+ domain, quoted (optional);
|
||||
+ stale=true (optional);
|
||||
+ charset=UTF-8 (optional);
|
||||
+ userhash=true (optional).
|
||||
*/
|
||||
|
||||
struct MHD_String algo_str;
|
||||
char *hdr_str;
|
||||
size_t hdr_maxlen;
|
||||
struct mhd_RespAuthDigestHeader *new_hdr;
|
||||
size_t pos;
|
||||
size_t elm_len;
|
||||
|
||||
mhd_assert ('0' == nonce_str.cstr[nonce_off]);
|
||||
mhd_assert ('0' == nonce_str.cstr[nonce_off + mhd_AUTH_DIGEST_NONCE_LEN]);
|
||||
mhd_assert ('"' == nonce_str.cstr[nonce_off - 1]);
|
||||
mhd_assert ('"' == nonce_str.cstr[nonce_off + mhd_AUTH_DIGEST_NONCE_LEN + 1]);
|
||||
|
||||
#ifdef MHD_SUPPORT_MD5
|
||||
if (MHD_DIGEST_AUTH_ALGO_MD5 == algo)
|
||||
algo_str = qop_none ? empty_str : algo_mh5_str;
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA256
|
||||
else if (MHD_DIGEST_AUTH_ALGO_SHA256 == algo)
|
||||
algo_str = algo_sha256_str;
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA512_256
|
||||
else if (MHD_DIGEST_AUTH_ALGO_SHA512_256 == algo)
|
||||
algo_str = algo_sha512_256_str;
|
||||
#endif
|
||||
else
|
||||
mhd_UNREACHABLE ();
|
||||
|
||||
/* ** Calculate the maximum length of the header string ** */
|
||||
hdr_maxlen = 0;
|
||||
|
||||
/* realm */
|
||||
hdr_maxlen += hdr_pref_realm_pref.len;
|
||||
hdr_maxlen += rlm->len * 2; /* Double length for quoting */
|
||||
hdr_maxlen += 1; /* closing quote (") */
|
||||
|
||||
/* qop */
|
||||
hdr_maxlen += qop_str.len;
|
||||
|
||||
/* algorithm */
|
||||
hdr_maxlen += algo_str.len;
|
||||
|
||||
/* nonce */
|
||||
hdr_maxlen += nonce_str.len;
|
||||
|
||||
/* opaque */
|
||||
hdr_maxlen += opaque_pref.len;
|
||||
hdr_maxlen += opq->len * 2; /* Double length for quoting */
|
||||
hdr_maxlen += 1; /* closing quote (") */
|
||||
|
||||
/* domain */
|
||||
hdr_maxlen += domain_pref.len;
|
||||
hdr_maxlen += dmn->len;
|
||||
hdr_maxlen += 1; /* closing quote (") */
|
||||
|
||||
/* stale */
|
||||
hdr_maxlen += stale_str.len;
|
||||
|
||||
/* charset */
|
||||
hdr_maxlen += charset_str.len;
|
||||
|
||||
/* userhash */
|
||||
hdr_maxlen += userhash_str.len;
|
||||
|
||||
/* CRLF */
|
||||
hdr_maxlen += 2;
|
||||
|
||||
/* ** Allocate ** */
|
||||
new_hdr = (struct mhd_RespAuthDigestHeader *)
|
||||
malloc (sizeof(struct mhd_RespAuthDigestHeader *)
|
||||
+ hdr_maxlen + 1);
|
||||
if (NULL == new_hdr)
|
||||
return MHD_SC_RESPONSE_HEADER_MEM_ALLOC_FAILED;
|
||||
hdr_str = (char *) (new_hdr + 1);
|
||||
|
||||
/* ** Build the header ** */
|
||||
pos = 0;
|
||||
|
||||
/* realm */
|
||||
memcpy (hdr_str + pos,
|
||||
hdr_pref_realm_pref.cstr,
|
||||
hdr_pref_realm_pref.len);
|
||||
pos += hdr_pref_realm_pref.len;
|
||||
elm_len = mhd_str_quote (rlm->cstr,
|
||||
rlm->len,
|
||||
hdr_str + pos,
|
||||
hdr_maxlen - pos);
|
||||
mhd_assert (0 != elm_len);
|
||||
pos += elm_len;
|
||||
hdr_str[pos++] = '"';
|
||||
|
||||
/* qop */
|
||||
if (! qop_none)
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
qop_str.cstr,
|
||||
qop_str.len);
|
||||
pos += qop_str.len;
|
||||
}
|
||||
|
||||
/* algorithm */
|
||||
if (0 != algo_str.len)
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
algo_str.cstr,
|
||||
algo_str.len);
|
||||
pos += algo_str.len;
|
||||
}
|
||||
|
||||
/* nonce */
|
||||
memcpy (hdr_str + pos,
|
||||
nonce_str.cstr,
|
||||
nonce_str.len);
|
||||
new_hdr->nonce_pos = pos + nonce_off;
|
||||
pos += nonce_str.len;
|
||||
|
||||
/* opaque */
|
||||
if (0 != opq->len)
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
opaque_pref.cstr,
|
||||
opaque_pref.len);
|
||||
pos += opaque_pref.len;
|
||||
elm_len = mhd_str_quote (opq->cstr,
|
||||
opq->len,
|
||||
hdr_str + pos,
|
||||
hdr_maxlen - pos);
|
||||
mhd_assert (0 != elm_len);
|
||||
pos += elm_len;
|
||||
hdr_str[pos++] = '"';
|
||||
}
|
||||
|
||||
/* domain */
|
||||
if (0 != dmn->len)
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
domain_pref.cstr,
|
||||
domain_pref.len);
|
||||
pos += domain_pref.len;
|
||||
memcpy (hdr_str + pos,
|
||||
dmn->cstr,
|
||||
dmn->len);
|
||||
pos += dmn->len;
|
||||
hdr_str[pos++] = '"';
|
||||
}
|
||||
|
||||
/* stale */
|
||||
if (MHD_NO != indicate_stale)
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
stale_str.cstr,
|
||||
stale_str.len);
|
||||
pos += stale_str.len;
|
||||
}
|
||||
|
||||
/* charset */
|
||||
if ((! qop_none) &&
|
||||
(MHD_NO != prefer_utf8))
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
charset_str.cstr,
|
||||
charset_str.len);
|
||||
pos += charset_str.len;
|
||||
}
|
||||
|
||||
/* userhash */
|
||||
if ((! qop_none) &&
|
||||
(MHD_NO != userhash_support))
|
||||
{
|
||||
memcpy (hdr_str + pos,
|
||||
userhash_str.cstr,
|
||||
userhash_str.len);
|
||||
pos += userhash_str.len;
|
||||
}
|
||||
|
||||
/* CRLF */
|
||||
hdr_str[pos++] = '\r';
|
||||
hdr_str[pos++] = '\n';
|
||||
|
||||
mhd_assert (pos <= hdr_maxlen);
|
||||
hdr_str[pos] = 0; /* Zero-terminate the string */
|
||||
|
||||
if (1)
|
||||
{ /* Try to shrink malloc'ed area */
|
||||
void *new_ptr;
|
||||
new_ptr = realloc (new_hdr,
|
||||
sizeof(struct mhd_RespAuthDigestHeader)
|
||||
+ pos);
|
||||
/* Just use the old pointer if realloc() failed */
|
||||
if (NULL != new_ptr)
|
||||
new_hdr = (struct mhd_RespAuthDigestHeader *) new_ptr;
|
||||
}
|
||||
|
||||
new_hdr->hdr.cstr = (char *) (new_hdr + 1);
|
||||
new_hdr->hdr.len = pos;
|
||||
mhd_assert (0 == \
|
||||
memcmp (new_hdr->hdr.cstr, \
|
||||
MHD_HTTP_HEADER_WWW_AUTHENTICATE ": ", \
|
||||
mhd_SSTR_LEN (MHD_HTTP_HEADER_WWW_AUTHENTICATE ": ")));
|
||||
mhd_assert (0 == new_hdr->hdr.cstr[new_hdr->hdr.len]);
|
||||
|
||||
mhd_DLINKEDL_INIT_LINKS (new_hdr, auth_d_hdrs);
|
||||
mhd_DLINKEDL_INS_LAST (response, new_hdr, auth_d_hdrs);
|
||||
|
||||
return MHD_SC_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create and add Digest Auth challenge headers for all specified algorithms
|
||||
* @param response the response to update
|
||||
* @param realm the real to use
|
||||
* @param opaque the "opaque" string, could be NULL
|
||||
* @param domain the "domain" string, could be NULL
|
||||
* @param indicate_stale whether to indicate "stale" nonce
|
||||
* @param mqop the QOP values to use
|
||||
* @param malgo the algorithms to use
|
||||
* @param userhash_support whether to indicate support for "userhash"
|
||||
* @param prefer_utf8 whether to indicate UTF-8 support
|
||||
* @return #MHD_SC_OK on success,
|
||||
* error code otherwise
|
||||
*/
|
||||
static MHD_FN_PAR_NONNULL_ (1)
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) enum MHD_StatusCode
|
||||
response_add_auth_digest_challenge_int (struct MHD_Response *restrict response,
|
||||
const char *restrict realm,
|
||||
const char *restrict opaque,
|
||||
const char *restrict domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8)
|
||||
{
|
||||
const struct MHD_String rlm = { strlen (realm), realm };
|
||||
const struct MHD_StringNullable opq =
|
||||
{ (NULL != opaque ? strlen (opaque) : 0), opaque };
|
||||
const struct MHD_StringNullable dmn =
|
||||
{ (NULL != domain ? strlen (domain) : 0), domain };
|
||||
const bool qop_none =
|
||||
(0 != (MHD_DIGEST_AUTH_QOP_NONE & ((unsigned int) mqop)));
|
||||
enum MHD_StatusCode res;
|
||||
|
||||
/* Check validity of the input data */
|
||||
|
||||
if (0 == rlm.len)
|
||||
return MHD_SC_RESP_HEADER_VALUE_INVALID; /* Failure exit point */
|
||||
if ((NULL != memchr (rlm.cstr, '\n', rlm.len)) ||
|
||||
(NULL != memchr (rlm.cstr, '\r', rlm.len)))
|
||||
return MHD_SC_RESP_HEADER_VALUE_INVALID; /* Failure exit point */
|
||||
|
||||
if ((0 != opq.len) &&
|
||||
((NULL != memchr (opq.cstr, '\n', opq.len)) ||
|
||||
(NULL != memchr (opq.cstr, '\r', opq.len))))
|
||||
return MHD_SC_RESP_HEADER_VALUE_INVALID; /* Failure exit point */
|
||||
|
||||
if ((0 != dmn.len) &&
|
||||
((NULL != memchr (dmn.cstr, '\n', dmn.len)) ||
|
||||
(NULL != memchr (dmn.cstr, '\r', dmn.len)) ||
|
||||
(NULL != memchr (dmn.cstr, '"', dmn.len))))
|
||||
return MHD_SC_RESP_HEADER_VALUE_INVALID; /* Failure exit point */
|
||||
|
||||
if (0 == (MHD_DIGEST_AUTH_ALGO_NON_SESSION & ((unsigned int) malgo)))
|
||||
return MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED; /* Failure exit point */
|
||||
|
||||
if (0 == ((MHD_DIGEST_AUTH_QOP_NONE | MHD_DIGEST_AUTH_QOP_AUTH)
|
||||
& ((unsigned int) mqop)))
|
||||
return MHD_SC_AUTH_DIGEST_QOP_NOT_SUPPORTED; /* Failure exit point */
|
||||
|
||||
res = MHD_SC_OK;
|
||||
|
||||
#ifdef MHD_SUPPORT_MD5
|
||||
if ((MHD_SC_OK == res) &&
|
||||
(0 == (MHD_DIGEST_BASE_ALGO_MD5 & ((unsigned int) malgo))))
|
||||
res = response_add_auth_digest_challenge_alg (response,
|
||||
&rlm,
|
||||
&opq,
|
||||
&dmn,
|
||||
indicate_stale,
|
||||
qop_none,
|
||||
MHD_DIGEST_AUTH_ALGO_MD5,
|
||||
userhash_support,
|
||||
prefer_utf8);
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA256
|
||||
if ((MHD_SC_OK == res) &&
|
||||
(0 == (MHD_DIGEST_BASE_ALGO_SHA256 & ((unsigned int) malgo))))
|
||||
res = response_add_auth_digest_challenge_alg (response,
|
||||
&rlm,
|
||||
&opq,
|
||||
&dmn,
|
||||
indicate_stale,
|
||||
qop_none,
|
||||
MHD_DIGEST_AUTH_ALGO_SHA256,
|
||||
userhash_support,
|
||||
prefer_utf8);
|
||||
#endif
|
||||
#ifdef MHD_SUPPORT_SHA512_256
|
||||
if ((MHD_SC_OK == res) &&
|
||||
(0 == (MHD_DIGEST_BASE_ALGO_SHA256 & ((unsigned int) malgo))))
|
||||
res = response_add_auth_digest_challenge_alg (
|
||||
response,
|
||||
&rlm,
|
||||
&opq,
|
||||
&dmn,
|
||||
indicate_stale,
|
||||
qop_none,
|
||||
MHD_DIGEST_AUTH_ALGO_SHA512_256,
|
||||
userhash_support,
|
||||
prefer_utf8);
|
||||
#endif
|
||||
|
||||
if (MHD_SC_OK != res)
|
||||
{
|
||||
mhd_response_remove_auth_digest_headers (response);
|
||||
return res; /* Failure exit point */
|
||||
}
|
||||
|
||||
if (NULL == mhd_DLINKEDL_GET_FIRST (response, auth_d_hdrs))
|
||||
return MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED; /* Failure exit point */
|
||||
|
||||
return MHD_SC_OK; /* Success exit point */
|
||||
}
|
||||
|
||||
|
||||
MHD_EXTERN_
|
||||
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
|
||||
MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4) enum MHD_StatusCode
|
||||
MHD_response_add_auth_digest_challenge (
|
||||
struct MHD_Response *MHD_RESTRICT response,
|
||||
const char *MHD_RESTRICT realm,
|
||||
const char *MHD_RESTRICT opaque,
|
||||
const char *MHD_RESTRICT domain,
|
||||
enum MHD_Bool indicate_stale,
|
||||
enum MHD_DigestAuthMultiQOP mqop,
|
||||
enum MHD_DigestAuthMultiAlgo malgo,
|
||||
enum MHD_Bool userhash_support,
|
||||
enum MHD_Bool prefer_utf8)
|
||||
{
|
||||
bool need_unlock;
|
||||
enum MHD_StatusCode res;
|
||||
|
||||
if (NULL == response)
|
||||
return MHD_SC_RESP_POINTER_NULL;
|
||||
if (response->frozen)
|
||||
return MHD_SC_TOO_LATE;
|
||||
if (MHD_HTTP_STATUS_UNAUTHORIZED != response->sc)
|
||||
return MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE;
|
||||
|
||||
if (response->reuse.reusable)
|
||||
{
|
||||
need_unlock = true;
|
||||
if (! mhd_mutex_lock (&(response->reuse.settings_lock)))
|
||||
return MHD_SC_RESPONSE_MUTEX_LOCK_FAILED;
|
||||
mhd_assert (1 == mhd_atomic_counter_get (&(response->reuse.counter)));
|
||||
}
|
||||
else
|
||||
need_unlock = false;
|
||||
|
||||
if (response->frozen) /* Re-check with the lock held */
|
||||
res = MHD_SC_TOO_LATE;
|
||||
else if (NULL != mhd_DLINKEDL_GET_FIRST (response, auth_d_hdrs))
|
||||
res = MHD_SC_RESP_HEADERS_CONFLICT;
|
||||
else
|
||||
res = response_add_auth_digest_challenge_int (response,
|
||||
realm,
|
||||
opaque,
|
||||
domain,
|
||||
indicate_stale,
|
||||
mqop,
|
||||
malgo,
|
||||
userhash_support,
|
||||
prefer_utf8);
|
||||
|
||||
if (need_unlock)
|
||||
mhd_mutex_unlock_chk (&(response->reuse.settings_lock));
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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/response_auth_digest.h
|
||||
* @brief The declaration of the Digest Auth response header helper functions
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#ifndef MHD_RESPONSE_AUTH_DIGEST_H
|
||||
#define MHD_RESPONSE_AUTH_DIGEST_H 1
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
struct MHD_Response; /* forward declaration */
|
||||
|
||||
/**
|
||||
* Remove all Digest Auth headers (if any) from the response
|
||||
* @param response the response to clean
|
||||
*/
|
||||
MHD_INTERNAL void
|
||||
mhd_response_remove_auth_digest_headers (struct MHD_Response*response)
|
||||
MHD_FN_PAR_NONNULL_ (1);
|
||||
|
||||
#endif /* ! MHD_RESPONSE_AUTH_DIGEST_H */
|
||||
@@ -40,6 +40,10 @@
|
||||
#include "response_funcs.h"
|
||||
#include "response_from.h"
|
||||
|
||||
#ifdef MHD_SUPPORT_AUTH_DIGEST
|
||||
# include "response_auth_digest.h"
|
||||
#endif
|
||||
|
||||
#define mhd_RESPONSE_DESTOYED "Attempt to use destroyed response, " \
|
||||
"re-use non-reusable response or wrong MHD_Response pointer"
|
||||
|
||||
@@ -52,6 +56,9 @@
|
||||
static MHD_FN_PAR_NONNULL_ (1) void
|
||||
response_full_deinit (struct MHD_Response *restrict r)
|
||||
{
|
||||
#ifdef MHD_SUPPORT_AUTH_DIGEST
|
||||
mhd_response_remove_auth_digest_headers (r);
|
||||
#endif
|
||||
mhd_response_remove_all_headers (r);
|
||||
if (NULL != r->special_resp.spec_hdr)
|
||||
free (r->special_resp.spec_hdr);
|
||||
|
||||
@@ -68,6 +68,9 @@ response_create_basic (enum MHD_HTTP_StatusCode sc,
|
||||
{
|
||||
#ifndef HAVE_NULL_PTR_ALL_ZEROS
|
||||
mhd_DLINKEDL_INIT_LIST (r, headers);
|
||||
#ifdef MHD_SUPPORT_AUTH_DIGEST
|
||||
mhd_DLINKEDL_INIT_LIST (r, auth_d_hdrs);
|
||||
#endif
|
||||
r->free.cb = NULL;
|
||||
r->free.cls = NULL;
|
||||
r->special_resp.spec_hdr = NULL;
|
||||
|
||||
+10
-10
@@ -175,10 +175,10 @@ if MHD_SUPPORT_AUTH_DIGEST
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
digestauth.c digestauth.h \
|
||||
mhd_bithelpers.h mhd_byteorder.h mhd_align.h
|
||||
if ENABLE_MD5
|
||||
if MHD_SUPPORT_MD5
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
mhd_md5_wrap.h
|
||||
if ! ENABLE_MD5_EXT
|
||||
if ! MHD_MD5_EXTR
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
md5.c md5.h
|
||||
else
|
||||
@@ -186,10 +186,10 @@ libmicrohttpd_la_SOURCES += \
|
||||
md5_ext.c md5_ext.h
|
||||
endif
|
||||
endif
|
||||
if ENABLE_SHA256
|
||||
if MHD_SUPPORT_SHA256
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
mhd_sha256_wrap.h
|
||||
if ! ENABLE_SHA256_EXT
|
||||
if ! MHD_SHA256_EXTR
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
sha256.c sha256.h
|
||||
else
|
||||
@@ -197,7 +197,7 @@ libmicrohttpd_la_SOURCES += \
|
||||
sha256_ext.c sha256_ext.h
|
||||
endif
|
||||
endif
|
||||
if ENABLE_SHA512_256
|
||||
if MHD_SUPPORT_SHA512_256
|
||||
libmicrohttpd_la_SOURCES += \
|
||||
sha512_256.c sha512_256.h
|
||||
endif
|
||||
@@ -244,15 +244,15 @@ check_PROGRAMS = \
|
||||
test_mhd_version \
|
||||
test_set_panic
|
||||
|
||||
if ENABLE_MD5
|
||||
if MHD_SUPPORT_MD5
|
||||
check_PROGRAMS += \
|
||||
test_md5
|
||||
endif
|
||||
if ENABLE_SHA256
|
||||
if MHD_SUPPORT_SHA256
|
||||
check_PROGRAMS += \
|
||||
test_sha256
|
||||
endif
|
||||
if ENABLE_SHA512_256
|
||||
if MHD_SUPPORT_SHA512_256
|
||||
check_PROGRAMS += \
|
||||
test_sha512_256
|
||||
endif
|
||||
@@ -518,7 +518,7 @@ test_http_reasons_SOURCES = \
|
||||
|
||||
test_md5_SOURCES = \
|
||||
test_md5.c test_helpers.h mhd_md5_wrap.h ../include/mhd_options.h
|
||||
if ! ENABLE_MD5_EXT
|
||||
if ! MHD_MD5_EXTR
|
||||
test_md5_SOURCES += \
|
||||
md5.c md5.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
|
||||
test_md5_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
@@ -536,7 +536,7 @@ endif
|
||||
|
||||
test_sha256_SOURCES = \
|
||||
test_sha256.c test_helpers.h mhd_sha256_wrap.h ../include/mhd_options.h
|
||||
if ! ENABLE_SHA256_EXT
|
||||
if ! MHD_SHA256_EXTR
|
||||
test_sha256_SOURCES += \
|
||||
sha256.c sha256.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
|
||||
test_sha256_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
@@ -181,18 +181,18 @@ endif
|
||||
|
||||
|
||||
if MHD_SUPPORT_AUTH_DIGEST
|
||||
if ENABLE_MD5
|
||||
if MHD_SUPPORT_MD5
|
||||
THREAD_ONLY_TESTS += \
|
||||
test_digestauth \
|
||||
test_digestauth_with_arguments \
|
||||
test_digestauth_concurrent
|
||||
endif
|
||||
if ENABLE_SHA256
|
||||
if MHD_SUPPORT_SHA256
|
||||
THREAD_ONLY_TESTS += \
|
||||
test_digestauth_sha256
|
||||
endif
|
||||
|
||||
if ENABLE_MD5
|
||||
if MHD_SUPPORT_MD5
|
||||
check_PROGRAMS += \
|
||||
test_digestauth_emu_ext \
|
||||
test_digestauth_emu_ext_oldapi \
|
||||
@@ -211,7 +211,7 @@ check_PROGRAMS += \
|
||||
test_digestauth2_oldapi1_bind_all \
|
||||
test_digestauth2_oldapi1_bind_uri
|
||||
endif
|
||||
if ENABLE_SHA256
|
||||
if MHD_SUPPORT_SHA256
|
||||
check_PROGRAMS += \
|
||||
test_digestauth2_sha256 \
|
||||
test_digestauth2_sha256_userhash \
|
||||
|
||||
Reference in New Issue
Block a user