aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-10-06 17:59:16 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-10-06 17:59:16 +0300
commit6336d8c796a30971e0eb57d5658de064e3c3be45 (patch)
tree713c685940e9b288e1bb076c904158ac9c71f5dd
parentce38b0fa79f0f0fc537163d39c1db0d76d616eb0 (diff)
downloadlibmicrohttpd-6336d8c796a30971e0eb57d5658de064e3c3be45.tar.gz
libmicrohttpd-6336d8c796a30971e0eb57d5658de064e3c3be45.zip
digest auth: updated header, slightly modified multi-value processing
-rw-r--r--src/include/microhttpd.h159
-rw-r--r--src/microhttpd/digestauth.c78
2 files changed, 143 insertions, 94 deletions
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index e8057ae5..738361dd 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -4718,7 +4718,7 @@ enum MHD_DigestAuthMultiAlgo3
4718 MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION, 4718 MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION,
4719 4719
4720 /** 4720 /**
4721 * The 'SHA-512-256' (SHA-512/256) algorithm. 4721 * The 'SHA-512-256' (SHA-512/256) algorithm, non-session version.
4722 */ 4722 */
4723 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256, 4723 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256,
4724 4724
@@ -4731,47 +4731,69 @@ enum MHD_DigestAuthMultiAlgo3
4731 MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION, 4731 MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION,
4732 4732
4733 /** 4733 /**
4734 * Any non-session algorithm, MHD will choose. 4734 * SHA-256 or SHA-512/256 non-session algorithm, MHD will choose
4735 * the preferred or the matching one.
4736 */
4737 MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_NON_SESSION =
4738 MHD_DIGEST_AUTH_ALGO3_SHA256 | MHD_DIGEST_AUTH_ALGO3_SHA512_256,
4739
4740 /**
4741 * Any non-session algorithm, MHD will choose the preferred or
4742 * the matching one.
4735 */ 4743 */
4736 MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION = 4744 MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION =
4737 (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION, 4745 (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION,
4738 4746
4739 /** 4747 /**
4740 * Any session algorithm, MHD will choose. 4748 * The SHA-256 or SHA-512/256 session algorithm.
4741 * Not supported by MHD. 4749 * Not supported by MHD.
4742 * Reserved value. 4750 * Reserved value.
4743 */ 4751 */
4744 MHD_DIGEST_AUTH_MULT_ALGO3_ANY_SESSION = 4752 MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_SESSION =
4745 (0x3F) | MHD_DIGEST_AUTH_ALGO3_SESSION, 4753 MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION
4754 | MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION,
4746 4755
4747 /** 4756 /**
4748 * The 'MD5' algorithm, session or non-session. 4757 * Any session algorithm.
4749 * Not supported by MHD. 4758 * Not supported by MHD.
4750 * Reserved value. 4759 * Reserved value.
4751 */ 4760 */
4761 MHD_DIGEST_AUTH_MULT_ALGO3_ANY_SESSION =
4762 (0x3F) | MHD_DIGEST_AUTH_ALGO3_SESSION,
4763
4764 /**
4765 * The MD5 algorithm, session or non-session.
4766 * Currently supported as non-session only.
4767 */
4752 MHD_DIGEST_AUTH_MULT_ALGO3_MD5_ANY = 4768 MHD_DIGEST_AUTH_MULT_ALGO3_MD5_ANY =
4753 MHD_DIGEST_AUTH_MULT_ALGO3_MD5 | MHD_DIGEST_AUTH_MULT_ALGO3_MD5_SESSION, 4769 MHD_DIGEST_AUTH_MULT_ALGO3_MD5 | MHD_DIGEST_AUTH_MULT_ALGO3_MD5_SESSION,
4754 4770
4755 /** 4771 /**
4756 * The 'SHA-256' algorithm, session or non-session. 4772 * The SHA-256 algorithm, session or non-session.
4757 * Not supported by MHD. 4773 * Currently supported as non-session only.
4758 * Reserved value.
4759 */ 4774 */
4760 MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_ANY = 4775 MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_ANY =
4761 MHD_DIGEST_AUTH_MULT_ALGO3_SHA256 4776 MHD_DIGEST_AUTH_MULT_ALGO3_SHA256
4762 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION, 4777 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION,
4763 4778
4764 /** 4779 /**
4765 * The 'SHA-512/256' algorithm, session or non-session. 4780 * The SHA-512/256 algorithm, session or non-session.
4766 * Not supported by MHD. 4781 * Currently supported as non-session only.
4767 * Reserved value.
4768 */ 4782 */
4769 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_ANY = 4783 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_ANY =
4770 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 4784 MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256
4771 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION, 4785 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION,
4772 4786
4773 /** 4787 /**
4774 * Any algorithm, MHD will choose. 4788 * The SHA-256 or SHA-512/256 algorithm, session or non-session.
4789 * Currently supported as non-session only.
4790 */
4791 MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_ANY =
4792 MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_NON_SESSION
4793 | MHD_DIGEST_AUTH_MULT_ALGO3_SHA_ANY_SESSION,
4794
4795 /**
4796 * Any algorithm, MHD will choose the preferred or the matching one.
4775 */ 4797 */
4776 MHD_DIGEST_AUTH_MULT_ALGO3_ANY = 4798 MHD_DIGEST_AUTH_MULT_ALGO3_ANY =
4777 (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION | MHD_DIGEST_AUTH_ALGO3_SESSION 4799 (0x3F) | MHD_DIGEST_AUTH_ALGO3_NON_SESSION | MHD_DIGEST_AUTH_ALGO3_SESSION
@@ -4783,7 +4805,7 @@ enum MHD_DigestAuthMultiAlgo3
4783 * 4805 *
4784 * The "userhash" is the hash of the string "username:realm". 4806 * The "userhash" is the hash of the string "username:realm".
4785 * 4807 *
4786 * The "Userhash" could be used to avoid sending username in cleartext in Digest 4808 * The "userhash" could be used to avoid sending username in cleartext in Digest
4787 * Authorization client's header. 4809 * Authorization client's header.
4788 * 4810 *
4789 * Userhash is not designed to hide the username in local database or files, 4811 * Userhash is not designed to hide the username in local database or files,
@@ -4795,7 +4817,7 @@ enum MHD_DigestAuthMultiAlgo3
4795 * when loading list of the usernames to generate the userhash for every loaded 4817 * when loading list of the usernames to generate the userhash for every loaded
4796 * username (this will cause delays at the start with the long lists). 4818 * username (this will cause delays at the start with the long lists).
4797 * 4819 *
4798 * Once "userhash" is generated it could be used to identify users for clients 4820 * Once "userhash" is generated it could be used to identify users by clients
4799 * with "userhash" support. 4821 * with "userhash" support.
4800 * Avoid repetitive usage of this function for the same username/realm 4822 * Avoid repetitive usage of this function for the same username/realm
4801 * combination as it will cause excessive CPU load; save and re-use the result 4823 * combination as it will cause excessive CPU load; save and re-use the result
@@ -4814,6 +4836,7 @@ enum MHD_DigestAuthMultiAlgo3
4814 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is 4836 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
4815 * not supported (or external error has occurred, 4837 * not supported (or external error has occurred,
4816 * see #MHD_FEATURE_EXTERN_HASH) 4838 * see #MHD_FEATURE_EXTERN_HASH)
4839 * @sa #MHD_digest_auth_calc_userhash_hex()
4817 * @note Available since #MHD_VERSION 0x00097701 4840 * @note Available since #MHD_VERSION 0x00097701
4818 * @ingroup authentication 4841 * @ingroup authentication
4819 */ 4842 */
@@ -4826,11 +4849,11 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
4826 4849
4827 4850
4828/** 4851/**
4829 * Calculate "userhash", return it as hexadecimal data. 4852 * Calculate "userhash", return it as hexadecimal string.
4830 * 4853 *
4831 * The "userhash" is the hash of the string "username:realm". 4854 * The "userhash" is the hash of the string "username:realm".
4832 * 4855 *
4833 * The "Userhash" could be used to avoid sending username in cleartext in Digest 4856 * The "userhash" could be used to avoid sending username in cleartext in Digest
4834 * Authorization client's header. 4857 * Authorization client's header.
4835 * 4858 *
4836 * Userhash is not designed to hide the username in local database or files, 4859 * Userhash is not designed to hide the username in local database or files,
@@ -4842,7 +4865,7 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
4842 * when loading list of the usernames to generate the userhash for every loaded 4865 * when loading list of the usernames to generate the userhash for every loaded
4843 * username (this will cause delays at the start with the long lists). 4866 * username (this will cause delays at the start with the long lists).
4844 * 4867 *
4845 * Once "userhash" is generated it could be used to identify users for clients 4868 * Once "userhash" is generated it could be used to identify users by clients
4846 * with "userhash" support. 4869 * with "userhash" support.
4847 * Avoid repetitive usage of this function for the same username/realm 4870 * Avoid repetitive usage of this function for the same username/realm
4848 * combination as it will cause excessive CPU load; save and re-use the result 4871 * combination as it will cause excessive CPU load; save and re-use the result
@@ -4851,16 +4874,17 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
4851 * @param algo3 the algorithm for userhash calculations 4874 * @param algo3 the algorithm for userhash calculations
4852 * @param username the username 4875 * @param username the username
4853 * @param realm the realm 4876 * @param realm the realm
4854 * @param[out] userhash_hex the output buffer for userhash as hex data; 4877 * @param[out] userhash_hex the output buffer for userhash as hex string;
4855 * if this function succeeds, then this buffer has 4878 * if this function succeeds, then this buffer has
4856 * #MHD_digest_get_hash_size(algo3)*2 chars long 4879 * #MHD_digest_get_hash_size(algo3)*2 chars long
4857 * userhash string 4880 * userhash zero-terminated string
4858 * @param bin_buf_size the size of the @a userhash_bin buffer, must be 4881 * @param bin_buf_size the size of the @a userhash_bin buffer, must be
4859 * at least #MHD_digest_get_hash_size(algo3)*2+1 chars long 4882 * at least #MHD_digest_get_hash_size(algo3)*2+1 chars long
4860 * @return MHD_YES on success, 4883 * @return MHD_YES on success,
4861 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is 4884 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
4862 * not supported (or external error has occurred, 4885 * not supported (or external error has occurred,
4863 * see #MHD_FEATURE_EXTERN_HASH). 4886 * see #MHD_FEATURE_EXTERN_HASH).
4887 * @sa #MHD_digest_auth_calc_userhash()
4864 * @note Available since #MHD_VERSION 0x00097701 4888 * @note Available since #MHD_VERSION 0x00097701
4865 * @ingroup authentication 4889 * @ingroup authentication
4866 */ 4890 */
@@ -4882,7 +4906,7 @@ MHD_digest_auth_calc_userhash_hex (enum MHD_DigestAuthAlgo3 algo3,
4882 * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH) is true if username is 4906 * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH) is true if username is
4883 * provided in any form 4907 * provided in any form
4884 * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD) is true if username is 4908 * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD) is true if username is
4885 * provided in clear text (not userhash matching is needed) 4909 * provided in clear text (no userhash matching is needed)
4886 * 4910 *
4887 * @note Available since #MHD_VERSION 0x00097701 4911 * @note Available since #MHD_VERSION 0x00097701
4888 */ 4912 */
@@ -4920,7 +4944,7 @@ enum MHD_DigestAuthUsernameType
4920 * * both 'username' and 'username*' are used 4944 * * both 'username' and 'username*' are used
4921 * * 'username*' is used with 'userhash=true' 4945 * * 'username*' is used with 'userhash=true'
4922 * * 'username*' used with invalid extended notation 4946 * * 'username*' used with invalid extended notation
4923 * * 'username' is not hexadecimal digits, while 'userhash' set to 'true' 4947 * * 'username' is not hexadecimal string, while 'userhash' set to 'true'
4924 */ 4948 */
4925 MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = (1 << 0) 4949 MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = (1 << 0)
4926} _MHD_FIXED_ENUM; 4950} _MHD_FIXED_ENUM;
@@ -5008,8 +5032,7 @@ enum MHD_DigestAuthMultiQOP
5008 5032
5009 /** 5033 /**
5010 * Any 'auth' QOP type ('auth' or 'auth-int'). 5034 * Any 'auth' QOP type ('auth' or 'auth-int').
5011 * Not supported by MHD. 5035 * Currently supported as 'auth' QOP type only.
5012 * Reserved value.
5013 */ 5036 */
5014 MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY = 5037 MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY =
5015 MHD_DIGEST_AUTH_QOP_AUTH | MHD_DIGEST_AUTH_QOP_AUTH_INT 5038 MHD_DIGEST_AUTH_QOP_AUTH | MHD_DIGEST_AUTH_QOP_AUTH_INT
@@ -5053,7 +5076,9 @@ struct MHD_DigestAuthInfo
5053 * with charset and language tag removed (i.e. it is original username 5076 * with charset and language tag removed (i.e. it is original username
5054 * extracted from the extended notation). 5077 * extracted from the extended notation).
5055 * When userhash is used by the client, this member is NULL and 5078 * When userhash is used by the client, this member is NULL and
5056 * @a userhash_hex is set. 5079 * @a userhash_hex and @a userhash_bin are set.
5080 * The buffer pointed by the @a username becomes invalid when the pointer
5081 * to the structure is freed by #MHD_free().
5057 */ 5082 */
5058 char *username; 5083 char *username;
5059 5084
@@ -5068,6 +5093,8 @@ struct MHD_DigestAuthInfo
5068 * Valid only if username type is userhash. 5093 * Valid only if username type is userhash.
5069 * This is unqoted string without decoding of the hexadecimal 5094 * This is unqoted string without decoding of the hexadecimal
5070 * digits (as provided by the client). 5095 * digits (as provided by the client).
5096 * The buffer pointed by the @a userhash_hex becomes invalid when the pointer
5097 * to the structure is freed by #MHD_free().
5071 * @sa #MHD_digest_auth_calc_userhash_hex() 5098 * @sa #MHD_digest_auth_calc_userhash_hex()
5072 */ 5099 */
5073 char *userhash_hex; 5100 char *userhash_hex;
@@ -5085,7 +5112,9 @@ struct MHD_DigestAuthInfo
5085 * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes 5112 * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes
5086 * long. 5113 * long.
5087 * The valid size should be #MHD_digest_get_hash_size(algo3) bytes. 5114 * The valid size should be #MHD_digest_get_hash_size(algo3) bytes.
5088 * @warning This is binary data, no zero termination. 5115 * The buffer pointed by the @a userhash_bin becomes invalid when the pointer
5116 * to the structure is freed by #MHD_free().
5117 * @warning This is a binary data, no zero termination.
5089 * @warning To avoid buffer overruns, always check the size of the data before 5118 * @warning To avoid buffer overruns, always check the size of the data before
5090 * use, because @a userhash_bin can point even to zero-sized 5119 * use, because @a userhash_bin can point even to zero-sized
5091 * data. 5120 * data.
@@ -5096,6 +5125,8 @@ struct MHD_DigestAuthInfo
5096 /** 5125 /**
5097 * The 'opaque' parameter value, as specified by client. 5126 * The 'opaque' parameter value, as specified by client.
5098 * NULL if not specified by client. 5127 * NULL if not specified by client.
5128 * The buffer pointed by the @a opaque becomes invalid when the pointer
5129 * to the structure is freed by #MHD_free().
5099 */ 5130 */
5100 char *opaque; 5131 char *opaque;
5101 5132
@@ -5108,6 +5139,8 @@ struct MHD_DigestAuthInfo
5108 /** 5139 /**
5109 * The 'realm' parameter value, as specified by client. 5140 * The 'realm' parameter value, as specified by client.
5110 * NULL if not specified by client. 5141 * NULL if not specified by client.
5142 * The buffer pointed by the @a realm becomes invalid when the pointer
5143 * to the structure is freed by #MHD_free().
5111 */ 5144 */
5112 char *realm; 5145 char *realm;
5113 5146
@@ -5135,8 +5168,9 @@ struct MHD_DigestAuthInfo
5135 /** 5168 /**
5136 * The nc parameter value. 5169 * The nc parameter value.
5137 * Can be used by application to limit the number of nonce re-uses. If @a nc 5170 * Can be used by application to limit the number of nonce re-uses. If @a nc
5138 * is higher than application wants to allow, then auth required response with 5171 * is higher than application wants to allow, then "auth required" response
5139 * 'stale=true' could be used to force client to retry with the fresh 'nonce'. 5172 * with 'stale=true' could be used to force client to retry with the fresh
5173 * 'nonce'.
5140 * If not specified by client or does not have hexadecimal digits only, the 5174 * If not specified by client or does not have hexadecimal digits only, the
5141 * value is #MHD_DIGEST_AUTH_INVALID_NC_VALUE. 5175 * value is #MHD_DIGEST_AUTH_INVALID_NC_VALUE.
5142 */ 5176 */
@@ -5193,7 +5227,9 @@ struct MHD_DigestAuthUsernameInfo
5193 * with charset and language tag removed (i.e. it is original username 5227 * with charset and language tag removed (i.e. it is original username
5194 * extracted from the extended notation). 5228 * extracted from the extended notation).
5195 * When userhash is used by the client, this member is NULL and 5229 * When userhash is used by the client, this member is NULL and
5196 * @a userhash_hex is set. 5230 * @a userhash_hex and @a userhash_bin are set.
5231 * The buffer pointed by the @a username becomes invalid when the pointer
5232 * to the structure is freed by #MHD_free().
5197 */ 5233 */
5198 char *username; 5234 char *username;
5199 5235
@@ -5208,6 +5244,8 @@ struct MHD_DigestAuthUsernameInfo
5208 * Valid only if username type is userhash. 5244 * Valid only if username type is userhash.
5209 * This is unqoted string without decoding of the hexadecimal 5245 * This is unqoted string without decoding of the hexadecimal
5210 * digits (as provided by the client). 5246 * digits (as provided by the client).
5247 * The buffer pointed by the @a userhash_hex becomes invalid when the pointer
5248 * to the structure is freed by #MHD_free().
5211 * @sa #MHD_digest_auth_calc_userhash_hex() 5249 * @sa #MHD_digest_auth_calc_userhash_hex()
5212 */ 5250 */
5213 char *userhash_hex; 5251 char *userhash_hex;
@@ -5225,7 +5263,9 @@ struct MHD_DigestAuthUsernameInfo
5225 * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes 5263 * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes
5226 * long. 5264 * long.
5227 * The valid size should be #MHD_digest_get_hash_size(algo3) bytes. 5265 * The valid size should be #MHD_digest_get_hash_size(algo3) bytes.
5228 * @warning This is binary data, no zero termination. 5266 * The buffer pointed by the @a userhash_bin becomes invalid when the pointer
5267 * to the structure is freed by #MHD_free().
5268 * @warning This is a binary data, no zero termination.
5229 * @warning To avoid buffer overruns, always check the size of the data before 5269 * @warning To avoid buffer overruns, always check the size of the data before
5230 * use, because @a userhash_bin can point even to zero-sized 5270 * use, because @a userhash_bin can point even to zero-sized
5231 * data. 5271 * data.
@@ -5352,16 +5392,17 @@ enum MHD_DigestAuthResult
5352 * @a mqop and the client uses this mode, then server generated nonces are 5392 * @a mqop and the client uses this mode, then server generated nonces are
5353 * used as one-time nonces because nonce-count is not supported in this old RFC. 5393 * used as one-time nonces because nonce-count is not supported in this old RFC.
5354 * Communication in this mode is very inefficient, especially if the client 5394 * Communication in this mode is very inefficient, especially if the client
5355 * requests several resources one-by-one as for every request new nonce must be 5395 * requests several resources one-by-one as for every request a new nonce must
5356 * generated and client repeat all requests twice (first time to get a new 5396 * be generated and client repeats all requests twice (first time to get a new
5357 * nonce and second time to perform an authorised request). 5397 * nonce and second time to perform an authorised request).
5358 * 5398 *
5359 * @param connection the MHD connection structure 5399 * @param connection the MHD connection structure
5360 * @param realm the realm to be used for authorization of the client 5400 * @param realm the realm for authorization of the client
5361 * @param username the username needs to be authenticated, must be in clear text 5401 * @param username the username to be authenticated, must be in clear text
5362 * even if userhash is used by the client 5402 * even if userhash is used by the client
5363 * @param password the password used in the authentication 5403 * @param password the password matching the @a username (and the @a realm)
5364 * @param nonce_timeout the nonce validity duration in seconds 5404 * @param nonce_timeout the period of seconds since nonce generation, when
5405 * the nonce is recognised as valid and not stale.
5365 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc 5406 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
5366 * exceeds the specified value then MHD_DAUTH_NONCE_STALE is 5407 * exceeds the specified value then MHD_DAUTH_NONCE_STALE is
5367 * returned; 5408 * returned;
@@ -5386,7 +5427,7 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
5386 5427
5387 5428
5388/** 5429/**
5389 * Calculate userdigest, return it as binary data. 5430 * Calculate userdigest, return it as a binary data.
5390 * 5431 *
5391 * The "userdigest" is the hash of the "username:realm:password" string. 5432 * The "userdigest" is the hash of the "username:realm:password" string.
5392 * 5433 *
@@ -5403,7 +5444,7 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
5403 * @param algo3 the digest algorithm 5444 * @param algo3 the digest algorithm
5404 * @param username the username 5445 * @param username the username
5405 * @param realm the realm 5446 * @param realm the realm
5406 * @param password the password, must be zero-terminated 5447 * @param password the password
5407 * @param[out] userdigest_bin the output buffer for userdigest; 5448 * @param[out] userdigest_bin the output buffer for userdigest;
5408 * if this function succeeds, then this buffer has 5449 * if this function succeeds, then this buffer has
5409 * #MHD_digest_get_hash_size(algo3) bytes of 5450 * #MHD_digest_get_hash_size(algo3) bytes of
@@ -5435,13 +5476,13 @@ MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 algo3,
5435 * @a mqop and the client uses this mode, then server generated nonces are 5476 * @a mqop and the client uses this mode, then server generated nonces are
5436 * used as one-time nonces because nonce-count is not supported in this old RFC. 5477 * used as one-time nonces because nonce-count is not supported in this old RFC.
5437 * Communication in this mode is very inefficient, especially if the client 5478 * Communication in this mode is very inefficient, especially if the client
5438 * requests several resources one-by-one as for every request new nonce must be 5479 * requests several resources one-by-one as for every request a new nonce must
5439 * generated and client repeat all requests twice (first time to get a new 5480 * be generated and client repeats all requests twice (first time to get a new
5440 * nonce and second time to perform an authorised request). 5481 * nonce and second time to perform an authorised request).
5441 * 5482 *
5442 * @param connection the MHD connection structure 5483 * @param connection the MHD connection structure
5443 * @param realm the realm to be used for authorization of the client 5484 * @param realm the realm for authorization of the client
5444 * @param username the username needs to be authenticated, must be in clear text 5485 * @param username the username to be authenticated, must be in clear text
5445 * even if userhash is used by the client 5486 * even if userhash is used by the client
5446 * @param userdigest the precalculated binary hash of the string 5487 * @param userdigest the precalculated binary hash of the string
5447 * "username:realm:password", 5488 * "username:realm:password",
@@ -5508,22 +5549,26 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection *connection,
5508 * any case client may assume that URI is in the same "protection 5549 * any case client may assume that URI is in the same "protection
5509 * space" if it starts with any of values specified here; 5550 * space" if it starts with any of values specified here;
5510 * could be NULL (clients typically assume that the same 5551 * could be NULL (clients typically assume that the same
5511 * credentials could be used for any URI on the same host) 5552 * credentials could be used for any URI on the same host);
5553 * this list provides information for the client only and does
5554 * not actually restrict anything on the server side
5512 * @param response the reply to send; should contain the "access denied" 5555 * @param response the reply to send; should contain the "access denied"
5513 * body; note that this function sets the "WWW Authenticate" 5556 * body;
5514 * header and that the caller should not do this; 5557 * note: this function sets the "WWW Authenticate" header and
5558 * the caller should not set this header;
5515 * the NULL is tolerated 5559 * the NULL is tolerated
5516 * @param signal_stale set to #MHD_YES if the nonce is stale to add 'stale=true' 5560 * @param signal_stale if set to #MHD_YES then indication of stale nonce used in
5561 * the client's request is signalled by adding 'stale=true'
5517 * to the authentication header, this instructs the client 5562 * to the authentication header, this instructs the client
5518 * to retry immediately with the new nonce and the same 5563 * to retry immediately with the new nonce and the same
5519 * credentials, without asking user for the new password 5564 * credentials, without asking user for the new password
5520 * @param mqop the QOP to use 5565 * @param mqop the QOP to use
5521 * @param malgo3 digest algorithm to use, MHD selects; if several algorithms 5566 * @param malgo3 digest algorithm to use; if several algorithms are allowed
5522 * are allowed then MD5 is preferred (currently, may be changed 5567 * then MD5 is preferred (currently, may be changed in next
5523 * in next versions) 5568 * versions)
5524 * @param userhash_support if set to non-zero value (#MHD_YES) then support of 5569 * @param userhash_support if set to non-zero value (#MHD_YES) then support of
5525 * userhash is indicated, the client may provide 5570 * userhash is indicated, allowing client to provide
5526 * hash("username:realm") instead of username in 5571 * hash("username:realm") instead of the username in
5527 * clear text; 5572 * clear text;
5528 * note that clients are allowed to provide the username 5573 * note that clients are allowed to provide the username
5529 * in cleartext even if this parameter set to non-zero; 5574 * in cleartext even if this parameter set to non-zero;
@@ -5532,8 +5577,8 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection *connection,
5532 * username; see #MHD_digest_auth_calc_userhash() and 5577 * username; see #MHD_digest_auth_calc_userhash() and
5533 * #MHD_digest_auth_calc_userhash_hex() 5578 * #MHD_digest_auth_calc_userhash_hex()
5534 * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is 5579 * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
5535 * added, indicating for the client that UTF-8 encoding 5580 * added, indicating for the client that UTF-8 encoding for
5536 * is preferred 5581 * the username is preferred
5537 * @return #MHD_YES on success, #MHD_NO otherwise 5582 * @return #MHD_YES on success, #MHD_NO otherwise
5538 * @note Available since #MHD_VERSION 0x00097701 5583 * @note Available since #MHD_VERSION 0x00097701
5539 * @ingroup authentication 5584 * @ingroup authentication
@@ -5545,7 +5590,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
5545 const char *domain, 5590 const char *domain,
5546 struct MHD_Response *response, 5591 struct MHD_Response *response,
5547 int signal_stale, 5592 int signal_stale,
5548 enum MHD_DigestAuthMultiQOP qop, 5593 enum MHD_DigestAuthMultiQOP mqop,
5549 enum MHD_DigestAuthMultiAlgo3 algo, 5594 enum MHD_DigestAuthMultiAlgo3 algo,
5550 int userhash_support, 5595 int userhash_support,
5551 int prefer_utf8); 5596 int prefer_utf8);
@@ -5581,12 +5626,6 @@ MHD_digest_auth_get_username (struct MHD_Connection *connection);
5581 5626
5582 5627
5583/** 5628/**
5584 * MHD digest auth internal code for an invalid nonce.
5585 */
5586#define MHD_INVALID_NONCE -1
5587
5588
5589/**
5590 * Which digest algorithm should MHD use for HTTP digest authentication? 5629 * Which digest algorithm should MHD use for HTTP digest authentication?
5591 * Used as parameter for #MHD_digest_auth_check2(), 5630 * Used as parameter for #MHD_digest_auth_check2(),
5592 * #MHD_digest_auth_check_digest2(), #MHD_queue_auth_fail_response2(). 5631 * #MHD_digest_auth_check_digest2(), #MHD_queue_auth_fail_response2().
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 16541523..12fa2f3a 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -1901,7 +1901,7 @@ calc_userdigest (struct DigestAlgorithm *da,
1901 1901
1902 1902
1903/** 1903/**
1904 * Calculate userdigest, return it as binary data. 1904 * Calculate userdigest, return it as a binary data.
1905 * 1905 *
1906 * The "userdigest" is the hash of the "username:realm:password" string. 1906 * The "userdigest" is the hash of the "username:realm:password" string.
1907 * 1907 *
@@ -1918,7 +1918,7 @@ calc_userdigest (struct DigestAlgorithm *da,
1918 * @param algo3 the digest algorithm 1918 * @param algo3 the digest algorithm
1919 * @param username the username 1919 * @param username the username
1920 * @param realm the realm 1920 * @param realm the realm
1921 * @param password the password, must be zero-terminated 1921 * @param password the password
1922 * @param[out] userdigest_bin the output buffer for userdigest; 1922 * @param[out] userdigest_bin the output buffer for userdigest;
1923 * if this function succeeds, then this buffer has 1923 * if this function succeeds, then this buffer has
1924 * #MHD_digest_get_hash_size(algo3) bytes of 1924 * #MHD_digest_get_hash_size(algo3) bytes of
@@ -2003,7 +2003,7 @@ calc_userhash (struct DigestAlgorithm *da,
2003 * 2003 *
2004 * The "userhash" is the hash of the string "username:realm". 2004 * The "userhash" is the hash of the string "username:realm".
2005 * 2005 *
2006 * The "Userhash" could be used to avoid sending username in cleartext in Digest 2006 * The "userhash" could be used to avoid sending username in cleartext in Digest
2007 * Authorization client's header. 2007 * Authorization client's header.
2008 * 2008 *
2009 * Userhash is not designed to hide the username in local database or files, 2009 * Userhash is not designed to hide the username in local database or files,
@@ -2015,7 +2015,7 @@ calc_userhash (struct DigestAlgorithm *da,
2015 * when loading list of the usernames to generate the userhash for every loaded 2015 * when loading list of the usernames to generate the userhash for every loaded
2016 * username (this will cause delays at the start with the long lists). 2016 * username (this will cause delays at the start with the long lists).
2017 * 2017 *
2018 * Once "userhash" is generated it could be used to identify users for clients 2018 * Once "userhash" is generated it could be used to identify users by clients
2019 * with "userhash" support. 2019 * with "userhash" support.
2020 * Avoid repetitive usage of this function for the same username/realm 2020 * Avoid repetitive usage of this function for the same username/realm
2021 * combination as it will cause excessive CPU load; save and re-use the result 2021 * combination as it will cause excessive CPU load; save and re-use the result
@@ -2034,6 +2034,7 @@ calc_userhash (struct DigestAlgorithm *da,
2034 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is 2034 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
2035 * not supported (or external error has occurred, 2035 * not supported (or external error has occurred,
2036 * see #MHD_FEATURE_EXTERN_HASH) 2036 * see #MHD_FEATURE_EXTERN_HASH)
2037 * @sa #MHD_digest_auth_calc_userhash_hex()
2037 * @note Available since #MHD_VERSION 0x00097701 2038 * @note Available since #MHD_VERSION 0x00097701
2038 * @ingroup authentication 2039 * @ingroup authentication
2039 */ 2040 */
@@ -2073,11 +2074,11 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
2073 2074
2074 2075
2075/** 2076/**
2076 * Calculate "userhash", return it as hexadecimal data. 2077 * Calculate "userhash", return it as hexadecimal string.
2077 * 2078 *
2078 * The "userhash" is the hash of the string "username:realm". 2079 * The "userhash" is the hash of the string "username:realm".
2079 * 2080 *
2080 * The "Userhash" could be used to avoid sending username in cleartext in Digest 2081 * The "userhash" could be used to avoid sending username in cleartext in Digest
2081 * Authorization client's header. 2082 * Authorization client's header.
2082 * 2083 *
2083 * Userhash is not designed to hide the username in local database or files, 2084 * Userhash is not designed to hide the username in local database or files,
@@ -2089,7 +2090,7 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
2089 * when loading list of the usernames to generate the userhash for every loaded 2090 * when loading list of the usernames to generate the userhash for every loaded
2090 * username (this will cause delays at the start with the long lists). 2091 * username (this will cause delays at the start with the long lists).
2091 * 2092 *
2092 * Once "userhash" is generated it could be used to identify users for clients 2093 * Once "userhash" is generated it could be used to identify users by clients
2093 * with "userhash" support. 2094 * with "userhash" support.
2094 * Avoid repetitive usage of this function for the same username/realm 2095 * Avoid repetitive usage of this function for the same username/realm
2095 * combination as it will cause excessive CPU load; save and re-use the result 2096 * combination as it will cause excessive CPU load; save and re-use the result
@@ -2098,16 +2099,17 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3 algo3,
2098 * @param algo3 the algorithm for userhash calculations 2099 * @param algo3 the algorithm for userhash calculations
2099 * @param username the username 2100 * @param username the username
2100 * @param realm the realm 2101 * @param realm the realm
2101 * @param[out] userhash_hex the output buffer for userhash as hex data; 2102 * @param[out] userhash_hex the output buffer for userhash as hex string;
2102 * if this function succeeds, then this buffer has 2103 * if this function succeeds, then this buffer has
2103 * #MHD_digest_get_hash_size(algo3)*2 chars long 2104 * #MHD_digest_get_hash_size(algo3)*2 chars long
2104 * userhash string 2105 * userhash zero-terminated string
2105 * @param bin_buf_size the size of the @a userhash_bin buffer, must be 2106 * @param bin_buf_size the size of the @a userhash_bin buffer, must be
2106 * at least #MHD_digest_get_hash_size(algo3)*2+1 chars long 2107 * at least #MHD_digest_get_hash_size(algo3)*2+1 chars long
2107 * @return MHD_YES on success, 2108 * @return MHD_YES on success,
2108 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is 2109 * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
2109 * not supported (or external error has occurred, 2110 * not supported (or external error has occurred,
2110 * see #MHD_FEATURE_EXTERN_HASH). 2111 * see #MHD_FEATURE_EXTERN_HASH).
2112 * @sa #MHD_digest_auth_calc_userhash()
2111 * @note Available since #MHD_VERSION 0x00097701 2113 * @note Available since #MHD_VERSION 0x00097701
2112 * @ingroup authentication 2114 * @ingroup authentication
2113 */ 2115 */
@@ -3135,16 +3137,17 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
3135 * @a mqop and the client uses this mode, then server generated nonces are 3137 * @a mqop and the client uses this mode, then server generated nonces are
3136 * used as one-time nonces because nonce-count is not supported in this old RFC. 3138 * used as one-time nonces because nonce-count is not supported in this old RFC.
3137 * Communication in this mode is very inefficient, especially if the client 3139 * Communication in this mode is very inefficient, especially if the client
3138 * requests several resources one-by-one as for every request new nonce must be 3140 * requests several resources one-by-one as for every request a new nonce must
3139 * generated and client repeat all requests twice (first time to get a new 3141 * be generated and client repeats all requests twice (first time to get a new
3140 * nonce and second time to perform an authorised request). 3142 * nonce and second time to perform an authorised request).
3141 * 3143 *
3142 * @param connection the MHD connection structure 3144 * @param connection the MHD connection structure
3143 * @param realm the realm to be used for authorization of the client 3145 * @param realm the realm for authorization of the client
3144 * @param username the username needs to be authenticated, must be in clear text 3146 * @param username the username to be authenticated, must be in clear text
3145 * even if userhash is used by the client 3147 * even if userhash is used by the client
3146 * @param password the password used in the authentication 3148 * @param password the password matching the @a username (and the @a realm)
3147 * @param nonce_timeout the nonce validity duration in seconds 3149 * @param nonce_timeout the period of seconds since nonce generation, when
3150 * the nonce is recognised as valid and not stale.
3148 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc 3151 * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
3149 * exceeds the specified value then MHD_DAUTH_NONCE_STALE is 3152 * exceeds the specified value then MHD_DAUTH_NONCE_STALE is
3150 * returned; 3153 * returned;
@@ -3189,13 +3192,13 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
3189 * @a mqop and the client uses this mode, then server generated nonces are 3192 * @a mqop and the client uses this mode, then server generated nonces are
3190 * used as one-time nonces because nonce-count is not supported in this old RFC. 3193 * used as one-time nonces because nonce-count is not supported in this old RFC.
3191 * Communication in this mode is very inefficient, especially if the client 3194 * Communication in this mode is very inefficient, especially if the client
3192 * requests several resources one-by-one as for every request new nonce must be 3195 * requests several resources one-by-one as for every request a new nonce must
3193 * generated and client repeat all requests twice (first time to get a new 3196 * be generated and client repeats all requests twice (first time to get a new
3194 * nonce and second time to perform an authorised request). 3197 * nonce and second time to perform an authorised request).
3195 * 3198 *
3196 * @param connection the MHD connection structure 3199 * @param connection the MHD connection structure
3197 * @param realm the realm to be used for authorization of the client 3200 * @param realm the realm for authorization of the client
3198 * @param username the username needs to be authenticated, must be in clear text 3201 * @param username the username to be authenticated, must be in clear text
3199 * even if userhash is used by the client 3202 * even if userhash is used by the client
3200 * @param userdigest the precalculated binary hash of the string 3203 * @param userdigest the precalculated binary hash of the string
3201 * "username:realm:password", 3204 * "username:realm:password",
@@ -3517,14 +3520,16 @@ queue_auth_required_response3_inner (struct MHD_Connection *connection,
3517 size_t p; /* The position in the buffer */ 3520 size_t p; /* The position in the buffer */
3518 char *hdr_name; 3521 char *hdr_name;
3519 3522
3520 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_AUTH_ALGO3_SESSION)) 3523 if (0 == (((unsigned int) malgo3) & MHD_DIGEST_AUTH_ALGO3_NON_SESSION))
3521 { 3524 {
3522#ifdef HAVE_MESSAGES 3525#ifdef HAVE_MESSAGES
3523 MHD_DLOG (connection->daemon, 3526 MHD_DLOG (connection->daemon,
3524 _ ("The 'session' algorithms are not supported.\n")); 3527 _ ("Only non-'session' algorithms are supported.\n"));
3525#endif /* HAVE_MESSAGES */ 3528#endif /* HAVE_MESSAGES */
3526 return MHD_NO; 3529 return MHD_NO;
3527 } 3530 }
3531 malgo3 &= (enum MHD_DigestAuthMultiQOP)
3532 (~((enum MHD_DigestAuthMultiQOP) MHD_DIGEST_AUTH_ALGO3_NON_SESSION));
3528#ifdef MHD_MD5_SUPPORT 3533#ifdef MHD_MD5_SUPPORT
3529 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5)) 3534 if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5))
3530 s_algo = MHD_DIGEST_AUTH_ALGO3_MD5; 3535 s_algo = MHD_DIGEST_AUTH_ALGO3_MD5;
@@ -3555,9 +3560,10 @@ queue_auth_required_response3_inner (struct MHD_Connection *connection,
3555 return MHD_NO; 3560 return MHD_NO;
3556 } 3561 }
3557 3562
3558 if (((unsigned int) mqop) != 3563 if (MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT == mqop)
3559 (((unsigned int) mqop) & MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT))
3560 MHD_PANIC (_ ("Wrong 'mqop' value, API violation")); 3564 MHD_PANIC (_ ("Wrong 'mqop' value, API violation"));
3565 mqop &= (enum MHD_DigestAuthMultiQOP)
3566 (~((enum MHD_DigestAuthMultiQOP) MHD_DIGEST_AUTH_QOP_AUTH_INT));
3561 3567
3562 if (! digest_init_one_time (da, get_base_digest_algo (s_algo))) 3568 if (! digest_init_one_time (da, get_base_digest_algo (s_algo)))
3563 MHD_PANIC (_ ("Wrong 'algo' value, API violation")); 3569 MHD_PANIC (_ ("Wrong 'algo' value, API violation"));
@@ -3904,22 +3910,26 @@ queue_auth_required_response3_inner (struct MHD_Connection *connection,
3904 * any case client may assume that URI is in the same "protection 3910 * any case client may assume that URI is in the same "protection
3905 * space" if it starts with any of values specified here; 3911 * space" if it starts with any of values specified here;
3906 * could be NULL (clients typically assume that the same 3912 * could be NULL (clients typically assume that the same
3907 * credentials could be used for any URI on the same host) 3913 * credentials could be used for any URI on the same host);
3914 * this list provides information for the client only and does
3915 * not actually restrict anything on the server side
3908 * @param response the reply to send; should contain the "access denied" 3916 * @param response the reply to send; should contain the "access denied"
3909 * body; note that this function sets the "WWW Authenticate" 3917 * body;
3910 * header and that the caller should not do this; 3918 * note: this function sets the "WWW Authenticate" header and
3919 * the caller should not set this header;
3911 * the NULL is tolerated 3920 * the NULL is tolerated
3912 * @param signal_stale set to #MHD_YES if the nonce is stale to add 'stale=true' 3921 * @param signal_stale if set to #MHD_YES then indication of stale nonce used in
3922 * the client's request is signalled by adding 'stale=true'
3913 * to the authentication header, this instructs the client 3923 * to the authentication header, this instructs the client
3914 * to retry immediately with the new nonce and the same 3924 * to retry immediately with the new nonce and the same
3915 * credentials, without asking user for the new password 3925 * credentials, without asking user for the new password
3916 * @param mqop the QOP to use 3926 * @param mqop the QOP to use
3917 * @param malgo3 digest algorithm to use, MHD selects; if several algorithms 3927 * @param malgo3 digest algorithm to use; if several algorithms are allowed
3918 * are allowed then MD5 is preferred (currently, may be changed 3928 * then MD5 is preferred (currently, may be changed in next
3919 * in next versions) 3929 * versions)
3920 * @param userhash_support if set to non-zero value (#MHD_YES) then support of 3930 * @param userhash_support if set to non-zero value (#MHD_YES) then support of
3921 * userhash is indicated, the client may provide 3931 * userhash is indicated, allowing client to provide
3922 * hash("username:realm") instead of username in 3932 * hash("username:realm") instead of the username in
3923 * clear text; 3933 * clear text;
3924 * note that clients are allowed to provide the username 3934 * note that clients are allowed to provide the username
3925 * in cleartext even if this parameter set to non-zero; 3935 * in cleartext even if this parameter set to non-zero;
@@ -3928,8 +3938,8 @@ queue_auth_required_response3_inner (struct MHD_Connection *connection,
3928 * username; see #MHD_digest_auth_calc_userhash() and 3938 * username; see #MHD_digest_auth_calc_userhash() and
3929 * #MHD_digest_auth_calc_userhash_hex() 3939 * #MHD_digest_auth_calc_userhash_hex()
3930 * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is 3940 * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
3931 * added, indicating for the client that UTF-8 encoding 3941 * added, indicating for the client that UTF-8 encoding for
3932 * is preferred 3942 * the username is preferred
3933 * @return #MHD_YES on success, #MHD_NO otherwise 3943 * @return #MHD_YES on success, #MHD_NO otherwise
3934 * @note Available since #MHD_VERSION 0x00097701 3944 * @note Available since #MHD_VERSION 0x00097701
3935 * @ingroup authentication 3945 * @ingroup authentication