1 /* Copyright (c) 2013-2016 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(_WIN32)
24 #if !defined(_CRT_SECURE_NO_WARNINGS)
25 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
26 #endif
27 #ifndef _WIN32_WINNT /* defined for tdm-gcc so we can use getnameinfo */
28 #define _WIN32_WINNT 0x0501
29 #endif
30 #else
31 #if defined(__GNUC__) && !defined(_GNU_SOURCE)
32 #define _GNU_SOURCE /* for setgroups() */
33 #endif
34 #if defined(__linux__) && !defined(_XOPEN_SOURCE)
35 #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
36 #endif
37 #ifndef _LARGEFILE_SOURCE
38 #define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
39 #endif
40 #ifndef _FILE_OFFSET_BITS
41 #define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
42 #endif
43 #ifndef __STDC_FORMAT_MACROS
44 #define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
45 #endif
46 #ifndef __STDC_LIMIT_MACROS
47 #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
48 #endif
49 #ifdef __sun
50 #define __EXTENSIONS__  /* to expose flockfile and friends in stdio.h */
51 #define __inline inline /* not recognized on older compiler versions */
52 #endif
53 #endif
54 
55 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
56 #define USE_TIMERS
57 #endif
58 
59 #if defined(_MSC_VER)
60 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
61 #pragma warning(disable : 4306)
62 /* conditional expression is constant: introduced by FD_SET(..) */
63 #pragma warning(disable : 4127)
64 /* non-constant aggregate initializer: issued due to missing C99 support */
65 #pragma warning(disable : 4204)
66 /* padding added after data member */
67 #pragma warning(disable : 4820)
68 /* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
69 #pragma warning(disable : 4668)
70 /* no function prototype given: converting '()' to '(void)' */
71 #pragma warning(disable : 4255)
72 /* function has been selected for automatic inline expansion */
73 #pragma warning(disable : 4711)
74 #endif
75 
76 
77 /* This code uses static_assert to check some conditions.
78  * Unfortunately some compilers still do not support it, so we have a
79  * replacement function here. */
80 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
81 #define mg_static_assert static_assert
82 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
83 #define mg_static_assert static_assert
84 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
85 #define mg_static_assert _Static_assert
86 #else
87 char static_assert_replacement[1];
88 #define mg_static_assert(cond, txt)                                            \
89 	extern char static_assert_replacement[(cond) ? 1 : -1]
90 #endif
91 
92 mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
93                  "int data type size check");
94 mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
95                  "pointer data type size check");
96 mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
97 
98 
99 /* DTL -- including winsock2.h works better if lean and mean */
100 #ifndef WIN32_LEAN_AND_MEAN
101 #define WIN32_LEAN_AND_MEAN
102 #endif
103 
104 #if defined(__SYMBIAN32__)
105 #define NO_SSL /* SSL is not supported */
106 #define NO_CGI /* CGI is not supported */
107 #define PATH_MAX FILENAME_MAX
108 #endif /* __SYMBIAN32__ */
109 
110 
111 /* Include the header file here, so the CivetWeb interface is defined for the
112  * entire implementation, including the following forward definitions. */
113 #include "civetweb.h"
114 
115 
116 #ifndef IGNORE_UNUSED_RESULT
117 #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
118 #endif
119 
120 #ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
121 #include <sys/types.h>
122 #include <sys/stat.h>
123 #include <errno.h>
124 #include <signal.h>
125 #include <fcntl.h>
126 #endif /* !_WIN32_WCE */
127 
128 
129 #ifdef __clang__
130 /* When using -Weverything, clang does not accept it's own headers
131  * in a release build configuration. Disable what is too much in
132  * -Weverything. */
133 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
134 #endif
135 
136 
137 #ifdef __MACH__ /* Apple OSX section */
138 
139 #ifdef __clang__
140 /* Avoid warnings for Xopen 7.00 and higher */
141 /* CYRUSH NOTE: Conduit Mod from: https://github.com/civetweb/civetweb/issues/503 */
142 #if (__clang_major__ < 3) || ((__clang_major__ < 4) && (__clang_minor__ < 9))
143 #pragma clang diagnostic ignored "-Wno-reserved-id-macro"
144 #pragma clang diagnostic ignored "-Wno-keyword-macro"
145 #endif
146 #endif
147 
148 #define CLOCK_MONOTONIC (1)
149 #define CLOCK_REALTIME (2)
150 
151 #include <sys/errno.h>
152 #include <sys/time.h>
153 #include <mach/clock.h>
154 #include <mach/mach.h>
155 #include <mach/mach_time.h>
156 #include <assert.h>
157 
158 /* clock_gettime is not implemented on OSX prior to 10.12 */
159 static int
_civet_clock_gettime(int clk_id,struct timespec * t)160 _civet_clock_gettime(int clk_id, struct timespec *t)
161 {
162 	memset(t, 0, sizeof(*t));
163 	if (clk_id == CLOCK_REALTIME) {
164 		struct timeval now;
165 		int rv = gettimeofday(&now, NULL);
166 		if (rv) {
167 			return rv;
168 		}
169 		t->tv_sec = now.tv_sec;
170 		t->tv_nsec = now.tv_usec * 1000;
171 		return 0;
172 
173 	} else if (clk_id == CLOCK_MONOTONIC) {
174 		static uint64_t clock_start_time = 0;
175 		static mach_timebase_info_data_t timebase_ifo = {0, 0};
176 
177 		uint64_t now = mach_absolute_time();
178 
179 		if (clock_start_time == 0) {
180 			kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
181 #if defined(DEBUG)
182 			assert(mach_status == KERN_SUCCESS);
183 #else
184 			/* appease "unused variable" warning for release builds */
185 			(void)mach_status;
186 #endif
187 			clock_start_time = now;
188 		}
189 
190 		now = (uint64_t)((double)(now - clock_start_time)
191 		                 * (double)timebase_ifo.numer
192 		                 / (double)timebase_ifo.denom);
193 
194 		t->tv_sec = now / 1000000000;
195 		t->tv_nsec = now % 1000000000;
196 		return 0;
197 	}
198 	return -1; /* EINVAL - Clock ID is unknown */
199 }
200 
201 /* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
202 #ifdef __CLOCK_AVAILABILITY
203 /* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
204  * declared but it may be NULL at runtime. So we need to check before using
205  * it. */
206 static int
_civet_safe_clock_gettime(int clk_id,struct timespec * t)207 _civet_safe_clock_gettime(int clk_id, struct timespec *t)
208 {
209 	if (clock_gettime) {
210 		return clock_gettime(clk_id, t);
211 	}
212 	return _civet_clock_gettime(clk_id, t);
213 }
214 #define clock_gettime _civet_safe_clock_gettime
215 #else
216 #define clock_gettime _civet_clock_gettime
217 #endif
218 
219 #endif
220 
221 
222 #include <time.h>
223 #include <stdlib.h>
224 #include <stdarg.h>
225 #include <assert.h>
226 #include <string.h>
227 #include <ctype.h>
228 #include <limits.h>
229 #include <stddef.h>
230 #include <stdio.h>
231 #include <stdint.h>
232 
233 #ifndef INT64_MAX
234 #define INT64_MAX (9223372036854775807)
235 #endif
236 
237 
238 #ifndef MAX_WORKER_THREADS
239 #define MAX_WORKER_THREADS (1024 * 64)
240 #endif
241 
242 #ifndef SOCKET_TIMEOUT_QUANTUM /* in ms */
243 #define SOCKET_TIMEOUT_QUANTUM (2000)
244 #endif
245 
246 #define SHUTDOWN_RD (0)
247 #define SHUTDOWN_WR (1)
248 #define SHUTDOWN_BOTH (2)
249 
250 mg_static_assert(MAX_WORKER_THREADS >= 1,
251                  "worker threads must be a positive number");
252 
253 mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
254                  "size_t data type size check");
255 
256 #if defined(_WIN32)                                                            \
257     && !defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
258 #include <windows.h>
259 #include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
260 #include <ws2tcpip.h>
261 
262 typedef const char *SOCK_OPT_TYPE;
263 
264 #if !defined(PATH_MAX)
265 #define PATH_MAX (MAX_PATH)
266 #endif
267 
268 #if !defined(PATH_MAX)
269 #define PATH_MAX (4096)
270 #endif
271 
272 mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
273 
274 #ifndef _IN_PORT_T
275 #ifndef in_port_t
276 #define in_port_t u_short
277 #endif
278 #endif
279 
280 #ifndef _WIN32_WCE
281 #include <process.h>
282 #include <direct.h>
283 #include <io.h>
284 #else            /* _WIN32_WCE */
285 #define NO_CGI   /* WinCE has no pipes */
286 #define NO_POPEN /* WinCE has no popen */
287 
288 typedef long off_t;
289 
290 #define errno ((int)(GetLastError()))
291 #define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
292 #endif /* _WIN32_WCE */
293 
294 #define MAKEUQUAD(lo, hi)                                                      \
295 	((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
296 #define RATE_DIFF (10000000) /* 100 nsecs */
297 #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
298 #define SYS2UNIX_TIME(lo, hi)                                                  \
299 	((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
300 
301 /* Visual Studio 6 does not know __func__ or __FUNCTION__
302  * The rest of MS compilers use __FUNCTION__, not C99 __func__
303  * Also use _strtoui64 on modern M$ compilers */
304 #if defined(_MSC_VER)
305 #if (_MSC_VER < 1300)
306 #define STRX(x) #x
307 #define STR(x) STRX(x)
308 #define __func__ __FILE__ ":" STR(__LINE__)
309 #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
310 #define strtoll(x, y, z) (_atoi64(x))
311 #else
312 #define __func__ __FUNCTION__
313 #define strtoull(x, y, z) (_strtoui64(x, y, z))
314 #define strtoll(x, y, z) (_strtoi64(x, y, z))
315 #endif
316 #endif /* _MSC_VER */
317 
318 #define ERRNO ((int)(GetLastError()))
319 #define NO_SOCKLEN_T
320 
321 #if defined(_WIN64) || defined(__MINGW64__)
322 #define SSL_LIB "ssleay64.dll"
323 #define CRYPTO_LIB "libeay64.dll"
324 #else
325 #define SSL_LIB "ssleay32.dll"
326 #define CRYPTO_LIB "libeay32.dll"
327 #endif
328 
329 #define O_NONBLOCK (0)
330 #ifndef W_OK
331 #define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
332 #endif
333 #if !defined(EWOULDBLOCK)
334 #define EWOULDBLOCK WSAEWOULDBLOCK
335 #endif /* !EWOULDBLOCK */
336 #define _POSIX_
337 #define INT64_FMT "I64d"
338 #define UINT64_FMT "I64u"
339 
340 #define WINCDECL __cdecl
341 #define vsnprintf_impl _vsnprintf
342 #define access _access
343 #define mg_sleep(x) (Sleep(x))
344 
345 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
346 #ifndef popen
347 #define popen(x, y) (_popen(x, y))
348 #endif
349 #ifndef pclose
350 #define pclose(x) (_pclose(x))
351 #endif
352 #define close(x) (_close(x))
353 #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
354 #define RTLD_LAZY (0)
355 #define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0)
356 #define fdopen(x, y) (_fdopen((x), (y)))
357 #define write(x, y, z) (_write((x), (y), (unsigned)z))
358 #define read(x, y, z) (_read((x), (y), (unsigned)z))
359 #define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
360 #define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
361 #define sleep(x) (Sleep((x)*1000))
362 #define rmdir(x) (_rmdir(x))
363 #define timegm(x) (_mkgmtime(x))
364 
365 #if !defined(fileno)
366 #define fileno(x) (_fileno(x))
367 #endif /* !fileno MINGW #defines fileno */
368 
369 typedef HANDLE pthread_mutex_t;
370 typedef DWORD pthread_key_t;
371 typedef HANDLE pthread_t;
372 typedef struct {
373 	CRITICAL_SECTION threadIdSec;
374 	struct mg_workerTLS *waiting_thread; /* The chain of threads */
375 } pthread_cond_t;
376 
377 #ifndef __clockid_t_defined
378 typedef DWORD clockid_t;
379 #endif
380 #ifndef CLOCK_MONOTONIC
381 #define CLOCK_MONOTONIC (1)
382 #endif
383 #ifndef CLOCK_REALTIME
384 #define CLOCK_REALTIME (2)
385 #endif
386 
387 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
388 #define _TIMESPEC_DEFINED
389 #endif
390 #ifndef _TIMESPEC_DEFINED
391 struct timespec {
392 	time_t tv_sec; /* seconds */
393 	long tv_nsec;  /* nanoseconds */
394 };
395 #endif
396 
397 #if !defined(WIN_PTHREADS_TIME_H)
398 #define MUST_IMPLEMENT_CLOCK_GETTIME
399 #endif
400 
401 #ifdef MUST_IMPLEMENT_CLOCK_GETTIME
402 #define clock_gettime mg_clock_gettime
403 static int
clock_gettime(clockid_t clk_id,struct timespec * tp)404 clock_gettime(clockid_t clk_id, struct timespec *tp)
405 {
406 	FILETIME ft;
407 	ULARGE_INTEGER li;
408 	BOOL ok = FALSE;
409 	double d;
410 	static double perfcnt_per_sec = 0.0;
411 
412 	if (tp) {
413 		memset(tp, 0, sizeof(*tp));
414 		if (clk_id == CLOCK_REALTIME) {
415 			GetSystemTimeAsFileTime(&ft);
416 			li.LowPart = ft.dwLowDateTime;
417 			li.HighPart = ft.dwHighDateTime;
418 			li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
419 			tp->tv_sec = (time_t)(li.QuadPart / 10000000);
420 			tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
421 			ok = TRUE;
422 		} else if (clk_id == CLOCK_MONOTONIC) {
423 			if (perfcnt_per_sec == 0.0) {
424 				QueryPerformanceFrequency((LARGE_INTEGER *)&li);
425 				perfcnt_per_sec = 1.0 / li.QuadPart;
426 			}
427 			if (perfcnt_per_sec != 0.0) {
428 				QueryPerformanceCounter((LARGE_INTEGER *)&li);
429 				d = li.QuadPart * perfcnt_per_sec;
430 				tp->tv_sec = (time_t)d;
431 				d -= tp->tv_sec;
432 				tp->tv_nsec = (long)(d * 1.0E9);
433 				ok = TRUE;
434 			}
435 		}
436 	}
437 
438 	return ok ? 0 : -1;
439 }
440 #endif
441 
442 
443 #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
444 
445 static int pthread_mutex_lock(pthread_mutex_t *);
446 static int pthread_mutex_unlock(pthread_mutex_t *);
447 static void path_to_unicode(const struct mg_connection *conn,
448                             const char *path,
449                             wchar_t *wbuf,
450                             size_t wbuf_len);
451 
452 /* All file operations need to be rewritten to solve #246. */
453 
454 #include "file_ops.inl"
455 
456 struct mg_file;
457 
458 static const char *
459 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p);
460 
461 
462 /* POSIX dirent interface */
463 struct dirent {
464 	char d_name[PATH_MAX];
465 };
466 
467 typedef struct DIR {
468 	HANDLE handle;
469 	WIN32_FIND_DATAW info;
470 	struct dirent result;
471 } DIR;
472 
473 #if defined(_WIN32) && !defined(POLLIN)
474 #ifndef HAVE_POLL
475 struct pollfd {
476 	SOCKET fd;
477 	short events;
478 	short revents;
479 };
480 #define POLLIN (0x0300)
481 #endif
482 #endif
483 
484 /* Mark required libraries */
485 #if defined(_MSC_VER)
486 #pragma comment(lib, "Ws2_32.lib")
487 #endif
488 
489 #else /* defined(_WIN32) && !defined(__SYMBIAN32__) -                          \
490          WINDOWS / UNIX include block */
491 
492 #include <sys/wait.h>
493 #include <sys/socket.h>
494 #include <sys/poll.h>
495 #include <netinet/in.h>
496 #include <arpa/inet.h>
497 #include <sys/time.h>
498 #include <sys/utsname.h>
499 #include <stdint.h>
500 #include <inttypes.h>
501 #include <netdb.h>
502 #include <netinet/tcp.h>
503 typedef const void *SOCK_OPT_TYPE;
504 
505 #if defined(ANDROID)
506 typedef unsigned short int in_port_t;
507 #endif
508 
509 #include <pwd.h>
510 #include <unistd.h>
511 #include <grp.h>
512 #include <dirent.h>
513 #define vsnprintf_impl vsnprintf
514 
515 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
516 #include <dlfcn.h>
517 #endif
518 #include <pthread.h>
519 #if defined(__MACH__)
520 #define SSL_LIB "libssl.dylib"
521 #define CRYPTO_LIB "libcrypto.dylib"
522 #else
523 #if !defined(SSL_LIB)
524 #define SSL_LIB "libssl.so"
525 #endif
526 #if !defined(CRYPTO_LIB)
527 #define CRYPTO_LIB "libcrypto.so"
528 #endif
529 #endif
530 #ifndef O_BINARY
531 #define O_BINARY (0)
532 #endif /* O_BINARY */
533 #define closesocket(a) (close(a))
534 #define mg_mkdir(conn, path, mode) (mkdir(path, mode))
535 #define mg_remove(conn, x) (remove(x))
536 #define mg_sleep(x) (usleep((x)*1000))
537 #define mg_opendir(conn, x) (opendir(x))
538 #define mg_closedir(x) (closedir(x))
539 #define mg_readdir(x) (readdir(x))
540 #define ERRNO (errno)
541 #define INVALID_SOCKET (-1)
542 #define INT64_FMT PRId64
543 #define UINT64_FMT PRIu64
544 typedef int SOCKET;
545 #define WINCDECL
546 
547 #if defined(__hpux)
548 /* HPUX 11 does not have monotonic, fall back to realtime */
549 #ifndef CLOCK_MONOTONIC
550 #define CLOCK_MONOTONIC CLOCK_REALTIME
551 #endif
552 
553 /* HPUX defines socklen_t incorrectly as size_t which is 64bit on
554  * Itanium.  Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
555  * the prototypes use int* rather than socklen_t* which matches the
556  * actual library expectation.  When called with the wrong size arg
557  * accept() returns a zero client inet addr and check_acl() always
558  * fails.  Since socklen_t is widely used below, just force replace
559  * their typedef with int. - DTL
560  */
561 #define socklen_t int
562 #endif /* hpux */
563 
564 #endif /* defined(_WIN32) && !defined(__SYMBIAN32__) -                         \
565           WINDOWS / UNIX include block */
566 
567 /* va_copy should always be a macro, C99 and C++11 - DTL */
568 #ifndef va_copy
569 #define va_copy(x, y) ((x) = (y))
570 #endif
571 
572 #ifdef _WIN32
573 /* Create substitutes for POSIX functions in Win32. */
574 
575 #if defined(__MINGW32__)
576 /* Show no warning in case system functions are not used. */
577 #pragma GCC diagnostic push
578 #pragma GCC diagnostic ignored "-Wunused-function"
579 #endif
580 
581 
582 static CRITICAL_SECTION global_log_file_lock;
583 static DWORD
pthread_self(void)584 pthread_self(void)
585 {
586 	return GetCurrentThreadId();
587 }
588 
589 
590 static int
pthread_key_create(pthread_key_t * key,void (* _ignored)(void *))591 pthread_key_create(
592     pthread_key_t *key,
593     void (*_ignored)(void *) /* destructor not supported for Windows */
594     )
595 {
596 	(void)_ignored;
597 
598 	if ((key != 0)) {
599 		*key = TlsAlloc();
600 		return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
601 	}
602 	return -2;
603 }
604 
605 
606 static int
pthread_key_delete(pthread_key_t key)607 pthread_key_delete(pthread_key_t key)
608 {
609 	return TlsFree(key) ? 0 : 1;
610 }
611 
612 
613 static int
pthread_setspecific(pthread_key_t key,void * value)614 pthread_setspecific(pthread_key_t key, void *value)
615 {
616 	return TlsSetValue(key, value) ? 0 : 1;
617 }
618 
619 
620 static void *
pthread_getspecific(pthread_key_t key)621 pthread_getspecific(pthread_key_t key)
622 {
623 	return TlsGetValue(key);
624 }
625 
626 #if defined(__MINGW32__)
627 /* Enable unused function warning again */
628 #pragma GCC diagnostic pop
629 #endif
630 
631 static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
632 #else
633 static pthread_mutexattr_t pthread_mutex_attr;
634 #endif /* _WIN32 */
635 
636 
637 #define PASSWORDS_FILE_NAME ".htpasswd"
638 #define CGI_ENVIRONMENT_SIZE (4096)
639 #define MAX_CGI_ENVIR_VARS (256)
640 #define MG_BUF_LEN (8192)
641 
642 #ifndef MAX_REQUEST_SIZE
643 #define MAX_REQUEST_SIZE (16384)
644 #endif
645 
646 mg_static_assert(MAX_REQUEST_SIZE >= 256,
647                  "request size length must be a positive number");
648 
649 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
650 
651 
652 #if defined(_WIN32_WCE)
653 /* Create substitutes for POSIX functions in Win32. */
654 
655 #if defined(__MINGW32__)
656 /* Show no warning in case system functions are not used. */
657 #pragma GCC diagnostic push
658 #pragma GCC diagnostic ignored "-Wunused-function"
659 #endif
660 
661 
662 static time_t
time(time_t * ptime)663 time(time_t *ptime)
664 {
665 	time_t t;
666 	SYSTEMTIME st;
667 	FILETIME ft;
668 
669 	GetSystemTime(&st);
670 	SystemTimeToFileTime(&st, &ft);
671 	t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
672 
673 	if (ptime != NULL) {
674 		*ptime = t;
675 	}
676 
677 	return t;
678 }
679 
680 
681 static struct tm *
localtime_s(const time_t * ptime,struct tm * ptm)682 localtime_s(const time_t *ptime, struct tm *ptm)
683 {
684 	int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
685 	FILETIME ft, lft;
686 	SYSTEMTIME st;
687 	TIME_ZONE_INFORMATION tzinfo;
688 
689 	if (ptm == NULL) {
690 		return NULL;
691 	}
692 
693 	*(int64_t *)&ft = t;
694 	FileTimeToLocalFileTime(&ft, &lft);
695 	FileTimeToSystemTime(&lft, &st);
696 	ptm->tm_year = st.wYear - 1900;
697 	ptm->tm_mon = st.wMonth - 1;
698 	ptm->tm_wday = st.wDayOfWeek;
699 	ptm->tm_mday = st.wDay;
700 	ptm->tm_hour = st.wHour;
701 	ptm->tm_min = st.wMinute;
702 	ptm->tm_sec = st.wSecond;
703 	ptm->tm_yday = 0; /* hope nobody uses this */
704 	ptm->tm_isdst =
705 	    (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
706 
707 	return ptm;
708 }
709 
710 
711 static struct tm *
gmtime_s(const time_t * ptime,struct tm * ptm)712 gmtime_s(const time_t *ptime, struct tm *ptm)
713 {
714 	/* FIXME(lsm): fix this. */
715 	return localtime_s(ptime, ptm);
716 }
717 
718 static int mg_atomic_inc(volatile int *addr);
719 static struct tm tm_array[MAX_WORKER_THREADS];
720 static int tm_index = 0;
721 
722 static struct tm *
localtime(const time_t * ptime)723 localtime(const time_t *ptime)
724 {
725 	int i = mg_atomic_inc(&tm_index) % (sizeof(tm_array) / sizeof(tm_array[0]));
726 	return localtime_s(ptime, tm_array + i);
727 }
728 
729 
730 static struct tm *
gmtime(const time_t * ptime)731 gmtime(const time_t *ptime)
732 {
733 	int i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array);
734 	return gmtime_s(ptime, tm_array + i);
735 }
736 
737 
738 static size_t
strftime(char * dst,size_t dst_size,const char * fmt,const struct tm * tm)739 strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
740 {
741 	/* TODO */ //(void)mg_snprintf(NULL, dst, dst_size, "implement strftime()
742 	// for WinCE");
743 	return 0;
744 }
745 
746 #define _beginthreadex(psec, stack, func, prm, flags, ptid)                    \
747 	(uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid)
748 
749 #define remove(f) mg_remove(NULL, f)
750 
751 static int
rename(const char * a,const char * b)752 rename(const char *a, const char *b)
753 {
754 	wchar_t wa[PATH_MAX];
755 	wchar_t wb[PATH_MAX];
756 	path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa));
757 	path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb));
758 
759 	return MoveFileW(wa, wb) ? 0 : -1;
760 }
761 
762 struct stat {
763 	int64_t st_size;
764 	time_t st_mtime;
765 };
766 
767 static int
stat(const char * name,struct stat * st)768 stat(const char *name, struct stat *st)
769 {
770 	wchar_t wbuf[PATH_MAX];
771 	WIN32_FILE_ATTRIBUTE_DATA attr;
772 	time_t creation_time, write_time;
773 
774 	path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf));
775 	memset(&attr, 0, sizeof(attr));
776 
777 	GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
778 	st->st_size =
779 	    (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
780 
781 	write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
782 	                           attr.ftLastWriteTime.dwHighDateTime);
783 	creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
784 	                              attr.ftCreationTime.dwHighDateTime);
785 
786 	if (creation_time > write_time) {
787 		st->st_mtime = creation_time;
788 	} else {
789 		st->st_mtime = write_time;
790 	}
791 	return 0;
792 }
793 
794 #define access(x, a) 1 /* not required anyway */
795 
796 /* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */
797 #define EEXIST 1 /* TODO: See Windows error codes */
798 #define EACCES 2 /* TODO: See Windows error codes */
799 #define ENOENT 3 /* TODO: See Windows Error codes */
800 
801 #if defined(__MINGW32__)
802 /* Enable unused function warning again */
803 #pragma GCC diagnostic pop
804 #endif
805 
806 #endif /* defined(_WIN32_WCE) */
807 
808 
809 #if !defined(DEBUG_TRACE)
810 #if defined(DEBUG)
811 static void DEBUG_TRACE_FUNC(const char *func,
812                              unsigned line,
813                              PRINTF_FORMAT_STRING(const char *fmt),
814                              ...) PRINTF_ARGS(3, 4);
815 
816 static void
DEBUG_TRACE_FUNC(const char * func,unsigned line,const char * fmt,...)817 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
818 {
819 	va_list args;
820 	struct timespec tsnow;
821 	uint64_t nsnow;
822 	static uint64_t nslast;
823 
824 	clock_gettime(CLOCK_REALTIME, &tsnow);
825 	nsnow = (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
826 
827 	flockfile(stdout);
828 	printf("*** %lu.%09lu %12" INT64_FMT " %p %s:%u: ",
829 	       (unsigned long)tsnow.tv_sec,
830 	       (unsigned long)tsnow.tv_nsec,
831 	       nsnow - nslast,
832 	       (void *)pthread_self(),
833 	       func,
834 	       line);
835 	va_start(args, fmt);
836 	vprintf(fmt, args);
837 	va_end(args);
838 	putchar('\n');
839 	fflush(stdout);
840 	funlockfile(stdout);
841 	nslast = nsnow;
842 }
843 
844 #define DEBUG_TRACE(fmt, ...)                                                  \
845 	DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
846 
847 #else
848 #define DEBUG_TRACE(fmt, ...)                                                  \
849 	do {                                                                       \
850 	} while (0)
851 #endif /* DEBUG */
852 #endif /* DEBUG_TRACE */
853 
854 
855 #if defined(MEMORY_DEBUGGING)
856 static unsigned long mg_memory_debug_blockCount = 0;
857 static unsigned long mg_memory_debug_totalMemUsed = 0;
858 
859 
860 static void *
mg_malloc_ex(size_t size,const char * file,unsigned line)861 mg_malloc_ex(size_t size, const char *file, unsigned line)
862 {
863 	void *data = malloc(size + sizeof(size_t));
864 	void *memory = 0;
865 	char mallocStr[256];
866 
867 	if (data) {
868 		*(size_t *)data = size;
869 		mg_memory_debug_totalMemUsed += size;
870 		mg_memory_debug_blockCount++;
871 		memory = (void *)(((char *)data) + sizeof(size_t));
872 	}
873 
874 	sprintf(mallocStr,
875 	        "MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n",
876 	        memory,
877 	        (unsigned long)size,
878 	        mg_memory_debug_totalMemUsed,
879 	        mg_memory_debug_blockCount,
880 	        file,
881 	        line);
882 #if defined(_WIN32)
883 	OutputDebugStringA(mallocStr);
884 #else
885 	DEBUG_TRACE("%s", mallocStr);
886 #endif
887 
888 	return memory;
889 }
890 
891 
892 static void *
mg_calloc_ex(size_t count,size_t size,const char * file,unsigned line)893 mg_calloc_ex(size_t count, size_t size, const char *file, unsigned line)
894 {
895 	void *data = mg_malloc_ex(size * count, file, line);
896 	if (data) {
897 		memset(data, 0, size * count);
898 	}
899 	return data;
900 }
901 
902 
903 static void
mg_free_ex(void * memory,const char * file,unsigned line)904 mg_free_ex(void *memory, const char *file, unsigned line)
905 {
906 	char mallocStr[256];
907 	void *data = (void *)(((char *)memory) - sizeof(size_t));
908 	size_t size;
909 
910 	if (memory) {
911 		size = *(size_t *)data;
912 		mg_memory_debug_totalMemUsed -= size;
913 		mg_memory_debug_blockCount--;
914 		sprintf(mallocStr,
915 		        "MEM: %p %5lu free    %7lu %4lu --- %s:%u\n",
916 		        memory,
917 		        (unsigned long)size,
918 		        mg_memory_debug_totalMemUsed,
919 		        mg_memory_debug_blockCount,
920 		        file,
921 		        line);
922 #if defined(_WIN32)
923 		OutputDebugStringA(mallocStr);
924 #else
925 		DEBUG_TRACE("%s", mallocStr);
926 #endif
927 
928 		free(data);
929 	}
930 }
931 
932 
933 static void *
mg_realloc_ex(void * memory,size_t newsize,const char * file,unsigned line)934 mg_realloc_ex(void *memory, size_t newsize, const char *file, unsigned line)
935 {
936 	char mallocStr[256];
937 	void *data;
938 	void *_realloc;
939 	size_t oldsize;
940 
941 	if (newsize) {
942 		if (memory) {
943 			data = (void *)(((char *)memory) - sizeof(size_t));
944 			oldsize = *(size_t *)data;
945 			_realloc = realloc(data, newsize + sizeof(size_t));
946 			if (_realloc) {
947 				data = _realloc;
948 				mg_memory_debug_totalMemUsed -= oldsize;
949 				sprintf(mallocStr,
950 				        "MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n",
951 				        memory,
952 				        (unsigned long)oldsize,
953 				        mg_memory_debug_totalMemUsed,
954 				        mg_memory_debug_blockCount,
955 				        file,
956 				        line);
957 #if defined(_WIN32)
958 				OutputDebugStringA(mallocStr);
959 #else
960 				DEBUG_TRACE("%s", mallocStr);
961 #endif
962 				mg_memory_debug_totalMemUsed += newsize;
963 				sprintf(mallocStr,
964 				        "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
965 				        memory,
966 				        (unsigned long)newsize,
967 				        mg_memory_debug_totalMemUsed,
968 				        mg_memory_debug_blockCount,
969 				        file,
970 				        line);
971 #if defined(_WIN32)
972 				OutputDebugStringA(mallocStr);
973 #else
974 				DEBUG_TRACE("%s", mallocStr);
975 #endif
976 				*(size_t *)data = newsize;
977 				data = (void *)(((char *)data) + sizeof(size_t));
978 			} else {
979 #if defined(_WIN32)
980 				OutputDebugStringA("MEM: realloc failed\n");
981 #else
982 				DEBUG_TRACE("%s", "MEM: realloc failed\n");
983 #endif
984 				return _realloc;
985 			}
986 		} else {
987 			data = mg_malloc_ex(newsize, file, line);
988 		}
989 	} else {
990 		data = 0;
991 		mg_free_ex(memory, file, line);
992 	}
993 
994 	return data;
995 }
996 
997 #define mg_malloc(a) mg_malloc_ex(a, __FILE__, __LINE__)
998 #define mg_calloc(a, b) mg_calloc_ex(a, b, __FILE__, __LINE__)
999 #define mg_realloc(a, b) mg_realloc_ex(a, b, __FILE__, __LINE__)
1000 #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
1001 
1002 #else
1003 
1004 static __inline void *
mg_malloc(size_t a)1005 mg_malloc(size_t a)
1006 {
1007 	return malloc(a);
1008 }
1009 
1010 static __inline void *
mg_calloc(size_t a,size_t b)1011 mg_calloc(size_t a, size_t b)
1012 {
1013 	return calloc(a, b);
1014 }
1015 
1016 static __inline void *
mg_realloc(void * a,size_t b)1017 mg_realloc(void *a, size_t b)
1018 {
1019 	return realloc(a, b);
1020 }
1021 
1022 static __inline void
mg_free(void * a)1023 mg_free(void *a)
1024 {
1025 	free(a);
1026 }
1027 
1028 #endif
1029 
1030 
1031 static void mg_vsnprintf(const struct mg_connection *conn,
1032                          int *truncated,
1033                          char *buf,
1034                          size_t buflen,
1035                          const char *fmt,
1036                          va_list ap);
1037 
1038 static void mg_snprintf(const struct mg_connection *conn,
1039                         int *truncated,
1040                         char *buf,
1041                         size_t buflen,
1042                         PRINTF_FORMAT_STRING(const char *fmt),
1043                         ...) PRINTF_ARGS(5, 6);
1044 
1045 /* This following lines are just meant as a reminder to use the mg-functions
1046  * for memory management */
1047 #ifdef malloc
1048 #undef malloc
1049 #endif
1050 #ifdef calloc
1051 #undef calloc
1052 #endif
1053 #ifdef realloc
1054 #undef realloc
1055 #endif
1056 #ifdef free
1057 #undef free
1058 #endif
1059 #ifdef snprintf
1060 #undef snprintf
1061 #endif
1062 #ifdef vsnprintf
1063 #undef vsnprintf
1064 #endif
1065 #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
1066 #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
1067 #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
1068 #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
1069 #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
1070 #ifdef _WIN32 /* vsnprintf must not be used in any system, * \ \ \             \
1071                * but this define only works well for Windows. */
1072 #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
1073 #endif
1074 
1075 #define MD5_STATIC static
1076 #include "md5.inl"
1077 
1078 /* Darwin prior to 7.0 and Win32 do not have socklen_t */
1079 #ifdef NO_SOCKLEN_T
1080 typedef int socklen_t;
1081 #endif /* NO_SOCKLEN_T */
1082 #define _DARWIN_UNLIMITED_SELECT
1083 
1084 #define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
1085 
1086 #if !defined(MSG_NOSIGNAL)
1087 #define MSG_NOSIGNAL (0)
1088 #endif
1089 
1090 #if !defined(SOMAXCONN)
1091 #define SOMAXCONN (100)
1092 #endif
1093 
1094 /* Size of the accepted socket queue */
1095 #if !defined(MGSQLEN)
1096 #define MGSQLEN (20)
1097 #endif
1098 
1099 
1100 #if defined(NO_SSL)
1101 typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
1102 typedef struct SSL_CTX SSL_CTX;
1103 #else
1104 #if defined(NO_SSL_DL)
1105 #include <openssl/ssl.h>
1106 #include <openssl/err.h>
1107 #include <openssl/crypto.h>
1108 #include <openssl/x509.h>
1109 #include <openssl/pem.h>
1110 #include <openssl/engine.h>
1111 #include <openssl/conf.h>
1112 #include <openssl/dh.h>
1113 #else
1114 /* SSL loaded dynamically from DLL.
1115  * I put the prototypes here to be independent from OpenSSL source
1116  * installation. */
1117 
1118 typedef struct ssl_st SSL;
1119 typedef struct ssl_method_st SSL_METHOD;
1120 typedef struct ssl_ctx_st SSL_CTX;
1121 typedef struct x509_store_ctx_st X509_STORE_CTX;
1122 typedef struct x509_name X509_NAME;
1123 typedef struct asn1_integer ASN1_INTEGER;
1124 typedef struct evp_md EVP_MD;
1125 typedef struct x509 X509;
1126 
1127 
1128 #define SSL_CTRL_OPTIONS (32)
1129 #define SSL_CTRL_CLEAR_OPTIONS (77)
1130 #define SSL_CTRL_SET_ECDH_AUTO (94)
1131 
1132 #define SSL_VERIFY_NONE (0)
1133 #define SSL_VERIFY_PEER (1)
1134 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
1135 #define SSL_VERIFY_CLIENT_ONCE (4)
1136 #define SSL_OP_ALL ((long)(0x80000BFFUL))
1137 #define SSL_OP_NO_SSLv2 (0x01000000L)
1138 #define SSL_OP_NO_SSLv3 (0x02000000L)
1139 #define SSL_OP_NO_TLSv1 (0x04000000L)
1140 #define SSL_OP_NO_TLSv1_2 (0x08000000L)
1141 #define SSL_OP_NO_TLSv1_1 (0x10000000L)
1142 #define SSL_OP_SINGLE_DH_USE (0x00100000L)
1143 #define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L)
1144 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L)
1145 
1146 #define SSL_ERROR_NONE (0)
1147 #define SSL_ERROR_SSL (1)
1148 #define SSL_ERROR_WANT_READ (2)
1149 #define SSL_ERROR_WANT_WRITE (3)
1150 #define SSL_ERROR_WANT_X509_LOOKUP (4)
1151 #define SSL_ERROR_SYSCALL (5) /* see errno */
1152 #define SSL_ERROR_ZERO_RETURN (6)
1153 #define SSL_ERROR_WANT_CONNECT (7)
1154 #define SSL_ERROR_WANT_ACCEPT (8)
1155 
1156 
1157 struct ssl_func {
1158 	const char *name;  /* SSL function name */
1159 	void (*ptr)(void); /* Function pointer */
1160 };
1161 
1162 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
1163 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
1164 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
1165 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
1166 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
1167 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
1168 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
1169 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
1170 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
1171 #define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
1172 #define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
1173 #define SSL_CTX_use_PrivateKey_file                                            \
1174 	(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
1175 #define SSL_CTX_use_certificate_file                                           \
1176 	(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
1177 #define SSL_CTX_set_default_passwd_cb                                          \
1178 	(*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
1179 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
1180 #define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
1181 #define SSL_CTX_use_certificate_chain_file                                     \
1182 	(*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
1183 #define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr)
1184 #define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
1185 #define SSL_CTX_set_verify                                                     \
1186 	(*(void (*)(SSL_CTX *,                                                     \
1187 	            int,                                                           \
1188 	            int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19].ptr)
1189 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
1190 #define SSL_CTX_load_verify_locations                                          \
1191 	(*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
1192 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
1193 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
1194 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr)
1195 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
1196 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr)
1197 #define SSL_CIPHER_get_name                                                    \
1198 	(*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
1199 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
1200 #define SSL_CTX_set_session_id_context                                         \
1201 	(*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
1202 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
1203 
1204 
1205 #define SSL_CTX_set_cipher_list                                                \
1206 	(*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
1207 #define SSL_CTX_set_options(ctx, op)                                           \
1208 	SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
1209 #define SSL_CTX_clear_options(ctx, op)                                         \
1210 	SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
1211 #define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      \
1212 	SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
1213 
1214 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
1215 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
1216 
1217 
1218 #define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
1219 #define CRYPTO_set_locking_callback                                            \
1220 	(*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
1221 #define CRYPTO_set_id_callback                                                 \
1222 	(*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
1223 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
1224 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
1225 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
1226 #define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
1227 #define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
1228 #define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
1229 #define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
1230 #define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
1231 #define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr)
1232 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[12].ptr)
1233 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[13].ptr)
1234 #define X509_NAME_oneline                                                      \
1235 	(*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr)
1236 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[15].ptr)
1237 #define i2c_ASN1_INTEGER                                                       \
1238 	(*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr)
1239 #define EVP_get_digestbyname                                                   \
1240 	(*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr)
1241 #define ASN1_digest                                                            \
1242 	(*(int (*)(int (*)(),                                                      \
1243 	           const EVP_MD *,                                                 \
1244 	           char *,                                                         \
1245 	           unsigned char *,                                                \
1246 	           unsigned int *))crypto_sw[18].ptr)
1247 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr)
1248 
1249 
1250 /* set_ssl_option() function updates this array.
1251  * It loads SSL library dynamically and changes NULLs to the actual addresses
1252  * of respective functions. The macros above (like SSL_connect()) are really
1253  * just calling these functions indirectly via the pointer. */
1254 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
1255                                    {"SSL_accept", NULL},
1256                                    {"SSL_connect", NULL},
1257                                    {"SSL_read", NULL},
1258                                    {"SSL_write", NULL},
1259                                    {"SSL_get_error", NULL},
1260                                    {"SSL_set_fd", NULL},
1261                                    {"SSL_new", NULL},
1262                                    {"SSL_CTX_new", NULL},
1263                                    {"SSLv23_server_method", NULL},
1264                                    {"SSL_library_init", NULL},
1265                                    {"SSL_CTX_use_PrivateKey_file", NULL},
1266                                    {"SSL_CTX_use_certificate_file", NULL},
1267                                    {"SSL_CTX_set_default_passwd_cb", NULL},
1268                                    {"SSL_CTX_free", NULL},
1269                                    {"SSL_load_error_strings", NULL},
1270                                    {"SSL_CTX_use_certificate_chain_file", NULL},
1271                                    {"SSLv23_client_method", NULL},
1272                                    {"SSL_pending", NULL},
1273                                    {"SSL_CTX_set_verify", NULL},
1274                                    {"SSL_shutdown", NULL},
1275                                    {"SSL_CTX_load_verify_locations", NULL},
1276                                    {"SSL_CTX_set_default_verify_paths", NULL},
1277                                    {"SSL_CTX_set_verify_depth", NULL},
1278                                    {"SSL_get_peer_certificate", NULL},
1279                                    {"SSL_get_version", NULL},
1280                                    {"SSL_get_current_cipher", NULL},
1281                                    {"SSL_CIPHER_get_name", NULL},
1282                                    {"SSL_CTX_check_private_key", NULL},
1283                                    {"SSL_CTX_set_session_id_context", NULL},
1284                                    {"SSL_CTX_ctrl", NULL},
1285                                    {"SSL_CTX_set_cipher_list", NULL},
1286                                    {NULL, NULL}};
1287 
1288 
1289 /* Similar array as ssl_sw. These functions could be located in different
1290  * lib. */
1291 static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
1292                                       {"CRYPTO_set_locking_callback", NULL},
1293                                       {"CRYPTO_set_id_callback", NULL},
1294                                       {"ERR_get_error", NULL},
1295                                       {"ERR_error_string", NULL},
1296                                       {"ERR_remove_state", NULL},
1297                                       {"ERR_free_strings", NULL},
1298                                       {"ENGINE_cleanup", NULL},
1299                                       {"CONF_modules_unload", NULL},
1300                                       {"CRYPTO_cleanup_all_ex_data", NULL},
1301                                       {"EVP_cleanup", NULL},
1302                                       {"X509_free", NULL},
1303                                       {"X509_get_subject_name", NULL},
1304                                       {"X509_get_issuer_name", NULL},
1305                                       {"X509_NAME_oneline", NULL},
1306                                       {"X509_get_serialNumber", NULL},
1307                                       {"i2c_ASN1_INTEGER", NULL},
1308                                       {"EVP_get_digestbyname", NULL},
1309                                       {"ASN1_digest", NULL},
1310                                       {"i2d_X509", NULL},
1311                                       {NULL, NULL}};
1312 #endif /* NO_SSL_DL */
1313 #endif /* NO_SSL */
1314 
1315 
1316 #if !defined(NO_CACHING)
1317 static const char *month_names[] = {"Jan",
1318                                     "Feb",
1319                                     "Mar",
1320                                     "Apr",
1321                                     "May",
1322                                     "Jun",
1323                                     "Jul",
1324                                     "Aug",
1325                                     "Sep",
1326                                     "Oct",
1327                                     "Nov",
1328                                     "Dec"};
1329 #endif /* !NO_CACHING */
1330 
1331 /* Unified socket address. For IPv6 support, add IPv6 address structure in the
1332  * union u. */
1333 union usa {
1334 	struct sockaddr sa;
1335 	struct sockaddr_in sin;
1336 #if defined(USE_IPV6)
1337 	struct sockaddr_in6 sin6;
1338 #endif
1339 };
1340 
1341 /* Describes a string (chunk of memory). */
1342 struct vec {
1343 	const char *ptr;
1344 	size_t len;
1345 };
1346 
1347 struct mg_file_stat {
1348 	/* File properties filled by mg_stat: */
1349 	uint64_t size;
1350 	time_t last_modified;
1351 	int is_directory; /* Set to 1 if mg_stat is called for a directory */
1352 	int is_gzipped;   /* Set to 1 if the content is gzipped, in which
1353 	                   * case we need a "Content-Eencoding: gzip" header */
1354 	int location;     /* 0 = nowhere, 1 = on disk, 2 = in memory */
1355 };
1356 
1357 struct mg_file_in_memory {
1358 	char *p;
1359 	uint32_t pos;
1360 	char mode;
1361 };
1362 
1363 struct mg_file_access {
1364 	/* File properties filled by mg_fopen: */
1365 	FILE *fp;
1366 	/* TODO: struct mg_file_in_memory *mf; */
1367 	const char *membuf; /* TODO: remove */
1368 };
1369 
1370 struct mg_file {
1371 	struct mg_file_stat stat;
1372 	struct mg_file_access access;
1373 };
1374 
1375 #define STRUCT_FILE_INITIALIZER                                                \
1376 	{                                                                          \
1377 		{                                                                      \
1378 			(uint64_t)0, (time_t)0, 0, 0, 0                                    \
1379 		}                                                                      \
1380 		,                                                                      \
1381 		{                                                                      \
1382 			(FILE *) NULL, (const char *)NULL                                  \
1383 		}                                                                      \
1384 	}
1385 
1386 /* Describes listening socket, or socket which was accept()-ed by the master
1387  * thread and queued for future handling by the worker thread. */
1388 struct socket {
1389 	SOCKET sock;             /* Listening socket */
1390 	union usa lsa;           /* Local socket address */
1391 	union usa rsa;           /* Remote socket address */
1392 	unsigned char is_ssl;    /* Is port SSL-ed */
1393 	unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
1394 	                          * port */
1395 	unsigned char in_use;    /* Is valid */
1396 };
1397 
1398 /* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
1399 enum {
1400 	CGI_EXTENSIONS,
1401 	CGI_ENVIRONMENT,
1402 	PUT_DELETE_PASSWORDS_FILE,
1403 	CGI_INTERPRETER,
1404 	PROTECT_URI,
1405 	AUTHENTICATION_DOMAIN,
1406 	SSI_EXTENSIONS,
1407 	THROTTLE,
1408 	ACCESS_LOG_FILE,
1409 	ENABLE_DIRECTORY_LISTING,
1410 	ERROR_LOG_FILE,
1411 	GLOBAL_PASSWORDS_FILE,
1412 	INDEX_FILES,
1413 	ENABLE_KEEP_ALIVE,
1414 	ACCESS_CONTROL_LIST,
1415 	EXTRA_MIME_TYPES,
1416 	LISTENING_PORTS,
1417 	DOCUMENT_ROOT,
1418 	SSL_CERTIFICATE,
1419 	NUM_THREADS,
1420 	RUN_AS_USER,
1421 	REWRITE,
1422 	HIDE_FILES,
1423 	REQUEST_TIMEOUT,
1424 	KEEP_ALIVE_TIMEOUT,
1425 	SSL_DO_VERIFY_PEER,
1426 	SSL_CA_PATH,
1427 	SSL_CA_FILE,
1428 	SSL_VERIFY_DEPTH,
1429 	SSL_DEFAULT_VERIFY_PATHS,
1430 	SSL_CIPHER_LIST,
1431 	SSL_PROTOCOL_VERSION,
1432 	SSL_SHORT_TRUST,
1433 
1434 #if defined(USE_WEBSOCKET)
1435 	WEBSOCKET_TIMEOUT,
1436 #endif
1437 
1438 	DECODE_URL,
1439 
1440 #if defined(USE_LUA)
1441 	LUA_PRELOAD_FILE,
1442 	LUA_SCRIPT_EXTENSIONS,
1443 	LUA_SERVER_PAGE_EXTENSIONS,
1444 #endif
1445 #if defined(USE_DUKTAPE)
1446 	DUKTAPE_SCRIPT_EXTENSIONS,
1447 #endif
1448 
1449 #if defined(USE_WEBSOCKET)
1450 	WEBSOCKET_ROOT,
1451 #endif
1452 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1453 	LUA_WEBSOCKET_EXTENSIONS,
1454 #endif
1455 
1456 	ACCESS_CONTROL_ALLOW_ORIGIN,
1457 	ERROR_PAGES,
1458 	CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
1459                          * socket option typedef TCP_NODELAY. */
1460 #if !defined(NO_CACHING)
1461 	STATIC_FILE_MAX_AGE,
1462 #endif
1463 #if defined(__linux__)
1464 	ALLOW_SENDFILE_CALL,
1465 #endif
1466 #if defined(_WIN32)
1467 	CASE_SENSITIVE_FILES,
1468 #endif
1469 
1470 	NUM_OPTIONS
1471 };
1472 
1473 
1474 /* Config option name, config types, default value */
1475 static struct mg_option config_options[] = {
1476     {"cgi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
1477     {"cgi_environment", CONFIG_TYPE_STRING, NULL},
1478     {"put_delete_auth_file", CONFIG_TYPE_FILE, NULL},
1479     {"cgi_interpreter", CONFIG_TYPE_FILE, NULL},
1480     {"protect_uri", CONFIG_TYPE_STRING, NULL},
1481     {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"},
1482     {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
1483     {"throttle", CONFIG_TYPE_STRING, NULL},
1484     {"access_log_file", CONFIG_TYPE_FILE, NULL},
1485     {"enable_directory_listing", CONFIG_TYPE_BOOLEAN, "yes"},
1486     {"error_log_file", CONFIG_TYPE_FILE, NULL},
1487     {"global_auth_file", CONFIG_TYPE_FILE, NULL},
1488     {"index_files",
1489      CONFIG_TYPE_STRING,
1490 #ifdef USE_LUA
1491      "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,"
1492      "index.shtml,index.php"},
1493 #else
1494      "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
1495 #endif
1496     {"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
1497     {"access_control_list", CONFIG_TYPE_STRING, NULL},
1498     {"extra_mime_types", CONFIG_TYPE_STRING, NULL},
1499     {"listening_ports", CONFIG_TYPE_STRING, "8080"},
1500     {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
1501     {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
1502     {"num_threads", CONFIG_TYPE_NUMBER, "50"},
1503     {"run_as_user", CONFIG_TYPE_STRING, NULL},
1504     {"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
1505     {"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
1506     {"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1507     {"keep_alive_timeout_ms", CONFIG_TYPE_NUMBER, "500"},
1508     {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
1509     {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
1510     {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
1511     {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
1512     {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
1513     {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
1514     {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
1515     {"ssl_short_trust", CONFIG_TYPE_BOOLEAN, "no"},
1516 #if defined(USE_WEBSOCKET)
1517     {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1518 #endif
1519     {"decode_url", CONFIG_TYPE_BOOLEAN, "yes"},
1520 
1521 #if defined(USE_LUA)
1522     {"lua_preload_file", CONFIG_TYPE_FILE, NULL},
1523     {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1524     {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
1525 #endif
1526 #if defined(USE_DUKTAPE)
1527     /* The support for duktape is still in alpha version state.
1528      * The name of this config option might change. */
1529     {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
1530 #endif
1531 
1532 #if defined(USE_WEBSOCKET)
1533     {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL},
1534 #endif
1535 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1536     {"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1537 #endif
1538     {"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
1539     {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
1540     {"tcp_nodelay", CONFIG_TYPE_NUMBER, "0"},
1541 #if !defined(NO_CACHING)
1542     {"static_file_max_age", CONFIG_TYPE_NUMBER, "3600"},
1543 #endif
1544 #if defined(__linux__)
1545     {"allow_sendfile_call", CONFIG_TYPE_BOOLEAN, "yes"},
1546 #endif
1547 #if defined(_WIN32)
1548     {"case_sensitive", CONFIG_TYPE_BOOLEAN, "no"},
1549 #endif
1550 
1551     {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
1552 
1553 /* Check if the config_options and the corresponding enum have compatible
1554  * sizes. */
1555 mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
1556                      == (NUM_OPTIONS + 1),
1557                  "config_options and enum not sync");
1558 
1559 enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
1560 
1561 struct mg_handler_info {
1562 	/* Name/Pattern of the URI. */
1563 	char *uri;
1564 	size_t uri_len;
1565 
1566 	/* handler type */
1567 	int handler_type;
1568 
1569 	/* Handler for http/https or authorization requests. */
1570 	mg_request_handler handler;
1571 
1572 	/* Handler for ws/wss (websocket) requests. */
1573 	mg_websocket_connect_handler connect_handler;
1574 	mg_websocket_ready_handler ready_handler;
1575 	mg_websocket_data_handler data_handler;
1576 	mg_websocket_close_handler close_handler;
1577 
1578 	/* accepted subprotocols for ws/wss requests. */
1579 	struct mg_websocket_subprotocols *subprotocols;
1580 
1581 	/* Handler for authorization requests */
1582 	mg_authorization_handler auth_handler;
1583 
1584 	/* User supplied argument for the handler function. */
1585 	void *cbdata;
1586 
1587 	/* next handler in a linked list */
1588 	struct mg_handler_info *next;
1589 };
1590 
1591 struct mg_context {
1592 	volatile int stop_flag;        /* Should we stop event loop */
1593 	SSL_CTX *ssl_ctx;              /* SSL context */
1594 	char *config[NUM_OPTIONS];     /* Civetweb configuration parameters */
1595 	struct mg_callbacks callbacks; /* User-defined callback function */
1596 	void *user_data;               /* User-defined data */
1597 	int context_type;              /* 1 = server context,
1598 	                                * 2 = ws/wss client context,
1599 	                                */
1600 
1601 	struct socket *listening_sockets;
1602 	struct pollfd *listening_socket_fds;
1603 	unsigned int num_listening_sockets;
1604 
1605 	pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
1606 
1607 #ifdef ALTERNATIVE_QUEUE
1608 	struct socket *client_socks;
1609 	void **client_wait_events;
1610 #else
1611 	struct socket queue[MGSQLEN]; /* Accepted sockets */
1612 	volatile int sq_head;         /* Head of the socket queue */
1613 	volatile int sq_tail;         /* Tail of the socket queue */
1614 	pthread_cond_t sq_full;       /* Signaled when socket is produced */
1615 	pthread_cond_t sq_empty;      /* Signaled when socket is consumed */
1616 #endif
1617 
1618 	pthread_t masterthreadid; /* The master thread ID */
1619 	unsigned int
1620 	    cfg_worker_threads;     /* The number of configured worker threads. */
1621 	pthread_t *workerthreadids; /* The worker thread IDs */
1622 
1623 	time_t start_time;        /* Server start time, used for authentication */
1624 	uint64_t auth_nonce_mask; /* Mask for all nonce values */
1625 	pthread_mutex_t nonce_mutex; /* Protects nonce_count */
1626 	unsigned long nonce_count;   /* Used nonces, used for authentication */
1627 
1628 	char *systemName; /* What operating system is running */
1629 
1630 	/* linked list of uri handlers */
1631 	struct mg_handler_info *handlers;
1632 
1633 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1634 	/* linked list of shared lua websockets */
1635 	struct mg_shared_lua_websocket_list *shared_lua_websockets;
1636 #endif
1637 
1638 #ifdef USE_TIMERS
1639 	struct ttimers *timers;
1640 #endif
1641 };
1642 
1643 
1644 struct mg_connection {
1645 	struct mg_request_info request_info;
1646 	struct mg_context *ctx;
1647 	SSL *ssl;                 /* SSL descriptor */
1648 	SSL_CTX *client_ssl_ctx;  /* SSL context for client connections */
1649 	struct socket client;     /* Connected client */
1650 	time_t conn_birth_time;   /* Time (wall clock) when connection was
1651 	                           * established */
1652 	struct timespec req_time; /* Time (since system start) when the request
1653 	                           * was received */
1654 	int64_t num_bytes_sent;   /* Total bytes sent to client */
1655 	int64_t content_len;      /* Content-Length header value */
1656 	int64_t consumed_content; /* How many bytes of content have been read */
1657 	int is_chunked;           /* Transfer-Encoding is chunked: 0=no, 1=yes:
1658 	                           * data available, 2: all data read */
1659 	size_t chunk_remainder;   /* Unread data from the last chunk */
1660 	char *buf;                /* Buffer for received data */
1661 	char *path_info;          /* PATH_INFO part of the URL */
1662 
1663 	int must_close;       /* 1 if connection must be closed */
1664 	int in_error_handler; /* 1 if in handler for user defined error
1665 	                       * pages */
1666 	int handled_requests; /* Number of requests handled by this connection */
1667 	int buf_size;         /* Buffer size */
1668 	int request_len;      /* Size of the request + headers in a buffer */
1669 	int data_len;         /* Total size of data in a buffer */
1670 	int status_code;      /* HTTP reply status code, e.g. 200 */
1671 	int throttle;         /* Throttling, bytes/sec. <= 0 means no
1672 	                       * throttle */
1673 	time_t last_throttle_time;   /* Last time throttled data was sent */
1674 	int64_t last_throttle_bytes; /* Bytes sent this second */
1675 	pthread_mutex_t mutex;       /* Used by mg_(un)lock_connection to ensure
1676 	                              * atomic transmissions for websockets */
1677 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1678 	void *lua_websocket_state; /* Lua_State for a websocket connection */
1679 #endif
1680 
1681 	int thread_index; /* Thread index within ctx */
1682 };
1683 
1684 
1685 static pthread_key_t sTlsKey; /* Thread local storage index */
1686 static int sTlsInit = 0;
1687 static int thread_idx_max = 0;
1688 
1689 
1690 struct mg_workerTLS {
1691 	int is_master;
1692 	unsigned long thread_idx;
1693 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1694 	HANDLE pthread_cond_helper_mutex;
1695 	struct mg_workerTLS *next_waiting_thread;
1696 #endif
1697 };
1698 
1699 /* Directory entry */
1700 struct de {
1701 	struct mg_connection *conn;
1702 	char *file_name;
1703 	struct mg_file_stat file;
1704 };
1705 
1706 
1707 #if defined(USE_WEBSOCKET)
1708 static int is_websocket_protocol(const struct mg_connection *conn);
1709 #else
1710 #define is_websocket_protocol(conn) (0)
1711 #endif
1712 
1713 
1714 static int
mg_atomic_inc(volatile int * addr)1715 mg_atomic_inc(volatile int *addr)
1716 {
1717 	int ret;
1718 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1719 	/* Depending on the SDK, this function uses either
1720 	 * (volatile unsigned int *) or (volatile LONG *),
1721 	 * so whatever you use, the other SDK is likely to raise a warning. */
1722 	ret = InterlockedIncrement((volatile long *)addr);
1723 #elif defined(__GNUC__)                                                        \
1724     && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1725 	ret = __sync_add_and_fetch(addr, 1);
1726 #else
1727 	ret = (++(*addr));
1728 #endif
1729 	return ret;
1730 }
1731 
1732 
1733 static int
mg_atomic_dec(volatile int * addr)1734 mg_atomic_dec(volatile int *addr)
1735 {
1736 	int ret;
1737 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1738 	/* Depending on the SDK, this function uses either
1739 	 * (volatile unsigned int *) or (volatile LONG *),
1740 	 * so whatever you use, the other SDK is likely to raise a warning. */
1741 	ret = InterlockedDecrement((volatile long *)addr);
1742 #elif defined(__GNUC__)                                                        \
1743     && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1744 	ret = __sync_sub_and_fetch(addr, 1);
1745 #else
1746 	ret = (--(*addr));
1747 #endif
1748 	return ret;
1749 }
1750 
1751 #if !defined(NO_THREAD_NAME)
1752 #if defined(_WIN32) && defined(_MSC_VER)
1753 /* Set the thread name for debugging purposes in Visual Studio
1754  * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
1755  */
1756 #pragma pack(push, 8)
1757 typedef struct tagTHREADNAME_INFO {
1758 	DWORD dwType;     /* Must be 0x1000. */
1759 	LPCSTR szName;    /* Pointer to name (in user addr space). */
1760 	DWORD dwThreadID; /* Thread ID (-1=caller thread). */
1761 	DWORD dwFlags;    /* Reserved for future use, must be zero. */
1762 } THREADNAME_INFO;
1763 #pragma pack(pop)
1764 
1765 #elif defined(__linux__)
1766 
1767 #include <sys/prctl.h>
1768 #include <sys/sendfile.h>
1769 #include <sys/eventfd.h>
1770 
1771 
1772 #if defined(ALTERNATIVE_QUEUE)
1773 
1774 static void *
event_create(void)1775 event_create(void)
1776 {
1777 	int ret = eventfd(0, EFD_CLOEXEC);
1778 	if (ret == -1) {
1779 		/* Linux uses -1 on error, Windows NULL. */
1780 		/* However, Linux does not return 0 on success either. */
1781 		return 0;
1782 	}
1783 	return (void *)ret;
1784 }
1785 
1786 
1787 static int
event_wait(void * eventhdl)1788 event_wait(void *eventhdl)
1789 {
1790 	uint64_t u;
1791 	int s = (int)read((int)eventhdl, &u, sizeof(u));
1792 	if (s != sizeof(uint64_t)) {
1793 		/* error */
1794 		return 0;
1795 	}
1796 	(void)u; /* the value is not required */
1797 	return 1;
1798 }
1799 
1800 
1801 static int
event_signal(void * eventhdl)1802 event_signal(void *eventhdl)
1803 {
1804 	uint64_t u = 1;
1805 	int s = (int)write((int)eventhdl, &u, sizeof(u));
1806 	if (s != sizeof(uint64_t)) {
1807 		/* error */
1808 		return 0;
1809 	}
1810 	return 1;
1811 }
1812 
1813 
1814 static void
event_destroy(void * eventhdl)1815 event_destroy(void *eventhdl)
1816 {
1817 	close((int)eventhdl);
1818 }
1819 #endif
1820 
1821 #endif
1822 
1823 
1824 #if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
1825 
1826 struct posix_event {
1827 	pthread_mutex_t mutex;
1828 	pthread_cond_t cond;
1829 };
1830 
1831 
1832 static void *
event_create(void)1833 event_create(void)
1834 {
1835 	struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
1836 	if (ret == 0) {
1837 		/* out of memory */
1838 		return 0;
1839 	}
1840 	if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
1841 		/* pthread mutex not available */
1842 		mg_free(ret);
1843 		return 0;
1844 	}
1845 	if (0 != pthread_cond_init(&(ret->cond), NULL)) {
1846 		/* pthread cond not available */
1847 		pthread_mutex_destroy(&(ret->mutex));
1848 		mg_free(ret);
1849 		return 0;
1850 	}
1851 	return (void *)ret;
1852 }
1853 
1854 
1855 static int
event_wait(void * eventhdl)1856 event_wait(void *eventhdl)
1857 {
1858 	struct posix_event *ev = (struct posix_event *)eventhdl;
1859 	pthread_mutex_lock(&(ev->mutex));
1860 	pthread_cond_wait(&(ev->cond), &(ev->mutex));
1861 	pthread_mutex_unlock(&(ev->mutex));
1862 	return 1;
1863 }
1864 
1865 
1866 static int
event_signal(void * eventhdl)1867 event_signal(void *eventhdl)
1868 {
1869 	struct posix_event *ev = (struct posix_event *)eventhdl;
1870 	pthread_mutex_lock(&(ev->mutex));
1871 	pthread_cond_signal(&(ev->cond));
1872 	pthread_mutex_unlock(&(ev->mutex));
1873 	return 1;
1874 }
1875 
1876 
1877 static void
event_destroy(void * eventhdl)1878 event_destroy(void *eventhdl)
1879 {
1880 	struct posix_event *ev = (struct posix_event *)eventhdl;
1881 	pthread_cond_destroy(&(ev->cond));
1882 	pthread_mutex_destroy(&(ev->mutex));
1883 	mg_free(ev);
1884 }
1885 #endif
1886 
1887 
1888 static void
mg_set_thread_name(const char * name)1889 mg_set_thread_name(const char *name)
1890 {
1891 	char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
1892 
1893 	mg_snprintf(
1894 	    NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
1895 
1896 #if defined(_WIN32)
1897 #if defined(_MSC_VER)
1898 	/* Windows and Visual Studio Compiler */
1899 	__try
1900 	{
1901 		THREADNAME_INFO info;
1902 		info.dwType = 0x1000;
1903 		info.szName = threadName;
1904 		info.dwThreadID = ~0U;
1905 		info.dwFlags = 0;
1906 
1907 		RaiseException(0x406D1388,
1908 		               0,
1909 		               sizeof(info) / sizeof(ULONG_PTR),
1910 		               (ULONG_PTR *)&info);
1911 	}
1912 	__except(EXCEPTION_EXECUTE_HANDLER)
1913 	{
1914 	}
1915 #elif defined(__MINGW32__)
1916 /* No option known to set thread name for MinGW */
1917 #endif
1918 #elif defined(__GLIBC__)                                                       \
1919     && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
1920 	/* pthread_setname_np first appeared in glibc in version 2.12*/
1921 	(void)pthread_setname_np(pthread_self(), threadName);
1922 #elif defined(__linux__)
1923 	/* on linux we can use the old prctl function */
1924 	(void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
1925 #endif
1926 }
1927 #else /* !defined(NO_THREAD_NAME) */
1928 void
mg_set_thread_name(const char * threadName)1929 mg_set_thread_name(const char *threadName)
1930 {
1931 }
1932 #endif
1933 
1934 
1935 #if defined(MG_LEGACY_INTERFACE)
1936 const char **
mg_get_valid_option_names(void)1937 mg_get_valid_option_names(void)
1938 {
1939 	/* This function is deprecated. Use mg_get_valid_options instead. */
1940 	static const char *
1941 	    data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
1942 	int i;
1943 
1944 	for (i = 0; config_options[i].name != NULL; i++) {
1945 		data[i * 2] = config_options[i].name;
1946 		data[i * 2 + 1] = config_options[i].default_value;
1947 	}
1948 
1949 	return data;
1950 }
1951 #endif
1952 
1953 
1954 const struct mg_option *
mg_get_valid_options(void)1955 mg_get_valid_options(void)
1956 {
1957 	return config_options;
1958 }
1959 
1960 
1961 /* Do not open file (used in is_file_in_memory) */
1962 #define MG_FOPEN_MODE_NONE (0)
1963 
1964 /* Open file for read only access */
1965 #define MG_FOPEN_MODE_READ (1)
1966 
1967 /* Open file for writing, create and overwrite */
1968 #define MG_FOPEN_MODE_WRITE (2)
1969 
1970 /* Open file for writing, create and append */
1971 #define MG_FOPEN_MODE_APPEND (4)
1972 
1973 
1974 /* If a file is in memory, set all "stat" members and the membuf pointer of
1975  * output filep and return 1, otherwise return 0 and don't modify anything. */
1976 static int
open_file_in_memory(const struct mg_connection * conn,const char * path,struct mg_file * filep,int mode)1977 open_file_in_memory(const struct mg_connection *conn,
1978                     const char *path,
1979                     struct mg_file *filep,
1980                     int mode)
1981 {
1982 	size_t size = 0;
1983 	const char *buf = NULL;
1984 	if (!conn) {
1985 		return 0;
1986 	}
1987 
1988 	if ((mode != MG_FOPEN_MODE_NONE) && (mode != MG_FOPEN_MODE_READ)) {
1989 		return 0;
1990 	}
1991 
1992 	if (conn->ctx->callbacks.open_file) {
1993 		buf = conn->ctx->callbacks.open_file(conn, path, &size);
1994 		if (buf != NULL) {
1995 			if (filep == NULL) {
1996 				/* This is a file in memory, but we cannot store the properties
1997 				 * now.
1998 				 * Called from "is_file_in_memory" function. */
1999 				return 1;
2000 			}
2001 
2002 			/* NOTE: override filep->size only on success. Otherwise, it might
2003 			 * break constructs like if (!mg_stat() || !mg_fopen()) ... */
2004 			filep->access.membuf = buf;
2005 			filep->access.fp = NULL;
2006 
2007 			/* Size was set by the callback */
2008 			filep->stat.size = size;
2009 
2010 			/* Assume the data may change during runtime by setting
2011 			 * last_modified = now */
2012 			filep->stat.last_modified = time(NULL);
2013 
2014 			filep->stat.is_directory = 0;
2015 			filep->stat.is_gzipped = 0;
2016 		}
2017 	}
2018 
2019 	return (buf != NULL);
2020 }
2021 
2022 
2023 static int
is_file_in_memory(const struct mg_connection * conn,const char * path)2024 is_file_in_memory(const struct mg_connection *conn, const char *path)
2025 {
2026 	return open_file_in_memory(conn, path, NULL, MG_FOPEN_MODE_NONE);
2027 }
2028 
2029 
2030 static int
is_file_opened(const struct mg_file_access * fileacc)2031 is_file_opened(const struct mg_file_access *fileacc)
2032 {
2033 	if (!fileacc) {
2034 		return 0;
2035 	}
2036 	return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
2037 }
2038 
2039 
2040 static int mg_stat(const struct mg_connection *conn,
2041                    const char *path,
2042                    struct mg_file_stat *filep);
2043 
2044 
2045 /* mg_fopen will open a file either in memory or on the disk.
2046  * The input parameter path is a string in UTF-8 encoding.
2047  * The input parameter mode is MG_FOPEN_MODE_*
2048  * On success, either fp or membuf will be set in the output
2049  * struct file. All status members will also be set.
2050  * The function returns 1 on success, 0 on error. */
2051 static int
mg_fopen(const struct mg_connection * conn,const char * path,int mode,struct mg_file * filep)2052 mg_fopen(const struct mg_connection *conn,
2053          const char *path,
2054          int mode,
2055          struct mg_file *filep)
2056 {
2057 	int found;
2058 
2059 	if (!filep) {
2060 		return 0;
2061 	}
2062 	filep->access.fp = NULL;
2063 	filep->access.membuf = NULL;
2064 
2065 	if (!is_file_in_memory(conn, path)) {
2066 
2067 		/* filep is initialized in mg_stat: all fields with memset to,
2068 		* some fields like size and modification date with values */
2069 		found = mg_stat(conn, path, &(filep->stat));
2070 
2071 		if ((mode == MG_FOPEN_MODE_READ) && (!found)) {
2072 			/* file does not exist and will not be created */
2073 			return 0;
2074 		}
2075 
2076 #ifdef _WIN32
2077 		{
2078 			wchar_t wbuf[PATH_MAX];
2079 			path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
2080 			switch (mode) {
2081 			case MG_FOPEN_MODE_READ:
2082 				filep->access.fp = _wfopen(wbuf, L"rb");
2083 				break;
2084 			case MG_FOPEN_MODE_WRITE:
2085 				filep->access.fp = _wfopen(wbuf, L"wb");
2086 				break;
2087 			case MG_FOPEN_MODE_APPEND:
2088 				filep->access.fp = _wfopen(wbuf, L"ab");
2089 				break;
2090 			}
2091 		}
2092 #else
2093 		/* Linux et al already use unicode. No need to convert. */
2094 		switch (mode) {
2095 		case MG_FOPEN_MODE_READ:
2096 			filep->access.fp = fopen(path, "r");
2097 			break;
2098 		case MG_FOPEN_MODE_WRITE:
2099 			filep->access.fp = fopen(path, "w");
2100 			break;
2101 		case MG_FOPEN_MODE_APPEND:
2102 			filep->access.fp = fopen(path, "a");
2103 			break;
2104 		}
2105 
2106 #endif
2107 		if (!found) {
2108 			/* File did not exist before fopen was called.
2109 			 * Maybe it has been created now. Get stat info
2110 			 * like creation time now. */
2111 			found = mg_stat(conn, path, &(filep->stat));
2112 			(void)found;
2113 		}
2114 
2115 		/* file is on disk */
2116 		return (filep->access.fp != NULL);
2117 
2118 	} else {
2119 		/* is_file_in_memory returned true */
2120 		if (open_file_in_memory(conn, path, filep, mode)) {
2121 			/* file is in memory */
2122 			return (filep->access.membuf != NULL);
2123 		}
2124 	}
2125 
2126 	/* Open failed */
2127 	return 0;
2128 }
2129 
2130 
2131 /* return 0 on success, just like fclose */
2132 static int
mg_fclose(struct mg_file_access * fileacc)2133 mg_fclose(struct mg_file_access *fileacc)
2134 {
2135 	int ret = -1;
2136 	if (fileacc != NULL) {
2137 		if (fileacc->fp != NULL) {
2138 			ret = fclose(fileacc->fp);
2139 		} else if (fileacc->membuf != NULL) {
2140 			ret = 0;
2141 		}
2142 		/* reset all members of fileacc */
2143 		memset(fileacc, 0, sizeof(*fileacc));
2144 	}
2145 	return ret;
2146 }
2147 
2148 
2149 static void
mg_strlcpy(register char * dst,register const char * src,size_t n)2150 mg_strlcpy(register char *dst, register const char *src, size_t n)
2151 {
2152 	for (; *src != '\0' && n > 1; n--) {
2153 		*dst++ = *src++;
2154 	}
2155 	*dst = '\0';
2156 }
2157 
2158 
2159 static int
lowercase(const char * s)2160 lowercase(const char *s)
2161 {
2162 	return tolower(*(const unsigned char *)s);
2163 }
2164 
2165 
2166 int
mg_strncasecmp(const char * s1,const char * s2,size_t len)2167 mg_strncasecmp(const char *s1, const char *s2, size_t len)
2168 {
2169 	int diff = 0;
2170 
2171 	if (len > 0) {
2172 		do {
2173 			diff = lowercase(s1++) - lowercase(s2++);
2174 		} while (diff == 0 && s1[-1] != '\0' && --len > 0);
2175 	}
2176 
2177 	return diff;
2178 }
2179 
2180 
2181 int
mg_strcasecmp(const char * s1,const char * s2)2182 mg_strcasecmp(const char *s1, const char *s2)
2183 {
2184 	int diff;
2185 
2186 	do {
2187 		diff = lowercase(s1++) - lowercase(s2++);
2188 	} while (diff == 0 && s1[-1] != '\0');
2189 
2190 	return diff;
2191 }
2192 
2193 
2194 static char *
mg_strndup(const char * ptr,size_t len)2195 mg_strndup(const char *ptr, size_t len)
2196 {
2197 	char *p;
2198 
2199 	if ((p = (char *)mg_malloc(len + 1)) != NULL) {
2200 		mg_strlcpy(p, ptr, len + 1);
2201 	}
2202 
2203 	return p;
2204 }
2205 
2206 
2207 static char *
mg_strdup(const char * str)2208 mg_strdup(const char *str)
2209 {
2210 	return mg_strndup(str, strlen(str));
2211 }
2212 
2213 
2214 static const char *
mg_strcasestr(const char * big_str,const char * small_str)2215 mg_strcasestr(const char *big_str, const char *small_str)
2216 {
2217 	size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
2218 
2219 	if (big_len >= small_len) {
2220 		for (i = 0; i <= (big_len - small_len); i++) {
2221 			if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
2222 				return big_str + i;
2223 			}
2224 		}
2225 	}
2226 
2227 	return NULL;
2228 }
2229 
2230 
2231 /* Return null terminated string of given maximum length.
2232  * Report errors if length is exceeded. */
2233 static void
mg_vsnprintf(const struct mg_connection * conn,int * truncated,char * buf,size_t buflen,const char * fmt,va_list ap)2234 mg_vsnprintf(const struct mg_connection *conn,
2235              int *truncated,
2236              char *buf,
2237              size_t buflen,
2238              const char *fmt,
2239              va_list ap)
2240 {
2241 	int n, ok;
2242 
2243 	if (buflen == 0) {
2244 		return;
2245 	}
2246 
2247 #ifdef __clang__
2248 #pragma clang diagnostic push
2249 #pragma clang diagnostic ignored "-Wformat-nonliteral"
2250 /* Using fmt as a non-literal is intended here, since it is mostly called
2251  * indirectly by mg_snprintf */
2252 #endif
2253 
2254 	n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
2255 	ok = (n >= 0) && ((size_t)n < buflen);
2256 
2257 #ifdef __clang__
2258 #pragma clang diagnostic pop
2259 #endif
2260 
2261 	if (ok) {
2262 		if (truncated) {
2263 			*truncated = 0;
2264 		}
2265 	} else {
2266 		if (truncated) {
2267 			*truncated = 1;
2268 		}
2269 		mg_cry(conn,
2270 		       "truncating vsnprintf buffer: [%.*s]",
2271 		       (int)((buflen > 200) ? 200 : (buflen - 1)),
2272 		       buf);
2273 		n = (int)buflen - 1;
2274 	}
2275 	buf[n] = '\0';
2276 }
2277 
2278 
2279 static void
mg_snprintf(const struct mg_connection * conn,int * truncated,char * buf,size_t buflen,const char * fmt,...)2280 mg_snprintf(const struct mg_connection *conn,
2281             int *truncated,
2282             char *buf,
2283             size_t buflen,
2284             const char *fmt,
2285             ...)
2286 {
2287 	va_list ap;
2288 
2289 	va_start(ap, fmt);
2290 	mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
2291 	va_end(ap);
2292 }
2293 
2294 
2295 static int
get_option_index(const char * name)2296 get_option_index(const char *name)
2297 {
2298 	int i;
2299 
2300 	for (i = 0; config_options[i].name != NULL; i++) {
2301 		if (strcmp(config_options[i].name, name) == 0) {
2302 			return i;
2303 		}
2304 	}
2305 	return -1;
2306 }
2307 
2308 
2309 const char *
mg_get_option(const struct mg_context * ctx,const char * name)2310 mg_get_option(const struct mg_context *ctx, const char *name)
2311 {
2312 	int i;
2313 	if ((i = get_option_index(name)) == -1) {
2314 		return NULL;
2315 	} else if (!ctx || ctx->config[i] == NULL) {
2316 		return "";
2317 	} else {
2318 		return ctx->config[i];
2319 	}
2320 }
2321 
2322 
2323 struct mg_context *
mg_get_context(const struct mg_connection * conn)2324 mg_get_context(const struct mg_connection *conn)
2325 {
2326 	return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
2327 }
2328 
2329 
2330 void *
mg_get_user_data(const struct mg_context * ctx)2331 mg_get_user_data(const struct mg_context *ctx)
2332 {
2333 	return (ctx == NULL) ? NULL : ctx->user_data;
2334 }
2335 
2336 
2337 void
mg_set_user_connection_data(struct mg_connection * conn,void * data)2338 mg_set_user_connection_data(struct mg_connection *conn, void *data)
2339 {
2340 	if (conn != NULL) {
2341 		conn->request_info.conn_data = data;
2342 	}
2343 }
2344 
2345 
2346 void *
mg_get_user_connection_data(const struct mg_connection * conn)2347 mg_get_user_connection_data(const struct mg_connection *conn)
2348 {
2349 	if (conn != NULL) {
2350 		return conn->request_info.conn_data;
2351 	}
2352 	return NULL;
2353 }
2354 
2355 
2356 size_t
mg_get_ports(const struct mg_context * ctx,size_t size,int * ports,int * ssl)2357 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
2358 {
2359 	size_t i;
2360 	if (!ctx) {
2361 		return 0;
2362 	}
2363 	for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
2364 		ssl[i] = ctx->listening_sockets[i].is_ssl;
2365 		ports[i] =
2366 #if defined(USE_IPV6)
2367 		    (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
2368 		        ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
2369 		        :
2370 #endif
2371 		        ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
2372 	}
2373 	return i;
2374 }
2375 
2376 
2377 int
mg_get_server_ports(const struct mg_context * ctx,int size,struct mg_server_ports * ports)2378 mg_get_server_ports(const struct mg_context *ctx,
2379                     int size,
2380                     struct mg_server_ports *ports)
2381 {
2382 	int i, cnt = 0;
2383 
2384 	if (size <= 0) {
2385 		return -1;
2386 	}
2387 	memset(ports, 0, sizeof(*ports) * (size_t)size);
2388 	if (!ctx) {
2389 		return -1;
2390 	}
2391 	if (!ctx->listening_sockets) {
2392 		return -1;
2393 	}
2394 
2395 	for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
2396 
2397 		ports[cnt].port =
2398 #if defined(USE_IPV6)
2399 		    (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
2400 		        ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
2401 		        :
2402 #endif
2403 		        ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
2404 		ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
2405 		ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
2406 
2407 		if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
2408 			/* IPv4 */
2409 			ports[cnt].protocol = 1;
2410 			cnt++;
2411 		} else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
2412 			/* IPv6 */
2413 			ports[cnt].protocol = 3;
2414 			cnt++;
2415 		}
2416 	}
2417 
2418 	return cnt;
2419 }
2420 
2421 
2422 static void
sockaddr_to_string(char * buf,size_t len,const union usa * usa)2423 sockaddr_to_string(char *buf, size_t len, const union usa *usa)
2424 {
2425 	buf[0] = '\0';
2426 
2427 	if (!usa) {
2428 		return;
2429 	}
2430 
2431 	if (usa->sa.sa_family == AF_INET) {
2432 		getnameinfo(&usa->sa,
2433 		            sizeof(usa->sin),
2434 		            buf,
2435 		            (unsigned)len,
2436 		            NULL,
2437 		            0,
2438 		            NI_NUMERICHOST);
2439 	}
2440 #if defined(USE_IPV6)
2441 	else if (usa->sa.sa_family == AF_INET6) {
2442 		getnameinfo(&usa->sa,
2443 		            sizeof(usa->sin6),
2444 		            buf,
2445 		            (unsigned)len,
2446 		            NULL,
2447 		            0,
2448 		            NI_NUMERICHOST);
2449 	}
2450 #endif
2451 }
2452 
2453 
2454 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
2455  * included in all responses other than 100, 101, 5xx. */
2456 static void
gmt_time_string(char * buf,size_t buf_len,time_t * t)2457 gmt_time_string(char *buf, size_t buf_len, time_t *t)
2458 {
2459 	struct tm *tm;
2460 
2461 	tm = ((t != NULL) ? gmtime(t) : NULL);
2462 	if (tm != NULL) {
2463 		strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
2464 	} else {
2465 		mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
2466 		buf[buf_len - 1] = '\0';
2467 	}
2468 }
2469 
2470 
2471 /* difftime for struct timespec. Return value is in seconds. */
2472 static double
mg_difftimespec(const struct timespec * ts_now,const struct timespec * ts_before)2473 mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
2474 {
2475 	return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
2476 	       + (double)(ts_now->tv_sec - ts_before->tv_sec);
2477 }
2478 
2479 
2480 /* Print error message to the opened error log stream. */
2481 void
mg_cry(const struct mg_connection * conn,const char * fmt,...)2482 mg_cry(const struct mg_connection *conn, const char *fmt, ...)
2483 {
2484 	char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
2485 	va_list ap;
2486 	struct mg_file fi;
2487 	time_t timestamp;
2488 
2489 	va_start(ap, fmt);
2490 	IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
2491 	va_end(ap);
2492 	buf[sizeof(buf) - 1] = 0;
2493 
2494 	if (!conn) {
2495 		puts(buf);
2496 		return;
2497 	}
2498 
2499 	/* Do not lock when getting the callback value, here and below.
2500 	 * I suppose this is fine, since function cannot disappear in the
2501 	 * same way string option can. */
2502 	if ((conn->ctx->callbacks.log_message == NULL)
2503 	    || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
2504 
2505 		if (conn->ctx->config[ERROR_LOG_FILE] != NULL) {
2506 			if (mg_fopen(conn,
2507 			             conn->ctx->config[ERROR_LOG_FILE],
2508 			             MG_FOPEN_MODE_APPEND,
2509 			             &fi) == 0) {
2510 				fi.access.fp = NULL;
2511 			}
2512 		} else {
2513 			fi.access.fp = NULL;
2514 		}
2515 
2516 		if (fi.access.fp != NULL) {
2517 			flockfile(fi.access.fp);
2518 			timestamp = time(NULL);
2519 
2520 			sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
2521 			fprintf(fi.access.fp,
2522 			        "[%010lu] [error] [client %s] ",
2523 			        (unsigned long)timestamp,
2524 			        src_addr);
2525 
2526 			if (conn->request_info.request_method != NULL) {
2527 				fprintf(fi.access.fp,
2528 				        "%s %s: ",
2529 				        conn->request_info.request_method,
2530 				        conn->request_info.request_uri);
2531 			}
2532 
2533 			fprintf(fi.access.fp, "%s", buf);
2534 			fputc('\n', fi.access.fp);
2535 			fflush(fi.access.fp);
2536 			funlockfile(fi.access.fp);
2537 			(void)mg_fclose(&fi.access); /* Ignore errors. We can't call
2538 			                              * mg_cry here anyway ;-) */
2539 		}
2540 	}
2541 }
2542 
2543 
2544 /* Return fake connection structure. Used for logging, if connection
2545  * is not applicable at the moment of logging. */
2546 static struct mg_connection *
fc(struct mg_context * ctx)2547 fc(struct mg_context *ctx)
2548 {
2549 	static struct mg_connection fake_connection;
2550 	fake_connection.ctx = ctx;
2551 	return &fake_connection;
2552 }
2553 
2554 
2555 const char *
mg_version(void)2556 mg_version(void)
2557 {
2558 	return CIVETWEB_VERSION;
2559 }
2560 
2561 
2562 const struct mg_request_info *
mg_get_request_info(const struct mg_connection * conn)2563 mg_get_request_info(const struct mg_connection *conn)
2564 {
2565 	if (!conn) {
2566 		return NULL;
2567 	}
2568 	return &conn->request_info;
2569 }
2570 
2571 
2572 /* Skip the characters until one of the delimiters characters found.
2573  * 0-terminate resulting word. Skip the delimiter and following whitespaces.
2574  * Advance pointer to buffer to the next word. Return found 0-terminated word.
2575  * Delimiters can be quoted with quotechar. */
2576 static char *
skip_quoted(char ** buf,const char * delimiters,const char * whitespace,char quotechar)2577 skip_quoted(char **buf,
2578             const char *delimiters,
2579             const char *whitespace,
2580             char quotechar)
2581 {
2582 	char *p, *begin_word, *end_word, *end_whitespace;
2583 
2584 	begin_word = *buf;
2585 	end_word = begin_word + strcspn(begin_word, delimiters);
2586 
2587 	/* Check for quotechar */
2588 	if (end_word > begin_word) {
2589 		p = end_word - 1;
2590 		while (*p == quotechar) {
2591 			/* While the delimiter is quoted, look for the next delimiter. */
2592 			/* This happens, e.g., in calls from parse_auth_header,
2593 			 * if the user name contains a " character. */
2594 
2595 			/* If there is anything beyond end_word, copy it. */
2596 			if (*end_word != '\0') {
2597 				size_t end_off = strcspn(end_word + 1, delimiters);
2598 				memmove(p, end_word, end_off + 1);
2599 				p += end_off; /* p must correspond to end_word - 1 */
2600 				end_word += end_off + 1;
2601 			} else {
2602 				*p = '\0';
2603 				break;
2604 			}
2605 		}
2606 		for (p++; p < end_word; p++) {
2607 			*p = '\0';
2608 		}
2609 	}
2610 
2611 	if (*end_word == '\0') {
2612 		*buf = end_word;
2613 	} else {
2614 
2615 #if defined(__MINGW32__) || defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
2616 /* Disable spurious conversion warning for GCC */
2617 #pragma GCC diagnostic push
2618 #pragma GCC diagnostic ignored "-Wsign-conversion"
2619 #endif
2620 
2621 		end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
2622 
2623 #if defined(__MINGW32__) || defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
2624 #pragma GCC diagnostic pop
2625 #endif
2626 
2627 		for (p = end_word; p < end_whitespace; p++) {
2628 			*p = '\0';
2629 		}
2630 
2631 		*buf = end_whitespace;
2632 	}
2633 
2634 	return begin_word;
2635 }
2636 
2637 
2638 /* Simplified version of skip_quoted without quote char
2639  * and whitespace == delimiters */
2640 static char *
skip(char ** buf,const char * delimiters)2641 skip(char **buf, const char *delimiters)
2642 {
2643 	return skip_quoted(buf, delimiters, delimiters, 0);
2644 }
2645 
2646 
2647 /* Return HTTP header value, or NULL if not found. */
2648 static const char *
get_header(const struct mg_request_info * ri,const char * name)2649 get_header(const struct mg_request_info *ri, const char *name)
2650 {
2651 	int i;
2652 	if (ri) {
2653 		for (i = 0; i < ri->num_headers; i++) {
2654 			if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
2655 				return ri->http_headers[i].value;
2656 			}
2657 		}
2658 	}
2659 
2660 	return NULL;
2661 }
2662 
2663 
2664 const char *
mg_get_header(const struct mg_connection * conn,const char * name)2665 mg_get_header(const struct mg_connection *conn, const char *name)
2666 {
2667 	if (!conn) {
2668 		return NULL;
2669 	}
2670 
2671 	return get_header(&conn->request_info, name);
2672 }
2673 
2674 
2675 /* A helper function for traversing a comma separated list of values.
2676  * It returns a list pointer shifted to the next value, or NULL if the end
2677  * of the list found.
2678  * Value is stored in val vector. If value has form "x=y", then eq_val
2679  * vector is initialized to point to the "y" part, and val vector length
2680  * is adjusted to point only to "x". */
2681 static const char *
next_option(const char * list,struct vec * val,struct vec * eq_val)2682 next_option(const char *list, struct vec *val, struct vec *eq_val)
2683 {
2684 	int end;
2685 
2686 reparse:
2687 	if (val == NULL || list == NULL || *list == '\0') {
2688 		/* End of the list */
2689 		list = NULL;
2690 	} else {
2691 		/* Skip over leading LWS */
2692 		while (*list == ' ' || *list == '\t')
2693 			list++;
2694 
2695 		val->ptr = list;
2696 		if ((list = strchr(val->ptr, ',')) != NULL) {
2697 			/* Comma found. Store length and shift the list ptr */
2698 			val->len = ((size_t)(list - val->ptr));
2699 			list++;
2700 		} else {
2701 			/* This value is the last one */
2702 			list = val->ptr + strlen(val->ptr);
2703 			val->len = ((size_t)(list - val->ptr));
2704 		}
2705 
2706 		/* Adjust length for trailing LWS */
2707 		end = (int)val->len - 1;
2708 		while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t'))
2709 			end--;
2710 		val->len = (size_t)(end + 1);
2711 
2712 		if (val->len == 0) {
2713 			/* Ignore any empty entries. */
2714 			goto reparse;
2715 		}
2716 
2717 		if (eq_val != NULL) {
2718 			/* Value has form "x=y", adjust pointers and lengths
2719 			 * so that val points to "x", and eq_val points to "y". */
2720 			eq_val->len = 0;
2721 			eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
2722 			if (eq_val->ptr != NULL) {
2723 				eq_val->ptr++; /* Skip over '=' character */
2724 				eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
2725 				val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
2726 			}
2727 		}
2728 	}
2729 
2730 	return list;
2731 }
2732 
2733 /* A helper function for checking if a comma separated list of values contains
2734  * the given option (case insensitvely).
2735  * 'header' can be NULL, in which case false is returned. */
2736 static int
header_has_option(const char * header,const char * option)2737 header_has_option(const char *header, const char *option)
2738 {
2739 	struct vec opt_vec;
2740 	struct vec eq_vec;
2741 
2742 	assert(option != NULL);
2743 	assert(option[0] != '\0');
2744 
2745 	while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
2746 		if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
2747 			return 1;
2748 	}
2749 
2750 	return 0;
2751 }
2752 
2753 /* Perform case-insensitive match of string against pattern */
2754 static int
match_prefix(const char * pattern,size_t pattern_len,const char * str)2755 match_prefix(const char *pattern, size_t pattern_len, const char *str)
2756 {
2757 	const char *or_str;
2758 	size_t i;
2759 	int j, len, res;
2760 
2761 	if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
2762 		res = match_prefix(pattern, (size_t)(or_str - pattern), str);
2763 		return (res > 0) ? res : match_prefix(or_str + 1,
2764 		                                      (size_t)((pattern + pattern_len)
2765 		                                               - (or_str + 1)),
2766 		                                      str);
2767 	}
2768 
2769 	for (i = 0, j = 0; i < pattern_len; i++, j++) {
2770 		if (pattern[i] == '?' && str[j] != '\0') {
2771 			continue;
2772 		} else if (pattern[i] == '$') {
2773 			return (str[j] == '\0') ? j : -1;
2774 		} else if (pattern[i] == '*') {
2775 			i++;
2776 			if (pattern[i] == '*') {
2777 				i++;
2778 				len = (int)strlen(str + j);
2779 			} else {
2780 				len = (int)strcspn(str + j, "/");
2781 			}
2782 			if (i == pattern_len) {
2783 				return j + len;
2784 			}
2785 			do {
2786 				res = match_prefix(pattern + i, pattern_len - i, str + j + len);
2787 			} while (res == -1 && len-- > 0);
2788 			return (res == -1) ? -1 : j + res + len;
2789 		} else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
2790 			return -1;
2791 		}
2792 	}
2793 	return j;
2794 }
2795 
2796 
2797 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
2798  * This function must tolerate situations when connection info is not
2799  * set up, for example if request parsing failed. */
2800 static int
should_keep_alive(const struct mg_connection * conn)2801 should_keep_alive(const struct mg_connection *conn)
2802 {
2803 	if (conn != NULL) {
2804 		const char *http_version = conn->request_info.http_version;
2805 		const char *header = mg_get_header(conn, "Connection");
2806 		if (conn->must_close || conn->status_code == 401
2807 		    || mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0
2808 		    || (header != NULL && !header_has_option(header, "keep-alive"))
2809 		    || (header == NULL && http_version
2810 		        && 0 != strcmp(http_version, "1.1"))) {
2811 			return 0;
2812 		}
2813 		return 1;
2814 	}
2815 	return 0;
2816 }
2817 
2818 
2819 static int
should_decode_url(const struct mg_connection * conn)2820 should_decode_url(const struct mg_connection *conn)
2821 {
2822 	if (!conn || !conn->ctx) {
2823 		return 0;
2824 	}
2825 
2826 	return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
2827 }
2828 
2829 
2830 static const char *
suggest_connection_header(const struct mg_connection * conn)2831 suggest_connection_header(const struct mg_connection *conn)
2832 {
2833 	return should_keep_alive(conn) ? "keep-alive" : "close";
2834 }
2835 
2836 
2837 static int
send_no_cache_header(struct mg_connection * conn)2838 send_no_cache_header(struct mg_connection *conn)
2839 {
2840 	/* Send all current and obsolete cache opt-out directives. */
2841 	return mg_printf(conn,
2842 	                 "Cache-Control: no-cache, no-store, "
2843 	                 "must-revalidate, private, max-age=0\r\n"
2844 	                 "Pragma: no-cache\r\n"
2845 	                 "Expires: 0\r\n");
2846 }
2847 
2848 
2849 static int
send_static_cache_header(struct mg_connection * conn)2850 send_static_cache_header(struct mg_connection *conn)
2851 {
2852 #if !defined(NO_CACHING)
2853 	/* Read the server config to check how long a file may be cached.
2854 	 * The configuration is in seconds. */
2855 	int max_age = atoi(conn->ctx->config[STATIC_FILE_MAX_AGE]);
2856 	if (max_age <= 0) {
2857 		/* 0 means "do not cache". All values <0 are reserved
2858 		 * and may be used differently in the future. */
2859 		/* If a file should not be cached, do not only send
2860 		 * max-age=0, but also pragmas and Expires headers. */
2861 		return send_no_cache_header(conn);
2862 	}
2863 
2864 	/* Use "Cache-Control: max-age" instead of "Expires" header.
2865 	 * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
2866 	/* See also https://www.mnot.net/cache_docs/ */
2867 	/* According to RFC 2616, Section 14.21, caching times should not exceed
2868 	 * one year. A year with 365 days corresponds to 31536000 seconds, a leap
2869 	 * year to 31622400 seconds. For the moment, we just send whatever has
2870 	 * been configured, still the behavior for >1 year should be considered
2871 	 * as undefined. */
2872 	return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
2873 #else  /* NO_CACHING */
2874 	return send_no_cache_header(conn);
2875 #endif /* !NO_CACHING */
2876 }
2877 
2878 
2879 static void handle_file_based_request(struct mg_connection *conn,
2880                                       const char *path,
2881                                       struct mg_file *filep);
2882 
2883 
2884 const char *
mg_get_response_code_text(struct mg_connection * conn,int response_code)2885 mg_get_response_code_text(struct mg_connection *conn, int response_code)
2886 {
2887 	/* See IANA HTTP status code assignment:
2888 	 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
2889 	 */
2890 
2891 	switch (response_code) {
2892 	/* RFC2616 Section 10.1 - Informational 1xx */
2893 	case 100:
2894 		return "Continue"; /* RFC2616 Section 10.1.1 */
2895 	case 101:
2896 		return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
2897 	case 102:
2898 		return "Processing"; /* RFC2518 Section 10.1 */
2899 
2900 	/* RFC2616 Section 10.2 - Successful 2xx */
2901 	case 200:
2902 		return "OK"; /* RFC2616 Section 10.2.1 */
2903 	case 201:
2904 		return "Created"; /* RFC2616 Section 10.2.2 */
2905 	case 202:
2906 		return "Accepted"; /* RFC2616 Section 10.2.3 */
2907 	case 203:
2908 		return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
2909 	case 204:
2910 		return "No Content"; /* RFC2616 Section 10.2.5 */
2911 	case 205:
2912 		return "Reset Content"; /* RFC2616 Section 10.2.6 */
2913 	case 206:
2914 		return "Partial Content"; /* RFC2616 Section 10.2.7 */
2915 	case 207:
2916 		return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
2917 	case 208:
2918 		return "Already Reported"; /* RFC5842 Section 7.1 */
2919 
2920 	case 226:
2921 		return "IM used"; /* RFC3229 Section 10.4.1 */
2922 
2923 	/* RFC2616 Section 10.3 - Redirection 3xx */
2924 	case 300:
2925 		return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
2926 	case 301:
2927 		return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
2928 	case 302:
2929 		return "Found"; /* RFC2616 Section 10.3.3 */
2930 	case 303:
2931 		return "See Other"; /* RFC2616 Section 10.3.4 */
2932 	case 304:
2933 		return "Not Modified"; /* RFC2616 Section 10.3.5 */
2934 	case 305:
2935 		return "Use Proxy"; /* RFC2616 Section 10.3.6 */
2936 	case 307:
2937 		return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
2938 	case 308:
2939 		return "Permanent Redirect"; /* RFC7238 Section 3 */
2940 
2941 	/* RFC2616 Section 10.4 - Client Error 4xx */
2942 	case 400:
2943 		return "Bad Request"; /* RFC2616 Section 10.4.1 */
2944 	case 401:
2945 		return "Unauthorized"; /* RFC2616 Section 10.4.2 */
2946 	case 402:
2947 		return "Payment Required"; /* RFC2616 Section 10.4.3 */
2948 	case 403:
2949 		return "Forbidden"; /* RFC2616 Section 10.4.4 */
2950 	case 404:
2951 		return "Not Found"; /* RFC2616 Section 10.4.5 */
2952 	case 405:
2953 		return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
2954 	case 406:
2955 		return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
2956 	case 407:
2957 		return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
2958 	case 408:
2959 		return "Request Time-out"; /* RFC2616 Section 10.4.9 */
2960 	case 409:
2961 		return "Conflict"; /* RFC2616 Section 10.4.10 */
2962 	case 410:
2963 		return "Gone"; /* RFC2616 Section 10.4.11 */
2964 	case 411:
2965 		return "Length Required"; /* RFC2616 Section 10.4.12 */
2966 	case 412:
2967 		return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
2968 	case 413:
2969 		return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
2970 	case 414:
2971 		return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
2972 	case 415:
2973 		return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
2974 	case 416:
2975 		return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
2976 	case 417:
2977 		return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
2978 
2979 	case 421:
2980 		return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
2981 	case 422:
2982 		return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
2983 		                                 * Section 11.2 */
2984 	case 423:
2985 		return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
2986 	case 424:
2987 		return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
2988 		                             * Section 11.4 */
2989 
2990 	case 426:
2991 		return "Upgrade Required"; /* RFC 2817 Section 4 */
2992 
2993 	case 428:
2994 		return "Precondition Required"; /* RFC 6585, Section 3 */
2995 	case 429:
2996 		return "Too Many Requests"; /* RFC 6585, Section 4 */
2997 
2998 	case 431:
2999 		return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
3000 
3001 	case 451:
3002 		return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
3003 		                                         * Section 3 */
3004 
3005 	/* RFC2616 Section 10.5 - Server Error 5xx */
3006 	case 500:
3007 		return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
3008 	case 501:
3009 		return "Not Implemented"; /* RFC2616 Section 10.5.2 */
3010 	case 502:
3011 		return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
3012 	case 503:
3013 		return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
3014 	case 504:
3015 		return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
3016 	case 505:
3017 		return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
3018 	case 506:
3019 		return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
3020 	case 507:
3021 		return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
3022 		                                * Section 11.5 */
3023 	case 508:
3024 		return "Loop Detected"; /* RFC5842 Section 7.1 */
3025 
3026 	case 510:
3027 		return "Not Extended"; /* RFC 2774, Section 7 */
3028 	case 511:
3029 		return "Network Authentication Required"; /* RFC 6585, Section 6 */
3030 
3031 	/* Other status codes, not shown in the IANA HTTP status code assignment.
3032 	 * E.g., "de facto" standards due to common use, ... */
3033 	case 418:
3034 		return "I am a teapot"; /* RFC2324 Section 2.3.2 */
3035 	case 419:
3036 		return "Authentication Timeout"; /* common use */
3037 	case 420:
3038 		return "Enhance Your Calm"; /* common use */
3039 	case 440:
3040 		return "Login Timeout"; /* common use */
3041 	case 509:
3042 		return "Bandwidth Limit Exceeded"; /* common use */
3043 
3044 	default:
3045 		/* This error code is unknown. This should not happen. */
3046 		if (conn) {
3047 			mg_cry(conn, "Unknown HTTP response code: %u", response_code);
3048 		}
3049 
3050 		/* Return at least a category according to RFC 2616 Section 10. */
3051 		if (response_code >= 100 && response_code < 200) {
3052 			/* Unknown informational status code */
3053 			return "Information";
3054 		}
3055 		if (response_code >= 200 && response_code < 300) {
3056 			/* Unknown success code */
3057 			return "Success";
3058 		}
3059 		if (response_code >= 300 && response_code < 400) {
3060 			/* Unknown redirection code */
3061 			return "Redirection";
3062 		}
3063 		if (response_code >= 400 && response_code < 500) {
3064 			/* Unknown request error code */
3065 			return "Client Error";
3066 		}
3067 		if (response_code >= 500 && response_code < 600) {
3068 			/* Unknown server error code */
3069 			return "Server Error";
3070 		}
3071 
3072 		/* Response code not even within reasonable range */
3073 		return "";
3074 	}
3075 }
3076 
3077 
3078 static void send_http_error(struct mg_connection *,
3079                             int,
3080                             PRINTF_FORMAT_STRING(const char *fmt),
3081                             ...) PRINTF_ARGS(3, 4);
3082 
3083 static void
send_http_error(struct mg_connection * conn,int status,const char * fmt,...)3084 send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
3085 {
3086 	char buf[MG_BUF_LEN];
3087 	va_list ap;
3088 	int len, i, page_handler_found, scope, truncated, has_body;
3089 	char date[64];
3090 	time_t curtime = time(NULL);
3091 	const char *error_handler = NULL;
3092 	struct mg_file error_page_file = STRUCT_FILE_INITIALIZER;
3093 	const char *error_page_file_ext, *tstr;
3094 
3095 	const char *status_text = mg_get_response_code_text(conn, status);
3096 
3097 	if (conn == NULL) {
3098 		return;
3099 	}
3100 
3101 	conn->status_code = status;
3102 	if (conn->in_error_handler || conn->ctx->callbacks.http_error == NULL
3103 	    || conn->ctx->callbacks.http_error(conn, status)) {
3104 		if (!conn->in_error_handler) {
3105 			/* Send user defined error pages, if defined */
3106 			error_handler = conn->ctx->config[ERROR_PAGES];
3107 			error_page_file_ext = conn->ctx->config[INDEX_FILES];
3108 			page_handler_found = 0;
3109 			if (error_handler != NULL) {
3110 				for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
3111 					switch (scope) {
3112 					case 1: /* Handler for specific error, e.g. 404 error */
3113 						mg_snprintf(conn,
3114 						            &truncated,
3115 						            buf,
3116 						            sizeof(buf) - 32,
3117 						            "%serror%03u.",
3118 						            error_handler,
3119 						            status);
3120 						break;
3121 					case 2: /* Handler for error group, e.g., 5xx error handler
3122 					         * for all server errors (500-599) */
3123 						mg_snprintf(conn,
3124 						            &truncated,
3125 						            buf,
3126 						            sizeof(buf) - 32,
3127 						            "%serror%01uxx.",
3128 						            error_handler,
3129 						            status / 100);
3130 						break;
3131 					default: /* Handler for all errors */
3132 						mg_snprintf(conn,
3133 						            &truncated,
3134 						            buf,
3135 						            sizeof(buf) - 32,
3136 						            "%serror.",
3137 						            error_handler);
3138 						break;
3139 					}
3140 
3141 					/* String truncation in buf may only occur if error_handler
3142 					 * is too long. This string is from the config, not from a
3143 					 * client. */
3144 					(void)truncated;
3145 
3146 					len = (int)strlen(buf);
3147 
3148 					tstr = strchr(error_page_file_ext, '.');
3149 
3150 					while (tstr) {
3151 						for (i = 1; i < 32 && tstr[i] != 0 && tstr[i] != ',';
3152 						     i++)
3153 							buf[len + i - 1] = tstr[i];
3154 						buf[len + i - 1] = 0;
3155 						if (mg_stat(conn, buf, &error_page_file.stat)) {
3156 							page_handler_found = 1;
3157 							break;
3158 						}
3159 						tstr = strchr(tstr + i, '.');
3160 					}
3161 				}
3162 			}
3163 
3164 			if (page_handler_found) {
3165 				conn->in_error_handler = 1;
3166 				handle_file_based_request(conn, buf, &error_page_file);
3167 				conn->in_error_handler = 0;
3168 				return;
3169 			}
3170 		}
3171 
3172 		/* No custom error page. Send default error page. */
3173 		gmt_time_string(date, sizeof(date), &curtime);
3174 
3175 		/* Errors 1xx, 204 and 304 MUST NOT send a body */
3176 		has_body = (status > 199 && status != 204 && status != 304);
3177 
3178 		conn->must_close = 1;
3179 		mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
3180 		send_no_cache_header(conn);
3181 		if (has_body) {
3182 			mg_printf(conn,
3183 			          "%s",
3184 			          "Content-Type: text/plain; charset=utf-8\r\n");
3185 		}
3186 		mg_printf(conn,
3187 		          "Date: %s\r\n"
3188 		          "Connection: close\r\n\r\n",
3189 		          date);
3190 
3191 		/* Errors 1xx, 204 and 304 MUST NOT send a body */
3192 		if (has_body) {
3193 			mg_printf(conn, "Error %d: %s\n", status, status_text);
3194 
3195 			if (fmt != NULL) {
3196 				va_start(ap, fmt);
3197 				mg_vsnprintf(conn, NULL, buf, sizeof(buf), fmt, ap);
3198 				va_end(ap);
3199 				mg_write(conn, buf, strlen(buf));
3200 				DEBUG_TRACE("Error %i - [%s]", status, buf);
3201 			}
3202 
3203 		} else {
3204 			/* No body allowed. Close the connection. */
3205 			DEBUG_TRACE("Error %i", status);
3206 		}
3207 	}
3208 }
3209 
3210 #if defined(_WIN32) && !defined(__SYMBIAN32__)
3211 /* Create substitutes for POSIX functions in Win32. */
3212 
3213 #if defined(__MINGW32__)
3214 /* Show no warning in case system functions are not used. */
3215 #pragma GCC diagnostic push
3216 #pragma GCC diagnostic ignored "-Wunused-function"
3217 #endif
3218 
3219 
3220 static int
pthread_mutex_init(pthread_mutex_t * mutex,void * unused)3221 pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
3222 {
3223 	(void)unused;
3224 	*mutex = CreateMutex(NULL, FALSE, NULL);
3225 	return (*mutex == NULL) ? -1 : 0;
3226 }
3227 
3228 
3229 static int
pthread_mutex_destroy(pthread_mutex_t * mutex)3230 pthread_mutex_destroy(pthread_mutex_t *mutex)
3231 {
3232 	return (CloseHandle(*mutex) == 0) ? -1 : 0;
3233 }
3234 
3235 
3236 static int
pthread_mutex_lock(pthread_mutex_t * mutex)3237 pthread_mutex_lock(pthread_mutex_t *mutex)
3238 {
3239 	return (WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
3240 }
3241 
3242 
3243 #ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS
3244 static int
pthread_mutex_trylock(pthread_mutex_t * mutex)3245 pthread_mutex_trylock(pthread_mutex_t *mutex)
3246 {
3247 	switch (WaitForSingleObject(*mutex, 0)) {
3248 	case WAIT_OBJECT_0:
3249 		return 0;
3250 	case WAIT_TIMEOUT:
3251 		return -2; /* EBUSY */
3252 	}
3253 	return -1;
3254 }
3255 #endif
3256 
3257 
3258 static int
pthread_mutex_unlock(pthread_mutex_t * mutex)3259 pthread_mutex_unlock(pthread_mutex_t *mutex)
3260 {
3261 	return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
3262 }
3263 
3264 
3265 static int
pthread_cond_init(pthread_cond_t * cv,const void * unused)3266 pthread_cond_init(pthread_cond_t *cv, const void *unused)
3267 {
3268 	(void)unused;
3269 	InitializeCriticalSection(&cv->threadIdSec);
3270 	cv->waiting_thread = NULL;
3271 	return 0;
3272 }
3273 
3274 
3275 static int
pthread_cond_timedwait(pthread_cond_t * cv,pthread_mutex_t * mutex,const struct timespec * abstime)3276 pthread_cond_timedwait(pthread_cond_t *cv,
3277                        pthread_mutex_t *mutex,
3278                        const struct timespec *abstime)
3279 {
3280 	struct mg_workerTLS **ptls,
3281 	    *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3282 	int ok;
3283 	struct timespec tsnow;
3284 	int64_t nsnow, nswaitabs, nswaitrel;
3285 	DWORD mswaitrel;
3286 
3287 	EnterCriticalSection(&cv->threadIdSec);
3288 	/* Add this thread to cv's waiting list */
3289 	ptls = &cv->waiting_thread;
3290 	for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
3291 		;
3292 	tls->next_waiting_thread = NULL;
3293 	*ptls = tls;
3294 	LeaveCriticalSection(&cv->threadIdSec);
3295 
3296 	if (abstime) {
3297 		clock_gettime(CLOCK_REALTIME, &tsnow);
3298 		nsnow = (((int64_t)tsnow.tv_sec) * 1000000000) + tsnow.tv_nsec;
3299 		nswaitabs =
3300 		    (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
3301 		nswaitrel = nswaitabs - nsnow;
3302 		if (nswaitrel < 0) {
3303 			nswaitrel = 0;
3304 		}
3305 		mswaitrel = (DWORD)(nswaitrel / 1000000);
3306 	} else {
3307 		mswaitrel = INFINITE;
3308 	}
3309 
3310 	pthread_mutex_unlock(mutex);
3311 	ok = (WAIT_OBJECT_0
3312 	      == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
3313 	if (!ok) {
3314 		ok = 1;
3315 		EnterCriticalSection(&cv->threadIdSec);
3316 		ptls = &cv->waiting_thread;
3317 		for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
3318 			if (*ptls == tls) {
3319 				*ptls = tls->next_waiting_thread;
3320 				ok = 0;
3321 				break;
3322 			}
3323 		}
3324 		LeaveCriticalSection(&cv->threadIdSec);
3325 		if (ok) {
3326 			WaitForSingleObject(tls->pthread_cond_helper_mutex, INFINITE);
3327 		}
3328 	}
3329 	/* This thread has been removed from cv's waiting list */
3330 	pthread_mutex_lock(mutex);
3331 
3332 	return ok ? 0 : -1;
3333 }
3334 
3335 
3336 static int
pthread_cond_wait(pthread_cond_t * cv,pthread_mutex_t * mutex)3337 pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
3338 {
3339 	return pthread_cond_timedwait(cv, mutex, NULL);
3340 }
3341 
3342 
3343 static int
pthread_cond_signal(pthread_cond_t * cv)3344 pthread_cond_signal(pthread_cond_t *cv)
3345 {
3346 	HANDLE wkup = NULL;
3347 	BOOL ok = FALSE;
3348 
3349 	EnterCriticalSection(&cv->threadIdSec);
3350 	if (cv->waiting_thread) {
3351 		wkup = cv->waiting_thread->pthread_cond_helper_mutex;
3352 		cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
3353 
3354 		ok = SetEvent(wkup);
3355 		assert(ok);
3356 	}
3357 	LeaveCriticalSection(&cv->threadIdSec);
3358 
3359 	return ok ? 0 : 1;
3360 }
3361 
3362 
3363 static int
pthread_cond_broadcast(pthread_cond_t * cv)3364 pthread_cond_broadcast(pthread_cond_t *cv)
3365 {
3366 	EnterCriticalSection(&cv->threadIdSec);
3367 	while (cv->waiting_thread) {
3368 		pthread_cond_signal(cv);
3369 	}
3370 	LeaveCriticalSection(&cv->threadIdSec);
3371 
3372 	return 0;
3373 }
3374 
3375 
3376 static int
pthread_cond_destroy(pthread_cond_t * cv)3377 pthread_cond_destroy(pthread_cond_t *cv)
3378 {
3379 	EnterCriticalSection(&cv->threadIdSec);
3380 	assert(cv->waiting_thread == NULL);
3381 	LeaveCriticalSection(&cv->threadIdSec);
3382 	DeleteCriticalSection(&cv->threadIdSec);
3383 
3384 	return 0;
3385 }
3386 
3387 
3388 #ifdef ALTERNATIVE_QUEUE
3389 static void *
event_create(void)3390 event_create(void)
3391 {
3392 	return (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
3393 }
3394 
3395 
3396 static int
event_wait(void * eventhdl)3397 event_wait(void *eventhdl)
3398 {
3399 	int res = WaitForSingleObject((HANDLE)eventhdl, INFINITE);
3400 	return (res == WAIT_OBJECT_0);
3401 }
3402 
3403 
3404 static int
event_signal(void * eventhdl)3405 event_signal(void *eventhdl)
3406 {
3407 	return (int)SetEvent((HANDLE)eventhdl);
3408 }
3409 
3410 
3411 static void
event_destroy(void * eventhdl)3412 event_destroy(void *eventhdl)
3413 {
3414 	CloseHandle((HANDLE)eventhdl);
3415 }
3416 #endif
3417 
3418 
3419 #if defined(__MINGW32__)
3420 /* Enable unused function warning again */
3421 #pragma GCC diagnostic pop
3422 #endif
3423 
3424 
3425 /* For Windows, change all slashes to backslashes in path names. */
3426 static void
change_slashes_to_backslashes(char * path)3427 change_slashes_to_backslashes(char *path)
3428 {
3429 	int i;
3430 
3431 	for (i = 0; path[i] != '\0'; i++) {
3432 		if (path[i] == '/') {
3433 			path[i] = '\\';
3434 		}
3435 
3436 		/* remove double backslash (check i > 0 to preserve UNC paths,
3437 		 * like \\server\file.txt) */
3438 		if ((path[i] == '\\') && (i > 0)) {
3439 			while (path[i + 1] == '\\' || path[i + 1] == '/') {
3440 				(void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
3441 			}
3442 		}
3443 	}
3444 }
3445 
3446 
3447 static int
mg_wcscasecmp(const wchar_t * s1,const wchar_t * s2)3448 mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
3449 {
3450 	int diff;
3451 
3452 	do {
3453 		diff = tolower(*s1) - tolower(*s2);
3454 		s1++;
3455 		s2++;
3456 	} while (diff == 0 && s1[-1] != '\0');
3457 
3458 	return diff;
3459 }
3460 
3461 
3462 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
3463  * wbuf and wbuf_len is a target buffer and its length. */
3464 static void
path_to_unicode(const struct mg_connection * conn,const char * path,wchar_t * wbuf,size_t wbuf_len)3465 path_to_unicode(const struct mg_connection *conn,
3466                 const char *path,
3467                 wchar_t *wbuf,
3468                 size_t wbuf_len)
3469 {
3470 	char buf[PATH_MAX], buf2[PATH_MAX];
3471 	wchar_t wbuf2[MAX_PATH + 1];
3472 	DWORD long_len, err;
3473 	int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
3474 
3475 	mg_strlcpy(buf, path, sizeof(buf));
3476 	change_slashes_to_backslashes(buf);
3477 
3478 	/* Convert to Unicode and back. If doubly-converted string does not
3479 	 * match the original, something is fishy, reject. */
3480 	memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
3481 	MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
3482 	WideCharToMultiByte(
3483 	    CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
3484 	if (strcmp(buf, buf2) != 0) {
3485 		wbuf[0] = L'\0';
3486 	}
3487 
3488 	/* Windows file systems are not case sensitive, but you can still use
3489 	 * uppercase and lowercase letters (on all modern file systems).
3490 	 * The server can check if the URI uses the same upper/lowercase
3491 	 * letters an the file system, effectively making Windows servers
3492 	 * case sensitive (like Linux servers are). It is still not possible
3493 	 * to use two files with the same name in different cases on Windows
3494 	 * (like /a and /A) - this would be possible in Linux.
3495 	 * As a default, Windows is not case sensitive, but the case sensitive
3496 	 * file name check can be activated by an additional configuration. */
3497 	if (conn) {
3498 		if (conn->ctx->config[CASE_SENSITIVE_FILES]
3499 		    && !mg_strcasecmp(conn->ctx->config[CASE_SENSITIVE_FILES], "yes")) {
3500 			/* Use case sensitive compare function */
3501 			fcompare = wcscmp;
3502 		}
3503 	}
3504 	(void)conn; /* conn is currently unused */
3505 
3506 #if !defined(_WIN32_WCE)
3507 	/* Only accept a full file path, not a Windows short (8.3) path. */
3508 	memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
3509 	long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
3510 	if (long_len == 0) {
3511 		err = GetLastError();
3512 		if (err == ERROR_FILE_NOT_FOUND) {
3513 			/* File does not exist. This is not always a problem here. */
3514 			return;
3515 		}
3516 	}
3517 	if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
3518 		/* Short name is used. */
3519 		wbuf[0] = L'\0';
3520 	}
3521 #else
3522 	(void)long_len;
3523 	(void)wbuf2;
3524 	(void)err;
3525 
3526 	if (strchr(path, '~')) {
3527 		wbuf[0] = L'\0';
3528 	}
3529 #endif
3530 }
3531 
3532 
3533 /* Windows happily opens files with some garbage at the end of file name.
3534  * For example, fopen("a.cgi    ", "r") on Windows successfully opens
3535  * "a.cgi", despite one would expect an error back.
3536  * This function returns non-0 if path ends with some garbage. */
3537 static int
path_cannot_disclose_cgi(const char * path)3538 path_cannot_disclose_cgi(const char *path)
3539 {
3540 	static const char *allowed_last_characters = "_-";
3541 	int last = path[strlen(path) - 1];
3542 	return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
3543 }
3544 
3545 
3546 static int
mg_stat(const struct mg_connection * conn,const char * path,struct mg_file_stat * filep)3547 mg_stat(const struct mg_connection *conn,
3548         const char *path,
3549         struct mg_file_stat *filep)
3550 {
3551 	wchar_t wbuf[PATH_MAX];
3552 	WIN32_FILE_ATTRIBUTE_DATA info;
3553 	time_t creation_time;
3554 
3555 	if (!filep) {
3556 		return 0;
3557 	}
3558 	memset(filep, 0, sizeof(*filep));
3559 
3560 	if (conn && is_file_in_memory(conn, path)) {
3561 		/* filep->is_directory = 0; filep->gzipped = 0; .. already done by
3562 		 * memset */
3563 		filep->last_modified = time(NULL); /* xxxxxxxx */
3564 		/* last_modified = now ... assumes the file may change during runtime,
3565 		 * so every mg_fopen call may return different data */
3566 		/* last_modified = conn->ctx.start_time;
3567 		 * May be used it the data does not change during runtime. This allows
3568 		 * browser caching. Since we do not know, we have to assume the file
3569 		 * in memory may change. */
3570 		return 1;
3571 	}
3572 
3573 	path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3574 	if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
3575 		filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
3576 		filep->last_modified =
3577 		    SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
3578 		                  info.ftLastWriteTime.dwHighDateTime);
3579 
3580 		/* On Windows, the file creation time can be higher than the
3581 		 * modification time, e.g. when a file is copied.
3582 		 * Since the Last-Modified timestamp is used for caching
3583 		 * it should be based on the most recent timestamp. */
3584 		creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
3585 		                              info.ftCreationTime.dwHighDateTime);
3586 		if (creation_time > filep->last_modified) {
3587 			filep->last_modified = creation_time;
3588 		}
3589 
3590 		filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3591 		/* If file name is fishy, reset the file structure and return
3592 		 * error.
3593 		 * Note it is important to reset, not just return the error, cause
3594 		 * functions like is_file_opened() check the struct. */
3595 		if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
3596 			memset(filep, 0, sizeof(*filep));
3597 			return 0;
3598 		}
3599 
3600 		return 1;
3601 	}
3602 
3603 	return 0;
3604 }
3605 
3606 
3607 static int
mg_remove(const struct mg_connection * conn,const char * path)3608 mg_remove(const struct mg_connection *conn, const char *path)
3609 {
3610 	wchar_t wbuf[PATH_MAX];
3611 	path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3612 	return DeleteFileW(wbuf) ? 0 : -1;
3613 }
3614 
3615 
3616 static int
mg_mkdir(const struct mg_connection * conn,const char * path,int mode)3617 mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
3618 {
3619 	wchar_t wbuf[PATH_MAX];
3620 	(void)mode;
3621 	path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3622 	return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
3623 }
3624 
3625 
3626 /* Create substitutes for POSIX functions in Win32. */
3627 
3628 #if defined(__MINGW32__)
3629 /* Show no warning in case system functions are not used. */
3630 #pragma GCC diagnostic push
3631 #pragma GCC diagnostic ignored "-Wunused-function"
3632 #endif
3633 
3634 
3635 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
3636 static DIR *
mg_opendir(const struct mg_connection * conn,const char * name)3637 mg_opendir(const struct mg_connection *conn, const char *name)
3638 {
3639 	DIR *dir = NULL;
3640 	wchar_t wpath[PATH_MAX];
3641 	DWORD attrs;
3642 
3643 	if (name == NULL) {
3644 		SetLastError(ERROR_BAD_ARGUMENTS);
3645 	} else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
3646 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3647 	} else {
3648 		path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
3649 		attrs = GetFileAttributesW(wpath);
3650 		if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
3651 		                            == FILE_ATTRIBUTE_DIRECTORY)) {
3652 			(void)wcscat(wpath, L"\\*");
3653 			dir->handle = FindFirstFileW(wpath, &dir->info);
3654 			dir->result.d_name[0] = '\0';
3655 		} else {
3656 			mg_free(dir);
3657 			dir = NULL;
3658 		}
3659 	}
3660 
3661 	return dir;
3662 }
3663 
3664 
3665 static int
mg_closedir(DIR * dir)3666 mg_closedir(DIR *dir)
3667 {
3668 	int result = 0;
3669 
3670 	if (dir != NULL) {
3671 		if (dir->handle != INVALID_HANDLE_VALUE)
3672 			result = FindClose(dir->handle) ? 0 : -1;
3673 
3674 		mg_free(dir);
3675 	} else {
3676 		result = -1;
3677 		SetLastError(ERROR_BAD_ARGUMENTS);
3678 	}
3679 
3680 	return result;
3681 }
3682 
3683 
3684 static struct dirent *
mg_readdir(DIR * dir)3685 mg_readdir(DIR *dir)
3686 {
3687 	struct dirent *result = 0;
3688 
3689 	if (dir) {
3690 		if (dir->handle != INVALID_HANDLE_VALUE) {
3691 			result = &dir->result;
3692 			(void)WideCharToMultiByte(CP_UTF8,
3693 			                          0,
3694 			                          dir->info.cFileName,
3695 			                          -1,
3696 			                          result->d_name,
3697 			                          sizeof(result->d_name),
3698 			                          NULL,
3699 			                          NULL);
3700 
3701 			if (!FindNextFileW(dir->handle, &dir->info)) {
3702 				(void)FindClose(dir->handle);
3703 				dir->handle = INVALID_HANDLE_VALUE;
3704 			}
3705 
3706 		} else {
3707 			SetLastError(ERROR_FILE_NOT_FOUND);
3708 		}
3709 	} else {
3710 		SetLastError(ERROR_BAD_ARGUMENTS);
3711 	}
3712 
3713 	return result;
3714 }
3715 
3716 
3717 #ifndef HAVE_POLL
3718 static int
poll(struct pollfd * pfd,unsigned int n,int milliseconds)3719 poll(struct pollfd *pfd, unsigned int n, int milliseconds)
3720 {
3721 	struct timeval tv;
3722 	fd_set set;
3723 	unsigned int i;
3724 	int result;
3725 	SOCKET maxfd = 0;
3726 
3727 	memset(&tv, 0, sizeof(tv));
3728 	tv.tv_sec = milliseconds / 1000;
3729 	tv.tv_usec = (milliseconds % 1000) * 1000;
3730 	FD_ZERO(&set);
3731 
3732 	for (i = 0; i < n; i++) {
3733 		FD_SET((SOCKET)pfd[i].fd, &set);
3734 		pfd[i].revents = 0;
3735 
3736 		if (pfd[i].fd > maxfd) {
3737 			maxfd = pfd[i].fd;
3738 		}
3739 	}
3740 
3741 	if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
3742 		for (i = 0; i < n; i++) {
3743 			if (FD_ISSET(pfd[i].fd, &set)) {
3744 				pfd[i].revents = POLLIN;
3745 			}
3746 		}
3747 	}
3748 
3749 	/* We should subtract the time used in select from remaining
3750 	 * "milliseconds", in particular if called from mg_poll with a
3751 	 * timeout quantum.
3752 	 * Unfortunately, the remaining time is not stored in "tv" in all
3753 	 * implementations, so the result in "tv" must be considered undefined.
3754 	 * See http://man7.org/linux/man-pages/man2/select.2.html */
3755 
3756 	return result;
3757 }
3758 #endif /* HAVE_POLL */
3759 
3760 
3761 #if defined(__MINGW32__)
3762 /* Enable unused function warning again */
3763 #pragma GCC diagnostic pop
3764 #endif
3765 
3766 
3767 static void
set_close_on_exec(SOCKET sock,struct mg_connection * conn)3768 set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
3769 {
3770 	(void)conn; /* Unused. */
3771 #if defined(_WIN32_WCE)
3772 	(void)sock;
3773 #else
3774 	(void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
3775 #endif
3776 }
3777 
3778 
3779 int
mg_start_thread(mg_thread_func_t f,void * p)3780 mg_start_thread(mg_thread_func_t f, void *p)
3781 {
3782 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3783 	/* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384
3784 	 */
3785 	return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
3786 	         == ((uintptr_t)(-1L)))
3787 	            ? -1
3788 	            : 0);
3789 #else
3790 	return (
3791 	    (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
3792 	        ? -1
3793 	        : 0);
3794 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3795 }
3796 
3797 
3798 /* Start a thread storing the thread context. */
3799 static int
mg_start_thread_with_id(unsigned (__stdcall * f)(void *),void * p,pthread_t * threadidptr)3800 mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
3801                         void *p,
3802                         pthread_t *threadidptr)
3803 {
3804 	uintptr_t uip;
3805 	HANDLE threadhandle;
3806 	int result = -1;
3807 
3808 	uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
3809 	threadhandle = (HANDLE)uip;
3810 	if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
3811 		*threadidptr = threadhandle;
3812 		result = 0;
3813 	}
3814 
3815 	return result;
3816 }
3817 
3818 
3819 /* Wait for a thread to finish. */
3820 static int
mg_join_thread(pthread_t threadid)3821 mg_join_thread(pthread_t threadid)
3822 {
3823 	int result;
3824 	DWORD dwevent;
3825 
3826 	result = -1;
3827 	dwevent = WaitForSingleObject(threadid, INFINITE);
3828 	if (dwevent == WAIT_FAILED) {
3829 		DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
3830 	} else {
3831 		if (dwevent == WAIT_OBJECT_0) {
3832 			CloseHandle(threadid);
3833 			result = 0;
3834 		}
3835 	}
3836 
3837 	return result;
3838 }
3839 
3840 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
3841 /* If SSL is loaded dynamically, dlopen/dlclose is required. */
3842 /* Create substitutes for POSIX functions in Win32. */
3843 
3844 #if defined(__MINGW32__)
3845 /* Show no warning in case system functions are not used. */
3846 #pragma GCC diagnostic push
3847 #pragma GCC diagnostic ignored "-Wunused-function"
3848 #endif
3849 
3850 
3851 static HANDLE
dlopen(const char * dll_name,int flags)3852 dlopen(const char *dll_name, int flags)
3853 {
3854 	wchar_t wbuf[PATH_MAX];
3855 	(void)flags;
3856 	path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
3857 	return LoadLibraryW(wbuf);
3858 }
3859 
3860 
3861 static int
dlclose(void * handle)3862 dlclose(void *handle)
3863 {
3864 	int result;
3865 
3866 	if (FreeLibrary((HMODULE)handle) != 0) {
3867 		result = 0;
3868 	} else {
3869 		result = -1;
3870 	}
3871 
3872 	return result;
3873 }
3874 
3875 
3876 #if defined(__MINGW32__)
3877 /* Enable unused function warning again */
3878 #pragma GCC diagnostic pop
3879 #endif
3880 
3881 #endif
3882 
3883 
3884 #if !defined(NO_CGI)
3885 #define SIGKILL (0)
3886 
3887 static int
kill(pid_t pid,int sig_num)3888 kill(pid_t pid, int sig_num)
3889 {
3890 	(void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
3891 	(void)CloseHandle((HANDLE)pid);
3892 	return 0;
3893 }
3894 
3895 
3896 static void
trim_trailing_whitespaces(char * s)3897 trim_trailing_whitespaces(char *s)
3898 {
3899 	char *e = s + strlen(s) - 1;
3900 	while (e > s && isspace(*(unsigned char *)e)) {
3901 		*e-- = '\0';
3902 	}
3903 }
3904 
3905 
3906 static pid_t
spawn_process(struct mg_connection * conn,const char * prog,char * envblk,char * envp[],int fdin[2],int fdout[2],int fderr[2],const char * dir)3907 spawn_process(struct mg_connection *conn,
3908               const char *prog,
3909               char *envblk,
3910               char *envp[],
3911               int fdin[2],
3912               int fdout[2],
3913               int fderr[2],
3914               const char *dir)
3915 {
3916 	HANDLE me;
3917 	char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
3918 	    cmdline[PATH_MAX], buf[PATH_MAX];
3919 	int truncated;
3920 	struct mg_file file = STRUCT_FILE_INITIALIZER;
3921 	STARTUPINFOA si;
3922 	PROCESS_INFORMATION pi = {0};
3923 
3924 	(void)envp;
3925 
3926 	memset(&si, 0, sizeof(si));
3927 	si.cb = sizeof(si);
3928 
3929 	si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3930 	si.wShowWindow = SW_HIDE;
3931 
3932 	me = GetCurrentProcess();
3933 	DuplicateHandle(me,
3934 	                (HANDLE)_get_osfhandle(fdin[0]),
3935 	                me,
3936 	                &si.hStdInput,
3937 	                0,
3938 	                TRUE,
3939 	                DUPLICATE_SAME_ACCESS);
3940 	DuplicateHandle(me,
3941 	                (HANDLE)_get_osfhandle(fdout[1]),
3942 	                me,
3943 	                &si.hStdOutput,
3944 	                0,
3945 	                TRUE,
3946 	                DUPLICATE_SAME_ACCESS);
3947 	DuplicateHandle(me,
3948 	                (HANDLE)_get_osfhandle(fderr[1]),
3949 	                me,
3950 	                &si.hStdError,
3951 	                0,
3952 	                TRUE,
3953 	                DUPLICATE_SAME_ACCESS);
3954 
3955 	/* Mark handles that should not be inherited. See
3956 	 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
3957 	 */
3958 	SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
3959 	                     HANDLE_FLAG_INHERIT,
3960 	                     0);
3961 	SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
3962 	                     HANDLE_FLAG_INHERIT,
3963 	                     0);
3964 	SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
3965 	                     HANDLE_FLAG_INHERIT,
3966 	                     0);
3967 
3968 	/* If CGI file is a script, try to read the interpreter line */
3969 	interp = conn->ctx->config[CGI_INTERPRETER];
3970 	if (interp == NULL) {
3971 		buf[0] = buf[1] = '\0';
3972 
3973 		/* Read the first line of the script into the buffer */
3974 		mg_snprintf(
3975 		    conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
3976 
3977 		if (truncated) {
3978 			pi.hProcess = (pid_t)-1;
3979 			goto spawn_cleanup;
3980 		}
3981 
3982 		if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) {
3983 			p = (char *)file.access.membuf;
3984 			mg_fgets(buf, sizeof(buf), &file, &p);
3985 			(void)mg_fclose(&file.access); /* ignore error on read only file */
3986 			buf[sizeof(buf) - 1] = '\0';
3987 		}
3988 
3989 		if (buf[0] == '#' && buf[1] == '!') {
3990 			trim_trailing_whitespaces(buf + 2);
3991 		} else {
3992 			buf[2] = '\0';
3993 		}
3994 		interp = buf + 2;
3995 	}
3996 
3997 	if (interp[0] != '\0') {
3998 		GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
3999 		interp = full_interp;
4000 	}
4001 	GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
4002 
4003 	if (interp[0] != '\0') {
4004 		mg_snprintf(conn,
4005 		            &truncated,
4006 		            cmdline,
4007 		            sizeof(cmdline),
4008 		            "\"%s\" \"%s\\%s\"",
4009 		            interp,
4010 		            full_dir,
4011 		            prog);
4012 	} else {
4013 		mg_snprintf(conn,
4014 		            &truncated,
4015 		            cmdline,
4016 		            sizeof(cmdline),
4017 		            "\"%s\\%s\"",
4018 		            full_dir,
4019 		            prog);
4020 	}
4021 
4022 	if (truncated) {
4023 		pi.hProcess = (pid_t)-1;
4024 		goto spawn_cleanup;
4025 	}
4026 
4027 	DEBUG_TRACE("Running [%s]", cmdline);
4028 	if (CreateProcessA(NULL,
4029 	                   cmdline,
4030 	                   NULL,
4031 	                   NULL,
4032 	                   TRUE,
4033 	                   CREATE_NEW_PROCESS_GROUP,
4034 	                   envblk,
4035 	                   NULL,
4036 	                   &si,
4037 	                   &pi) == 0) {
4038 		mg_cry(
4039 		    conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
4040 		pi.hProcess = (pid_t)-1;
4041 		/* goto spawn_cleanup; */
4042 	}
4043 
4044 spawn_cleanup:
4045 	(void)CloseHandle(si.hStdOutput);
4046 	(void)CloseHandle(si.hStdError);
4047 	(void)CloseHandle(si.hStdInput);
4048 	if (pi.hThread != NULL) {
4049 		(void)CloseHandle(pi.hThread);
4050 	}
4051 
4052 	return (pid_t)pi.hProcess;
4053 }
4054 #endif /* !NO_CGI */
4055 
4056 
4057 static int
set_blocking_mode(SOCKET sock,int blocking)4058 set_blocking_mode(SOCKET sock, int blocking)
4059 {
4060 	unsigned long non_blocking = !blocking;
4061 	return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
4062 }
4063 
4064 #else
4065 
4066 static int
mg_stat(const struct mg_connection * conn,const char * path,struct mg_file_stat * filep)4067 mg_stat(const struct mg_connection *conn,
4068         const char *path,
4069         struct mg_file_stat *filep)
4070 {
4071 	struct stat st;
4072 	if (!filep) {
4073 		return 0;
4074 	}
4075 	memset(filep, 0, sizeof(*filep));
4076 
4077 	if (conn && is_file_in_memory(conn, path)) {
4078 		return 1;
4079 	}
4080 
4081 	if (0 == stat(path, &st)) {
4082 		filep->size = (uint64_t)(st.st_size);
4083 		filep->last_modified = st.st_mtime;
4084 		filep->is_directory = S_ISDIR(st.st_mode);
4085 		return 1;
4086 	}
4087 
4088 	return 0;
4089 }
4090 
4091 
4092 static void
set_close_on_exec(SOCKET fd,struct mg_connection * conn)4093 set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
4094 {
4095 	if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
4096 		if (conn) {
4097 			mg_cry(conn,
4098 			       "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
4099 			       __func__,
4100 			       strerror(ERRNO));
4101 		}
4102 	}
4103 }
4104 
4105 
4106 int
mg_start_thread(mg_thread_func_t func,void * param)4107 mg_start_thread(mg_thread_func_t func, void *param)
4108 {
4109 	pthread_t thread_id;
4110 	pthread_attr_t attr;
4111 	int result;
4112 
4113 	(void)pthread_attr_init(&attr);
4114 	(void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4115 
4116 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
4117 	/* Compile-time option to control stack size,
4118 	 * e.g. -DUSE_STACK_SIZE=16384 */
4119 	(void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
4120 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
4121 
4122 	result = pthread_create(&thread_id, &attr, func, param);
4123 	pthread_attr_destroy(&attr);
4124 
4125 	return result;
4126 }
4127 
4128 
4129 /* Start a thread storing the thread context. */
4130 static int
mg_start_thread_with_id(mg_thread_func_t func,void * param,pthread_t * threadidptr)4131 mg_start_thread_with_id(mg_thread_func_t func,
4132                         void *param,
4133                         pthread_t *threadidptr)
4134 {
4135 	pthread_t thread_id;
4136 	pthread_attr_t attr;
4137 	int result;
4138 
4139 	(void)pthread_attr_init(&attr);
4140 
4141 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
4142 	/* Compile-time option to control stack size,
4143 	 * e.g. -DUSE_STACK_SIZE=16384 */
4144 	(void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
4145 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
4146 
4147 	result = pthread_create(&thread_id, &attr, func, param);
4148 	pthread_attr_destroy(&attr);
4149 	if ((result == 0) && (threadidptr != NULL)) {
4150 		*threadidptr = thread_id;
4151 	}
4152 	return result;
4153 }
4154 
4155 
4156 /* Wait for a thread to finish. */
4157 static int
mg_join_thread(pthread_t threadid)4158 mg_join_thread(pthread_t threadid)
4159 {
4160 	int result;
4161 
4162 	result = pthread_join(threadid, NULL);
4163 	return result;
4164 }
4165 
4166 
4167 #ifndef NO_CGI
4168 static pid_t
spawn_process(struct mg_connection * conn,const char * prog,char * envblk,char * envp[],int fdin[2],int fdout[2],int fderr[2],const char * dir)4169 spawn_process(struct mg_connection *conn,
4170               const char *prog,
4171               char *envblk,
4172               char *envp[],
4173               int fdin[2],
4174               int fdout[2],
4175               int fderr[2],
4176               const char *dir)
4177 {
4178 	pid_t pid;
4179 	const char *interp;
4180 
4181 	(void)envblk;
4182 
4183 	if (conn == NULL) {
4184 		return 0;
4185 	}
4186 
4187 	if ((pid = fork()) == -1) {
4188 		/* Parent */
4189 		send_http_error(conn,
4190 		                500,
4191 		                "Error: Creating CGI process\nfork(): %s",
4192 		                strerror(ERRNO));
4193 	} else if (pid == 0) {
4194 		/* Child */
4195 		if (chdir(dir) != 0) {
4196 			mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
4197 		} else if (dup2(fdin[0], 0) == -1) {
4198 			mg_cry(conn,
4199 			       "%s: dup2(%d, 0): %s",
4200 			       __func__,
4201 			       fdin[0],
4202 			       strerror(ERRNO));
4203 		} else if (dup2(fdout[1], 1) == -1) {
4204 			mg_cry(conn,
4205 			       "%s: dup2(%d, 1): %s",
4206 			       __func__,
4207 			       fdout[1],
4208 			       strerror(ERRNO));
4209 		} else if (dup2(fderr[1], 2) == -1) {
4210 			mg_cry(conn,
4211 			       "%s: dup2(%d, 2): %s",
4212 			       __func__,
4213 			       fderr[1],
4214 			       strerror(ERRNO));
4215 		} else {
4216 			/* Keep stderr and stdout in two different pipes.
4217 			 * Stdout will be sent back to the client,
4218 			 * stderr should go into a server error log. */
4219 			(void)close(fdin[0]);
4220 			(void)close(fdout[1]);
4221 			(void)close(fderr[1]);
4222 
4223 			/* Close write end fdin and read end fdout and fderr */
4224 			(void)close(fdin[1]);
4225 			(void)close(fdout[0]);
4226 			(void)close(fderr[0]);
4227 
4228 			/* After exec, all signal handlers are restored to their default
4229 			 * values, with one exception of SIGCHLD. According to
4230 			 * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
4231 			 * leave unchanged after exec if it was set to be ignored. Restore
4232 			 * it to default action. */
4233 			signal(SIGCHLD, SIG_DFL);
4234 
4235 			interp = conn->ctx->config[CGI_INTERPRETER];
4236 			if (interp == NULL) {
4237 				(void)execle(prog, prog, NULL, envp);
4238 				mg_cry(conn,
4239 				       "%s: execle(%s): %s",
4240 				       __func__,
4241 				       prog,
4242 				       strerror(ERRNO));
4243 			} else {
4244 				(void)execle(interp, interp, prog, NULL, envp);
4245 				mg_cry(conn,
4246 				       "%s: execle(%s %s): %s",
4247 				       __func__,
4248 				       interp,
4249 				       prog,
4250 				       strerror(ERRNO));
4251 			}
4252 		}
4253 		exit(EXIT_FAILURE);
4254 	}
4255 
4256 	return pid;
4257 }
4258 #endif /* !NO_CGI */
4259 
4260 
4261 static int
set_blocking_mode(SOCKET sock,int blocking)4262 set_blocking_mode(SOCKET sock, int blocking)
4263 {
4264 	int flags;
4265 
4266 	flags = fcntl(sock, F_GETFL, 0);
4267 	if (blocking) {
4268 		(void)fcntl(sock, F_SETFL, flags | O_NONBLOCK);
4269 	} else {
4270 		(void)fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK)));
4271 	}
4272 
4273 	return 0;
4274 }
4275 #endif /* _WIN32 */
4276 /* End of initial operating system specific define block. */
4277 
4278 
4279 /* Get a random number (independent of C rand function) */
4280 static uint64_t
get_random(void)4281 get_random(void)
4282 {
4283 	static uint64_t lfsr = 0; /* Linear feedback shift register */
4284 	static uint64_t lcg = 0;  /* Linear congruential generator */
4285 	struct timespec now;
4286 
4287 	memset(&now, 0, sizeof(now));
4288 	clock_gettime(CLOCK_MONOTONIC, &now);
4289 
4290 	if (lfsr == 0) {
4291 		/* lfsr will be only 0 if has not been initialized,
4292 		 * so this code is called only once. */
4293 		lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec)
4294 		       ^ ((uint64_t)(ptrdiff_t)&now) ^ (((uint64_t)time(NULL)) << 33);
4295 		lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec
4296 		      + (uint64_t)(ptrdiff_t)&now;
4297 	} else {
4298 		/* Get the next step of both random number generators. */
4299 		lfsr = (lfsr >> 1)
4300 		       | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
4301 		          << 63);
4302 		lcg = lcg * 6364136223846793005 + 1442695040888963407;
4303 	}
4304 
4305 	/* Combining two pseudo-random number generators and a high resolution part
4306 	 * of the current server time will make it hard (impossible?) to guess the
4307 	 * next number. */
4308 	return (lfsr ^ lcg ^ (uint64_t)now.tv_nsec);
4309 }
4310 
4311 
4312 static int
mg_poll(struct pollfd * pfd,unsigned int n,int milliseconds,volatile int * stop_server)4313 mg_poll(struct pollfd *pfd,
4314         unsigned int n,
4315         int milliseconds,
4316         volatile int *stop_server)
4317 {
4318 	int ms_now, result;
4319 
4320 	/* Call poll, but only for a maximum time of a few seconds.
4321 	 * This will allow to stop the server after some seconds, instead
4322 	 * of having to wait for a long socket timeout. */
4323 	ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
4324 
4325 	do {
4326 		if (*stop_server) {
4327 			/* Shut down signal */
4328 			return -2;
4329 		}
4330 
4331 		if ((milliseconds >= 0) && (milliseconds < ms_now)) {
4332 			ms_now = milliseconds;
4333 		}
4334 
4335 		result = poll(pfd, n, ms_now);
4336 		if (result != 0) {
4337 			/* Poll returned either success (1) or error (-1).
4338 			 * Forward both to the caller. */
4339 			return result;
4340 		}
4341 
4342 		/* Poll returned timeout (0). */
4343 		if (milliseconds > 0) {
4344 			milliseconds -= ms_now;
4345 		}
4346 
4347 	} while (milliseconds != 0);
4348 
4349 	return result;
4350 }
4351 
4352 
4353 /* Write data to the IO channel - opened file descriptor, socket or SSL
4354  * descriptor. Return number of bytes written. */
4355 static int
push(struct mg_context * ctx,FILE * fp,SOCKET sock,SSL * ssl,const char * buf,int len,double timeout)4356 push(struct mg_context *ctx,
4357      FILE *fp,
4358      SOCKET sock,
4359      SSL *ssl,
4360      const char *buf,
4361      int len,
4362      double timeout)
4363 {
4364 	struct timespec start, now;
4365 	int n, err;
4366 
4367 #ifdef _WIN32
4368 	typedef int len_t;
4369 #else
4370 	typedef size_t len_t;
4371 #endif
4372 
4373 	if (timeout > 0) {
4374 		memset(&start, 0, sizeof(start));
4375 		memset(&now, 0, sizeof(now));
4376 		clock_gettime(CLOCK_MONOTONIC, &start);
4377 	}
4378 
4379 	if (ctx == NULL) {
4380 		return -1;
4381 	}
4382 
4383 #ifdef NO_SSL
4384 	if (ssl) {
4385 		return -1;
4386 	}
4387 #endif
4388 
4389 	do {
4390 
4391 #ifndef NO_SSL
4392 		if (ssl != NULL) {
4393 			n = SSL_write(ssl, buf, len);
4394 			if (n <= 0) {
4395 				err = SSL_get_error(ssl, n);
4396 				if ((err == SSL_ERROR_SYSCALL) && (n == -1)) {
4397 					err = ERRNO;
4398 				} else if ((err == SSL_ERROR_WANT_READ)
4399 				           || (err == SSL_ERROR_WANT_WRITE)) {
4400 					n = 0;
4401 				} else {
4402 					DEBUG_TRACE("SSL_write() failed, error %d", err);
4403 					return -1;
4404 				}
4405 			} else {
4406 				err = 0;
4407 			}
4408 		} else
4409 #endif
4410 		    if (fp != NULL) {
4411 			n = (int)fwrite(buf, 1, (size_t)len, fp);
4412 			if (ferror(fp)) {
4413 				n = -1;
4414 				err = ERRNO;
4415 			} else {
4416 				err = 0;
4417 			}
4418 		} else {
4419 			n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
4420 			err = (n < 0) ? ERRNO : 0;
4421 			if (n <= 0) {
4422 				/* shutdown of the socket at client side */
4423 				return -1;
4424 			}
4425 #if defined(TEMPORARY_INSTRUMENTATION)
4426 			{
4427 				FILE *f = fopen("r:\\all.txt", "ab");
4428 				fprintf(f, "\r\n%010u SEND:\r\n", GetTickCount());
4429 				fwrite(buf, 1, n, f);
4430 				fclose(f);
4431 			}
4432 #endif
4433 		}
4434 
4435 		if (ctx->stop_flag) {
4436 			return -1;
4437 		}
4438 
4439 		if ((n > 0) || (n == 0 && len == 0)) {
4440 			/* some data has been read, or no data was requested */
4441 			return n;
4442 		}
4443 		if (n < 0) {
4444 			/* socket error - check errno */
4445 			DEBUG_TRACE("send() failed, error %d", err);
4446 
4447 			/* TODO: error handling depending on the error code.
4448 			 * These codes are different between Windows and Linux.
4449 			 */
4450 			return -1;
4451 		}
4452 
4453 		/* Only in case n=0 (timeout), repeat calling the write function */
4454 
4455 		if (timeout > 0) {
4456 			clock_gettime(CLOCK_MONOTONIC, &now);
4457 		}
4458 
4459 	} while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
4460 
4461 	(void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
4462 	              used */
4463 
4464 	return -1;
4465 }
4466 
4467 
4468 static int64_t
push_all(struct mg_context * ctx,FILE * fp,SOCKET sock,SSL * ssl,const char * buf,int64_t len)4469 push_all(struct mg_context *ctx,
4470          FILE *fp,
4471          SOCKET sock,
4472          SSL *ssl,
4473          const char *buf,
4474          int64_t len)
4475 {
4476 	double timeout = -1.0;
4477 	int64_t n, nwritten = 0;
4478 
4479 	if (ctx == NULL) {
4480 		return -1;
4481 	}
4482 
4483 	if (ctx->config[REQUEST_TIMEOUT]) {
4484 		timeout = atoi(ctx->config[REQUEST_TIMEOUT]) / 1000.0;
4485 	}
4486 
4487 	while (len > 0 && ctx->stop_flag == 0) {
4488 		n = push(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
4489 		if (n < 0) {
4490 			if (nwritten == 0) {
4491 				nwritten = n; /* Propagate the error */
4492 			}
4493 			break;
4494 		} else if (n == 0) {
4495 			break; /* No more data to write */
4496 		} else {
4497 			nwritten += n;
4498 			len -= n;
4499 		}
4500 	}
4501 
4502 	return nwritten;
4503 }
4504 
4505 
4506 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
4507  * Return negative value on error, or number of bytes read on success. */
4508 static int
pull(FILE * fp,struct mg_connection * conn,char * buf,int len,double timeout)4509 pull(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
4510 {
4511 	int nread, err = 0;
4512 
4513 #ifdef _WIN32
4514 	typedef int len_t;
4515 #else
4516 	typedef size_t len_t;
4517 #endif
4518 
4519 	if (fp != NULL) {
4520 #if !defined(_WIN32_WCE)
4521 		/* Use read() instead of fread(), because if we're reading from the
4522 		 * CGI pipe, fread() may block until IO buffer is filled up. We
4523 		 * cannot afford to block and must pass all read bytes immediately
4524 		 * to the client. */
4525 		nread = (int)read(fileno(fp), buf, (size_t)len);
4526 #else
4527 		/* WinCE does not support CGI pipes */
4528 		nread = (int)fread(buf, 1, (size_t)len, fp);
4529 #endif
4530 		err = (nread < 0) ? ERRNO : 0;
4531 
4532 #ifndef NO_SSL
4533 	} else if (conn->ssl != NULL) {
4534 
4535 		struct pollfd pfd[1];
4536 		int pollres;
4537 
4538 		pfd[0].fd = conn->client.sock;
4539 		pfd[0].events = POLLIN;
4540 		pollres =
4541 		    mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->ctx->stop_flag));
4542 		if (conn->ctx->stop_flag) {
4543 			return -1;
4544 		}
4545 		if (pollres > 0) {
4546 			nread = SSL_read(conn->ssl, buf, len);
4547 			if (nread <= 0) {
4548 				err = SSL_get_error(conn->ssl, nread);
4549 				if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
4550 					err = ERRNO;
4551 				} else if ((err == SSL_ERROR_WANT_READ)
4552 				           || (err == SSL_ERROR_WANT_WRITE)) {
4553 					nread = 0;
4554 				} else {
4555 					DEBUG_TRACE("SSL_read() failed, error %d", err);
4556 					return -1;
4557 				}
4558 			} else {
4559 				err = 0;
4560 			}
4561 
4562 		} else if (pollres < 0) {
4563 			/* Error */
4564 			return -1;
4565 		} else {
4566 			/* pollres = 0 means timeout */
4567 			nread = 0;
4568 		}
4569 
4570 #endif
4571 
4572 	} else {
4573 		struct pollfd pfd[1];
4574 		int pollres;
4575 
4576 		pfd[0].fd = conn->client.sock;
4577 		pfd[0].events = POLLIN;
4578 		pollres =
4579 		    mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->ctx->stop_flag));
4580 		if (conn->ctx->stop_flag) {
4581 			return -1;
4582 		}
4583 		if (pollres > 0) {
4584 			nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
4585 			err = (nread < 0) ? ERRNO : 0;
4586 			if (nread <= 0) {
4587 				/* shutdown of the socket at client side */
4588 				return -1;
4589 			}
4590 #if defined(TEMPORARY_INSTRUMENTATION)
4591 			{
4592 				FILE *f = fopen("r:\\all.txt", "ab");
4593 				fprintf(f, "\r\n%010u RECV:\r\n", GetTickCount());
4594 				fwrite(buf, 1, nread, f);
4595 				fclose(f);
4596 			}
4597 #endif
4598 		} else if (pollres < 0) {
4599 			/* error callint poll */
4600 			return -1;
4601 		} else {
4602 			/* pollres = 0 means timeout */
4603 			nread = 0;
4604 		}
4605 	}
4606 
4607 	if (conn->ctx->stop_flag) {
4608 		return -1;
4609 	}
4610 
4611 	if ((nread > 0) || (nread == 0 && len == 0)) {
4612 		/* some data has been read, or no data was requested */
4613 		return nread;
4614 	}
4615 
4616 	if (nread < 0) {
4617 /* socket error - check errno */
4618 #ifdef _WIN32
4619 		if (err == WSAEWOULDBLOCK) {
4620 			/* TODO: check if this is still required */
4621 			/* standard case if called from close_socket_gracefully */
4622 			return -1;
4623 		} else if (err == WSAETIMEDOUT) {
4624 			/* TODO: check if this is still required */
4625 			/* timeout is handled by the while loop  */
4626 			return 0;
4627 		} else if (err == WSAECONNABORTED) {
4628 			/* See https://www.chilkatsoft.com/p/p_299.asp */
4629 			return -1;
4630 		} else {
4631 			DEBUG_TRACE("recv() failed, error %d", err);
4632 			return -1;
4633 		}
4634 #else
4635 		/* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
4636 		 * if the timeout is reached and if the socket was set to non-
4637 		 * blocking in close_socket_gracefully, so we can not distinguish
4638 		 * here. We have to wait for the timeout in both cases for now.
4639 		 */
4640 		if (err == EAGAIN || err == EWOULDBLOCK || err == EINTR) {
4641 			/* TODO: check if this is still required */
4642 			/* EAGAIN/EWOULDBLOCK:
4643 			 * standard case if called from close_socket_gracefully
4644 			 * => should return -1 */
4645 			/* or timeout occured
4646 			 * => the code must stay in the while loop */
4647 
4648 			/* EINTR can be generated on a socket with a timeout set even
4649 			 * when SA_RESTART is effective for all relevant signals
4650 			 * (see signal(7)).
4651 			 * => stay in the while loop */
4652 		} else {
4653 			DEBUG_TRACE("recv() failed, error %d", err);
4654 			return -1;
4655 		}
4656 #endif
4657 	}
4658 
4659 	/* Timeout occured, but no data available. */
4660 	return -1;
4661 }
4662 
4663 
4664 static int
pull_all(FILE * fp,struct mg_connection * conn,char * buf,int len)4665 pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
4666 {
4667 	int n, nread = 0;
4668 	double timeout = -1.0;
4669 
4670 	if (conn->ctx->config[REQUEST_TIMEOUT]) {
4671 		timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
4672 	}
4673 
4674 	while (len > 0 && conn->ctx->stop_flag == 0) {
4675 		n = pull(fp, conn, buf + nread, len, timeout);
4676 		if (n < 0) {
4677 			if (nread == 0) {
4678 				nread = n; /* Propagate the error */
4679 			}
4680 			break;
4681 		} else if (n == 0) {
4682 			break; /* No more data to read */
4683 		} else {
4684 			conn->consumed_content += n;
4685 			nread += n;
4686 			len -= n;
4687 		}
4688 	}
4689 
4690 	return nread;
4691 }
4692 
4693 
4694 static void
discard_unread_request_data(struct mg_connection * conn)4695 discard_unread_request_data(struct mg_connection *conn)
4696 {
4697 	char buf[MG_BUF_LEN];
4698 	size_t to_read;
4699 	int nread;
4700 
4701 	if (conn == NULL) {
4702 		return;
4703 	}
4704 
4705 	to_read = sizeof(buf);
4706 
4707 	if (conn->is_chunked) {
4708 		/* Chunked encoding: 1=chunk not read completely, 2=chunk read
4709 		 * completely */
4710 		while (conn->is_chunked == 1) {
4711 			nread = mg_read(conn, buf, to_read);
4712 			if (nread <= 0) {
4713 				break;
4714 			}
4715 		}
4716 
4717 	} else {
4718 		/* Not chunked: content length is known */
4719 		while (conn->consumed_content < conn->content_len) {
4720 			if (to_read
4721 			    > (size_t)(conn->content_len - conn->consumed_content)) {
4722 				to_read = (size_t)(conn->content_len - conn->consumed_content);
4723 			}
4724 
4725 			nread = mg_read(conn, buf, to_read);
4726 			if (nread <= 0) {
4727 				break;
4728 			}
4729 		}
4730 	}
4731 }
4732 
4733 
4734 static int
mg_read_inner(struct mg_connection * conn,void * buf,size_t len)4735 mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
4736 {
4737 	int64_t n, buffered_len, nread;
4738 	int64_t len64 =
4739 	    (int64_t)((len > INT_MAX) ? INT_MAX : len); /* since the return value is
4740 	                                               * int, we may not read more
4741 	                                               * bytes */
4742 	const char *body;
4743 
4744 	if (conn == NULL) {
4745 		return 0;
4746 	}
4747 
4748 	/* If Content-Length is not set for a PUT or POST request, read until
4749 	 * socket is closed */
4750 	if (conn->consumed_content == 0 && conn->content_len == -1) {
4751 		conn->content_len = INT64_MAX;
4752 		conn->must_close = 1;
4753 	}
4754 
4755 	nread = 0;
4756 	if (conn->consumed_content < conn->content_len) {
4757 		/* Adjust number of bytes to read. */
4758 		int64_t left_to_read = conn->content_len - conn->consumed_content;
4759 		if (left_to_read < len64) {
4760 			/* Do not read more than the total content length of the request.
4761 			 */
4762 			len64 = left_to_read;
4763 		}
4764 
4765 		/* Return buffered data */
4766 		buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
4767 		               - conn->consumed_content;
4768 		if (buffered_len > 0) {
4769 			if (len64 < buffered_len) {
4770 				buffered_len = len64;
4771 			}
4772 			body = conn->buf + conn->request_len + conn->consumed_content;
4773 			memcpy(buf, body, (size_t)buffered_len);
4774 			len64 -= buffered_len;
4775 			conn->consumed_content += buffered_len;
4776 			nread += buffered_len;
4777 			buf = (char *)buf + buffered_len;
4778 		}
4779 
4780 		/* We have returned all buffered data. Read new data from the remote
4781 		 * socket.
4782 		 */
4783 		if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
4784 			nread += n;
4785 		} else {
4786 			nread = ((nread > 0) ? nread : n);
4787 		}
4788 	}
4789 	return (int)nread;
4790 }
4791 
4792 
4793 static char
mg_getc(struct mg_connection * conn)4794 mg_getc(struct mg_connection *conn)
4795 {
4796 	char c;
4797 	if (conn == NULL) {
4798 		return 0;
4799 	}
4800 	conn->content_len++;
4801 	if (mg_read_inner(conn, &c, 1) <= 0) {
4802 		return (char)0;
4803 	}
4804 	return c;
4805 }
4806 
4807 
4808 int
mg_read(struct mg_connection * conn,void * buf,size_t len)4809 mg_read(struct mg_connection *conn, void *buf, size_t len)
4810 {
4811 	if (len > INT_MAX) {
4812 		len = INT_MAX;
4813 	}
4814 
4815 	if (conn == NULL) {
4816 		return 0;
4817 	}
4818 
4819 	if (conn->is_chunked) {
4820 		size_t all_read = 0;
4821 
4822 		while (len > 0) {
4823 
4824 			if (conn->is_chunked == 2) {
4825 				/* No more data left to read */
4826 				return 0;
4827 			}
4828 
4829 			if (conn->chunk_remainder) {
4830 				/* copy from the remainder of the last received chunk */
4831 				long read_ret;
4832 				size_t read_now =
4833 				    ((conn->chunk_remainder > len) ? (len)
4834 				                                   : (conn->chunk_remainder));
4835 
4836 				conn->content_len += (int)read_now;
4837 				read_ret =
4838 				    mg_read_inner(conn, (char *)buf + all_read, read_now);
4839 
4840 				if (read_ret < 1) {
4841 					/* read error */
4842 					return -1;
4843 				}
4844 
4845 				all_read += (size_t)read_ret;
4846 				conn->chunk_remainder -= (size_t)read_ret;
4847 				len -= (size_t)read_ret;
4848 
4849 				if (conn->chunk_remainder == 0) {
4850 					/* Add data bytes in the current chunk have been read,
4851 					 * so we are expecting \r\n now. */
4852 					char x1 = mg_getc(conn);
4853 					char x2 = mg_getc(conn);
4854 					if ((x1 != '\r') || (x2 != '\n')) {
4855 						/* Protocol violation */
4856 						return -1;
4857 					}
4858 				}
4859 
4860 			} else {
4861 				/* fetch a new chunk */
4862 				int i = 0;
4863 				char lenbuf[64];
4864 				char *end = 0;
4865 				unsigned long chunkSize = 0;
4866 
4867 				for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
4868 					lenbuf[i] = mg_getc(conn);
4869 					if (i > 0 && lenbuf[i] == '\r' && lenbuf[i - 1] != '\r') {
4870 						continue;
4871 					}
4872 					if (i > 1 && lenbuf[i] == '\n' && lenbuf[i - 1] == '\r') {
4873 						lenbuf[i + 1] = 0;
4874 						chunkSize = strtoul(lenbuf, &end, 16);
4875 						if (chunkSize == 0) {
4876 							/* regular end of content */
4877 							conn->is_chunked = 2;
4878 						}
4879 						break;
4880 					}
4881 					if (!isxdigit(lenbuf[i])) {
4882 						/* illegal character for chunk length */
4883 						return -1;
4884 					}
4885 				}
4886 				if ((end == NULL) || (*end != '\r')) {
4887 					/* chunksize not set correctly */
4888 					return -1;
4889 				}
4890 				if (chunkSize == 0) {
4891 					break;
4892 				}
4893 
4894 				conn->chunk_remainder = chunkSize;
4895 			}
4896 		}
4897 
4898 		return (int)all_read;
4899 	}
4900 	return mg_read_inner(conn, buf, len);
4901 }
4902 
4903 
4904 int
mg_write(struct mg_connection * conn,const void * buf,size_t len)4905 mg_write(struct mg_connection *conn, const void *buf, size_t len)
4906 {
4907 	time_t now;
4908 	int64_t n, total, allowed;
4909 
4910 	if (conn == NULL) {
4911 		return 0;
4912 	}
4913 
4914 	if (conn->throttle > 0) {
4915 		if ((now = time(NULL)) != conn->last_throttle_time) {
4916 			conn->last_throttle_time = now;
4917 			conn->last_throttle_bytes = 0;
4918 		}
4919 		allowed = conn->throttle - conn->last_throttle_bytes;
4920 		if (allowed > (int64_t)len) {
4921 			allowed = (int64_t)len;
4922 		}
4923 		if ((total = push_all(conn->ctx,
4924 		                      NULL,
4925 		                      conn->client.sock,
4926 		                      conn->ssl,
4927 		                      (const char *)buf,
4928 		                      (int64_t)allowed)) == allowed) {
4929 			buf = (const char *)buf + total;
4930 			conn->last_throttle_bytes += total;
4931 			while (total < (int64_t)len && conn->ctx->stop_flag == 0) {
4932 				allowed = (conn->throttle > ((int64_t)len - total))
4933 				              ? (int64_t)len - total
4934 				              : conn->throttle;
4935 				if ((n = push_all(conn->ctx,
4936 				                  NULL,
4937 				                  conn->client.sock,
4938 				                  conn->ssl,
4939 				                  (const char *)buf,
4940 				                  (int64_t)allowed)) != allowed) {
4941 					break;
4942 				}
4943 				sleep(1);
4944 				conn->last_throttle_bytes = allowed;
4945 				conn->last_throttle_time = time(NULL);
4946 				buf = (const char *)buf + n;
4947 				total += n;
4948 			}
4949 		}
4950 	} else {
4951 		total = push_all(conn->ctx,
4952 		                 NULL,
4953 		                 conn->client.sock,
4954 		                 conn->ssl,
4955 		                 (const char *)buf,
4956 		                 (int64_t)len);
4957 	}
4958 	return (int)total;
4959 }
4960 
4961 
4962 /* Alternative alloc_vprintf() for non-compliant C runtimes */
4963 static int
alloc_vprintf2(char ** buf,const char * fmt,va_list ap)4964 alloc_vprintf2(char **buf, const char *fmt, va_list ap)
4965 {
4966 	va_list ap_copy;
4967 	size_t size = MG_BUF_LEN / 4;
4968 	int len = -1;
4969 
4970 	*buf = NULL;
4971 	while (len < 0) {
4972 		if (*buf) {
4973 			mg_free(*buf);
4974 		}
4975 
4976 		size *= 4;
4977 		*buf = (char *)mg_malloc(size);
4978 		if (!*buf) {
4979 			break;
4980 		}
4981 
4982 		va_copy(ap_copy, ap);
4983 		len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
4984 		va_end(ap_copy);
4985 		(*buf)[size - 1] = 0;
4986 	}
4987 
4988 	return len;
4989 }
4990 
4991 
4992 /* Print message to buffer. If buffer is large enough to hold the message,
4993  * return buffer. If buffer is to small, allocate large enough buffer on heap,
4994  * and return allocated buffer. */
4995 static int
alloc_vprintf(char ** out_buf,char * prealloc_buf,size_t prealloc_size,const char * fmt,va_list ap)4996 alloc_vprintf(char **out_buf,
4997               char *prealloc_buf,
4998               size_t prealloc_size,
4999               const char *fmt,
5000               va_list ap)
5001 {
5002 	va_list ap_copy;
5003 	int len;
5004 
5005 	/* Windows is not standard-compliant, and vsnprintf() returns -1 if
5006 	 * buffer is too small. Also, older versions of msvcrt.dll do not have
5007 	 * _vscprintf().  However, if size is 0, vsnprintf() behaves correctly.
5008 	 * Therefore, we make two passes: on first pass, get required message
5009 	 * length.
5010 	 * On second pass, actually print the message. */
5011 	va_copy(ap_copy, ap);
5012 	len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
5013 	va_end(ap_copy);
5014 
5015 	if (len < 0) {
5016 		/* C runtime is not standard compliant, vsnprintf() returned -1.
5017 		 * Switch to alternative code path that uses incremental allocations.
5018 		*/
5019 		va_copy(ap_copy, ap);
5020 		len = alloc_vprintf2(out_buf, fmt, ap);
5021 		va_end(ap_copy);
5022 
5023 	} else if ((size_t)(len) >= prealloc_size) {
5024 		/* The pre-allocated buffer not large enough. */
5025 		/* Allocate a new buffer. */
5026 		*out_buf = (char *)mg_malloc((size_t)(len) + 1);
5027 		if (!*out_buf) {
5028 			/* Allocation failed. Return -1 as "out of memory" error. */
5029 			return -1;
5030 		}
5031 		/* Buffer allocation successful. Store the string there. */
5032 		va_copy(ap_copy, ap);
5033 		IGNORE_UNUSED_RESULT(
5034 		    vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
5035 		va_end(ap_copy);
5036 
5037 	} else {
5038 		/* The pre-allocated buffer is large enough.
5039 		 * Use it to store the string and return the address. */
5040 		va_copy(ap_copy, ap);
5041 		IGNORE_UNUSED_RESULT(
5042 		    vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
5043 		va_end(ap_copy);
5044 		*out_buf = prealloc_buf;
5045 	}
5046 
5047 	return len;
5048 }
5049 
5050 
5051 static int
mg_vprintf(struct mg_connection * conn,const char * fmt,va_list ap)5052 mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
5053 {
5054 	char mem[MG_BUF_LEN];
5055 	char *buf = NULL;
5056 	int len;
5057 
5058 	if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
5059 		len = mg_write(conn, buf, (size_t)len);
5060 	}
5061 	if (buf != mem && buf != NULL) {
5062 		mg_free(buf);
5063 	}
5064 
5065 	return len;
5066 }
5067 
5068 
5069 int
mg_printf(struct mg_connection * conn,const char * fmt,...)5070 mg_printf(struct mg_connection *conn, const char *fmt, ...)
5071 {
5072 	va_list ap;
5073 	int result;
5074 
5075 	va_start(ap, fmt);
5076 	result = mg_vprintf(conn, fmt, ap);
5077 	va_end(ap);
5078 
5079 	return result;
5080 }
5081 
5082 
5083 int
mg_url_decode(const char * src,int src_len,char * dst,int dst_len,int is_form_url_encoded)5084 mg_url_decode(const char *src,
5085               int src_len,
5086               char *dst,
5087               int dst_len,
5088               int is_form_url_encoded)
5089 {
5090 	int i, j, a, b;
5091 #define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W'))
5092 
5093 	for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
5094 		if (i < src_len - 2 && src[i] == '%'
5095 		    && isxdigit(*(const unsigned char *)(src + i + 1))
5096 		    && isxdigit(*(const unsigned char *)(src + i + 2))) {
5097 			a = tolower(*(const unsigned char *)(src + i + 1));
5098 			b = tolower(*(const unsigned char *)(src + i + 2));
5099 			dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
5100 			i += 2;
5101 		} else if (is_form_url_encoded && src[i] == '+') {
5102 			dst[j] = ' ';
5103 		} else {
5104 			dst[j] = src[i];
5105 		}
5106 	}
5107 
5108 	dst[j] = '\0'; /* Null-terminate the destination */
5109 
5110 	return (i >= src_len) ? j : -1;
5111 }
5112 
5113 
5114 int
mg_get_var(const char * data,size_t data_len,const char * name,char * dst,size_t dst_len)5115 mg_get_var(const char *data,
5116            size_t data_len,
5117            const char *name,
5118            char *dst,
5119            size_t dst_len)
5120 {
5121 	return mg_get_var2(data, data_len, name, dst, dst_len, 0);
5122 }
5123 
5124 
5125 int
mg_get_var2(const char * data,size_t data_len,const char * name,char * dst,size_t dst_len,size_t occurrence)5126 mg_get_var2(const char *data,
5127             size_t data_len,
5128             const char *name,
5129             char *dst,
5130             size_t dst_len,
5131             size_t occurrence)
5132 {
5133 	const char *p, *e, *s;
5134 	size_t name_len;
5135 	int len;
5136 
5137 	if (dst == NULL || dst_len == 0) {
5138 		len = -2;
5139 	} else if (data == NULL || name == NULL || data_len == 0) {
5140 		len = -1;
5141 		dst[0] = '\0';
5142 	} else {
5143 		name_len = strlen(name);
5144 		e = data + data_len;
5145 		len = -1;
5146 		dst[0] = '\0';
5147 
5148 		/* data is "var1=val1&var2=val2...". Find variable first */
5149 		for (p = data; p + name_len < e; p++) {
5150 			if ((p == data || p[-1] == '&') && p[name_len] == '='
5151 			    && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
5152 				/* Point p to variable value */
5153 				p += name_len + 1;
5154 
5155 				/* Point s to the end of the value */
5156 				s = (const char *)memchr(p, '&', (size_t)(e - p));
5157 				if (s == NULL) {
5158 					s = e;
5159 				}
5160 				/* assert(s >= p); */
5161 				if (s < p) {
5162 					return -3;
5163 				}
5164 
5165 				/* Decode variable into destination buffer */
5166 				len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
5167 
5168 				/* Redirect error code from -1 to -2 (destination buffer too
5169 				 * small). */
5170 				if (len == -1) {
5171 					len = -2;
5172 				}
5173 				break;
5174 			}
5175 		}
5176 	}
5177 
5178 	return len;
5179 }
5180 
5181 
5182 /* HCP24: some changes to compare hole var_name */
5183 int
mg_get_cookie(const char * cookie_header,const char * var_name,char * dst,size_t dst_size)5184 mg_get_cookie(const char *cookie_header,
5185               const char *var_name,
5186               char *dst,
5187               size_t dst_size)
5188 {
5189 	const char *s, *p, *end;
5190 	int name_len, len = -1;
5191 
5192 	if (dst == NULL || dst_size == 0) {
5193 		return -2;
5194 	}
5195 
5196 	dst[0] = '\0';
5197 	if (var_name == NULL || (s = cookie_header) == NULL) {
5198 		return -1;
5199 	}
5200 
5201 	name_len = (int)strlen(var_name);
5202 	end = s + strlen(s);
5203 	for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
5204 		if (s[name_len] == '=') {
5205 			/* HCP24: now check is it a substring or a full cookie name */
5206 			if ((s == cookie_header) || (s[-1] == ' ')) {
5207 				s += name_len + 1;
5208 				if ((p = strchr(s, ' ')) == NULL) {
5209 					p = end;
5210 				}
5211 				if (p[-1] == ';') {
5212 					p--;
5213 				}
5214 				if (*s == '"' && p[-1] == '"' && p > s + 1) {
5215 					s++;
5216 					p--;
5217 				}
5218 				if ((size_t)(p - s) < dst_size) {
5219 					len = (int)(p - s);
5220 					mg_strlcpy(dst, s, (size_t)len + 1);
5221 				} else {
5222 					len = -3;
5223 				}
5224 				break;
5225 			}
5226 		}
5227 	}
5228 	return len;
5229 }
5230 
5231 
5232 #if defined(USE_WEBSOCKET) || defined(USE_LUA)
5233 static void
base64_encode(const unsigned char * src,int src_len,char * dst)5234 base64_encode(const unsigned char *src, int src_len, char *dst)
5235 {
5236 	static const char *b64 =
5237 	    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5238 	int i, j, a, b, c;
5239 
5240 	for (i = j = 0; i < src_len; i += 3) {
5241 		a = src[i];
5242 		b = ((i + 1) >= src_len) ? 0 : src[i + 1];
5243 		c = ((i + 2) >= src_len) ? 0 : src[i + 2];
5244 
5245 		dst[j++] = b64[a >> 2];
5246 		dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
5247 		if (i + 1 < src_len) {
5248 			dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
5249 		}
5250 		if (i + 2 < src_len) {
5251 			dst[j++] = b64[c & 63];
5252 		}
5253 	}
5254 	while (j % 4 != 0) {
5255 		dst[j++] = '=';
5256 	}
5257 	dst[j++] = '\0';
5258 }
5259 #endif
5260 
5261 
5262 #if defined(USE_LUA)
5263 static unsigned char
b64reverse(char letter)5264 b64reverse(char letter)
5265 {
5266 	if (letter >= 'A' && letter <= 'Z') {
5267 		return letter - 'A';
5268 	}
5269 	if (letter >= 'a' && letter <= 'z') {
5270 		return letter - 'a' + 26;
5271 	}
5272 	if (letter >= '0' && letter <= '9') {
5273 		return letter - '0' + 52;
5274 	}
5275 	if (letter == '+') {
5276 		return 62;
5277 	}
5278 	if (letter == '/') {
5279 		return 63;
5280 	}
5281 	if (letter == '=') {
5282 		return 255; /* normal end */
5283 	}
5284 	return 254; /* error */
5285 }
5286 
5287 
5288 static int
base64_decode(const unsigned char * src,int src_len,char * dst,size_t * dst_len)5289 base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
5290 {
5291 	int i;
5292 	unsigned char a, b, c, d;
5293 
5294 	*dst_len = 0;
5295 
5296 	for (i = 0; i < src_len; i += 4) {
5297 		a = b64reverse(src[i]);
5298 		if (a >= 254) {
5299 			return i;
5300 		}
5301 
5302 		b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
5303 		if (b >= 254) {
5304 			return i + 1;
5305 		}
5306 
5307 		c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
5308 		if (c == 254) {
5309 			return i + 2;
5310 		}
5311 
5312 		d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
5313 		if (d == 254) {
5314 			return i + 3;
5315 		}
5316 
5317 		dst[(*dst_len)++] = (a << 2) + (b >> 4);
5318 		if (c != 255) {
5319 			dst[(*dst_len)++] = (b << 4) + (c >> 2);
5320 			if (d != 255) {
5321 				dst[(*dst_len)++] = (c << 6) + d;
5322 			}
5323 		}
5324 	}
5325 	return -1;
5326 }
5327 #endif
5328 
5329 
5330 static int
is_put_or_delete_method(const struct mg_connection * conn)5331 is_put_or_delete_method(const struct mg_connection *conn)
5332 {
5333 	if (conn) {
5334 		const char *s = conn->request_info.request_method;
5335 		return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
5336 		                     || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
5337 	}
5338 	return 0;
5339 }
5340 
5341 
5342 static void
interpret_uri(struct mg_connection * conn,char * filename,size_t filename_buf_len,struct mg_file_stat * filestat,int * is_found,int * is_script_resource,int * is_websocket_request,int * is_put_or_delete_request)5343 interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
5344               char *filename,                /* out: filename */
5345               size_t filename_buf_len,       /* in: size of filename buffer */
5346               struct mg_file_stat *filestat, /* out: file structure */
5347               int *is_found,                 /* out: file found (directly) */
5348               int *is_script_resource,       /* out: handled by a script? */
5349               int *is_websocket_request,     /* out: websocket connetion? */
5350               int *is_put_or_delete_request  /* out: put/delete a file? */
5351               )
5352 {
5353 /* TODO (high): Restructure this function */
5354 
5355 #if !defined(NO_FILES)
5356 	const char *uri = conn->request_info.local_uri;
5357 	const char *root = conn->ctx->config[DOCUMENT_ROOT];
5358 	const char *rewrite;
5359 	struct vec a, b;
5360 	int match_len;
5361 	char gz_path[PATH_MAX];
5362 	char const *accept_encoding;
5363 	int truncated;
5364 #if !defined(NO_CGI) || defined(USE_LUA)
5365 	char *p;
5366 #endif
5367 #else
5368 	(void)filename_buf_len; /* unused if NO_FILES is defined */
5369 #endif
5370 
5371 	memset(filestat, 0, sizeof(*filestat));
5372 	*filename = 0;
5373 	*is_found = 0;
5374 	*is_script_resource = 0;
5375 	*is_put_or_delete_request = is_put_or_delete_method(conn);
5376 
5377 #if defined(USE_WEBSOCKET)
5378 	*is_websocket_request = is_websocket_protocol(conn);
5379 #if !defined(NO_FILES)
5380 	if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
5381 		root = conn->ctx->config[WEBSOCKET_ROOT];
5382 	}
5383 #endif /* !NO_FILES */
5384 #else  /* USE_WEBSOCKET */
5385 	*is_websocket_request = 0;
5386 #endif /* USE_WEBSOCKET */
5387 
5388 #if !defined(NO_FILES)
5389 	/* Note that root == NULL is a regular use case here. This occurs,
5390 	 * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
5391 	 * config is not required. */
5392 	if (root == NULL) {
5393 		/* all file related outputs have already been set to 0, just return
5394 		 */
5395 		return;
5396 	}
5397 
5398 	/* Using buf_len - 1 because memmove() for PATH_INFO may shift part
5399 	 * of the path one byte on the right.
5400 	 * If document_root is NULL, leave the file empty. */
5401 	mg_snprintf(
5402 	    conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
5403 
5404 	if (truncated) {
5405 		goto interpret_cleanup;
5406 	}
5407 
5408 	rewrite = conn->ctx->config[REWRITE];
5409 	while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
5410 		if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
5411 			mg_snprintf(conn,
5412 			            &truncated,
5413 			            filename,
5414 			            filename_buf_len - 1,
5415 			            "%.*s%s",
5416 			            (int)b.len,
5417 			            b.ptr,
5418 			            uri + match_len);
5419 			break;
5420 		}
5421 	}
5422 
5423 	if (truncated) {
5424 		goto interpret_cleanup;
5425 	}
5426 
5427 	/* Local file path and name, corresponding to requested URI
5428 	 * is now stored in "filename" variable. */
5429 	if (mg_stat(conn, filename, filestat)) {
5430 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
5431 		/* File exists. Check if it is a script type. */
5432 		if (0
5433 #if !defined(NO_CGI)
5434 		    || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
5435 		                    strlen(conn->ctx->config[CGI_EXTENSIONS]),
5436 		                    filename) > 0
5437 #endif
5438 #if defined(USE_LUA)
5439 		    || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
5440 		                    strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
5441 		                    filename) > 0
5442 #endif
5443 #if defined(USE_DUKTAPE)
5444 		    || match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
5445 		                    strlen(
5446 		                        conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
5447 		                    filename) > 0
5448 #endif
5449 		    ) {
5450 			/* The request addresses a CGI script or a Lua script. The URI
5451 			 * corresponds to the script itself (like /path/script.cgi),
5452 			 * and there is no additional resource path
5453 			 * (like /path/script.cgi/something).
5454 			 * Requests that modify (replace or delete) a resource, like
5455 			 * PUT and DELETE requests, should replace/delete the script
5456 			 * file.
5457 			 * Requests that read or write from/to a resource, like GET and
5458 			 * POST requests, should call the script and return the
5459 			 * generated response. */
5460 			*is_script_resource = !*is_put_or_delete_request;
5461 		}
5462 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
5463 		*is_found = 1;
5464 		return;
5465 	}
5466 
5467 	/* If we can't find the actual file, look for the file
5468 	 * with the same name but a .gz extension. If we find it,
5469 	 * use that and set the gzipped flag in the file struct
5470 	 * to indicate that the response need to have the content-
5471 	 * encoding: gzip header.
5472 	 * We can only do this if the browser declares support. */
5473 	if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
5474 		if (strstr(accept_encoding, "gzip") != NULL) {
5475 			mg_snprintf(
5476 			    conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
5477 
5478 			if (truncated) {
5479 				goto interpret_cleanup;
5480 			}
5481 
5482 			if (mg_stat(conn, gz_path, filestat)) {
5483 				if (filestat) {
5484 					filestat->is_gzipped = 1;
5485 					*is_found = 1;
5486 				}
5487 				/* Currently gz files can not be scripts. */
5488 				return;
5489 			}
5490 		}
5491 	}
5492 
5493 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
5494 	/* Support PATH_INFO for CGI scripts. */
5495 	for (p = filename + strlen(filename); p > filename + 1; p--) {
5496 		if (*p == '/') {
5497 			*p = '\0';
5498 			if ((0
5499 #if !defined(NO_CGI)
5500 			     || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
5501 			                     strlen(conn->ctx->config[CGI_EXTENSIONS]),
5502 			                     filename) > 0
5503 #endif
5504 #if defined(USE_LUA)
5505 			     || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
5506 			                     strlen(
5507 			                         conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
5508 			                     filename) > 0
5509 #endif
5510 #if defined(USE_DUKTAPE)
5511 			     || match_prefix(
5512 			            conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
5513 			            strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
5514 			            filename) > 0
5515 #endif
5516 			     ) && mg_stat(conn, filename, filestat)) {
5517 				/* Shift PATH_INFO block one character right, e.g.
5518 				 * "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
5519 				 * conn->path_info is pointing to the local variable "path"
5520 				 * declared in handle_request(), so PATH_INFO is not valid
5521 				 * after handle_request returns. */
5522 				conn->path_info = p + 1;
5523 				memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
5524 				                                           * trailing \0 */
5525 				p[1] = '/';
5526 				*is_script_resource = 1;
5527 				break;
5528 			} else {
5529 				*p = '/';
5530 			}
5531 		}
5532 	}
5533 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
5534 #endif /* !defined(NO_FILES) */
5535 	return;
5536 
5537 #if !defined(NO_FILES)
5538 /* Reset all outputs */
5539 interpret_cleanup:
5540 	memset(filestat, 0, sizeof(*filestat));
5541 	*filename = 0;
5542 	*is_found = 0;
5543 	*is_script_resource = 0;
5544 	*is_websocket_request = 0;
5545 	*is_put_or_delete_request = 0;
5546 #endif /* !defined(NO_FILES) */
5547 }
5548 
5549 
5550 /* Check whether full request is buffered. Return:
5551  * -1  if request is malformed
5552  *  0  if request is not yet fully buffered
5553  * >0  actual request length, including last \r\n\r\n */
5554 static int
get_request_len(const char * buf,int buflen)5555 get_request_len(const char *buf, int buflen)
5556 {
5557 	const char *s, *e;
5558 	int len = 0;
5559 
5560 	for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++)
5561 		/* Control characters are not allowed but >=128 is. */
5562 		if (!isprint(*(const unsigned char *)s) && *s != '\r' && *s != '\n'
5563 		    && *(const unsigned char *)s < 128) {
5564 			len = -1;
5565 			break; /* [i_a] abort scan as soon as one malformed character is
5566 			        * found; */
5567 			/* don't let subsequent \r\n\r\n win us over anyhow */
5568 		} else if (s[0] == '\n' && s[1] == '\n') {
5569 			len = (int)(s - buf) + 2;
5570 		} else if (s[0] == '\n' && &s[1] < e && s[1] == '\r' && s[2] == '\n') {
5571 			len = (int)(s - buf) + 3;
5572 		}
5573 
5574 	return len;
5575 }
5576 
5577 
5578 #if !defined(NO_CACHING)
5579 /* Convert month to the month number. Return -1 on error, or month number */
5580 static int
get_month_index(const char * s)5581 get_month_index(const char *s)
5582 {
5583 	size_t i;
5584 
5585 	for (i = 0; i < ARRAY_SIZE(month_names); i++) {
5586 		if (!strcmp(s, month_names[i])) {
5587 			return (int)i;
5588 		}
5589 	}
5590 
5591 	return -1;
5592 }
5593 
5594 
5595 /* Parse UTC date-time string, and return the corresponding time_t value. */
5596 static time_t
parse_date_string(const char * datetime)5597 parse_date_string(const char *datetime)
5598 {
5599 	char month_str[32] = {0};
5600 	int second, minute, hour, day, month, year;
5601 	time_t result = (time_t)0;
5602 	struct tm tm;
5603 
5604 	if ((sscanf(datetime,
5605 	            "%d/%3s/%d %d:%d:%d",
5606 	            &day,
5607 	            month_str,
5608 	            &year,
5609 	            &hour,
5610 	            &minute,
5611 	            &second) == 6) || (sscanf(datetime,
5612 	                                      "%d %3s %d %d:%d:%d",
5613 	                                      &day,
5614 	                                      month_str,
5615 	                                      &year,
5616 	                                      &hour,
5617 	                                      &minute,
5618 	                                      &second) == 6)
5619 	    || (sscanf(datetime,
5620 	               "%*3s, %d %3s %d %d:%d:%d",
5621 	               &day,
5622 	               month_str,
5623 	               &year,
5624 	               &hour,
5625 	               &minute,
5626 	               &second) == 6) || (sscanf(datetime,
5627 	                                         "%d-%3s-%d %d:%d:%d",
5628 	                                         &day,
5629 	                                         month_str,
5630 	                                         &year,
5631 	                                         &hour,
5632 	                                         &minute,
5633 	                                         &second) == 6)) {
5634 		month = get_month_index(month_str);
5635 		if ((month >= 0) && (year >= 1970)) {
5636 			memset(&tm, 0, sizeof(tm));
5637 			tm.tm_year = year - 1900;
5638 			tm.tm_mon = month;
5639 			tm.tm_mday = day;
5640 			tm.tm_hour = hour;
5641 			tm.tm_min = minute;
5642 			tm.tm_sec = second;
5643 			result = timegm(&tm);
5644 		}
5645 	}
5646 
5647 	return result;
5648 }
5649 #endif /* !NO_CACHING */
5650 
5651 
5652 /* Protect against directory disclosure attack by removing '..',
5653  * excessive '/' and '\' characters */
5654 static void
remove_double_dots_and_double_slashes(char * s)5655 remove_double_dots_and_double_slashes(char *s)
5656 {
5657 	char *p = s;
5658 
5659 	while ((s[0] == '.') && (s[1] == '.')) {
5660 		s++;
5661 	}
5662 
5663 	while (*s != '\0') {
5664 		*p++ = *s++;
5665 		if (s[-1] == '/' || s[-1] == '\\') {
5666 			/* Skip all following slashes, backslashes and double-dots */
5667 			while (s[0] != '\0') {
5668 				if (s[0] == '/' || s[0] == '\\') {
5669 					s++;
5670 				} else if (s[0] == '.' && s[1] == '.') {
5671 					s += 2;
5672 				} else {
5673 					break;
5674 				}
5675 			}
5676 		}
5677 	}
5678 	*p = '\0';
5679 }
5680 
5681 
5682 static const struct {
5683 	const char *extension;
5684 	size_t ext_len;
5685 	const char *mime_type;
5686 } builtin_mime_types[] = {
5687     /* IANA registered MIME types (http://www.iana.org/assignments/media-types)
5688      * application types */
5689     {".doc", 4, "application/msword"},
5690     {".eps", 4, "application/postscript"},
5691     {".exe", 4, "application/octet-stream"},
5692     {".js", 3, "application/javascript"},
5693     {".json", 5, "application/json"},
5694     {".pdf", 4, "application/pdf"},
5695     {".ps", 3, "application/postscript"},
5696     {".rtf", 4, "application/rtf"},
5697     {".xhtml", 6, "application/xhtml+xml"},
5698     {".xsl", 4, "application/xml"},
5699     {".xslt", 5, "application/xml"},
5700 
5701     /* fonts */
5702     {".ttf", 4, "application/font-sfnt"},
5703     {".cff", 4, "application/font-sfnt"},
5704     {".otf", 4, "application/font-sfnt"},
5705     {".aat", 4, "application/font-sfnt"},
5706     {".sil", 4, "application/font-sfnt"},
5707     {".pfr", 4, "application/font-tdpfr"},
5708     {".woff", 5, "application/font-woff"},
5709 
5710     /* audio */
5711     {".mp3", 4, "audio/mpeg"},
5712     {".oga", 4, "audio/ogg"},
5713     {".ogg", 4, "audio/ogg"},
5714 
5715     /* image */
5716     {".gif", 4, "image/gif"},
5717     {".ief", 4, "image/ief"},
5718     {".jpeg", 5, "image/jpeg"},
5719     {".jpg", 4, "image/jpeg"},
5720     {".jpm", 4, "image/jpm"},
5721     {".jpx", 4, "image/jpx"},
5722     {".png", 4, "image/png"},
5723     {".svg", 4, "image/svg+xml"},
5724     {".tif", 4, "image/tiff"},
5725     {".tiff", 5, "image/tiff"},
5726 
5727     /* model */
5728     {".wrl", 4, "model/vrml"},
5729 
5730     /* text */
5731     {".css", 4, "text/css"},
5732     {".csv", 4, "text/csv"},
5733     {".htm", 4, "text/html"},
5734     {".html", 5, "text/html"},
5735     {".sgm", 4, "text/sgml"},
5736     {".shtm", 5, "text/html"},
5737     {".shtml", 6, "text/html"},
5738     {".txt", 4, "text/plain"},
5739     {".xml", 4, "text/xml"},
5740 
5741     /* video */
5742     {".mov", 4, "video/quicktime"},
5743     {".mp4", 4, "video/mp4"},
5744     {".mpeg", 5, "video/mpeg"},
5745     {".mpg", 4, "video/mpeg"},
5746     {".ogv", 4, "video/ogg"},
5747     {".qt", 3, "video/quicktime"},
5748 
5749     /* not registered types
5750      * (http://reference.sitepoint.com/html/mime-types-full,
5751      * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
5752     {".arj", 4, "application/x-arj-compressed"},
5753     {".gz", 3, "application/x-gunzip"},
5754     {".rar", 4, "application/x-arj-compressed"},
5755     {".swf", 4, "application/x-shockwave-flash"},
5756     {".tar", 4, "application/x-tar"},
5757     {".tgz", 4, "application/x-tar-gz"},
5758     {".torrent", 8, "application/x-bittorrent"},
5759     {".ppt", 4, "application/x-mspowerpoint"},
5760     {".xls", 4, "application/x-msexcel"},
5761     {".zip", 4, "application/x-zip-compressed"},
5762     {".aac",
5763      4,
5764      "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
5765     {".aif", 4, "audio/x-aif"},
5766     {".m3u", 4, "audio/x-mpegurl"},
5767     {".mid", 4, "audio/x-midi"},
5768     {".ra", 3, "audio/x-pn-realaudio"},
5769     {".ram", 4, "audio/x-pn-realaudio"},
5770     {".wav", 4, "audio/x-wav"},
5771     {".bmp", 4, "image/bmp"},
5772     {".ico", 4, "image/x-icon"},
5773     {".pct", 4, "image/x-pct"},
5774     {".pict", 5, "image/pict"},
5775     {".rgb", 4, "image/x-rgb"},
5776     {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
5777     {".asf", 4, "video/x-ms-asf"},
5778     {".avi", 4, "video/x-msvideo"},
5779     {".m4v", 4, "video/x-m4v"},
5780     {NULL, 0, NULL}};
5781 
5782 
5783 const char *
mg_get_builtin_mime_type(const char * path)5784 mg_get_builtin_mime_type(const char *path)
5785 {
5786 	const char *ext;
5787 	size_t i, path_len;
5788 
5789 	path_len = strlen(path);
5790 
5791 	for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
5792 		ext = path + (path_len - builtin_mime_types[i].ext_len);
5793 		if (path_len > builtin_mime_types[i].ext_len
5794 		    && mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
5795 			return builtin_mime_types[i].mime_type;
5796 		}
5797 	}
5798 
5799 	return "text/plain";
5800 }
5801 
5802 
5803 /* Look at the "path" extension and figure what mime type it has.
5804  * Store mime type in the vector. */
5805 static void
get_mime_type(struct mg_context * ctx,const char * path,struct vec * vec)5806 get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
5807 {
5808 	struct vec ext_vec, mime_vec;
5809 	const char *list, *ext;
5810 	size_t path_len;
5811 
5812 	path_len = strlen(path);
5813 
5814 	if (ctx == NULL || vec == NULL) {
5815 		return;
5816 	}
5817 
5818 	/* Scan user-defined mime types first, in case user wants to
5819 	 * override default mime types. */
5820 	list = ctx->config[EXTRA_MIME_TYPES];
5821 	while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
5822 		/* ext now points to the path suffix */
5823 		ext = path + path_len - ext_vec.len;
5824 		if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
5825 			*vec = mime_vec;
5826 			return;
5827 		}
5828 	}
5829 
5830 	vec->ptr = mg_get_builtin_mime_type(path);
5831 	vec->len = strlen(vec->ptr);
5832 }
5833 
5834 
5835 /* Stringify binary data. Output buffer must be twice as big as input,
5836  * because each byte takes 2 bytes in string representation */
5837 static void
bin2str(char * to,const unsigned char * p,size_t len)5838 bin2str(char *to, const unsigned char *p, size_t len)
5839 {
5840 	static const char *hex = "0123456789abcdef";
5841 
5842 	for (; len--; p++) {
5843 		*to++ = hex[p[0] >> 4];
5844 		*to++ = hex[p[0] & 0x0f];
5845 	}
5846 	*to = '\0';
5847 }
5848 
5849 
5850 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */
5851 char *
mg_md5(char buf[33],...)5852 mg_md5(char buf[33], ...)
5853 {
5854 	md5_byte_t hash[16];
5855 	const char *p;
5856 	va_list ap;
5857 	md5_state_t ctx;
5858 
5859 	md5_init(&ctx);
5860 
5861 	va_start(ap, buf);
5862 	while ((p = va_arg(ap, const char *)) != NULL) {
5863 		md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
5864 	}
5865 	va_end(ap);
5866 
5867 	md5_finish(&ctx, hash);
5868 	bin2str(buf, hash, sizeof(hash));
5869 	return buf;
5870 }
5871 
5872 
5873 /* Check the user's password, return 1 if OK */
5874 static int
check_password(const char * method,const char * ha1,const char * uri,const char * nonce,const char * nc,const char * cnonce,const char * qop,const char * response)5875 check_password(const char *method,
5876                const char *ha1,
5877                const char *uri,
5878                const char *nonce,
5879                const char *nc,
5880                const char *cnonce,
5881                const char *qop,
5882                const char *response)
5883 {
5884 	char ha2[32 + 1], expected_response[32 + 1];
5885 
5886 	/* Some of the parameters may be NULL */
5887 	if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL
5888 	    || qop == NULL
5889 	    || response == NULL) {
5890 		return 0;
5891 	}
5892 
5893 	/* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
5894 	if (strlen(response) != 32) {
5895 		return 0;
5896 	}
5897 
5898 	mg_md5(ha2, method, ":", uri, NULL);
5899 	mg_md5(expected_response,
5900 	       ha1,
5901 	       ":",
5902 	       nonce,
5903 	       ":",
5904 	       nc,
5905 	       ":",
5906 	       cnonce,
5907 	       ":",
5908 	       qop,
5909 	       ":",
5910 	       ha2,
5911 	       NULL);
5912 
5913 	return mg_strcasecmp(response, expected_response) == 0;
5914 }
5915 
5916 
5917 /* Use the global passwords file, if specified by auth_gpass option,
5918  * or search for .htpasswd in the requested directory. */
5919 static void
open_auth_file(struct mg_connection * conn,const char * path,struct mg_file * filep)5920 open_auth_file(struct mg_connection *conn,
5921                const char *path,
5922                struct mg_file *filep)
5923 {
5924 	if (conn != NULL && conn->ctx != NULL) {
5925 		char name[PATH_MAX];
5926 		const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
5927 		int truncated;
5928 
5929 		if (gpass != NULL) {
5930 			/* Use global passwords file */
5931 			if (!mg_fopen(conn, gpass, MG_FOPEN_MODE_READ, filep)) {
5932 #ifdef DEBUG
5933 				mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
5934 #endif
5935 			}
5936 			/* Important: using local struct mg_file to test path for
5937 			 * is_directory
5938 			 * flag. If filep is used, mg_stat() makes it appear as if auth file
5939 			 * was opened. TODO: mg_stat must not make anything appear to be
5940 			 * opened */
5941 		} else if (mg_stat(conn, path, &filep->stat)
5942 		           && filep->stat.is_directory) {
5943 			mg_snprintf(conn,
5944 			            &truncated,
5945 			            name,
5946 			            sizeof(name),
5947 			            "%s/%s",
5948 			            path,
5949 			            PASSWORDS_FILE_NAME);
5950 
5951 			if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
5952 #ifdef DEBUG
5953 				mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5954 #endif
5955 			}
5956 		} else {
5957 			/* Try to find .htpasswd in requested directory. */
5958 			for (p = path, e = p + strlen(p) - 1; e > p; e--) {
5959 				if (e[0] == '/') {
5960 					break;
5961 				}
5962 			}
5963 			mg_snprintf(conn,
5964 			            &truncated,
5965 			            name,
5966 			            sizeof(name),
5967 			            "%.*s/%s",
5968 			            (int)(e - p),
5969 			            p,
5970 			            PASSWORDS_FILE_NAME);
5971 
5972 			if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
5973 #ifdef DEBUG
5974 				mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5975 #endif
5976 			}
5977 		}
5978 	}
5979 }
5980 
5981 
5982 /* Parsed Authorization header */
5983 struct ah {
5984 	char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
5985 };
5986 
5987 
5988 /* Return 1 on success. Always initializes the ah structure. */
5989 static int
parse_auth_header(struct mg_connection * conn,char * buf,size_t buf_size,struct ah * ah)5990 parse_auth_header(struct mg_connection *conn,
5991                   char *buf,
5992                   size_t buf_size,
5993                   struct ah *ah)
5994 {
5995 	char *name, *value, *s;
5996 	const char *auth_header;
5997 	uint64_t nonce;
5998 
5999 	if (!ah || !conn) {
6000 		return 0;
6001 	}
6002 
6003 	(void)memset(ah, 0, sizeof(*ah));
6004 	if ((auth_header = mg_get_header(conn, "Authorization")) == NULL
6005 	    || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
6006 		return 0;
6007 	}
6008 
6009 	/* Make modifiable copy of the auth header */
6010 	(void)mg_strlcpy(buf, auth_header + 7, buf_size);
6011 	s = buf;
6012 
6013 	/* Parse authorization header */
6014 	for (;;) {
6015 		/* Gobble initial spaces */
6016 		while (isspace(*(unsigned char *)s)) {
6017 			s++;
6018 		}
6019 		name = skip_quoted(&s, "=", " ", 0);
6020 		/* Value is either quote-delimited, or ends at first comma or space. */
6021 		if (s[0] == '\"') {
6022 			s++;
6023 			value = skip_quoted(&s, "\"", " ", '\\');
6024 			if (s[0] == ',') {
6025 				s++;
6026 			}
6027 		} else {
6028 			value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
6029 			                                        * spaces */
6030 		}
6031 		if (*name == '\0') {
6032 			break;
6033 		}
6034 
6035 		if (!strcmp(name, "username")) {
6036 			ah->user = value;
6037 		} else if (!strcmp(name, "cnonce")) {
6038 			ah->cnonce = value;
6039 		} else if (!strcmp(name, "response")) {
6040 			ah->response = value;
6041 		} else if (!strcmp(name, "uri")) {
6042 			ah->uri = value;
6043 		} else if (!strcmp(name, "qop")) {
6044 			ah->qop = value;
6045 		} else if (!strcmp(name, "nc")) {
6046 			ah->nc = value;
6047 		} else if (!strcmp(name, "nonce")) {
6048 			ah->nonce = value;
6049 		}
6050 	}
6051 
6052 #ifndef NO_NONCE_CHECK
6053 	/* Read the nonce from the response. */
6054 	if (ah->nonce == NULL) {
6055 		return 0;
6056 	}
6057 	s = NULL;
6058 	nonce = strtoull(ah->nonce, &s, 10);
6059 	if ((s == NULL) || (*s != 0)) {
6060 		return 0;
6061 	}
6062 
6063 	/* Convert the nonce from the client to a number. */
6064 	nonce ^= conn->ctx->auth_nonce_mask;
6065 
6066 	/* The converted number corresponds to the time the nounce has been
6067 	 * created. This should not be earlier than the server start. */
6068 	/* Server side nonce check is valuable in all situations but one:
6069 	 * if the server restarts frequently, but the client should not see
6070 	 * that, so the server should accept nonces from previous starts. */
6071 	/* However, the reasonable default is to not accept a nonce from a
6072 	 * previous start, so if anyone changed the access rights between
6073 	 * two restarts, a new login is required. */
6074 	if (nonce < (uint64_t)conn->ctx->start_time) {
6075 		/* nonce is from a previous start of the server and no longer valid
6076 		 * (replay attack?) */
6077 		return 0;
6078 	}
6079 	/* Check if the nonce is too high, so it has not (yet) been used by the
6080 	 * server. */
6081 	if (nonce >= ((uint64_t)conn->ctx->start_time + conn->ctx->nonce_count)) {
6082 		return 0;
6083 	}
6084 #else
6085 	(void)nonce;
6086 #endif
6087 
6088 	/* CGI needs it as REMOTE_USER */
6089 	if (ah->user != NULL) {
6090 		conn->request_info.remote_user = mg_strdup(ah->user);
6091 	} else {
6092 		return 0;
6093 	}
6094 
6095 	return 1;
6096 }
6097 
6098 
6099 static const char *
mg_fgets(char * buf,size_t size,struct mg_file * filep,char ** p)6100 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p)
6101 {
6102 	const char *eof;
6103 	size_t len;
6104 	const char *memend;
6105 
6106 	if (!filep) {
6107 		return NULL;
6108 	}
6109 
6110 	if (filep->access.membuf != NULL && *p != NULL) {
6111 		memend = (const char *)&filep->access.membuf[filep->stat.size];
6112 		/* Search for \n from p till the end of stream */
6113 		eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
6114 		if (eof != NULL) {
6115 			eof += 1; /* Include \n */
6116 		} else {
6117 			eof = memend; /* Copy remaining data */
6118 		}
6119 		len =
6120 		    ((size_t)(eof - *p) > (size - 1)) ? (size - 1) : (size_t)(eof - *p);
6121 		memcpy(buf, *p, len);
6122 		buf[len] = '\0';
6123 		*p += len;
6124 		return len ? eof : NULL;
6125 	} else if (filep->access.fp != NULL) {
6126 		return fgets(buf, (int)size, filep->access.fp);
6127 	} else {
6128 		return NULL;
6129 	}
6130 }
6131 
6132 /* Define the initial recursion depth for procesesing htpasswd files that include other htpasswd
6133  * (or even the same) files.  It is not difficult to provide a file or files s.t. they force civetweb
6134  * to infinitely recurse and then crash.
6135  */
6136 #define INITIAL_DEPTH 9
6137 #if INITIAL_DEPTH <= 0
6138 #error Bad INITIAL_DEPTH for recursion, set to at least 1
6139 #endif
6140 
6141 struct read_auth_file_struct {
6142 	struct mg_connection *conn;
6143 	struct ah ah;
6144 	char *domain;
6145 	char buf[256 + 256 + 40];
6146 	char *f_user;
6147 	char *f_domain;
6148 	char *f_ha1;
6149 };
6150 
6151 
6152 static int
read_auth_file(struct mg_file * filep,struct read_auth_file_struct * workdata,int depth)6153 read_auth_file(struct mg_file *filep, struct read_auth_file_struct *workdata, int depth)
6154 {
6155 	char *p;
6156 	int is_authorized = 0;
6157 	struct mg_file fp;
6158 	size_t l;
6159 
6160 	if (!filep || !workdata || 0 == depth) {
6161 		return 0;
6162 	}
6163 
6164 	/* Loop over passwords file */
6165 	p = (char *)filep->access.membuf;
6166 	while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
6167 		l = strlen(workdata->buf);
6168 		while (l > 0) {
6169 			if (isspace(workdata->buf[l - 1])
6170 			    || iscntrl(workdata->buf[l - 1])) {
6171 				l--;
6172 				workdata->buf[l] = 0;
6173 			} else
6174 				break;
6175 		}
6176 		if (l < 1) {
6177 			continue;
6178 		}
6179 
6180 		workdata->f_user = workdata->buf;
6181 
6182 		if (workdata->f_user[0] == ':') {
6183 			/* user names may not contain a ':' and may not be empty,
6184 			 * so lines starting with ':' may be used for a special purpose */
6185 			if (workdata->f_user[1] == '#') {
6186 				/* :# is a comment */
6187 				continue;
6188 			} else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
6189 				if (mg_fopen(workdata->conn,
6190 				             workdata->f_user + 9,
6191 				             MG_FOPEN_MODE_READ,
6192 				             &fp)) {
6193 					is_authorized = read_auth_file(&fp, workdata, depth - 1);
6194 					(void)mg_fclose(
6195 					    &fp.access); /* ignore error on read only file */
6196 
6197 					/* No need to continue processing files once we have a match, since nothing will reset it back
6198 					 * to 0.
6199 					 */
6200 					if (is_authorized) {
6201 						return is_authorized;
6202 					}
6203 				} else {
6204 					mg_cry(workdata->conn,
6205 					       "%s: cannot open authorization file: %s",
6206 					       __func__,
6207 					       workdata->buf);
6208 				}
6209 				continue;
6210 			}
6211 			/* everything is invalid for the moment (might change in the
6212 			 * future) */
6213 			mg_cry(workdata->conn,
6214 			       "%s: syntax error in authorization file: %s",
6215 			       __func__,
6216 			       workdata->buf);
6217 			continue;
6218 		}
6219 
6220 		workdata->f_domain = strchr(workdata->f_user, ':');
6221 		if (workdata->f_domain == NULL) {
6222 			mg_cry(workdata->conn,
6223 			       "%s: syntax error in authorization file: %s",
6224 			       __func__,
6225 			       workdata->buf);
6226 			continue;
6227 		}
6228 		*(workdata->f_domain) = 0;
6229 		(workdata->f_domain)++;
6230 
6231 		workdata->f_ha1 = strchr(workdata->f_domain, ':');
6232 		if (workdata->f_ha1 == NULL) {
6233 			mg_cry(workdata->conn,
6234 			       "%s: syntax error in authorization file: %s",
6235 			       __func__,
6236 			       workdata->buf);
6237 			continue;
6238 		}
6239 		*(workdata->f_ha1) = 0;
6240 		(workdata->f_ha1)++;
6241 
6242 		if (!strcmp(workdata->ah.user, workdata->f_user)
6243 		    && !strcmp(workdata->domain, workdata->f_domain)) {
6244 			return check_password(workdata->conn->request_info.request_method,
6245 			                      workdata->f_ha1,
6246 			                      workdata->ah.uri,
6247 			                      workdata->ah.nonce,
6248 			                      workdata->ah.nc,
6249 			                      workdata->ah.cnonce,
6250 			                      workdata->ah.qop,
6251 			                      workdata->ah.response);
6252 		}
6253 	}
6254 
6255 	return is_authorized;
6256 }
6257 
6258 
6259 /* Authorize against the opened passwords file. Return 1 if authorized. */
6260 static int
authorize(struct mg_connection * conn,struct mg_file * filep)6261 authorize(struct mg_connection *conn, struct mg_file *filep)
6262 {
6263 	struct read_auth_file_struct workdata;
6264 	char buf[MG_BUF_LEN];
6265 
6266 	if (!conn || !conn->ctx) {
6267 		return 0;
6268 	}
6269 
6270 	memset(&workdata, 0, sizeof(workdata));
6271 	workdata.conn = conn;
6272 
6273 	if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
6274 		return 0;
6275 	}
6276 	workdata.domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
6277 
6278 	return read_auth_file(filep, &workdata, INITIAL_DEPTH);
6279 }
6280 
6281 
6282 /* Return 1 if request is authorised, 0 otherwise. */
6283 static int
check_authorization(struct mg_connection * conn,const char * path)6284 check_authorization(struct mg_connection *conn, const char *path)
6285 {
6286 	char fname[PATH_MAX];
6287 	struct vec uri_vec, filename_vec;
6288 	const char *list;
6289 	struct mg_file file = STRUCT_FILE_INITIALIZER;
6290 	int authorized = 1, truncated;
6291 
6292 	if (!conn || !conn->ctx) {
6293 		return 0;
6294 	}
6295 
6296 	list = conn->ctx->config[PROTECT_URI];
6297 	while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
6298 		if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
6299 			mg_snprintf(conn,
6300 			            &truncated,
6301 			            fname,
6302 			            sizeof(fname),
6303 			            "%.*s",
6304 			            (int)filename_vec.len,
6305 			            filename_vec.ptr);
6306 
6307 			if (truncated
6308 			    || !mg_fopen(conn, fname, MG_FOPEN_MODE_READ, &file)) {
6309 				mg_cry(conn,
6310 				       "%s: cannot open %s: %s",
6311 				       __func__,
6312 				       fname,
6313 				       strerror(errno));
6314 			}
6315 			break;
6316 		}
6317 	}
6318 
6319 	if (!is_file_opened(&file.access)) {
6320 		open_auth_file(conn, path, &file);
6321 	}
6322 
6323 	if (is_file_opened(&file.access)) {
6324 		authorized = authorize(conn, &file);
6325 		(void)mg_fclose(&file.access); /* ignore error on read only file */
6326 	}
6327 
6328 	return authorized;
6329 }
6330 
6331 
6332 static void
send_authorization_request(struct mg_connection * conn)6333 send_authorization_request(struct mg_connection *conn)
6334 {
6335 	char date[64];
6336 	time_t curtime = time(NULL);
6337 
6338 	if (conn && conn->ctx) {
6339 		uint64_t nonce = (uint64_t)(conn->ctx->start_time);
6340 
6341 		(void)pthread_mutex_lock(&conn->ctx->nonce_mutex);
6342 		nonce += conn->ctx->nonce_count;
6343 		++conn->ctx->nonce_count;
6344 		(void)pthread_mutex_unlock(&conn->ctx->nonce_mutex);
6345 
6346 		nonce ^= conn->ctx->auth_nonce_mask;
6347 		conn->status_code = 401;
6348 		conn->must_close = 1;
6349 
6350 		gmt_time_string(date, sizeof(date), &curtime);
6351 
6352 		mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
6353 		send_no_cache_header(conn);
6354 		mg_printf(conn,
6355 		          "Date: %s\r\n"
6356 		          "Connection: %s\r\n"
6357 		          "Content-Length: 0\r\n"
6358 		          "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
6359 		          "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
6360 		          date,
6361 		          suggest_connection_header(conn),
6362 		          conn->ctx->config[AUTHENTICATION_DOMAIN],
6363 		          nonce);
6364 	}
6365 }
6366 
6367 
6368 #if !defined(NO_FILES)
6369 static int
is_authorized_for_put(struct mg_connection * conn)6370 is_authorized_for_put(struct mg_connection *conn)
6371 {
6372 	if (conn) {
6373 		struct mg_file file = STRUCT_FILE_INITIALIZER;
6374 		const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
6375 		int ret = 0;
6376 
6377 		if (passfile != NULL
6378 		    && mg_fopen(conn, passfile, MG_FOPEN_MODE_READ, &file)) {
6379 			ret = authorize(conn, &file);
6380 			(void)mg_fclose(&file.access); /* ignore error on read only file */
6381 		}
6382 
6383 		return ret;
6384 	}
6385 	return 0;
6386 }
6387 #endif
6388 
6389 
6390 int
mg_modify_passwords_file(const char * fname,const char * domain,const char * user,const char * pass)6391 mg_modify_passwords_file(const char *fname,
6392                          const char *domain,
6393                          const char *user,
6394                          const char *pass)
6395 {
6396 	int found, i;
6397 	char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
6398 	FILE *fp, *fp2;
6399 
6400 	found = 0;
6401 	fp = fp2 = NULL;
6402 
6403 	/* Regard empty password as no password - remove user record. */
6404 	if (pass != NULL && pass[0] == '\0') {
6405 		pass = NULL;
6406 	}
6407 
6408 	/* Other arguments must not be empty */
6409 	if (fname == NULL || domain == NULL || user == NULL) {
6410 		return 0;
6411 	}
6412 
6413 	/* Using the given file format, user name and domain must not contain ':'
6414 	 */
6415 	if (strchr(user, ':') != NULL) {
6416 		return 0;
6417 	}
6418 	if (strchr(domain, ':') != NULL) {
6419 		return 0;
6420 	}
6421 
6422 	/* Do not allow control characters like newline in user name and domain.
6423 	 * Do not allow excessively long names either. */
6424 	for (i = 0; i < 255 && user[i] != 0; i++) {
6425 		if (iscntrl(user[i])) {
6426 			return 0;
6427 		}
6428 	}
6429 	if (user[i]) {
6430 		return 0;
6431 	}
6432 	for (i = 0; i < 255 && domain[i] != 0; i++) {
6433 		if (iscntrl(domain[i])) {
6434 			return 0;
6435 		}
6436 	}
6437 	if (domain[i]) {
6438 		return 0;
6439 	}
6440 
6441 	/* The maximum length of the path to the password file is limited */
6442 	if ((strlen(fname) + 4) >= PATH_MAX) {
6443 		return 0;
6444 	}
6445 
6446 	/* Create a temporary file name. Length has been checked before. */
6447 	strcpy(tmp, fname);
6448 	strcat(tmp, ".tmp");
6449 
6450 	/* Create the file if does not exist */
6451 	/* Use of fopen here is OK, since fname is only ASCII */
6452 	if ((fp = fopen(fname, "a+")) != NULL) {
6453 		(void)fclose(fp);
6454 	}
6455 
6456 	/* Open the given file and temporary file */
6457 	if ((fp = fopen(fname, "r")) == NULL) {
6458 		return 0;
6459 	} else if ((fp2 = fopen(tmp, "w+")) == NULL) {
6460 		fclose(fp);
6461 		return 0;
6462 	}
6463 
6464 	/* Copy the stuff to temporary file */
6465 	while (fgets(line, sizeof(line), fp) != NULL) {
6466 		if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
6467 			continue;
6468 		}
6469 		u[255] = 0;
6470 		d[255] = 0;
6471 
6472 		if (!strcmp(u, user) && !strcmp(d, domain)) {
6473 			found++;
6474 			if (pass != NULL) {
6475 				mg_md5(ha1, user, ":", domain, ":", pass, NULL);
6476 				fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
6477 			}
6478 		} else {
6479 			fprintf(fp2, "%s", line);
6480 		}
6481 	}
6482 
6483 	/* If new user, just add it */
6484 	if (!found && pass != NULL) {
6485 		mg_md5(ha1, user, ":", domain, ":", pass, NULL);
6486 		fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
6487 	}
6488 
6489 	/* Close files */
6490 	fclose(fp);
6491 	fclose(fp2);
6492 
6493 	/* Put the temp file in place of real file */
6494 	IGNORE_UNUSED_RESULT(remove(fname));
6495 	IGNORE_UNUSED_RESULT(rename(tmp, fname));
6496 
6497 	return 1;
6498 }
6499 
6500 
6501 static int
is_valid_port(unsigned long port)6502 is_valid_port(unsigned long port)
6503 {
6504 	return port < 0xffff;
6505 }
6506 
6507 
6508 static int
mg_inet_pton(int af,const char * src,void * dst,size_t dstlen)6509 mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
6510 {
6511 	struct addrinfo hints, *res, *ressave;
6512 	int func_ret = 0;
6513 	int gai_ret;
6514 
6515 	memset(&hints, 0, sizeof(struct addrinfo));
6516 	hints.ai_family = af;
6517 
6518 	gai_ret = getaddrinfo(src, NULL, &hints, &res);
6519 	if (gai_ret != 0) {
6520 		/* gai_strerror could be used to convert gai_ret to a string */
6521 		/* POSIX return values: see
6522 		 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
6523 		 */
6524 		/* Windows return values: see
6525 		 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
6526 		 */
6527 		return 0;
6528 	}
6529 
6530 	ressave = res;
6531 
6532 	while (res) {
6533 		if (dstlen >= res->ai_addrlen) {
6534 			memcpy(dst, res->ai_addr, res->ai_addrlen);
6535 			func_ret = 1;
6536 		}
6537 		res = res->ai_next;
6538 	}
6539 
6540 	freeaddrinfo(ressave);
6541 	return func_ret;
6542 }
6543 
6544 
6545 static int
connect_socket(struct mg_context * ctx,const char * host,int port,int use_ssl,char * ebuf,size_t ebuf_len,SOCKET * sock,union usa * sa)6546 connect_socket(struct mg_context *ctx /* may be NULL */,
6547                const char *host,
6548                int port,
6549                int use_ssl,
6550                char *ebuf,
6551                size_t ebuf_len,
6552                SOCKET *sock /* output: socket, must not be NULL */,
6553                union usa *sa /* output: socket address, must not be NULL  */
6554                )
6555 {
6556 	int ip_ver = 0;
6557 	*sock = INVALID_SOCKET;
6558 	memset(sa, 0, sizeof(*sa));
6559 
6560 	if (ebuf_len > 0) {
6561 		*ebuf = 0;
6562 	}
6563 
6564 	if (host == NULL) {
6565 		mg_snprintf(NULL,
6566 		            NULL, /* No truncation check for ebuf */
6567 		            ebuf,
6568 		            ebuf_len,
6569 		            "%s",
6570 		            "NULL host");
6571 		return 0;
6572 	}
6573 
6574 	if (port < 0 || !is_valid_port((unsigned)port)) {
6575 		mg_snprintf(NULL,
6576 		            NULL, /* No truncation check for ebuf */
6577 		            ebuf,
6578 		            ebuf_len,
6579 		            "%s",
6580 		            "invalid port");
6581 		return 0;
6582 	}
6583 
6584 #if !defined(NO_SSL)
6585 	if (use_ssl && (SSLv23_client_method == NULL)) {
6586 		mg_snprintf(NULL,
6587 		            NULL, /* No truncation check for ebuf */
6588 		            ebuf,
6589 		            ebuf_len,
6590 		            "%s",
6591 		            "SSL is not initialized");
6592 		return 0;
6593 	}
6594 #else
6595 	(void)use_ssl;
6596 #endif
6597 
6598 	if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
6599 		sa->sin.sin_port = htons((uint16_t)port);
6600 		ip_ver = 4;
6601 #ifdef USE_IPV6
6602 	} else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
6603 		sa->sin6.sin6_port = htons((uint16_t)port);
6604 		ip_ver = 6;
6605 	} else if (host[0] == '[') {
6606 		/* While getaddrinfo on Windows will work with [::1],
6607 		 * getaddrinfo on Linux only works with ::1 (without []). */
6608 		size_t l = strlen(host + 1);
6609 		char *h = (l > 1) ? mg_strdup(host + 1) : NULL;
6610 		if (h) {
6611 			h[l - 1] = 0;
6612 			if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
6613 				sa->sin6.sin6_port = htons((uint16_t)port);
6614 				ip_ver = 6;
6615 			}
6616 			mg_free(h);
6617 		}
6618 #endif
6619 	}
6620 
6621 	if (ip_ver == 0) {
6622 		mg_snprintf(NULL,
6623 		            NULL, /* No truncation check for ebuf */
6624 		            ebuf,
6625 		            ebuf_len,
6626 		            "%s",
6627 		            "host not found");
6628 		return 0;
6629 	}
6630 
6631 	if (ip_ver == 4) {
6632 		*sock = socket(PF_INET, SOCK_STREAM, 0);
6633 	}
6634 #ifdef USE_IPV6
6635 	else if (ip_ver == 6) {
6636 		*sock = socket(PF_INET6, SOCK_STREAM, 0);
6637 	}
6638 #endif
6639 
6640 	if (*sock == INVALID_SOCKET) {
6641 		mg_snprintf(NULL,
6642 		            NULL, /* No truncation check for ebuf */
6643 		            ebuf,
6644 		            ebuf_len,
6645 		            "socket(): %s",
6646 		            strerror(ERRNO));
6647 		return 0;
6648 	}
6649 
6650 	set_close_on_exec(*sock, fc(ctx));
6651 
6652 	if ((ip_ver == 4)
6653 	    && (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
6654 	        == 0)) {
6655 		/* connected with IPv4 */
6656 		set_blocking_mode(*sock, 0);
6657 		return 1;
6658 	}
6659 
6660 #ifdef USE_IPV6
6661 	if ((ip_ver == 6)
6662 	    && (connect(*sock, (struct sockaddr *)&sa->sin6, sizeof(sa->sin6))
6663 	        == 0)) {
6664 		/* connected with IPv6 */
6665 		set_blocking_mode(*sock, 0);
6666 		return 1;
6667 	}
6668 #endif
6669 
6670 	/* Not connected */
6671 	mg_snprintf(NULL,
6672 	            NULL, /* No truncation check for ebuf */
6673 	            ebuf,
6674 	            ebuf_len,
6675 	            "connect(%s:%d): %s",
6676 	            host,
6677 	            port,
6678 	            strerror(ERRNO));
6679 	closesocket(*sock);
6680 	*sock = INVALID_SOCKET;
6681 
6682 	return 0;
6683 }
6684 
6685 
6686 int
mg_url_encode(const char * src,char * dst,size_t dst_len)6687 mg_url_encode(const char *src, char *dst, size_t dst_len)
6688 {
6689 	static const char *dont_escape = "._-$,;~()";
6690 	static const char *hex = "0123456789abcdef";
6691 	char *pos = dst;
6692 	const char *end = dst + dst_len - 1;
6693 
6694 	for (; *src != '\0' && pos < end; src++, pos++) {
6695 		if (isalnum(*(const unsigned char *)src)
6696 		    || strchr(dont_escape, *(const unsigned char *)src) != NULL) {
6697 			*pos = *src;
6698 		} else if (pos + 2 < end) {
6699 			pos[0] = '%';
6700 			pos[1] = hex[(*(const unsigned char *)src) >> 4];
6701 			pos[2] = hex[(*(const unsigned char *)src) & 0xf];
6702 			pos += 2;
6703 		} else {
6704 			break;
6705 		}
6706 	}
6707 
6708 	*pos = '\0';
6709 	return (*src == '\0') ? (int)(pos - dst) : -1;
6710 }
6711 
6712 
6713 static void
print_dir_entry(struct de * de)6714 print_dir_entry(struct de *de)
6715 {
6716 	char size[64], mod[64], href[PATH_MAX * 3 /* worst case */];
6717 	struct tm *tm;
6718 
6719 	if (de->file.is_directory) {
6720 		mg_snprintf(de->conn,
6721 		            NULL, /* Buffer is big enough */
6722 		            size,
6723 		            sizeof(size),
6724 		            "%s",
6725 		            "[DIRECTORY]");
6726 	} else {
6727 		/* We use (signed) cast below because MSVC 6 compiler cannot
6728 		 * convert unsigned __int64 to double. Sigh. */
6729 		if (de->file.size < 1024) {
6730 			mg_snprintf(de->conn,
6731 			            NULL, /* Buffer is big enough */
6732 			            size,
6733 			            sizeof(size),
6734 			            "%d",
6735 			            (int)de->file.size);
6736 		} else if (de->file.size < 0x100000) {
6737 			mg_snprintf(de->conn,
6738 			            NULL, /* Buffer is big enough */
6739 			            size,
6740 			            sizeof(size),
6741 			            "%.1fk",
6742 			            (double)de->file.size / 1024.0);
6743 		} else if (de->file.size < 0x40000000) {
6744 			mg_snprintf(de->conn,
6745 			            NULL, /* Buffer is big enough */
6746 			            size,
6747 			            sizeof(size),
6748 			            "%.1fM",
6749 			            (double)de->file.size / 1048576);
6750 		} else {
6751 			mg_snprintf(de->conn,
6752 			            NULL, /* Buffer is big enough */
6753 			            size,
6754 			            sizeof(size),
6755 			            "%.1fG",
6756 			            (double)de->file.size / 1073741824);
6757 		}
6758 	}
6759 
6760 	/* Note: mg_snprintf will not cause a buffer overflow above.
6761 	 * So, string truncation checks are not required here. */
6762 
6763 	tm = localtime(&de->file.last_modified);
6764 	if (tm != NULL) {
6765 		strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
6766 	} else {
6767 		mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
6768 		mod[sizeof(mod) - 1] = '\0';
6769 	}
6770 	mg_url_encode(de->file_name, href, sizeof(href));
6771 	de->conn->num_bytes_sent +=
6772 	    mg_printf(de->conn,
6773 	              "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
6774 	              "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6775 	              de->conn->request_info.local_uri,
6776 	              href,
6777 	              de->file.is_directory ? "/" : "",
6778 	              de->file_name,
6779 	              de->file.is_directory ? "/" : "",
6780 	              mod,
6781 	              size);
6782 }
6783 
6784 
6785 /* This function is called from send_directory() and used for
6786  * sorting directory entries by size, or name, or modification time.
6787  * On windows, __cdecl specification is needed in case if project is built
6788  * with __stdcall convention. qsort always requires __cdels callback. */
6789 static int WINCDECL
compare_dir_entries(const void * p1,const void * p2)6790 compare_dir_entries(const void *p1, const void *p2)
6791 {
6792 	if (p1 && p2) {
6793 		const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
6794 		const char *query_string = a->conn->request_info.query_string;
6795 		int cmp_result = 0;
6796 
6797 		if (query_string == NULL) {
6798 			query_string = "na";
6799 		}
6800 
6801 		if (a->file.is_directory && !b->file.is_directory) {
6802 			return -1; /* Always put directories on top */
6803 		} else if (!a->file.is_directory && b->file.is_directory) {
6804 			return 1; /* Always put directories on top */
6805 		} else if (*query_string == 'n') {
6806 			cmp_result = strcmp(a->file_name, b->file_name);
6807 		} else if (*query_string == 's') {
6808 			cmp_result = (a->file.size == b->file.size)
6809 			                 ? 0
6810 			                 : ((a->file.size > b->file.size) ? 1 : -1);
6811 		} else if (*query_string == 'd') {
6812 			cmp_result =
6813 			    (a->file.last_modified == b->file.last_modified)
6814 			        ? 0
6815 			        : ((a->file.last_modified > b->file.last_modified) ? 1
6816 			                                                           : -1);
6817 		}
6818 
6819 		return (query_string[1] == 'd') ? -cmp_result : cmp_result;
6820 	}
6821 	return 0;
6822 }
6823 
6824 
6825 static int
must_hide_file(struct mg_connection * conn,const char * path)6826 must_hide_file(struct mg_connection *conn, const char *path)
6827 {
6828 	if (conn && conn->ctx) {
6829 		const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
6830 		const char *pattern = conn->ctx->config[HIDE_FILES];
6831 		return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
6832 		       || (pattern != NULL
6833 		           && match_prefix(pattern, strlen(pattern), path) > 0);
6834 	}
6835 	return 0;
6836 }
6837 
6838 
6839 static int
scan_directory(struct mg_connection * conn,const char * dir,void * data,void (* cb)(struct de *,void *))6840 scan_directory(struct mg_connection *conn,
6841                const char *dir,
6842                void *data,
6843                void (*cb)(struct de *, void *))
6844 {
6845 	char path[PATH_MAX];
6846 	struct dirent *dp;
6847 	DIR *dirp;
6848 	struct de de;
6849 	int truncated;
6850 
6851 	if ((dirp = mg_opendir(conn, dir)) == NULL) {
6852 		return 0;
6853 	} else {
6854 		de.conn = conn;
6855 
6856 		while ((dp = mg_readdir(dirp)) != NULL) {
6857 			/* Do not show current dir and hidden files */
6858 			if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
6859 			    || must_hide_file(conn, dp->d_name)) {
6860 				continue;
6861 			}
6862 
6863 			mg_snprintf(
6864 			    conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6865 
6866 			/* If we don't memset stat structure to zero, mtime will have
6867 			 * garbage and strftime() will segfault later on in
6868 			 * print_dir_entry(). memset is required only if mg_stat()
6869 			 * fails. For more details, see
6870 			 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6871 			memset(&de.file, 0, sizeof(de.file));
6872 
6873 			if (truncated) {
6874 				/* If the path is not complete, skip processing. */
6875 				continue;
6876 			}
6877 
6878 			if (!mg_stat(conn, path, &de.file)) {
6879 				mg_cry(conn,
6880 				       "%s: mg_stat(%s) failed: %s",
6881 				       __func__,
6882 				       path,
6883 				       strerror(ERRNO));
6884 			}
6885 			de.file_name = dp->d_name;
6886 			cb(&de, data);
6887 		}
6888 		(void)mg_closedir(dirp);
6889 	}
6890 	return 1;
6891 }
6892 
6893 
6894 #if !defined(NO_FILES)
6895 static int
remove_directory(struct mg_connection * conn,const char * dir)6896 remove_directory(struct mg_connection *conn, const char *dir)
6897 {
6898 	char path[PATH_MAX];
6899 	struct dirent *dp;
6900 	DIR *dirp;
6901 	struct de de;
6902 	int truncated;
6903 	int ok = 1;
6904 
6905 	if ((dirp = mg_opendir(conn, dir)) == NULL) {
6906 		return 0;
6907 	} else {
6908 		de.conn = conn;
6909 
6910 		while ((dp = mg_readdir(dirp)) != NULL) {
6911 			/* Do not show current dir (but show hidden files as they will
6912 			 * also be removed) */
6913 			if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
6914 				continue;
6915 			}
6916 
6917 			mg_snprintf(
6918 			    conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6919 
6920 			/* If we don't memset stat structure to zero, mtime will have
6921 			 * garbage and strftime() will segfault later on in
6922 			 * print_dir_entry(). memset is required only if mg_stat()
6923 			 * fails. For more details, see
6924 			 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6925 			memset(&de.file, 0, sizeof(de.file));
6926 
6927 			if (truncated) {
6928 				/* Do not delete anything shorter */
6929 				ok = 0;
6930 				continue;
6931 			}
6932 
6933 			if (!mg_stat(conn, path, &de.file)) {
6934 				mg_cry(conn,
6935 				       "%s: mg_stat(%s) failed: %s",
6936 				       __func__,
6937 				       path,
6938 				       strerror(ERRNO));
6939 				ok = 0;
6940 			}
6941 
6942 			if (de.file.is_directory) {
6943 				if (remove_directory(conn, path) == 0) {
6944 					ok = 0;
6945 				}
6946 			} else {
6947 				/* This will fail file is the file is in memory */
6948 				if (mg_remove(conn, path) == 0) {
6949 					ok = 0;
6950 				}
6951 			}
6952 		}
6953 		(void)mg_closedir(dirp);
6954 
6955 		IGNORE_UNUSED_RESULT(rmdir(dir));
6956 	}
6957 
6958 	return ok;
6959 }
6960 #endif
6961 
6962 
6963 struct dir_scan_data {
6964 	struct de *entries;
6965 	unsigned int num_entries;
6966 	unsigned int arr_size;
6967 };
6968 
6969 
6970 /* Behaves like realloc(), but frees original pointer on failure */
6971 static void *
realloc2(void * ptr,size_t size)6972 realloc2(void *ptr, size_t size)
6973 {
6974 	void *new_ptr = mg_realloc(ptr, size);
6975 	if (new_ptr == NULL) {
6976 		mg_free(ptr);
6977 	}
6978 	return new_ptr;
6979 }
6980 
6981 
6982 static void
dir_scan_callback(struct de * de,void * data)6983 dir_scan_callback(struct de *de, void *data)
6984 {
6985 	struct dir_scan_data *dsd = (struct dir_scan_data *)data;
6986 
6987 	if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
6988 		dsd->arr_size *= 2;
6989 		dsd->entries =
6990 		    (struct de *)realloc2(dsd->entries,
6991 		                          dsd->arr_size * sizeof(dsd->entries[0]));
6992 	}
6993 	if (dsd->entries == NULL) {
6994 		/* TODO(lsm, low): propagate an error to the caller */
6995 		dsd->num_entries = 0;
6996 	} else {
6997 		dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
6998 		dsd->entries[dsd->num_entries].file = de->file;
6999 		dsd->entries[dsd->num_entries].conn = de->conn;
7000 		dsd->num_entries++;
7001 	}
7002 }
7003 
7004 
7005 static void
handle_directory_request(struct mg_connection * conn,const char * dir)7006 handle_directory_request(struct mg_connection *conn, const char *dir)
7007 {
7008 	unsigned int i;
7009 	int sort_direction;
7010 	struct dir_scan_data data = {NULL, 0, 128};
7011 	char date[64];
7012 	time_t curtime = time(NULL);
7013 
7014 	if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
7015 		send_http_error(conn,
7016 		                500,
7017 		                "Error: Cannot open directory\nopendir(%s): %s",
7018 		                dir,
7019 		                strerror(ERRNO));
7020 		return;
7021 	}
7022 
7023 	gmt_time_string(date, sizeof(date), &curtime);
7024 
7025 	if (!conn) {
7026 		return;
7027 	}
7028 
7029 	sort_direction = ((conn->request_info.query_string != NULL)
7030 	                  && (conn->request_info.query_string[1] == 'd'))
7031 	                     ? 'a'
7032 	                     : 'd';
7033 
7034 	conn->must_close = 1;
7035 	mg_printf(conn, "HTTP/1.1 200 OK\r\n");
7036 	send_static_cache_header(conn);
7037 	mg_printf(conn,
7038 	          "Date: %s\r\n"
7039 	          "Connection: close\r\n"
7040 	          "Content-Type: text/html; charset=utf-8\r\n\r\n",
7041 	          date);
7042 
7043 	conn->num_bytes_sent +=
7044 	    mg_printf(conn,
7045 	              "<html><head><title>Index of %s</title>"
7046 	              "<style>th {text-align: left;}</style></head>"
7047 	              "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
7048 	              "<tr><th><a href=\"?n%c\">Name</a></th>"
7049 	              "<th><a href=\"?d%c\">Modified</a></th>"
7050 	              "<th><a href=\"?s%c\">Size</a></th></tr>"
7051 	              "<tr><td colspan=\"3\"><hr></td></tr>",
7052 	              conn->request_info.local_uri,
7053 	              conn->request_info.local_uri,
7054 	              sort_direction,
7055 	              sort_direction,
7056 	              sort_direction);
7057 
7058 	/* Print first entry - link to a parent directory */
7059 	conn->num_bytes_sent +=
7060 	    mg_printf(conn,
7061 	              "<tr><td><a href=\"%s%s\">%s</a></td>"
7062 	              "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
7063 	              conn->request_info.local_uri,
7064 	              "..",
7065 	              "Parent directory",
7066 	              "-",
7067 	              "-");
7068 
7069 	/* Sort and print directory entries */
7070 	if (data.entries != NULL) {
7071 		qsort(data.entries,
7072 		      (size_t)data.num_entries,
7073 		      sizeof(data.entries[0]),
7074 		      compare_dir_entries);
7075 		for (i = 0; i < data.num_entries; i++) {
7076 			print_dir_entry(&data.entries[i]);
7077 			mg_free(data.entries[i].file_name);
7078 		}
7079 		mg_free(data.entries);
7080 	}
7081 
7082 	conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
7083 	conn->status_code = 200;
7084 }
7085 
7086 
7087 /* Send len bytes from the opened file to the client. */
7088 static void
send_file_data(struct mg_connection * conn,struct mg_file * filep,int64_t offset,int64_t len)7089 send_file_data(struct mg_connection *conn,
7090                struct mg_file *filep,
7091                int64_t offset,
7092                int64_t len)
7093 {
7094 	char buf[MG_BUF_LEN];
7095 	int to_read, num_read, num_written;
7096 	int64_t size;
7097 
7098 	if (!filep || !conn) {
7099 		return;
7100 	}
7101 
7102 	/* Sanity check the offset */
7103 	size = (filep->stat.size > INT64_MAX) ? INT64_MAX
7104 	                                      : (int64_t)(filep->stat.size);
7105 	offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
7106 
7107 	if ((len > 0) && (filep->access.membuf != NULL) && (size > 0)) {
7108 		/* file stored in memory */
7109 		if (len > size - offset) {
7110 			len = size - offset;
7111 		}
7112 		mg_write(conn, filep->access.membuf + offset, (size_t)len);
7113 	} else if (len > 0 && filep->access.fp != NULL) {
7114 /* file stored on disk */
7115 #if defined(__linux__)
7116 		/* sendfile is only available for Linux */
7117 		if ((conn->ssl == 0) && (conn->throttle == 0)
7118 		    && (!mg_strcasecmp(conn->ctx->config[ALLOW_SENDFILE_CALL],
7119 		                       "yes"))) {
7120 			off_t sf_offs = (off_t)offset;
7121 			ssize_t sf_sent;
7122 			int sf_file = fileno(filep->access.fp);
7123 			int loop_cnt = 0;
7124 
7125 			do {
7126 				/* 2147479552 (0x7FFFF000) is a limit found by experiment on
7127 				 * 64 bit Linux (2^31 minus one memory page of 4k?). */
7128 				size_t sf_tosend =
7129 				    (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
7130 				sf_sent =
7131 				    sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
7132 				if (sf_sent > 0) {
7133 					conn->num_bytes_sent += sf_sent;
7134 					len -= sf_sent;
7135 					offset += sf_sent;
7136 				} else if (loop_cnt == 0) {
7137 					/* This file can not be sent using sendfile.
7138 					 * This might be the case for pseudo-files in the
7139 					 * /sys/ and /proc/ file system.
7140 					 * Use the regular user mode copy code instead. */
7141 					break;
7142 				} else if (sf_sent == 0) {
7143 					/* No error, but 0 bytes sent. May be EOF? */
7144 					return;
7145 				}
7146 				loop_cnt++;
7147 
7148 			} while ((len > 0) && (sf_sent >= 0));
7149 
7150 			if (sf_sent > 0) {
7151 				return; /* OK */
7152 			}
7153 
7154 			/* sf_sent<0 means error, thus fall back to the classic way */
7155 			/* This is always the case, if sf_file is not a "normal" file,
7156 			 * e.g., for sending data from the output of a CGI process. */
7157 			offset = (int64_t)sf_offs;
7158 		}
7159 #endif
7160 		if ((offset > 0) && (fseeko(filep->access.fp, offset, SEEK_SET) != 0)) {
7161 			mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
7162 			send_http_error(
7163 			    conn,
7164 			    500,
7165 			    "%s",
7166 			    "Error: Unable to access file at requested position.");
7167 		} else {
7168 			while (len > 0) {
7169 				/* Calculate how much to read from the file in the buffer */
7170 				to_read = sizeof(buf);
7171 				if ((int64_t)to_read > len) {
7172 					to_read = (int)len;
7173 				}
7174 
7175 				/* Read from file, exit the loop on error */
7176 				if ((num_read =
7177 				         (int)fread(buf, 1, (size_t)to_read, filep->access.fp))
7178 				    <= 0) {
7179 					break;
7180 				}
7181 
7182 				/* Send read bytes to the client, exit the loop on error */
7183 				if ((num_written = mg_write(conn, buf, (size_t)num_read))
7184 				    != num_read) {
7185 					break;
7186 				}
7187 
7188 				/* Both read and were successful, adjust counters */
7189 				conn->num_bytes_sent += num_written;
7190 				len -= num_written;
7191 			}
7192 		}
7193 	}
7194 }
7195 
7196 
7197 static int
parse_range_header(const char * header,int64_t * a,int64_t * b)7198 parse_range_header(const char *header, int64_t *a, int64_t *b)
7199 {
7200 	return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
7201 }
7202 
7203 
7204 static void
construct_etag(char * buf,size_t buf_len,const struct mg_file_stat * filestat)7205 construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat)
7206 {
7207 	if (filestat != NULL && buf != NULL) {
7208 		mg_snprintf(NULL,
7209 		            NULL, /* All calls to construct_etag use 64 byte buffer */
7210 		            buf,
7211 		            buf_len,
7212 		            "\"%lx.%" INT64_FMT "\"",
7213 		            (unsigned long)filestat->last_modified,
7214 		            filestat->size);
7215 	}
7216 }
7217 
7218 
7219 static void
fclose_on_exec(struct mg_file_access * filep,struct mg_connection * conn)7220 fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
7221 {
7222 	if (filep != NULL && filep->fp != NULL) {
7223 #ifdef _WIN32
7224 		(void)conn; /* Unused. */
7225 #else
7226 		if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
7227 			mg_cry(conn,
7228 			       "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
7229 			       __func__,
7230 			       strerror(ERRNO));
7231 		}
7232 #endif
7233 	}
7234 }
7235 
7236 
7237 static void
handle_static_file_request(struct mg_connection * conn,const char * path,struct mg_file * filep,const char * mime_type,const char * additional_headers)7238 handle_static_file_request(struct mg_connection *conn,
7239                            const char *path,
7240                            struct mg_file *filep,
7241                            const char *mime_type,
7242                            const char *additional_headers)
7243 {
7244 	char date[64], lm[64], etag[64];
7245 	char range[128]; /* large enough, so there will be no overflow */
7246 	const char *msg = "OK", *hdr;
7247 	time_t curtime = time(NULL);
7248 	int64_t cl, r1, r2;
7249 	struct vec mime_vec;
7250 	int n, truncated;
7251 	char gz_path[PATH_MAX];
7252 	const char *encoding = "";
7253 	const char *cors1, *cors2, *cors3;
7254 
7255 	if (conn == NULL || conn->ctx == NULL || filep == NULL) {
7256 		return;
7257 	}
7258 
7259 	if (mime_type == NULL) {
7260 		get_mime_type(conn->ctx, path, &mime_vec);
7261 	} else {
7262 		mime_vec.ptr = mime_type;
7263 		mime_vec.len = strlen(mime_type);
7264 	}
7265 	if (filep->stat.size > INT64_MAX) {
7266 		send_http_error(conn,
7267 		                500,
7268 		                "Error: File size is too large to send\n%" INT64_FMT,
7269 		                filep->stat.size);
7270 	}
7271 	cl = (int64_t)filep->stat.size;
7272 	conn->status_code = 200;
7273 	range[0] = '\0';
7274 
7275 	/* if this file is in fact a pre-gzipped file, rewrite its filename
7276 	 * it's important to rewrite the filename after resolving
7277 	 * the mime type from it, to preserve the actual file's type */
7278 	if (filep->stat.is_gzipped) {
7279 		mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
7280 
7281 		if (truncated) {
7282 			send_http_error(conn,
7283 			                500,
7284 			                "Error: Path of zipped file too long (%s)",
7285 			                path);
7286 			return;
7287 		}
7288 
7289 		path = gz_path;
7290 		encoding = "Content-Encoding: gzip\r\n";
7291 	}
7292 
7293 	if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
7294 		send_http_error(conn,
7295 		                500,
7296 		                "Error: Cannot open file\nfopen(%s): %s",
7297 		                path,
7298 		                strerror(ERRNO));
7299 		return;
7300 	}
7301 
7302 	fclose_on_exec(&filep->access, conn);
7303 
7304 	/* If Range: header specified, act accordingly */
7305 	r1 = r2 = 0;
7306 	hdr = mg_get_header(conn, "Range");
7307 	if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && r1 >= 0
7308 	    && r2 >= 0) {
7309 		/* actually, range requests don't play well with a pre-gzipped
7310 		 * file (since the range is specified in the uncompressed space) */
7311 		if (filep->stat.is_gzipped) {
7312 			send_http_error(
7313 			    conn,
7314 			    501,
7315 			    "%s",
7316 			    "Error: Range requests in gzipped files are not supported");
7317 			(void)mg_fclose(
7318 			    &filep->access); /* ignore error on read only file */
7319 			return;
7320 		}
7321 		conn->status_code = 206;
7322 		cl = (n == 2) ? (((r2 > cl) ? cl : r2) - r1 + 1) : (cl - r1);
7323 		mg_snprintf(conn,
7324 		            NULL, /* range buffer is big enough */
7325 		            range,
7326 		            sizeof(range),
7327 		            "Content-Range: bytes "
7328 		            "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
7329 		            r1,
7330 		            r1 + cl - 1,
7331 		            filep->stat.size);
7332 		msg = "Partial Content";
7333 	}
7334 
7335 	hdr = mg_get_header(conn, "Origin");
7336 	if (hdr) {
7337 		/* Cross-origin resource sharing (CORS), see
7338 		 * http://www.html5rocks.com/en/tutorials/cors/,
7339 		 * http://www.html5rocks.com/static/images/cors_server_flowchart.png -
7340 		 * preflight is not supported for files. */
7341 		cors1 = "Access-Control-Allow-Origin: ";
7342 		cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
7343 		cors3 = "\r\n";
7344 	} else {
7345 		cors1 = cors2 = cors3 = "";
7346 	}
7347 
7348 	/* Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
7349 	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
7350 	gmt_time_string(date, sizeof(date), &curtime);
7351 	gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
7352 	construct_etag(etag, sizeof(etag), &filep->stat);
7353 
7354 	(void)mg_printf(conn,
7355 	                "HTTP/1.1 %d %s\r\n"
7356 	                "%s%s%s"
7357 	                "Date: %s\r\n",
7358 	                conn->status_code,
7359 	                msg,
7360 	                cors1,
7361 	                cors2,
7362 	                cors3,
7363 	                date);
7364 	send_static_cache_header(conn);
7365 	(void)mg_printf(conn,
7366 	                "Last-Modified: %s\r\n"
7367 	                "Etag: %s\r\n"
7368 	                "Content-Type: %.*s\r\n"
7369 	                "Content-Length: %" INT64_FMT "\r\n"
7370 	                "Connection: %s\r\n"
7371 	                "Accept-Ranges: bytes\r\n"
7372 	                "%s%s",
7373 	                lm,
7374 	                etag,
7375 	                (int)mime_vec.len,
7376 	                mime_vec.ptr,
7377 	                cl,
7378 	                suggest_connection_header(conn),
7379 	                range,
7380 	                encoding);
7381 
7382 	/* The previous code must not add any header starting with X- to make
7383 	 * sure no one of the additional_headers is included twice */
7384 
7385 	if (additional_headers != NULL) {
7386 		(void)mg_printf(conn,
7387 		                "%.*s\r\n\r\n",
7388 		                (int)strlen(additional_headers),
7389 		                additional_headers);
7390 	} else {
7391 		(void)mg_printf(conn, "\r\n");
7392 	}
7393 
7394 	if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
7395 		send_file_data(conn, filep, r1, cl);
7396 	}
7397 	(void)mg_fclose(&filep->access); /* ignore error on read only file */
7398 }
7399 
7400 
7401 #if !defined(NO_CACHING)
7402 static void
handle_not_modified_static_file_request(struct mg_connection * conn,struct mg_file * filep)7403 handle_not_modified_static_file_request(struct mg_connection *conn,
7404                                         struct mg_file *filep)
7405 {
7406 	char date[64], lm[64], etag[64];
7407 	time_t curtime = time(NULL);
7408 
7409 	if (conn == NULL || filep == NULL) {
7410 		return;
7411 	}
7412 	conn->status_code = 304;
7413 	gmt_time_string(date, sizeof(date), &curtime);
7414 	gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
7415 	construct_etag(etag, sizeof(etag), &filep->stat);
7416 
7417 	(void)mg_printf(conn,
7418 	                "HTTP/1.1 %d %s\r\n"
7419 	                "Date: %s\r\n",
7420 	                conn->status_code,
7421 	                mg_get_response_code_text(conn, conn->status_code),
7422 	                date);
7423 	send_static_cache_header(conn);
7424 	(void)mg_printf(conn,
7425 	                "Last-Modified: %s\r\n"
7426 	                "Etag: %s\r\n"
7427 	                "Connection: %s\r\n"
7428 	                "\r\n",
7429 	                lm,
7430 	                etag,
7431 	                suggest_connection_header(conn));
7432 }
7433 #endif
7434 
7435 
7436 void
mg_send_file(struct mg_connection * conn,const char * path)7437 mg_send_file(struct mg_connection *conn, const char *path)
7438 {
7439 	mg_send_mime_file(conn, path, NULL);
7440 }
7441 
7442 
7443 void
mg_send_mime_file(struct mg_connection * conn,const char * path,const char * mime_type)7444 mg_send_mime_file(struct mg_connection *conn,
7445                   const char *path,
7446                   const char *mime_type)
7447 {
7448 	mg_send_mime_file2(conn, path, mime_type, NULL);
7449 }
7450 
7451 
7452 void
mg_send_mime_file2(struct mg_connection * conn,const char * path,const char * mime_type,const char * additional_headers)7453 mg_send_mime_file2(struct mg_connection *conn,
7454                    const char *path,
7455                    const char *mime_type,
7456                    const char *additional_headers)
7457 {
7458 	struct mg_file file = STRUCT_FILE_INITIALIZER;
7459 	if (mg_stat(conn, path, &file.stat)) {
7460 		if (file.stat.is_directory) {
7461 			if (!conn) {
7462 				return;
7463 			}
7464 			if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
7465 			                   "yes")) {
7466 				handle_directory_request(conn, path);
7467 			} else {
7468 				send_http_error(conn,
7469 				                403,
7470 				                "%s",
7471 				                "Error: Directory listing denied");
7472 			}
7473 		} else {
7474 			handle_static_file_request(
7475 			    conn, path, &file, mime_type, additional_headers);
7476 		}
7477 	} else {
7478 		send_http_error(conn, 404, "%s", "Error: File not found");
7479 	}
7480 }
7481 
7482 
7483 /* For a given PUT path, create all intermediate subdirectories.
7484  * Return  0  if the path itself is a directory.
7485  * Return  1  if the path leads to a file.
7486  * Return -1  for if the path is too long.
7487  * Return -2  if path can not be created.
7488 */
7489 static int
put_dir(struct mg_connection * conn,const char * path)7490 put_dir(struct mg_connection *conn, const char *path)
7491 {
7492 	char buf[PATH_MAX];
7493 	const char *s, *p;
7494 	struct mg_file file = STRUCT_FILE_INITIALIZER;
7495 	size_t len;
7496 	int res = 1;
7497 
7498 	for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
7499 		len = (size_t)(p - path);
7500 		if (len >= sizeof(buf)) {
7501 			/* path too long */
7502 			res = -1;
7503 			break;
7504 		}
7505 		memcpy(buf, path, len);
7506 		buf[len] = '\0';
7507 
7508 		/* Try to create intermediate directory */
7509 		DEBUG_TRACE("mkdir(%s)", buf);
7510 		if (!mg_stat(conn, buf, &file.stat) && mg_mkdir(conn, buf, 0755) != 0) {
7511 			/* path does not exixt and can not be created */
7512 			res = -2;
7513 			break;
7514 		}
7515 
7516 		/* Is path itself a directory? */
7517 		if (p[1] == '\0') {
7518 			res = 0;
7519 		}
7520 	}
7521 
7522 	return res;
7523 }
7524 
7525 
7526 static void
remove_bad_file(const struct mg_connection * conn,const char * path)7527 remove_bad_file(const struct mg_connection *conn, const char *path)
7528 {
7529 	int r = mg_remove(conn, path);
7530 	if (r != 0) {
7531 		mg_cry(conn, "%s: Cannot remove invalid file %s", __func__, path);
7532 	}
7533 }
7534 
7535 
7536 long long
mg_store_body(struct mg_connection * conn,const char * path)7537 mg_store_body(struct mg_connection *conn, const char *path)
7538 {
7539 	char buf[MG_BUF_LEN];
7540 	long long len = 0;
7541 	int ret, n;
7542 	struct mg_file fi;
7543 
7544 	if (conn->consumed_content != 0) {
7545 		mg_cry(conn, "%s: Contents already consumed", __func__);
7546 		return -11;
7547 	}
7548 
7549 	ret = put_dir(conn, path);
7550 	if (ret < 0) {
7551 		/* -1 for path too long,
7552 		 * -2 for path can not be created. */
7553 		return ret;
7554 	}
7555 	if (ret != 1) {
7556 		/* Return 0 means, path itself is a directory. */
7557 		return 0;
7558 	}
7559 
7560 	if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fi) == 0) {
7561 		return -12;
7562 	}
7563 
7564 	ret = mg_read(conn, buf, sizeof(buf));
7565 	while (ret > 0) {
7566 		n = (int)fwrite(buf, 1, (size_t)ret, fi.access.fp);
7567 		if (n != ret) {
7568 			(void)mg_fclose(
7569 			    &fi.access); /* File is bad and will be removed anyway. */
7570 			remove_bad_file(conn, path);
7571 			return -13;
7572 		}
7573 		ret = mg_read(conn, buf, sizeof(buf));
7574 	}
7575 
7576 	/* File is open for writing. If fclose fails, there was probably an
7577 	 * error flushing the buffer to disk, so the file on disk might be
7578 	 * broken. Delete it and return an error to the caller. */
7579 	if (mg_fclose(&fi.access) != 0) {
7580 		remove_bad_file(conn, path);
7581 		return -14;
7582 	}
7583 
7584 	return len;
7585 }
7586 
7587 
7588 /* Parse HTTP headers from the given buffer, advance buf pointer
7589  * to the point where parsing stopped.
7590  * All parameters must be valid pointers (not NULL).
7591  * Return <0 on error. */
7592 static int
parse_http_headers(char ** buf,struct mg_request_info * ri)7593 parse_http_headers(char **buf, struct mg_request_info *ri)
7594 {
7595 	int i;
7596 
7597 	ri->num_headers = 0;
7598 
7599 	for (i = 0; i < (int)ARRAY_SIZE(ri->http_headers); i++) {
7600 		char *dp = *buf;
7601 		while ((*dp != ':') && (*dp >= 33) && (*dp <= 126)) {
7602 			dp++;
7603 		}
7604 		if (dp == *buf) {
7605 			/* End of headers reached. */
7606 			break;
7607 		}
7608 		if (*dp != ':') {
7609 			/* This is not a valid field. */
7610 			return -1;
7611 		}
7612 
7613 		/* End of header key (*dp == ':') */
7614 		/* Truncate here and set the key name */
7615 		*dp = 0;
7616 		ri->http_headers[i].name = *buf;
7617 		do {
7618 			dp++;
7619 		} while (*dp == ' ');
7620 
7621 		/* The rest of the line is the value */
7622 		ri->http_headers[i].value = dp;
7623 		*buf = dp + strcspn(dp, "\r\n");
7624 		if (((*buf)[0] != '\r') || ((*buf)[1] != '\n')) {
7625 			*buf = NULL;
7626 		}
7627 
7628 
7629 		ri->num_headers = i + 1;
7630 		if (*buf) {
7631 			(*buf)[0] = 0;
7632 			(*buf)[1] = 0;
7633 			*buf += 2;
7634 		} else {
7635 			*buf = dp;
7636 			break;
7637 		}
7638 
7639 		if ((*buf)[0] == '\r') {
7640 			/* This is the end of the header */
7641 			break;
7642 		}
7643 	}
7644 	return ri->num_headers;
7645 }
7646 
7647 
7648 static int
is_valid_http_method(const char * method)7649 is_valid_http_method(const char *method)
7650 {
7651 	return !strcmp(method, "GET")        /* HTTP (RFC 2616) */
7652 	       || !strcmp(method, "POST")    /* HTTP (RFC 2616) */
7653 	       || !strcmp(method, "HEAD")    /* HTTP (RFC 2616) */
7654 	       || !strcmp(method, "PUT")     /* HTTP (RFC 2616) */
7655 	       || !strcmp(method, "DELETE")  /* HTTP (RFC 2616) */
7656 	       || !strcmp(method, "OPTIONS") /* HTTP (RFC 2616) */
7657 	       /* TRACE method (RFC 2616) is not supported for security reasons */
7658 	       || !strcmp(method, "CONNECT") /* HTTP (RFC 2616) */
7659 
7660 	       || !strcmp(method, "PROPFIND") /* WEBDAV (RFC 2518) */
7661 	       || !strcmp(method, "MKCOL")    /* WEBDAV (RFC 2518) */
7662 
7663 	       /* Unsupported WEBDAV Methods: */
7664 	       /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
7665 	       /* + 11 methods from RFC 3253 */
7666 	       /* ORDERPATCH (RFC 3648) */
7667 	       /* ACL (RFC 3744) */
7668 	       /* SEARCH (RFC 5323) */
7669 	       /* + MicroSoft extensions
7670 	        * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
7671 
7672 	       /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
7673 	       || !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
7674 }
7675 
7676 
7677 /* Parse HTTP request, fill in mg_request_info structure.
7678  * This function modifies the buffer by NUL-terminating
7679  * HTTP request components, header names and header values.
7680  * Parameters:
7681  *   buf (in/out): pointer to the HTTP header to parse and split
7682  *   len (in): length of HTTP header buffer
7683  *   re (out): parsed header as mg_request_info
7684  * buf and ri must be valid pointers (not NULL), len>0.
7685  * Returns <0 on error. */
7686 static int
parse_http_message(char * buf,int len,struct mg_request_info * ri)7687 parse_http_message(char *buf, int len, struct mg_request_info *ri)
7688 {
7689 	int is_request, request_length;
7690 	char *start_line;
7691 
7692 	request_length = get_request_len(buf, len);
7693 
7694 	if (request_length > 0) {
7695 		/* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
7696 		 * remote_port */
7697 		ri->remote_user = ri->request_method = ri->request_uri =
7698 		    ri->http_version = NULL;
7699 		ri->num_headers = 0;
7700 
7701 		buf[request_length - 1] = '\0';
7702 
7703 		/* RFC says that all initial whitespaces should be ingored */
7704 		while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
7705 			buf++;
7706 		}
7707 		start_line = skip(&buf, "\r\n");
7708 		ri->request_method = skip(&start_line, " ");
7709 		ri->request_uri = skip(&start_line, " ");
7710 		ri->http_version = start_line;
7711 
7712 		/* HTTP message could be either HTTP request:
7713 		 * "GET / HTTP/1.0 ..."
7714 		 * or a HTTP response:
7715 		 *  "HTTP/1.0 200 OK ..."
7716 		 * otherwise it is invalid.
7717 		 */
7718 		is_request = is_valid_http_method(ri->request_method);
7719 		if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
7720 		    || (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
7721 			/* Not a valid request or response: invalid */
7722 			return -1;
7723 		}
7724 		if (is_request) {
7725 			ri->http_version += 5;
7726 		}
7727 		if (parse_http_headers(&buf, ri) < 0) {
7728 			/* Error while parsing headers */
7729 			return -1;
7730 		}
7731 	}
7732 	return request_length;
7733 }
7734 
7735 
7736 /* Keep reading the input (either opened file descriptor fd, or socket sock,
7737  * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
7738  * buffer (which marks the end of HTTP request). Buffer buf may already
7739  * have some data. The length of the data is stored in nread.
7740  * Upon every read operation, increase nread by the number of bytes read. */
7741 static int
read_request(FILE * fp,struct mg_connection * conn,char * buf,int bufsiz,int * nread)7742 read_request(FILE *fp,
7743              struct mg_connection *conn,
7744              char *buf,
7745              int bufsiz,
7746              int *nread)
7747 {
7748 	int request_len, n = 0;
7749 	struct timespec last_action_time;
7750 	double request_timeout;
7751 
7752 	if (!conn) {
7753 		return 0;
7754 	}
7755 
7756 	memset(&last_action_time, 0, sizeof(last_action_time));
7757 
7758 	if (conn->ctx->config[REQUEST_TIMEOUT]) {
7759 		/* value of request_timeout is in seconds, config in milliseconds */
7760 		request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7761 	} else {
7762 		request_timeout = -1.0;
7763 	}
7764 	if (conn->handled_requests > 0) {
7765 		if (conn->ctx->config[KEEP_ALIVE_TIMEOUT]) {
7766 			request_timeout =
7767 			    atof(conn->ctx->config[KEEP_ALIVE_TIMEOUT]) / 1000.0;
7768 		}
7769 	}
7770 
7771 	request_len = get_request_len(buf, *nread);
7772 
7773 	/* first time reading from this connection */
7774 	clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7775 
7776 	while (request_len == 0) {
7777 		/* Full request not yet received */
7778 		if (conn->ctx->stop_flag != 0) {
7779 			/* Server is to be stopped. */
7780 			return -1;
7781 		}
7782 
7783 		if (*nread >= bufsiz) {
7784 			/* Request too long */
7785 			return -2;
7786 		}
7787 
7788 		n = pull(fp, conn, buf + *nread, bufsiz - *nread, request_timeout);
7789 		if (n < 0) {
7790 			/* Receive error */
7791 			return -1;
7792 		}
7793 		*nread += n;
7794 		request_len = get_request_len(buf, *nread);
7795 
7796 		if ((request_len == 0) && (request_timeout >= 0)) {
7797 			if (mg_difftimespec(&last_action_time, &(conn->req_time))
7798 			    > request_timeout) {
7799 				/* Timeout */
7800 				return -1;
7801 			}
7802 			clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7803 		}
7804 	}
7805 
7806 	return request_len;
7807 }
7808 
7809 #if !defined(NO_FILES)
7810 /* For given directory path, substitute it to valid index file.
7811  * Return 1 if index file has been found, 0 if not found.
7812  * If the file is found, it's stats is returned in stp. */
7813 static int
substitute_index_file(struct mg_connection * conn,char * path,size_t path_len,struct mg_file * filep)7814 substitute_index_file(struct mg_connection *conn,
7815                       char *path,
7816                       size_t path_len,
7817                       struct mg_file *filep)
7818 {
7819 	if (conn && conn->ctx) {
7820 		const char *list = conn->ctx->config[INDEX_FILES];
7821 		struct mg_file file = STRUCT_FILE_INITIALIZER;
7822 		struct vec filename_vec;
7823 		size_t n = strlen(path);
7824 		int found = 0;
7825 
7826 		/* The 'path' given to us points to the directory. Remove all trailing
7827 		 * directory separator characters from the end of the path, and
7828 		 * then append single directory separator character. */
7829 		while (n > 0 && path[n - 1] == '/') {
7830 			n--;
7831 		}
7832 		path[n] = '/';
7833 
7834 		/* Traverse index files list. For each entry, append it to the given
7835 		 * path and see if the file exists. If it exists, break the loop */
7836 		while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7837 			/* Ignore too long entries that may overflow path buffer */
7838 			if (filename_vec.len > path_len - (n + 2)) {
7839 				continue;
7840 			}
7841 
7842 			/* Prepare full path to the index file */
7843 			mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7844 
7845 			/* Does it exist? */
7846 			if (mg_stat(conn, path, &file.stat)) {
7847 				/* Yes it does, break the loop */
7848 				*filep = file;
7849 				found = 1;
7850 				break;
7851 			}
7852 		}
7853 
7854 		/* If no index file exists, restore directory path */
7855 		if (!found) {
7856 			path[n] = '\0';
7857 		}
7858 
7859 		return found;
7860 	}
7861 	return 0;
7862 }
7863 #endif
7864 
7865 
7866 #if !defined(NO_CACHING)
7867 /* Return True if we should reply 304 Not Modified. */
7868 static int
is_not_modified(const struct mg_connection * conn,const struct mg_file_stat * filestat)7869 is_not_modified(const struct mg_connection *conn,
7870                 const struct mg_file_stat *filestat)
7871 {
7872 	char etag[64];
7873 	const char *ims = mg_get_header(conn, "If-Modified-Since");
7874 	const char *inm = mg_get_header(conn, "If-None-Match");
7875 	construct_etag(etag, sizeof(etag), filestat);
7876 
7877 	return (inm != NULL && !mg_strcasecmp(etag, inm))
7878 	       || ((ims != NULL)
7879 	           && (filestat->last_modified <= parse_date_string(ims)));
7880 }
7881 #endif /* !NO_CACHING */
7882 
7883 
7884 #if !defined(NO_CGI) || !defined(NO_FILES)
7885 static int
forward_body_data(struct mg_connection * conn,FILE * fp,SOCKET sock,SSL * ssl)7886 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
7887 {
7888 	const char *expect, *body;
7889 	char buf[MG_BUF_LEN];
7890 	int to_read, nread, success = 0;
7891 	int64_t buffered_len;
7892 	double timeout = -1.0;
7893 
7894 	if (!conn) {
7895 		return 0;
7896 	}
7897 	if (conn->ctx->config[REQUEST_TIMEOUT]) {
7898 		timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7899 	}
7900 
7901 	expect = mg_get_header(conn, "Expect");
7902 	/* assert(fp != NULL); */
7903 	if (!fp) {
7904 		send_http_error(conn, 500, "%s", "Error: NULL File");
7905 		return 0;
7906 	}
7907 
7908 	if (conn->content_len == -1 && !conn->is_chunked) {
7909 		/* Content length is not specified by the client. */
7910 		send_http_error(conn,
7911 		                411,
7912 		                "%s",
7913 		                "Error: Client did not specify content length");
7914 	} else if ((expect != NULL)
7915 	           && (mg_strcasecmp(expect, "100-continue") != 0)) {
7916 		/* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
7917 		send_http_error(conn,
7918 		                417,
7919 		                "Error: Can not fulfill expectation %s",
7920 		                expect);
7921 	} else {
7922 		if (expect != NULL) {
7923 			(void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
7924 			conn->status_code = 100;
7925 		} else {
7926 			conn->status_code = 200;
7927 		}
7928 
7929 		buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
7930 		               - conn->consumed_content;
7931 
7932 		/* assert(buffered_len >= 0); */
7933 		/* assert(conn->consumed_content == 0); */
7934 
7935 		if ((buffered_len < 0) || (conn->consumed_content != 0)) {
7936 			send_http_error(conn, 500, "%s", "Error: Size mismatch");
7937 			return 0;
7938 		}
7939 
7940 		if (buffered_len > 0) {
7941 			if ((int64_t)buffered_len > conn->content_len) {
7942 				buffered_len = (int)conn->content_len;
7943 			}
7944 			body = conn->buf + conn->request_len + conn->consumed_content;
7945 			push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
7946 			conn->consumed_content += buffered_len;
7947 		}
7948 
7949 		nread = 0;
7950 		while (conn->consumed_content < conn->content_len) {
7951 			to_read = sizeof(buf);
7952 			if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
7953 				to_read = (int)(conn->content_len - conn->consumed_content);
7954 			}
7955 			nread = pull(NULL, conn, buf, to_read, timeout);
7956 			if (nread <= 0
7957 			    || push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
7958 				break;
7959 			}
7960 			conn->consumed_content += nread;
7961 		}
7962 
7963 		if (conn->consumed_content == conn->content_len) {
7964 			success = (nread >= 0);
7965 		}
7966 
7967 		/* Each error code path in this function must send an error */
7968 		if (!success) {
7969 			/* NOTE: Maybe some data has already been sent. */
7970 			/* TODO (low): If some data has been sent, a correct error
7971 			 * reply can no longer be sent, so just close the connection */
7972 			send_http_error(conn, 500, "%s", "");
7973 		}
7974 	}
7975 
7976 	return success;
7977 }
7978 #endif
7979 
7980 #if !defined(NO_CGI)
7981 /* This structure helps to create an environment for the spawned CGI program.
7982  * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
7983  * last element must be NULL.
7984  * However, on Windows there is a requirement that all these VARIABLE=VALUE\0
7985  * strings must reside in a contiguous buffer. The end of the buffer is
7986  * marked by two '\0' characters.
7987  * We satisfy both worlds: we create an envp array (which is vars), all
7988  * entries are actually pointers inside buf. */
7989 struct cgi_environment {
7990 	struct mg_connection *conn;
7991 	/* Data block */
7992 	char *buf;      /* Environment buffer */
7993 	size_t buflen;  /* Space available in buf */
7994 	size_t bufused; /* Space taken in buf */
7995 	                /* Index block */
7996 	char **var;     /* char **envp */
7997 	size_t varlen;  /* Number of variables available in var */
7998 	size_t varused; /* Number of variables stored in var */
7999 };
8000 
8001 
8002 static void addenv(struct cgi_environment *env,
8003                    PRINTF_FORMAT_STRING(const char *fmt),
8004                    ...) PRINTF_ARGS(2, 3);
8005 
8006 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
8007  * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
8008 static void
addenv(struct cgi_environment * env,const char * fmt,...)8009 addenv(struct cgi_environment *env, const char *fmt, ...)
8010 {
8011 	size_t n, space;
8012 	int truncated = 0;
8013 	char *added;
8014 	va_list ap;
8015 
8016 	/* Calculate how much space is left in the buffer */
8017 	space = (env->buflen - env->bufused);
8018 
8019 	/* Calculate an estimate for the required space */
8020 	n = strlen(fmt) + 2 + 128;
8021 
8022 	do {
8023 		if (space <= n) {
8024 			/* Allocate new buffer */
8025 			n = env->buflen + CGI_ENVIRONMENT_SIZE;
8026 			added = (char *)mg_realloc(env->buf, n);
8027 			if (!added) {
8028 				/* Out of memory */
8029 				mg_cry(env->conn,
8030 				       "%s: Cannot allocate memory for CGI variable [%s]",
8031 				       __func__,
8032 				       fmt);
8033 				return;
8034 			}
8035 			env->buf = added;
8036 			env->buflen = n;
8037 			space = (env->buflen - env->bufused);
8038 		}
8039 
8040 		/* Make a pointer to the free space int the buffer */
8041 		added = env->buf + env->bufused;
8042 
8043 		/* Copy VARIABLE=VALUE\0 string into the free space */
8044 		va_start(ap, fmt);
8045 		mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
8046 		va_end(ap);
8047 
8048 		/* Do not add truncated strings to the environment */
8049 		if (truncated) {
8050 			/* Reallocate the buffer */
8051 			space = 0;
8052 			n = 1;
8053 		}
8054 	} while (truncated);
8055 
8056 	/* Calculate number of bytes added to the environment */
8057 	n = strlen(added) + 1;
8058 	env->bufused += n;
8059 
8060 	/* Now update the variable index */
8061 	space = (env->varlen - env->varused);
8062 	if (space < 2) {
8063 		mg_cry(env->conn,
8064 		       "%s: Cannot register CGI variable [%s]",
8065 		       __func__,
8066 		       fmt);
8067 		return;
8068 	}
8069 
8070 	/* Append a pointer to the added string into the envp array */
8071 	env->var[env->varused] = added;
8072 	env->varused++;
8073 }
8074 
8075 
8076 static void
prepare_cgi_environment(struct mg_connection * conn,const char * prog,struct cgi_environment * env)8077 prepare_cgi_environment(struct mg_connection *conn,
8078                         const char *prog,
8079                         struct cgi_environment *env)
8080 {
8081 	const char *s;
8082 	struct vec var_vec;
8083 	char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
8084 	int i, truncated, uri_len;
8085 
8086 	if (conn == NULL || prog == NULL || env == NULL) {
8087 		return;
8088 	}
8089 
8090 	env->conn = conn;
8091 	env->buflen = CGI_ENVIRONMENT_SIZE;
8092 	env->bufused = 0;
8093 	env->buf = (char *)mg_malloc(env->buflen);
8094 	env->varlen = MAX_CGI_ENVIR_VARS;
8095 	env->varused = 0;
8096 	env->var = (char **)mg_malloc(env->buflen * sizeof(char *));
8097 
8098 	addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
8099 	addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
8100 	addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
8101 	addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
8102 
8103 	/* Prepare the environment block */
8104 	addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
8105 	addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
8106 	addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
8107 
8108 #if defined(USE_IPV6)
8109 	if (conn->client.lsa.sa.sa_family == AF_INET6) {
8110 		addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
8111 	} else
8112 #endif
8113 	{
8114 		addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
8115 	}
8116 
8117 	sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
8118 	addenv(env, "REMOTE_ADDR=%s", src_addr);
8119 
8120 	addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
8121 	addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
8122 
8123 	addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
8124 	addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
8125 
8126 	/* SCRIPT_NAME */
8127 	uri_len = (int)strlen(conn->request_info.local_uri);
8128 	if (conn->path_info == NULL) {
8129 		if (conn->request_info.local_uri[uri_len - 1] != '/') {
8130 			/* URI: /path_to_script/script.cgi */
8131 			addenv(env, "SCRIPT_NAME=%s", conn->request_info.local_uri);
8132 		} else {
8133 			/* URI: /path_to_script/ ... using index.cgi */
8134 			char *index_file = strrchr(prog, '/');
8135 			if (index_file) {
8136 				addenv(env,
8137 				       "SCRIPT_NAME=%s%s",
8138 				       conn->request_info.local_uri,
8139 				       index_file + 1);
8140 			}
8141 		}
8142 	} else {
8143 		/* URI: /path_to_script/script.cgi/path_info */
8144 		addenv(env,
8145 		       "SCRIPT_NAME=%.*s",
8146 		       uri_len - (int)strlen(conn->path_info),
8147 		       conn->request_info.local_uri);
8148 	}
8149 
8150 	addenv(env, "SCRIPT_FILENAME=%s", prog);
8151 	if (conn->path_info == NULL) {
8152 		addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
8153 	} else {
8154 		addenv(env,
8155 		       "PATH_TRANSLATED=%s%s",
8156 		       conn->ctx->config[DOCUMENT_ROOT],
8157 		       conn->path_info);
8158 	}
8159 
8160 	addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on");
8161 
8162 	if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
8163 		addenv(env, "CONTENT_TYPE=%s", s);
8164 	}
8165 	if (conn->request_info.query_string != NULL) {
8166 		addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
8167 	}
8168 	if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
8169 		addenv(env, "CONTENT_LENGTH=%s", s);
8170 	}
8171 	if ((s = getenv("PATH")) != NULL) {
8172 		addenv(env, "PATH=%s", s);
8173 	}
8174 	if (conn->path_info != NULL) {
8175 		addenv(env, "PATH_INFO=%s", conn->path_info);
8176 	}
8177 
8178 	if (conn->status_code > 0) {
8179 		/* CGI error handler should show the status code */
8180 		addenv(env, "STATUS=%d", conn->status_code);
8181 	}
8182 
8183 #if defined(_WIN32)
8184 	if ((s = getenv("COMSPEC")) != NULL) {
8185 		addenv(env, "COMSPEC=%s", s);
8186 	}
8187 	if ((s = getenv("SYSTEMROOT")) != NULL) {
8188 		addenv(env, "SYSTEMROOT=%s", s);
8189 	}
8190 	if ((s = getenv("SystemDrive")) != NULL) {
8191 		addenv(env, "SystemDrive=%s", s);
8192 	}
8193 	if ((s = getenv("ProgramFiles")) != NULL) {
8194 		addenv(env, "ProgramFiles=%s", s);
8195 	}
8196 	if ((s = getenv("ProgramFiles(x86)")) != NULL) {
8197 		addenv(env, "ProgramFiles(x86)=%s", s);
8198 	}
8199 #else
8200 	if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
8201 		addenv(env, "LD_LIBRARY_PATH=%s", s);
8202 	}
8203 #endif /* _WIN32 */
8204 
8205 	if ((s = getenv("PERLLIB")) != NULL) {
8206 		addenv(env, "PERLLIB=%s", s);
8207 	}
8208 
8209 	if (conn->request_info.remote_user != NULL) {
8210 		addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
8211 		addenv(env, "%s", "AUTH_TYPE=Digest");
8212 	}
8213 
8214 	/* Add all headers as HTTP_* variables */
8215 	for (i = 0; i < conn->request_info.num_headers; i++) {
8216 
8217 		(void)mg_snprintf(conn,
8218 		                  &truncated,
8219 		                  http_var_name,
8220 		                  sizeof(http_var_name),
8221 		                  "HTTP_%s",
8222 		                  conn->request_info.http_headers[i].name);
8223 
8224 		if (truncated) {
8225 			mg_cry(conn,
8226 			       "%s: HTTP header variable too long [%s]",
8227 			       __func__,
8228 			       conn->request_info.http_headers[i].name);
8229 			continue;
8230 		}
8231 
8232 		/* Convert variable name into uppercase, and change - to _ */
8233 		for (p = http_var_name; *p != '\0'; p++) {
8234 			if (*p == '-') {
8235 				*p = '_';
8236 			}
8237 			*p = (char)toupper(*(unsigned char *)p);
8238 		}
8239 
8240 		addenv(env,
8241 		       "%s=%s",
8242 		       http_var_name,
8243 		       conn->request_info.http_headers[i].value);
8244 	}
8245 
8246 	/* Add user-specified variables */
8247 	s = conn->ctx->config[CGI_ENVIRONMENT];
8248 	while ((s = next_option(s, &var_vec, NULL)) != NULL) {
8249 		addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
8250 	}
8251 
8252 	env->var[env->varused] = NULL;
8253 	env->buf[env->bufused] = '\0';
8254 }
8255 
8256 
8257 static void
handle_cgi_request(struct mg_connection * conn,const char * prog)8258 handle_cgi_request(struct mg_connection *conn, const char *prog)
8259 {
8260 	char *buf;
8261 	size_t buflen;
8262 	int headers_len, data_len, i, truncated;
8263 	int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
8264 	const char *status, *status_text, *connection_state;
8265 	char *pbuf, dir[PATH_MAX], *p;
8266 	struct mg_request_info ri;
8267 	struct cgi_environment blk;
8268 	FILE *in = NULL, *out = NULL, *err = NULL;
8269 	struct mg_file fout = STRUCT_FILE_INITIALIZER;
8270 	pid_t pid = (pid_t)-1;
8271 
8272 	if (conn == NULL) {
8273 		return;
8274 	}
8275 
8276 	buf = NULL;
8277 	buflen = 16384;
8278 	prepare_cgi_environment(conn, prog, &blk);
8279 
8280 	/* CGI must be executed in its own directory. 'dir' must point to the
8281 	 * directory containing executable program, 'p' must point to the
8282 	 * executable program name relative to 'dir'. */
8283 	(void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
8284 
8285 	if (truncated) {
8286 		mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
8287 		send_http_error(conn, 500, "Error: %s", "CGI path too long");
8288 		goto done;
8289 	}
8290 
8291 	if ((p = strrchr(dir, '/')) != NULL) {
8292 		*p++ = '\0';
8293 	} else {
8294 		dir[0] = '.', dir[1] = '\0';
8295 		p = (char *)prog;
8296 	}
8297 
8298 	if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) {
8299 		status = strerror(ERRNO);
8300 		mg_cry(conn,
8301 		       "Error: CGI program \"%s\": Can not create CGI pipes: %s",
8302 		       prog,
8303 		       status);
8304 		send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status);
8305 		goto done;
8306 	}
8307 
8308 	pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
8309 
8310 	if (pid == (pid_t)-1) {
8311 		status = strerror(ERRNO);
8312 		mg_cry(conn,
8313 		       "Error: CGI program \"%s\": Can not spawn CGI process: %s",
8314 		       prog,
8315 		       status);
8316 		send_http_error(conn,
8317 		                500,
8318 		                "Error: Cannot spawn CGI process [%s]: %s",
8319 		                prog,
8320 		                status);
8321 		goto done;
8322 	}
8323 
8324 	/* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
8325 	set_close_on_exec((SOCKET)fdin[0], conn);  /* stdin read */
8326 	set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
8327 	set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
8328 	set_close_on_exec((SOCKET)fdin[1], conn);  /* stdin write */
8329 	set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
8330 	set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
8331 
8332 	/* Parent closes only one side of the pipes.
8333 	 * If we don't mark them as closed, close() attempt before
8334 	 * return from this function throws an exception on Windows.
8335 	 * Windows does not like when closed descriptor is closed again. */
8336 	(void)close(fdin[0]);
8337 	(void)close(fdout[1]);
8338 	(void)close(fderr[1]);
8339 	fdin[0] = fdout[1] = fderr[1] = -1;
8340 
8341 	if ((in = fdopen(fdin[1], "wb")) == NULL) {
8342 		status = strerror(ERRNO);
8343 		mg_cry(conn,
8344 		       "Error: CGI program \"%s\": Can not open stdin: %s",
8345 		       prog,
8346 		       status);
8347 		send_http_error(conn,
8348 		                500,
8349 		                "Error: CGI can not open fdin\nfopen: %s",
8350 		                status);
8351 		goto done;
8352 	}
8353 
8354 	if ((out = fdopen(fdout[0], "rb")) == NULL) {
8355 		status = strerror(ERRNO);
8356 		mg_cry(conn,
8357 		       "Error: CGI program \"%s\": Can not open stdout: %s",
8358 		       prog,
8359 		       status);
8360 		send_http_error(conn,
8361 		                500,
8362 		                "Error: CGI can not open fdout\nfopen: %s",
8363 		                status);
8364 		goto done;
8365 	}
8366 
8367 	if ((err = fdopen(fderr[0], "rb")) == NULL) {
8368 		status = strerror(ERRNO);
8369 		mg_cry(conn,
8370 		       "Error: CGI program \"%s\": Can not open stderr: %s",
8371 		       prog,
8372 		       status);
8373 		send_http_error(conn,
8374 		                500,
8375 		                "Error: CGI can not open fdout\nfopen: %s",
8376 		                status);
8377 		goto done;
8378 	}
8379 
8380 	setbuf(in, NULL);
8381 	setbuf(out, NULL);
8382 	setbuf(err, NULL);
8383 	fout.access.fp = out;
8384 
8385 	if ((conn->request_info.content_length > 0) || conn->is_chunked) {
8386 		/* This is a POST/PUT request, or another request with body data. */
8387 		if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
8388 			/* Error sending the body data */
8389 			mg_cry(conn,
8390 			       "Error: CGI program \"%s\": Forward body data failed",
8391 			       prog);
8392 			goto done;
8393 		}
8394 	}
8395 
8396 	/* Close so child gets an EOF. */
8397 	fclose(in);
8398 	in = NULL;
8399 	fdin[1] = -1;
8400 
8401 	/* Now read CGI reply into a buffer. We need to set correct
8402 	 * status code, thus we need to see all HTTP headers first.
8403 	 * Do not send anything back to client, until we buffer in all
8404 	 * HTTP headers. */
8405 	data_len = 0;
8406 	buf = (char *)mg_malloc(buflen);
8407 	if (buf == NULL) {
8408 		send_http_error(conn,
8409 		                500,
8410 		                "Error: Not enough memory for CGI buffer (%u bytes)",
8411 		                (unsigned int)buflen);
8412 		mg_cry(conn,
8413 		       "Error: CGI program \"%s\": Not enough memory for buffer (%u "
8414 		       "bytes)",
8415 		       prog,
8416 		       (unsigned int)buflen);
8417 		goto done;
8418 	}
8419 	headers_len = read_request(out, conn, buf, (int)buflen, &data_len);
8420 	if (headers_len <= 0) {
8421 
8422 		/* Could not parse the CGI response. Check if some error message on
8423 		 * stderr. */
8424 		i = pull_all(err, conn, buf, (int)buflen);
8425 		if (i > 0) {
8426 			mg_cry(conn,
8427 			       "Error: CGI program \"%s\" sent error "
8428 			       "message: [%.*s]",
8429 			       prog,
8430 			       i,
8431 			       buf);
8432 			send_http_error(conn,
8433 			                500,
8434 			                "Error: CGI program \"%s\" sent error "
8435 			                "message: [%.*s]",
8436 			                prog,
8437 			                i,
8438 			                buf);
8439 		} else {
8440 			mg_cry(conn,
8441 			       "Error: CGI program sent malformed or too big "
8442 			       "(>%u bytes) HTTP headers: [%.*s]",
8443 			       (unsigned)buflen,
8444 			       data_len,
8445 			       buf);
8446 
8447 			send_http_error(conn,
8448 			                500,
8449 			                "Error: CGI program sent malformed or too big "
8450 			                "(>%u bytes) HTTP headers: [%.*s]",
8451 			                (unsigned)buflen,
8452 			                data_len,
8453 			                buf);
8454 		}
8455 
8456 		goto done;
8457 	}
8458 	pbuf = buf;
8459 	buf[headers_len - 1] = '\0';
8460 	parse_http_headers(&pbuf, &ri);
8461 
8462 	/* Make up and send the status line */
8463 	status_text = "OK";
8464 	if ((status = get_header(&ri, "Status")) != NULL) {
8465 		conn->status_code = atoi(status);
8466 		status_text = status;
8467 		while (isdigit(*(const unsigned char *)status_text)
8468 		       || *status_text == ' ') {
8469 			status_text++;
8470 		}
8471 	} else if (get_header(&ri, "Location") != NULL) {
8472 		conn->status_code = 302;
8473 	} else {
8474 		conn->status_code = 200;
8475 	}
8476 	connection_state = get_header(&ri, "Connection");
8477 	if (!header_has_option(connection_state, "keep-alive")) {
8478 		conn->must_close = 1;
8479 	}
8480 	(void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
8481 
8482 	/* Send headers */
8483 	for (i = 0; i < ri.num_headers; i++) {
8484 		mg_printf(conn,
8485 		          "%s: %s\r\n",
8486 		          ri.http_headers[i].name,
8487 		          ri.http_headers[i].value);
8488 	}
8489 	mg_write(conn, "\r\n", 2);
8490 
8491 	/* Send chunk of data that may have been read after the headers */
8492 	conn->num_bytes_sent +=
8493 	    mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
8494 
8495 	/* Read the rest of CGI output and send to the client */
8496 	send_file_data(conn, &fout, 0, INT64_MAX);
8497 
8498 done:
8499 	mg_free(blk.var);
8500 	mg_free(blk.buf);
8501 
8502 	if (pid != (pid_t)-1) {
8503 		kill(pid, SIGKILL);
8504 #if !defined(_WIN32)
8505 		{
8506 			int st;
8507 			while (waitpid(pid, &st, 0) != -1)
8508 				; /* clean zombies */
8509 		}
8510 #endif
8511 	}
8512 	if (fdin[0] != -1) {
8513 		close(fdin[0]);
8514 	}
8515 	if (fdout[1] != -1) {
8516 		close(fdout[1]);
8517 	}
8518 
8519 	if (in != NULL) {
8520 		fclose(in);
8521 	} else if (fdin[1] != -1) {
8522 		close(fdin[1]);
8523 	}
8524 
8525 	if (out != NULL) {
8526 		fclose(out);
8527 	} else if (fdout[0] != -1) {
8528 		close(fdout[0]);
8529 	}
8530 
8531 	if (err != NULL) {
8532 		fclose(err);
8533 	} else if (fderr[0] != -1) {
8534 		close(fderr[0]);
8535 	}
8536 
8537 	if (buf != NULL) {
8538 		mg_free(buf);
8539 	}
8540 }
8541 #endif /* !NO_CGI */
8542 
8543 
8544 #if !defined(NO_FILES)
8545 static void
mkcol(struct mg_connection * conn,const char * path)8546 mkcol(struct mg_connection *conn, const char *path)
8547 {
8548 	int rc, body_len;
8549 	struct de de;
8550 	char date[64];
8551 	time_t curtime = time(NULL);
8552 
8553 	if (conn == NULL) {
8554 		return;
8555 	}
8556 
8557 	/* TODO (mid): Check the send_http_error situations in this function */
8558 
8559 	memset(&de.file, 0, sizeof(de.file));
8560 	if (!mg_stat(conn, path, &de.file)) {
8561 		mg_cry(conn,
8562 		       "%s: mg_stat(%s) failed: %s",
8563 		       __func__,
8564 		       path,
8565 		       strerror(ERRNO));
8566 	}
8567 
8568 	if (de.file.last_modified) {
8569 		/* TODO (high): This check does not seem to make any sense ! */
8570 		send_http_error(
8571 		    conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
8572 		return;
8573 	}
8574 
8575 	body_len = conn->data_len - conn->request_len;
8576 	if (body_len > 0) {
8577 		send_http_error(
8578 		    conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
8579 		return;
8580 	}
8581 
8582 	rc = mg_mkdir(conn, path, 0755);
8583 
8584 	if (rc == 0) {
8585 		conn->status_code = 201;
8586 		gmt_time_string(date, sizeof(date), &curtime);
8587 		mg_printf(conn,
8588 		          "HTTP/1.1 %d Created\r\n"
8589 		          "Date: %s\r\n",
8590 		          conn->status_code,
8591 		          date);
8592 		send_static_cache_header(conn);
8593 		mg_printf(conn,
8594 		          "Content-Length: 0\r\n"
8595 		          "Connection: %s\r\n\r\n",
8596 		          suggest_connection_header(conn));
8597 	} else if (rc == -1) {
8598 		if (errno == EEXIST) {
8599 			send_http_error(
8600 			    conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
8601 		} else if (errno == EACCES) {
8602 			send_http_error(
8603 			    conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
8604 		} else if (errno == ENOENT) {
8605 			send_http_error(
8606 			    conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
8607 		} else {
8608 			send_http_error(conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
8609 		}
8610 	}
8611 }
8612 
8613 
8614 static void
put_file(struct mg_connection * conn,const char * path)8615 put_file(struct mg_connection *conn, const char *path)
8616 {
8617 	struct mg_file file = STRUCT_FILE_INITIALIZER;
8618 	const char *range;
8619 	int64_t r1, r2;
8620 	int rc;
8621 	char date[64];
8622 	time_t curtime = time(NULL);
8623 
8624 	if (conn == NULL) {
8625 		return;
8626 	}
8627 
8628 	if (mg_stat(conn, path, &file.stat)) {
8629 		/* File already exists */
8630 		conn->status_code = 200;
8631 
8632 		if (file.stat.is_directory) {
8633 			/* This is an already existing directory,
8634 			 * so there is nothing to do for the server. */
8635 			rc = 0;
8636 
8637 		} else {
8638 			/* File exists and is not a directory. */
8639 			/* Can it be replaced? */
8640 
8641 			if (file.access.membuf != NULL) {
8642 				/* This is an "in-memory" file, that can not be replaced */
8643 				send_http_error(
8644 				    conn,
8645 				    405,
8646 				    "Error: Put not possible\nReplacing %s is not supported",
8647 				    path);
8648 				return;
8649 			}
8650 
8651 			/* Check if the server may write this file */
8652 			if (access(path, W_OK) == 0) {
8653 				/* Access granted */
8654 				conn->status_code = 200;
8655 				rc = 1;
8656 			} else {
8657 				send_http_error(
8658 				    conn,
8659 				    403,
8660 				    "Error: Put not possible\nReplacing %s is not allowed",
8661 				    path);
8662 				return;
8663 			}
8664 		}
8665 	} else {
8666 		/* File should be created */
8667 		conn->status_code = 201;
8668 		rc = put_dir(conn, path);
8669 	}
8670 
8671 	if (rc == 0) {
8672 		/* put_dir returns 0 if path is a directory */
8673 		gmt_time_string(date, sizeof(date), &curtime);
8674 		mg_printf(conn,
8675 		          "HTTP/1.1 %d %s\r\n",
8676 		          conn->status_code,
8677 		          mg_get_response_code_text(NULL, conn->status_code));
8678 		send_no_cache_header(conn);
8679 		mg_printf(conn,
8680 		          "Date: %s\r\n"
8681 		          "Content-Length: 0\r\n"
8682 		          "Connection: %s\r\n\r\n",
8683 		          date,
8684 		          suggest_connection_header(conn));
8685 
8686 		/* Request to create a directory has been fulfilled successfully.
8687 		 * No need to put a file. */
8688 		return;
8689 	}
8690 
8691 	if (rc == -1) {
8692 		/* put_dir returns -1 if the path is too long */
8693 		send_http_error(conn,
8694 		                414,
8695 		                "Error: Path too long\nput_dir(%s): %s",
8696 		                path,
8697 		                strerror(ERRNO));
8698 		return;
8699 	}
8700 
8701 	if (rc == -2) {
8702 		/* put_dir returns -2 if the directory can not be created */
8703 		send_http_error(conn,
8704 		                500,
8705 		                "Error: Can not create directory\nput_dir(%s): %s",
8706 		                path,
8707 		                strerror(ERRNO));
8708 		return;
8709 	}
8710 
8711 	/* A file should be created or overwritten. */
8712 	/* TODO: Test if write or write+read is required. */
8713 	if (!mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &file)
8714 	    || file.access.fp == NULL) {
8715 		(void)mg_fclose(&file.access);
8716 		send_http_error(conn,
8717 		                500,
8718 		                "Error: Can not create file\nfopen(%s): %s",
8719 		                path,
8720 		                strerror(ERRNO));
8721 		return;
8722 	}
8723 
8724 	fclose_on_exec(&file.access, conn);
8725 	range = mg_get_header(conn, "Content-Range");
8726 	r1 = r2 = 0;
8727 	if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
8728 		conn->status_code = 206; /* Partial content */
8729 		fseeko(file.access.fp, r1, SEEK_SET);
8730 	}
8731 
8732 	if (!forward_body_data(conn, file.access.fp, INVALID_SOCKET, NULL)) {
8733 		/* forward_body_data failed.
8734 		 * The error code has already been sent to the client,
8735 		 * and conn->status_code is already set. */
8736 		(void)mg_fclose(&file.access);
8737 		return;
8738 	}
8739 
8740 	if (mg_fclose(&file.access) != 0) {
8741 		/* fclose failed. This might have different reasons, but a likely
8742 		 * one is "no space on disk", http 507. */
8743 		conn->status_code = 507;
8744 	}
8745 
8746 	gmt_time_string(date, sizeof(date), &curtime);
8747 	mg_printf(conn,
8748 	          "HTTP/1.1 %d %s\r\n",
8749 	          conn->status_code,
8750 	          mg_get_response_code_text(NULL, conn->status_code));
8751 	send_no_cache_header(conn);
8752 	mg_printf(conn,
8753 	          "Date: %s\r\n"
8754 	          "Content-Length: 0\r\n"
8755 	          "Connection: %s\r\n\r\n",
8756 	          date,
8757 	          suggest_connection_header(conn));
8758 }
8759 
8760 
8761 static void
delete_file(struct mg_connection * conn,const char * path)8762 delete_file(struct mg_connection *conn, const char *path)
8763 {
8764 	struct de de;
8765 	memset(&de.file, 0, sizeof(de.file));
8766 	if (!mg_stat(conn, path, &de.file)) {
8767 		/* mg_stat returns 0 if the file does not exist */
8768 		send_http_error(conn,
8769 		                404,
8770 		                "Error: Cannot delete file\nFile %s not found",
8771 		                path);
8772 		return;
8773 	}
8774 
8775 #if 0 /* Ignore if a file in memory is inside a folder */
8776 	if (de.access.membuf != NULL) {
8777 		/* the file is cached in memory */
8778 		send_http_error(
8779 		    conn,
8780 		    405,
8781 		    "Error: Delete not possible\nDeleting %s is not supported",
8782 		    path);
8783 		return;
8784 	}
8785 #endif
8786 
8787 	if (de.file.is_directory) {
8788 		if (remove_directory(conn, path)) {
8789 			/* Delete is successful: Return 204 without content. */
8790 			send_http_error(conn, 204, "%s", "");
8791 		} else {
8792 			/* Delete is not successful: Return 500 (Server error). */
8793 			send_http_error(conn, 500, "Error: Could not delete %s", path);
8794 		}
8795 		return;
8796 	}
8797 
8798 	/* This is an existing file (not a directory).
8799 	 * Check if write permission is granted. */
8800 	if (access(path, W_OK) != 0) {
8801 		/* File is read only */
8802 		send_http_error(
8803 		    conn,
8804 		    403,
8805 		    "Error: Delete not possible\nDeleting %s is not allowed",
8806 		    path);
8807 		return;
8808 	}
8809 
8810 	/* Try to delete it. */
8811 	if (mg_remove(conn, path) == 0) {
8812 		/* Delete was successful: Return 204 without content. */
8813 		send_http_error(conn, 204, "%s", "");
8814 	} else {
8815 		/* Delete not successful (file locked). */
8816 		send_http_error(conn,
8817 		                423,
8818 		                "Error: Cannot delete file\nremove(%s): %s",
8819 		                path,
8820 		                strerror(ERRNO));
8821 	}
8822 }
8823 #endif /* !NO_FILES */
8824 
8825 
8826 static void
8827 send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int);
8828 
8829 
8830 static void
do_ssi_include(struct mg_connection * conn,const char * ssi,char * tag,int include_level)8831 do_ssi_include(struct mg_connection *conn,
8832                const char *ssi,
8833                char *tag,
8834                int include_level)
8835 {
8836 	char file_name[MG_BUF_LEN], path[512], *p;
8837 	struct mg_file file = STRUCT_FILE_INITIALIZER;
8838 	size_t len;
8839 	int truncated = 0;
8840 
8841 	if (conn == NULL) {
8842 		return;
8843 	}
8844 
8845 	/* sscanf() is safe here, since send_ssi_file() also uses buffer
8846 	 * of size MG_BUF_LEN to get the tag. So strlen(tag) is
8847 	 * always < MG_BUF_LEN. */
8848 	if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
8849 		/* File name is relative to the webserver root */
8850 		file_name[511] = 0;
8851 		(void)mg_snprintf(conn,
8852 		                  &truncated,
8853 		                  path,
8854 		                  sizeof(path),
8855 		                  "%s/%s",
8856 		                  conn->ctx->config[DOCUMENT_ROOT],
8857 		                  file_name);
8858 
8859 	} else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
8860 		/* File name is relative to the webserver working directory
8861 		 * or it is absolute system path */
8862 		file_name[511] = 0;
8863 		(void)
8864 		    mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
8865 
8866 	} else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1
8867 	           || sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
8868 		/* File name is relative to the currect document */
8869 		file_name[511] = 0;
8870 		(void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
8871 
8872 		if (!truncated) {
8873 			if ((p = strrchr(path, '/')) != NULL) {
8874 				p[1] = '\0';
8875 			}
8876 			len = strlen(path);
8877 			(void)mg_snprintf(conn,
8878 			                  &truncated,
8879 			                  path + len,
8880 			                  sizeof(path) - len,
8881 			                  "%s",
8882 			                  file_name);
8883 		}
8884 
8885 	} else {
8886 		mg_cry(conn, "Bad SSI #include: [%s]", tag);
8887 		return;
8888 	}
8889 
8890 	if (truncated) {
8891 		mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
8892 		return;
8893 	}
8894 
8895 	if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) {
8896 		mg_cry(conn,
8897 		       "Cannot open SSI #include: [%s]: fopen(%s): %s",
8898 		       tag,
8899 		       path,
8900 		       strerror(ERRNO));
8901 	} else {
8902 		fclose_on_exec(&file.access, conn);
8903 		if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
8904 		                 strlen(conn->ctx->config[SSI_EXTENSIONS]),
8905 		                 path) > 0) {
8906 			send_ssi_file(conn, path, &file, include_level + 1);
8907 		} else {
8908 			send_file_data(conn, &file, 0, INT64_MAX);
8909 		}
8910 		(void)mg_fclose(&file.access); /* Ignore errors for readonly files */
8911 	}
8912 }
8913 
8914 
8915 #if !defined(NO_POPEN)
8916 static void
do_ssi_exec(struct mg_connection * conn,char * tag)8917 do_ssi_exec(struct mg_connection *conn, char *tag)
8918 {
8919 	char cmd[1024] = "";
8920 	struct mg_file file = STRUCT_FILE_INITIALIZER;
8921 
8922 	if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
8923 		mg_cry(conn, "Bad SSI #exec: [%s]", tag);
8924 	} else {
8925 		cmd[1023] = 0;
8926 		if ((file.access.fp = popen(cmd, "r")) == NULL) {
8927 			mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
8928 		} else {
8929 			send_file_data(conn, &file, 0, INT64_MAX);
8930 			pclose(file.access.fp);
8931 		}
8932 	}
8933 }
8934 #endif /* !NO_POPEN */
8935 
8936 
8937 static int
mg_fgetc(struct mg_file * filep,int offset)8938 mg_fgetc(struct mg_file *filep, int offset)
8939 {
8940 	if (filep == NULL) {
8941 		return EOF;
8942 	}
8943 	if (filep->access.membuf != NULL && offset >= 0
8944 	    && ((unsigned int)(offset)) < filep->stat.size) {
8945 		return ((const unsigned char *)filep->access.membuf)[offset];
8946 	} else if (filep->access.fp != NULL) {
8947 		return fgetc(filep->access.fp);
8948 	} else {
8949 		return EOF;
8950 	}
8951 }
8952 
8953 
8954 static void
send_ssi_file(struct mg_connection * conn,const char * path,struct mg_file * filep,int include_level)8955 send_ssi_file(struct mg_connection *conn,
8956               const char *path,
8957               struct mg_file *filep,
8958               int include_level)
8959 {
8960 	char buf[MG_BUF_LEN];
8961 	int ch, offset, len, in_ssi_tag;
8962 
8963 	if (include_level > 10) {
8964 		mg_cry(conn, "SSI #include level is too deep (%s)", path);
8965 		return;
8966 	}
8967 
8968 	in_ssi_tag = len = offset = 0;
8969 	while ((ch = mg_fgetc(filep, offset)) != EOF) {
8970 		if (in_ssi_tag && ch == '>') {
8971 			in_ssi_tag = 0;
8972 			buf[len++] = (char)ch;
8973 			buf[len] = '\0';
8974 			/* assert(len <= (int) sizeof(buf)); */
8975 			if (len > (int)sizeof(buf)) {
8976 				break;
8977 			}
8978 			if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
8979 				/* Not an SSI tag, pass it */
8980 				(void)mg_write(conn, buf, (size_t)len);
8981 			} else {
8982 				if (!memcmp(buf + 5, "include", 7)) {
8983 					do_ssi_include(conn, path, buf + 12, include_level);
8984 #if !defined(NO_POPEN)
8985 				} else if (!memcmp(buf + 5, "exec", 4)) {
8986 					do_ssi_exec(conn, buf + 9);
8987 #endif /* !NO_POPEN */
8988 				} else {
8989 					mg_cry(conn,
8990 					       "%s: unknown SSI "
8991 					       "command: \"%s\"",
8992 					       path,
8993 					       buf);
8994 				}
8995 			}
8996 			len = 0;
8997 		} else if (in_ssi_tag) {
8998 			if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
8999 				/* Not an SSI tag */
9000 				in_ssi_tag = 0;
9001 			} else if (len == (int)sizeof(buf) - 2) {
9002 				mg_cry(conn, "%s: SSI tag is too large", path);
9003 				len = 0;
9004 			}
9005 			buf[len++] = (char)(ch & 0xff);
9006 		} else if (ch == '<') {
9007 			in_ssi_tag = 1;
9008 			if (len > 0) {
9009 				mg_write(conn, buf, (size_t)len);
9010 			}
9011 			len = 0;
9012 			buf[len++] = (char)(ch & 0xff);
9013 		} else {
9014 			buf[len++] = (char)(ch & 0xff);
9015 			if (len == (int)sizeof(buf)) {
9016 				mg_write(conn, buf, (size_t)len);
9017 				len = 0;
9018 			}
9019 		}
9020 	}
9021 
9022 	/* Send the rest of buffered data */
9023 	if (len > 0) {
9024 		mg_write(conn, buf, (size_t)len);
9025 	}
9026 }
9027 
9028 
9029 static void
handle_ssi_file_request(struct mg_connection * conn,const char * path,struct mg_file * filep)9030 handle_ssi_file_request(struct mg_connection *conn,
9031                         const char *path,
9032                         struct mg_file *filep)
9033 {
9034 	char date[64];
9035 	time_t curtime = time(NULL);
9036 	const char *cors1, *cors2, *cors3;
9037 
9038 	if (conn == NULL || path == NULL || filep == NULL) {
9039 		return;
9040 	}
9041 
9042 	if (mg_get_header(conn, "Origin")) {
9043 		/* Cross-origin resource sharing (CORS). */
9044 		cors1 = "Access-Control-Allow-Origin: ";
9045 		cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
9046 		cors3 = "\r\n";
9047 	} else {
9048 		cors1 = cors2 = cors3 = "";
9049 	}
9050 
9051 	if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
9052 		/* File exists (precondition for calling this function),
9053 		 * but can not be opened by the server. */
9054 		send_http_error(conn,
9055 		                500,
9056 		                "Error: Cannot read file\nfopen(%s): %s",
9057 		                path,
9058 		                strerror(ERRNO));
9059 	} else {
9060 		conn->must_close = 1;
9061 		gmt_time_string(date, sizeof(date), &curtime);
9062 		fclose_on_exec(&filep->access, conn);
9063 		mg_printf(conn, "HTTP/1.1 200 OK\r\n");
9064 		send_no_cache_header(conn);
9065 		mg_printf(conn,
9066 		          "%s%s%s"
9067 		          "Date: %s\r\n"
9068 		          "Content-Type: text/html\r\n"
9069 		          "Connection: %s\r\n\r\n",
9070 		          cors1,
9071 		          cors2,
9072 		          cors3,
9073 		          date,
9074 		          suggest_connection_header(conn));
9075 		send_ssi_file(conn, path, filep, 0);
9076 		(void)mg_fclose(&filep->access); /* Ignore errors for readonly files */
9077 	}
9078 }
9079 
9080 
9081 #if !defined(NO_FILES)
9082 static void
send_options(struct mg_connection * conn)9083 send_options(struct mg_connection *conn)
9084 {
9085 	char date[64];
9086 	time_t curtime = time(NULL);
9087 
9088 	if (!conn) {
9089 		return;
9090 	}
9091 
9092 	conn->status_code = 200;
9093 	conn->must_close = 1;
9094 	gmt_time_string(date, sizeof(date), &curtime);
9095 
9096 	mg_printf(conn,
9097 	          "HTTP/1.1 200 OK\r\n"
9098 	          "Date: %s\r\n"
9099 	          /* TODO: "Cache-Control" (?) */
9100 	          "Connection: %s\r\n"
9101 	          "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
9102 	          "PROPFIND, MKCOL\r\n"
9103 	          "DAV: 1\r\n\r\n",
9104 	          date,
9105 	          suggest_connection_header(conn));
9106 }
9107 
9108 
9109 /* Writes PROPFIND properties for a collection element */
9110 static void
print_props(struct mg_connection * conn,const char * uri,struct mg_file_stat * filep)9111 print_props(struct mg_connection *conn,
9112             const char *uri,
9113             struct mg_file_stat *filep)
9114 {
9115 	char mtime[64];
9116 
9117 	if (conn == NULL || uri == NULL || filep == NULL) {
9118 		return;
9119 	}
9120 
9121 	gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
9122 	conn->num_bytes_sent +=
9123 	    mg_printf(conn,
9124 	              "<d:response>"
9125 	              "<d:href>%s</d:href>"
9126 	              "<d:propstat>"
9127 	              "<d:prop>"
9128 	              "<d:resourcetype>%s</d:resourcetype>"
9129 	              "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
9130 	              "<d:getlastmodified>%s</d:getlastmodified>"
9131 	              "</d:prop>"
9132 	              "<d:status>HTTP/1.1 200 OK</d:status>"
9133 	              "</d:propstat>"
9134 	              "</d:response>\n",
9135 	              uri,
9136 	              filep->is_directory ? "<d:collection/>" : "",
9137 	              filep->size,
9138 	              mtime);
9139 }
9140 
9141 
9142 static void
print_dav_dir_entry(struct de * de,void * data)9143 print_dav_dir_entry(struct de *de, void *data)
9144 {
9145 	char href[PATH_MAX];
9146 	char href_encoded[PATH_MAX * 3 /* worst case */];
9147 	int truncated;
9148 
9149 	struct mg_connection *conn = (struct mg_connection *)data;
9150 	if (!de || !conn) {
9151 		return;
9152 	}
9153 	mg_snprintf(conn,
9154 	            &truncated,
9155 	            href,
9156 	            sizeof(href),
9157 	            "%s%s",
9158 	            conn->request_info.local_uri,
9159 	            de->file_name);
9160 
9161 	if (!truncated) {
9162 		mg_url_encode(href, href_encoded, PATH_MAX * 3);
9163 		print_props(conn, href_encoded, &de->file);
9164 	}
9165 }
9166 
9167 
9168 static void
handle_propfind(struct mg_connection * conn,const char * path,struct mg_file_stat * filep)9169 handle_propfind(struct mg_connection *conn,
9170                 const char *path,
9171                 struct mg_file_stat *filep)
9172 {
9173 	const char *depth = mg_get_header(conn, "Depth");
9174 	char date[64];
9175 	time_t curtime = time(NULL);
9176 
9177 	gmt_time_string(date, sizeof(date), &curtime);
9178 
9179 	if (!conn || !path || !filep || !conn->ctx) {
9180 		return;
9181 	}
9182 
9183 	conn->must_close = 1;
9184 	conn->status_code = 207;
9185 	mg_printf(conn,
9186 	          "HTTP/1.1 207 Multi-Status\r\n"
9187 	          "Date: %s\r\n",
9188 	          date);
9189 	send_static_cache_header(conn);
9190 	mg_printf(conn,
9191 	          "Connection: %s\r\n"
9192 	          "Content-Type: text/xml; charset=utf-8\r\n\r\n",
9193 	          suggest_connection_header(conn));
9194 
9195 	conn->num_bytes_sent +=
9196 	    mg_printf(conn,
9197 	              "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
9198 	              "<d:multistatus xmlns:d='DAV:'>\n");
9199 
9200 	/* Print properties for the requested resource itself */
9201 	print_props(conn, conn->request_info.local_uri, filep);
9202 
9203 	/* If it is a directory, print directory entries too if Depth is not 0 */
9204 	if (filep && filep->is_directory
9205 	    && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
9206 	    && (depth == NULL || strcmp(depth, "0") != 0)) {
9207 		scan_directory(conn, path, conn, &print_dav_dir_entry);
9208 	}
9209 
9210 	conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
9211 }
9212 #endif
9213 
9214 void
mg_lock_connection(struct mg_connection * conn)9215 mg_lock_connection(struct mg_connection *conn)
9216 {
9217 	if (conn) {
9218 		(void)pthread_mutex_lock(&conn->mutex);
9219 	}
9220 }
9221 
9222 void
mg_unlock_connection(struct mg_connection * conn)9223 mg_unlock_connection(struct mg_connection *conn)
9224 {
9225 	if (conn) {
9226 		(void)pthread_mutex_unlock(&conn->mutex);
9227 	}
9228 }
9229 
9230 void
mg_lock_context(struct mg_context * ctx)9231 mg_lock_context(struct mg_context *ctx)
9232 {
9233 	if (ctx) {
9234 		(void)pthread_mutex_lock(&ctx->nonce_mutex);
9235 	}
9236 }
9237 
9238 void
mg_unlock_context(struct mg_context * ctx)9239 mg_unlock_context(struct mg_context *ctx)
9240 {
9241 	if (ctx) {
9242 		(void)pthread_mutex_unlock(&ctx->nonce_mutex);
9243 	}
9244 }
9245 
9246 #if defined(USE_TIMERS)
9247 #include "timer.inl"
9248 #endif /* USE_TIMERS */
9249 
9250 #ifdef USE_LUA
9251 #include "mod_lua.inl"
9252 #endif /* USE_LUA */
9253 
9254 #ifdef USE_DUKTAPE
9255 #include "mod_duktape.inl"
9256 #endif /* USE_DUKTAPE */
9257 
9258 #if defined(USE_WEBSOCKET)
9259 
9260 #define SHA_API static
9261 #include "sha1.inl"
9262 
9263 static int
send_websocket_handshake(struct mg_connection * conn,const char * websock_key)9264 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
9265 {
9266 	static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
9267 	char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
9268 	SHA1_CTX sha_ctx;
9269 	int truncated;
9270 
9271 	/* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
9272 	mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
9273 	if (truncated) {
9274 		conn->must_close = 1;
9275 		return 0;
9276 	}
9277 
9278 	SHA1_Init(&sha_ctx);
9279 	SHA1_Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
9280 	SHA1_Final(&sha_ctx, (unsigned char *)sha);
9281 	base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
9282 	mg_printf(conn,
9283 	          "HTTP/1.1 101 Switching Protocols\r\n"
9284 	          "Upgrade: websocket\r\n"
9285 	          "Connection: Upgrade\r\n"
9286 	          "Sec-WebSocket-Accept: %s\r\n",
9287 	          b64_sha);
9288 	if (conn->request_info.acceptedWebSocketSubprotocol) {
9289 		mg_printf(conn,
9290 		          "Sec-WebSocket-Protocol: %s\r\n\r\n",
9291 		          conn->request_info.acceptedWebSocketSubprotocol);
9292 	} else {
9293 		mg_printf(conn, "%s", "\r\n");
9294 	}
9295 
9296 	return 1;
9297 }
9298 
9299 
9300 static void
read_websocket(struct mg_connection * conn,mg_websocket_data_handler ws_data_handler,void * callback_data)9301 read_websocket(struct mg_connection *conn,
9302                mg_websocket_data_handler ws_data_handler,
9303                void *callback_data)
9304 {
9305 	/* Pointer to the beginning of the portion of the incoming websocket
9306 	 * message queue.
9307 	 * The original websocket upgrade request is never removed, so the queue
9308 	 * begins after it. */
9309 	unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
9310 	int n, error, exit_by_callback;
9311 
9312 	/* body_len is the length of the entire queue in bytes
9313 	 * len is the length of the current message
9314 	 * data_len is the length of the current message's data payload
9315 	 * header_len is the length of the current message's header */
9316 	size_t i, len, mask_len = 0, data_len = 0, header_len, body_len;
9317 
9318 	/* "The masking key is a 32-bit value chosen at random by the client."
9319 	 * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
9320 	*/
9321 	unsigned char mask[4];
9322 
9323 	/* data points to the place where the message is stored when passed to
9324 	 * the
9325 	 * websocket_data callback.  This is either mem on the stack, or a
9326 	 * dynamically allocated buffer if it is too large. */
9327 	unsigned char mem[4096];
9328 	unsigned char *data = mem;
9329 	unsigned char mop; /* mask flag and opcode */
9330 	double timeout = -1.0;
9331 
9332 	if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
9333 		timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
9334 	}
9335 	if ((timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
9336 		timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
9337 	}
9338 
9339 	mg_set_thread_name("wsock");
9340 
9341 	/* Loop continuously, reading messages from the socket, invoking the
9342 	 * callback, and waiting repeatedly until an error occurs. */
9343 	while (!conn->ctx->stop_flag) {
9344 		header_len = 0;
9345 		assert(conn->data_len >= conn->request_len);
9346 		if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
9347 			len = buf[1] & 127;
9348 			mask_len = (buf[1] & 128) ? 4 : 0;
9349 			if ((len < 126) && (body_len >= mask_len)) {
9350 				data_len = len;
9351 				header_len = 2 + mask_len;
9352 			} else if ((len == 126) && (body_len >= (4 + mask_len))) {
9353 				header_len = 4 + mask_len;
9354 				data_len = ((((size_t)buf[2]) << 8) + buf[3]);
9355 			} else if (body_len >= (10 + mask_len)) {
9356 				header_len = 10 + mask_len;
9357 				data_len = (((uint64_t)ntohl(*(uint32_t *)(void *)&buf[2]))
9358 				            << 32) + ntohl(*(uint32_t *)(void *)&buf[6]);
9359 			}
9360 		}
9361 
9362 		if (header_len > 0 && body_len >= header_len) {
9363 			/* Allocate space to hold websocket payload */
9364 			data = mem;
9365 			if (data_len > sizeof(mem)) {
9366 				data = (unsigned char *)mg_malloc(data_len);
9367 				if (data == NULL) {
9368 					/* Allocation failed, exit the loop and then close the
9369 					 * connection */
9370 					mg_cry(conn, "websocket out of memory; closing connection");
9371 					break;
9372 				}
9373 			}
9374 
9375 			/* Copy the mask before we shift the queue and destroy it */
9376 			if (mask_len > 0) {
9377 				memcpy(mask, buf + header_len - mask_len, sizeof(mask));
9378 			} else {
9379 				memset(mask, 0, sizeof(mask));
9380 			}
9381 
9382 			/* Read frame payload from the first message in the queue into
9383 			 * data and advance the queue by moving the memory in place. */
9384 			assert(body_len >= header_len);
9385 			if (data_len + header_len > body_len) {
9386 				mop = buf[0]; /* current mask and opcode */
9387 				/* Overflow case */
9388 				len = body_len - header_len;
9389 				memcpy(data, buf + header_len, len);
9390 				error = 0;
9391 				while (len < data_len) {
9392 					n = pull(NULL,
9393 					         conn,
9394 					         (char *)(data + len),
9395 					         (int)(data_len - len),
9396 					         timeout);
9397 					if (n <= 0) {
9398 						error = 1;
9399 						break;
9400 					}
9401 					len += (size_t)n;
9402 				}
9403 				if (error) {
9404 					mg_cry(conn, "Websocket pull failed; closing connection");
9405 					break;
9406 				}
9407 				conn->data_len = conn->request_len;
9408 			} else {
9409 				mop = buf[0]; /* current mask and opcode, overwritten by
9410 				               * memmove() */
9411 				/* Length of the message being read at the front of the
9412 				 * queue */
9413 				len = data_len + header_len;
9414 
9415 				/* Copy the data payload into the data pointer for the
9416 				 * callback */
9417 				memcpy(data, buf + header_len, data_len);
9418 
9419 				/* Move the queue forward len bytes */
9420 				memmove(buf, buf + len, body_len - len);
9421 
9422 				/* Mark the queue as advanced */
9423 				conn->data_len -= (int)len;
9424 			}
9425 
9426 			/* Apply mask if necessary */
9427 			if (mask_len > 0) {
9428 				for (i = 0; i < data_len; ++i) {
9429 					data[i] ^= mask[i & 3];
9430 				}
9431 			}
9432 
9433 			/* Exit the loop if callback signals to exit (server side),
9434 			 * or "connection close" opcode received (client side). */
9435 			exit_by_callback = 0;
9436 			if ((ws_data_handler != NULL)
9437 			    && !ws_data_handler(
9438 			           conn, mop, (char *)data, data_len, callback_data)) {
9439 				exit_by_callback = 1;
9440 			}
9441 
9442 			if (data != mem) {
9443 				mg_free(data);
9444 			}
9445 
9446 			if (exit_by_callback
9447 			    || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
9448 				/* Opcode == 8, connection close */
9449 				break;
9450 			}
9451 
9452 			/* Not breaking the loop, process next websocket frame. */
9453 		} else {
9454 			/* Read from the socket into the next available location in the
9455 			 * message queue. */
9456 			if ((n = pull(NULL,
9457 			              conn,
9458 			              conn->buf + conn->data_len,
9459 			              conn->buf_size - conn->data_len,
9460 			              timeout)) <= 0) {
9461 				/* Error, no bytes read */
9462 				break;
9463 			}
9464 			conn->data_len += n;
9465 		}
9466 	}
9467 
9468 	mg_set_thread_name("worker");
9469 }
9470 
9471 
9472 static int
mg_websocket_write_exec(struct mg_connection * conn,int opcode,const char * data,size_t dataLen,uint32_t masking_key)9473 mg_websocket_write_exec(struct mg_connection *conn,
9474                         int opcode,
9475                         const char *data,
9476                         size_t dataLen,
9477                         uint32_t masking_key)
9478 {
9479 	unsigned char header[14];
9480 	size_t headerLen = 1;
9481 
9482 	int retval = -1;
9483 
9484 #if defined(__MINGW32__) || defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
9485 /* Disable spurious conversion warning for GCC */
9486 #pragma GCC diagnostic push
9487 #pragma GCC diagnostic ignored "-Wconversion"
9488 #endif
9489 
9490 	header[0] = 0x80u | (unsigned char)((unsigned)opcode & 0xf);
9491 
9492 #if defined(__MINGW32__) || defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
9493 #pragma GCC diagnostic pop
9494 #endif
9495 
9496 	/* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
9497 	if (dataLen < 126) {
9498 		/* inline 7-bit length field */
9499 		header[1] = (unsigned char)dataLen;
9500 		headerLen = 2;
9501 	} else if (dataLen <= 0xFFFF) {
9502 		/* 16-bit length field */
9503 		uint16_t len = htons((uint16_t)dataLen);
9504 		header[1] = 126;
9505 		memcpy(header + 2, &len, 2);
9506 		headerLen = 4;
9507 	} else {
9508 		/* 64-bit length field */
9509 		uint32_t len1 = htonl((uint32_t)((uint64_t)dataLen >> 32));
9510 		uint32_t len2 = htonl((uint32_t)(dataLen & 0xFFFFFFFFu));
9511 		header[1] = 127;
9512 		memcpy(header + 2, &len1, 4);
9513 		memcpy(header + 6, &len2, 4);
9514 		headerLen = 10;
9515 	}
9516 
9517 	if (masking_key) {
9518 		/* add mask */
9519 		header[1] |= 0x80;
9520 		memcpy(header + headerLen, &masking_key, 4);
9521 		headerLen += 4;
9522 	}
9523 
9524 
9525 	/* Note that POSIX/Winsock's send() is threadsafe
9526 	 * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
9527 	 * but mongoose's mg_printf/mg_write is not (because of the loop in
9528 	 * push(), although that is only a problem if the packet is large or
9529 	 * outgoing buffer is full). */
9530 	(void)mg_lock_connection(conn);
9531 	retval = mg_write(conn, header, headerLen);
9532 	if (dataLen > 0) {
9533 		retval = mg_write(conn, data, dataLen);
9534 	}
9535 	mg_unlock_connection(conn);
9536 
9537 	return retval;
9538 }
9539 
9540 int
mg_websocket_write(struct mg_connection * conn,int opcode,const char * data,size_t dataLen)9541 mg_websocket_write(struct mg_connection *conn,
9542                    int opcode,
9543                    const char *data,
9544                    size_t dataLen)
9545 {
9546 	return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
9547 }
9548 
9549 
9550 static void
mask_data(const char * in,size_t in_len,uint32_t masking_key,char * out)9551 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
9552 {
9553 	size_t i = 0;
9554 
9555 	i = 0;
9556 	if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
9557 		/* Convert in 32 bit words, if data is 4 byte aligned */
9558 		while (i < (in_len - 3)) {
9559 			*(uint32_t *)(void *)(out + i) =
9560 			    *(uint32_t *)(void *)(in + i) ^ masking_key;
9561 			i += 4;
9562 		}
9563 	}
9564 	if (i != in_len) {
9565 		/* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
9566 		while (i < in_len) {
9567 			*(uint8_t *)(void *)(out + i) =
9568 			    *(uint8_t *)(void *)(in + i)
9569 			    ^ *(((uint8_t *)&masking_key) + (i % 4));
9570 			i++;
9571 		}
9572 	}
9573 }
9574 
9575 
9576 int
mg_websocket_client_write(struct mg_connection * conn,int opcode,const char * data,size_t dataLen)9577 mg_websocket_client_write(struct mg_connection *conn,
9578                           int opcode,
9579                           const char *data,
9580                           size_t dataLen)
9581 {
9582 	int retval = -1;
9583 	char *masked_data = (char *)mg_malloc(((dataLen + 7) / 4) * 4);
9584 	uint32_t masking_key = (uint32_t)get_random();
9585 
9586 	if (masked_data == NULL) {
9587 		/* Return -1 in an error case */
9588 		mg_cry(conn,
9589 		       "Cannot allocate buffer for masked websocket response: "
9590 		       "Out of memory");
9591 		return -1;
9592 	}
9593 
9594 	mask_data(data, dataLen, masking_key, masked_data);
9595 
9596 	retval = mg_websocket_write_exec(
9597 	    conn, opcode, masked_data, dataLen, masking_key);
9598 	mg_free(masked_data);
9599 
9600 	return retval;
9601 }
9602 
9603 
9604 static void
handle_websocket_request(struct mg_connection * conn,const char * path,int is_callback_resource,struct mg_websocket_subprotocols * subprotocols,mg_websocket_connect_handler ws_connect_handler,mg_websocket_ready_handler ws_ready_handler,mg_websocket_data_handler ws_data_handler,mg_websocket_close_handler ws_close_handler,void * cbData)9605 handle_websocket_request(struct mg_connection *conn,
9606                          const char *path,
9607                          int is_callback_resource,
9608                          struct mg_websocket_subprotocols *subprotocols,
9609                          mg_websocket_connect_handler ws_connect_handler,
9610                          mg_websocket_ready_handler ws_ready_handler,
9611                          mg_websocket_data_handler ws_data_handler,
9612                          mg_websocket_close_handler ws_close_handler,
9613                          void *cbData)
9614 {
9615 	const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
9616 	const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
9617 	int lua_websock = 0;
9618 
9619 #if !defined(USE_LUA)
9620 	(void)path;
9621 #endif
9622 
9623 	/* Step 1: Check websocket protocol version. */
9624 	/* Step 1.1: Check Sec-WebSocket-Key. */
9625 	if (!websock_key) {
9626 		/* The RFC standard version (https://tools.ietf.org/html/rfc6455)
9627 		 * requires a Sec-WebSocket-Key header.
9628 		 */
9629 		/* It could be the hixie draft version
9630 		 * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
9631 		 */
9632 		const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
9633 		const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
9634 		char key3[8];
9635 
9636 		if ((key1 != NULL) && (key2 != NULL)) {
9637 			/* This version uses 8 byte body data in a GET request */
9638 			conn->content_len = 8;
9639 			if (8 == mg_read(conn, key3, 8)) {
9640 				/* This is the hixie version */
9641 				send_http_error(conn,
9642 				                426,
9643 				                "%s",
9644 				                "Protocol upgrade to RFC 6455 required");
9645 				return;
9646 			}
9647 		}
9648 		/* This is an unknown version */
9649 		send_http_error(conn, 400, "%s", "Malformed websocket request");
9650 		return;
9651 	}
9652 
9653 	/* Step 1.2: Check websocket protocol version. */
9654 	/* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
9655 	if (version == NULL || strcmp(version, "13") != 0) {
9656 		/* Reject wrong versions */
9657 		send_http_error(conn, 426, "%s", "Protocol upgrade required");
9658 		return;
9659 	}
9660 
9661 	/* Step 1.3: Could check for "Host", but we do not really nead this
9662 	 * value for anything, so just ignore it. */
9663 
9664 	/* Step 2: If a callback is responsible, call it. */
9665 	if (is_callback_resource) {
9666 		/* Step 2.1 check and select subprotocol */
9667 		const char *protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
9668 		if (protocol && subprotocols) {
9669 			int idx;
9670 			unsigned long len;
9671 			const char *sep, *curSubProtocol,
9672 			    *acceptedWebSocketSubprotocol = NULL;
9673 
9674 
9675 			/* look for matching subprotocol */
9676 			do {
9677 				sep = strchr(protocol, ',');
9678 				curSubProtocol = protocol;
9679                 // CONDUIT CHANGE: supress warnings ident on windows
9680 				len = (unsigned long) (sep ? (unsigned long)(sep - protocol) : strlen(protocol));
9681 				while (sep && isspace(*++sep))
9682 					; // ignore leading whitespaces
9683 				protocol = sep;
9684 
9685 
9686 				for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
9687 					if ((strlen(subprotocols->subprotocols[idx]) == len)
9688 					    && (strncmp(curSubProtocol,
9689 					                subprotocols->subprotocols[idx],
9690 					                len) == 0)) {
9691 						acceptedWebSocketSubprotocol =
9692 						    subprotocols->subprotocols[idx];
9693 						break;
9694 					}
9695 				}
9696 			} while (sep && !acceptedWebSocketSubprotocol);
9697 
9698 			conn->request_info.acceptedWebSocketSubprotocol =
9699 			    acceptedWebSocketSubprotocol;
9700 		} else if (protocol) {
9701 			/* keep legacy behavior */
9702 
9703 			/* The protocol is a comma seperated list of names. */
9704 			/* The server must only return one value from this list. */
9705 			/* First check if it is a list or just a single value. */
9706 			const char *sep = strrchr(protocol, ',');
9707 			if (sep == NULL) {
9708 				/* Just a single protocol -> accept it. */
9709 				conn->request_info.acceptedWebSocketSubprotocol = protocol;
9710 			} else {
9711 				/* Multiple protocols -> accept the last one. */
9712 				/* This is just a quick fix if the client offers multiple
9713 				 * protocols. The handler should have a list of accepted
9714 				 * protocols on his own
9715 				 * and use it to select one protocol among those the client has
9716 				 * offered.
9717 				 */
9718 				while (isspace(*++sep))
9719 					; // ignore leading whitespaces
9720 				conn->request_info.acceptedWebSocketSubprotocol = sep;
9721 			}
9722 		}
9723 
9724 		if (ws_connect_handler != NULL
9725 		    && ws_connect_handler(conn, cbData) != 0) {
9726 			/* C callback has returned non-zero, do not proceed with
9727 			 * handshake.
9728 			 */
9729 			/* Note that C callbacks are no longer called when Lua is
9730 			 * responsible, so C can no longer filter callbacks for Lua. */
9731 			return;
9732 		}
9733 	}
9734 #if defined(USE_LUA)
9735 	/* Step 3: No callback. Check if Lua is responsible. */
9736 	else {
9737 		/* Step 3.1: Check if Lua is responsible. */
9738 		if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
9739 			lua_websock =
9740 			    match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
9741 			                 strlen(
9742 			                     conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
9743 			                 path);
9744 		}
9745 
9746 		if (lua_websock) {
9747 			/* Step 3.2: Lua is responsible: call it. */
9748 			conn->lua_websocket_state = lua_websocket_new(path, conn);
9749 			if (!conn->lua_websocket_state) {
9750 				/* Lua rejected the new client */
9751 				return;
9752 			}
9753 		}
9754 	}
9755 #endif
9756 
9757 	/* Step 4: Check if there is a responsible websocket handler. */
9758 	if (!is_callback_resource && !lua_websock) {
9759 		/* There is no callback, and Lua is not responsible either. */
9760 		/* Reply with a 404 Not Found or with nothing at all?
9761 		 * TODO (mid): check the websocket standards, how to reply to
9762 		 * requests to invalid websocket addresses. */
9763 		send_http_error(conn, 404, "%s", "Not found");
9764 		return;
9765 	}
9766 
9767 	/* Step 5: The websocket connection has been accepted */
9768 	if (!send_websocket_handshake(conn, websock_key)) {
9769 		send_http_error(conn, 500, "%s", "Websocket handshake failed");
9770 		return;
9771 	}
9772 
9773 	/* Step 6: Call the ready handler */
9774 	if (is_callback_resource) {
9775 		if (ws_ready_handler != NULL) {
9776 			ws_ready_handler(conn, cbData);
9777 		}
9778 #if defined(USE_LUA)
9779 	} else if (lua_websock) {
9780 		if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
9781 			/* the ready handler returned false */
9782 			return;
9783 		}
9784 #endif
9785 	}
9786 
9787 	/* Step 7: Enter the read loop */
9788 	if (is_callback_resource) {
9789 		read_websocket(conn, ws_data_handler, cbData);
9790 #if defined(USE_LUA)
9791 	} else if (lua_websock) {
9792 		read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
9793 #endif
9794 	}
9795 
9796 	/* Step 8: Call the close handler */
9797 	if (ws_close_handler) {
9798 		ws_close_handler(conn, cbData);
9799 	}
9800 }
9801 
9802 
9803 static int
is_websocket_protocol(const struct mg_connection * conn)9804 is_websocket_protocol(const struct mg_connection *conn)
9805 {
9806 	const char *upgrade, *connection;
9807 
9808 	/* A websocket protocoll has the following HTTP headers:
9809 	 *
9810 	 * Connection: Upgrade
9811 	 * Upgrade: Websocket
9812 	 */
9813 
9814 	upgrade = mg_get_header(conn, "Upgrade");
9815 	if (upgrade == NULL) {
9816 		return 0; /* fail early, don't waste time checking other header
9817 		           * fields
9818 		             */
9819 	}
9820 	if (!mg_strcasestr(upgrade, "websocket")) {
9821 		return 0;
9822 	}
9823 
9824 	connection = mg_get_header(conn, "Connection");
9825 	if (connection == NULL) {
9826 		return 0;
9827 	}
9828 	if (!mg_strcasestr(connection, "upgrade")) {
9829 		return 0;
9830 	}
9831 
9832 	/* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
9833 	 * "Sec-WebSocket-Version" are also required.
9834 	 * Don't check them here, since even an unsupported websocket protocol
9835 	 * request still IS a websocket request (in contrast to a standard HTTP
9836 	 * request). It will fail later in handle_websocket_request.
9837 	 */
9838 
9839 	return 1;
9840 }
9841 #endif /* !USE_WEBSOCKET */
9842 
9843 
9844 static int
isbyte(int n)9845 isbyte(int n)
9846 {
9847 	return n >= 0 && n <= 255;
9848 }
9849 
9850 
9851 static int
parse_net(const char * spec,uint32_t * net,uint32_t * mask)9852 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
9853 {
9854 	int n, a, b, c, d, slash = 32, len = 0;
9855 
9856 	if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
9857 	     || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
9858 	    && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
9859 	    && slash < 33) {
9860 		len = n;
9861 		*net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
9862 		       | (uint32_t)d;
9863 		*mask = slash ? (0xffffffffU << (32 - slash)) : 0;
9864 	}
9865 
9866 	return len;
9867 }
9868 
9869 
9870 static int
set_throttle(const char * spec,uint32_t remote_ip,const char * uri)9871 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
9872 {
9873 	int throttle = 0;
9874 	struct vec vec, val;
9875 	uint32_t net, mask;
9876 	char mult;
9877 	double v;
9878 
9879 	while ((spec = next_option(spec, &vec, &val)) != NULL) {
9880 		mult = ',';
9881 		if ((val.ptr == NULL) || (sscanf(val.ptr, "%lf%c", &v, &mult) < 1)
9882 		    || (v < 0) || ((lowercase(&mult) != 'k')
9883 		                   && (lowercase(&mult) != 'm') && (mult != ','))) {
9884 			continue;
9885 		}
9886 		v *= (lowercase(&mult) == 'k')
9887 		         ? 1024
9888 		         : ((lowercase(&mult) == 'm') ? 1048576 : 1);
9889 		if (vec.len == 1 && vec.ptr[0] == '*') {
9890 			throttle = (int)v;
9891 		} else if (parse_net(vec.ptr, &net, &mask) > 0) {
9892 			if ((remote_ip & mask) == net) {
9893 				throttle = (int)v;
9894 			}
9895 		} else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
9896 			throttle = (int)v;
9897 		}
9898 	}
9899 
9900 	return throttle;
9901 }
9902 
9903 
9904 static uint32_t
get_remote_ip(const struct mg_connection * conn)9905 get_remote_ip(const struct mg_connection *conn)
9906 {
9907 	if (!conn) {
9908 		return 0;
9909 	}
9910 	return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
9911 }
9912 
9913 
9914 /* The mg_upload function is superseeded by mg_handle_form_request. */
9915 #include "handle_form.inl"
9916 
9917 
9918 #if defined(MG_LEGACY_INTERFACE)
9919 /* Implement the deprecated mg_upload function by calling the new
9920  * mg_handle_form_request function. While mg_upload could only handle
9921  * HTML forms sent as POST request in multipart/form-data format
9922  * containing only file input elements, mg_handle_form_request can
9923  * handle all form input elements and all standard request methods. */
9924 struct mg_upload_user_data {
9925 	struct mg_connection *conn;
9926 	const char *destination_dir;
9927 	int num_uploaded_files;
9928 };
9929 
9930 
9931 /* Helper function for deprecated mg_upload. */
9932 static int
mg_upload_field_found(const char * key,const char * filename,char * path,size_t pathlen,void * user_data)9933 mg_upload_field_found(const char *key,
9934                       const char *filename,
9935                       char *path,
9936                       size_t pathlen,
9937                       void *user_data)
9938 {
9939 	int truncated = 0;
9940 	struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9941 	(void)key;
9942 
9943 	if (!filename) {
9944 		mg_cry(fud->conn, "%s: No filename set", __func__);
9945 		return FORM_FIELD_STORAGE_ABORT;
9946 	}
9947 	mg_snprintf(fud->conn,
9948 	            &truncated,
9949 	            path,
9950 	            pathlen - 1,
9951 	            "%s/%s",
9952 	            fud->destination_dir,
9953 	            filename);
9954 	if (!truncated) {
9955 		mg_cry(fud->conn, "%s: File path too long", __func__);
9956 		return FORM_FIELD_STORAGE_ABORT;
9957 	}
9958 	return FORM_FIELD_STORAGE_STORE;
9959 }
9960 
9961 
9962 /* Helper function for deprecated mg_upload. */
9963 static int
mg_upload_field_get(const char * key,const char * value,size_t value_size,void * user_data)9964 mg_upload_field_get(const char *key,
9965                     const char *value,
9966                     size_t value_size,
9967                     void *user_data)
9968 {
9969 	/* Function should never be called */
9970 	(void)key;
9971 	(void)value;
9972 	(void)value_size;
9973 	(void)user_data;
9974 
9975 	return 0;
9976 }
9977 
9978 
9979 /* Helper function for deprecated mg_upload. */
9980 static int
mg_upload_field_stored(const char * path,long long file_size,void * user_data)9981 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
9982 {
9983 	struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9984 	(void)file_size;
9985 
9986 	fud->num_uploaded_files++;
9987 	fud->conn->ctx->callbacks.upload(fud->conn, path);
9988 
9989 	return 0;
9990 }
9991 
9992 
9993 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
9994 int
mg_upload(struct mg_connection * conn,const char * destination_dir)9995 mg_upload(struct mg_connection *conn, const char *destination_dir)
9996 {
9997 	struct mg_upload_user_data fud = {conn, destination_dir, 0};
9998 	struct mg_form_data_handler fdh = {mg_upload_field_found,
9999 	                                   mg_upload_field_get,
10000 	                                   mg_upload_field_stored,
10001 	                                   0};
10002 	int ret;
10003 
10004 	fdh.user_data = (void *)&fud;
10005 	ret = mg_handle_form_request(conn, &fdh);
10006 
10007 	if (ret < 0) {
10008 		mg_cry(conn, "%s: Error while parsing the request", __func__);
10009 	}
10010 
10011 	return fud.num_uploaded_files;
10012 }
10013 #endif
10014 
10015 
10016 static int
get_first_ssl_listener_index(const struct mg_context * ctx)10017 get_first_ssl_listener_index(const struct mg_context *ctx)
10018 {
10019 	unsigned int i;
10020 	int idx = -1;
10021 	if (ctx) {
10022 		for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
10023 			idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
10024 		}
10025 	}
10026 	return idx;
10027 }
10028 
10029 
10030 static void
redirect_to_https_port(struct mg_connection * conn,int ssl_index)10031 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
10032 {
10033 	char host[1025];
10034 	const char *host_header;
10035 	size_t hostlen;
10036 
10037 	host_header = mg_get_header(conn, "Host");
10038 	hostlen = sizeof(host);
10039 	if (host_header != NULL) {
10040 		char *pos;
10041 
10042 		mg_strlcpy(host, host_header, hostlen);
10043 		host[hostlen - 1] = '\0';
10044 		pos = strchr(host, ':');
10045 		if (pos != NULL) {
10046 			*pos = '\0';
10047 		}
10048 	} else {
10049 		/* Cannot get host from the Host: header.
10050 		 * Fallback to our IP address. */
10051 		if (conn) {
10052 			sockaddr_to_string(host, hostlen, &conn->client.lsa);
10053 		}
10054 	}
10055 
10056 	/* Send host, port, uri and (if it exists) ?query_string */
10057 	if (conn) {
10058 		mg_printf(conn,
10059 		          "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
10060 		          host,
10061 #if defined(USE_IPV6)
10062 		          (conn->ctx->listening_sockets[ssl_index].lsa.sa.sa_family
10063 		           == AF_INET6)
10064 		              ? (int)ntohs(conn->ctx->listening_sockets[ssl_index]
10065 		                               .lsa.sin6.sin6_port)
10066 		              :
10067 #endif
10068 		              (int)ntohs(conn->ctx->listening_sockets[ssl_index]
10069 		                             .lsa.sin.sin_port),
10070 		          conn->request_info.local_uri,
10071 		          (conn->request_info.query_string == NULL) ? "" : "?",
10072 		          (conn->request_info.query_string == NULL)
10073 		              ? ""
10074 		              : conn->request_info.query_string);
10075 	}
10076 }
10077 
10078 
10079 static void
mg_set_handler_type(struct mg_context * ctx,const char * uri,int handler_type,int is_delete_request,mg_request_handler handler,struct mg_websocket_subprotocols * subprotocols,mg_websocket_connect_handler connect_handler,mg_websocket_ready_handler ready_handler,mg_websocket_data_handler data_handler,mg_websocket_close_handler close_handler,mg_authorization_handler auth_handler,void * cbdata)10080 mg_set_handler_type(struct mg_context *ctx,
10081                     const char *uri,
10082                     int handler_type,
10083                     int is_delete_request,
10084                     mg_request_handler handler,
10085                     struct mg_websocket_subprotocols *subprotocols,
10086                     mg_websocket_connect_handler connect_handler,
10087                     mg_websocket_ready_handler ready_handler,
10088                     mg_websocket_data_handler data_handler,
10089                     mg_websocket_close_handler close_handler,
10090                     mg_authorization_handler auth_handler,
10091                     void *cbdata)
10092 {
10093 	struct mg_handler_info *tmp_rh, **lastref;
10094 	size_t urilen = strlen(uri);
10095 
10096 	if (handler_type == WEBSOCKET_HANDLER) {
10097 		/* assert(handler == NULL); */
10098 		/* assert(is_delete_request || connect_handler!=NULL ||
10099 		 *        ready_handler!=NULL || data_handler!=NULL ||
10100 		 *        close_handler!=NULL);
10101 		 */
10102 		/* assert(auth_handler == NULL); */
10103 		if (handler != NULL) {
10104 			return;
10105 		}
10106 		if (!is_delete_request && connect_handler == NULL
10107 		    && ready_handler == NULL
10108 		    && data_handler == NULL
10109 		    && close_handler == NULL) {
10110 			return;
10111 		}
10112 		if (auth_handler != NULL) {
10113 			return;
10114 		}
10115 	} else if (handler_type == REQUEST_HANDLER) {
10116 		/* assert(connect_handler==NULL && ready_handler==NULL &&
10117 		 *        data_handler==NULL && close_handler==NULL); */
10118 		/* assert(is_delete_request || (handler!=NULL));
10119 		 */
10120 		/* assert(auth_handler == NULL); */
10121 		if (connect_handler != NULL || ready_handler != NULL
10122 		    || data_handler != NULL
10123 		    || close_handler != NULL) {
10124 			return;
10125 		}
10126 		if (!is_delete_request && (handler == NULL)) {
10127 			return;
10128 		}
10129 		if (auth_handler != NULL) {
10130 			return;
10131 		}
10132 	} else { /* AUTH_HANDLER */
10133 		     /* assert(handler == NULL); */
10134 		     /* assert(connect_handler==NULL && ready_handler==NULL &&
10135 		      *        data_handler==NULL && close_handler==NULL); */
10136 		/* assert(auth_handler != NULL); */
10137 		if (handler != NULL) {
10138 			return;
10139 		}
10140 		if (connect_handler != NULL || ready_handler != NULL
10141 		    || data_handler != NULL
10142 		    || close_handler != NULL) {
10143 			return;
10144 		}
10145 		if (!is_delete_request && (auth_handler == NULL)) {
10146 			return;
10147 		}
10148 	}
10149 
10150 	if (!ctx) {
10151 		return;
10152 	}
10153 
10154 	mg_lock_context(ctx);
10155 
10156 	/* first try to find an existing handler */
10157 	lastref = &(ctx->handlers);
10158 	for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
10159 		if (tmp_rh->handler_type == handler_type) {
10160 			if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
10161 				if (!is_delete_request) {
10162 					/* update existing handler */
10163 					if (handler_type == REQUEST_HANDLER) {
10164 						tmp_rh->handler = handler;
10165 					} else if (handler_type == WEBSOCKET_HANDLER) {
10166 						tmp_rh->subprotocols = subprotocols;
10167 						tmp_rh->connect_handler = connect_handler;
10168 						tmp_rh->ready_handler = ready_handler;
10169 						tmp_rh->data_handler = data_handler;
10170 						tmp_rh->close_handler = close_handler;
10171 					} else { /* AUTH_HANDLER */
10172 						tmp_rh->auth_handler = auth_handler;
10173 					}
10174 					tmp_rh->cbdata = cbdata;
10175 				} else {
10176 					/* remove existing handler */
10177 					*lastref = tmp_rh->next;
10178 					mg_free(tmp_rh->uri);
10179 					mg_free(tmp_rh);
10180 				}
10181 				mg_unlock_context(ctx);
10182 				return;
10183 			}
10184 		}
10185 		lastref = &(tmp_rh->next);
10186 	}
10187 
10188 	if (is_delete_request) {
10189 		/* no handler to set, this was a remove request to a non-existing
10190 		 * handler */
10191 		mg_unlock_context(ctx);
10192 		return;
10193 	}
10194 
10195 	tmp_rh =
10196 	    (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
10197 	if (tmp_rh == NULL) {
10198 		mg_unlock_context(ctx);
10199 		mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
10200 		return;
10201 	}
10202 	tmp_rh->uri = mg_strdup(uri);
10203 	if (!tmp_rh->uri) {
10204 		mg_unlock_context(ctx);
10205 		mg_free(tmp_rh);
10206 		mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
10207 		return;
10208 	}
10209 	tmp_rh->uri_len = urilen;
10210 	if (handler_type == REQUEST_HANDLER) {
10211 		tmp_rh->handler = handler;
10212 	} else if (handler_type == WEBSOCKET_HANDLER) {
10213 		tmp_rh->subprotocols = subprotocols;
10214 		tmp_rh->connect_handler = connect_handler;
10215 		tmp_rh->ready_handler = ready_handler;
10216 		tmp_rh->data_handler = data_handler;
10217 		tmp_rh->close_handler = close_handler;
10218 	} else { /* AUTH_HANDLER */
10219 		tmp_rh->auth_handler = auth_handler;
10220 	}
10221 	tmp_rh->cbdata = cbdata;
10222 	tmp_rh->handler_type = handler_type;
10223 	tmp_rh->next = NULL;
10224 
10225 	*lastref = tmp_rh;
10226 	mg_unlock_context(ctx);
10227 }
10228 
10229 
10230 void
mg_set_request_handler(struct mg_context * ctx,const char * uri,mg_request_handler handler,void * cbdata)10231 mg_set_request_handler(struct mg_context *ctx,
10232                        const char *uri,
10233                        mg_request_handler handler,
10234                        void *cbdata)
10235 {
10236 	mg_set_handler_type(ctx,
10237 	                    uri,
10238 	                    REQUEST_HANDLER,
10239 	                    handler == NULL,
10240 	                    handler,
10241 	                    NULL,
10242 	                    NULL,
10243 	                    NULL,
10244 	                    NULL,
10245 	                    NULL,
10246 	                    NULL,
10247 	                    cbdata);
10248 }
10249 
10250 
10251 void
mg_set_websocket_handler(struct mg_context * ctx,const char * uri,mg_websocket_connect_handler connect_handler,mg_websocket_ready_handler ready_handler,mg_websocket_data_handler data_handler,mg_websocket_close_handler close_handler,void * cbdata)10252 mg_set_websocket_handler(struct mg_context *ctx,
10253                          const char *uri,
10254                          mg_websocket_connect_handler connect_handler,
10255                          mg_websocket_ready_handler ready_handler,
10256                          mg_websocket_data_handler data_handler,
10257                          mg_websocket_close_handler close_handler,
10258                          void *cbdata)
10259 {
10260 	mg_set_websocket_handler_with_subprotocols(ctx,
10261 	                                           uri,
10262 	                                           NULL,
10263 	                                           connect_handler,
10264 	                                           ready_handler,
10265 	                                           data_handler,
10266 	                                           close_handler,
10267 	                                           cbdata);
10268 }
10269 
10270 
10271 void
mg_set_websocket_handler_with_subprotocols(struct mg_context * ctx,const char * uri,struct mg_websocket_subprotocols * subprotocols,mg_websocket_connect_handler connect_handler,mg_websocket_ready_handler ready_handler,mg_websocket_data_handler data_handler,mg_websocket_close_handler close_handler,void * cbdata)10272 mg_set_websocket_handler_with_subprotocols(
10273     struct mg_context *ctx,
10274     const char *uri,
10275     struct mg_websocket_subprotocols *subprotocols,
10276     mg_websocket_connect_handler connect_handler,
10277     mg_websocket_ready_handler ready_handler,
10278     mg_websocket_data_handler data_handler,
10279     mg_websocket_close_handler close_handler,
10280     void *cbdata)
10281 {
10282 	int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
10283 	                        && (data_handler == NULL)
10284 	                        && (close_handler == NULL);
10285 	mg_set_handler_type(ctx,
10286 	                    uri,
10287 	                    WEBSOCKET_HANDLER,
10288 	                    is_delete_request,
10289 	                    NULL,
10290 	                    subprotocols,
10291 	                    connect_handler,
10292 	                    ready_handler,
10293 	                    data_handler,
10294 	                    close_handler,
10295 	                    NULL,
10296 	                    cbdata);
10297 }
10298 
10299 
10300 void
mg_set_auth_handler(struct mg_context * ctx,const char * uri,mg_request_handler handler,void * cbdata)10301 mg_set_auth_handler(struct mg_context *ctx,
10302                     const char *uri,
10303                     mg_request_handler handler,
10304                     void *cbdata)
10305 {
10306 	mg_set_handler_type(ctx,
10307 	                    uri,
10308 	                    AUTH_HANDLER,
10309 	                    handler == NULL,
10310 	                    NULL,
10311 	                    NULL,
10312 	                    NULL,
10313 	                    NULL,
10314 	                    NULL,
10315 	                    NULL,
10316 	                    handler,
10317 	                    cbdata);
10318 }
10319 
10320 
10321 static int
get_request_handler(struct mg_connection * conn,int handler_type,mg_request_handler * handler,struct mg_websocket_subprotocols ** subprotocols,mg_websocket_connect_handler * connect_handler,mg_websocket_ready_handler * ready_handler,mg_websocket_data_handler * data_handler,mg_websocket_close_handler * close_handler,mg_authorization_handler * auth_handler,void ** cbdata)10322 get_request_handler(struct mg_connection *conn,
10323                     int handler_type,
10324                     mg_request_handler *handler,
10325                     struct mg_websocket_subprotocols **subprotocols,
10326                     mg_websocket_connect_handler *connect_handler,
10327                     mg_websocket_ready_handler *ready_handler,
10328                     mg_websocket_data_handler *data_handler,
10329                     mg_websocket_close_handler *close_handler,
10330                     mg_authorization_handler *auth_handler,
10331                     void **cbdata)
10332 {
10333 	const struct mg_request_info *request_info = mg_get_request_info(conn);
10334 	if (request_info) {
10335 		const char *uri = request_info->local_uri;
10336 		size_t urilen = strlen(uri);
10337 		struct mg_handler_info *tmp_rh;
10338 
10339 		if (!conn || !conn->ctx) {
10340 			return 0;
10341 		}
10342 
10343 		mg_lock_context(conn->ctx);
10344 
10345 		/* first try for an exact match */
10346 		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
10347 		     tmp_rh = tmp_rh->next) {
10348 			if (tmp_rh->handler_type == handler_type) {
10349 				if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
10350 					if (handler_type == WEBSOCKET_HANDLER) {
10351 						*subprotocols = tmp_rh->subprotocols;
10352 						*connect_handler = tmp_rh->connect_handler;
10353 						*ready_handler = tmp_rh->ready_handler;
10354 						*data_handler = tmp_rh->data_handler;
10355 						*close_handler = tmp_rh->close_handler;
10356 					} else if (handler_type == REQUEST_HANDLER) {
10357 						*handler = tmp_rh->handler;
10358 					} else { /* AUTH_HANDLER */
10359 						*auth_handler = tmp_rh->auth_handler;
10360 					}
10361 					*cbdata = tmp_rh->cbdata;
10362 					mg_unlock_context(conn->ctx);
10363 					return 1;
10364 				}
10365 			}
10366 		}
10367 
10368 		/* next try for a partial match, we will accept uri/something */
10369 		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
10370 		     tmp_rh = tmp_rh->next) {
10371 			if (tmp_rh->handler_type == handler_type) {
10372 				if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
10373 				    && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
10374 					if (handler_type == WEBSOCKET_HANDLER) {
10375 						*subprotocols = tmp_rh->subprotocols;
10376 						*connect_handler = tmp_rh->connect_handler;
10377 						*ready_handler = tmp_rh->ready_handler;
10378 						*data_handler = tmp_rh->data_handler;
10379 						*close_handler = tmp_rh->close_handler;
10380 					} else if (handler_type == REQUEST_HANDLER) {
10381 						*handler = tmp_rh->handler;
10382 					} else { /* AUTH_HANDLER */
10383 						*auth_handler = tmp_rh->auth_handler;
10384 					}
10385 					*cbdata = tmp_rh->cbdata;
10386 					mg_unlock_context(conn->ctx);
10387 					return 1;
10388 				}
10389 			}
10390 		}
10391 
10392 		/* finally try for pattern match */
10393 		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
10394 		     tmp_rh = tmp_rh->next) {
10395 			if (tmp_rh->handler_type == handler_type) {
10396 				if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
10397 					if (handler_type == WEBSOCKET_HANDLER) {
10398 						*subprotocols = tmp_rh->subprotocols;
10399 						*connect_handler = tmp_rh->connect_handler;
10400 						*ready_handler = tmp_rh->ready_handler;
10401 						*data_handler = tmp_rh->data_handler;
10402 						*close_handler = tmp_rh->close_handler;
10403 					} else if (handler_type == REQUEST_HANDLER) {
10404 						*handler = tmp_rh->handler;
10405 					} else { /* AUTH_HANDLER */
10406 						*auth_handler = tmp_rh->auth_handler;
10407 					}
10408 					*cbdata = tmp_rh->cbdata;
10409 					mg_unlock_context(conn->ctx);
10410 					return 1;
10411 				}
10412 			}
10413 		}
10414 
10415 		mg_unlock_context(conn->ctx);
10416 	}
10417 	return 0; /* none found */
10418 }
10419 
10420 
10421 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
10422 static int
deprecated_websocket_connect_wrapper(const struct mg_connection * conn,void * cbdata)10423 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
10424                                      void *cbdata)
10425 {
10426 	struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
10427 	if (pcallbacks->websocket_connect) {
10428 		return pcallbacks->websocket_connect(conn);
10429 	}
10430 	/* No handler set - assume "OK" */
10431 	return 0;
10432 }
10433 
10434 
10435 static void
deprecated_websocket_ready_wrapper(struct mg_connection * conn,void * cbdata)10436 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
10437 {
10438 	struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
10439 	if (pcallbacks->websocket_ready) {
10440 		pcallbacks->websocket_ready(conn);
10441 	}
10442 }
10443 
10444 
10445 static int
deprecated_websocket_data_wrapper(struct mg_connection * conn,int bits,char * data,size_t len,void * cbdata)10446 deprecated_websocket_data_wrapper(struct mg_connection *conn,
10447                                   int bits,
10448                                   char *data,
10449                                   size_t len,
10450                                   void *cbdata)
10451 {
10452 	struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
10453 	if (pcallbacks->websocket_data) {
10454 		return pcallbacks->websocket_data(conn, bits, data, len);
10455 	}
10456 	/* No handler set - assume "OK" */
10457 	return 1;
10458 }
10459 #endif
10460 
10461 
10462 /* This is the heart of the Civetweb's logic.
10463  * This function is called when the request is read, parsed and validated,
10464  * and Civetweb must decide what action to take: serve a file, or
10465  * a directory, or call embedded function, etcetera. */
10466 static void
handle_request(struct mg_connection * conn)10467 handle_request(struct mg_connection *conn)
10468 {
10469 	if (conn) {
10470 		struct mg_request_info *ri = &conn->request_info;
10471 		char path[PATH_MAX];
10472 		int uri_len, ssl_index;
10473 		int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
10474 		    is_put_or_delete_request = 0, is_callback_resource = 0;
10475 		int i;
10476 		struct mg_file file = STRUCT_FILE_INITIALIZER;
10477 		mg_request_handler callback_handler = NULL;
10478 		struct mg_websocket_subprotocols *subprotocols;
10479 		mg_websocket_connect_handler ws_connect_handler = NULL;
10480 		mg_websocket_ready_handler ws_ready_handler = NULL;
10481 		mg_websocket_data_handler ws_data_handler = NULL;
10482 		mg_websocket_close_handler ws_close_handler = NULL;
10483 		void *callback_data = NULL;
10484 		mg_authorization_handler auth_handler = NULL;
10485 		void *auth_callback_data = NULL;
10486 #if !defined(NO_FILES)
10487 		time_t curtime = time(NULL);
10488 		char date[64];
10489 #endif
10490 
10491 		path[0] = 0;
10492 
10493 		if (!ri) {
10494 			return;
10495 		}
10496 
10497 		/* 1. get the request url */
10498 		/* 1.1. split into url and query string */
10499 		if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
10500 		    != NULL) {
10501 			*((char *)conn->request_info.query_string++) = '\0';
10502 		}
10503 
10504 		/* 1.2. do a https redirect, if required. Do not decode URIs yet. */
10505 		if (!conn->client.is_ssl && conn->client.ssl_redir) {
10506 			ssl_index = get_first_ssl_listener_index(conn->ctx);
10507 			if (ssl_index >= 0) {
10508 				redirect_to_https_port(conn, ssl_index);
10509 			} else {
10510 				/* A http to https forward port has been specified,
10511 				 * but no https port to forward to. */
10512 				send_http_error(conn,
10513 				                503,
10514 				                "%s",
10515 				                "Error: SSL forward not configured properly");
10516 				mg_cry(conn, "Can not redirect to SSL, no SSL port available");
10517 			}
10518 			return;
10519 		}
10520 		uri_len = (int)strlen(ri->local_uri);
10521 
10522 		/* 1.3. decode url (if config says so) */
10523 		if (should_decode_url(conn)) {
10524 			mg_url_decode(
10525 			    ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
10526 		}
10527 
10528 		/* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is
10529 		 * not possible */
10530 		remove_double_dots_and_double_slashes((char *)ri->local_uri);
10531 
10532 		/* step 1. completed, the url is known now */
10533 		uri_len = (int)strlen(ri->local_uri);
10534 		DEBUG_TRACE("URL: %s", ri->local_uri);
10535 
10536 		/* 3. if this ip has limited speed, set it for this connection */
10537 		conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
10538 		                              get_remote_ip(conn),
10539 		                              ri->local_uri);
10540 
10541 		/* 4. call a "handle everything" callback, if registered */
10542 		if (conn->ctx->callbacks.begin_request != NULL) {
10543 			/* Note that since V1.7 the "begin_request" function is called
10544 			 * before an authorization check. If an authorization check is
10545 			 * required, use a request_handler instead. */
10546 			i = conn->ctx->callbacks.begin_request(conn);
10547 			if (i > 0) {
10548 				/* callback already processed the request. Store the
10549 				   return value as a status code for the access log. */
10550 				conn->status_code = i;
10551 				discard_unread_request_data(conn);
10552 				return;
10553 			} else if (i == 0) {
10554 				/* civetweb should process the request */
10555 			} else {
10556 				/* unspecified - may change with the next version */
10557 				return;
10558 			}
10559 		}
10560 
10561 		/* request not yet handled by a handler or redirect, so the request
10562 		 * is processed here */
10563 
10564 		/* 5. interpret the url to find out how the request must be handled
10565 		 */
10566 		/* 5.1. first test, if the request targets the regular http(s)://
10567 		 * protocol namespace or the websocket ws(s):// protocol namespace.
10568 		 */
10569 		is_websocket_request = is_websocket_protocol(conn);
10570 
10571 		/* 5.2. check if the request will be handled by a callback */
10572 		if (get_request_handler(conn,
10573 		                        is_websocket_request ? WEBSOCKET_HANDLER
10574 		                                             : REQUEST_HANDLER,
10575 		                        &callback_handler,
10576 		                        &subprotocols,
10577 		                        &ws_connect_handler,
10578 		                        &ws_ready_handler,
10579 		                        &ws_data_handler,
10580 		                        &ws_close_handler,
10581 		                        NULL,
10582 		                        &callback_data)) {
10583 			/* 5.2.1. A callback will handle this request. All requests
10584 			 * handled
10585 			 * by a callback have to be considered as requests to a script
10586 			 * resource. */
10587 			is_callback_resource = 1;
10588 			is_script_resource = 1;
10589 			is_put_or_delete_request = is_put_or_delete_method(conn);
10590 		} else {
10591 		no_callback_resource:
10592 			/* 5.2.2. No callback is responsible for this request. The URI
10593 			 * addresses a file based resource (static content or Lua/cgi
10594 			 * scripts in the file system). */
10595 			is_callback_resource = 0;
10596 			interpret_uri(conn,
10597 			              path,
10598 			              sizeof(path),
10599 			              &file.stat,
10600 			              &is_found,
10601 			              &is_script_resource,
10602 			              &is_websocket_request,
10603 			              &is_put_or_delete_request);
10604 		}
10605 
10606 		/* 6. authorization check */
10607 		/* 6.1. a custom authorization handler is installed */
10608 		if (get_request_handler(conn,
10609 		                        AUTH_HANDLER,
10610 		                        NULL,
10611 		                        NULL,
10612 		                        NULL,
10613 		                        NULL,
10614 		                        NULL,
10615 		                        NULL,
10616 		                        &auth_handler,
10617 		                        &auth_callback_data)) {
10618 			if (!auth_handler(conn, auth_callback_data)) {
10619 				return;
10620 			}
10621 		} else if (is_put_or_delete_request && !is_script_resource
10622 		           && !is_callback_resource) {
10623 /* 6.2. this request is a PUT/DELETE to a real file */
10624 /* 6.2.1. thus, the server must have real files */
10625 #if defined(NO_FILES)
10626 			if (1) {
10627 #else
10628 			if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10629 #endif
10630 				/* This server does not have any real files, thus the
10631 				 * PUT/DELETE methods are not valid. */
10632 				send_http_error(conn,
10633 				                405,
10634 				                "%s method not allowed",
10635 				                conn->request_info.request_method);
10636 				return;
10637 			}
10638 
10639 #if !defined(NO_FILES)
10640 			/* 6.2.2. Check if put authorization for static files is
10641 			 * available.
10642 			 */
10643 			if (!is_authorized_for_put(conn)) {
10644 				send_authorization_request(conn);
10645 				return;
10646 			}
10647 #endif
10648 
10649 		} else {
10650 			/* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
10651 			 * or it is a PUT or DELETE request to a resource that does not
10652 			 * correspond to a file. Check authorization. */
10653 			if (!check_authorization(conn, path)) {
10654 				send_authorization_request(conn);
10655 				return;
10656 			}
10657 		}
10658 
10659 		/* request is authorized or does not need authorization */
10660 
10661 		/* 7. check if there are request handlers for this uri */
10662 		if (is_callback_resource) {
10663 			if (!is_websocket_request) {
10664 				i = callback_handler(conn, callback_data);
10665 				if (i > 0) {
10666 					/* Do nothing, callback has served the request. Store
10667 					 * the
10668 					 * return value as status code for the log and discard
10669 					 * all
10670 					 * data from the client not used by the callback. */
10671 					conn->status_code = i;
10672 					discard_unread_request_data(conn);
10673 				} else {
10674 					/* TODO (high): what if the handler did NOT handle the
10675 					 * request */
10676 					/* The last version did handle this as a file request,
10677 					 * but
10678 					 * since a file request is not always a script resource,
10679 					 * the authorization check might be different */
10680 					interpret_uri(conn,
10681 					              path,
10682 					              sizeof(path),
10683 					              &file.stat,
10684 					              &is_found,
10685 					              &is_script_resource,
10686 					              &is_websocket_request,
10687 					              &is_put_or_delete_request);
10688 					callback_handler = NULL;
10689 
10690 					/* TODO (very low): goto is deprecated but for the
10691 					 * moment,
10692 					 * a goto is simpler than some curious loop. */
10693 					/* The situation "callback does not handle the request"
10694 					 * needs to be reconsidered anyway. */
10695 					goto no_callback_resource;
10696 				}
10697 			} else {
10698 #if defined(USE_WEBSOCKET)
10699 				handle_websocket_request(conn,
10700 				                         path,
10701 				                         is_callback_resource,
10702 				                         subprotocols,
10703 				                         ws_connect_handler,
10704 				                         ws_ready_handler,
10705 				                         ws_data_handler,
10706 				                         ws_close_handler,
10707 				                         callback_data);
10708 #endif
10709 			}
10710 			return;
10711 		}
10712 
10713 /* 8. handle websocket requests */
10714 #if defined(USE_WEBSOCKET)
10715 		if (is_websocket_request) {
10716 			if (is_script_resource) {
10717 				/* Websocket Lua script */
10718 				handle_websocket_request(conn,
10719 				                         path,
10720 				                         0 /* Lua Script */,
10721 				                         NULL,
10722 				                         NULL,
10723 				                         NULL,
10724 				                         NULL,
10725 				                         NULL,
10726 				                         &conn->ctx->callbacks);
10727 			} else {
10728 #if defined(MG_LEGACY_INTERFACE)
10729 				handle_websocket_request(
10730 				    conn,
10731 				    path,
10732 				    !is_script_resource /* could be deprecated global callback */,
10733 				    NULL,
10734 				    deprecated_websocket_connect_wrapper,
10735 				    deprecated_websocket_ready_wrapper,
10736 				    deprecated_websocket_data_wrapper,
10737 				    NULL,
10738 				    &conn->ctx->callbacks);
10739 #else
10740 				send_http_error(conn, 404, "%s", "Not found");
10741 #endif
10742 			}
10743 			return;
10744 		} else
10745 #endif
10746 
10747 #if defined(NO_FILES)
10748 			/* 9a. In case the server uses only callbacks, this uri is
10749 			 * unknown.
10750 			 * Then, all request handling ends here. */
10751 			send_http_error(conn, 404, "%s", "Not Found");
10752 
10753 #else
10754 		/* 9b. This request is either for a static file or resource handled
10755 		 * by a script file. Thus, a DOCUMENT_ROOT must exist. */
10756 		if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10757 			send_http_error(conn, 404, "%s", "Not Found");
10758 			return;
10759 		}
10760 
10761 		/* 10. File is handled by a script. */
10762 		if (is_script_resource) {
10763 			handle_file_based_request(conn, path, &file);
10764 			return;
10765 		}
10766 
10767 		/* 11. Handle put/delete/mkcol requests */
10768 		if (is_put_or_delete_request) {
10769 			/* 11.1. PUT method */
10770 			if (!strcmp(ri->request_method, "PUT")) {
10771 				put_file(conn, path);
10772 				return;
10773 			}
10774 			/* 11.2. DELETE method */
10775 			if (!strcmp(ri->request_method, "DELETE")) {
10776 				delete_file(conn, path);
10777 				return;
10778 			}
10779 			/* 11.3. MKCOL method */
10780 			if (!strcmp(ri->request_method, "MKCOL")) {
10781 				mkcol(conn, path);
10782 				return;
10783 			}
10784 			/* 11.4. PATCH method
10785 			 * This method is not supported for static resources,
10786 			 * only for scripts (Lua, CGI) and callbacks. */
10787 			send_http_error(conn,
10788 			                405,
10789 			                "%s method not allowed",
10790 			                conn->request_info.request_method);
10791 			return;
10792 		}
10793 
10794 		/* 11. File does not exist, or it was configured that it should be
10795 		 * hidden */
10796 		if (!is_found || (must_hide_file(conn, path))) {
10797 			send_http_error(conn, 404, "%s", "Not found");
10798 			return;
10799 		}
10800 
10801 		/* 12. Directory uris should end with a slash */
10802 		if (file.stat.is_directory && (uri_len > 0)
10803 		    && (ri->local_uri[uri_len - 1] != '/')) {
10804 			gmt_time_string(date, sizeof(date), &curtime);
10805 			mg_printf(conn,
10806 			          "HTTP/1.1 301 Moved Permanently\r\n"
10807 			          "Location: %s/\r\n"
10808 			          "Date: %s\r\n"
10809 			          /* "Cache-Control: private\r\n" (= default) */
10810 			          "Content-Length: 0\r\n"
10811 			          "Connection: %s\r\n\r\n",
10812 			          ri->request_uri,
10813 			          date,
10814 			          suggest_connection_header(conn));
10815 			return;
10816 		}
10817 
10818 		/* 13. Handle other methods than GET/HEAD */
10819 		/* 13.1. Handle PROPFIND */
10820 		if (!strcmp(ri->request_method, "PROPFIND")) {
10821 			handle_propfind(conn, path, &file.stat);
10822 			return;
10823 		}
10824 		/* 13.2. Handle OPTIONS for files */
10825 		if (!strcmp(ri->request_method, "OPTIONS")) {
10826 			/* This standard handler is only used for real files.
10827 			 * Scripts should support the OPTIONS method themselves, to allow a
10828 			 * maximum flexibility.
10829 			 * Lua and CGI scripts may fully support CORS this way (including
10830 			 * preflights). */
10831 			send_options(conn);
10832 			return;
10833 		}
10834 		/* 13.3. everything but GET and HEAD (e.g. POST) */
10835 		if (0 != strcmp(ri->request_method, "GET")
10836 		    && 0 != strcmp(ri->request_method, "HEAD")) {
10837 			send_http_error(conn,
10838 			                405,
10839 			                "%s method not allowed",
10840 			                conn->request_info.request_method);
10841 			return;
10842 		}
10843 
10844 		/* 14. directories */
10845 		if (file.stat.is_directory) {
10846 			if (substitute_index_file(conn, path, sizeof(path), &file)) {
10847 				/* 14.1. use a substitute file */
10848 				/* TODO (high): substitute index may be a script resource.
10849 				 * define what should be possible in this case. */
10850 			} else {
10851 				/* 14.2. no substitute file */
10852 				if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
10853 				                   "yes")) {
10854 					handle_directory_request(conn, path);
10855 				} else {
10856 					send_http_error(conn,
10857 					                403,
10858 					                "%s",
10859 					                "Error: Directory listing denied");
10860 				}
10861 				return;
10862 			}
10863 		}
10864 
10865 		handle_file_based_request(conn, path, &file);
10866 #endif /* !defined(NO_FILES) */
10867 
10868 #if 0
10869             /* Perform redirect and auth checks before calling begin_request()
10870              * handler.
10871              * Otherwise, begin_request() would need to perform auth checks and
10872              * redirects. */
10873 #endif
10874 	}
10875 	return;
10876 }
10877 
10878 
10879 static void
10880 handle_file_based_request(struct mg_connection *conn,
10881                           const char *path,
10882                           struct mg_file *file)
10883 {
10884 	if (!conn || !conn->ctx) {
10885 		return;
10886 	}
10887 
10888 	if (0) {
10889 #ifdef USE_LUA
10890 	} else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
10891 	                        strlen(
10892 	                            conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
10893 	                        path) > 0) {
10894 		/* Lua server page: an SSI like page containing mostly plain html
10895 		 * code
10896 		 * plus some tags with server generated contents. */
10897 		handle_lsp_request(conn, path, file, NULL);
10898 	} else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
10899 	                        strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
10900 	                        path) > 0) {
10901 		/* Lua in-server module script: a CGI like script used to generate
10902 		 * the
10903 		 * entire reply. */
10904 		mg_exec_lua_script(conn, path, NULL);
10905 #endif
10906 #if defined(USE_DUKTAPE)
10907 	} else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
10908 	                        strlen(
10909 	                            conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
10910 	                        path) > 0) {
10911 		/* Call duktape to generate the page */
10912 		mg_exec_duktape_script(conn, path);
10913 #endif
10914 #if !defined(NO_CGI)
10915 	} else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
10916 	                        strlen(conn->ctx->config[CGI_EXTENSIONS]),
10917 	                        path) > 0) {
10918 		/* CGI scripts may support all HTTP methods */
10919 		handle_cgi_request(conn, path);
10920 #endif /* !NO_CGI */
10921 	} else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10922 	                        strlen(conn->ctx->config[SSI_EXTENSIONS]),
10923 	                        path) > 0) {
10924 		handle_ssi_file_request(conn, path, file);
10925 #if !defined(NO_CACHING)
10926 	} else if ((!conn->in_error_handler)
10927 	           && is_not_modified(conn, &file->stat)) {
10928 		/* Send 304 "Not Modified" - this must not send any body data */
10929 		handle_not_modified_static_file_request(conn, file);
10930 #endif /* !NO_CACHING */
10931 	} else {
10932 		handle_static_file_request(conn, path, file, NULL, NULL);
10933 	}
10934 }
10935 
10936 
10937 static void
10938 close_all_listening_sockets(struct mg_context *ctx)
10939 {
10940 	unsigned int i;
10941 	if (!ctx) {
10942 		return;
10943 	}
10944 
10945 	for (i = 0; i < ctx->num_listening_sockets; i++) {
10946 		closesocket(ctx->listening_sockets[i].sock);
10947 		ctx->listening_sockets[i].sock = INVALID_SOCKET;
10948 	}
10949 	mg_free(ctx->listening_sockets);
10950 	ctx->listening_sockets = NULL;
10951 	mg_free(ctx->listening_socket_fds);
10952 	ctx->listening_socket_fds = NULL;
10953 }
10954 
10955 
10956 /* Valid listening port specification is: [ip_address:]port[s]
10957  * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 192.0.2.3:8080s
10958  * Examples for IPv6: [::]:80, [::1]:80,
10959  *   [2001:0db8:7654:3210:FEDC:BA98:7654:3210]:443s
10960  *   see https://tools.ietf.org/html/rfc3513#section-2.2
10961  * In order to bind to both, IPv4 and IPv6, you can either add
10962  * both ports using 8080,[::]:8080, or the short form +8080.
10963  * Both forms differ in detail: 8080,[::]:8080 create two sockets,
10964  * one only accepting IPv4 the other only IPv6. +8080 creates
10965  * one socket accepting IPv4 and IPv6. Depending on the IPv6
10966  * environment, they might work differently, or might not work
10967  * at all - it must be tested what options work best in the
10968  * relevant network environment.
10969  */
10970 static int
10971 parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
10972 {
10973 	unsigned int a, b, c, d, port;
10974 	int ch, len;
10975 #if defined(USE_IPV6)
10976 	char buf[100] = {0};
10977 #endif
10978 
10979 	/* MacOS needs that. If we do not zero it, subsequent bind() will fail.
10980 	 * Also, all-zeroes in the socket address means binding to all addresses
10981 	 * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
10982 	memset(so, 0, sizeof(*so));
10983 	so->lsa.sin.sin_family = AF_INET;
10984 	*ip_version = 0;
10985 
10986 	if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
10987 	    == 5) {
10988 		/* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
10989 		so->lsa.sin.sin_addr.s_addr =
10990 		    htonl((a << 24) | (b << 16) | (c << 8) | d);
10991 		so->lsa.sin.sin_port = htons((uint16_t)port);
10992 		*ip_version = 4;
10993 
10994 #if defined(USE_IPV6)
10995 	} else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
10996 	           && mg_inet_pton(
10997 	                  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
10998 		/* IPv6 address, examples: see above */
10999 		/* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
11000 		 */
11001 		so->lsa.sin6.sin6_port = htons((uint16_t)port);
11002 		*ip_version = 6;
11003 #endif
11004 
11005 	} else if ((vec->ptr[0] == '+')
11006 	           && (sscanf(vec->ptr + 1, "%u%n", &port, &len) == 1)) {
11007 
11008 		/* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */
11009 		/* Add 1 to len for the + character we skipped before */
11010 		len++;
11011 
11012 #if defined(USE_IPV6)
11013 		/* Set socket family to IPv6, do not use IPV6_V6ONLY */
11014 		so->lsa.sin6.sin6_family = AF_INET6;
11015 		so->lsa.sin6.sin6_port = htons((uint16_t)port);
11016 		*ip_version = 4 + 6;
11017 #else
11018 		/* Bind to IPv4 only, since IPv6 is not built in. */
11019 		so->lsa.sin.sin_port = htons((uint16_t)port);
11020 		*ip_version = 4;
11021 #endif
11022 
11023 	} else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
11024 		/* If only port is specified, bind to IPv4, INADDR_ANY */
11025 		so->lsa.sin.sin_port = htons((uint16_t)port);
11026 		*ip_version = 4;
11027 
11028 	} else {
11029 		/* Parsing failure. Make port invalid. */
11030 		port = 0;
11031 		len = 0;
11032 	}
11033 
11034 	/* sscanf and the option splitting code ensure the following condition
11035 	 */
11036 	if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
11037 		*ip_version = 0;
11038 		return 0;
11039 	}
11040 	ch = vec->ptr[len]; /* Next character after the port number */
11041 	so->is_ssl = (ch == 's');
11042 	so->ssl_redir = (ch == 'r');
11043 
11044 	/* Make sure the port is valid and vector ends with 's', 'r' or ',' */
11045 	if (is_valid_port(port)
11046 	    && (ch == '\0' || ch == 's' || ch == 'r' || ch == ',')) {
11047 		return 1;
11048 	}
11049 
11050 	/* Reset ip_version to 0 of there is an error */
11051 	*ip_version = 0;
11052 	return 0;
11053 }
11054 
11055 
11056 static int
11057 set_ports_option(struct mg_context *ctx)
11058 {
11059 	const char *list;
11060 	int on = 1;
11061 #if defined(USE_IPV6)
11062 	int off = 0;
11063 #endif
11064 	struct vec vec;
11065 	struct socket so, *ptr;
11066 
11067 	struct pollfd *pfd;
11068 	union usa usa;
11069 	socklen_t len;
11070 	int ip_version;
11071 
11072 	int portsTotal = 0;
11073 	int portsOk = 0;
11074 
11075 	if (!ctx) {
11076 		return 0;
11077 	}
11078 
11079 	memset(&so, 0, sizeof(so));
11080 	memset(&usa, 0, sizeof(usa));
11081 	len = sizeof(usa);
11082 	list = ctx->config[LISTENING_PORTS];
11083 
11084 	while ((list = next_option(list, &vec, NULL)) != NULL) {
11085 
11086 		portsTotal++;
11087 
11088 		if (!parse_port_string(&vec, &so, &ip_version)) {
11089 			mg_cry(fc(ctx),
11090 			       "%.*s: invalid port spec (entry %i). Expecting list of: %s",
11091 			       (int)vec.len,
11092 			       vec.ptr,
11093 			       portsTotal,
11094 			       "[IP_ADDRESS:]PORT[s|r]");
11095 			continue;
11096 		}
11097 
11098 #if !defined(NO_SSL)
11099 		if (so.is_ssl && ctx->ssl_ctx == NULL) {
11100 
11101 			mg_cry(fc(ctx),
11102 			       "Cannot add SSL socket (entry %i). Is -ssl_certificate "
11103 			       "option set?",
11104 			       portsTotal);
11105 			continue;
11106 		}
11107 #endif
11108 
11109 		if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
11110 		    == INVALID_SOCKET) {
11111 
11112 			mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
11113 			continue;
11114 		}
11115 
11116 #ifdef _WIN32
11117 		/* Windows SO_REUSEADDR lets many procs binds to a
11118 		 * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
11119 		 * if someone already has the socket -- DTL */
11120 		/* NOTE: If SO_EXCLUSIVEADDRUSE is used,
11121 		 * Windows might need a few seconds before
11122 		 * the same port can be used again in the
11123 		 * same process, so a short Sleep may be
11124 		 * required between mg_stop and mg_start.
11125 		 */
11126 		if (setsockopt(so.sock,
11127 		               SOL_SOCKET,
11128 		               SO_EXCLUSIVEADDRUSE,
11129 		               (SOCK_OPT_TYPE)&on,
11130 		               sizeof(on)) != 0) {
11131 
11132 			/* Set reuse option, but don't abort on errors. */
11133 			mg_cry(fc(ctx),
11134 			       "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
11135 			       portsTotal);
11136 		}
11137 #else
11138 		if (setsockopt(so.sock,
11139 		               SOL_SOCKET,
11140 		               SO_REUSEADDR,
11141 		               (SOCK_OPT_TYPE)&on,
11142 		               sizeof(on)) != 0) {
11143 
11144 			/* Set reuse option, but don't abort on errors. */
11145 			mg_cry(fc(ctx),
11146 			       "cannot set socket option SO_REUSEADDR (entry %i)",
11147 			       portsTotal);
11148 		}
11149 #endif
11150 
11151 		if (ip_version > 4) {
11152 #if defined(USE_IPV6)
11153 			if (ip_version == 6) {
11154 				if (so.lsa.sa.sa_family == AF_INET6
11155 				    && setsockopt(so.sock,
11156 				                  IPPROTO_IPV6,
11157 				                  IPV6_V6ONLY,
11158 				                  (void *)&off,
11159 				                  sizeof(off)) != 0) {
11160 
11161 					/* Set IPv6 only option, but don't abort on errors. */
11162 					mg_cry(fc(ctx),
11163 					       "cannot set socket option IPV6_V6ONLY (entry %i)",
11164 					       portsTotal);
11165 				}
11166 			}
11167 #else
11168 			mg_cry(fc(ctx), "IPv6 not available");
11169 			closesocket(so.sock);
11170 			so.sock = INVALID_SOCKET;
11171 			continue;
11172 #endif
11173 		}
11174 
11175 		if (so.lsa.sa.sa_family == AF_INET) {
11176 
11177 			len = sizeof(so.lsa.sin);
11178 			if (bind(so.sock, &so.lsa.sa, len) != 0) {
11179 				mg_cry(fc(ctx),
11180 				       "cannot bind to %.*s: %d (%s)",
11181 				       (int)vec.len,
11182 				       vec.ptr,
11183 				       (int)ERRNO,
11184 				       strerror(errno));
11185 				closesocket(so.sock);
11186 				so.sock = INVALID_SOCKET;
11187 				continue;
11188 			}
11189 		}
11190 #if defined(USE_IPV6)
11191 		else if (so.lsa.sa.sa_family == AF_INET6) {
11192 
11193 			len = sizeof(so.lsa.sin6);
11194 			if (bind(so.sock, &so.lsa.sa, len) != 0) {
11195 				mg_cry(fc(ctx),
11196 				       "cannot bind to IPv6 %.*s: %d (%s)",
11197 				       (int)vec.len,
11198 				       vec.ptr,
11199 				       (int)ERRNO,
11200 				       strerror(errno));
11201 				closesocket(so.sock);
11202 				so.sock = INVALID_SOCKET;
11203 				continue;
11204 			}
11205 		}
11206 #endif
11207 		else {
11208 			mg_cry(fc(ctx),
11209 			       "cannot bind: address family not supported (entry %i)",
11210 			       portsTotal);
11211 			continue;
11212 		}
11213 
11214 		if (listen(so.sock, SOMAXCONN) != 0) {
11215 
11216 			mg_cry(fc(ctx),
11217 			       "cannot listen to %.*s: %d (%s)",
11218 			       (int)vec.len,
11219 			       vec.ptr,
11220 			       (int)ERRNO,
11221 			       strerror(errno));
11222 			closesocket(so.sock);
11223 			so.sock = INVALID_SOCKET;
11224 			continue;
11225 		}
11226 
11227 		if (getsockname(so.sock, &(usa.sa), &len) != 0
11228 		    || usa.sa.sa_family != so.lsa.sa.sa_family) {
11229 
11230 			int err = (int)ERRNO;
11231 			mg_cry(fc(ctx),
11232 			       "call to getsockname failed %.*s: %d (%s)",
11233 			       (int)vec.len,
11234 			       vec.ptr,
11235 			       err,
11236 			       strerror(errno));
11237 			closesocket(so.sock);
11238 			so.sock = INVALID_SOCKET;
11239 			continue;
11240 		}
11241 
11242 /* Update lsa port in case of random free ports */
11243 #if defined(USE_IPV6)
11244 		if (so.lsa.sa.sa_family == AF_INET6) {
11245 			so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
11246 		} else
11247 #endif
11248 		{
11249 			so.lsa.sin.sin_port = usa.sin.sin_port;
11250 		}
11251 
11252 		if ((ptr = (struct socket *)
11253 		         mg_realloc(ctx->listening_sockets,
11254 		                    (ctx->num_listening_sockets + 1)
11255 		                        * sizeof(ctx->listening_sockets[0]))) == NULL) {
11256 
11257 			mg_cry(fc(ctx), "%s", "Out of memory");
11258 			closesocket(so.sock);
11259 			so.sock = INVALID_SOCKET;
11260 			continue;
11261 		}
11262 
11263 		if ((pfd = (struct pollfd *)mg_realloc(
11264 		         ctx->listening_socket_fds,
11265 		         (ctx->num_listening_sockets + 1)
11266 		             * sizeof(ctx->listening_socket_fds[0]))) == NULL) {
11267 
11268 			mg_cry(fc(ctx), "%s", "Out of memory");
11269 			closesocket(so.sock);
11270 			so.sock = INVALID_SOCKET;
11271 			mg_free(ptr);
11272 			continue;
11273 		}
11274 
11275 		set_close_on_exec(so.sock, fc(ctx));
11276 		ctx->listening_sockets = ptr;
11277 		ctx->listening_sockets[ctx->num_listening_sockets] = so;
11278 		ctx->listening_socket_fds = pfd;
11279 		ctx->num_listening_sockets++;
11280 		portsOk++;
11281 	}
11282 
11283 	if (portsOk != portsTotal) {
11284 		close_all_listening_sockets(ctx);
11285 		portsOk = 0;
11286 	}
11287 
11288 	return portsOk;
11289 }
11290 
11291 
11292 static const char *
11293 header_val(const struct mg_connection *conn, const char *header)
11294 {
11295 	const char *header_value;
11296 
11297 	if ((header_value = mg_get_header(conn, header)) == NULL) {
11298 		return "-";
11299 	} else {
11300 		return header_value;
11301 	}
11302 }
11303 
11304 
11305 static void
11306 log_access(const struct mg_connection *conn)
11307 {
11308 	const struct mg_request_info *ri;
11309 	struct mg_file fi;
11310 	char date[64], src_addr[IP_ADDR_STR_LEN];
11311 	struct tm *tm;
11312 
11313 	const char *referer;
11314 	const char *user_agent;
11315 
11316 	char buf[4096];
11317 
11318 	if (!conn || !conn->ctx) {
11319 		return;
11320 	}
11321 
11322 	if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
11323 		if (mg_fopen(conn,
11324 		             conn->ctx->config[ACCESS_LOG_FILE],
11325 		             MG_FOPEN_MODE_APPEND,
11326 		             &fi) == 0) {
11327 			fi.access.fp = NULL;
11328 		}
11329 	} else {
11330 		fi.access.fp = NULL;
11331 	}
11332 
11333 	/* Log is written to a file and/or a callback. If both are not set,
11334 	 * executing the rest of the function is pointless. */
11335 	if ((fi.access.fp == NULL) && (conn->ctx->callbacks.log_access == NULL)) {
11336 		return;
11337 	}
11338 
11339 	tm = localtime(&conn->conn_birth_time);
11340 	if (tm != NULL) {
11341 		strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
11342 	} else {
11343 		mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
11344 		date[sizeof(date) - 1] = '\0';
11345 	}
11346 
11347 	ri = &conn->request_info;
11348 
11349 	sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
11350 	referer = header_val(conn, "Referer");
11351 	user_agent = header_val(conn, "User-Agent");
11352 
11353 	mg_snprintf(conn,
11354 	            NULL, /* Ignore truncation in access log */
11355 	            buf,
11356 	            sizeof(buf),
11357 	            "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
11358 	            src_addr,
11359 	            (ri->remote_user == NULL) ? "-" : ri->remote_user,
11360 	            date,
11361 	            ri->request_method ? ri->request_method : "-",
11362 	            ri->request_uri ? ri->request_uri : "-",
11363 	            ri->query_string ? "?" : "",
11364 	            ri->query_string ? ri->query_string : "",
11365 	            ri->http_version,
11366 	            conn->status_code,
11367 	            conn->num_bytes_sent,
11368 	            referer,
11369 	            user_agent);
11370 
11371 	if (conn->ctx->callbacks.log_access) {
11372 		conn->ctx->callbacks.log_access(conn, buf);
11373 	}
11374 
11375 	if (fi.access.fp) {
11376 		int ok = 1;
11377 		flockfile(fi.access.fp);
11378 		if (fprintf(fi.access.fp, "%s\n", buf) < 1) {
11379 			ok = 0;
11380 		}
11381 		if (fflush(fi.access.fp) != 0) {
11382 			ok = 0;
11383 		}
11384 		funlockfile(fi.access.fp);
11385 		if (mg_fclose(&fi.access) != 0) {
11386 			ok = 0;
11387 		}
11388 		if (!ok) {
11389 			mg_cry(conn,
11390 			       "Error writing log file %s",
11391 			       conn->ctx->config[ACCESS_LOG_FILE]);
11392 		}
11393 	}
11394 }
11395 
11396 
11397 /* Verify given socket address against the ACL.
11398  * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
11399  */
11400 static int
11401 check_acl(struct mg_context *ctx, uint32_t remote_ip)
11402 {
11403 	int allowed, flag;
11404 	uint32_t net, mask;
11405 	struct vec vec;
11406 
11407 	if (ctx) {
11408 		const char *list = ctx->config[ACCESS_CONTROL_LIST];
11409 
11410 		/* If any ACL is set, deny by default */
11411 		allowed = (list == NULL) ? '+' : '-';
11412 
11413 		while ((list = next_option(list, &vec, NULL)) != NULL) {
11414 			flag = vec.ptr[0];
11415 			if ((flag != '+' && flag != '-')
11416 			    || parse_net(&vec.ptr[1], &net, &mask) == 0) {
11417 				mg_cry(fc(ctx),
11418 				       "%s: subnet must be [+|-]x.x.x.x[/x]",
11419 				       __func__);
11420 				return -1;
11421 			}
11422 
11423 			if (net == (remote_ip & mask)) {
11424 				allowed = flag;
11425 			}
11426 		}
11427 
11428 		return allowed == '+';
11429 	}
11430 	return -1;
11431 }
11432 
11433 
11434 #if !defined(_WIN32)
11435 static int
11436 set_uid_option(struct mg_context *ctx)
11437 {
11438 	struct passwd *pw;
11439 	if (ctx) {
11440 		const char *uid = ctx->config[RUN_AS_USER];
11441 		int success = 0;
11442 
11443 		if (uid == NULL) {
11444 			success = 1;
11445 		} else {
11446 			if ((pw = getpwnam(uid)) == NULL) {
11447 				mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
11448 			} else if (setgid(pw->pw_gid) == -1) {
11449 				mg_cry(fc(ctx),
11450 				       "%s: setgid(%s): %s",
11451 				       __func__,
11452 				       uid,
11453 				       strerror(errno));
11454 			} else if (setgroups(0, NULL)) {
11455 				mg_cry(fc(ctx),
11456 				       "%s: setgroups(): %s",
11457 				       __func__,
11458 				       strerror(errno));
11459 			} else if (setuid(pw->pw_uid) == -1) {
11460 				mg_cry(fc(ctx),
11461 				       "%s: setuid(%s): %s",
11462 				       __func__,
11463 				       uid,
11464 				       strerror(errno));
11465 			} else {
11466 				success = 1;
11467 			}
11468 		}
11469 
11470 		return success;
11471 	}
11472 	return 0;
11473 }
11474 #endif /* !_WIN32 */
11475 
11476 
11477 static void
11478 tls_dtor(void *key)
11479 {
11480 	struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
11481 	/* key == pthread_getspecific(sTlsKey); */
11482 
11483 	if (tls) {
11484 		if (tls->is_master == 2) {
11485 			tls->is_master = -3; /* Mark memory as dead */
11486 			mg_free(tls);
11487 		}
11488 	}
11489 	pthread_setspecific(sTlsKey, NULL);
11490 }
11491 
11492 
11493 #if !defined(NO_SSL)
11494 
11495 /* Must be set if sizeof(pthread_t) > sizeof(unsigned long) */
11496 static unsigned long
11497 ssl_id_callback(void)
11498 {
11499 #ifdef _WIN32
11500 	return GetCurrentThreadId();
11501 #else
11502 
11503 #ifdef __clang__
11504 #pragma clang diagnostic push
11505 #pragma clang diagnostic ignored "-Wunreachable-code"
11506 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
11507  * or not, so one of the two conditions will be unreachable by construction.
11508  * Unfortunately the C standard does not define a way to check this at
11509  * compile time, since the #if preprocessor conditions can not use the sizeof
11510  * operator as an argument. */
11511 #endif
11512 
11513 	if (sizeof(pthread_t) > sizeof(unsigned long)) {
11514 		/* This is the problematic case for CRYPTO_set_id_callback:
11515 		 * The OS pthread_t can not be cast to unsigned long. */
11516 		struct mg_workerTLS *tls =
11517 		    (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
11518 		if (tls == NULL) {
11519 			/* SSL called from an unknown thread: Create some thread index.
11520 			 */
11521 			tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
11522 			tls->is_master = -2; /* -2 means "3rd party thread" */
11523 			tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
11524 			pthread_setspecific(sTlsKey, tls);
11525 		}
11526 		return tls->thread_idx;
11527 	} else {
11528 		/* pthread_t may be any data type, so a simple cast to unsigned long
11529 		 * can rise a warning/error, depending on the platform.
11530 		 * Here memcpy is used as an anything-to-anything cast. */
11531 		unsigned long ret = 0;
11532 		pthread_t t = pthread_self();
11533 		memcpy(&ret, &t, sizeof(pthread_t));
11534 		return ret;
11535 	}
11536 
11537 #ifdef __clang__
11538 #pragma clang diagnostic pop
11539 #endif
11540 
11541 #endif
11542 }
11543 
11544 
11545 static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
11546 static const char *ssl_error(void);
11547 
11548 
11549 static int
11550 refresh_trust(struct mg_connection *conn)
11551 {
11552 	static int reload_lock = 0;
11553 	static long int data_check = 0;
11554 	volatile int *p_reload_lock = (volatile int *)&reload_lock;
11555 
11556 	struct stat cert_buf;
11557 	long int t;
11558 	char *pem;
11559 	int should_verify_peer;
11560 
11561 	if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL) {
11562 		/* If peem is NULL and conn->ctx->callbacks.init_ssl is not,
11563 		 * refresh_trust still can not work. */
11564 		return 0;
11565 	}
11566 
11567 	t = data_check;
11568 	if (stat(pem, &cert_buf) != -1) {
11569 		t = (long int)cert_buf.st_mtime;
11570 	}
11571 
11572 	if (data_check != t) {
11573 		data_check = t;
11574 
11575 		should_verify_peer =
11576 		    (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
11577 		    && (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
11578 		        == 0);
11579 
11580 		if (should_verify_peer) {
11581 			char *ca_path = conn->ctx->config[SSL_CA_PATH];
11582 			char *ca_file = conn->ctx->config[SSL_CA_FILE];
11583 			if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
11584 			                                  ca_file,
11585 			                                  ca_path) != 1) {
11586 				mg_cry(fc(conn->ctx),
11587 				       "SSL_CTX_load_verify_locations error: %s "
11588 				       "ssl_verify_peer requires setting "
11589 				       "either ssl_ca_path or ssl_ca_file. Is any of them "
11590 				       "present in "
11591 				       "the .conf file?",
11592 				       ssl_error());
11593 				return 0;
11594 			}
11595 		}
11596 
11597 		if (1 == mg_atomic_inc(p_reload_lock)) {
11598 			if (ssl_use_pem_file(conn->ctx, pem) == 0) {
11599 				return 0;
11600 			}
11601 			*p_reload_lock = 0;
11602 		}
11603 	}
11604 	/* lock while cert is reloading */
11605 	while (*p_reload_lock) {
11606 		sleep(1);
11607 	}
11608 
11609 	return 1;
11610 }
11611 
11612 
11613 static pthread_mutex_t *ssl_mutexes;
11614 
11615 
11616 static int
11617 sslize(struct mg_connection *conn,
11618        SSL_CTX *s,
11619        int (*func)(SSL *),
11620        volatile int *stop_server)
11621 {
11622 	int ret, err;
11623 	int short_trust;
11624 	unsigned i;
11625 
11626 	if (!conn) {
11627 		return 0;
11628 	}
11629 
11630 	short_trust =
11631 	    (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
11632 	    && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
11633 
11634 	if (short_trust) {
11635 		int trust_ret = refresh_trust(conn);
11636 		if (!trust_ret) {
11637 			return trust_ret;
11638 		}
11639 	}
11640 
11641 	conn->ssl = SSL_new(s);
11642 	if (conn->ssl == NULL) {
11643 		return 0;
11644 	}
11645 
11646 	ret = SSL_set_fd(conn->ssl, conn->client.sock);
11647 	if (ret != 1) {
11648 		err = SSL_get_error(conn->ssl, ret);
11649 		(void)err; /* TODO: set some error message */
11650 		SSL_free(conn->ssl);
11651 		conn->ssl = NULL;
11652 		/* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
11653 		 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11654 		ERR_remove_state(0);
11655 		return 0;
11656 	}
11657 
11658 	/* SSL functions may fail and require to be called again:
11659 	 * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
11660 	 * Here "func" could be SSL_connect or SSL_accept. */
11661 	for (i = 16; i <= 1024; i *= 2) {
11662 		ret = func(conn->ssl);
11663 		if (ret != 1) {
11664 			err = SSL_get_error(conn->ssl, ret);
11665 			if ((err == SSL_ERROR_WANT_CONNECT)
11666 			    || (err == SSL_ERROR_WANT_ACCEPT)
11667 			    || (err == SSL_ERROR_WANT_READ)
11668 			    || (err == SSL_ERROR_WANT_WRITE)) {
11669 				/* Need to retry the function call "later".
11670 				 * See https://linux.die.net/man/3/ssl_get_error
11671 				 * This is typical for non-blocking sockets. */
11672 				if (*stop_server) {
11673 					/* Don't wait if the server is going to be stopped. */
11674 					break;
11675 				}
11676 				mg_sleep(i);
11677 
11678 			} else if (err == SSL_ERROR_SYSCALL) {
11679 				/* This is an IO error. Look at errno. */
11680 				err = errno;
11681 				/* TODO: set some error message */
11682 				break;
11683 			} else {
11684 				/* This is an SSL specific error */
11685 				/* TODO: set some error message */
11686 				break;
11687 			}
11688 
11689 		} else {
11690 			/* success */
11691 			break;
11692 		}
11693 	}
11694 
11695 	if (ret != 1) {
11696 		SSL_free(conn->ssl);
11697 		conn->ssl = NULL;
11698 		/* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
11699 		 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11700 		ERR_remove_state(0);
11701 		return 0;
11702 	}
11703 
11704 	return 1;
11705 }
11706 
11707 
11708 /* Return OpenSSL error message (from CRYPTO lib) */
11709 static const char *
11710 ssl_error(void)
11711 {
11712 	unsigned long err;
11713 	err = ERR_get_error();
11714 	return ((err == 0) ? "" : ERR_error_string(err, NULL));
11715 }
11716 
11717 
11718 static int
11719 hexdump2string(void *mem, int memlen, char *buf, int buflen)
11720 {
11721 	int i;
11722 	const char hexdigit[] = "0123456789abcdef";
11723 
11724 	if (memlen <= 0 || buflen <= 0) {
11725 		return 0;
11726 	}
11727 	if (buflen < (3 * memlen)) {
11728 		return 0;
11729 	}
11730 
11731 	for (i = 0; i < memlen; i++) {
11732 		if (i > 0) {
11733 			buf[3 * i - 1] = ' ';
11734 		}
11735 		buf[3 * i] = hexdigit[(((uint8_t *)mem)[i] >> 4) & 0xF];
11736 		buf[3 * i + 1] = hexdigit[((uint8_t *)mem)[i] & 0xF];
11737 	}
11738 	buf[3 * memlen - 1] = 0;
11739 
11740 	return 1;
11741 }
11742 
11743 
11744 static void
11745 ssl_get_client_cert_info(struct mg_connection *conn)
11746 {
11747 	X509 *cert = SSL_get_peer_certificate(conn->ssl);
11748 	if (cert) {
11749 		char str_subject[1024];
11750 		char str_issuer[1024];
11751 		char str_serial[1024];
11752 		char str_finger[1024];
11753 		unsigned char buf[256];
11754 		int len;
11755 		unsigned int ulen;
11756 
11757 		/* Handle to algorithm used for fingerprint */
11758 		const EVP_MD *digest = EVP_get_digestbyname("sha1");
11759 
11760 		/* Get Subject and issuer */
11761 		X509_NAME *subj = X509_get_subject_name(cert);
11762 		X509_NAME *iss = X509_get_issuer_name(cert);
11763 
11764 		/* Get serial number */
11765 		ASN1_INTEGER *serial = X509_get_serialNumber(cert);
11766 
11767 		/* Translate subject and issuer to a string */
11768 		(void)X509_NAME_oneline(subj, str_subject, (int)sizeof(str_subject));
11769 		(void)X509_NAME_oneline(iss, str_issuer, (int)sizeof(str_issuer));
11770 
11771 		/* Translate serial number to a hex string */
11772 		len = i2c_ASN1_INTEGER(serial, NULL);
11773 		if ((len > 0) && ((unsigned)len < (unsigned)sizeof(buf))) {
11774 			unsigned char *pbuf = buf;
11775 			int len2 = i2c_ASN1_INTEGER(serial, &pbuf);
11776 			if (!hexdump2string(
11777 			        buf, len2, str_serial, (int)sizeof(str_serial))) {
11778 				*str_serial = 0;
11779 			}
11780 		} else {
11781 			*str_serial = 0;
11782 		}
11783 
11784 		/* Calculate SHA1 fingerprint and store as a hex string */
11785 		ulen = 0;
11786 		ASN1_digest((int (*)())i2d_X509, digest, (char *)cert, buf, &ulen);
11787 		if (!hexdump2string(
11788 		        buf, (int)ulen, str_finger, (int)sizeof(str_finger))) {
11789 			*str_finger = 0;
11790 		}
11791 
11792 		conn->request_info.client_cert =
11793 		    (struct client_cert *)mg_malloc(sizeof(struct client_cert));
11794 		if (conn->request_info.client_cert) {
11795 			conn->request_info.client_cert->subject = mg_strdup(str_subject);
11796 			conn->request_info.client_cert->issuer = mg_strdup(str_issuer);
11797 			conn->request_info.client_cert->serial = mg_strdup(str_serial);
11798 			conn->request_info.client_cert->finger = mg_strdup(str_finger);
11799 		} else {
11800 			/* TODO: write some OOM message */
11801 		}
11802 
11803 		X509_free(cert);
11804 	}
11805 }
11806 
11807 
11808 static void
11809 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
11810 {
11811 	(void)line;
11812 	(void)file;
11813 
11814 	if (mode & 1) {
11815 		/* 1 is CRYPTO_LOCK */
11816 		(void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
11817 	} else {
11818 		(void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
11819 	}
11820 }
11821 
11822 
11823 #if !defined(NO_SSL_DL)
11824 static void *
11825 load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
11826 {
11827 	union {
11828 		void *p;
11829 		void (*fp)(void);
11830 	} u;
11831 	void *dll_handle;
11832 	struct ssl_func *fp;
11833 
11834 	if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
11835 		mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
11836 		return NULL;
11837 	}
11838 
11839 	for (fp = sw; fp->name != NULL; fp++) {
11840 #ifdef _WIN32
11841 		/* GetProcAddress() returns pointer to function */
11842 		u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
11843 #else
11844 		/* dlsym() on UNIX returns void *. ISO C forbids casts of data
11845 		 * pointers to function pointers. We need to use a union to make a
11846 		 * cast. */
11847 		u.p = dlsym(dll_handle, fp->name);
11848 #endif /* _WIN32 */
11849 		if (u.fp == NULL) {
11850 			mg_cry(fc(ctx),
11851 			       "%s: %s: cannot find %s",
11852 			       __func__,
11853 			       dll_name,
11854 			       fp->name);
11855 			dlclose(dll_handle);
11856 			return NULL;
11857 		} else {
11858 			fp->ptr = u.fp;
11859 		}
11860 	}
11861 
11862 	return dll_handle;
11863 }
11864 
11865 
11866 static void *ssllib_dll_handle;    /* Store the ssl library handle. */
11867 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
11868 
11869 #endif /* NO_SSL_DL */
11870 
11871 
11872 #if defined(SSL_ALREADY_INITIALIZED)
11873 static int cryptolib_users = 1; /* Reference counter for crypto library. */
11874 #else
11875 static int cryptolib_users = 0; /* Reference counter for crypto library. */
11876 #endif
11877 
11878 
11879 static int
11880 initialize_ssl(struct mg_context *ctx)
11881 {
11882 	int i;
11883 	size_t size;
11884 
11885 #if !defined(NO_SSL_DL)
11886 	if (!cryptolib_dll_handle) {
11887 		cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
11888 		if (!cryptolib_dll_handle) {
11889 			return 0;
11890 		}
11891 	}
11892 #endif /* NO_SSL_DL */
11893 
11894 	if (mg_atomic_inc(&cryptolib_users) > 1) {
11895 		return 1;
11896 	}
11897 
11898 	/* Initialize locking callbacks, needed for thread safety.
11899 	 * http://www.openssl.org/support/faq.html#PROG1
11900 	 */
11901 	i = CRYPTO_num_locks();
11902 	if (i < 0) {
11903 		i = 0;
11904 	}
11905 	size = sizeof(pthread_mutex_t) * ((size_t)(i));
11906 	if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
11907 		mg_cry(fc(ctx),
11908 		       "%s: cannot allocate mutexes: %s",
11909 		       __func__,
11910 		       ssl_error());
11911 		return 0;
11912 	}
11913 
11914 	for (i = 0; i < CRYPTO_num_locks(); i++) {
11915 		pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
11916 	}
11917 
11918 	CRYPTO_set_locking_callback(&ssl_locking_callback);
11919 	CRYPTO_set_id_callback(&ssl_id_callback);
11920 
11921 	return 1;
11922 }
11923 
11924 
11925 static int
11926 ssl_use_pem_file(struct mg_context *ctx, const char *pem)
11927 {
11928 	if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
11929 		mg_cry(fc(ctx),
11930 		       "%s: cannot open certificate file %s: %s",
11931 		       __func__,
11932 		       pem,
11933 		       ssl_error());
11934 		return 0;
11935 	}
11936 
11937 	/* could use SSL_CTX_set_default_passwd_cb_userdata */
11938 	if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
11939 		mg_cry(fc(ctx),
11940 		       "%s: cannot open private key file %s: %s",
11941 		       __func__,
11942 		       pem,
11943 		       ssl_error());
11944 		return 0;
11945 	}
11946 
11947 	if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
11948 		mg_cry(fc(ctx),
11949 		       "%s: certificate and private key do not match: %s",
11950 		       __func__,
11951 		       pem);
11952 		return 0;
11953 	}
11954 
11955 	if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
11956 		mg_cry(fc(ctx),
11957 		       "%s: cannot use certificate chain file %s: %s",
11958 		       __func__,
11959 		       pem,
11960 		       ssl_error());
11961 		return 0;
11962 	}
11963 	return 1;
11964 }
11965 
11966 
11967 static long
11968 ssl_get_protocol(int version_id)
11969 {
11970 	long ret = SSL_OP_ALL;
11971 	if (version_id > 0)
11972 		ret |= SSL_OP_NO_SSLv2;
11973 	if (version_id > 1)
11974 		ret |= SSL_OP_NO_SSLv3;
11975 	if (version_id > 2)
11976 		ret |= SSL_OP_NO_TLSv1;
11977 	if (version_id > 3)
11978 		ret |= SSL_OP_NO_TLSv1_1;
11979 	return ret;
11980 }
11981 
11982 
11983 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
11984 static int
11985 set_ssl_option(struct mg_context *ctx)
11986 {
11987 	const char *pem;
11988 	int callback_ret;
11989 	int should_verify_peer;
11990 	const char *ca_path;
11991 	const char *ca_file;
11992 	int use_default_verify_paths;
11993 	int verify_depth;
11994 	time_t now_rt = time(NULL);
11995 	struct timespec now_mt;
11996 	md5_byte_t ssl_context_id[16];
11997 	md5_state_t md5state;
11998 	int protocol_ver;
11999 
12000 	/* If PEM file is not specified and the init_ssl callback
12001 	 * is not specified, skip SSL initialization. */
12002 	if (!ctx) {
12003 		return 0;
12004 	}
12005 	if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
12006 	    && ctx->callbacks.init_ssl == NULL) {
12007 		return 1;
12008 	}
12009 
12010 	if (!initialize_ssl(ctx)) {
12011 		return 0;
12012 	}
12013 
12014 #if !defined(NO_SSL_DL)
12015 	if (!ssllib_dll_handle) {
12016 		ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
12017 		if (!ssllib_dll_handle) {
12018 			return 0;
12019 		}
12020 	}
12021 #endif /* NO_SSL_DL */
12022 
12023 	/* Initialize SSL library */
12024 	SSL_library_init();
12025 	SSL_load_error_strings();
12026 
12027 	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
12028 		mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
12029 		return 0;
12030 	}
12031 
12032 	SSL_CTX_clear_options(ctx->ssl_ctx,
12033 	                      SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1
12034 	                          | SSL_OP_NO_TLSv1_1);
12035 	protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
12036 	SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
12037 	SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
12038 	SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
12039 	SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
12040 
12041 	/* If a callback has been specified, call it. */
12042 	callback_ret =
12043 	    (ctx->callbacks.init_ssl == NULL)
12044 	        ? 0
12045 	        : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
12046 
12047 	/* If callback returns 0, civetweb sets up the SSL certificate.
12048 	 * If it returns 1, civetweb assumes the calback already did this.
12049 	 * If it returns -1, initializing ssl fails. */
12050 	if (callback_ret < 0) {
12051 		mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
12052 		return 0;
12053 	}
12054 	if (callback_ret > 0) {
12055 		if (pem != NULL) {
12056 			(void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
12057 		}
12058 		return 1;
12059 	}
12060 
12061 	/* Use some UID as session context ID. */
12062 	md5_init(&md5state);
12063 	md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
12064 	clock_gettime(CLOCK_MONOTONIC, &now_mt);
12065 	md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
12066 	md5_append(&md5state,
12067 	           (const md5_byte_t *)ctx->config[LISTENING_PORTS],
12068 	           strlen(ctx->config[LISTENING_PORTS]));
12069 	md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
12070 	md5_finish(&md5state, ssl_context_id);
12071 
12072 	SSL_CTX_set_session_id_context(ctx->ssl_ctx,
12073 	                               (const unsigned char *)&ssl_context_id,
12074 	                               sizeof(ssl_context_id));
12075 
12076 	if (pem != NULL) {
12077 		if (!ssl_use_pem_file(ctx, pem)) {
12078 			return 0;
12079 		}
12080 	}
12081 
12082 	should_verify_peer =
12083 	    (ctx->config[SSL_DO_VERIFY_PEER] != NULL)
12084 	    && (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
12085 
12086 	use_default_verify_paths =
12087 	    (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
12088 	    && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
12089 
12090 	if (should_verify_peer) {
12091 		ca_path = ctx->config[SSL_CA_PATH];
12092 		ca_file = ctx->config[SSL_CA_FILE];
12093 		if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
12094 		    != 1) {
12095 			mg_cry(fc(ctx),
12096 			       "SSL_CTX_load_verify_locations error: %s "
12097 			       "ssl_verify_peer requires setting "
12098 			       "either ssl_ca_path or ssl_ca_file. Is any of them "
12099 			       "present in "
12100 			       "the .conf file?",
12101 			       ssl_error());
12102 			return 0;
12103 		}
12104 
12105 		SSL_CTX_set_verify(ctx->ssl_ctx,
12106 		                   SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
12107 		                   NULL);
12108 
12109 		if (use_default_verify_paths
12110 		    && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
12111 			mg_cry(fc(ctx),
12112 			       "SSL_CTX_set_default_verify_paths error: %s",
12113 			       ssl_error());
12114 			return 0;
12115 		}
12116 
12117 		if (ctx->config[SSL_VERIFY_DEPTH]) {
12118 			verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
12119 			SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
12120 		}
12121 	}
12122 
12123 	if (ctx->config[SSL_CIPHER_LIST] != NULL) {
12124 		if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
12125 		    != 1) {
12126 			mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
12127 		}
12128 	}
12129 
12130 	return 1;
12131 }
12132 
12133 
12134 static void
12135 uninitialize_ssl(struct mg_context *ctx)
12136 {
12137 	int i;
12138 	(void)ctx;
12139 
12140 	if (mg_atomic_dec(&cryptolib_users) == 0) {
12141 
12142 		/* Shutdown according to
12143 		 * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
12144 		 * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
12145 		 */
12146 		CRYPTO_set_locking_callback(NULL);
12147 		CRYPTO_set_id_callback(NULL);
12148 		ENGINE_cleanup();
12149 		CONF_modules_unload(1);
12150 		ERR_free_strings();
12151 		EVP_cleanup();
12152 		CRYPTO_cleanup_all_ex_data();
12153 		ERR_remove_state(0);
12154 
12155 		for (i = 0; i < CRYPTO_num_locks(); i++) {
12156 			pthread_mutex_destroy(&ssl_mutexes[i]);
12157 		}
12158 		mg_free(ssl_mutexes);
12159 		ssl_mutexes = NULL;
12160 	}
12161 }
12162 #endif /* !NO_SSL */
12163 
12164 
12165 static int
12166 set_gpass_option(struct mg_context *ctx)
12167 {
12168 	if (ctx) {
12169 		struct mg_file file = STRUCT_FILE_INITIALIZER;
12170 		const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
12171 		if (path != NULL && !mg_stat(fc(ctx), path, &file.stat)) {
12172 			mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
12173 			return 0;
12174 		}
12175 		return 1;
12176 	}
12177 	return 0;
12178 }
12179 
12180 
12181 static int
12182 set_acl_option(struct mg_context *ctx)
12183 {
12184 	return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
12185 }
12186 
12187 
12188 static void
12189 reset_per_request_attributes(struct mg_connection *conn)
12190 {
12191 	if (!conn) {
12192 		return;
12193 	}
12194 	conn->path_info = NULL;
12195 	conn->num_bytes_sent = conn->consumed_content = 0;
12196 	conn->status_code = -1;
12197 	conn->is_chunked = 0;
12198 	conn->must_close = conn->request_len = conn->throttle = 0;
12199 	conn->request_info.content_length = -1;
12200 	conn->request_info.remote_user = NULL;
12201 	conn->request_info.request_method = NULL;
12202 	conn->request_info.request_uri = NULL;
12203 	conn->request_info.local_uri = NULL;
12204 	conn->request_info.uri = NULL; /* TODO: cleanup uri,
12205 	                                * local_uri and request_uri */
12206 	conn->request_info.http_version = NULL;
12207 	conn->request_info.num_headers = 0;
12208 	conn->data_len = 0;
12209 	conn->chunk_remainder = 0;
12210 }
12211 
12212 
12213 #if 0
12214 /* Note: set_sock_timeout is not required for non-blocking sockets.
12215  * Leave this function here (commented out) for reference until
12216  * CivetWeb 1.9 is tested, and the tests confirme this function is
12217  * no longer required.
12218 */
12219 static int
12220 set_sock_timeout(SOCKET sock, int milliseconds)
12221 {
12222 	int r0 = 0, r1, r2;
12223 
12224 #ifdef _WIN32
12225 	/* Windows specific */
12226 
12227 	DWORD tv = (DWORD)milliseconds;
12228 
12229 #else
12230 	/* Linux, ... (not Windows) */
12231 
12232 	struct timeval tv;
12233 
12234 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
12235  * max. time waiting for the acknowledged of TCP data before the connection
12236  * will be forcefully closed and ETIMEDOUT is returned to the application.
12237  * If this option is not set, the default timeout of 20-30 minutes is used.
12238 */
12239 /* #define TCP_USER_TIMEOUT (18) */
12240 
12241 #if defined(TCP_USER_TIMEOUT)
12242 	unsigned int uto = (unsigned int)milliseconds;
12243 	r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
12244 #endif
12245 
12246 	memset(&tv, 0, sizeof(tv));
12247 	tv.tv_sec = milliseconds / 1000;
12248 	tv.tv_usec = (milliseconds * 1000) % 1000000;
12249 
12250 #endif /* _WIN32 */
12251 
12252 	r1 = setsockopt(
12253 	    sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
12254 	r2 = setsockopt(
12255 	    sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
12256 
12257 	return r0 || r1 || r2;
12258 }
12259 #endif
12260 
12261 
12262 static int
12263 set_tcp_nodelay(SOCKET sock, int nodelay_on)
12264 {
12265 	if (setsockopt(sock,
12266 	               IPPROTO_TCP,
12267 	               TCP_NODELAY,
12268 	               (SOCK_OPT_TYPE)&nodelay_on,
12269 	               sizeof(nodelay_on)) != 0) {
12270 		/* Error */
12271 		return 1;
12272 	}
12273 	/* OK */
12274 	return 0;
12275 }
12276 
12277 
12278 static void
12279 close_socket_gracefully(struct mg_connection *conn)
12280 {
12281 #if defined(_WIN32)
12282 	char buf[MG_BUF_LEN];
12283 	int n;
12284 #endif
12285 	struct linger linger;
12286 	int error_code = 0;
12287 	socklen_t opt_len = sizeof(error_code);
12288 
12289 	if (!conn) {
12290 		return;
12291 	}
12292 
12293 	/* http://msdn.microsoft.com/en-us/library/ms739165(v=vs.85).aspx:
12294 	 * "Note that enabling a nonzero timeout on a nonblocking socket
12295 	 * is not recommended.", so set it to blocking now */
12296 	set_blocking_mode(conn->client.sock, 1);
12297 
12298 	/* Send FIN to the client */
12299 	shutdown(conn->client.sock, SHUTDOWN_WR);
12300 
12301 
12302 #if defined(_WIN32)
12303 	/* Read and discard pending incoming data. If we do not do that and
12304 	 * close
12305 	 * the socket, the data in the send buffer may be discarded. This
12306 	 * behaviour is seen on Windows, when client keeps sending data
12307 	 * when server decides to close the connection; then when client
12308 	 * does recv() it gets no data back. */
12309 	do {
12310 		n = pull(NULL, conn, buf, sizeof(buf), /* Timeout in s: */ 1.0);
12311 	} while (n > 0);
12312 #endif
12313 
12314 	/* Set linger option to avoid socket hanging out after close. This
12315 	 * prevent ephemeral port exhaust problem under high QPS. */
12316 	linger.l_onoff = 1;
12317 	linger.l_linger = 1;
12318 
12319 	if (getsockopt(conn->client.sock,
12320 	               SOL_SOCKET,
12321 	               SO_ERROR,
12322 	               (char *)&error_code,
12323 	               &opt_len) != 0) {
12324 		/* Cannot determine if socket is already closed. This should
12325 		 * not occur and never did in a test. Log an error message
12326 		 * and continue. */
12327 		mg_cry(conn,
12328 		       "%s: getsockopt(SOL_SOCKET SO_ERROR) failed: %s",
12329 		       __func__,
12330 		       strerror(ERRNO));
12331 	} else if (error_code == ECONNRESET) {
12332 		/* Socket already closed by client/peer, close socket without linger */
12333 	} else {
12334 
12335 
12336 		/* Set linger timeout */
12337 		if (setsockopt(conn->client.sock,
12338 		               SOL_SOCKET,
12339 		               SO_LINGER,
12340 		               (char *)&linger,
12341 		               sizeof(linger)) != 0) {
12342 			mg_cry(conn,
12343 			       "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
12344 			       __func__,
12345 			       strerror(ERRNO));
12346 		}
12347 	}
12348 
12349 	/* Now we know that our FIN is ACK-ed, safe to close */
12350 	closesocket(conn->client.sock);
12351 	conn->client.sock = INVALID_SOCKET;
12352 }
12353 
12354 
12355 static void
12356 close_connection(struct mg_connection *conn)
12357 {
12358 	if (!conn || !conn->ctx) {
12359 		return;
12360 	}
12361 
12362 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
12363 	if (conn->lua_websocket_state) {
12364 		lua_websocket_close(conn, conn->lua_websocket_state);
12365 		conn->lua_websocket_state = NULL;
12366 	}
12367 #endif
12368 
12369 	/* call the connection_close callback if assigned */
12370 	if ((conn->ctx->callbacks.connection_close != NULL)
12371 	    && (conn->ctx->context_type == 1)) {
12372 		conn->ctx->callbacks.connection_close(conn);
12373 	}
12374 
12375 	mg_lock_connection(conn);
12376 
12377 	conn->must_close = 1;
12378 
12379 #ifndef NO_SSL
12380 	if (conn->ssl != NULL) {
12381 		/* Run SSL_shutdown twice to ensure completly close SSL connection
12382 		 */
12383 		SSL_shutdown(conn->ssl);
12384 		SSL_free(conn->ssl);
12385 		/* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
12386 		 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
12387 		ERR_remove_state(0);
12388 		conn->ssl = NULL;
12389 	}
12390 #endif
12391 	if (conn->client.sock != INVALID_SOCKET) {
12392 		close_socket_gracefully(conn);
12393 		conn->client.sock = INVALID_SOCKET;
12394 	}
12395 
12396 	mg_unlock_connection(conn);
12397 }
12398 
12399 
12400 void
12401 mg_close_connection(struct mg_connection *conn)
12402 {
12403 	struct mg_context *client_ctx = NULL;
12404 
12405 	if (conn == NULL) {
12406 		return;
12407 	}
12408 
12409 #if defined(USE_WEBSOCKET)
12410 	if (conn->ctx->context_type == 2) {
12411 		unsigned int i;
12412 
12413 		/* ws/wss client */
12414 		client_ctx = conn->ctx;
12415 
12416 		/* client context: loops must end */
12417 		conn->ctx->stop_flag = 1;
12418 
12419 		/* We need to get the client thread out of the select/recv call here. */
12420 		/* Since we use a sleep quantum of some seconds to check for recv
12421 		 * timeouts, we will just wait a few seconds in mg_join_thread. */
12422 
12423 		/* join worker thread */
12424 		for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
12425 			if (client_ctx->workerthreadids[i] != 0) {
12426 				mg_join_thread(client_ctx->workerthreadids[i]);
12427 			}
12428 		}
12429 	}
12430 #else
12431 	(void)client_ctx;
12432 #endif
12433 
12434 	close_connection(conn);
12435 
12436 #ifndef NO_SSL
12437 	if (conn->client_ssl_ctx != NULL) {
12438 		SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
12439 	}
12440 #endif
12441 
12442 	if (client_ctx != NULL) {
12443 		/* free context */
12444 		mg_free(client_ctx->workerthreadids);
12445 		mg_free(client_ctx);
12446 		(void)pthread_mutex_destroy(&conn->mutex);
12447 		mg_free(conn);
12448 	}
12449 }
12450 
12451 
12452 static struct mg_connection *
12453 mg_connect_client_impl(const struct mg_client_options *client_options,
12454                        int use_ssl,
12455                        char *ebuf,
12456                        size_t ebuf_len)
12457 {
12458 	static struct mg_context fake_ctx;
12459 	struct mg_connection *conn = NULL;
12460 	SOCKET sock;
12461 	union usa sa;
12462 
12463 	if (!connect_socket(&fake_ctx,
12464 	                    client_options->host,
12465 	                    client_options->port,
12466 	                    use_ssl,
12467 	                    ebuf,
12468 	                    ebuf_len,
12469 	                    &sock,
12470 	                    &sa)) {
12471 		;
12472 	} else if ((conn = (struct mg_connection *)
12473 	                mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
12474 		mg_snprintf(NULL,
12475 		            NULL, /* No truncation check for ebuf */
12476 		            ebuf,
12477 		            ebuf_len,
12478 		            "calloc(): %s",
12479 		            strerror(ERRNO));
12480 		closesocket(sock);
12481 #ifndef NO_SSL
12482 	} else if (use_ssl
12483 	           && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
12484 	                  == NULL) {
12485 		mg_snprintf(NULL,
12486 		            NULL, /* No truncation check for ebuf */
12487 		            ebuf,
12488 		            ebuf_len,
12489 		            "SSL_CTX_new error");
12490 		closesocket(sock);
12491 		mg_free(conn);
12492 		conn = NULL;
12493 #endif /* NO_SSL */
12494 
12495 	} else {
12496 
12497 #ifdef USE_IPV6
12498 		socklen_t len = (sa.sa.sa_family == AF_INET)
12499 		                    ? sizeof(conn->client.rsa.sin)
12500 		                    : sizeof(conn->client.rsa.sin6);
12501 		struct sockaddr *psa =
12502 		    (sa.sa.sa_family == AF_INET)
12503 		        ? (struct sockaddr *)&(conn->client.rsa.sin)
12504 		        : (struct sockaddr *)&(conn->client.rsa.sin6);
12505 #else
12506 		socklen_t len = sizeof(conn->client.rsa.sin);
12507 		struct sockaddr *psa = (struct sockaddr *)&(conn->client.rsa.sin);
12508 #endif
12509 
12510 		conn->buf_size = MAX_REQUEST_SIZE;
12511 		conn->buf = (char *)(conn + 1);
12512 		conn->ctx = &fake_ctx;
12513 		conn->client.sock = sock;
12514 		conn->client.lsa = sa;
12515 
12516 		if (getsockname(sock, psa, &len) != 0) {
12517 			mg_cry(conn,
12518 			       "%s: getsockname() failed: %s",
12519 			       __func__,
12520 			       strerror(ERRNO));
12521 		}
12522 
12523 		conn->client.is_ssl = use_ssl ? 1 : 0;
12524 		(void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
12525 
12526 #ifndef NO_SSL
12527 		if (use_ssl) {
12528 			fake_ctx.ssl_ctx = conn->client_ssl_ctx;
12529 
12530 			/* TODO: Check ssl_verify_peer and ssl_ca_path here.
12531 			 * SSL_CTX_set_verify call is needed to switch off server
12532 			 * certificate checking, which is off by default in OpenSSL and
12533 			 * on in yaSSL. */
12534 			/* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
12535 			 * SSL_VERIFY_PEER, verify_ssl_server); */
12536 
12537 			if (client_options->client_cert) {
12538 				if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
12539 					mg_snprintf(NULL,
12540 					            NULL, /* No truncation check for ebuf */
12541 					            ebuf,
12542 					            ebuf_len,
12543 					            "Can not use SSL client certificate");
12544 					SSL_CTX_free(conn->client_ssl_ctx);
12545 					closesocket(sock);
12546 					mg_free(conn);
12547 					conn = NULL;
12548 				}
12549 			}
12550 
12551 			if (client_options->server_cert) {
12552 				SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
12553 				                              client_options->server_cert,
12554 				                              NULL);
12555 				SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
12556 			} else {
12557 				SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
12558 			}
12559 
12560 			if (!sslize(conn,
12561 			            conn->client_ssl_ctx,
12562 			            SSL_connect,
12563 			            &(conn->ctx->stop_flag))) {
12564 				mg_snprintf(NULL,
12565 				            NULL, /* No truncation check for ebuf */
12566 				            ebuf,
12567 				            ebuf_len,
12568 				            "SSL connection error");
12569 				SSL_CTX_free(conn->client_ssl_ctx);
12570 				closesocket(sock);
12571 				mg_free(conn);
12572 				conn = NULL;
12573 			}
12574 		}
12575 #endif
12576 	}
12577 
12578 	if (conn) {
12579 		set_blocking_mode(sock, 0);
12580 	}
12581 
12582 	return conn;
12583 }
12584 
12585 
12586 CIVETWEB_API struct mg_connection *
12587 mg_connect_client_secure(const struct mg_client_options *client_options,
12588                          char *error_buffer,
12589                          size_t error_buffer_size)
12590 {
12591 	return mg_connect_client_impl(client_options,
12592 	                              1,
12593 	                              error_buffer,
12594 	                              error_buffer_size);
12595 }
12596 
12597 
12598 struct mg_connection *
12599 mg_connect_client(const char *host,
12600                   int port,
12601                   int use_ssl,
12602                   char *error_buffer,
12603                   size_t error_buffer_size)
12604 {
12605 	struct mg_client_options opts;
12606 	memset(&opts, 0, sizeof(opts));
12607 	opts.host = host;
12608 	opts.port = port;
12609 	return mg_connect_client_impl(&opts,
12610 	                              use_ssl,
12611 	                              error_buffer,
12612 	                              error_buffer_size);
12613 }
12614 
12615 
12616 static const struct {
12617 	const char *proto;
12618 	size_t proto_len;
12619 	unsigned default_port;
12620 } abs_uri_protocols[] = {{"http://", 7, 80},
12621                          {"https://", 8, 443},
12622                          {"ws://", 5, 80},
12623                          {"wss://", 6, 443},
12624                          {NULL, 0, 0}};
12625 
12626 
12627 /* Check if the uri is valid.
12628  * return 0 for invalid uri,
12629  * return 1 for *,
12630  * return 2 for relative uri,
12631  * return 3 for absolute uri without port,
12632  * return 4 for absolute uri with port */
12633 static int
12634 get_uri_type(const char *uri)
12635 {
12636 	int i;
12637 	char *hostend, *portbegin, *portend;
12638 	unsigned long port;
12639 
12640 	/* According to the HTTP standard
12641 	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
12642 	 * URI can be an asterisk (*) or should start with slash (relative uri),
12643 	 * or it should start with the protocol (absolute uri). */
12644 	if (uri[0] == '*' && uri[1] == '\0') {
12645 		/* asterisk */
12646 		return 1;
12647 	}
12648 
12649 	/* Valid URIs according to RFC 3986
12650 	 * (https://www.ietf.org/rfc/rfc3986.txt)
12651 	 * must only contain reserved characters :/?#[]@!$&'()*+,;=
12652 	 * and unreserved characters A-Z a-z 0-9 and -._~
12653 	 * and % encoded symbols.
12654 	 */
12655 	for (i = 0; uri[i] != 0; i++) {
12656 		if (uri[i] < 33) {
12657 			/* control characters and spaces are invalid */
12658 			return 0;
12659 		}
12660 		if (uri[i] > 126) {
12661 			/* non-ascii characters must be % encoded */
12662 			return 0;
12663 		} else {
12664 			switch (uri[i]) {
12665 			case '"':  /* 34 */
12666 			case '<':  /* 60 */
12667 			case '>':  /* 62 */
12668 			case '\\': /* 92 */
12669 			case '^':  /* 94 */
12670 			case '`':  /* 96 */
12671 			case '{':  /* 123 */
12672 			case '|':  /* 124 */
12673 			case '}':  /* 125 */
12674 				return 0;
12675 			default:
12676 				/* character is ok */
12677 				break;
12678 			}
12679 		}
12680 	}
12681 
12682 	/* A relative uri starts with a / character */
12683 	if (uri[0] == '/') {
12684 		/* relative uri */
12685 		return 2;
12686 	}
12687 
12688 	/* It could be an absolute uri: */
12689 	/* This function only checks if the uri is valid, not if it is
12690 	 * addressing the current server. So civetweb can also be used
12691 	 * as a proxy server. */
12692 	for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
12693 		if (mg_strncasecmp(uri,
12694 		                   abs_uri_protocols[i].proto,
12695 		                   abs_uri_protocols[i].proto_len) == 0) {
12696 
12697 			hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
12698 			if (!hostend) {
12699 				return 0;
12700 			}
12701 			portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
12702 			if (!portbegin) {
12703 				return 3;
12704 			}
12705 
12706 			port = strtoul(portbegin + 1, &portend, 10);
12707 			if ((portend != hostend) || !port || !is_valid_port(port)) {
12708 				return 0;
12709 			}
12710 
12711 			return 4;
12712 		}
12713 	}
12714 
12715 	return 0;
12716 }
12717 
12718 
12719 /* Return NULL or the relative uri at the current server */
12720 static const char *
12721 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
12722 {
12723 	const char *server_domain;
12724 	size_t server_domain_len;
12725 	size_t request_domain_len = 0;
12726 	unsigned long port = 0;
12727 	int i;
12728 	const char *hostbegin = NULL;
12729 	const char *hostend = NULL;
12730 	const char *portbegin;
12731 	char *portend;
12732 
12733 	/* DNS is case insensitive, so use case insensitive string compare here
12734 	 */
12735 	server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
12736 	if (!server_domain) {
12737 		return 0;
12738 	}
12739 	server_domain_len = strlen(server_domain);
12740 	if (!server_domain_len) {
12741 		return 0;
12742 	}
12743 
12744 	for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
12745 		if (mg_strncasecmp(uri,
12746 		                   abs_uri_protocols[i].proto,
12747 		                   abs_uri_protocols[i].proto_len) == 0) {
12748 
12749 			hostbegin = uri + abs_uri_protocols[i].proto_len;
12750 			hostend = strchr(hostbegin, '/');
12751 			if (!hostend) {
12752 				return 0;
12753 			}
12754 			portbegin = strchr(hostbegin, ':');
12755 			if ((!portbegin) || (portbegin > hostend)) {
12756 				port = abs_uri_protocols[i].default_port;
12757 				request_domain_len = (size_t)(hostend - hostbegin);
12758 			} else {
12759 				port = strtoul(portbegin + 1, &portend, 10);
12760 				if ((portend != hostend) || !port || !is_valid_port(port)) {
12761 					return 0;
12762 				}
12763 				request_domain_len = (size_t)(portbegin - hostbegin);
12764 			}
12765 			/* protocol found, port set */
12766 			break;
12767 		}
12768 	}
12769 
12770 	if (!port) {
12771 		/* port remains 0 if the protocol is not found */
12772 		return 0;
12773 	}
12774 
12775 /* Check if the request is directed to a different server. */
12776 /* First check if the port is the same (IPv4 and IPv6). */
12777 #if defined(USE_IPV6)
12778 	if (conn->client.lsa.sa.sa_family == AF_INET6) {
12779 		if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
12780 			/* Request is directed to a different port */
12781 			return 0;
12782 		}
12783 	} else
12784 #endif
12785 	{
12786 		if (ntohs(conn->client.lsa.sin.sin_port) != port) {
12787 			/* Request is directed to a different port */
12788 			return 0;
12789 		}
12790 	}
12791 
12792 	/* Finally check if the server corresponds to the authentication
12793 	 * domain of the server (the server domain).
12794 	 * Allow full matches (like http://mydomain.com/path/file.ext), and
12795 	 * allow subdomain matches (like http://www.mydomain.com/path/file.ext),
12796 	 * but do not allow substrings (like http://notmydomain.com/path/file.ext
12797 	 * or http://mydomain.com.fake/path/file.ext).
12798 	 */
12799 	if ((request_domain_len == server_domain_len)
12800 	    && (!memcmp(server_domain, hostbegin, server_domain_len))) {
12801 		/* Request is directed to this server - full name match. */
12802 	} else {
12803 		if (request_domain_len < (server_domain_len + 2)) {
12804 			/* Request is directed to another server: The server name is longer
12805 			 * than
12806 			 * the request name. Drop this case here to avoid overflows in the
12807 			 * following checks. */
12808 			return 0;
12809 		}
12810 		if (hostbegin[request_domain_len - server_domain_len - 1] != '.') {
12811 			/* Request is directed to another server: It could be a substring
12812 			 * like notmyserver.com */
12813 			return 0;
12814 		}
12815 		if (0 != memcmp(server_domain,
12816 		                hostbegin + request_domain_len - server_domain_len,
12817 		                server_domain_len)) {
12818 			/* Request is directed to another server:
12819 			 * The server name is different. */
12820 			return 0;
12821 		}
12822 	}
12823 
12824 	return hostend;
12825 }
12826 
12827 
12828 static int
12829 getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
12830 {
12831 	const char *cl;
12832 
12833 	if (ebuf_len > 0) {
12834 		ebuf[0] = '\0';
12835 	}
12836 	*err = 0;
12837 
12838 	reset_per_request_attributes(conn);
12839 
12840 	if (!conn) {
12841 		mg_snprintf(conn,
12842 		            NULL, /* No truncation check for ebuf */
12843 		            ebuf,
12844 		            ebuf_len,
12845 		            "%s",
12846 		            "Internal error");
12847 		*err = 500;
12848 		return 0;
12849 	}
12850 	/* Set the time the request was received. This value should be used for
12851 	 * timeouts. */
12852 	clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
12853 
12854 	conn->request_len =
12855 	    read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
12856 	/* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
12857 	 */
12858 	if (conn->request_len >= 0 && conn->data_len < conn->request_len) {
12859 		mg_snprintf(conn,
12860 		            NULL, /* No truncation check for ebuf */
12861 		            ebuf,
12862 		            ebuf_len,
12863 		            "%s",
12864 		            "Invalid request size");
12865 		*err = 500;
12866 		return 0;
12867 	}
12868 
12869 	if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
12870 		mg_snprintf(conn,
12871 		            NULL, /* No truncation check for ebuf */
12872 		            ebuf,
12873 		            ebuf_len,
12874 		            "%s",
12875 		            "Request Too Large");
12876 		*err = 413;
12877 		return 0;
12878 	} else if (conn->request_len <= 0) {
12879 		if (conn->data_len > 0) {
12880 			mg_snprintf(conn,
12881 			            NULL, /* No truncation check for ebuf */
12882 			            ebuf,
12883 			            ebuf_len,
12884 			            "%s",
12885 			            "Client sent malformed request");
12886 			*err = 400;
12887 		} else {
12888 			/* Server did not recv anything -> just close the connection */
12889 			conn->must_close = 1;
12890 			mg_snprintf(conn,
12891 			            NULL, /* No truncation check for ebuf */
12892 			            ebuf,
12893 			            ebuf_len,
12894 			            "%s",
12895 			            "Client did not send a request");
12896 			*err = 0;
12897 		}
12898 		return 0;
12899 	} else if (parse_http_message(conn->buf,
12900 	                              conn->buf_size,
12901 	                              &conn->request_info) <= 0) {
12902 		mg_snprintf(conn,
12903 		            NULL, /* No truncation check for ebuf */
12904 		            ebuf,
12905 		            ebuf_len,
12906 		            "%s",
12907 		            "Bad Request");
12908 		*err = 400;
12909 		return 0;
12910 	} else {
12911 		/* Message is a valid request or response */
12912 		if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
12913 			/* Request/response has content length set */
12914 			char *endptr = NULL;
12915 			conn->content_len = strtoll(cl, &endptr, 10);
12916 			if (endptr == cl) {
12917 				mg_snprintf(conn,
12918 				            NULL, /* No truncation check for ebuf */
12919 				            ebuf,
12920 				            ebuf_len,
12921 				            "%s",
12922 				            "Bad Request");
12923 				*err = 411;
12924 				return 0;
12925 			}
12926 			/* Publish the content length back to the request info. */
12927 			conn->request_info.content_length = conn->content_len;
12928 		} else if ((cl = get_header(&conn->request_info, "Transfer-Encoding"))
12929 		               != NULL
12930 		           && !mg_strcasecmp(cl, "chunked")) {
12931 			conn->is_chunked = 1;
12932 		} else if (!mg_strcasecmp(conn->request_info.request_method, "POST")
12933 		           || !mg_strcasecmp(conn->request_info.request_method,
12934 		                             "PUT")) {
12935 			/* POST or PUT request without content length set */
12936 			conn->content_len = -1;
12937 		} else if (!mg_strncasecmp(conn->request_info.request_method,
12938 		                           "HTTP/",
12939 		                           5)) {
12940 			/* Response without content length set */
12941 			conn->content_len = -1;
12942 		} else {
12943 			/* Other request */
12944 			conn->content_len = 0;
12945 		}
12946 	}
12947 	return 1;
12948 }
12949 
12950 
12951 int
12952 mg_get_response(struct mg_connection *conn,
12953                 char *ebuf,
12954                 size_t ebuf_len,
12955                 int timeout)
12956 {
12957 	if (conn) {
12958 		/* Implementation of API function for HTTP clients */
12959 		int err, ret;
12960 		struct mg_context *octx = conn->ctx;
12961 		struct mg_context rctx = *(conn->ctx);
12962 		char txt[32]; /* will not overflow */
12963 
12964 		if (timeout >= 0) {
12965 			mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
12966 			rctx.config[REQUEST_TIMEOUT] = txt;
12967 			/* Not required for non-blocking sockets.
12968 			set_sock_timeout(conn->client.sock, timeout);
12969 			*/
12970 		} else {
12971 			rctx.config[REQUEST_TIMEOUT] = NULL;
12972 		}
12973 
12974 		conn->ctx = &rctx;
12975 		ret = getreq(conn, ebuf, ebuf_len, &err);
12976 		conn->ctx = octx;
12977 
12978 		/* TODO: 1) uri is deprecated;
12979 		 *       2) here, ri.uri is the http response code */
12980 		conn->request_info.uri = conn->request_info.request_uri;
12981 
12982 		/* TODO (mid): Define proper return values - maybe return length?
12983 		 * For the first test use <0 for error and >0 for OK */
12984 		return (ret == 0) ? -1 : +1;
12985 	}
12986 	return -1;
12987 }
12988 
12989 
12990 struct mg_connection *
12991 mg_download(const char *host,
12992             int port,
12993             int use_ssl,
12994             char *ebuf,
12995             size_t ebuf_len,
12996             const char *fmt,
12997             ...)
12998 {
12999 	struct mg_connection *conn;
13000 	va_list ap;
13001 	int i;
13002 	int reqerr;
13003 
13004 	va_start(ap, fmt);
13005 	ebuf[0] = '\0';
13006 
13007 	/* open a connection */
13008 	conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
13009 
13010 	if (conn != NULL) {
13011 		i = mg_vprintf(conn, fmt, ap);
13012 		if (i <= 0) {
13013 			mg_snprintf(conn,
13014 			            NULL, /* No truncation check for ebuf */
13015 			            ebuf,
13016 			            ebuf_len,
13017 			            "%s",
13018 			            "Error sending request");
13019 		} else {
13020 			getreq(conn, ebuf, ebuf_len, &reqerr);
13021 
13022 			/* TODO: 1) uri is deprecated;
13023 			 *       2) here, ri.uri is the http response code */
13024 			conn->request_info.uri = conn->request_info.request_uri;
13025 		}
13026 	}
13027 
13028 	/* if an error occured, close the connection */
13029 	if (ebuf[0] != '\0' && conn != NULL) {
13030 		mg_close_connection(conn);
13031 		conn = NULL;
13032 	}
13033 
13034 	va_end(ap);
13035 	return conn;
13036 }
13037 
13038 
13039 struct websocket_client_thread_data {
13040 	struct mg_connection *conn;
13041 	mg_websocket_data_handler data_handler;
13042 	mg_websocket_close_handler close_handler;
13043 	void *callback_data;
13044 };
13045 
13046 
13047 #if defined(USE_WEBSOCKET)
13048 #ifdef _WIN32
13049 static unsigned __stdcall websocket_client_thread(void *data)
13050 #else
13051 static void *
13052 websocket_client_thread(void *data)
13053 #endif
13054 {
13055 	struct websocket_client_thread_data *cdata =
13056 	    (struct websocket_client_thread_data *)data;
13057 
13058 	mg_set_thread_name("ws-clnt");
13059 
13060 	if (cdata->conn->ctx) {
13061 		if (cdata->conn->ctx->callbacks.init_thread) {
13062 			/* 3 indicates a websocket client thread */
13063 			/* TODO: check if conn->ctx can be set */
13064 			cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
13065 		}
13066 	}
13067 
13068 	read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
13069 
13070 	DEBUG_TRACE("%s", "Websocket client thread exited\n");
13071 
13072 	if (cdata->close_handler != NULL) {
13073 		cdata->close_handler(cdata->conn, cdata->callback_data);
13074 	}
13075 
13076 	/* The websocket_client context has only this thread. If it runs out,
13077 	   set the stop_flag to 2 (= "stopped"). */
13078 	cdata->conn->ctx->stop_flag = 2;
13079 
13080 	mg_free((void *)cdata);
13081 
13082 #ifdef _WIN32
13083 	return 0;
13084 #else
13085 	return NULL;
13086 #endif
13087 }
13088 #endif
13089 
13090 
13091 struct mg_connection *
13092 mg_connect_websocket_client(const char *host,
13093                             int port,
13094                             int use_ssl,
13095                             char *error_buffer,
13096                             size_t error_buffer_size,
13097                             const char *path,
13098                             const char *origin,
13099                             mg_websocket_data_handler data_func,
13100                             mg_websocket_close_handler close_func,
13101                             void *user_data)
13102 {
13103 	struct mg_connection *conn = NULL;
13104 
13105 #if defined(USE_WEBSOCKET)
13106 	struct mg_context *newctx = NULL;
13107 	struct websocket_client_thread_data *thread_data;
13108 	static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
13109 	static const char *handshake_req;
13110 
13111 	if (origin != NULL) {
13112 		handshake_req = "GET %s HTTP/1.1\r\n"
13113 		                "Host: %s\r\n"
13114 		                "Upgrade: websocket\r\n"
13115 		                "Connection: Upgrade\r\n"
13116 		                "Sec-WebSocket-Key: %s\r\n"
13117 		                "Sec-WebSocket-Version: 13\r\n"
13118 		                "Origin: %s\r\n"
13119 		                "\r\n";
13120 	} else {
13121 		handshake_req = "GET %s HTTP/1.1\r\n"
13122 		                "Host: %s\r\n"
13123 		                "Upgrade: websocket\r\n"
13124 		                "Connection: Upgrade\r\n"
13125 		                "Sec-WebSocket-Key: %s\r\n"
13126 		                "Sec-WebSocket-Version: 13\r\n"
13127 		                "\r\n";
13128 	}
13129 
13130 	/* Establish the client connection and request upgrade */
13131 	conn = mg_download(host,
13132 	                   port,
13133 	                   use_ssl,
13134 	                   error_buffer,
13135 	                   error_buffer_size,
13136 	                   handshake_req,
13137 	                   path,
13138 	                   host,
13139 	                   magic,
13140 	                   origin);
13141 
13142 	/* Connection object will be null if something goes wrong */
13143 	if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) {
13144 		if (!*error_buffer) {
13145 			/* if there is a connection, but it did not return 101,
13146 			 * error_buffer is not yet set */
13147 			mg_snprintf(conn,
13148 			            NULL, /* No truncation check for ebuf */
13149 			            error_buffer,
13150 			            error_buffer_size,
13151 			            "Unexpected server reply");
13152 		}
13153 		DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
13154 		if (conn != NULL) {
13155 			mg_free(conn);
13156 			conn = NULL;
13157 		}
13158 		return conn;
13159 	}
13160 
13161 	/* For client connections, mg_context is fake. Since we need to set a
13162 	 * callback function, we need to create a copy and modify it. */
13163 	newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
13164 	memcpy(newctx, conn->ctx, sizeof(struct mg_context));
13165 	newctx->user_data = user_data;
13166 	newctx->context_type = 2;       /* ws/wss client context type */
13167 	newctx->cfg_worker_threads = 1; /* one worker thread will be created */
13168 	newctx->workerthreadids =
13169 	    (pthread_t *)mg_calloc(newctx->cfg_worker_threads, sizeof(pthread_t));
13170 	conn->ctx = newctx;
13171 	thread_data = (struct websocket_client_thread_data *)
13172 	    mg_calloc(sizeof(struct websocket_client_thread_data), 1);
13173 	thread_data->conn = conn;
13174 	thread_data->data_handler = data_func;
13175 	thread_data->close_handler = close_func;
13176 	thread_data->callback_data = NULL;
13177 
13178 	/* Start a thread to read the websocket client connection
13179 	 * This thread will automatically stop when mg_disconnect is
13180 	 * called on the client connection */
13181 	if (mg_start_thread_with_id(websocket_client_thread,
13182 	                            (void *)thread_data,
13183 	                            newctx->workerthreadids) != 0) {
13184 		mg_free((void *)thread_data);
13185 		mg_free((void *)newctx->workerthreadids);
13186 		mg_free((void *)newctx);
13187 		mg_free((void *)conn);
13188 		conn = NULL;
13189 		DEBUG_TRACE("%s",
13190 		            "Websocket client connect thread could not be started\r\n");
13191 	}
13192 
13193 #else
13194 	/* Appease "unused parameter" warnings */
13195 	(void)host;
13196 	(void)port;
13197 	(void)use_ssl;
13198 	(void)error_buffer;
13199 	(void)error_buffer_size;
13200 	(void)path;
13201 	(void)origin;
13202 	(void)user_data;
13203 	(void)data_func;
13204 	(void)close_func;
13205 #endif
13206 
13207 	return conn;
13208 }
13209 
13210 
13211 static void
13212 process_new_connection(struct mg_connection *conn)
13213 {
13214 	if (conn && conn->ctx) {
13215 		struct mg_request_info *ri = &conn->request_info;
13216 		int keep_alive_enabled, keep_alive, discard_len;
13217 		char ebuf[100];
13218 		const char *hostend;
13219 		int reqerr, uri_type;
13220 
13221 		keep_alive_enabled =
13222 		    !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
13223 
13224 		/* Important: on new connection, reset the receiving buffer. Credit
13225 		 * goes to crule42. */
13226 		conn->data_len = 0;
13227 		conn->handled_requests = 0;
13228 		do {
13229 
13230 			DEBUG_TRACE("calling getreq (%i times for this connection)",
13231 			            conn->handled_requests + 1);
13232 
13233 			if (!getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
13234 				/* The request sent by the client could not be understood by
13235 				 * the server, or it was incomplete or a timeout. Send an
13236 				 * error message and close the connection. */
13237 				if (reqerr > 0) {
13238 					/*assert(ebuf[0] != '\0');*/
13239 					send_http_error(conn, reqerr, "%s", ebuf);
13240 				}
13241 			} else if (strcmp(ri->http_version, "1.0")
13242 			           && strcmp(ri->http_version, "1.1")) {
13243 				mg_snprintf(conn,
13244 				            NULL, /* No truncation check for ebuf */
13245 				            ebuf,
13246 				            sizeof(ebuf),
13247 				            "Bad HTTP version: [%s]",
13248 				            ri->http_version);
13249 				send_http_error(conn, 505, "%s", ebuf);
13250 			}
13251 
13252 			if (ebuf[0] == '\0') {
13253 				uri_type = get_uri_type(conn->request_info.request_uri);
13254 				switch (uri_type) {
13255 				case 1:
13256 					/* Asterisk */
13257 					conn->request_info.local_uri = NULL;
13258 					break;
13259 				case 2:
13260 					/* relative uri */
13261 					conn->request_info.local_uri =
13262 					    conn->request_info.request_uri;
13263 					break;
13264 				case 3:
13265 				case 4:
13266 					/* absolute uri (with/without port) */
13267 					hostend = get_rel_url_at_current_server(
13268 					    conn->request_info.request_uri, conn);
13269 					if (hostend) {
13270 						conn->request_info.local_uri = hostend;
13271 					} else {
13272 						conn->request_info.local_uri = NULL;
13273 					}
13274 					break;
13275 				default:
13276 					mg_snprintf(conn,
13277 					            NULL, /* No truncation check for ebuf */
13278 					            ebuf,
13279 					            sizeof(ebuf),
13280 					            "Invalid URI");
13281 					send_http_error(conn, 400, "%s", ebuf);
13282 					conn->request_info.local_uri = NULL;
13283 					break;
13284 				}
13285 
13286 				/* TODO: cleanup uri, local_uri and request_uri */
13287 				conn->request_info.uri = conn->request_info.local_uri;
13288 			}
13289 
13290 			DEBUG_TRACE("http: %s, error: %s",
13291 			            (ri->http_version ? ri->http_version : "none"),
13292 			            (ebuf[0] ? ebuf : "none"));
13293 
13294 			if (ebuf[0] == '\0') {
13295 				if (conn->request_info.local_uri) {
13296 					/* handle request to local server */
13297 					handle_request(conn);
13298 					DEBUG_TRACE("%s", "handle_request done");
13299 					if (conn->ctx->callbacks.end_request != NULL) {
13300 						conn->ctx->callbacks.end_request(conn,
13301 						                                 conn->status_code);
13302 						DEBUG_TRACE("%s", "end_request callback done");
13303 					}
13304 					log_access(conn);
13305 				} else {
13306 					/* TODO: handle non-local request (PROXY) */
13307 					conn->must_close = 1;
13308 				}
13309 			} else {
13310 				conn->must_close = 1;
13311 			}
13312 
13313 			if (ri->remote_user != NULL) {
13314 				mg_free((void *)ri->remote_user);
13315 				/* Important! When having connections with and without auth
13316 				 * would cause double free and then crash */
13317 				ri->remote_user = NULL;
13318 			}
13319 
13320 			/* NOTE(lsm): order is important here. should_keep_alive() call
13321 			 * is
13322 			 * using parsed request, which will be invalid after memmove's
13323 			 * below.
13324 			 * Therefore, memorize should_keep_alive() result now for later
13325 			 * use
13326 			 * in loop exit condition. */
13327 			keep_alive = (conn->ctx->stop_flag == 0) && keep_alive_enabled
13328 			             && (conn->content_len >= 0) && should_keep_alive(conn);
13329 
13330 
13331 			/* Discard all buffered data for this request */
13332 			discard_len = ((conn->content_len >= 0) && (conn->request_len > 0)
13333 			               && ((conn->request_len + conn->content_len)
13334 			                   < (int64_t)conn->data_len))
13335 			                  ? (int)(conn->request_len + conn->content_len)
13336 			                  : conn->data_len;
13337 			/*assert(discard_len >= 0);*/
13338 			if (discard_len < 0) {
13339 				DEBUG_TRACE("internal error: discard_len = %li",
13340 				            (long int)discard_len);
13341 				break;
13342 			}
13343 			conn->data_len -= discard_len;
13344 			if (conn->data_len > 0) {
13345 				DEBUG_TRACE("discard_len = %lu", (long unsigned)discard_len);
13346 				memmove(conn->buf,
13347 				        conn->buf + discard_len,
13348 				        (size_t)conn->data_len);
13349 			}
13350 
13351 			/* assert(conn->data_len >= 0); */
13352 			/* assert(conn->data_len <= conn->buf_size); */
13353 
13354 			if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
13355 				DEBUG_TRACE("internal error: data_len = %li, buf_size = %li",
13356 				            (long int)conn->data_len,
13357 				            (long int)conn->buf_size);
13358 				break;
13359 			}
13360 
13361 			conn->handled_requests++;
13362 
13363 		} while (keep_alive);
13364 	}
13365 }
13366 
13367 
13368 #if defined(ALTERNATIVE_QUEUE)
13369 
13370 static void
13371 produce_socket(struct mg_context *ctx, const struct socket *sp)
13372 {
13373 	unsigned int i;
13374 
13375 	for (;;) {
13376 		for (i = 0; i < ctx->cfg_worker_threads; i++) {
13377 			/* find a free worker slot and signal it */
13378 			if (ctx->client_socks[i].in_use == 0) {
13379 				ctx->client_socks[i] = *sp;
13380 				ctx->client_socks[i].in_use = 1;
13381 				event_signal(ctx->client_wait_events[i]);
13382 				return;
13383 			}
13384 		}
13385 		/* queue is full */
13386 		mg_sleep(1);
13387 	}
13388 }
13389 
13390 
13391 static int
13392 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
13393 {
13394 	DEBUG_TRACE("%s", "going idle");
13395 	ctx->client_socks[thread_index].in_use = 0;
13396 	event_wait(ctx->client_wait_events[thread_index]);
13397 	*sp = ctx->client_socks[thread_index];
13398 	DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
13399 
13400 	return !ctx->stop_flag;
13401 }
13402 
13403 #else /* ALTERNATIVE_QUEUE */
13404 
13405 /* Worker threads take accepted socket from the queue */
13406 static int
13407 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
13408 {
13409 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
13410 
13411 	(void)thread_index;
13412 
13413 	(void)pthread_mutex_lock(&ctx->thread_mutex);
13414 	DEBUG_TRACE("%s", "going idle");
13415 
13416 	/* If the queue is empty, wait. We're idle at this point. */
13417 	while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
13418 		pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
13419 	}
13420 
13421 	/* If we're stopping, sq_head may be equal to sq_tail. */
13422 	if (ctx->sq_head > ctx->sq_tail) {
13423 		/* Copy socket from the queue and increment tail */
13424 		*sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
13425 		ctx->sq_tail++;
13426 
13427 		DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
13428 
13429 		/* Wrap pointers if needed */
13430 		while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
13431 			ctx->sq_tail -= QUEUE_SIZE(ctx);
13432 			ctx->sq_head -= QUEUE_SIZE(ctx);
13433 		}
13434 	}
13435 
13436 	(void)pthread_cond_signal(&ctx->sq_empty);
13437 	(void)pthread_mutex_unlock(&ctx->thread_mutex);
13438 
13439 	return !ctx->stop_flag;
13440 #undef QUEUE_SIZE
13441 }
13442 
13443 
13444 /* Master thread adds accepted socket to a queue */
13445 static void
13446 produce_socket(struct mg_context *ctx, const struct socket *sp)
13447 {
13448 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
13449 	if (!ctx) {
13450 		return;
13451 	}
13452 	(void)pthread_mutex_lock(&ctx->thread_mutex);
13453 
13454 	/* If the queue is full, wait */
13455 	while (ctx->stop_flag == 0
13456 	       && ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
13457 		(void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
13458 	}
13459 
13460 	if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
13461 		/* Copy socket to the queue and increment head */
13462 		ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
13463 		ctx->sq_head++;
13464 		DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
13465 	}
13466 
13467 	(void)pthread_cond_signal(&ctx->sq_full);
13468 	(void)pthread_mutex_unlock(&ctx->thread_mutex);
13469 #undef QUEUE_SIZE
13470 }
13471 #endif /* ALTERNATIVE_QUEUE */
13472 
13473 
13474 struct worker_thread_args {
13475 	struct mg_context *ctx;
13476 	int index;
13477 };
13478 
13479 
13480 static void *
13481 worker_thread_run(struct worker_thread_args *thread_args)
13482 {
13483 	struct mg_context *ctx = thread_args->ctx;
13484 	struct mg_connection *conn;
13485 	struct mg_workerTLS tls;
13486 #if defined(MG_LEGACY_INTERFACE)
13487 	uint32_t addr;
13488 #endif
13489 
13490 	mg_set_thread_name("worker");
13491 
13492 	tls.is_master = 0;
13493 	tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
13494 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13495 	tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
13496 #endif
13497 
13498 	if (ctx->callbacks.init_thread) {
13499 		/* call init_thread for a worker thread (type 1) */
13500 		ctx->callbacks.init_thread(ctx, 1);
13501 	}
13502 
13503 	conn =
13504 	    (struct mg_connection *)mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
13505 	if (conn == NULL) {
13506 		mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
13507 	} else {
13508 		pthread_setspecific(sTlsKey, &tls);
13509 		conn->buf_size = MAX_REQUEST_SIZE;
13510 		conn->buf = (char *)(conn + 1);
13511 		conn->ctx = ctx;
13512 		conn->thread_index = thread_args->index;
13513 		conn->request_info.user_data = ctx->user_data;
13514 		/* Allocate a mutex for this connection to allow communication both
13515 		 * within the request handler and from elsewhere in the application
13516 		 */
13517 		(void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
13518 
13519 		/* Call consume_socket() even when ctx->stop_flag > 0, to let it
13520 		 * signal sq_empty condvar to wake up the master waiting in
13521 		 * produce_socket() */
13522 		while (consume_socket(ctx, &conn->client, conn->thread_index)) {
13523 			conn->conn_birth_time = time(NULL);
13524 
13525 /* Fill in IP, port info early so even if SSL setup below fails,
13526  * error handler would have the corresponding info.
13527  * Thanks to Johannes Winkelmann for the patch.
13528  */
13529 #if defined(USE_IPV6)
13530 			if (conn->client.rsa.sa.sa_family == AF_INET6) {
13531 				conn->request_info.remote_port =
13532 				    ntohs(conn->client.rsa.sin6.sin6_port);
13533 			} else
13534 #endif
13535 			{
13536 				conn->request_info.remote_port =
13537 				    ntohs(conn->client.rsa.sin.sin_port);
13538 			}
13539 
13540 			sockaddr_to_string(conn->request_info.remote_addr,
13541 			                   sizeof(conn->request_info.remote_addr),
13542 			                   &conn->client.rsa);
13543 
13544 			DEBUG_TRACE("Start processing connection from %s",
13545 			            conn->request_info.remote_addr);
13546 
13547 #if defined(MG_LEGACY_INTERFACE)
13548 			/* This legacy interface only works for the IPv4 case */
13549 			addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
13550 			memcpy(&conn->request_info.remote_ip, &addr, 4);
13551 #endif
13552 
13553 			conn->request_info.is_ssl = conn->client.is_ssl;
13554 
13555 			if (conn->client.is_ssl) {
13556 #ifndef NO_SSL
13557 				/* HTTPS connection */
13558 				if (sslize(conn,
13559 				           conn->ctx->ssl_ctx,
13560 				           SSL_accept,
13561 				           &(conn->ctx->stop_flag))) {
13562 					/* Get SSL client certificate information (if set) */
13563 					ssl_get_client_cert_info(conn);
13564 
13565 					/* process HTTPS connection */
13566 					process_new_connection(conn);
13567 
13568 					/* Free client certificate info */
13569 					if (conn->request_info.client_cert) {
13570 						mg_free(
13571 						    (void *)(conn->request_info.client_cert->subject));
13572 						mg_free(
13573 						    (void *)(conn->request_info.client_cert->issuer));
13574 						mg_free(
13575 						    (void *)(conn->request_info.client_cert->serial));
13576 						mg_free(
13577 						    (void *)(conn->request_info.client_cert->finger));
13578 						conn->request_info.client_cert->subject = 0;
13579 						conn->request_info.client_cert->issuer = 0;
13580 						conn->request_info.client_cert->serial = 0;
13581 						conn->request_info.client_cert->finger = 0;
13582 						mg_free(conn->request_info.client_cert);
13583 						conn->request_info.client_cert = 0;
13584 					}
13585 				}
13586 #endif
13587 			} else {
13588 				/* process HTTP connection */
13589 				process_new_connection(conn);
13590 			}
13591 
13592 			DEBUG_TRACE("Done processing connection from %s (%f sec)",
13593 			            conn->request_info.remote_addr,
13594 			            difftime(time(NULL), conn->conn_birth_time));
13595 
13596 			close_connection(conn);
13597 
13598 			DEBUG_TRACE("%s", "Connection closed");
13599 		}
13600 	}
13601 
13602 	pthread_setspecific(sTlsKey, NULL);
13603 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13604 	CloseHandle(tls.pthread_cond_helper_mutex);
13605 #endif
13606 	pthread_mutex_destroy(&conn->mutex);
13607 	mg_free(conn);
13608 
13609 	DEBUG_TRACE("%s", "exiting");
13610 	return NULL;
13611 }
13612 
13613 
13614 /* Threads have different return types on Windows and Unix. */
13615 #ifdef _WIN32
13616 static unsigned __stdcall worker_thread(void *thread_func_param)
13617 {
13618 	struct worker_thread_args *pwta =
13619 	    (struct worker_thread_args *)thread_func_param;
13620 	worker_thread_run(pwta);
13621 	mg_free(thread_func_param);
13622 	return 0;
13623 }
13624 #else
13625 static void *
13626 worker_thread(void *thread_func_param)
13627 {
13628 	struct worker_thread_args *pwta =
13629 	    (struct worker_thread_args *)thread_func_param;
13630 	worker_thread_run(pwta);
13631 	mg_free(thread_func_param);
13632 	return NULL;
13633 }
13634 #endif /* _WIN32 */
13635 
13636 
13637 static void
13638 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
13639 {
13640 	struct socket so;
13641 	char src_addr[IP_ADDR_STR_LEN];
13642 	socklen_t len = sizeof(so.rsa);
13643 	int on = 1;
13644 	int timeout;
13645 
13646 	if (!listener) {
13647 		return;
13648 	}
13649 
13650 	if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
13651 	    == INVALID_SOCKET) {
13652 	} else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
13653 		sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
13654 		mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
13655 		closesocket(so.sock);
13656 		so.sock = INVALID_SOCKET;
13657 	} else {
13658 		/* Put so socket structure into the queue */
13659 		DEBUG_TRACE("Accepted socket %d", (int)so.sock);
13660 		set_close_on_exec(so.sock, fc(ctx));
13661 		so.is_ssl = listener->is_ssl;
13662 		so.ssl_redir = listener->ssl_redir;
13663 		if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
13664 			mg_cry(fc(ctx),
13665 			       "%s: getsockname() failed: %s",
13666 			       __func__,
13667 			       strerror(ERRNO));
13668 		}
13669 
13670 		/* Set TCP keep-alive. This is needed because if HTTP-level
13671 		 * keep-alive
13672 		 * is enabled, and client resets the connection, server won't get
13673 		 * TCP FIN or RST and will keep the connection open forever. With
13674 		 * TCP keep-alive, next keep-alive handshake will figure out that
13675 		 * the client is down and will close the server end.
13676 		 * Thanks to Igor Klopov who suggested the patch. */
13677 		if (setsockopt(so.sock,
13678 		               SOL_SOCKET,
13679 		               SO_KEEPALIVE,
13680 		               (SOCK_OPT_TYPE)&on,
13681 		               sizeof(on)) != 0) {
13682 			mg_cry(fc(ctx),
13683 			       "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
13684 			       __func__,
13685 			       strerror(ERRNO));
13686 		}
13687 
13688 		/* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
13689 		 * to effectively fill up the underlying IP packet payload and
13690 		 * reduce the overhead of sending lots of small buffers. However
13691 		 * this hurts the server's throughput (ie. operations per second)
13692 		 * when HTTP 1.1 persistent connections are used and the responses
13693 		 * are relatively small (eg. less than 1400 bytes).
13694 		 */
13695 		if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
13696 		    && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
13697 			if (set_tcp_nodelay(so.sock, 1) != 0) {
13698 				mg_cry(fc(ctx),
13699 				       "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
13700 				       __func__,
13701 				       strerror(ERRNO));
13702 			}
13703 		}
13704 
13705 		if (ctx && ctx->config[REQUEST_TIMEOUT]) {
13706 			timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
13707 		} else {
13708 			timeout = -1;
13709 		}
13710 
13711 
13712 		/* TODO: if non blocking sockets are used, timeouts are implemented
13713 		 * differently */
13714 		// if (timeout > 0) {
13715 		//	set_sock_timeout(so.sock, timeout);
13716 		//}
13717 		(void)timeout;
13718 		set_blocking_mode(so.sock, 0);
13719 
13720 		produce_socket(ctx, &so);
13721 	}
13722 }
13723 
13724 
13725 static void
13726 master_thread_run(void *thread_func_param)
13727 {
13728 	struct mg_context *ctx = (struct mg_context *)thread_func_param;
13729 	struct mg_workerTLS tls;
13730 	struct pollfd *pfd;
13731 	unsigned int i;
13732 	unsigned int workerthreadcount;
13733 
13734 	if (!ctx) {
13735 		return;
13736 	}
13737 
13738 	mg_set_thread_name("master");
13739 
13740 /* Increase priority of the master thread */
13741 #if defined(_WIN32)
13742 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
13743 #elif defined(USE_MASTER_THREAD_PRIORITY)
13744 	int min_prio = sched_get_priority_min(SCHED_RR);
13745 	int max_prio = sched_get_priority_max(SCHED_RR);
13746 	if ((min_prio >= 0) && (max_prio >= 0)
13747 	    && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
13748 	    && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
13749 		struct sched_param sched_param = {0};
13750 		sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
13751 		pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
13752 	}
13753 #endif
13754 
13755 /* Initialize thread local storage */
13756 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13757 	tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
13758 #endif
13759 	tls.is_master = 1;
13760 	pthread_setspecific(sTlsKey, &tls);
13761 
13762 	if (ctx->callbacks.init_thread) {
13763 		/* Callback for the master thread (type 0) */
13764 		ctx->callbacks.init_thread(ctx, 0);
13765 	}
13766 
13767 	/* Server starts *now* */
13768 	ctx->start_time = time(NULL);
13769 
13770 	/* Start the server */
13771 	pfd = ctx->listening_socket_fds;
13772 	while (ctx->stop_flag == 0) {
13773 		for (i = 0; i < ctx->num_listening_sockets; i++) {
13774 			pfd[i].fd = ctx->listening_sockets[i].sock;
13775 			pfd[i].events = POLLIN;
13776 		}
13777 
13778 		if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
13779 			for (i = 0; i < ctx->num_listening_sockets; i++) {
13780 				/* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
13781 				 * successful poll, and POLLIN is defined as
13782 				 * (POLLRDNORM | POLLRDBAND)
13783 				 * Therefore, we're checking pfd[i].revents & POLLIN, not
13784 				 * pfd[i].revents == POLLIN. */
13785 				if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
13786 					accept_new_connection(&ctx->listening_sockets[i], ctx);
13787 				}
13788 			}
13789 		}
13790 	}
13791 
13792 	/* Here stop_flag is 1 - Initiate shutdown. */
13793 	DEBUG_TRACE("%s", "stopping workers");
13794 
13795 	/* Stop signal received: somebody called mg_stop. Quit. */
13796 	close_all_listening_sockets(ctx);
13797 
13798 	/* Wakeup workers that are waiting for connections to handle. */
13799 	(void)pthread_mutex_lock(&ctx->thread_mutex);
13800 #if defined(ALTERNATIVE_QUEUE)
13801 	for (i = 0; i < ctx->cfg_worker_threads; i++) {
13802 		event_signal(ctx->client_wait_events[i]);
13803 
13804 		/* Since we know all sockets, we can shutdown the connections. */
13805 		if (ctx->client_socks[i].in_use) {
13806 			shutdown(ctx->client_socks[i].sock, SHUTDOWN_BOTH);
13807 		}
13808 	}
13809 #else
13810 	pthread_cond_broadcast(&ctx->sq_full);
13811 #endif
13812 	(void)pthread_mutex_unlock(&ctx->thread_mutex);
13813 
13814 	/* Join all worker threads to avoid leaking threads. */
13815 	workerthreadcount = ctx->cfg_worker_threads;
13816 	for (i = 0; i < workerthreadcount; i++) {
13817 		if (ctx->workerthreadids[i] != 0) {
13818 			mg_join_thread(ctx->workerthreadids[i]);
13819 		}
13820 	}
13821 
13822 #if !defined(NO_SSL)
13823 	if (ctx->ssl_ctx != NULL) {
13824 		uninitialize_ssl(ctx);
13825 	}
13826 #endif
13827 	DEBUG_TRACE("%s", "exiting");
13828 
13829 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13830 	CloseHandle(tls.pthread_cond_helper_mutex);
13831 #endif
13832 	pthread_setspecific(sTlsKey, NULL);
13833 
13834 	/* Signal mg_stop() that we're done.
13835 	 * WARNING: This must be the very last thing this
13836 	 * thread does, as ctx becomes invalid after this line. */
13837 	ctx->stop_flag = 2;
13838 }
13839 
13840 
13841 /* Threads have different return types on Windows and Unix. */
13842 #ifdef _WIN32
13843 static unsigned __stdcall master_thread(void *thread_func_param)
13844 {
13845 	master_thread_run(thread_func_param);
13846 	return 0;
13847 }
13848 #else
13849 static void *
13850 master_thread(void *thread_func_param)
13851 {
13852 	master_thread_run(thread_func_param);
13853 	return NULL;
13854 }
13855 #endif /* _WIN32 */
13856 
13857 
13858 static void
13859 free_context(struct mg_context *ctx)
13860 {
13861 	int i;
13862 	struct mg_handler_info *tmp_rh;
13863 
13864 	if (ctx == NULL) {
13865 		return;
13866 	}
13867 
13868 	if (ctx->callbacks.exit_context) {
13869 		ctx->callbacks.exit_context(ctx);
13870 	}
13871 
13872 	/* All threads exited, no sync is needed. Destroy thread mutex and
13873 	 * condvars
13874 	 */
13875 	(void)pthread_mutex_destroy(&ctx->thread_mutex);
13876 #if defined(ALTERNATIVE_QUEUE)
13877 	mg_free(ctx->client_socks);
13878 	for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
13879 		event_destroy(ctx->client_wait_events[i]);
13880 	}
13881 	mg_free(ctx->client_wait_events);
13882 #else
13883 	(void)pthread_cond_destroy(&ctx->sq_empty);
13884 	(void)pthread_cond_destroy(&ctx->sq_full);
13885 #endif
13886 
13887 	/* Destroy other context global data structures mutex */
13888 	(void)pthread_mutex_destroy(&ctx->nonce_mutex);
13889 
13890 #if defined(USE_TIMERS)
13891 	timers_exit(ctx);
13892 #endif
13893 
13894 	/* Deallocate config parameters */
13895 	for (i = 0; i < NUM_OPTIONS; i++) {
13896 		if (ctx->config[i] != NULL) {
13897 #if defined(_MSC_VER)
13898 #pragma warning(suppress : 6001)
13899 #endif
13900 			mg_free(ctx->config[i]);
13901 		}
13902 	}
13903 
13904 	/* Deallocate request handlers */
13905 	while (ctx->handlers) {
13906 		tmp_rh = ctx->handlers;
13907 		ctx->handlers = tmp_rh->next;
13908 		mg_free(tmp_rh->uri);
13909 		mg_free(tmp_rh);
13910 	}
13911 
13912 #ifndef NO_SSL
13913 	/* Deallocate SSL context */
13914 	if (ctx->ssl_ctx != NULL) {
13915 		SSL_CTX_free(ctx->ssl_ctx);
13916 	}
13917 #endif /* !NO_SSL */
13918 
13919 	/* Deallocate worker thread ID array */
13920 	if (ctx->workerthreadids != NULL) {
13921 		mg_free(ctx->workerthreadids);
13922 	}
13923 
13924 	/* Deallocate the tls variable */
13925 	if (mg_atomic_dec(&sTlsInit) == 0) {
13926 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13927 		DeleteCriticalSection(&global_log_file_lock);
13928 #endif /* _WIN32 && !__SYMBIAN32__ */
13929 #if !defined(_WIN32)
13930 		pthread_mutexattr_destroy(&pthread_mutex_attr);
13931 #endif
13932 
13933 		pthread_key_delete(sTlsKey);
13934 
13935 #if defined(USE_LUA)
13936 		lua_exit_optional_libraries();
13937 #endif
13938 	}
13939 
13940 	/* deallocate system name string */
13941 	mg_free(ctx->systemName);
13942 
13943 	/* Deallocate context itself */
13944 	mg_free(ctx);
13945 }
13946 
13947 
13948 void
13949 mg_stop(struct mg_context *ctx)
13950 {
13951 	pthread_t mt;
13952 	if (!ctx) {
13953 		return;
13954 	}
13955 
13956 	/* We don't use a lock here. Calling mg_stop with the same ctx from
13957 	 * two threads is not allowed. */
13958 	mt = ctx->masterthreadid;
13959 	if (mt == 0) {
13960 		return;
13961 	}
13962 
13963 	ctx->masterthreadid = 0;
13964 
13965 	/* Set stop flag, so all threads know they have to exit. */
13966 	ctx->stop_flag = 1;
13967 
13968 	/* Wait until everything has stopped. */
13969 	while (ctx->stop_flag != 2) {
13970 		(void)mg_sleep(10);
13971 	}
13972 
13973 	mg_join_thread(mt);
13974 	free_context(ctx);
13975 
13976 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13977 	(void)WSACleanup();
13978 #endif /* _WIN32 && !__SYMBIAN32__ */
13979 }
13980 
13981 
13982 static void
13983 get_system_name(char **sysName)
13984 {
13985 #if defined(_WIN32)
13986 #if !defined(__SYMBIAN32__)
13987 #if defined(_WIN32_WCE)
13988 	*sysName = mg_strdup("WinCE");
13989 #else
13990 	char name[128];
13991 	DWORD dwVersion = 0;
13992 	DWORD dwMajorVersion = 0;
13993 	DWORD dwMinorVersion = 0;
13994 	DWORD dwBuild = 0;
13995 
13996 #ifdef _MSC_VER
13997 #pragma warning(push)
13998 /* GetVersion was declared deprecated */
13999 #pragma warning(disable : 4996)
14000 #endif
14001 	dwVersion = GetVersion();
14002 #ifdef _MSC_VER
14003 #pragma warning(pop)
14004 #endif
14005 
14006 	dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
14007 	dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
14008 	dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
14009 	(void)dwBuild;
14010 
14011 	sprintf(name,
14012 	        "Windows %u.%u",
14013 	        (unsigned)dwMajorVersion,
14014 	        (unsigned)dwMinorVersion);
14015 	*sysName = mg_strdup(name);
14016 #endif
14017 #else
14018 	*sysName = mg_strdup("Symbian");
14019 #endif
14020 #else
14021 	struct utsname name;
14022 	memset(&name, 0, sizeof(name));
14023 	uname(&name);
14024 	*sysName = mg_strdup(name.sysname);
14025 #endif
14026 }
14027 
14028 
14029 struct mg_context *
14030 mg_start(const struct mg_callbacks *callbacks,
14031          void *user_data,
14032          const char **options)
14033 {
14034 	struct mg_context *ctx;
14035 	const char *name, *value, *default_value;
14036 	int idx, ok, workerthreadcount;
14037 	unsigned int i;
14038 	void (*exit_callback)(const struct mg_context *ctx) = 0;
14039 
14040 	struct mg_workerTLS tls;
14041 
14042 #if defined(_WIN32) && !defined(__SYMBIAN32__)
14043 	WSADATA data;
14044 	WSAStartup(MAKEWORD(2, 2), &data);
14045 #endif /* _WIN32 && !__SYMBIAN32__ */
14046 
14047 	/* Allocate context and initialize reasonable general case defaults. */
14048 	if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
14049 		return NULL;
14050 	}
14051 
14052 	/* Random number generator will initialize at the first call */
14053 	ctx->auth_nonce_mask =
14054 	    (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
14055 
14056 	if (mg_atomic_inc(&sTlsInit) == 1) {
14057 
14058 #if defined(_WIN32) && !defined(__SYMBIAN32__)
14059 		InitializeCriticalSection(&global_log_file_lock);
14060 #endif /* _WIN32 && !__SYMBIAN32__ */
14061 #if !defined(_WIN32)
14062 		pthread_mutexattr_init(&pthread_mutex_attr);
14063 		pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
14064 #endif
14065 
14066 		if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
14067 			/* Fatal error - abort start. However, this situation should
14068 			 * never
14069 			 * occur in practice. */
14070 			mg_atomic_dec(&sTlsInit);
14071 			mg_cry(fc(ctx), "Cannot initialize thread local storage");
14072 			mg_free(ctx);
14073 			return NULL;
14074 		}
14075 
14076 #if defined(USE_LUA)
14077 		lua_init_optional_libraries();
14078 #endif
14079 
14080 	} else {
14081 		/* TODO (low): istead of sleeping, check if sTlsKey is already
14082 		 * initialized. */
14083 		mg_sleep(1);
14084 	}
14085 
14086 	tls.is_master = -1;
14087 	tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
14088 #if defined(_WIN32) && !defined(__SYMBIAN32__)
14089 	tls.pthread_cond_helper_mutex = NULL;
14090 #endif
14091 	pthread_setspecific(sTlsKey, &tls);
14092 
14093 	ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
14094 #if !defined(ALTERNATIVE_QUEUE)
14095 	ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
14096 	ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
14097 #endif
14098 	ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
14099 	if (!ok) {
14100 		/* Fatal error - abort start. However, this situation should never
14101 		 * occur in practice. */
14102 		mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
14103 		mg_free(ctx);
14104 		pthread_setspecific(sTlsKey, NULL);
14105 		return NULL;
14106 	}
14107 
14108 	if (callbacks) {
14109 		ctx->callbacks = *callbacks;
14110 		exit_callback = callbacks->exit_context;
14111 		ctx->callbacks.exit_context = 0;
14112 	}
14113 	ctx->user_data = user_data;
14114 	ctx->handlers = NULL;
14115 
14116 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
14117 	ctx->shared_lua_websockets = 0;
14118 #endif
14119 
14120 	while (options && (name = *options++) != NULL) {
14121 		if ((idx = get_option_index(name)) == -1) {
14122 			mg_cry(fc(ctx), "Invalid option: %s", name);
14123 			free_context(ctx);
14124 			pthread_setspecific(sTlsKey, NULL);
14125 			return NULL;
14126 		} else if ((value = *options++) == NULL) {
14127 			mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
14128 			free_context(ctx);
14129 			pthread_setspecific(sTlsKey, NULL);
14130 			return NULL;
14131 		}
14132 		if (ctx->config[idx] != NULL) {
14133 			mg_cry(fc(ctx), "warning: %s: duplicate option", name);
14134 			mg_free(ctx->config[idx]);
14135 		}
14136 		ctx->config[idx] = mg_strdup(value);
14137 		DEBUG_TRACE("[%s] -> [%s]", name, value);
14138 	}
14139 
14140 	/* Set default value if needed */
14141 	for (i = 0; config_options[i].name != NULL; i++) {
14142 		default_value = config_options[i].default_value;
14143 		if (ctx->config[i] == NULL && default_value != NULL) {
14144 			ctx->config[i] = mg_strdup(default_value);
14145 		}
14146 	}
14147 
14148 #if defined(NO_FILES)
14149 	if (ctx->config[DOCUMENT_ROOT] != NULL) {
14150 		mg_cry(fc(ctx), "%s", "Document root must not be set");
14151 		free_context(ctx);
14152 		pthread_setspecific(sTlsKey, NULL);
14153 		return NULL;
14154 	}
14155 #endif
14156 
14157 	get_system_name(&ctx->systemName);
14158 
14159 	/* NOTE(lsm): order is important here. SSL certificates must
14160 	 * be initialized before listening ports. UID must be set last. */
14161 	if (!set_gpass_option(ctx) ||
14162 #if !defined(NO_SSL)
14163 	    !set_ssl_option(ctx) ||
14164 #endif
14165 	    !set_ports_option(ctx) ||
14166 #if !defined(_WIN32)
14167 	    !set_uid_option(ctx) ||
14168 #endif
14169 	    !set_acl_option(ctx)) {
14170 		free_context(ctx);
14171 		pthread_setspecific(sTlsKey, NULL);
14172 		return NULL;
14173 	}
14174 
14175 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
14176 	/* Ignore SIGPIPE signal, so if browser cancels the request, it
14177 	 * won't kill the whole process. */
14178 	(void)signal(SIGPIPE, SIG_IGN);
14179 #endif /* !_WIN32 && !__SYMBIAN32__ */
14180 
14181 	workerthreadcount = atoi(ctx->config[NUM_THREADS]);
14182 
14183 	if (workerthreadcount > MAX_WORKER_THREADS) {
14184 		mg_cry(fc(ctx), "Too many worker threads");
14185 		free_context(ctx);
14186 		pthread_setspecific(sTlsKey, NULL);
14187 		return NULL;
14188 	}
14189 
14190 	if (workerthreadcount > 0) {
14191 		ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
14192 		ctx->workerthreadids =
14193 		    (pthread_t *)mg_calloc(ctx->cfg_worker_threads, sizeof(pthread_t));
14194 		if (ctx->workerthreadids == NULL) {
14195 			mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
14196 			free_context(ctx);
14197 			pthread_setspecific(sTlsKey, NULL);
14198 			return NULL;
14199 		}
14200 
14201 #if defined(ALTERNATIVE_QUEUE)
14202 		ctx->client_wait_events = mg_calloc(sizeof(ctx->client_wait_events[0]),
14203 		                                    ctx->cfg_worker_threads);
14204 		if (ctx->client_wait_events == NULL) {
14205 			mg_cry(fc(ctx), "Not enough memory for worker event array");
14206 			mg_free(ctx->workerthreadids);
14207 			free_context(ctx);
14208 			pthread_setspecific(sTlsKey, NULL);
14209 			return NULL;
14210 		}
14211 
14212 		ctx->client_socks =
14213 		    mg_calloc(sizeof(ctx->client_socks[0]), ctx->cfg_worker_threads);
14214 		if (ctx->client_wait_events == NULL) {
14215 			mg_cry(fc(ctx), "Not enough memory for worker socket array");
14216 			mg_free(ctx->client_socks);
14217 			mg_free(ctx->workerthreadids);
14218 			free_context(ctx);
14219 			pthread_setspecific(sTlsKey, NULL);
14220 			return NULL;
14221 		}
14222 
14223 		for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
14224 			ctx->client_wait_events[i] = event_create();
14225 			if (ctx->client_wait_events[i] == 0) {
14226 				mg_cry(fc(ctx), "Error creating worker event %i", i);
14227 				/* TODO: clean all and exit */
14228 			}
14229 		}
14230 #endif
14231 	}
14232 
14233 #if defined(USE_TIMERS)
14234 	if (timers_init(ctx) != 0) {
14235 		mg_cry(fc(ctx), "Error creating timers");
14236 		free_context(ctx);
14237 		pthread_setspecific(sTlsKey, NULL);
14238 		return NULL;
14239 	}
14240 #endif
14241 
14242 	/* Context has been created - init user libraries */
14243 	if (ctx->callbacks.init_context) {
14244 		ctx->callbacks.init_context(ctx);
14245 	}
14246 	ctx->callbacks.exit_context = exit_callback;
14247 	ctx->context_type = 1; /* server context */
14248 
14249 	/* Start master (listening) thread */
14250 	mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
14251 
14252 	/* Start worker threads */
14253 	for (i = 0; i < ctx->cfg_worker_threads; i++) {
14254 		struct worker_thread_args *wta =
14255 		    mg_malloc(sizeof(struct worker_thread_args));
14256 		if (wta) {
14257 			wta->ctx = ctx;
14258 			wta->index = (int)i;
14259 		}
14260 
14261 		if ((wta == NULL)
14262 		    || (mg_start_thread_with_id(worker_thread,
14263 		                                wta,
14264 		                                &ctx->workerthreadids[i]) != 0)) {
14265 
14266 			/* thread was not created */
14267 			if (wta != NULL) {
14268 				mg_free(wta);
14269 			}
14270 
14271 			if (i > 0) {
14272 				mg_cry(fc(ctx),
14273 				       "Cannot start worker thread %i: error %ld",
14274 				       i + 1,
14275 				       (long)ERRNO);
14276 			} else {
14277 				mg_cry(fc(ctx),
14278 				       "Cannot create threads: error %ld",
14279 				       (long)ERRNO);
14280 				free_context(ctx);
14281 				pthread_setspecific(sTlsKey, NULL);
14282 				return NULL;
14283 			}
14284 			break;
14285 		}
14286 	}
14287 
14288 	pthread_setspecific(sTlsKey, NULL);
14289 	return ctx;
14290 }
14291 
14292 
14293 /* Feature check API function */
14294 unsigned
14295 mg_check_feature(unsigned feature)
14296 {
14297 	static const unsigned feature_set = 0
14298 /* Set bits for available features according to API documentation.
14299  * This bit mask is created at compile time, according to the active
14300  * preprocessor defines. It is a single const value at runtime. */
14301 #if !defined(NO_FILES)
14302 	                                    | 0x0001u
14303 #endif
14304 #if !defined(NO_SSL)
14305 	                                    | 0x0002u
14306 #endif
14307 #if !defined(NO_CGI)
14308 	                                    | 0x0004u
14309 #endif
14310 #if defined(USE_IPV6)
14311 	                                    | 0x0008u
14312 #endif
14313 #if defined(USE_WEBSOCKET)
14314 	                                    | 0x0010u
14315 #endif
14316 #if defined(USE_LUA)
14317 	                                    | 0x0020u
14318 #endif
14319 #if defined(USE_DUKTAPE)
14320 	                                    | 0x0040u
14321 #endif
14322 #if !defined(NO_CACHING)
14323 	                                    | 0x0080u
14324 #endif
14325 
14326 /* Set some extra bits not defined in the API documentation.
14327  * These bits may change without further notice. */
14328 #if defined(MG_LEGACY_INTERFACE)
14329 	                                    | 0x8000u
14330 #endif
14331 #if defined(MEMORY_DEBUGGING)
14332 	                                    | 0x0100u
14333 #endif
14334 #if defined(USE_TIMERS)
14335 	                                    | 0x0200u
14336 #endif
14337 #if !defined(NO_NONCE_CHECK)
14338 	                                    | 0x0400u
14339 #endif
14340 #if !defined(NO_POPEN)
14341 	                                    | 0x0800u
14342 #endif
14343 	    ;
14344 	return (feature & feature_set);
14345 }
14346