aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-01-27 18:27:29 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-01-27 18:48:03 +0300
commitb5b731a456f382019bc6035f33632430c408695a (patch)
tree48e644a9b841709af1fb6d21153a54747c7c58f2
parente0cb9221febf35fca0e8de5623ac7a92fc71b6b8 (diff)
downloadlibmicrohttpd-b5b731a456f382019bc6035f33632430c408695a.tar.gz
libmicrohttpd-b5b731a456f382019bc6035f33632430c408695a.zip
test_digestauth: added more detailed error reporting
-rw-r--r--src/testcurl/test_digestauth.c242
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
111static 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
284static CURL *
285setupCURL (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 &copyBuffer)) ||
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
161static int 318static int
162testDigestAuth () 319testDigestAuth ()
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, &copyBuffer);
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