diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2022-01-27 18:27:29 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2022-01-27 18:48:03 +0300 |
commit | b5b731a456f382019bc6035f33632430c408695a (patch) | |
tree | 48e644a9b841709af1fb6d21153a54747c7c58f2 | |
parent | e0cb9221febf35fca0e8de5623ac7a92fc71b6b8 (diff) | |
download | libmicrohttpd-b5b731a456f382019bc6035f33632430c408695a.tar.gz libmicrohttpd-b5b731a456f382019bc6035f33632430c408695a.zip |
test_digestauth: added more detailed error reporting
-rw-r--r-- | src/testcurl/test_digestauth.c | 242 |
1 files changed, 178 insertions, 64 deletions
diff --git a/src/testcurl/test_digestauth.c b/src/testcurl/test_digestauth.c index 5bf5e8e0..04a3995d 100644 --- a/src/testcurl/test_digestauth.c +++ b/src/testcurl/test_digestauth.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libmicrohttpd | 2 | This file is part of libmicrohttpd |
3 | Copyright (C) 2010 Christian Grothoff | 3 | Copyright (C) 2010 Christian Grothoff |
4 | Copyright (C) 2016-2021 Evgeny Grin (Karlson2k) | 4 | Copyright (C) 2016-2022 Evgeny Grin (Karlson2k) |
5 | 5 | ||
6 | libmicrohttpd is free software; you can redistribute it and/or modify | 6 | libmicrohttpd is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published | 7 | it under the terms of the GNU General Public License as published |
@@ -46,6 +46,119 @@ | |||
46 | #include <wincrypt.h> | 46 | #include <wincrypt.h> |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | |||
50 | #if defined(HAVE___FUNC__) | ||
51 | #define externalErrorExit(ignore) \ | ||
52 | _externalErrorExit_func(NULL, __func__, __LINE__) | ||
53 | #define externalErrorExitDesc(errDesc) \ | ||
54 | _externalErrorExit_func(errDesc, __func__, __LINE__) | ||
55 | #define libcurlErrorExit(ignore) \ | ||
56 | _libcurlErrorExit_func(NULL, __func__, __LINE__) | ||
57 | #define libcurlErrorExitDesc(errDesc) \ | ||
58 | _libcurlErrorExit_func(errDesc, __func__, __LINE__) | ||
59 | #define mhdErrorExit(ignore) \ | ||
60 | _mhdErrorExit_func(NULL, __func__, __LINE__) | ||
61 | #define mhdErrorExitDesc(errDesc) \ | ||
62 | _mhdErrorExit_func(errDesc, __func__, __LINE__) | ||
63 | #elif defined(HAVE___FUNCTION__) | ||
64 | #define externalErrorExit(ignore) \ | ||
65 | _externalErrorExit_func(NULL, __FUNCTION__, __LINE__) | ||
66 | #define externalErrorExitDesc(errDesc) \ | ||
67 | _externalErrorExit_func(errDesc, __FUNCTION__, __LINE__) | ||
68 | #define libcurlErrorExit(ignore) \ | ||
69 | _libcurlErrorExit_func(NULL, __FUNCTION__, __LINE__) | ||
70 | #define libcurlErrorExitDesc(errDesc) \ | ||
71 | _libcurlErrorExit_func(errDesc, __FUNCTION__, __LINE__) | ||
72 | #define mhdErrorExit(ignore) \ | ||
73 | _mhdErrorExit_func(NULL, __FUNCTION__, __LINE__) | ||
74 | #define mhdErrorExitDesc(errDesc) \ | ||
75 | _mhdErrorExit_func(errDesc, __FUNCTION__, __LINE__) | ||
76 | #else | ||
77 | #define externalErrorExit(ignore) _externalErrorExit_func(NULL, NULL, __LINE__) | ||
78 | #define externalErrorExitDesc(errDesc) \ | ||
79 | _externalErrorExit_func(errDesc, NULL, __LINE__) | ||
80 | #define libcurlErrorExit(ignore) _libcurlErrorExit_func(NULL, NULL, __LINE__) | ||
81 | #define libcurlErrorExitDesc(errDesc) \ | ||
82 | _libcurlErrorExit_func(errDesc, NULL, __LINE__) | ||
83 | #define mhdErrorExit(ignore) _mhdErrorExit_func(NULL, NULL, __LINE__) | ||
84 | #define mhdErrorExitDesc(errDesc) _mhdErrorExit_func(errDesc, NULL, __LINE__) | ||
85 | #endif | ||
86 | |||
87 | |||
88 | _MHD_NORETURN static void | ||
89 | _externalErrorExit_func (const char *errDesc, const char *funcName, int lineNum) | ||
90 | { | ||
91 | fflush (stdout); | ||
92 | if ((NULL != errDesc) && (0 != errDesc[0])) | ||
93 | fprintf (stderr, "%s", errDesc); | ||
94 | else | ||
95 | fprintf (stderr, "System or external library call failed"); | ||
96 | if ((NULL != funcName) && (0 != funcName[0])) | ||
97 | fprintf (stderr, " in %s", funcName); | ||
98 | if (0 < lineNum) | ||
99 | fprintf (stderr, " at line %d", lineNum); | ||
100 | |||
101 | fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, | ||
102 | strerror (errno)); | ||
103 | #ifdef MHD_WINSOCK_SOCKETS | ||
104 | fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); | ||
105 | #endif /* MHD_WINSOCK_SOCKETS */ | ||
106 | fflush (stderr); | ||
107 | exit (99); | ||
108 | } | ||
109 | |||
110 | |||
111 | static char libcurl_errbuf[CURL_ERROR_SIZE] = ""; | ||
112 | |||
113 | _MHD_NORETURN static void | ||
114 | _libcurlErrorExit_func (const char *errDesc, const char *funcName, int lineNum) | ||
115 | { | ||
116 | fflush (stdout); | ||
117 | if ((NULL != errDesc) && (0 != errDesc[0])) | ||
118 | fprintf (stderr, "%s", errDesc); | ||
119 | else | ||
120 | fprintf (stderr, "CURL library call failed"); | ||
121 | if ((NULL != funcName) && (0 != funcName[0])) | ||
122 | fprintf (stderr, " in %s", funcName); | ||
123 | if (0 < lineNum) | ||
124 | fprintf (stderr, " at line %d", lineNum); | ||
125 | |||
126 | fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, | ||
127 | strerror (errno)); | ||
128 | if (0 != libcurl_errbuf[0]) | ||
129 | fprintf (stderr, "Last libcurl error details: %s\n", libcurl_errbuf); | ||
130 | |||
131 | fflush (stderr); | ||
132 | exit (99); | ||
133 | } | ||
134 | |||
135 | |||
136 | _MHD_NORETURN static void | ||
137 | _mhdErrorExit_func (const char *errDesc, const char *funcName, int lineNum) | ||
138 | { | ||
139 | fflush (stdout); | ||
140 | if ((NULL != errDesc) && (0 != errDesc[0])) | ||
141 | fprintf (stderr, "%s", errDesc); | ||
142 | else | ||
143 | fprintf (stderr, "MHD unexpected error"); | ||
144 | if ((NULL != funcName) && (0 != funcName[0])) | ||
145 | fprintf (stderr, " in %s", funcName); | ||
146 | if (0 < lineNum) | ||
147 | fprintf (stderr, " at line %d", lineNum); | ||
148 | |||
149 | fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, | ||
150 | strerror (errno)); | ||
151 | |||
152 | fflush (stderr); | ||
153 | exit (8); | ||
154 | } | ||
155 | |||
156 | |||
157 | /* Could be increased to facilitate debugging */ | ||
158 | #define TIMEOUTS_VAL 5 | ||
159 | |||
160 | #define MHD_URI_BASE_PATH "/bar%%20foo%%3Fkey%%3Dvalue" | ||
161 | |||
49 | #define PAGE \ | 162 | #define PAGE \ |
50 | "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>" | 163 | "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>" |
51 | 164 | ||
@@ -71,7 +184,7 @@ copyBuffer (void *ptr, | |||
71 | struct CBC *cbc = ctx; | 184 | struct CBC *cbc = ctx; |
72 | 185 | ||
73 | if (cbc->pos + size * nmemb > cbc->size) | 186 | if (cbc->pos + size * nmemb > cbc->size) |
74 | return 0; /* overflow */ | 187 | mhdErrorExitDesc ("Wrong too large data"); /* overflow */ |
75 | memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); | 188 | memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); |
76 | cbc->pos += size * nmemb; | 189 | cbc->pos += size * nmemb; |
77 | return size * nmemb; | 190 | return size * nmemb; |
@@ -113,12 +226,16 @@ ahc_echo (void *cls, | |||
113 | response = MHD_create_response_from_buffer (strlen (DENIED), | 226 | response = MHD_create_response_from_buffer (strlen (DENIED), |
114 | DENIED, | 227 | DENIED, |
115 | MHD_RESPMEM_PERSISTENT); | 228 | MHD_RESPMEM_PERSISTENT); |
229 | if (NULL == response) | ||
230 | mhdErrorExitDesc ("MHD_create_response_from_buffer failed"); | ||
116 | ret = MHD_queue_auth_fail_response2 (connection, | 231 | ret = MHD_queue_auth_fail_response2 (connection, |
117 | realm, | 232 | realm, |
118 | MY_OPAQUE, | 233 | MY_OPAQUE, |
119 | response, | 234 | response, |
120 | MHD_NO, | 235 | MHD_NO, |
121 | MHD_DIGEST_ALG_MD5); | 236 | MHD_DIGEST_ALG_MD5); |
237 | if (MHD_YES != ret) | ||
238 | mhdErrorExitDesc ("MHD_queue_auth_fail_response2 failed"); | ||
122 | MHD_destroy_response (response); | 239 | MHD_destroy_response (response); |
123 | return ret; | 240 | return ret; |
124 | } | 241 | } |
@@ -136,7 +253,7 @@ ahc_echo (void *cls, | |||
136 | DENIED, | 253 | DENIED, |
137 | MHD_RESPMEM_PERSISTENT); | 254 | MHD_RESPMEM_PERSISTENT); |
138 | if (NULL == response) | 255 | if (NULL == response) |
139 | return MHD_NO; | 256 | mhdErrorExitDesc ("MHD_create_response_from_buffer() failed"); |
140 | ret = MHD_queue_auth_fail_response2 (connection, | 257 | ret = MHD_queue_auth_fail_response2 (connection, |
141 | realm, | 258 | realm, |
142 | MY_OPAQUE, | 259 | MY_OPAQUE, |
@@ -144,20 +261,60 @@ ahc_echo (void *cls, | |||
144 | (MHD_INVALID_NONCE == ret_i) ? | 261 | (MHD_INVALID_NONCE == ret_i) ? |
145 | MHD_YES : MHD_NO, | 262 | MHD_YES : MHD_NO, |
146 | MHD_DIGEST_ALG_MD5); | 263 | MHD_DIGEST_ALG_MD5); |
264 | if (MHD_YES != ret) | ||
265 | mhdErrorExitDesc ("MHD_queue_auth_fail_response2() failed"); | ||
147 | MHD_destroy_response (response); | 266 | MHD_destroy_response (response); |
148 | return ret; | 267 | return ret; |
149 | } | 268 | } |
150 | response = MHD_create_response_from_buffer (strlen (PAGE), | 269 | response = MHD_create_response_from_buffer (strlen (PAGE), |
151 | PAGE, | 270 | PAGE, |
152 | MHD_RESPMEM_PERSISTENT); | 271 | MHD_RESPMEM_PERSISTENT); |
272 | if (NULL == response) | ||
273 | mhdErrorExitDesc ("MHD_create_response_from_buffer() failed"); | ||
153 | ret = MHD_queue_response (connection, | 274 | ret = MHD_queue_response (connection, |
154 | MHD_HTTP_OK, | 275 | MHD_HTTP_OK, |
155 | response); | 276 | response); |
277 | if (MHD_YES != ret) | ||
278 | mhdErrorExitDesc ("MHD_queue_auth_fail_response2() failed"); | ||
156 | MHD_destroy_response (response); | 279 | MHD_destroy_response (response); |
157 | return ret; | 280 | return ret; |
158 | } | 281 | } |
159 | 282 | ||
160 | 283 | ||
284 | static CURL * | ||
285 | setupCURL (void *cbc, int port) | ||
286 | { | ||
287 | CURL *c; | ||
288 | |||
289 | c = curl_easy_init (); | ||
290 | if (NULL == c) | ||
291 | libcurlErrorExitDesc ("curl_easy_init() failed"); | ||
292 | |||
293 | if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)) || | ||
294 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_URL, | ||
295 | "http://127.0.0.1" MHD_URI_BASE_PATH)) || | ||
296 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_PORT, (long) port)) || | ||
297 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, | ||
298 | ©Buffer)) || | ||
299 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc)) || | ||
300 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, | ||
301 | (long) TIMEOUTS_VAL)) || | ||
302 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_TIMEOUT, | ||
303 | (long) TIMEOUTS_VAL)) || | ||
304 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_ERRORBUFFER, | ||
305 | libcurl_errbuf)) || | ||
306 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L)) || | ||
307 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTP_VERSION, | ||
308 | CURL_HTTP_VERSION_1_1))) | ||
309 | libcurlErrorExitDesc ("curl_easy_setopt() failed"); | ||
310 | if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST)) || | ||
311 | (CURLE_OK != curl_easy_setopt (c, CURLOPT_USERPWD, | ||
312 | "testuser:testpass"))) | ||
313 | libcurlErrorExitDesc ("curl_easy_setopt() authorization options failed"); | ||
314 | return c; | ||
315 | } | ||
316 | |||
317 | |||
161 | static int | 318 | static int |
162 | testDigestAuth () | 319 | testDigestAuth () |
163 | { | 320 | { |
@@ -168,7 +325,6 @@ testDigestAuth () | |||
168 | char buf[2048]; | 325 | char buf[2048]; |
169 | char rnd[8]; | 326 | char rnd[8]; |
170 | int port; | 327 | int port; |
171 | char url[128]; | ||
172 | #ifndef WINDOWS | 328 | #ifndef WINDOWS |
173 | int fd; | 329 | int fd; |
174 | size_t len; | 330 | size_t len; |
@@ -187,27 +343,15 @@ testDigestAuth () | |||
187 | fd = open ("/dev/urandom", | 343 | fd = open ("/dev/urandom", |
188 | O_RDONLY); | 344 | O_RDONLY); |
189 | if (-1 == fd) | 345 | if (-1 == fd) |
190 | { | 346 | externalErrorExitDesc ("Failed to open '/dev/urandom'"); |
191 | fprintf (stderr, | 347 | |
192 | "Failed to open `%s': %s\n", | ||
193 | "/dev/urandom", | ||
194 | strerror (errno)); | ||
195 | return 1; | ||
196 | } | ||
197 | while (off < 8) | 348 | while (off < 8) |
198 | { | 349 | { |
199 | len = read (fd, | 350 | len = read (fd, |
200 | rnd, | 351 | rnd, |
201 | 8); | 352 | 8); |
202 | if (len == (size_t) -1) | 353 | if (len == (size_t) -1) |
203 | { | 354 | externalErrorExitDesc ("Failed to read '/dev/urandom'"); |
204 | fprintf (stderr, | ||
205 | "Failed to read `%s': %s\n", | ||
206 | "/dev/urandom", | ||
207 | strerror (errno)); | ||
208 | (void) close (fd); | ||
209 | return 1; | ||
210 | } | ||
211 | off += len; | 355 | off += len; |
212 | } | 356 | } |
213 | (void) close (fd); | 357 | (void) close (fd); |
@@ -222,22 +366,11 @@ testDigestAuth () | |||
222 | PROV_RSA_FULL, | 366 | PROV_RSA_FULL, |
223 | CRYPT_VERIFYCONTEXT); | 367 | CRYPT_VERIFYCONTEXT); |
224 | if (b == 0) | 368 | if (b == 0) |
225 | { | 369 | externalErrorExitDesc ("CryptAcquireContext() failed"); |
226 | fprintf (stderr, | ||
227 | "Failed to acquire crypto provider context: %lu\n", | ||
228 | GetLastError ()); | ||
229 | return 1; | ||
230 | } | ||
231 | b = CryptGenRandom (cc, 8, (BYTE *) rnd); | 370 | b = CryptGenRandom (cc, 8, (BYTE *) rnd); |
232 | if (b == 0) | 371 | if (b == 0) |
233 | { | 372 | externalErrorExitDesc ("CryptGenRandom() failed"); |
234 | fprintf (stderr, | ||
235 | "Failed to generate 8 random bytes: %lu\n", | ||
236 | GetLastError ()); | ||
237 | } | ||
238 | CryptReleaseContext (cc, 0); | 373 | CryptReleaseContext (cc, 0); |
239 | if (b == 0) | ||
240 | return 1; | ||
241 | } | 374 | } |
242 | #endif | 375 | #endif |
243 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, | 376 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, |
@@ -256,45 +389,26 @@ testDigestAuth () | |||
256 | MHD_DAEMON_INFO_BIND_PORT); | 389 | MHD_DAEMON_INFO_BIND_PORT); |
257 | if ( (NULL == dinfo) || | 390 | if ( (NULL == dinfo) || |
258 | (0 == dinfo->port) ) | 391 | (0 == dinfo->port) ) |
259 | { | 392 | mhdErrorExitDesc ("MHD_get_daemon_info() failed"); |
260 | MHD_stop_daemon (d); | ||
261 | return 32; | ||
262 | } | ||
263 | port = (int) dinfo->port; | 393 | port = (int) dinfo->port; |
264 | } | 394 | } |
265 | snprintf (url, | 395 | c = setupCURL (&cbc, port); |
266 | sizeof (url), | ||
267 | "http://127.0.0.1:%d/bar%%20foo%%3Fkey%%3Dvalue", | ||
268 | port); | ||
269 | c = curl_easy_init (); | ||
270 | curl_easy_setopt (c, CURLOPT_URL, url); | ||
271 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
272 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
273 | curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); | ||
274 | curl_easy_setopt (c, CURLOPT_USERPWD, "testuser:testpass"); | ||
275 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
276 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
277 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
278 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
279 | /* NOTE: use of CONNECTTIMEOUT without also | ||
280 | setting NOSIGNAL results in really weird | ||
281 | crashes on my system!*/ | ||
282 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
283 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | 396 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
284 | { | 397 | mhdErrorExitDesc ("curl_easy_perform() failed"); |
285 | fprintf (stderr, | ||
286 | "curl_easy_perform failed: `%s'\n", | ||
287 | curl_easy_strerror (errornum)); | ||
288 | curl_easy_cleanup (c); | ||
289 | MHD_stop_daemon (d); | ||
290 | return 2; | ||
291 | } | ||
292 | curl_easy_cleanup (c); | 398 | curl_easy_cleanup (c); |
293 | MHD_stop_daemon (d); | 399 | MHD_stop_daemon (d); |
294 | if (cbc.pos != strlen (PAGE)) | 400 | if (cbc.pos != strlen (PAGE)) |
295 | return 4; | 401 | { |
402 | fprintf (stderr, "Got %u bytes ('%.*s'), expected %u bytes. ", | ||
403 | (unsigned) cbc.pos, (int) cbc.pos, cbc.buf, | ||
404 | (unsigned) strlen (MHD_URI_BASE_PATH)); | ||
405 | mhdErrorExitDesc ("Wrong returned data length"); | ||
406 | } | ||
296 | if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE))) | 407 | if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE))) |
297 | return 8; | 408 | { |
409 | fprintf (stderr, "Got invalid response '%.*s'. ", (int) cbc.pos, cbc.buf); | ||
410 | mhdErrorExitDesc ("Wrong returned data"); | ||
411 | } | ||
298 | return 0; | 412 | return 0; |
299 | } | 413 | } |
300 | 414 | ||