diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-08-22 15:03:32 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-08-22 15:03:32 +0000 |
commit | daa1e7fa9723ef2f60d6ea68b711c1254b4d9718 (patch) | |
tree | e47092fd021073136a5b93311357209d79d5e96b | |
parent | 9e7a668f097b6bbc321507cd6391d373e1e00def (diff) | |
download | libmicrohttpd-daa1e7fa9723ef2f60d6ea68b711c1254b4d9718.tar.gz libmicrohttpd-daa1e7fa9723ef2f60d6ea68b711c1254b4d9718.zip |
indentation
-rw-r--r-- | src/daemon/digestauth.c | 951 |
1 files changed, 488 insertions, 463 deletions
diff --git a/src/daemon/digestauth.c b/src/daemon/digestauth.c index 93f4c9f2..83fd0fad 100644 --- a/src/daemon/digestauth.c +++ b/src/daemon/digestauth.c | |||
@@ -40,24 +40,26 @@ | |||
40 | 40 | ||
41 | /* convert bin to hex */ | 41 | /* convert bin to hex */ |
42 | static void | 42 | static void |
43 | cvthex(const unsigned char *bin, size_t len, char *hex) | 43 | cvthex(const unsigned char *bin, |
44 | size_t len, | ||
45 | char *hex) | ||
44 | { | 46 | { |
45 | size_t i; | 47 | size_t i; |
46 | unsigned int j; | 48 | unsigned int j; |
47 | 49 | ||
48 | for (i = 0; i < len; ++i) { | 50 | for (i = 0; i < len; ++i) { |
49 | j = (bin[i] >> 4) & 0x0f; | 51 | j = (bin[i] >> 4) & 0x0f; |
50 | 52 | ||
51 | hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10); | 53 | hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10); |
52 | 54 | ||
53 | j = bin[i] & 0x0f; | 55 | j = bin[i] & 0x0f; |
54 | 56 | ||
55 | hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10); | 57 | hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10); |
56 | } | 58 | } |
57 | 59 | hex[len * 2] = '\0'; | |
58 | hex[len * 2] = '\0'; | ||
59 | } | 60 | } |
60 | 61 | ||
62 | |||
61 | /* calculate H(A1) as per RFC2617 spec */ | 63 | /* calculate H(A1) as per RFC2617 spec */ |
62 | static int | 64 | static int |
63 | digest_calc_ha1(const char *alg, | 65 | digest_calc_ha1(const char *alg, |
@@ -68,160 +70,172 @@ digest_calc_ha1(const char *alg, | |||
68 | const char *cnonce, | 70 | const char *cnonce, |
69 | char *sessionkey) | 71 | char *sessionkey) |
70 | { | 72 | { |
71 | gcry_md_hd_t md5; | 73 | gcry_md_hd_t md5; |
72 | gcry_error_t gerror; | 74 | gcry_error_t gerror; |
73 | unsigned char *ha1; | 75 | unsigned char *ha1; |
74 | 76 | ||
75 | gerror = gcry_md_open(&md5, GCRY_MD_MD5, GCRY_MD_FLAG_SECURE); | 77 | gerror = gcry_md_open(&md5, GCRY_MD_MD5, GCRY_MD_FLAG_SECURE); |
76 | 78 | if (gerror) | |
77 | if (gerror) return gerror; | 79 | return gerror; |
78 | 80 | gcry_md_write(md5, username, strlen(username)); | |
79 | gcry_md_write(md5, username, strlen(username)); | 81 | gcry_md_write(md5, ":", 1); |
80 | gcry_md_write(md5, ":", 1); | 82 | gcry_md_write(md5, realm, strlen(realm)); |
81 | gcry_md_write(md5, realm, strlen(realm)); | 83 | gcry_md_write(md5, ":", 1); |
82 | gcry_md_write(md5, ":", 1); | 84 | gcry_md_write(md5, password, strlen(password)); |
83 | gcry_md_write(md5, password, strlen(password)); | 85 | gcry_md_final(md5); |
84 | gcry_md_final(md5); | 86 | ha1 = gcry_md_read(md5, GCRY_MD_MD5); |
85 | 87 | if (strcasecmp(alg, "md5-sess") == 0) | |
86 | ha1 = gcry_md_read(md5, GCRY_MD_MD5); | 88 | { |
87 | 89 | gcry_md_reset(md5); | |
88 | if (strcasecmp(alg, "md5-sess") == 0) { | 90 | gcry_md_write(md5, ha1, HASH_MD5_LEN); |
89 | gcry_md_reset(md5); | 91 | gcry_md_write(md5, ":", 1); |
90 | gcry_md_write(md5, ha1, HASH_MD5_LEN); | 92 | gcry_md_write(md5, nonce, strlen(nonce)); |
91 | gcry_md_write(md5, ":", 1); | 93 | gcry_md_write(md5, ":", 1); |
92 | gcry_md_write(md5, nonce, strlen(nonce)); | 94 | gcry_md_write(md5, cnonce, strlen(cnonce)); |
93 | gcry_md_write(md5, ":", 1); | 95 | gcry_md_final(md5); |
94 | gcry_md_write(md5, cnonce, strlen(cnonce)); | 96 | ha1 = gcry_md_read(md5, GCRY_MD_MD5); |
95 | gcry_md_final(md5); | 97 | } |
96 | 98 | cvthex(ha1, HASH_MD5_LEN, sessionkey); | |
97 | ha1 = gcry_md_read(md5, GCRY_MD_MD5); | 99 | gcry_md_close(md5); |
98 | } | 100 | return 0; |
99 | |||
100 | cvthex(ha1, HASH_MD5_LEN, sessionkey); | ||
101 | gcry_md_close(md5); | ||
102 | |||
103 | return 0; | ||
104 | } | 101 | } |
105 | 102 | ||
106 | /* calculate request-digest/response-digest as per RFC2617 spec */ | 103 | /** |
104 | * calculate request-digest/response-digest as per RFC2617 spec | ||
105 | * | ||
106 | * @param ha1 H(A1) | ||
107 | * @param nonce nonce from server | ||
108 | * @param noncecount 8 hex digits | ||
109 | * @param cnonce client nonce | ||
110 | * @param qop qop-value: "", "auth" or "auth-int" | ||
111 | * @param method method from request | ||
112 | * @param uri requested URL | ||
113 | * @param hentity H(entity body) if qop="auth-int" | ||
114 | * @param response request-digest or response-digest | ||
115 | * @return ??? | ||
116 | */ | ||
107 | static int | 117 | static int |
108 | digest_calc_response(const char *ha1, /* H(A1) */ | 118 | digest_calc_response(const char *ha1, |
109 | const char *nonce, /* nonce from server */ | 119 | const char *nonce, |
110 | const char *noncecount, /* 8 hex digits */ | 120 | const char *noncecount, |
111 | const char *cnonce, /* client nonce */ | 121 | const char *cnonce, |
112 | const char *qop, /* qop-value: "", "auth", "auth-int" */ | 122 | const char *qop, |
113 | const char *method, /* method from the request */ | 123 | const char *method, |
114 | const char *uri, /* requested URL */ | 124 | const char *uri, |
115 | const char *hentity, /* H(entity body) if qop="auth-int" */ | 125 | const char *hentity, |
116 | char *response /* request-digest or response-digest */ | 126 | char *response) |
117 | ) | ||
118 | { | 127 | { |
119 | gcry_md_hd_t md5; | 128 | gcry_md_hd_t md5; |
120 | gcry_error_t gerror; | 129 | gcry_error_t gerror; |
121 | unsigned char *ha2; | 130 | unsigned char *ha2; |
122 | unsigned char *resphash; | 131 | unsigned char *resphash; |
123 | char ha2hex[HASH_MD5_HEX_LEN + 1]; | 132 | char ha2hex[HASH_MD5_HEX_LEN + 1]; |
124 | 133 | ||
125 | gerror = gcry_md_open(&md5, GCRY_MD_MD5, GCRY_MD_FLAG_SECURE); | 134 | gerror = gcry_md_open(&md5, GCRY_MD_MD5, GCRY_MD_FLAG_SECURE); |
126 | 135 | if (gerror) | |
127 | if (gerror) return gerror; | 136 | return gerror; |
128 | 137 | /* | |
129 | /* | 138 | * calculate H(A2) |
130 | * calculate H(A2) | 139 | */ |
131 | */ | 140 | |
132 | 141 | gcry_md_write(md5, method, strlen(method)); | |
133 | gcry_md_write(md5, method, strlen(method)); | 142 | gcry_md_write(md5, ":", 1); |
134 | gcry_md_write(md5, ":", 1); | 143 | gcry_md_write(md5, uri, strlen(uri)); |
135 | gcry_md_write(md5, uri, strlen(uri)); | 144 | |
136 | 145 | if (strcasecmp(qop, "auth-int") == 0) | |
137 | if (strcasecmp(qop, "auth-int") == 0) { | 146 | { |
138 | gcry_md_write(md5, ":", 1); | 147 | gcry_md_write(md5, ":", 1); |
139 | gcry_md_write(md5, hentity, strlen(hentity)); | 148 | gcry_md_write(md5, hentity, strlen(hentity)); |
140 | } | 149 | } |
141 | 150 | ||
142 | gcry_md_final(md5); | 151 | gcry_md_final(md5); |
143 | 152 | ||
144 | ha2 = gcry_md_read(md5, GCRY_MD_MD5); | 153 | ha2 = gcry_md_read(md5, GCRY_MD_MD5); |
145 | 154 | ||
146 | cvthex(ha2, HASH_MD5_LEN, ha2hex); | 155 | cvthex(ha2, HASH_MD5_LEN, ha2hex); |
147 | gcry_md_reset(md5); | 156 | gcry_md_reset(md5); |
148 | 157 | ||
149 | /* | 158 | /* |
150 | * calculate response | 159 | * calculate response |
151 | */ | 160 | */ |
152 | 161 | ||
153 | gcry_md_write(md5, ha1, HASH_MD5_HEX_LEN); | 162 | gcry_md_write(md5, ha1, HASH_MD5_HEX_LEN); |
154 | gcry_md_write(md5, ":", 1); | 163 | gcry_md_write(md5, ":", 1); |
155 | gcry_md_write(md5, nonce, strlen(nonce)); | 164 | gcry_md_write(md5, nonce, strlen(nonce)); |
156 | gcry_md_write(md5, ":", 1); | 165 | gcry_md_write(md5, ":", 1); |
157 | 166 | ||
158 | if (*qop) { | 167 | if (*qop) |
159 | gcry_md_write(md5, noncecount, strlen(noncecount)); | 168 | { |
160 | gcry_md_write(md5, ":", 1); | 169 | gcry_md_write(md5, noncecount, strlen(noncecount)); |
161 | gcry_md_write(md5, cnonce, strlen(cnonce)); | 170 | gcry_md_write(md5, ":", 1); |
162 | gcry_md_write(md5, ":", 1); | 171 | gcry_md_write(md5, cnonce, strlen(cnonce)); |
163 | gcry_md_write(md5, qop, strlen(qop)); | 172 | gcry_md_write(md5, ":", 1); |
164 | gcry_md_write(md5, ":", 1); | 173 | gcry_md_write(md5, qop, strlen(qop)); |
165 | } | 174 | gcry_md_write(md5, ":", 1); |
166 | 175 | } | |
167 | gcry_md_write(md5, ha2hex, HASH_MD5_HEX_LEN); | 176 | |
168 | gcry_md_final(md5); | 177 | gcry_md_write(md5, ha2hex, HASH_MD5_HEX_LEN); |
169 | 178 | gcry_md_final(md5); | |
170 | resphash = gcry_md_read(md5, GCRY_MD_MD5); | 179 | |
171 | 180 | resphash = gcry_md_read(md5, GCRY_MD_MD5); | |
172 | cvthex(resphash, HASH_MD5_LEN, response); | 181 | |
173 | gcry_md_close(md5); | 182 | cvthex(resphash, HASH_MD5_LEN, response); |
174 | 183 | gcry_md_close(md5); | |
175 | return 0; | 184 | |
185 | return 0; | ||
176 | } | 186 | } |
177 | 187 | ||
178 | static const char * | 188 | static const char * |
179 | lookup_sub_value(char *data, size_t len, const char *key) | 189 | lookup_sub_value(char *data, |
190 | size_t len, | ||
191 | const char *key) | ||
180 | { | 192 | { |
181 | char *tmp = data; | 193 | char *tmp = data; |
182 | char *value = NULL; | 194 | char *value = NULL; |
183 | size_t keylen; | 195 | size_t keylen; |
184 | size_t i; | 196 | size_t i; |
185 | 197 | ||
186 | keylen = strlen(key); | 198 | keylen = strlen(key); |
187 | 199 | for (i = 0; i < len; ++i) { | |
188 | for (i = 0; i < len; ++i) { | 200 | if (strncmp(tmp, key, keylen) == 0 && |
189 | if (strncmp(tmp, key, keylen) == 0 && | 201 | strncmp(tmp + keylen, "=", 1) == 0) |
190 | strncmp(tmp + keylen, "=", 1) == 0) { | 202 | { |
191 | tmp += keylen; | 203 | tmp += keylen; |
192 | break; | 204 | break; |
193 | } else { | 205 | } |
194 | tmp++; | 206 | else |
195 | } | 207 | { |
196 | 208 | tmp++; | |
197 | if ((i + 1) == len) return NULL; | 209 | } |
198 | } | 210 | if ((i + 1) == len) |
199 | 211 | return NULL; | |
200 | while (1) { | 212 | } |
201 | tmp++; | 213 | while (1) |
202 | 214 | { | |
203 | if (*tmp == '"' && *(tmp + 1) == ',') { | 215 | tmp++; |
204 | *tmp = '\0'; | 216 | |
205 | break; | 217 | if (*tmp == '"' && *(tmp + 1) == ',') |
206 | } | 218 | { |
207 | 219 | *tmp = '\0'; | |
208 | if (*tmp == '"' && *(tmp + 1) == '\0') { | 220 | break; |
209 | *tmp = '\0'; | 221 | } |
210 | break; | 222 | if (*tmp == '"' && *(tmp + 1) == '\0') |
211 | } | 223 | { |
212 | 224 | *tmp = '\0'; | |
213 | if (*tmp == ',' || *tmp == '\0') { | 225 | break; |
214 | *tmp = '\0'; | 226 | } |
215 | break; | 227 | if (*tmp == ',' || *tmp == '\0') |
216 | } | 228 | { |
217 | 229 | *tmp = '\0'; | |
218 | if (*tmp == '"') continue; | 230 | break; |
219 | 231 | } | |
220 | if (value == NULL) | 232 | if (*tmp == '"') |
221 | value = tmp; | 233 | continue; |
222 | } | 234 | if (value == NULL) |
223 | 235 | value = tmp; | |
224 | return value; | 236 | } |
237 | |||
238 | return value; | ||
225 | } | 239 | } |
226 | 240 | ||
227 | 241 | ||
@@ -235,41 +249,46 @@ lookup_sub_value(char *data, size_t len, const char *key) | |||
235 | char * | 249 | char * |
236 | MHD_digest_auth_get_username(struct MHD_Connection *connection) | 250 | MHD_digest_auth_get_username(struct MHD_Connection *connection) |
237 | { | 251 | { |
238 | size_t len; | 252 | size_t len; |
239 | size_t userlen; | 253 | size_t userlen; |
240 | char *buffer; | 254 | char *buffer; |
241 | char *username; | 255 | char *username; |
242 | const char *user; | 256 | const char *user; |
243 | const char *header; | 257 | const char *header; |
244 | 258 | ||
245 | header = MHD_lookup_connection_value(connection, | 259 | header = MHD_lookup_connection_value(connection, |
246 | MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION); | 260 | MHD_HEADER_KIND, |
247 | 261 | MHD_HTTP_HEADER_AUTHORIZATION); | |
248 | if (header == NULL) return NULL; | 262 | |
249 | if (strncmp(header, _BASE, strlen(_BASE)) != 0) return NULL; | 263 | if (header == NULL) |
250 | 264 | return NULL; | |
251 | len = strlen(header) - strlen(_BASE) + 1; | 265 | if (strncmp(header, _BASE, strlen(_BASE)) != 0) |
252 | buffer = malloc(len); | 266 | return NULL; |
253 | 267 | ||
254 | if (buffer == NULL) return NULL; | 268 | len = strlen(header) - strlen(_BASE) + 1; |
255 | 269 | buffer = malloc(len); | |
256 | strncpy(buffer, header + strlen(_BASE), len); | 270 | |
257 | 271 | if (buffer == NULL) return NULL; | |
258 | user = lookup_sub_value(buffer, len, "username"); | 272 | |
259 | 273 | strncpy(buffer, header + strlen(_BASE), len); | |
260 | if (user) { | 274 | |
261 | userlen = strlen(user) + 1; | 275 | user = lookup_sub_value(buffer, len, "username"); |
262 | username = malloc(userlen); | 276 | |
263 | 277 | if (user) | |
264 | if (username != NULL) { | 278 | { |
265 | strncpy(username, user, userlen); | 279 | userlen = strlen(user) + 1; |
266 | free(buffer); | 280 | username = malloc(userlen); |
267 | return username; | 281 | |
268 | } | 282 | if (username != NULL) |
283 | { | ||
284 | strncpy(username, user, userlen); | ||
285 | free(buffer); | ||
286 | return username; | ||
269 | } | 287 | } |
270 | 288 | } | |
271 | free(buffer); | 289 | |
272 | return NULL; | 290 | free(buffer); |
291 | return NULL; | ||
273 | } | 292 | } |
274 | 293 | ||
275 | /** | 294 | /** |
@@ -291,192 +310,197 @@ MHD_digest_auth_check(struct MHD_Connection *connection, | |||
291 | const char *password, | 310 | const char *password, |
292 | unsigned int nonce_timeout) | 311 | unsigned int nonce_timeout) |
293 | { | 312 | { |
294 | int auth; | 313 | int auth; |
295 | size_t len; | 314 | size_t len; |
296 | char *buffer; | 315 | char *buffer; |
297 | const char *header; | 316 | const char *header; |
298 | const char *ret; | 317 | const char *ret; |
299 | const char *nonce; | 318 | const char *nonce; |
300 | const char *cnonce; | 319 | const char *cnonce; |
301 | const char *uri; | 320 | const char *uri; |
302 | const char *qop; | 321 | const char *qop; |
303 | const char *nc; | 322 | const char *nc; |
304 | const char *response; | 323 | const char *response; |
305 | unsigned char *tmpnonce; | 324 | unsigned char *tmpnonce; |
306 | char *hentity = NULL; /* "auth-int" is not supported */ | 325 | char *hentity = NULL; /* "auth-int" is not supported */ |
307 | char timestamp[5]; | 326 | char timestamp[5]; |
308 | char ha1[HASH_MD5_HEX_LEN + 1]; | 327 | char ha1[HASH_MD5_HEX_LEN + 1]; |
309 | char respexp[HASH_MD5_HEX_LEN + 1]; | 328 | char respexp[HASH_MD5_HEX_LEN + 1]; |
310 | char noncehashexp[HASH_SHA1_HEX_LEN + 9]; | 329 | char noncehashexp[HASH_SHA1_HEX_LEN + 9]; |
311 | unsigned int nonce_time; | 330 | unsigned int nonce_time; |
312 | time_t t; | 331 | time_t t; |
313 | gcry_error_t gerror; | 332 | gcry_error_t gerror; |
314 | gcry_md_hd_t sha1; | 333 | gcry_md_hd_t sha1; |
315 | 334 | ||
316 | header = MHD_lookup_connection_value( | 335 | header = MHD_lookup_connection_value(connection, |
317 | connection, MHD_HEADER_KIND, | 336 | MHD_HEADER_KIND, |
318 | MHD_HTTP_HEADER_AUTHORIZATION); | 337 | MHD_HTTP_HEADER_AUTHORIZATION); |
319 | 338 | if (header == NULL) | |
320 | if (header == NULL) return MHD_NO; | 339 | return MHD_NO; |
321 | if (strncmp(header, _BASE, strlen(_BASE)) != 0) return MHD_NO; | 340 | if (strncmp(header, _BASE, strlen(_BASE)) != 0) |
322 | 341 | return MHD_NO; | |
323 | len = strlen(header) - strlen(_BASE) + 1; | 342 | len = strlen(header) - strlen(_BASE) + 1; |
324 | 343 | buffer = malloc(len); | |
325 | buffer = malloc(len); | 344 | |
326 | 345 | if (buffer == NULL) | |
327 | if (buffer == NULL) return MHD_NO; | 346 | return MHD_NO; |
328 | 347 | strncpy(buffer, | |
329 | strncpy(buffer, header + strlen(_BASE), len); | 348 | header + strlen(_BASE), |
330 | 349 | len); | |
331 | ret = lookup_sub_value(buffer, len, "username"); | 350 | |
332 | 351 | ret = lookup_sub_value(buffer, len, "username"); | |
333 | if (ret == NULL || strcmp(username, ret) != 0) { | 352 | |
334 | free(buffer); | 353 | if ( (ret == NULL) || (strcmp(username, ret) != 0) ) |
335 | return MHD_NO; | 354 | { |
336 | } | 355 | free(buffer); |
337 | 356 | return MHD_NO; | |
338 | ret = lookup_sub_value(buffer, len, "realm"); | 357 | } |
339 | 358 | ret = lookup_sub_value(buffer, len, "realm"); | |
340 | if (ret == NULL || strcmp(realm, ret) != 0) { | 359 | |
341 | free(buffer); | 360 | if (ret == NULL || strcmp(realm, ret) != 0) |
342 | return MHD_NO; | 361 | { |
343 | } | 362 | free(buffer); |
344 | 363 | return MHD_NO; | |
345 | if ((uri = lookup_sub_value(buffer, len, "uri")) == NULL) { | 364 | } |
346 | free(buffer); | 365 | if ((uri = lookup_sub_value(buffer, len, "uri")) == NULL) |
347 | return MHD_NO; | 366 | { |
348 | } | 367 | free(buffer); |
349 | 368 | return MHD_NO; | |
350 | if ((nonce = lookup_sub_value(buffer, len, "nonce")) == NULL) { | 369 | } |
351 | free(buffer); | 370 | if ((nonce = lookup_sub_value(buffer, len, "nonce")) == NULL) |
352 | return MHD_NO; | 371 | { |
353 | } | 372 | free(buffer); |
354 | 373 | return MHD_NO; | |
355 | /* | 374 | } |
356 | * 8 = 4 hexadecimal numbers for the timestamp | 375 | |
357 | */ | 376 | /* |
358 | 377 | * 8 = 4 hexadecimal numbers for the timestamp | |
359 | nonce_time = strtoul(nonce + strlen(nonce) - 8, 0, 16); | 378 | */ |
360 | 379 | ||
361 | time(&t); | 380 | nonce_time = strtoul(nonce + strlen(nonce) - 8, 0, 16); |
362 | 381 | time(&t); | |
363 | /* | 382 | |
364 | * First level vetting for the nonce validity | 383 | /* |
365 | * if the timestamp attached to the nonce | 384 | * First level vetting for the nonce validity |
366 | * exceeds `nonce_timeout' then the nonce is | 385 | * if the timestamp attached to the nonce |
367 | * invalid. | 386 | * exceeds `nonce_timeout' then the nonce is |
368 | */ | 387 | * invalid. |
369 | 388 | */ | |
370 | if (t - nonce_time > nonce_timeout) { | 389 | |
371 | free(buffer); | 390 | if (t - nonce_time > nonce_timeout) |
372 | return MHD_INVALID_NONCE; | 391 | { |
373 | } | 392 | free(buffer); |
374 | 393 | return MHD_INVALID_NONCE; | |
375 | gerror = gcry_md_open(&sha1, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); | 394 | } |
376 | 395 | gerror = gcry_md_open(&sha1, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); | |
377 | if (gerror) { | 396 | if (gerror) |
378 | free(buffer); | 397 | { |
379 | return MHD_NO; | 398 | free(buffer); |
380 | } | 399 | return MHD_NO; |
381 | 400 | } | |
382 | timestamp[0] = (nonce_time & 0xff000000) >> 0x18; | 401 | |
383 | timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; | 402 | timestamp[0] = (nonce_time & 0xff000000) >> 0x18; |
384 | timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; | 403 | timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; |
385 | timestamp[3] = nonce_time & 0x000000ff; | 404 | timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; |
386 | timestamp[4] = '\0'; | 405 | timestamp[3] = nonce_time & 0x000000ff; |
387 | 406 | timestamp[4] = '\0'; | |
388 | gcry_md_write(sha1, timestamp, 4); | 407 | |
389 | gcry_md_write(sha1, ":", 1); | 408 | gcry_md_write(sha1, timestamp, 4); |
390 | gcry_md_write(sha1, connection->method, strlen(connection->method)); | 409 | gcry_md_write(sha1, ":", 1); |
391 | gcry_md_write(sha1, ":", 1); | 410 | gcry_md_write(sha1, connection->method, strlen(connection->method)); |
392 | gcry_md_write(sha1, password, strlen(password)); | 411 | gcry_md_write(sha1, ":", 1); |
393 | gcry_md_write(sha1, ":", 1); | 412 | gcry_md_write(sha1, password, strlen(password)); |
394 | gcry_md_write(sha1, uri, strlen(uri)); | 413 | gcry_md_write(sha1, ":", 1); |
395 | gcry_md_write(sha1, ":", 1); | 414 | gcry_md_write(sha1, uri, strlen(uri)); |
396 | gcry_md_write(sha1, realm, strlen(realm)); | 415 | gcry_md_write(sha1, ":", 1); |
397 | gcry_md_final(sha1); | 416 | gcry_md_write(sha1, realm, strlen(realm)); |
398 | 417 | gcry_md_final(sha1); | |
399 | tmpnonce = gcry_md_read(sha1, GCRY_MD_SHA1); | 418 | |
400 | 419 | tmpnonce = gcry_md_read(sha1, GCRY_MD_SHA1); | |
401 | cvthex(tmpnonce, HASH_SHA1_LEN, noncehashexp); | 420 | |
402 | gcry_md_close(sha1); | 421 | cvthex(tmpnonce, HASH_SHA1_LEN, noncehashexp); |
403 | 422 | gcry_md_close(sha1); | |
404 | strncat(noncehashexp, nonce + strlen(nonce) - 8, 8); | 423 | |
405 | 424 | strncat(noncehashexp, nonce + strlen(nonce) - 8, 8); | |
406 | /* | 425 | |
407 | * Second level vetting for the nonce validity | 426 | /* |
408 | * if the timestamp attached to the nonce is valid | 427 | * Second level vetting for the nonce validity |
409 | * and possibility fabricated (in case of an attack) | 428 | * if the timestamp attached to the nonce is valid |
410 | * the attacker must also know the password to be | 429 | * and possibility fabricated (in case of an attack) |
411 | * able to generate a "sane" nonce, which if he does | 430 | * the attacker must also know the password to be |
412 | * not, the nonce fabrication process going to be | 431 | * able to generate a "sane" nonce, which if he does |
413 | * very hard to achieve. | 432 | * not, the nonce fabrication process going to be |
414 | */ | 433 | * very hard to achieve. |
415 | 434 | */ | |
416 | if (strncmp(nonce, noncehashexp, strlen(nonce)) != 0) { | 435 | |
417 | free(buffer); | 436 | if (strncmp(nonce, noncehashexp, strlen(nonce)) != 0) |
418 | return MHD_INVALID_NONCE; | 437 | { |
419 | } | 438 | free(buffer); |
420 | 439 | return MHD_INVALID_NONCE; | |
421 | if ((cnonce = lookup_sub_value(buffer, len, "cnonce")) == NULL) { | 440 | } |
422 | free(buffer); | 441 | |
423 | return MHD_NO; | 442 | if ((cnonce = lookup_sub_value(buffer, len, "cnonce")) == NULL) |
424 | } | 443 | { |
425 | 444 | free(buffer); | |
426 | if ((qop = lookup_sub_value(buffer, len, "qop")) == NULL) { | 445 | return MHD_NO; |
427 | free(buffer); | 446 | } |
428 | return MHD_NO; | 447 | |
429 | } | 448 | if ((qop = lookup_sub_value(buffer, len, "qop")) == NULL) |
430 | 449 | { | |
431 | if ((nc = lookup_sub_value(buffer, len, "nc")) == NULL) { | 450 | free(buffer); |
432 | free(buffer); | 451 | return MHD_NO; |
433 | return MHD_NO; | 452 | } |
434 | } | 453 | |
435 | 454 | if ((nc = lookup_sub_value(buffer, len, "nc")) == NULL) | |
436 | if ((response = lookup_sub_value(buffer, len, "response")) == NULL) { | 455 | { |
437 | free(buffer); | 456 | free(buffer); |
438 | return MHD_NO; | 457 | return MHD_NO; |
439 | } | 458 | } |
440 | 459 | ||
441 | auth = digest_calc_ha1( | 460 | if ((response = lookup_sub_value(buffer, len, "response")) == NULL) |
442 | "md5", | 461 | { |
443 | username, | 462 | free(buffer); |
444 | realm, | 463 | return MHD_NO; |
445 | password, | 464 | } |
446 | nonce, | 465 | |
447 | cnonce, | 466 | auth = digest_calc_ha1("md5", |
448 | ha1 | 467 | username, |
449 | ); | 468 | realm, |
450 | 469 | password, | |
451 | if (auth) { | 470 | nonce, |
452 | free(buffer); | 471 | cnonce, |
453 | return MHD_NO; | 472 | ha1); |
454 | } | 473 | |
455 | 474 | if (auth) | |
456 | auth = digest_calc_response( | 475 | { |
457 | ha1, | 476 | free(buffer); |
458 | nonce, | 477 | return MHD_NO; |
459 | nc, | 478 | } |
460 | cnonce, | 479 | |
461 | qop, | 480 | auth = digest_calc_response(ha1, |
462 | connection->method, | 481 | nonce, |
463 | uri, | 482 | nc, |
464 | hentity, | 483 | cnonce, |
465 | respexp | 484 | qop, |
466 | ); | 485 | connection->method, |
467 | 486 | uri, | |
468 | if (auth) { | 487 | hentity, |
469 | free(buffer); | 488 | respexp); |
470 | return MHD_NO; | 489 | |
471 | } | 490 | if (auth) |
472 | 491 | { | |
473 | auth = strcmp(response, respexp) == 0 ? MHD_YES : MHD_NO; | 492 | free(buffer); |
474 | 493 | return MHD_NO; | |
475 | free(buffer); | 494 | } |
476 | 495 | ||
477 | return auth; | 496 | auth = strcmp(response, respexp) == 0 ? MHD_YES : MHD_NO; |
497 | |||
498 | free(buffer); | ||
499 | |||
500 | return auth; | ||
478 | } | 501 | } |
479 | 502 | ||
503 | |||
480 | /** | 504 | /** |
481 | * Queues a response to request authentication from the client | 505 | * Queues a response to request authentication from the client |
482 | * | 506 | * |
@@ -494,90 +518,91 @@ MHD_queue_auth_fail_response(struct MHD_Connection *connection, | |||
494 | const char *opaque, | 518 | const char *opaque, |
495 | int signal_stale) | 519 | int signal_stale) |
496 | { | 520 | { |
497 | int ret; | 521 | int ret; |
498 | size_t hlen; | 522 | size_t hlen; |
499 | unsigned char *tmpnonce; | 523 | unsigned char *tmpnonce; |
500 | char *header; | 524 | char *header; |
501 | unsigned char timestamp[5]; | 525 | unsigned char timestamp[5]; |
502 | char timestamphex[9]; | 526 | char timestamphex[9]; |
503 | char nonce[HASH_SHA1_HEX_LEN + 9]; | 527 | char nonce[HASH_SHA1_HEX_LEN + 9]; |
504 | time_t t; | 528 | time_t t; |
505 | struct MHD_Response *response; | 529 | struct MHD_Response *response; |
506 | gcry_error_t gerror; | 530 | gcry_error_t gerror; |
507 | gcry_md_hd_t sha1; | 531 | gcry_md_hd_t sha1; |
508 | 532 | ||
509 | response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); | 533 | response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); |
510 | 534 | if (!response) | |
511 | if (!response) return MHD_NO; | 535 | return MHD_NO; |
512 | 536 | ||
513 | /* | 537 | /* |
514 | * Generating the server nonce | 538 | * Generating the server nonce |
515 | */ | 539 | */ |
516 | 540 | ||
517 | gerror = gcry_md_open(&sha1, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); | 541 | gerror = gcry_md_open(&sha1, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); |
518 | 542 | ||
519 | if (gerror) return MHD_NO; | 543 | if (gerror) |
520 | 544 | return MHD_NO; | |
521 | time(&t); | 545 | |
522 | 546 | time(&t); | |
523 | timestamp[0] = (t & 0xff000000) >> 0x18; | 547 | |
524 | timestamp[1] = (t & 0x00ff0000) >> 0x10; | 548 | timestamp[0] = (t & 0xff000000) >> 0x18; |
525 | timestamp[2] = (t & 0x0000ff00) >> 0x08; | 549 | timestamp[1] = (t & 0x00ff0000) >> 0x10; |
526 | timestamp[3] = t & 0x000000ff; | 550 | timestamp[2] = (t & 0x0000ff00) >> 0x08; |
527 | timestamp[4] = '\0'; | 551 | timestamp[3] = t & 0x000000ff; |
528 | 552 | timestamp[4] = '\0'; | |
529 | gcry_md_write(sha1, timestamp, 4); | 553 | |
530 | gcry_md_write(sha1, ":", 1); | 554 | gcry_md_write(sha1, timestamp, 4); |
531 | gcry_md_write(sha1, connection->method, strlen(connection->method)); | 555 | gcry_md_write(sha1, ":", 1); |
532 | gcry_md_write(sha1, ":", 1); | 556 | gcry_md_write(sha1, connection->method, strlen(connection->method)); |
533 | gcry_md_write(sha1, password, strlen(password)); | 557 | gcry_md_write(sha1, ":", 1); |
534 | gcry_md_write(sha1, ":", 1); | 558 | gcry_md_write(sha1, password, strlen(password)); |
535 | gcry_md_write(sha1, connection->url, strlen(connection->url)); | 559 | gcry_md_write(sha1, ":", 1); |
536 | gcry_md_write(sha1, ":", 1); | 560 | gcry_md_write(sha1, connection->url, strlen(connection->url)); |
537 | gcry_md_write(sha1, realm, strlen(realm)); | 561 | gcry_md_write(sha1, ":", 1); |
538 | gcry_md_final(sha1); | 562 | gcry_md_write(sha1, realm, strlen(realm)); |
539 | 563 | gcry_md_final(sha1); | |
540 | tmpnonce = gcry_md_read(sha1, GCRY_MD_SHA1); | 564 | |
541 | 565 | tmpnonce = gcry_md_read(sha1, GCRY_MD_SHA1); | |
542 | cvthex(timestamp, 4, timestamphex); | 566 | |
543 | cvthex(tmpnonce, HASH_SHA1_LEN, nonce); | 567 | cvthex(timestamp, 4, timestamphex); |
544 | strncat(nonce, timestamphex, 8); | 568 | cvthex(tmpnonce, HASH_SHA1_LEN, nonce); |
545 | gcry_md_close(sha1); | 569 | strncat(nonce, timestamphex, 8); |
546 | 570 | gcry_md_close(sha1); | |
547 | /* | 571 | |
548 | * Building the authentication header | 572 | /* |
549 | */ | 573 | * Building the authentication header |
550 | hlen = snprintf(NULL, | 574 | */ |
551 | 0, | 575 | hlen = snprintf(NULL, |
552 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", | 576 | 0, |
553 | realm, | 577 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", |
554 | nonce, | 578 | realm, |
555 | opaque, | 579 | nonce, |
556 | signal_stale ? ",stale=true" : ""); | 580 | opaque, |
557 | { | 581 | signal_stale ? ",stale=true" : ""); |
558 | char header[hlen + 1]; | 582 | { |
559 | snprintf(header, | 583 | char header[hlen + 1]; |
560 | sizeof(header), | 584 | snprintf(header, |
561 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", | 585 | sizeof(header), |
562 | realm, | 586 | "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s", |
563 | nonce, | 587 | realm, |
564 | opaque, | 588 | nonce, |
565 | signal_stale ? ",stale=true" : ""); | 589 | opaque, |
566 | ret = MHD_add_response_header(response, | 590 | signal_stale ? ",stale=true" : ""); |
567 | MHD_HTTP_HEADER_WWW_AUTHENTICATE, | 591 | ret = MHD_add_response_header(response, |
568 | header); | 592 | MHD_HTTP_HEADER_WWW_AUTHENTICATE, |
569 | } | 593 | header); |
570 | if(!ret) | 594 | } |
571 | { | 595 | if(!ret) |
572 | MHD_destroy_response(response); | 596 | { |
573 | return MHD_NO; | 597 | MHD_destroy_response(response); |
574 | } | 598 | return MHD_NO; |
575 | 599 | } | |
576 | ret = MHD_queue_response(connection, MHD_HTTP_UNAUTHORIZED, response); | 600 | |
577 | 601 | ret = MHD_queue_response(connection, MHD_HTTP_UNAUTHORIZED, response); | |
578 | MHD_destroy_response(response); | 602 | |
579 | 603 | MHD_destroy_response(response); | |
580 | return ret; | 604 | |
605 | return ret; | ||
581 | } | 606 | } |
582 | 607 | ||
583 | /* end of digestauth.c */ | 608 | /* end of digestauth.c */ |