aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-08-22 15:03:32 +0000
committerChristian Grothoff <christian@grothoff.org>2010-08-22 15:03:32 +0000
commitdaa1e7fa9723ef2f60d6ea68b711c1254b4d9718 (patch)
treee47092fd021073136a5b93311357209d79d5e96b
parent9e7a668f097b6bbc321507cd6391d373e1e00def (diff)
downloadlibmicrohttpd-daa1e7fa9723ef2f60d6ea68b711c1254b4d9718.tar.gz
libmicrohttpd-daa1e7fa9723ef2f60d6ea68b711c1254b4d9718.zip
indentation
-rw-r--r--src/daemon/digestauth.c951
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 */
42static void 42static void
43cvthex(const unsigned char *bin, size_t len, char *hex) 43cvthex(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 */
62static int 64static int
63digest_calc_ha1(const char *alg, 65digest_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 */
107static int 117static int
108digest_calc_response(const char *ha1, /* H(A1) */ 118digest_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
178static const char * 188static const char *
179lookup_sub_value(char *data, size_t len, const char *key) 189lookup_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)
235char * 249char *
236MHD_digest_auth_get_username(struct MHD_Connection *connection) 250MHD_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 */