aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/digestauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r--src/microhttpd/digestauth.c213
1 files changed, 163 insertions, 50 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index b0e7ce00..0c5baffb 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 Copyright (C) 2010, 2011, 2012, 2015 Daniel Pittman and Christian Grothoff 3 Copyright (C) 2010, 2011, 2012, 2015, 2018 Daniel Pittman and Christian Grothoff
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,7 @@
37#include <windows.h> 37#include <windows.h>
38#endif /* MHD_W32_MUTEX_ */ 38#endif /* MHD_W32_MUTEX_ */
39 39
40#define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE) 40#define HASH_MD5_HEX_LEN (2 * MHD_MD5_DIGEST_SIZE)
41/* 32 bit value is 4 bytes */ 41/* 32 bit value is 4 bytes */
42#define TIMESTAMP_BIN_SIZE 4 42#define TIMESTAMP_BIN_SIZE 4
43#define TIMESTAMP_HEX_LEN (2 * TIMESTAMP_BIN_SIZE) 43#define TIMESTAMP_HEX_LEN (2 * TIMESTAMP_BIN_SIZE)
@@ -93,8 +93,65 @@ cvthex (const unsigned char *bin,
93 93
94 94
95/** 95/**
96 * calculate H(A1) as per RFC2617 spec and store the 96 * calculate H(A1) from given hash as per RFC2617 spec
97 * result in 'sessionkey'. 97 * and store the * result in 'sessionkey'.
98 *
99 * @param alg The hash algorithm used, can be "md5" or "md5-sess"
100 * @param digest An `unsigned char *' pointer to the binary MD5 sum
101 * for the precalculated hash value "username:realm:password"
102 * of #MHD_MD5_DIGEST_SIZE bytes
103 * @param nonce A `char *' pointer to the nonce value
104 * @param cnonce A `char *' pointer to the cnonce value
105 * @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
106 */
107static void
108digest_calc_ha1_from_digest (const char *alg,
109 const uint8_t digest[MHD_MD5_DIGEST_SIZE],
110 const char *nonce,
111 const char *cnonce,
112 char sessionkey[HASH_MD5_HEX_LEN + 1])
113{
114 struct MD5Context md5;
115
116 if (MHD_str_equal_caseless_(alg,
117 "md5-sess"))
118 {
119 unsigned char ha1[MHD_MD5_DIGEST_SIZE];
120
121 MD5Init (&md5);
122 MD5Update (&md5,
123 digest,
124 MHD_MD5_DIGEST_SIZE);
125 MD5Update (&md5,
126 (const unsigned char *) ":",
127 1);
128 MD5Update (&md5,
129 (const unsigned char *) nonce,
130 strlen (nonce));
131 MD5Update (&md5,
132 (const unsigned char *) ":",
133 1);
134 MD5Update (&md5,
135 (const unsigned char *) cnonce,
136 strlen (cnonce));
137 MD5Final (ha1,
138 &md5);
139 cvthex (ha1,
140 sizeof (ha1),
141 sessionkey);
142 }
143 else
144 {
145 cvthex (digest,
146 MHD_MD5_DIGEST_SIZE,
147 sessionkey);
148 }
149}
150
151
152/**
153 * calculate H(A1) from username, realm and password as per RFC2617 spec
154 * and store the result in 'sessionkey'.
98 * 155 *
99 * @param alg The hash algorithm used, can be "md5" or "md5-sess" 156 * @param alg The hash algorithm used, can be "md5" or "md5-sess"
100 * @param username A `char *' pointer to the username value 157 * @param username A `char *' pointer to the username value
@@ -105,16 +162,16 @@ cvthex (const unsigned char *bin,
105 * @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes 162 * @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
106 */ 163 */
107static void 164static void
108digest_calc_ha1 (const char *alg, 165digest_calc_ha1_from_user (const char *alg,
109 const char *username, 166 const char *username,
110 const char *realm, 167 const char *realm,
111 const char *password, 168 const char *password,
112 const char *nonce, 169 const char *nonce,
113 const char *cnonce, 170 const char *cnonce,
114 char sessionkey[HASH_MD5_HEX_LEN + 1]) 171 char sessionkey[HASH_MD5_HEX_LEN + 1])
115{ 172{
116 struct MD5Context md5; 173 struct MD5Context md5;
117 unsigned char ha1[MD5_DIGEST_SIZE]; 174 unsigned char ha1[MHD_MD5_DIGEST_SIZE];
118 175
119 MD5Init (&md5); 176 MD5Init (&md5);
120 MD5Update (&md5, 177 MD5Update (&md5,
@@ -134,31 +191,11 @@ digest_calc_ha1 (const char *alg,
134 strlen (password)); 191 strlen (password));
135 MD5Final (ha1, 192 MD5Final (ha1,
136 &md5); 193 &md5);
137 if (MHD_str_equal_caseless_(alg, 194 digest_calc_ha1_from_digest(alg,
138 "md5-sess")) 195 ha1,
139 { 196 nonce,
140 MD5Init (&md5); 197 cnonce,
141 MD5Update (&md5, 198 sessionkey);
142 (const unsigned char *) ha1,
143 sizeof (ha1));
144 MD5Update (&md5,
145 (const unsigned char *) ":",
146 1);
147 MD5Update (&md5,
148 (const unsigned char *) nonce,
149 strlen (nonce));
150 MD5Update (&md5,
151 (const unsigned char *) ":",
152 1);
153 MD5Update (&md5,
154 (const unsigned char *) cnonce,
155 strlen (cnonce));
156 MD5Final (ha1,
157 &md5);
158 }
159 cvthex (ha1,
160 sizeof (ha1),
161 sessionkey);
162} 199}
163 200
164 201
@@ -187,8 +224,8 @@ digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 1],
187 char response[HASH_MD5_HEX_LEN + 1]) 224 char response[HASH_MD5_HEX_LEN + 1])
188{ 225{
189 struct MD5Context md5; 226 struct MD5Context md5;
190 unsigned char ha2[MD5_DIGEST_SIZE]; 227 unsigned char ha2[MHD_MD5_DIGEST_SIZE];
191 unsigned char resphash[MD5_DIGEST_SIZE]; 228 unsigned char resphash[MHD_MD5_DIGEST_SIZE];
192 char ha2hex[HASH_MD5_HEX_LEN + 1]; 229 char ha2hex[HASH_MD5_HEX_LEN + 1];
193 (void)hentity; /* Unused. Silent compiler warning. */ 230 (void)hentity; /* Unused. Silent compiler warning. */
194 231
@@ -220,7 +257,7 @@ digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 1],
220 MD5Final (ha2, 257 MD5Final (ha2,
221 &md5); 258 &md5);
222 cvthex (ha2, 259 cvthex (ha2,
223 MD5_DIGEST_SIZE, 260 MHD_MD5_DIGEST_SIZE,
224 ha2hex); 261 ha2hex);
225 MD5Init (&md5); 262 MD5Init (&md5);
226 /* calculate response */ 263 /* calculate response */
@@ -518,7 +555,7 @@ calculate_nonce (uint32_t nonce_time,
518{ 555{
519 struct MD5Context md5; 556 struct MD5Context md5;
520 unsigned char timestamp[TIMESTAMP_BIN_SIZE]; 557 unsigned char timestamp[TIMESTAMP_BIN_SIZE];
521 unsigned char tmpnonce[MD5_DIGEST_SIZE]; 558 unsigned char tmpnonce[MHD_MD5_DIGEST_SIZE];
522 char timestamphex[TIMESTAMP_HEX_LEN + 1]; 559 char timestamphex[TIMESTAMP_HEX_LEN + 1];
523 560
524 MD5Init (&md5); 561 MD5Init (&md5);
@@ -667,17 +704,21 @@ check_argument_match (struct MHD_Connection *connection,
667 * @param realm The realm presented to the client 704 * @param realm The realm presented to the client
668 * @param username The username needs to be authenticated 705 * @param username The username needs to be authenticated
669 * @param password The password used in the authentication 706 * @param password The password used in the authentication
707 * @param digest An optional `unsigned char *' pointer to the binary MD5 sum
708 * for the precalculated hash value "username:realm:password"
709 * of #MHD_MD5_DIGEST_SIZE bytes
670 * @param nonce_timeout The amount of time for a nonce to be 710 * @param nonce_timeout The amount of time for a nonce to be
671 * invalid in seconds 711 * invalid in seconds
672 * @return #MHD_YES if authenticated, #MHD_NO if not, 712 * @return #MHD_YES if authenticated, #MHD_NO if not,
673 * #MHD_INVALID_NONCE if nonce is invalid 713 * #MHD_INVALID_NONCE if nonce is invalid
674 * @ingroup authentication 714 * @ingroup authentication
675 */ 715 */
676int 716static int
677MHD_digest_auth_check (struct MHD_Connection *connection, 717digest_auth_check_all (struct MHD_Connection *connection,
678 const char *realm, 718 const char *realm,
679 const char *username, 719 const char *username,
680 const char *password, 720 const char *password,
721 const uint8_t digest[MHD_MD5_DIGEST_SIZE],
681 unsigned int nonce_timeout) 722 unsigned int nonce_timeout)
682{ 723{
683 struct MHD_Daemon *daemon = connection->daemon; 724 struct MHD_Daemon *daemon = connection->daemon;
@@ -871,13 +912,24 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
871 return MHD_NO; 912 return MHD_NO;
872 } 913 }
873 914
874 digest_calc_ha1 ("md5", 915 if (NULL != digest)
875 username, 916 {
876 realm, 917 digest_calc_ha1_from_digest ("md5",
877 password, 918 digest,
878 nonce, 919 nonce,
879 cnonce, 920 cnonce,
880 ha1); 921 ha1);
922 }
923 else
924 {
925 digest_calc_ha1_from_user ("md5",
926 username,
927 realm,
928 password,
929 nonce,
930 cnonce,
931 ha1);
932 }
881 digest_calc_response (ha1, 933 digest_calc_response (ha1,
882 nonce, 934 nonce,
883 nc, 935 nc,
@@ -888,6 +940,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
888 hentity, 940 hentity,
889 respexp); 941 respexp);
890 942
943
891 /* Need to unescape URI before comparing with connection->url */ 944 /* Need to unescape URI before comparing with connection->url */
892 daemon->unescape_callback (daemon->unescape_callback_cls, 945 daemon->unescape_callback (daemon->unescape_callback_cls,
893 connection, 946 connection,
@@ -934,6 +987,66 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
934 987
935 988
936/** 989/**
990 * Authenticates the authorization header sent by the client
991 *
992 * @param connection The MHD connection structure
993 * @param realm The realm presented to the client
994 * @param username The username needs to be authenticated
995 * @param password The password used in the authentication
996 * @param nonce_timeout The amount of time for a nonce to be
997 * invalid in seconds
998 * @return #MHD_YES if authenticated, #MHD_NO if not,
999 * #MHD_INVALID_NONCE if nonce is invalid
1000 * @ingroup authentication
1001 */
1002_MHD_EXTERN int
1003MHD_digest_auth_check (struct MHD_Connection *connection,
1004 const char *realm,
1005 const char *username,
1006 const char *password,
1007 unsigned int nonce_timeout)
1008{
1009 return digest_auth_check_all(connection,
1010 realm,
1011 username,
1012 password,
1013 NULL,
1014 nonce_timeout);
1015}
1016
1017
1018/**
1019 * Authenticates the authorization header sent by the client
1020 *
1021 * @param connection The MHD connection structure
1022 * @param realm The realm presented to the client
1023 * @param username The username needs to be authenticated
1024 * @param digest An `unsigned char *' pointer to the binary MD5 sum
1025 * for the precalculated hash value "username:realm:password"
1026 * of #MHD_MD5_DIGEST_SIZE bytes
1027 * @param nonce_timeout The amount of time for a nonce to be
1028 * invalid in seconds
1029 * @return #MHD_YES if authenticated, #MHD_NO if not,
1030 * #MHD_INVALID_NONCE if nonce is invalid
1031 * @ingroup authentication
1032 */
1033_MHD_EXTERN int
1034MHD_digest_auth_check_digest (struct MHD_Connection *connection,
1035 const char *realm,
1036 const char *username,
1037 const uint8_t digest[MD5_DIGEST_SIZE],
1038 unsigned int nonce_timeout)
1039{
1040 return digest_auth_check_all (connection,
1041 realm,
1042 username,
1043 NULL,
1044 digest,
1045 nonce_timeout);
1046}
1047
1048
1049/**
937 * Queues a response to request authentication from the client 1050 * Queues a response to request authentication from the client
938 * 1051 *
939 * @param connection The MHD connection structure 1052 * @param connection The MHD connection structure