Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
civetweb.c
Go to the documentation of this file.
1 /* Copyright (c) 2013-2018 the Civetweb developers
2  * Copyright (c) 2004-2013 Sergey Lyubka
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #if defined(__GNUC__) || defined(__MINGW32__)
24 #define GCC_VERSION \
25  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
26 #if GCC_VERSION >= 40500
27 /* gcc diagnostic pragmas available */
28 #define GCC_DIAGNOSTIC
29 #endif
30 #endif
31 
32 #if defined(GCC_DIAGNOSTIC)
33 /* Disable unused macros warnings - not all defines are required
34  * for all systems and all compilers. */
35 #pragma GCC diagnostic ignored "-Wunused-macros"
36 /* A padding warning is just plain useless */
37 #pragma GCC diagnostic ignored "-Wpadded"
38 #endif
39 
40 #if defined(__clang__) /* GCC does not (yet) support this pragma */
41 /* We must set some flags for the headers we include. These flags
42  * are reserved ids according to C99, so we need to disable a
43  * warning for that. */
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wreserved-id-macro"
46 #endif
47 
48 #if defined(_WIN32)
49 #if !defined(_CRT_SECURE_NO_WARNINGS)
50 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
51 #endif
52 #if !defined(_WIN32_WINNT) /* defined for tdm-gcc so we can use getnameinfo */
53 #define _WIN32_WINNT 0x0501
54 #endif
55 #else
56 #if !defined(_GNU_SOURCE)
57 #define _GNU_SOURCE /* for setgroups(), pthread_setname_np() */
58 #endif
59 #if defined(__linux__) && !defined(_XOPEN_SOURCE)
60 #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
61 #endif
62 #if !defined(_LARGEFILE_SOURCE)
63 #define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
64 #endif
65 #if !defined(_FILE_OFFSET_BITS)
66 #define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
67 #endif
68 #if !defined(__STDC_FORMAT_MACROS)
69 #define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
70 #endif
71 #if !defined(__STDC_LIMIT_MACROS)
72 #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
73 #endif
74 #if !defined(_DARWIN_UNLIMITED_SELECT)
75 #define _DARWIN_UNLIMITED_SELECT
76 #endif
77 #if defined(__sun)
78 #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
79 #define __inline inline /* not recognized on older compiler versions */
80 #endif
81 #endif
82 
83 #if defined(__clang__)
84 /* Enable reserved-id-macro warning again. */
85 #pragma GCC diagnostic pop
86 #endif
87 
88 
89 #if defined(USE_LUA)
90 #define USE_TIMERS
91 #endif
92 
93 #if defined(_MSC_VER)
94 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
95 #pragma warning(disable : 4306)
96 /* conditional expression is constant: introduced by FD_SET(..) */
97 #pragma warning(disable : 4127)
98 /* non-constant aggregate initializer: issued due to missing C99 support */
99 #pragma warning(disable : 4204)
100 /* padding added after data member */
101 #pragma warning(disable : 4820)
102 /* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
103 #pragma warning(disable : 4668)
104 /* no function prototype given: converting '()' to '(void)' */
105 #pragma warning(disable : 4255)
106 /* function has been selected for automatic inline expansion */
107 #pragma warning(disable : 4711)
108 #endif
109 
110 
111 /* This code uses static_assert to check some conditions.
112  * Unfortunately some compilers still do not support it, so we have a
113  * replacement function here. */
114 #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201100L
115 #define mg_static_assert _Static_assert
116 #elif defined(__cplusplus) && __cplusplus >= 201103L
117 #define mg_static_assert static_assert
118 #else
119 char static_assert_replacement[1];
120 #define mg_static_assert(cond, txt) \
121  extern char static_assert_replacement[(cond) ? 1 : -1]
122 #endif
123 
124 mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
125  "int data type size check");
126 mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
127  "pointer data type size check");
128 mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
129 
130 
131 /* Alternative queue is well tested and should be the new default */
132 #if defined(NO_ALTERNATIVE_QUEUE)
133 #if defined(ALTERNATIVE_QUEUE)
134 #error "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE or none, but not both"
135 #endif
136 #else
137 #define ALTERNATIVE_QUEUE
138 #endif
139 
140 
141 /* DTL -- including winsock2.h works better if lean and mean */
142 #if !defined(WIN32_LEAN_AND_MEAN)
143 #define WIN32_LEAN_AND_MEAN
144 #endif
145 
146 #if defined(__SYMBIAN32__)
147 /* According to https://en.wikipedia.org/wiki/Symbian#History,
148  * Symbian is no longer maintained since 2014-01-01.
149  * Recent versions of CivetWeb are no longer tested for Symbian.
150  * It makes no sense, to support an abandoned operating system.
151  */
152 #error "Symbian is no longer maintained. CivetWeb no longer supports Symbian."
153 #define NO_SSL /* SSL is not supported */
154 #define NO_CGI /* CGI is not supported */
155 #define PATH_MAX FILENAME_MAX
156 #endif /* __SYMBIAN32__ */
157 
158 
159 #if !defined(CIVETWEB_HEADER_INCLUDED)
160 /* Include the header file here, so the CivetWeb interface is defined for the
161  * entire implementation, including the following forward definitions. */
162 #include "civetweb.h"
163 #endif
164 
165 #if !defined(DEBUG_TRACE)
166 #if defined(DEBUG)
167 static void DEBUG_TRACE_FUNC(const char *func,
168  unsigned line,
169  PRINTF_FORMAT_STRING(const char *fmt),
170  ...) PRINTF_ARGS(3, 4);
171 
172 #define DEBUG_TRACE(fmt, ...) \
173  DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
174 
175 #define NEED_DEBUG_TRACE_FUNC
176 
177 #else
178 #define DEBUG_TRACE(fmt, ...) \
179  do { \
180  } while (0)
181 #endif /* DEBUG */
182 #endif /* DEBUG_TRACE */
183 
184 
185 #if !defined(DEBUG_ASSERT)
186 #if defined(DEBUG)
187 #define DEBUG_ASSERT(cond) \
188  do { \
189  if (!(cond)) { \
190  DEBUG_TRACE("ASSERTION FAILED: %s", #cond); \
191  exit(2); /* Exit with error */ \
192  } \
193  } while (0)
194 #else
195 #define DEBUG_ASSERT(cond)
196 #endif /* DEBUG */
197 #endif
198 
199 
200 #if defined(__GNUC__) && defined(GCC_INSTRUMENTATION)
201 void __cyg_profile_func_enter(void *this_fn, void *call_site)
202  __attribute__((no_instrument_function));
203 
204 void __cyg_profile_func_exit(void *this_fn, void *call_site)
205  __attribute__((no_instrument_function));
206 
207 void
208 __cyg_profile_func_enter(void *this_fn, void *call_site)
209 {
210  if ((void *)this_fn != (void *)printf) {
211  printf("E %p %p\n", this_fn, call_site);
212  }
213 }
214 
215 void
216 __cyg_profile_func_exit(void *this_fn, void *call_site)
217 {
218  if ((void *)this_fn != (void *)printf) {
219  printf("X %p %p\n", this_fn, call_site);
220  }
221 }
222 #endif
223 
224 
225 #if !defined(IGNORE_UNUSED_RESULT)
226 #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
227 #endif
228 
229 
230 #if defined(__GNUC__) || defined(__MINGW32__)
231 
232 /* GCC unused function attribute seems fundamentally broken.
233  * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED
234  * OR UNUSED" for individual functions failed.
235  * Either the compiler creates an "unused-function" warning if a
236  * function is not marked with __attribute__((unused)).
237  * On the other hand, if the function is marked with this attribute,
238  * but is used, the compiler raises a completely idiotic
239  * "used-but-marked-unused" warning - and
240  * #pragma GCC diagnostic ignored "-Wused-but-marked-unused"
241  * raises error: unknown option after "#pragma GCC diagnostic".
242  * Disable this warning completely, until the GCC guys sober up
243  * again.
244  */
245 
246 #pragma GCC diagnostic ignored "-Wunused-function"
247 
248 #define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */
249 
250 #else
251 #define FUNCTION_MAY_BE_UNUSED
252 #endif
253 
254 
255 /* Some ANSI #includes are not available on Windows CE */
256 #if !defined(_WIN32_WCE)
257 #include <errno.h>
258 #include <fcntl.h>
259 #include <signal.h>
260 #include <sys/stat.h>
261 #include <sys/types.h>
262 #endif /* !_WIN32_WCE */
263 
264 
265 #if defined(__clang__)
266 /* When using -Weverything, clang does not accept it's own headers
267  * in a release build configuration. Disable what is too much in
268  * -Weverything. */
269 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
270 #endif
271 
272 #if defined(__GNUC__) || defined(__MINGW32__)
273 /* Who on earth came to the conclusion, using __DATE__ should rise
274  * an "expansion of date or time macro is not reproducible"
275  * warning. That's exactly what was intended by using this macro.
276  * Just disable this nonsense warning. */
277 
278 /* And disabling them does not work either:
279  * #pragma clang diagnostic ignored "-Wno-error=date-time"
280  * #pragma clang diagnostic ignored "-Wdate-time"
281  * So we just have to disable ALL warnings for some lines
282  * of code.
283  * This seems to be a known GCC bug, not resolved since 2012:
284  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
285  */
286 #endif
287 
288 
289 #if defined(__MACH__) /* Apple OSX section */
290 
291 #if defined(__clang__)
292 #if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8))
293 /* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */
294 #pragma clang diagnostic ignored "-Wno-reserved-id-macro"
295 #pragma clang diagnostic ignored "-Wno-keyword-macro"
296 #endif
297 #endif
298 
299 #define CLOCK_MONOTONIC (1)
300 #define CLOCK_REALTIME (2)
301 
302 #include <mach/clock.h>
303 #include <mach/mach.h>
304 #include <mach/mach_time.h>
305 #include <sys/errno.h>
306 #include <sys/time.h>
307 
308 /* clock_gettime is not implemented on OSX prior to 10.12 */
309 static int
310 _civet_clock_gettime(int clk_id, struct timespec *t)
311 {
312  memset(t, 0, sizeof(*t));
313  if (clk_id == CLOCK_REALTIME) {
314  struct timeval now;
315  int rv = gettimeofday(&now, NULL);
316  if (rv) {
317  return rv;
318  }
319  t->tv_sec = now.tv_sec;
320  t->tv_nsec = now.tv_usec * 1000;
321  return 0;
322 
323  } else if (clk_id == CLOCK_MONOTONIC) {
324  static uint64_t clock_start_time = 0;
325  static mach_timebase_info_data_t timebase_ifo = {0, 0};
326 
327  uint64_t now = mach_absolute_time();
328 
329  if (clock_start_time == 0) {
330  kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
331  DEBUG_ASSERT(mach_status == KERN_SUCCESS);
332 
333  /* appease "unused variable" warning for release builds */
334  (void)mach_status;
335 
336  clock_start_time = now;
337  }
338 
339  now = (uint64_t)((double)(now - clock_start_time)
340  * (double)timebase_ifo.numer
341  / (double)timebase_ifo.denom);
342 
343  t->tv_sec = now / 1000000000;
344  t->tv_nsec = now % 1000000000;
345  return 0;
346  }
347  return -1; /* EINVAL - Clock ID is unknown */
348 }
349 
350 /* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
351 #if defined(__CLOCK_AVAILABILITY)
352 /* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
353  * declared but it may be NULL at runtime. So we need to check before using
354  * it. */
355 static int
356 _civet_safe_clock_gettime(int clk_id, struct timespec *t)
357 {
358  if (clock_gettime) {
359  return clock_gettime(clk_id, t);
360  }
361  return _civet_clock_gettime(clk_id, t);
362 }
363 #define clock_gettime _civet_safe_clock_gettime
364 #else
365 #define clock_gettime _civet_clock_gettime
366 #endif
367 
368 #endif
369 
370 
371 #include <ctype.h>
372 #include <limits.h>
373 #include <stdarg.h>
374 #include <stddef.h>
375 #include <stdint.h>
376 #include <stdio.h>
377 #include <stdlib.h>
378 #include <string.h>
379 #include <time.h>
380 
381 /********************************************************************/
382 /* CivetWeb configuration defines */
383 /********************************************************************/
384 
385 /* Maximum number of threads that can be configured.
386  * The number of threads actually created depends on the "num_threads"
387  * configuration parameter, but this is the upper limit. */
388 #if !defined(MAX_WORKER_THREADS)
389 #define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */
390 #endif
391 
392 /* Timeout interval for select/poll calls.
393  * The timeouts depend on "*_timeout_ms" configuration values, but long
394  * timeouts are split into timouts as small as SOCKET_TIMEOUT_QUANTUM.
395  * This reduces the time required to stop the server. */
396 #if !defined(SOCKET_TIMEOUT_QUANTUM)
397 #define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
398 #endif
399 
400 /* Do not try to compress files smaller than this limit. */
401 #if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT)
402 #define MG_FILE_COMPRESSION_SIZE_LIMIT (1024) /* in bytes */
403 #endif
404 
405 #if !defined(PASSWORDS_FILE_NAME)
406 #define PASSWORDS_FILE_NAME ".htpasswd"
407 #endif
408 
409 /* Initial buffer size for all CGI environment variables. In case there is
410  * not enough space, another block is allocated. */
411 #if !defined(CGI_ENVIRONMENT_SIZE)
412 #define CGI_ENVIRONMENT_SIZE (4096) /* in bytes */
413 #endif
414 
415 /* Maximum number of environment variables. */
416 #if !defined(MAX_CGI_ENVIR_VARS)
417 #define MAX_CGI_ENVIR_VARS (256) /* in variables (count) */
418 #endif
419 
420 /* General purpose buffer size. */
421 #if !defined(MG_BUF_LEN) /* in bytes */
422 #define MG_BUF_LEN (1024 * 8)
423 #endif
424 
425 /* Size of the accepted socket queue (in case the old queue implementation
426  * is used). */
427 #if !defined(MGSQLEN)
428 #define MGSQLEN (20) /* count */
429 #endif
430 
431 
432 /********************************************************************/
433 
434 /* Helper makros */
435 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
436 
437 /* Standard defines */
438 #if !defined(INT64_MAX)
439 #define INT64_MAX (9223372036854775807)
440 #endif
441 
442 #define SHUTDOWN_RD (0)
443 #define SHUTDOWN_WR (1)
444 #define SHUTDOWN_BOTH (2)
445 
446 mg_static_assert(MAX_WORKER_THREADS >= 1,
447  "worker threads must be a positive number");
448 
449 mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
450  "size_t data type size check");
451 
452 #if defined(_WIN32) /* WINDOWS include block */
453 #include <windows.h>
454 #include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
455 #include <ws2tcpip.h>
456 
457 typedef const char *SOCK_OPT_TYPE;
458 
459 #if !defined(PATH_MAX)
460 #define W_PATH_MAX (MAX_PATH)
461 /* at most three UTF-8 chars per wchar_t */
462 #define PATH_MAX (W_PATH_MAX * 3)
463 #else
464 #define W_PATH_MAX ((PATH_MAX + 2) / 3)
465 #endif
466 
467 mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
468 
469 #if !defined(_IN_PORT_T)
470 #if !defined(in_port_t)
471 #define in_port_t u_short
472 #endif
473 #endif
474 
475 #if !defined(_WIN32_WCE)
476 #include <direct.h>
477 #include <io.h>
478 #include <process.h>
479 #else /* _WIN32_WCE */
480 #define NO_CGI /* WinCE has no pipes */
481 #define NO_POPEN /* WinCE has no popen */
482 
483 typedef long off_t;
484 
485 #define errno ((int)(GetLastError()))
486 #define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
487 #endif /* _WIN32_WCE */
488 
489 #define MAKEUQUAD(lo, hi) \
490  ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
491 #define RATE_DIFF (10000000) /* 100 nsecs */
492 #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
493 #define SYS2UNIX_TIME(lo, hi) \
494  ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
495 
496 /* Visual Studio 6 does not know __func__ or __FUNCTION__
497  * The rest of MS compilers use __FUNCTION__, not C99 __func__
498  * Also use _strtoui64 on modern M$ compilers */
499 #if defined(_MSC_VER)
500 #if (_MSC_VER < 1300)
501 #define STRX(x) #x
502 #define STR(x) STRX(x)
503 #define __func__ __FILE__ ":" STR(__LINE__)
504 #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
505 #define strtoll(x, y, z) (_atoi64(x))
506 #else
507 #define __func__ __FUNCTION__
508 #define strtoull(x, y, z) (_strtoui64(x, y, z))
509 #define strtoll(x, y, z) (_strtoi64(x, y, z))
510 #endif
511 #endif /* _MSC_VER */
512 
513 #define ERRNO ((int)(GetLastError()))
514 #define NO_SOCKLEN_T
515 
516 #if defined(_WIN64) || defined(__MINGW64__)
517 #if !defined(SSL_LIB)
518 #define SSL_LIB "ssleay64.dll"
519 #endif
520 #if !defined(CRYPTO_LIB)
521 #define CRYPTO_LIB "libeay64.dll"
522 #endif
523 #else
524 #if !defined(SSL_LIB)
525 #define SSL_LIB "ssleay32.dll"
526 #endif
527 #if !defined(CRYPTO_LIB)
528 #define CRYPTO_LIB "libeay32.dll"
529 #endif
530 #endif
531 
532 #define O_NONBLOCK (0)
533 #if !defined(W_OK)
534 #define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
535 #endif
536 #if !defined(EWOULDBLOCK)
537 #define EWOULDBLOCK WSAEWOULDBLOCK
538 #endif /* !EWOULDBLOCK */
539 #define _POSIX_
540 #define INT64_FMT "I64d"
541 #define UINT64_FMT "I64u"
542 
543 #define WINCDECL __cdecl
544 #define vsnprintf_impl _vsnprintf
545 #define access _access
546 #define mg_sleep(x) (Sleep(x))
547 
548 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
549 #if !defined(popen)
550 #define popen(x, y) (_popen(x, y))
551 #endif
552 #if !defined(pclose)
553 #define pclose(x) (_pclose(x))
554 #endif
555 #define close(x) (_close(x))
556 #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
557 #define RTLD_LAZY (0)
558 #define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0)
559 #define fdopen(x, y) (_fdopen((x), (y)))
560 #define write(x, y, z) (_write((x), (y), (unsigned)z))
561 #define read(x, y, z) (_read((x), (y), (unsigned)z))
562 #define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
563 #define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
564 #define sleep(x) (Sleep((x)*1000))
565 #define rmdir(x) (_rmdir(x))
566 #if defined(_WIN64) || !defined(__MINGW32__)
567 /* Only MinGW 32 bit is missing this function */
568 #define timegm(x) (_mkgmtime(x))
569 #else
570 time_t timegm(struct tm *tm);
571 #define NEED_TIMEGM
572 #endif
573 
574 
575 #if !defined(fileno)
576 #define fileno(x) (_fileno(x))
577 #endif /* !fileno MINGW #defines fileno */
578 
579 typedef HANDLE pthread_mutex_t;
580 typedef DWORD pthread_key_t;
581 typedef HANDLE pthread_t;
582 typedef struct {
583  CRITICAL_SECTION threadIdSec;
584  struct mg_workerTLS *waiting_thread; /* The chain of threads */
585 } pthread_cond_t;
586 
587 #if !defined(__clockid_t_defined)
588 typedef DWORD clockid_t;
589 #endif
590 #if !defined(CLOCK_MONOTONIC)
591 #define CLOCK_MONOTONIC (1)
592 #endif
593 #if !defined(CLOCK_REALTIME)
594 #define CLOCK_REALTIME (2)
595 #endif
596 #if !defined(CLOCK_THREAD)
597 #define CLOCK_THREAD (3)
598 #endif
599 #if !defined(CLOCK_PROCESS)
600 #define CLOCK_PROCESS (4)
601 #endif
602 
603 
604 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
605 #define _TIMESPEC_DEFINED
606 #endif
607 #if !defined(_TIMESPEC_DEFINED)
608 struct timespec {
609  time_t tv_sec; /* seconds */
610  long tv_nsec; /* nanoseconds */
611 };
612 #endif
613 
614 #if !defined(WIN_PTHREADS_TIME_H)
615 #define MUST_IMPLEMENT_CLOCK_GETTIME
616 #endif
617 
618 #if defined(MUST_IMPLEMENT_CLOCK_GETTIME)
619 #define clock_gettime mg_clock_gettime
620 static int
621 clock_gettime(clockid_t clk_id, struct timespec *tp)
622 {
623  FILETIME ft;
624  ULARGE_INTEGER li, li2;
625  BOOL ok = FALSE;
626  double d;
627  static double perfcnt_per_sec = 0.0;
628  static BOOL initialized = FALSE;
629 
630  if (!initialized) {
631  QueryPerformanceFrequency((LARGE_INTEGER *)&li);
632  perfcnt_per_sec = 1.0 / li.QuadPart;
633  initialized = TRUE;
634  }
635 
636  if (tp) {
637  memset(tp, 0, sizeof(*tp));
638 
639  if (clk_id == CLOCK_REALTIME) {
640 
641  /* BEGIN: CLOCK_REALTIME = wall clock (date and time) */
642  GetSystemTimeAsFileTime(&ft);
643  li.LowPart = ft.dwLowDateTime;
644  li.HighPart = ft.dwHighDateTime;
645  li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
646  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
647  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
648  ok = TRUE;
649  /* END: CLOCK_REALTIME */
650 
651  } else if (clk_id == CLOCK_MONOTONIC) {
652 
653  /* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */
654  QueryPerformanceCounter((LARGE_INTEGER *)&li);
655  d = li.QuadPart * perfcnt_per_sec;
656  tp->tv_sec = (time_t)d;
657  d -= (double)tp->tv_sec;
658  tp->tv_nsec = (long)(d * 1.0E9);
659  ok = TRUE;
660  /* END: CLOCK_MONOTONIC */
661 
662  } else if (clk_id == CLOCK_THREAD) {
663 
664  /* BEGIN: CLOCK_THREAD = CPU usage of thread */
665  FILETIME t_create, t_exit, t_kernel, t_user;
666  if (GetThreadTimes(GetCurrentThread(),
667  &t_create,
668  &t_exit,
669  &t_kernel,
670  &t_user)) {
671  li.LowPart = t_user.dwLowDateTime;
672  li.HighPart = t_user.dwHighDateTime;
673  li2.LowPart = t_kernel.dwLowDateTime;
674  li2.HighPart = t_kernel.dwHighDateTime;
675  li.QuadPart += li2.QuadPart;
676  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
677  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
678  ok = TRUE;
679  }
680  /* END: CLOCK_THREAD */
681 
682  } else if (clk_id == CLOCK_PROCESS) {
683 
684  /* BEGIN: CLOCK_PROCESS = CPU usage of process */
685  FILETIME t_create, t_exit, t_kernel, t_user;
686  if (GetProcessTimes(GetCurrentProcess(),
687  &t_create,
688  &t_exit,
689  &t_kernel,
690  &t_user)) {
691  li.LowPart = t_user.dwLowDateTime;
692  li.HighPart = t_user.dwHighDateTime;
693  li2.LowPart = t_kernel.dwLowDateTime;
694  li2.HighPart = t_kernel.dwHighDateTime;
695  li.QuadPart += li2.QuadPart;
696  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
697  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
698  ok = TRUE;
699  }
700  /* END: CLOCK_PROCESS */
701 
702  } else {
703 
704  /* BEGIN: unknown clock */
705  /* ok = FALSE; already set by init */
706  /* END: unknown clock */
707  }
708  }
709 
710  return ok ? 0 : -1;
711 }
712 #endif
713 
714 
715 #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
716 
717 static int pthread_mutex_lock(pthread_mutex_t *);
718 static int pthread_mutex_unlock(pthread_mutex_t *);
719 static void path_to_unicode(const struct mg_connection *conn,
720  const char *path,
721  wchar_t *wbuf,
722  size_t wbuf_len);
723 
724 /* All file operations need to be rewritten to solve #246. */
725 
726 struct mg_file;
727 
728 static const char *
729 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p);
730 
731 
732 /* POSIX dirent interface */
733 struct dirent {
734  char d_name[PATH_MAX];
735 };
736 
737 typedef struct DIR {
738  HANDLE handle;
739  WIN32_FIND_DATAW info;
740  struct dirent result;
741 } DIR;
742 
743 #if defined(_WIN32)
744 #if !defined(HAVE_POLL)
745 struct pollfd {
746  SOCKET fd;
747  short events;
748  short revents;
749 };
750 #endif
751 #endif
752 
753 /* Mark required libraries */
754 #if defined(_MSC_VER)
755 #pragma comment(lib, "Ws2_32.lib")
756 #endif
757 
758 #else /* defined(_WIN32) - WINDOWS vs UNIX include block */
759 
760 #include <arpa/inet.h>
761 #include <inttypes.h>
762 #include <netdb.h>
763 #include <netinet/in.h>
764 #include <netinet/tcp.h>
765 #include <stdint.h>
766 #include <sys/poll.h>
767 #include <sys/socket.h>
768 #include <sys/time.h>
769 #include <sys/utsname.h>
770 #include <sys/wait.h>
771 typedef const void *SOCK_OPT_TYPE;
772 
773 #if defined(ANDROID)
774 typedef unsigned short int in_port_t;
775 #endif
776 
777 #include <dirent.h>
778 #include <grp.h>
779 #include <pwd.h>
780 #include <unistd.h>
781 #define vsnprintf_impl vsnprintf
782 
783 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
784 #include <dlfcn.h>
785 #endif
786 #include <pthread.h>
787 #if defined(__MACH__)
788 #define SSL_LIB "libssl.dylib"
789 #define CRYPTO_LIB "libcrypto.dylib"
790 #else
791 #if !defined(SSL_LIB)
792 #define SSL_LIB "libssl.so"
793 #endif
794 #if !defined(CRYPTO_LIB)
795 #define CRYPTO_LIB "libcrypto.so"
796 #endif
797 #endif
798 #if !defined(O_BINARY)
799 #define O_BINARY (0)
800 #endif /* O_BINARY */
801 #define closesocket(a) (close(a))
802 #define mg_mkdir(conn, path, mode) (mkdir(path, mode))
803 #define mg_remove(conn, x) (remove(x))
804 #define mg_sleep(x) (usleep((x)*1000))
805 #define mg_opendir(conn, x) (opendir(x))
806 #define mg_closedir(x) (closedir(x))
807 #define mg_readdir(x) (readdir(x))
808 #define ERRNO (errno)
809 #define INVALID_SOCKET (-1)
810 #define INT64_FMT PRId64
811 #define UINT64_FMT PRIu64
812 typedef int SOCKET;
813 #define WINCDECL
814 
815 #if defined(__hpux)
816 /* HPUX 11 does not have monotonic, fall back to realtime */
817 #if !defined(CLOCK_MONOTONIC)
818 #define CLOCK_MONOTONIC CLOCK_REALTIME
819 #endif
820 
821 /* HPUX defines socklen_t incorrectly as size_t which is 64bit on
822  * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
823  * the prototypes use int* rather than socklen_t* which matches the
824  * actual library expectation. When called with the wrong size arg
825  * accept() returns a zero client inet addr and check_acl() always
826  * fails. Since socklen_t is widely used below, just force replace
827  * their typedef with int. - DTL
828  */
829 #define socklen_t int
830 #endif /* hpux */
831 
832 #endif /* defined(_WIN32) - WINDOWS vs UNIX include block */
833 
834 /* Maximum queue length for pending connections. This value is passed as
835  * parameter to the "listen" socket call. */
836 #if !defined(SOMAXCONN)
837 /* This symbol may be defined in winsock2.h so this must after that include */
838 #define SOMAXCONN (100) /* in pending connections (count) */
839 #endif
840 
841 /* In case our C library is missing "timegm", provide an implementation */
842 #if defined(NEED_TIMEGM)
843 static inline int
844 is_leap(int y)
845 {
846  return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
847 }
848 
849 static inline int
850 count_leap(int y)
851 {
852  return (y - 1969) / 4 - (y - 1901) / 100 + (y - 1601) / 400;
853 }
854 
855 time_t
856 timegm(struct tm *tm)
857 {
858  static const unsigned short ydays[] = {
859  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
860  int year = tm->tm_year + 1900;
861  int mon = tm->tm_mon;
862  int mday = tm->tm_mday - 1;
863  int hour = tm->tm_hour;
864  int min = tm->tm_min;
865  int sec = tm->tm_sec;
866 
867  if (year < 1970 || mon < 0 || mon > 11 || mday < 0
868  || (mday >= ydays[mon + 1] - ydays[mon]
869  + (mon == 1 && is_leap(year) ? 1 : 0))
870  || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60)
871  return -1;
872 
873  time_t res = year - 1970;
874  res *= 365;
875  res += mday;
876  res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0);
877  res += count_leap(year);
878 
879  res *= 24;
880  res += hour;
881  res *= 60;
882  res += min;
883  res *= 60;
884  res += sec;
885  return res;
886 }
887 #endif /* NEED_TIMEGM */
888 
889 
890 /* va_copy should always be a macro, C99 and C++11 - DTL */
891 #if !defined(va_copy)
892 #define va_copy(x, y) ((x) = (y))
893 #endif
894 
895 
896 #if defined(_WIN32)
897 /* Create substitutes for POSIX functions in Win32. */
898 
899 #if defined(GCC_DIAGNOSTIC)
900 /* Show no warning in case system functions are not used. */
901 #pragma GCC diagnostic push
902 #pragma GCC diagnostic ignored "-Wunused-function"
903 #endif
904 
905 
906 static CRITICAL_SECTION global_log_file_lock;
907 
908 FUNCTION_MAY_BE_UNUSED
909 static DWORD
910 pthread_self(void)
911 {
912  return GetCurrentThreadId();
913 }
914 
915 
916 FUNCTION_MAY_BE_UNUSED
917 static int
918 pthread_key_create(
919  pthread_key_t *key,
920  void (*_ignored)(void *) /* destructor not supported for Windows */
921 )
922 {
923  (void)_ignored;
924 
925  if ((key != 0)) {
926  *key = TlsAlloc();
927  return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
928  }
929  return -2;
930 }
931 
932 
933 FUNCTION_MAY_BE_UNUSED
934 static int
935 pthread_key_delete(pthread_key_t key)
936 {
937  return TlsFree(key) ? 0 : 1;
938 }
939 
940 
941 FUNCTION_MAY_BE_UNUSED
942 static int
943 pthread_setspecific(pthread_key_t key, void *value)
944 {
945  return TlsSetValue(key, value) ? 0 : 1;
946 }
947 
948 
949 FUNCTION_MAY_BE_UNUSED
950 static void *
951 pthread_getspecific(pthread_key_t key)
952 {
953  return TlsGetValue(key);
954 }
955 
956 #if defined(GCC_DIAGNOSTIC)
957 /* Enable unused function warning again */
958 #pragma GCC diagnostic pop
959 #endif
960 
961 static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
962 #else
963 static pthread_mutexattr_t pthread_mutex_attr;
964 #endif /* _WIN32 */
965 
966 
967 #if defined(_WIN32_WCE)
968 /* Create substitutes for POSIX functions in Win32. */
969 
970 #if defined(GCC_DIAGNOSTIC)
971 /* Show no warning in case system functions are not used. */
972 #pragma GCC diagnostic push
973 #pragma GCC diagnostic ignored "-Wunused-function"
974 #endif
975 
976 
977 FUNCTION_MAY_BE_UNUSED
978 static time_t
979 time(time_t *ptime)
980 {
981  time_t t;
982  SYSTEMTIME st;
983  FILETIME ft;
984 
985  GetSystemTime(&st);
986  SystemTimeToFileTime(&st, &ft);
987  t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
988 
989  if (ptime != NULL) {
990  *ptime = t;
991  }
992 
993  return t;
994 }
995 
996 
997 FUNCTION_MAY_BE_UNUSED
998 static struct tm *
999 localtime_s(const time_t *ptime, struct tm *ptm)
1000 {
1001  int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
1002  FILETIME ft, lft;
1003  SYSTEMTIME st;
1004  TIME_ZONE_INFORMATION tzinfo;
1005 
1006  if (ptm == NULL) {
1007  return NULL;
1008  }
1009 
1010  *(int64_t *)&ft = t;
1011  FileTimeToLocalFileTime(&ft, &lft);
1012  FileTimeToSystemTime(&lft, &st);
1013  ptm->tm_year = st.wYear - 1900;
1014  ptm->tm_mon = st.wMonth - 1;
1015  ptm->tm_wday = st.wDayOfWeek;
1016  ptm->tm_mday = st.wDay;
1017  ptm->tm_hour = st.wHour;
1018  ptm->tm_min = st.wMinute;
1019  ptm->tm_sec = st.wSecond;
1020  ptm->tm_yday = 0; /* hope nobody uses this */
1021  ptm->tm_isdst =
1022  (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
1023 
1024  return ptm;
1025 }
1026 
1027 
1028 FUNCTION_MAY_BE_UNUSED
1029 static struct tm *
1030 gmtime_s(const time_t *ptime, struct tm *ptm)
1031 {
1032  /* FIXME(lsm): fix this. */
1033  return localtime_s(ptime, ptm);
1034 }
1035 
1036 
1037 static int mg_atomic_inc(volatile int *addr);
1038 static struct tm tm_array[MAX_WORKER_THREADS];
1039 static int tm_index = 0;
1040 
1041 
1042 FUNCTION_MAY_BE_UNUSED
1043 static struct tm *
1044 localtime(const time_t *ptime)
1045 {
1046  int i = mg_atomic_inc(&tm_index) % (sizeof(tm_array) / sizeof(tm_array[0]));
1047  return localtime_s(ptime, tm_array + i);
1048 }
1049 
1050 
1051 FUNCTION_MAY_BE_UNUSED
1052 static struct tm *
1053 gmtime(const time_t *ptime)
1054 {
1055  int i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array);
1056  return gmtime_s(ptime, tm_array + i);
1057 }
1058 
1059 
1060 FUNCTION_MAY_BE_UNUSED
1061 static size_t
1062 strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
1063 {
1064  /* TODO: (void)mg_snprintf(NULL, dst, dst_size, "implement strftime()
1065  * for WinCE"); */
1066  return 0;
1067 }
1068 
1069 #define _beginthreadex(psec, stack, func, prm, flags, ptid) \
1070  (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid)
1071 
1072 #define remove(f) mg_remove(NULL, f)
1073 
1074 
1075 FUNCTION_MAY_BE_UNUSED
1076 static int
1077 rename(const char *a, const char *b)
1078 {
1079  wchar_t wa[W_PATH_MAX];
1080  wchar_t wb[W_PATH_MAX];
1081  path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa));
1082  path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb));
1083 
1084  return MoveFileW(wa, wb) ? 0 : -1;
1085 }
1086 
1087 
1088 struct stat {
1089  int64_t st_size;
1090  time_t st_mtime;
1091 };
1092 
1093 
1094 FUNCTION_MAY_BE_UNUSED
1095 static int
1096 stat(const char *name, struct stat *st)
1097 {
1098  wchar_t wbuf[W_PATH_MAX];
1099  WIN32_FILE_ATTRIBUTE_DATA attr;
1100  time_t creation_time, write_time;
1101 
1102  path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf));
1103  memset(&attr, 0, sizeof(attr));
1104 
1105  GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
1106  st->st_size =
1107  (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
1108 
1109  write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
1110  attr.ftLastWriteTime.dwHighDateTime);
1111  creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
1112  attr.ftCreationTime.dwHighDateTime);
1113 
1114  if (creation_time > write_time) {
1115  st->st_mtime = creation_time;
1116  } else {
1117  st->st_mtime = write_time;
1118  }
1119  return 0;
1120 }
1121 
1122 #define access(x, a) 1 /* not required anyway */
1123 
1124 /* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */
1125 /* Values from errno.h in Windows SDK (Visual Studio). */
1126 #define EEXIST 17
1127 #define EACCES 13
1128 #define ENOENT 2
1129 
1130 #if defined(GCC_DIAGNOSTIC)
1131 /* Enable unused function warning again */
1132 #pragma GCC diagnostic pop
1133 #endif
1134 
1135 #endif /* defined(_WIN32_WCE) */
1136 
1137 
1138 #if defined(GCC_DIAGNOSTIC)
1139 /* Show no warning in case system functions are not used. */
1140 #pragma GCC diagnostic push
1141 #pragma GCC diagnostic ignored "-Wunused-function"
1142 #endif /* defined(GCC_DIAGNOSTIC) */
1143 #if defined(__clang__)
1144 /* Show no warning in case system functions are not used. */
1145 #pragma clang diagnostic push
1146 #pragma clang diagnostic ignored "-Wunused-function"
1147 #endif
1148 
1149 static pthread_mutex_t global_lock_mutex;
1150 
1151 
1152 #if defined(_WIN32)
1153 /* Forward declaration for Windows */
1154 FUNCTION_MAY_BE_UNUSED
1155 static int pthread_mutex_lock(pthread_mutex_t *mutex);
1156 
1157 FUNCTION_MAY_BE_UNUSED
1158 static int pthread_mutex_unlock(pthread_mutex_t *mutex);
1159 #endif
1160 
1161 
1162 FUNCTION_MAY_BE_UNUSED
1163 static void
1164 mg_global_lock(void)
1165 {
1166  (void)pthread_mutex_lock(&global_lock_mutex);
1167 }
1168 
1169 
1170 FUNCTION_MAY_BE_UNUSED
1171 static void
1172 mg_global_unlock(void)
1173 {
1174  (void)pthread_mutex_unlock(&global_lock_mutex);
1175 }
1176 
1177 
1178 FUNCTION_MAY_BE_UNUSED
1179 static int
1180 mg_atomic_inc(volatile int *addr)
1181 {
1182  int ret;
1183 #if defined(_WIN32) && !defined(NO_ATOMICS)
1184  /* Depending on the SDK, this function uses either
1185  * (volatile unsigned int *) or (volatile LONG *),
1186  * so whatever you use, the other SDK is likely to raise a warning. */
1187  ret = InterlockedIncrement((volatile long *)addr);
1188 #elif defined(__GNUC__) \
1189  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1190  && !defined(NO_ATOMICS)
1191  ret = __sync_add_and_fetch(addr, 1);
1192 #else
1193  mg_global_lock();
1194  ret = (++(*addr));
1195  mg_global_unlock();
1196 #endif
1197  return ret;
1198 }
1199 
1200 
1201 FUNCTION_MAY_BE_UNUSED
1202 static int
1203 mg_atomic_dec(volatile int *addr)
1204 {
1205  int ret;
1206 #if defined(_WIN32) && !defined(NO_ATOMICS)
1207  /* Depending on the SDK, this function uses either
1208  * (volatile unsigned int *) or (volatile LONG *),
1209  * so whatever you use, the other SDK is likely to raise a warning. */
1210  ret = InterlockedDecrement((volatile long *)addr);
1211 #elif defined(__GNUC__) \
1212  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1213  && !defined(NO_ATOMICS)
1214  ret = __sync_sub_and_fetch(addr, 1);
1215 #else
1216  mg_global_lock();
1217  ret = (--(*addr));
1218  mg_global_unlock();
1219 #endif
1220  return ret;
1221 }
1222 
1223 
1224 #if defined(USE_SERVER_STATS)
1225 static int64_t
1226 mg_atomic_add(volatile int64_t *addr, int64_t value)
1227 {
1228  int64_t ret;
1229 #if defined(_WIN64) && !defined(NO_ATOMICS)
1230  ret = InterlockedAdd64(addr, value);
1231 #elif defined(__GNUC__) \
1232  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1233  && !defined(NO_ATOMICS)
1234  ret = __sync_add_and_fetch(addr, value);
1235 #else
1236  mg_global_lock();
1237  *addr += value;
1238  ret = (*addr);
1239  mg_global_unlock();
1240 #endif
1241  return ret;
1242 }
1243 #endif
1244 
1245 
1246 #if defined(GCC_DIAGNOSTIC)
1247 /* Show no warning in case system functions are not used. */
1248 #pragma GCC diagnostic pop
1249 #endif /* defined(GCC_DIAGNOSTIC) */
1250 #if defined(__clang__)
1251 /* Show no warning in case system functions are not used. */
1252 #pragma clang diagnostic pop
1253 #endif
1254 
1255 
1256 #if defined(USE_SERVER_STATS)
1257 
1258 struct mg_memory_stat {
1259  volatile int64_t totalMemUsed;
1260  volatile int64_t maxMemUsed;
1261  volatile int blockCount;
1262 };
1263 
1264 
1265 static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx);
1266 
1267 
1268 static void *
1269 mg_malloc_ex(size_t size,
1270  struct mg_context *ctx,
1271  const char *file,
1272  unsigned line)
1273 {
1274  void *data = malloc(size + 2 * sizeof(uintptr_t));
1275  void *memory = 0;
1276  struct mg_memory_stat *mstat = get_memory_stat(ctx);
1277 
1278 #if defined(MEMORY_DEBUGGING)
1279  char mallocStr[256];
1280 #else
1281  (void)file;
1282  (void)line;
1283 #endif
1284 
1285  if (data) {
1286  int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
1287  if (mmem > mstat->maxMemUsed) {
1288  /* could use atomic compare exchange, but this
1289  * seems overkill for statistics data */
1290  mstat->maxMemUsed = mmem;
1291  }
1292 
1293  mg_atomic_inc(&mstat->blockCount);
1294  ((uintptr_t *)data)[0] = size;
1295  ((uintptr_t *)data)[1] = (uintptr_t)mstat;
1296  memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1297  }
1298 
1299 #if defined(MEMORY_DEBUGGING)
1300  sprintf(mallocStr,
1301  "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
1302  memory,
1303  (unsigned long)size,
1304  (unsigned long)mstat->totalMemUsed,
1305  (unsigned long)mstat->blockCount,
1306  file,
1307  line);
1308 #if defined(_WIN32)
1309  OutputDebugStringA(mallocStr);
1310 #else
1311  DEBUG_TRACE("%s", mallocStr);
1312 #endif
1313 #endif
1314 
1315  return memory;
1316 }
1317 
1318 
1319 static void *
1320 mg_calloc_ex(size_t count,
1321  size_t size,
1322  struct mg_context *ctx,
1323  const char *file,
1324  unsigned line)
1325 {
1326  void *data = mg_malloc_ex(size * count, ctx, file, line);
1327 
1328  if (data) {
1329  memset(data, 0, size * count);
1330  }
1331  return data;
1332 }
1333 
1334 
1335 static void
1336 mg_free_ex(void *memory, const char *file, unsigned line)
1337 {
1338  void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1339 
1340 
1341 #if defined(MEMORY_DEBUGGING)
1342  char mallocStr[256];
1343 #else
1344  (void)file;
1345  (void)line;
1346 #endif
1347 
1348  if (memory) {
1349  uintptr_t size = ((uintptr_t *)data)[0];
1350  struct mg_memory_stat *mstat =
1351  (struct mg_memory_stat *)(((uintptr_t *)data)[1]);
1352  mg_atomic_add(&mstat->totalMemUsed, -(int64_t)size);
1353  mg_atomic_dec(&mstat->blockCount);
1354 #if defined(MEMORY_DEBUGGING)
1355  sprintf(mallocStr,
1356  "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
1357  memory,
1358  (unsigned long)size,
1359  (unsigned long)mstat->totalMemUsed,
1360  (unsigned long)mstat->blockCount,
1361  file,
1362  line);
1363 #if defined(_WIN32)
1364  OutputDebugStringA(mallocStr);
1365 #else
1366  DEBUG_TRACE("%s", mallocStr);
1367 #endif
1368 #endif
1369  free(data);
1370  }
1371 }
1372 
1373 
1374 static void *
1375 mg_realloc_ex(void *memory,
1376  size_t newsize,
1377  struct mg_context *ctx,
1378  const char *file,
1379  unsigned line)
1380 {
1381  void *data;
1382  void *_realloc;
1383  uintptr_t oldsize;
1384 
1385 #if defined(MEMORY_DEBUGGING)
1386  char mallocStr[256];
1387 #else
1388  (void)file;
1389  (void)line;
1390 #endif
1391 
1392  if (newsize) {
1393  if (memory) {
1394  /* Reallocate existing block */
1395  struct mg_memory_stat *mstat;
1396  data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1397  oldsize = ((uintptr_t *)data)[0];
1398  mstat = (struct mg_memory_stat *)((uintptr_t *)data)[1];
1399  _realloc = realloc(data, newsize + 2 * sizeof(uintptr_t));
1400  if (_realloc) {
1401  data = _realloc;
1402  mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
1403 #if defined(MEMORY_DEBUGGING)
1404  sprintf(mallocStr,
1405  "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
1406  memory,
1407  (unsigned long)oldsize,
1408  (unsigned long)mstat->totalMemUsed,
1409  (unsigned long)mstat->blockCount,
1410  file,
1411  line);
1412 #if defined(_WIN32)
1413  OutputDebugStringA(mallocStr);
1414 #else
1415  DEBUG_TRACE("%s", mallocStr);
1416 #endif
1417 #endif
1418  mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
1419 #if defined(MEMORY_DEBUGGING)
1420  sprintf(mallocStr,
1421  "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
1422  memory,
1423  (unsigned long)newsize,
1424  (unsigned long)mstat->totalMemUsed,
1425  (unsigned long)mstat->blockCount,
1426  file,
1427  line);
1428 #if defined(_WIN32)
1429  OutputDebugStringA(mallocStr);
1430 #else
1431  DEBUG_TRACE("%s", mallocStr);
1432 #endif
1433 #endif
1434  *(uintptr_t *)data = newsize;
1435  data = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1436  } else {
1437 #if defined(MEMORY_DEBUGGING)
1438 #if defined(_WIN32)
1439  OutputDebugStringA("MEM: realloc failed\n");
1440 #else
1441  DEBUG_TRACE("%s", "MEM: realloc failed\n");
1442 #endif
1443 #endif
1444  return _realloc;
1445  }
1446  } else {
1447  /* Allocate new block */
1448  data = mg_malloc_ex(newsize, ctx, file, line);
1449  }
1450  } else {
1451  /* Free existing block */
1452  data = 0;
1453  mg_free_ex(memory, file, line);
1454  }
1455 
1456  return data;
1457 }
1458 
1459 #define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__)
1460 #define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__)
1461 #define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__)
1462 #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
1463 
1464 #define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__)
1465 #define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__)
1466 #define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__)
1467 
1468 #else /* USE_SERVER_STATS */
1469 
1470 static __inline void *
1471 mg_malloc(size_t a)
1472 {
1473  return malloc(a);
1474 }
1475 
1476 static __inline void *
1477 mg_calloc(size_t a, size_t b)
1478 {
1479  return calloc(a, b);
1480 }
1481 
1482 static __inline void *
1483 mg_realloc(void *a, size_t b)
1484 {
1485  return realloc(a, b);
1486 }
1487 
1488 static __inline void
1489 mg_free(void *a)
1490 {
1491  free(a);
1492 }
1493 
1494 #define mg_malloc_ctx(a, c) mg_malloc(a)
1495 #define mg_calloc_ctx(a, b, c) mg_calloc(a, b)
1496 #define mg_realloc_ctx(a, b, c) mg_realloc(a, b)
1497 #define mg_free_ctx(a, c) mg_free(a)
1498 
1499 #endif /* USE_SERVER_STATS */
1500 
1501 
1502 static void mg_vsnprintf(const struct mg_connection *conn,
1503  int *truncated,
1504  char *buf,
1505  size_t buflen,
1506  const char *fmt,
1507  va_list ap);
1508 
1509 static void mg_snprintf(const struct mg_connection *conn,
1510  int *truncated,
1511  char *buf,
1512  size_t buflen,
1513  PRINTF_FORMAT_STRING(const char *fmt),
1514  ...) PRINTF_ARGS(5, 6);
1515 
1516 /* This following lines are just meant as a reminder to use the mg-functions
1517  * for memory management */
1518 #if defined(malloc)
1519 #undef malloc
1520 #endif
1521 #if defined(calloc)
1522 #undef calloc
1523 #endif
1524 #if defined(realloc)
1525 #undef realloc
1526 #endif
1527 #if defined(free)
1528 #undef free
1529 #endif
1530 #if defined(snprintf)
1531 #undef snprintf
1532 #endif
1533 #if defined(vsnprintf)
1534 #undef vsnprintf
1535 #endif
1536 #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
1537 #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
1538 #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
1539 #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
1540 #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
1541 #if defined(_WIN32)
1542 /* vsnprintf must not be used in any system,
1543  * but this define only works well for Windows. */
1544 #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
1545 #endif
1546 
1547 
1548 /* mg_init_library counter */
1549 static int mg_init_library_called = 0;
1550 
1551 #if !defined(NO_SSL)
1552 static int mg_ssl_initialized = 0;
1553 #endif
1554 
1555 static pthread_key_t sTlsKey; /* Thread local storage index */
1556 static int thread_idx_max = 0;
1557 
1558 #if defined(MG_LEGACY_INTERFACE)
1559 #define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE
1560 #endif
1561 
1562 struct mg_workerTLS {
1563  int is_master;
1564  unsigned long thread_idx;
1565 #if defined(_WIN32)
1566  HANDLE pthread_cond_helper_mutex;
1567  struct mg_workerTLS *next_waiting_thread;
1568 #endif
1569 #if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
1570  char txtbuf[4];
1571 #endif
1572 };
1573 
1574 
1575 #if defined(GCC_DIAGNOSTIC)
1576 /* Show no warning in case system functions are not used. */
1577 #pragma GCC diagnostic push
1578 #pragma GCC diagnostic ignored "-Wunused-function"
1579 #endif /* defined(GCC_DIAGNOSTIC) */
1580 #if defined(__clang__)
1581 /* Show no warning in case system functions are not used. */
1582 #pragma clang diagnostic push
1583 #pragma clang diagnostic ignored "-Wunused-function"
1584 #endif
1585 
1586 
1587 /* Get a unique thread ID as unsigned long, independent from the data type
1588  * of thread IDs defined by the operating system API.
1589  * If two calls to mg_current_thread_id return the same value, they calls
1590  * are done from the same thread. If they return different values, they are
1591  * done from different threads. (Provided this function is used in the same
1592  * process context and threads are not repeatedly created and deleted, but
1593  * CivetWeb does not do that).
1594  * This function must match the signature required for SSL id callbacks:
1595  * CRYPTO_set_id_callback
1596  */
1597 FUNCTION_MAY_BE_UNUSED
1598 static unsigned long
1599 mg_current_thread_id(void)
1600 {
1601 #if defined(_WIN32)
1602  return GetCurrentThreadId();
1603 #else
1604 
1605 #if defined(__clang__)
1606 #pragma clang diagnostic push
1607 #pragma clang diagnostic ignored "-Wunreachable-code"
1608 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
1609  * or not, so one of the two conditions will be unreachable by construction.
1610  * Unfortunately the C standard does not define a way to check this at
1611  * compile time, since the #if preprocessor conditions can not use the sizeof
1612  * operator as an argument. */
1613 #endif
1614 
1615  if (sizeof(pthread_t) > sizeof(unsigned long)) {
1616  /* This is the problematic case for CRYPTO_set_id_callback:
1617  * The OS pthread_t can not be cast to unsigned long. */
1618  struct mg_workerTLS *tls =
1619  (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
1620  if (tls == NULL) {
1621  /* SSL called from an unknown thread: Create some thread index.
1622  */
1623  tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
1624  tls->is_master = -2; /* -2 means "3rd party thread" */
1625  tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
1626  pthread_setspecific(sTlsKey, tls);
1627  }
1628  return tls->thread_idx;
1629  } else {
1630  /* pthread_t may be any data type, so a simple cast to unsigned long
1631  * can rise a warning/error, depending on the platform.
1632  * Here memcpy is used as an anything-to-anything cast. */
1633  unsigned long ret = 0;
1634  pthread_t t = pthread_self();
1635  memcpy(&ret, &t, sizeof(pthread_t));
1636  return ret;
1637  }
1638 
1639 #if defined(__clang__)
1640 #pragma clang diagnostic pop
1641 #endif
1642 
1643 #endif
1644 }
1645 
1646 
1647 FUNCTION_MAY_BE_UNUSED
1648 static uint64_t
1649 mg_get_current_time_ns(void)
1650 {
1651  struct timespec tsnow;
1652  clock_gettime(CLOCK_REALTIME, &tsnow);
1653  return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
1654 }
1655 
1656 
1657 #if defined(GCC_DIAGNOSTIC)
1658 /* Show no warning in case system functions are not used. */
1659 #pragma GCC diagnostic pop
1660 #endif /* defined(GCC_DIAGNOSTIC) */
1661 #if defined(__clang__)
1662 /* Show no warning in case system functions are not used. */
1663 #pragma clang diagnostic pop
1664 #endif
1665 
1666 
1667 #if defined(NEED_DEBUG_TRACE_FUNC)
1668 static void
1669 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
1670 {
1671  va_list args;
1672  uint64_t nsnow;
1673  static uint64_t nslast;
1674  struct timespec tsnow;
1675 
1676  /* Get some operating system independent thread id */
1677  unsigned long thread_id = mg_current_thread_id();
1678 
1679  clock_gettime(CLOCK_REALTIME, &tsnow);
1680  nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
1681  + ((uint64_t)tsnow.tv_nsec);
1682 
1683  if (!nslast) {
1684  nslast = nsnow;
1685  }
1686 
1687  flockfile(stdout);
1688  printf("*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
1689  (unsigned long)tsnow.tv_sec,
1690  (unsigned long)tsnow.tv_nsec,
1691  nsnow - nslast,
1692  thread_id,
1693  func,
1694  line);
1695  va_start(args, fmt);
1696  vprintf(fmt, args);
1697  va_end(args);
1698  putchar('\n');
1699  fflush(stdout);
1700  funlockfile(stdout);
1701  nslast = nsnow;
1702 }
1703 #endif /* NEED_DEBUG_TRACE_FUNC */
1704 
1705 
1706 #define MD5_STATIC static
1707 #include "md5.inl"
1708 
1709 /* Darwin prior to 7.0 and Win32 do not have socklen_t */
1710 #if defined(NO_SOCKLEN_T)
1711 typedef int socklen_t;
1712 #endif /* NO_SOCKLEN_T */
1713 
1714 #define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
1715 
1716 #if !defined(MSG_NOSIGNAL)
1717 #define MSG_NOSIGNAL (0)
1718 #endif
1719 
1720 
1721 #if defined(NO_SSL)
1722 typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
1723 typedef struct SSL_CTX SSL_CTX;
1724 #else
1725 #if defined(NO_SSL_DL)
1726 #include <openssl/bn.h>
1727 #include <openssl/conf.h>
1728 #include <openssl/crypto.h>
1729 #include <openssl/dh.h>
1730 #include <openssl/engine.h>
1731 #include <openssl/err.h>
1732 #include <openssl/opensslv.h>
1733 #include <openssl/pem.h>
1734 #include <openssl/ssl.h>
1735 #include <openssl/tls1.h>
1736 #include <openssl/x509.h>
1737 
1738 #if defined(WOLFSSL_VERSION)
1739 /* Additional defines for WolfSSL, see
1740  * https://github.com/civetweb/civetweb/issues/583 */
1741 #include "wolfssl_extras.inl"
1742 #endif
1743 
1744 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1745 /* If OpenSSL headers are included, automatically select the API version */
1746 #if !defined(OPENSSL_API_1_1)
1747 #define OPENSSL_API_1_1
1748 #endif
1749 #define OPENSSL_REMOVE_THREAD_STATE()
1750 #else
1751 #define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL)
1752 #endif
1753 
1754 #else
1755 
1756 /* SSL loaded dynamically from DLL.
1757  * I put the prototypes here to be independent from OpenSSL source
1758  * installation. */
1759 
1760 typedef struct ssl_st SSL;
1761 typedef struct ssl_method_st SSL_METHOD;
1762 typedef struct ssl_ctx_st SSL_CTX;
1763 typedef struct x509_store_ctx_st X509_STORE_CTX;
1764 typedef struct x509_name X509_NAME;
1765 typedef struct asn1_integer ASN1_INTEGER;
1766 typedef struct bignum BIGNUM;
1767 typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
1768 typedef struct evp_md EVP_MD;
1769 typedef struct x509 X509;
1770 
1771 
1772 #define SSL_CTRL_OPTIONS (32)
1773 #define SSL_CTRL_CLEAR_OPTIONS (77)
1774 #define SSL_CTRL_SET_ECDH_AUTO (94)
1775 
1776 #define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
1777 #define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
1778 #define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
1779 
1780 #define SSL_VERIFY_NONE (0)
1781 #define SSL_VERIFY_PEER (1)
1782 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
1783 #define SSL_VERIFY_CLIENT_ONCE (4)
1784 #define SSL_OP_ALL ((long)(0x80000BFFUL))
1785 #define SSL_OP_NO_SSLv2 (0x01000000L)
1786 #define SSL_OP_NO_SSLv3 (0x02000000L)
1787 #define SSL_OP_NO_TLSv1 (0x04000000L)
1788 #define SSL_OP_NO_TLSv1_2 (0x08000000L)
1789 #define SSL_OP_NO_TLSv1_1 (0x10000000L)
1790 #define SSL_OP_SINGLE_DH_USE (0x00100000L)
1791 #define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L)
1792 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L)
1793 #define SSL_OP_NO_COMPRESSION (0x00020000L)
1794 
1795 #define SSL_CB_HANDSHAKE_START (0x10)
1796 #define SSL_CB_HANDSHAKE_DONE (0x20)
1797 
1798 #define SSL_ERROR_NONE (0)
1799 #define SSL_ERROR_SSL (1)
1800 #define SSL_ERROR_WANT_READ (2)
1801 #define SSL_ERROR_WANT_WRITE (3)
1802 #define SSL_ERROR_WANT_X509_LOOKUP (4)
1803 #define SSL_ERROR_SYSCALL (5) /* see errno */
1804 #define SSL_ERROR_ZERO_RETURN (6)
1805 #define SSL_ERROR_WANT_CONNECT (7)
1806 #define SSL_ERROR_WANT_ACCEPT (8)
1807 
1808 #define TLSEXT_TYPE_server_name (0)
1809 #define TLSEXT_NAMETYPE_host_name (0)
1810 #define SSL_TLSEXT_ERR_OK (0)
1811 #define SSL_TLSEXT_ERR_ALERT_WARNING (1)
1812 #define SSL_TLSEXT_ERR_ALERT_FATAL (2)
1813 #define SSL_TLSEXT_ERR_NOACK (3)
1814 
1815 struct ssl_func {
1816  const char *name; /* SSL function name */
1817  void (*ptr)(void); /* Function pointer */
1818 };
1819 
1820 
1821 #if defined(OPENSSL_API_1_1)
1822 
1823 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
1824 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
1825 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
1826 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
1827 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
1828 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
1829 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
1830 #define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
1831 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
1832 #define TLS_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
1833 #define OPENSSL_init_ssl \
1834  (*(int (*)(uint64_t opts, \
1835  const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10] \
1836  .ptr)
1837 #define SSL_CTX_use_PrivateKey_file \
1838  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
1839 #define SSL_CTX_use_certificate_file \
1840  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
1841 #define SSL_CTX_set_default_passwd_cb \
1842  (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
1843 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
1844 #define SSL_CTX_use_certificate_chain_file \
1845  (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr)
1846 #define TLS_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[16].ptr)
1847 #define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr)
1848 #define SSL_CTX_set_verify \
1849  (*(void (*)(SSL_CTX *, \
1850  int, \
1851  int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18] \
1852  .ptr)
1853 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr)
1854 #define SSL_CTX_load_verify_locations \
1855  (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr)
1856 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr)
1857 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr)
1858 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[23].ptr)
1859 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr)
1860 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[25].ptr)
1861 #define SSL_CIPHER_get_name \
1862  (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr)
1863 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr)
1864 #define SSL_CTX_set_session_id_context \
1865  (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr)
1866 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr)
1867 #define SSL_CTX_set_cipher_list \
1868  (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr)
1869 #define SSL_CTX_set_options \
1870  (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr)
1871 #define SSL_CTX_set_info_callback \
1872  (*(void (*)(SSL_CTX * ctx, void (*callback)(const SSL *, int, int))) \
1873  ssl_sw[32] \
1874  .ptr)
1875 #define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr)
1876 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
1877 #define SSL_CTX_callback_ctrl \
1878  (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
1879 #define SSL_get_servername \
1880  (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
1881 #define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr)
1882 #define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr)
1883 
1884 #define SSL_CTX_clear_options(ctx, op) \
1885  SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
1886 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \
1887  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
1888 
1889 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
1890 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
1891 #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
1892 #define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
1893  SSL_CTX_callback_ctrl(ctx, \
1894  SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
1895  (void (*)(void))cb)
1896 #define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
1897  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
1898 #define SSL_set_tlsext_host_name(ctx, arg) \
1899  SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
1900 
1901 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
1902 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
1903 
1904 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
1905 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
1906 
1907 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr)
1908 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr)
1909 #define CONF_modules_unload (*(void (*)(int))crypto_sw[2].ptr)
1910 #define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr)
1911 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[4].ptr)
1912 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[5].ptr)
1913 #define X509_NAME_oneline \
1914  (*(char *(*)(X509_NAME *, char *, int))crypto_sw[6].ptr)
1915 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[7].ptr)
1916 #define EVP_get_digestbyname \
1917  (*(const EVP_MD *(*)(const char *))crypto_sw[8].ptr)
1918 #define EVP_Digest \
1919  (*(int (*)( \
1920  const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
1921  crypto_sw[9] \
1922  .ptr)
1923 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[10].ptr)
1924 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[11].ptr)
1925 #define ASN1_INTEGER_to_BN \
1926  (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[12].ptr)
1927 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[13].ptr)
1928 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[14].ptr)
1929 
1930 #define OPENSSL_free(a) CRYPTO_free(a)
1931 
1932 #define OPENSSL_REMOVE_THREAD_STATE()
1933 
1934 /* init_ssl_ctx() function updates this array.
1935  * It loads SSL library dynamically and changes NULLs to the actual addresses
1936  * of respective functions. The macros above (like SSL_connect()) are really
1937  * just calling these functions indirectly via the pointer. */
1938 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
1939  {"SSL_accept", NULL},
1940  {"SSL_connect", NULL},
1941  {"SSL_read", NULL},
1942  {"SSL_write", NULL},
1943  {"SSL_get_error", NULL},
1944  {"SSL_set_fd", NULL},
1945  {"SSL_new", NULL},
1946  {"SSL_CTX_new", NULL},
1947  {"TLS_server_method", NULL},
1948  {"OPENSSL_init_ssl", NULL},
1949  {"SSL_CTX_use_PrivateKey_file", NULL},
1950  {"SSL_CTX_use_certificate_file", NULL},
1951  {"SSL_CTX_set_default_passwd_cb", NULL},
1952  {"SSL_CTX_free", NULL},
1953  {"SSL_CTX_use_certificate_chain_file", NULL},
1954  {"TLS_client_method", NULL},
1955  {"SSL_pending", NULL},
1956  {"SSL_CTX_set_verify", NULL},
1957  {"SSL_shutdown", NULL},
1958  {"SSL_CTX_load_verify_locations", NULL},
1959  {"SSL_CTX_set_default_verify_paths", NULL},
1960  {"SSL_CTX_set_verify_depth", NULL},
1961  {"SSL_get_peer_certificate", NULL},
1962  {"SSL_get_version", NULL},
1963  {"SSL_get_current_cipher", NULL},
1964  {"SSL_CIPHER_get_name", NULL},
1965  {"SSL_CTX_check_private_key", NULL},
1966  {"SSL_CTX_set_session_id_context", NULL},
1967  {"SSL_CTX_ctrl", NULL},
1968  {"SSL_CTX_set_cipher_list", NULL},
1969  {"SSL_CTX_set_options", NULL},
1970  {"SSL_CTX_set_info_callback", NULL},
1971  {"SSL_get_ex_data", NULL},
1972  {"SSL_set_ex_data", NULL},
1973  {"SSL_CTX_callback_ctrl", NULL},
1974  {"SSL_get_servername", NULL},
1975  {"SSL_set_SSL_CTX", NULL},
1976  {"SSL_ctrl", NULL},
1977  {NULL, NULL}};
1978 
1979 
1980 /* Similar array as ssl_sw. These functions could be located in different
1981  * lib. */
1982 static struct ssl_func crypto_sw[] = {{"ERR_get_error", NULL},
1983  {"ERR_error_string", NULL},
1984  {"CONF_modules_unload", NULL},
1985  {"X509_free", NULL},
1986  {"X509_get_subject_name", NULL},
1987  {"X509_get_issuer_name", NULL},
1988  {"X509_NAME_oneline", NULL},
1989  {"X509_get_serialNumber", NULL},
1990  {"EVP_get_digestbyname", NULL},
1991  {"EVP_Digest", NULL},
1992  {"i2d_X509", NULL},
1993  {"BN_bn2hex", NULL},
1994  {"ASN1_INTEGER_to_BN", NULL},
1995  {"BN_free", NULL},
1996  {"CRYPTO_free", NULL},
1997  {NULL, NULL}};
1998 #else
1999 
2000 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
2001 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
2002 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
2003 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
2004 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
2005 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
2006 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
2007 #define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
2008 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
2009 #define SSLv23_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
2010 #define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
2011 #define SSL_CTX_use_PrivateKey_file \
2012  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
2013 #define SSL_CTX_use_certificate_file \
2014  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
2015 #define SSL_CTX_set_default_passwd_cb \
2016  (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
2017 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
2018 #define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
2019 #define SSL_CTX_use_certificate_chain_file \
2020  (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
2021 #define SSLv23_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
2022 #define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
2023 #define SSL_CTX_set_verify \
2024  (*(void (*)(SSL_CTX *, \
2025  int, \
2026  int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19] \
2027  .ptr)
2028 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
2029 #define SSL_CTX_load_verify_locations \
2030  (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
2031 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
2032 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
2033 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[24].ptr)
2034 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
2035 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[26].ptr)
2036 #define SSL_CIPHER_get_name \
2037  (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
2038 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
2039 #define SSL_CTX_set_session_id_context \
2040  (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
2041 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
2042 #define SSL_CTX_set_cipher_list \
2043  (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
2044 #define SSL_CTX_set_info_callback \
2045  (*(void (*)(SSL_CTX *, void (*callback)(const SSL *, int, int)))ssl_sw[32] \
2046  .ptr)
2047 #define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr)
2048 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
2049 #define SSL_CTX_callback_ctrl \
2050  (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
2051 #define SSL_get_servername \
2052  (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
2053 #define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr)
2054 #define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr)
2055 
2056 #define SSL_CTX_set_options(ctx, op) \
2057  SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
2058 #define SSL_CTX_clear_options(ctx, op) \
2059  SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
2060 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \
2061  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
2062 
2063 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
2064 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
2065 #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
2066 #define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
2067  SSL_CTX_callback_ctrl(ctx, \
2068  SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
2069  (void (*)(void))cb)
2070 #define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
2071  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
2072 #define SSL_set_tlsext_host_name(ctx, arg) \
2073  SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
2074 
2075 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
2076 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
2077 
2078 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
2079 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
2080 
2081 #define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
2082 #define CRYPTO_set_locking_callback \
2083  (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
2084 #define CRYPTO_set_id_callback \
2085  (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
2086 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
2087 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
2088 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
2089 #define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
2090 #define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
2091 #define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
2092 #define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
2093 #define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
2094 #define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr)
2095 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[12].ptr)
2096 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[13].ptr)
2097 #define X509_NAME_oneline \
2098  (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr)
2099 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[15].ptr)
2100 #define i2c_ASN1_INTEGER \
2101  (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr)
2102 #define EVP_get_digestbyname \
2103  (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr)
2104 #define EVP_Digest \
2105  (*(int (*)( \
2106  const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
2107  crypto_sw[18] \
2108  .ptr)
2109 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr)
2110 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr)
2111 #define ASN1_INTEGER_to_BN \
2112  (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[21].ptr)
2113 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr)
2114 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr)
2115 
2116 #define OPENSSL_free(a) CRYPTO_free(a)
2117 
2118 /* use here ERR_remove_state,
2119  * while on some platforms function is not included into library due to
2120  * deprication */
2121 #define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0)
2122 
2123 /* init_ssl_ctx() function updates this array.
2124  * It loads SSL library dynamically and changes NULLs to the actual addresses
2125  * of respective functions. The macros above (like SSL_connect()) are really
2126  * just calling these functions indirectly via the pointer. */
2127 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
2128  {"SSL_accept", NULL},
2129  {"SSL_connect", NULL},
2130  {"SSL_read", NULL},
2131  {"SSL_write", NULL},
2132  {"SSL_get_error", NULL},
2133  {"SSL_set_fd", NULL},
2134  {"SSL_new", NULL},
2135  {"SSL_CTX_new", NULL},
2136  {"SSLv23_server_method", NULL},
2137  {"SSL_library_init", NULL},
2138  {"SSL_CTX_use_PrivateKey_file", NULL},
2139  {"SSL_CTX_use_certificate_file", NULL},
2140  {"SSL_CTX_set_default_passwd_cb", NULL},
2141  {"SSL_CTX_free", NULL},
2142  {"SSL_load_error_strings", NULL},
2143  {"SSL_CTX_use_certificate_chain_file", NULL},
2144  {"SSLv23_client_method", NULL},
2145  {"SSL_pending", NULL},
2146  {"SSL_CTX_set_verify", NULL},
2147  {"SSL_shutdown", NULL},
2148  {"SSL_CTX_load_verify_locations", NULL},
2149  {"SSL_CTX_set_default_verify_paths", NULL},
2150  {"SSL_CTX_set_verify_depth", NULL},
2151  {"SSL_get_peer_certificate", NULL},
2152  {"SSL_get_version", NULL},
2153  {"SSL_get_current_cipher", NULL},
2154  {"SSL_CIPHER_get_name", NULL},
2155  {"SSL_CTX_check_private_key", NULL},
2156  {"SSL_CTX_set_session_id_context", NULL},
2157  {"SSL_CTX_ctrl", NULL},
2158  {"SSL_CTX_set_cipher_list", NULL},
2159  {"SSL_CTX_set_info_callback", NULL},
2160  {"SSL_get_ex_data", NULL},
2161  {"SSL_set_ex_data", NULL},
2162  {"SSL_CTX_callback_ctrl", NULL},
2163  {"SSL_get_servername", NULL},
2164  {"SSL_set_SSL_CTX", NULL},
2165  {"SSL_ctrl", NULL},
2166  {NULL, NULL}};
2167 
2168 
2169 /* Similar array as ssl_sw. These functions could be located in different
2170  * lib. */
2171 static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
2172  {"CRYPTO_set_locking_callback", NULL},
2173  {"CRYPTO_set_id_callback", NULL},
2174  {"ERR_get_error", NULL},
2175  {"ERR_error_string", NULL},
2176  {"ERR_remove_state", NULL},
2177  {"ERR_free_strings", NULL},
2178  {"ENGINE_cleanup", NULL},
2179  {"CONF_modules_unload", NULL},
2180  {"CRYPTO_cleanup_all_ex_data", NULL},
2181  {"EVP_cleanup", NULL},
2182  {"X509_free", NULL},
2183  {"X509_get_subject_name", NULL},
2184  {"X509_get_issuer_name", NULL},
2185  {"X509_NAME_oneline", NULL},
2186  {"X509_get_serialNumber", NULL},
2187  {"i2c_ASN1_INTEGER", NULL},
2188  {"EVP_get_digestbyname", NULL},
2189  {"EVP_Digest", NULL},
2190  {"i2d_X509", NULL},
2191  {"BN_bn2hex", NULL},
2192  {"ASN1_INTEGER_to_BN", NULL},
2193  {"BN_free", NULL},
2194  {"CRYPTO_free", NULL},
2195  {NULL, NULL}};
2196 #endif /* OPENSSL_API_1_1 */
2197 #endif /* NO_SSL_DL */
2198 #endif /* NO_SSL */
2199 
2200 
2201 #if !defined(NO_CACHING)
2202 static const char *month_names[] = {"Jan",
2203  "Feb",
2204  "Mar",
2205  "Apr",
2206  "May",
2207  "Jun",
2208  "Jul",
2209  "Aug",
2210  "Sep",
2211  "Oct",
2212  "Nov",
2213  "Dec"};
2214 #endif /* !NO_CACHING */
2215 
2216 /* Unified socket address. For IPv6 support, add IPv6 address structure in
2217  * the
2218  * union u. */
2219 union usa {
2220  struct sockaddr sa;
2221  struct sockaddr_in sin;
2222 #if defined(USE_IPV6)
2223  struct sockaddr_in6 sin6;
2224 #endif
2225 };
2226 
2227 /* Describes a string (chunk of memory). */
2228 struct vec {
2229  const char *ptr;
2230  size_t len;
2231 };
2232 
2233 struct mg_file_stat {
2234  /* File properties filled by mg_stat: */
2235  uint64_t size;
2236  time_t last_modified;
2237  int is_directory; /* Set to 1 if mg_stat is called for a directory */
2238  int is_gzipped; /* Set to 1 if the content is gzipped, in which
2239  * case we need a "Content-Eencoding: gzip" header */
2240  int location; /* 0 = nowhere, 1 = on disk, 2 = in memory */
2241 };
2242 
2243 struct mg_file_in_memory {
2244  char *p;
2245  uint32_t pos;
2246  char mode;
2247 };
2248 
2249 struct mg_file_access {
2250  /* File properties filled by mg_fopen: */
2251  FILE *fp;
2252 #if defined(MG_USE_OPEN_FILE)
2253  /* TODO (low): Remove obsolete "file in memory" implementation.
2254  * In an "early 2017" discussion at Google groups
2255  * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
2256  * we decided to get rid of this feature (after some fade-out
2257  * phase). */
2258  const char *membuf;
2259 #endif
2260 };
2261 
2262 struct mg_file {
2263  struct mg_file_stat stat;
2264  struct mg_file_access access;
2265 };
2266 
2267 #if defined(MG_USE_OPEN_FILE)
2268 
2269 #define STRUCT_FILE_INITIALIZER \
2270  { \
2271  {(uint64_t)0, (time_t)0, 0, 0, 0}, \
2272  { \
2273  (FILE *)NULL, (const char *)NULL \
2274  } \
2275  }
2276 
2277 #else
2278 
2279 #define STRUCT_FILE_INITIALIZER \
2280  { \
2281  {(uint64_t)0, (time_t)0, 0, 0, 0}, \
2282  { \
2283  (FILE *)NULL \
2284  } \
2285  }
2286 
2287 #endif
2288 
2289 
2290 /* Describes listening socket, or socket which was accept()-ed by the master
2291  * thread and queued for future handling by the worker thread. */
2292 struct socket {
2293  SOCKET sock; /* Listening socket */
2294  union usa lsa; /* Local socket address */
2295  union usa rsa; /* Remote socket address */
2296  unsigned char is_ssl; /* Is port SSL-ed */
2297  unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
2298  * port */
2299  unsigned char in_use; /* Is valid */
2300 };
2301 
2302 
2303 /* Enum const for all options must be in sync with
2304  * static struct mg_option config_options[]
2305  * This is tested in the unit test (test/private.c)
2306  * "Private Config Options"
2307  */
2308 enum {
2309  /* Once for each server */
2310  LISTENING_PORTS,
2311  NUM_THREADS,
2312  RUN_AS_USER,
2313  CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
2314  * socket option typedef TCP_NODELAY. */
2315  MAX_REQUEST_SIZE,
2316  LINGER_TIMEOUT,
2317 #if defined(__linux__)
2318  ALLOW_SENDFILE_CALL,
2319 #endif
2320 #if defined(_WIN32)
2321  CASE_SENSITIVE_FILES,
2322 #endif
2323  THROTTLE,
2324  ACCESS_LOG_FILE,
2325  ERROR_LOG_FILE,
2326  ENABLE_KEEP_ALIVE,
2327  REQUEST_TIMEOUT,
2328  KEEP_ALIVE_TIMEOUT,
2329 #if defined(USE_WEBSOCKET)
2330  WEBSOCKET_TIMEOUT,
2331  ENABLE_WEBSOCKET_PING_PONG,
2332 #endif
2333  DECODE_URL,
2334 #if defined(USE_LUA)
2335  LUA_BACKGROUND_SCRIPT,
2336  LUA_BACKGROUND_SCRIPT_PARAMS,
2337 #endif
2338 #if defined(USE_TIMERS)
2339  CGI_TIMEOUT,
2340 #endif
2341 
2342  /* Once for each domain */
2343  DOCUMENT_ROOT,
2344  CGI_EXTENSIONS,
2345  CGI_ENVIRONMENT,
2346  PUT_DELETE_PASSWORDS_FILE,
2347  CGI_INTERPRETER,
2348  PROTECT_URI,
2349  AUTHENTICATION_DOMAIN,
2350  ENABLE_AUTH_DOMAIN_CHECK,
2351  SSI_EXTENSIONS,
2352  ENABLE_DIRECTORY_LISTING,
2353  GLOBAL_PASSWORDS_FILE,
2354  INDEX_FILES,
2355  ACCESS_CONTROL_LIST,
2356  EXTRA_MIME_TYPES,
2357  SSL_CERTIFICATE,
2358  SSL_CERTIFICATE_CHAIN,
2359  URL_REWRITE_PATTERN,
2360  HIDE_FILES,
2361  SSL_DO_VERIFY_PEER,
2362  SSL_CA_PATH,
2363  SSL_CA_FILE,
2364  SSL_VERIFY_DEPTH,
2365  SSL_DEFAULT_VERIFY_PATHS,
2366  SSL_CIPHER_LIST,
2367  SSL_PROTOCOL_VERSION,
2368  SSL_SHORT_TRUST,
2369 
2370 #if defined(USE_LUA)
2371  LUA_PRELOAD_FILE,
2372  LUA_SCRIPT_EXTENSIONS,
2373  LUA_SERVER_PAGE_EXTENSIONS,
2374 #if defined(MG_EXPERIMENTAL_INTERFACES)
2375  LUA_DEBUG_PARAMS,
2376 #endif
2377 #endif
2378 #if defined(USE_DUKTAPE)
2379  DUKTAPE_SCRIPT_EXTENSIONS,
2380 #endif
2381 
2382 #if defined(USE_WEBSOCKET)
2383  WEBSOCKET_ROOT,
2384 #endif
2385 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2386  LUA_WEBSOCKET_EXTENSIONS,
2387 #endif
2388 
2389  ACCESS_CONTROL_ALLOW_ORIGIN,
2390  ACCESS_CONTROL_ALLOW_METHODS,
2391  ACCESS_CONTROL_ALLOW_HEADERS,
2392  ERROR_PAGES,
2393 #if !defined(NO_CACHING)
2394  STATIC_FILE_MAX_AGE,
2395 #endif
2396 #if !defined(NO_SSL)
2397  STRICT_HTTPS_MAX_AGE,
2398 #endif
2399  ADDITIONAL_HEADER,
2400  ALLOW_INDEX_SCRIPT_SUB_RES,
2401 
2402  NUM_OPTIONS
2403 };
2404 
2405 
2406 /* Config option name, config types, default value.
2407  * Must be in the same order as the enum const above.
2408  */
2409 static const struct mg_option config_options[] = {
2410 
2411  /* Once for each server */
2412  {"listening_ports", MG_CONFIG_TYPE_STRING_LIST, "8080"},
2413  {"num_threads", MG_CONFIG_TYPE_NUMBER, "50"},
2414  {"run_as_user", MG_CONFIG_TYPE_STRING, NULL},
2415  {"tcp_nodelay", MG_CONFIG_TYPE_NUMBER, "0"},
2416  {"max_request_size", MG_CONFIG_TYPE_NUMBER, "16384"},
2417  {"linger_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2418 #if defined(__linux__)
2419  {"allow_sendfile_call", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2420 #endif
2421 #if defined(_WIN32)
2422  {"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2423 #endif
2424  {"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL},
2425  {"access_log_file", MG_CONFIG_TYPE_FILE, NULL},
2426  {"error_log_file", MG_CONFIG_TYPE_FILE, NULL},
2427  {"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2428  {"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"},
2429  {"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"},
2430 #if defined(USE_WEBSOCKET)
2431  {"websocket_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2432  {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
2433 #endif
2434  {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2435 #if defined(USE_LUA)
2436  {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
2437  {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
2438 #endif
2439 #if defined(USE_TIMERS)
2440  {"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2441 #endif
2442 
2443  /* Once for each domain */
2444  {"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2445  {"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
2446  {"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2447  {"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2448  {"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2449  {"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL},
2450  {"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"},
2451  {"enable_auth_domain_check", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2452  {"ssi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
2453  {"enable_directory_listing", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2454  {"global_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2455  {"index_files",
2456  MG_CONFIG_TYPE_STRING_LIST,
2457 #if defined(USE_LUA)
2458  "index.xhtml,index.html,index.htm,"
2459  "index.lp,index.lsp,index.lua,index.cgi,"
2460  "index.shtml,index.php"},
2461 #else
2462  "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
2463 #endif
2464  {"access_control_list", MG_CONFIG_TYPE_STRING_LIST, NULL},
2465  {"extra_mime_types", MG_CONFIG_TYPE_STRING_LIST, NULL},
2466  {"ssl_certificate", MG_CONFIG_TYPE_FILE, NULL},
2467  {"ssl_certificate_chain", MG_CONFIG_TYPE_FILE, NULL},
2468  {"url_rewrite_patterns", MG_CONFIG_TYPE_STRING_LIST, NULL},
2469  {"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2470 
2471  {"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
2472 
2473  {"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
2474  {"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
2475  {"ssl_verify_depth", MG_CONFIG_TYPE_NUMBER, "9"},
2476  {"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2477  {"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL},
2478  {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "0"},
2479  {"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"},
2480 
2481 #if defined(USE_LUA)
2482  {"lua_preload_file", MG_CONFIG_TYPE_FILE, NULL},
2483  {"lua_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2484  {"lua_server_page_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
2485 #if defined(MG_EXPERIMENTAL_INTERFACES)
2486  {"lua_debug", MG_CONFIG_TYPE_STRING, NULL},
2487 #endif
2488 #endif
2489 #if defined(USE_DUKTAPE)
2490  /* The support for duktape is still in alpha version state.
2491  * The name of this config option might change. */
2492  {"duktape_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
2493 #endif
2494 
2495 #if defined(USE_WEBSOCKET)
2496  {"websocket_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2497 #endif
2498 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2499  {"lua_websocket_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2500 #endif
2501  {"access_control_allow_origin", MG_CONFIG_TYPE_STRING, "*"},
2502  {"access_control_allow_methods", MG_CONFIG_TYPE_STRING, "*"},
2503  {"access_control_allow_headers", MG_CONFIG_TYPE_STRING, "*"},
2504  {"error_pages", MG_CONFIG_TYPE_DIRECTORY, NULL},
2505 #if !defined(NO_CACHING)
2506  {"static_file_max_age", MG_CONFIG_TYPE_NUMBER, "3600"},
2507 #endif
2508 #if !defined(NO_SSL)
2509  {"strict_transport_security_max_age", MG_CONFIG_TYPE_NUMBER, NULL},
2510 #endif
2511  {"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL},
2512  {"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"},
2513 
2514  {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}};
2515 
2516 
2517 /* Check if the config_options and the corresponding enum have compatible
2518  * sizes. */
2519 mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
2520  == (NUM_OPTIONS + 1),
2521  "config_options and enum not sync");
2522 
2523 
2524 enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
2525 
2526 
2527 struct mg_handler_info {
2528  /* Name/Pattern of the URI. */
2529  char *uri;
2530  size_t uri_len;
2531 
2532  /* handler type */
2533  int handler_type;
2534 
2535  /* Handler for http/https or authorization requests. */
2536  mg_request_handler handler;
2537  unsigned int refcount;
2538  pthread_mutex_t refcount_mutex; /* Protects refcount */
2539  pthread_cond_t
2540  refcount_cond; /* Signaled when handler refcount is decremented */
2541 
2542  /* Handler for ws/wss (websocket) requests. */
2543  mg_websocket_connect_handler connect_handler;
2544  mg_websocket_ready_handler ready_handler;
2545  mg_websocket_data_handler data_handler;
2546  mg_websocket_close_handler close_handler;
2547 
2548  /* accepted subprotocols for ws/wss requests. */
2549  struct mg_websocket_subprotocols *subprotocols;
2550 
2551  /* Handler for authorization requests */
2552  mg_authorization_handler auth_handler;
2553 
2554  /* User supplied argument for the handler function. */
2555  void *cbdata;
2556 
2557  /* next handler in a linked list */
2558  struct mg_handler_info *next;
2559 };
2560 
2561 
2562 enum {
2563  CONTEXT_INVALID,
2564  CONTEXT_SERVER,
2565  CONTEXT_HTTP_CLIENT,
2566  CONTEXT_WS_CLIENT
2567 };
2568 
2569 
2570 struct mg_domain_context {
2571  SSL_CTX *ssl_ctx; /* SSL context */
2572  char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
2573  struct mg_handler_info *handlers; /* linked list of uri handlers */
2574 
2575  /* Server nonce */
2576  uint64_t auth_nonce_mask; /* Mask for all nonce values */
2577  unsigned long nonce_count; /* Used nonces, used for authentication */
2578 
2579 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2580  /* linked list of shared lua websockets */
2581  struct mg_shared_lua_websocket_list *shared_lua_websockets;
2582 #endif
2583 
2584  /* Linked list of domains */
2585  struct mg_domain_context *next;
2586 };
2587 
2588 
2589 struct mg_context {
2590 
2591  /* Part 1 - Physical context:
2592  * This holds threads, ports, timeouts, ...
2593  * set for the entire server, independent from the
2594  * addressed hostname.
2595  */
2596 
2597  /* Connection related */
2598  int context_type; /* See CONTEXT_* above */
2599 
2600  struct socket *listening_sockets;
2601  struct pollfd *listening_socket_fds;
2602  unsigned int num_listening_sockets;
2603 
2604  struct mg_connection *worker_connections; /* The connection struct, pre-
2605  * allocated for each worker */
2606 
2607 #if defined(USE_SERVER_STATS)
2608  int active_connections;
2609  int max_connections;
2610  int64_t total_connections;
2611  int64_t total_requests;
2612  int64_t total_data_read;
2613  int64_t total_data_written;
2614 #endif
2615 
2616  /* Thread related */
2617  volatile int stop_flag; /* Should we stop event loop */
2618  pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
2619 
2620  pthread_t masterthreadid; /* The master thread ID */
2621  unsigned int
2622  cfg_worker_threads; /* The number of configured worker threads. */
2623  pthread_t *worker_threadids; /* The worker thread IDs */
2624 
2625 /* Connection to thread dispatching */
2626 #if defined(ALTERNATIVE_QUEUE)
2627  struct socket *client_socks;
2628  void **client_wait_events;
2629 #else
2630  struct socket queue[MGSQLEN]; /* Accepted sockets */
2631  volatile int sq_head; /* Head of the socket queue */
2632  volatile int sq_tail; /* Tail of the socket queue */
2633  pthread_cond_t sq_full; /* Signaled when socket is produced */
2634  pthread_cond_t sq_empty; /* Signaled when socket is consumed */
2635 #endif
2636 
2637  /* Memory related */
2638  unsigned int max_request_size; /* The max request size */
2639 
2640 #if defined(USE_SERVER_STATS)
2641  struct mg_memory_stat ctx_memory;
2642 #endif
2643 
2644  /* Operating system related */
2645  char *systemName; /* What operating system is running */
2646  time_t start_time; /* Server start time, used for authentication
2647  * and for diagnstics. */
2648 
2649 #if defined(USE_TIMERS)
2650  struct ttimers *timers;
2651 #endif
2652 
2653 /* Lua specific: Background operations and shared websockets */
2654 #if defined(USE_LUA)
2655  void *lua_background_state;
2656 #endif
2657 
2658  /* Server nonce */
2659  pthread_mutex_t nonce_mutex; /* Protects nonce_count */
2660 
2661  /* Server callbacks */
2662  struct mg_callbacks callbacks; /* User-defined callback function */
2663  void *user_data; /* User-defined data */
2664 
2665  /* Part 2 - Logical domain:
2666  * This holds hostname, TLS certificate, document root, ...
2667  * set for a domain hosted at the server.
2668  * There may be multiple domains hosted at one physical server.
2669  * The default domain "dd" is the first element of a list of
2670  * domains.
2671  */
2672  struct mg_domain_context dd; /* default domain */
2673 };
2674 
2675 
2676 #if defined(USE_SERVER_STATS)
2677 static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2678 
2679 static struct mg_memory_stat *
2680 get_memory_stat(struct mg_context *ctx)
2681 {
2682  if (ctx) {
2683  return &(ctx->ctx_memory);
2684  }
2685  return &mg_common_memory;
2686 }
2687 #endif
2688 
2689 enum {
2690  CONNECTION_TYPE_INVALID,
2691  CONNECTION_TYPE_REQUEST,
2692  CONNECTION_TYPE_RESPONSE
2693 };
2694 
2695 struct mg_connection {
2696  int connection_type; /* see CONNECTION_TYPE_* above */
2697 
2698  struct mg_request_info request_info;
2699  struct mg_response_info response_info;
2700 
2701  struct mg_context *phys_ctx;
2702  struct mg_domain_context *dom_ctx;
2703 
2704 #if defined(USE_SERVER_STATS)
2705  int conn_state; /* 0 = undef, numerical value may change in different
2706  * versions. For the current definition, see
2707  * mg_get_connection_info_impl */
2708 #endif
2709 
2710  const char *host; /* Host (HTTP/1.1 header or SNI) */
2711  SSL *ssl; /* SSL descriptor */
2712  SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
2713  struct socket client; /* Connected client */
2714  time_t conn_birth_time; /* Time (wall clock) when connection was
2715  * established */
2716  struct timespec req_time; /* Time (since system start) when the request
2717  * was received */
2718  int64_t num_bytes_sent; /* Total bytes sent to client */
2719  int64_t content_len; /* Content-Length header value */
2720  int64_t consumed_content; /* How many bytes of content have been read */
2721  int is_chunked; /* Transfer-Encoding is chunked:
2722  * 0 = not chunked,
2723  * 1 = chunked, do data read yet,
2724  * 2 = chunked, some data read,
2725  * 3 = chunked, all data read
2726  */
2727  size_t chunk_remainder; /* Unread data from the last chunk */
2728  char *buf; /* Buffer for received data */
2729  char *path_info; /* PATH_INFO part of the URL */
2730 
2731  int must_close; /* 1 if connection must be closed */
2732  int accept_gzip; /* 1 if gzip encoding is accepted */
2733  int in_error_handler; /* 1 if in handler for user defined error
2734  * pages */
2735 #if defined(USE_WEBSOCKET)
2736  int in_websocket_handling; /* 1 if in read_websocket */
2737 #endif
2738  int handled_requests; /* Number of requests handled by this connection
2739  */
2740  int buf_size; /* Buffer size */
2741  int request_len; /* Size of the request + headers in a buffer */
2742  int data_len; /* Total size of data in a buffer */
2743  int status_code; /* HTTP reply status code, e.g. 200 */
2744  int throttle; /* Throttling, bytes/sec. <= 0 means no
2745  * throttle */
2746 
2747  time_t last_throttle_time; /* Last time throttled data was sent */
2748  int64_t last_throttle_bytes; /* Bytes sent this second */
2749  pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
2750  * atomic transmissions for websockets */
2751 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2752  void *lua_websocket_state; /* Lua_State for a websocket connection */
2753 #endif
2754 
2755  int thread_index; /* Thread index within ctx */
2756 };
2757 
2758 
2759 /* Directory entry */
2760 struct de {
2761  struct mg_connection *conn;
2762  char *file_name;
2763  struct mg_file_stat file;
2764 };
2765 
2766 
2767 #if defined(USE_WEBSOCKET)
2768 static int is_websocket_protocol(const struct mg_connection *conn);
2769 #else
2770 #define is_websocket_protocol(conn) (0)
2771 #endif
2772 
2773 
2774 #define mg_cry_internal(conn, fmt, ...) \
2775  mg_cry_internal_wrap(conn, __func__, __LINE__, fmt, __VA_ARGS__)
2776 
2777 static void mg_cry_internal_wrap(const struct mg_connection *conn,
2778  const char *func,
2779  unsigned line,
2780  const char *fmt,
2781  ...) PRINTF_ARGS(4, 5);
2782 
2783 
2784 #if !defined(NO_THREAD_NAME)
2785 #if defined(_WIN32) && defined(_MSC_VER)
2786 /* Set the thread name for debugging purposes in Visual Studio
2787  * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
2788  */
2789 #pragma pack(push, 8)
2790 typedef struct tagTHREADNAME_INFO {
2791  DWORD dwType; /* Must be 0x1000. */
2792  LPCSTR szName; /* Pointer to name (in user addr space). */
2793  DWORD dwThreadID; /* Thread ID (-1=caller thread). */
2794  DWORD dwFlags; /* Reserved for future use, must be zero. */
2795 } THREADNAME_INFO;
2796 #pragma pack(pop)
2797 
2798 #elif defined(__linux__)
2799 
2800 #include <sys/prctl.h>
2801 #include <sys/sendfile.h>
2802 #if defined(ALTERNATIVE_QUEUE)
2803 #include <sys/eventfd.h>
2804 #endif /* ALTERNATIVE_QUEUE */
2805 
2806 
2807 #if defined(ALTERNATIVE_QUEUE)
2808 
2809 static void *
2810 event_create(void)
2811 {
2812  int evhdl = eventfd(0, EFD_CLOEXEC);
2813  int *ret;
2814 
2815  if (evhdl == -1) {
2816  /* Linux uses -1 on error, Windows NULL. */
2817  /* However, Linux does not return 0 on success either. */
2818  return 0;
2819  }
2820 
2821  ret = (int *)mg_malloc(sizeof(int));
2822  if (ret) {
2823  *ret = evhdl;
2824  } else {
2825  (void)close(evhdl);
2826  }
2827 
2828  return (void *)ret;
2829 }
2830 
2831 
2832 static int
2833 event_wait(void *eventhdl)
2834 {
2835  uint64_t u;
2836  int evhdl, s;
2837 
2838  if (!eventhdl) {
2839  /* error */
2840  return 0;
2841  }
2842  evhdl = *(int *)eventhdl;
2843 
2844  s = (int)read(evhdl, &u, sizeof(u));
2845  if (s != sizeof(u)) {
2846  /* error */
2847  return 0;
2848  }
2849  (void)u; /* the value is not required */
2850  return 1;
2851 }
2852 
2853 
2854 static int
2855 event_signal(void *eventhdl)
2856 {
2857  uint64_t u = 1;
2858  int evhdl, s;
2859 
2860  if (!eventhdl) {
2861  /* error */
2862  return 0;
2863  }
2864  evhdl = *(int *)eventhdl;
2865 
2866  s = (int)write(evhdl, &u, sizeof(u));
2867  if (s != sizeof(u)) {
2868  /* error */
2869  return 0;
2870  }
2871  return 1;
2872 }
2873 
2874 
2875 static void
2876 event_destroy(void *eventhdl)
2877 {
2878  int evhdl;
2879 
2880  if (!eventhdl) {
2881  /* error */
2882  return;
2883  }
2884  evhdl = *(int *)eventhdl;
2885 
2886  close(evhdl);
2887  mg_free(eventhdl);
2888 }
2889 
2890 
2891 #endif
2892 
2893 #endif
2894 
2895 
2896 #if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
2897 
2898 struct posix_event {
2899  pthread_mutex_t mutex;
2900  pthread_cond_t cond;
2901 };
2902 
2903 
2904 static void *
2905 event_create(void)
2906 {
2907  struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
2908  if (ret == 0) {
2909  /* out of memory */
2910  return 0;
2911  }
2912  if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
2913  /* pthread mutex not available */
2914  mg_free(ret);
2915  return 0;
2916  }
2917  if (0 != pthread_cond_init(&(ret->cond), NULL)) {
2918  /* pthread cond not available */
2919  pthread_mutex_destroy(&(ret->mutex));
2920  mg_free(ret);
2921  return 0;
2922  }
2923  return (void *)ret;
2924 }
2925 
2926 
2927 static int
2928 event_wait(void *eventhdl)
2929 {
2930  struct posix_event *ev = (struct posix_event *)eventhdl;
2931  pthread_mutex_lock(&(ev->mutex));
2932  pthread_cond_wait(&(ev->cond), &(ev->mutex));
2933  pthread_mutex_unlock(&(ev->mutex));
2934  return 1;
2935 }
2936 
2937 
2938 static int
2939 event_signal(void *eventhdl)
2940 {
2941  struct posix_event *ev = (struct posix_event *)eventhdl;
2942  pthread_mutex_lock(&(ev->mutex));
2943  pthread_cond_signal(&(ev->cond));
2944  pthread_mutex_unlock(&(ev->mutex));
2945  return 1;
2946 }
2947 
2948 
2949 static void
2950 event_destroy(void *eventhdl)
2951 {
2952  struct posix_event *ev = (struct posix_event *)eventhdl;
2953  pthread_cond_destroy(&(ev->cond));
2954  pthread_mutex_destroy(&(ev->mutex));
2955  mg_free(ev);
2956 }
2957 #endif
2958 
2959 
2960 static void
2961 mg_set_thread_name(const char *name)
2962 {
2963  char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
2964 
2965  mg_snprintf(
2966  NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
2967 
2968 #if defined(_WIN32)
2969 #if defined(_MSC_VER)
2970  /* Windows and Visual Studio Compiler */
2971  __try {
2972  THREADNAME_INFO info;
2973  info.dwType = 0x1000;
2974  info.szName = threadName;
2975  info.dwThreadID = ~0U;
2976  info.dwFlags = 0;
2977 
2978  RaiseException(0x406D1388,
2979  0,
2980  sizeof(info) / sizeof(ULONG_PTR),
2981  (ULONG_PTR *)&info);
2982  } __except (EXCEPTION_EXECUTE_HANDLER) {
2983  }
2984 #elif defined(__MINGW32__)
2985 /* No option known to set thread name for MinGW */
2986 #endif
2987 #elif defined(_GNU_SOURCE) && defined(__GLIBC__) \
2988  && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
2989 /* pthread_setname_np first appeared in glibc in version 2.12*/
2990 #if defined(__MACH__)
2991  /* OS X only current thread name can be changed */
2992  (void)pthread_setname_np(threadName);
2993 #else
2994  (void)pthread_setname_np(pthread_self(), threadName);
2995 #endif
2996 #elif defined(__linux__)
2997  /* on linux we can use the old prctl function */
2998  (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
2999 #endif
3000 }
3001 #else /* !defined(NO_THREAD_NAME) */
3002 void
3003 mg_set_thread_name(const char *threadName)
3004 {
3005 }
3006 #endif
3007 
3008 
3009 #if defined(MG_LEGACY_INTERFACE)
3010 const char **
3011 mg_get_valid_option_names(void)
3012 {
3013  /* This function is deprecated. Use mg_get_valid_options instead. */
3014  static const char
3015  *data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
3016  int i;
3017 
3018  for (i = 0; config_options[i].name != NULL; i++) {
3019  data[i * 2] = config_options[i].name;
3020  data[i * 2 + 1] = config_options[i].default_value;
3021  }
3022 
3023  return data;
3024 }
3025 #endif
3026 
3027 
3028 const struct mg_option *
3029 mg_get_valid_options(void)
3030 {
3031  return config_options;
3032 }
3033 
3034 
3035 /* Do not open file (used in is_file_in_memory) */
3036 #define MG_FOPEN_MODE_NONE (0)
3037 
3038 /* Open file for read only access */
3039 #define MG_FOPEN_MODE_READ (1)
3040 
3041 /* Open file for writing, create and overwrite */
3042 #define MG_FOPEN_MODE_WRITE (2)
3043 
3044 /* Open file for writing, create and append */
3045 #define MG_FOPEN_MODE_APPEND (4)
3046 
3047 
3048 /* If a file is in memory, set all "stat" members and the membuf pointer of
3049  * output filep and return 1, otherwise return 0 and don't modify anything.
3050  */
3051 static int
3052 open_file_in_memory(const struct mg_connection *conn,
3053  const char *path,
3054  struct mg_file *filep,
3055  int mode)
3056 {
3057 #if defined(MG_USE_OPEN_FILE)
3058 
3059  size_t size = 0;
3060  const char *buf = NULL;
3061  if (!conn) {
3062  return 0;
3063  }
3064 
3065  if ((mode != MG_FOPEN_MODE_NONE) && (mode != MG_FOPEN_MODE_READ)) {
3066  return 0;
3067  }
3068 
3069  if (conn->phys_ctx->callbacks.open_file) {
3070  buf = conn->phys_ctx->callbacks.open_file(conn, path, &size);
3071  if (buf != NULL) {
3072  if (filep == NULL) {
3073  /* This is a file in memory, but we cannot store the
3074  * properties
3075  * now.
3076  * Called from "is_file_in_memory" function. */
3077  return 1;
3078  }
3079 
3080  /* NOTE: override filep->size only on success. Otherwise, it
3081  * might
3082  * break constructs like if (!mg_stat() || !mg_fopen()) ... */
3083  filep->access.membuf = buf;
3084  filep->access.fp = NULL;
3085 
3086  /* Size was set by the callback */
3087  filep->stat.size = size;
3088 
3089  /* Assume the data may change during runtime by setting
3090  * last_modified = now */
3091  filep->stat.last_modified = time(NULL);
3092 
3093  filep->stat.is_directory = 0;
3094  filep->stat.is_gzipped = 0;
3095  }
3096  }
3097 
3098  return (buf != NULL);
3099 
3100 #else
3101  (void)conn;
3102  (void)path;
3103  (void)filep;
3104  (void)mode;
3105 
3106  return 0;
3107 
3108 #endif
3109 }
3110 
3111 
3112 static int
3113 is_file_in_memory(const struct mg_connection *conn, const char *path)
3114 {
3115  return open_file_in_memory(conn, path, NULL, MG_FOPEN_MODE_NONE);
3116 }
3117 
3118 
3119 static int
3120 is_file_opened(const struct mg_file_access *fileacc)
3121 {
3122  if (!fileacc) {
3123  return 0;
3124  }
3125 
3126 #if defined(MG_USE_OPEN_FILE)
3127  return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
3128 #else
3129  return (fileacc->fp != NULL);
3130 #endif
3131 }
3132 
3133 
3134 static int mg_stat(const struct mg_connection *conn,
3135  const char *path,
3136  struct mg_file_stat *filep);
3137 
3138 
3139 /* mg_fopen will open a file either in memory or on the disk.
3140  * The input parameter path is a string in UTF-8 encoding.
3141  * The input parameter mode is MG_FOPEN_MODE_*
3142  * On success, either fp or membuf will be set in the output
3143  * struct file. All status members will also be set.
3144  * The function returns 1 on success, 0 on error. */
3145 static int
3146 mg_fopen(const struct mg_connection *conn,
3147  const char *path,
3148  int mode,
3149  struct mg_file *filep)
3150 {
3151  int found;
3152 
3153  if (!filep) {
3154  return 0;
3155  }
3156  filep->access.fp = NULL;
3157 #if defined(MG_USE_OPEN_FILE)
3158  filep->access.membuf = NULL;
3159 #endif
3160 
3161  if (!is_file_in_memory(conn, path)) {
3162 
3163  /* filep is initialized in mg_stat: all fields with memset to,
3164  * some fields like size and modification date with values */
3165  found = mg_stat(conn, path, &(filep->stat));
3166 
3167  if ((mode == MG_FOPEN_MODE_READ) && (!found)) {
3168  /* file does not exist and will not be created */
3169  return 0;
3170  }
3171 
3172 #if defined(_WIN32)
3173  {
3174  wchar_t wbuf[W_PATH_MAX];
3175  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3176  switch (mode) {
3177  case MG_FOPEN_MODE_READ:
3178  filep->access.fp = _wfopen(wbuf, L"rb");
3179  break;
3180  case MG_FOPEN_MODE_WRITE:
3181  filep->access.fp = _wfopen(wbuf, L"wb");
3182  break;
3183  case MG_FOPEN_MODE_APPEND:
3184  filep->access.fp = _wfopen(wbuf, L"ab");
3185  break;
3186  }
3187  }
3188 #else
3189  /* Linux et al already use unicode. No need to convert. */
3190  switch (mode) {
3191  case MG_FOPEN_MODE_READ:
3192  filep->access.fp = fopen(path, "r");
3193  break;
3194  case MG_FOPEN_MODE_WRITE:
3195  filep->access.fp = fopen(path, "w");
3196  break;
3197  case MG_FOPEN_MODE_APPEND:
3198  filep->access.fp = fopen(path, "a");
3199  break;
3200  }
3201 
3202 #endif
3203  if (!found) {
3204  /* File did not exist before fopen was called.
3205  * Maybe it has been created now. Get stat info
3206  * like creation time now. */
3207  found = mg_stat(conn, path, &(filep->stat));
3208  (void)found;
3209  }
3210 
3211  /* file is on disk */
3212  return (filep->access.fp != NULL);
3213 
3214  } else {
3215 #if defined(MG_USE_OPEN_FILE)
3216  /* is_file_in_memory returned true */
3217  if (open_file_in_memory(conn, path, filep, mode)) {
3218  /* file is in memory */
3219  return (filep->access.membuf != NULL);
3220  }
3221 #endif
3222  }
3223 
3224  /* Open failed */
3225  return 0;
3226 }
3227 
3228 
3229 /* return 0 on success, just like fclose */
3230 static int
3231 mg_fclose(struct mg_file_access *fileacc)
3232 {
3233  int ret = -1;
3234  if (fileacc != NULL) {
3235  if (fileacc->fp != NULL) {
3236  ret = fclose(fileacc->fp);
3237 #if defined(MG_USE_OPEN_FILE)
3238  } else if (fileacc->membuf != NULL) {
3239  ret = 0;
3240 #endif
3241  }
3242  /* reset all members of fileacc */
3243  memset(fileacc, 0, sizeof(*fileacc));
3244  }
3245  return ret;
3246 }
3247 
3248 
3249 static void
3250 mg_strlcpy(register char *dst, register const char *src, size_t n)
3251 {
3252  for (; *src != '\0' && n > 1; n--) {
3253  *dst++ = *src++;
3254  }
3255  *dst = '\0';
3256 }
3257 
3258 
3259 static int
3260 lowercase(const char *s)
3261 {
3262  return tolower(*(const unsigned char *)s);
3263 }
3264 
3265 
3266 int
3267 mg_strncasecmp(const char *s1, const char *s2, size_t len)
3268 {
3269  int diff = 0;
3270 
3271  if (len > 0) {
3272  do {
3273  diff = lowercase(s1++) - lowercase(s2++);
3274  } while (diff == 0 && s1[-1] != '\0' && --len > 0);
3275  }
3276 
3277  return diff;
3278 }
3279 
3280 
3281 int
3282 mg_strcasecmp(const char *s1, const char *s2)
3283 {
3284  int diff;
3285 
3286  do {
3287  diff = lowercase(s1++) - lowercase(s2++);
3288  } while (diff == 0 && s1[-1] != '\0');
3289 
3290  return diff;
3291 }
3292 
3293 
3294 static char *
3295 mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx)
3296 {
3297  char *p;
3298  (void)ctx; /* Avoid Visual Studio warning if USE_SERVER_STATS is not
3299  * defined */
3300 
3301  if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) {
3302  mg_strlcpy(p, ptr, len + 1);
3303  }
3304 
3305  return p;
3306 }
3307 
3308 
3309 static char *
3310 mg_strdup_ctx(const char *str, struct mg_context *ctx)
3311 {
3312  return mg_strndup_ctx(str, strlen(str), ctx);
3313 }
3314 
3315 static char *
3316 mg_strdup(const char *str)
3317 {
3318  return mg_strndup_ctx(str, strlen(str), NULL);
3319 }
3320 
3321 
3322 static const char *
3323 mg_strcasestr(const char *big_str, const char *small_str)
3324 {
3325  size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
3326 
3327  if (big_len >= small_len) {
3328  for (i = 0; i <= (big_len - small_len); i++) {
3329  if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
3330  return big_str + i;
3331  }
3332  }
3333  }
3334 
3335  return NULL;
3336 }
3337 
3338 
3339 /* Return null terminated string of given maximum length.
3340  * Report errors if length is exceeded. */
3341 static void
3342 mg_vsnprintf(const struct mg_connection *conn,
3343  int *truncated,
3344  char *buf,
3345  size_t buflen,
3346  const char *fmt,
3347  va_list ap)
3348 {
3349  int n, ok;
3350 
3351  if (buflen == 0) {
3352  if (truncated) {
3353  *truncated = 1;
3354  }
3355  return;
3356  }
3357 
3358 #if defined(__clang__)
3359 #pragma clang diagnostic push
3360 #pragma clang diagnostic ignored "-Wformat-nonliteral"
3361 /* Using fmt as a non-literal is intended here, since it is mostly called
3362  * indirectly by mg_snprintf */
3363 #endif
3364 
3365  n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
3366  ok = (n >= 0) && ((size_t)n < buflen);
3367 
3368 #if defined(__clang__)
3369 #pragma clang diagnostic pop
3370 #endif
3371 
3372  if (ok) {
3373  if (truncated) {
3374  *truncated = 0;
3375  }
3376  } else {
3377  if (truncated) {
3378  *truncated = 1;
3379  }
3380  mg_cry_internal(conn,
3381  "truncating vsnprintf buffer: [%.*s]",
3382  (int)((buflen > 200) ? 200 : (buflen - 1)),
3383  buf);
3384  n = (int)buflen - 1;
3385  }
3386  buf[n] = '\0';
3387 }
3388 
3389 
3390 static void
3391 mg_snprintf(const struct mg_connection *conn,
3392  int *truncated,
3393  char *buf,
3394  size_t buflen,
3395  const char *fmt,
3396  ...)
3397 {
3398  va_list ap;
3399 
3400  va_start(ap, fmt);
3401  mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
3402  va_end(ap);
3403 }
3404 
3405 
3406 static int
3407 get_option_index(const char *name)
3408 {
3409  int i;
3410 
3411  for (i = 0; config_options[i].name != NULL; i++) {
3412  if (strcmp(config_options[i].name, name) == 0) {
3413  return i;
3414  }
3415  }
3416  return -1;
3417 }
3418 
3419 
3420 const char *
3421 mg_get_option(const struct mg_context *ctx, const char *name)
3422 {
3423  int i;
3424  if ((i = get_option_index(name)) == -1) {
3425  return NULL;
3426  } else if (!ctx || ctx->dd.config[i] == NULL) {
3427  return "";
3428  } else {
3429  return ctx->dd.config[i];
3430  }
3431 }
3432 
3433 #define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly
3434 
3435 struct mg_context *
3436 mg_get_context(const struct mg_connection *conn)
3437 {
3438  return (conn == NULL) ? (struct mg_context *)NULL : (conn->phys_ctx);
3439 }
3440 
3441 
3442 void *
3443 mg_get_user_data(const struct mg_context *ctx)
3444 {
3445  return (ctx == NULL) ? NULL : ctx->user_data;
3446 }
3447 
3448 
3449 void
3450 mg_set_user_connection_data(struct mg_connection *conn, void *data)
3451 {
3452  if (conn != NULL) {
3453  conn->request_info.conn_data = data;
3454  }
3455 }
3456 
3457 
3458 void *
3459 mg_get_user_connection_data(const struct mg_connection *conn)
3460 {
3461  if (conn != NULL) {
3462  return conn->request_info.conn_data;
3463  }
3464  return NULL;
3465 }
3466 
3467 
3468 #if defined(MG_LEGACY_INTERFACE)
3469 /* Deprecated: Use mg_get_server_ports instead. */
3470 size_t
3471 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
3472 {
3473  size_t i;
3474  if (!ctx) {
3475  return 0;
3476  }
3477  for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
3478  ssl[i] = ctx->listening_sockets[i].is_ssl;
3479  ports[i] =
3480 #if defined(USE_IPV6)
3481  (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3482  ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3483  :
3484 #endif
3485  ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3486  }
3487  return i;
3488 }
3489 #endif
3490 
3491 
3492 int
3493 mg_get_server_ports(const struct mg_context *ctx,
3494  int size,
3495  struct mg_server_ports *ports)
3496 {
3497  int i, cnt = 0;
3498 
3499  if (size <= 0) {
3500  return -1;
3501  }
3502  memset(ports, 0, sizeof(*ports) * (size_t)size);
3503  if (!ctx) {
3504  return -1;
3505  }
3506  if (!ctx->listening_sockets) {
3507  return -1;
3508  }
3509 
3510  for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
3511 
3512  ports[cnt].port =
3513 #if defined(USE_IPV6)
3514  (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3515  ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3516  :
3517 #endif
3518  ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3519  ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
3520  ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3521 
3522  if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3523  /* IPv4 */
3524  ports[cnt].protocol = 1;
3525  cnt++;
3526  } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3527  /* IPv6 */
3528  ports[cnt].protocol = 3;
3529  cnt++;
3530  }
3531  }
3532 
3533  return cnt;
3534 }
3535 
3536 
3537 static void
3538 sockaddr_to_string(char *buf, size_t len, const union usa *usa)
3539 {
3540  buf[0] = '\0';
3541 
3542  if (!usa) {
3543  return;
3544  }
3545 
3546  if (usa->sa.sa_family == AF_INET) {
3547  getnameinfo(&usa->sa,
3548  sizeof(usa->sin),
3549  buf,
3550  (unsigned)len,
3551  NULL,
3552  0,
3553  NI_NUMERICHOST);
3554  }
3555 #if defined(USE_IPV6)
3556  else if (usa->sa.sa_family == AF_INET6) {
3557  getnameinfo(&usa->sa,
3558  sizeof(usa->sin6),
3559  buf,
3560  (unsigned)len,
3561  NULL,
3562  0,
3563  NI_NUMERICHOST);
3564  }
3565 #endif
3566 }
3567 
3568 
3569 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
3570  * included in all responses other than 100, 101, 5xx. */
3571 static void
3572 gmt_time_string(char *buf, size_t buf_len, time_t *t)
3573 {
3574 #if !defined(REENTRANT_TIME)
3575  struct tm *tm;
3576 
3577  tm = ((t != NULL) ? gmtime(t) : NULL);
3578  if (tm != NULL) {
3579 #else
3580  struct tm _tm;
3581  struct tm *tm = &_tm;
3582 
3583  if (t != NULL) {
3584  gmtime_r(t, tm);
3585 #endif
3586  strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
3587  } else {
3588  mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
3589  buf[buf_len - 1] = '\0';
3590  }
3591 }
3592 
3593 
3594 /* difftime for struct timespec. Return value is in seconds. */
3595 static double
3596 mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
3597 {
3598  return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
3599  + (double)(ts_now->tv_sec - ts_before->tv_sec);
3600 }
3601 
3602 
3603 #if defined(MG_EXTERNAL_FUNCTION_mg_cry_internal_impl)
3604 static void mg_cry_internal_impl(const struct mg_connection *conn,
3605  const char *func,
3606  unsigned line,
3607  const char *fmt,
3608  va_list ap);
3609 #include "external_mg_cry_internal_impl.inl"
3610 #else
3611 
3612 /* Print error message to the opened error log stream. */
3613 static void
3614 mg_cry_internal_impl(const struct mg_connection *conn,
3615  const char *func,
3616  unsigned line,
3617  const char *fmt,
3618  va_list ap)
3619 {
3620  char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
3621  struct mg_file fi;
3622  time_t timestamp;
3623 
3624  /* Unused, in the RELEASE build */
3625  (void)func;
3626  (void)line;
3627 
3628 #if defined(GCC_DIAGNOSTIC)
3629 #pragma GCC diagnostic push
3630 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
3631 #endif
3632 
3633  IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
3634 
3635 #if defined(GCC_DIAGNOSTIC)
3636 #pragma GCC diagnostic pop
3637 #endif
3638 
3639  buf[sizeof(buf) - 1] = 0;
3640 
3641  DEBUG_TRACE("mg_cry called from %s:%u: %s", func, line, buf);
3642 
3643  if (!conn) {
3644  puts(buf);
3645  return;
3646  }
3647 
3648  /* Do not lock when getting the callback value, here and below.
3649  * I suppose this is fine, since function cannot disappear in the
3650  * same way string option can. */
3651  if ((conn->phys_ctx->callbacks.log_message == NULL)
3652  || (conn->phys_ctx->callbacks.log_message(conn, buf) == 0)) {
3653 
3654  if (conn->dom_ctx->config[ERROR_LOG_FILE] != NULL) {
3655  if (mg_fopen(conn,
3656  conn->dom_ctx->config[ERROR_LOG_FILE],
3657  MG_FOPEN_MODE_APPEND,
3658  &fi)
3659  == 0) {
3660  fi.access.fp = NULL;
3661  }
3662  } else {
3663  fi.access.fp = NULL;
3664  }
3665 
3666  if (fi.access.fp != NULL) {
3667  flockfile(fi.access.fp);
3668  timestamp = time(NULL);
3669 
3670  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
3671  fprintf(fi.access.fp,
3672  "[%010lu] [error] [client %s] ",
3673  (unsigned long)timestamp,
3674  src_addr);
3675 
3676  if (conn->request_info.request_method != NULL) {
3677  fprintf(fi.access.fp,
3678  "%s %s: ",
3679  conn->request_info.request_method,
3680  conn->request_info.request_uri
3681  ? conn->request_info.request_uri
3682  : "");
3683  }
3684 
3685  fprintf(fi.access.fp, "%s", buf);
3686  fputc('\n', fi.access.fp);
3687  fflush(fi.access.fp);
3688  funlockfile(fi.access.fp);
3689  (void)mg_fclose(&fi.access); /* Ignore errors. We can't call
3690  * mg_cry here anyway ;-) */
3691  }
3692  }
3693 }
3694 
3695 #endif /* Externally provided function */
3696 
3697 
3698 static void
3699 mg_cry_internal_wrap(const struct mg_connection *conn,
3700  const char *func,
3701  unsigned line,
3702  const char *fmt,
3703  ...)
3704 {
3705  va_list ap;
3706  va_start(ap, fmt);
3707  mg_cry_internal_impl(conn, func, line, fmt, ap);
3708  va_end(ap);
3709 }
3710 
3711 
3712 void
3713 mg_cry(const struct mg_connection *conn, const char *fmt, ...)
3714 {
3715  va_list ap;
3716  va_start(ap, fmt);
3717  mg_cry_internal_impl(conn, "user", 0, fmt, ap);
3718  va_end(ap);
3719 }
3720 
3721 
3722 #define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal
3723 
3724 
3725 /* Return fake connection structure. Used for logging, if connection
3726  * is not applicable at the moment of logging. */
3727 static struct mg_connection *
3728 fc(struct mg_context *ctx)
3729 {
3730  static struct mg_connection fake_connection;
3731  fake_connection.phys_ctx = ctx;
3732  fake_connection.dom_ctx = &(ctx->dd);
3733  return &fake_connection;
3734 }
3735 
3736 
3737 const char *
3738 mg_version(void)
3739 {
3740  return CIVETWEB_VERSION;
3741 }
3742 
3743 
3744 const struct mg_request_info *
3745 mg_get_request_info(const struct mg_connection *conn)
3746 {
3747  if (!conn) {
3748  return NULL;
3749  }
3750 #if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
3751  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
3752  char txt[16];
3753  struct mg_workerTLS *tls =
3754  (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3755 
3756  sprintf(txt, "%03i", conn->response_info.status_code);
3757  if (strlen(txt) == 3) {
3758  memcpy(tls->txtbuf, txt, 4);
3759  } else {
3760  strcpy(tls->txtbuf, "ERR");
3761  }
3762 
3763  ((struct mg_connection *)conn)->request_info.local_uri =
3764  ((struct mg_connection *)conn)->request_info.request_uri =
3765  tls->txtbuf; /* use thread safe buffer */
3766 
3767  ((struct mg_connection *)conn)->request_info.num_headers =
3768  conn->response_info.num_headers;
3769  memcpy(((struct mg_connection *)conn)->request_info.http_headers,
3770  conn->response_info.http_headers,
3771  sizeof(conn->response_info.http_headers));
3772  } else
3773 #endif
3774  if (conn->connection_type != CONNECTION_TYPE_REQUEST) {
3775  return NULL;
3776  }
3777  return &conn->request_info;
3778 }
3779 
3780 
3781 const struct mg_response_info *
3782 mg_get_response_info(const struct mg_connection *conn)
3783 {
3784  if (!conn) {
3785  return NULL;
3786  }
3787  if (conn->connection_type != CONNECTION_TYPE_RESPONSE) {
3788  return NULL;
3789  }
3790  return &conn->response_info;
3791 }
3792 
3793 
3794 static const char *
3795 get_proto_name(const struct mg_connection *conn)
3796 {
3797 #if defined(__clang__)
3798 #pragma clang diagnostic push
3799 #pragma clang diagnostic ignored "-Wunreachable-code"
3800 /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
3801  * not supported. Clang raises an "unreachable code" warning for parts of ?:
3802  * unreachable, but splitting into four different #ifdef clauses here is more
3803  * complicated.
3804  */
3805 #endif
3806 
3807  const struct mg_request_info *ri = &conn->request_info;
3808 
3809  const char *proto =
3810  (is_websocket_protocol(conn) ? (ri->is_ssl ? "wss" : "ws")
3811  : (ri->is_ssl ? "https" : "http"));
3812 
3813  return proto;
3814 
3815 #if defined(__clang__)
3816 #pragma clang diagnostic pop
3817 #endif
3818 }
3819 
3820 
3821 int
3822 mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
3823 {
3824  if ((buflen < 1) || (buf == 0) || (conn == 0)) {
3825  return -1;
3826  } else {
3827 
3828  int truncated = 0;
3829  const struct mg_request_info *ri = &conn->request_info;
3830 
3831  const char *proto = get_proto_name(conn);
3832 
3833  if (ri->local_uri == NULL) {
3834  return -1;
3835  }
3836 
3837  if ((ri->request_uri != NULL)
3838  && (0 != strcmp(ri->local_uri, ri->request_uri))) {
3839  /* The request uri is different from the local uri.
3840  * This is usually if an absolute URI, including server
3841  * name has been provided. */
3842  mg_snprintf(conn,
3843  &truncated,
3844  buf,
3845  buflen,
3846  "%s://%s",
3847  proto,
3848  ri->request_uri);
3849  if (truncated) {
3850  return -1;
3851  }
3852  return 0;
3853 
3854  } else {
3855 
3856  /* The common case is a relative URI, so we have to
3857  * construct an absolute URI from server name and port */
3858 
3859 #if defined(USE_IPV6)
3860  int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
3861  int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
3862  : htons(conn->client.lsa.sin.sin_port);
3863 #else
3864  int port = htons(conn->client.lsa.sin.sin_port);
3865 #endif
3866  int def_port = ri->is_ssl ? 443 : 80;
3867  int auth_domain_check_enabled =
3868  conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK]
3869  && (!mg_strcasecmp(
3870  conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes"));
3871  const char *server_domain =
3872  conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
3873 
3874  char portstr[16];
3875  char server_ip[48];
3876 
3877  if (port != def_port) {
3878  sprintf(portstr, ":%u", (unsigned)port);
3879  } else {
3880  portstr[0] = 0;
3881  }
3882 
3883  if (!auth_domain_check_enabled || !server_domain) {
3884 
3885  sockaddr_to_string(server_ip,
3886  sizeof(server_ip),
3887  &conn->client.lsa);
3888 
3889  server_domain = server_ip;
3890  }
3891 
3892  mg_snprintf(conn,
3893  &truncated,
3894  buf,
3895  buflen,
3896  "%s://%s%s%s",
3897  proto,
3898  server_domain,
3899  portstr,
3900  ri->local_uri);
3901  if (truncated) {
3902  return -1;
3903  }
3904  return 0;
3905  }
3906  }
3907 }
3908 
3909 /* Skip the characters until one of the delimiters characters found.
3910  * 0-terminate resulting word. Skip the delimiter and following whitespaces.
3911  * Advance pointer to buffer to the next word. Return found 0-terminated
3912  * word.
3913  * Delimiters can be quoted with quotechar. */
3914 static char *
3915 skip_quoted(char **buf,
3916  const char *delimiters,
3917  const char *whitespace,
3918  char quotechar)
3919 {
3920  char *p, *begin_word, *end_word, *end_whitespace;
3921 
3922  begin_word = *buf;
3923  end_word = begin_word + strcspn(begin_word, delimiters);
3924 
3925  /* Check for quotechar */
3926  if (end_word > begin_word) {
3927  p = end_word - 1;
3928  while (*p == quotechar) {
3929  /* While the delimiter is quoted, look for the next delimiter.
3930  */
3931  /* This happens, e.g., in calls from parse_auth_header,
3932  * if the user name contains a " character. */
3933 
3934  /* If there is anything beyond end_word, copy it. */
3935  if (*end_word != '\0') {
3936  size_t end_off = strcspn(end_word + 1, delimiters);
3937  memmove(p, end_word, end_off + 1);
3938  p += end_off; /* p must correspond to end_word - 1 */
3939  end_word += end_off + 1;
3940  } else {
3941  *p = '\0';
3942  break;
3943  }
3944  }
3945  for (p++; p < end_word; p++) {
3946  *p = '\0';
3947  }
3948  }
3949 
3950  if (*end_word == '\0') {
3951  *buf = end_word;
3952  } else {
3953 
3954 #if defined(GCC_DIAGNOSTIC)
3955 /* Disable spurious conversion warning for GCC */
3956 #pragma GCC diagnostic push
3957 #pragma GCC diagnostic ignored "-Wsign-conversion"
3958 #endif /* defined(GCC_DIAGNOSTIC) */
3959 
3960  end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
3961 
3962 #if defined(GCC_DIAGNOSTIC)
3963 #pragma GCC diagnostic pop
3964 #endif /* defined(GCC_DIAGNOSTIC) */
3965 
3966  for (p = end_word; p < end_whitespace; p++) {
3967  *p = '\0';
3968  }
3969 
3970  *buf = end_whitespace;
3971  }
3972 
3973  return begin_word;
3974 }
3975 
3976 
3977 /* Return HTTP header value, or NULL if not found. */
3978 static const char *
3979 get_header(const struct mg_header *hdr, int num_hdr, const char *name)
3980 {
3981  int i;
3982  for (i = 0; i < num_hdr; i++) {
3983  if (!mg_strcasecmp(name, hdr[i].name)) {
3984  return hdr[i].value;
3985  }
3986  }
3987 
3988  return NULL;
3989 }
3990 
3991 
3992 #if defined(USE_WEBSOCKET)
3993 /* Retrieve requested HTTP header multiple values, and return the number of
3994  * found occurrences */
3995 static int
3996 get_req_headers(const struct mg_request_info *ri,
3997  const char *name,
3998  const char **output,
3999  int output_max_size)
4000 {
4001  int i;
4002  int cnt = 0;
4003  if (ri) {
4004  for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) {
4005  if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
4006  output[cnt++] = ri->http_headers[i].value;
4007  }
4008  }
4009  }
4010  return cnt;
4011 }
4012 #endif
4013 
4014 
4015 const char *
4016 mg_get_header(const struct mg_connection *conn, const char *name)
4017 {
4018  if (!conn) {
4019  return NULL;
4020  }
4021 
4022  if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
4023  return get_header(conn->request_info.http_headers,
4024  conn->request_info.num_headers,
4025  name);
4026  }
4027  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
4028  return get_header(conn->response_info.http_headers,
4029  conn->response_info.num_headers,
4030  name);
4031  }
4032  return NULL;
4033 }
4034 
4035 
4036 static const char *
4037 get_http_version(const struct mg_connection *conn)
4038 {
4039  if (!conn) {
4040  return NULL;
4041  }
4042 
4043  if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
4044  return conn->request_info.http_version;
4045  }
4046  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
4047  return conn->response_info.http_version;
4048  }
4049  return NULL;
4050 }
4051 
4052 
4053 /* A helper function for traversing a comma separated list of values.
4054  * It returns a list pointer shifted to the next value, or NULL if the end
4055  * of the list found.
4056  * Value is stored in val vector. If value has form "x=y", then eq_val
4057  * vector is initialized to point to the "y" part, and val vector length
4058  * is adjusted to point only to "x". */
4059 static const char *
4060 next_option(const char *list, struct vec *val, struct vec *eq_val)
4061 {
4062  int end;
4063 
4064 reparse:
4065  if (val == NULL || list == NULL || *list == '\0') {
4066  /* End of the list */
4067  return NULL;
4068  }
4069 
4070  /* Skip over leading LWS */
4071  while (*list == ' ' || *list == '\t')
4072  list++;
4073 
4074  val->ptr = list;
4075  if ((list = strchr(val->ptr, ',')) != NULL) {
4076  /* Comma found. Store length and shift the list ptr */
4077  val->len = ((size_t)(list - val->ptr));
4078  list++;
4079  } else {
4080  /* This value is the last one */
4081  list = val->ptr + strlen(val->ptr);
4082  val->len = ((size_t)(list - val->ptr));
4083  }
4084 
4085  /* Adjust length for trailing LWS */
4086  end = (int)val->len - 1;
4087  while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t')))
4088  end--;
4089  val->len = (size_t)(end + 1);
4090 
4091  if (val->len == 0) {
4092  /* Ignore any empty entries. */
4093  goto reparse;
4094  }
4095 
4096  if (eq_val != NULL) {
4097  /* Value has form "x=y", adjust pointers and lengths
4098  * so that val points to "x", and eq_val points to "y". */
4099  eq_val->len = 0;
4100  eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
4101  if (eq_val->ptr != NULL) {
4102  eq_val->ptr++; /* Skip over '=' character */
4103  eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
4104  val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
4105  }
4106  }
4107 
4108  return list;
4109 }
4110 
4111 
4112 /* A helper function for checking if a comma separated list of values
4113  * contains
4114  * the given option (case insensitvely).
4115  * 'header' can be NULL, in which case false is returned. */
4116 static int
4117 header_has_option(const char *header, const char *option)
4118 {
4119  struct vec opt_vec;
4120  struct vec eq_vec;
4121 
4122  DEBUG_ASSERT(option != NULL);
4123  DEBUG_ASSERT(option[0] != '\0');
4124 
4125  while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
4126  if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
4127  return 1;
4128  }
4129 
4130  return 0;
4131 }
4132 
4133 
4134 /* Perform case-insensitive match of string against pattern */
4135 static ptrdiff_t
4136 match_prefix(const char *pattern, size_t pattern_len, const char *str)
4137 {
4138  const char *or_str;
4139  ptrdiff_t i, j, len, res;
4140 
4141  if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
4142  res = match_prefix(pattern, (size_t)(or_str - pattern), str);
4143  return (res > 0) ? res
4144  : match_prefix(or_str + 1,
4145  (size_t)((pattern + pattern_len)
4146  - (or_str + 1)),
4147  str);
4148  }
4149 
4150  for (i = 0, j = 0; (i < (ptrdiff_t)pattern_len); i++, j++) {
4151  if ((pattern[i] == '?') && (str[j] != '\0')) {
4152  continue;
4153  } else if (pattern[i] == '$') {
4154  return (str[j] == '\0') ? j : -1;
4155  } else if (pattern[i] == '*') {
4156  i++;
4157  if (pattern[i] == '*') {
4158  i++;
4159  len = strlen(str + j);
4160  } else {
4161  len = strcspn(str + j, "/");
4162  }
4163  if (i == (ptrdiff_t)pattern_len) {
4164  return j + len;
4165  }
4166  do {
4167  res = match_prefix(pattern + i, pattern_len - i, str + j + len);
4168  } while (res == -1 && len-- > 0);
4169  return (res == -1) ? -1 : j + res + len;
4170  } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
4171  return -1;
4172  }
4173  }
4174  return (ptrdiff_t)j;
4175 }
4176 
4177 
4178 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
4179  * This function must tolerate situations when connection info is not
4180  * set up, for example if request parsing failed. */
4181 static int
4182 should_keep_alive(const struct mg_connection *conn)
4183 {
4184  const char *http_version;
4185  const char *header;
4186 
4187  /* First satisfy needs of the server */
4188  if ((conn == NULL) || conn->must_close) {
4189  /* Close, if civetweb framework needs to close */
4190  return 0;
4191  }
4192 
4193  if (mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0) {
4194  /* Close, if keep alive is not enabled */
4195  return 0;
4196  }
4197 
4198  /* Check explicit wish of the client */
4199  header = mg_get_header(conn, "Connection");
4200  if (header) {
4201  /* If there is a connection header from the client, obey */
4202  if (header_has_option(header, "keep-alive")) {
4203  return 1;
4204  }
4205  return 0;
4206  }
4207 
4208  /* Use default of the standard */
4209  http_version = get_http_version(conn);
4210  if (http_version && (0 == strcmp(http_version, "1.1"))) {
4211  /* HTTP 1.1 default is keep alive */
4212  return 1;
4213  }
4214 
4215  /* HTTP 1.0 (and earlier) default is to close the connection */
4216  return 0;
4217 }
4218 
4219 
4220 static int
4221 should_decode_url(const struct mg_connection *conn)
4222 {
4223  if (!conn || !conn->dom_ctx) {
4224  return 0;
4225  }
4226 
4227  return (mg_strcasecmp(conn->dom_ctx->config[DECODE_URL], "yes") == 0);
4228 }
4229 
4230 
4231 static const char *
4232 suggest_connection_header(const struct mg_connection *conn)
4233 {
4234  return should_keep_alive(conn) ? "keep-alive" : "close";
4235 }
4236 
4237 
4238 static int
4239 send_no_cache_header(struct mg_connection *conn)
4240 {
4241  /* Send all current and obsolete cache opt-out directives. */
4242  return mg_printf(conn,
4243  "Cache-Control: no-cache, no-store, "
4244  "must-revalidate, private, max-age=0\r\n"
4245  "Pragma: no-cache\r\n"
4246  "Expires: 0\r\n");
4247 }
4248 
4249 
4250 static int
4251 send_static_cache_header(struct mg_connection *conn)
4252 {
4253 #if !defined(NO_CACHING)
4254  /* Read the server config to check how long a file may be cached.
4255  * The configuration is in seconds. */
4256  int max_age = atoi(conn->dom_ctx->config[STATIC_FILE_MAX_AGE]);
4257  if (max_age <= 0) {
4258  /* 0 means "do not cache". All values <0 are reserved
4259  * and may be used differently in the future. */
4260  /* If a file should not be cached, do not only send
4261  * max-age=0, but also pragmas and Expires headers. */
4262  return send_no_cache_header(conn);
4263  }
4264 
4265  /* Use "Cache-Control: max-age" instead of "Expires" header.
4266  * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
4267  /* See also https://www.mnot.net/cache_docs/ */
4268  /* According to RFC 2616, Section 14.21, caching times should not exceed
4269  * one year. A year with 365 days corresponds to 31536000 seconds, a
4270  * leap
4271  * year to 31622400 seconds. For the moment, we just send whatever has
4272  * been configured, still the behavior for >1 year should be considered
4273  * as undefined. */
4274  return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
4275 #else /* NO_CACHING */
4276  return send_no_cache_header(conn);
4277 #endif /* !NO_CACHING */
4278 }
4279 
4280 
4281 static int
4282 send_additional_header(struct mg_connection *conn)
4283 {
4284  int i = 0;
4285  const char *header = conn->dom_ctx->config[ADDITIONAL_HEADER];
4286 
4287 #if !defined(NO_SSL)
4288  if (conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]) {
4289  int max_age = atoi(conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]);
4290  if (max_age >= 0) {
4291  i += mg_printf(conn,
4292  "Strict-Transport-Security: max-age=%u\r\n",
4293  (unsigned)max_age);
4294  }
4295  }
4296 #endif
4297 
4298  if (header && header[0]) {
4299  i += mg_printf(conn, "%s\r\n", header);
4300  }
4301 
4302  return i;
4303 }
4304 
4305 
4306 static void handle_file_based_request(struct mg_connection *conn,
4307  const char *path,
4308  struct mg_file *filep);
4309 
4310 
4311 const char *
4312 mg_get_response_code_text(const struct mg_connection *conn, int response_code)
4313 {
4314  /* See IANA HTTP status code assignment:
4315  * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
4316  */
4317 
4318  switch (response_code) {
4319  /* RFC2616 Section 10.1 - Informational 1xx */
4320  case 100:
4321  return "Continue"; /* RFC2616 Section 10.1.1 */
4322  case 101:
4323  return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
4324  case 102:
4325  return "Processing"; /* RFC2518 Section 10.1 */
4326 
4327  /* RFC2616 Section 10.2 - Successful 2xx */
4328  case 200:
4329  return "OK"; /* RFC2616 Section 10.2.1 */
4330  case 201:
4331  return "Created"; /* RFC2616 Section 10.2.2 */
4332  case 202:
4333  return "Accepted"; /* RFC2616 Section 10.2.3 */
4334  case 203:
4335  return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
4336  case 204:
4337  return "No Content"; /* RFC2616 Section 10.2.5 */
4338  case 205:
4339  return "Reset Content"; /* RFC2616 Section 10.2.6 */
4340  case 206:
4341  return "Partial Content"; /* RFC2616 Section 10.2.7 */
4342  case 207:
4343  return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1
4344  */
4345  case 208:
4346  return "Already Reported"; /* RFC5842 Section 7.1 */
4347 
4348  case 226:
4349  return "IM used"; /* RFC3229 Section 10.4.1 */
4350 
4351  /* RFC2616 Section 10.3 - Redirection 3xx */
4352  case 300:
4353  return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
4354  case 301:
4355  return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
4356  case 302:
4357  return "Found"; /* RFC2616 Section 10.3.3 */
4358  case 303:
4359  return "See Other"; /* RFC2616 Section 10.3.4 */
4360  case 304:
4361  return "Not Modified"; /* RFC2616 Section 10.3.5 */
4362  case 305:
4363  return "Use Proxy"; /* RFC2616 Section 10.3.6 */
4364  case 307:
4365  return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
4366  case 308:
4367  return "Permanent Redirect"; /* RFC7238 Section 3 */
4368 
4369  /* RFC2616 Section 10.4 - Client Error 4xx */
4370  case 400:
4371  return "Bad Request"; /* RFC2616 Section 10.4.1 */
4372  case 401:
4373  return "Unauthorized"; /* RFC2616 Section 10.4.2 */
4374  case 402:
4375  return "Payment Required"; /* RFC2616 Section 10.4.3 */
4376  case 403:
4377  return "Forbidden"; /* RFC2616 Section 10.4.4 */
4378  case 404:
4379  return "Not Found"; /* RFC2616 Section 10.4.5 */
4380  case 405:
4381  return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
4382  case 406:
4383  return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
4384  case 407:
4385  return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
4386  case 408:
4387  return "Request Time-out"; /* RFC2616 Section 10.4.9 */
4388  case 409:
4389  return "Conflict"; /* RFC2616 Section 10.4.10 */
4390  case 410:
4391  return "Gone"; /* RFC2616 Section 10.4.11 */
4392  case 411:
4393  return "Length Required"; /* RFC2616 Section 10.4.12 */
4394  case 412:
4395  return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
4396  case 413:
4397  return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
4398  case 414:
4399  return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
4400  case 415:
4401  return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
4402  case 416:
4403  return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17
4404  */
4405  case 417:
4406  return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
4407 
4408  case 421:
4409  return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
4410  case 422:
4411  return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
4412  * Section 11.2 */
4413  case 423:
4414  return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
4415  case 424:
4416  return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
4417  * Section 11.4 */
4418 
4419  case 426:
4420  return "Upgrade Required"; /* RFC 2817 Section 4 */
4421 
4422  case 428:
4423  return "Precondition Required"; /* RFC 6585, Section 3 */
4424  case 429:
4425  return "Too Many Requests"; /* RFC 6585, Section 4 */
4426 
4427  case 431:
4428  return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
4429 
4430  case 451:
4431  return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
4432  * Section 3 */
4433 
4434  /* RFC2616 Section 10.5 - Server Error 5xx */
4435  case 500:
4436  return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
4437  case 501:
4438  return "Not Implemented"; /* RFC2616 Section 10.5.2 */
4439  case 502:
4440  return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
4441  case 503:
4442  return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
4443  case 504:
4444  return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
4445  case 505:
4446  return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
4447  case 506:
4448  return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
4449  case 507:
4450  return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
4451  * Section 11.5 */
4452  case 508:
4453  return "Loop Detected"; /* RFC5842 Section 7.1 */
4454 
4455  case 510:
4456  return "Not Extended"; /* RFC 2774, Section 7 */
4457  case 511:
4458  return "Network Authentication Required"; /* RFC 6585, Section 6 */
4459 
4460  /* Other status codes, not shown in the IANA HTTP status code
4461  * assignment.
4462  * E.g., "de facto" standards due to common use, ... */
4463  case 418:
4464  return "I am a teapot"; /* RFC2324 Section 2.3.2 */
4465  case 419:
4466  return "Authentication Timeout"; /* common use */
4467  case 420:
4468  return "Enhance Your Calm"; /* common use */
4469  case 440:
4470  return "Login Timeout"; /* common use */
4471  case 509:
4472  return "Bandwidth Limit Exceeded"; /* common use */
4473 
4474  default:
4475  /* This error code is unknown. This should not happen. */
4476  if (conn) {
4477  mg_cry_internal(conn,
4478  "Unknown HTTP response code: %u",
4479  response_code);
4480  }
4481 
4482  /* Return at least a category according to RFC 2616 Section 10. */
4483  if (response_code >= 100 && response_code < 200) {
4484  /* Unknown informational status code */
4485  return "Information";
4486  }
4487  if (response_code >= 200 && response_code < 300) {
4488  /* Unknown success code */
4489  return "Success";
4490  }
4491  if (response_code >= 300 && response_code < 400) {
4492  /* Unknown redirection code */
4493  return "Redirection";
4494  }
4495  if (response_code >= 400 && response_code < 500) {
4496  /* Unknown request error code */
4497  return "Client Error";
4498  }
4499  if (response_code >= 500 && response_code < 600) {
4500  /* Unknown server error code */
4501  return "Server Error";
4502  }
4503 
4504  /* Response code not even within reasonable range */
4505  return "";
4506  }
4507 }
4508 
4509 
4510 static int
4511 mg_send_http_error_impl(struct mg_connection *conn,
4512  int status,
4513  const char *fmt,
4514  va_list args)
4515 {
4516  char errmsg_buf[MG_BUF_LEN];
4517  char path_buf[PATH_MAX];
4518  va_list ap;
4519  int len, i, page_handler_found, scope, truncated, has_body;
4520  char date[64];
4521  time_t curtime = time(NULL);
4522  const char *error_handler = NULL;
4523  struct mg_file error_page_file = STRUCT_FILE_INITIALIZER;
4524  const char *error_page_file_ext, *tstr;
4525  int handled_by_callback = 0;
4526 
4527  const char *status_text = mg_get_response_code_text(conn, status);
4528 
4529  if ((conn == NULL) || (fmt == NULL)) {
4530  return -2;
4531  }
4532 
4533  /* Set status (for log) */
4534  conn->status_code = status;
4535 
4536  /* Errors 1xx, 204 and 304 MUST NOT send a body */
4537  has_body = ((status > 199) && (status != 204) && (status != 304));
4538 
4539  /* Prepare message in buf, if required */
4540  if (has_body
4541  || (!conn->in_error_handler
4542  && (conn->phys_ctx->callbacks.http_error != NULL))) {
4543  /* Store error message in errmsg_buf */
4544  va_copy(ap, args);
4545  mg_vsnprintf(conn, NULL, errmsg_buf, sizeof(errmsg_buf), fmt, ap);
4546  va_end(ap);
4547  /* In a debug build, print all html errors */
4548  DEBUG_TRACE("Error %i - [%s]", status, errmsg_buf);
4549  }
4550 
4551  /* If there is a http_error callback, call it.
4552  * But don't do it recursively, if callback calls mg_send_http_error again.
4553  */
4554  if (!conn->in_error_handler
4555  && (conn->phys_ctx->callbacks.http_error != NULL)) {
4556  /* Mark in_error_handler to avoid recursion and call user callback. */
4557  conn->in_error_handler = 1;
4558  handled_by_callback =
4559  (conn->phys_ctx->callbacks.http_error(conn, status, errmsg_buf)
4560  == 0);
4561  conn->in_error_handler = 0;
4562  }
4563 
4564  if (!handled_by_callback) {
4565  /* Check for recursion */
4566  if (conn->in_error_handler) {
4567  DEBUG_TRACE(
4568  "Recursion when handling error %u - fall back to default",
4569  status);
4570  } else {
4571  /* Send user defined error pages, if defined */
4572  error_handler = conn->dom_ctx->config[ERROR_PAGES];
4573  error_page_file_ext = conn->dom_ctx->config[INDEX_FILES];
4574  page_handler_found = 0;
4575 
4576  if (error_handler != NULL) {
4577  for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
4578  switch (scope) {
4579  case 1: /* Handler for specific error, e.g. 404 error */
4580  mg_snprintf(conn,
4581  &truncated,
4582  path_buf,
4583  sizeof(path_buf) - 32,
4584  "%serror%03u.",
4585  error_handler,
4586  status);
4587  break;
4588  case 2: /* Handler for error group, e.g., 5xx error
4589  * handler
4590  * for all server errors (500-599) */
4591  mg_snprintf(conn,
4592  &truncated,
4593  path_buf,
4594  sizeof(path_buf) - 32,
4595  "%serror%01uxx.",
4596  error_handler,
4597  status / 100);
4598  break;
4599  default: /* Handler for all errors */
4600  mg_snprintf(conn,
4601  &truncated,
4602  path_buf,
4603  sizeof(path_buf) - 32,
4604  "%serror.",
4605  error_handler);
4606  break;
4607  }
4608 
4609  /* String truncation in buf may only occur if
4610  * error_handler is too long. This string is
4611  * from the config, not from a client. */
4612  (void)truncated;
4613 
4614  len = (int)strlen(path_buf);
4615 
4616  tstr = strchr(error_page_file_ext, '.');
4617 
4618  while (tstr) {
4619  for (i = 1;
4620  (i < 32) && (tstr[i] != 0) && (tstr[i] != ',');
4621  i++) {
4622  /* buffer overrun is not possible here, since
4623  * (i < 32) && (len < sizeof(path_buf) - 32)
4624  * ==> (i + len) < sizeof(path_buf) */
4625  path_buf[len + i - 1] = tstr[i];
4626  }
4627  /* buffer overrun is not possible here, since
4628  * (i <= 32) && (len < sizeof(path_buf) - 32)
4629  * ==> (i + len) <= sizeof(path_buf) */
4630  path_buf[len + i - 1] = 0;
4631 
4632  if (mg_stat(conn, path_buf, &error_page_file.stat)) {
4633  DEBUG_TRACE("Check error page %s - found",
4634  path_buf);
4635  page_handler_found = 1;
4636  break;
4637  }
4638  DEBUG_TRACE("Check error page %s - not found",
4639  path_buf);
4640 
4641  tstr = strchr(tstr + i, '.');
4642  }
4643  }
4644  }
4645 
4646  if (page_handler_found) {
4647  conn->in_error_handler = 1;
4648  handle_file_based_request(conn, path_buf, &error_page_file);
4649  conn->in_error_handler = 0;
4650  return 0;
4651  }
4652  }
4653 
4654  /* No custom error page. Send default error page. */
4655  gmt_time_string(date, sizeof(date), &curtime);
4656 
4657  conn->must_close = 1;
4658  mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
4659  send_no_cache_header(conn);
4660  send_additional_header(conn);
4661  if (has_body) {
4662  mg_printf(conn,
4663  "%s",
4664  "Content-Type: text/plain; charset=utf-8\r\n");
4665  }
4666  mg_printf(conn,
4667  "Date: %s\r\n"
4668  "Connection: close\r\n\r\n",
4669  date);
4670 
4671  /* HTTP responses 1xx, 204 and 304 MUST NOT send a body */
4672  if (has_body) {
4673  /* For other errors, send a generic error message. */
4674  mg_printf(conn, "Error %d: %s\n", status, status_text);
4675  mg_write(conn, errmsg_buf, strlen(errmsg_buf));
4676 
4677  } else {
4678  /* No body allowed. Close the connection. */
4679  DEBUG_TRACE("Error %i", status);
4680  }
4681  }
4682  return 0;
4683 }
4684 
4685 
4686 int
4687 mg_send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
4688 {
4689  va_list ap;
4690  int ret;
4691 
4692  va_start(ap, fmt);
4693  ret = mg_send_http_error_impl(conn, status, fmt, ap);
4694  va_end(ap);
4695 
4696  return ret;
4697 }
4698 
4699 
4700 int
4701 mg_send_http_ok(struct mg_connection *conn,
4702  const char *mime_type,
4703  long long content_length)
4704 {
4705  char date[64];
4706  time_t curtime = time(NULL);
4707 
4708  if ((mime_type == NULL) || (*mime_type == 0)) {
4709  /* Parameter error */
4710  return -2;
4711  }
4712 
4713  gmt_time_string(date, sizeof(date), &curtime);
4714 
4715  mg_printf(conn,
4716  "HTTP/1.1 200 OK\r\n"
4717  "Content-Type: %s\r\n"
4718  "Date: %s\r\n"
4719  "Connection: %s\r\n",
4720  mime_type,
4721  date,
4722  suggest_connection_header(conn));
4723 
4724  send_no_cache_header(conn);
4725  send_additional_header(conn);
4726  if (content_length < 0) {
4727  mg_printf(conn, "Transfer-Encoding: chunked\r\n\r\n");
4728  } else {
4729  mg_printf(conn,
4730  "Content-Length: %" UINT64_FMT "\r\n\r\n",
4731  (uint64_t)content_length);
4732  }
4733 
4734  return 0;
4735 }
4736 
4737 
4738 int
4739 mg_send_http_redirect(struct mg_connection *conn,
4740  const char *target_url,
4741  int redirect_code)
4742 {
4743  /* Send a 30x redirect response.
4744  *
4745  * Redirect types (status codes):
4746  *
4747  * Status | Perm/Temp | Method | Version
4748  * 301 | permanent | POST->GET undefined | HTTP/1.0
4749  * 302 | temporary | POST->GET undefined | HTTP/1.0
4750  * 303 | temporary | always use GET | HTTP/1.1
4751  * 307 | temporary | always keep method | HTTP/1.1
4752  * 308 | permanent | always keep method | HTTP/1.1
4753  */
4754  const char *redirect_text;
4755  int ret;
4756  size_t content_len = 0;
4757  char reply[MG_BUF_LEN];
4758 
4759  /* In case redirect_code=0, use 307. */
4760  if (redirect_code == 0) {
4761  redirect_code = 307;
4762  }
4763 
4764  /* In case redirect_code is none of the above, return error. */
4765  if ((redirect_code != 301) && (redirect_code != 302)
4766  && (redirect_code != 303) && (redirect_code != 307)
4767  && (redirect_code != 308)) {
4768  /* Parameter error */
4769  return -2;
4770  }
4771 
4772  /* Get proper text for response code */
4773  redirect_text = mg_get_response_code_text(conn, redirect_code);
4774 
4775  /* If target_url is not defined, redirect to "/". */
4776  if ((target_url == NULL) || (*target_url == 0)) {
4777  target_url = "/";
4778  }
4779 
4780 #if defined(MG_SEND_REDIRECT_BODY)
4781  /* TODO: condition name? */
4782 
4783  /* Prepare a response body with a hyperlink.
4784  *
4785  * According to RFC2616 (and RFC1945 before):
4786  * Unless the request method was HEAD, the entity of the
4787  * response SHOULD contain a short hypertext note with a hyperlink to
4788  * the new URI(s).
4789  *
4790  * However, this response body is not useful in M2M communication.
4791  * Probably the original reason in the RFC was, clients not supporting
4792  * a 30x HTTP redirect could still show the HTML page and let the user
4793  * press the link. Since current browsers support 30x HTTP, the additional
4794  * HTML body does not seem to make sense anymore.
4795  *
4796  * The new RFC7231 (Section 6.4) does no longer recommend it ("SHOULD"),
4797  * but it only notes:
4798  * The server's response payload usually contains a short
4799  * hypertext note with a hyperlink to the new URI(s).
4800  *
4801  * Deactivated by default. If you need the 30x body, set the define.
4802  */
4803  mg_snprintf(
4804  conn,
4805  NULL /* ignore truncation */,
4806  reply,
4807  sizeof(reply),
4808  "<html><head>%s</head><body><a href=\"%s\">%s</a></body></html>",
4809  redirect_text,
4810  target_url,
4811  target_url);
4812  content_len = strlen(reply);
4813 #else
4814  reply[0] = 0;
4815 #endif
4816 
4817  /* Do not send any additional header. For all other options,
4818  * including caching, there are suitable defaults. */
4819  ret = mg_printf(conn,
4820  "HTTP/1.1 %i %s\r\n"
4821  "Location: %s\r\n"
4822  "Content-Length: %u\r\n"
4823  "Connection: %s\r\n\r\n",
4824  redirect_code,
4825  redirect_text,
4826  target_url,
4827  (unsigned int)content_len,
4828  suggest_connection_header(conn));
4829 
4830  /* Send response body */
4831  if (ret > 0) {
4832  /* ... unless it is a HEAD request */
4833  if (0 != strcmp(conn->request_info.request_method, "HEAD")) {
4834  ret = mg_write(conn, reply, content_len);
4835  }
4836  }
4837 
4838  return (ret > 0) ? ret : -1;
4839 }
4840 
4841 
4842 #if defined(_WIN32)
4843 /* Create substitutes for POSIX functions in Win32. */
4844 
4845 #if defined(GCC_DIAGNOSTIC)
4846 /* Show no warning in case system functions are not used. */
4847 #pragma GCC diagnostic push
4848 #pragma GCC diagnostic ignored "-Wunused-function"
4849 #endif
4850 
4851 
4852 FUNCTION_MAY_BE_UNUSED
4853 static int
4854 pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
4855 {
4856  (void)unused;
4857  *mutex = CreateMutex(NULL, FALSE, NULL);
4858  return (*mutex == NULL) ? -1 : 0;
4859 }
4860 
4861 FUNCTION_MAY_BE_UNUSED
4862 static int
4863 pthread_mutex_destroy(pthread_mutex_t *mutex)
4864 {
4865  return (CloseHandle(*mutex) == 0) ? -1 : 0;
4866 }
4867 
4868 
4869 FUNCTION_MAY_BE_UNUSED
4870 static int
4871 pthread_mutex_lock(pthread_mutex_t *mutex)
4872 {
4873  return (WaitForSingleObject(*mutex, (DWORD)INFINITE) == WAIT_OBJECT_0) ? 0
4874  : -1;
4875 }
4876 
4877 
4878 #if defined(ENABLE_UNUSED_PTHREAD_FUNCTIONS)
4879 FUNCTION_MAY_BE_UNUSED
4880 static int
4881 pthread_mutex_trylock(pthread_mutex_t *mutex)
4882 {
4883  switch (WaitForSingleObject(*mutex, 0)) {
4884  case WAIT_OBJECT_0:
4885  return 0;
4886  case WAIT_TIMEOUT:
4887  return -2; /* EBUSY */
4888  }
4889  return -1;
4890 }
4891 #endif
4892 
4893 
4894 FUNCTION_MAY_BE_UNUSED
4895 static int
4896 pthread_mutex_unlock(pthread_mutex_t *mutex)
4897 {
4898  return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
4899 }
4900 
4901 
4902 FUNCTION_MAY_BE_UNUSED
4903 static int
4904 pthread_cond_init(pthread_cond_t *cv, const void *unused)
4905 {
4906  (void)unused;
4907  InitializeCriticalSection(&cv->threadIdSec);
4908  cv->waiting_thread = NULL;
4909  return 0;
4910 }
4911 
4912 
4913 FUNCTION_MAY_BE_UNUSED
4914 static int
4915 pthread_cond_timedwait(pthread_cond_t *cv,
4916  pthread_mutex_t *mutex,
4917  FUNCTION_MAY_BE_UNUSED const struct timespec *abstime)
4918 {
4919  struct mg_workerTLS **ptls,
4920  *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
4921  int ok;
4922  int64_t nsnow, nswaitabs, nswaitrel;
4923  DWORD mswaitrel;
4924 
4925  EnterCriticalSection(&cv->threadIdSec);
4926  /* Add this thread to cv's waiting list */
4927  ptls = &cv->waiting_thread;
4928  for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
4929  ;
4930  tls->next_waiting_thread = NULL;
4931  *ptls = tls;
4932  LeaveCriticalSection(&cv->threadIdSec);
4933 
4934  if (abstime) {
4935  nsnow = mg_get_current_time_ns();
4936  nswaitabs =
4937  (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
4938  nswaitrel = nswaitabs - nsnow;
4939  if (nswaitrel < 0) {
4940  nswaitrel = 0;
4941  }
4942  mswaitrel = (DWORD)(nswaitrel / 1000000);
4943  } else {
4944  mswaitrel = (DWORD)INFINITE;
4945  }
4946 
4947  pthread_mutex_unlock(mutex);
4948  ok = (WAIT_OBJECT_0
4949  == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
4950  if (!ok) {
4951  ok = 1;
4952  EnterCriticalSection(&cv->threadIdSec);
4953  ptls = &cv->waiting_thread;
4954  for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
4955  if (*ptls == tls) {
4956  *ptls = tls->next_waiting_thread;
4957  ok = 0;
4958  break;
4959  }
4960  }
4961  LeaveCriticalSection(&cv->threadIdSec);
4962  if (ok) {
4963  WaitForSingleObject(tls->pthread_cond_helper_mutex,
4964  (DWORD)INFINITE);
4965  }
4966  }
4967  /* This thread has been removed from cv's waiting list */
4968  pthread_mutex_lock(mutex);
4969 
4970  return ok ? 0 : -1;
4971 }
4972 
4973 
4974 FUNCTION_MAY_BE_UNUSED
4975 static int
4976 pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
4977 {
4978  return pthread_cond_timedwait(cv, mutex, NULL);
4979 }
4980 
4981 
4982 FUNCTION_MAY_BE_UNUSED
4983 static int
4984 pthread_cond_signal(pthread_cond_t *cv)
4985 {
4986  HANDLE wkup = NULL;
4987  BOOL ok = FALSE;
4988 
4989  EnterCriticalSection(&cv->threadIdSec);
4990  if (cv->waiting_thread) {
4991  wkup = cv->waiting_thread->pthread_cond_helper_mutex;
4992  cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
4993 
4994  ok = SetEvent(wkup);
4995  DEBUG_ASSERT(ok);
4996  }
4997  LeaveCriticalSection(&cv->threadIdSec);
4998 
4999  return ok ? 0 : 1;
5000 }
5001 
5002 
5003 FUNCTION_MAY_BE_UNUSED
5004 static int
5005 pthread_cond_broadcast(pthread_cond_t *cv)
5006 {
5007  EnterCriticalSection(&cv->threadIdSec);
5008  while (cv->waiting_thread) {
5009  pthread_cond_signal(cv);
5010  }
5011  LeaveCriticalSection(&cv->threadIdSec);
5012 
5013  return 0;
5014 }
5015 
5016 
5017 FUNCTION_MAY_BE_UNUSED
5018 static int
5019 pthread_cond_destroy(pthread_cond_t *cv)
5020 {
5021  EnterCriticalSection(&cv->threadIdSec);
5022  DEBUG_ASSERT(cv->waiting_thread == NULL);
5023  LeaveCriticalSection(&cv->threadIdSec);
5024  DeleteCriticalSection(&cv->threadIdSec);
5025 
5026  return 0;
5027 }
5028 
5029 
5030 #if defined(ALTERNATIVE_QUEUE)
5031 FUNCTION_MAY_BE_UNUSED
5032 static void *
5033 event_create(void)
5034 {
5035  return (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
5036 }
5037 
5038 
5039 FUNCTION_MAY_BE_UNUSED
5040 static int
5041 event_wait(void *eventhdl)
5042 {
5043  int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
5044  return (res == WAIT_OBJECT_0);
5045 }
5046 
5047 
5048 FUNCTION_MAY_BE_UNUSED
5049 static int
5050 event_signal(void *eventhdl)
5051 {
5052  return (int)SetEvent((HANDLE)eventhdl);
5053 }
5054 
5055 
5056 FUNCTION_MAY_BE_UNUSED
5057 static void
5058 event_destroy(void *eventhdl)
5059 {
5060  CloseHandle((HANDLE)eventhdl);
5061 }
5062 #endif
5063 
5064 
5065 #if defined(GCC_DIAGNOSTIC)
5066 /* Enable unused function warning again */
5067 #pragma GCC diagnostic pop
5068 #endif
5069 
5070 
5071 /* For Windows, change all slashes to backslashes in path names. */
5072 static void
5073 change_slashes_to_backslashes(char *path)
5074 {
5075  int i;
5076 
5077  for (i = 0; path[i] != '\0'; i++) {
5078  if (path[i] == '/') {
5079  path[i] = '\\';
5080  }
5081 
5082  /* remove double backslash (check i > 0 to preserve UNC paths,
5083  * like \\server\file.txt) */
5084  if ((path[i] == '\\') && (i > 0)) {
5085  while ((path[i + 1] == '\\') || (path[i + 1] == '/')) {
5086  (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
5087  }
5088  }
5089  }
5090 }
5091 
5092 
5093 static int
5094 mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
5095 {
5096  int diff;
5097 
5098  do {
5099  diff = tolower(*s1) - tolower(*s2);
5100  s1++;
5101  s2++;
5102  } while ((diff == 0) && (s1[-1] != '\0'));
5103 
5104  return diff;
5105 }
5106 
5107 
5108 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
5109  * wbuf and wbuf_len is a target buffer and its length. */
5110 static void
5111 path_to_unicode(const struct mg_connection *conn,
5112  const char *path,
5113  wchar_t *wbuf,
5114  size_t wbuf_len)
5115 {
5116  char buf[PATH_MAX], buf2[PATH_MAX];
5117  wchar_t wbuf2[W_PATH_MAX + 1];
5118  DWORD long_len, err;
5119  int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
5120 
5121  mg_strlcpy(buf, path, sizeof(buf));
5122  change_slashes_to_backslashes(buf);
5123 
5124  /* Convert to Unicode and back. If doubly-converted string does not
5125  * match the original, something is fishy, reject. */
5126  memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
5127  MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
5128  WideCharToMultiByte(
5129  CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
5130  if (strcmp(buf, buf2) != 0) {
5131  wbuf[0] = L'\0';
5132  }
5133 
5134  /* Windows file systems are not case sensitive, but you can still use
5135  * uppercase and lowercase letters (on all modern file systems).
5136  * The server can check if the URI uses the same upper/lowercase
5137  * letters an the file system, effectively making Windows servers
5138  * case sensitive (like Linux servers are). It is still not possible
5139  * to use two files with the same name in different cases on Windows
5140  * (like /a and /A) - this would be possible in Linux.
5141  * As a default, Windows is not case sensitive, but the case sensitive
5142  * file name check can be activated by an additional configuration. */
5143  if (conn) {
5144  if (conn->dom_ctx->config[CASE_SENSITIVE_FILES]
5145  && !mg_strcasecmp(conn->dom_ctx->config[CASE_SENSITIVE_FILES],
5146  "yes")) {
5147  /* Use case sensitive compare function */
5148  fcompare = wcscmp;
5149  }
5150  }
5151  (void)conn; /* conn is currently unused */
5152 
5153 #if !defined(_WIN32_WCE)
5154  /* Only accept a full file path, not a Windows short (8.3) path. */
5155  memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
5156  long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
5157  if (long_len == 0) {
5158  err = GetLastError();
5159  if (err == ERROR_FILE_NOT_FOUND) {
5160  /* File does not exist. This is not always a problem here. */
5161  return;
5162  }
5163  }
5164  if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
5165  /* Short name is used. */
5166  wbuf[0] = L'\0';
5167  }
5168 #else
5169  (void)long_len;
5170  (void)wbuf2;
5171  (void)err;
5172 
5173  if (strchr(path, '~')) {
5174  wbuf[0] = L'\0';
5175  }
5176 #endif
5177 }
5178 
5179 
5180 /* Windows happily opens files with some garbage at the end of file name.
5181  * For example, fopen("a.cgi ", "r") on Windows successfully opens
5182  * "a.cgi", despite one would expect an error back.
5183  * This function returns non-0 if path ends with some garbage. */
5184 static int
5185 path_cannot_disclose_cgi(const char *path)
5186 {
5187  static const char *allowed_last_characters = "_-";
5188  int last = path[strlen(path) - 1];
5189  return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
5190 }
5191 
5192 
5193 static int
5194 mg_stat(const struct mg_connection *conn,
5195  const char *path,
5196  struct mg_file_stat *filep)
5197 {
5198  wchar_t wbuf[W_PATH_MAX];
5199  WIN32_FILE_ATTRIBUTE_DATA info;
5200  time_t creation_time;
5201 
5202  if (!filep) {
5203  return 0;
5204  }
5205  memset(filep, 0, sizeof(*filep));
5206 
5207  if (conn && is_file_in_memory(conn, path)) {
5208  /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
5209  * memset */
5210 
5211  /* Quick fix (for 1.9.x): */
5212  /* mg_stat must fill all fields, also for files in memory */
5213  struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
5214  open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
5215  filep->size = tmp_file.stat.size;
5216  filep->location = 2;
5217  /* TODO: for 1.10: restructure how files in memory are handled */
5218 
5219  /* The "file in memory" feature is a candidate for deletion.
5220  * Please join the discussion at
5221  * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
5222  */
5223 
5224  filep->last_modified = time(NULL); /* TODO */
5225  /* last_modified = now ... assumes the file may change during
5226  * runtime,
5227  * so every mg_fopen call may return different data */
5228  /* last_modified = conn->phys_ctx.start_time;
5229  * May be used it the data does not change during runtime. This
5230  * allows
5231  * browser caching. Since we do not know, we have to assume the file
5232  * in memory may change. */
5233  return 1;
5234  }
5235 
5236  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5237  if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
5238  filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
5239  filep->last_modified =
5240  SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
5241  info.ftLastWriteTime.dwHighDateTime);
5242 
5243  /* On Windows, the file creation time can be higher than the
5244  * modification time, e.g. when a file is copied.
5245  * Since the Last-Modified timestamp is used for caching
5246  * it should be based on the most recent timestamp. */
5247  creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
5248  info.ftCreationTime.dwHighDateTime);
5249  if (creation_time > filep->last_modified) {
5250  filep->last_modified = creation_time;
5251  }
5252 
5253  filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5254  /* If file name is fishy, reset the file structure and return
5255  * error.
5256  * Note it is important to reset, not just return the error, cause
5257  * functions like is_file_opened() check the struct. */
5258  if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
5259  memset(filep, 0, sizeof(*filep));
5260  return 0;
5261  }
5262 
5263  return 1;
5264  }
5265 
5266  return 0;
5267 }
5268 
5269 
5270 static int
5271 mg_remove(const struct mg_connection *conn, const char *path)
5272 {
5273  wchar_t wbuf[W_PATH_MAX];
5274  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5275  return DeleteFileW(wbuf) ? 0 : -1;
5276 }
5277 
5278 
5279 static int
5280 mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
5281 {
5282  wchar_t wbuf[W_PATH_MAX];
5283  (void)mode;
5284  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5285  return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
5286 }
5287 
5288 
5289 /* Create substitutes for POSIX functions in Win32. */
5290 
5291 #if defined(GCC_DIAGNOSTIC)
5292 /* Show no warning in case system functions are not used. */
5293 #pragma GCC diagnostic push
5294 #pragma GCC diagnostic ignored "-Wunused-function"
5295 #endif
5296 
5297 
5298 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
5299 FUNCTION_MAY_BE_UNUSED
5300 static DIR *
5301 mg_opendir(const struct mg_connection *conn, const char *name)
5302 {
5303  DIR *dir = NULL;
5304  wchar_t wpath[W_PATH_MAX];
5305  DWORD attrs;
5306 
5307  if (name == NULL) {
5308  SetLastError(ERROR_BAD_ARGUMENTS);
5309  } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
5310  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5311  } else {
5312  path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
5313  attrs = GetFileAttributesW(wpath);
5314  if ((wcslen(wpath) + 2 < ARRAY_SIZE(wpath)) && (attrs != 0xFFFFFFFF)
5315  && ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
5316  (void)wcscat(wpath, L"\\*");
5317  dir->handle = FindFirstFileW(wpath, &dir->info);
5318  dir->result.d_name[0] = '\0';
5319  } else {
5320  mg_free(dir);
5321  dir = NULL;
5322  }
5323  }
5324 
5325  return dir;
5326 }
5327 
5328 
5329 FUNCTION_MAY_BE_UNUSED
5330 static int
5331 mg_closedir(DIR *dir)
5332 {
5333  int result = 0;
5334 
5335  if (dir != NULL) {
5336  if (dir->handle != INVALID_HANDLE_VALUE)
5337  result = FindClose(dir->handle) ? 0 : -1;
5338 
5339  mg_free(dir);
5340  } else {
5341  result = -1;
5342  SetLastError(ERROR_BAD_ARGUMENTS);
5343  }
5344 
5345  return result;
5346 }
5347 
5348 
5349 FUNCTION_MAY_BE_UNUSED
5350 static struct dirent *
5351 mg_readdir(DIR *dir)
5352 {
5353  struct dirent *result = 0;
5354 
5355  if (dir) {
5356  if (dir->handle != INVALID_HANDLE_VALUE) {
5357  result = &dir->result;
5358  (void)WideCharToMultiByte(CP_UTF8,
5359  0,
5360  dir->info.cFileName,
5361  -1,
5362  result->d_name,
5363  sizeof(result->d_name),
5364  NULL,
5365  NULL);
5366 
5367  if (!FindNextFileW(dir->handle, &dir->info)) {
5368  (void)FindClose(dir->handle);
5369  dir->handle = INVALID_HANDLE_VALUE;
5370  }
5371 
5372  } else {
5373  SetLastError(ERROR_FILE_NOT_FOUND);
5374  }
5375  } else {
5376  SetLastError(ERROR_BAD_ARGUMENTS);
5377  }
5378 
5379  return result;
5380 }
5381 
5382 
5383 #if !defined(HAVE_POLL)
5384 #define POLLIN (1) /* Data ready - read will not block. */
5385 #define POLLPRI (2) /* Priority data ready. */
5386 #define POLLOUT (4) /* Send queue not full - write will not block. */
5387 
5388 FUNCTION_MAY_BE_UNUSED
5389 static int
5390 poll(struct pollfd *pfd, unsigned int n, int milliseconds)
5391 {
5392  struct timeval tv;
5393  fd_set rset;
5394  fd_set wset;
5395  unsigned int i;
5396  int result;
5397  SOCKET maxfd = 0;
5398 
5399  memset(&tv, 0, sizeof(tv));
5400  tv.tv_sec = milliseconds / 1000;
5401  tv.tv_usec = (milliseconds % 1000) * 1000;
5402  FD_ZERO(&rset);
5403  FD_ZERO(&wset);
5404 
5405  for (i = 0; i < n; i++) {
5406  if (pfd[i].events & POLLIN) {
5407  FD_SET((SOCKET)pfd[i].fd, &rset);
5408  } else if (pfd[i].events & POLLOUT) {
5409  FD_SET((SOCKET)pfd[i].fd, &wset);
5410  }
5411  pfd[i].revents = 0;
5412 
5413  if (pfd[i].fd > maxfd) {
5414  maxfd = pfd[i].fd;
5415  }
5416  }
5417 
5418  if ((result = select((int)maxfd + 1, &rset, &wset, NULL, &tv)) > 0) {
5419  for (i = 0; i < n; i++) {
5420  if (FD_ISSET(pfd[i].fd, &rset)) {
5421  pfd[i].revents |= POLLIN;
5422  }
5423  if (FD_ISSET(pfd[i].fd, &wset)) {
5424  pfd[i].revents |= POLLOUT;
5425  }
5426  }
5427  }
5428 
5429  /* We should subtract the time used in select from remaining
5430  * "milliseconds", in particular if called from mg_poll with a
5431  * timeout quantum.
5432  * Unfortunately, the remaining time is not stored in "tv" in all
5433  * implementations, so the result in "tv" must be considered undefined.
5434  * See http://man7.org/linux/man-pages/man2/select.2.html */
5435 
5436  return result;
5437 }
5438 #endif /* HAVE_POLL */
5439 
5440 
5441 #if defined(GCC_DIAGNOSTIC)
5442 /* Enable unused function warning again */
5443 #pragma GCC diagnostic pop
5444 #endif
5445 
5446 
5447 static void
5448 set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
5449 {
5450  (void)conn; /* Unused. */
5451 #if defined(_WIN32_WCE)
5452  (void)sock;
5453 #else
5454  (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
5455 #endif
5456 }
5457 
5458 
5459 int
5460 mg_start_thread(mg_thread_func_t f, void *p)
5461 {
5462 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5463  /* Compile-time option to control stack size, e.g.
5464  * -DUSE_STACK_SIZE=16384
5465  */
5466  return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
5467  == ((uintptr_t)(-1L)))
5468  ? -1
5469  : 0);
5470 #else
5471  return (
5472  (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
5473  ? -1
5474  : 0);
5475 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5476 }
5477 
5478 
5479 /* Start a thread storing the thread context. */
5480 static int
5481 mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
5482  void *p,
5483  pthread_t *threadidptr)
5484 {
5485  uintptr_t uip;
5486  HANDLE threadhandle;
5487  int result = -1;
5488 
5489  uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
5490  threadhandle = (HANDLE)uip;
5491  if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
5492  *threadidptr = threadhandle;
5493  result = 0;
5494  }
5495 
5496  return result;
5497 }
5498 
5499 
5500 /* Wait for a thread to finish. */
5501 static int
5502 mg_join_thread(pthread_t threadid)
5503 {
5504  int result;
5505  DWORD dwevent;
5506 
5507  result = -1;
5508  dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
5509  if (dwevent == WAIT_FAILED) {
5510  DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
5511  } else {
5512  if (dwevent == WAIT_OBJECT_0) {
5513  CloseHandle(threadid);
5514  result = 0;
5515  }
5516  }
5517 
5518  return result;
5519 }
5520 
5521 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
5522 /* If SSL is loaded dynamically, dlopen/dlclose is required. */
5523 /* Create substitutes for POSIX functions in Win32. */
5524 
5525 #if defined(GCC_DIAGNOSTIC)
5526 /* Show no warning in case system functions are not used. */
5527 #pragma GCC diagnostic push
5528 #pragma GCC diagnostic ignored "-Wunused-function"
5529 #endif
5530 
5531 
5532 FUNCTION_MAY_BE_UNUSED
5533 static HANDLE
5534 dlopen(const char *dll_name, int flags)
5535 {
5536  wchar_t wbuf[W_PATH_MAX];
5537  (void)flags;
5538  path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
5539  return LoadLibraryW(wbuf);
5540 }
5541 
5542 
5543 FUNCTION_MAY_BE_UNUSED
5544 static int
5545 dlclose(void *handle)
5546 {
5547  int result;
5548 
5549  if (FreeLibrary((HMODULE)handle) != 0) {
5550  result = 0;
5551  } else {
5552  result = -1;
5553  }
5554 
5555  return result;
5556 }
5557 
5558 
5559 #if defined(GCC_DIAGNOSTIC)
5560 /* Enable unused function warning again */
5561 #pragma GCC diagnostic pop
5562 #endif
5563 
5564 #endif
5565 
5566 
5567 #if !defined(NO_CGI)
5568 #define SIGKILL (0)
5569 
5570 
5571 static int
5572 kill(pid_t pid, int sig_num)
5573 {
5574  (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
5575  (void)CloseHandle((HANDLE)pid);
5576  return 0;
5577 }
5578 
5579 
5580 #if !defined(WNOHANG)
5581 #define WNOHANG (1)
5582 #endif
5583 
5584 
5585 static pid_t
5586 waitpid(pid_t pid, int *status, int flags)
5587 {
5588  DWORD timeout = INFINITE;
5589  DWORD waitres;
5590 
5591  (void)status; /* Currently not used by any client here */
5592 
5593  if ((flags | WNOHANG) == WNOHANG) {
5594  timeout = 0;
5595  }
5596 
5597  waitres = WaitForSingleObject((HANDLE)pid, timeout);
5598  if (waitres == WAIT_OBJECT_0) {
5599  return pid;
5600  }
5601  if (waitres == WAIT_TIMEOUT) {
5602  return 0;
5603  }
5604  return (pid_t)-1;
5605 }
5606 
5607 
5608 static void
5609 trim_trailing_whitespaces(char *s)
5610 {
5611  char *e = s + strlen(s) - 1;
5612  while ((e > s) && isspace(*(unsigned char *)e)) {
5613  *e-- = '\0';
5614  }
5615 }
5616 
5617 
5618 static pid_t
5619 spawn_process(struct mg_connection *conn,
5620  const char *prog,
5621  char *envblk,
5622  char *envp[],
5623  int fdin[2],
5624  int fdout[2],
5625  int fderr[2],
5626  const char *dir)
5627 {
5628  HANDLE me;
5629  char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
5630  cmdline[PATH_MAX], buf[PATH_MAX];
5631  int truncated;
5632  struct mg_file file = STRUCT_FILE_INITIALIZER;
5633  STARTUPINFOA si;
5634  PROCESS_INFORMATION pi = {0};
5635 
5636  (void)envp;
5637 
5638  memset(&si, 0, sizeof(si));
5639  si.cb = sizeof(si);
5640 
5641  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5642  si.wShowWindow = SW_HIDE;
5643 
5644  me = GetCurrentProcess();
5645  DuplicateHandle(me,
5646  (HANDLE)_get_osfhandle(fdin[0]),
5647  me,
5648  &si.hStdInput,
5649  0,
5650  TRUE,
5651  DUPLICATE_SAME_ACCESS);
5652  DuplicateHandle(me,
5653  (HANDLE)_get_osfhandle(fdout[1]),
5654  me,
5655  &si.hStdOutput,
5656  0,
5657  TRUE,
5658  DUPLICATE_SAME_ACCESS);
5659  DuplicateHandle(me,
5660  (HANDLE)_get_osfhandle(fderr[1]),
5661  me,
5662  &si.hStdError,
5663  0,
5664  TRUE,
5665  DUPLICATE_SAME_ACCESS);
5666 
5667  /* Mark handles that should not be inherited. See
5668  * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
5669  */
5670  SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
5671  HANDLE_FLAG_INHERIT,
5672  0);
5673  SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
5674  HANDLE_FLAG_INHERIT,
5675  0);
5676  SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
5677  HANDLE_FLAG_INHERIT,
5678  0);
5679 
5680  /* If CGI file is a script, try to read the interpreter line */
5681  interp = conn->dom_ctx->config[CGI_INTERPRETER];
5682  if (interp == NULL) {
5683  buf[0] = buf[1] = '\0';
5684 
5685  /* Read the first line of the script into the buffer */
5686  mg_snprintf(
5687  conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
5688 
5689  if (truncated) {
5690  pi.hProcess = (pid_t)-1;
5691  goto spawn_cleanup;
5692  }
5693 
5694  if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) {
5695 #if defined(MG_USE_OPEN_FILE)
5696  p = (char *)file.access.membuf;
5697 #else
5698  p = (char *)NULL;
5699 #endif
5700  mg_fgets(buf, sizeof(buf), &file, &p);
5701  (void)mg_fclose(&file.access); /* ignore error on read only file */
5702  buf[sizeof(buf) - 1] = '\0';
5703  }
5704 
5705  if ((buf[0] == '#') && (buf[1] == '!')) {
5706  trim_trailing_whitespaces(buf + 2);
5707  } else {
5708  buf[2] = '\0';
5709  }
5710  interp = buf + 2;
5711  }
5712 
5713  if (interp[0] != '\0') {
5714  GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
5715  interp = full_interp;
5716  }
5717  GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
5718 
5719  if (interp[0] != '\0') {
5720  mg_snprintf(conn,
5721  &truncated,
5722  cmdline,
5723  sizeof(cmdline),
5724  "\"%s\" \"%s\\%s\"",
5725  interp,
5726  full_dir,
5727  prog);
5728  } else {
5729  mg_snprintf(conn,
5730  &truncated,
5731  cmdline,
5732  sizeof(cmdline),
5733  "\"%s\\%s\"",
5734  full_dir,
5735  prog);
5736  }
5737 
5738  if (truncated) {
5739  pi.hProcess = (pid_t)-1;
5740  goto spawn_cleanup;
5741  }
5742 
5743  DEBUG_TRACE("Running [%s]", cmdline);
5744  if (CreateProcessA(NULL,
5745  cmdline,
5746  NULL,
5747  NULL,
5748  TRUE,
5749  CREATE_NEW_PROCESS_GROUP,
5750  envblk,
5751  NULL,
5752  &si,
5753  &pi)
5754  == 0) {
5755  mg_cry_internal(
5756  conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
5757  pi.hProcess = (pid_t)-1;
5758  /* goto spawn_cleanup; */
5759  }
5760 
5761 spawn_cleanup:
5762  (void)CloseHandle(si.hStdOutput);
5763  (void)CloseHandle(si.hStdError);
5764  (void)CloseHandle(si.hStdInput);
5765  if (pi.hThread != NULL) {
5766  (void)CloseHandle(pi.hThread);
5767  }
5768 
5769  return (pid_t)pi.hProcess;
5770 }
5771 #endif /* !NO_CGI */
5772 
5773 
5774 static int
5775 set_blocking_mode(SOCKET sock)
5776 {
5777  unsigned long non_blocking = 0;
5778  return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5779 }
5780 
5781 static int
5782 set_non_blocking_mode(SOCKET sock)
5783 {
5784  unsigned long non_blocking = 1;
5785  return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5786 }
5787 
5788 #else
5789 
5790 static int
5791 mg_stat(const struct mg_connection *conn,
5792  const char *path,
5793  struct mg_file_stat *filep)
5794 {
5795  struct stat st;
5796  if (!filep) {
5797  return 0;
5798  }
5799  memset(filep, 0, sizeof(*filep));
5800 
5801  if (conn && is_file_in_memory(conn, path)) {
5802 
5803  /* Quick fix (for 1.9.x): */
5804  /* mg_stat must fill all fields, also for files in memory */
5805  struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
5806  open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
5807  filep->size = tmp_file.stat.size;
5808  filep->last_modified = time(NULL);
5809  filep->location = 2;
5810  /* TODO: remove legacy "files in memory" feature */
5811 
5812  return 1;
5813  }
5814 
5815  if (0 == stat(path, &st)) {
5816  filep->size = (uint64_t)(st.st_size);
5817  filep->last_modified = st.st_mtime;
5818  filep->is_directory = S_ISDIR(st.st_mode);
5819  return 1;
5820  }
5821 
5822  return 0;
5823 }
5824 
5825 
5826 static void
5827 set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
5828 {
5829  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
5830  if (conn) {
5831  mg_cry_internal(conn,
5832  "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
5833  __func__,
5834  strerror(ERRNO));
5835  }
5836  }
5837 }
5838 
5839 
5840 int
5841 mg_start_thread(mg_thread_func_t func, void *param)
5842 {
5843  pthread_t thread_id;
5844  pthread_attr_t attr;
5845  int result;
5846 
5847  (void)pthread_attr_init(&attr);
5848  (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5849 
5850 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5851  /* Compile-time option to control stack size,
5852  * e.g. -DUSE_STACK_SIZE=16384 */
5853  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5854 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5855 
5856  result = pthread_create(&thread_id, &attr, func, param);
5857  pthread_attr_destroy(&attr);
5858 
5859  return result;
5860 }
5861 
5862 
5863 /* Start a thread storing the thread context. */
5864 static int
5865 mg_start_thread_with_id(mg_thread_func_t func,
5866  void *param,
5867  pthread_t *threadidptr)
5868 {
5869  pthread_t thread_id;
5870  pthread_attr_t attr;
5871  int result;
5872 
5873  (void)pthread_attr_init(&attr);
5874 
5875 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5876  /* Compile-time option to control stack size,
5877  * e.g. -DUSE_STACK_SIZE=16384 */
5878  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5879 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
5880 
5881  result = pthread_create(&thread_id, &attr, func, param);
5882  pthread_attr_destroy(&attr);
5883  if ((result == 0) && (threadidptr != NULL)) {
5884  *threadidptr = thread_id;
5885  }
5886  return result;
5887 }
5888 
5889 
5890 /* Wait for a thread to finish. */
5891 static int
5892 mg_join_thread(pthread_t threadid)
5893 {
5894  int result;
5895 
5896  result = pthread_join(threadid, NULL);
5897  return result;
5898 }
5899 
5900 
5901 #if !defined(NO_CGI)
5902 static pid_t
5903 spawn_process(struct mg_connection *conn,
5904  const char *prog,
5905  char *envblk,
5906  char *envp[],
5907  int fdin[2],
5908  int fdout[2],
5909  int fderr[2],
5910  const char *dir)
5911 {
5912  pid_t pid;
5913  const char *interp;
5914 
5915  (void)envblk;
5916 
5917  if (conn == NULL) {
5918  return 0;
5919  }
5920 
5921  if ((pid = fork()) == -1) {
5922  /* Parent */
5923  mg_send_http_error(conn,
5924  500,
5925  "Error: Creating CGI process\nfork(): %s",
5926  strerror(ERRNO));
5927  } else if (pid == 0) {
5928  /* Child */
5929  if (chdir(dir) != 0) {
5930  mg_cry_internal(
5931  conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
5932  } else if (dup2(fdin[0], 0) == -1) {
5933  mg_cry_internal(conn,
5934  "%s: dup2(%d, 0): %s",
5935  __func__,
5936  fdin[0],
5937  strerror(ERRNO));
5938  } else if (dup2(fdout[1], 1) == -1) {
5939  mg_cry_internal(conn,
5940  "%s: dup2(%d, 1): %s",
5941  __func__,
5942  fdout[1],
5943  strerror(ERRNO));
5944  } else if (dup2(fderr[1], 2) == -1) {
5945  mg_cry_internal(conn,
5946  "%s: dup2(%d, 2): %s",
5947  __func__,
5948  fderr[1],
5949  strerror(ERRNO));
5950  } else {
5951  /* Keep stderr and stdout in two different pipes.
5952  * Stdout will be sent back to the client,
5953  * stderr should go into a server error log. */
5954  (void)close(fdin[0]);
5955  (void)close(fdout[1]);
5956  (void)close(fderr[1]);
5957 
5958  /* Close write end fdin and read end fdout and fderr */
5959  (void)close(fdin[1]);
5960  (void)close(fdout[0]);
5961  (void)close(fderr[0]);
5962 
5963  /* After exec, all signal handlers are restored to their default
5964  * values, with one exception of SIGCHLD. According to
5965  * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler
5966  * will leave unchanged after exec if it was set to be ignored.
5967  * Restore it to default action. */
5968  signal(SIGCHLD, SIG_DFL);
5969 
5970  interp = conn->dom_ctx->config[CGI_INTERPRETER];
5971  if (interp == NULL) {
5972  (void)execle(prog, prog, NULL, envp);
5973  mg_cry_internal(conn,
5974  "%s: execle(%s): %s",
5975  __func__,
5976  prog,
5977  strerror(ERRNO));
5978  } else {
5979  (void)execle(interp, interp, prog, NULL, envp);
5980  mg_cry_internal(conn,
5981  "%s: execle(%s %s): %s",
5982  __func__,
5983  interp,
5984  prog,
5985  strerror(ERRNO));
5986  }
5987  }
5988  exit(EXIT_FAILURE);
5989  }
5990 
5991  return pid;
5992 }
5993 #endif /* !NO_CGI */
5994 
5995 
5996 static int
5997 set_non_blocking_mode(SOCKET sock)
5998 {
5999  int flags = fcntl(sock, F_GETFL, 0);
6000  if (flags < 0) {
6001  return -1;
6002  }
6003 
6004  if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
6005  return -1;
6006  }
6007  return 0;
6008 }
6009 
6010 static int
6011 set_blocking_mode(SOCKET sock)
6012 {
6013  int flags = fcntl(sock, F_GETFL, 0);
6014  if (flags < 0) {
6015  return -1;
6016  }
6017 
6018  if (fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK))) < 0) {
6019  return -1;
6020  }
6021  return 0;
6022 }
6023 #endif /* _WIN32 / else */
6024 
6025 /* End of initial operating system specific define block. */
6026 
6027 
6028 /* Get a random number (independent of C rand function) */
6029 static uint64_t
6030 get_random(void)
6031 {
6032  static uint64_t lfsr = 0; /* Linear feedback shift register */
6033  static uint64_t lcg = 0; /* Linear congruential generator */
6034  uint64_t now = mg_get_current_time_ns();
6035 
6036  if (lfsr == 0) {
6037  /* lfsr will be only 0 if has not been initialized,
6038  * so this code is called only once. */
6039  lfsr = mg_get_current_time_ns();
6040  lcg = mg_get_current_time_ns();
6041  } else {
6042  /* Get the next step of both random number generators. */
6043  lfsr = (lfsr >> 1)
6044  | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
6045  << 63);
6046  lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
6047  }
6048 
6049  /* Combining two pseudo-random number generators and a high resolution
6050  * part
6051  * of the current server time will make it hard (impossible?) to guess
6052  * the
6053  * next number. */
6054  return (lfsr ^ lcg ^ now);
6055 }
6056 
6057 
6058 static int
6059 mg_poll(struct pollfd *pfd,
6060  unsigned int n,
6061  int milliseconds,
6062  volatile int *stop_server)
6063 {
6064  /* Call poll, but only for a maximum time of a few seconds.
6065  * This will allow to stop the server after some seconds, instead
6066  * of having to wait for a long socket timeout. */
6067  int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
6068 
6069  do {
6070  int result;
6071 
6072  if (*stop_server) {
6073  /* Shut down signal */
6074  return -2;
6075  }
6076 
6077  if ((milliseconds >= 0) && (milliseconds < ms_now)) {
6078  ms_now = milliseconds;
6079  }
6080 
6081  result = poll(pfd, n, ms_now);
6082  if (result != 0) {
6083  /* Poll returned either success (1) or error (-1).
6084  * Forward both to the caller. */
6085  return result;
6086  }
6087 
6088  /* Poll returned timeout (0). */
6089  if (milliseconds > 0) {
6090  milliseconds -= ms_now;
6091  }
6092 
6093  } while (milliseconds != 0);
6094 
6095  /* timeout: return 0 */
6096  return 0;
6097 }
6098 
6099 
6100 /* Write data to the IO channel - opened file descriptor, socket or SSL
6101  * descriptor.
6102  * Return value:
6103  * >=0 .. number of bytes successfully written
6104  * -1 .. timeout
6105  * -2 .. error
6106  */
6107 static int
6108 push_inner(struct mg_context *ctx,
6109  FILE *fp,
6110  SOCKET sock,
6111  SSL *ssl,
6112  const char *buf,
6113  int len,
6114  double timeout)
6115 {
6116  uint64_t start = 0, now = 0, timeout_ns = 0;
6117  int n, err;
6118  unsigned ms_wait = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
6119 
6120 #if defined(_WIN32)
6121  typedef int len_t;
6122 #else
6123  typedef size_t len_t;
6124 #endif
6125 
6126  if (timeout > 0) {
6127  now = mg_get_current_time_ns();
6128  start = now;
6129  timeout_ns = (uint64_t)(timeout * 1.0E9);
6130  }
6131 
6132  if (ctx == NULL) {
6133  return -2;
6134  }
6135 
6136 #if defined(NO_SSL)
6137  if (ssl) {
6138  return -2;
6139  }
6140 #endif
6141 
6142  /* Try to read until it succeeds, fails, times out, or the server
6143  * shuts down. */
6144  for (;;) {
6145 
6146 #if !defined(NO_SSL)
6147  if (ssl != NULL) {
6148  n = SSL_write(ssl, buf, len);
6149  if (n <= 0) {
6150  err = SSL_get_error(ssl, n);
6151  if ((err == SSL_ERROR_SYSCALL) && (n == -1)) {
6152  err = ERRNO;
6153  } else if ((err == SSL_ERROR_WANT_READ)
6154  || (err == SSL_ERROR_WANT_WRITE)) {
6155  n = 0;
6156  } else {
6157  DEBUG_TRACE("SSL_write() failed, error %d", err);
6158  return -2;
6159  }
6160  } else {
6161  err = 0;
6162  }
6163  } else
6164 #endif
6165  if (fp != NULL) {
6166  n = (int)fwrite(buf, 1, (size_t)len, fp);
6167  if (ferror(fp)) {
6168  n = -1;
6169  err = ERRNO;
6170  } else {
6171  err = 0;
6172  }
6173  } else {
6174  n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
6175  err = (n < 0) ? ERRNO : 0;
6176 #if defined(_WIN32)
6177  if (err == WSAEWOULDBLOCK) {
6178  err = 0;
6179  n = 0;
6180  }
6181 #else
6182  if (err == EWOULDBLOCK) {
6183  err = 0;
6184  n = 0;
6185  }
6186 #endif
6187  if (n < 0) {
6188  /* shutdown of the socket at client side */
6189  return -2;
6190  }
6191  }
6192 
6193  if (ctx->stop_flag) {
6194  return -2;
6195  }
6196 
6197  if ((n > 0) || ((n == 0) && (len == 0))) {
6198  /* some data has been read, or no data was requested */
6199  return n;
6200  }
6201  if (n < 0) {
6202  /* socket error - check errno */
6203  DEBUG_TRACE("send() failed, error %d", err);
6204 
6205  /* TODO (mid): error handling depending on the error code.
6206  * These codes are different between Windows and Linux.
6207  * Currently there is no problem with failing send calls,
6208  * if there is a reproducible situation, it should be
6209  * investigated in detail.
6210  */
6211  return -2;
6212  }
6213 
6214  /* Only in case n=0 (timeout), repeat calling the write function */
6215 
6216  /* If send failed, wait before retry */
6217  if (fp != NULL) {
6218  /* For files, just wait a fixed time.
6219  * Maybe it helps, maybe not. */
6220  mg_sleep(5);
6221  } else {
6222  /* For sockets, wait for the socket using poll */
6223  struct pollfd pfd[1];
6224  int pollres;
6225 
6226  pfd[0].fd = sock;
6227  pfd[0].events = POLLOUT;
6228  pollres = mg_poll(pfd, 1, (int)(ms_wait), &(ctx->stop_flag));
6229  if (ctx->stop_flag) {
6230  return -2;
6231  }
6232  if (pollres > 0) {
6233  continue;
6234  }
6235  }
6236 
6237  if (timeout > 0) {
6238  now = mg_get_current_time_ns();
6239  if ((now - start) > timeout_ns) {
6240  /* Timeout */
6241  break;
6242  }
6243  }
6244  }
6245 
6246  (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
6247  used */
6248 
6249  return -1;
6250 }
6251 
6252 
6253 static int64_t
6254 push_all(struct mg_context *ctx,
6255  FILE *fp,
6256  SOCKET sock,
6257  SSL *ssl,
6258  const char *buf,
6259  int64_t len)
6260 {
6261  double timeout = -1.0;
6262  int64_t n, nwritten = 0;
6263 
6264  if (ctx == NULL) {
6265  return -1;
6266  }
6267 
6268  if (ctx->dd.config[REQUEST_TIMEOUT]) {
6269  timeout = atoi(ctx->dd.config[REQUEST_TIMEOUT]) / 1000.0;
6270  }
6271 
6272  while ((len > 0) && (ctx->stop_flag == 0)) {
6273  n = push_inner(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
6274  if (n < 0) {
6275  if (nwritten == 0) {
6276  nwritten = n; /* Propagate the error */
6277  }
6278  break;
6279  } else if (n == 0) {
6280  break; /* No more data to write */
6281  } else {
6282  nwritten += n;
6283  len -= n;
6284  }
6285  }
6286 
6287  return nwritten;
6288 }
6289 
6290 
6291 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
6292  * Return value:
6293  * >=0 .. number of bytes successfully read
6294  * -1 .. timeout
6295  * -2 .. error
6296  */
6297 static int
6298 pull_inner(FILE *fp,
6299  struct mg_connection *conn,
6300  char *buf,
6301  int len,
6302  double timeout)
6303 {
6304  int nread, err = 0;
6305 
6306 #if defined(_WIN32)
6307  typedef int len_t;
6308 #else
6309  typedef size_t len_t;
6310 #endif
6311 #if !defined(NO_SSL)
6312  int ssl_pending;
6313 #endif
6314 
6315  /* We need an additional wait loop around this, because in some cases
6316  * with TLSwe may get data from the socket but not from SSL_read.
6317  * In this case we need to repeat at least once.
6318  */
6319 
6320  if (fp != NULL) {
6321 #if !defined(_WIN32_WCE)
6322  /* Use read() instead of fread(), because if we're reading from the
6323  * CGI pipe, fread() may block until IO buffer is filled up. We
6324  * cannot afford to block and must pass all read bytes immediately
6325  * to the client. */
6326  nread = (int)read(fileno(fp), buf, (size_t)len);
6327 #else
6328  /* WinCE does not support CGI pipes */
6329  nread = (int)fread(buf, 1, (size_t)len, fp);
6330 #endif
6331  err = (nread < 0) ? ERRNO : 0;
6332  if ((nread == 0) && (len > 0)) {
6333  /* Should get data, but got EOL */
6334  return -2;
6335  }
6336 
6337 #if !defined(NO_SSL)
6338  } else if ((conn->ssl != NULL)
6339  && ((ssl_pending = SSL_pending(conn->ssl)) > 0)) {
6340  /* We already know there is no more data buffered in conn->buf
6341  * but there is more available in the SSL layer. So don't poll
6342  * conn->client.sock yet. */
6343  if (ssl_pending > len) {
6344  ssl_pending = len;
6345  }
6346  nread = SSL_read(conn->ssl, buf, ssl_pending);
6347  if (nread <= 0) {
6348  err = SSL_get_error(conn->ssl, nread);
6349  if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
6350  err = ERRNO;
6351  } else if ((err == SSL_ERROR_WANT_READ)
6352  || (err == SSL_ERROR_WANT_WRITE)) {
6353  nread = 0;
6354  } else {
6355  DEBUG_TRACE("SSL_read() failed, error %d", err);
6356  return -1;
6357  }
6358  } else {
6359  err = 0;
6360  }
6361 
6362  } else if (conn->ssl != NULL) {
6363 
6364  struct pollfd pfd[1];
6365  int pollres;
6366 
6367  pfd[0].fd = conn->client.sock;
6368  pfd[0].events = POLLIN;
6369  pollres = mg_poll(pfd,
6370  1,
6371  (int)(timeout * 1000.0),
6372  &(conn->phys_ctx->stop_flag));
6373  if (conn->phys_ctx->stop_flag) {
6374  return -2;
6375  }
6376  if (pollres > 0) {
6377  nread = SSL_read(conn->ssl, buf, len);
6378  if (nread <= 0) {
6379  err = SSL_get_error(conn->ssl, nread);
6380  if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
6381  err = ERRNO;
6382  } else if ((err == SSL_ERROR_WANT_READ)
6383  || (err == SSL_ERROR_WANT_WRITE)) {
6384  nread = 0;
6385  } else {
6386  DEBUG_TRACE("SSL_read() failed, error %d", err);
6387  return -2;
6388  }
6389  } else {
6390  err = 0;
6391  }
6392 
6393  } else if (pollres < 0) {
6394  /* Error */
6395  return -2;
6396  } else {
6397  /* pollres = 0 means timeout */
6398  nread = 0;
6399  }
6400 #endif
6401 
6402  } else {
6403  struct pollfd pfd[1];
6404  int pollres;
6405 
6406  pfd[0].fd = conn->client.sock;
6407  pfd[0].events = POLLIN;
6408  pollres = mg_poll(pfd,
6409  1,
6410  (int)(timeout * 1000.0),
6411  &(conn->phys_ctx->stop_flag));
6412  if (conn->phys_ctx->stop_flag) {
6413  return -2;
6414  }
6415  if (pollres > 0) {
6416  nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
6417  err = (nread < 0) ? ERRNO : 0;
6418  if (nread <= 0) {
6419  /* shutdown of the socket at client side */
6420  return -2;
6421  }
6422  } else if (pollres < 0) {
6423  /* error callint poll */
6424  return -2;
6425  } else {
6426  /* pollres = 0 means timeout */
6427  nread = 0;
6428  }
6429  }
6430 
6431  if (conn->phys_ctx->stop_flag) {
6432  return -2;
6433  }
6434 
6435  if ((nread > 0) || ((nread == 0) && (len == 0))) {
6436  /* some data has been read, or no data was requested */
6437  return nread;
6438  }
6439 
6440  if (nread < 0) {
6441 /* socket error - check errno */
6442 #if defined(_WIN32)
6443  if (err == WSAEWOULDBLOCK) {
6444  /* TODO (low): check if this is still required */
6445  /* standard case if called from close_socket_gracefully */
6446  return -2;
6447  } else if (err == WSAETIMEDOUT) {
6448  /* TODO (low): check if this is still required */
6449  /* timeout is handled by the while loop */
6450  return 0;
6451  } else if (err == WSAECONNABORTED) {
6452  /* See https://www.chilkatsoft.com/p/p_299.asp */
6453  return -2;
6454  } else {
6455  DEBUG_TRACE("recv() failed, error %d", err);
6456  return -2;
6457  }
6458 #else
6459  /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
6460  * if the timeout is reached and if the socket was set to non-
6461  * blocking in close_socket_gracefully, so we can not distinguish
6462  * here. We have to wait for the timeout in both cases for now.
6463  */
6464  if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == EINTR)) {
6465  /* TODO (low): check if this is still required */
6466  /* EAGAIN/EWOULDBLOCK:
6467  * standard case if called from close_socket_gracefully
6468  * => should return -1 */
6469  /* or timeout occurred
6470  * => the code must stay in the while loop */
6471 
6472  /* EINTR can be generated on a socket with a timeout set even
6473  * when SA_RESTART is effective for all relevant signals
6474  * (see signal(7)).
6475  * => stay in the while loop */
6476  } else {
6477  DEBUG_TRACE("recv() failed, error %d", err);
6478  return -2;
6479  }
6480 #endif
6481  }
6482 
6483  /* Timeout occurred, but no data available. */
6484  return -1;
6485 }
6486 
6487 
6488 static int
6489 pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
6490 {
6491  int n, nread = 0;
6492  double timeout = -1.0;
6493  uint64_t start_time = 0, now = 0, timeout_ns = 0;
6494 
6495  if (conn->dom_ctx->config[REQUEST_TIMEOUT]) {
6496  timeout = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0;
6497  }
6498  if (timeout >= 0.0) {
6499  start_time = mg_get_current_time_ns();
6500  timeout_ns = (uint64_t)(timeout * 1.0E9);
6501  }
6502 
6503  while ((len > 0) && (conn->phys_ctx->stop_flag == 0)) {
6504  n = pull_inner(fp, conn, buf + nread, len, timeout);
6505  if (n == -2) {
6506  if (nread == 0) {
6507  nread = -1; /* Propagate the error */
6508  }
6509  break;
6510  } else if (n == -1) {
6511  /* timeout */
6512  if (timeout >= 0.0) {
6513  now = mg_get_current_time_ns();
6514  if ((now - start_time) <= timeout_ns) {
6515  continue;
6516  }
6517  }
6518  break;
6519  } else if (n == 0) {
6520  break; /* No more data to read */
6521  } else {
6522  conn->consumed_content += n;
6523  nread += n;
6524  len -= n;
6525  }
6526  }
6527 
6528  return nread;
6529 }
6530 
6531 
6532 static void
6533 discard_unread_request_data(struct mg_connection *conn)
6534 {
6535  char buf[MG_BUF_LEN];
6536  size_t to_read;
6537  int nread;
6538 
6539  if (conn == NULL) {
6540  return;
6541  }
6542 
6543  to_read = sizeof(buf);
6544 
6545  if (conn->is_chunked) {
6546  /* Chunked encoding: 3=chunk read completely
6547  * completely */
6548  while (conn->is_chunked != 3) {
6549  nread = mg_read(conn, buf, to_read);
6550  if (nread <= 0) {
6551  break;
6552  }
6553  }
6554 
6555  } else {
6556  /* Not chunked: content length is known */
6557  while (conn->consumed_content < conn->content_len) {
6558  if (to_read
6559  > (size_t)(conn->content_len - conn->consumed_content)) {
6560  to_read = (size_t)(conn->content_len - conn->consumed_content);
6561  }
6562 
6563  nread = mg_read(conn, buf, to_read);
6564  if (nread <= 0) {
6565  break;
6566  }
6567  }
6568  }
6569 }
6570 
6571 
6572 static int
6573 mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
6574 {
6575  int64_t n, buffered_len, nread;
6576  int64_t len64 =
6577  (int64_t)((len > INT_MAX) ? INT_MAX : len); /* since the return value is
6578  * int, we may not read more
6579  * bytes */
6580  const char *body;
6581 
6582  if (conn == NULL) {
6583  return 0;
6584  }
6585 
6586  /* If Content-Length is not set for a request with body data
6587  * (e.g., a PUT or POST request), we do not know in advance
6588  * how much data should be read. */
6589  if (conn->consumed_content == 0) {
6590  if (conn->is_chunked == 1) {
6591  conn->content_len = len64;
6592  conn->is_chunked = 2;
6593  } else if (conn->content_len == -1) {
6594  /* The body data is completed when the connection
6595  * is closed. */
6596  conn->content_len = INT64_MAX;
6597  conn->must_close = 1;
6598  }
6599  }
6600 
6601  nread = 0;
6602  if (conn->consumed_content < conn->content_len) {
6603  /* Adjust number of bytes to read. */
6604  int64_t left_to_read = conn->content_len - conn->consumed_content;
6605  if (left_to_read < len64) {
6606  /* Do not read more than the total content length of the
6607  * request.
6608  */
6609  len64 = left_to_read;
6610  }
6611 
6612  /* Return buffered data */
6613  buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
6614  - conn->consumed_content;
6615  if (buffered_len > 0) {
6616  if (len64 < buffered_len) {
6617  buffered_len = len64;
6618  }
6619  body = conn->buf + conn->request_len + conn->consumed_content;
6620  memcpy(buf, body, (size_t)buffered_len);
6621  len64 -= buffered_len;
6622  conn->consumed_content += buffered_len;
6623  nread += buffered_len;
6624  buf = (char *)buf + buffered_len;
6625  }
6626 
6627  /* We have returned all buffered data. Read new data from the remote
6628  * socket.
6629  */
6630  if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
6631  nread += n;
6632  } else {
6633  nread = ((nread > 0) ? nread : n);
6634  }
6635  }
6636  return (int)nread;
6637 }
6638 
6639 
6640 static char
6641 mg_getc(struct mg_connection *conn)
6642 {
6643  char c;
6644  if (conn == NULL) {
6645  return 0;
6646  }
6647  if (mg_read_inner(conn, &c, 1) <= 0) {
6648  return (char)0;
6649  }
6650  return c;
6651 }
6652 
6653 
6654 int
6655 mg_read(struct mg_connection *conn, void *buf, size_t len)
6656 {
6657  if (len > INT_MAX) {
6658  len = INT_MAX;
6659  }
6660 
6661  if (conn == NULL) {
6662  return 0;
6663  }
6664 
6665  if (conn->is_chunked) {
6666  size_t all_read = 0;
6667 
6668  while (len > 0) {
6669  if (conn->is_chunked == 3) {
6670  /* No more data left to read */
6671  return 0;
6672  }
6673 
6674  if (conn->chunk_remainder) {
6675  /* copy from the remainder of the last received chunk */
6676  long read_ret;
6677  size_t read_now =
6678  ((conn->chunk_remainder > len) ? (len)
6679  : (conn->chunk_remainder));
6680 
6681  conn->content_len += (int)read_now;
6682  read_ret =
6683  mg_read_inner(conn, (char *)buf + all_read, read_now);
6684 
6685  if (read_ret < 1) {
6686  /* read error */
6687  return -1;
6688  }
6689 
6690  all_read += (size_t)read_ret;
6691  conn->chunk_remainder -= (size_t)read_ret;
6692  len -= (size_t)read_ret;
6693 
6694  if (conn->chunk_remainder == 0) {
6695  /* Add data bytes in the current chunk have been read,
6696  * so we are expecting \r\n now. */
6697  char x1, x2;
6698  conn->content_len += 2;
6699  x1 = mg_getc(conn);
6700  x2 = mg_getc(conn);
6701  if ((x1 != '\r') || (x2 != '\n')) {
6702  /* Protocol violation */
6703  return -1;
6704  }
6705  }
6706 
6707  } else {
6708  /* fetch a new chunk */
6709  int i = 0;
6710  char lenbuf[64];
6711  char *end = 0;
6712  unsigned long chunkSize = 0;
6713 
6714  for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
6715  conn->content_len++;
6716  lenbuf[i] = mg_getc(conn);
6717  if ((i > 0) && (lenbuf[i] == '\r')
6718  && (lenbuf[i - 1] != '\r')) {
6719  continue;
6720  }
6721  if ((i > 1) && (lenbuf[i] == '\n')
6722  && (lenbuf[i - 1] == '\r')) {
6723  lenbuf[i + 1] = 0;
6724  chunkSize = strtoul(lenbuf, &end, 16);
6725  if (chunkSize == 0) {
6726  /* regular end of content */
6727  conn->is_chunked = 3;
6728  }
6729  break;
6730  }
6731  if (!isxdigit(lenbuf[i])) {
6732  /* illegal character for chunk length */
6733  return -1;
6734  }
6735  }
6736  if ((end == NULL) || (*end != '\r')) {
6737  /* chunksize not set correctly */
6738  return -1;
6739  }
6740  if (chunkSize == 0) {
6741  break;
6742  }
6743 
6744  conn->chunk_remainder = chunkSize;
6745  }
6746  }
6747 
6748  return (int)all_read;
6749  }
6750  return mg_read_inner(conn, buf, len);
6751 }
6752 
6753 
6754 int
6755 mg_write(struct mg_connection *conn, const void *buf, size_t len)
6756 {
6757  time_t now;
6758  int64_t n, total, allowed;
6759 
6760  if (conn == NULL) {
6761  return 0;
6762  }
6763 
6764  if (conn->throttle > 0) {
6765  if ((now = time(NULL)) != conn->last_throttle_time) {
6766  conn->last_throttle_time = now;
6767  conn->last_throttle_bytes = 0;
6768  }
6769  allowed = conn->throttle - conn->last_throttle_bytes;
6770  if (allowed > (int64_t)len) {
6771  allowed = (int64_t)len;
6772  }
6773  if ((total = push_all(conn->phys_ctx,
6774  NULL,
6775  conn->client.sock,
6776  conn->ssl,
6777  (const char *)buf,
6778  (int64_t)allowed))
6779  == allowed) {
6780  buf = (const char *)buf + total;
6781  conn->last_throttle_bytes += total;
6782  while ((total < (int64_t)len) && (conn->phys_ctx->stop_flag == 0)) {
6783  allowed = (conn->throttle > ((int64_t)len - total))
6784  ? (int64_t)len - total
6785  : conn->throttle;
6786  if ((n = push_all(conn->phys_ctx,
6787  NULL,
6788  conn->client.sock,
6789  conn->ssl,
6790  (const char *)buf,
6791  (int64_t)allowed))
6792  != allowed) {
6793  break;
6794  }
6795  sleep(1);
6796  conn->last_throttle_bytes = allowed;
6797  conn->last_throttle_time = time(NULL);
6798  buf = (const char *)buf + n;
6799  total += n;
6800  }
6801  }
6802  } else {
6803  total = push_all(conn->phys_ctx,
6804  NULL,
6805  conn->client.sock,
6806  conn->ssl,
6807  (const char *)buf,
6808  (int64_t)len);
6809  }
6810  if (total > 0) {
6811  conn->num_bytes_sent += total;
6812  }
6813  return (int)total;
6814 }
6815 
6816 
6817 /* Send a chunk, if "Transfer-Encoding: chunked" is used */
6818 int
6819 mg_send_chunk(struct mg_connection *conn,
6820  const char *chunk,
6821  unsigned int chunk_len)
6822 {
6823  char lenbuf[16];
6824  size_t lenbuf_len;
6825  int ret;
6826  int t;
6827 
6828  /* First store the length information in a text buffer. */
6829  sprintf(lenbuf, "%x\r\n", chunk_len);
6830  lenbuf_len = strlen(lenbuf);
6831 
6832  /* Then send length information, chunk and terminating \r\n. */
6833  ret = mg_write(conn, lenbuf, lenbuf_len);
6834  if (ret != (int)lenbuf_len) {
6835  return -1;
6836  }
6837  t = ret;
6838 
6839  ret = mg_write(conn, chunk, chunk_len);
6840  if (ret != (int)chunk_len) {
6841  return -1;
6842  }
6843  t += ret;
6844 
6845  ret = mg_write(conn, "\r\n", 2);
6846  if (ret != 2) {
6847  return -1;
6848  }
6849  t += ret;
6850 
6851  return t;
6852 }
6853 
6854 
6855 #if defined(GCC_DIAGNOSTIC)
6856 /* This block forwards format strings to printf implementations,
6857  * so we need to disable the format-nonliteral warning. */
6858 #pragma GCC diagnostic push
6859 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
6860 #endif
6861 
6862 
6863 /* Alternative alloc_vprintf() for non-compliant C runtimes */
6864 static int
6865 alloc_vprintf2(char **buf, const char *fmt, va_list ap)
6866 {
6867  va_list ap_copy;
6868  size_t size = MG_BUF_LEN / 4;
6869  int len = -1;
6870 
6871  *buf = NULL;
6872  while (len < 0) {
6873  if (*buf) {
6874  mg_free(*buf);
6875  }
6876 
6877  size *= 4;
6878  *buf = (char *)mg_malloc(size);
6879  if (!*buf) {
6880  break;
6881  }
6882 
6883  va_copy(ap_copy, ap);
6884  len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
6885  va_end(ap_copy);
6886  (*buf)[size - 1] = 0;
6887  }
6888 
6889  return len;
6890 }
6891 
6892 
6893 /* Print message to buffer. If buffer is large enough to hold the message,
6894  * return buffer. If buffer is to small, allocate large enough buffer on
6895  * heap,
6896  * and return allocated buffer. */
6897 static int
6898 alloc_vprintf(char **out_buf,
6899  char *prealloc_buf,
6900  size_t prealloc_size,
6901  const char *fmt,
6902  va_list ap)
6903 {
6904  va_list ap_copy;
6905  int len;
6906 
6907  /* Windows is not standard-compliant, and vsnprintf() returns -1 if
6908  * buffer is too small. Also, older versions of msvcrt.dll do not have
6909  * _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
6910  * Therefore, we make two passes: on first pass, get required message
6911  * length.
6912  * On second pass, actually print the message. */
6913  va_copy(ap_copy, ap);
6914  len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
6915  va_end(ap_copy);
6916 
6917  if (len < 0) {
6918  /* C runtime is not standard compliant, vsnprintf() returned -1.
6919  * Switch to alternative code path that uses incremental
6920  * allocations.
6921  */
6922  va_copy(ap_copy, ap);
6923  len = alloc_vprintf2(out_buf, fmt, ap_copy);
6924  va_end(ap_copy);
6925 
6926  } else if ((size_t)(len) >= prealloc_size) {
6927  /* The pre-allocated buffer not large enough. */
6928  /* Allocate a new buffer. */
6929  *out_buf = (char *)mg_malloc((size_t)(len) + 1);
6930  if (!*out_buf) {
6931  /* Allocation failed. Return -1 as "out of memory" error. */
6932  return -1;
6933  }
6934  /* Buffer allocation successful. Store the string there. */
6935  va_copy(ap_copy, ap);
6936  IGNORE_UNUSED_RESULT(
6937  vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
6938  va_end(ap_copy);
6939 
6940  } else {
6941  /* The pre-allocated buffer is large enough.
6942  * Use it to store the string and return the address. */
6943  va_copy(ap_copy, ap);
6944  IGNORE_UNUSED_RESULT(
6945  vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
6946  va_end(ap_copy);
6947  *out_buf = prealloc_buf;
6948  }
6949 
6950  return len;
6951 }
6952 
6953 
6954 #if defined(GCC_DIAGNOSTIC)
6955 /* Enable format-nonliteral warning again. */
6956 #pragma GCC diagnostic pop
6957 #endif
6958 
6959 
6960 static int
6961 mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
6962 {
6963  char mem[MG_BUF_LEN];
6964  char *buf = NULL;
6965  int len;
6966 
6967  if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
6968  len = mg_write(conn, buf, (size_t)len);
6969  }
6970  if ((buf != mem) && (buf != NULL)) {
6971  mg_free(buf);
6972  }
6973 
6974  return len;
6975 }
6976 
6977 
6978 int
6979 mg_printf(struct mg_connection *conn, const char *fmt, ...)
6980 {
6981  va_list ap;
6982  int result;
6983 
6984  va_start(ap, fmt);
6985  result = mg_vprintf(conn, fmt, ap);
6986  va_end(ap);
6987 
6988  return result;
6989 }
6990 
6991 
6992 int
6993 mg_url_decode(const char *src,
6994  int src_len,
6995  char *dst,
6996  int dst_len,
6997  int is_form_url_encoded)
6998 {
6999  int i, j, a, b;
7000 #define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W'))
7001 
7002  for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
7003  if ((i < src_len - 2) && (src[i] == '%')
7004  && isxdigit(*(const unsigned char *)(src + i + 1))
7005  && isxdigit(*(const unsigned char *)(src + i + 2))) {
7006  a = tolower(*(const unsigned char *)(src + i + 1));
7007  b = tolower(*(const unsigned char *)(src + i + 2));
7008  dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
7009  i += 2;
7010  } else if (is_form_url_encoded && (src[i] == '+')) {
7011  dst[j] = ' ';
7012  } else {
7013  dst[j] = src[i];
7014  }
7015  }
7016 
7017  dst[j] = '\0'; /* Null-terminate the destination */
7018 
7019  return (i >= src_len) ? j : -1;
7020 }
7021 
7022 
7023 int
7024 mg_get_var(const char *data,
7025  size_t data_len,
7026  const char *name,
7027  char *dst,
7028  size_t dst_len)
7029 {
7030  return mg_get_var2(data, data_len, name, dst, dst_len, 0);
7031 }
7032 
7033 
7034 int
7035 mg_get_var2(const char *data,
7036  size_t data_len,
7037  const char *name,
7038  char *dst,
7039  size_t dst_len,
7040  size_t occurrence)
7041 {
7042  const char *p, *e, *s;
7043  size_t name_len;
7044  int len;
7045 
7046  if ((dst == NULL) || (dst_len == 0)) {
7047  len = -2;
7048  } else if ((data == NULL) || (name == NULL) || (data_len == 0)) {
7049  len = -1;
7050  dst[0] = '\0';
7051  } else {
7052  name_len = strlen(name);
7053  e = data + data_len;
7054  len = -1;
7055  dst[0] = '\0';
7056 
7057  /* data is "var1=val1&var2=val2...". Find variable first */
7058  for (p = data; p + name_len < e; p++) {
7059  if (((p == data) || (p[-1] == '&')) && (p[name_len] == '=')
7060  && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
7061  /* Point p to variable value */
7062  p += name_len + 1;
7063 
7064  /* Point s to the end of the value */
7065  s = (const char *)memchr(p, '&', (size_t)(e - p));
7066  if (s == NULL) {
7067  s = e;
7068  }
7069  DEBUG_ASSERT(s >= p);
7070  if (s < p) {
7071  return -3;
7072  }
7073 
7074  /* Decode variable into destination buffer */
7075  len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
7076 
7077  /* Redirect error code from -1 to -2 (destination buffer too
7078  * small). */
7079  if (len == -1) {
7080  len = -2;
7081  }
7082  break;
7083  }
7084  }
7085  }
7086 
7087  return len;
7088 }
7089 
7090 
7091 /* HCP24: some changes to compare hole var_name */
7092 int
7093 mg_get_cookie(const char *cookie_header,
7094  const char *var_name,
7095  char *dst,
7096  size_t dst_size)
7097 {
7098  const char *s, *p, *end;
7099  int name_len, len = -1;
7100 
7101  if ((dst == NULL) || (dst_size == 0)) {
7102  return -2;
7103  }
7104 
7105  dst[0] = '\0';
7106  if ((var_name == NULL) || ((s = cookie_header) == NULL)) {
7107  return -1;
7108  }
7109 
7110  name_len = (int)strlen(var_name);
7111  end = s + strlen(s);
7112  for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
7113  if (s[name_len] == '=') {
7114  /* HCP24: now check is it a substring or a full cookie name */
7115  if ((s == cookie_header) || (s[-1] == ' ')) {
7116  s += name_len + 1;
7117  if ((p = strchr(s, ' ')) == NULL) {
7118  p = end;
7119  }
7120  if (p[-1] == ';') {
7121  p--;
7122  }
7123  if ((*s == '"') && (p[-1] == '"') && (p > s + 1)) {
7124  s++;
7125  p--;
7126  }
7127  if ((size_t)(p - s) < dst_size) {
7128  len = (int)(p - s);
7129  mg_strlcpy(dst, s, (size_t)len + 1);
7130  } else {
7131  len = -3;
7132  }
7133  break;
7134  }
7135  }
7136  }
7137  return len;
7138 }
7139 
7140 
7141 #if defined(USE_WEBSOCKET) || defined(USE_LUA)
7142 static void
7143 base64_encode(const unsigned char *src, int src_len, char *dst)
7144 {
7145  static const char *b64 =
7146  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7147  int i, j, a, b, c;
7148 
7149  for (i = j = 0; i < src_len; i += 3) {
7150  a = src[i];
7151  b = ((i + 1) >= src_len) ? 0 : src[i + 1];
7152  c = ((i + 2) >= src_len) ? 0 : src[i + 2];
7153 
7154  dst[j++] = b64[a >> 2];
7155  dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
7156  if (i + 1 < src_len) {
7157  dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
7158  }
7159  if (i + 2 < src_len) {
7160  dst[j++] = b64[c & 63];
7161  }
7162  }
7163  while (j % 4 != 0) {
7164  dst[j++] = '=';
7165  }
7166  dst[j++] = '\0';
7167 }
7168 #endif
7169 
7170 
7171 #if defined(USE_LUA)
7172 static unsigned char
7173 b64reverse(char letter)
7174 {
7175  if ((letter >= 'A') && (letter <= 'Z')) {
7176  return letter - 'A';
7177  }
7178  if ((letter >= 'a') && (letter <= 'z')) {
7179  return letter - 'a' + 26;
7180  }
7181  if ((letter >= '0') && (letter <= '9')) {
7182  return letter - '0' + 52;
7183  }
7184  if (letter == '+') {
7185  return 62;
7186  }
7187  if (letter == '/') {
7188  return 63;
7189  }
7190  if (letter == '=') {
7191  return 255; /* normal end */
7192  }
7193  return 254; /* error */
7194 }
7195 
7196 
7197 static int
7198 base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
7199 {
7200  int i;
7201  unsigned char a, b, c, d;
7202 
7203  *dst_len = 0;
7204 
7205  for (i = 0; i < src_len; i += 4) {
7206  a = b64reverse(src[i]);
7207  if (a >= 254) {
7208  return i;
7209  }
7210 
7211  b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
7212  if (b >= 254) {
7213  return i + 1;
7214  }
7215 
7216  c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
7217  if (c == 254) {
7218  return i + 2;
7219  }
7220 
7221  d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
7222  if (d == 254) {
7223  return i + 3;
7224  }
7225 
7226  dst[(*dst_len)++] = (a << 2) + (b >> 4);
7227  if (c != 255) {
7228  dst[(*dst_len)++] = (b << 4) + (c >> 2);
7229  if (d != 255) {
7230  dst[(*dst_len)++] = (c << 6) + d;
7231  }
7232  }
7233  }
7234  return -1;
7235 }
7236 #endif
7237 
7238 
7239 static int
7240 is_put_or_delete_method(const struct mg_connection *conn)
7241 {
7242  if (conn) {
7243  const char *s = conn->request_info.request_method;
7244  return (s != NULL)
7245  && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
7246  || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
7247  }
7248  return 0;
7249 }
7250 
7251 
7252 #if !defined(NO_FILES)
7253 static int
7254 extention_matches_script(
7255  struct mg_connection *conn, /* in: request (must be valid) */
7256  const char *filename /* in: filename (must be valid) */
7257 )
7258 {
7259 #if !defined(NO_CGI)
7260  if (match_prefix(conn->dom_ctx->config[CGI_EXTENSIONS],
7261  strlen(conn->dom_ctx->config[CGI_EXTENSIONS]),
7262  filename)
7263  > 0) {
7264  return 1;
7265  }
7266 #endif
7267 #if defined(USE_LUA)
7268  if (match_prefix(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS],
7269  strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS]),
7270  filename)
7271  > 0) {
7272  return 1;
7273  }
7274 #endif
7275 #if defined(USE_DUKTAPE)
7276  if (match_prefix(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
7277  strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
7278  filename)
7279  > 0) {
7280  return 1;
7281  }
7282 #endif
7283  /* filename and conn could be unused, if all preocessor conditions
7284  * are false (no script language supported). */
7285  (void)filename;
7286  (void)conn;
7287 
7288  return 0;
7289 }
7290 
7291 
7292 /* For given directory path, substitute it to valid index file.
7293  * Return 1 if index file has been found, 0 if not found.
7294  * If the file is found, it's stats is returned in stp. */
7295 static int
7296 substitute_index_file(struct mg_connection *conn,
7297  char *path,
7298  size_t path_len,
7299  struct mg_file_stat *filestat)
7300 {
7301  const char *list = conn->dom_ctx->config[INDEX_FILES];
7302  struct vec filename_vec;
7303  size_t n = strlen(path);
7304  int found = 0;
7305 
7306  /* The 'path' given to us points to the directory. Remove all trailing
7307  * directory separator characters from the end of the path, and
7308  * then append single directory separator character. */
7309  while ((n > 0) && (path[n - 1] == '/')) {
7310  n--;
7311  }
7312  path[n] = '/';
7313 
7314  /* Traverse index files list. For each entry, append it to the given
7315  * path and see if the file exists. If it exists, break the loop */
7316  while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7317  /* Ignore too long entries that may overflow path buffer */
7318  if ((filename_vec.len + 1) > (path_len - (n + 1))) {
7319  continue;
7320  }
7321 
7322  /* Prepare full path to the index file */
7323  mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7324 
7325  /* Does it exist? */
7326  if (mg_stat(conn, path, filestat)) {
7327  /* Yes it does, break the loop */
7328  found = 1;
7329  break;
7330  }
7331  }
7332 
7333  /* If no index file exists, restore directory path */
7334  if (!found) {
7335  path[n] = '\0';
7336  }
7337 
7338  return found;
7339 }
7340 #endif
7341 
7342 
7343 static void
7344 interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
7345  char *filename, /* out: filename */
7346  size_t filename_buf_len, /* in: size of filename buffer */
7347  struct mg_file_stat *filestat, /* out: file status structure */
7348  int *is_found, /* out: file found (directly) */
7349  int *is_script_resource, /* out: handled by a script? */
7350  int *is_websocket_request, /* out: websocket connetion? */
7351  int *is_put_or_delete_request /* out: put/delete a file? */
7352 )
7353 {
7354  char const *accept_encoding;
7355 
7356 #if !defined(NO_FILES)
7357  const char *uri = conn->request_info.local_uri;
7358  const char *root = conn->dom_ctx->config[DOCUMENT_ROOT];
7359  const char *rewrite;
7360  struct vec a, b;
7361  ptrdiff_t match_len;
7362  char gz_path[PATH_MAX];
7363  int truncated;
7364 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
7365  char *tmp_str;
7366  size_t tmp_str_len, sep_pos;
7367  int allow_substitute_script_subresources;
7368 #endif
7369 #else
7370  (void)filename_buf_len; /* unused if NO_FILES is defined */
7371 #endif
7372 
7373  /* Step 1: Set all initially unknown outputs to zero */
7374  memset(filestat, 0, sizeof(*filestat));
7375  *filename = 0;
7376  *is_found = 0;
7377  *is_script_resource = 0;
7378 
7379  /* Step 2: Check if the request attempts to modify the file system */
7380  *is_put_or_delete_request = is_put_or_delete_method(conn);
7381 
7382 /* Step 3: Check if it is a websocket request, and modify the document
7383  * root if required */
7384 #if defined(USE_WEBSOCKET)
7385  *is_websocket_request = is_websocket_protocol(conn);
7386 #if !defined(NO_FILES)
7387  if (*is_websocket_request && conn->dom_ctx->config[WEBSOCKET_ROOT]) {
7388  root = conn->dom_ctx->config[WEBSOCKET_ROOT];
7389  }
7390 #endif /* !NO_FILES */
7391 #else /* USE_WEBSOCKET */
7392  *is_websocket_request = 0;
7393 #endif /* USE_WEBSOCKET */
7394 
7395  /* Step 4: Check if gzip encoded response is allowed */
7396  conn->accept_gzip = 0;
7397  if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
7398  if (strstr(accept_encoding, "gzip") != NULL) {
7399  conn->accept_gzip = 1;
7400  }
7401  }
7402 
7403 #if !defined(NO_FILES)
7404  /* Step 5: If there is no root directory, don't look for files. */
7405  /* Note that root == NULL is a regular use case here. This occurs,
7406  * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
7407  * config is not required. */
7408  if (root == NULL) {
7409  /* all file related outputs have already been set to 0, just return
7410  */
7411  return;
7412  }
7413 
7414  /* Step 6: Determine the local file path from the root path and the
7415  * request uri. */
7416  /* Using filename_buf_len - 1 because memmove() for PATH_INFO may shift
7417  * part of the path one byte on the right. */
7418  mg_snprintf(
7419  conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
7420 
7421  if (truncated) {
7422  goto interpret_cleanup;
7423  }
7424 
7425  /* Step 7: URI rewriting */
7426  rewrite = conn->dom_ctx->config[URL_REWRITE_PATTERN];
7427  while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
7428  if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
7429  mg_snprintf(conn,
7430  &truncated,
7431  filename,
7432  filename_buf_len - 1,
7433  "%.*s%s",
7434  (int)b.len,
7435  b.ptr,
7436  uri + match_len);
7437  break;
7438  }
7439  }
7440 
7441  if (truncated) {
7442  goto interpret_cleanup;
7443  }
7444 
7445  /* Step 8: Check if the file exists at the server */
7446  /* Local file path and name, corresponding to requested URI
7447  * is now stored in "filename" variable. */
7448  if (mg_stat(conn, filename, filestat)) {
7449  int uri_len = (int)strlen(uri);
7450  int is_uri_end_slash = (uri_len > 0) && (uri[uri_len - 1] == '/');
7451 
7452  /* 8.1: File exists. */
7453  *is_found = 1;
7454 
7455  /* 8.2: Check if it is a script type. */
7456  if (extention_matches_script(conn, filename)) {
7457  /* The request addresses a CGI resource, Lua script or
7458  * server-side javascript.
7459  * The URI corresponds to the script itself (like
7460  * /path/script.cgi), and there is no additional resource
7461  * path (like /path/script.cgi/something).
7462  * Requests that modify (replace or delete) a resource, like
7463  * PUT and DELETE requests, should replace/delete the script
7464  * file.
7465  * Requests that read or write from/to a resource, like GET and
7466  * POST requests, should call the script and return the
7467  * generated response. */
7468  *is_script_resource = (!*is_put_or_delete_request);
7469  }
7470 
7471  /* 8.3: If the request target is a directory, there could be
7472  * a substitute file (index.html, index.cgi, ...). */
7473  if (filestat->is_directory && is_uri_end_slash) {
7474  /* Use a local copy here, since substitute_index_file will
7475  * change the content of the file status */
7476  struct mg_file_stat tmp_filestat;
7477  memset(&tmp_filestat, 0, sizeof(tmp_filestat));
7478 
7479  if (substitute_index_file(
7480  conn, filename, filename_buf_len, &tmp_filestat)) {
7481 
7482  /* Substitute file found. Copy stat to the output, then
7483  * check if the file is a script file */
7484  *filestat = tmp_filestat;
7485 
7486  if (extention_matches_script(conn, filename)) {
7487  /* Substitute file is a script file */
7488  *is_script_resource = 1;
7489  } else {
7490  /* Substitute file is a regular file */
7491  *is_script_resource = 0;
7492  *is_found = (mg_stat(conn, filename, filestat) ? 1 : 0);
7493  }
7494  }
7495  /* If there is no substitute file, the server could return
7496  * a directory listing in a later step */
7497  }
7498  return;
7499  }
7500 
7501  /* Step 9: Check for zipped files: */
7502  /* If we can't find the actual file, look for the file
7503  * with the same name but a .gz extension. If we find it,
7504  * use that and set the gzipped flag in the file struct
7505  * to indicate that the response need to have the content-
7506  * encoding: gzip header.
7507  * We can only do this if the browser declares support. */
7508  if (conn->accept_gzip) {
7509  mg_snprintf(
7510  conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
7511 
7512  if (truncated) {
7513  goto interpret_cleanup;
7514  }
7515 
7516  if (mg_stat(conn, gz_path, filestat)) {
7517  if (filestat) {
7518  filestat->is_gzipped = 1;
7519  *is_found = 1;
7520  }
7521  /* Currently gz files can not be scripts. */
7522  return;
7523  }
7524  }
7525 
7526 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
7527  /* Step 10: Script resources may handle sub-resources */
7528  /* Support PATH_INFO for CGI scripts. */
7529  tmp_str_len = strlen(filename);
7530  tmp_str = (char *)mg_malloc_ctx(tmp_str_len + PATH_MAX + 1, conn->phys_ctx);
7531  if (!tmp_str) {
7532  /* Out of memory */
7533  goto interpret_cleanup;
7534  }
7535  memcpy(tmp_str, filename, tmp_str_len + 1);
7536 
7537  /* Check config, if index scripts may have sub-resources */
7538  allow_substitute_script_subresources =
7539  !mg_strcasecmp(conn->dom_ctx->config[ALLOW_INDEX_SCRIPT_SUB_RES],
7540  "yes");
7541 
7542  sep_pos = tmp_str_len;
7543  while (sep_pos > 0) {
7544  sep_pos--;
7545  if (tmp_str[sep_pos] == '/') {
7546  int is_script = 0, does_exist = 0;
7547 
7548  tmp_str[sep_pos] = 0;
7549  if (tmp_str[0]) {
7550  is_script = extention_matches_script(conn, tmp_str);
7551  does_exist = mg_stat(conn, tmp_str, filestat);
7552  }
7553 
7554  if (does_exist && is_script) {
7555  filename[sep_pos] = 0;
7556  memmove(filename + sep_pos + 2,
7557  filename + sep_pos + 1,
7558  strlen(filename + sep_pos + 1) + 1);
7559  conn->path_info = filename + sep_pos + 1;
7560  filename[sep_pos + 1] = '/';
7561  *is_script_resource = 1;
7562  *is_found = 1;
7563  break;
7564  }
7565 
7566  if (allow_substitute_script_subresources) {
7567  if (substitute_index_file(
7568  conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
7569 
7570  /* some intermediate directory has an index file */
7571  if (extention_matches_script(conn, tmp_str)) {
7572 
7573  char *tmp_str2;
7574 
7575  DEBUG_TRACE("Substitute script %s serving path %s",
7576  tmp_str,
7577  filename);
7578 
7579  /* this index file is a script */
7580  tmp_str2 = mg_strdup_ctx(filename + sep_pos + 1,
7581  conn->phys_ctx);
7582  mg_snprintf(conn,
7583  &truncated,
7584  filename,
7585  filename_buf_len,
7586  "%s//%s",
7587  tmp_str,
7588  tmp_str2);
7589  mg_free(tmp_str2);
7590 
7591  if (truncated) {
7592  mg_free(tmp_str);
7593  goto interpret_cleanup;
7594  }
7595  sep_pos = strlen(tmp_str);
7596  filename[sep_pos] = 0;
7597  conn->path_info = filename + sep_pos + 1;
7598  *is_script_resource = 1;
7599  *is_found = 1;
7600  break;
7601 
7602  } else {
7603 
7604  DEBUG_TRACE("Substitute file %s serving path %s",
7605  tmp_str,
7606  filename);
7607 
7608  /* non-script files will not have sub-resources */
7609  filename[sep_pos] = 0;
7610  conn->path_info = 0;
7611  *is_script_resource = 0;
7612  *is_found = 0;
7613  break;
7614  }
7615  }
7616  }
7617 
7618  tmp_str[sep_pos] = '/';
7619  }
7620  }
7621 
7622  mg_free(tmp_str);
7623 
7624 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
7625 #endif /* !defined(NO_FILES) */
7626  return;
7627 
7628 #if !defined(NO_FILES)
7629 /* Reset all outputs */
7630 interpret_cleanup:
7631  memset(filestat, 0, sizeof(*filestat));
7632  *filename = 0;
7633  *is_found = 0;
7634  *is_script_resource = 0;
7635  *is_websocket_request = 0;
7636  *is_put_or_delete_request = 0;
7637 #endif /* !defined(NO_FILES) */
7638 }
7639 
7640 
7641 /* Check whether full request is buffered. Return:
7642  * -1 if request or response is malformed
7643  * 0 if request or response is not yet fully buffered
7644  * >0 actual request length, including last \r\n\r\n */
7645 static int
7646 get_http_header_len(const char *buf, int buflen)
7647 {
7648  int i;
7649  for (i = 0; i < buflen; i++) {
7650  /* Do an unsigned comparison in some conditions below */
7651  const unsigned char c = ((const unsigned char *)buf)[i];
7652 
7653  if ((c < 128) && ((char)c != '\r') && ((char)c != '\n')
7654  && !isprint(c)) {
7655  /* abort scan as soon as one malformed character is found */
7656  return -1;
7657  }
7658 
7659  if (i < buflen - 1) {
7660  if ((buf[i] == '\n') && (buf[i + 1] == '\n')) {
7661  /* Two newline, no carriage return - not standard compliant,
7662  * but
7663  * it
7664  * should be accepted */
7665  return i + 2;
7666  }
7667  }
7668 
7669  if (i < buflen - 3) {
7670  if ((buf[i] == '\r') && (buf[i + 1] == '\n') && (buf[i + 2] == '\r')
7671  && (buf[i + 3] == '\n')) {
7672  /* Two \r\n - standard compliant */
7673  return i + 4;
7674  }
7675  }
7676  }
7677 
7678  return 0;
7679 }
7680 
7681 
7682 #if !defined(NO_CACHING)
7683 /* Convert month to the month number. Return -1 on error, or month number */
7684 static int
7685 get_month_index(const char *s)
7686 {
7687  size_t i;
7688 
7689  for (i = 0; i < ARRAY_SIZE(month_names); i++) {
7690  if (!strcmp(s, month_names[i])) {
7691  return (int)i;
7692  }
7693  }
7694 
7695  return -1;
7696 }
7697 
7698 
7699 /* Parse UTC date-time string, and return the corresponding time_t value. */
7700 static time_t
7701 parse_date_string(const char *datetime)
7702 {
7703  char month_str[32] = {0};
7704  int second, minute, hour, day, month, year;
7705  time_t result = (time_t)0;
7706  struct tm tm;
7707 
7708  if ((sscanf(datetime,
7709  "%d/%3s/%d %d:%d:%d",
7710  &day,
7711  month_str,
7712  &year,
7713  &hour,
7714  &minute,
7715  &second)
7716  == 6)
7717  || (sscanf(datetime,
7718  "%d %3s %d %d:%d:%d",
7719  &day,
7720  month_str,
7721  &year,
7722  &hour,
7723  &minute,
7724  &second)
7725  == 6)
7726  || (sscanf(datetime,
7727  "%*3s, %d %3s %d %d:%d:%d",
7728  &day,
7729  month_str,
7730  &year,
7731  &hour,
7732  &minute,
7733  &second)
7734  == 6)
7735  || (sscanf(datetime,
7736  "%d-%3s-%d %d:%d:%d",
7737  &day,
7738  month_str,
7739  &year,
7740  &hour,
7741  &minute,
7742  &second)
7743  == 6)) {
7744  month = get_month_index(month_str);
7745  if ((month >= 0) && (year >= 1970)) {
7746  memset(&tm, 0, sizeof(tm));
7747  tm.tm_year = year - 1900;
7748  tm.tm_mon = month;
7749  tm.tm_mday = day;
7750  tm.tm_hour = hour;
7751  tm.tm_min = minute;
7752  tm.tm_sec = second;
7753  result = timegm(&tm);
7754  }
7755  }
7756 
7757  return result;
7758 }
7759 #endif /* !NO_CACHING */
7760 
7761 
7762 /* Protect against directory disclosure attack by removing '..',
7763  * excessive '/' and '\' characters */
7764 static void
7765 remove_double_dots_and_double_slashes(char *s)
7766 {
7767  char *p = s;
7768 
7769  while ((s[0] == '.') && (s[1] == '.')) {
7770  s++;
7771  }
7772 
7773  while (*s != '\0') {
7774  *p++ = *s++;
7775  if ((s[-1] == '/') || (s[-1] == '\\')) {
7776  /* Skip all following slashes, backslashes and double-dots */
7777  while (s[0] != '\0') {
7778  if ((s[0] == '/') || (s[0] == '\\')) {
7779  s++;
7780  } else if ((s[0] == '.') && (s[1] == '.')) {
7781  s += 2;
7782  } else {
7783  break;
7784  }
7785  }
7786  }
7787  }
7788  *p = '\0';
7789 }
7790 
7791 
7792 static const struct {
7793  const char *extension;
7794  size_t ext_len;
7795  const char *mime_type;
7796 } builtin_mime_types[] = {
7797  /* IANA registered MIME types
7798  * (http://www.iana.org/assignments/media-types)
7799  * application types */
7800  {".doc", 4, "application/msword"},
7801  {".eps", 4, "application/postscript"},
7802  {".exe", 4, "application/octet-stream"},
7803  {".js", 3, "application/javascript"},
7804  {".json", 5, "application/json"},
7805  {".pdf", 4, "application/pdf"},
7806  {".ps", 3, "application/postscript"},
7807  {".rtf", 4, "application/rtf"},
7808  {".xhtml", 6, "application/xhtml+xml"},
7809  {".xsl", 4, "application/xml"},
7810  {".xslt", 5, "application/xml"},
7811 
7812  /* fonts */
7813  {".ttf", 4, "application/font-sfnt"},
7814  {".cff", 4, "application/font-sfnt"},
7815  {".otf", 4, "application/font-sfnt"},
7816  {".aat", 4, "application/font-sfnt"},
7817  {".sil", 4, "application/font-sfnt"},
7818  {".pfr", 4, "application/font-tdpfr"},
7819  {".woff", 5, "application/font-woff"},
7820 
7821  /* audio */
7822  {".mp3", 4, "audio/mpeg"},
7823  {".oga", 4, "audio/ogg"},
7824  {".ogg", 4, "audio/ogg"},
7825 
7826  /* image */
7827  {".gif", 4, "image/gif"},
7828  {".ief", 4, "image/ief"},
7829  {".jpeg", 5, "image/jpeg"},
7830  {".jpg", 4, "image/jpeg"},
7831  {".jpm", 4, "image/jpm"},
7832  {".jpx", 4, "image/jpx"},
7833  {".png", 4, "image/png"},
7834  {".svg", 4, "image/svg+xml"},
7835  {".tif", 4, "image/tiff"},
7836  {".tiff", 5, "image/tiff"},
7837 
7838  /* model */
7839  {".wrl", 4, "model/vrml"},
7840 
7841  /* text */
7842  {".css", 4, "text/css"},
7843  {".csv", 4, "text/csv"},
7844  {".htm", 4, "text/html"},
7845  {".html", 5, "text/html"},
7846  {".sgm", 4, "text/sgml"},
7847  {".shtm", 5, "text/html"},
7848  {".shtml", 6, "text/html"},
7849  {".txt", 4, "text/plain"},
7850  {".xml", 4, "text/xml"},
7851 
7852  /* video */
7853  {".mov", 4, "video/quicktime"},
7854  {".mp4", 4, "video/mp4"},
7855  {".mpeg", 5, "video/mpeg"},
7856  {".mpg", 4, "video/mpeg"},
7857  {".ogv", 4, "video/ogg"},
7858  {".qt", 3, "video/quicktime"},
7859 
7860  /* not registered types
7861  * (http://reference.sitepoint.com/html/mime-types-full,
7862  * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
7863  {".arj", 4, "application/x-arj-compressed"},
7864  {".gz", 3, "application/x-gunzip"},
7865  {".rar", 4, "application/x-arj-compressed"},
7866  {".swf", 4, "application/x-shockwave-flash"},
7867  {".tar", 4, "application/x-tar"},
7868  {".tgz", 4, "application/x-tar-gz"},
7869  {".torrent", 8, "application/x-bittorrent"},
7870  {".ppt", 4, "application/x-mspowerpoint"},
7871  {".xls", 4, "application/x-msexcel"},
7872  {".zip", 4, "application/x-zip-compressed"},
7873  {".aac",
7874  4,
7875  "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
7876  {".aif", 4, "audio/x-aif"},
7877  {".m3u", 4, "audio/x-mpegurl"},
7878  {".mid", 4, "audio/x-midi"},
7879  {".ra", 3, "audio/x-pn-realaudio"},
7880  {".ram", 4, "audio/x-pn-realaudio"},
7881  {".wav", 4, "audio/x-wav"},
7882  {".bmp", 4, "image/bmp"},
7883  {".ico", 4, "image/x-icon"},
7884  {".pct", 4, "image/x-pct"},
7885  {".pict", 5, "image/pict"},
7886  {".rgb", 4, "image/x-rgb"},
7887  {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
7888  {".asf", 4, "video/x-ms-asf"},
7889  {".avi", 4, "video/x-msvideo"},
7890  {".m4v", 4, "video/x-m4v"},
7891  {NULL, 0, NULL}};
7892 
7893 
7894 const char *
7895 mg_get_builtin_mime_type(const char *path)
7896 {
7897  const char *ext;
7898  size_t i, path_len;
7899 
7900  path_len = strlen(path);
7901 
7902  for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
7903  ext = path + (path_len - builtin_mime_types[i].ext_len);
7904  if ((path_len > builtin_mime_types[i].ext_len)
7905  && (mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0)) {
7906  return builtin_mime_types[i].mime_type;
7907  }
7908  }
7909 
7910  return "text/plain";
7911 }
7912 
7913 
7914 /* Look at the "path" extension and figure what mime type it has.
7915  * Store mime type in the vector. */
7916 static void
7917 get_mime_type(struct mg_connection *conn, const char *path, struct vec *vec)
7918 {
7919  struct vec ext_vec, mime_vec;
7920  const char *list, *ext;
7921  size_t path_len;
7922 
7923  path_len = strlen(path);
7924 
7925  if ((conn == NULL) || (vec == NULL)) {
7926  if (vec != NULL) {
7927  memset(vec, '\0', sizeof(struct vec));
7928  }
7929  return;
7930  }
7931 
7932  /* Scan user-defined mime types first, in case user wants to
7933  * override default mime types. */
7934  list = conn->dom_ctx->config[EXTRA_MIME_TYPES];
7935  while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
7936  /* ext now points to the path suffix */
7937  ext = path + path_len - ext_vec.len;
7938  if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
7939  *vec = mime_vec;
7940  return;
7941  }
7942  }
7943 
7944  vec->ptr = mg_get_builtin_mime_type(path);
7945  vec->len = strlen(vec->ptr);
7946 }
7947 
7948 
7949 /* Stringify binary data. Output buffer must be twice as big as input,
7950  * because each byte takes 2 bytes in string representation */
7951 static void
7952 bin2str(char *to, const unsigned char *p, size_t len)
7953 {
7954  static const char *hex = "0123456789abcdef";
7955 
7956  for (; len--; p++) {
7957  *to++ = hex[p[0] >> 4];
7958  *to++ = hex[p[0] & 0x0f];
7959  }
7960  *to = '\0';
7961 }
7962 
7963 
7964 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes.
7965  */
7966 char *
7967 mg_md5(char buf[33], ...)
7968 {
7969  md5_byte_t hash[16];
7970  const char *p;
7971  va_list ap;
7972  md5_state_t ctx;
7973 
7974  md5_init(&ctx);
7975 
7976  va_start(ap, buf);
7977  while ((p = va_arg(ap, const char *)) != NULL) {
7978  md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
7979  }
7980  va_end(ap);
7981 
7982  md5_finish(&ctx, hash);
7983  bin2str(buf, hash, sizeof(hash));
7984  return buf;
7985 }
7986 
7987 
7988 /* Check the user's password, return 1 if OK */
7989 static int
7990 check_password(const char *method,
7991  const char *ha1,
7992  const char *uri,
7993  const char *nonce,
7994  const char *nc,
7995  const char *cnonce,
7996  const char *qop,
7997  const char *response)
7998 {
7999  char ha2[32 + 1], expected_response[32 + 1];
8000 
8001  /* Some of the parameters may be NULL */
8002  if ((method == NULL) || (nonce == NULL) || (nc == NULL) || (cnonce == NULL)
8003  || (qop == NULL) || (response == NULL)) {
8004  return 0;
8005  }
8006 
8007  /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
8008  if (strlen(response) != 32) {
8009  return 0;
8010  }
8011 
8012  mg_md5(ha2, method, ":", uri, NULL);
8013  mg_md5(expected_response,
8014  ha1,
8015  ":",
8016  nonce,
8017  ":",
8018  nc,
8019  ":",
8020  cnonce,
8021  ":",
8022  qop,
8023  ":",
8024  ha2,
8025  NULL);
8026 
8027  return mg_strcasecmp(response, expected_response) == 0;
8028 }
8029 
8030 
8031 /* Use the global passwords file, if specified by auth_gpass option,
8032  * or search for .htpasswd in the requested directory. */
8033 static void
8034 open_auth_file(struct mg_connection *conn,
8035  const char *path,
8036  struct mg_file *filep)
8037 {
8038  if ((conn != NULL) && (conn->dom_ctx != NULL)) {
8039  char name[PATH_MAX];
8040  const char *p, *e,
8041  *gpass = conn->dom_ctx->config[GLOBAL_PASSWORDS_FILE];
8042  int truncated;
8043 
8044  if (gpass != NULL) {
8045  /* Use global passwords file */
8046  if (!mg_fopen(conn, gpass, MG_FOPEN_MODE_READ, filep)) {
8047 #if defined(DEBUG)
8048  /* Use mg_cry_internal here, since gpass has been configured. */
8049  mg_cry_internal(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
8050 #endif
8051  }
8052  /* Important: using local struct mg_file to test path for
8053  * is_directory flag. If filep is used, mg_stat() makes it
8054  * appear as if auth file was opened.
8055  * TODO(mid): Check if this is still required after rewriting
8056  * mg_stat */
8057  } else if (mg_stat(conn, path, &filep->stat)
8058  && filep->stat.is_directory) {
8059  mg_snprintf(conn,
8060  &truncated,
8061  name,
8062  sizeof(name),
8063  "%s/%s",
8064  path,
8065  PASSWORDS_FILE_NAME);
8066 
8067  if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
8068 #if defined(DEBUG)
8069  /* Don't use mg_cry_internal here, but only a trace, since this
8070  * is
8071  * a typical case. It will occur for every directory
8072  * without a password file. */
8073  DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO));
8074 #endif
8075  }
8076  } else {
8077  /* Try to find .htpasswd in requested directory. */
8078  for (p = path, e = p + strlen(p) - 1; e > p; e--) {
8079  if (e[0] == '/') {
8080  break;
8081  }
8082  }
8083  mg_snprintf(conn,
8084  &truncated,
8085  name,
8086  sizeof(name),
8087  "%.*s/%s",
8088  (int)(e - p),
8089  p,
8090  PASSWORDS_FILE_NAME);
8091 
8092  if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
8093 #if defined(DEBUG)
8094  /* Don't use mg_cry_internal here, but only a trace, since this
8095  * is
8096  * a typical case. It will occur for every directory
8097  * without a password file. */
8098  DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO));
8099 #endif
8100  }
8101  }
8102  }
8103 }
8104 
8105 
8106 /* Parsed Authorization header */
8107 struct ah {
8108  char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
8109 };
8110 
8111 
8112 /* Return 1 on success. Always initializes the ah structure. */
8113 static int
8114 parse_auth_header(struct mg_connection *conn,
8115  char *buf,
8116  size_t buf_size,
8117  struct ah *ah)
8118 {
8119  char *name, *value, *s;
8120  const char *auth_header;
8121  uint64_t nonce;
8122 
8123  if (!ah || !conn) {
8124  return 0;
8125  }
8126 
8127  (void)memset(ah, 0, sizeof(*ah));
8128  if (((auth_header = mg_get_header(conn, "Authorization")) == NULL)
8129  || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
8130  return 0;
8131  }
8132 
8133  /* Make modifiable copy of the auth header */
8134  (void)mg_strlcpy(buf, auth_header + 7, buf_size);
8135  s = buf;
8136 
8137  /* Parse authorization header */
8138  for (;;) {
8139  /* Gobble initial spaces */
8140  while (isspace(*(unsigned char *)s)) {
8141  s++;
8142  }
8143  name = skip_quoted(&s, "=", " ", 0);
8144  /* Value is either quote-delimited, or ends at first comma or space.
8145  */
8146  if (s[0] == '\"') {
8147  s++;
8148  value = skip_quoted(&s, "\"", " ", '\\');
8149  if (s[0] == ',') {
8150  s++;
8151  }
8152  } else {
8153  value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
8154  * spaces */
8155  }
8156  if (*name == '\0') {
8157  break;
8158  }
8159 
8160  if (!strcmp(name, "username")) {
8161  ah->user = value;
8162  } else if (!strcmp(name, "cnonce")) {
8163  ah->cnonce = value;
8164  } else if (!strcmp(name, "response")) {
8165  ah->response = value;
8166  } else if (!strcmp(name, "uri")) {
8167  ah->uri = value;
8168  } else if (!strcmp(name, "qop")) {
8169  ah->qop = value;
8170  } else if (!strcmp(name, "nc")) {
8171  ah->nc = value;
8172  } else if (!strcmp(name, "nonce")) {
8173  ah->nonce = value;
8174  }
8175  }
8176 
8177 #if !defined(NO_NONCE_CHECK)
8178  /* Read the nonce from the response. */
8179  if (ah->nonce == NULL) {
8180  return 0;
8181  }
8182  s = NULL;
8183  nonce = strtoull(ah->nonce, &s, 10);
8184  if ((s == NULL) || (*s != 0)) {
8185  return 0;
8186  }
8187 
8188  /* Convert the nonce from the client to a number. */
8189  nonce ^= conn->dom_ctx->auth_nonce_mask;
8190 
8191  /* The converted number corresponds to the time the nounce has been
8192  * created. This should not be earlier than the server start. */
8193  /* Server side nonce check is valuable in all situations but one:
8194  * if the server restarts frequently, but the client should not see
8195  * that, so the server should accept nonces from previous starts. */
8196  /* However, the reasonable default is to not accept a nonce from a
8197  * previous start, so if anyone changed the access rights between
8198  * two restarts, a new login is required. */
8199  if (nonce < (uint64_t)conn->phys_ctx->start_time) {
8200  /* nonce is from a previous start of the server and no longer valid
8201  * (replay attack?) */
8202  return 0;
8203  }
8204  /* Check if the nonce is too high, so it has not (yet) been used by the
8205  * server. */
8206  if (nonce >= ((uint64_t)conn->phys_ctx->start_time
8207  + conn->dom_ctx->nonce_count)) {
8208  return 0;
8209  }
8210 #else
8211  (void)nonce;
8212 #endif
8213 
8214  /* CGI needs it as REMOTE_USER */
8215  if (ah->user != NULL) {
8216  conn->request_info.remote_user =
8217  mg_strdup_ctx(ah->user, conn->phys_ctx);
8218  } else {
8219  return 0;
8220  }
8221 
8222  return 1;
8223 }
8224 
8225 
8226 static const char *
8227 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p)
8228 {
8229 #if defined(MG_USE_OPEN_FILE)
8230  const char *eof;
8231  size_t len;
8232  const char *memend;
8233 #else
8234  (void)p; /* parameter is unused */
8235 #endif
8236 
8237  if (!filep) {
8238  return NULL;
8239  }
8240 
8241 #if defined(MG_USE_OPEN_FILE)
8242  if ((filep->access.membuf != NULL) && (*p != NULL)) {
8243  memend = (const char *)&filep->access.membuf[filep->stat.size];
8244  /* Search for \n from p till the end of stream */
8245  eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
8246  if (eof != NULL) {
8247  eof += 1; /* Include \n */
8248  } else {
8249  eof = memend; /* Copy remaining data */
8250  }
8251  len =
8252  ((size_t)(eof - *p) > (size - 1)) ? (size - 1) : (size_t)(eof - *p);
8253  memcpy(buf, *p, len);
8254  buf[len] = '\0';
8255  *p += len;
8256  return len ? eof : NULL;
8257  } else /* filep->access.fp block below */
8258 #endif
8259  if (filep->access.fp != NULL) {
8260  return fgets(buf, (int)size, filep->access.fp);
8261  } else {
8262  return NULL;
8263  }
8264 }
8265 
8266 /* Define the initial recursion depth for procesesing htpasswd files that
8267  * include other htpasswd
8268  * (or even the same) files. It is not difficult to provide a file or files
8269  * s.t. they force civetweb
8270  * to infinitely recurse and then crash.
8271  */
8272 #define INITIAL_DEPTH 9
8273 #if INITIAL_DEPTH <= 0
8274 #error Bad INITIAL_DEPTH for recursion, set to at least 1
8275 #endif
8276 
8277 struct read_auth_file_struct {
8278  struct mg_connection *conn;
8279  struct ah ah;
8280  const char *domain;
8281  char buf[256 + 256 + 40];
8282  const char *f_user;
8283  const char *f_domain;
8284  const char *f_ha1;
8285 };
8286 
8287 
8288 static int
8289 read_auth_file(struct mg_file *filep,
8290  struct read_auth_file_struct *workdata,
8291  int depth)
8292 {
8293  char *p = NULL /* init if MG_USE_OPEN_FILE is not set */;
8294  int is_authorized = 0;
8295  struct mg_file fp;
8296  size_t l;
8297 
8298  if (!filep || !workdata || (0 == depth)) {
8299  return 0;
8300  }
8301 
8302 /* Loop over passwords file */
8303 #if defined(MG_USE_OPEN_FILE)
8304  p = (char *)filep->access.membuf;
8305 #endif
8306  while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
8307  l = strlen(workdata->buf);
8308  while (l > 0) {
8309  if (isspace(workdata->buf[l - 1])
8310  || iscntrl(workdata->buf[l - 1])) {
8311  l--;
8312  workdata->buf[l] = 0;
8313  } else
8314  break;
8315  }
8316  if (l < 1) {
8317  continue;
8318  }
8319 
8320  workdata->f_user = workdata->buf;
8321 
8322  if (workdata->f_user[0] == ':') {
8323  /* user names may not contain a ':' and may not be empty,
8324  * so lines starting with ':' may be used for a special purpose
8325  */
8326  if (workdata->f_user[1] == '#') {
8327  /* :# is a comment */
8328  continue;
8329  } else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
8330  if (mg_fopen(workdata->conn,
8331  workdata->f_user + 9,
8332  MG_FOPEN_MODE_READ,
8333  &fp)) {
8334  is_authorized = read_auth_file(&fp, workdata, depth - 1);
8335  (void)mg_fclose(
8336  &fp.access); /* ignore error on read only file */
8337 
8338  /* No need to continue processing files once we have a
8339  * match, since nothing will reset it back
8340  * to 0.
8341  */
8342  if (is_authorized) {
8343  return is_authorized;
8344  }
8345  } else {
8346  mg_cry_internal(workdata->conn,
8347  "%s: cannot open authorization file: %s",
8348  __func__,
8349  workdata->buf);
8350  }
8351  continue;
8352  }
8353  /* everything is invalid for the moment (might change in the
8354  * future) */
8355  mg_cry_internal(workdata->conn,
8356  "%s: syntax error in authorization file: %s",
8357  __func__,
8358  workdata->buf);
8359  continue;
8360  }
8361 
8362  workdata->f_domain = strchr(workdata->f_user, ':');
8363  if (workdata->f_domain == NULL) {
8364  mg_cry_internal(workdata->conn,
8365  "%s: syntax error in authorization file: %s",
8366  __func__,
8367  workdata->buf);
8368  continue;
8369  }
8370  *(char *)(workdata->f_domain) = 0;
8371  (workdata->f_domain)++;
8372 
8373  workdata->f_ha1 = strchr(workdata->f_domain, ':');
8374  if (workdata->f_ha1 == NULL) {
8375  mg_cry_internal(workdata->conn,
8376  "%s: syntax error in authorization file: %s",
8377  __func__,
8378  workdata->buf);
8379  continue;
8380  }
8381  *(char *)(workdata->f_ha1) = 0;
8382  (workdata->f_ha1)++;
8383 
8384  if (!strcmp(workdata->ah.user, workdata->f_user)
8385  && !strcmp(workdata->domain, workdata->f_domain)) {
8386  return check_password(workdata->conn->request_info.request_method,
8387  workdata->f_ha1,
8388  workdata->ah.uri,
8389  workdata->ah.nonce,
8390  workdata->ah.nc,
8391  workdata->ah.cnonce,
8392  workdata->ah.qop,
8393  workdata->ah.response);
8394  }
8395  }
8396 
8397  return is_authorized;
8398 }
8399 
8400 
8401 /* Authorize against the opened passwords file. Return 1 if authorized. */
8402 static int
8403 authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
8404 {
8405  struct read_auth_file_struct workdata;
8406  char buf[MG_BUF_LEN];
8407 
8408  if (!conn || !conn->dom_ctx) {
8409  return 0;
8410  }
8411 
8412  memset(&workdata, 0, sizeof(workdata));
8413  workdata.conn = conn;
8414 
8415  if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
8416  return 0;
8417  }
8418 
8419  if (realm) {
8420  workdata.domain = realm;
8421  } else {
8422  workdata.domain = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
8423  }
8424 
8425  return read_auth_file(filep, &workdata, INITIAL_DEPTH);
8426 }
8427 
8428 
8429 /* Public function to check http digest authentication header */
8430 int
8431 mg_check_digest_access_authentication(struct mg_connection *conn,
8432  const char *realm,
8433  const char *filename)
8434 {
8435  struct mg_file file = STRUCT_FILE_INITIALIZER;
8436  int auth;
8437 
8438  if (!conn || !filename) {
8439  return -1;
8440  }
8441  if (!mg_fopen(conn, filename, MG_FOPEN_MODE_READ, &file)) {
8442  return -2;
8443  }
8444 
8445  auth = authorize(conn, &file, realm);
8446 
8447  mg_fclose(&file.access);
8448 
8449  return auth;
8450 }
8451 
8452 
8453 /* Return 1 if request is authorised, 0 otherwise. */
8454 static int
8455 check_authorization(struct mg_connection *conn, const char *path)
8456 {
8457  char fname[PATH_MAX];
8458  struct vec uri_vec, filename_vec;
8459  const char *list;
8460  struct mg_file file = STRUCT_FILE_INITIALIZER;
8461  int authorized = 1, truncated;
8462 
8463  if (!conn || !conn->dom_ctx) {
8464  return 0;
8465  }
8466 
8467  list = conn->dom_ctx->config[PROTECT_URI];
8468  while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
8469  if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
8470  mg_snprintf(conn,
8471  &truncated,
8472  fname,
8473  sizeof(fname),
8474  "%.*s",
8475  (int)filename_vec.len,
8476  filename_vec.ptr);
8477 
8478  if (truncated
8479  || !mg_fopen(conn, fname, MG_FOPEN_MODE_READ, &file)) {
8480  mg_cry_internal(conn,
8481  "%s: cannot open %s: %s",
8482  __func__,
8483  fname,
8484  strerror(errno));
8485  }
8486  break;
8487  }
8488  }
8489 
8490  if (!is_file_opened(&file.access)) {
8491  open_auth_file(conn, path, &file);
8492  }
8493 
8494  if (is_file_opened(&file.access)) {
8495  authorized = authorize(conn, &file, NULL);
8496  (void)mg_fclose(&file.access); /* ignore error on read only file */
8497  }
8498 
8499  return authorized;
8500 }
8501 
8502 
8503 /* Internal function. Assumes conn is valid */
8504 static void
8505 send_authorization_request(struct mg_connection *conn, const char *realm)
8506 {
8507  char date[64];
8508  time_t curtime = time(NULL);
8509  uint64_t nonce = (uint64_t)(conn->phys_ctx->start_time);
8510 
8511  if (!realm) {
8512  realm = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
8513  }
8514 
8515  (void)pthread_mutex_lock(&conn->phys_ctx->nonce_mutex);
8516  nonce += conn->dom_ctx->nonce_count;
8517  ++conn->dom_ctx->nonce_count;
8518  (void)pthread_mutex_unlock(&conn->phys_ctx->nonce_mutex);
8519 
8520  nonce ^= conn->dom_ctx->auth_nonce_mask;
8521  conn->status_code = 401;
8522  conn->must_close = 1;
8523 
8524  gmt_time_string(date, sizeof(date), &curtime);
8525 
8526  mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
8527  send_no_cache_header(conn);
8528  send_additional_header(conn);
8529  mg_printf(conn,
8530  "Date: %s\r\n"
8531  "Connection: %s\r\n"
8532  "Content-Length: 0\r\n"
8533  "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
8534  "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
8535  date,
8536  suggest_connection_header(conn),
8537  realm,
8538  nonce);
8539 }
8540 
8541 
8542 /* Interface function. Parameters are provided by the user, so do
8543  * at least some basic checks.
8544  */
8545 int
8546 mg_send_digest_access_authentication_request(struct mg_connection *conn,
8547  const char *realm)
8548 {
8549  if (conn && conn->dom_ctx) {
8550  send_authorization_request(conn, realm);
8551  return 0;
8552  }
8553  return -1;
8554 }
8555 
8556 
8557 #if !defined(NO_FILES)
8558 static int
8559 is_authorized_for_put(struct mg_connection *conn)
8560 {
8561  if (conn) {
8562  struct mg_file file = STRUCT_FILE_INITIALIZER;
8563  const char *passfile = conn->dom_ctx->config[PUT_DELETE_PASSWORDS_FILE];
8564  int ret = 0;
8565 
8566  if (passfile != NULL
8567  && mg_fopen(conn, passfile, MG_FOPEN_MODE_READ, &file)) {
8568  ret = authorize(conn, &file, NULL);
8569  (void)mg_fclose(&file.access); /* ignore error on read only file */
8570  }
8571 
8572  return ret;
8573  }
8574  return 0;
8575 }
8576 #endif
8577 
8578 
8579 int
8580 mg_modify_passwords_file(const char *fname,
8581  const char *domain,
8582  const char *user,
8583  const char *pass)
8584 {
8585  int found, i;
8586  char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
8587  FILE *fp, *fp2;
8588 
8589  found = 0;
8590  fp = fp2 = NULL;
8591 
8592  /* Regard empty password as no password - remove user record. */
8593  if ((pass != NULL) && (pass[0] == '\0')) {
8594  pass = NULL;
8595  }
8596 
8597  /* Other arguments must not be empty */
8598  if ((fname == NULL) || (domain == NULL) || (user == NULL)) {
8599  return 0;
8600  }
8601 
8602  /* Using the given file format, user name and domain must not contain
8603  * ':'
8604  */
8605  if (strchr(user, ':') != NULL) {
8606  return 0;
8607  }
8608  if (strchr(domain, ':') != NULL) {
8609  return 0;
8610  }
8611 
8612  /* Do not allow control characters like newline in user name and domain.
8613  * Do not allow excessively long names either. */
8614  for (i = 0; ((i < 255) && (user[i] != 0)); i++) {
8615  if (iscntrl(user[i])) {
8616  return 0;
8617  }
8618  }
8619  if (user[i]) {
8620  return 0;
8621  }
8622  for (i = 0; ((i < 255) && (domain[i] != 0)); i++) {
8623  if (iscntrl(domain[i])) {
8624  return 0;
8625  }
8626  }
8627  if (domain[i]) {
8628  return 0;
8629  }
8630 
8631  /* The maximum length of the path to the password file is limited */
8632  if ((strlen(fname) + 4) >= PATH_MAX) {
8633  return 0;
8634  }
8635 
8636  /* Create a temporary file name. Length has been checked before. */
8637  strcpy(tmp, fname);
8638  strcat(tmp, ".tmp");
8639 
8640  /* Create the file if does not exist */
8641  /* Use of fopen here is OK, since fname is only ASCII */
8642  if ((fp = fopen(fname, "a+")) != NULL) {
8643  (void)fclose(fp);
8644  }
8645 
8646  /* Open the given file and temporary file */
8647  if ((fp = fopen(fname, "r")) == NULL) {
8648  return 0;
8649  } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
8650  fclose(fp);
8651  return 0;
8652  }
8653 
8654  /* Copy the stuff to temporary file */
8655  while (fgets(line, sizeof(line), fp) != NULL) {
8656  if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
8657  continue;
8658  }
8659  u[255] = 0;
8660  d[255] = 0;
8661 
8662  if (!strcmp(u, user) && !strcmp(d, domain)) {
8663  found++;
8664  if (pass != NULL) {
8665  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
8666  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
8667  }
8668  } else {
8669  fprintf(fp2, "%s", line);
8670  }
8671  }
8672 
8673  /* If new user, just add it */
8674  if (!found && (pass != NULL)) {
8675  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
8676  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
8677  }
8678 
8679  /* Close files */
8680  fclose(fp);
8681  fclose(fp2);
8682 
8683  /* Put the temp file in place of real file */
8684  IGNORE_UNUSED_RESULT(remove(fname));
8685  IGNORE_UNUSED_RESULT(rename(tmp, fname));
8686 
8687  return 1;
8688 }
8689 
8690 
8691 static int
8692 is_valid_port(unsigned long port)
8693 {
8694  return (port <= 0xffff);
8695 }
8696 
8697 
8698 static int
8699 mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
8700 {
8701  struct addrinfo hints, *res, *ressave;
8702  int func_ret = 0;
8703  int gai_ret;
8704 
8705  memset(&hints, 0, sizeof(struct addrinfo));
8706  hints.ai_family = af;
8707 
8708  gai_ret = getaddrinfo(src, NULL, &hints, &res);
8709  if (gai_ret != 0) {
8710  /* gai_strerror could be used to convert gai_ret to a string */
8711  /* POSIX return values: see
8712  * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
8713  */
8714  /* Windows return values: see
8715  * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
8716  */
8717  return 0;
8718  }
8719 
8720  ressave = res;
8721 
8722  while (res) {
8723  if (dstlen >= (size_t)res->ai_addrlen) {
8724  memcpy(dst, res->ai_addr, res->ai_addrlen);
8725  func_ret = 1;
8726  }
8727  res = res->ai_next;
8728  }
8729 
8730  freeaddrinfo(ressave);
8731  return func_ret;
8732 }
8733 
8734 
8735 static int
8736 connect_socket(struct mg_context *ctx /* may be NULL */,
8737  const char *host,
8738  int port,
8739  int use_ssl,
8740  char *ebuf,
8741  size_t ebuf_len,
8742  SOCKET *sock /* output: socket, must not be NULL */,
8743  union usa *sa /* output: socket address, must not be NULL */
8744 )
8745 {
8746  int ip_ver = 0;
8747  int conn_ret = -1;
8748  int ret;
8749  *sock = INVALID_SOCKET;
8750  memset(sa, 0, sizeof(*sa));
8751 
8752  if (ebuf_len > 0) {
8753  *ebuf = 0;
8754  }
8755 
8756  if (host == NULL) {
8757  mg_snprintf(NULL,
8758  NULL, /* No truncation check for ebuf */
8759  ebuf,
8760  ebuf_len,
8761  "%s",
8762  "NULL host");
8763  return 0;
8764  }
8765 
8766  if ((port <= 0) || !is_valid_port((unsigned)port)) {
8767  mg_snprintf(NULL,
8768  NULL, /* No truncation check for ebuf */
8769  ebuf,
8770  ebuf_len,
8771  "%s",
8772  "invalid port");
8773  return 0;
8774  }
8775 
8776 #if !defined(NO_SSL)
8777 #if !defined(NO_SSL_DL)
8778 #if defined(OPENSSL_API_1_1)
8779  if (use_ssl && (TLS_client_method == NULL)) {
8780  mg_snprintf(NULL,
8781  NULL, /* No truncation check for ebuf */
8782  ebuf,
8783  ebuf_len,
8784  "%s",
8785  "SSL is not initialized");
8786  return 0;
8787  }
8788 #else
8789  if (use_ssl && (SSLv23_client_method == NULL)) {
8790  mg_snprintf(NULL,
8791  NULL, /* No truncation check for ebuf */
8792  ebuf,
8793  ebuf_len,
8794  "%s",
8795  "SSL is not initialized");
8796  return 0;
8797  }
8798 
8799 #endif /* OPENSSL_API_1_1 */
8800 #else
8801  (void)use_ssl;
8802 #endif /* NO_SSL_DL */
8803 #else
8804  (void)use_ssl;
8805 #endif /* !defined(NO_SSL) */
8806 
8807  if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
8808  sa->sin.sin_family = AF_INET;
8809  sa->sin.sin_port = htons((uint16_t)port);
8810  ip_ver = 4;
8811 #if defined(USE_IPV6)
8812  } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
8813  sa->sin6.sin6_family = AF_INET6;
8814  sa->sin6.sin6_port = htons((uint16_t)port);
8815  ip_ver = 6;
8816  } else if (host[0] == '[') {
8817  /* While getaddrinfo on Windows will work with [::1],
8818  * getaddrinfo on Linux only works with ::1 (without []). */
8819  size_t l = strlen(host + 1);
8820  char *h = (l > 1) ? mg_strdup_ctx(host + 1, ctx) : NULL;
8821  if (h) {
8822  h[l - 1] = 0;
8823  if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
8824  sa->sin6.sin6_family = AF_INET6;
8825  sa->sin6.sin6_port = htons((uint16_t)port);
8826  ip_ver = 6;
8827  }
8828  mg_free(h);
8829  }
8830 #endif
8831  }
8832 
8833  if (ip_ver == 0) {
8834  mg_snprintf(NULL,
8835  NULL, /* No truncation check for ebuf */
8836  ebuf,
8837  ebuf_len,
8838  "%s",
8839  "host not found");
8840  return 0;
8841  }
8842 
8843  if (ip_ver == 4) {
8844  *sock = socket(PF_INET, SOCK_STREAM, 0);
8845  }
8846 #if defined(USE_IPV6)
8847  else if (ip_ver == 6) {
8848  *sock = socket(PF_INET6, SOCK_STREAM, 0);
8849  }
8850 #endif
8851 
8852  if (*sock == INVALID_SOCKET) {
8853  mg_snprintf(NULL,
8854  NULL, /* No truncation check for ebuf */
8855  ebuf,
8856  ebuf_len,
8857  "socket(): %s",
8858  strerror(ERRNO));
8859  return 0;
8860  }
8861 
8862  if (0 != set_non_blocking_mode(*sock)) {
8863  mg_snprintf(NULL,
8864  NULL, /* No truncation check for ebuf */
8865  ebuf,
8866  ebuf_len,
8867  "Cannot set socket to non-blocking: %s",
8868  strerror(ERRNO));
8869  closesocket(*sock);
8870  *sock = INVALID_SOCKET;
8871  return 0;
8872  }
8873 
8874  set_close_on_exec(*sock, fc(ctx));
8875 
8876  if (ip_ver == 4) {
8877  /* connected with IPv4 */
8878  conn_ret = connect(*sock,
8879  (struct sockaddr *)((void *)&sa->sin),
8880  sizeof(sa->sin));
8881  }
8882 #if defined(USE_IPV6)
8883  else if (ip_ver == 6) {
8884  /* connected with IPv6 */
8885  conn_ret = connect(*sock,
8886  (struct sockaddr *)((void *)&sa->sin6),
8887  sizeof(sa->sin6));
8888  }
8889 #endif
8890 
8891 #if defined(_WIN32)
8892  if (conn_ret != 0) {
8893  DWORD err = WSAGetLastError(); /* could return WSAEWOULDBLOCK */
8894  conn_ret = (int)err;
8895 #if !defined(EINPROGRESS)
8896 #define EINPROGRESS (WSAEWOULDBLOCK) /* Winsock equivalent */
8897 #endif /* if !defined(EINPROGRESS) */
8898  }
8899 #endif
8900 
8901  if ((conn_ret != 0) && (conn_ret != EINPROGRESS)) {
8902  /* Data for getsockopt */
8903  int sockerr = -1;
8904  void *psockerr = &sockerr;
8905 
8906 #if defined(_WIN32)
8907  int len = (int)sizeof(sockerr);
8908 #else
8909  socklen_t len = (socklen_t)sizeof(sockerr);
8910 #endif
8911 
8912  /* Data for poll */
8913  struct pollfd pfd[1];
8914  int pollres;
8915  int ms_wait = 10000; /* 10 second timeout */
8916 
8917  /* For a non-blocking socket, the connect sequence is:
8918  * 1) call connect (will not block)
8919  * 2) wait until the socket is ready for writing (select or poll)
8920  * 3) check connection state with getsockopt
8921  */
8922  pfd[0].fd = *sock;
8923  pfd[0].events = POLLOUT;
8924  pollres = mg_poll(pfd, 1, (int)(ms_wait), &(ctx->stop_flag));
8925 
8926  if (pollres != 1) {
8927  /* Not connected */
8928  mg_snprintf(NULL,
8929  NULL, /* No truncation check for ebuf */
8930  ebuf,
8931  ebuf_len,
8932  "connect(%s:%d): timeout",
8933  host,
8934  port);
8935  closesocket(*sock);
8936  *sock = INVALID_SOCKET;
8937  return 0;
8938  }
8939 
8940 #if defined(_WIN32)
8941  ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, (char *)psockerr, &len);
8942 #else
8943  ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, psockerr, &len);
8944 #endif
8945 
8946  if ((ret != 0) || (sockerr != 0)) {
8947  /* Not connected */
8948  mg_snprintf(NULL,
8949  NULL, /* No truncation check for ebuf */
8950  ebuf,
8951  ebuf_len,
8952  "connect(%s:%d): error %s",
8953  host,
8954  port,
8955  strerror(sockerr));
8956  closesocket(*sock);
8957  *sock = INVALID_SOCKET;
8958  return 0;
8959  }
8960  }
8961 
8962  return 1;
8963 }
8964 
8965 
8966 int
8967 mg_url_encode(const char *src, char *dst, size_t dst_len)
8968 {
8969  static const char *dont_escape = "._-$,;~()";
8970  static const char *hex = "0123456789abcdef";
8971  char *pos = dst;
8972  const char *end = dst + dst_len - 1;
8973 
8974  for (; ((*src != '\0') && (pos < end)); src++, pos++) {
8975  if (isalnum(*(const unsigned char *)src)
8976  || (strchr(dont_escape, *(const unsigned char *)src) != NULL)) {
8977  *pos = *src;
8978  } else if (pos + 2 < end) {
8979  pos[0] = '%';
8980  pos[1] = hex[(*(const unsigned char *)src) >> 4];
8981  pos[2] = hex[(*(const unsigned char *)src) & 0xf];
8982  pos += 2;
8983  } else {
8984  break;
8985  }
8986  }
8987 
8988  *pos = '\0';
8989  return (*src == '\0') ? (int)(pos - dst) : -1;
8990 }
8991 
8992 /* Return 0 on success, non-zero if an error occurs. */
8993 
8994 static int
8995 print_dir_entry(struct de *de)
8996 {
8997  size_t hrefsize;
8998  char *href;
8999  char size[64], mod[64];
9000 #if defined(REENTRANT_TIME)
9001  struct tm _tm;
9002  struct tm *tm = &_tm;
9003 #else
9004  struct tm *tm;
9005 #endif
9006 
9007  hrefsize = PATH_MAX * 3; /* worst case */
9008  href = (char *)mg_malloc(hrefsize);
9009  if (href == NULL) {
9010  return -1;
9011  }
9012  if (de->file.is_directory) {
9013  mg_snprintf(de->conn,
9014  NULL, /* Buffer is big enough */
9015  size,
9016  sizeof(size),
9017  "%s",
9018  "[DIRECTORY]");
9019  } else {
9020  /* We use (signed) cast below because MSVC 6 compiler cannot
9021  * convert unsigned __int64 to double. Sigh. */
9022  if (de->file.size < 1024) {
9023  mg_snprintf(de->conn,
9024  NULL, /* Buffer is big enough */
9025  size,
9026  sizeof(size),
9027  "%d",
9028  (int)de->file.size);
9029  } else if (de->file.size < 0x100000) {
9030  mg_snprintf(de->conn,
9031  NULL, /* Buffer is big enough */
9032  size,
9033  sizeof(size),
9034  "%.1fk",
9035  (double)de->file.size / 1024.0);
9036  } else if (de->file.size < 0x40000000) {
9037  mg_snprintf(de->conn,
9038  NULL, /* Buffer is big enough */
9039  size,
9040  sizeof(size),
9041  "%.1fM",
9042  (double)de->file.size / 1048576);
9043  } else {
9044  mg_snprintf(de->conn,
9045  NULL, /* Buffer is big enough */
9046  size,
9047  sizeof(size),
9048  "%.1fG",
9049  (double)de->file.size / 1073741824);
9050  }
9051  }
9052 
9053  /* Note: mg_snprintf will not cause a buffer overflow above.
9054  * So, string truncation checks are not required here. */
9055 
9056 #if defined(REENTRANT_TIME)
9057  localtime_r(&de->file.last_modified, tm);
9058 #else
9059  tm = localtime(&de->file.last_modified);
9060 #endif
9061  if (tm != NULL) {
9062  strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
9063  } else {
9064  mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
9065  mod[sizeof(mod) - 1] = '\0';
9066  }
9067  mg_url_encode(de->file_name, href, hrefsize);
9068  mg_printf(de->conn,
9069  "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
9070  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
9071  de->conn->request_info.local_uri,
9072  href,
9073  de->file.is_directory ? "/" : "",
9074  de->file_name,
9075  de->file.is_directory ? "/" : "",
9076  mod,
9077  size);
9078  mg_free(href);
9079  return 0;
9080 }
9081 
9082 
9083 /* This function is called from send_directory() and used for
9084  * sorting directory entries by size, or name, or modification time.
9085  * On windows, __cdecl specification is needed in case if project is built
9086  * with __stdcall convention. qsort always requires __cdels callback. */
9087 static int WINCDECL
9088 compare_dir_entries(const void *p1, const void *p2)
9089 {
9090  if (p1 && p2) {
9091  const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
9092  const char *query_string = a->conn->request_info.query_string;
9093  int cmp_result = 0;
9094 
9095  if (query_string == NULL) {
9096  query_string = "na";
9097  }
9098 
9099  if (a->file.is_directory && !b->file.is_directory) {
9100  return -1; /* Always put directories on top */
9101  } else if (!a->file.is_directory && b->file.is_directory) {
9102  return 1; /* Always put directories on top */
9103  } else if (*query_string == 'n') {
9104  cmp_result = strcmp(a->file_name, b->file_name);
9105  } else if (*query_string == 's') {
9106  cmp_result = (a->file.size == b->file.size)
9107  ? 0
9108  : ((a->file.size > b->file.size) ? 1 : -1);
9109  } else if (*query_string == 'd') {
9110  cmp_result =
9111  (a->file.last_modified == b->file.last_modified)
9112  ? 0
9113  : ((a->file.last_modified > b->file.last_modified) ? 1
9114  : -1);
9115  }
9116 
9117  return (query_string[1] == 'd') ? -cmp_result : cmp_result;
9118  }
9119  return 0;
9120 }
9121 
9122 
9123 static int
9124 must_hide_file(struct mg_connection *conn, const char *path)
9125 {
9126  if (conn && conn->dom_ctx) {
9127  const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
9128  const char *pattern = conn->dom_ctx->config[HIDE_FILES];
9129  return (match_prefix(pw_pattern, strlen(pw_pattern), path) > 0)
9130  || ((pattern != NULL)
9131  && (match_prefix(pattern, strlen(pattern), path) > 0));
9132  }
9133  return 0;
9134 }
9135 
9136 
9137 static int
9138 scan_directory(struct mg_connection *conn,
9139  const char *dir,
9140  void *data,
9141  int (*cb)(struct de *, void *))
9142 {
9143  char path[PATH_MAX];
9144  struct dirent *dp;
9145  DIR *dirp;
9146  struct de de;
9147  int truncated;
9148 
9149  if ((dirp = mg_opendir(conn, dir)) == NULL) {
9150  return 0;
9151  } else {
9152  de.conn = conn;
9153 
9154  while ((dp = mg_readdir(dirp)) != NULL) {
9155  /* Do not show current dir and hidden files */
9156  if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
9157  || must_hide_file(conn, dp->d_name)) {
9158  continue;
9159  }
9160 
9161  mg_snprintf(
9162  conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
9163 
9164  /* If we don't memset stat structure to zero, mtime will have
9165  * garbage and strftime() will segfault later on in
9166  * print_dir_entry(). memset is required only if mg_stat()
9167  * fails. For more details, see
9168  * http://code.google.com/p/mongoose/issues/detail?id=79 */
9169  memset(&de.file, 0, sizeof(de.file));
9170 
9171  if (truncated) {
9172  /* If the path is not complete, skip processing. */
9173  continue;
9174  }
9175 
9176  if (!mg_stat(conn, path, &de.file)) {
9177  mg_cry_internal(conn,
9178  "%s: mg_stat(%s) failed: %s",
9179  __func__,
9180  path,
9181  strerror(ERRNO));
9182  }
9183  de.file_name = dp->d_name;
9184  cb(&de, data);
9185  }
9186  (void)mg_closedir(dirp);
9187  }
9188  return 1;
9189 }
9190 
9191 
9192 #if !defined(NO_FILES)
9193 static int
9194 remove_directory(struct mg_connection *conn, const char *dir)
9195 {
9196  char path[PATH_MAX];
9197  struct dirent *dp;
9198  DIR *dirp;
9199  struct de de;
9200  int truncated;
9201  int ok = 1;
9202 
9203  if ((dirp = mg_opendir(conn, dir)) == NULL) {
9204  return 0;
9205  } else {
9206  de.conn = conn;
9207 
9208  while ((dp = mg_readdir(dirp)) != NULL) {
9209  /* Do not show current dir (but show hidden files as they will
9210  * also be removed) */
9211  if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
9212  continue;
9213  }
9214 
9215  mg_snprintf(
9216  conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
9217 
9218  /* If we don't memset stat structure to zero, mtime will have
9219  * garbage and strftime() will segfault later on in
9220  * print_dir_entry(). memset is required only if mg_stat()
9221  * fails. For more details, see
9222  * http://code.google.com/p/mongoose/issues/detail?id=79 */
9223  memset(&de.file, 0, sizeof(de.file));
9224 
9225  if (truncated) {
9226  /* Do not delete anything shorter */
9227  ok = 0;
9228  continue;
9229  }
9230 
9231  if (!mg_stat(conn, path, &de.file)) {
9232  mg_cry_internal(conn,
9233  "%s: mg_stat(%s) failed: %s",
9234  __func__,
9235  path,
9236  strerror(ERRNO));
9237  ok = 0;
9238  }
9239 
9240  if (de.file.is_directory) {
9241  if (remove_directory(conn, path) == 0) {
9242  ok = 0;
9243  }
9244  } else {
9245  /* This will fail file is the file is in memory */
9246  if (mg_remove(conn, path) == 0) {
9247  ok = 0;
9248  }
9249  }
9250  }
9251  (void)mg_closedir(dirp);
9252 
9253  IGNORE_UNUSED_RESULT(rmdir(dir));
9254  }
9255 
9256  return ok;
9257 }
9258 #endif
9259 
9260 
9261 struct dir_scan_data {
9262  struct de *entries;
9263  unsigned int num_entries;
9264  unsigned int arr_size;
9265 };
9266 
9267 
9268 /* Behaves like realloc(), but frees original pointer on failure */
9269 static void *
9270 realloc2(void *ptr, size_t size)
9271 {
9272  void *new_ptr = mg_realloc(ptr, size);
9273  if (new_ptr == NULL) {
9274  mg_free(ptr);
9275  }
9276  return new_ptr;
9277 }
9278 
9279 
9280 static int
9281 dir_scan_callback(struct de *de, void *data)
9282 {
9283  struct dir_scan_data *dsd = (struct dir_scan_data *)data;
9284 
9285  if ((dsd->entries == NULL) || (dsd->num_entries >= dsd->arr_size)) {
9286  dsd->arr_size *= 2;
9287  dsd->entries =
9288  (struct de *)realloc2(dsd->entries,
9289  dsd->arr_size * sizeof(dsd->entries[0]));
9290  }
9291  if (dsd->entries == NULL) {
9292  /* TODO(lsm, low): propagate an error to the caller */
9293  dsd->num_entries = 0;
9294  } else {
9295  dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
9296  dsd->entries[dsd->num_entries].file = de->file;
9297  dsd->entries[dsd->num_entries].conn = de->conn;
9298  dsd->num_entries++;
9299  }
9300 
9301  return 0;
9302 }
9303 
9304 
9305 static void
9306 handle_directory_request(struct mg_connection *conn, const char *dir)
9307 {
9308  unsigned int i;
9309  int sort_direction;
9310  struct dir_scan_data data = {NULL, 0, 128};
9311  char date[64];
9312  time_t curtime = time(NULL);
9313 
9314  if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
9315  mg_send_http_error(conn,
9316  500,
9317  "Error: Cannot open directory\nopendir(%s): %s",
9318  dir,
9319  strerror(ERRNO));
9320  return;
9321  }
9322 
9323  gmt_time_string(date, sizeof(date), &curtime);
9324 
9325  if (!conn) {
9326  return;
9327  }
9328 
9329  sort_direction = ((conn->request_info.query_string != NULL)
9330  && (conn->request_info.query_string[1] == 'd'))
9331  ? 'a'
9332  : 'd';
9333 
9334  conn->must_close = 1;
9335  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
9336  send_static_cache_header(conn);
9337  send_additional_header(conn);
9338  mg_printf(conn,
9339  "Date: %s\r\n"
9340  "Connection: close\r\n"
9341  "Content-Type: text/html; charset=utf-8\r\n\r\n",
9342  date);
9343  mg_printf(conn,
9344  "<html><head><title>Index of %s</title>"
9345  "<style>th {text-align: left;}</style></head>"
9346  "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
9347  "<tr><th><a href=\"?n%c\">Name</a></th>"
9348  "<th><a href=\"?d%c\">Modified</a></th>"
9349  "<th><a href=\"?s%c\">Size</a></th></tr>"
9350  "<tr><td colspan=\"3\"><hr></td></tr>",
9351  conn->request_info.local_uri,
9352  conn->request_info.local_uri,
9353  sort_direction,
9354  sort_direction,
9355  sort_direction);
9356 
9357  /* Print first entry - link to a parent directory */
9358  mg_printf(conn,
9359  "<tr><td><a href=\"%s%s\">%s</a></td>"
9360  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
9361  conn->request_info.local_uri,
9362  "..",
9363  "Parent directory",
9364  "-",
9365  "-");
9366 
9367  /* Sort and print directory entries */
9368  if (data.entries != NULL) {
9369  qsort(data.entries,
9370  (size_t)data.num_entries,
9371  sizeof(data.entries[0]),
9372  compare_dir_entries);
9373  for (i = 0; i < data.num_entries; i++) {
9374  print_dir_entry(&data.entries[i]);
9375  mg_free(data.entries[i].file_name);
9376  }
9377  mg_free(data.entries);
9378  }
9379 
9380  mg_printf(conn, "%s", "</table></body></html>");
9381  conn->status_code = 200;
9382 }
9383 
9384 
9385 /* Send len bytes from the opened file to the client. */
9386 static void
9387 send_file_data(struct mg_connection *conn,
9388  struct mg_file *filep,
9389  int64_t offset,
9390  int64_t len)
9391 {
9392  char buf[MG_BUF_LEN];
9393  int to_read, num_read, num_written;
9394  int64_t size;
9395 
9396  if (!filep || !conn) {
9397  return;
9398  }
9399 
9400  /* Sanity check the offset */
9401  size = (filep->stat.size > INT64_MAX) ? INT64_MAX
9402  : (int64_t)(filep->stat.size);
9403  offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
9404 
9405 #if defined(MG_USE_OPEN_FILE)
9406  if ((len > 0) && (filep->access.membuf != NULL) && (size > 0)) {
9407  /* file stored in memory */
9408  if (len > size - offset) {
9409  len = size - offset;
9410  }
9411  mg_write(conn, filep->access.membuf + offset, (size_t)len);
9412  } else /* else block below */
9413 #endif
9414  if (len > 0 && filep->access.fp != NULL) {
9415 /* file stored on disk */
9416 #if defined(__linux__)
9417  /* sendfile is only available for Linux */
9418  if ((conn->ssl == 0) && (conn->throttle == 0)
9419  && (!mg_strcasecmp(conn->dom_ctx->config[ALLOW_SENDFILE_CALL],
9420  "yes"))) {
9421  off_t sf_offs = (off_t)offset;
9422  ssize_t sf_sent;
9423  int sf_file = fileno(filep->access.fp);
9424  int loop_cnt = 0;
9425 
9426  do {
9427  /* 2147479552 (0x7FFFF000) is a limit found by experiment on
9428  * 64 bit Linux (2^31 minus one memory page of 4k?). */
9429  size_t sf_tosend =
9430  (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
9431  sf_sent =
9432  sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
9433  if (sf_sent > 0) {
9434  len -= sf_sent;
9435  offset += sf_sent;
9436  } else if (loop_cnt == 0) {
9437  /* This file can not be sent using sendfile.
9438  * This might be the case for pseudo-files in the
9439  * /sys/ and /proc/ file system.
9440  * Use the regular user mode copy code instead. */
9441  break;
9442  } else if (sf_sent == 0) {
9443  /* No error, but 0 bytes sent. May be EOF? */
9444  return;
9445  }
9446  loop_cnt++;
9447 
9448  } while ((len > 0) && (sf_sent >= 0));
9449 
9450  if (sf_sent > 0) {
9451  return; /* OK */
9452  }
9453 
9454  /* sf_sent<0 means error, thus fall back to the classic way */
9455  /* This is always the case, if sf_file is not a "normal" file,
9456  * e.g., for sending data from the output of a CGI process. */
9457  offset = (int64_t)sf_offs;
9458  }
9459 #endif
9460  if ((offset > 0) && (fseeko(filep->access.fp, offset, SEEK_SET) != 0)) {
9461  mg_cry_internal(conn,
9462  "%s: fseeko() failed: %s",
9463  __func__,
9464  strerror(ERRNO));
9465  mg_send_http_error(
9466  conn,
9467  500,
9468  "%s",
9469  "Error: Unable to access file at requested position.");
9470  } else {
9471  while (len > 0) {
9472  /* Calculate how much to read from the file in the buffer */
9473  to_read = sizeof(buf);
9474  if ((int64_t)to_read > len) {
9475  to_read = (int)len;
9476  }
9477 
9478  /* Read from file, exit the loop on error */
9479  if ((num_read =
9480  (int)fread(buf, 1, (size_t)to_read, filep->access.fp))
9481  <= 0) {
9482  break;
9483  }
9484 
9485  /* Send read bytes to the client, exit the loop on error */
9486  if ((num_written = mg_write(conn, buf, (size_t)num_read))
9487  != num_read) {
9488  break;
9489  }
9490 
9491  /* Both read and were successful, adjust counters */
9492  len -= num_written;
9493  }
9494  }
9495  }
9496 }
9497 
9498 
9499 static int
9500 parse_range_header(const char *header, int64_t *a, int64_t *b)
9501 {
9502  return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
9503 }
9504 
9505 
9506 static void
9507 construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat)
9508 {
9509  if ((filestat != NULL) && (buf != NULL)) {
9510  mg_snprintf(NULL,
9511  NULL, /* All calls to construct_etag use 64 byte buffer */
9512  buf,
9513  buf_len,
9514  "\"%lx.%" INT64_FMT "\"",
9515  (unsigned long)filestat->last_modified,
9516  filestat->size);
9517  }
9518 }
9519 
9520 
9521 static void
9522 fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
9523 {
9524  if (filep != NULL && filep->fp != NULL) {
9525 #if defined(_WIN32)
9526  (void)conn; /* Unused. */
9527 #else
9528  if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
9529  mg_cry_internal(conn,
9530  "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
9531  __func__,
9532  strerror(ERRNO));
9533  }
9534 #endif
9535  }
9536 }
9537 
9538 
9539 #if defined(USE_ZLIB)
9540 #include "mod_zlib.inl"
9541 #endif
9542 
9543 
9544 static void
9545 handle_static_file_request(struct mg_connection *conn,
9546  const char *path,
9547  struct mg_file *filep,
9548  const char *mime_type,
9549  const char *additional_headers)
9550 {
9551  char date[64], lm[64], etag[64];
9552  char range[128]; /* large enough, so there will be no overflow */
9553  const char *msg = "OK", *hdr;
9554  time_t curtime = time(NULL);
9555  int64_t cl, r1, r2;
9556  struct vec mime_vec;
9557  int n, truncated;
9558  char gz_path[PATH_MAX];
9559  const char *encoding = "";
9560  const char *cors1, *cors2, *cors3;
9561  int is_head_request;
9562 
9563 #if defined(USE_ZLIB)
9564  /* Compression is allowed, unless there is a reason not to use compression.
9565  * If the file is already compressed, too small or a "range" request was
9566  * made, on the fly compression is not possible. */
9567  int allow_on_the_fly_compression = 1;
9568 #endif
9569 
9570  if ((conn == NULL) || (conn->dom_ctx == NULL) || (filep == NULL)) {
9571  return;
9572  }
9573 
9574  is_head_request = !strcmp(conn->request_info.request_method, "HEAD");
9575 
9576  if (mime_type == NULL) {
9577  get_mime_type(conn, path, &mime_vec);
9578  } else {
9579  mime_vec.ptr = mime_type;
9580  mime_vec.len = strlen(mime_type);
9581  }
9582  if (filep->stat.size > INT64_MAX) {
9583  mg_send_http_error(conn,
9584  500,
9585  "Error: File size is too large to send\n%" INT64_FMT,
9586  filep->stat.size);
9587  return;
9588  }
9589  cl = (int64_t)filep->stat.size;
9590  conn->status_code = 200;
9591  range[0] = '\0';
9592 
9593 #if defined(USE_ZLIB)
9594  /* if this file is in fact a pre-gzipped file, rewrite its filename
9595  * it's important to rewrite the filename after resolving
9596  * the mime type from it, to preserve the actual file's type */
9597  if (!conn->accept_gzip) {
9598  allow_on_the_fly_compression = 0;
9599  }
9600 #endif
9601 
9602  if (filep->stat.is_gzipped) {
9603  mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
9604 
9605  if (truncated) {
9606  mg_send_http_error(conn,
9607  500,
9608  "Error: Path of zipped file too long (%s)",
9609  path);
9610  return;
9611  }
9612 
9613  path = gz_path;
9614  encoding = "Content-Encoding: gzip\r\n";
9615 
9616 #if defined(USE_ZLIB)
9617  /* File is already compressed. No "on the fly" compression. */
9618  allow_on_the_fly_compression = 0;
9619 #endif
9620  }
9621 
9622  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
9623  mg_send_http_error(conn,
9624  500,
9625  "Error: Cannot open file\nfopen(%s): %s",
9626  path,
9627  strerror(ERRNO));
9628  return;
9629  }
9630 
9631  fclose_on_exec(&filep->access, conn);
9632 
9633  /* If "Range" request was made: parse header, send only selected part
9634  * of the file. */
9635  r1 = r2 = 0;
9636  hdr = mg_get_header(conn, "Range");
9637  if ((hdr != NULL) && ((n = parse_range_header(hdr, &r1, &r2)) > 0)
9638  && (r1 >= 0) && (r2 >= 0)) {
9639  /* actually, range requests don't play well with a pre-gzipped
9640  * file (since the range is specified in the uncompressed space) */
9641  if (filep->stat.is_gzipped) {
9642  mg_send_http_error(
9643  conn,
9644  416, /* 416 = Range Not Satisfiable */
9645  "%s",
9646  "Error: Range requests in gzipped files are not supported");
9647  (void)mg_fclose(
9648  &filep->access); /* ignore error on read only file */
9649  return;
9650  }
9651  conn->status_code = 206;
9652  cl = (n == 2) ? (((r2 > cl) ? cl : r2) - r1 + 1) : (cl - r1);
9653  mg_snprintf(conn,
9654  NULL, /* range buffer is big enough */
9655  range,
9656  sizeof(range),
9657  "Content-Range: bytes "
9658  "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
9659  r1,
9660  r1 + cl - 1,
9661  filep->stat.size);
9662  msg = "Partial Content";
9663 
9664 #if defined(USE_ZLIB)
9665  /* Do not compress ranges. */
9666  allow_on_the_fly_compression = 0;
9667 #endif
9668  }
9669 
9670 /* Do not compress small files. Small files do not benefit from file
9671  * compression, but there is still some overhead. */
9672 #if defined(USE_ZLIB)
9673  if (filep->stat.size < MG_FILE_COMPRESSION_SIZE_LIMIT) {
9674  /* File is below the size limit. */
9675  allow_on_the_fly_compression = 0;
9676  }
9677 #endif
9678 
9679  /* Standard CORS header */
9680  hdr = mg_get_header(conn, "Origin");
9681  if (hdr) {
9682  /* Cross-origin resource sharing (CORS), see
9683  * http://www.html5rocks.com/en/tutorials/cors/,
9684  * http://www.html5rocks.com/static/images/cors_server_flowchart.png
9685  * -
9686  * preflight is not supported for files. */
9687  cors1 = "Access-Control-Allow-Origin: ";
9688  cors2 = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
9689  cors3 = "\r\n";
9690  } else {
9691  cors1 = cors2 = cors3 = "";
9692  }
9693 
9694  /* Prepare Etag, Date, Last-Modified headers. Must be in UTC,
9695  * according to
9696  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
9697  gmt_time_string(date, sizeof(date), &curtime);
9698  gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
9699  construct_etag(etag, sizeof(etag), &filep->stat);
9700 
9701  /* Send header */
9702  (void)mg_printf(conn,
9703  "HTTP/1.1 %d %s\r\n"
9704  "%s%s%s" /* CORS */
9705  "Date: %s\r\n"
9706  "Last-Modified: %s\r\n"
9707  "Etag: %s\r\n"
9708  "Content-Type: %.*s\r\n"
9709  "Connection: %s\r\n",
9710  conn->status_code,
9711  msg,
9712  cors1,
9713  cors2,
9714  cors3,
9715  date,
9716  lm,
9717  etag,
9718  (int)mime_vec.len,
9719  mime_vec.ptr,
9720  suggest_connection_header(conn));
9721  send_static_cache_header(conn);
9722  send_additional_header(conn);
9723 
9724 #if defined(USE_ZLIB)
9725  /* On the fly compression allowed */
9726  if (allow_on_the_fly_compression) {
9727  /* For on the fly compression, we don't know the content size in
9728  * advance, so we have to use chunked encoding */
9729  (void)mg_printf(conn,
9730  "Content-Encoding: gzip\r\n"
9731  "Transfer-Encoding: chunked\r\n");
9732  } else
9733 #endif
9734  {
9735  /* Without on-the-fly compression, we know the content-length
9736  * and we can use ranges (with on-the-fly compression we cannot).
9737  * So we send these response headers only in this case. */
9738  (void)mg_printf(conn,
9739  "Content-Length: %" INT64_FMT "\r\n"
9740  "Accept-Ranges: bytes\r\n"
9741  "%s" /* range */
9742  "%s" /* encoding */,
9743  cl,
9744  range,
9745  encoding);
9746  }
9747 
9748  /* The previous code must not add any header starting with X- to make
9749  * sure no one of the additional_headers is included twice */
9750  if (additional_headers != NULL) {
9751  (void)mg_printf(conn,
9752  "%.*s\r\n\r\n",
9753  (int)strlen(additional_headers),
9754  additional_headers);
9755  } else {
9756  (void)mg_printf(conn, "\r\n");
9757  }
9758 
9759  if (!is_head_request) {
9760 #if defined(USE_ZLIB)
9761  if (allow_on_the_fly_compression) {
9762  /* Compress and send */
9763  send_compressed_data(conn, filep);
9764  } else
9765 #endif
9766  {
9767  /* Send file directly */
9768  send_file_data(conn, filep, r1, cl);
9769  }
9770  }
9771  (void)mg_fclose(&filep->access); /* ignore error on read only file */
9772 }
9773 
9774 
9775 int
9776 mg_send_file_body(struct mg_connection *conn, const char *path)
9777 {
9778  struct mg_file file = STRUCT_FILE_INITIALIZER;
9779  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) {
9780  return -1;
9781  }
9782  fclose_on_exec(&file.access, conn);
9783  send_file_data(conn, &file, 0, INT64_MAX);
9784  (void)mg_fclose(&file.access); /* Ignore errors for readonly files */
9785  return 0; /* >= 0 for OK */
9786 }
9787 
9788 
9789 #if !defined(NO_CACHING)
9790 /* Return True if we should reply 304 Not Modified. */
9791 static int
9792 is_not_modified(const struct mg_connection *conn,
9793  const struct mg_file_stat *filestat)
9794 {
9795  char etag[64];
9796  const char *ims = mg_get_header(conn, "If-Modified-Since");
9797  const char *inm = mg_get_header(conn, "If-None-Match");
9798  construct_etag(etag, sizeof(etag), filestat);
9799 
9800  return ((inm != NULL) && !mg_strcasecmp(etag, inm))
9801  || ((ims != NULL)
9802  && (filestat->last_modified <= parse_date_string(ims)));
9803 }
9804 
9805 static void
9806 handle_not_modified_static_file_request(struct mg_connection *conn,
9807  struct mg_file *filep)
9808 {
9809  char date[64], lm[64], etag[64];
9810  time_t curtime = time(NULL);
9811 
9812  if ((conn == NULL) || (filep == NULL)) {
9813  return;
9814  }
9815  conn->status_code = 304;
9816  gmt_time_string(date, sizeof(date), &curtime);
9817  gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
9818  construct_etag(etag, sizeof(etag), &filep->stat);
9819 
9820  (void)mg_printf(conn,
9821  "HTTP/1.1 %d %s\r\n"
9822  "Date: %s\r\n",
9823  conn->status_code,
9824  mg_get_response_code_text(conn, conn->status_code),
9825  date);
9826  send_static_cache_header(conn);
9827  send_additional_header(conn);
9828  (void)mg_printf(conn,
9829  "Last-Modified: %s\r\n"
9830  "Etag: %s\r\n"
9831  "Connection: %s\r\n"
9832  "\r\n",
9833  lm,
9834  etag,
9835  suggest_connection_header(conn));
9836 }
9837 #endif
9838 
9839 
9840 void
9841 mg_send_file(struct mg_connection *conn, const char *path)
9842 {
9843  mg_send_mime_file2(conn, path, NULL, NULL);
9844 }
9845 
9846 
9847 void
9848 mg_send_mime_file(struct mg_connection *conn,
9849  const char *path,
9850  const char *mime_type)
9851 {
9852  mg_send_mime_file2(conn, path, mime_type, NULL);
9853 }
9854 
9855 
9856 void
9857 mg_send_mime_file2(struct mg_connection *conn,
9858  const char *path,
9859  const char *mime_type,
9860  const char *additional_headers)
9861 {
9862  struct mg_file file = STRUCT_FILE_INITIALIZER;
9863 
9864  if (!conn) {
9865  /* No conn */
9866  return;
9867  }
9868 
9869  if (mg_stat(conn, path, &file.stat)) {
9870 #if !defined(NO_CACHING)
9871  if (is_not_modified(conn, &file.stat)) {
9872  /* Send 304 "Not Modified" - this must not send any body data */
9873  handle_not_modified_static_file_request(conn, &file);
9874  } else
9875 #endif /* NO_CACHING */
9876  if (file.stat.is_directory) {
9877  if (!mg_strcasecmp(conn->dom_ctx->config[ENABLE_DIRECTORY_LISTING],
9878  "yes")) {
9879  handle_directory_request(conn, path);
9880  } else {
9881  mg_send_http_error(conn,
9882  403,
9883  "%s",
9884  "Error: Directory listing denied");
9885  }
9886  } else {
9887  handle_static_file_request(
9888  conn, path, &file, mime_type, additional_headers);
9889  }
9890  } else {
9891  mg_send_http_error(conn, 404, "%s", "Error: File not found");
9892  }
9893 }
9894 
9895 
9896 /* For a given PUT path, create all intermediate subdirectories.
9897  * Return 0 if the path itself is a directory.
9898  * Return 1 if the path leads to a file.
9899  * Return -1 for if the path is too long.
9900  * Return -2 if path can not be created.
9901  */
9902 static int
9903 put_dir(struct mg_connection *conn, const char *path)
9904 {
9905  char buf[PATH_MAX];
9906  const char *s, *p;
9907  struct mg_file file = STRUCT_FILE_INITIALIZER;
9908  size_t len;
9909  int res = 1;
9910 
9911  for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
9912  len = (size_t)(p - path);
9913  if (len >= sizeof(buf)) {
9914  /* path too long */
9915  res = -1;
9916  break;
9917  }
9918  memcpy(buf, path, len);
9919  buf[len] = '\0';
9920 
9921  /* Try to create intermediate directory */
9922  DEBUG_TRACE("mkdir(%s)", buf);
9923  if (!mg_stat(conn, buf, &file.stat) && mg_mkdir(conn, buf, 0755) != 0) {
9924  /* path does not exixt and can not be created */
9925  res = -2;
9926  break;
9927  }
9928 
9929  /* Is path itself a directory? */
9930  if (p[1] == '\0') {
9931  res = 0;
9932  }
9933  }
9934 
9935  return res;
9936 }
9937 
9938 
9939 static void
9940 remove_bad_file(const struct mg_connection *conn, const char *path)
9941 {
9942  int r = mg_remove(conn, path);
9943  if (r != 0) {
9944  mg_cry_internal(conn,
9945  "%s: Cannot remove invalid file %s",
9946  __func__,
9947  path);
9948  }
9949 }
9950 
9951 
9952 long long
9953 mg_store_body(struct mg_connection *conn, const char *path)
9954 {
9955  char buf[MG_BUF_LEN];
9956  long long len = 0;
9957  int ret, n;
9958  struct mg_file fi;
9959 
9960  if (conn->consumed_content != 0) {
9961  mg_cry_internal(conn, "%s: Contents already consumed", __func__);
9962  return -11;
9963  }
9964 
9965  ret = put_dir(conn, path);
9966  if (ret < 0) {
9967  /* -1 for path too long,
9968  * -2 for path can not be created. */
9969  return ret;
9970  }
9971  if (ret != 1) {
9972  /* Return 0 means, path itself is a directory. */
9973  return 0;
9974  }
9975 
9976  if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fi) == 0) {
9977  return -12;
9978  }
9979 
9980  ret = mg_read(conn, buf, sizeof(buf));
9981  while (ret > 0) {
9982  n = (int)fwrite(buf, 1, (size_t)ret, fi.access.fp);
9983  if (n != ret) {
9984  (void)mg_fclose(
9985  &fi.access); /* File is bad and will be removed anyway. */
9986  remove_bad_file(conn, path);
9987  return -13;
9988  }
9989  len += ret;
9990  ret = mg_read(conn, buf, sizeof(buf));
9991  }
9992 
9993  /* File is open for writing. If fclose fails, there was probably an
9994  * error flushing the buffer to disk, so the file on disk might be
9995  * broken. Delete it and return an error to the caller. */
9996  if (mg_fclose(&fi.access) != 0) {
9997  remove_bad_file(conn, path);
9998  return -14;
9999  }
10000 
10001  return len;
10002 }
10003 
10004 
10005 /* Parse a buffer:
10006  * Forward the string pointer till the end of a word, then
10007  * terminate it and forward till the begin of the next word.
10008  */
10009 static int
10010 skip_to_end_of_word_and_terminate(char **ppw, int eol)
10011 {
10012  /* Forward until a space is found - use isgraph here */
10013  /* See http://www.cplusplus.com/reference/cctype/ */
10014  while (isgraph(**ppw)) {
10015  (*ppw)++;
10016  }
10017 
10018  /* Check end of word */
10019  if (eol) {
10020  /* must be a end of line */
10021  if ((**ppw != '\r') && (**ppw != '\n')) {
10022  return -1;
10023  }
10024  } else {
10025  /* must be a end of a word, but not a line */
10026  if (**ppw != ' ') {
10027  return -1;
10028  }
10029  }
10030 
10031  /* Terminate and forward to the next word */
10032  do {
10033  **ppw = 0;
10034  (*ppw)++;
10035  } while ((**ppw) && isspace(**ppw));
10036 
10037  /* Check after term */
10038  if (!eol) {
10039  /* if it's not the end of line, there must be a next word */
10040  if (!isgraph(**ppw)) {
10041  return -1;
10042  }
10043  }
10044 
10045  /* ok */
10046  return 1;
10047 }
10048 
10049 
10050 /* Parse HTTP headers from the given buffer, advance buf pointer
10051  * to the point where parsing stopped.
10052  * All parameters must be valid pointers (not NULL).
10053  * Return <0 on error. */
10054 static int
10055 parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS])
10056 {
10057  int i;
10058  int num_headers = 0;
10059 
10060  for (i = 0; i < (int)MG_MAX_HEADERS; i++) {
10061  char *dp = *buf;
10062  while ((*dp != ':') && (*dp >= 33) && (*dp <= 126)) {
10063  dp++;
10064  }
10065  if (dp == *buf) {
10066  /* End of headers reached. */
10067  break;
10068  }
10069  if (*dp != ':') {
10070  /* This is not a valid field. */
10071  return -1;
10072  }
10073 
10074  /* End of header key (*dp == ':') */
10075  /* Truncate here and set the key name */
10076  *dp = 0;
10077  hdr[i].name = *buf;
10078  do {
10079  dp++;
10080  } while (*dp == ' ');
10081 
10082  /* The rest of the line is the value */
10083  hdr[i].value = dp;
10084  *buf = dp + strcspn(dp, "\r\n");
10085  if (((*buf)[0] != '\r') || ((*buf)[1] != '\n')) {
10086  *buf = NULL;
10087  }
10088 
10089  num_headers = i + 1;
10090  if (*buf) {
10091  (*buf)[0] = 0;
10092  (*buf)[1] = 0;
10093  *buf += 2;
10094  } else {
10095  *buf = dp;
10096  break;
10097  }
10098 
10099  if ((*buf)[0] == '\r') {
10100  /* This is the end of the header */
10101  break;
10102  }
10103  }
10104  return num_headers;
10105 }
10106 
10107 
10108 struct mg_http_method_info {
10109  const char *name;
10110  int request_has_body;
10111  int response_has_body;
10112  int is_safe;
10113  int is_idempotent;
10114  int is_cacheable;
10115 };
10116 
10117 
10118 /* https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods */
10119 static struct mg_http_method_info http_methods[] = {
10120  /* HTTP (RFC 2616) */
10121  {"GET", 0, 1, 1, 1, 1},
10122  {"POST", 1, 1, 0, 0, 0},
10123  {"PUT", 1, 0, 0, 1, 0},
10124  {"DELETE", 0, 0, 0, 1, 0},
10125  {"HEAD", 0, 0, 1, 1, 1},
10126  {"OPTIONS", 0, 0, 1, 1, 0},
10127  {"CONNECT", 1, 1, 0, 0, 0},
10128  /* TRACE method (RFC 2616) is not supported for security reasons */
10129 
10130  /* PATCH method (RFC 5789) */
10131  {"PATCH", 1, 0, 0, 0, 0},
10132  /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
10133 
10134  /* WEBDAV (RFC 2518) */
10135  {"PROPFIND", 0, 1, 1, 1, 0},
10136  /* http://www.webdav.org/specs/rfc4918.html, 9.1:
10137  * Some PROPFIND results MAY be cached, with care,
10138  * as there is no cache validation mechanism for
10139  * most properties. This method is both safe and
10140  * idempotent (see Section 9.1 of [RFC2616]). */
10141  {"MKCOL", 0, 0, 0, 1, 0},
10142  /* http://www.webdav.org/specs/rfc4918.html, 9.1:
10143  * When MKCOL is invoked without a request body,
10144  * the newly created collection SHOULD have no
10145  * members. A MKCOL request message may contain
10146  * a message body. The precise behavior of a MKCOL
10147  * request when the body is present is undefined,
10148  * ... ==> We do not support MKCOL with body data.
10149  * This method is idempotent, but not safe (see
10150  * Section 9.1 of [RFC2616]). Responses to this
10151  * method MUST NOT be cached. */
10152 
10153  /* Unsupported WEBDAV Methods: */
10154  /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
10155  /* + 11 methods from RFC 3253 */
10156  /* ORDERPATCH (RFC 3648) */
10157  /* ACL (RFC 3744) */
10158  /* SEARCH (RFC 5323) */
10159  /* + MicroSoft extensions
10160  * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
10161 
10162  /* REPORT method (RFC 3253) */
10163  {"REPORT", 1, 1, 1, 1, 1},
10164  /* REPORT method only allowed for CGI/Lua/LSP and callbacks. */
10165  /* It was defined for WEBDAV in RFC 3253, Sec. 3.6
10166  * (https://tools.ietf.org/html/rfc3253#section-3.6), but seems
10167  * to be useful for REST in case a "GET request with body" is
10168  * required. */
10169 
10170  {NULL, 0, 0, 0, 0, 0}
10171  /* end of list */
10172 };
10173 
10174 
10175 static const struct mg_http_method_info *
10176 get_http_method_info(const char *method)
10177 {
10178  /* Check if the method is known to the server. The list of all known
10179  * HTTP methods can be found here at
10180  * http://www.iana.org/assignments/http-methods/http-methods.xhtml
10181  */
10182  const struct mg_http_method_info *m = http_methods;
10183 
10184  while (m->name) {
10185  if (!strcmp(m->name, method)) {
10186  return m;
10187  }
10188  m++;
10189  }
10190  return NULL;
10191 }
10192 
10193 
10194 static int
10195 is_valid_http_method(const char *method)
10196 {
10197  return (get_http_method_info(method) != NULL);
10198 }
10199 
10200 
10201 /* Parse HTTP request, fill in mg_request_info structure.
10202  * This function modifies the buffer by NUL-terminating
10203  * HTTP request components, header names and header values.
10204  * Parameters:
10205  * buf (in/out): pointer to the HTTP header to parse and split
10206  * len (in): length of HTTP header buffer
10207  * re (out): parsed header as mg_request_info
10208  * buf and ri must be valid pointers (not NULL), len>0.
10209  * Returns <0 on error. */
10210 static int
10211 parse_http_request(char *buf, int len, struct mg_request_info *ri)
10212 {
10213  int request_length;
10214  int init_skip = 0;
10215 
10216  /* Reset attributes. DO NOT TOUCH is_ssl, remote_addr,
10217  * remote_port */
10218  ri->remote_user = ri->request_method = ri->request_uri = ri->http_version =
10219  NULL;
10220  ri->num_headers = 0;
10221 
10222  /* RFC says that all initial whitespaces should be ingored */
10223  /* This included all leading \r and \n (isspace) */
10224  /* See table: http://www.cplusplus.com/reference/cctype/ */
10225  while ((len > 0) && isspace(*(unsigned char *)buf)) {
10226  buf++;
10227  len--;
10228  init_skip++;
10229  }
10230 
10231  if (len == 0) {
10232  /* Incomplete request */
10233  return 0;
10234  }
10235 
10236  /* Control characters are not allowed, including zero */
10237  if (iscntrl(*(unsigned char *)buf)) {
10238  return -1;
10239  }
10240 
10241  /* Find end of HTTP header */
10242  request_length = get_http_header_len(buf, len);
10243  if (request_length <= 0) {
10244  return request_length;
10245  }
10246  buf[request_length - 1] = '\0';
10247 
10248  if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) {
10249  return -1;
10250  }
10251 
10252  /* The first word has to be the HTTP method */
10253  ri->request_method = buf;
10254 
10255  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
10256  return -1;
10257  }
10258 
10259  /* Check for a valid http method */
10260  if (!is_valid_http_method(ri->request_method)) {
10261  return -1;
10262  }
10263 
10264  /* The second word is the URI */
10265  ri->request_uri = buf;
10266 
10267  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
10268  return -1;
10269  }
10270 
10271  /* Next would be the HTTP version */
10272  ri->http_version = buf;
10273 
10274  if (skip_to_end_of_word_and_terminate(&buf, 1) <= 0) {
10275  return -1;
10276  }
10277 
10278  /* Check for a valid HTTP version key */
10279  if (strncmp(ri->http_version, "HTTP/", 5) != 0) {
10280  /* Invalid request */
10281  return -1;
10282  }
10283  ri->http_version += 5;
10284 
10285 
10286  /* Parse all HTTP headers */
10287  ri->num_headers = parse_http_headers(&buf, ri->http_headers);
10288  if (ri->num_headers < 0) {
10289  /* Error while parsing headers */
10290  return -1;
10291  }
10292 
10293  return request_length + init_skip;
10294 }
10295 
10296 
10297 static int
10298 parse_http_response(char *buf, int len, struct mg_response_info *ri)
10299 {
10300  int response_length;
10301  int init_skip = 0;
10302  char *tmp, *tmp2;
10303  long l;
10304 
10305  /* Initialize elements. */
10306  ri->http_version = ri->status_text = NULL;
10307  ri->num_headers = ri->status_code = 0;
10308 
10309  /* RFC says that all initial whitespaces should be ingored */
10310  /* This included all leading \r and \n (isspace) */
10311  /* See table: http://www.cplusplus.com/reference/cctype/ */
10312  while ((len > 0) && isspace(*(unsigned char *)buf)) {
10313  buf++;
10314  len--;
10315  init_skip++;
10316  }
10317 
10318  if (len == 0) {
10319  /* Incomplete request */
10320  return 0;
10321  }
10322 
10323  /* Control characters are not allowed, including zero */
10324  if (iscntrl(*(unsigned char *)buf)) {
10325  return -1;
10326  }
10327 
10328  /* Find end of HTTP header */
10329  response_length = get_http_header_len(buf, len);
10330  if (response_length <= 0) {
10331  return response_length;
10332  }
10333  buf[response_length - 1] = '\0';
10334 
10335  if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) {
10336  return -1;
10337  }
10338 
10339  /* The first word is the HTTP version */
10340  /* Check for a valid HTTP version key */
10341  if (strncmp(buf, "HTTP/", 5) != 0) {
10342  /* Invalid request */
10343  return -1;
10344  }
10345  buf += 5;
10346  if (!isgraph(buf[0])) {
10347  /* Invalid request */
10348  return -1;
10349  }
10350  ri->http_version = buf;
10351 
10352  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
10353  return -1;
10354  }
10355 
10356  /* The second word is the status as a number */
10357  tmp = buf;
10358 
10359  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
10360  return -1;
10361  }
10362 
10363  l = strtol(tmp, &tmp2, 10);
10364  if ((l < 100) || (l >= 1000) || ((tmp2 - tmp) != 3) || (*tmp2 != 0)) {
10365  /* Everything else but a 3 digit code is invalid */
10366  return -1;
10367  }
10368  ri->status_code = (int)l;
10369 
10370  /* The rest of the line is the status text */
10371  ri->status_text = buf;
10372 
10373  /* Find end of status text */
10374  /* isgraph or isspace = isprint */
10375  while (isprint(*buf)) {
10376  buf++;
10377  }
10378  if ((*buf != '\r') && (*buf != '\n')) {
10379  return -1;
10380  }
10381  /* Terminate string and forward buf to next line */
10382  do {
10383  *buf = 0;
10384  buf++;
10385  } while ((*buf) && isspace(*buf));
10386 
10387 
10388  /* Parse all HTTP headers */
10389  ri->num_headers = parse_http_headers(&buf, ri->http_headers);
10390  if (ri->num_headers < 0) {
10391  /* Error while parsing headers */
10392  return -1;
10393  }
10394 
10395  return response_length + init_skip;
10396 }
10397 
10398 
10399 /* Keep reading the input (either opened file descriptor fd, or socket sock,
10400  * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
10401  * buffer (which marks the end of HTTP request). Buffer buf may already
10402  * have some data. The length of the data is stored in nread.
10403  * Upon every read operation, increase nread by the number of bytes read. */
10404 static int
10405 read_message(FILE *fp,
10406  struct mg_connection *conn,
10407  char *buf,
10408  int bufsiz,
10409  int *nread)
10410 {
10411  int request_len, n = 0;
10412  struct timespec last_action_time;
10413  double request_timeout;
10414 
10415  if (!conn) {
10416  return 0;
10417  }
10418 
10419  memset(&last_action_time, 0, sizeof(last_action_time));
10420 
10421  if (conn->dom_ctx->config[REQUEST_TIMEOUT]) {
10422  /* value of request_timeout is in seconds, config in milliseconds */
10423  request_timeout = atof(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0;
10424  } else {
10425  request_timeout = -1.0;
10426  }
10427  if (conn->handled_requests > 0) {
10428  if (conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT]) {
10429  request_timeout =
10430  atof(conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT]) / 1000.0;
10431  }
10432  }
10433 
10434  request_len = get_http_header_len(buf, *nread);
10435 
10436  /* first time reading from this connection */
10437  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
10438 
10439  while (request_len == 0) {
10440  /* Full request not yet received */
10441  if (conn->phys_ctx->stop_flag != 0) {
10442  /* Server is to be stopped. */
10443  return -1;
10444  }
10445 
10446  if (*nread >= bufsiz) {
10447  /* Request too long */
10448  return -2;
10449  }
10450 
10451  n = pull_inner(
10452  fp, conn, buf + *nread, bufsiz - *nread, request_timeout);
10453  if (n == -2) {
10454  /* Receive error */
10455  return -1;
10456  }
10457  if (n > 0) {
10458  *nread += n;
10459  request_len = get_http_header_len(buf, *nread);
10460  } else {
10461  request_len = 0;
10462  }
10463 
10464  if ((request_len == 0) && (request_timeout >= 0)) {
10465  if (mg_difftimespec(&last_action_time, &(conn->req_time))
10466  > request_timeout) {
10467  /* Timeout */
10468  return -1;
10469  }
10470  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
10471  }
10472  }
10473 
10474  return request_len;
10475 }
10476 
10477 
10478 #if !defined(NO_CGI) || !defined(NO_FILES)
10479 static int
10480 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
10481 {
10482  const char *expect, *body;
10483  char buf[MG_BUF_LEN];
10484  int to_read, nread, success = 0;
10485  int64_t buffered_len;
10486  double timeout = -1.0;
10487 
10488  if (!conn) {
10489  return 0;
10490  }
10491  if (conn->dom_ctx->config[REQUEST_TIMEOUT]) {
10492  timeout = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0;
10493  }
10494 
10495  expect = mg_get_header(conn, "Expect");
10496  DEBUG_ASSERT(fp != NULL);
10497  if (!fp) {
10498  mg_send_http_error(conn, 500, "%s", "Error: NULL File");
10499  return 0;
10500  }
10501 
10502  if ((conn->content_len == -1) && (!conn->is_chunked)) {
10503  /* Content length is not specified by the client. */
10504  mg_send_http_error(conn,
10505  411,
10506  "%s",
10507  "Error: Client did not specify content length");
10508  } else if ((expect != NULL)
10509  && (mg_strcasecmp(expect, "100-continue") != 0)) {
10510  /* Client sent an "Expect: xyz" header and xyz is not 100-continue.
10511  */
10512  mg_send_http_error(conn,
10513  417,
10514  "Error: Can not fulfill expectation %s",
10515  expect);
10516  } else {
10517  if (expect != NULL) {
10518  (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
10519  conn->status_code = 100;
10520  } else {
10521  conn->status_code = 200;
10522  }
10523 
10524  buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
10525  - conn->consumed_content;
10526 
10527  DEBUG_ASSERT(buffered_len >= 0);
10528  DEBUG_ASSERT(conn->consumed_content == 0);
10529 
10530  if ((buffered_len < 0) || (conn->consumed_content != 0)) {
10531  mg_send_http_error(conn, 500, "%s", "Error: Size mismatch");
10532  return 0;
10533  }
10534 
10535  if (buffered_len > 0) {
10536  if ((int64_t)buffered_len > conn->content_len) {
10537  buffered_len = (int)conn->content_len;
10538  }
10539  body = conn->buf + conn->request_len + conn->consumed_content;
10540  push_all(
10541  conn->phys_ctx, fp, sock, ssl, body, (int64_t)buffered_len);
10542  conn->consumed_content += buffered_len;
10543  }
10544 
10545  nread = 0;
10546  while (conn->consumed_content < conn->content_len) {
10547  to_read = sizeof(buf);
10548  if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
10549  to_read = (int)(conn->content_len - conn->consumed_content);
10550  }
10551  nread = pull_inner(NULL, conn, buf, to_read, timeout);
10552  if (nread == -2) {
10553  /* error */
10554  break;
10555  }
10556  if (nread > 0) {
10557  if (push_all(conn->phys_ctx, fp, sock, ssl, buf, nread)
10558  != nread) {
10559  break;
10560  }
10561  }
10562  conn->consumed_content += nread;
10563  }
10564 
10565  if (conn->consumed_content == conn->content_len) {
10566  success = (nread >= 0);
10567  }
10568 
10569  /* Each error code path in this function must send an error */
10570  if (!success) {
10571  /* NOTE: Maybe some data has already been sent. */
10572  /* TODO (low): If some data has been sent, a correct error
10573  * reply can no longer be sent, so just close the connection */
10574  mg_send_http_error(conn, 500, "%s", "");
10575  }
10576  }
10577 
10578  return success;
10579 }
10580 #endif
10581 
10582 
10583 #if defined(USE_TIMERS)
10584 
10585 #define TIMER_API static
10586 #include "timer.inl"
10587 
10588 #endif /* USE_TIMERS */
10589 
10590 
10591 #if !defined(NO_CGI)
10592 /* This structure helps to create an environment for the spawned CGI
10593  * program.
10594  * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
10595  * last element must be NULL.
10596  * However, on Windows there is a requirement that all these
10597  * VARIABLE=VALUE\0
10598  * strings must reside in a contiguous buffer. The end of the buffer is
10599  * marked by two '\0' characters.
10600  * We satisfy both worlds: we create an envp array (which is vars), all
10601  * entries are actually pointers inside buf. */
10602 struct cgi_environment {
10603  struct mg_connection *conn;
10604  /* Data block */
10605  char *buf; /* Environment buffer */
10606  size_t buflen; /* Space available in buf */
10607  size_t bufused; /* Space taken in buf */
10608  /* Index block */
10609  char **var; /* char **envp */
10610  size_t varlen; /* Number of variables available in var */
10611  size_t varused; /* Number of variables stored in var */
10612 };
10613 
10614 
10615 static void addenv(struct cgi_environment *env,
10616  PRINTF_FORMAT_STRING(const char *fmt),
10617  ...) PRINTF_ARGS(2, 3);
10618 
10619 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
10620  * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
10621 static void
10622 addenv(struct cgi_environment *env, const char *fmt, ...)
10623 {
10624  size_t n, space;
10625  int truncated = 0;
10626  char *added;
10627  va_list ap;
10628 
10629  /* Calculate how much space is left in the buffer */
10630  space = (env->buflen - env->bufused);
10631 
10632  /* Calculate an estimate for the required space */
10633  n = strlen(fmt) + 2 + 128;
10634 
10635  do {
10636  if (space <= n) {
10637  /* Allocate new buffer */
10638  n = env->buflen + CGI_ENVIRONMENT_SIZE;
10639  added = (char *)mg_realloc_ctx(env->buf, n, env->conn->phys_ctx);
10640  if (!added) {
10641  /* Out of memory */
10642  mg_cry_internal(
10643  env->conn,
10644  "%s: Cannot allocate memory for CGI variable [%s]",
10645  __func__,
10646  fmt);
10647  return;
10648  }
10649  env->buf = added;
10650  env->buflen = n;
10651  space = (env->buflen - env->bufused);
10652  }
10653 
10654  /* Make a pointer to the free space int the buffer */
10655  added = env->buf + env->bufused;
10656 
10657  /* Copy VARIABLE=VALUE\0 string into the free space */
10658  va_start(ap, fmt);
10659  mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
10660  va_end(ap);
10661 
10662  /* Do not add truncated strings to the environment */
10663  if (truncated) {
10664  /* Reallocate the buffer */
10665  space = 0;
10666  n = 1;
10667  }
10668  } while (truncated);
10669 
10670  /* Calculate number of bytes added to the environment */
10671  n = strlen(added) + 1;
10672  env->bufused += n;
10673 
10674  /* Now update the variable index */
10675  space = (env->varlen - env->varused);
10676  if (space < 2) {
10677  mg_cry_internal(env->conn,
10678  "%s: Cannot register CGI variable [%s]",
10679  __func__,
10680  fmt);
10681  return;
10682  }
10683 
10684  /* Append a pointer to the added string into the envp array */
10685  env->var[env->varused] = added;
10686  env->varused++;
10687 }
10688 
10689 /* Return 0 on success, non-zero if an error occurs. */
10690 
10691 static int
10692 prepare_cgi_environment(struct mg_connection *conn,
10693  const char *prog,
10694  struct cgi_environment *env)
10695 {
10696  const char *s;
10697  struct vec var_vec;
10698  char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
10699  int i, truncated, uri_len;
10700 
10701  if ((conn == NULL) || (prog == NULL) || (env == NULL)) {
10702  return -1;
10703  }
10704 
10705  env->conn = conn;
10706  env->buflen = CGI_ENVIRONMENT_SIZE;
10707  env->bufused = 0;
10708  env->buf = (char *)mg_malloc_ctx(env->buflen, conn->phys_ctx);
10709  if (env->buf == NULL) {
10710  mg_cry_internal(conn,
10711  "%s: Not enough memory for environmental buffer",
10712  __func__);
10713  return -1;
10714  }
10715  env->varlen = MAX_CGI_ENVIR_VARS;
10716  env->varused = 0;
10717  env->var =
10718  (char **)mg_malloc_ctx(env->buflen * sizeof(char *), conn->phys_ctx);
10719  if (env->var == NULL) {
10720  mg_cry_internal(conn,
10721  "%s: Not enough memory for environmental variables",
10722  __func__);
10723  mg_free(env->buf);
10724  return -1;
10725  }
10726 
10727  addenv(env, "SERVER_NAME=%s", conn->dom_ctx->config[AUTHENTICATION_DOMAIN]);
10728  addenv(env, "SERVER_ROOT=%s", conn->dom_ctx->config[DOCUMENT_ROOT]);
10729  addenv(env, "DOCUMENT_ROOT=%s", conn->dom_ctx->config[DOCUMENT_ROOT]);
10730  addenv(env, "SERVER_SOFTWARE=CivetWeb/%s", mg_version());
10731 
10732  /* Prepare the environment block */
10733  addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
10734  addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
10735  addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
10736 
10737 #if defined(USE_IPV6)
10738  if (conn->client.lsa.sa.sa_family == AF_INET6) {
10739  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
10740  } else
10741 #endif
10742  {
10743  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
10744  }
10745 
10746  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
10747  addenv(env, "REMOTE_ADDR=%s", src_addr);
10748 
10749  addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
10750  addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
10751 
10752  addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
10753  addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
10754 
10755  /* SCRIPT_NAME */
10756  uri_len = (int)strlen(conn->request_info.local_uri);
10757  if (conn->path_info == NULL) {
10758  if (conn->request_info.local_uri[uri_len - 1] != '/') {
10759  /* URI: /path_to_script/script.cgi */
10760  addenv(env, "SCRIPT_NAME=%s", conn->request_info.local_uri);
10761  } else {
10762  /* URI: /path_to_script/ ... using index.cgi */
10763  const char *index_file = strrchr(prog, '/');
10764  if (index_file) {
10765  addenv(env,
10766  "SCRIPT_NAME=%s%s",
10767  conn->request_info.local_uri,
10768  index_file + 1);
10769  }
10770  }
10771  } else {
10772  /* URI: /path_to_script/script.cgi/path_info */
10773  addenv(env,
10774  "SCRIPT_NAME=%.*s",
10775  uri_len - (int)strlen(conn->path_info),
10776  conn->request_info.local_uri);
10777  }
10778 
10779  addenv(env, "SCRIPT_FILENAME=%s", prog);
10780  if (conn->path_info == NULL) {
10781  addenv(env, "PATH_TRANSLATED=%s", conn->dom_ctx->config[DOCUMENT_ROOT]);
10782  } else {
10783  addenv(env,
10784  "PATH_TRANSLATED=%s%s",
10785  conn->dom_ctx->config[DOCUMENT_ROOT],
10786  conn->path_info);
10787  }
10788 
10789  addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on");
10790 
10791  if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
10792  addenv(env, "CONTENT_TYPE=%s", s);
10793  }
10794  if (conn->request_info.query_string != NULL) {
10795  addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
10796  }
10797  if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
10798  addenv(env, "CONTENT_LENGTH=%s", s);
10799  }
10800  if ((s = getenv("PATH")) != NULL) {
10801  addenv(env, "PATH=%s", s);
10802  }
10803  if (conn->path_info != NULL) {
10804  addenv(env, "PATH_INFO=%s", conn->path_info);
10805  }
10806 
10807  if (conn->status_code > 0) {
10808  /* CGI error handler should show the status code */
10809  addenv(env, "STATUS=%d", conn->status_code);
10810  }
10811 
10812 #if defined(_WIN32)
10813  if ((s = getenv("COMSPEC")) != NULL) {
10814  addenv(env, "COMSPEC=%s", s);
10815  }
10816  if ((s = getenv("SYSTEMROOT")) != NULL) {
10817  addenv(env, "SYSTEMROOT=%s", s);
10818  }
10819  if ((s = getenv("SystemDrive")) != NULL) {
10820  addenv(env, "SystemDrive=%s", s);
10821  }
10822  if ((s = getenv("ProgramFiles")) != NULL) {
10823  addenv(env, "ProgramFiles=%s", s);
10824  }
10825  if ((s = getenv("ProgramFiles(x86)")) != NULL) {
10826  addenv(env, "ProgramFiles(x86)=%s", s);
10827  }
10828 #else
10829  if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
10830  addenv(env, "LD_LIBRARY_PATH=%s", s);
10831  }
10832 #endif /* _WIN32 */
10833 
10834  if ((s = getenv("PERLLIB")) != NULL) {
10835  addenv(env, "PERLLIB=%s", s);
10836  }
10837 
10838  if (conn->request_info.remote_user != NULL) {
10839  addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
10840  addenv(env, "%s", "AUTH_TYPE=Digest");
10841  }
10842 
10843  /* Add all headers as HTTP_* variables */
10844  for (i = 0; i < conn->request_info.num_headers; i++) {
10845 
10846  (void)mg_snprintf(conn,
10847  &truncated,
10848  http_var_name,
10849  sizeof(http_var_name),
10850  "HTTP_%s",
10851  conn->request_info.http_headers[i].name);
10852 
10853  if (truncated) {
10854  mg_cry_internal(conn,
10855  "%s: HTTP header variable too long [%s]",
10856  __func__,
10857  conn->request_info.http_headers[i].name);
10858  continue;
10859  }
10860 
10861  /* Convert variable name into uppercase, and change - to _ */
10862  for (p = http_var_name; *p != '\0'; p++) {
10863  if (*p == '-') {
10864  *p = '_';
10865  }
10866  *p = (char)toupper(*(unsigned char *)p);
10867  }
10868 
10869  addenv(env,
10870  "%s=%s",
10871  http_var_name,
10872  conn->request_info.http_headers[i].value);
10873  }
10874 
10875  /* Add user-specified variables */
10876  s = conn->dom_ctx->config[CGI_ENVIRONMENT];
10877  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
10878  addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
10879  }
10880 
10881  env->var[env->varused] = NULL;
10882  env->buf[env->bufused] = '\0';
10883 
10884  return 0;
10885 }
10886 
10887 
10888 /* Data for CGI process control: PID and number of references */
10889 struct process_control_data {
10890  pid_t pid;
10891  int references;
10892 };
10893 
10894 static int
10895 abort_process(void *data)
10896 {
10897  /* Waitpid checks for child status and won't work for a pid that does not
10898  * identify a child of the current process. Thus, if the pid is reused,
10899  * we will not affect a different process. */
10900  struct process_control_data *proc = (struct process_control_data *)data;
10901  int status = 0;
10902  int refs;
10903  pid_t ret_pid;
10904 
10905  ret_pid = waitpid(proc->pid, &status, WNOHANG);
10906  if ((ret_pid != (pid_t)-1) && (status == 0)) {
10907  /* Stop child process */
10908  DEBUG_TRACE("CGI timer: Stop child process %p\n", proc->pid);
10909  kill(proc->pid, SIGABRT);
10910 
10911  /* Wait until process is terminated (don't leave zombies) */
10912  while (waitpid(proc->pid, &status, 0) != (pid_t)-1) /* nop */
10913  ;
10914  } else {
10915  DEBUG_TRACE("CGI timer: Child process %p already stopped\n", proc->pid);
10916  }
10917  /* Dec reference counter */
10918  refs = mg_atomic_dec(&proc->references);
10919  if (refs == 0) {
10920  /* no more references - free data */
10921  mg_free(data);
10922  }
10923 
10924  return 0;
10925 }
10926 
10927 
10928 static void
10929 handle_cgi_request(struct mg_connection *conn, const char *prog)
10930 {
10931  char *buf;
10932  size_t buflen;
10933  int headers_len, data_len, i, truncated;
10934  int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
10935  const char *status, *status_text, *connection_state;
10936  char *pbuf, dir[PATH_MAX], *p;
10937  struct mg_request_info ri;
10938  struct cgi_environment blk;
10939  FILE *in = NULL, *out = NULL, *err = NULL;
10940  struct mg_file fout = STRUCT_FILE_INITIALIZER;
10941  pid_t pid = (pid_t)-1;
10942  struct process_control_data *proc = NULL;
10943 
10944 #if defined(USE_TIMERS)
10945  double cgi_timeout = -1.0;
10946  if (conn->dom_ctx->config[CGI_TIMEOUT]) {
10947  /* Get timeout in seconds */
10948  cgi_timeout = atof(conn->dom_ctx->config[CGI_TIMEOUT]) * 0.001;
10949  }
10950 #endif
10951 
10952  if (conn == NULL) {
10953  return;
10954  }
10955 
10956  buf = NULL;
10957  buflen = conn->phys_ctx->max_request_size;
10958  i = prepare_cgi_environment(conn, prog, &blk);
10959  if (i != 0) {
10960  blk.buf = NULL;
10961  blk.var = NULL;
10962  goto done;
10963  }
10964 
10965  /* CGI must be executed in its own directory. 'dir' must point to the
10966  * directory containing executable program, 'p' must point to the
10967  * executable program name relative to 'dir'. */
10968  (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
10969 
10970  if (truncated) {
10971  mg_cry_internal(conn, "Error: CGI program \"%s\": Path too long", prog);
10972  mg_send_http_error(conn, 500, "Error: %s", "CGI path too long");
10973  goto done;
10974  }
10975 
10976  if ((p = strrchr(dir, '/')) != NULL) {
10977  *p++ = '\0';
10978  } else {
10979  dir[0] = '.';
10980  dir[1] = '\0';
10981  p = (char *)prog;
10982  }
10983 
10984  if ((pipe(fdin) != 0) || (pipe(fdout) != 0) || (pipe(fderr) != 0)) {
10985  status = strerror(ERRNO);
10986  mg_cry_internal(
10987  conn,
10988  "Error: CGI program \"%s\": Can not create CGI pipes: %s",
10989  prog,
10990  status);
10991  mg_send_http_error(conn,
10992  500,
10993  "Error: Cannot create CGI pipe: %s",
10994  status);
10995  goto done;
10996  }
10997 
10998  proc = (struct process_control_data *)
10999  mg_malloc_ctx(sizeof(struct process_control_data), conn->phys_ctx);
11000  if (proc == NULL) {
11001  mg_cry_internal(conn, "Error: CGI program \"%s\": Out or memory", prog);
11002  mg_send_http_error(conn, 500, "Error: Out of memory [%s]", prog);
11003  goto done;
11004  }
11005 
11006  DEBUG_TRACE("CGI: spawn %s %s\n", dir, p);
11007  pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
11008 
11009  if (pid == (pid_t)-1) {
11010  status = strerror(ERRNO);
11011  mg_cry_internal(
11012  conn,
11013  "Error: CGI program \"%s\": Can not spawn CGI process: %s",
11014  prog,
11015  status);
11016  mg_send_http_error(conn,
11017  500,
11018  "Error: Cannot spawn CGI process [%s]: %s",
11019  prog,
11020  status);
11021  mg_free(proc);
11022  proc = NULL;
11023  goto done;
11024  }
11025 
11026  /* Store data in shared process_control_data */
11027  proc->pid = pid;
11028  proc->references = 1;
11029 
11030 #if defined(USE_TIMERS)
11031  if (cgi_timeout > 0.0) {
11032  proc->references = 2;
11033 
11034  // Start a timer for CGI
11035  timer_add(conn->phys_ctx,
11036  cgi_timeout /* in seconds */,
11037  0.0,
11038  1,
11039  abort_process,
11040  (void *)proc);
11041  }
11042 #endif
11043 
11044  /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
11045  set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
11046  set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
11047  set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
11048  set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
11049  set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
11050  set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
11051 
11052  /* Parent closes only one side of the pipes.
11053  * If we don't mark them as closed, close() attempt before
11054  * return from this function throws an exception on Windows.
11055  * Windows does not like when closed descriptor is closed again. */
11056  (void)close(fdin[0]);
11057  (void)close(fdout[1]);
11058  (void)close(fderr[1]);
11059  fdin[0] = fdout[1] = fderr[1] = -1;
11060 
11061  if ((in = fdopen(fdin[1], "wb")) == NULL) {
11062  status = strerror(ERRNO);
11063  mg_cry_internal(conn,
11064  "Error: CGI program \"%s\": Can not open stdin: %s",
11065  prog,
11066  status);
11067  mg_send_http_error(conn,
11068  500,
11069  "Error: CGI can not open fdin\nfopen: %s",
11070  status);
11071  goto done;
11072  }
11073 
11074  if ((out = fdopen(fdout[0], "rb")) == NULL) {
11075  status = strerror(ERRNO);
11076  mg_cry_internal(conn,
11077  "Error: CGI program \"%s\": Can not open stdout: %s",
11078  prog,
11079  status);
11080  mg_send_http_error(conn,
11081  500,
11082  "Error: CGI can not open fdout\nfopen: %s",
11083  status);
11084  goto done;
11085  }
11086 
11087  if ((err = fdopen(fderr[0], "rb")) == NULL) {
11088  status = strerror(ERRNO);
11089  mg_cry_internal(conn,
11090  "Error: CGI program \"%s\": Can not open stderr: %s",
11091  prog,
11092  status);
11093  mg_send_http_error(conn,
11094  500,
11095  "Error: CGI can not open fderr\nfopen: %s",
11096  status);
11097  goto done;
11098  }
11099 
11100  setbuf(in, NULL);
11101  setbuf(out, NULL);
11102  setbuf(err, NULL);
11103  fout.access.fp = out;
11104 
11105  if ((conn->request_info.content_length != 0) || (conn->is_chunked)) {
11106  DEBUG_TRACE("CGI: send body data (%lli)\n",
11107  (signed long long)conn->request_info.content_length);
11108 
11109  /* This is a POST/PUT request, or another request with body data. */
11110  if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
11111  /* Error sending the body data */
11112  mg_cry_internal(
11113  conn,
11114  "Error: CGI program \"%s\": Forward body data failed",
11115  prog);
11116  goto done;
11117  }
11118  }
11119 
11120  /* Close so child gets an EOF. */
11121  fclose(in);
11122  in = NULL;
11123  fdin[1] = -1;
11124 
11125  /* Now read CGI reply into a buffer. We need to set correct
11126  * status code, thus we need to see all HTTP headers first.
11127  * Do not send anything back to client, until we buffer in all
11128  * HTTP headers. */
11129  data_len = 0;
11130  buf = (char *)mg_malloc_ctx(buflen, conn->phys_ctx);
11131  if (buf == NULL) {
11132  mg_send_http_error(conn,
11133  500,
11134  "Error: Not enough memory for CGI buffer (%u bytes)",
11135  (unsigned int)buflen);
11136  mg_cry_internal(
11137  conn,
11138  "Error: CGI program \"%s\": Not enough memory for buffer (%u "
11139  "bytes)",
11140  prog,
11141  (unsigned int)buflen);
11142  goto done;
11143  }
11144 
11145  DEBUG_TRACE("CGI: %s", "wait for response");
11146  headers_len = read_message(out, conn, buf, (int)buflen, &data_len);
11147  DEBUG_TRACE("CGI: response: %li", (signed long)headers_len);
11148 
11149  if (headers_len <= 0) {
11150 
11151  /* Could not parse the CGI response. Check if some error message on
11152  * stderr. */
11153  i = pull_all(err, conn, buf, (int)buflen);
11154  if (i > 0) {
11155  /* CGI program explicitly sent an error */
11156  /* Write the error message to the internal log */
11157  mg_cry_internal(conn,
11158  "Error: CGI program \"%s\" sent error "
11159  "message: [%.*s]",
11160  prog,
11161  i,
11162  buf);
11163  /* Don't send the error message back to the client */
11164  mg_send_http_error(conn,
11165  500,
11166  "Error: CGI program \"%s\" failed.",
11167  prog);
11168  } else {
11169  /* CGI program did not explicitly send an error, but a broken
11170  * respon header */
11171  mg_cry_internal(conn,
11172  "Error: CGI program sent malformed or too big "
11173  "(>%u bytes) HTTP headers: [%.*s]",
11174  (unsigned)buflen,
11175  data_len,
11176  buf);
11177 
11178  mg_send_http_error(conn,
11179  500,
11180  "Error: CGI program sent malformed or too big "
11181  "(>%u bytes) HTTP headers: [%.*s]",
11182  (unsigned)buflen,
11183  data_len,
11184  buf);
11185  }
11186 
11187  /* in both cases, abort processing CGI */
11188  goto done;
11189  }
11190 
11191  pbuf = buf;
11192  buf[headers_len - 1] = '\0';
11193  ri.num_headers = parse_http_headers(&pbuf, ri.http_headers);
11194 
11195  /* Make up and send the status line */
11196  status_text = "OK";
11197  if ((status = get_header(ri.http_headers, ri.num_headers, "Status"))
11198  != NULL) {
11199  conn->status_code = atoi(status);
11200  status_text = status;
11201  while (isdigit(*(const unsigned char *)status_text)
11202  || *status_text == ' ') {
11203  status_text++;
11204  }
11205  } else if (get_header(ri.http_headers, ri.num_headers, "Location")
11206  != NULL) {
11207  conn->status_code = 307;
11208  } else {
11209  conn->status_code = 200;
11210  }
11211  connection_state =
11212  get_header(ri.http_headers, ri.num_headers, "Connection");
11213  if (!header_has_option(connection_state, "keep-alive")) {
11214  conn->must_close = 1;
11215  }
11216 
11217  DEBUG_TRACE("CGI: response %u %s", conn->status_code, status_text);
11218 
11219  (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
11220 
11221  /* Send headers */
11222  for (i = 0; i < ri.num_headers; i++) {
11223  mg_printf(conn,
11224  "%s: %s\r\n",
11225  ri.http_headers[i].name,
11226  ri.http_headers[i].value);
11227  }
11228  mg_write(conn, "\r\n", 2);
11229 
11230  /* Send chunk of data that may have been read after the headers */
11231  mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
11232 
11233  /* Read the rest of CGI output and send to the client */
11234  DEBUG_TRACE("CGI: %s", "forward all data");
11235  send_file_data(conn, &fout, 0, INT64_MAX);
11236  DEBUG_TRACE("CGI: %s", "all data sent");
11237 
11238 done:
11239  mg_free(blk.var);
11240  mg_free(blk.buf);
11241 
11242  if (pid != (pid_t)-1) {
11243  abort_process((void *)proc);
11244  }
11245 
11246  if (fdin[0] != -1) {
11247  close(fdin[0]);
11248  }
11249  if (fdout[1] != -1) {
11250  close(fdout[1]);
11251  }
11252 
11253  if (in != NULL) {
11254  fclose(in);
11255  } else if (fdin[1] != -1) {
11256  close(fdin[1]);
11257  }
11258 
11259  if (out != NULL) {
11260  fclose(out);
11261  } else if (fdout[0] != -1) {
11262  close(fdout[0]);
11263  }
11264 
11265  if (err != NULL) {
11266  fclose(err);
11267  } else if (fderr[0] != -1) {
11268  close(fderr[0]);
11269  }
11270 
11271  if (buf != NULL) {
11272  mg_free(buf);
11273  }
11274 }
11275 #endif /* !NO_CGI */
11276 
11277 
11278 #if !defined(NO_FILES)
11279 static void
11280 mkcol(struct mg_connection *conn, const char *path)
11281 {
11282  int rc, body_len;
11283  struct de de;
11284  char date[64];
11285  time_t curtime = time(NULL);
11286 
11287  if (conn == NULL) {
11288  return;
11289  }
11290 
11291  /* TODO (mid): Check the mg_send_http_error situations in this function
11292  */
11293 
11294  memset(&de.file, 0, sizeof(de.file));
11295  if (!mg_stat(conn, path, &de.file)) {
11296  mg_cry_internal(conn,
11297  "%s: mg_stat(%s) failed: %s",
11298  __func__,
11299  path,
11300  strerror(ERRNO));
11301  }
11302 
11303  if (de.file.last_modified) {
11304  /* TODO (mid): This check does not seem to make any sense ! */
11305  /* TODO (mid): Add a webdav unit test first, before changing
11306  * anything here. */
11307  mg_send_http_error(
11308  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
11309  return;
11310  }
11311 
11312  body_len = conn->data_len - conn->request_len;
11313  if (body_len > 0) {
11314  mg_send_http_error(
11315  conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
11316  return;
11317  }
11318 
11319  rc = mg_mkdir(conn, path, 0755);
11320 
11321  if (rc == 0) {
11322  conn->status_code = 201;
11323  gmt_time_string(date, sizeof(date), &curtime);
11324  mg_printf(conn,
11325  "HTTP/1.1 %d Created\r\n"
11326  "Date: %s\r\n",
11327  conn->status_code,
11328  date);
11329  send_static_cache_header(conn);
11330  send_additional_header(conn);
11331  mg_printf(conn,
11332  "Content-Length: 0\r\n"
11333  "Connection: %s\r\n\r\n",
11334  suggest_connection_header(conn));
11335  } else {
11336  if (errno == EEXIST) {
11337  mg_send_http_error(
11338  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
11339  } else if (errno == EACCES) {
11340  mg_send_http_error(
11341  conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
11342  } else if (errno == ENOENT) {
11343  mg_send_http_error(
11344  conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
11345  } else {
11346  mg_send_http_error(
11347  conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
11348  }
11349  }
11350 }
11351 
11352 
11353 static void
11354 put_file(struct mg_connection *conn, const char *path)
11355 {
11356  struct mg_file file = STRUCT_FILE_INITIALIZER;
11357  const char *range;
11358  int64_t r1, r2;
11359  int rc;
11360  char date[64];
11361  time_t curtime = time(NULL);
11362 
11363  if (conn == NULL) {
11364  return;
11365  }
11366 
11367  if (mg_stat(conn, path, &file.stat)) {
11368  /* File already exists */
11369  conn->status_code = 200;
11370 
11371  if (file.stat.is_directory) {
11372  /* This is an already existing directory,
11373  * so there is nothing to do for the server. */
11374  rc = 0;
11375 
11376  } else {
11377  /* File exists and is not a directory. */
11378  /* Can it be replaced? */
11379 
11380 #if defined(MG_USE_OPEN_FILE)
11381  if (file.access.membuf != NULL) {
11382  /* This is an "in-memory" file, that can not be replaced */
11383  mg_send_http_error(conn,
11384  405,
11385  "Error: Put not possible\nReplacing %s "
11386  "is not supported",
11387  path);
11388  return;
11389  }
11390 #endif
11391 
11392  /* Check if the server may write this file */
11393  if (access(path, W_OK) == 0) {
11394  /* Access granted */
11395  conn->status_code = 200;
11396  rc = 1;
11397  } else {
11398  mg_send_http_error(
11399  conn,
11400  403,
11401  "Error: Put not possible\nReplacing %s is not allowed",
11402  path);
11403  return;
11404  }
11405  }
11406  } else {
11407  /* File should be created */
11408  conn->status_code = 201;
11409  rc = put_dir(conn, path);
11410  }
11411 
11412  if (rc == 0) {
11413  /* put_dir returns 0 if path is a directory */
11414  gmt_time_string(date, sizeof(date), &curtime);
11415  mg_printf(conn,
11416  "HTTP/1.1 %d %s\r\n",
11417  conn->status_code,
11418  mg_get_response_code_text(NULL, conn->status_code));
11419  send_no_cache_header(conn);
11420  send_additional_header(conn);
11421  mg_printf(conn,
11422  "Date: %s\r\n"
11423  "Content-Length: 0\r\n"
11424  "Connection: %s\r\n\r\n",
11425  date,
11426  suggest_connection_header(conn));
11427 
11428  /* Request to create a directory has been fulfilled successfully.
11429  * No need to put a file. */
11430  return;
11431  }
11432 
11433  if (rc == -1) {
11434  /* put_dir returns -1 if the path is too long */
11435  mg_send_http_error(conn,
11436  414,
11437  "Error: Path too long\nput_dir(%s): %s",
11438  path,
11439  strerror(ERRNO));
11440  return;
11441  }
11442 
11443  if (rc == -2) {
11444  /* put_dir returns -2 if the directory can not be created */
11445  mg_send_http_error(conn,
11446  500,
11447  "Error: Can not create directory\nput_dir(%s): %s",
11448  path,
11449  strerror(ERRNO));
11450  return;
11451  }
11452 
11453  /* A file should be created or overwritten. */
11454  /* Currently CivetWeb does not nead read+write access. */
11455  if (!mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &file)
11456  || file.access.fp == NULL) {
11457  (void)mg_fclose(&file.access);
11458  mg_send_http_error(conn,
11459  500,
11460  "Error: Can not create file\nfopen(%s): %s",
11461  path,
11462  strerror(ERRNO));
11463  return;
11464  }
11465 
11466  fclose_on_exec(&file.access, conn);
11467  range = mg_get_header(conn, "Content-Range");
11468  r1 = r2 = 0;
11469  if ((range != NULL) && parse_range_header(range, &r1, &r2) > 0) {
11470  conn->status_code = 206; /* Partial content */
11471  fseeko(file.access.fp, r1, SEEK_SET);
11472  }
11473 
11474  if (!forward_body_data(conn, file.access.fp, INVALID_SOCKET, NULL)) {
11475  /* forward_body_data failed.
11476  * The error code has already been sent to the client,
11477  * and conn->status_code is already set. */
11478  (void)mg_fclose(&file.access);
11479  return;
11480  }
11481 
11482  if (mg_fclose(&file.access) != 0) {
11483  /* fclose failed. This might have different reasons, but a likely
11484  * one is "no space on disk", http 507. */
11485  conn->status_code = 507;
11486  }
11487 
11488  gmt_time_string(date, sizeof(date), &curtime);
11489  mg_printf(conn,
11490  "HTTP/1.1 %d %s\r\n",
11491  conn->status_code,
11492  mg_get_response_code_text(NULL, conn->status_code));
11493  send_no_cache_header(conn);
11494  send_additional_header(conn);
11495  mg_printf(conn,
11496  "Date: %s\r\n"
11497  "Content-Length: 0\r\n"
11498  "Connection: %s\r\n\r\n",
11499  date,
11500  suggest_connection_header(conn));
11501 }
11502 
11503 
11504 static void
11505 delete_file(struct mg_connection *conn, const char *path)
11506 {
11507  struct de de;
11508  memset(&de.file, 0, sizeof(de.file));
11509  if (!mg_stat(conn, path, &de.file)) {
11510  /* mg_stat returns 0 if the file does not exist */
11511  mg_send_http_error(conn,
11512  404,
11513  "Error: Cannot delete file\nFile %s not found",
11514  path);
11515  return;
11516  }
11517 
11518 #if 0 /* Ignore if a file in memory is inside a folder */
11519  if (de.access.membuf != NULL) {
11520  /* the file is cached in memory */
11521  mg_send_http_error(
11522  conn,
11523  405,
11524  "Error: Delete not possible\nDeleting %s is not supported",
11525  path);
11526  return;
11527  }
11528 #endif
11529 
11530  if (de.file.is_directory) {
11531  if (remove_directory(conn, path)) {
11532  /* Delete is successful: Return 204 without content. */
11533  mg_send_http_error(conn, 204, "%s", "");
11534  } else {
11535  /* Delete is not successful: Return 500 (Server error). */
11536  mg_send_http_error(conn, 500, "Error: Could not delete %s", path);
11537  }
11538  return;
11539  }
11540 
11541  /* This is an existing file (not a directory).
11542  * Check if write permission is granted. */
11543  if (access(path, W_OK) != 0) {
11544  /* File is read only */
11545  mg_send_http_error(
11546  conn,
11547  403,
11548  "Error: Delete not possible\nDeleting %s is not allowed",
11549  path);
11550  return;
11551  }
11552 
11553  /* Try to delete it. */
11554  if (mg_remove(conn, path) == 0) {
11555  /* Delete was successful: Return 204 without content. */
11556  mg_send_http_error(conn, 204, "%s", "");
11557  } else {
11558  /* Delete not successful (file locked). */
11559  mg_send_http_error(conn,
11560  423,
11561  "Error: Cannot delete file\nremove(%s): %s",
11562  path,
11563  strerror(ERRNO));
11564  }
11565 }
11566 #endif /* !NO_FILES */
11567 
11568 
11569 static void
11570 send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int);
11571 
11572 
11573 static void
11574 do_ssi_include(struct mg_connection *conn,
11575  const char *ssi,
11576  char *tag,
11577  int include_level)
11578 {
11579  char file_name[MG_BUF_LEN], path[512], *p;
11580  struct mg_file file = STRUCT_FILE_INITIALIZER;
11581  size_t len;
11582  int truncated = 0;
11583 
11584  if (conn == NULL) {
11585  return;
11586  }
11587 
11588  /* sscanf() is safe here, since send_ssi_file() also uses buffer
11589  * of size MG_BUF_LEN to get the tag. So strlen(tag) is
11590  * always < MG_BUF_LEN. */
11591  if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
11592  /* File name is relative to the webserver root */
11593  file_name[511] = 0;
11594  (void)mg_snprintf(conn,
11595  &truncated,
11596  path,
11597  sizeof(path),
11598  "%s/%s",
11599  conn->dom_ctx->config[DOCUMENT_ROOT],
11600  file_name);
11601 
11602  } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
11603  /* File name is relative to the webserver working directory
11604  * or it is absolute system path */
11605  file_name[511] = 0;
11606  (void)
11607  mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
11608 
11609  } else if ((sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1)
11610  || (sscanf(tag, " \"%511[^\"]\"", file_name) == 1)) {
11611  /* File name is relative to the currect document */
11612  file_name[511] = 0;
11613  (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
11614 
11615  if (!truncated) {
11616  if ((p = strrchr(path, '/')) != NULL) {
11617  p[1] = '\0';
11618  }
11619  len = strlen(path);
11620  (void)mg_snprintf(conn,
11621  &truncated,
11622  path + len,
11623  sizeof(path) - len,
11624  "%s",
11625  file_name);
11626  }
11627 
11628  } else {
11629  mg_cry_internal(conn, "Bad SSI #include: [%s]", tag);
11630  return;
11631  }
11632 
11633  if (truncated) {
11634  mg_cry_internal(conn, "SSI #include path length overflow: [%s]", tag);
11635  return;
11636  }
11637 
11638  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) {
11639  mg_cry_internal(conn,
11640  "Cannot open SSI #include: [%s]: fopen(%s): %s",
11641  tag,
11642  path,
11643  strerror(ERRNO));
11644  } else {
11645  fclose_on_exec(&file.access, conn);
11646  if (match_prefix(conn->dom_ctx->config[SSI_EXTENSIONS],
11647  strlen(conn->dom_ctx->config[SSI_EXTENSIONS]),
11648  path)
11649  > 0) {
11650  send_ssi_file(conn, path, &file, include_level + 1);
11651  } else {
11652  send_file_data(conn, &file, 0, INT64_MAX);
11653  }
11654  (void)mg_fclose(&file.access); /* Ignore errors for readonly files */
11655  }
11656 }
11657 
11658 
11659 #if !defined(NO_POPEN)
11660 static void
11661 do_ssi_exec(struct mg_connection *conn, char *tag)
11662 {
11663  char cmd[1024] = "";
11664  struct mg_file file = STRUCT_FILE_INITIALIZER;
11665 
11666  if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
11667  mg_cry_internal(conn, "Bad SSI #exec: [%s]", tag);
11668  } else {
11669  cmd[1023] = 0;
11670  if ((file.access.fp = popen(cmd, "r")) == NULL) {
11671  mg_cry_internal(conn,
11672  "Cannot SSI #exec: [%s]: %s",
11673  cmd,
11674  strerror(ERRNO));
11675  } else {
11676  send_file_data(conn, &file, 0, INT64_MAX);
11677  pclose(file.access.fp);
11678  }
11679  }
11680 }
11681 #endif /* !NO_POPEN */
11682 
11683 
11684 static int
11685 mg_fgetc(struct mg_file *filep, int offset)
11686 {
11687  (void)offset; /* unused in case MG_USE_OPEN_FILE is set */
11688 
11689  if (filep == NULL) {
11690  return EOF;
11691  }
11692 #if defined(MG_USE_OPEN_FILE)
11693  if ((filep->access.membuf != NULL) && (offset >= 0)
11694  && (((unsigned int)(offset)) < filep->stat.size)) {
11695  return ((const unsigned char *)filep->access.membuf)[offset];
11696  } else /* else block below */
11697 #endif
11698  if (filep->access.fp != NULL) {
11699  return fgetc(filep->access.fp);
11700  } else {
11701  return EOF;
11702  }
11703 }
11704 
11705 
11706 static void
11707 send_ssi_file(struct mg_connection *conn,
11708  const char *path,
11709  struct mg_file *filep,
11710  int include_level)
11711 {
11712  char buf[MG_BUF_LEN];
11713  int ch, offset, len, in_tag, in_ssi_tag;
11714 
11715  if (include_level > 10) {
11716  mg_cry_internal(conn, "SSI #include level is too deep (%s)", path);
11717  return;
11718  }
11719 
11720  in_tag = in_ssi_tag = len = offset = 0;
11721 
11722  /* Read file, byte by byte, and look for SSI include tags */
11723  while ((ch = mg_fgetc(filep, offset++)) != EOF) {
11724 
11725  if (in_tag) {
11726  /* We are in a tag, either SSI tag or html tag */
11727 
11728  if (ch == '>') {
11729  /* Tag is closing */
11730  buf[len++] = '>';
11731 
11732  if (in_ssi_tag) {
11733  /* Handle SSI tag */
11734  buf[len] = 0;
11735 
11736  if ((len > 12) && !memcmp(buf + 5, "include", 7)) {
11737  do_ssi_include(conn, path, buf + 12, include_level + 1);
11738 #if !defined(NO_POPEN)
11739  } else if ((len > 9) && !memcmp(buf + 5, "exec", 4)) {
11740  do_ssi_exec(conn, buf + 9);
11741 #endif /* !NO_POPEN */
11742  } else {
11743  mg_cry_internal(conn,
11744  "%s: unknown SSI "
11745  "command: \"%s\"",
11746  path,
11747  buf);
11748  }
11749  len = 0;
11750  in_ssi_tag = in_tag = 0;
11751 
11752  } else {
11753  /* Not an SSI tag */
11754  /* Flush buffer */
11755  (void)mg_write(conn, buf, (size_t)len);
11756  len = 0;
11757  in_tag = 0;
11758  }
11759 
11760  } else {
11761  /* Tag is still open */
11762  buf[len++] = (char)(ch & 0xff);
11763 
11764  if ((len == 5) && !memcmp(buf, "<!--#", 5)) {
11765  /* All SSI tags start with <!--# */
11766  in_ssi_tag = 1;
11767  }
11768 
11769  if ((len + 2) > (int)sizeof(buf)) {
11770  /* Tag to long for buffer */
11771  mg_cry_internal(conn, "%s: tag is too large", path);
11772  return;
11773  }
11774  }
11775 
11776  } else {
11777 
11778  /* We are not in a tag yet. */
11779  if (ch == '<') {
11780  /* Tag is opening */
11781  in_tag = 1;
11782 
11783  if (len > 0) {
11784  /* Flush current buffer.
11785  * Buffer is filled with "len" bytes. */
11786  (void)mg_write(conn, buf, (size_t)len);
11787  }
11788  /* Store the < */
11789  len = 1;
11790  buf[0] = '<';
11791 
11792  } else {
11793  /* No Tag */
11794  /* Add data to buffer */
11795  buf[len++] = (char)(ch & 0xff);
11796  /* Flush if buffer is full */
11797  if (len == (int)sizeof(buf)) {
11798  mg_write(conn, buf, (size_t)len);
11799  len = 0;
11800  }
11801  }
11802  }
11803  }
11804 
11805  /* Send the rest of buffered data */
11806  if (len > 0) {
11807  mg_write(conn, buf, (size_t)len);
11808  }
11809 }
11810 
11811 
11812 static void
11813 handle_ssi_file_request(struct mg_connection *conn,
11814  const char *path,
11815  struct mg_file *filep)
11816 {
11817  char date[64];
11818  time_t curtime = time(NULL);
11819  const char *cors1, *cors2, *cors3;
11820 
11821  if ((conn == NULL) || (path == NULL) || (filep == NULL)) {
11822  return;
11823  }
11824 
11825  if (mg_get_header(conn, "Origin")) {
11826  /* Cross-origin resource sharing (CORS). */
11827  cors1 = "Access-Control-Allow-Origin: ";
11828  cors2 = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
11829  cors3 = "\r\n";
11830  } else {
11831  cors1 = cors2 = cors3 = "";
11832  }
11833 
11834  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
11835  /* File exists (precondition for calling this function),
11836  * but can not be opened by the server. */
11837  mg_send_http_error(conn,
11838  500,
11839  "Error: Cannot read file\nfopen(%s): %s",
11840  path,
11841  strerror(ERRNO));
11842  } else {
11843  conn->must_close = 1;
11844  gmt_time_string(date, sizeof(date), &curtime);
11845  fclose_on_exec(&filep->access, conn);
11846  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
11847  send_no_cache_header(conn);
11848  send_additional_header(conn);
11849  mg_printf(conn,
11850  "%s%s%s"
11851  "Date: %s\r\n"
11852  "Content-Type: text/html\r\n"
11853  "Connection: %s\r\n\r\n",
11854  cors1,
11855  cors2,
11856  cors3,
11857  date,
11858  suggest_connection_header(conn));
11859  send_ssi_file(conn, path, filep, 0);
11860  (void)mg_fclose(&filep->access); /* Ignore errors for readonly files */
11861  }
11862 }
11863 
11864 
11865 #if !defined(NO_FILES)
11866 static void
11867 send_options(struct mg_connection *conn)
11868 {
11869  char date[64];
11870  time_t curtime = time(NULL);
11871 
11872  if (!conn) {
11873  return;
11874  }
11875 
11876  conn->status_code = 200;
11877  conn->must_close = 1;
11878  gmt_time_string(date, sizeof(date), &curtime);
11879 
11880  /* We do not set a "Cache-Control" header here, but leave the default.
11881  * Since browsers do not send an OPTIONS request, we can not test the
11882  * effect anyway. */
11883  mg_printf(conn,
11884  "HTTP/1.1 200 OK\r\n"
11885  "Date: %s\r\n"
11886  "Connection: %s\r\n"
11887  "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
11888  "PROPFIND, MKCOL\r\n"
11889  "DAV: 1\r\n",
11890  date,
11891  suggest_connection_header(conn));
11892  send_additional_header(conn);
11893  mg_printf(conn, "\r\n");
11894 }
11895 
11896 
11897 /* Writes PROPFIND properties for a collection element */
11898 static void
11899 print_props(struct mg_connection *conn,
11900  const char *uri,
11901  struct mg_file_stat *filep)
11902 {
11903  char mtime[64];
11904 
11905  if ((conn == NULL) || (uri == NULL) || (filep == NULL)) {
11906  return;
11907  }
11908 
11909  gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
11910  mg_printf(conn,
11911  "<d:response>"
11912  "<d:href>%s</d:href>"
11913  "<d:propstat>"
11914  "<d:prop>"
11915  "<d:resourcetype>%s</d:resourcetype>"
11916  "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
11917  "<d:getlastmodified>%s</d:getlastmodified>"
11918  "</d:prop>"
11919  "<d:status>HTTP/1.1 200 OK</d:status>"
11920  "</d:propstat>"
11921  "</d:response>\n",
11922  uri,
11923  filep->is_directory ? "<d:collection/>" : "",
11924  filep->size,
11925  mtime);
11926 }
11927 
11928 
11929 static int
11930 print_dav_dir_entry(struct de *de, void *data)
11931 {
11932  char href[PATH_MAX];
11933  int truncated;
11934 
11935  struct mg_connection *conn = (struct mg_connection *)data;
11936  if (!de || !conn) {
11937  return -1;
11938  }
11939  mg_snprintf(conn,
11940  &truncated,
11941  href,
11942  sizeof(href),
11943  "%s%s",
11944  conn->request_info.local_uri,
11945  de->file_name);
11946 
11947  if (!truncated) {
11948  size_t href_encoded_size;
11949  char *href_encoded;
11950 
11951  href_encoded_size = PATH_MAX * 3; /* worst case */
11952  href_encoded = (char *)mg_malloc(href_encoded_size);
11953  if (href_encoded == NULL) {
11954  return -1;
11955  }
11956  mg_url_encode(href, href_encoded, href_encoded_size);
11957  print_props(conn, href_encoded, &de->file);
11958  mg_free(href_encoded);
11959  }
11960 
11961  return 0;
11962 }
11963 
11964 
11965 static void
11966 handle_propfind(struct mg_connection *conn,
11967  const char *path,
11968  struct mg_file_stat *filep)
11969 {
11970  const char *depth = mg_get_header(conn, "Depth");
11971  char date[64];
11972  time_t curtime = time(NULL);
11973 
11974  gmt_time_string(date, sizeof(date), &curtime);
11975 
11976  if (!conn || !path || !filep || !conn->dom_ctx) {
11977  return;
11978  }
11979 
11980  conn->must_close = 1;
11981  conn->status_code = 207;
11982  mg_printf(conn,
11983  "HTTP/1.1 207 Multi-Status\r\n"
11984  "Date: %s\r\n",
11985  date);
11986  send_static_cache_header(conn);
11987  send_additional_header(conn);
11988  mg_printf(conn,
11989  "Connection: %s\r\n"
11990  "Content-Type: text/xml; charset=utf-8\r\n\r\n",
11991  suggest_connection_header(conn));
11992 
11993  mg_printf(conn,
11994  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
11995  "<d:multistatus xmlns:d='DAV:'>\n");
11996 
11997  /* Print properties for the requested resource itself */
11998  print_props(conn, conn->request_info.local_uri, filep);
11999 
12000  /* If it is a directory, print directory entries too if Depth is not 0
12001  */
12002  if (filep->is_directory
12003  && !mg_strcasecmp(conn->dom_ctx->config[ENABLE_DIRECTORY_LISTING],
12004  "yes")
12005  && ((depth == NULL) || (strcmp(depth, "0") != 0))) {
12006  scan_directory(conn, path, conn, &print_dav_dir_entry);
12007  }
12008 
12009  mg_printf(conn, "%s\n", "</d:multistatus>");
12010 }
12011 #endif
12012 
12013 void
12014 mg_lock_connection(struct mg_connection *conn)
12015 {
12016  if (conn) {
12017  (void)pthread_mutex_lock(&conn->mutex);
12018  }
12019 }
12020 
12021 void
12022 mg_unlock_connection(struct mg_connection *conn)
12023 {
12024  if (conn) {
12025  (void)pthread_mutex_unlock(&conn->mutex);
12026  }
12027 }
12028 
12029 void
12030 mg_lock_context(struct mg_context *ctx)
12031 {
12032  if (ctx) {
12033  (void)pthread_mutex_lock(&ctx->nonce_mutex);
12034  }
12035 }
12036 
12037 void
12038 mg_unlock_context(struct mg_context *ctx)
12039 {
12040  if (ctx) {
12041  (void)pthread_mutex_unlock(&ctx->nonce_mutex);
12042  }
12043 }
12044 
12045 
12046 #if defined(USE_LUA)
12047 #include "mod_lua.inl"
12048 #endif /* USE_LUA */
12049 
12050 #if defined(USE_DUKTAPE)
12051 #include "mod_duktape.inl"
12052 #endif /* USE_DUKTAPE */
12053 
12054 #if defined(USE_WEBSOCKET)
12055 
12056 #if !defined(NO_SSL_DL)
12057 #define SHA_API static
12058 #include "sha1.inl"
12059 #endif
12060 
12061 static int
12062 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
12063 {
12064  static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
12065  char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
12066  SHA_CTX sha_ctx;
12067  int truncated;
12068 
12069  /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
12070  mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
12071  if (truncated) {
12072  conn->must_close = 1;
12073  return 0;
12074  }
12075 
12076  DEBUG_TRACE("%s", "Send websocket handshake");
12077 
12078  SHA1_Init(&sha_ctx);
12079  SHA1_Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
12080  SHA1_Final((unsigned char *)sha, &sha_ctx);
12081  base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
12082  mg_printf(conn,
12083  "HTTP/1.1 101 Switching Protocols\r\n"
12084  "Upgrade: websocket\r\n"
12085  "Connection: Upgrade\r\n"
12086  "Sec-WebSocket-Accept: %s\r\n",
12087  b64_sha);
12088  if (conn->request_info.acceptedWebSocketSubprotocol) {
12089  mg_printf(conn,
12090  "Sec-WebSocket-Protocol: %s\r\n\r\n",
12091  conn->request_info.acceptedWebSocketSubprotocol);
12092  } else {
12093  mg_printf(conn, "%s", "\r\n");
12094  }
12095 
12096  return 1;
12097 }
12098 
12099 
12100 #if !defined(MG_MAX_UNANSWERED_PING)
12101 /* Configuration of the maximum number of websocket PINGs that might
12102  * stay unanswered before the connection is considered broken.
12103  * Note: The name of this define may still change (until it is
12104  * defined as a compile parameter in a documentation).
12105  */
12106 #define MG_MAX_UNANSWERED_PING (5)
12107 #endif
12108 
12109 
12110 static void
12111 read_websocket(struct mg_connection *conn,
12112  mg_websocket_data_handler ws_data_handler,
12113  void *callback_data)
12114 {
12115  /* Pointer to the beginning of the portion of the incoming websocket
12116  * message queue.
12117  * The original websocket upgrade request is never removed, so the queue
12118  * begins after it. */
12119  unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
12120  int n, error, exit_by_callback;
12121  int ret;
12122 
12123  /* body_len is the length of the entire queue in bytes
12124  * len is the length of the current message
12125  * data_len is the length of the current message's data payload
12126  * header_len is the length of the current message's header */
12127  size_t i, len, mask_len = 0, header_len, body_len;
12128  uint64_t data_len = 0;
12129 
12130  /* "The masking key is a 32-bit value chosen at random by the client."
12131  * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
12132  */
12133  unsigned char mask[4];
12134 
12135  /* data points to the place where the message is stored when passed to
12136  * the websocket_data callback. This is either mem on the stack, or a
12137  * dynamically allocated buffer if it is too large. */
12138  unsigned char mem[4096];
12139  unsigned char mop; /* mask flag and opcode */
12140 
12141 
12142  /* Variables used for connection monitoring */
12143  double timeout = -1.0;
12144  int enable_ping_pong = 0;
12145  int ping_count = 0;
12146 
12147  if (conn->dom_ctx->config[ENABLE_WEBSOCKET_PING_PONG]) {
12148  enable_ping_pong =
12149  !mg_strcasecmp(conn->dom_ctx->config[ENABLE_WEBSOCKET_PING_PONG],
12150  "yes");
12151  }
12152 
12153  if (conn->dom_ctx->config[WEBSOCKET_TIMEOUT]) {
12154  timeout = atoi(conn->dom_ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
12155  }
12156  if ((timeout <= 0.0) && (conn->dom_ctx->config[REQUEST_TIMEOUT])) {
12157  timeout = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0;
12158  }
12159 
12160  /* Enter data processing loop */
12161  DEBUG_TRACE("Websocket connection %s:%u start data processing loop",
12162  conn->request_info.remote_addr,
12163  conn->request_info.remote_port);
12164  conn->in_websocket_handling = 1;
12165  mg_set_thread_name("wsock");
12166 
12167  /* Loop continuously, reading messages from the socket, invoking the
12168  * callback, and waiting repeatedly until an error occurs. */
12169  while (!conn->phys_ctx->stop_flag && !conn->must_close) {
12170  header_len = 0;
12171  DEBUG_ASSERT(conn->data_len >= conn->request_len);
12172  if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
12173  len = buf[1] & 127;
12174  mask_len = (buf[1] & 128) ? 4 : 0;
12175  if ((len < 126) && (body_len >= mask_len)) {
12176  /* inline 7-bit length field */
12177  data_len = len;
12178  header_len = 2 + mask_len;
12179  } else if ((len == 126) && (body_len >= (4 + mask_len))) {
12180  /* 16-bit length field */
12181  header_len = 4 + mask_len;
12182  data_len = ((((size_t)buf[2]) << 8) + buf[3]);
12183  } else if (body_len >= (10 + mask_len)) {
12184  /* 64-bit length field */
12185  uint32_t l1, l2;
12186  memcpy(&l1, &buf[2], 4); /* Use memcpy for alignment */
12187  memcpy(&l2, &buf[6], 4);
12188  header_len = 10 + mask_len;
12189  data_len = (((uint64_t)ntohl(l1)) << 32) + ntohl(l2);
12190 
12191  if (data_len > (uint64_t)0x7FFF0000ul) {
12192  /* no can do */
12193  mg_cry_internal(
12194  conn,
12195  "%s",
12196  "websocket out of memory; closing connection");
12197  break;
12198  }
12199  }
12200  }
12201 
12202  if ((header_len > 0) && (body_len >= header_len)) {
12203  /* Allocate space to hold websocket payload */
12204  unsigned char *data = mem;
12205 
12206  if ((size_t)data_len > (size_t)sizeof(mem)) {
12207  data = (unsigned char *)mg_malloc_ctx((size_t)data_len,
12208  conn->phys_ctx);
12209  if (data == NULL) {
12210  /* Allocation failed, exit the loop and then close the
12211  * connection */
12212  mg_cry_internal(
12213  conn,
12214  "%s",
12215  "websocket out of memory; closing connection");
12216  break;
12217  }
12218  }
12219 
12220  /* Copy the mask before we shift the queue and destroy it */
12221  if (mask_len > 0) {
12222  memcpy(mask, buf + header_len - mask_len, sizeof(mask));
12223  } else {
12224  memset(mask, 0, sizeof(mask));
12225  }
12226 
12227  /* Read frame payload from the first message in the queue into
12228  * data and advance the queue by moving the memory in place. */
12229  DEBUG_ASSERT(body_len >= header_len);
12230  if (data_len + (uint64_t)header_len > (uint64_t)body_len) {
12231  mop = buf[0]; /* current mask and opcode */
12232  /* Overflow case */
12233  len = body_len - header_len;
12234  memcpy(data, buf + header_len, len);
12235  error = 0;
12236  while ((uint64_t)len < data_len) {
12237  n = pull_inner(NULL,
12238  conn,
12239  (char *)(data + len),
12240  (int)(data_len - len),
12241  timeout);
12242  if (n <= -2) {
12243  error = 1;
12244  break;
12245  } else if (n > 0) {
12246  len += (size_t)n;
12247  } else {
12248  /* Timeout: should retry */
12249  /* TODO: retry condition */
12250  }
12251  }
12252  if (error) {
12253  mg_cry_internal(
12254  conn,
12255  "%s",
12256  "Websocket pull failed; closing connection");
12257  if (data != mem) {
12258  mg_free(data);
12259  }
12260  break;
12261  }
12262 
12263  conn->data_len = conn->request_len;
12264 
12265  } else {
12266 
12267  mop = buf[0]; /* current mask and opcode, overwritten by
12268  * memmove() */
12269 
12270  /* Length of the message being read at the front of the
12271  * queue. Cast to 31 bit is OK, since we limited
12272  * data_len before. */
12273  len = (size_t)data_len + header_len;
12274 
12275  /* Copy the data payload into the data pointer for the
12276  * callback. Cast to 31 bit is OK, since we
12277  * limited data_len */
12278  memcpy(data, buf + header_len, (size_t)data_len);
12279 
12280  /* Move the queue forward len bytes */
12281  memmove(buf, buf + len, body_len - len);
12282 
12283  /* Mark the queue as advanced */
12284  conn->data_len -= (int)len;
12285  }
12286 
12287  /* Apply mask if necessary */
12288  if (mask_len > 0) {
12289  for (i = 0; i < (size_t)data_len; i++) {
12290  data[i] ^= mask[i & 3];
12291  }
12292  }
12293 
12294  exit_by_callback = 0;
12295  if (enable_ping_pong && ((mop & 0xF) == MG_WEBSOCKET_OPCODE_PONG)) {
12296  /* filter PONG messages */
12297  DEBUG_TRACE("PONG from %s:%u",
12298  conn->request_info.remote_addr,
12299  conn->request_info.remote_port);
12300  /* No unanwered PINGs left */
12301  ping_count = 0;
12302  } else if (enable_ping_pong
12303  && ((mop & 0xF) == MG_WEBSOCKET_OPCODE_PING)) {
12304  /* reply PING messages */
12305  DEBUG_TRACE("Reply PING from %s:%u",
12306  conn->request_info.remote_addr,
12307  conn->request_info.remote_port);
12308  ret = mg_websocket_write(conn,
12309  MG_WEBSOCKET_OPCODE_PONG,
12310  (char *)data,
12311  (size_t)data_len);
12312  if (ret <= 0) {
12313  /* Error: send failed */
12314  DEBUG_TRACE("Reply PONG failed (%i)", ret);
12315  break;
12316  }
12317 
12318 
12319  } else {
12320  /* Exit the loop if callback signals to exit (server side),
12321  * or "connection close" opcode received (client side). */
12322  if ((ws_data_handler != NULL)
12323  && !ws_data_handler(conn,
12324  mop,
12325  (char *)data,
12326  (size_t)data_len,
12327  callback_data)) {
12328  exit_by_callback = 1;
12329  }
12330  }
12331 
12332  /* It a buffer has been allocated, free it again */
12333  if (data != mem) {
12334  mg_free(data);
12335  }
12336 
12337  if (exit_by_callback) {
12338  DEBUG_TRACE("Callback requests to close connection from %s:%u",
12339  conn->request_info.remote_addr,
12340  conn->request_info.remote_port);
12341  break;
12342  }
12343  if ((mop & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE) {
12344  /* Opcode == 8, connection close */
12345  DEBUG_TRACE("Message requests to close connection from %s:%u",
12346  conn->request_info.remote_addr,
12347  conn->request_info.remote_port);
12348  break;
12349  }
12350 
12351  /* Not breaking the loop, process next websocket frame. */
12352  } else {
12353  /* Read from the socket into the next available location in the
12354  * message queue. */
12355  n = pull_inner(NULL,
12356  conn,
12357  conn->buf + conn->data_len,
12358  conn->buf_size - conn->data_len,
12359  timeout);
12360  if (n <= -2) {
12361  /* Error, no bytes read */
12362  DEBUG_TRACE("PULL from %s:%u failed",
12363  conn->request_info.remote_addr,
12364  conn->request_info.remote_port);
12365  break;
12366  }
12367  if (n > 0) {
12368  conn->data_len += n;
12369  /* Reset open PING count */
12370  ping_count = 0;
12371  } else {
12372  if (!conn->phys_ctx->stop_flag && !conn->must_close) {
12373  if (ping_count > MG_MAX_UNANSWERED_PING) {
12374  /* Stop sending PING */
12375  DEBUG_TRACE("Too many (%i) unanswered ping from %s:%u "
12376  "- closing connection",
12377  ping_count,
12378  conn->request_info.remote_addr,
12379  conn->request_info.remote_port);
12380  break;
12381  }
12382  if (enable_ping_pong) {
12383  /* Send Websocket PING message */
12384  DEBUG_TRACE("PING to %s:%u",
12385  conn->request_info.remote_addr,
12386  conn->request_info.remote_port);
12387  ret = mg_websocket_write(conn,
12388  MG_WEBSOCKET_OPCODE_PING,
12389  NULL,
12390  0);
12391 
12392  if (ret <= 0) {
12393  /* Error: send failed */
12394  DEBUG_TRACE("Send PING failed (%i)", ret);
12395  break;
12396  }
12397  ping_count++;
12398  }
12399  }
12400  /* Timeout: should retry */
12401  /* TODO: get timeout def */
12402  }
12403  }
12404  }
12405 
12406  /* Leave data processing loop */
12407  mg_set_thread_name("worker");
12408  conn->in_websocket_handling = 0;
12409  DEBUG_TRACE("Websocket connection %s:%u left data processing loop",
12410  conn->request_info.remote_addr,
12411  conn->request_info.remote_port);
12412 }
12413 
12414 
12415 static int
12416 mg_websocket_write_exec(struct mg_connection *conn,
12417  int opcode,
12418  const char *data,
12419  size_t dataLen,
12420  uint32_t masking_key)
12421 {
12422  unsigned char header[14];
12423  size_t headerLen;
12424  int retval;
12425 
12426 #if defined(GCC_DIAGNOSTIC)
12427 /* Disable spurious conversion warning for GCC */
12428 #pragma GCC diagnostic push
12429 #pragma GCC diagnostic ignored "-Wconversion"
12430 #endif
12431 
12432  header[0] = 0x80u | (unsigned char)((unsigned)opcode & 0xf);
12433 
12434 #if defined(GCC_DIAGNOSTIC)
12435 #pragma GCC diagnostic pop
12436 #endif
12437 
12438  /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
12439  if (dataLen < 126) {
12440  /* inline 7-bit length field */
12441  header[1] = (unsigned char)dataLen;
12442  headerLen = 2;
12443  } else if (dataLen <= 0xFFFF) {
12444  /* 16-bit length field */
12445  uint16_t len = htons((uint16_t)dataLen);
12446  header[1] = 126;
12447  memcpy(header + 2, &len, 2);
12448  headerLen = 4;
12449  } else {
12450  /* 64-bit length field */
12451  uint32_t len1 = htonl((uint32_t)((uint64_t)dataLen >> 32));
12452  uint32_t len2 = htonl((uint32_t)(dataLen & 0xFFFFFFFFu));
12453  header[1] = 127;
12454  memcpy(header + 2, &len1, 4);
12455  memcpy(header + 6, &len2, 4);
12456  headerLen = 10;
12457  }
12458 
12459  if (masking_key) {
12460  /* add mask */
12461  header[1] |= 0x80;
12462  memcpy(header + headerLen, &masking_key, 4);
12463  headerLen += 4;
12464  }
12465 
12466  /* Note that POSIX/Winsock's send() is threadsafe
12467  * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
12468  * but mongoose's mg_printf/mg_write is not (because of the loop in
12469  * push(), although that is only a problem if the packet is large or
12470  * outgoing buffer is full). */
12471 
12472  /* TODO: Check if this lock should be moved to user land.
12473  * Currently the server sets this lock for websockets, but
12474  * not for any other connection. It must be set for every
12475  * conn read/written by more than one thread, no matter if
12476  * it is a websocket or regular connection. */
12477  (void)mg_lock_connection(conn);
12478 
12479  retval = mg_write(conn, header, headerLen);
12480  if (retval != (int)headerLen) {
12481  /* Did not send complete header */
12482  retval = -1;
12483  } else {
12484  if (dataLen > 0) {
12485  retval = mg_write(conn, data, dataLen);
12486  }
12487  /* if dataLen == 0, the header length (2) is returned */
12488  }
12489 
12490  /* TODO: Remove this unlock as well, when lock is removed. */
12491  mg_unlock_connection(conn);
12492 
12493  return retval;
12494 }
12495 
12496 int
12497 mg_websocket_write(struct mg_connection *conn,
12498  int opcode,
12499  const char *data,
12500  size_t dataLen)
12501 {
12502  return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
12503 }
12504 
12505 
12506 static void
12507 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
12508 {
12509  size_t i = 0;
12510 
12511  i = 0;
12512  if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
12513  /* Convert in 32 bit words, if data is 4 byte aligned */
12514  while (i < (in_len - 3)) {
12515  *(uint32_t *)(void *)(out + i) =
12516  *(uint32_t *)(void *)(in + i) ^ masking_key;
12517  i += 4;
12518  }
12519  }
12520  if (i != in_len) {
12521  /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
12522  while (i < in_len) {
12523  *(uint8_t *)(void *)(out + i) =
12524  *(uint8_t *)(void *)(in + i)
12525  ^ *(((uint8_t *)&masking_key) + (i % 4));
12526  i++;
12527  }
12528  }
12529 }
12530 
12531 
12532 int
12533 mg_websocket_client_write(struct mg_connection *conn,
12534  int opcode,
12535  const char *data,
12536  size_t dataLen)
12537 {
12538  int retval = -1;
12539  char *masked_data =
12540  (char *)mg_malloc_ctx(((dataLen + 7) / 4) * 4, conn->phys_ctx);
12541  uint32_t masking_key = 0;
12542 
12543  if (masked_data == NULL) {
12544  /* Return -1 in an error case */
12545  mg_cry_internal(conn,
12546  "%s",
12547  "Cannot allocate buffer for masked websocket response: "
12548  "Out of memory");
12549  return -1;
12550  }
12551 
12552  do {
12553  /* Get a masking key - but not 0 */
12554  masking_key = (uint32_t)get_random();
12555  } while (masking_key == 0);
12556 
12557  mask_data(data, dataLen, masking_key, masked_data);
12558 
12559  retval = mg_websocket_write_exec(
12560  conn, opcode, masked_data, dataLen, masking_key);
12561  mg_free(masked_data);
12562 
12563  return retval;
12564 }
12565 
12566 
12567 static void
12568 handle_websocket_request(struct mg_connection *conn,
12569  const char *path,
12570  int is_callback_resource,
12571  struct mg_websocket_subprotocols *subprotocols,
12572  mg_websocket_connect_handler ws_connect_handler,
12573  mg_websocket_ready_handler ws_ready_handler,
12574  mg_websocket_data_handler ws_data_handler,
12575  mg_websocket_close_handler ws_close_handler,
12576  void *cbData)
12577 {
12578  const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
12579  const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
12580  ptrdiff_t lua_websock = 0;
12581 
12582 #if !defined(USE_LUA)
12583  (void)path;
12584 #endif
12585 
12586  /* Step 1: Check websocket protocol version. */
12587  /* Step 1.1: Check Sec-WebSocket-Key. */
12588  if (!websock_key) {
12589  /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
12590  * requires a Sec-WebSocket-Key header.
12591  */
12592  /* It could be the hixie draft version
12593  * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
12594  */
12595  const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
12596  const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
12597  char key3[8];
12598 
12599  if ((key1 != NULL) && (key2 != NULL)) {
12600  /* This version uses 8 byte body data in a GET request */
12601  conn->content_len = 8;
12602  if (8 == mg_read(conn, key3, 8)) {
12603  /* This is the hixie version */
12604  mg_send_http_error(conn,
12605  426,
12606  "%s",
12607  "Protocol upgrade to RFC 6455 required");
12608  return;
12609  }
12610  }
12611  /* This is an unknown version */
12612  mg_send_http_error(conn, 400, "%s", "Malformed websocket request");
12613  return;
12614  }
12615 
12616  /* Step 1.2: Check websocket protocol version. */
12617  /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
12618  if ((version == NULL) || (strcmp(version, "13") != 0)) {
12619  /* Reject wrong versions */
12620  mg_send_http_error(conn, 426, "%s", "Protocol upgrade required");
12621  return;
12622  }
12623 
12624  /* Step 1.3: Could check for "Host", but we do not really nead this
12625  * value for anything, so just ignore it. */
12626 
12627  /* Step 2: If a callback is responsible, call it. */
12628  if (is_callback_resource) {
12629  /* Step 2.1 check and select subprotocol */
12630  const char *protocols[64]; // max 64 headers
12631  int nbSubprotocolHeader = get_req_headers(&conn->request_info,
12632  "Sec-WebSocket-Protocol",
12633  protocols,
12634  64);
12635  if ((nbSubprotocolHeader > 0) && subprotocols) {
12636  int cnt = 0;
12637  int idx;
12638  unsigned long len;
12639  const char *sep, *curSubProtocol,
12640  *acceptedWebSocketSubprotocol = NULL;
12641 
12642 
12643  /* look for matching subprotocol */
12644  do {
12645  const char *protocol = protocols[cnt];
12646 
12647  do {
12648  sep = strchr(protocol, ',');
12649  curSubProtocol = protocol;
12650  len = sep ? (unsigned long)(sep - protocol)
12651  : (unsigned long)strlen(protocol);
12652  while (sep && isspace(*++sep))
12653  ; // ignore leading whitespaces
12654  protocol = sep;
12655 
12656 
12657  for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
12658  if ((strlen(subprotocols->subprotocols[idx]) == len)
12659  && (strncmp(curSubProtocol,
12660  subprotocols->subprotocols[idx],
12661  len)
12662  == 0)) {
12663  acceptedWebSocketSubprotocol =
12664  subprotocols->subprotocols[idx];
12665  break;
12666  }
12667  }
12668  } while (sep && !acceptedWebSocketSubprotocol);
12669  } while (++cnt < nbSubprotocolHeader
12670  && !acceptedWebSocketSubprotocol);
12671 
12672  conn->request_info.acceptedWebSocketSubprotocol =
12673  acceptedWebSocketSubprotocol;
12674 
12675  } else if (nbSubprotocolHeader > 0) {
12676  /* keep legacy behavior */
12677  const char *protocol = protocols[0];
12678 
12679  /* The protocol is a comma separated list of names. */
12680  /* The server must only return one value from this list. */
12681  /* First check if it is a list or just a single value. */
12682  const char *sep = strrchr(protocol, ',');
12683  if (sep == NULL) {
12684  /* Just a single protocol -> accept it. */
12685  conn->request_info.acceptedWebSocketSubprotocol = protocol;
12686  } else {
12687  /* Multiple protocols -> accept the last one. */
12688  /* This is just a quick fix if the client offers multiple
12689  * protocols. The handler should have a list of accepted
12690  * protocols on his own
12691  * and use it to select one protocol among those the client
12692  * has
12693  * offered.
12694  */
12695  while (isspace(*++sep)) {
12696  ; /* ignore leading whitespaces */
12697  }
12698  conn->request_info.acceptedWebSocketSubprotocol = sep;
12699  }
12700  }
12701 
12702  if ((ws_connect_handler != NULL)
12703  && (ws_connect_handler(conn, cbData) != 0)) {
12704  /* C callback has returned non-zero, do not proceed with
12705  * handshake.
12706  */
12707  /* Note that C callbacks are no longer called when Lua is
12708  * responsible, so C can no longer filter callbacks for Lua. */
12709  return;
12710  }
12711  }
12712 
12713 #if defined(USE_LUA)
12714  /* Step 3: No callback. Check if Lua is responsible. */
12715  else {
12716  /* Step 3.1: Check if Lua is responsible. */
12717  if (conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
12718  lua_websock = match_prefix(
12719  conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS],
12720  strlen(conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
12721  path);
12722  }
12723 
12724  if (lua_websock) {
12725  /* Step 3.2: Lua is responsible: call it. */
12726  conn->lua_websocket_state = lua_websocket_new(path, conn);
12727  if (!conn->lua_websocket_state) {
12728  /* Lua rejected the new client */
12729  return;
12730  }
12731  }
12732  }
12733 #endif
12734 
12735  /* Step 4: Check if there is a responsible websocket handler. */
12736  if (!is_callback_resource && !lua_websock) {
12737  /* There is no callback, and Lua is not responsible either. */
12738  /* Reply with a 404 Not Found. We are still at a standard
12739  * HTTP request here, before the websocket handshake, so
12740  * we can still send standard HTTP error replies. */
12741  mg_send_http_error(conn, 404, "%s", "Not found");
12742  return;
12743  }
12744 
12745  /* Step 5: The websocket connection has been accepted */
12746  if (!send_websocket_handshake(conn, websock_key)) {
12747  mg_send_http_error(conn, 500, "%s", "Websocket handshake failed");
12748  return;
12749  }
12750 
12751  /* Step 6: Call the ready handler */
12752  if (is_callback_resource) {
12753  if (ws_ready_handler != NULL) {
12754  ws_ready_handler(conn, cbData);
12755  }
12756 #if defined(USE_LUA)
12757  } else if (lua_websock) {
12758  if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
12759  /* the ready handler returned false */
12760  return;
12761  }
12762 #endif
12763  }
12764 
12765  /* Step 7: Enter the read loop */
12766  if (is_callback_resource) {
12767  read_websocket(conn, ws_data_handler, cbData);
12768 #if defined(USE_LUA)
12769  } else if (lua_websock) {
12770  read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
12771 #endif
12772  }
12773 
12774  /* Step 8: Call the close handler */
12775  if (ws_close_handler) {
12776  ws_close_handler(conn, cbData);
12777  }
12778 }
12779 
12780 
12781 static int
12782 is_websocket_protocol(const struct mg_connection *conn)
12783 {
12784  const char *upgrade, *connection;
12785 
12786  /* A websocket protocoll has the following HTTP headers:
12787  *
12788  * Connection: Upgrade
12789  * Upgrade: Websocket
12790  */
12791 
12792  upgrade = mg_get_header(conn, "Upgrade");
12793  if (upgrade == NULL) {
12794  return 0; /* fail early, don't waste time checking other header
12795  * fields
12796  */
12797  }
12798  if (!mg_strcasestr(upgrade, "websocket")) {
12799  return 0;
12800  }
12801 
12802  connection = mg_get_header(conn, "Connection");
12803  if (connection == NULL) {
12804  return 0;
12805  }
12806  if (!mg_strcasestr(connection, "upgrade")) {
12807  return 0;
12808  }
12809 
12810  /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
12811  * "Sec-WebSocket-Version" are also required.
12812  * Don't check them here, since even an unsupported websocket protocol
12813  * request still IS a websocket request (in contrast to a standard HTTP
12814  * request). It will fail later in handle_websocket_request.
12815  */
12816 
12817  return 1;
12818 }
12819 #endif /* !USE_WEBSOCKET */
12820 
12821 
12822 static int
12823 isbyte(int n)
12824 {
12825  return (n >= 0) && (n <= 255);
12826 }
12827 
12828 
12829 static int
12830 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
12831 {
12832  int n, a, b, c, d, slash = 32, len = 0;
12833 
12834  if (((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5)
12835  || (sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4))
12836  && isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && (slash >= 0)
12837  && (slash < 33)) {
12838  len = n;
12839  *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
12840  | (uint32_t)d;
12841  *mask = slash ? (0xffffffffU << (32 - slash)) : 0;
12842  }
12843 
12844  return len;
12845 }
12846 
12847 
12848 static int
12849 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
12850 {
12851  int throttle = 0;
12852  struct vec vec, val;
12853  uint32_t net, mask;
12854  char mult;
12855  double v;
12856 
12857  while ((spec = next_option(spec, &vec, &val)) != NULL) {
12858  mult = ',';
12859  if ((val.ptr == NULL) || (sscanf(val.ptr, "%lf%c", &v, &mult) < 1)
12860  || (v < 0)
12861  || ((lowercase(&mult) != 'k') && (lowercase(&mult) != 'm')
12862  && (mult != ','))) {
12863  continue;
12864  }
12865  v *= (lowercase(&mult) == 'k')
12866  ? 1024
12867  : ((lowercase(&mult) == 'm') ? 1048576 : 1);
12868  if (vec.len == 1 && vec.ptr[0] == '*') {
12869  throttle = (int)v;
12870  } else if (parse_net(vec.ptr, &net, &mask) > 0) {
12871  if ((remote_ip & mask) == net) {
12872  throttle = (int)v;
12873  }
12874  } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
12875  throttle = (int)v;
12876  }
12877  }
12878 
12879  return throttle;
12880 }
12881 
12882 
12883 static uint32_t
12884 get_remote_ip(const struct mg_connection *conn)
12885 {
12886  if (!conn) {
12887  return 0;
12888  }
12889  return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
12890 }
12891 
12892 
12893 /* The mg_upload function is superseeded by mg_handle_form_request. */
12894 #include "handle_form.inl"
12895 
12896 
12897 #if defined(MG_LEGACY_INTERFACE)
12898 /* Implement the deprecated mg_upload function by calling the new
12899  * mg_handle_form_request function. While mg_upload could only handle
12900  * HTML forms sent as POST request in multipart/form-data format
12901  * containing only file input elements, mg_handle_form_request can
12902  * handle all form input elements and all standard request methods. */
12903 struct mg_upload_user_data {
12904  struct mg_connection *conn;
12905  const char *destination_dir;
12906  int num_uploaded_files;
12907 };
12908 
12909 
12910 /* Helper function for deprecated mg_upload. */
12911 static int
12912 mg_upload_field_found(const char *key,
12913  const char *filename,
12914  char *path,
12915  size_t pathlen,
12916  void *user_data)
12917 {
12918  int truncated = 0;
12919  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
12920  (void)key;
12921 
12922  if (!filename) {
12923  mg_cry_internal(fud->conn, "%s: No filename set", __func__);
12924  return FORM_FIELD_STORAGE_ABORT;
12925  }
12926  mg_snprintf(fud->conn,
12927  &truncated,
12928  path,
12929  pathlen - 1,
12930  "%s/%s",
12931  fud->destination_dir,
12932  filename);
12933  if (truncated) {
12934  mg_cry_internal(fud->conn, "%s: File path too long", __func__);
12935  return FORM_FIELD_STORAGE_ABORT;
12936  }
12937  return FORM_FIELD_STORAGE_STORE;
12938 }
12939 
12940 
12941 /* Helper function for deprecated mg_upload. */
12942 static int
12943 mg_upload_field_get(const char *key,
12944  const char *value,
12945  size_t value_size,
12946  void *user_data)
12947 {
12948  /* Function should never be called */
12949  (void)key;
12950  (void)value;
12951  (void)value_size;
12952  (void)user_data;
12953 
12954  return 0;
12955 }
12956 
12957 
12958 /* Helper function for deprecated mg_upload. */
12959 static int
12960 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
12961 {
12962  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
12963  (void)file_size;
12964 
12965  fud->num_uploaded_files++;
12966  fud->conn->phys_ctx->callbacks.upload(fud->conn, path);
12967 
12968  return 0;
12969 }
12970 
12971 
12972 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
12973 int
12974 mg_upload(struct mg_connection *conn, const char *destination_dir)
12975 {
12976  struct mg_upload_user_data fud = {conn, destination_dir, 0};
12977  struct mg_form_data_handler fdh = {mg_upload_field_found,
12978  mg_upload_field_get,
12979  mg_upload_field_stored,
12980  0};
12981  int ret;
12982 
12983  fdh.user_data = (void *)&fud;
12984  ret = mg_handle_form_request(conn, &fdh);
12985 
12986  if (ret < 0) {
12987  mg_cry_internal(conn, "%s: Error while parsing the request", __func__);
12988  }
12989 
12990  return fud.num_uploaded_files;
12991 }
12992 #endif
12993 
12994 
12995 static int
12996 get_first_ssl_listener_index(const struct mg_context *ctx)
12997 {
12998  unsigned int i;
12999  int idx = -1;
13000  if (ctx) {
13001  for (i = 0; ((idx == -1) && (i < ctx->num_listening_sockets)); i++) {
13002  idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
13003  }
13004  }
13005  return idx;
13006 }
13007 
13008 
13009 /* Return host (without port) */
13010 /* Use mg_free to free the result */
13011 static const char *
13012 alloc_get_host(struct mg_connection *conn)
13013 {
13014  char buf[1025];
13015  size_t buflen = sizeof(buf);
13016  const char *host_header = get_header(conn->request_info.http_headers,
13017  conn->request_info.num_headers,
13018  "Host");
13019  char *host;
13020 
13021  if (host_header != NULL) {
13022  char *pos;
13023 
13024  /* Create a local copy of the "Host" header, since it might be
13025  * modified here. */
13026  mg_strlcpy(buf, host_header, buflen);
13027  buf[buflen - 1] = '\0';
13028  host = buf;
13029  while (isspace(*host)) {
13030  host++;
13031  }
13032 
13033  /* If the "Host" is an IPv6 address, like [::1], parse until ]
13034  * is found. */
13035  if (*host == '[') {
13036  pos = strchr(host, ']');
13037  if (!pos) {
13038  /* Malformed hostname starts with '[', but no ']' found */
13039  DEBUG_TRACE("%s", "Host name format error '[' without ']'");
13040  return NULL;
13041  }
13042  /* terminate after ']' */
13043  pos[1] = 0;
13044  } else {
13045  /* Otherwise, a ':' separates hostname and port number */
13046  pos = strchr(host, ':');
13047  if (pos != NULL) {
13048  *pos = '\0';
13049  }
13050  }
13051 
13052  if (conn->ssl) {
13053  /* This is a HTTPS connection, maybe we have a hostname
13054  * from SNI (set in ssl_servername_callback). */
13055  const char *sslhost = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
13056  if (sslhost && (conn->dom_ctx != &(conn->phys_ctx->dd))) {
13057  /* We are not using the default domain */
13058  if (mg_strcasecmp(host, sslhost)) {
13059  /* Mismatch between SNI domain and HTTP domain */
13060  DEBUG_TRACE("Host mismatch: SNI: %s, HTTPS: %s",
13061  sslhost,
13062  host);
13063  return NULL;
13064  }
13065  }
13066  DEBUG_TRACE("HTTPS Host: %s", host);
13067 
13068  } else {
13069  struct mg_domain_context *dom = &(conn->phys_ctx->dd);
13070  while (dom) {
13071  if (!mg_strcasecmp(host, dom->config[AUTHENTICATION_DOMAIN])) {
13072 
13073  /* Found matching domain */
13074  DEBUG_TRACE("HTTP domain %s found",
13075  dom->config[AUTHENTICATION_DOMAIN]);
13076 
13077  /* TODO: Check if this is a HTTP or HTTPS domain */
13078  conn->dom_ctx = dom;
13079  break;
13080  }
13081  dom = dom->next;
13082  }
13083 
13084  DEBUG_TRACE("HTTP Host: %s", host);
13085  }
13086 
13087  } else {
13088  sockaddr_to_string(buf, buflen, &conn->client.lsa);
13089  host = buf;
13090 
13091  DEBUG_TRACE("IP: %s", host);
13092  }
13093 
13094  return mg_strdup_ctx(host, conn->phys_ctx);
13095 }
13096 
13097 
13098 static void
13099 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
13100 {
13101  char target_url[MG_BUF_LEN];
13102  int truncated = 0;
13103 
13104  conn->must_close = 1;
13105 
13106  /* Send host, port, uri and (if it exists) ?query_string */
13107  if (conn->host) {
13108 
13109  /* Use "308 Permanent Redirect" */
13110  int redirect_code = 308;
13111 
13112  /* Create target URL */
13113  mg_snprintf(
13114  conn,
13115  &truncated,
13116  target_url,
13117  sizeof(target_url),
13118  "https://%s:%d%s%s%s",
13119 
13120  conn->host,
13121 #if defined(USE_IPV6)
13122  (conn->phys_ctx->listening_sockets[ssl_index].lsa.sa.sa_family
13123  == AF_INET6)
13124  ? (int)ntohs(conn->phys_ctx->listening_sockets[ssl_index]
13125  .lsa.sin6.sin6_port)
13126  :
13127 #endif
13128  (int)ntohs(conn->phys_ctx->listening_sockets[ssl_index]
13129  .lsa.sin.sin_port),
13130  conn->request_info.local_uri,
13131  (conn->request_info.query_string == NULL) ? "" : "?",
13132  (conn->request_info.query_string == NULL)
13133  ? ""
13134  : conn->request_info.query_string);
13135 
13136  /* Check overflow in location buffer (will not occur if MG_BUF_LEN
13137  * is used as buffer size) */
13138  if (truncated) {
13139  mg_send_http_error(conn, 500, "%s", "Redirect URL too long");
13140  return;
13141  }
13142 
13143  /* Use redirect helper function */
13144  mg_send_http_redirect(conn, target_url, redirect_code);
13145  }
13146 }
13147 
13148 
13149 static void
13150 handler_info_acquire(struct mg_handler_info *handler_info)
13151 {
13152  pthread_mutex_lock(&handler_info->refcount_mutex);
13153  handler_info->refcount++;
13154  pthread_mutex_unlock(&handler_info->refcount_mutex);
13155 }
13156 
13157 
13158 static void
13159 handler_info_release(struct mg_handler_info *handler_info)
13160 {
13161  pthread_mutex_lock(&handler_info->refcount_mutex);
13162  handler_info->refcount--;
13163  pthread_cond_signal(&handler_info->refcount_cond);
13164  pthread_mutex_unlock(&handler_info->refcount_mutex);
13165 }
13166 
13167 
13168 static void
13169 handler_info_wait_unused(struct mg_handler_info *handler_info)
13170 {
13171  pthread_mutex_lock(&handler_info->refcount_mutex);
13172  while (handler_info->refcount) {
13173  pthread_cond_wait(&handler_info->refcount_cond,
13174  &handler_info->refcount_mutex);
13175  }
13176  pthread_mutex_unlock(&handler_info->refcount_mutex);
13177 }
13178 
13179 
13180 static void
13181 mg_set_handler_type(struct mg_context *phys_ctx,
13182  struct mg_domain_context *dom_ctx,
13183  const char *uri,
13184  int handler_type,
13185  int is_delete_request,
13186  mg_request_handler handler,
13187  struct mg_websocket_subprotocols *subprotocols,
13188  mg_websocket_connect_handler connect_handler,
13189  mg_websocket_ready_handler ready_handler,
13190  mg_websocket_data_handler data_handler,
13191  mg_websocket_close_handler close_handler,
13192  mg_authorization_handler auth_handler,
13193  void *cbdata)
13194 {
13195  struct mg_handler_info *tmp_rh, **lastref;
13196  size_t urilen = strlen(uri);
13197 
13198  if (handler_type == WEBSOCKET_HANDLER) {
13199  DEBUG_ASSERT(handler == NULL);
13200  DEBUG_ASSERT(is_delete_request || connect_handler != NULL
13201  || ready_handler != NULL || data_handler != NULL
13202  || close_handler != NULL);
13203 
13204  DEBUG_ASSERT(auth_handler == NULL);
13205  if (handler != NULL) {
13206  return;
13207  }
13208  if (!is_delete_request && (connect_handler == NULL)
13209  && (ready_handler == NULL) && (data_handler == NULL)
13210  && (close_handler == NULL)) {
13211  return;
13212  }
13213  if (auth_handler != NULL) {
13214  return;
13215  }
13216  } else if (handler_type == REQUEST_HANDLER) {
13217  DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL
13218  && data_handler == NULL && close_handler == NULL);
13219  DEBUG_ASSERT(is_delete_request || (handler != NULL));
13220  DEBUG_ASSERT(auth_handler == NULL);
13221 
13222  if ((connect_handler != NULL) || (ready_handler != NULL)
13223  || (data_handler != NULL) || (close_handler != NULL)) {
13224  return;
13225  }
13226  if (!is_delete_request && (handler == NULL)) {
13227  return;
13228  }
13229  if (auth_handler != NULL) {
13230  return;
13231  }
13232  } else { /* AUTH_HANDLER */
13233  DEBUG_ASSERT(handler == NULL);
13234  DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL
13235  && data_handler == NULL && close_handler == NULL);
13236  DEBUG_ASSERT(auth_handler != NULL);
13237  if (handler != NULL) {
13238  return;
13239  }
13240  if ((connect_handler != NULL) || (ready_handler != NULL)
13241  || (data_handler != NULL) || (close_handler != NULL)) {
13242  return;
13243  }
13244  if (!is_delete_request && (auth_handler == NULL)) {
13245  return;
13246  }
13247  }
13248 
13249  if (!phys_ctx || !dom_ctx) {
13250  return;
13251  }
13252 
13253  mg_lock_context(phys_ctx);
13254 
13255  /* first try to find an existing handler */
13256  lastref = &(dom_ctx->handlers);
13257  for (tmp_rh = dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
13258  if (tmp_rh->handler_type == handler_type) {
13259  if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
13260  if (!is_delete_request) {
13261  /* update existing handler */
13262  if (handler_type == REQUEST_HANDLER) {
13263  /* Wait for end of use before updating */
13264  handler_info_wait_unused(tmp_rh);
13265 
13266  /* Ok, the handler is no more use -> Update it */
13267  tmp_rh->handler = handler;
13268  } else if (handler_type == WEBSOCKET_HANDLER) {
13269  tmp_rh->subprotocols = subprotocols;
13270  tmp_rh->connect_handler = connect_handler;
13271  tmp_rh->ready_handler = ready_handler;
13272  tmp_rh->data_handler = data_handler;
13273  tmp_rh->close_handler = close_handler;
13274  } else { /* AUTH_HANDLER */
13275  tmp_rh->auth_handler = auth_handler;
13276  }
13277  tmp_rh->cbdata = cbdata;
13278  } else {
13279  /* remove existing handler */
13280  if (handler_type == REQUEST_HANDLER) {
13281  /* Wait for end of use before removing */
13282  handler_info_wait_unused(tmp_rh);
13283 
13284  /* Ok, the handler is no more used -> Destroy resources
13285  */
13286  pthread_cond_destroy(&tmp_rh->refcount_cond);
13287  pthread_mutex_destroy(&tmp_rh->refcount_mutex);
13288  }
13289  *lastref = tmp_rh->next;
13290  mg_free(tmp_rh->uri);
13291  mg_free(tmp_rh);
13292  }
13293  mg_unlock_context(phys_ctx);
13294  return;
13295  }
13296  }
13297  lastref = &(tmp_rh->next);
13298  }
13299 
13300  if (is_delete_request) {
13301  /* no handler to set, this was a remove request to a non-existing
13302  * handler */
13303  mg_unlock_context(phys_ctx);
13304  return;
13305  }
13306 
13307  tmp_rh =
13308  (struct mg_handler_info *)mg_calloc_ctx(sizeof(struct mg_handler_info),
13309  1,
13310  phys_ctx);
13311  if (tmp_rh == NULL) {
13312  mg_unlock_context(phys_ctx);
13313  mg_cry_internal(fc(phys_ctx),
13314  "%s",
13315  "Cannot create new request handler struct, OOM");
13316  return;
13317  }
13318  tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
13319  if (!tmp_rh->uri) {
13320  mg_unlock_context(phys_ctx);
13321  mg_free(tmp_rh);
13322  mg_cry_internal(fc(phys_ctx),
13323  "%s",
13324  "Cannot create new request handler struct, OOM");
13325  return;
13326  }
13327  tmp_rh->uri_len = urilen;
13328  if (handler_type == REQUEST_HANDLER) {
13329  /* Init refcount mutex and condition */
13330  if (0 != pthread_mutex_init(&tmp_rh->refcount_mutex, NULL)) {
13331  mg_unlock_context(phys_ctx);
13332  mg_free(tmp_rh);
13333  mg_cry_internal(fc(phys_ctx), "%s", "Cannot init refcount mutex");
13334  return;
13335  }
13336  if (0 != pthread_cond_init(&tmp_rh->refcount_cond, NULL)) {
13337  mg_unlock_context(phys_ctx);
13338  pthread_mutex_destroy(&tmp_rh->refcount_mutex);
13339  mg_free(tmp_rh);
13340  mg_cry_internal(fc(phys_ctx), "%s", "Cannot init refcount cond");
13341  return;
13342  }
13343  tmp_rh->refcount = 0;
13344  tmp_rh->handler = handler;
13345  } else if (handler_type == WEBSOCKET_HANDLER) {
13346  tmp_rh->subprotocols = subprotocols;
13347  tmp_rh->connect_handler = connect_handler;
13348  tmp_rh->ready_handler = ready_handler;
13349  tmp_rh->data_handler = data_handler;
13350  tmp_rh->close_handler = close_handler;
13351  } else { /* AUTH_HANDLER */
13352  tmp_rh->auth_handler = auth_handler;
13353  }
13354  tmp_rh->cbdata = cbdata;
13355  tmp_rh->handler_type = handler_type;
13356  tmp_rh->next = NULL;
13357 
13358  *lastref = tmp_rh;
13359  mg_unlock_context(phys_ctx);
13360 }
13361 
13362 
13363 void
13364 mg_set_request_handler(struct mg_context *ctx,
13365  const char *uri,
13366  mg_request_handler handler,
13367  void *cbdata)
13368 {
13369  mg_set_handler_type(ctx,
13370  &(ctx->dd),
13371  uri,
13372  REQUEST_HANDLER,
13373  handler == NULL,
13374  handler,
13375  NULL,
13376  NULL,
13377  NULL,
13378  NULL,
13379  NULL,
13380  NULL,
13381  cbdata);
13382 }
13383 
13384 
13385 void
13386 mg_set_websocket_handler(struct mg_context *ctx,
13387  const char *uri,
13388  mg_websocket_connect_handler connect_handler,
13389  mg_websocket_ready_handler ready_handler,
13390  mg_websocket_data_handler data_handler,
13391  mg_websocket_close_handler close_handler,
13392  void *cbdata)
13393 {
13394  mg_set_websocket_handler_with_subprotocols(ctx,
13395  uri,
13396  NULL,
13397  connect_handler,
13398  ready_handler,
13399  data_handler,
13400  close_handler,
13401  cbdata);
13402 }
13403 
13404 
13405 void
13406 mg_set_websocket_handler_with_subprotocols(
13407  struct mg_context *ctx,
13408  const char *uri,
13409  struct mg_websocket_subprotocols *subprotocols,
13410  mg_websocket_connect_handler connect_handler,
13411  mg_websocket_ready_handler ready_handler,
13412  mg_websocket_data_handler data_handler,
13413  mg_websocket_close_handler close_handler,
13414  void *cbdata)
13415 {
13416  int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
13417  && (data_handler == NULL)
13418  && (close_handler == NULL);
13419  mg_set_handler_type(ctx,
13420  &(ctx->dd),
13421  uri,
13422  WEBSOCKET_HANDLER,
13423  is_delete_request,
13424  NULL,
13425  subprotocols,
13426  connect_handler,
13427  ready_handler,
13428  data_handler,
13429  close_handler,
13430  NULL,
13431  cbdata);
13432 }
13433 
13434 
13435 void
13436 mg_set_auth_handler(struct mg_context *ctx,
13437  const char *uri,
13438  mg_request_handler handler,
13439  void *cbdata)
13440 {
13441  mg_set_handler_type(ctx,
13442  &(ctx->dd),
13443  uri,
13444  AUTH_HANDLER,
13445  handler == NULL,
13446  NULL,
13447  NULL,
13448  NULL,
13449  NULL,
13450  NULL,
13451  NULL,
13452  handler,
13453  cbdata);
13454 }
13455 
13456 
13457 static int
13458 get_request_handler(struct mg_connection *conn,
13459  int handler_type,
13460  mg_request_handler *handler,
13461  struct mg_websocket_subprotocols **subprotocols,
13462  mg_websocket_connect_handler *connect_handler,
13463  mg_websocket_ready_handler *ready_handler,
13464  mg_websocket_data_handler *data_handler,
13465  mg_websocket_close_handler *close_handler,
13466  mg_authorization_handler *auth_handler,
13467  void **cbdata,
13468  struct mg_handler_info **handler_info)
13469 {
13470  const struct mg_request_info *request_info = mg_get_request_info(conn);
13471  if (request_info) {
13472  const char *uri = request_info->local_uri;
13473  size_t urilen = strlen(uri);
13474  struct mg_handler_info *tmp_rh;
13475 
13476  if (!conn || !conn->phys_ctx || !conn->dom_ctx) {
13477  return 0;
13478  }
13479 
13480  mg_lock_context(conn->phys_ctx);
13481 
13482  /* first try for an exact match */
13483  for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
13484  tmp_rh = tmp_rh->next) {
13485  if (tmp_rh->handler_type == handler_type) {
13486  if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
13487  if (handler_type == WEBSOCKET_HANDLER) {
13488  *subprotocols = tmp_rh->subprotocols;
13489  *connect_handler = tmp_rh->connect_handler;
13490  *ready_handler = tmp_rh->ready_handler;
13491  *data_handler = tmp_rh->data_handler;
13492  *close_handler = tmp_rh->close_handler;
13493  } else if (handler_type == REQUEST_HANDLER) {
13494  *handler = tmp_rh->handler;
13495  /* Acquire handler and give it back */
13496  handler_info_acquire(tmp_rh);
13497  *handler_info = tmp_rh;
13498  } else { /* AUTH_HANDLER */
13499  *auth_handler = tmp_rh->auth_handler;
13500  }
13501  *cbdata = tmp_rh->cbdata;
13502  mg_unlock_context(conn->phys_ctx);
13503  return 1;
13504  }
13505  }
13506  }
13507 
13508  /* next try for a partial match, we will accept uri/something */
13509  for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
13510  tmp_rh = tmp_rh->next) {
13511  if (tmp_rh->handler_type == handler_type) {
13512  if ((tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == '/')
13513  && (memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0)) {
13514  if (handler_type == WEBSOCKET_HANDLER) {
13515  *subprotocols = tmp_rh->subprotocols;
13516  *connect_handler = tmp_rh->connect_handler;
13517  *ready_handler = tmp_rh->ready_handler;
13518  *data_handler = tmp_rh->data_handler;
13519  *close_handler = tmp_rh->close_handler;
13520  } else if (handler_type == REQUEST_HANDLER) {
13521  *handler = tmp_rh->handler;
13522  /* Acquire handler and give it back */
13523  handler_info_acquire(tmp_rh);
13524  *handler_info = tmp_rh;
13525  } else { /* AUTH_HANDLER */
13526  *auth_handler = tmp_rh->auth_handler;
13527  }
13528  *cbdata = tmp_rh->cbdata;
13529  mg_unlock_context(conn->phys_ctx);
13530  return 1;
13531  }
13532  }
13533  }
13534 
13535  /* finally try for pattern match */
13536  for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
13537  tmp_rh = tmp_rh->next) {
13538  if (tmp_rh->handler_type == handler_type) {
13539  if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
13540  if (handler_type == WEBSOCKET_HANDLER) {
13541  *subprotocols = tmp_rh->subprotocols;
13542  *connect_handler = tmp_rh->connect_handler;
13543  *ready_handler = tmp_rh->ready_handler;
13544  *data_handler = tmp_rh->data_handler;
13545  *close_handler = tmp_rh->close_handler;
13546  } else if (handler_type == REQUEST_HANDLER) {
13547  *handler = tmp_rh->handler;
13548  /* Acquire handler and give it back */
13549  handler_info_acquire(tmp_rh);
13550  *handler_info = tmp_rh;
13551  } else { /* AUTH_HANDLER */
13552  *auth_handler = tmp_rh->auth_handler;
13553  }
13554  *cbdata = tmp_rh->cbdata;
13555  mg_unlock_context(conn->phys_ctx);
13556  return 1;
13557  }
13558  }
13559  }
13560 
13561  mg_unlock_context(conn->phys_ctx);
13562  }
13563  return 0; /* none found */
13564 }
13565 
13566 
13567 /* Check if the script file is in a path, allowed for script files.
13568  * This can be used if uploading files is possible not only for the server
13569  * admin, and the upload mechanism does not check the file extension.
13570  */
13571 static int
13572 is_in_script_path(const struct mg_connection *conn, const char *path)
13573 {
13574  /* TODO (Feature): Add config value for allowed script path.
13575  * Default: All allowed. */
13576  (void)conn;
13577  (void)path;
13578  return 1;
13579 }
13580 
13581 
13582 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
13583 static int
13584 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
13585  void *cbdata)
13586 {
13587  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
13588  if (pcallbacks->websocket_connect) {
13589  return pcallbacks->websocket_connect(conn);
13590  }
13591  /* No handler set - assume "OK" */
13592  return 0;
13593 }
13594 
13595 
13596 static void
13597 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
13598 {
13599  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
13600  if (pcallbacks->websocket_ready) {
13601  pcallbacks->websocket_ready(conn);
13602  }
13603 }
13604 
13605 
13606 static int
13607 deprecated_websocket_data_wrapper(struct mg_connection *conn,
13608  int bits,
13609  char *data,
13610  size_t len,
13611  void *cbdata)
13612 {
13613  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
13614  if (pcallbacks->websocket_data) {
13615  return pcallbacks->websocket_data(conn, bits, data, len);
13616  }
13617  /* No handler set - assume "OK" */
13618  return 1;
13619 }
13620 #endif
13621 
13622 
13623 /* This is the heart of the Civetweb's logic.
13624  * This function is called when the request is read, parsed and validated,
13625  * and Civetweb must decide what action to take: serve a file, or
13626  * a directory, or call embedded function, etcetera. */
13627 static void
13628 handle_request(struct mg_connection *conn)
13629 {
13630  struct mg_request_info *ri = &conn->request_info;
13631  char path[PATH_MAX];
13632  int uri_len, ssl_index;
13633  int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
13634  is_put_or_delete_request = 0, is_callback_resource = 0;
13635  int i;
13636  struct mg_file file = STRUCT_FILE_INITIALIZER;
13637  mg_request_handler callback_handler = NULL;
13638  struct mg_handler_info *handler_info = NULL;
13639  struct mg_websocket_subprotocols *subprotocols;
13640  mg_websocket_connect_handler ws_connect_handler = NULL;
13641  mg_websocket_ready_handler ws_ready_handler = NULL;
13642  mg_websocket_data_handler ws_data_handler = NULL;
13643  mg_websocket_close_handler ws_close_handler = NULL;
13644  void *callback_data = NULL;
13645  mg_authorization_handler auth_handler = NULL;
13646  void *auth_callback_data = NULL;
13647  int handler_type;
13648  time_t curtime = time(NULL);
13649  char date[64];
13650 
13651  path[0] = 0;
13652 
13653  /* 1. get the request url */
13654  /* 1.1. split into url and query string */
13655  if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
13656  != NULL) {
13657  *((char *)conn->request_info.query_string++) = '\0';
13658  }
13659 
13660  /* 1.2. do a https redirect, if required. Do not decode URIs yet. */
13661  if (!conn->client.is_ssl && conn->client.ssl_redir) {
13662  ssl_index = get_first_ssl_listener_index(conn->phys_ctx);
13663  if (ssl_index >= 0) {
13664  redirect_to_https_port(conn, ssl_index);
13665  } else {
13666  /* A http to https forward port has been specified,
13667  * but no https port to forward to. */
13668  mg_send_http_error(conn,
13669  503,
13670  "%s",
13671  "Error: SSL forward not configured properly");
13672  mg_cry_internal(conn,
13673  "%s",
13674  "Can not redirect to SSL, no SSL port available");
13675  }
13676  return;
13677  }
13678  uri_len = (int)strlen(ri->local_uri);
13679 
13680  /* 1.3. decode url (if config says so) */
13681  if (should_decode_url(conn)) {
13682  mg_url_decode(
13683  ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
13684  }
13685 
13686  /* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is
13687  * not possible */
13688  remove_double_dots_and_double_slashes((char *)ri->local_uri);
13689 
13690  /* step 1. completed, the url is known now */
13691  uri_len = (int)strlen(ri->local_uri);
13692  DEBUG_TRACE("URL: %s", ri->local_uri);
13693 
13694  /* 2. if this ip has limited speed, set it for this connection */
13695  conn->throttle = set_throttle(conn->dom_ctx->config[THROTTLE],
13696  get_remote_ip(conn),
13697  ri->local_uri);
13698 
13699  /* 3. call a "handle everything" callback, if registered */
13700  if (conn->phys_ctx->callbacks.begin_request != NULL) {
13701  /* Note that since V1.7 the "begin_request" function is called
13702  * before an authorization check. If an authorization check is
13703  * required, use a request_handler instead. */
13704  i = conn->phys_ctx->callbacks.begin_request(conn);
13705  if (i > 0) {
13706  /* callback already processed the request. Store the
13707  return value as a status code for the access log. */
13708  conn->status_code = i;
13709  discard_unread_request_data(conn);
13710  return;
13711  } else if (i == 0) {
13712  /* civetweb should process the request */
13713  } else {
13714  /* unspecified - may change with the next version */
13715  return;
13716  }
13717  }
13718 
13719  /* request not yet handled by a handler or redirect, so the request
13720  * is processed here */
13721 
13722  /* 4. Check for CORS preflight requests and handle them (if configured).
13723  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
13724  */
13725  if (!strcmp(ri->request_method, "OPTIONS")) {
13726  /* Send a response to CORS preflights only if
13727  * access_control_allow_methods is not NULL and not an empty string.
13728  * In this case, scripts can still handle CORS. */
13729  const char *cors_meth_cfg =
13730  conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_METHODS];
13731  const char *cors_orig_cfg =
13732  conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
13733  const char *cors_origin =
13734  get_header(ri->http_headers, ri->num_headers, "Origin");
13735  const char *cors_acrm = get_header(ri->http_headers,
13736  ri->num_headers,
13737  "Access-Control-Request-Method");
13738 
13739  /* Todo: check if cors_origin is in cors_orig_cfg.
13740  * Or, let the client check this. */
13741 
13742  if ((cors_meth_cfg != NULL) && (*cors_meth_cfg != 0)
13743  && (cors_orig_cfg != NULL) && (*cors_orig_cfg != 0)
13744  && (cors_origin != NULL) && (cors_acrm != NULL)) {
13745  /* This is a valid CORS preflight, and the server is configured
13746  * to
13747  * handle it automatically. */
13748  const char *cors_acrh =
13749  get_header(ri->http_headers,
13750  ri->num_headers,
13751  "Access-Control-Request-Headers");
13752 
13753  gmt_time_string(date, sizeof(date), &curtime);
13754  mg_printf(conn,
13755  "HTTP/1.1 200 OK\r\n"
13756  "Date: %s\r\n"
13757  "Access-Control-Allow-Origin: %s\r\n"
13758  "Access-Control-Allow-Methods: %s\r\n"
13759  "Content-Length: 0\r\n"
13760  "Connection: %s\r\n",
13761  date,
13762  cors_orig_cfg,
13763  ((cors_meth_cfg[0] == '*') ? cors_acrm : cors_meth_cfg),
13764  suggest_connection_header(conn));
13765 
13766  if (cors_acrh != NULL) {
13767  /* CORS request is asking for additional headers */
13768  const char *cors_hdr_cfg =
13769  conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_HEADERS];
13770 
13771  if ((cors_hdr_cfg != NULL) && (*cors_hdr_cfg != 0)) {
13772  /* Allow only if access_control_allow_headers is
13773  * not NULL and not an empty string. If this
13774  * configuration is set to *, allow everything.
13775  * Otherwise this configuration must be a list
13776  * of allowed HTTP header names. */
13777  mg_printf(conn,
13778  "Access-Control-Allow-Headers: %s\r\n",
13779  ((cors_hdr_cfg[0] == '*') ? cors_acrh
13780  : cors_hdr_cfg));
13781  }
13782  }
13783  mg_printf(conn, "Access-Control-Max-Age: 60\r\n");
13784 
13785  mg_printf(conn, "\r\n");
13786  return;
13787  }
13788  }
13789 
13790  /* 5. interpret the url to find out how the request must be handled
13791  */
13792  /* 5.1. first test, if the request targets the regular http(s)://
13793  * protocol namespace or the websocket ws(s):// protocol namespace.
13794  */
13795  is_websocket_request = is_websocket_protocol(conn);
13796 #if defined(USE_WEBSOCKET)
13797  handler_type = is_websocket_request ? WEBSOCKET_HANDLER : REQUEST_HANDLER;
13798 #else
13799  handler_type = REQUEST_HANDLER;
13800 #endif /* defined(USE_WEBSOCKET) */
13801  /* 5.2. check if the request will be handled by a callback */
13802  if (get_request_handler(conn,
13803  handler_type,
13804  &callback_handler,
13805  &subprotocols,
13806  &ws_connect_handler,
13807  &ws_ready_handler,
13808  &ws_data_handler,
13809  &ws_close_handler,
13810  NULL,
13811  &callback_data,
13812  &handler_info)) {
13813  /* 5.2.1. A callback will handle this request. All requests
13814  * handled
13815  * by a callback have to be considered as requests to a script
13816  * resource. */
13817  is_callback_resource = 1;
13818  is_script_resource = 1;
13819  is_put_or_delete_request = is_put_or_delete_method(conn);
13820  } else {
13821  no_callback_resource:
13822 
13823  /* 5.2.2. No callback is responsible for this request. The URI
13824  * addresses a file based resource (static content or Lua/cgi
13825  * scripts in the file system). */
13826  is_callback_resource = 0;
13827  interpret_uri(conn,
13828  path,
13829  sizeof(path),
13830  &file.stat,
13831  &is_found,
13832  &is_script_resource,
13833  &is_websocket_request,
13834  &is_put_or_delete_request);
13835  }
13836 
13837  /* 6. authorization check */
13838  /* 6.1. a custom authorization handler is installed */
13839  if (get_request_handler(conn,
13840  AUTH_HANDLER,
13841  NULL,
13842  NULL,
13843  NULL,
13844  NULL,
13845  NULL,
13846  NULL,
13847  &auth_handler,
13848  &auth_callback_data,
13849  NULL)) {
13850  if (!auth_handler(conn, auth_callback_data)) {
13851  return;
13852  }
13853  } else if (is_put_or_delete_request && !is_script_resource
13854  && !is_callback_resource) {
13855 /* 6.2. this request is a PUT/DELETE to a real file */
13856 /* 6.2.1. thus, the server must have real files */
13857 #if defined(NO_FILES)
13858  if (1) {
13859 #else
13860  if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL) {
13861 #endif
13862  /* This server does not have any real files, thus the
13863  * PUT/DELETE methods are not valid. */
13864  mg_send_http_error(conn,
13865  405,
13866  "%s method not allowed",
13867  conn->request_info.request_method);
13868  return;
13869  }
13870 
13871 #if !defined(NO_FILES)
13872  /* 6.2.2. Check if put authorization for static files is
13873  * available.
13874  */
13875  if (!is_authorized_for_put(conn)) {
13876  send_authorization_request(conn, NULL);
13877  return;
13878  }
13879 #endif
13880 
13881  } else {
13882  /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
13883  * or it is a PUT or DELETE request to a resource that does not
13884  * correspond to a file. Check authorization. */
13885  if (!check_authorization(conn, path)) {
13886  send_authorization_request(conn, NULL);
13887  return;
13888  }
13889  }
13890 
13891  /* request is authorized or does not need authorization */
13892 
13893  /* 7. check if there are request handlers for this uri */
13894  if (is_callback_resource) {
13895  if (!is_websocket_request) {
13896  i = callback_handler(conn, callback_data);
13897 
13898  /* Callback handler will not be used anymore. Release it */
13899  handler_info_release(handler_info);
13900 
13901  if (i > 0) {
13902  /* Do nothing, callback has served the request. Store
13903  * then return value as status code for the log and discard
13904  * all data from the client not used by the callback. */
13905  conn->status_code = i;
13906  discard_unread_request_data(conn);
13907  } else {
13908  /* The handler did NOT handle the request. */
13909  /* Some proper reactions would be:
13910  * a) close the connections without sending anything
13911  * b) send a 404 not found
13912  * c) try if there is a file matching the URI
13913  * It would be possible to do a, b or c in the callback
13914  * implementation, and return 1 - we cannot do anything
13915  * here, that is not possible in the callback.
13916  *
13917  * TODO: What would be the best reaction here?
13918  * (Note: The reaction may change, if there is a better
13919  *idea.)
13920  */
13921 
13922  /* For the moment, use option c: We look for a proper file,
13923  * but since a file request is not always a script resource,
13924  * the authorization check might be different. */
13925  interpret_uri(conn,
13926  path,
13927  sizeof(path),
13928  &file.stat,
13929  &is_found,
13930  &is_script_resource,
13931  &is_websocket_request,
13932  &is_put_or_delete_request);
13933  callback_handler = NULL;
13934 
13935  /* Here we are at a dead end:
13936  * According to URI matching, a callback should be
13937  * responsible for handling the request,
13938  * we called it, but the callback declared itself
13939  * not responsible.
13940  * We use a goto here, to get out of this dead end,
13941  * and continue with the default handling.
13942  * A goto here is simpler and better to understand
13943  * than some curious loop. */
13944  goto no_callback_resource;
13945  }
13946  } else {
13947 #if defined(USE_WEBSOCKET)
13948  handle_websocket_request(conn,
13949  path,
13950  is_callback_resource,
13951  subprotocols,
13952  ws_connect_handler,
13953  ws_ready_handler,
13954  ws_data_handler,
13955  ws_close_handler,
13956  callback_data);
13957 #endif
13958  }
13959  return;
13960  }
13961 
13962 /* 8. handle websocket requests */
13963 #if defined(USE_WEBSOCKET)
13964  if (is_websocket_request) {
13965  if (is_script_resource) {
13966 
13967  if (is_in_script_path(conn, path)) {
13968  /* Websocket Lua script */
13969  handle_websocket_request(conn,
13970  path,
13971  0 /* Lua Script */,
13972  NULL,
13973  NULL,
13974  NULL,
13975  NULL,
13976  NULL,
13977  conn->phys_ctx->user_data);
13978  } else {
13979  /* Script was in an illegal path */
13980  mg_send_http_error(conn, 403, "%s", "Forbidden");
13981  }
13982  } else {
13983 #if defined(MG_LEGACY_INTERFACE)
13984  handle_websocket_request(
13985  conn,
13986  path,
13987  !is_script_resource /* could be deprecated global callback */,
13988  NULL,
13989  deprecated_websocket_connect_wrapper,
13990  deprecated_websocket_ready_wrapper,
13991  deprecated_websocket_data_wrapper,
13992  NULL,
13993  conn->phys_ctx->user_data);
13994 #else
13995  mg_send_http_error(conn, 404, "%s", "Not found");
13996 #endif
13997  }
13998  return;
13999  } else
14000 #endif
14001 
14002 #if defined(NO_FILES)
14003  /* 9a. In case the server uses only callbacks, this uri is
14004  * unknown.
14005  * Then, all request handling ends here. */
14006  mg_send_http_error(conn, 404, "%s", "Not Found");
14007 
14008 #else
14009  /* 9b. This request is either for a static file or resource handled
14010  * by a script file. Thus, a DOCUMENT_ROOT must exist. */
14011  if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL) {
14012  mg_send_http_error(conn, 404, "%s", "Not Found");
14013  return;
14014  }
14015 
14016  /* 10. Request is handled by a script */
14017  if (is_script_resource) {
14018  handle_file_based_request(conn, path, &file);
14019  return;
14020  }
14021 
14022  /* 11. Handle put/delete/mkcol requests */
14023  if (is_put_or_delete_request) {
14024  /* 11.1. PUT method */
14025  if (!strcmp(ri->request_method, "PUT")) {
14026  put_file(conn, path);
14027  return;
14028  }
14029  /* 11.2. DELETE method */
14030  if (!strcmp(ri->request_method, "DELETE")) {
14031  delete_file(conn, path);
14032  return;
14033  }
14034  /* 11.3. MKCOL method */
14035  if (!strcmp(ri->request_method, "MKCOL")) {
14036  mkcol(conn, path);
14037  return;
14038  }
14039  /* 11.4. PATCH method
14040  * This method is not supported for static resources,
14041  * only for scripts (Lua, CGI) and callbacks. */
14042  mg_send_http_error(conn,
14043  405,
14044  "%s method not allowed",
14045  conn->request_info.request_method);
14046  return;
14047  }
14048 
14049  /* 11. File does not exist, or it was configured that it should be
14050  * hidden */
14051  if (!is_found || (must_hide_file(conn, path))) {
14052  mg_send_http_error(conn, 404, "%s", "Not found");
14053  return;
14054  }
14055 
14056  /* 12. Directory uris should end with a slash */
14057  if (file.stat.is_directory && (uri_len > 0)
14058  && (ri->local_uri[uri_len - 1] != '/')) {
14059  gmt_time_string(date, sizeof(date), &curtime);
14060  mg_printf(conn,
14061  "HTTP/1.1 301 Moved Permanently\r\n"
14062  "Location: %s/\r\n"
14063  "Date: %s\r\n"
14064  /* "Cache-Control: private\r\n" (= default) */
14065  "Content-Length: 0\r\n"
14066  "Connection: %s\r\n",
14067  ri->request_uri,
14068  date,
14069  suggest_connection_header(conn));
14070  send_additional_header(conn);
14071  mg_printf(conn, "\r\n");
14072  return;
14073  }
14074 
14075  /* 13. Handle other methods than GET/HEAD */
14076  /* 13.1. Handle PROPFIND */
14077  if (!strcmp(ri->request_method, "PROPFIND")) {
14078  handle_propfind(conn, path, &file.stat);
14079  return;
14080  }
14081  /* 13.2. Handle OPTIONS for files */
14082  if (!strcmp(ri->request_method, "OPTIONS")) {
14083  /* This standard handler is only used for real files.
14084  * Scripts should support the OPTIONS method themselves, to allow a
14085  * maximum flexibility.
14086  * Lua and CGI scripts may fully support CORS this way (including
14087  * preflights). */
14088  send_options(conn);
14089  return;
14090  }
14091  /* 13.3. everything but GET and HEAD (e.g. POST) */
14092  if ((0 != strcmp(ri->request_method, "GET"))
14093  && (0 != strcmp(ri->request_method, "HEAD"))) {
14094  mg_send_http_error(conn,
14095  405,
14096  "%s method not allowed",
14097  conn->request_info.request_method);
14098  return;
14099  }
14100 
14101  /* 14. directories */
14102  if (file.stat.is_directory) {
14103  /* Substitute files have already been handled above. */
14104  /* Here we can either generate and send a directory listing,
14105  * or send an "access denied" error. */
14106  if (!mg_strcasecmp(conn->dom_ctx->config[ENABLE_DIRECTORY_LISTING],
14107  "yes")) {
14108  handle_directory_request(conn, path);
14109  } else {
14110  mg_send_http_error(conn,
14111  403,
14112  "%s",
14113  "Error: Directory listing denied");
14114  }
14115  return;
14116  }
14117 
14118  /* 15. read a normal file with GET or HEAD */
14119  handle_file_based_request(conn, path, &file);
14120 #endif /* !defined(NO_FILES) */
14121 }
14122 
14123 
14124 static void
14125 handle_file_based_request(struct mg_connection *conn,
14126  const char *path,
14127  struct mg_file *file)
14128 {
14129  if (!conn || !conn->dom_ctx) {
14130  return;
14131  }
14132 
14133  if (0) {
14134 #if defined(USE_LUA)
14135  } else if (match_prefix(
14136  conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
14137  strlen(conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
14138  path)
14139  > 0) {
14140  if (is_in_script_path(conn, path)) {
14141  /* Lua server page: an SSI like page containing mostly plain
14142  * html
14143  * code
14144  * plus some tags with server generated contents. */
14145  handle_lsp_request(conn, path, file, NULL);
14146  } else {
14147  /* Script was in an illegal path */
14148  mg_send_http_error(conn, 403, "%s", "Forbidden");
14149  }
14150 
14151  } else if (match_prefix(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS],
14152  strlen(
14153  conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS]),
14154  path)
14155  > 0) {
14156  if (is_in_script_path(conn, path)) {
14157  /* Lua in-server module script: a CGI like script used to
14158  * generate
14159  * the
14160  * entire reply. */
14161  mg_exec_lua_script(conn, path, NULL);
14162  } else {
14163  /* Script was in an illegal path */
14164  mg_send_http_error(conn, 403, "%s", "Forbidden");
14165  }
14166 #endif
14167 #if defined(USE_DUKTAPE)
14168  } else if (match_prefix(
14169  conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
14170  strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
14171  path)
14172  > 0) {
14173  if (is_in_script_path(conn, path)) {
14174  /* Call duktape to generate the page */
14175  mg_exec_duktape_script(conn, path);
14176  } else {
14177  /* Script was in an illegal path */
14178  mg_send_http_error(conn, 403, "%s", "Forbidden");
14179  }
14180 #endif
14181 #if !defined(NO_CGI)
14182  } else if (match_prefix(conn->dom_ctx->config[CGI_EXTENSIONS],
14183  strlen(conn->dom_ctx->config[CGI_EXTENSIONS]),
14184  path)
14185  > 0) {
14186  if (is_in_script_path(conn, path)) {
14187  /* CGI scripts may support all HTTP methods */
14188  handle_cgi_request(conn, path);
14189  } else {
14190  /* Script was in an illegal path */
14191  mg_send_http_error(conn, 403, "%s", "Forbidden");
14192  }
14193 #endif /* !NO_CGI */
14194  } else if (match_prefix(conn->dom_ctx->config[SSI_EXTENSIONS],
14195  strlen(conn->dom_ctx->config[SSI_EXTENSIONS]),
14196  path)
14197  > 0) {
14198  if (is_in_script_path(conn, path)) {
14199  handle_ssi_file_request(conn, path, file);
14200  } else {
14201  /* Script was in an illegal path */
14202  mg_send_http_error(conn, 403, "%s", "Forbidden");
14203  }
14204 #if !defined(NO_CACHING)
14205  } else if ((!conn->in_error_handler)
14206  && is_not_modified(conn, &file->stat)) {
14207  /* Send 304 "Not Modified" - this must not send any body data */
14208  handle_not_modified_static_file_request(conn, file);
14209 #endif /* !NO_CACHING */
14210  } else {
14211  handle_static_file_request(conn, path, file, NULL, NULL);
14212  }
14213 }
14214 
14215 
14216 static void
14217 close_all_listening_sockets(struct mg_context *ctx)
14218 {
14219  unsigned int i;
14220  if (!ctx) {
14221  return;
14222  }
14223 
14224  for (i = 0; i < ctx->num_listening_sockets; i++) {
14225  closesocket(ctx->listening_sockets[i].sock);
14226  ctx->listening_sockets[i].sock = INVALID_SOCKET;
14227  }
14228  mg_free(ctx->listening_sockets);
14229  ctx->listening_sockets = NULL;
14230  mg_free(ctx->listening_socket_fds);
14231  ctx->listening_socket_fds = NULL;
14232 }
14233 
14234 
14235 /* Valid listening port specification is: [ip_address:]port[s]
14236  * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 192.0.2.3:8080s
14237  * Examples for IPv6: [::]:80, [::1]:80,
14238  * [2001:0db8:7654:3210:FEDC:BA98:7654:3210]:443s
14239  * see https://tools.ietf.org/html/rfc3513#section-2.2
14240  * In order to bind to both, IPv4 and IPv6, you can either add
14241  * both ports using 8080,[::]:8080, or the short form +8080.
14242  * Both forms differ in detail: 8080,[::]:8080 create two sockets,
14243  * one only accepting IPv4 the other only IPv6. +8080 creates
14244  * one socket accepting IPv4 and IPv6. Depending on the IPv6
14245  * environment, they might work differently, or might not work
14246  * at all - it must be tested what options work best in the
14247  * relevant network environment.
14248  */
14249 static int
14250 parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
14251 {
14252  unsigned int a, b, c, d, port;
14253  int ch, len;
14254  const char *cb;
14255 #if defined(USE_IPV6)
14256  char buf[100] = {0};
14257 #endif
14258 
14259  /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
14260  * Also, all-zeroes in the socket address means binding to all addresses
14261  * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
14262  memset(so, 0, sizeof(*so));
14263  so->lsa.sin.sin_family = AF_INET;
14264  *ip_version = 0;
14265 
14266  /* Initialize port and len as invalid. */
14267  port = 0;
14268  len = 0;
14269 
14270  /* Test for different ways to format this string */
14271  if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
14272  == 5) {
14273  /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
14274  so->lsa.sin.sin_addr.s_addr =
14275  htonl((a << 24) | (b << 16) | (c << 8) | d);
14276  so->lsa.sin.sin_port = htons((uint16_t)port);
14277  *ip_version = 4;
14278 
14279 #if defined(USE_IPV6)
14280  } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
14281  && mg_inet_pton(
14282  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
14283  /* IPv6 address, examples: see above */
14284  /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
14285  */
14286  so->lsa.sin6.sin6_port = htons((uint16_t)port);
14287  *ip_version = 6;
14288 #endif
14289 
14290  } else if ((vec->ptr[0] == '+')
14291  && (sscanf(vec->ptr + 1, "%u%n", &port, &len) == 1)) {
14292 
14293  /* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */
14294  /* Add 1 to len for the + character we skipped before */
14295  len++;
14296 
14297 #if defined(USE_IPV6)
14298  /* Set socket family to IPv6, do not use IPV6_V6ONLY */
14299  so->lsa.sin6.sin6_family = AF_INET6;
14300  so->lsa.sin6.sin6_port = htons((uint16_t)port);
14301  *ip_version = 4 + 6;
14302 #else
14303  /* Bind to IPv4 only, since IPv6 is not built in. */
14304  so->lsa.sin.sin_port = htons((uint16_t)port);
14305  *ip_version = 4;
14306 #endif
14307 
14308  } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
14309  /* If only port is specified, bind to IPv4, INADDR_ANY */
14310  so->lsa.sin.sin_port = htons((uint16_t)port);
14311  *ip_version = 4;
14312 
14313  } else if ((cb = strchr(vec->ptr, ':')) != NULL) {
14314  /* String could be a hostname. This check algotithm
14315  * will only work for RFC 952 compliant hostnames,
14316  * starting with a letter, containing only letters,
14317  * digits and hyphen ('-'). Newer specs may allow
14318  * more, but this is not guaranteed here, since it
14319  * may interfere with rules for port option lists. */
14320 
14321  /* According to RFC 1035, hostnames are restricted to 255 characters
14322  * in total (63 between two dots). */
14323  char hostname[256];
14324  size_t hostnlen = (size_t)(cb - vec->ptr);
14325 
14326  if (hostnlen >= sizeof(hostname)) {
14327  /* This would be invalid in any case */
14328  *ip_version = 0;
14329  return 0;
14330  }
14331 
14332  memcpy(hostname, vec->ptr, hostnlen);
14333  hostname[hostnlen] = 0;
14334 
14335  if (mg_inet_pton(
14336  AF_INET, vec->ptr, &so->lsa.sin, sizeof(so->lsa.sin))) {
14337  if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
14338  *ip_version = 4;
14339  so->lsa.sin.sin_family = AF_INET;
14340  so->lsa.sin.sin_port = htons((uint16_t)port);
14341  len += (int)(hostnlen + 1);
14342  } else {
14343  port = 0;
14344  len = 0;
14345  }
14346 #if defined(USE_IPV6)
14347  } else if (mg_inet_pton(AF_INET6,
14348  vec->ptr,
14349  &so->lsa.sin6,
14350  sizeof(so->lsa.sin6))) {
14351  if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
14352  *ip_version = 6;
14353  so->lsa.sin6.sin6_family = AF_INET6;
14354  so->lsa.sin.sin_port = htons((uint16_t)port);
14355  len += (int)(hostnlen + 1);
14356  } else {
14357  port = 0;
14358  len = 0;
14359  }
14360 #endif
14361  }
14362 
14363 
14364  } else {
14365  /* Parsing failure. */
14366  }
14367 
14368  /* sscanf and the option splitting code ensure the following condition
14369  */
14370  if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
14371  *ip_version = 0;
14372  return 0;
14373  }
14374  ch = vec->ptr[len]; /* Next character after the port number */
14375  so->is_ssl = (ch == 's');
14376  so->ssl_redir = (ch == 'r');
14377 
14378  /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
14379  if (is_valid_port(port)
14380  && ((ch == '\0') || (ch == 's') || (ch == 'r') || (ch == ','))) {
14381  return 1;
14382  }
14383 
14384  /* Reset ip_version to 0 if there is an error */
14385  *ip_version = 0;
14386  return 0;
14387 }
14388 
14389 
14390 /* Is there any SSL port in use? */
14391 static int
14392 is_ssl_port_used(const char *ports)
14393 {
14394  if (ports) {
14395  /* There are several different allowed syntax variants:
14396  * - "80" for a single port using every network interface
14397  * - "localhost:80" for a single port using only localhost
14398  * - "80,localhost:8080" for two ports, one bound to localhost
14399  * - "80,127.0.0.1:8084,[::1]:8086" for three ports, one bound
14400  * to IPv4 localhost, one to IPv6 localhost
14401  * - "+80" use port 80 for IPv4 and IPv6
14402  * - "+80r,+443s" port 80 (HTTP) is a redirect to port 443 (HTTPS),
14403  * for both: IPv4 and IPv4
14404  * - "+443s,localhost:8080" port 443 (HTTPS) for every interface,
14405  * additionally port 8080 bound to localhost connections
14406  *
14407  * If we just look for 's' anywhere in the string, "localhost:80"
14408  * will be detected as SSL (false positive).
14409  * Looking for 's' after a digit may cause false positives in
14410  * "my24service:8080".
14411  * Looking from 's' backward if there are only ':' and numbers
14412  * before will not work for "24service:8080" (non SSL, port 8080)
14413  * or "24s" (SSL, port 24).
14414  *
14415  * Remark: Initially hostnames were not allowed to start with a
14416  * digit (according to RFC 952), this was allowed later (RFC 1123,
14417  * Section 2.1).
14418  *
14419  * To get this correct, the entire string must be parsed as a whole,
14420  * reading it as a list element for element and parsing with an
14421  * algorithm equivalent to parse_port_string.
14422  *
14423  * In fact, we use local interface names here, not arbitrary hostnames,
14424  * so in most cases the only name will be "localhost".
14425  *
14426  * So, for now, we use this simple algorithm, that may still return
14427  * a false positive in bizarre cases.
14428  */
14429  int i;
14430  int portslen = (int)strlen(ports);
14431  char prevIsNumber = 0;
14432 
14433  for (i = 0; i < portslen; i++) {
14434  if (prevIsNumber && (ports[i] == 's' || ports[i] == 'r')) {
14435  return 1;
14436  }
14437  if (ports[i] >= '0' && ports[i] <= '9') {
14438  prevIsNumber = 1;
14439  } else {
14440  prevIsNumber = 0;
14441  }
14442  }
14443  }
14444  return 0;
14445 }
14446 
14447 
14448 static int
14449 set_ports_option(struct mg_context *phys_ctx)
14450 {
14451  const char *list;
14452  int on = 1;
14453 #if defined(USE_IPV6)
14454  int off = 0;
14455 #endif
14456  struct vec vec;
14457  struct socket so, *ptr;
14458 
14459  struct pollfd *pfd;
14460  union usa usa;
14461  socklen_t len;
14462  int ip_version;
14463 
14464  int portsTotal = 0;
14465  int portsOk = 0;
14466 
14467  if (!phys_ctx) {
14468  return 0;
14469  }
14470 
14471  memset(&so, 0, sizeof(so));
14472  memset(&usa, 0, sizeof(usa));
14473  len = sizeof(usa);
14474  list = phys_ctx->dd.config[LISTENING_PORTS];
14475 
14476  while ((list = next_option(list, &vec, NULL)) != NULL) {
14477 
14478  portsTotal++;
14479 
14480  if (!parse_port_string(&vec, &so, &ip_version)) {
14481  mg_cry_internal(
14482  fc(phys_ctx),
14483  "%.*s: invalid port spec (entry %i). Expecting list of: %s",
14484  (int)vec.len,
14485  vec.ptr,
14486  portsTotal,
14487  "[IP_ADDRESS:]PORT[s|r]");
14488  continue;
14489  }
14490 
14491 #if !defined(NO_SSL)
14492  if (so.is_ssl && phys_ctx->dd.ssl_ctx == NULL) {
14493 
14494  mg_cry_internal(fc(phys_ctx),
14495  "Cannot add SSL socket (entry %i)",
14496  portsTotal);
14497  continue;
14498  }
14499 #endif
14500 
14501  if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
14502  == INVALID_SOCKET) {
14503 
14504  mg_cry_internal(fc(phys_ctx),
14505  "cannot create socket (entry %i)",
14506  portsTotal);
14507  continue;
14508  }
14509 
14510 #if defined(_WIN32)
14511  /* Windows SO_REUSEADDR lets many procs binds to a
14512  * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
14513  * if someone already has the socket -- DTL */
14514  /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
14515  * Windows might need a few seconds before
14516  * the same port can be used again in the
14517  * same process, so a short Sleep may be
14518  * required between mg_stop and mg_start.
14519  */
14520  if (setsockopt(so.sock,
14521  SOL_SOCKET,
14522  SO_EXCLUSIVEADDRUSE,
14523  (SOCK_OPT_TYPE)&on,
14524  sizeof(on))
14525  != 0) {
14526 
14527  /* Set reuse option, but don't abort on errors. */
14528  mg_cry_internal(
14529  fc(phys_ctx),
14530  "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
14531  portsTotal);
14532  }
14533 #else
14534  if (setsockopt(so.sock,
14535  SOL_SOCKET,
14536  SO_REUSEADDR,
14537  (SOCK_OPT_TYPE)&on,
14538  sizeof(on))
14539  != 0) {
14540 
14541  /* Set reuse option, but don't abort on errors. */
14542  mg_cry_internal(fc(phys_ctx),
14543  "cannot set socket option SO_REUSEADDR (entry %i)",
14544  portsTotal);
14545  }
14546 #endif
14547 
14548  if (ip_version > 4) {
14549 /* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */
14550 #if defined(USE_IPV6)
14551  if (ip_version > 6) {
14552  if (so.lsa.sa.sa_family == AF_INET6
14553  && setsockopt(so.sock,
14554  IPPROTO_IPV6,
14555  IPV6_V6ONLY,
14556  (void *)&off,
14557  sizeof(off))
14558  != 0) {
14559 
14560  /* Set IPv6 only option, but don't abort on errors. */
14561  mg_cry_internal(
14562  fc(phys_ctx),
14563  "cannot set socket option IPV6_V6ONLY=off (entry %i)",
14564  portsTotal);
14565  }
14566  } else {
14567  if (so.lsa.sa.sa_family == AF_INET6
14568  && setsockopt(so.sock,
14569  IPPROTO_IPV6,
14570  IPV6_V6ONLY,
14571  (void *)&on,
14572  sizeof(on))
14573  != 0) {
14574 
14575  /* Set IPv6 only option, but don't abort on errors. */
14576  mg_cry_internal(
14577  fc(phys_ctx),
14578  "cannot set socket option IPV6_V6ONLY=on (entry %i)",
14579  portsTotal);
14580  }
14581  }
14582 #else
14583  mg_cry_internal(fc(phys_ctx), "%s", "IPv6 not available");
14584  closesocket(so.sock);
14585  so.sock = INVALID_SOCKET;
14586  continue;
14587 #endif
14588  }
14589 
14590  if (so.lsa.sa.sa_family == AF_INET) {
14591 
14592  len = sizeof(so.lsa.sin);
14593  if (bind(so.sock, &so.lsa.sa, len) != 0) {
14594  mg_cry_internal(fc(phys_ctx),
14595  "cannot bind to %.*s: %d (%s)",
14596  (int)vec.len,
14597  vec.ptr,
14598  (int)ERRNO,
14599  strerror(errno));
14600  closesocket(so.sock);
14601  so.sock = INVALID_SOCKET;
14602  continue;
14603  }
14604  }
14605 #if defined(USE_IPV6)
14606  else if (so.lsa.sa.sa_family == AF_INET6) {
14607 
14608  len = sizeof(so.lsa.sin6);
14609  if (bind(so.sock, &so.lsa.sa, len) != 0) {
14610  mg_cry_internal(fc(phys_ctx),
14611  "cannot bind to IPv6 %.*s: %d (%s)",
14612  (int)vec.len,
14613  vec.ptr,
14614  (int)ERRNO,
14615  strerror(errno));
14616  closesocket(so.sock);
14617  so.sock = INVALID_SOCKET;
14618  continue;
14619  }
14620  }
14621 #endif
14622  else {
14623  mg_cry_internal(
14624  fc(phys_ctx),
14625  "cannot bind: address family not supported (entry %i)",
14626  portsTotal);
14627  closesocket(so.sock);
14628  so.sock = INVALID_SOCKET;
14629  continue;
14630  }
14631 
14632  if (listen(so.sock, SOMAXCONN) != 0) {
14633 
14634  mg_cry_internal(fc(phys_ctx),
14635  "cannot listen to %.*s: %d (%s)",
14636  (int)vec.len,
14637  vec.ptr,
14638  (int)ERRNO,
14639  strerror(errno));
14640  closesocket(so.sock);
14641  so.sock = INVALID_SOCKET;
14642  continue;
14643  }
14644 
14645  if ((getsockname(so.sock, &(usa.sa), &len) != 0)
14646  || (usa.sa.sa_family != so.lsa.sa.sa_family)) {
14647 
14648  int err = (int)ERRNO;
14649  mg_cry_internal(fc(phys_ctx),
14650  "call to getsockname failed %.*s: %d (%s)",
14651  (int)vec.len,
14652  vec.ptr,
14653  err,
14654  strerror(errno));
14655  closesocket(so.sock);
14656  so.sock = INVALID_SOCKET;
14657  continue;
14658  }
14659 
14660 /* Update lsa port in case of random free ports */
14661 #if defined(USE_IPV6)
14662  if (so.lsa.sa.sa_family == AF_INET6) {
14663  so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
14664  } else
14665 #endif
14666  {
14667  so.lsa.sin.sin_port = usa.sin.sin_port;
14668  }
14669 
14670  if ((ptr = (struct socket *)
14671  mg_realloc_ctx(phys_ctx->listening_sockets,
14672  (phys_ctx->num_listening_sockets + 1)
14673  * sizeof(phys_ctx->listening_sockets[0]),
14674  phys_ctx))
14675  == NULL) {
14676 
14677  mg_cry_internal(fc(phys_ctx), "%s", "Out of memory");
14678  closesocket(so.sock);
14679  so.sock = INVALID_SOCKET;
14680  continue;
14681  }
14682 
14683  if ((pfd = (struct pollfd *)
14684  mg_realloc_ctx(phys_ctx->listening_socket_fds,
14685  (phys_ctx->num_listening_sockets + 1)
14686  * sizeof(phys_ctx->listening_socket_fds[0]),
14687  phys_ctx))
14688  == NULL) {
14689 
14690  mg_cry_internal(fc(phys_ctx), "%s", "Out of memory");
14691  closesocket(so.sock);
14692  so.sock = INVALID_SOCKET;
14693  mg_free(ptr);
14694  continue;
14695  }
14696 
14697  set_close_on_exec(so.sock, fc(phys_ctx));
14698  phys_ctx->listening_sockets = ptr;
14699  phys_ctx->listening_sockets[phys_ctx->num_listening_sockets] = so;
14700  phys_ctx->listening_socket_fds = pfd;
14701  phys_ctx->num_listening_sockets++;
14702  portsOk++;
14703  }
14704 
14705  if (portsOk != portsTotal) {
14706  close_all_listening_sockets(phys_ctx);
14707  portsOk = 0;
14708  }
14709 
14710  return portsOk;
14711 }
14712 
14713 
14714 static const char *
14715 header_val(const struct mg_connection *conn, const char *header)
14716 {
14717  const char *header_value;
14718 
14719  if ((header_value = mg_get_header(conn, header)) == NULL) {
14720  return "-";
14721  } else {
14722  return header_value;
14723  }
14724 }
14725 
14726 
14727 #if defined(MG_EXTERNAL_FUNCTION_log_access)
14728 static void log_access(const struct mg_connection *conn);
14729 #include "external_log_access.inl"
14730 #else
14731 
14732 static void
14733 log_access(const struct mg_connection *conn)
14734 {
14735  const struct mg_request_info *ri;
14736  struct mg_file fi;
14737  char date[64], src_addr[IP_ADDR_STR_LEN];
14738  struct tm *tm;
14739 
14740  const char *referer;
14741  const char *user_agent;
14742 
14743  char buf[4096];
14744 
14745  if (!conn || !conn->dom_ctx) {
14746  return;
14747  }
14748 
14749  if (conn->dom_ctx->config[ACCESS_LOG_FILE] != NULL) {
14750  if (mg_fopen(conn,
14751  conn->dom_ctx->config[ACCESS_LOG_FILE],
14752  MG_FOPEN_MODE_APPEND,
14753  &fi)
14754  == 0) {
14755  fi.access.fp = NULL;
14756  }
14757  } else {
14758  fi.access.fp = NULL;
14759  }
14760 
14761  /* Log is written to a file and/or a callback. If both are not set,
14762  * executing the rest of the function is pointless. */
14763  if ((fi.access.fp == NULL)
14764  && (conn->phys_ctx->callbacks.log_access == NULL)) {
14765  return;
14766  }
14767 
14768  tm = localtime(&conn->conn_birth_time);
14769  if (tm != NULL) {
14770  strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
14771  } else {
14772  mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
14773  date[sizeof(date) - 1] = '\0';
14774  }
14775 
14776  ri = &conn->request_info;
14777 
14778  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
14779  referer = header_val(conn, "Referer");
14780  user_agent = header_val(conn, "User-Agent");
14781 
14782  mg_snprintf(conn,
14783  NULL, /* Ignore truncation in access log */
14784  buf,
14785  sizeof(buf),
14786  "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
14787  src_addr,
14788  (ri->remote_user == NULL) ? "-" : ri->remote_user,
14789  date,
14790  ri->request_method ? ri->request_method : "-",
14791  ri->request_uri ? ri->request_uri : "-",
14792  ri->query_string ? "?" : "",
14793  ri->query_string ? ri->query_string : "",
14794  ri->http_version,
14795  conn->status_code,
14796  conn->num_bytes_sent,
14797  referer,
14798  user_agent);
14799 
14800  if (conn->phys_ctx->callbacks.log_access) {
14801  conn->phys_ctx->callbacks.log_access(conn, buf);
14802  }
14803 
14804  if (fi.access.fp) {
14805  int ok = 1;
14806  flockfile(fi.access.fp);
14807  if (fprintf(fi.access.fp, "%s\n", buf) < 1) {
14808  ok = 0;
14809  }
14810  if (fflush(fi.access.fp) != 0) {
14811  ok = 0;
14812  }
14813  funlockfile(fi.access.fp);
14814  if (mg_fclose(&fi.access) != 0) {
14815  ok = 0;
14816  }
14817  if (!ok) {
14818  mg_cry_internal(conn,
14819  "Error writing log file %s",
14820  conn->dom_ctx->config[ACCESS_LOG_FILE]);
14821  }
14822  }
14823 }
14824 
14825 #endif /* Externally provided function */
14826 
14827 
14828 /* Verify given socket address against the ACL.
14829  * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
14830  */
14831 static int
14832 check_acl(struct mg_context *phys_ctx, uint32_t remote_ip)
14833 {
14834  int allowed, flag;
14835  uint32_t net, mask;
14836  struct vec vec;
14837 
14838  if (phys_ctx) {
14839  const char *list = phys_ctx->dd.config[ACCESS_CONTROL_LIST];
14840 
14841  /* If any ACL is set, deny by default */
14842  allowed = (list == NULL) ? '+' : '-';
14843 
14844  while ((list = next_option(list, &vec, NULL)) != NULL) {
14845  flag = vec.ptr[0];
14846  if ((flag != '+' && flag != '-')
14847  || (parse_net(&vec.ptr[1], &net, &mask) == 0)) {
14848  mg_cry_internal(fc(phys_ctx),
14849  "%s: subnet must be [+|-]x.x.x.x[/x]",
14850  __func__);
14851  return -1;
14852  }
14853 
14854  if (net == (remote_ip & mask)) {
14855  allowed = flag;
14856  }
14857  }
14858 
14859  return allowed == '+';
14860  }
14861  return -1;
14862 }
14863 
14864 
14865 #if !defined(_WIN32)
14866 static int
14867 set_uid_option(struct mg_context *phys_ctx)
14868 {
14869  int success = 0;
14870 
14871  if (phys_ctx) {
14872  /* We are currently running as curr_uid. */
14873  const uid_t curr_uid = getuid();
14874  /* If set, we want to run as run_as_user. */
14875  const char *run_as_user = phys_ctx->dd.config[RUN_AS_USER];
14876  const struct passwd *to_pw = NULL;
14877 
14878  if (run_as_user != NULL && (to_pw = getpwnam(run_as_user)) == NULL) {
14879  /* run_as_user does not exist on the system. We can't proceed
14880  * further. */
14881  mg_cry_internal(fc(phys_ctx),
14882  "%s: unknown user [%s]",
14883  __func__,
14884  run_as_user);
14885  } else if (run_as_user == NULL || curr_uid == to_pw->pw_uid) {
14886  /* There was either no request to change user, or we're already
14887  * running as run_as_user. Nothing else to do.
14888  */
14889  success = 1;
14890  } else {
14891  /* Valid change request. */
14892  if (setgid(to_pw->pw_gid) == -1) {
14893  mg_cry_internal(fc(phys_ctx),
14894  "%s: setgid(%s): %s",
14895  __func__,
14896  run_as_user,
14897  strerror(errno));
14898  } else if (setgroups(0, NULL) == -1) {
14899  mg_cry_internal(fc(phys_ctx),
14900  "%s: setgroups(): %s",
14901  __func__,
14902  strerror(errno));
14903  } else if (setuid(to_pw->pw_uid) == -1) {
14904  mg_cry_internal(fc(phys_ctx),
14905  "%s: setuid(%s): %s",
14906  __func__,
14907  run_as_user,
14908  strerror(errno));
14909  } else {
14910  success = 1;
14911  }
14912  }
14913  }
14914 
14915  return success;
14916 }
14917 #endif /* !_WIN32 */
14918 
14919 
14920 static void
14921 tls_dtor(void *key)
14922 {
14923  struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
14924  /* key == pthread_getspecific(sTlsKey); */
14925 
14926  if (tls) {
14927  if (tls->is_master == 2) {
14928  tls->is_master = -3; /* Mark memory as dead */
14929  mg_free(tls);
14930  }
14931  }
14932  pthread_setspecific(sTlsKey, NULL);
14933 }
14934 
14935 
14936 #if !defined(NO_SSL)
14937 
14938 static int ssl_use_pem_file(struct mg_context *phys_ctx,
14939  struct mg_domain_context *dom_ctx,
14940  const char *pem,
14941  const char *chain);
14942 static const char *ssl_error(void);
14943 
14944 
14945 static int
14946 refresh_trust(struct mg_connection *conn)
14947 {
14948  static int reload_lock = 0;
14949  static long int data_check = 0;
14950  volatile int *p_reload_lock = (volatile int *)&reload_lock;
14951 
14952  struct stat cert_buf;
14953  long int t;
14954  const char *pem;
14955  const char *chain;
14956  int should_verify_peer;
14957 
14958  if ((pem = conn->dom_ctx->config[SSL_CERTIFICATE]) == NULL) {
14959  /* If peem is NULL and conn->phys_ctx->callbacks.init_ssl is not,
14960  * refresh_trust still can not work. */
14961  return 0;
14962  }
14963  chain = conn->dom_ctx->config[SSL_CERTIFICATE_CHAIN];
14964  if (chain == NULL) {
14965  /* pem is not NULL here */
14966  chain = pem;
14967  }
14968  if (*chain == 0) {
14969  chain = NULL;
14970  }
14971 
14972  t = data_check;
14973  if (stat(pem, &cert_buf) != -1) {
14974  t = (long int)cert_buf.st_mtime;
14975  }
14976 
14977  if (data_check != t) {
14978  data_check = t;
14979 
14980  should_verify_peer = 0;
14981  if (conn->dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
14982  if (mg_strcasecmp(conn->dom_ctx->config[SSL_DO_VERIFY_PEER], "yes")
14983  == 0) {
14984  should_verify_peer = 1;
14985  } else if (mg_strcasecmp(conn->dom_ctx->config[SSL_DO_VERIFY_PEER],
14986  "optional")
14987  == 0) {
14988  should_verify_peer = 1;
14989  }
14990  }
14991 
14992  if (should_verify_peer) {
14993  char *ca_path = conn->dom_ctx->config[SSL_CA_PATH];
14994  char *ca_file = conn->dom_ctx->config[SSL_CA_FILE];
14995  if (SSL_CTX_load_verify_locations(conn->dom_ctx->ssl_ctx,
14996  ca_file,
14997  ca_path)
14998  != 1) {
14999  mg_cry_internal(
15000  fc(conn->phys_ctx),
15001  "SSL_CTX_load_verify_locations error: %s "
15002  "ssl_verify_peer requires setting "
15003  "either ssl_ca_path or ssl_ca_file. Is any of them "
15004  "present in "
15005  "the .conf file?",
15006  ssl_error());
15007  return 0;
15008  }
15009  }
15010 
15011  if (1 == mg_atomic_inc(p_reload_lock)) {
15012  if (ssl_use_pem_file(conn->phys_ctx, conn->dom_ctx, pem, chain)
15013  == 0) {
15014  return 0;
15015  }
15016  *p_reload_lock = 0;
15017  }
15018  }
15019  /* lock while cert is reloading */
15020  while (*p_reload_lock) {
15021  sleep(1);
15022  }
15023 
15024  return 1;
15025 }
15026 
15027 #if defined(OPENSSL_API_1_1)
15028 #else
15029 static pthread_mutex_t *ssl_mutexes;
15030 #endif /* OPENSSL_API_1_1 */
15031 
15032 static int
15033 sslize(struct mg_connection *conn,
15034  SSL_CTX *s,
15035  int (*func)(SSL *),
15036  volatile int *stop_server,
15037  const struct mg_client_options *client_options)
15038 {
15039  int ret, err;
15040  int short_trust;
15041  unsigned i;
15042 
15043  if (!conn) {
15044  return 0;
15045  }
15046 
15047  short_trust =
15048  (conn->dom_ctx->config[SSL_SHORT_TRUST] != NULL)
15049  && (mg_strcasecmp(conn->dom_ctx->config[SSL_SHORT_TRUST], "yes") == 0);
15050 
15051  if (short_trust) {
15052  int trust_ret = refresh_trust(conn);
15053  if (!trust_ret) {
15054  return trust_ret;
15055  }
15056  }
15057 
15058  conn->ssl = SSL_new(s);
15059  if (conn->ssl == NULL) {
15060  return 0;
15061  }
15062  SSL_set_app_data(conn->ssl, (char *)conn);
15063 
15064  ret = SSL_set_fd(conn->ssl, conn->client.sock);
15065  if (ret != 1) {
15066  err = SSL_get_error(conn->ssl, ret);
15067  mg_cry_internal(conn, "SSL error %i, destroying SSL context", err);
15068  SSL_free(conn->ssl);
15069  conn->ssl = NULL;
15070  OPENSSL_REMOVE_THREAD_STATE();
15071  return 0;
15072  }
15073 
15074  if (client_options) {
15075  if (client_options->host_name) {
15076  SSL_set_tlsext_host_name(conn->ssl, client_options->host_name);
15077  }
15078  }
15079 
15080  /* SSL functions may fail and require to be called again:
15081  * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
15082  * Here "func" could be SSL_connect or SSL_accept. */
15083  for (i = 16; i <= 1024; i *= 2) {
15084  ret = func(conn->ssl);
15085  if (ret != 1) {
15086  err = SSL_get_error(conn->ssl, ret);
15087  if ((err == SSL_ERROR_WANT_CONNECT)
15088  || (err == SSL_ERROR_WANT_ACCEPT)
15089  || (err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE)
15090  || (err == SSL_ERROR_WANT_X509_LOOKUP)) {
15091  /* Need to retry the function call "later".
15092  * See https://linux.die.net/man/3/ssl_get_error
15093  * This is typical for non-blocking sockets. */
15094  if (*stop_server) {
15095  /* Don't wait if the server is going to be stopped. */
15096  break;
15097  }
15098  mg_sleep(i);
15099 
15100  } else if (err == SSL_ERROR_SYSCALL) {
15101  /* This is an IO error. Look at errno. */
15102  err = errno;
15103  mg_cry_internal(conn, "SSL syscall error %i", err);
15104  break;
15105 
15106  } else {
15107  /* This is an SSL specific error, e.g. SSL_ERROR_SSL */
15108  mg_cry_internal(conn, "sslize error: %s", ssl_error());
15109  break;
15110  }
15111 
15112  } else {
15113  /* success */
15114  break;
15115  }
15116  }
15117 
15118  if (ret != 1) {
15119  SSL_free(conn->ssl);
15120  conn->ssl = NULL;
15121  OPENSSL_REMOVE_THREAD_STATE();
15122  return 0;
15123  }
15124 
15125  return 1;
15126 }
15127 
15128 
15129 /* Return OpenSSL error message (from CRYPTO lib) */
15130 static const char *
15131 ssl_error(void)
15132 {
15133  unsigned long err;
15134  err = ERR_get_error();
15135  return ((err == 0) ? "" : ERR_error_string(err, NULL));
15136 }
15137 
15138 
15139 static int
15140 hexdump2string(void *mem, int memlen, char *buf, int buflen)
15141 {
15142  int i;
15143  const char hexdigit[] = "0123456789abcdef";
15144 
15145  if ((memlen <= 0) || (buflen <= 0)) {
15146  return 0;
15147  }
15148  if (buflen < (3 * memlen)) {
15149  return 0;
15150  }
15151 
15152  for (i = 0; i < memlen; i++) {
15153  if (i > 0) {
15154  buf[3 * i - 1] = ' ';
15155  }
15156  buf[3 * i] = hexdigit[(((uint8_t *)mem)[i] >> 4) & 0xF];
15157  buf[3 * i + 1] = hexdigit[((uint8_t *)mem)[i] & 0xF];
15158  }
15159  buf[3 * memlen - 1] = 0;
15160 
15161  return 1;
15162 }
15163 
15164 
15165 static void
15166 ssl_get_client_cert_info(struct mg_connection *conn)
15167 {
15168  X509 *cert = SSL_get_peer_certificate(conn->ssl);
15169  if (cert) {
15170  char str_subject[1024];
15171  char str_issuer[1024];
15172  char str_finger[1024];
15173  unsigned char buf[256];
15174  char *str_serial = NULL;
15175  unsigned int ulen;
15176  int ilen;
15177  unsigned char *tmp_buf;
15178  unsigned char *tmp_p;
15179 
15180  /* Handle to algorithm used for fingerprint */
15181  const EVP_MD *digest = EVP_get_digestbyname("sha1");
15182 
15183  /* Get Subject and issuer */
15184  X509_NAME *subj = X509_get_subject_name(cert);
15185  X509_NAME *iss = X509_get_issuer_name(cert);
15186 
15187  /* Get serial number */
15188  ASN1_INTEGER *serial = X509_get_serialNumber(cert);
15189 
15190  /* Translate serial number to a hex string */
15191  BIGNUM *serial_bn = ASN1_INTEGER_to_BN(serial, NULL);
15192  str_serial = BN_bn2hex(serial_bn);
15193  BN_free(serial_bn);
15194 
15195  /* Translate subject and issuer to a string */
15196  (void)X509_NAME_oneline(subj, str_subject, (int)sizeof(str_subject));
15197  (void)X509_NAME_oneline(iss, str_issuer, (int)sizeof(str_issuer));
15198 
15199  /* Calculate SHA1 fingerprint and store as a hex string */
15200  ulen = 0;
15201 
15202  /* ASN1_digest is deprecated. Do the calculation manually,
15203  * using EVP_Digest. */
15204  ilen = i2d_X509(cert, NULL);
15205  tmp_buf = (ilen > 0)
15206  ? (unsigned char *)mg_malloc_ctx((unsigned)ilen + 1,
15207  conn->phys_ctx)
15208  : NULL;
15209  if (tmp_buf) {
15210  tmp_p = tmp_buf;
15211  (void)i2d_X509(cert, &tmp_p);
15212  if (!EVP_Digest(
15213  tmp_buf, (unsigned)ilen, buf, &ulen, digest, NULL)) {
15214  ulen = 0;
15215  }
15216  mg_free(tmp_buf);
15217  }
15218 
15219  if (!hexdump2string(
15220  buf, (int)ulen, str_finger, (int)sizeof(str_finger))) {
15221  *str_finger = 0;
15222  }
15223 
15224  conn->request_info.client_cert = (struct mg_client_cert *)
15225  mg_malloc_ctx(sizeof(struct mg_client_cert), conn->phys_ctx);
15226  if (conn->request_info.client_cert) {
15227  conn->request_info.client_cert->peer_cert = (void *)cert;
15228  conn->request_info.client_cert->subject =
15229  mg_strdup_ctx(str_subject, conn->phys_ctx);
15230  conn->request_info.client_cert->issuer =
15231  mg_strdup_ctx(str_issuer, conn->phys_ctx);
15232  conn->request_info.client_cert->serial =
15233  mg_strdup_ctx(str_serial, conn->phys_ctx);
15234  conn->request_info.client_cert->finger =
15235  mg_strdup_ctx(str_finger, conn->phys_ctx);
15236  } else {
15237  mg_cry_internal(conn,
15238  "%s",
15239  "Out of memory: Cannot allocate memory for client "
15240  "certificate");
15241  }
15242 
15243  /* Strings returned from bn_bn2hex must be freed using OPENSSL_free,
15244  * see https://linux.die.net/man/3/bn_bn2hex */
15245  OPENSSL_free(str_serial);
15246  }
15247 }
15248 
15249 
15250 #if defined(OPENSSL_API_1_1)
15251 #else
15252 static void
15253 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
15254 {
15255  (void)line;
15256  (void)file;
15257 
15258  if (mode & 1) {
15259  /* 1 is CRYPTO_LOCK */
15260  (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
15261  } else {
15262  (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
15263  }
15264 }
15265 #endif /* OPENSSL_API_1_1 */
15266 
15267 
15268 #if !defined(NO_SSL_DL)
15269 static void *
15270 load_dll(char *ebuf, size_t ebuf_len, const char *dll_name, struct ssl_func *sw)
15271 {
15272  union {
15273  void *p;
15274  void (*fp)(void);
15275  } u;
15276  void *dll_handle;
15277  struct ssl_func *fp;
15278  int ok;
15279  int truncated = 0;
15280 
15281  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
15282  mg_snprintf(NULL,
15283  NULL, /* No truncation check for ebuf */
15284  ebuf,
15285  ebuf_len,
15286  "%s: cannot load %s",
15287  __func__,
15288  dll_name);
15289  return NULL;
15290  }
15291 
15292  ok = 1;
15293  for (fp = sw; fp->name != NULL; fp++) {
15294 #if defined(_WIN32)
15295  /* GetProcAddress() returns pointer to function */
15296  u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
15297 #else
15298  /* dlsym() on UNIX returns void *. ISO C forbids casts of data
15299  * pointers to function pointers. We need to use a union to make a
15300  * cast. */
15301  u.p = dlsym(dll_handle, fp->name);
15302 #endif /* _WIN32 */
15303  if (u.fp == NULL) {
15304  if (ok) {
15305  mg_snprintf(NULL,
15306  &truncated,
15307  ebuf,
15308  ebuf_len,
15309  "%s: %s: cannot find %s",
15310  __func__,
15311  dll_name,
15312  fp->name);
15313  ok = 0;
15314  } else {
15315  size_t cur_len = strlen(ebuf);
15316  if (!truncated) {
15317  mg_snprintf(NULL,
15318  &truncated,
15319  ebuf + cur_len,
15320  ebuf_len - cur_len - 3,
15321  ", %s",
15322  fp->name);
15323  if (truncated) {
15324  /* If truncated, add "..." */
15325  strcat(ebuf, "...");
15326  }
15327  }
15328  }
15329  /* Debug:
15330  * printf("Missing function: %s\n", fp->name); */
15331  } else {
15332  fp->ptr = u.fp;
15333  }
15334  }
15335 
15336  if (!ok) {
15337  (void)dlclose(dll_handle);
15338  return NULL;
15339  }
15340 
15341  return dll_handle;
15342 }
15343 
15344 
15345 static void *ssllib_dll_handle; /* Store the ssl library handle. */
15346 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
15347 
15348 #endif /* NO_SSL_DL */
15349 
15350 
15351 #if defined(SSL_ALREADY_INITIALIZED)
15352 static int cryptolib_users = 1; /* Reference counter for crypto library. */
15353 #else
15354 static int cryptolib_users = 0; /* Reference counter for crypto library. */
15355 #endif
15356 
15357 
15358 static int
15359 initialize_ssl(char *ebuf, size_t ebuf_len)
15360 {
15361 #if defined(OPENSSL_API_1_1)
15362  if (ebuf_len > 0) {
15363  ebuf[0] = 0;
15364  }
15365 
15366 #if !defined(NO_SSL_DL)
15367  if (!cryptolib_dll_handle) {
15368  cryptolib_dll_handle = load_dll(ebuf, ebuf_len, CRYPTO_LIB, crypto_sw);
15369  if (!cryptolib_dll_handle) {
15370  mg_snprintf(NULL,
15371  NULL, /* No truncation check for ebuf */
15372  ebuf,
15373  ebuf_len,
15374  "%s: error loading library %s",
15375  __func__,
15376  CRYPTO_LIB);
15377  DEBUG_TRACE("%s", ebuf);
15378  return 0;
15379  }
15380  }
15381 #endif /* NO_SSL_DL */
15382 
15383  if (mg_atomic_inc(&cryptolib_users) > 1) {
15384  return 1;
15385  }
15386 
15387 #else /* not OPENSSL_API_1_1 */
15388  int i, num_locks;
15389  size_t size;
15390 
15391  if (ebuf_len > 0) {
15392  ebuf[0] = 0;
15393  }
15394 
15395 #if !defined(NO_SSL_DL)
15396  if (!cryptolib_dll_handle) {
15397  cryptolib_dll_handle = load_dll(ebuf, ebuf_len, CRYPTO_LIB, crypto_sw);
15398  if (!cryptolib_dll_handle) {
15399  mg_snprintf(NULL,
15400  NULL, /* No truncation check for ebuf */
15401  ebuf,
15402  ebuf_len,
15403  "%s: error loading library %s",
15404  __func__,
15405  CRYPTO_LIB);
15406  DEBUG_TRACE("%s", ebuf);
15407  return 0;
15408  }
15409  }
15410 #endif /* NO_SSL_DL */
15411 
15412  if (mg_atomic_inc(&cryptolib_users) > 1) {
15413  return 1;
15414  }
15415 
15416  /* Initialize locking callbacks, needed for thread safety.
15417  * http://www.openssl.org/support/faq.html#PROG1
15418  */
15419  num_locks = CRYPTO_num_locks();
15420  if (num_locks < 0) {
15421  num_locks = 0;
15422  }
15423  size = sizeof(pthread_mutex_t) * ((size_t)(num_locks));
15424 
15425  /* allocate mutex array, if required */
15426  if (num_locks == 0) {
15427  /* No mutex array required */
15428  ssl_mutexes = NULL;
15429  } else {
15430  /* Mutex array required - allocate it */
15431  ssl_mutexes = (pthread_mutex_t *)mg_malloc(size);
15432 
15433  /* Check OOM */
15434  if (ssl_mutexes == NULL) {
15435  mg_snprintf(NULL,
15436  NULL, /* No truncation check for ebuf */
15437  ebuf,
15438  ebuf_len,
15439  "%s: cannot allocate mutexes: %s",
15440  __func__,
15441  ssl_error());
15442  DEBUG_TRACE("%s", ebuf);
15443  return 0;
15444  }
15445 
15446  /* initialize mutex array */
15447  for (i = 0; i < num_locks; i++) {
15448  if (0 != pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr)) {
15449  mg_snprintf(NULL,
15450  NULL, /* No truncation check for ebuf */
15451  ebuf,
15452  ebuf_len,
15453  "%s: error initializing mutex %i of %i",
15454  __func__,
15455  i,
15456  num_locks);
15457  DEBUG_TRACE("%s", ebuf);
15458  mg_free(ssl_mutexes);
15459  return 0;
15460  }
15461  }
15462  }
15463 
15464  CRYPTO_set_locking_callback(&ssl_locking_callback);
15465  CRYPTO_set_id_callback(&mg_current_thread_id);
15466 #endif /* OPENSSL_API_1_1 */
15467 
15468 #if !defined(NO_SSL_DL)
15469  if (!ssllib_dll_handle) {
15470  ssllib_dll_handle = load_dll(ebuf, ebuf_len, SSL_LIB, ssl_sw);
15471  if (!ssllib_dll_handle) {
15472 #if !defined(OPENSSL_API_1_1)
15473  mg_free(ssl_mutexes);
15474 #endif
15475  DEBUG_TRACE("%s", ebuf);
15476  return 0;
15477  }
15478  }
15479 #endif /* NO_SSL_DL */
15480 
15481 #if defined(OPENSSL_API_1_1)
15482  /* Initialize SSL library */
15483  OPENSSL_init_ssl(0, NULL);
15484  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
15485  | OPENSSL_INIT_LOAD_CRYPTO_STRINGS,
15486  NULL);
15487 #else
15488  /* Initialize SSL library */
15489  SSL_library_init();
15490  SSL_load_error_strings();
15491 #endif
15492 
15493  return 1;
15494 }
15495 
15496 
15497 static int
15498 ssl_use_pem_file(struct mg_context *phys_ctx,
15499  struct mg_domain_context *dom_ctx,
15500  const char *pem,
15501  const char *chain)
15502 {
15503  if (SSL_CTX_use_certificate_file(dom_ctx->ssl_ctx, pem, 1) == 0) {
15504  mg_cry_internal(fc(phys_ctx),
15505  "%s: cannot open certificate file %s: %s",
15506  __func__,
15507  pem,
15508  ssl_error());
15509  return 0;
15510  }
15511 
15512  /* could use SSL_CTX_set_default_passwd_cb_userdata */
15513  if (SSL_CTX_use_PrivateKey_file(dom_ctx->ssl_ctx, pem, 1) == 0) {
15514  mg_cry_internal(fc(phys_ctx),
15515  "%s: cannot open private key file %s: %s",
15516  __func__,
15517  pem,
15518  ssl_error());
15519  return 0;
15520  }
15521 
15522  if (SSL_CTX_check_private_key(dom_ctx->ssl_ctx) == 0) {
15523  mg_cry_internal(fc(phys_ctx),
15524  "%s: certificate and private key do not match: %s",
15525  __func__,
15526  pem);
15527  return 0;
15528  }
15529 
15530  /* In contrast to OpenSSL, wolfSSL does not support certificate
15531  * chain files that contain private keys and certificates in
15532  * SSL_CTX_use_certificate_chain_file.
15533  * The CivetWeb-Server used pem-Files that contained both information.
15534  * In order to make wolfSSL work, it is split in two files.
15535  * One file that contains key and certificate used by the server and
15536  * an optional chain file for the ssl stack.
15537  */
15538  if (chain) {
15539  if (SSL_CTX_use_certificate_chain_file(dom_ctx->ssl_ctx, chain) == 0) {
15540  mg_cry_internal(fc(phys_ctx),
15541  "%s: cannot use certificate chain file %s: %s",
15542  __func__,
15543  pem,
15544  ssl_error());
15545  return 0;
15546  }
15547  }
15548  return 1;
15549 }
15550 
15551 
15552 #if defined(OPENSSL_API_1_1)
15553 static unsigned long
15554 ssl_get_protocol(int version_id)
15555 {
15556  long unsigned ret = (long unsigned)SSL_OP_ALL;
15557  if (version_id > 0)
15558  ret |= SSL_OP_NO_SSLv2;
15559  if (version_id > 1)
15560  ret |= SSL_OP_NO_SSLv3;
15561  if (version_id > 2)
15562  ret |= SSL_OP_NO_TLSv1;
15563  if (version_id > 3)
15564  ret |= SSL_OP_NO_TLSv1_1;
15565  return ret;
15566 }
15567 #else
15568 static long
15569 ssl_get_protocol(int version_id)
15570 {
15571  long ret = (long)SSL_OP_ALL;
15572  if (version_id > 0)
15573  ret |= SSL_OP_NO_SSLv2;
15574  if (version_id > 1)
15575  ret |= SSL_OP_NO_SSLv3;
15576  if (version_id > 2)
15577  ret |= SSL_OP_NO_TLSv1;
15578  if (version_id > 3)
15579  ret |= SSL_OP_NO_TLSv1_1;
15580  return ret;
15581 }
15582 #endif /* OPENSSL_API_1_1 */
15583 
15584 
15585 /* SSL callback documentation:
15586  * https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_info_callback.html
15587  * https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_info_callback(3)
15588  * https://linux.die.net/man/3/ssl_set_info_callback */
15589 /* Note: There is no "const" for the first argument in the documentation
15590  * examples, however some (maybe most, but not all) headers of OpenSSL versions
15591  * / OpenSSL compatibility layers have it. Having a different definition will
15592  * cause a warning in C and an error in C++. Use "const SSL *", while
15593  * automatical conversion from "SSL *" works for all compilers, but not other
15594  * way around */
15595 static void
15596 ssl_info_callback(const SSL *ssl, int what, int ret)
15597 {
15598  (void)ret;
15599 
15600  if (what & SSL_CB_HANDSHAKE_START) {
15601  SSL_get_app_data(ssl);
15602  }
15603  if (what & SSL_CB_HANDSHAKE_DONE) {
15604  /* TODO: check for openSSL 1.1 */
15605  //#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
15606  // ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
15607  }
15608 }
15609 
15610 
15611 static int
15612 ssl_servername_callback(SSL *ssl, int *ad, void *arg)
15613 {
15614  struct mg_context *ctx = (struct mg_context *)arg;
15615  struct mg_domain_context *dom =
15616  (struct mg_domain_context *)ctx ? &(ctx->dd) : NULL;
15617 
15618 #if defined(GCC_DIAGNOSTIC)
15619 #pragma GCC diagnostic push
15620 #pragma GCC diagnostic ignored "-Wcast-align"
15621 #endif /* defined(GCC_DIAGNOSTIC) */
15622 
15623  /* We used an aligned pointer in SSL_set_app_data */
15624  struct mg_connection *conn = (struct mg_connection *)SSL_get_app_data(ssl);
15625 
15626 #if defined(GCC_DIAGNOSTIC)
15627 #pragma GCC diagnostic pop
15628 #endif /* defined(GCC_DIAGNOSTIC) */
15629 
15630  const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
15631 
15632  (void)ad;
15633 
15634  if ((ctx == NULL) || (conn->phys_ctx == ctx)) {
15635  DEBUG_TRACE("%s", "internal error - assertion failed");
15636  return SSL_TLSEXT_ERR_NOACK;
15637  }
15638 
15639  /* Old clients (Win XP) will not support SNI. Then, there
15640  * is no server name available in the request - we can
15641  * only work with the default certificate.
15642  * Multiple HTTPS hosts on one IP+port are only possible
15643  * with a certificate containing all alternative names.
15644  */
15645  if ((servername == NULL) || (*servername == 0)) {
15646  DEBUG_TRACE("%s", "SSL connection not supporting SNI");
15647  conn->dom_ctx = &(ctx->dd);
15648  SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
15649  return SSL_TLSEXT_ERR_NOACK;
15650  }
15651 
15652  DEBUG_TRACE("TLS connection to host %s", servername);
15653 
15654  while (dom) {
15655  if (!mg_strcasecmp(servername, dom->config[AUTHENTICATION_DOMAIN])) {
15656 
15657  /* Found matching domain */
15658  DEBUG_TRACE("TLS domain %s found",
15659  dom->config[AUTHENTICATION_DOMAIN]);
15660  SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
15661  conn->dom_ctx = dom;
15662  return SSL_TLSEXT_ERR_OK;
15663  }
15664  dom = dom->next;
15665  }
15666 
15667  /* Default domain */
15668  DEBUG_TRACE("TLS default domain %s used",
15669  ctx->dd.config[AUTHENTICATION_DOMAIN]);
15670  conn->dom_ctx = &(ctx->dd);
15671  SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
15672  return SSL_TLSEXT_ERR_OK;
15673 }
15674 
15675 
15676 /* Setup SSL CTX as required by CivetWeb */
15677 static int
15678 init_ssl_ctx_impl(struct mg_context *phys_ctx,
15679  struct mg_domain_context *dom_ctx,
15680  const char *pem,
15681  const char *chain)
15682 {
15683  int callback_ret;
15684  int should_verify_peer;
15685  int peer_certificate_optional;
15686  const char *ca_path;
15687  const char *ca_file;
15688  int use_default_verify_paths;
15689  int verify_depth;
15690  struct timespec now_mt;
15691  md5_byte_t ssl_context_id[16];
15692  md5_state_t md5state;
15693  int protocol_ver;
15694 
15695 #if defined(OPENSSL_API_1_1)
15696  if ((dom_ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) {
15697  mg_cry_internal(fc(phys_ctx),
15698  "SSL_CTX_new (server) error: %s",
15699  ssl_error());
15700  return 0;
15701  }
15702 #else
15703  if ((dom_ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
15704  mg_cry_internal(fc(phys_ctx),
15705  "SSL_CTX_new (server) error: %s",
15706  ssl_error());
15707  return 0;
15708  }
15709 #endif /* OPENSSL_API_1_1 */
15710 
15711  SSL_CTX_clear_options(dom_ctx->ssl_ctx,
15712  SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1
15713  | SSL_OP_NO_TLSv1_1);
15714  protocol_ver = atoi(dom_ctx->config[SSL_PROTOCOL_VERSION]);
15715  SSL_CTX_set_options(dom_ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
15716  SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
15717  SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
15718  SSL_CTX_set_options(dom_ctx->ssl_ctx,
15719  SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
15720  SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
15721 #if !defined(NO_SSL_DL)
15722  SSL_CTX_set_ecdh_auto(dom_ctx->ssl_ctx, 1);
15723 #endif /* NO_SSL_DL */
15724 
15725  /* In SSL documentation examples callback defined without const specifier
15726  * 'void (*)(SSL *, int, int)' See:
15727  * https://www.openssl.org/docs/man1.0.2/ssl/ssl.html
15728  * https://www.openssl.org/docs/man1.1.0/ssl/ssl.html
15729  * But in the source code const SSL is used:
15730  * 'void (*)(const SSL *, int, int)' See:
15731  * https://github.com/openssl/openssl/blob/1d97c8435171a7af575f73c526d79e1ef0ee5960/ssl/ssl.h#L1173
15732  * Problem about wrong documentation described, but not resolved:
15733  * https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/1147526
15734  * Wrong const cast ignored on C or can be suppressed by compiler flags.
15735  * But when compiled with modern C++ compiler, correct const should be
15736  * provided
15737  */
15738  SSL_CTX_set_info_callback(dom_ctx->ssl_ctx, ssl_info_callback);
15739 
15740  SSL_CTX_set_tlsext_servername_callback(dom_ctx->ssl_ctx,
15741  ssl_servername_callback);
15742  SSL_CTX_set_tlsext_servername_arg(dom_ctx->ssl_ctx, phys_ctx);
15743 
15744  /* If a callback has been specified, call it. */
15745  callback_ret = (phys_ctx->callbacks.init_ssl == NULL)
15746  ? 0
15747  : (phys_ctx->callbacks.init_ssl(dom_ctx->ssl_ctx,
15748  phys_ctx->user_data));
15749 
15750  /* If callback returns 0, civetweb sets up the SSL certificate.
15751  * If it returns 1, civetweb assumes the calback already did this.
15752  * If it returns -1, initializing ssl fails. */
15753  if (callback_ret < 0) {
15754  mg_cry_internal(fc(phys_ctx),
15755  "SSL callback returned error: %i",
15756  callback_ret);
15757  return 0;
15758  }
15759  if (callback_ret > 0) {
15760  /* Callback did everything. */
15761  return 1;
15762  }
15763 
15764  /* Use some combination of start time, domain and port as a SSL
15765  * context ID. This should be unique on the current machine. */
15766  md5_init(&md5state);
15767  clock_gettime(CLOCK_MONOTONIC, &now_mt);
15768  md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
15769  md5_append(&md5state,
15770  (const md5_byte_t *)phys_ctx->dd.config[LISTENING_PORTS],
15771  strlen(phys_ctx->dd.config[LISTENING_PORTS]));
15772  md5_append(&md5state,
15773  (const md5_byte_t *)dom_ctx->config[AUTHENTICATION_DOMAIN],
15774  strlen(dom_ctx->config[AUTHENTICATION_DOMAIN]));
15775  md5_append(&md5state, (const md5_byte_t *)phys_ctx, sizeof(*phys_ctx));
15776  md5_append(&md5state, (const md5_byte_t *)dom_ctx, sizeof(*dom_ctx));
15777  md5_finish(&md5state, ssl_context_id);
15778 
15779  SSL_CTX_set_session_id_context(dom_ctx->ssl_ctx,
15780  (unsigned char *)ssl_context_id,
15781  sizeof(ssl_context_id));
15782 
15783  if (pem != NULL) {
15784  if (!ssl_use_pem_file(phys_ctx, dom_ctx, pem, chain)) {
15785  return 0;
15786  }
15787  }
15788 
15789  /* Should we support client certificates? */
15790  /* Default is "no". */
15791  should_verify_peer = 0;
15792  peer_certificate_optional = 0;
15793  if (dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
15794  if (mg_strcasecmp(dom_ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0) {
15795  /* Yes, they are mandatory */
15796  should_verify_peer = 1;
15797  peer_certificate_optional = 0;
15798  } else if (mg_strcasecmp(dom_ctx->config[SSL_DO_VERIFY_PEER],
15799  "optional")
15800  == 0) {
15801  /* Yes, they are optional */
15802  should_verify_peer = 1;
15803  peer_certificate_optional = 1;
15804  }
15805  }
15806 
15807  use_default_verify_paths =
15808  (dom_ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
15809  && (mg_strcasecmp(dom_ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes")
15810  == 0);
15811 
15812  if (should_verify_peer) {
15813  ca_path = dom_ctx->config[SSL_CA_PATH];
15814  ca_file = dom_ctx->config[SSL_CA_FILE];
15815  if (SSL_CTX_load_verify_locations(dom_ctx->ssl_ctx, ca_file, ca_path)
15816  != 1) {
15817  mg_cry_internal(fc(phys_ctx),
15818  "SSL_CTX_load_verify_locations error: %s "
15819  "ssl_verify_peer requires setting "
15820  "either ssl_ca_path or ssl_ca_file. "
15821  "Is any of them present in the "
15822  ".conf file?",
15823  ssl_error());
15824  return 0;
15825  }
15826 
15827  if (peer_certificate_optional) {
15828  SSL_CTX_set_verify(dom_ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
15829  } else {
15830  SSL_CTX_set_verify(dom_ctx->ssl_ctx,
15831  SSL_VERIFY_PEER
15832  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
15833  NULL);
15834  }
15835 
15836  if (use_default_verify_paths
15837  && (SSL_CTX_set_default_verify_paths(dom_ctx->ssl_ctx) != 1)) {
15838  mg_cry_internal(fc(phys_ctx),
15839  "SSL_CTX_set_default_verify_paths error: %s",
15840  ssl_error());
15841  return 0;
15842  }
15843 
15844  if (dom_ctx->config[SSL_VERIFY_DEPTH]) {
15845  verify_depth = atoi(dom_ctx->config[SSL_VERIFY_DEPTH]);
15846  SSL_CTX_set_verify_depth(dom_ctx->ssl_ctx, verify_depth);
15847  }
15848  }
15849 
15850  if (dom_ctx->config[SSL_CIPHER_LIST] != NULL) {
15851  if (SSL_CTX_set_cipher_list(dom_ctx->ssl_ctx,
15852  dom_ctx->config[SSL_CIPHER_LIST])
15853  != 1) {
15854  mg_cry_internal(fc(phys_ctx),
15855  "SSL_CTX_set_cipher_list error: %s",
15856  ssl_error());
15857  }
15858  }
15859 
15860  return 1;
15861 }
15862 
15863 
15864 /* Check if SSL is required.
15865  * If so, dynamically load SSL library
15866  * and set up ctx->ssl_ctx pointer. */
15867 static int
15868 init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
15869 {
15870  void *ssl_ctx = 0;
15871  int callback_ret;
15872  const char *pem;
15873  const char *chain;
15874  char ebuf[128];
15875 
15876  if (!phys_ctx) {
15877  return 0;
15878  }
15879 
15880  if (!dom_ctx) {
15881  dom_ctx = &(phys_ctx->dd);
15882  }
15883 
15884  if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) {
15885  /* No SSL port is set. No need to setup SSL. */
15886  return 1;
15887  }
15888 
15889  /* Check for external SSL_CTX */
15890  callback_ret =
15891  (phys_ctx->callbacks.external_ssl_ctx == NULL)
15892  ? 0
15893  : (phys_ctx->callbacks.external_ssl_ctx(&ssl_ctx,
15894  phys_ctx->user_data));
15895 
15896  if (callback_ret < 0) {
15897  mg_cry_internal(fc(phys_ctx),
15898  "external_ssl_ctx callback returned error: %i",
15899  callback_ret);
15900  return 0;
15901  } else if (callback_ret > 0) {
15902  dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
15903  if (!initialize_ssl(ebuf, sizeof(ebuf))) {
15904  mg_cry_internal(fc(phys_ctx), "%s", ebuf);
15905  return 0;
15906  }
15907  return 1;
15908  }
15909  /* else: external_ssl_ctx does not exist or returns 0,
15910  * CivetWeb should continue initializing SSL */
15911 
15912  /* If PEM file is not specified and the init_ssl callback
15913  * is not specified, setup will fail. */
15914  if (((pem = dom_ctx->config[SSL_CERTIFICATE]) == NULL)
15915  && (phys_ctx->callbacks.init_ssl == NULL)) {
15916  /* No certificate and no callback:
15917  * Essential data to set up TLS is missing.
15918  */
15919  mg_cry_internal(fc(phys_ctx),
15920  "Initializing SSL failed: -%s is not set",
15921  config_options[SSL_CERTIFICATE].name);
15922  return 0;
15923  }
15924 
15925  chain = dom_ctx->config[SSL_CERTIFICATE_CHAIN];
15926  if (chain == NULL) {
15927  chain = pem;
15928  }
15929  if ((chain != NULL) && (*chain == 0)) {
15930  chain = NULL;
15931  }
15932 
15933  if (!initialize_ssl(ebuf, sizeof(ebuf))) {
15934  mg_cry_internal(fc(phys_ctx), "%s", ebuf);
15935  return 0;
15936  }
15937 
15938  return init_ssl_ctx_impl(phys_ctx, dom_ctx, pem, chain);
15939 }
15940 
15941 
15942 static void
15943 uninitialize_ssl(void)
15944 {
15945 #if defined(OPENSSL_API_1_1)
15946 
15947  if (mg_atomic_dec(&cryptolib_users) == 0) {
15948 
15949  /* Shutdown according to
15950  * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
15951  * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
15952  */
15953  CONF_modules_unload(1);
15954 #else
15955  int i;
15956 
15957  if (mg_atomic_dec(&cryptolib_users) == 0) {
15958 
15959  /* Shutdown according to
15960  * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
15961  * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
15962  */
15963  CRYPTO_set_locking_callback(NULL);
15964  CRYPTO_set_id_callback(NULL);
15965  ENGINE_cleanup();
15966  CONF_modules_unload(1);
15967  ERR_free_strings();
15968  EVP_cleanup();
15969  CRYPTO_cleanup_all_ex_data();
15970  OPENSSL_REMOVE_THREAD_STATE();
15971 
15972  for (i = 0; i < CRYPTO_num_locks(); i++) {
15973  pthread_mutex_destroy(&ssl_mutexes[i]);
15974  }
15975  mg_free(ssl_mutexes);
15976  ssl_mutexes = NULL;
15977 #endif /* OPENSSL_API_1_1 */
15978  }
15979 }
15980 #endif /* !NO_SSL */
15981 
15982 
15983 static int
15984 set_gpass_option(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
15985 {
15986  if (phys_ctx) {
15987  struct mg_file file = STRUCT_FILE_INITIALIZER;
15988  const char *path;
15989  if (!dom_ctx) {
15990  dom_ctx = &(phys_ctx->dd);
15991  }
15992  path = dom_ctx->config[GLOBAL_PASSWORDS_FILE];
15993  if ((path != NULL) && !mg_stat(fc(phys_ctx), path, &file.stat)) {
15994  mg_cry_internal(fc(phys_ctx),
15995  "Cannot open %s: %s",
15996  path,
15997  strerror(ERRNO));
15998  return 0;
15999  }
16000  return 1;
16001  }
16002  return 0;
16003 }
16004 
16005 
16006 static int
16007 set_acl_option(struct mg_context *phys_ctx)
16008 {
16009  return check_acl(phys_ctx, (uint32_t)0x7f000001UL) != -1;
16010 }
16011 
16012 
16013 static void
16014 reset_per_request_attributes(struct mg_connection *conn)
16015 {
16016  if (!conn) {
16017  return;
16018  }
16019  conn->connection_type =
16020  CONNECTION_TYPE_INVALID; /* Not yet a valid request/response */
16021 
16022  conn->num_bytes_sent = conn->consumed_content = 0;
16023 
16024  conn->path_info = NULL;
16025  conn->status_code = -1;
16026  conn->content_len = -1;
16027  conn->is_chunked = 0;
16028  conn->must_close = 0;
16029  conn->request_len = 0;
16030  conn->throttle = 0;
16031  conn->data_len = 0;
16032  conn->chunk_remainder = 0;
16033  conn->accept_gzip = 0;
16034 
16035  conn->response_info.content_length = conn->request_info.content_length = -1;
16036  conn->response_info.http_version = conn->request_info.http_version = NULL;
16037  conn->response_info.num_headers = conn->request_info.num_headers = 0;
16038  conn->response_info.status_text = NULL;
16039  conn->response_info.status_code = 0;
16040 
16041  conn->request_info.remote_user = NULL;
16042  conn->request_info.request_method = NULL;
16043  conn->request_info.request_uri = NULL;
16044  conn->request_info.local_uri = NULL;
16045 
16046 #if defined(MG_LEGACY_INTERFACE)
16047  /* Legacy before split into local_uri and request_uri */
16048  conn->request_info.uri = NULL;
16049 #endif
16050 }
16051 
16052 
16053 #if 0
16054 /* Note: set_sock_timeout is not required for non-blocking sockets.
16055  * Leave this function here (commented out) for reference until
16056  * CivetWeb 1.9 is tested, and the tests confirme this function is
16057  * no longer required.
16058 */
16059 static int
16060 set_sock_timeout(SOCKET sock, int milliseconds)
16061 {
16062  int r0 = 0, r1, r2;
16063 
16064 #if defined(_WIN32)
16065  /* Windows specific */
16066 
16067  DWORD tv = (DWORD)milliseconds;
16068 
16069 #else
16070  /* Linux, ... (not Windows) */
16071 
16072  struct timeval tv;
16073 
16074 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
16075  * max. time waiting for the acknowledged of TCP data before the connection
16076  * will be forcefully closed and ETIMEDOUT is returned to the application.
16077  * If this option is not set, the default timeout of 20-30 minutes is used.
16078 */
16079 /* #define TCP_USER_TIMEOUT (18) */
16080 
16081 #if defined(TCP_USER_TIMEOUT)
16082  unsigned int uto = (unsigned int)milliseconds;
16083  r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
16084 #endif
16085 
16086  memset(&tv, 0, sizeof(tv));
16087  tv.tv_sec = milliseconds / 1000;
16088  tv.tv_usec = (milliseconds * 1000) % 1000000;
16089 
16090 #endif /* _WIN32 */
16091 
16092  r1 = setsockopt(
16093  sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
16094  r2 = setsockopt(
16095  sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
16096 
16097  return r0 || r1 || r2;
16098 }
16099 #endif
16100 
16101 
16102 static int
16103 set_tcp_nodelay(SOCKET sock, int nodelay_on)
16104 {
16105  if (setsockopt(sock,
16106  IPPROTO_TCP,
16107  TCP_NODELAY,
16108  (SOCK_OPT_TYPE)&nodelay_on,
16109  sizeof(nodelay_on))
16110  != 0) {
16111  /* Error */
16112  return 1;
16113  }
16114  /* OK */
16115  return 0;
16116 }
16117 
16118 
16119 static void
16120 close_socket_gracefully(struct mg_connection *conn)
16121 {
16122 #if defined(_WIN32)
16123  char buf[MG_BUF_LEN];
16124  int n;
16125 #endif
16126  struct linger linger;
16127  int error_code = 0;
16128  int linger_timeout = -2;
16129  socklen_t opt_len = sizeof(error_code);
16130 
16131  if (!conn) {
16132  return;
16133  }
16134 
16135  /* http://msdn.microsoft.com/en-us/library/ms739165(v=vs.85).aspx:
16136  * "Note that enabling a nonzero timeout on a nonblocking socket
16137  * is not recommended.", so set it to blocking now */
16138  set_blocking_mode(conn->client.sock);
16139 
16140  /* Send FIN to the client */
16141  shutdown(conn->client.sock, SHUTDOWN_WR);
16142 
16143 
16144 #if defined(_WIN32)
16145  /* Read and discard pending incoming data. If we do not do that and
16146  * close
16147  * the socket, the data in the send buffer may be discarded. This
16148  * behaviour is seen on Windows, when client keeps sending data
16149  * when server decides to close the connection; then when client
16150  * does recv() it gets no data back. */
16151  do {
16152  n = pull_inner(NULL, conn, buf, sizeof(buf), /* Timeout in s: */ 1.0);
16153  } while (n > 0);
16154 #endif
16155 
16156  if (conn->dom_ctx->config[LINGER_TIMEOUT]) {
16157  linger_timeout = atoi(conn->dom_ctx->config[LINGER_TIMEOUT]);
16158  }
16159 
16160  /* Set linger option according to configuration */
16161  if (linger_timeout >= 0) {
16162  /* Set linger option to avoid socket hanging out after close. This
16163  * prevent ephemeral port exhaust problem under high QPS. */
16164  linger.l_onoff = 1;
16165 
16166 #if defined(_MSC_VER)
16167 #pragma warning(push)
16168 #pragma warning(disable : 4244)
16169 #endif
16170 #if defined(GCC_DIAGNOSTIC)
16171 #pragma GCC diagnostic push
16172 #pragma GCC diagnostic ignored "-Wconversion"
16173 #endif
16174  /* Data type of linger structure elements may differ,
16175  * so we don't know what cast we need here.
16176  * Disable type conversion warnings. */
16177 
16178  linger.l_linger = (linger_timeout + 999) / 1000;
16179 
16180 #if defined(GCC_DIAGNOSTIC)
16181 #pragma GCC diagnostic pop
16182 #endif
16183 #if defined(_MSC_VER)
16184 #pragma warning(pop)
16185 #endif
16186 
16187  } else {
16188  linger.l_onoff = 0;
16189  linger.l_linger = 0;
16190  }
16191 
16192  if (linger_timeout < -1) {
16193  /* Default: don't configure any linger */
16194  } else if (getsockopt(conn->client.sock,
16195  SOL_SOCKET,
16196  SO_ERROR,
16197 #if defined(_WIN32) /* WinSock uses different data type here */
16198  (char *)&error_code,
16199 #else
16200  &error_code,
16201 #endif
16202  &opt_len)
16203  != 0) {
16204  /* Cannot determine if socket is already closed. This should
16205  * not occur and never did in a test. Log an error message
16206  * and continue. */
16207  mg_cry_internal(conn,
16208  "%s: getsockopt(SOL_SOCKET SO_ERROR) failed: %s",
16209  __func__,
16210  strerror(ERRNO));
16211  } else if (error_code == ECONNRESET) {
16212  /* Socket already closed by client/peer, close socket without linger
16213  */
16214  } else {
16215 
16216  /* Set linger timeout */
16217  if (setsockopt(conn->client.sock,
16218  SOL_SOCKET,
16219  SO_LINGER,
16220  (char *)&linger,
16221  sizeof(linger))
16222  != 0) {
16223  mg_cry_internal(
16224  conn,
16225  "%s: setsockopt(SOL_SOCKET SO_LINGER(%i,%i)) failed: %s",
16226  __func__,
16227  linger.l_onoff,
16228  linger.l_linger,
16229  strerror(ERRNO));
16230  }
16231  }
16232 
16233  /* Now we know that our FIN is ACK-ed, safe to close */
16234  closesocket(conn->client.sock);
16235  conn->client.sock = INVALID_SOCKET;
16236 }
16237 
16238 
16239 static void
16240 close_connection(struct mg_connection *conn)
16241 {
16242 #if defined(USE_SERVER_STATS)
16243  conn->conn_state = 6; /* to close */
16244 #endif
16245 
16246 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
16247  if (conn->lua_websocket_state) {
16248  lua_websocket_close(conn, conn->lua_websocket_state);
16249  conn->lua_websocket_state = NULL;
16250  }
16251 #endif
16252 
16253  mg_lock_connection(conn);
16254 
16255  /* Set close flag, so keep-alive loops will stop */
16256  conn->must_close = 1;
16257 
16258  /* call the connection_close callback if assigned */
16259  if (conn->phys_ctx->callbacks.connection_close != NULL) {
16260  if (conn->phys_ctx->context_type == CONTEXT_SERVER) {
16261  conn->phys_ctx->callbacks.connection_close(conn);
16262  }
16263  }
16264 
16265  /* Reset user data, after close callback is called.
16266  * Do not reuse it. If the user needs a destructor,
16267  * it must be done in the connection_close callback. */
16268  mg_set_user_connection_data(conn, NULL);
16269 
16270 
16271 #if defined(USE_SERVER_STATS)
16272  conn->conn_state = 7; /* closing */
16273 #endif
16274 
16275 #if !defined(NO_SSL)
16276  if (conn->ssl != NULL) {
16277  /* Run SSL_shutdown twice to ensure completely close SSL connection
16278  */
16279  SSL_shutdown(conn->ssl);
16280  SSL_free(conn->ssl);
16281  OPENSSL_REMOVE_THREAD_STATE();
16282  conn->ssl = NULL;
16283  }
16284 #endif
16285  if (conn->client.sock != INVALID_SOCKET) {
16286  close_socket_gracefully(conn);
16287  conn->client.sock = INVALID_SOCKET;
16288  }
16289 
16290  if (conn->host) {
16291  mg_free((void *)conn->host);
16292  conn->host = NULL;
16293  }
16294 
16295  mg_unlock_connection(conn);
16296 
16297 #if defined(USE_SERVER_STATS)
16298  conn->conn_state = 8; /* closed */
16299 #endif
16300 }
16301 
16302 
16303 void
16304 mg_close_connection(struct mg_connection *conn)
16305 {
16306 #if defined(USE_WEBSOCKET)
16307  struct mg_context *client_ctx = NULL;
16308 #endif /* defined(USE_WEBSOCKET) */
16309 
16310  if ((conn == NULL) || (conn->phys_ctx == NULL)) {
16311  return;
16312  }
16313 
16314 #if defined(USE_WEBSOCKET)
16315  if (conn->phys_ctx->context_type == CONTEXT_SERVER) {
16316  if (conn->in_websocket_handling) {
16317  /* Set close flag, so the server thread can exit. */
16318  conn->must_close = 1;
16319  return;
16320  }
16321  }
16322  if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) {
16323 
16324  unsigned int i;
16325 
16326  /* ws/wss client */
16327  client_ctx = conn->phys_ctx;
16328 
16329  /* client context: loops must end */
16330  client_ctx->stop_flag = 1;
16331  conn->must_close = 1;
16332 
16333  /* We need to get the client thread out of the select/recv call
16334  * here. */
16335  /* Since we use a sleep quantum of some seconds to check for recv
16336  * timeouts, we will just wait a few seconds in mg_join_thread. */
16337 
16338  /* join worker thread */
16339  for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
16340  if (client_ctx->worker_threadids[i] != 0) {
16341  mg_join_thread(client_ctx->worker_threadids[i]);
16342  }
16343  }
16344  }
16345 #endif /* defined(USE_WEBSOCKET) */
16346 
16347  close_connection(conn);
16348 
16349 #if !defined(NO_SSL)
16350  if (conn->client_ssl_ctx != NULL) {
16351  SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
16352  }
16353 #endif
16354 
16355 #if defined(USE_WEBSOCKET)
16356  if (client_ctx != NULL) {
16357  /* free context */
16358  mg_free(client_ctx->worker_threadids);
16359  mg_free(client_ctx);
16360  (void)pthread_mutex_destroy(&conn->mutex);
16361  mg_free(conn);
16362  } else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) {
16363  mg_free(conn);
16364  }
16365 #else
16366  if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) { /* Client */
16367  mg_free(conn);
16368  }
16369 #endif /* defined(USE_WEBSOCKET) */
16370 }
16371 
16372 
16373 /* Only for memory statistics */
16374 static struct mg_context common_client_context;
16375 
16376 
16377 static struct mg_connection *
16378 mg_connect_client_impl(const struct mg_client_options *client_options,
16379  int use_ssl,
16380  char *ebuf,
16381  size_t ebuf_len)
16382 {
16383  struct mg_connection *conn = NULL;
16384  SOCKET sock;
16385  union usa sa;
16386  struct sockaddr *psa;
16387  socklen_t len;
16388 
16389  unsigned max_req_size =
16390  (unsigned)atoi(config_options[MAX_REQUEST_SIZE].default_value);
16391 
16392  /* Size of structures, aligned to 8 bytes */
16393  size_t conn_size = ((sizeof(struct mg_connection) + 7) >> 3) << 3;
16394  size_t ctx_size = ((sizeof(struct mg_context) + 7) >> 3) << 3;
16395 
16396  conn = (struct mg_connection *)mg_calloc_ctx(
16397  1, conn_size + ctx_size + max_req_size, &common_client_context);
16398 
16399  if (conn == NULL) {
16400  mg_snprintf(NULL,
16401  NULL, /* No truncation check for ebuf */
16402  ebuf,
16403  ebuf_len,
16404  "calloc(): %s",
16405  strerror(ERRNO));
16406  return NULL;
16407  }
16408 
16409 #if defined(GCC_DIAGNOSTIC)
16410 #pragma GCC diagnostic push
16411 #pragma GCC diagnostic ignored "-Wcast-align"
16412 #endif /* defined(GCC_DIAGNOSTIC) */
16413  /* conn_size is aligned to 8 bytes */
16414 
16415  conn->phys_ctx = (struct mg_context *)(((char *)conn) + conn_size);
16416 
16417 #if defined(GCC_DIAGNOSTIC)
16418 #pragma GCC diagnostic pop
16419 #endif /* defined(GCC_DIAGNOSTIC) */
16420 
16421  conn->buf = (((char *)conn) + conn_size + ctx_size);
16422  conn->buf_size = (int)max_req_size;
16423  conn->phys_ctx->context_type = CONTEXT_HTTP_CLIENT;
16424  conn->dom_ctx = &(conn->phys_ctx->dd);
16425 
16426  if (!connect_socket(&common_client_context,
16427  client_options->host,
16428  client_options->port,
16429  use_ssl,
16430  ebuf,
16431  ebuf_len,
16432  &sock,
16433  &sa)) {
16434  /* ebuf is set by connect_socket,
16435  * free all memory and return NULL; */
16436  mg_free(conn);
16437  return NULL;
16438  }
16439 
16440 #if !defined(NO_SSL)
16441 #if defined(OPENSSL_API_1_1)
16442  if (use_ssl
16443  && (conn->client_ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) {
16444  mg_snprintf(NULL,
16445  NULL, /* No truncation check for ebuf */
16446  ebuf,
16447  ebuf_len,
16448  "SSL_CTX_new error");
16449  closesocket(sock);
16450  mg_free(conn);
16451  return NULL;
16452  }
16453 #else
16454  if (use_ssl
16455  && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
16456  == NULL) {
16457  mg_snprintf(NULL,
16458  NULL, /* No truncation check for ebuf */
16459  ebuf,
16460  ebuf_len,
16461  "SSL_CTX_new error");
16462  closesocket(sock);
16463  mg_free(conn);
16464  return NULL;
16465  }
16466 #endif /* OPENSSL_API_1_1 */
16467 #endif /* NO_SSL */
16468 
16469 
16470 #if defined(USE_IPV6)
16471  len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin)
16472  : sizeof(conn->client.rsa.sin6);
16473  psa = (sa.sa.sa_family == AF_INET)
16474  ? (struct sockaddr *)&(conn->client.rsa.sin)
16475  : (struct sockaddr *)&(conn->client.rsa.sin6);
16476 #else
16477  len = sizeof(conn->client.rsa.sin);
16478  psa = (struct sockaddr *)&(conn->client.rsa.sin);
16479 #endif
16480 
16481  conn->client.sock = sock;
16482  conn->client.lsa = sa;
16483 
16484  if (getsockname(sock, psa, &len) != 0) {
16485  mg_cry_internal(conn,
16486  "%s: getsockname() failed: %s",
16487  __func__,
16488  strerror(ERRNO));
16489  }
16490 
16491  conn->client.is_ssl = use_ssl ? 1 : 0;
16492  if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) {
16493  mg_snprintf(NULL,
16494  NULL, /* No truncation check for ebuf */
16495  ebuf,
16496  ebuf_len,
16497  "Can not create mutex");
16498 #if !defined(NO_SSL)
16499  SSL_CTX_free(conn->client_ssl_ctx);
16500 #endif
16501  closesocket(sock);
16502  mg_free(conn);
16503  return NULL;
16504  }
16505 
16506 
16507 #if !defined(NO_SSL)
16508  if (use_ssl) {
16509  common_client_context.dd.ssl_ctx = conn->client_ssl_ctx;
16510 
16511  /* TODO: Check ssl_verify_peer and ssl_ca_path here.
16512  * SSL_CTX_set_verify call is needed to switch off server
16513  * certificate checking, which is off by default in OpenSSL and
16514  * on in yaSSL. */
16515  /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
16516  * SSL_VERIFY_PEER, verify_ssl_server); */
16517 
16518  if (client_options->client_cert) {
16519  if (!ssl_use_pem_file(&common_client_context,
16520  &(common_client_context.dd),
16521  client_options->client_cert,
16522  NULL)) {
16523  mg_snprintf(NULL,
16524  NULL, /* No truncation check for ebuf */
16525  ebuf,
16526  ebuf_len,
16527  "Can not use SSL client certificate");
16528  SSL_CTX_free(conn->client_ssl_ctx);
16529  closesocket(sock);
16530  mg_free(conn);
16531  return NULL;
16532  }
16533  }
16534 
16535  if (client_options->server_cert) {
16536  SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
16537  client_options->server_cert,
16538  NULL);
16539  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
16540  } else {
16541  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
16542  }
16543 
16544  if (!sslize(conn,
16545  conn->client_ssl_ctx,
16546  SSL_connect,
16547  &(conn->phys_ctx->stop_flag),
16548  client_options)) {
16549  mg_snprintf(NULL,
16550  NULL, /* No truncation check for ebuf */
16551  ebuf,
16552  ebuf_len,
16553  "SSL connection error");
16554  SSL_CTX_free(conn->client_ssl_ctx);
16555  closesocket(sock);
16556  mg_free(conn);
16557  return NULL;
16558  }
16559  }
16560 #endif
16561 
16562  if (0 != set_non_blocking_mode(sock)) {
16563  mg_cry_internal(conn,
16564  "Cannot set non-blocking mode for client %s:%i",
16565  client_options->host,
16566  client_options->port);
16567  }
16568 
16569  return conn;
16570 }
16571 
16572 
16573 CIVETWEB_API struct mg_connection *
16574 mg_connect_client_secure(const struct mg_client_options *client_options,
16575  char *error_buffer,
16576  size_t error_buffer_size)
16577 {
16578  return mg_connect_client_impl(client_options,
16579  1,
16580  error_buffer,
16581  error_buffer_size);
16582 }
16583 
16584 
16585 struct mg_connection *
16586 mg_connect_client(const char *host,
16587  int port,
16588  int use_ssl,
16589  char *error_buffer,
16590  size_t error_buffer_size)
16591 {
16592  struct mg_client_options opts;
16593  memset(&opts, 0, sizeof(opts));
16594  opts.host = host;
16595  opts.port = port;
16596  return mg_connect_client_impl(&opts,
16597  use_ssl,
16598  error_buffer,
16599  error_buffer_size);
16600 }
16601 
16602 
16603 static const struct {
16604  const char *proto;
16605  size_t proto_len;
16606  unsigned default_port;
16607 } abs_uri_protocols[] = {{"http://", 7, 80},
16608  {"https://", 8, 443},
16609  {"ws://", 5, 80},
16610  {"wss://", 6, 443},
16611  {NULL, 0, 0}};
16612 
16613 
16614 /* Check if the uri is valid.
16615  * return 0 for invalid uri,
16616  * return 1 for *,
16617  * return 2 for relative uri,
16618  * return 3 for absolute uri without port,
16619  * return 4 for absolute uri with port */
16620 static int
16621 get_uri_type(const char *uri)
16622 {
16623  int i;
16624  const char *hostend, *portbegin;
16625  char *portend;
16626  unsigned long port;
16627 
16628  /* According to the HTTP standard
16629  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
16630  * URI can be an asterisk (*) or should start with slash (relative uri),
16631  * or it should start with the protocol (absolute uri). */
16632  if ((uri[0] == '*') && (uri[1] == '\0')) {
16633  /* asterisk */
16634  return 1;
16635  }
16636 
16637  /* Valid URIs according to RFC 3986
16638  * (https://www.ietf.org/rfc/rfc3986.txt)
16639  * must only contain reserved characters :/?#[]@!$&'()*+,;=
16640  * and unreserved characters A-Z a-z 0-9 and -._~
16641  * and % encoded symbols.
16642  */
16643  for (i = 0; uri[i] != 0; i++) {
16644  if (uri[i] < 33) {
16645  /* control characters and spaces are invalid */
16646  return 0;
16647  }
16648  if (uri[i] > 126) {
16649  /* non-ascii characters must be % encoded */
16650  return 0;
16651  } else {
16652  switch (uri[i]) {
16653  case '"': /* 34 */
16654  case '<': /* 60 */
16655  case '>': /* 62 */
16656  case '\\': /* 92 */
16657  case '^': /* 94 */
16658  case '`': /* 96 */
16659  case '{': /* 123 */
16660  case '|': /* 124 */
16661  case '}': /* 125 */
16662  return 0;
16663  default:
16664  /* character is ok */
16665  break;
16666  }
16667  }
16668  }
16669 
16670  /* A relative uri starts with a / character */
16671  if (uri[0] == '/') {
16672  /* relative uri */
16673  return 2;
16674  }
16675 
16676  /* It could be an absolute uri: */
16677  /* This function only checks if the uri is valid, not if it is
16678  * addressing the current server. So civetweb can also be used
16679  * as a proxy server. */
16680  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
16681  if (mg_strncasecmp(uri,
16682  abs_uri_protocols[i].proto,
16683  abs_uri_protocols[i].proto_len)
16684  == 0) {
16685 
16686  hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
16687  if (!hostend) {
16688  return 0;
16689  }
16690  portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
16691  if (!portbegin) {
16692  return 3;
16693  }
16694 
16695  port = strtoul(portbegin + 1, &portend, 10);
16696  if ((portend != hostend) || (port <= 0) || !is_valid_port(port)) {
16697  return 0;
16698  }
16699 
16700  return 4;
16701  }
16702  }
16703 
16704  return 0;
16705 }
16706 
16707 
16708 /* Return NULL or the relative uri at the current server */
16709 static const char *
16710 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
16711 {
16712  const char *server_domain;
16713  size_t server_domain_len;
16714  size_t request_domain_len = 0;
16715  unsigned long port = 0;
16716  int i, auth_domain_check_enabled;
16717  const char *hostbegin = NULL;
16718  const char *hostend = NULL;
16719  const char *portbegin;
16720  char *portend;
16721 
16722  auth_domain_check_enabled =
16723  !mg_strcasecmp(conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes");
16724 
16725  /* DNS is case insensitive, so use case insensitive string compare here
16726  */
16727  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
16728  if (mg_strncasecmp(uri,
16729  abs_uri_protocols[i].proto,
16730  abs_uri_protocols[i].proto_len)
16731  == 0) {
16732 
16733  hostbegin = uri + abs_uri_protocols[i].proto_len;
16734  hostend = strchr(hostbegin, '/');
16735  if (!hostend) {
16736  return 0;
16737  }
16738  portbegin = strchr(hostbegin, ':');
16739  if ((!portbegin) || (portbegin > hostend)) {
16740  port = abs_uri_protocols[i].default_port;
16741  request_domain_len = (size_t)(hostend - hostbegin);
16742  } else {
16743  port = strtoul(portbegin + 1, &portend, 10);
16744  if ((portend != hostend) || (port <= 0)
16745  || !is_valid_port(port)) {
16746  return 0;
16747  }
16748  request_domain_len = (size_t)(portbegin - hostbegin);
16749  }
16750  /* protocol found, port set */
16751  break;
16752  }
16753  }
16754 
16755  if (!port) {
16756  /* port remains 0 if the protocol is not found */
16757  return 0;
16758  }
16759 
16760 /* Check if the request is directed to a different server. */
16761 /* First check if the port is the same (IPv4 and IPv6). */
16762 #if defined(USE_IPV6)
16763  if (conn->client.lsa.sa.sa_family == AF_INET6) {
16764  if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
16765  /* Request is directed to a different port */
16766  return 0;
16767  }
16768  } else
16769 #endif
16770  {
16771  if (ntohs(conn->client.lsa.sin.sin_port) != port) {
16772  /* Request is directed to a different port */
16773  return 0;
16774  }
16775  }
16776 
16777  /* Finally check if the server corresponds to the authentication
16778  * domain of the server (the server domain).
16779  * Allow full matches (like http://mydomain.com/path/file.ext), and
16780  * allow subdomain matches (like http://www.mydomain.com/path/file.ext),
16781  * but do not allow substrings (like
16782  * http://notmydomain.com/path/file.ext
16783  * or http://mydomain.com.fake/path/file.ext).
16784  */
16785  if (auth_domain_check_enabled) {
16786  server_domain = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
16787  server_domain_len = strlen(server_domain);
16788  if ((server_domain_len == 0) || (hostbegin == NULL)) {
16789  return 0;
16790  }
16791  if ((request_domain_len == server_domain_len)
16792  && (!memcmp(server_domain, hostbegin, server_domain_len))) {
16793  /* Request is directed to this server - full name match. */
16794  } else {
16795  if (request_domain_len < (server_domain_len + 2)) {
16796  /* Request is directed to another server: The server name
16797  * is longer than the request name.
16798  * Drop this case here to avoid overflows in the
16799  * following checks. */
16800  return 0;
16801  }
16802  if (hostbegin[request_domain_len - server_domain_len - 1] != '.') {
16803  /* Request is directed to another server: It could be a
16804  * substring
16805  * like notmyserver.com */
16806  return 0;
16807  }
16808  if (0
16809  != memcmp(server_domain,
16810  hostbegin + request_domain_len - server_domain_len,
16811  server_domain_len)) {
16812  /* Request is directed to another server:
16813  * The server name is different. */
16814  return 0;
16815  }
16816  }
16817  }
16818 
16819  return hostend;
16820 }
16821 
16822 
16823 static int
16824 get_message(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
16825 {
16826  if (ebuf_len > 0) {
16827  ebuf[0] = '\0';
16828  }
16829  *err = 0;
16830 
16831  reset_per_request_attributes(conn);
16832 
16833  if (!conn) {
16834  mg_snprintf(conn,
16835  NULL, /* No truncation check for ebuf */
16836  ebuf,
16837  ebuf_len,
16838  "%s",
16839  "Internal error");
16840  *err = 500;
16841  return 0;
16842  }
16843  /* Set the time the request was received. This value should be used for
16844  * timeouts. */
16845  clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
16846 
16847  conn->request_len =
16848  read_message(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
16849  DEBUG_ASSERT(conn->request_len < 0 || conn->data_len >= conn->request_len);
16850  if ((conn->request_len >= 0) && (conn->data_len < conn->request_len)) {
16851  mg_snprintf(conn,
16852  NULL, /* No truncation check for ebuf */
16853  ebuf,
16854  ebuf_len,
16855  "%s",
16856  "Invalid message size");
16857  *err = 500;
16858  return 0;
16859  }
16860 
16861  if ((conn->request_len == 0) && (conn->data_len == conn->buf_size)) {
16862  mg_snprintf(conn,
16863  NULL, /* No truncation check for ebuf */
16864  ebuf,
16865  ebuf_len,
16866  "%s",
16867  "Message too large");
16868  *err = 413;
16869  return 0;
16870  }
16871 
16872  if (conn->request_len <= 0) {
16873  if (conn->data_len > 0) {
16874  mg_snprintf(conn,
16875  NULL, /* No truncation check for ebuf */
16876  ebuf,
16877  ebuf_len,
16878  "%s",
16879  "Malformed message");
16880  *err = 400;
16881  } else {
16882  /* Server did not recv anything -> just close the connection */
16883  conn->must_close = 1;
16884  mg_snprintf(conn,
16885  NULL, /* No truncation check for ebuf */
16886  ebuf,
16887  ebuf_len,
16888  "%s",
16889  "No data received");
16890  *err = 0;
16891  }
16892  return 0;
16893  }
16894  return 1;
16895 }
16896 
16897 
16898 static int
16899 get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
16900 {
16901  const char *cl;
16902  if (!get_message(conn, ebuf, ebuf_len, err)) {
16903  return 0;
16904  }
16905 
16906  if (parse_http_request(conn->buf, conn->buf_size, &conn->request_info)
16907  <= 0) {
16908  mg_snprintf(conn,
16909  NULL, /* No truncation check for ebuf */
16910  ebuf,
16911  ebuf_len,
16912  "%s",
16913  "Bad request");
16914  *err = 400;
16915  return 0;
16916  }
16917 
16918  /* Message is a valid request */
16919 
16920  /* Is there a "host" ? */
16921  conn->host = alloc_get_host(conn);
16922  if (!conn->host) {
16923  mg_snprintf(conn,
16924  NULL, /* No truncation check for ebuf */
16925  ebuf,
16926  ebuf_len,
16927  "%s",
16928  "Bad request: Host mismatch");
16929  *err = 400;
16930  return 0;
16931  }
16932 
16933  /* Do we know the content length? */
16934  if ((cl = get_header(conn->request_info.http_headers,
16935  conn->request_info.num_headers,
16936  "Content-Length"))
16937  != NULL) {
16938  /* Request/response has content length set */
16939  char *endptr = NULL;
16940  conn->content_len = strtoll(cl, &endptr, 10);
16941  if (endptr == cl) {
16942  mg_snprintf(conn,
16943  NULL, /* No truncation check for ebuf */
16944  ebuf,
16945  ebuf_len,
16946  "%s",
16947  "Bad request");
16948  *err = 411;
16949  return 0;
16950  }
16951  /* Publish the content length back to the request info. */
16952  conn->request_info.content_length = conn->content_len;
16953  } else if ((cl = get_header(conn->request_info.http_headers,
16954  conn->request_info.num_headers,
16955  "Transfer-Encoding"))
16956  != NULL
16957  && !mg_strcasecmp(cl, "chunked")) {
16958  conn->is_chunked = 1;
16959  conn->content_len = -1; /* unknown content length */
16960  } else {
16961  const struct mg_http_method_info *meth =
16962  get_http_method_info(conn->request_info.request_method);
16963  if (!meth) {
16964  /* No valid HTTP method */
16965  mg_snprintf(conn,
16966  NULL, /* No truncation check for ebuf */
16967  ebuf,
16968  ebuf_len,
16969  "%s",
16970  "Bad request");
16971  *err = 411;
16972  return 0;
16973  }
16974  if (meth->request_has_body) {
16975  /* POST or PUT request without content length set */
16976  conn->content_len = -1; /* unknown content length */
16977  } else {
16978  /* Other request */
16979  conn->content_len = 0; /* No content */
16980  }
16981  }
16982 
16983  conn->connection_type = CONNECTION_TYPE_REQUEST; /* Valid request */
16984  return 1;
16985 }
16986 
16987 
16988 /* conn is assumed to be valid in this internal function */
16989 static int
16990 get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
16991 {
16992  const char *cl;
16993  if (!get_message(conn, ebuf, ebuf_len, err)) {
16994  return 0;
16995  }
16996 
16997  if (parse_http_response(conn->buf, conn->buf_size, &conn->response_info)
16998  <= 0) {
16999  mg_snprintf(conn,
17000  NULL, /* No truncation check for ebuf */
17001  ebuf,
17002  ebuf_len,
17003  "%s",
17004  "Bad response");
17005  *err = 400;
17006  return 0;
17007  }
17008 
17009  /* Message is a valid response */
17010 
17011  /* Do we know the content length? */
17012  if ((cl = get_header(conn->response_info.http_headers,
17013  conn->response_info.num_headers,
17014  "Content-Length"))
17015  != NULL) {
17016  /* Request/response has content length set */
17017  char *endptr = NULL;
17018  conn->content_len = strtoll(cl, &endptr, 10);
17019  if (endptr == cl) {
17020  mg_snprintf(conn,
17021  NULL, /* No truncation check for ebuf */
17022  ebuf,
17023  ebuf_len,
17024  "%s",
17025  "Bad request");
17026  *err = 411;
17027  return 0;
17028  }
17029  /* Publish the content length back to the response info. */
17030  conn->response_info.content_length = conn->content_len;
17031 
17032  /* TODO: check if it is still used in response_info */
17033  conn->request_info.content_length = conn->content_len;
17034 
17035  } else if ((cl = get_header(conn->response_info.http_headers,
17036  conn->response_info.num_headers,
17037  "Transfer-Encoding"))
17038  != NULL
17039  && !mg_strcasecmp(cl, "chunked")) {
17040  conn->is_chunked = 1;
17041  conn->content_len = -1; /* unknown content length */
17042  } else {
17043  conn->content_len = -1; /* unknown content length */
17044  }
17045 
17046  conn->connection_type = CONNECTION_TYPE_RESPONSE; /* Valid response */
17047  return 1;
17048 }
17049 
17050 
17051 int
17052 mg_get_response(struct mg_connection *conn,
17053  char *ebuf,
17054  size_t ebuf_len,
17055  int timeout)
17056 {
17057  int err, ret;
17058  char txt[32]; /* will not overflow */
17059  char *save_timeout;
17060  char *new_timeout;
17061 
17062  if (ebuf_len > 0) {
17063  ebuf[0] = '\0';
17064  }
17065 
17066  if (!conn) {
17067  mg_snprintf(conn,
17068  NULL, /* No truncation check for ebuf */
17069  ebuf,
17070  ebuf_len,
17071  "%s",
17072  "Parameter error");
17073  return -1;
17074  }
17075 
17076  /* Implementation of API function for HTTP clients */
17077  save_timeout = conn->dom_ctx->config[REQUEST_TIMEOUT];
17078 
17079  if (timeout >= 0) {
17080  mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
17081  new_timeout = txt;
17082  /* Not required for non-blocking sockets.
17083  set_sock_timeout(conn->client.sock, timeout);
17084  */
17085  } else {
17086  new_timeout = NULL;
17087  }
17088 
17089  conn->dom_ctx->config[REQUEST_TIMEOUT] = new_timeout;
17090  ret = get_response(conn, ebuf, ebuf_len, &err);
17091  conn->dom_ctx->config[REQUEST_TIMEOUT] = save_timeout;
17092 
17093 #if defined(MG_LEGACY_INTERFACE)
17094  /* TODO: 1) uri is deprecated;
17095  * 2) here, ri.uri is the http response code */
17096  conn->request_info.uri = conn->request_info.request_uri;
17097 #endif
17098  conn->request_info.local_uri = conn->request_info.request_uri;
17099 
17100  /* TODO (mid): Define proper return values - maybe return length?
17101  * For the first test use <0 for error and >0 for OK */
17102  return (ret == 0) ? -1 : +1;
17103 }
17104 
17105 
17106 struct mg_connection *
17107 mg_download(const char *host,
17108  int port,
17109  int use_ssl,
17110  char *ebuf,
17111  size_t ebuf_len,
17112  const char *fmt,
17113  ...)
17114 {
17115  struct mg_connection *conn;
17116  va_list ap;
17117  int i;
17118  int reqerr;
17119 
17120  if (ebuf_len > 0) {
17121  ebuf[0] = '\0';
17122  }
17123 
17124  va_start(ap, fmt);
17125 
17126  /* open a connection */
17127  conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
17128 
17129  if (conn != NULL) {
17130  i = mg_vprintf(conn, fmt, ap);
17131  if (i <= 0) {
17132  mg_snprintf(conn,
17133  NULL, /* No truncation check for ebuf */
17134  ebuf,
17135  ebuf_len,
17136  "%s",
17137  "Error sending request");
17138  } else {
17139  get_response(conn, ebuf, ebuf_len, &reqerr);
17140 
17141 #if defined(MG_LEGACY_INTERFACE)
17142  /* TODO: 1) uri is deprecated;
17143  * 2) here, ri.uri is the http response code */
17144  conn->request_info.uri = conn->request_info.request_uri;
17145 #endif
17146  conn->request_info.local_uri = conn->request_info.request_uri;
17147  }
17148  }
17149 
17150  /* if an error occurred, close the connection */
17151  if ((ebuf[0] != '\0') && (conn != NULL)) {
17152  mg_close_connection(conn);
17153  conn = NULL;
17154  }
17155 
17156  va_end(ap);
17157  return conn;
17158 }
17159 
17160 
17161 struct websocket_client_thread_data {
17162  struct mg_connection *conn;
17163  mg_websocket_data_handler data_handler;
17164  mg_websocket_close_handler close_handler;
17165  void *callback_data;
17166 };
17167 
17168 
17169 #if defined(USE_WEBSOCKET)
17170 #if defined(_WIN32)
17171 static unsigned __stdcall websocket_client_thread(void *data)
17172 #else
17173 static void *
17174 websocket_client_thread(void *data)
17175 #endif
17176 {
17177  struct websocket_client_thread_data *cdata =
17178  (struct websocket_client_thread_data *)data;
17179 
17180 #if !defined(_WIN32)
17181  struct sigaction sa;
17182 
17183  /* Ignore SIGPIPE */
17184  memset(&sa, 0, sizeof(sa));
17185  sa.sa_handler = SIG_IGN;
17186  sigaction(SIGPIPE, &sa, NULL);
17187 #endif
17188 
17189  mg_set_thread_name("ws-clnt");
17190 
17191  if (cdata->conn->phys_ctx) {
17192  if (cdata->conn->phys_ctx->callbacks.init_thread) {
17193  /* 3 indicates a websocket client thread */
17194  /* TODO: check if conn->phys_ctx can be set */
17195  cdata->conn->phys_ctx->callbacks.init_thread(cdata->conn->phys_ctx,
17196  3);
17197  }
17198  }
17199 
17200  read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
17201 
17202  DEBUG_TRACE("%s", "Websocket client thread exited\n");
17203 
17204  if (cdata->close_handler != NULL) {
17205  cdata->close_handler(cdata->conn, cdata->callback_data);
17206  }
17207 
17208  /* The websocket_client context has only this thread. If it runs out,
17209  set the stop_flag to 2 (= "stopped"). */
17210  cdata->conn->phys_ctx->stop_flag = 2;
17211 
17212  mg_free((void *)cdata);
17213 
17214 #if defined(_WIN32)
17215  return 0;
17216 #else
17217  return NULL;
17218 #endif
17219 }
17220 #endif
17221 
17222 
17223 struct mg_connection *
17224 mg_connect_websocket_client(const char *host,
17225  int port,
17226  int use_ssl,
17227  char *error_buffer,
17228  size_t error_buffer_size,
17229  const char *path,
17230  const char *origin,
17231  mg_websocket_data_handler data_func,
17232  mg_websocket_close_handler close_func,
17233  void *user_data)
17234 {
17235  struct mg_connection *conn = NULL;
17236 
17237 #if defined(USE_WEBSOCKET)
17238  struct mg_context *newctx = NULL;
17239  struct websocket_client_thread_data *thread_data;
17240  static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
17241  static const char *handshake_req;
17242 
17243  if (origin != NULL) {
17244  handshake_req = "GET %s HTTP/1.1\r\n"
17245  "Host: %s\r\n"
17246  "Upgrade: websocket\r\n"
17247  "Connection: Upgrade\r\n"
17248  "Sec-WebSocket-Key: %s\r\n"
17249  "Sec-WebSocket-Version: 13\r\n"
17250  "Origin: %s\r\n"
17251  "\r\n";
17252  } else {
17253  handshake_req = "GET %s HTTP/1.1\r\n"
17254  "Host: %s\r\n"
17255  "Upgrade: websocket\r\n"
17256  "Connection: Upgrade\r\n"
17257  "Sec-WebSocket-Key: %s\r\n"
17258  "Sec-WebSocket-Version: 13\r\n"
17259  "\r\n";
17260  }
17261 
17262 #if defined(__clang__)
17263 #pragma clang diagnostic push
17264 #pragma clang diagnostic ignored "-Wformat-nonliteral"
17265 #endif
17266 
17267  /* Establish the client connection and request upgrade */
17268  conn = mg_download(host,
17269  port,
17270  use_ssl,
17271  error_buffer,
17272  error_buffer_size,
17273  handshake_req,
17274  path,
17275  host,
17276  magic,
17277  origin);
17278 
17279 #if defined(__clang__)
17280 #pragma clang diagnostic pop
17281 #endif
17282 
17283  /* Connection object will be null if something goes wrong */
17284  if (conn == NULL) {
17285  if (!*error_buffer) {
17286  /* There should be already an error message */
17287  mg_snprintf(conn,
17288  NULL, /* No truncation check for ebuf */
17289  error_buffer,
17290  error_buffer_size,
17291  "Unexpected error");
17292  }
17293  return NULL;
17294  }
17295 
17296  if (conn->response_info.status_code != 101) {
17297  /* We sent an "upgrade" request. For a correct websocket
17298  * protocol handshake, we expect a "101 Continue" response.
17299  * Otherwise it is a protocol violation. Maybe the HTTP
17300  * Server does not know websockets. */
17301  if (!*error_buffer) {
17302  /* set an error, if not yet set */
17303  mg_snprintf(conn,
17304  NULL, /* No truncation check for ebuf */
17305  error_buffer,
17306  error_buffer_size,
17307  "Unexpected server reply");
17308  }
17309 
17310  DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
17311  mg_free(conn);
17312  return NULL;
17313  }
17314 
17315  /* For client connections, mg_context is fake. Since we need to set a
17316  * callback function, we need to create a copy and modify it. */
17317  newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
17318  if (!newctx) {
17319  DEBUG_TRACE("%s\r\n", "Out of memory");
17320  mg_free(conn);
17321  return NULL;
17322  }
17323 
17324  memcpy(newctx, conn->phys_ctx, sizeof(struct mg_context));
17325  newctx->user_data = user_data;
17326  newctx->context_type = CONTEXT_WS_CLIENT; /* ws/wss client context */
17327  newctx->cfg_worker_threads = 1; /* one worker thread will be created */
17328  newctx->worker_threadids =
17329  (pthread_t *)mg_calloc_ctx(newctx->cfg_worker_threads,
17330  sizeof(pthread_t),
17331  newctx);
17332 
17333  conn->phys_ctx = newctx;
17334  conn->dom_ctx = &(newctx->dd);
17335 
17336  thread_data = (struct websocket_client_thread_data *)
17337  mg_calloc_ctx(sizeof(struct websocket_client_thread_data), 1, newctx);
17338  if (!thread_data) {
17339  DEBUG_TRACE("%s\r\n", "Out of memory");
17340  mg_free(newctx);
17341  mg_free(conn);
17342  return NULL;
17343  }
17344 
17345  thread_data->conn = conn;
17346  thread_data->data_handler = data_func;
17347  thread_data->close_handler = close_func;
17348  thread_data->callback_data = user_data;
17349 
17350  /* Start a thread to read the websocket client connection
17351  * This thread will automatically stop when mg_disconnect is
17352  * called on the client connection */
17353  if (mg_start_thread_with_id(websocket_client_thread,
17354  (void *)thread_data,
17355  newctx->worker_threadids)
17356  != 0) {
17357  mg_free((void *)thread_data);
17358  mg_free((void *)newctx->worker_threadids);
17359  mg_free((void *)newctx);
17360  mg_free((void *)conn);
17361  conn = NULL;
17362  DEBUG_TRACE("%s",
17363  "Websocket client connect thread could not be started\r\n");
17364  }
17365 
17366 #else
17367  /* Appease "unused parameter" warnings */
17368  (void)host;
17369  (void)port;
17370  (void)use_ssl;
17371  (void)error_buffer;
17372  (void)error_buffer_size;
17373  (void)path;
17374  (void)origin;
17375  (void)user_data;
17376  (void)data_func;
17377  (void)close_func;
17378 #endif
17379 
17380  return conn;
17381 }
17382 
17383 
17384 /* Prepare connection data structure */
17385 static void
17386 init_connection(struct mg_connection *conn)
17387 {
17388  /* Is keep alive allowed by the server */
17389  int keep_alive_enabled =
17390  !mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes");
17391 
17392  if (!keep_alive_enabled) {
17393  conn->must_close = 1;
17394  }
17395 
17396  /* Important: on new connection, reset the receiving buffer. Credit
17397  * goes to crule42. */
17398  conn->data_len = 0;
17399  conn->handled_requests = 0;
17400  mg_set_user_connection_data(conn, NULL);
17401 
17402 #if defined(USE_SERVER_STATS)
17403  conn->conn_state = 2; /* init */
17404 #endif
17405 
17406  /* call the init_connection callback if assigned */
17407  if (conn->phys_ctx->callbacks.init_connection != NULL) {
17408  if (conn->phys_ctx->context_type == CONTEXT_SERVER) {
17409  void *conn_data = NULL;
17410  conn->phys_ctx->callbacks.init_connection(conn, &conn_data);
17411  mg_set_user_connection_data(conn, conn_data);
17412  }
17413  }
17414 }
17415 
17416 
17417 /* Process a connection - may handle multiple requests
17418  * using the same connection.
17419  * Must be called with a valid connection (conn and
17420  * conn->phys_ctx must be valid).
17421  */
17422 static void
17423 process_new_connection(struct mg_connection *conn)
17424 {
17425  struct mg_request_info *ri = &conn->request_info;
17426  int keep_alive, discard_len;
17427  char ebuf[100];
17428  const char *hostend;
17429  int reqerr, uri_type;
17430 
17431 #if defined(USE_SERVER_STATS)
17432  int mcon = mg_atomic_inc(&(conn->phys_ctx->active_connections));
17433  mg_atomic_add(&(conn->phys_ctx->total_connections), 1);
17434  if (mcon > (conn->phys_ctx->max_connections)) {
17435  /* could use atomic compare exchange, but this
17436  * seems overkill for statistics data */
17437  conn->phys_ctx->max_connections = mcon;
17438  }
17439 #endif
17440 
17441  init_connection(conn);
17442 
17443  DEBUG_TRACE("Start processing connection from %s",
17444  conn->request_info.remote_addr);
17445 
17446  /* Loop over multiple requests sent using the same connection
17447  * (while "keep alive"). */
17448  do {
17449 
17450  DEBUG_TRACE("calling get_request (%i times for this connection)",
17451  conn->handled_requests + 1);
17452 
17453 #if defined(USE_SERVER_STATS)
17454  conn->conn_state = 3; /* ready */
17455 #endif
17456 
17457  if (!get_request(conn, ebuf, sizeof(ebuf), &reqerr)) {
17458  /* The request sent by the client could not be understood by
17459  * the server, or it was incomplete or a timeout. Send an
17460  * error message and close the connection. */
17461  if (reqerr > 0) {
17462  DEBUG_ASSERT(ebuf[0] != '\0');
17463  mg_send_http_error(conn, reqerr, "%s", ebuf);
17464  }
17465  } else if (strcmp(ri->http_version, "1.0")
17466  && strcmp(ri->http_version, "1.1")) {
17467  mg_snprintf(conn,
17468  NULL, /* No truncation check for ebuf */
17469  ebuf,
17470  sizeof(ebuf),
17471  "Bad HTTP version: [%s]",
17472  ri->http_version);
17473  mg_send_http_error(conn, 505, "%s", ebuf);
17474  }
17475 
17476  if (ebuf[0] == '\0') {
17477  uri_type = get_uri_type(conn->request_info.request_uri);
17478  switch (uri_type) {
17479  case 1:
17480  /* Asterisk */
17481  conn->request_info.local_uri = NULL;
17482  break;
17483  case 2:
17484  /* relative uri */
17485  conn->request_info.local_uri = conn->request_info.request_uri;
17486  break;
17487  case 3:
17488  case 4:
17489  /* absolute uri (with/without port) */
17490  hostend = get_rel_url_at_current_server(
17491  conn->request_info.request_uri, conn);
17492  if (hostend) {
17493  conn->request_info.local_uri = hostend;
17494  } else {
17495  conn->request_info.local_uri = NULL;
17496  }
17497  break;
17498  default:
17499  mg_snprintf(conn,
17500  NULL, /* No truncation check for ebuf */
17501  ebuf,
17502  sizeof(ebuf),
17503  "Invalid URI");
17504  mg_send_http_error(conn, 400, "%s", ebuf);
17505  conn->request_info.local_uri = NULL;
17506  break;
17507  }
17508 
17509 #if defined(MG_LEGACY_INTERFACE)
17510  /* Legacy before split into local_uri and request_uri */
17511  conn->request_info.uri = conn->request_info.local_uri;
17512 #endif
17513  }
17514 
17515  DEBUG_TRACE("http: %s, error: %s",
17516  (ri->http_version ? ri->http_version : "none"),
17517  (ebuf[0] ? ebuf : "none"));
17518 
17519  if (ebuf[0] == '\0') {
17520  if (conn->request_info.local_uri) {
17521 
17522 /* handle request to local server */
17523 #if defined(USE_SERVER_STATS)
17524  conn->conn_state = 4; /* processing */
17525 #endif
17526  handle_request(conn);
17527 
17528 #if defined(USE_SERVER_STATS)
17529  conn->conn_state = 5; /* processed */
17530 
17531  mg_atomic_add(&(conn->phys_ctx->total_data_read),
17532  conn->consumed_content);
17533  mg_atomic_add(&(conn->phys_ctx->total_data_written),
17534  conn->num_bytes_sent);
17535 #endif
17536 
17537  DEBUG_TRACE("%s", "handle_request done");
17538 
17539  if (conn->phys_ctx->callbacks.end_request != NULL) {
17540  conn->phys_ctx->callbacks.end_request(conn,
17541  conn->status_code);
17542  DEBUG_TRACE("%s", "end_request callback done");
17543  }
17544  log_access(conn);
17545  } else {
17546  /* TODO: handle non-local request (PROXY) */
17547  conn->must_close = 1;
17548  }
17549  } else {
17550  conn->must_close = 1;
17551  }
17552 
17553  if (ri->remote_user != NULL) {
17554  mg_free((void *)ri->remote_user);
17555  /* Important! When having connections with and without auth
17556  * would cause double free and then crash */
17557  ri->remote_user = NULL;
17558  }
17559 
17560  /* NOTE(lsm): order is important here. should_keep_alive() call
17561  * is using parsed request, which will be invalid after
17562  * memmove's below.
17563  * Therefore, memorize should_keep_alive() result now for later
17564  * use in loop exit condition. */
17565  keep_alive = (conn->phys_ctx->stop_flag == 0) && should_keep_alive(conn)
17566  && (conn->content_len >= 0);
17567 
17568 
17569  /* Discard all buffered data for this request */
17570  discard_len = ((conn->content_len >= 0) && (conn->request_len > 0)
17571  && ((conn->request_len + conn->content_len)
17572  < (int64_t)conn->data_len))
17573  ? (int)(conn->request_len + conn->content_len)
17574  : conn->data_len;
17575  DEBUG_ASSERT(discard_len >= 0);
17576  if (discard_len < 0) {
17577  DEBUG_TRACE("internal error: discard_len = %li",
17578  (long int)discard_len);
17579  break;
17580  }
17581  conn->data_len -= discard_len;
17582  if (conn->data_len > 0) {
17583  DEBUG_TRACE("discard_len = %lu", (long unsigned)discard_len);
17584  memmove(conn->buf, conn->buf + discard_len, (size_t)conn->data_len);
17585  }
17586 
17587  DEBUG_ASSERT(conn->data_len >= 0);
17588  DEBUG_ASSERT(conn->data_len <= conn->buf_size);
17589 
17590  if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
17591  DEBUG_TRACE("internal error: data_len = %li, buf_size = %li",
17592  (long int)conn->data_len,
17593  (long int)conn->buf_size);
17594  break;
17595  }
17596 
17597  conn->handled_requests++;
17598 
17599  } while (keep_alive);
17600 
17601  DEBUG_TRACE("Done processing connection from %s (%f sec)",
17602  conn->request_info.remote_addr,
17603  difftime(time(NULL), conn->conn_birth_time));
17604 
17605  close_connection(conn);
17606 
17607 #if defined(USE_SERVER_STATS)
17608  mg_atomic_add(&(conn->phys_ctx->total_requests), conn->handled_requests);
17609  mg_atomic_dec(&(conn->phys_ctx->active_connections));
17610 #endif
17611 }
17612 
17613 
17614 #if defined(ALTERNATIVE_QUEUE)
17615 
17616 static void
17617 produce_socket(struct mg_context *ctx, const struct socket *sp)
17618 {
17619  unsigned int i;
17620 
17621  while (!ctx->stop_flag) {
17622  for (i = 0; i < ctx->cfg_worker_threads; i++) {
17623  /* find a free worker slot and signal it */
17624  if (ctx->client_socks[i].in_use == 0) {
17625  ctx->client_socks[i] = *sp;
17626  ctx->client_socks[i].in_use = 1;
17627  event_signal(ctx->client_wait_events[i]);
17628  return;
17629  }
17630  }
17631  /* queue is full */
17632  mg_sleep(1);
17633  }
17634 }
17635 
17636 
17637 static int
17638 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
17639 {
17640  DEBUG_TRACE("%s", "going idle");
17641  ctx->client_socks[thread_index].in_use = 0;
17642  event_wait(ctx->client_wait_events[thread_index]);
17643  *sp = ctx->client_socks[thread_index];
17644  DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
17645 
17646  return !ctx->stop_flag;
17647 }
17648 
17649 #else /* ALTERNATIVE_QUEUE */
17650 
17651 /* Worker threads take accepted socket from the queue */
17652 static int
17653 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
17654 {
17655 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
17656 
17657  (void)thread_index;
17658 
17659  (void)pthread_mutex_lock(&ctx->thread_mutex);
17660  DEBUG_TRACE("%s", "going idle");
17661 
17662  /* If the queue is empty, wait. We're idle at this point. */
17663  while ((ctx->sq_head == ctx->sq_tail) && (ctx->stop_flag == 0)) {
17664  pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
17665  }
17666 
17667  /* If we're stopping, sq_head may be equal to sq_tail. */
17668  if (ctx->sq_head > ctx->sq_tail) {
17669  /* Copy socket from the queue and increment tail */
17670  *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
17671  ctx->sq_tail++;
17672 
17673  DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
17674 
17675  /* Wrap pointers if needed */
17676  while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
17677  ctx->sq_tail -= QUEUE_SIZE(ctx);
17678  ctx->sq_head -= QUEUE_SIZE(ctx);
17679  }
17680  }
17681 
17682  (void)pthread_cond_signal(&ctx->sq_empty);
17683  (void)pthread_mutex_unlock(&ctx->thread_mutex);
17684 
17685  return !ctx->stop_flag;
17686 #undef QUEUE_SIZE
17687 }
17688 
17689 
17690 /* Master thread adds accepted socket to a queue */
17691 static void
17692 produce_socket(struct mg_context *ctx, const struct socket *sp)
17693 {
17694 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
17695  if (!ctx) {
17696  return;
17697  }
17698  (void)pthread_mutex_lock(&ctx->thread_mutex);
17699 
17700  /* If the queue is full, wait */
17701  while ((ctx->stop_flag == 0)
17702  && (ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx))) {
17703  (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
17704  }
17705 
17706  if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
17707  /* Copy socket to the queue and increment head */
17708  ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
17709  ctx->sq_head++;
17710  DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
17711  }
17712 
17713  (void)pthread_cond_signal(&ctx->sq_full);
17714  (void)pthread_mutex_unlock(&ctx->thread_mutex);
17715 #undef QUEUE_SIZE
17716 }
17717 #endif /* ALTERNATIVE_QUEUE */
17718 
17719 
17720 struct worker_thread_args {
17721  struct mg_context *ctx;
17722  int index;
17723 };
17724 
17725 
17726 static void *
17727 worker_thread_run(struct worker_thread_args *thread_args)
17728 {
17729  struct mg_context *ctx = thread_args->ctx;
17730  struct mg_connection *conn;
17731  struct mg_workerTLS tls;
17732 #if defined(MG_LEGACY_INTERFACE)
17733  uint32_t addr;
17734 #endif
17735 
17736  mg_set_thread_name("worker");
17737 
17738  tls.is_master = 0;
17739  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
17740 #if defined(_WIN32)
17741  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
17742 #endif
17743 
17744  /* Initialize thread local storage before calling any callback */
17745  pthread_setspecific(sTlsKey, &tls);
17746 
17747  if (ctx->callbacks.init_thread) {
17748  /* call init_thread for a worker thread (type 1) */
17749  ctx->callbacks.init_thread(ctx, 1);
17750  }
17751 
17752  /* Connection structure has been pre-allocated */
17753  if (((int)thread_args->index < 0)
17754  || ((unsigned)thread_args->index
17755  >= (unsigned)ctx->cfg_worker_threads)) {
17756  mg_cry_internal(fc(ctx),
17757  "Internal error: Invalid worker index %i",
17758  (int)thread_args->index);
17759  return NULL;
17760  }
17761  conn = ctx->worker_connections + thread_args->index;
17762 
17763  /* Request buffers are not pre-allocated. They are private to the
17764  * request and do not contain any state information that might be
17765  * of interest to anyone observing a server status. */
17766  conn->buf = (char *)mg_malloc_ctx(ctx->max_request_size, conn->phys_ctx);
17767  if (conn->buf == NULL) {
17768  mg_cry_internal(fc(ctx),
17769  "Out of memory: Cannot allocate buffer for worker %i",
17770  (int)thread_args->index);
17771  return NULL;
17772  }
17773  conn->buf_size = (int)ctx->max_request_size;
17774 
17775  conn->phys_ctx = ctx;
17776  conn->dom_ctx = &(ctx->dd); /* Use default domain and default host */
17777  conn->host = NULL; /* until we have more information. */
17778 
17779  conn->thread_index = thread_args->index;
17780  conn->request_info.user_data = ctx->user_data;
17781  /* Allocate a mutex for this connection to allow communication both
17782  * within the request handler and from elsewhere in the application
17783  */
17784  if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) {
17785  mg_free(conn->buf);
17786  mg_cry_internal(fc(ctx), "%s", "Cannot create mutex");
17787  return NULL;
17788  }
17789 
17790 #if defined(USE_SERVER_STATS)
17791  conn->conn_state = 1; /* not consumed */
17792 #endif
17793 
17794 #if defined(ALTERNATIVE_QUEUE)
17795  while ((ctx->stop_flag == 0)
17796  && consume_socket(ctx, &conn->client, conn->thread_index)) {
17797 #else
17798  /* Call consume_socket() even when ctx->stop_flag > 0, to let it
17799  * signal sq_empty condvar to wake up the master waiting in
17800  * produce_socket() */
17801  while (consume_socket(ctx, &conn->client, conn->thread_index)) {
17802 #endif
17803 
17804  conn->conn_birth_time = time(NULL);
17805 
17806 /* Fill in IP, port info early so even if SSL setup below fails,
17807  * error handler would have the corresponding info.
17808  * Thanks to Johannes Winkelmann for the patch.
17809  */
17810 #if defined(USE_IPV6)
17811  if (conn->client.rsa.sa.sa_family == AF_INET6) {
17812  conn->request_info.remote_port =
17813  ntohs(conn->client.rsa.sin6.sin6_port);
17814  } else
17815 #endif
17816  {
17817  conn->request_info.remote_port =
17818  ntohs(conn->client.rsa.sin.sin_port);
17819  }
17820 
17821  sockaddr_to_string(conn->request_info.remote_addr,
17822  sizeof(conn->request_info.remote_addr),
17823  &conn->client.rsa);
17824 
17825  DEBUG_TRACE("Start processing connection from %s",
17826  conn->request_info.remote_addr);
17827 
17828  conn->request_info.is_ssl = conn->client.is_ssl;
17829 
17830  if (conn->client.is_ssl) {
17831 #if !defined(NO_SSL)
17832  /* HTTPS connection */
17833  if (sslize(conn,
17834  conn->dom_ctx->ssl_ctx,
17835  SSL_accept,
17836  &(conn->phys_ctx->stop_flag),
17837  NULL)) {
17838  /* conn->dom_ctx is set in get_request */
17839 
17840  /* Get SSL client certificate information (if set) */
17841  ssl_get_client_cert_info(conn);
17842 
17843  /* process HTTPS connection */
17844  process_new_connection(conn);
17845 
17846  /* Free client certificate info */
17847  if (conn->request_info.client_cert) {
17848  mg_free((void *)(conn->request_info.client_cert->subject));
17849  mg_free((void *)(conn->request_info.client_cert->issuer));
17850  mg_free((void *)(conn->request_info.client_cert->serial));
17851  mg_free((void *)(conn->request_info.client_cert->finger));
17852  /* Free certificate memory */
17853  X509_free(
17854  (X509 *)conn->request_info.client_cert->peer_cert);
17855  conn->request_info.client_cert->peer_cert = 0;
17856  conn->request_info.client_cert->subject = 0;
17857  conn->request_info.client_cert->issuer = 0;
17858  conn->request_info.client_cert->serial = 0;
17859  conn->request_info.client_cert->finger = 0;
17860  mg_free(conn->request_info.client_cert);
17861  conn->request_info.client_cert = 0;
17862  }
17863  } else {
17864  /* make sure the connection is cleaned up on SSL failure */
17865  close_connection(conn);
17866  }
17867 #endif
17868  } else {
17869  /* process HTTP connection */
17870  process_new_connection(conn);
17871  }
17872 
17873  DEBUG_TRACE("%s", "Connection closed");
17874  }
17875 
17876 
17877  pthread_setspecific(sTlsKey, NULL);
17878 #if defined(_WIN32)
17879  CloseHandle(tls.pthread_cond_helper_mutex);
17880 #endif
17881  pthread_mutex_destroy(&conn->mutex);
17882 
17883  /* Free the request buffer. */
17884  conn->buf_size = 0;
17885  mg_free(conn->buf);
17886  conn->buf = NULL;
17887 
17888 #if defined(USE_SERVER_STATS)
17889  conn->conn_state = 9; /* done */
17890 #endif
17891 
17892  DEBUG_TRACE("%s", "exiting");
17893  return NULL;
17894 }
17895 
17896 
17897 /* Threads have different return types on Windows and Unix. */
17898 #if defined(_WIN32)
17899 static unsigned __stdcall worker_thread(void *thread_func_param)
17900 {
17901  struct worker_thread_args *pwta =
17902  (struct worker_thread_args *)thread_func_param;
17903  worker_thread_run(pwta);
17904  mg_free(thread_func_param);
17905  return 0;
17906 }
17907 #else
17908 static void *
17909 worker_thread(void *thread_func_param)
17910 {
17911  struct worker_thread_args *pwta =
17912  (struct worker_thread_args *)thread_func_param;
17913  struct sigaction sa;
17914 
17915  /* Ignore SIGPIPE */
17916  memset(&sa, 0, sizeof(sa));
17917  sa.sa_handler = SIG_IGN;
17918  sigaction(SIGPIPE, &sa, NULL);
17919 
17920  worker_thread_run(pwta);
17921  mg_free(thread_func_param);
17922  return NULL;
17923 }
17924 #endif /* _WIN32 */
17925 
17926 
17927 /* This is an internal function, thus all arguments are expected to be
17928  * valid - a NULL check is not required. */
17929 static void
17930 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
17931 {
17932  struct socket so;
17933  char src_addr[IP_ADDR_STR_LEN];
17934  socklen_t len = sizeof(so.rsa);
17935  int on = 1;
17936 
17937  if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
17938  == INVALID_SOCKET) {
17939  } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
17940  sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
17941  mg_cry_internal(fc(ctx),
17942  "%s: %s is not allowed to connect",
17943  __func__,
17944  src_addr);
17945  closesocket(so.sock);
17946  } else {
17947  /* Put so socket structure into the queue */
17948  DEBUG_TRACE("Accepted socket %d", (int)so.sock);
17949  set_close_on_exec(so.sock, fc(ctx));
17950  so.is_ssl = listener->is_ssl;
17951  so.ssl_redir = listener->ssl_redir;
17952  if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
17953  mg_cry_internal(fc(ctx),
17954  "%s: getsockname() failed: %s",
17955  __func__,
17956  strerror(ERRNO));
17957  }
17958 
17959  /* Set TCP keep-alive. This is needed because if HTTP-level
17960  * keep-alive
17961  * is enabled, and client resets the connection, server won't get
17962  * TCP FIN or RST and will keep the connection open forever. With
17963  * TCP keep-alive, next keep-alive handshake will figure out that
17964  * the client is down and will close the server end.
17965  * Thanks to Igor Klopov who suggested the patch. */
17966  if (setsockopt(so.sock,
17967  SOL_SOCKET,
17968  SO_KEEPALIVE,
17969  (SOCK_OPT_TYPE)&on,
17970  sizeof(on))
17971  != 0) {
17972  mg_cry_internal(
17973  fc(ctx),
17974  "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
17975  __func__,
17976  strerror(ERRNO));
17977  }
17978 
17979  /* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
17980  * to effectively fill up the underlying IP packet payload and
17981  * reduce the overhead of sending lots of small buffers. However
17982  * this hurts the server's throughput (ie. operations per second)
17983  * when HTTP 1.1 persistent connections are used and the responses
17984  * are relatively small (eg. less than 1400 bytes).
17985  */
17986  if ((ctx->dd.config[CONFIG_TCP_NODELAY] != NULL)
17987  && (!strcmp(ctx->dd.config[CONFIG_TCP_NODELAY], "1"))) {
17988  if (set_tcp_nodelay(so.sock, 1) != 0) {
17989  mg_cry_internal(
17990  fc(ctx),
17991  "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
17992  __func__,
17993  strerror(ERRNO));
17994  }
17995  }
17996 
17997  /* We are using non-blocking sockets. Thus, the
17998  * set_sock_timeout(so.sock, timeout);
17999  * call is no longer required. */
18000 
18001  /* The "non blocking" property should already be
18002  * inherited from the parent socket. Set it for
18003  * non-compliant socket implementations. */
18004  set_non_blocking_mode(so.sock);
18005 
18006  so.in_use = 0;
18007  produce_socket(ctx, &so);
18008  }
18009 }
18010 
18011 
18012 static void
18013 master_thread_run(void *thread_func_param)
18014 {
18015  struct mg_context *ctx = (struct mg_context *)thread_func_param;
18016  struct mg_workerTLS tls;
18017  struct pollfd *pfd;
18018  unsigned int i;
18019  unsigned int workerthreadcount;
18020 
18021  if (!ctx) {
18022  return;
18023  }
18024 
18025  mg_set_thread_name("master");
18026 
18027 /* Increase priority of the master thread */
18028 #if defined(_WIN32)
18029  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
18030 #elif defined(USE_MASTER_THREAD_PRIORITY)
18031  int min_prio = sched_get_priority_min(SCHED_RR);
18032  int max_prio = sched_get_priority_max(SCHED_RR);
18033  if ((min_prio >= 0) && (max_prio >= 0)
18034  && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
18035  && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
18036  struct sched_param sched_param = {0};
18037  sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
18038  pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
18039  }
18040 #endif
18041 
18042 /* Initialize thread local storage */
18043 #if defined(_WIN32)
18044  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
18045 #endif
18046  tls.is_master = 1;
18047  pthread_setspecific(sTlsKey, &tls);
18048 
18049  if (ctx->callbacks.init_thread) {
18050  /* Callback for the master thread (type 0) */
18051  ctx->callbacks.init_thread(ctx, 0);
18052  }
18053 
18054  /* Server starts *now* */
18055  ctx->start_time = time(NULL);
18056 
18057  /* Start the server */
18058  pfd = ctx->listening_socket_fds;
18059  while (ctx->stop_flag == 0) {
18060  for (i = 0; i < ctx->num_listening_sockets; i++) {
18061  pfd[i].fd = ctx->listening_sockets[i].sock;
18062  pfd[i].events = POLLIN;
18063  }
18064 
18065  if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
18066  for (i = 0; i < ctx->num_listening_sockets; i++) {
18067  /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
18068  * successful poll, and POLLIN is defined as
18069  * (POLLRDNORM | POLLRDBAND)
18070  * Therefore, we're checking pfd[i].revents & POLLIN, not
18071  * pfd[i].revents == POLLIN. */
18072  if ((ctx->stop_flag == 0) && (pfd[i].revents & POLLIN)) {
18073  accept_new_connection(&ctx->listening_sockets[i], ctx);
18074  }
18075  }
18076  }
18077  }
18078 
18079  /* Here stop_flag is 1 - Initiate shutdown. */
18080  DEBUG_TRACE("%s", "stopping workers");
18081 
18082  /* Stop signal received: somebody called mg_stop. Quit. */
18083  close_all_listening_sockets(ctx);
18084 
18085  /* Wakeup workers that are waiting for connections to handle. */
18086  (void)pthread_mutex_lock(&ctx->thread_mutex);
18087 #if defined(ALTERNATIVE_QUEUE)
18088  for (i = 0; i < ctx->cfg_worker_threads; i++) {
18089  event_signal(ctx->client_wait_events[i]);
18090 
18091  /* Since we know all sockets, we can shutdown the connections. */
18092  if (ctx->client_socks[i].in_use) {
18093  shutdown(ctx->client_socks[i].sock, SHUTDOWN_BOTH);
18094  }
18095  }
18096 #else
18097  pthread_cond_broadcast(&ctx->sq_full);
18098 #endif
18099  (void)pthread_mutex_unlock(&ctx->thread_mutex);
18100 
18101  /* Join all worker threads to avoid leaking threads. */
18102  workerthreadcount = ctx->cfg_worker_threads;
18103  for (i = 0; i < workerthreadcount; i++) {
18104  if (ctx->worker_threadids[i] != 0) {
18105  mg_join_thread(ctx->worker_threadids[i]);
18106  }
18107  }
18108 
18109 #if defined(USE_LUA)
18110  /* Free Lua state of lua background task */
18111  if (ctx->lua_background_state) {
18112  lua_State *lstate = (lua_State *)ctx->lua_background_state;
18113  lua_getglobal(lstate, LUABACKGROUNDPARAMS);
18114  if (lua_istable(lstate, -1)) {
18115  reg_boolean(lstate, "shutdown", 1);
18116  lua_pop(lstate, 1);
18117  mg_sleep(2);
18118  }
18119  lua_close(lstate);
18120  ctx->lua_background_state = 0;
18121  }
18122 #endif
18123 
18124  DEBUG_TRACE("%s", "exiting");
18125 
18126 #if defined(_WIN32)
18127  CloseHandle(tls.pthread_cond_helper_mutex);
18128 #endif
18129  pthread_setspecific(sTlsKey, NULL);
18130 
18131  /* Signal mg_stop() that we're done.
18132  * WARNING: This must be the very last thing this
18133  * thread does, as ctx becomes invalid after this line. */
18134  ctx->stop_flag = 2;
18135 }
18136 
18137 
18138 /* Threads have different return types on Windows and Unix. */
18139 #if defined(_WIN32)
18140 static unsigned __stdcall master_thread(void *thread_func_param)
18141 {
18142  master_thread_run(thread_func_param);
18143  return 0;
18144 }
18145 #else
18146 static void *
18147 master_thread(void *thread_func_param)
18148 {
18149  struct sigaction sa;
18150 
18151  /* Ignore SIGPIPE */
18152  memset(&sa, 0, sizeof(sa));
18153  sa.sa_handler = SIG_IGN;
18154  sigaction(SIGPIPE, &sa, NULL);
18155 
18156  master_thread_run(thread_func_param);
18157  return NULL;
18158 }
18159 #endif /* _WIN32 */
18160 
18161 
18162 static void
18163 free_context(struct mg_context *ctx)
18164 {
18165  int i;
18166  struct mg_handler_info *tmp_rh;
18167 
18168  if (ctx == NULL) {
18169  return;
18170  }
18171 
18172  if (ctx->callbacks.exit_context) {
18173  ctx->callbacks.exit_context(ctx);
18174  }
18175 
18176  /* All threads exited, no sync is needed. Destroy thread mutex and
18177  * condvars
18178  */
18179  (void)pthread_mutex_destroy(&ctx->thread_mutex);
18180 #if defined(ALTERNATIVE_QUEUE)
18181  mg_free(ctx->client_socks);
18182  for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
18183  event_destroy(ctx->client_wait_events[i]);
18184  }
18185  mg_free(ctx->client_wait_events);
18186 #else
18187  (void)pthread_cond_destroy(&ctx->sq_empty);
18188  (void)pthread_cond_destroy(&ctx->sq_full);
18189 #endif
18190 
18191  /* Destroy other context global data structures mutex */
18192  (void)pthread_mutex_destroy(&ctx->nonce_mutex);
18193 
18194 #if defined(USE_TIMERS)
18195  timers_exit(ctx);
18196 #endif
18197 
18198  /* Deallocate config parameters */
18199  for (i = 0; i < NUM_OPTIONS; i++) {
18200  if (ctx->dd.config[i] != NULL) {
18201 #if defined(_MSC_VER)
18202 #pragma warning(suppress : 6001)
18203 #endif
18204  mg_free(ctx->dd.config[i]);
18205  }
18206  }
18207 
18208  /* Deallocate request handlers */
18209  while (ctx->dd.handlers) {
18210  tmp_rh = ctx->dd.handlers;
18211  ctx->dd.handlers = tmp_rh->next;
18212  if (tmp_rh->handler_type == REQUEST_HANDLER) {
18213  pthread_cond_destroy(&tmp_rh->refcount_cond);
18214  pthread_mutex_destroy(&tmp_rh->refcount_mutex);
18215  }
18216  mg_free(tmp_rh->uri);
18217  mg_free(tmp_rh);
18218  }
18219 
18220 #if !defined(NO_SSL)
18221  /* Deallocate SSL context */
18222  if (ctx->dd.ssl_ctx != NULL) {
18223  void *ssl_ctx = (void *)ctx->dd.ssl_ctx;
18224  int callback_ret =
18225  (ctx->callbacks.external_ssl_ctx == NULL)
18226  ? 0
18227  : (ctx->callbacks.external_ssl_ctx(&ssl_ctx, ctx->user_data));
18228 
18229  if (callback_ret == 0) {
18230  SSL_CTX_free(ctx->dd.ssl_ctx);
18231  }
18232  /* else: ignore error and ommit SSL_CTX_free in case
18233  * callback_ret is 1 */
18234  }
18235 #endif /* !NO_SSL */
18236 
18237  /* Deallocate worker thread ID array */
18238  if (ctx->worker_threadids != NULL) {
18239  mg_free(ctx->worker_threadids);
18240  }
18241 
18242  /* Deallocate worker thread ID array */
18243  if (ctx->worker_connections != NULL) {
18244  mg_free(ctx->worker_connections);
18245  }
18246 
18247  /* deallocate system name string */
18248  mg_free(ctx->systemName);
18249 
18250  /* Deallocate context itself */
18251  mg_free(ctx);
18252 }
18253 
18254 
18255 void
18256 mg_stop(struct mg_context *ctx)
18257 {
18258  pthread_t mt;
18259  if (!ctx) {
18260  return;
18261  }
18262 
18263  /* We don't use a lock here. Calling mg_stop with the same ctx from
18264  * two threads is not allowed. */
18265  mt = ctx->masterthreadid;
18266  if (mt == 0) {
18267  return;
18268  }
18269 
18270  ctx->masterthreadid = 0;
18271 
18272  /* Set stop flag, so all threads know they have to exit. */
18273  ctx->stop_flag = 1;
18274 
18275  /* Wait until everything has stopped. */
18276  while (ctx->stop_flag != 2) {
18277  (void)mg_sleep(10);
18278  }
18279 
18280  mg_join_thread(mt);
18281  free_context(ctx);
18282 
18283 #if defined(_WIN32)
18284  (void)WSACleanup();
18285 #endif /* _WIN32 */
18286 }
18287 
18288 
18289 static void
18290 get_system_name(char **sysName)
18291 {
18292 #if defined(_WIN32)
18293 #if !defined(__SYMBIAN32__)
18294 #if defined(_WIN32_WCE)
18295  *sysName = mg_strdup("WinCE");
18296 #else
18297  char name[128];
18298  DWORD dwVersion = 0;
18299  DWORD dwMajorVersion = 0;
18300  DWORD dwMinorVersion = 0;
18301  DWORD dwBuild = 0;
18302  BOOL wowRet, isWoW = FALSE;
18303 
18304 #if defined(_MSC_VER)
18305 #pragma warning(push)
18306 /* GetVersion was declared deprecated */
18307 #pragma warning(disable : 4996)
18308 #endif
18309  dwVersion = GetVersion();
18310 #if defined(_MSC_VER)
18311 #pragma warning(pop)
18312 #endif
18313 
18314  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
18315  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
18316  dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
18317  (void)dwBuild;
18318 
18319  wowRet = IsWow64Process(GetCurrentProcess(), &isWoW);
18320 
18321  sprintf(name,
18322  "Windows %u.%u%s",
18323  (unsigned)dwMajorVersion,
18324  (unsigned)dwMinorVersion,
18325  (wowRet ? (isWoW ? " (WoW64)" : "") : " (?)"));
18326 
18327  *sysName = mg_strdup(name);
18328 #endif
18329 #else
18330  *sysName = mg_strdup("Symbian");
18331 #endif
18332 #else
18333  struct utsname name;
18334  memset(&name, 0, sizeof(name));
18335  uname(&name);
18336  *sysName = mg_strdup(name.sysname);
18337 #endif
18338 }
18339 
18340 
18341 struct mg_context *
18342 mg_start(const struct mg_callbacks *callbacks,
18343  void *user_data,
18344  const char **options)
18345 {
18346  struct mg_context *ctx;
18347  const char *name, *value, *default_value;
18348  int idx, ok, workerthreadcount;
18349  unsigned int i;
18350  int itmp;
18351  void (*exit_callback)(const struct mg_context *ctx) = 0;
18352 
18353  struct mg_workerTLS tls;
18354 
18355 #if defined(_WIN32)
18356  WSADATA data;
18357  WSAStartup(MAKEWORD(2, 2), &data);
18358 #endif /* _WIN32 */
18359 
18360  /* Allocate context and initialize reasonable general case defaults. */
18361  if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
18362  return NULL;
18363  }
18364 
18365  /* Random number generator will initialize at the first call */
18366  ctx->dd.auth_nonce_mask =
18367  (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
18368 
18369  if (mg_init_library_called == 0) {
18370  /* Legacy INIT, if mg_start is called without mg_init_library.
18371  * Note: This may cause a memory leak */
18372  const char *ports_option =
18373  config_options[LISTENING_PORTS].default_value;
18374 
18375  if (options) {
18376  const char **run_options = options;
18377  const char *optname = config_options[LISTENING_PORTS].name;
18378 
18379  /* Try to find the "listening_ports" option */
18380  while (*run_options) {
18381  if (!strcmp(*run_options, optname)) {
18382  ports_option = run_options[1];
18383  }
18384  run_options += 2;
18385  }
18386  }
18387 
18388  if (is_ssl_port_used(ports_option)) {
18389  /* Initialize with SSL support */
18390  mg_init_library(MG_FEATURES_TLS);
18391  } else {
18392  /* Initialize without SSL support */
18393  mg_init_library(MG_FEATURES_DEFAULT);
18394  }
18395  }
18396 
18397  tls.is_master = -1;
18398  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
18399 #if defined(_WIN32)
18400  tls.pthread_cond_helper_mutex = NULL;
18401 #endif
18402  pthread_setspecific(sTlsKey, &tls);
18403 
18404  ok = (0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr));
18405 #if !defined(ALTERNATIVE_QUEUE)
18406  ok &= (0 == pthread_cond_init(&ctx->sq_empty, NULL));
18407  ok &= (0 == pthread_cond_init(&ctx->sq_full, NULL));
18408 #endif
18409  ok &= (0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr));
18410  if (!ok) {
18411  /* Fatal error - abort start. However, this situation should never
18412  * occur in practice. */
18413  mg_cry_internal(fc(ctx),
18414  "%s",
18415  "Cannot initialize thread synchronization objects");
18416  mg_free(ctx);
18417  pthread_setspecific(sTlsKey, NULL);
18418  return NULL;
18419  }
18420 
18421  if (callbacks) {
18422  ctx->callbacks = *callbacks;
18423  exit_callback = callbacks->exit_context;
18424  ctx->callbacks.exit_context = 0;
18425  }
18426  ctx->user_data = user_data;
18427  ctx->dd.handlers = NULL;
18428  ctx->dd.next = NULL;
18429 
18430 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
18431  ctx->dd.shared_lua_websockets = NULL;
18432 #endif
18433 
18434  /* Store options */
18435  while (options && (name = *options++) != NULL) {
18436  if ((idx = get_option_index(name)) == -1) {
18437  mg_cry_internal(fc(ctx), "Invalid option: %s", name);
18438  free_context(ctx);
18439  pthread_setspecific(sTlsKey, NULL);
18440  return NULL;
18441  } else if ((value = *options++) == NULL) {
18442  mg_cry_internal(fc(ctx), "%s: option value cannot be NULL", name);
18443  free_context(ctx);
18444  pthread_setspecific(sTlsKey, NULL);
18445  return NULL;
18446  }
18447  if (ctx->dd.config[idx] != NULL) {
18448  mg_cry_internal(fc(ctx), "warning: %s: duplicate option", name);
18449  mg_free(ctx->dd.config[idx]);
18450  }
18451  ctx->dd.config[idx] = mg_strdup_ctx(value, ctx);
18452  DEBUG_TRACE("[%s] -> [%s]", name, value);
18453  }
18454 
18455  /* Set default value if needed */
18456  for (i = 0; config_options[i].name != NULL; i++) {
18457  default_value = config_options[i].default_value;
18458  if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
18459  ctx->dd.config[i] = mg_strdup_ctx(default_value, ctx);
18460  }
18461  }
18462 
18463  /* Request size option */
18464  itmp = atoi(ctx->dd.config[MAX_REQUEST_SIZE]);
18465  if (itmp < 1024) {
18466  mg_cry_internal(fc(ctx), "%s", "max_request_size too small");
18467  free_context(ctx);
18468  pthread_setspecific(sTlsKey, NULL);
18469  return NULL;
18470  }
18471  ctx->max_request_size = (unsigned)itmp;
18472 
18473  /* Worker thread count option */
18474  workerthreadcount = atoi(ctx->dd.config[NUM_THREADS]);
18475 
18476  if (workerthreadcount > MAX_WORKER_THREADS) {
18477  mg_cry_internal(fc(ctx), "%s", "Too many worker threads");
18478  free_context(ctx);
18479  pthread_setspecific(sTlsKey, NULL);
18480  return NULL;
18481  }
18482 
18483  if (workerthreadcount <= 0) {
18484  mg_cry_internal(fc(ctx), "%s", "Invalid number of worker threads");
18485  free_context(ctx);
18486  pthread_setspecific(sTlsKey, NULL);
18487  return NULL;
18488  }
18489 
18490 /* Document root */
18491 #if defined(NO_FILES)
18492  if (ctx->dd.config[DOCUMENT_ROOT] != NULL) {
18493  mg_cry_internal(fc(ctx), "%s", "Document root must not be set");
18494  free_context(ctx);
18495  pthread_setspecific(sTlsKey, NULL);
18496  return NULL;
18497  }
18498 #endif
18499 
18500  get_system_name(&ctx->systemName);
18501 
18502 #if defined(USE_LUA)
18503  /* If a Lua background script has been configured, start it. */
18504  if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) {
18505  char ebuf[256];
18506  struct vec opt_vec;
18507  struct vec eq_vec;
18508  const char *sparams;
18509  lua_State *state = mg_prepare_lua_context_script(
18510  ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf));
18511  if (!state) {
18512  mg_cry_internal(fc(ctx), "lua_background_script error: %s", ebuf);
18513  free_context(ctx);
18514  pthread_setspecific(sTlsKey, NULL);
18515  return NULL;
18516  }
18517  ctx->lua_background_state = (void *)state;
18518 
18519  lua_newtable(state);
18520  reg_boolean(state, "shutdown", 0);
18521 
18522  sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS];
18523 
18524  while ((sparams = next_option(sparams, &opt_vec, &eq_vec)) != NULL) {
18525  reg_llstring(
18526  state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len);
18527  if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0)
18528  break;
18529  }
18530  lua_setglobal(state, LUABACKGROUNDPARAMS);
18531 
18532  } else {
18533  ctx->lua_background_state = 0;
18534  }
18535 #endif
18536 
18537  /* NOTE(lsm): order is important here. SSL certificates must
18538  * be initialized before listening ports. UID must be set last. */
18539  if (!set_gpass_option(ctx, NULL) ||
18540 #if !defined(NO_SSL)
18541  !init_ssl_ctx(ctx, NULL) ||
18542 #endif
18543  !set_ports_option(ctx) ||
18544 #if !defined(_WIN32)
18545  !set_uid_option(ctx) ||
18546 #endif
18547  !set_acl_option(ctx)) {
18548  free_context(ctx);
18549  pthread_setspecific(sTlsKey, NULL);
18550  return NULL;
18551  }
18552 
18553  ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
18554  ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(ctx->cfg_worker_threads,
18555  sizeof(pthread_t),
18556  ctx);
18557 
18558  if (ctx->worker_threadids == NULL) {
18559  mg_cry_internal(fc(ctx),
18560  "%s",
18561  "Not enough memory for worker thread ID array");
18562  free_context(ctx);
18563  pthread_setspecific(sTlsKey, NULL);
18564  return NULL;
18565  }
18566  ctx->worker_connections =
18567  (struct mg_connection *)mg_calloc_ctx(ctx->cfg_worker_threads,
18568  sizeof(struct mg_connection),
18569  ctx);
18570  if (ctx->worker_connections == NULL) {
18571  mg_cry_internal(fc(ctx),
18572  "%s",
18573  "Not enough memory for worker thread connection array");
18574  free_context(ctx);
18575  pthread_setspecific(sTlsKey, NULL);
18576  return NULL;
18577  }
18578 
18579 
18580 #if defined(ALTERNATIVE_QUEUE)
18581  ctx->client_wait_events =
18582  (void **)mg_calloc_ctx(sizeof(ctx->client_wait_events[0]),
18583  ctx->cfg_worker_threads,
18584  ctx);
18585  if (ctx->client_wait_events == NULL) {
18586  mg_cry_internal(fc(ctx),
18587  "%s",
18588  "Not enough memory for worker event array");
18589  mg_free(ctx->worker_threadids);
18590  free_context(ctx);
18591  pthread_setspecific(sTlsKey, NULL);
18592  return NULL;
18593  }
18594 
18595  ctx->client_socks =
18596  (struct socket *)mg_calloc_ctx(sizeof(ctx->client_socks[0]),
18597  ctx->cfg_worker_threads,
18598  ctx);
18599  if (ctx->client_socks == NULL) {
18600  mg_cry_internal(fc(ctx),
18601  "%s",
18602  "Not enough memory for worker socket array");
18603  mg_free(ctx->client_wait_events);
18604  mg_free(ctx->worker_threadids);
18605  free_context(ctx);
18606  pthread_setspecific(sTlsKey, NULL);
18607  return NULL;
18608  }
18609 
18610  for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
18611  ctx->client_wait_events[i] = event_create();
18612  if (ctx->client_wait_events[i] == 0) {
18613  mg_cry_internal(fc(ctx), "Error creating worker event %i", i);
18614  while (i > 0) {
18615  i--;
18616  event_destroy(ctx->client_wait_events[i]);
18617  }
18618  mg_free(ctx->client_socks);
18619  mg_free(ctx->client_wait_events);
18620  mg_free(ctx->worker_threadids);
18621  free_context(ctx);
18622  pthread_setspecific(sTlsKey, NULL);
18623  return NULL;
18624  }
18625  }
18626 #endif
18627 
18628 
18629 #if defined(USE_TIMERS)
18630  if (timers_init(ctx) != 0) {
18631  mg_cry_internal(fc(ctx), "%s", "Error creating timers");
18632  free_context(ctx);
18633  pthread_setspecific(sTlsKey, NULL);
18634  return NULL;
18635  }
18636 #endif
18637 
18638  /* Context has been created - init user libraries */
18639  if (ctx->callbacks.init_context) {
18640  ctx->callbacks.init_context(ctx);
18641  }
18642  ctx->callbacks.exit_context = exit_callback;
18643  ctx->context_type = CONTEXT_SERVER; /* server context */
18644 
18645  /* Start master (listening) thread */
18646  mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
18647 
18648  /* Start worker threads */
18649  for (i = 0; i < ctx->cfg_worker_threads; i++) {
18650  struct worker_thread_args *wta = (struct worker_thread_args *)
18651  mg_malloc_ctx(sizeof(struct worker_thread_args), ctx);
18652  if (wta) {
18653  wta->ctx = ctx;
18654  wta->index = (int)i;
18655  }
18656 
18657  if ((wta == NULL)
18658  || (mg_start_thread_with_id(worker_thread,
18659  wta,
18660  &ctx->worker_threadids[i])
18661  != 0)) {
18662 
18663  /* thread was not created */
18664  if (wta != NULL) {
18665  mg_free(wta);
18666  }
18667 
18668  if (i > 0) {
18669  mg_cry_internal(fc(ctx),
18670  "Cannot start worker thread %i: error %ld",
18671  i + 1,
18672  (long)ERRNO);
18673  } else {
18674  mg_cry_internal(fc(ctx),
18675  "Cannot create threads: error %ld",
18676  (long)ERRNO);
18677  free_context(ctx);
18678  pthread_setspecific(sTlsKey, NULL);
18679  return NULL;
18680  }
18681  break;
18682  }
18683  }
18684 
18685  pthread_setspecific(sTlsKey, NULL);
18686  return ctx;
18687 }
18688 
18689 
18690 #if defined(MG_EXPERIMENTAL_INTERFACES)
18691 /* Add an additional domain to an already running web server. */
18692 int
18693 mg_start_domain(struct mg_context *ctx, const char **options)
18694 {
18695  const char *name;
18696  const char *value;
18697  const char *default_value;
18698  struct mg_domain_context *new_dom;
18699  struct mg_domain_context *dom;
18700  int idx, i;
18701 
18702  if ((ctx == NULL) || (ctx->stop_flag != 0) || (options == NULL)) {
18703  return -1;
18704  }
18705 
18706  new_dom = (struct mg_domain_context *)
18707  mg_calloc_ctx(1, sizeof(struct mg_domain_context), ctx);
18708 
18709  if (!new_dom) {
18710  /* Out of memory */
18711  return -6;
18712  }
18713 
18714  /* Store options - TODO: unite duplicate code */
18715  while (options && (name = *options++) != NULL) {
18716  if ((idx = get_option_index(name)) == -1) {
18717  mg_cry_internal(fc(ctx), "Invalid option: %s", name);
18718  mg_free(new_dom);
18719  return -2;
18720  } else if ((value = *options++) == NULL) {
18721  mg_cry_internal(fc(ctx), "%s: option value cannot be NULL", name);
18722  mg_free(new_dom);
18723  return -2;
18724  }
18725  if (new_dom->config[idx] != NULL) {
18726  mg_cry_internal(fc(ctx), "warning: %s: duplicate option", name);
18727  mg_free(new_dom->config[idx]);
18728  }
18729  new_dom->config[idx] = mg_strdup_ctx(value, ctx);
18730  DEBUG_TRACE("[%s] -> [%s]", name, value);
18731  }
18732 
18733  /* Authentication domain is mandatory */
18734  /* TODO: Maybe use a new option hostname? */
18735  if (!new_dom->config[AUTHENTICATION_DOMAIN]) {
18736  mg_cry_internal(fc(ctx), "%s", "authentication domain required");
18737  mg_free(new_dom);
18738  return -4;
18739  }
18740 
18741  /* Set default value if needed. Take the config value from
18742  * ctx as a default value. */
18743  for (i = 0; config_options[i].name != NULL; i++) {
18744  default_value = ctx->dd.config[i];
18745  if ((new_dom->config[i] == NULL) && (default_value != NULL)) {
18746  new_dom->config[i] = mg_strdup_ctx(default_value, ctx);
18747  }
18748  }
18749 
18750  new_dom->handlers = NULL;
18751  new_dom->next = NULL;
18752  new_dom->nonce_count = 0;
18753  new_dom->auth_nonce_mask =
18754  (uint64_t)get_random() ^ ((uint64_t)get_random() << 31);
18755 
18756 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
18757  new_dom->shared_lua_websockets = NULL;
18758 #endif
18759 
18760  if (!init_ssl_ctx(ctx, new_dom)) {
18761  /* Init SSL failed */
18762  mg_free(new_dom);
18763  return -3;
18764  }
18765 
18766  /* Add element to linked list. */
18767  mg_lock_context(ctx);
18768 
18769  idx = 0;
18770  dom = &(ctx->dd);
18771  for (;;) {
18772  if (!strcasecmp(new_dom->config[AUTHENTICATION_DOMAIN],
18773  dom->config[AUTHENTICATION_DOMAIN])) {
18774  /* Domain collision */
18775  mg_cry_internal(fc(ctx),
18776  "domain %s already in use",
18777  new_dom->config[AUTHENTICATION_DOMAIN]);
18778  mg_free(new_dom);
18779  return -5;
18780  }
18781 
18782  /* Count number of domains */
18783  idx++;
18784 
18785  if (dom->next == NULL) {
18786  dom->next = new_dom;
18787  break;
18788  }
18789  dom = dom->next;
18790  }
18791 
18792  mg_unlock_context(ctx);
18793 
18794  /* Return domain number */
18795  return idx;
18796 }
18797 #endif
18798 
18799 
18800 /* Feature check API function */
18801 unsigned
18802 mg_check_feature(unsigned feature)
18803 {
18804  static const unsigned feature_set = 0
18805 /* Set bits for available features according to API documentation.
18806  * This bit mask is created at compile time, according to the active
18807  * preprocessor defines. It is a single const value at runtime. */
18808 #if !defined(NO_FILES)
18809  | MG_FEATURES_FILES
18810 #endif
18811 #if !defined(NO_SSL)
18812  | MG_FEATURES_SSL
18813 #endif
18814 #if !defined(NO_CGI)
18815  | MG_FEATURES_CGI
18816 #endif
18817 #if defined(USE_IPV6)
18818  | MG_FEATURES_IPV6
18819 #endif
18820 #if defined(USE_WEBSOCKET)
18821  | MG_FEATURES_WEBSOCKET
18822 #endif
18823 #if defined(USE_LUA)
18824  | MG_FEATURES_LUA
18825 #endif
18826 #if defined(USE_DUKTAPE)
18827  | MG_FEATURES_SSJS
18828 #endif
18829 #if !defined(NO_CACHING)
18830  | MG_FEATURES_CACHE
18831 #endif
18832 #if defined(USE_SERVER_STATS)
18833  | MG_FEATURES_STATS
18834 #endif
18835 #if defined(USE_ZLIB)
18836  | MG_FEATURES_COMPRESSION
18837 #endif
18838 
18839 /* Set some extra bits not defined in the API documentation.
18840  * These bits may change without further notice. */
18841 #if defined(MG_LEGACY_INTERFACE)
18842  | 0x00008000u
18843 #endif
18844 #if defined(MG_EXPERIMENTAL_INTERFACES)
18845  | 0x00004000u
18846 #endif
18847 #if defined(MEMORY_DEBUGGING)
18848  | 0x00001000u
18849 #endif
18850 #if defined(USE_TIMERS)
18851  | 0x00020000u
18852 #endif
18853 #if !defined(NO_NONCE_CHECK)
18854  | 0x00040000u
18855 #endif
18856 #if !defined(NO_POPEN)
18857  | 0x00080000u
18858 #endif
18859  ;
18860  return (feature & feature_set);
18861 }
18862 
18863 
18864 /* strcat with additional NULL check to avoid clang scan-build warning. */
18865 #define strcat0(a, b) \
18866  { \
18867  if ((a != NULL) && (b != NULL)) { \
18868  strcat(a, b); \
18869  } \
18870  }
18871 
18872 
18873 /* Get system information. It can be printed or stored by the caller.
18874  * Return the size of available information. */
18875 static int
18876 mg_get_system_info_impl(char *buffer, int buflen)
18877 {
18878  char block[256];
18879  int system_info_length = 0;
18880 
18881 #if defined(_WIN32)
18882  const char *eol = "\r\n";
18883 #else
18884  const char *eol = "\n";
18885 #endif
18886 
18887  const char *eoobj = "}";
18888  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
18889 
18890  if ((buffer == NULL) || (buflen < 1)) {
18891  buflen = 0;
18892  } else {
18893  *buffer = 0;
18894  }
18895 
18896  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
18897  system_info_length += (int)strlen(block);
18898  if (system_info_length < buflen) {
18899  strcat0(buffer, block);
18900  }
18901 
18902  /* Server version */
18903  {
18904  const char *version = mg_version();
18905  mg_snprintf(NULL,
18906  NULL,
18907  block,
18908  sizeof(block),
18909  "\"version\" : \"%s\",%s",
18910  version,
18911  eol);
18912  system_info_length += (int)strlen(block);
18913  if (system_info_length < buflen) {
18914  strcat0(buffer, block);
18915  }
18916  }
18917 
18918  /* System info */
18919  {
18920 #if defined(_WIN32)
18921  DWORD dwVersion = 0;
18922  DWORD dwMajorVersion = 0;
18923  DWORD dwMinorVersion = 0;
18924  SYSTEM_INFO si;
18925 
18926  GetSystemInfo(&si);
18927 
18928 #if defined(_MSC_VER)
18929 #pragma warning(push)
18930 /* GetVersion was declared deprecated */
18931 #pragma warning(disable : 4996)
18932 #endif
18933  dwVersion = GetVersion();
18934 #if defined(_MSC_VER)
18935 #pragma warning(pop)
18936 #endif
18937 
18938  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
18939  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
18940 
18941  mg_snprintf(NULL,
18942  NULL,
18943  block,
18944  sizeof(block),
18945  "\"os\" : \"Windows %u.%u\",%s",
18946  (unsigned)dwMajorVersion,
18947  (unsigned)dwMinorVersion,
18948  eol);
18949  system_info_length += (int)strlen(block);
18950  if (system_info_length < buflen) {
18951  strcat0(buffer, block);
18952  }
18953 
18954  mg_snprintf(NULL,
18955  NULL,
18956  block,
18957  sizeof(block),
18958  "\"cpu\" : \"type %u, cores %u, mask %x\",%s",
18959  (unsigned)si.wProcessorArchitecture,
18960  (unsigned)si.dwNumberOfProcessors,
18961  (unsigned)si.dwActiveProcessorMask,
18962  eol);
18963  system_info_length += (int)strlen(block);
18964  if (system_info_length < buflen) {
18965  strcat0(buffer, block);
18966  }
18967 #else
18968  struct utsname name;
18969  memset(&name, 0, sizeof(name));
18970  uname(&name);
18971 
18972  mg_snprintf(NULL,
18973  NULL,
18974  block,
18975  sizeof(block),
18976  "\"os\" : \"%s %s (%s) - %s\",%s",
18977  name.sysname,
18978  name.version,
18979  name.release,
18980  name.machine,
18981  eol);
18982  system_info_length += (int)strlen(block);
18983  if (system_info_length < buflen) {
18984  strcat0(buffer, block);
18985  }
18986 #endif
18987  }
18988 
18989  /* Features */
18990  {
18991  mg_snprintf(NULL,
18992  NULL,
18993  block,
18994  sizeof(block),
18995  "\"features\" : %lu,%s"
18996  "\"feature_list\" : \"Server:%s%s%s%s%s%s%s%s%s\",%s",
18997  (unsigned long)mg_check_feature(0xFFFFFFFFu),
18998  eol,
18999  mg_check_feature(MG_FEATURES_FILES) ? " Files" : "",
19000  mg_check_feature(MG_FEATURES_SSL) ? " HTTPS" : "",
19001  mg_check_feature(MG_FEATURES_CGI) ? " CGI" : "",
19002  mg_check_feature(MG_FEATURES_IPV6) ? " IPv6" : "",
19003  mg_check_feature(MG_FEATURES_WEBSOCKET) ? " WebSockets"
19004  : "",
19005  mg_check_feature(MG_FEATURES_LUA) ? " Lua" : "",
19006  mg_check_feature(MG_FEATURES_SSJS) ? " JavaScript" : "",
19007  mg_check_feature(MG_FEATURES_CACHE) ? " Cache" : "",
19008  mg_check_feature(MG_FEATURES_STATS) ? " Stats" : "",
19009  eol);
19010  system_info_length += (int)strlen(block);
19011  if (system_info_length < buflen) {
19012  strcat0(buffer, block);
19013  }
19014 
19015 #if defined(USE_LUA)
19016  mg_snprintf(NULL,
19017  NULL,
19018  block,
19019  sizeof(block),
19020  "\"lua_version\" : \"%u (%s)\",%s",
19021  (unsigned)LUA_VERSION_NUM,
19022  LUA_RELEASE,
19023  eol);
19024  system_info_length += (int)strlen(block);
19025  if (system_info_length < buflen) {
19026  strcat0(buffer, block);
19027  }
19028 #endif
19029 #if defined(USE_DUKTAPE)
19030  mg_snprintf(NULL,
19031  NULL,
19032  block,
19033  sizeof(block),
19034  "\"javascript\" : \"Duktape %u.%u.%u\",%s",
19035  (unsigned)DUK_VERSION / 10000,
19036  ((unsigned)DUK_VERSION / 100) % 100,
19037  (unsigned)DUK_VERSION % 100,
19038  eol);
19039  system_info_length += (int)strlen(block);
19040  if (system_info_length < buflen) {
19041  strcat0(buffer, block);
19042  }
19043 #endif
19044  }
19045 
19046  /* Build date */
19047  {
19048 #if defined(GCC_DIAGNOSTIC)
19049 #if GCC_VERSION >= 50000
19050 #pragma GCC diagnostic push
19051 /* Disable bogus compiler warning -Wdate-time */
19052 #pragma GCC diagnostic ignored "-Wdate-time"
19053 #endif
19054 #endif
19055  mg_snprintf(NULL,
19056  NULL,
19057  block,
19058  sizeof(block),
19059  "\"build\" : \"%s\",%s",
19060  __DATE__,
19061  eol);
19062 
19063 #if defined(GCC_DIAGNOSTIC)
19064 #if GCC_VERSION >= 50000
19065 #pragma GCC diagnostic pop
19066 #endif
19067 #endif
19068 
19069  system_info_length += (int)strlen(block);
19070  if (system_info_length < buflen) {
19071  strcat0(buffer, block);
19072  }
19073  }
19074 
19075 
19076  /* Compiler information */
19077  /* http://sourceforge.net/p/predef/wiki/Compilers/ */
19078  {
19079 #if defined(_MSC_VER)
19080  mg_snprintf(NULL,
19081  NULL,
19082  block,
19083  sizeof(block),
19084  "\"compiler\" : \"MSC: %u (%u)\",%s",
19085  (unsigned)_MSC_VER,
19086  (unsigned)_MSC_FULL_VER,
19087  eol);
19088  system_info_length += (int)strlen(block);
19089  if (system_info_length < buflen) {
19090  strcat0(buffer, block);
19091  }
19092 #elif defined(__MINGW64__)
19093  mg_snprintf(NULL,
19094  NULL,
19095  block,
19096  sizeof(block),
19097  "\"compiler\" : \"MinGW64: %u.%u\",%s",
19098  (unsigned)__MINGW64_VERSION_MAJOR,
19099  (unsigned)__MINGW64_VERSION_MINOR,
19100  eol);
19101  system_info_length += (int)strlen(block);
19102  if (system_info_length < buflen) {
19103  strcat0(buffer, block);
19104  }
19105  mg_snprintf(NULL,
19106  NULL,
19107  block,
19108  sizeof(block),
19109  "\"compiler\" : \"MinGW32: %u.%u\",%s",
19110  (unsigned)__MINGW32_MAJOR_VERSION,
19111  (unsigned)__MINGW32_MINOR_VERSION,
19112  eol);
19113  system_info_length += (int)strlen(block);
19114  if (system_info_length < buflen) {
19115  strcat0(buffer, block);
19116  }
19117 #elif defined(__MINGW32__)
19118  mg_snprintf(NULL,
19119  NULL,
19120  block,
19121  sizeof(block),
19122  "\"compiler\" : \"MinGW32: %u.%u\",%s",
19123  (unsigned)__MINGW32_MAJOR_VERSION,
19124  (unsigned)__MINGW32_MINOR_VERSION,
19125  eol);
19126  system_info_length += (int)strlen(block);
19127  if (system_info_length < buflen) {
19128  strcat0(buffer, block);
19129  }
19130 #elif defined(__clang__)
19131  mg_snprintf(NULL,
19132  NULL,
19133  block,
19134  sizeof(block),
19135  "\"compiler\" : \"clang: %u.%u.%u (%s)\",%s",
19136  __clang_major__,
19137  __clang_minor__,
19138  __clang_patchlevel__,
19139  __clang_version__,
19140  eol);
19141  system_info_length += (int)strlen(block);
19142  if (system_info_length < buflen) {
19143  strcat0(buffer, block);
19144  }
19145 #elif defined(__GNUC__)
19146  mg_snprintf(NULL,
19147  NULL,
19148  block,
19149  sizeof(block),
19150  "\"compiler\" : \"gcc: %u.%u.%u\",%s",
19151  (unsigned)__GNUC__,
19152  (unsigned)__GNUC_MINOR__,
19153  (unsigned)__GNUC_PATCHLEVEL__,
19154  eol);
19155  system_info_length += (int)strlen(block);
19156  if (system_info_length < buflen) {
19157  strcat0(buffer, block);
19158  }
19159 #elif defined(__INTEL_COMPILER)
19160  mg_snprintf(NULL,
19161  NULL,
19162  block,
19163  sizeof(block),
19164  "\"compiler\" : \"Intel C/C++: %u\",%s",
19165  (unsigned)__INTEL_COMPILER,
19166  eol);
19167  system_info_length += (int)strlen(block);
19168  if (system_info_length < buflen) {
19169  strcat0(buffer, block);
19170  }
19171 #elif defined(__BORLANDC__)
19172  mg_snprintf(NULL,
19173  NULL,
19174  block,
19175  sizeof(block),
19176  "\"compiler\" : \"Borland C: 0x%x\",%s",
19177  (unsigned)__BORLANDC__,
19178  eol);
19179  system_info_length += (int)strlen(block);
19180  if (system_info_length < buflen) {
19181  strcat0(buffer, block);
19182  }
19183 #elif defined(__SUNPRO_C)
19184  mg_snprintf(NULL,
19185  NULL,
19186  block,
19187  sizeof(block),
19188  "\"compiler\" : \"Solaris: 0x%x\",%s",
19189  (unsigned)__SUNPRO_C,
19190  eol);
19191  system_info_length += (int)strlen(block);
19192  if (system_info_length < buflen) {
19193  strcat0(buffer, block);
19194  }
19195 #else
19196  mg_snprintf(NULL,
19197  NULL,
19198  block,
19199  sizeof(block),
19200  "\"compiler\" : \"other\",%s",
19201  eol);
19202  system_info_length += (int)strlen(block);
19203  if (system_info_length < buflen) {
19204  strcat0(buffer, block);
19205  }
19206 #endif
19207  }
19208 
19209  /* Determine 32/64 bit data mode.
19210  * see https://en.wikipedia.org/wiki/64-bit_computing */
19211  {
19212  mg_snprintf(NULL,
19213  NULL,
19214  block,
19215  sizeof(block),
19216  "\"data_model\" : \"int:%u/%u/%u/%u, float:%u/%u/%u, "
19217  "char:%u/%u, "
19218  "ptr:%u, size:%u, time:%u\"%s",
19219  (unsigned)sizeof(short),
19220  (unsigned)sizeof(int),
19221  (unsigned)sizeof(long),
19222  (unsigned)sizeof(long long),
19223  (unsigned)sizeof(float),
19224  (unsigned)sizeof(double),
19225  (unsigned)sizeof(long double),
19226  (unsigned)sizeof(char),
19227  (unsigned)sizeof(wchar_t),
19228  (unsigned)sizeof(void *),
19229  (unsigned)sizeof(size_t),
19230  (unsigned)sizeof(time_t),
19231  eol);
19232  system_info_length += (int)strlen(block);
19233  if (system_info_length < buflen) {
19234  strcat0(buffer, block);
19235  }
19236  }
19237 
19238  /* Terminate string */
19239  if ((buflen > 0) && buffer && buffer[0]) {
19240  if (system_info_length < buflen) {
19241  strcat0(buffer, eoobj);
19242  strcat0(buffer, eol);
19243  }
19244  }
19245  system_info_length += reserved_len;
19246 
19247  return system_info_length;
19248 }
19249 
19250 
19251 #if defined(USE_SERVER_STATS)
19252 /* Get context information. It can be printed or stored by the caller.
19253  * Return the size of available information. */
19254 static int
19255 mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
19256 
19257 {
19258  char block[256];
19259  int context_info_length = 0;
19260 
19261 #if defined(_WIN32)
19262  const char *eol = "\r\n";
19263 #else
19264  const char *eol = "\n";
19265 #endif
19266  struct mg_memory_stat *ms = get_memory_stat((struct mg_context *)ctx);
19267 
19268  const char *eoobj = "}";
19269  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
19270 
19271  if ((buffer == NULL) || (buflen < 1)) {
19272  buflen = 0;
19273  } else {
19274  *buffer = 0;
19275  }
19276 
19277  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
19278  context_info_length += (int)strlen(block);
19279  if (context_info_length < buflen) {
19280  strcat0(buffer, block);
19281  }
19282 
19283  if (ms) { /* <-- should be always true */
19284  /* Memory information */
19285  mg_snprintf(NULL,
19286  NULL,
19287  block,
19288  sizeof(block),
19289  "\"memory\" : {%s"
19290  "\"blocks\" : %i,%s"
19291  "\"used\" : %" INT64_FMT ",%s"
19292  "\"maxUsed\" : %" INT64_FMT "%s"
19293  "}%s%s",
19294  eol,
19295  ms->blockCount,
19296  eol,
19297  ms->totalMemUsed,
19298  eol,
19299  ms->maxMemUsed,
19300  eol,
19301  (ctx ? "," : ""),
19302  eol);
19303 
19304  context_info_length += (int)strlen(block);
19305  if (context_info_length + reserved_len < buflen) {
19306  strcat0(buffer, block);
19307  }
19308  }
19309 
19310  if (ctx) {
19311  /* Declare all variables at begin of the block, to comply
19312  * with old C standards. */
19313  char start_time_str[64] = {0};
19314  char now_str[64] = {0};
19315  time_t start_time = ctx->start_time;
19316  time_t now = time(NULL);
19317 
19318  /* Connections information */
19319  mg_snprintf(NULL,
19320  NULL,
19321  block,
19322  sizeof(block),
19323  "\"connections\" : {%s"
19324  "\"active\" : %i,%s"
19325  "\"maxActive\" : %i,%s"
19326  "\"total\" : %" INT64_FMT "%s"
19327  "},%s",
19328  eol,
19329  ctx->active_connections,
19330  eol,
19331  ctx->max_connections,
19332  eol,
19333  ctx->total_connections,
19334  eol,
19335  eol);
19336 
19337  context_info_length += (int)strlen(block);
19338  if (context_info_length + reserved_len < buflen) {
19339  strcat0(buffer, block);
19340  }
19341 
19342  /* Requests information */
19343  mg_snprintf(NULL,
19344  NULL,
19345  block,
19346  sizeof(block),
19347  "\"requests\" : {%s"
19348  "\"total\" : %" INT64_FMT "%s"
19349  "},%s",
19350  eol,
19351  ctx->total_requests,
19352  eol,
19353  eol);
19354 
19355  context_info_length += (int)strlen(block);
19356  if (context_info_length + reserved_len < buflen) {
19357  strcat0(buffer, block);
19358  }
19359 
19360  /* Data information */
19361  mg_snprintf(NULL,
19362  NULL,
19363  block,
19364  sizeof(block),
19365  "\"data\" : {%s"
19366  "\"read\" : %" INT64_FMT "%s,"
19367  "\"written\" : %" INT64_FMT "%s"
19368  "},%s",
19369  eol,
19370  ctx->total_data_read,
19371  eol,
19372  ctx->total_data_written,
19373  eol,
19374  eol);
19375 
19376  context_info_length += (int)strlen(block);
19377  if (context_info_length + reserved_len < buflen) {
19378  strcat0(buffer, block);
19379  }
19380 
19381  /* Execution time information */
19382  gmt_time_string(start_time_str,
19383  sizeof(start_time_str) - 1,
19384  &start_time);
19385  gmt_time_string(now_str, sizeof(now_str) - 1, &now);
19386 
19387  mg_snprintf(NULL,
19388  NULL,
19389  block,
19390  sizeof(block),
19391  "\"time\" : {%s"
19392  "\"uptime\" : %.0f,%s"
19393  "\"start\" : \"%s\",%s"
19394  "\"now\" : \"%s\"%s"
19395  "}%s",
19396  eol,
19397  difftime(now, start_time),
19398  eol,
19399  start_time_str,
19400  eol,
19401  now_str,
19402  eol,
19403  eol);
19404 
19405  context_info_length += (int)strlen(block);
19406  if (context_info_length + reserved_len < buflen) {
19407  strcat0(buffer, block);
19408  }
19409  }
19410 
19411  /* Terminate string */
19412  if ((buflen > 0) && buffer && buffer[0]) {
19413  if (context_info_length < buflen) {
19414  strcat0(buffer, eoobj);
19415  strcat0(buffer, eol);
19416  }
19417  }
19418  context_info_length += reserved_len;
19419 
19420  return context_info_length;
19421 }
19422 #endif
19423 
19424 
19425 #if defined(MG_EXPERIMENTAL_INTERFACES)
19426 /* Get connection information. It can be printed or stored by the caller.
19427  * Return the size of available information. */
19428 static int
19429 mg_get_connection_info_impl(const struct mg_context *ctx,
19430  int idx,
19431  char *buffer,
19432  int buflen)
19433 {
19434  const struct mg_connection *conn;
19435  const struct mg_request_info *ri;
19436  char block[256];
19437  int connection_info_length = 0;
19438  int state = 0;
19439  const char *state_str = "unknown";
19440 
19441 #if defined(_WIN32)
19442  const char *eol = "\r\n";
19443 #else
19444  const char *eol = "\n";
19445 #endif
19446 
19447  const char *eoobj = "}";
19448  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
19449 
19450  if ((buffer == NULL) || (buflen < 1)) {
19451  buflen = 0;
19452  } else {
19453  *buffer = 0;
19454  }
19455 
19456  if ((ctx == NULL) || (idx < 0)) {
19457  /* Parameter error */
19458  return 0;
19459  }
19460 
19461  if ((unsigned)idx >= ctx->cfg_worker_threads) {
19462  /* Out of range */
19463  return 0;
19464  }
19465 
19466  /* Take connection [idx]. This connection is not locked in
19467  * any way, so some other thread might use it. */
19468  conn = (ctx->worker_connections) + idx;
19469 
19470  /* Initialize output string */
19471  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
19472  connection_info_length += (int)strlen(block);
19473  if (connection_info_length < buflen) {
19474  strcat0(buffer, block);
19475  }
19476 
19477  /* Init variables */
19478  ri = &(conn->request_info);
19479 
19480 #if defined(USE_SERVER_STATS)
19481  state = conn->conn_state;
19482 
19483  /* State as string */
19484  switch (state) {
19485  case 0:
19486  state_str = "undefined";
19487  break;
19488  case 1:
19489  state_str = "not used";
19490  break;
19491  case 2:
19492  state_str = "init";
19493  break;
19494  case 3:
19495  state_str = "ready";
19496  break;
19497  case 4:
19498  state_str = "processing";
19499  break;
19500  case 5:
19501  state_str = "processed";
19502  break;
19503  case 6:
19504  state_str = "to close";
19505  break;
19506  case 7:
19507  state_str = "closing";
19508  break;
19509  case 8:
19510  state_str = "closed";
19511  break;
19512  case 9:
19513  state_str = "done";
19514  break;
19515  }
19516 #endif
19517 
19518  /* Connection info */
19519  if ((state >= 3) && (state < 9)) {
19520  mg_snprintf(NULL,
19521  NULL,
19522  block,
19523  sizeof(block),
19524  "\"connection\" : {%s"
19525  "\"remote\" : {%s"
19526  "\"protocol\" : \"%s\",%s"
19527  "\"addr\" : \"%s\",%s"
19528  "\"port\" : %u%s"
19529  "},%s"
19530  "\"handled_requests\" : %u%s"
19531  "},%s",
19532  eol,
19533  eol,
19534  get_proto_name(conn),
19535  eol,
19536  ri->remote_addr,
19537  eol,
19538  ri->remote_port,
19539  eol,
19540  eol,
19541  conn->handled_requests,
19542  eol,
19543  eol);
19544 
19545  connection_info_length += (int)strlen(block);
19546  if (connection_info_length + reserved_len < buflen) {
19547  strcat0(buffer, block);
19548  }
19549  }
19550 
19551  /* Request info */
19552  if ((state >= 4) && (state < 6)) {
19553  mg_snprintf(NULL,
19554  NULL,
19555  block,
19556  sizeof(block),
19557  "\"request_info\" : {%s"
19558  "\"method\" : \"%s\",%s"
19559  "\"uri\" : \"%s\",%s"
19560  "\"query\" : %s%s%s%s"
19561  "},%s",
19562  eol,
19563  ri->request_method,
19564  eol,
19565  ri->request_uri,
19566  eol,
19567  ri->query_string ? "\"" : "",
19568  ri->query_string ? ri->query_string : "null",
19569  ri->query_string ? "\"" : "",
19570  eol,
19571  eol);
19572 
19573  connection_info_length += (int)strlen(block);
19574  if (connection_info_length + reserved_len < buflen) {
19575  strcat0(buffer, block);
19576  }
19577  }
19578 
19579  /* Execution time information */
19580  if ((state >= 2) && (state < 9)) {
19581  char start_time_str[64] = {0};
19582  char now_str[64] = {0};
19583  time_t start_time = conn->conn_birth_time;
19584  time_t now = time(NULL);
19585 
19586  gmt_time_string(start_time_str,
19587  sizeof(start_time_str) - 1,
19588  &start_time);
19589  gmt_time_string(now_str, sizeof(now_str) - 1, &now);
19590 
19591  mg_snprintf(NULL,
19592  NULL,
19593  block,
19594  sizeof(block),
19595  "\"time\" : {%s"
19596  "\"uptime\" : %.0f,%s"
19597  "\"start\" : \"%s\",%s"
19598  "\"now\" : \"%s\"%s"
19599  "},%s",
19600  eol,
19601  difftime(now, start_time),
19602  eol,
19603  start_time_str,
19604  eol,
19605  now_str,
19606  eol,
19607  eol);
19608 
19609  connection_info_length += (int)strlen(block);
19610  if (connection_info_length + reserved_len < buflen) {
19611  strcat0(buffer, block);
19612  }
19613  }
19614 
19615  /* Remote user name */
19616  if ((ri->remote_user) && (state < 9)) {
19617  mg_snprintf(NULL,
19618  NULL,
19619  block,
19620  sizeof(block),
19621  "\"user\" : {%s"
19622  "\"name\" : \"%s\",%s"
19623  "},%s",
19624  eol,
19625  ri->remote_user,
19626  eol,
19627  eol);
19628 
19629  connection_info_length += (int)strlen(block);
19630  if (connection_info_length + reserved_len < buflen) {
19631  strcat0(buffer, block);
19632  }
19633  }
19634 
19635  /* Data block */
19636  if (state >= 3) {
19637  mg_snprintf(NULL,
19638  NULL,
19639  block,
19640  sizeof(block),
19641  "\"data\" : {%s"
19642  "\"read\" : %" INT64_FMT ",%s"
19643  "\"written\" : %" INT64_FMT "%s"
19644  "},%s",
19645  eol,
19646  conn->consumed_content,
19647  eol,
19648  conn->num_bytes_sent,
19649  eol,
19650  eol);
19651 
19652  connection_info_length += (int)strlen(block);
19653  if (connection_info_length + reserved_len < buflen) {
19654  strcat0(buffer, block);
19655  }
19656  }
19657 
19658  /* State */
19659  mg_snprintf(NULL,
19660  NULL,
19661  block,
19662  sizeof(block),
19663  "\"state\" : \"%s\"%s",
19664  state_str,
19665  eol);
19666 
19667  connection_info_length += (int)strlen(block);
19668  if (connection_info_length + reserved_len < buflen) {
19669  strcat0(buffer, block);
19670  }
19671 
19672  /* Terminate string */
19673  if ((buflen > 0) && buffer && buffer[0]) {
19674  if (connection_info_length < buflen) {
19675  strcat0(buffer, eoobj);
19676  strcat0(buffer, eol);
19677  }
19678  }
19679  connection_info_length += reserved_len;
19680 
19681  return connection_info_length;
19682 }
19683 #endif
19684 
19685 
19686 /* Get system information. It can be printed or stored by the caller.
19687  * Return the size of available information. */
19688 int
19689 mg_get_system_info(char *buffer, int buflen)
19690 {
19691  if ((buffer == NULL) || (buflen < 1)) {
19692  return mg_get_system_info_impl(NULL, 0);
19693  } else {
19694  /* Reset buffer, so we can always use strcat. */
19695  buffer[0] = 0;
19696  return mg_get_system_info_impl(buffer, buflen);
19697  }
19698 }
19699 
19700 
19701 /* Get context information. It can be printed or stored by the caller.
19702  * Return the size of available information. */
19703 int
19704 mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
19705 {
19706 #if defined(USE_SERVER_STATS)
19707  if ((buffer == NULL) || (buflen < 1)) {
19708  return mg_get_context_info_impl(ctx, NULL, 0);
19709  } else {
19710  /* Reset buffer, so we can always use strcat. */
19711  buffer[0] = 0;
19712  return mg_get_context_info_impl(ctx, buffer, buflen);
19713  }
19714 #else
19715  (void)ctx;
19716  if ((buffer != NULL) && (buflen > 0)) {
19717  buffer[0] = 0;
19718  }
19719  return 0;
19720 #endif
19721 }
19722 
19723 
19724 #if defined(MG_EXPERIMENTAL_INTERFACES)
19725 int
19726 mg_get_connection_info(const struct mg_context *ctx,
19727  int idx,
19728  char *buffer,
19729  int buflen)
19730 {
19731  if ((buffer == NULL) || (buflen < 1)) {
19732  return mg_get_connection_info_impl(ctx, idx, NULL, 0);
19733  } else {
19734  /* Reset buffer, so we can always use strcat. */
19735  buffer[0] = 0;
19736  return mg_get_connection_info_impl(ctx, idx, buffer, buflen);
19737  }
19738 }
19739 #endif
19740 
19741 
19742 /* Initialize this library. This function does not need to be thread safe.
19743  */
19744 unsigned
19745 mg_init_library(unsigned features)
19746 {
19747 #if !defined(NO_SSL)
19748  char ebuf[128];
19749 #endif
19750 
19751  unsigned features_to_init = mg_check_feature(features & 0xFFu);
19752  unsigned features_inited = features_to_init;
19753 
19754  if (mg_init_library_called <= 0) {
19755  /* Not initialized yet */
19756  if (0 != pthread_mutex_init(&global_lock_mutex, NULL)) {
19757  return 0;
19758  }
19759  }
19760 
19761  mg_global_lock();
19762 
19763  if (mg_init_library_called <= 0) {
19764  if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
19765  /* Fatal error - abort start. However, this situation should
19766  * never occur in practice. */
19767  mg_global_unlock();
19768  return 0;
19769  }
19770 
19771 #if defined(_WIN32)
19772  InitializeCriticalSection(&global_log_file_lock);
19773 #endif
19774 #if !defined(_WIN32)
19775  pthread_mutexattr_init(&pthread_mutex_attr);
19776  pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
19777 #endif
19778 
19779 #if defined(USE_LUA)
19780  lua_init_optional_libraries();
19781 #endif
19782  }
19783 
19784  mg_global_unlock();
19785 
19786 #if !defined(NO_SSL)
19787  if (features_to_init & MG_FEATURES_SSL) {
19788  if (!mg_ssl_initialized) {
19789  if (initialize_ssl(ebuf, sizeof(ebuf))) {
19790  mg_ssl_initialized = 1;
19791  } else {
19792  (void)ebuf;
19793  DEBUG_TRACE("Initializing SSL failed: %s", ebuf);
19794  features_inited &= ~((unsigned)(MG_FEATURES_SSL));
19795  }
19796  } else {
19797  /* ssl already initialized */
19798  }
19799  }
19800 #endif
19801 
19802  /* Start WinSock for Windows */
19803  mg_global_lock();
19804  if (mg_init_library_called <= 0) {
19805 #if defined(_WIN32)
19806  WSADATA data;
19807  WSAStartup(MAKEWORD(2, 2), &data);
19808 #endif /* _WIN32 */
19809  mg_init_library_called = 1;
19810  } else {
19811  mg_init_library_called++;
19812  }
19813  mg_global_unlock();
19814 
19815  return features_inited;
19816 }
19817 
19818 
19819 /* Un-initialize this library. */
19820 unsigned
19821 mg_exit_library(void)
19822 {
19823  if (mg_init_library_called <= 0) {
19824  return 0;
19825  }
19826 
19827  mg_global_lock();
19828 
19829  mg_init_library_called--;
19830  if (mg_init_library_called == 0) {
19831 #if defined(_WIN32)
19832  (void)WSACleanup();
19833 #endif /* _WIN32 */
19834 #if !defined(NO_SSL)
19835  if (mg_ssl_initialized) {
19836  uninitialize_ssl();
19837  mg_ssl_initialized = 0;
19838  }
19839 #endif
19840 
19841 #if defined(_WIN32)
19842  (void)DeleteCriticalSection(&global_log_file_lock);
19843 #endif /* _WIN32 */
19844 #if !defined(_WIN32)
19845  (void)pthread_mutexattr_destroy(&pthread_mutex_attr);
19846 #endif
19847 
19848  (void)pthread_key_delete(sTlsKey);
19849 
19850 #if defined(USE_LUA)
19851  lua_exit_optional_libraries();
19852 #endif
19853 
19854  mg_global_unlock();
19855  (void)pthread_mutex_destroy(&global_lock_mutex);
19856  return 1;
19857  }
19858 
19859  mg_global_unlock();
19860  return 1;
19861 }
19862 
19863 
19864 /* End of civetweb.c */