aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-12-08 22:54:33 +0100
committerChristian Grothoff <christian@grothoff.org>2018-12-08 22:54:33 +0100
commit2897bd23e57cf016a713876e551cd20b8a28427d (patch)
tree835d3e5972f83fd55eca47af047acdf3ce4eac23
parentbcba3f58c5fc9b4a3776494d3edddceb244ab110 (diff)
downloadlibmicrohttpd-2897bd23e57cf016a713876e551cd20b8a28427d.tar.gz
libmicrohttpd-2897bd23e57cf016a713876e551cd20b8a28427d.zip
add test for RFC 7616 and document new API
-rw-r--r--ChangeLog3
-rw-r--r--doc/libmicrohttpd.texi126
-rw-r--r--src/include/microhttpd.h2
-rw-r--r--src/testcurl/.gitignore2
-rw-r--r--src/testcurl/Makefile.am9
-rw-r--r--src/testcurl/test_digestauth_sha256.c314
6 files changed, 438 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 352cdc8e..c482a6a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
1Sat Dec 8 22:53:56 CET 2018
2 Added test for RFC 7616 and documented new API. -CG
3
1Sat Dec 8 17:34:58 CET 2018 4Sat Dec 8 17:34:58 CET 2018
2 Adding support for RFC 7616, experimental, needs 5 Adding support for RFC 7616, experimental, needs
3 testing and documentation still! -CG 6 testing and documentation still! -CG
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index 851f23cc..f2e3576c 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -2440,15 +2440,57 @@ client with a 401 HTTP status.
2440@node microhttpd-dauth digest 2440@node microhttpd-dauth digest
2441@section Using Digest Authentication 2441@section Using Digest Authentication
2442 2442
2443MHD supports MD5 (deprecated by IETF) and SHA-256 hash algorithms
2444for digest authentication. The @code{MHD_DigestAuthAlgorithm} enumeration
2445is used to specify which algorithm should be used.
2446
2447@deftp {Enumeration} MHD_DigestAuthAlgorithm
2448Which digest algorithm should be used. Must be used consistently.
2449
2450@table @code
2451@item MHD_DIGEST_ALG_AUTO
2452Have MHD pick an algorithm currently considered secure. For now defaults to SHA-256.
2453
2454@item MHD_DIGEST_ALG_MD5
2455Force use of (deprecated, ancient, insecure) MD5.
2456
2457@item MHD_DIGEST_ALG_SHA256
2458Force use of SHA-256.
2459
2460@end table
2461@end deftp
2462
2463
2443@deftypefun {char *} MHD_digest_auth_get_username (struct MHD_Connection *connection) 2464@deftypefun {char *} MHD_digest_auth_get_username (struct MHD_Connection *connection)
2444Find and return a pointer to the username value from the request header. 2465Find and return a pointer to the username value from the request header.
2445Return @code{NULL} if the value is not found or header does not exist. 2466Return @code{NULL} if the value is not found or header does not exist.
2446If returned value is not @code{NULL}, the value must be @code{MHD_free()}'ed. 2467If returned value is not @code{NULL}, the value must be @code{MHD_free()}'ed.
2447@end deftypefun 2468@end deftypefun
2448 2469
2470@deftypefun int MHD_digest_auth_check2 (struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
2471Checks if the provided values in the WWW-Authenticate header are valid
2472and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}.
2473
2474@var{realm} must reference to a zero-terminated string representing the realm.
2475
2476@var{username} must reference to a zero-terminated string representing the username,
2477it is usually the returned value from MHD_digest_auth_get_username.
2478
2479@var{password} must reference to a zero-terminated string representing the password,
2480most probably it will be the result of a lookup of the username against a local database.
2481
2482@var{nonce_timeout} is the amount of time in seconds for a nonce to be invalid.
2483Most of the time it is sound to specify 300 seconds as its values.
2484
2485@var{algo} which digest algorithm should we use.
2486@end deftypefun
2487
2488
2449@deftypefun int MHD_digest_auth_check (struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout) 2489@deftypefun int MHD_digest_auth_check (struct MHD_Connection *connection, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
2450Checks if the provided values in the WWW-Authenticate header are valid 2490Checks if the provided values in the WWW-Authenticate header are valid
2451and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}. 2491and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}.
2492Deprecated, use @code{MHD_digest_auth_check2} instead.
2493
2452 2494
2453@var{realm} must reference to a zero-terminated string representing the realm. 2495@var{realm} must reference to a zero-terminated string representing the realm.
2454 2496
@@ -2462,9 +2504,29 @@ most probably it will be the result of a lookup of the username against a local
2462Most of the time it is sound to specify 300 seconds as its values. 2504Most of the time it is sound to specify 300 seconds as its values.
2463@end deftypefun 2505@end deftypefun
2464 2506
2507
2508
2509@deftypefun int MHD_digest_auth_check_digest2 (struct MHD_Connection *connection, const char *realm, const char *username, const uint8_t *digest, unsigned int nonce_timeout, enum MHD_DigestAuthAlgorithm algo)
2510Checks if the provided values in the WWW-Authenticate header are valid
2511and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}.
2512
2513@var{realm} must reference to a zero-terminated string representing the realm.
2514
2515@var{username} must reference to a zero-terminated string representing the username,
2516it is usually the returned value from MHD_digest_auth_get_username.
2517
2518@var{digest} pointer to the binary MD5 sum for the precalculated hash value ``userame:realm:password''. The size must match the selected @var{algo}!
2519
2520@var{nonce_timeout} is the amount of time in seconds for a nonce to be invalid.
2521Most of the time it is sound to specify 300 seconds as its values.
2522
2523@var{algo} digest authentication algorithm to use.
2524@end deftypefun
2525
2465@deftypefun int MHD_digest_auth_check_digest (struct MHD_Connection *connection, const char *realm, const char *username, const unsigned char digest[MHD_MD5_DIGEST_SIZE], unsigned int nonce_timeout) 2526@deftypefun int MHD_digest_auth_check_digest (struct MHD_Connection *connection, const char *realm, const char *username, const unsigned char digest[MHD_MD5_DIGEST_SIZE], unsigned int nonce_timeout)
2466Checks if the provided values in the WWW-Authenticate header are valid 2527Checks if the provided values in the WWW-Authenticate header are valid
2467and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}. 2528and sound according to RFC2716. If valid return @code{MHD_YES}, otherwise return @code{MHD_NO}.
2529Deprecated, use @code{MHD_digest_auth_check_digest2} instead.
2468 2530
2469@var{realm} must reference to a zero-terminated string representing the realm. 2531@var{realm} must reference to a zero-terminated string representing the realm.
2470 2532
@@ -2477,6 +2539,31 @@ it is usually the returned value from MHD_digest_auth_get_username.
2477Most of the time it is sound to specify 300 seconds as its values. 2539Most of the time it is sound to specify 300 seconds as its values.
2478@end deftypefun 2540@end deftypefun
2479 2541
2542
2543@deftypefun int MHD_queue_auth_fail_response2 (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale, enum MHD_DigestAuthAlgorithm algo)
2544Queues a response to request authentication from the client,
2545return @code{MHD_YES} if successful, otherwise @code{MHD_NO}.
2546
2547@var{realm} must reference to a zero-terminated string representing the realm.
2548
2549@var{opaque} must reference to a zero-terminated string representing a value
2550that gets passed to the client and expected to be passed again to the server
2551as-is. This value can be a hexadecimal or base64 string.
2552
2553@var{response} a response structure to specify what shall be presented to the
2554client with a 401 HTTP status.
2555
2556@var{signal_stale} a value that signals "stale=true" in the response header to
2557indicate the invalidity of the nonce and no need to ask for authentication
2558parameters and only a new nonce gets generated. @code{MHD_YES} to generate a new
2559nonce, @code{MHD_NO} to ask for authentication parameters.
2560
2561@var{algo} which digest algorithm should we use. The same algorithm
2562must then be selected when checking digests received from clients!
2563
2564@end deftypefun
2565
2566
2480@deftypefun int MHD_queue_auth_fail_response (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale) 2567@deftypefun int MHD_queue_auth_fail_response (struct MHD_Connection *connection, const char *realm, const char *opaque, struct MHD_Response *response, int signal_stale)
2481Queues a response to request authentication from the client, 2568Queues a response to request authentication from the client,
2482return @code{MHD_YES} if successful, otherwise @code{MHD_NO}. 2569return @code{MHD_YES} if successful, otherwise @code{MHD_NO}.
@@ -2517,23 +2604,27 @@ ahc_echo (void *cls,
2517 const char *realm = "test@@example.com"; 2604 const char *realm = "test@@example.com";
2518 int ret; 2605 int ret;
2519 2606
2520 username = MHD_digest_auth_get_username(connection); 2607 username = MHD_digest_auth_get_username (connection);
2521 if (username == NULL) 2608 if (username == NULL)
2522 @{ 2609 @{
2523 response = MHD_create_response_from_buffer(strlen (DENIED), 2610 response = MHD_create_response_from_buffer(strlen (DENIED),
2524 DENIED, 2611 DENIED,
2525 MHD_RESPMEM_PERSISTENT); 2612 MHD_RESPMEM_PERSISTENT);
2526 ret = MHD_queue_auth_fail_response(connection, realm, 2613 ret = MHD_queue_auth_fail_response2 (connection,
2527 OPAQUE, 2614 realm,
2528 response, 2615 OPAQUE,
2529 MHD_NO); 2616 response,
2617 MHD_NO,
2618 MHD_DIGEST_ALG_SHA256);
2530 MHD_destroy_response(response); 2619 MHD_destroy_response(response);
2531 return ret; 2620 return ret;
2532 @} 2621 @}
2533 ret = MHD_digest_auth_check(connection, realm, 2622 ret = MHD_digest_auth_check2 (connection,
2534 username, 2623 realm,
2535 password, 2624 username,
2536 300); 2625 password,
2626 300,
2627 MHD_DIGEST_ALG_SHA256);
2537 free(username); 2628 free(username);
2538 if ( (ret == MHD_INVALID_NONCE) || 2629 if ( (ret == MHD_INVALID_NONCE) ||
2539 (ret == MHD_NO) ) 2630 (ret == MHD_NO) )
@@ -2543,16 +2634,21 @@ ahc_echo (void *cls,
2543 MHD_RESPMEM_PERSISTENT); 2634 MHD_RESPMEM_PERSISTENT);
2544 if (NULL == response) 2635 if (NULL == response)
2545 return MHD_NO; 2636 return MHD_NO;
2546 ret = MHD_queue_auth_fail_response(connection, realm, 2637 ret = MHD_queue_auth_fail_response2 (connection,
2547 OPAQUE, 2638 realm,
2548 response, 2639 OPAQUE,
2549 (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO); 2640 response,
2641 (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO,
2642 MHD_DIGEST_ALG_SHA256);
2550 MHD_destroy_response(response); 2643 MHD_destroy_response(response);
2551 return ret; 2644 return ret;
2552 @} 2645 @}
2553 response = MHD_create_response_from_buffer (strlen(PAGE), PAGE, 2646 response = MHD_create_response_from_buffer (strlen(PAGE),
2647 PAGE,
2554 MHD_RESPMEM_PERSISTENT); 2648 MHD_RESPMEM_PERSISTENT);
2555 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); 2649 ret = MHD_queue_response (connection,
2650 MHD_HTTP_OK,
2651 response);
2556 MHD_destroy_response(response); 2652 MHD_destroy_response(response);
2557 return ret; 2653 return ret;
2558@} 2654@}
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 7591bdc4..2362d2bc 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -3331,7 +3331,7 @@ MHD_digest_auth_check_digest (struct MHD_Connection *connection,
3331 * @return #MHD_YES on success, #MHD_NO otherwise 3331 * @return #MHD_YES on success, #MHD_NO otherwise
3332 * @ingroup authentication 3332 * @ingroup authentication
3333 */ 3333 */
3334int 3334_MHD_EXTERN int
3335MHD_queue_auth_fail_response2 (struct MHD_Connection *connection, 3335MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
3336 const char *realm, 3336 const char *realm,
3337 const char *opaque, 3337 const char *opaque,
diff --git a/src/testcurl/.gitignore b/src/testcurl/.gitignore
index 5f2e7da2..747b4b9d 100644
--- a/src/testcurl/.gitignore
+++ b/src/testcurl/.gitignore
@@ -104,4 +104,4 @@
104*.exe 104*.exe
105test_quiesce_stream 105test_quiesce_stream
106test_large_put_inc11 106test_large_put_inc11
107/test_delete \ No newline at end of file 107/test_deletetest_digestauth_sha256
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index e564241c..fde060c5 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -23,7 +23,7 @@ THREAD_ONLY_TESTS = \
23 test_long_header11 \ 23 test_long_header11 \
24 test_iplimit11 \ 24 test_iplimit11 \
25 test_termination \ 25 test_termination \
26 test_timeout 26 test_timeout
27 27
28 28
29 29
@@ -42,6 +42,7 @@ endif
42if ENABLE_DAUTH 42if ENABLE_DAUTH
43 THREAD_ONLY_TESTS += \ 43 THREAD_ONLY_TESTS += \
44 test_digestauth \ 44 test_digestauth \
45 test_digestauth_sha256 \
45 test_digestauth_with_arguments 46 test_digestauth_with_arguments
46endif 47endif
47 48
@@ -156,6 +157,12 @@ test_digestauth_LDADD = \
156 $(top_builddir)/src/microhttpd/libmicrohttpd.la \ 157 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
157 @LIBGCRYPT_LIBS@ @LIBCURL@ 158 @LIBGCRYPT_LIBS@ @LIBCURL@
158 159
160test_digestauth_sha256_SOURCES = \
161 test_digestauth_sha256.c
162test_digestauth_sha256_LDADD = \
163 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
164 @LIBGCRYPT_LIBS@ @LIBCURL@
165
159test_digestauth_with_arguments_SOURCES = \ 166test_digestauth_with_arguments_SOURCES = \
160 test_digestauth_with_arguments.c 167 test_digestauth_with_arguments.c
161test_digestauth_with_arguments_LDADD = \ 168test_digestauth_with_arguments_LDADD = \
diff --git a/src/testcurl/test_digestauth_sha256.c b/src/testcurl/test_digestauth_sha256.c
new file mode 100644
index 00000000..aaa57bbe
--- /dev/null
+++ b/src/testcurl/test_digestauth_sha256.c
@@ -0,0 +1,314 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2010, 2018 Christian Grothoff
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file daemontest_digestauth_sha256.c
23 * @brief Testcase for libmicrohttpd Digest Auth with SHA256
24 * @author Amr Ali
25 * @author Christian Grothoff
26 */
27
28#include "MHD_config.h"
29#include "platform.h"
30#include <curl/curl.h>
31#include <microhttpd.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35#ifdef MHD_HTTPS_REQUIRE_GRYPT
36#ifdef HAVE_GCRYPT_H
37#include <gcrypt.h>
38#endif
39#endif /* MHD_HTTPS_REQUIRE_GRYPT */
40
41#ifndef WINDOWS
42#include <sys/socket.h>
43#include <unistd.h>
44#else
45#include <wincrypt.h>
46#endif
47
48#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>"
49
50#define DENIED "<html><head><title>libmicrohttpd demo</title></head><body>Access denied</body></html>"
51
52#define MY_OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
53
54struct CBC
55{
56 char *buf;
57 size_t pos;
58 size_t size;
59};
60
61
62static size_t
63copyBuffer (void *ptr,
64 size_t size,
65 size_t nmemb,
66 void *ctx)
67{
68 struct CBC *cbc = ctx;
69
70 if (cbc->pos + size * nmemb > cbc->size)
71 return 0; /* overflow */
72 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
73 cbc->pos += size * nmemb;
74 return size * nmemb;
75}
76
77
78static int
79ahc_echo (void *cls,
80 struct MHD_Connection *connection,
81 const char *url,
82 const char *method,
83 const char *version,
84 const char *upload_data,
85 size_t *upload_data_size,
86 void **unused)
87{
88 struct MHD_Response *response;
89 char *username;
90 const char *password = "testpass";
91 const char *realm = "test@example.com";
92 int ret;
93 (void)cls;(void)url; /* Unused. Silent compiler warning. */
94 (void)method;(void)version;(void)upload_data; /* Unused. Silent compiler warning. */
95 (void)upload_data_size;(void)unused; /* Unused. Silent compiler warning. */
96
97 username = MHD_digest_auth_get_username (connection);
98 if ( (username == NULL) ||
99 (0 != strcmp (username, "testuser")) )
100 {
101 response = MHD_create_response_from_buffer (strlen (DENIED),
102 DENIED,
103 MHD_RESPMEM_PERSISTENT);
104 ret = MHD_queue_auth_fail_response2 (connection,
105 realm,
106 MY_OPAQUE,
107 response,
108 MHD_NO,
109 MHD_DIGEST_ALG_SHA256);
110 MHD_destroy_response(response);
111 return ret;
112 }
113 ret = MHD_digest_auth_check2 (connection,
114 realm,
115 username,
116 password,
117 300,
118 MHD_DIGEST_ALG_SHA256);
119 free (username);
120 if ( (ret == MHD_INVALID_NONCE) ||
121 (ret == MHD_NO) )
122 {
123 response = MHD_create_response_from_buffer (strlen (DENIED),
124 DENIED,
125 MHD_RESPMEM_PERSISTENT);
126 if (NULL == response)
127 return MHD_NO;
128 ret = MHD_queue_auth_fail_response2 (connection,
129 realm,
130 MY_OPAQUE,
131 response,
132 (MHD_INVALID_NONCE == ret) ? MHD_YES : MHD_NO,
133 MHD_DIGEST_ALG_SHA256);
134 MHD_destroy_response(response);
135 return ret;
136 }
137 response = MHD_create_response_from_buffer (strlen(PAGE),
138 PAGE,
139 MHD_RESPMEM_PERSISTENT);
140 ret = MHD_queue_response (connection,
141 MHD_HTTP_OK,
142 response);
143 MHD_destroy_response (response);
144 return ret;
145}
146
147
148static int
149testDigestAuth ()
150{
151 CURL *c;
152 CURLcode errornum;
153 struct MHD_Daemon *d;
154 struct CBC cbc;
155 char buf[2048];
156 char rnd[8];
157 int port;
158 char url[128];
159#ifndef WINDOWS
160 int fd;
161 size_t len;
162 size_t off = 0;
163#endif /* ! WINDOWS */
164
165 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
166 port = 0;
167 else
168 port = 1165;
169
170 cbc.buf = buf;
171 cbc.size = 2048;
172 cbc.pos = 0;
173#ifndef WINDOWS
174 fd = open ("/dev/urandom",
175 O_RDONLY);
176 if (-1 == fd)
177 {
178 fprintf (stderr,
179 "Failed to open `%s': %s\n",
180 "/dev/urandom",
181 strerror(errno));
182 return 1;
183 }
184 while (off < 8)
185 {
186 len = read (fd,
187 rnd,
188 8);
189 if (len == (size_t)-1)
190 {
191 fprintf (stderr,
192 "Failed to read `%s': %s\n",
193 "/dev/urandom",
194 strerror(errno));
195 (void) close(fd);
196 return 1;
197 }
198 off += len;
199 }
200 (void) close(fd);
201#else
202 {
203 HCRYPTPROV cc;
204 BOOL b;
205
206 b = CryptAcquireContext (&cc,
207 NULL,
208 NULL,
209 PROV_RSA_FULL,
210 CRYPT_VERIFYCONTEXT);
211 if (b == 0)
212 {
213 fprintf (stderr,
214 "Failed to acquire crypto provider context: %lu\n",
215 GetLastError ());
216 return 1;
217 }
218 b = CryptGenRandom (cc, 8, (BYTE*)rnd);
219 if (b == 0)
220 {
221 fprintf (stderr,
222 "Failed to generate 8 random bytes: %lu\n",
223 GetLastError ());
224 }
225 CryptReleaseContext (cc, 0);
226 if (b == 0)
227 return 1;
228 }
229#endif
230 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
231 port, NULL, NULL,
232 &ahc_echo, PAGE,
233 MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof (rnd), rnd,
234 MHD_OPTION_NONCE_NC_SIZE, 300,
235 MHD_OPTION_END);
236 if (d == NULL)
237 return 1;
238 if (0 == port)
239 {
240 const union MHD_DaemonInfo *dinfo;
241
242 dinfo = MHD_get_daemon_info (d,
243 MHD_DAEMON_INFO_BIND_PORT);
244 if ( (NULL == dinfo) ||
245 (0 == dinfo->port) )
246 {
247 MHD_stop_daemon (d);
248 return 32;
249 }
250 port = (int)dinfo->port;
251 }
252 snprintf (url,
253 sizeof (url),
254 "http://127.0.0.1:%d/bar%%20foo%%3Fkey%%3Dvalue",
255 port);
256 c = curl_easy_init ();
257 curl_easy_setopt (c, CURLOPT_URL, url);
258 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
259 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
260 curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
261 curl_easy_setopt (c, CURLOPT_USERPWD, "testuser:testpass");
262 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
263 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
264 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
265 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
266 /* NOTE: use of CONNECTTIMEOUT without also
267 setting NOSIGNAL results in really weird
268 crashes on my system!*/
269 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
270 if (CURLE_OK != (errornum = curl_easy_perform (c)))
271 {
272 fprintf (stderr,
273 "curl_easy_perform failed: `%s'\n",
274 curl_easy_strerror (errornum));
275 curl_easy_cleanup (c);
276 MHD_stop_daemon (d);
277 return 2;
278 }
279 curl_easy_cleanup (c);
280 MHD_stop_daemon (d);
281 if (cbc.pos != strlen (PAGE))
282 return 4;
283 if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE)))
284 return 8;
285 return 0;
286}
287
288
289int
290main (int argc, char *const *argv)
291{
292 unsigned int errorCount = 0;
293 curl_version_info_data *d = curl_version_info (CURLVERSION_NOW);
294 (void)argc; (void)argv; /* Unused. Silent compiler warning. */
295
296 /* curl added SHA256 support in 7.57 = 7.0x39 */
297 if (d->version_num < 0x073900)
298 return 77; /* skip test, curl is too old */
299#ifdef MHD_HTTPS_REQUIRE_GRYPT
300#ifdef HAVE_GCRYPT_H
301 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
302#ifdef GCRYCTL_INITIALIZATION_FINISHED
303 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
304#endif
305#endif
306#endif /* MHD_HTTPS_REQUIRE_GRYPT */
307if (0 != curl_global_init (CURL_GLOBAL_WIN32))
308 return 2;
309 errorCount += testDigestAuth ();
310 if (errorCount != 0)
311 fprintf (stderr, "Error (code: %u)\n", errorCount);
312 curl_global_cleanup ();
313 return errorCount != 0; /* 0 == pass */
314}