]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/civetweb.c
update sources to v12.2.3
[ceph.git] / ceph / src / civetweb / src / civetweb.c
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
24 #if defined(_WIN32)
25 #if !defined(_CRT_SECURE_NO_WARNINGS)
26 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
27 #endif
28 #ifndef _WIN32_WINNT /* defined for tdm-gcc so we can use getnameinfo */
29 #define _WIN32_WINNT 0x0501
30 #endif
31 #else
32 #if defined(__GNUC__) && !defined(_GNU_SOURCE)
33 #define _GNU_SOURCE /* for setgroups() */
34 #endif
35 #if defined(__linux__) && !defined(_XOPEN_SOURCE)
36 #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
37 #endif
38 #ifndef _LARGEFILE_SOURCE
39 #define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
40 #endif
41 #ifndef _FILE_OFFSET_BITS
42 #define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
43 #endif
44 #ifndef __STDC_FORMAT_MACROS
45 #define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
46 #endif
47 #ifndef __STDC_LIMIT_MACROS
48 #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
49 #endif
50 #ifdef __sun
51 #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
52 #define __inline inline /* not recognized on older compiler versions */
53 #endif
54 #endif
55
56 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
57 #define USE_TIMERS
58 #endif
59
60 #if defined(_MSC_VER)
61 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
62 #pragma warning(disable : 4306)
63 /* conditional expression is constant: introduced by FD_SET(..) */
64 #pragma warning(disable : 4127)
65 /* non-constant aggregate initializer: issued due to missing C99 support */
66 #pragma warning(disable : 4204)
67 /* padding added after data member */
68 #pragma warning(disable : 4820)
69 /* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
70 #pragma warning(disable : 4668)
71 /* no function prototype given: converting '()' to '(void)' */
72 #pragma warning(disable : 4255)
73 /* function has been selected for automatic inline expansion */
74 #pragma warning(disable : 4711)
75 #endif
76
77
78 /* This code uses static_assert to check some conditions.
79 * Unfortunately some compilers still do not support it, so we have a
80 * replacement function here. */
81 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
82 #define mg_static_assert static_assert
83 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
84 #define mg_static_assert static_assert
85 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
86 #define mg_static_assert _Static_assert
87 #else
88 char static_assert_replacement[1];
89 #define mg_static_assert(cond, txt) \
90 extern char static_assert_replacement[(cond) ? 1 : -1]
91 #endif
92
93 mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
94 "int data type size check");
95 mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
96 "pointer data type size check");
97 mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
98 /* mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t data
99 * type size check"); */
100
101 /* DTL -- including winsock2.h works better if lean and mean */
102 #ifndef WIN32_LEAN_AND_MEAN
103 #define WIN32_LEAN_AND_MEAN
104 #endif
105
106 #if defined(__SYMBIAN32__)
107 #define NO_SSL /* SSL is not supported */
108 #define NO_CGI /* CGI is not supported */
109 #define PATH_MAX FILENAME_MAX
110 #endif /* __SYMBIAN32__ */
111
112
113 /* Include the header file here, so the CivetWeb interface is defined for the
114 * entire implementation, including the following forward definitions. */
115 #include "civetweb.h"
116
117
118 #ifndef IGNORE_UNUSED_RESULT
119 #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
120 #endif
121
122 #ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
123 #include <sys/types.h>
124 #include <sys/stat.h>
125 #include <errno.h>
126 #include <signal.h>
127 #include <fcntl.h>
128 #endif /* !_WIN32_WCE */
129
130 #ifdef __MACH__
131
132 #define CLOCK_MONOTONIC (1)
133 #define CLOCK_REALTIME (2)
134
135 #include <sys/time.h>
136 #include <mach/clock.h>
137 #include <mach/mach.h>
138 #include <mach/mach_time.h>
139 #include <assert.h>
140
141
142 /* clock_gettime is not implemented on OSX */
143 int clock_gettime(int clk_id, struct timespec *t);
144
145 int
146 clock_gettime(int clk_id, struct timespec *t)
147 {
148 memset(t, 0, sizeof(*t));
149 if (clk_id == CLOCK_REALTIME) {
150 struct timeval now;
151 int rv = gettimeofday(&now, NULL);
152 if (rv) {
153 return rv;
154 }
155 t->tv_sec = now.tv_sec;
156 t->tv_nsec = now.tv_usec * 1000;
157 return 0;
158
159 } else if (clk_id == CLOCK_MONOTONIC) {
160 static uint64_t clock_start_time = 0;
161 static mach_timebase_info_data_t timebase_ifo = {0, 0};
162
163 uint64_t now = mach_absolute_time();
164
165 if (clock_start_time == 0) {
166 kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
167 #if defined(DEBUG)
168 assert(mach_status == KERN_SUCCESS);
169 #else
170 /* appease "unused variable" warning for release builds */
171 (void)mach_status;
172 #endif
173 clock_start_time = now;
174 }
175
176 now = (uint64_t)((double)(now - clock_start_time)
177 * (double)timebase_ifo.numer
178 / (double)timebase_ifo.denom);
179
180 t->tv_sec = now / 1000000000;
181 t->tv_nsec = now % 1000000000;
182 return 0;
183 }
184 return -1; /* EINVAL - Clock ID is unknown */
185 }
186 #endif
187
188
189 #include <time.h>
190 #include <stdlib.h>
191 #include <stdarg.h>
192 #include <assert.h>
193 #include <string.h>
194 #include <ctype.h>
195 #include <limits.h>
196 #include <stddef.h>
197 #include <stdio.h>
198
199
200 #ifndef MAX_WORKER_THREADS
201 #define MAX_WORKER_THREADS (1024 * 64)
202 #endif
203 #ifndef SOCKET_TIMEOUT_QUANTUM
204 #define SOCKET_TIMEOUT_QUANTUM (10000)
205 #endif
206
207 mg_static_assert(MAX_WORKER_THREADS >= 1,
208 "worker threads must be a positive number");
209
210 #if defined(_WIN32) \
211 && !defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
212 #include <windows.h>
213 #include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
214 #include <ws2tcpip.h>
215
216 typedef const char *SOCK_OPT_TYPE;
217
218 #if !defined(PATH_MAX)
219 #define PATH_MAX (MAX_PATH)
220 #endif
221
222 #if !defined(PATH_MAX)
223 #define PATH_MAX (4096)
224 #endif
225
226 mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
227
228 #ifndef _IN_PORT_T
229 #ifndef in_port_t
230 #define in_port_t u_short
231 #endif
232 #endif
233
234 #ifndef _WIN32_WCE
235 #include <process.h>
236 #include <direct.h>
237 #include <io.h>
238 #else /* _WIN32_WCE */
239 #define NO_CGI /* WinCE has no pipes */
240
241 typedef long off_t;
242
243 #define errno ((int)(GetLastError()))
244 #define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
245 #endif /* _WIN32_WCE */
246
247 #define MAKEUQUAD(lo, hi) \
248 ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
249 #define RATE_DIFF (10000000) /* 100 nsecs */
250 #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
251 #define SYS2UNIX_TIME(lo, hi) \
252 ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
253
254 /* Visual Studio 6 does not know __func__ or __FUNCTION__
255 * The rest of MS compilers use __FUNCTION__, not C99 __func__
256 * Also use _strtoui64 on modern M$ compilers */
257 #if defined(_MSC_VER)
258 #if (_MSC_VER < 1300)
259 #define STRX(x) #x
260 #define STR(x) STRX(x)
261 #define __func__ __FILE__ ":" STR(__LINE__)
262 #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
263 #define strtoll(x, y, z) (_atoi64(x))
264 #else
265 #define __func__ __FUNCTION__
266 #define strtoull(x, y, z) (_strtoui64(x, y, z))
267 #define strtoll(x, y, z) (_strtoi64(x, y, z))
268 #endif
269 #endif /* _MSC_VER */
270
271 #define ERRNO ((int)(GetLastError()))
272 #define NO_SOCKLEN_T
273
274 #if defined(_WIN64) || defined(__MINGW64__)
275 #define SSL_LIB "ssleay64.dll"
276 #define CRYPTO_LIB "libeay64.dll"
277 #else
278 #define SSL_LIB "ssleay32.dll"
279 #define CRYPTO_LIB "libeay32.dll"
280 #endif
281
282 #define O_NONBLOCK (0)
283 #ifndef W_OK
284 #define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
285 #endif
286 #if !defined(EWOULDBLOCK)
287 #define EWOULDBLOCK WSAEWOULDBLOCK
288 #endif /* !EWOULDBLOCK */
289 #define _POSIX_
290 #define INT64_FMT "I64d"
291 #define UINT64_FMT "I64u"
292
293 #define WINCDECL __cdecl
294 #define SHUT_RD (0)
295 #define SHUT_WR (1)
296 #define SHUT_BOTH (2)
297 #define vsnprintf_impl _vsnprintf
298 #define access _access
299 #define mg_sleep(x) (Sleep(x))
300
301 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
302 #ifndef popen
303 #define popen(x, y) (_popen(x, y))
304 #endif
305 #ifndef pclose
306 #define pclose(x) (_pclose(x))
307 #endif
308 #define close(x) (_close(x))
309 #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
310 #define RTLD_LAZY (0)
311 #define fseeko(x, y, z) (_lseeki64(_fileno(x), (y), (z)) == -1 ? -1 : 0)
312 #define fdopen(x, y) (_fdopen((x), (y)))
313 #define write(x, y, z) (_write((x), (y), (unsigned)z))
314 #define read(x, y, z) (_read((x), (y), (unsigned)z))
315 #define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
316 #define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
317 #define sleep(x) (Sleep((x)*1000))
318 #define rmdir(x) (_rmdir(x))
319 #define timegm(x) (_mkgmtime(x))
320
321 #if !defined(fileno)
322 #define fileno(x) (_fileno(x))
323 #endif /* !fileno MINGW #defines fileno */
324
325 typedef HANDLE pthread_mutex_t;
326 typedef DWORD pthread_key_t;
327 typedef HANDLE pthread_t;
328 typedef struct {
329 CRITICAL_SECTION threadIdSec;
330 int waitingthreadcount; /* The number of threads queued. */
331 pthread_t *waitingthreadhdls; /* The thread handles. */
332 } pthread_cond_t;
333
334 #ifndef __clockid_t_defined
335 typedef DWORD clockid_t;
336 #endif
337 #ifndef CLOCK_MONOTONIC
338 #define CLOCK_MONOTONIC (1)
339 #endif
340 #ifndef CLOCK_REALTIME
341 #define CLOCK_REALTIME (2)
342 #endif
343
344 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
345 #define _TIMESPEC_DEFINED
346 #endif
347 #ifndef _TIMESPEC_DEFINED
348 struct timespec {
349 time_t tv_sec; /* seconds */
350 long tv_nsec; /* nanoseconds */
351 };
352 #endif
353
354 #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
355
356 static int pthread_mutex_lock(pthread_mutex_t *);
357 static int pthread_mutex_unlock(pthread_mutex_t *);
358 static void path_to_unicode(const struct mg_connection *conn,
359 const char *path,
360 wchar_t *wbuf,
361 size_t wbuf_len);
362 struct file;
363 static const char *
364 mg_fgets(char *buf, size_t size, struct file *filep, char **p);
365
366
367 #if defined(HAVE_STDINT)
368 #include <stdint.h>
369 #else
370 typedef unsigned char uint8_t;
371 typedef unsigned short uint16_t;
372 typedef unsigned int uint32_t;
373 typedef unsigned __int64 uint64_t;
374 typedef __int64 int64_t;
375 #define INT64_MAX (9223372036854775807)
376 #endif /* HAVE_STDINT */
377
378 /* POSIX dirent interface */
379 struct dirent {
380 char d_name[PATH_MAX];
381 };
382
383 typedef struct DIR {
384 HANDLE handle;
385 WIN32_FIND_DATAW info;
386 struct dirent result;
387 } DIR;
388
389 #if defined(_WIN32) && !defined(POLLIN)
390 #ifndef HAVE_POLL
391 struct pollfd {
392 SOCKET fd;
393 short events;
394 short revents;
395 };
396 #define POLLIN (0x0300)
397 #endif
398 #endif
399
400 /* Mark required libraries */
401 #if defined(_MSC_VER)
402 #pragma comment(lib, "Ws2_32.lib")
403 #endif
404
405 #else /* defined(_WIN32) && !defined(__SYMBIAN32__) - WINDOWS / UNIX include \
406 block */
407
408 #include <sys/wait.h>
409 #include <sys/socket.h>
410 #include <sys/poll.h>
411 #include <netinet/in.h>
412 #include <arpa/inet.h>
413 #include <sys/time.h>
414 #include <sys/utsname.h>
415 #include <stdint.h>
416 #include <inttypes.h>
417 #include <netdb.h>
418 #include <netinet/tcp.h>
419 typedef const void *SOCK_OPT_TYPE;
420
421 #if defined(ANDROID)
422 typedef unsigned short int in_port_t;
423 #endif
424
425 #include <pwd.h>
426 #include <unistd.h>
427 #include <grp.h>
428 #include <dirent.h>
429 #define vsnprintf_impl vsnprintf
430
431 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
432 #include <dlfcn.h>
433 #endif
434 #include <pthread.h>
435 #if defined(__MACH__)
436 #define SSL_LIB "libssl.dylib"
437 #define CRYPTO_LIB "libcrypto.dylib"
438 #else
439 #if !defined(SSL_LIB)
440 #define SSL_LIB "libssl.so"
441 #endif
442 #if !defined(CRYPTO_LIB)
443 #define CRYPTO_LIB "libcrypto.so"
444 #endif
445 #endif
446 #ifndef O_BINARY
447 #define O_BINARY (0)
448 #endif /* O_BINARY */
449 #define closesocket(a) (close(a))
450 #define mg_mkdir(conn, path, mode) (mkdir(path, mode))
451 #define mg_remove(conn, x) (remove(x))
452 #define mg_sleep(x) (usleep((x)*1000))
453 #define mg_opendir(conn, x) (opendir(x))
454 #define mg_closedir(x) (closedir(x))
455 #define mg_readdir(x) (readdir(x))
456 #define ERRNO (errno)
457 #define INVALID_SOCKET (-1)
458 #define INT64_FMT PRId64
459 #define UINT64_FMT PRIu64
460 typedef int SOCKET;
461 #define WINCDECL
462
463 #if defined(__hpux)
464 /* HPUX 11 does not have monotonic, fall back to realtime */
465 #ifndef CLOCK_MONOTONIC
466 #define CLOCK_MONOTONIC CLOCK_REALTIME
467 #endif
468
469 /* HPUX defines socklen_t incorrectly as size_t which is 64bit on
470 * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
471 * the prototypes use int* rather than socklen_t* which matches the
472 * actual library expectation. When called with the wrong size arg
473 * accept() returns a zero client inet addr and check_acl() always
474 * fails. Since socklen_t is widely used below, just force replace
475 * their typedef with int. - DTL
476 */
477 #define socklen_t int
478 #endif /* hpux */
479
480 #endif /* defined(_WIN32) && !defined(__SYMBIAN32__) - WINDOWS / UNIX include \
481 block */
482
483 /* va_copy should always be a macro, C99 and C++11 - DTL */
484 #ifndef va_copy
485 #define va_copy(x, y) ((x) = (y))
486 #endif
487
488 #ifdef _WIN32
489 /* Create substitutes for POSIX functions in Win32. */
490
491 #if defined(__MINGW32__)
492 /* Show no warning in case system functions are not used. */
493 #pragma GCC diagnostic push
494 #pragma GCC diagnostic ignored "-Wunused-function"
495 #endif
496
497
498 static CRITICAL_SECTION global_log_file_lock;
499 static DWORD
500 pthread_self(void)
501 {
502 return GetCurrentThreadId();
503 }
504
505
506 static int
507 pthread_key_create(
508 pthread_key_t *key,
509 void (*_ignored)(void *) /* destructor not supported for Windows */
510 )
511 {
512 (void)_ignored;
513
514 if ((key != 0)) {
515 *key = TlsAlloc();
516 return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
517 }
518 return -2;
519 }
520
521
522 static int
523 pthread_key_delete(pthread_key_t key)
524 {
525 return TlsFree(key) ? 0 : 1;
526 }
527
528
529 static int
530 pthread_setspecific(pthread_key_t key, void *value)
531 {
532 return TlsSetValue(key, value) ? 0 : 1;
533 }
534
535
536 static void *
537 pthread_getspecific(pthread_key_t key)
538 {
539 return TlsGetValue(key);
540 }
541
542 #if defined(__MINGW32__)
543 /* Enable unused function warning again */
544 #pragma GCC diagnostic pop
545 #endif
546
547 static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
548 #else
549 static pthread_mutexattr_t pthread_mutex_attr;
550 #endif /* _WIN32 */
551
552
553 #define PASSWORDS_FILE_NAME ".htpasswd"
554 #define CGI_ENVIRONMENT_SIZE (4096)
555 #define MAX_CGI_ENVIR_VARS (256)
556 #define MG_BUF_LEN (8192)
557
558 #ifndef MAX_REQUEST_SIZE
559 #define MAX_REQUEST_SIZE (16384)
560 #endif
561
562 mg_static_assert(MAX_REQUEST_SIZE >= 256,
563 "request size length must be a positive number");
564
565 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
566
567 #if !defined(DEBUG_TRACE)
568 #if defined(DEBUG)
569
570
571 static void DEBUG_TRACE_FUNC(const char *func,
572 unsigned line,
573 PRINTF_FORMAT_STRING(const char *fmt),
574 ...) PRINTF_ARGS(3, 4);
575
576 static void
577 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
578 {
579 va_list args;
580 flockfile(stdout);
581 printf("*** %lu.%p.%s.%u: ",
582 (unsigned long)time(NULL),
583 (void *)pthread_self(),
584 func,
585 line);
586 va_start(args, fmt);
587 vprintf(fmt, args);
588 va_end(args);
589 putchar('\n');
590 fflush(stdout);
591 funlockfile(stdout);
592 }
593
594 #define DEBUG_TRACE(fmt, ...) \
595 DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
596
597 #else
598 #define DEBUG_TRACE(fmt, ...) \
599 do { \
600 } while (0)
601 #endif /* DEBUG */
602 #endif /* DEBUG_TRACE */
603
604 #if defined(MEMORY_DEBUGGING)
605 unsigned long mg_memory_debug_blockCount = 0;
606 unsigned long mg_memory_debug_totalMemUsed = 0;
607
608
609 static void *
610 mg_malloc_ex(size_t size, const char *file, unsigned line)
611 {
612 void *data = malloc(size + sizeof(size_t));
613 void *memory = 0;
614 char mallocStr[256];
615
616 if (data) {
617 *(size_t *)data = size;
618 mg_memory_debug_totalMemUsed += size;
619 mg_memory_debug_blockCount++;
620 memory = (void *)(((char *)data) + sizeof(size_t));
621 }
622
623 sprintf(mallocStr,
624 "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
625 memory,
626 (unsigned long)size,
627 mg_memory_debug_totalMemUsed,
628 mg_memory_debug_blockCount,
629 file,
630 line);
631 #if defined(_WIN32)
632 OutputDebugStringA(mallocStr);
633 #else
634 DEBUG_TRACE("%s", mallocStr);
635 #endif
636
637 return memory;
638 }
639
640
641 static void *
642 mg_calloc_ex(size_t count, size_t size, const char *file, unsigned line)
643 {
644 void *data = mg_malloc_ex(size * count, file, line);
645 if (data) {
646 memset(data, 0, size);
647 }
648 return data;
649 }
650
651
652 static void
653 mg_free_ex(void *memory, const char *file, unsigned line)
654 {
655 char mallocStr[256];
656 void *data = (void *)(((char *)memory) - sizeof(size_t));
657 size_t size;
658
659 if (memory) {
660 size = *(size_t *)data;
661 mg_memory_debug_totalMemUsed -= size;
662 mg_memory_debug_blockCount--;
663 sprintf(mallocStr,
664 "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
665 memory,
666 (unsigned long)size,
667 mg_memory_debug_totalMemUsed,
668 mg_memory_debug_blockCount,
669 file,
670 line);
671 #if defined(_WIN32)
672 OutputDebugStringA(mallocStr);
673 #else
674 DEBUG_TRACE("%s", mallocStr);
675 #endif
676
677 free(data);
678 }
679 }
680
681
682 static void *
683 mg_realloc_ex(void *memory, size_t newsize, const char *file, unsigned line)
684 {
685 char mallocStr[256];
686 void *data;
687 void *_realloc;
688 size_t oldsize;
689
690 if (newsize) {
691 if (memory) {
692 data = (void *)(((char *)memory) - sizeof(size_t));
693 oldsize = *(size_t *)data;
694 _realloc = realloc(data, newsize + sizeof(size_t));
695 if (_realloc) {
696 data = _realloc;
697 mg_memory_debug_totalMemUsed -= oldsize;
698 sprintf(mallocStr,
699 "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
700 memory,
701 (unsigned long)oldsize,
702 mg_memory_debug_totalMemUsed,
703 mg_memory_debug_blockCount,
704 file,
705 line);
706 #if defined(_WIN32)
707 OutputDebugStringA(mallocStr);
708 #else
709 DEBUG_TRACE("%s", mallocStr);
710 #endif
711 mg_memory_debug_totalMemUsed += newsize;
712 sprintf(mallocStr,
713 "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
714 memory,
715 (unsigned long)newsize,
716 mg_memory_debug_totalMemUsed,
717 mg_memory_debug_blockCount,
718 file,
719 line);
720 #if defined(_WIN32)
721 OutputDebugStringA(mallocStr);
722 #else
723 DEBUG_TRACE("%s", mallocStr);
724 #endif
725 *(size_t *)data = newsize;
726 data = (void *)(((char *)data) + sizeof(size_t));
727 } else {
728 #if defined(_WIN32)
729 OutputDebugStringA("MEM: realloc failed\n");
730 #else
731 DEBUG_TRACE("%s", "MEM: realloc failed\n");
732 #endif
733 return _realloc;
734 }
735 } else {
736 data = mg_malloc_ex(newsize, file, line);
737 }
738 } else {
739 data = 0;
740 mg_free_ex(memory, file, line);
741 }
742
743 return data;
744 }
745
746 #define mg_malloc(a) mg_malloc_ex(a, __FILE__, __LINE__)
747 #define mg_calloc(a, b) mg_calloc_ex(a, b, __FILE__, __LINE__)
748 #define mg_realloc(a, b) mg_realloc_ex(a, b, __FILE__, __LINE__)
749 #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
750
751 #else
752
753 static __inline void *
754 mg_malloc(size_t a)
755 {
756 return malloc(a);
757 }
758
759 static __inline void *
760 mg_calloc(size_t a, size_t b)
761 {
762 return calloc(a, b);
763 }
764
765 static __inline void *
766 mg_realloc(void *a, size_t b)
767 {
768 return realloc(a, b);
769 }
770
771 static __inline void
772 mg_free(void *a)
773 {
774 free(a);
775 }
776
777 #endif
778
779
780 static void mg_vsnprintf(const struct mg_connection *conn,
781 int *truncated,
782 char *buf,
783 size_t buflen,
784 const char *fmt,
785 va_list ap);
786
787 static void mg_snprintf(const struct mg_connection *conn,
788 int *truncated,
789 char *buf,
790 size_t buflen,
791 PRINTF_FORMAT_STRING(const char *fmt),
792 ...) PRINTF_ARGS(5, 6);
793
794 /* This following lines are just meant as a reminder to use the mg-functions
795 * for memory management */
796 #ifdef malloc
797 #undef malloc
798 #endif
799 #ifdef calloc
800 #undef calloc
801 #endif
802 #ifdef realloc
803 #undef realloc
804 #endif
805 #ifdef free
806 #undef free
807 #endif
808 #ifdef snprintf
809 #undef snprintf
810 #endif
811 #ifdef vsnprintf
812 #undef vsnprintf
813 #endif
814 #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
815 #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
816 #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
817 #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
818 #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
819 #ifdef _WIN32 /* vsnprintf must not be used in any system, * \
820 * but this define only works well for Windows. */
821 #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
822 #endif
823
824 #define MD5_STATIC static
825 #include "md5.inl"
826
827 /* Darwin prior to 7.0 and Win32 do not have socklen_t */
828 #ifdef NO_SOCKLEN_T
829 typedef int socklen_t;
830 #endif /* NO_SOCKLEN_T */
831 #define _DARWIN_UNLIMITED_SELECT
832
833 #define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
834
835 #if !defined(MSG_NOSIGNAL)
836 #define MSG_NOSIGNAL (0)
837 #endif
838
839 #if !defined(SOMAXCONN)
840 #define SOMAXCONN (100)
841 #endif
842
843 /* Size of the accepted socket queue */
844 #if !defined(MGSQLEN)
845 #define MGSQLEN (20)
846 #endif
847
848 #if defined(NO_SSL_DL)
849 #include <openssl/ssl.h>
850 #include <openssl/err.h>
851 #include <openssl/crypto.h>
852 #include <openssl/x509.h>
853 #include <openssl/pem.h>
854 #else
855 /* SSL loaded dynamically from DLL.
856 * I put the prototypes here to be independent from OpenSSL source
857 * installation. */
858
859 typedef struct ssl_st SSL;
860 typedef struct ssl_method_st SSL_METHOD;
861 typedef struct ssl_ctx_st SSL_CTX;
862 typedef struct x509_store_ctx_st X509_STORE_CTX;
863
864 #define SSL_CTRL_OPTIONS (32)
865 #define SSL_CTRL_CLEAR_OPTIONS (77)
866 #define SSL_CTRL_SET_ECDH_AUTO (94)
867
868 #define SSL_VERIFY_NONE (0)
869 #define SSL_VERIFY_PEER (1)
870 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
871 #define SSL_VERIFY_CLIENT_ONCE (4)
872 #define SSL_OP_ALL ((long)(0x80000BFFUL))
873 #define SSL_OP_NO_SSLv2 (0x01000000L)
874 #define SSL_OP_NO_SSLv3 (0x02000000L)
875 #define SSL_OP_NO_TLSv1 (0x04000000L)
876 #define SSL_OP_NO_TLSv1_2 (0x08000000L)
877 #define SSL_OP_NO_TLSv1_1 (0x10000000L)
878 #define SSL_OP_SINGLE_DH_USE (0x00100000L)
879
880 struct ssl_func {
881 const char *name; /* SSL function name */
882 void (*ptr)(void); /* Function pointer */
883 };
884
885 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
886 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
887 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
888 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
889 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
890 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
891 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
892 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
893 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
894 #define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
895 #define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
896 #define SSL_CTX_use_PrivateKey_file \
897 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
898 #define SSL_CTX_use_certificate_file \
899 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
900 #define SSL_CTX_set_default_passwd_cb \
901 (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
902 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
903 #define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
904 #define SSL_CTX_use_certificate_chain_file \
905 (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
906 #define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr)
907 #define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
908 #define SSL_CTX_set_verify \
909 (*(void (*)(SSL_CTX *, \
910 int, \
911 int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19].ptr)
912 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
913 #define SSL_CTX_load_verify_locations \
914 (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
915 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
916 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
917 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr)
918 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
919 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr)
920 #define SSL_CIPHER_get_name \
921 (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
922 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
923 #define SSL_CTX_set_session_id_context \
924 (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
925 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
926 #define SSL_CTX_set_cipher_list \
927 (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
928 #define SSL_CTX_set_options(ctx, op) \
929 SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
930 #define SSL_CTX_clear_options(ctx, op) \
931 SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
932 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \
933 SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
934
935 #define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
936 #define CRYPTO_set_locking_callback \
937 (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
938 #define CRYPTO_set_id_callback \
939 (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
940 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
941 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
942 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
943 #define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
944 #define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
945 #define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
946 #define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
947 #define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
948
949
950 /* set_ssl_option() function updates this array.
951 * It loads SSL library dynamically and changes NULLs to the actual addresses
952 * of respective functions. The macros above (like SSL_connect()) are really
953 * just calling these functions indirectly via the pointer. */
954 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
955 {"SSL_accept", NULL},
956 {"SSL_connect", NULL},
957 {"SSL_read", NULL},
958 {"SSL_write", NULL},
959 {"SSL_get_error", NULL},
960 {"SSL_set_fd", NULL},
961 {"SSL_new", NULL},
962 {"SSL_CTX_new", NULL},
963 {"SSLv23_server_method", NULL},
964 {"SSL_library_init", NULL},
965 {"SSL_CTX_use_PrivateKey_file", NULL},
966 {"SSL_CTX_use_certificate_file", NULL},
967 {"SSL_CTX_set_default_passwd_cb", NULL},
968 {"SSL_CTX_free", NULL},
969 {"SSL_load_error_strings", NULL},
970 {"SSL_CTX_use_certificate_chain_file", NULL},
971 {"SSLv23_client_method", NULL},
972 {"SSL_pending", NULL},
973 {"SSL_CTX_set_verify", NULL},
974 {"SSL_shutdown", NULL},
975 {"SSL_CTX_load_verify_locations", NULL},
976 {"SSL_CTX_set_default_verify_paths", NULL},
977 {"SSL_CTX_set_verify_depth", NULL},
978 {"SSL_get_peer_certificate", NULL},
979 {"SSL_get_version", NULL},
980 {"SSL_get_current_cipher", NULL},
981 {"SSL_CIPHER_get_name", NULL},
982 {"SSL_CTX_check_private_key", NULL},
983 {"SSL_CTX_set_session_id_context", NULL},
984 {"SSL_CTX_ctrl", NULL},
985 {"SSL_CTX_set_cipher_list", NULL},
986 {NULL, NULL}};
987
988
989 /* Similar array as ssl_sw. These functions could be located in different
990 * lib. */
991 #if !defined(NO_SSL)
992 static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
993 {"CRYPTO_set_locking_callback", NULL},
994 {"CRYPTO_set_id_callback", NULL},
995 {"ERR_get_error", NULL},
996 {"ERR_error_string", NULL},
997 {"ERR_remove_state", NULL},
998 {"ERR_free_strings", NULL},
999 {"ENGINE_cleanup", NULL},
1000 {"CONF_modules_unload", NULL},
1001 {"CRYPTO_cleanup_all_ex_data", NULL},
1002 {"EVP_cleanup", NULL},
1003 {NULL, NULL}};
1004 #endif /* NO_SSL */
1005 #endif /* NO_SSL_DL */
1006
1007
1008 #if !defined(NO_CACHING)
1009 static const char *month_names[] = {"Jan",
1010 "Feb",
1011 "Mar",
1012 "Apr",
1013 "May",
1014 "Jun",
1015 "Jul",
1016 "Aug",
1017 "Sep",
1018 "Oct",
1019 "Nov",
1020 "Dec"};
1021 #endif /* !NO_CACHING */
1022
1023 /* Unified socket address. For IPv6 support, add IPv6 address structure in the
1024 * union u. */
1025 union usa {
1026 struct sockaddr sa;
1027 struct sockaddr_in sin;
1028 #if defined(USE_IPV6)
1029 struct sockaddr_in6 sin6;
1030 #endif
1031 };
1032
1033 /* Describes a string (chunk of memory). */
1034 struct vec {
1035 const char *ptr;
1036 size_t len;
1037 };
1038
1039 struct file {
1040 uint64_t size;
1041 time_t last_modified;
1042 FILE *fp;
1043 const char *membuf; /* Non-NULL if file data is in memory */
1044 int is_directory;
1045 int gzipped; /* set to 1 if the content is gzipped
1046 * in which case we need a content-encoding: gzip header */
1047 };
1048
1049 #define STRUCT_FILE_INITIALIZER \
1050 { \
1051 (uint64_t)0, (time_t)0, (FILE *)NULL, (const char *)NULL, 0, 0 \
1052 }
1053
1054 /* Describes listening socket, or socket which was accept()-ed by the master
1055 * thread and queued for future handling by the worker thread. */
1056 struct socket {
1057 SOCKET sock; /* Listening socket */
1058 union usa lsa; /* Local socket address */
1059 union usa rsa; /* Remote socket address */
1060 unsigned char is_ssl; /* Is port SSL-ed */
1061 unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
1062 * port */
1063 };
1064
1065 /* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
1066 enum {
1067 CGI_EXTENSIONS,
1068 CGI_ENVIRONMENT,
1069 PUT_DELETE_PASSWORDS_FILE,
1070 CGI_INTERPRETER,
1071 PROTECT_URI,
1072 AUTHENTICATION_DOMAIN,
1073 ENABLE_AUTH_DOMAIN_CHECK,
1074 SSI_EXTENSIONS,
1075 THROTTLE,
1076 ACCESS_LOG_FILE,
1077 ENABLE_DIRECTORY_LISTING,
1078 ERROR_LOG_FILE,
1079 GLOBAL_PASSWORDS_FILE,
1080 INDEX_FILES,
1081 ENABLE_KEEP_ALIVE,
1082 ACCESS_CONTROL_LIST,
1083 EXTRA_MIME_TYPES,
1084 LISTENING_PORTS,
1085 DOCUMENT_ROOT,
1086 SSL_CERTIFICATE,
1087 NUM_THREADS,
1088 RUN_AS_USER,
1089 REWRITE,
1090 HIDE_FILES,
1091 REQUEST_TIMEOUT,
1092 SSL_DO_VERIFY_PEER,
1093 SSL_CA_PATH,
1094 SSL_CA_FILE,
1095 SSL_VERIFY_DEPTH,
1096 SSL_DEFAULT_VERIFY_PATHS,
1097 SSL_CIPHER_LIST,
1098 SSL_PROTOCOL_VERSION,
1099 SSL_SHORT_TRUST,
1100 #if defined(USE_WEBSOCKET)
1101 WEBSOCKET_TIMEOUT,
1102 #endif
1103 DECODE_URL,
1104
1105 #if defined(USE_LUA)
1106 LUA_PRELOAD_FILE,
1107 LUA_SCRIPT_EXTENSIONS,
1108 LUA_SERVER_PAGE_EXTENSIONS,
1109 #endif
1110 #if defined(USE_DUKTAPE)
1111 DUKTAPE_SCRIPT_EXTENSIONS,
1112 #endif
1113
1114 #if defined(USE_WEBSOCKET)
1115 WEBSOCKET_ROOT,
1116 #endif
1117 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1118 LUA_WEBSOCKET_EXTENSIONS,
1119 #endif
1120 ACCESS_CONTROL_ALLOW_ORIGIN,
1121 ERROR_PAGES,
1122 CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
1123 * socket option typedef TCP_NODELAY. */
1124 #if !defined(NO_CACHING)
1125 STATIC_FILE_MAX_AGE,
1126 #endif
1127 VALIDATE_HTTP_METHOD,
1128 CANONICALIZE_URL_PATH,
1129
1130 NUM_OPTIONS
1131 };
1132
1133
1134 /* Config option name, config types, default value */
1135 static struct mg_option config_options[] = {
1136 {"cgi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
1137 {"cgi_environment", CONFIG_TYPE_STRING, NULL},
1138 {"put_delete_auth_file", CONFIG_TYPE_FILE, NULL},
1139 {"cgi_interpreter", CONFIG_TYPE_FILE, NULL},
1140 {"protect_uri", CONFIG_TYPE_STRING, NULL},
1141 {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"},
1142 {"enable_auth_domain_check", CONFIG_TYPE_BOOLEAN, "yes"},
1143 {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
1144 {"throttle", CONFIG_TYPE_STRING, NULL},
1145 {"access_log_file", CONFIG_TYPE_FILE, NULL},
1146 {"enable_directory_listing", CONFIG_TYPE_BOOLEAN, "yes"},
1147 {"error_log_file", CONFIG_TYPE_FILE, NULL},
1148 {"global_auth_file", CONFIG_TYPE_FILE, NULL},
1149 {"index_files",
1150 CONFIG_TYPE_STRING,
1151 #ifdef USE_LUA
1152 "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,"
1153 "index.shtml,index.php"},
1154 #else
1155 "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
1156 #endif
1157 {"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
1158 {"access_control_list", CONFIG_TYPE_STRING, NULL},
1159 {"extra_mime_types", CONFIG_TYPE_STRING, NULL},
1160 {"listening_ports", CONFIG_TYPE_STRING, "8080"},
1161 {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
1162 {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
1163 {"num_threads", CONFIG_TYPE_NUMBER, "50"},
1164 {"run_as_user", CONFIG_TYPE_STRING, NULL},
1165 {"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
1166 {"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
1167 {"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1168 {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
1169 {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
1170 {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
1171 {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
1172 {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
1173 {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
1174 {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
1175 {"ssl_short_trust", CONFIG_TYPE_BOOLEAN, "no"},
1176 #if defined(USE_WEBSOCKET)
1177 {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1178 #endif
1179 {"decode_url", CONFIG_TYPE_BOOLEAN, "yes"},
1180
1181 #if defined(USE_LUA)
1182 {"lua_preload_file", CONFIG_TYPE_FILE, NULL},
1183 {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1184 {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
1185 #endif
1186 #if defined(USE_DUKTAPE)
1187 /* The support for duktape is still in alpha version state.
1188 * The name of this config option might change. */
1189 {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
1190 #endif
1191
1192 #if defined(USE_WEBSOCKET)
1193 {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL},
1194 #endif
1195 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1196 {"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1197 #endif
1198 {"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
1199 {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
1200 {"tcp_nodelay", CONFIG_TYPE_NUMBER, "0"},
1201 #if !defined(NO_CACHING)
1202 {"static_file_max_age", CONFIG_TYPE_NUMBER, "3600"},
1203 #endif
1204 {"validate_http_method", CONFIG_TYPE_BOOLEAN, "yes"},
1205 {"canonicalize_url_path", CONFIG_TYPE_BOOLEAN, "yes"},
1206
1207 {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
1208
1209 /* Check if the config_options and the corresponding enum have compatible
1210 * sizes. */
1211 mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
1212 == (NUM_OPTIONS + 1),
1213 "config_options and enum not sync");
1214
1215 enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
1216
1217 struct mg_handler_info {
1218 /* Name/Pattern of the URI. */
1219 char *uri;
1220 size_t uri_len;
1221
1222 /* handler type */
1223 int handler_type;
1224
1225 /* Handler for http/https or authorization requests. */
1226 mg_request_handler handler;
1227
1228 /* Handler for ws/wss (websocket) requests. */
1229 mg_websocket_connect_handler connect_handler;
1230 mg_websocket_ready_handler ready_handler;
1231 mg_websocket_data_handler data_handler;
1232 mg_websocket_close_handler close_handler;
1233
1234 /* Handler for authorization requests */
1235 mg_authorization_handler auth_handler;
1236
1237 /* User supplied argument for the handler function. */
1238 void *cbdata;
1239
1240 /* next handler in a linked list */
1241 struct mg_handler_info *next;
1242 };
1243
1244 struct mg_context {
1245 volatile int stop_flag; /* Should we stop event loop */
1246 SSL_CTX *ssl_ctx; /* SSL context */
1247 char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
1248 struct mg_callbacks callbacks; /* User-defined callback function */
1249 void *user_data; /* User-defined data */
1250 int context_type; /* 1 = server context, 2 = client context */
1251
1252 struct socket *listening_sockets;
1253 in_port_t *listening_ports;
1254 unsigned int num_listening_sockets;
1255
1256 volatile int
1257 running_worker_threads; /* Number of currently running worker threads */
1258 pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
1259 pthread_cond_t thread_cond; /* Condvar for tracking workers terminations */
1260
1261 struct socket queue[MGSQLEN]; /* Accepted sockets */
1262 volatile int sq_head; /* Head of the socket queue */
1263 volatile int sq_tail; /* Tail of the socket queue */
1264 pthread_cond_t sq_full; /* Signaled when socket is produced */
1265 pthread_cond_t sq_empty; /* Signaled when socket is consumed */
1266 pthread_t masterthreadid; /* The master thread ID */
1267 unsigned int
1268 cfg_worker_threads; /* The number of configured worker threads. */
1269 pthread_t *workerthreadids; /* The worker thread IDs */
1270
1271 time_t start_time; /* Server start time, used for authentication */
1272 uint64_t auth_nonce_mask; /* Mask for all nonce values */
1273 pthread_mutex_t nonce_mutex; /* Protects nonce_count */
1274 unsigned long nonce_count; /* Used nonces, used for authentication */
1275
1276 char *systemName; /* What operating system is running */
1277
1278 /* linked list of uri handlers */
1279 struct mg_handler_info *handlers;
1280
1281 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1282 /* linked list of shared lua websockets */
1283 struct mg_shared_lua_websocket_list *shared_lua_websockets;
1284 #endif
1285
1286 #ifdef USE_TIMERS
1287 struct ttimers *timers;
1288 #endif
1289 };
1290
1291
1292 struct mg_connection {
1293 struct mg_request_info request_info;
1294 struct mg_context *ctx;
1295 SSL *ssl; /* SSL descriptor */
1296 SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
1297 struct socket client; /* Connected client */
1298 time_t conn_birth_time; /* Time (wall clock) when connection was
1299 * established */
1300 struct timespec req_time; /* Time (since system start) when the request
1301 * was received */
1302 int64_t num_bytes_sent; /* Total bytes sent to client */
1303 int64_t content_len; /* Content-Length header value */
1304 int64_t consumed_content; /* How many bytes of content have been read */
1305 int is_chunked; /* Transfer-Encoding is chunked: 0=no, 1=yes:
1306 * data available, 2: all data read */
1307 size_t chunk_remainder; /* Unread data from the last chunk */
1308 char *buf; /* Buffer for received data */
1309 char *path_info; /* PATH_INFO part of the URL */
1310
1311 int must_close; /* 1 if connection must be closed */
1312 int in_error_handler; /* 1 if in handler for user defined error
1313 * pages */
1314 int internal_error; /* 1 if an error occured while processing the
1315 * request */
1316
1317 int buf_size; /* Buffer size */
1318 int request_len; /* Size of the request + headers in a buffer */
1319 int data_len; /* Total size of data in a buffer */
1320 int status_code; /* HTTP reply status code, e.g. 200 */
1321 int throttle; /* Throttling, bytes/sec. <= 0 means no
1322 * throttle */
1323 time_t last_throttle_time; /* Last time throttled data was sent */
1324 int64_t last_throttle_bytes; /* Bytes sent this second */
1325 pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
1326 * atomic transmissions for websockets */
1327 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1328 void *lua_websocket_state; /* Lua_State for a websocket connection */
1329 #endif
1330 };
1331
1332
1333 static pthread_key_t sTlsKey; /* Thread local storage index */
1334 static int sTlsInit = 0;
1335 static int thread_idx_max = 0;
1336
1337
1338 struct mg_workerTLS {
1339 int is_master;
1340 unsigned long thread_idx;
1341 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1342 HANDLE pthread_cond_helper_mutex;
1343 #endif
1344 };
1345
1346 /* Directory entry */
1347 struct de {
1348 struct mg_connection *conn;
1349 char *file_name;
1350 struct file file;
1351 };
1352
1353
1354 #if defined(USE_WEBSOCKET)
1355 static int is_websocket_protocol(const struct mg_connection *conn);
1356 #else
1357 #define is_websocket_protocol(conn) (0)
1358 #endif
1359
1360
1361 static int
1362 mg_atomic_inc(volatile int *addr)
1363 {
1364 int ret;
1365 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1366 /* Depending on the SDK, this function uses either
1367 * (volatile unsigned int *) or (volatile LONG *),
1368 * so whatever you use, the other SDK is likely to raise a warning. */
1369 ret = InterlockedIncrement((volatile long *)addr);
1370 #elif defined(__GNUC__) \
1371 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1372 ret = __sync_add_and_fetch(addr, 1);
1373 #else
1374 ret = (++(*addr));
1375 #endif
1376 return ret;
1377 }
1378
1379
1380 static int
1381 mg_atomic_dec(volatile int *addr)
1382 {
1383 int ret;
1384 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1385 /* Depending on the SDK, this function uses either
1386 * (volatile unsigned int *) or (volatile LONG *),
1387 * so whatever you use, the other SDK is likely to raise a warning. */
1388 ret = InterlockedDecrement((volatile long *)addr);
1389 #elif defined(__GNUC__) \
1390 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1391 ret = __sync_sub_and_fetch(addr, 1);
1392 #else
1393 ret = (--(*addr));
1394 #endif
1395 return ret;
1396 }
1397
1398 #if !defined(NO_THREAD_NAME)
1399 #if defined(_WIN32) && defined(_MSC_VER)
1400 /* Set the thread name for debugging purposes in Visual Studio
1401 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
1402 */
1403 #pragma pack(push, 8)
1404 typedef struct tagTHREADNAME_INFO {
1405 DWORD dwType; /* Must be 0x1000. */
1406 LPCSTR szName; /* Pointer to name (in user addr space). */
1407 DWORD dwThreadID; /* Thread ID (-1=caller thread). */
1408 DWORD dwFlags; /* Reserved for future use, must be zero. */
1409 } THREADNAME_INFO;
1410 #pragma pack(pop)
1411 #elif defined(__linux__)
1412 #include <sys/prctl.h>
1413 #include <sys/sendfile.h>
1414 #endif
1415
1416
1417 static void
1418 mg_set_thread_name(const char *name)
1419 {
1420 char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
1421
1422 mg_snprintf(
1423 NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
1424
1425 #if defined(_WIN32)
1426 #if defined(_MSC_VER)
1427 /* Windows and Visual Studio Compiler */
1428 __try
1429 {
1430 THREADNAME_INFO info;
1431 info.dwType = 0x1000;
1432 info.szName = threadName;
1433 info.dwThreadID = ~0U;
1434 info.dwFlags = 0;
1435
1436 RaiseException(0x406D1388,
1437 0,
1438 sizeof(info) / sizeof(ULONG_PTR),
1439 (ULONG_PTR *)&info);
1440 }
1441 __except(EXCEPTION_EXECUTE_HANDLER)
1442 {
1443 }
1444 #elif defined(__MINGW32__)
1445 /* No option known to set thread name for MinGW */
1446 #endif
1447 #elif defined(__GLIBC__) \
1448 && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
1449 /* pthread_setname_np first appeared in glibc in version 2.12*/
1450 (void)pthread_setname_np(pthread_self(), threadName);
1451 #elif defined(__linux__)
1452 /* on linux we can use the old prctl function */
1453 (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
1454 #endif
1455 }
1456 #else /* !defined(NO_THREAD_NAME) */
1457 void
1458 mg_set_thread_name(const char *threadName)
1459 {
1460 }
1461 #endif
1462
1463
1464 #if defined(MG_LEGACY_INTERFACE)
1465 const char **
1466 mg_get_valid_option_names(void)
1467 {
1468 /* This function is deprecated. Use mg_get_valid_options instead. */
1469 static const char *
1470 data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
1471 int i;
1472
1473 for (i = 0; config_options[i].name != NULL; i++) {
1474 data[i * 2] = config_options[i].name;
1475 data[i * 2 + 1] = config_options[i].default_value;
1476 }
1477
1478 return data;
1479 }
1480 #endif
1481
1482
1483 const struct mg_option *
1484 mg_get_valid_options(void)
1485 {
1486 return config_options;
1487 }
1488
1489
1490 static int
1491 is_file_in_memory(const struct mg_connection *conn,
1492 const char *path,
1493 struct file *filep)
1494 {
1495 size_t size = 0;
1496 if (!conn || !filep) {
1497 return 0;
1498 }
1499
1500 if (conn->ctx->callbacks.open_file) {
1501 filep->membuf = conn->ctx->callbacks.open_file(conn, path, &size);
1502 if (filep->membuf != NULL) {
1503 /* NOTE: override filep->size only on success. Otherwise, it might
1504 * break constructs like if (!mg_stat() || !mg_fopen()) ... */
1505 filep->size = size;
1506 }
1507 }
1508
1509 return filep->membuf != NULL;
1510 }
1511
1512
1513 static int
1514 is_file_opened(const struct file *filep)
1515 {
1516 if (!filep) {
1517 return 0;
1518 }
1519
1520 return filep->membuf != NULL || filep->fp != NULL;
1521 }
1522
1523
1524 /* mg_fopen will open a file either in memory or on the disk.
1525 * The input parameter path is a string in UTF-8 encoding.
1526 * The input parameter mode is the same as for fopen.
1527 * Either fp or membuf will be set in the output struct filep.
1528 * The function returns 1 on success, 0 on error. */
1529 static int
1530 mg_fopen(const struct mg_connection *conn,
1531 const char *path,
1532 const char *mode,
1533 struct file *filep)
1534 {
1535 struct stat st;
1536
1537 if (!filep) {
1538 return 0;
1539 }
1540
1541 /* TODO (high): mg_fopen should only open a file, while mg_stat should
1542 * only get the file status. They should not work on different members of
1543 * the same structure (bad cohesion). */
1544 memset(filep, 0, sizeof(*filep));
1545
1546 if (stat(path, &st) == 0) {
1547 filep->size = (uint64_t)(st.st_size);
1548 }
1549
1550 if (!is_file_in_memory(conn, path, filep)) {
1551 #ifdef _WIN32
1552 wchar_t wbuf[PATH_MAX], wmode[20];
1553 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
1554 MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
1555 filep->fp = _wfopen(wbuf, wmode);
1556 #else
1557 /* Linux et al already use unicode. No need to convert. */
1558 filep->fp = fopen(path, mode);
1559 #endif
1560 }
1561
1562 return is_file_opened(filep);
1563 }
1564
1565
1566 static void
1567 mg_fclose(struct file *filep)
1568 {
1569 if (filep != NULL && filep->fp != NULL) {
1570 fclose(filep->fp);
1571 }
1572 }
1573
1574
1575 static void
1576 mg_strlcpy(register char *dst, register const char *src, size_t n)
1577 {
1578 for (; *src != '\0' && n > 1; n--) {
1579 *dst++ = *src++;
1580 }
1581 *dst = '\0';
1582 }
1583
1584
1585 static int
1586 lowercase(const char *s)
1587 {
1588 return tolower(*(const unsigned char *)s);
1589 }
1590
1591
1592 int
1593 mg_strncasecmp(const char *s1, const char *s2, size_t len)
1594 {
1595 int diff = 0;
1596
1597 if (len > 0) {
1598 do {
1599 diff = lowercase(s1++) - lowercase(s2++);
1600 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
1601 }
1602
1603 return diff;
1604 }
1605
1606
1607 int
1608 mg_strcasecmp(const char *s1, const char *s2)
1609 {
1610 int diff;
1611
1612 do {
1613 diff = lowercase(s1++) - lowercase(s2++);
1614 } while (diff == 0 && s1[-1] != '\0');
1615
1616 return diff;
1617 }
1618
1619
1620 static char *
1621 mg_strndup(const char *ptr, size_t len)
1622 {
1623 char *p;
1624
1625 if ((p = (char *)mg_malloc(len + 1)) != NULL) {
1626 mg_strlcpy(p, ptr, len + 1);
1627 }
1628
1629 return p;
1630 }
1631
1632
1633 static char *
1634 mg_strdup(const char *str)
1635 {
1636 return mg_strndup(str, strlen(str));
1637 }
1638
1639
1640 static const char *
1641 mg_strcasestr(const char *big_str, const char *small_str)
1642 {
1643 size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
1644
1645 if (big_len >= small_len) {
1646 for (i = 0; i <= (big_len - small_len); i++) {
1647 if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
1648 return big_str + i;
1649 }
1650 }
1651 }
1652
1653 return NULL;
1654 }
1655
1656
1657 /* Return null terminated string of given maximum length.
1658 * Report errors if length is exceeded. */
1659 static void
1660 mg_vsnprintf(const struct mg_connection *conn,
1661 int *truncated,
1662 char *buf,
1663 size_t buflen,
1664 const char *fmt,
1665 va_list ap)
1666 {
1667 int n, ok;
1668
1669 if (buflen == 0) {
1670 return;
1671 }
1672
1673 #ifdef __clang__
1674 #pragma clang diagnostic push
1675 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1676 /* Using fmt as a non-literal is intended here, since it is mostly called
1677 * indirectly by mg_snprintf */
1678 #endif
1679
1680 n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
1681 ok = (n >= 0) && ((size_t)n < buflen);
1682
1683 #ifdef __clang__
1684 #pragma clang diagnostic pop
1685 #endif
1686
1687 if (ok) {
1688 if (truncated) {
1689 *truncated = 0;
1690 }
1691 } else {
1692 if (truncated) {
1693 *truncated = 1;
1694 }
1695 mg_cry(conn,
1696 "truncating vsnprintf buffer: [%.*s]",
1697 (int)((buflen > 200) ? 200 : (buflen - 1)),
1698 buf);
1699 n = (int)buflen - 1;
1700 }
1701 buf[n] = '\0';
1702 }
1703
1704
1705 static void
1706 mg_snprintf(const struct mg_connection *conn,
1707 int *truncated,
1708 char *buf,
1709 size_t buflen,
1710 const char *fmt,
1711 ...)
1712 {
1713 va_list ap;
1714
1715 va_start(ap, fmt);
1716 mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
1717 va_end(ap);
1718 }
1719
1720
1721 static int
1722 get_option_index(const char *name)
1723 {
1724 int i;
1725
1726 for (i = 0; config_options[i].name != NULL; i++) {
1727 if (strcmp(config_options[i].name, name) == 0) {
1728 return i;
1729 }
1730 }
1731 return -1;
1732 }
1733
1734
1735 const char *
1736 mg_get_option(const struct mg_context *ctx, const char *name)
1737 {
1738 int i;
1739 if ((i = get_option_index(name)) == -1) {
1740 return NULL;
1741 } else if (!ctx || ctx->config[i] == NULL) {
1742 return "";
1743 } else {
1744 return ctx->config[i];
1745 }
1746 }
1747
1748
1749 struct mg_context *
1750 mg_get_context(const struct mg_connection *conn)
1751 {
1752 return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
1753 }
1754
1755
1756 void *
1757 mg_get_user_data(const struct mg_context *ctx)
1758 {
1759 return (ctx == NULL) ? NULL : ctx->user_data;
1760 }
1761
1762
1763 void
1764 mg_set_user_connection_data(struct mg_connection *conn, void *data)
1765 {
1766 if (conn != NULL) {
1767 conn->request_info.conn_data = data;
1768 }
1769 }
1770
1771
1772 void *
1773 mg_get_user_connection_data(const struct mg_connection *conn)
1774 {
1775 if (conn != NULL) {
1776 return conn->request_info.conn_data;
1777 }
1778 return NULL;
1779 }
1780
1781
1782 size_t
1783 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
1784 {
1785 size_t i;
1786 if (!ctx) {
1787 return 0;
1788 }
1789 for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
1790 ssl[i] = ctx->listening_sockets[i].is_ssl;
1791 ports[i] = ctx->listening_ports[i];
1792 }
1793 return i;
1794 }
1795
1796
1797 int
1798 mg_get_server_ports(const struct mg_context *ctx,
1799 int size,
1800 struct mg_server_ports *ports)
1801 {
1802 int i, cnt = 0;
1803
1804 if (size <= 0) {
1805 return -1;
1806 }
1807 memset(ports, 0, sizeof(*ports) * (size_t)size);
1808 if (!ctx) {
1809 return -1;
1810 }
1811 if (!ctx->listening_sockets || !ctx->listening_ports) {
1812 return -1;
1813 }
1814
1815 for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
1816
1817 ports[cnt].port = ctx->listening_ports[i];
1818 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
1819 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
1820
1821 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
1822 /* IPv4 */
1823 ports[cnt].protocol = 1;
1824 cnt++;
1825 } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
1826 /* IPv6 */
1827 ports[cnt].protocol = 3;
1828 cnt++;
1829 }
1830 }
1831
1832 return cnt;
1833 }
1834
1835
1836 static void
1837 sockaddr_to_string(char *buf, size_t len, const union usa *usa)
1838 {
1839 buf[0] = '\0';
1840
1841 if (!usa) {
1842 return;
1843 }
1844
1845 if (usa->sa.sa_family == AF_INET) {
1846 getnameinfo(&usa->sa,
1847 sizeof(usa->sin),
1848 buf,
1849 (unsigned)len,
1850 NULL,
1851 0,
1852 NI_NUMERICHOST);
1853 }
1854 #if defined(USE_IPV6)
1855 else if (usa->sa.sa_family == AF_INET6) {
1856 getnameinfo(&usa->sa,
1857 sizeof(usa->sin6),
1858 buf,
1859 (unsigned)len,
1860 NULL,
1861 0,
1862 NI_NUMERICHOST);
1863 }
1864 #endif
1865 }
1866
1867
1868 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
1869 * included in all responses other than 100, 101, 5xx. */
1870 static void
1871 gmt_time_string(char *buf, size_t buf_len, time_t *t)
1872 {
1873 struct tm *tm;
1874
1875 tm = ((t != NULL) ? gmtime(t) : NULL);
1876 if (tm != NULL) {
1877 strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
1878 } else {
1879 mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
1880 buf[buf_len - 1] = '\0';
1881 }
1882 }
1883
1884
1885 /* difftime for struct timespec. Return value is in seconds. */
1886 static double
1887 mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
1888 {
1889 return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
1890 + (double)(ts_now->tv_sec - ts_before->tv_sec);
1891 }
1892
1893
1894 /* Print error message to the opened error log stream. */
1895 void
1896 mg_cry(const struct mg_connection *conn, const char *fmt, ...)
1897 {
1898 char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
1899 va_list ap;
1900 struct file fi;
1901 time_t timestamp;
1902
1903 va_start(ap, fmt);
1904 IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
1905 va_end(ap);
1906 buf[sizeof(buf) - 1] = 0;
1907
1908 if (!conn) {
1909 puts(buf);
1910 return;
1911 }
1912
1913 /* Do not lock when getting the callback value, here and below.
1914 * I suppose this is fine, since function cannot disappear in the
1915 * same way string option can. */
1916 if ((conn->ctx->callbacks.log_message == NULL)
1917 || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
1918
1919 if (conn->ctx->config[ERROR_LOG_FILE] != NULL) {
1920 if (mg_fopen(conn, conn->ctx->config[ERROR_LOG_FILE], "a+", &fi)
1921 == 0) {
1922 fi.fp = NULL;
1923 }
1924 } else {
1925 fi.fp = NULL;
1926 }
1927
1928 if (fi.fp != NULL) {
1929 flockfile(fi.fp);
1930 timestamp = time(NULL);
1931
1932 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
1933 fprintf(fi.fp,
1934 "[%010lu] [error] [client %s] ",
1935 (unsigned long)timestamp,
1936 src_addr);
1937
1938 if (conn->request_info.request_method != NULL) {
1939 fprintf(fi.fp,
1940 "%s %s: ",
1941 conn->request_info.request_method,
1942 conn->request_info.request_uri);
1943 }
1944
1945 fprintf(fi.fp, "%s", buf);
1946 fputc('\n', fi.fp);
1947 fflush(fi.fp);
1948 funlockfile(fi.fp);
1949 mg_fclose(&fi);
1950 }
1951 }
1952 }
1953
1954 void
1955 mg_set_http_status(struct mg_connection *conn, int status)
1956 {
1957 conn->status_code = status;
1958 }
1959
1960 /* Return fake connection structure. Used for logging, if connection
1961 * is not applicable at the moment of logging. */
1962 static struct mg_connection *
1963 fc(struct mg_context *ctx)
1964 {
1965 static struct mg_connection fake_connection;
1966 fake_connection.ctx = ctx;
1967 return &fake_connection;
1968 }
1969
1970
1971 const char *
1972 mg_version(void)
1973 {
1974 return CIVETWEB_VERSION;
1975 }
1976
1977
1978 const struct mg_request_info *
1979 mg_get_request_info(const struct mg_connection *conn)
1980 {
1981 if (!conn) {
1982 return NULL;
1983 }
1984 return &conn->request_info;
1985 }
1986
1987
1988 struct sockaddr *
1989 mg_get_local_addr(struct mg_connection *conn)
1990 {
1991 return &conn->client.lsa.sa;
1992 }
1993
1994
1995 /* Skip the characters until one of the delimiters characters found.
1996 * 0-terminate resulting word. Skip the delimiter and following whitespaces.
1997 * Advance pointer to buffer to the next word. Return found 0-terminated word.
1998 * Delimiters can be quoted with quotechar. */
1999 static char *
2000 skip_quoted(char **buf,
2001 const char *delimiters,
2002 const char *whitespace,
2003 char quotechar)
2004 {
2005 char *p, *begin_word, *end_word, *end_whitespace;
2006
2007 begin_word = *buf;
2008 end_word = begin_word + strcspn(begin_word, delimiters);
2009
2010 /* Check for quotechar */
2011 if (end_word > begin_word) {
2012 p = end_word - 1;
2013 while (*p == quotechar) {
2014 /* While the delimiter is quoted, look for the next delimiter. */
2015 /* This happens, e.g., in calls from parse_auth_header,
2016 * if the user name contains a " character. */
2017
2018 /* If there is anything beyond end_word, copy it. */
2019 if (*end_word != '\0') {
2020 size_t end_off = strcspn(end_word + 1, delimiters);
2021 memmove(p, end_word, end_off + 1);
2022 p += end_off; /* p must correspond to end_word - 1 */
2023 end_word += end_off + 1;
2024 } else {
2025 *p = '\0';
2026 break;
2027 }
2028 }
2029 for (p++; p < end_word; p++) {
2030 *p = '\0';
2031 }
2032 }
2033
2034 if (*end_word == '\0') {
2035 *buf = end_word;
2036 } else {
2037 end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
2038
2039 for (p = end_word; p < end_whitespace; p++) {
2040 *p = '\0';
2041 }
2042
2043 *buf = end_whitespace;
2044 }
2045
2046 return begin_word;
2047 }
2048
2049
2050 /* Simplified version of skip_quoted without quote char
2051 * and whitespace == delimiters */
2052 static char *
2053 skip(char **buf, const char *delimiters)
2054 {
2055 return skip_quoted(buf, delimiters, delimiters, 0);
2056 }
2057
2058
2059 /* Return HTTP header value, or NULL if not found. */
2060 static const char *
2061 get_header(const struct mg_request_info *ri, const char *name)
2062 {
2063 int i;
2064 if (ri) {
2065 for (i = 0; i < ri->num_headers; i++) {
2066 if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
2067 return ri->http_headers[i].value;
2068 }
2069 }
2070 }
2071
2072 return NULL;
2073 }
2074
2075
2076 const char *
2077 mg_get_header(const struct mg_connection *conn, const char *name)
2078 {
2079 if (!conn) {
2080 return NULL;
2081 }
2082
2083 return get_header(&conn->request_info, name);
2084 }
2085
2086
2087 /* A helper function for traversing a comma separated list of values.
2088 * It returns a list pointer shifted to the next value, or NULL if the end
2089 * of the list found.
2090 * Value is stored in val vector. If value has form "x=y", then eq_val
2091 * vector is initialized to point to the "y" part, and val vector length
2092 * is adjusted to point only to "x". */
2093 static const char *
2094 next_option(const char *list, struct vec *val, struct vec *eq_val)
2095 {
2096 int end;
2097
2098 reparse:
2099 if (val == NULL || list == NULL || *list == '\0') {
2100 /* End of the list */
2101 list = NULL;
2102 } else {
2103 /* Skip over leading LWS */
2104 while (*list == ' ' || *list == '\t')
2105 list++;
2106
2107 val->ptr = list;
2108 if ((list = strchr(val->ptr, ',')) != NULL) {
2109 /* Comma found. Store length and shift the list ptr */
2110 val->len = ((size_t)(list - val->ptr));
2111 list++;
2112 } else {
2113 /* This value is the last one */
2114 list = val->ptr + strlen(val->ptr);
2115 val->len = ((size_t)(list - val->ptr));
2116 }
2117
2118 /* Adjust length for trailing LWS */
2119 end = (int)val->len - 1;
2120 while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t'))
2121 end--;
2122 val->len = (size_t)(end + 1);
2123
2124 if (val->len == 0) {
2125 /* Ignore any empty entries. */
2126 goto reparse;
2127 }
2128
2129 if (eq_val != NULL) {
2130 /* Value has form "x=y", adjust pointers and lengths
2131 * so that val points to "x", and eq_val points to "y". */
2132 eq_val->len = 0;
2133 eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
2134 if (eq_val->ptr != NULL) {
2135 eq_val->ptr++; /* Skip over '=' character */
2136 eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
2137 val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
2138 }
2139 }
2140 }
2141
2142 return list;
2143 }
2144
2145 /* A helper function for checking if a comma separated list of values contains
2146 * the given option (case insensitvely).
2147 * 'header' can be NULL, in which case false is returned. */
2148 static int
2149 header_has_option(const char *header, const char *option)
2150 {
2151 struct vec opt_vec;
2152 struct vec eq_vec;
2153
2154 assert(option != NULL);
2155 assert(option[0] != '\0');
2156
2157 while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
2158 if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
2159 return 1;
2160 }
2161
2162 return 0;
2163 }
2164
2165 /* Perform case-insensitive match of string against pattern */
2166 static int
2167 match_prefix(const char *pattern, size_t pattern_len, const char *str)
2168 {
2169 const char *or_str;
2170 size_t i;
2171 int j, len, res;
2172
2173 if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
2174 res = match_prefix(pattern, (size_t)(or_str - pattern), str);
2175 return res > 0 ? res : match_prefix(or_str + 1,
2176 (size_t)((pattern + pattern_len)
2177 - (or_str + 1)),
2178 str);
2179 }
2180
2181 for (i = 0, j = 0; i < pattern_len; i++, j++) {
2182 if (pattern[i] == '?' && str[j] != '\0') {
2183 continue;
2184 } else if (pattern[i] == '$') {
2185 return str[j] == '\0' ? j : -1;
2186 } else if (pattern[i] == '*') {
2187 i++;
2188 if (pattern[i] == '*') {
2189 i++;
2190 len = (int)strlen(str + j);
2191 } else {
2192 len = (int)strcspn(str + j, "/");
2193 }
2194 if (i == pattern_len) {
2195 return j + len;
2196 }
2197 do {
2198 res = match_prefix(pattern + i, pattern_len - i, str + j + len);
2199 } while (res == -1 && len-- > 0);
2200 return res == -1 ? -1 : j + res + len;
2201 } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
2202 return -1;
2203 }
2204 }
2205 return j;
2206 }
2207
2208
2209 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
2210 * This function must tolerate situations when connection info is not
2211 * set up, for example if request parsing failed. */
2212 static int
2213 should_keep_alive(const struct mg_connection *conn)
2214 {
2215 if (conn != NULL) {
2216 const char *http_version = conn->request_info.http_version;
2217 const char *header = mg_get_header(conn, "Connection");
2218 if (conn->must_close || conn->internal_error || conn->status_code == 401
2219 || mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0
2220 || (header != NULL && !header_has_option(header, "keep-alive"))
2221 || (header == NULL && http_version
2222 && 0 != strcmp(http_version, "1.1"))) {
2223 return 0;
2224 }
2225 return 1;
2226 }
2227 return 0;
2228 }
2229
2230
2231 static int
2232 should_decode_url(const struct mg_connection *conn)
2233 {
2234 if (!conn || !conn->ctx) {
2235 return 0;
2236 }
2237
2238 return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
2239 }
2240
2241 static int
2242 should_validate_http_method(const struct mg_connection *conn)
2243 {
2244 if (!conn || !conn->ctx || !conn->ctx->config[VALIDATE_HTTP_METHOD]) {
2245 return 1;
2246 }
2247
2248 return (mg_strcasecmp(conn->ctx->config[VALIDATE_HTTP_METHOD], "yes") == 0);
2249 }
2250
2251
2252 static const char *
2253 suggest_connection_header(const struct mg_connection *conn)
2254 {
2255 return should_keep_alive(conn) ? "keep-alive" : "close";
2256 }
2257
2258
2259 static int
2260 send_no_cache_header(struct mg_connection *conn)
2261 {
2262 /* Send all current and obsolete cache opt-out directives. */
2263 return mg_printf(conn,
2264 "Cache-Control: no-cache, no-store, "
2265 "must-revalidate, private, max-age=0\r\n"
2266 "Pragma: no-cache\r\n"
2267 "Expires: 0\r\n");
2268 }
2269
2270
2271 static int
2272 send_static_cache_header(struct mg_connection *conn)
2273 {
2274 #if !defined(NO_CACHING)
2275 /* Read the server config to check how long a file may be cached.
2276 * The configuration is in seconds. */
2277 int max_age = atoi(conn->ctx->config[STATIC_FILE_MAX_AGE]);
2278 if (max_age <= 0) {
2279 /* 0 means "do not cache". All values <0 are reserved
2280 * and may be used differently in the future. */
2281 /* If a file should not be cached, do not only send
2282 * max-age=0, but also pragmas and Expires headers. */
2283 return send_no_cache_header(conn);
2284 }
2285
2286 /* Use "Cache-Control: max-age" instead of "Expires" header.
2287 * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
2288 /* See also https://www.mnot.net/cache_docs/ */
2289 /* According to RFC 2616, Section 14.21, caching times should not exceed
2290 * one year. A year with 365 days corresponds to 31536000 seconds, a leap
2291 * year to 31622400 seconds. For the moment, we just send whatever has
2292 * been configured, still the behavior for >1 year should be considered
2293 * as undefined. */
2294 return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
2295 #else /* NO_CACHING */
2296 return send_no_cache_header(conn);
2297 #endif /* !NO_CACHING */
2298 }
2299
2300
2301 static void handle_file_based_request(struct mg_connection *conn,
2302 const char *path,
2303 struct file *filep);
2304
2305 static int
2306 mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
2307
2308
2309 const char *
2310 mg_get_response_code_text(struct mg_connection *conn, int response_code)
2311 {
2312 /* See IANA HTTP status code assignment:
2313 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
2314 */
2315
2316 switch (response_code) {
2317 /* RFC2616 Section 10.1 - Informational 1xx */
2318 case 100:
2319 return "Continue"; /* RFC2616 Section 10.1.1 */
2320 case 101:
2321 return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
2322 case 102:
2323 return "Processing"; /* RFC2518 Section 10.1 */
2324
2325 /* RFC2616 Section 10.2 - Successful 2xx */
2326 case 200:
2327 return "OK"; /* RFC2616 Section 10.2.1 */
2328 case 201:
2329 return "Created"; /* RFC2616 Section 10.2.2 */
2330 case 202:
2331 return "Accepted"; /* RFC2616 Section 10.2.3 */
2332 case 203:
2333 return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
2334 case 204:
2335 return "No Content"; /* RFC2616 Section 10.2.5 */
2336 case 205:
2337 return "Reset Content"; /* RFC2616 Section 10.2.6 */
2338 case 206:
2339 return "Partial Content"; /* RFC2616 Section 10.2.7 */
2340 case 207:
2341 return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
2342 case 208:
2343 return "Already Reported"; /* RFC5842 Section 7.1 */
2344
2345 case 226:
2346 return "IM used"; /* RFC3229 Section 10.4.1 */
2347
2348 /* RFC2616 Section 10.3 - Redirection 3xx */
2349 case 300:
2350 return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
2351 case 301:
2352 return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
2353 case 302:
2354 return "Found"; /* RFC2616 Section 10.3.3 */
2355 case 303:
2356 return "See Other"; /* RFC2616 Section 10.3.4 */
2357 case 304:
2358 return "Not Modified"; /* RFC2616 Section 10.3.5 */
2359 case 305:
2360 return "Use Proxy"; /* RFC2616 Section 10.3.6 */
2361 case 307:
2362 return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
2363 case 308:
2364 return "Permanent Redirect"; /* RFC7238 Section 3 */
2365
2366 /* RFC2616 Section 10.4 - Client Error 4xx */
2367 case 400:
2368 return "Bad Request"; /* RFC2616 Section 10.4.1 */
2369 case 401:
2370 return "Unauthorized"; /* RFC2616 Section 10.4.2 */
2371 case 402:
2372 return "Payment Required"; /* RFC2616 Section 10.4.3 */
2373 case 403:
2374 return "Forbidden"; /* RFC2616 Section 10.4.4 */
2375 case 404:
2376 return "Not Found"; /* RFC2616 Section 10.4.5 */
2377 case 405:
2378 return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
2379 case 406:
2380 return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
2381 case 407:
2382 return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
2383 case 408:
2384 return "Request Time-out"; /* RFC2616 Section 10.4.9 */
2385 case 409:
2386 return "Conflict"; /* RFC2616 Section 10.4.10 */
2387 case 410:
2388 return "Gone"; /* RFC2616 Section 10.4.11 */
2389 case 411:
2390 return "Length Required"; /* RFC2616 Section 10.4.12 */
2391 case 412:
2392 return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
2393 case 413:
2394 return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
2395 case 414:
2396 return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
2397 case 415:
2398 return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
2399 case 416:
2400 return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
2401 case 417:
2402 return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
2403
2404 case 421:
2405 return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
2406 case 422:
2407 return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
2408 * Section 11.2 */
2409 case 423:
2410 return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
2411 case 424:
2412 return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
2413 * Section 11.4 */
2414
2415 case 426:
2416 return "Upgrade Required"; /* RFC 2817 Section 4 */
2417
2418 case 428:
2419 return "Precondition Required"; /* RFC 6585, Section 3 */
2420 case 429:
2421 return "Too Many Requests"; /* RFC 6585, Section 4 */
2422
2423 case 431:
2424 return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
2425
2426 case 451:
2427 return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
2428 * Section 3 */
2429
2430 /* RFC2616 Section 10.5 - Server Error 5xx */
2431 case 500:
2432 return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
2433 case 501:
2434 return "Not Implemented"; /* RFC2616 Section 10.5.2 */
2435 case 502:
2436 return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
2437 case 503:
2438 return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
2439 case 504:
2440 return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
2441 case 505:
2442 return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
2443 case 506:
2444 return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
2445 case 507:
2446 return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
2447 * Section 11.5 */
2448 case 508:
2449 return "Loop Detected"; /* RFC5842 Section 7.1 */
2450
2451 case 510:
2452 return "Not Extended"; /* RFC 2774, Section 7 */
2453 case 511:
2454 return "Network Authentication Required"; /* RFC 6585, Section 6 */
2455
2456 /* Other status codes, not shown in the IANA HTTP status code assignment.
2457 * E.g., "de facto" standards due to common use, ... */
2458 case 418:
2459 return "I am a teapot"; /* RFC2324 Section 2.3.2 */
2460 case 419:
2461 return "Authentication Timeout"; /* common use */
2462 case 420:
2463 return "Enhance Your Calm"; /* common use */
2464 case 440:
2465 return "Login Timeout"; /* common use */
2466 case 509:
2467 return "Bandwidth Limit Exceeded"; /* common use */
2468
2469 default:
2470 /* This error code is unknown. This should not happen. */
2471 if (conn) {
2472 mg_cry(conn, "Unknown HTTP response code: %u", response_code);
2473 }
2474
2475 /* Return at least a category according to RFC 2616 Section 10. */
2476 if (response_code >= 100 && response_code < 200) {
2477 /* Unknown informational status code */
2478 return "Information";
2479 }
2480 if (response_code >= 200 && response_code < 300) {
2481 /* Unknown success code */
2482 return "Success";
2483 }
2484 if (response_code >= 300 && response_code < 400) {
2485 /* Unknown redirection code */
2486 return "Redirection";
2487 }
2488 if (response_code >= 400 && response_code < 500) {
2489 /* Unknown request error code */
2490 return "Client Error";
2491 }
2492 if (response_code >= 500 && response_code < 600) {
2493 /* Unknown server error code */
2494 return "Server Error";
2495 }
2496
2497 /* Response code not even within reasonable range */
2498 return "";
2499 }
2500 }
2501
2502
2503 static void send_http_error(struct mg_connection *,
2504 int,
2505 PRINTF_FORMAT_STRING(const char *fmt),
2506 ...) PRINTF_ARGS(3, 4);
2507
2508 static void
2509 send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
2510 {
2511 char buf[MG_BUF_LEN];
2512 va_list ap;
2513 int len, i, page_handler_found, scope, truncated;
2514 char date[64];
2515 time_t curtime = time(NULL);
2516 const char *error_handler = NULL;
2517 struct file error_page_file = STRUCT_FILE_INITIALIZER;
2518 const char *error_page_file_ext, *tstr;
2519
2520 const char *status_text = mg_get_response_code_text(conn, status);
2521
2522 if (conn == NULL) {
2523 return;
2524 }
2525
2526 conn->status_code = status;
2527 if (conn->in_error_handler || conn->ctx->callbacks.http_error == NULL
2528 || conn->ctx->callbacks.http_error(conn, status)) {
2529 if (!conn->in_error_handler) {
2530 /* Send user defined error pages, if defined */
2531 error_handler = conn->ctx->config[ERROR_PAGES];
2532 error_page_file_ext = conn->ctx->config[INDEX_FILES];
2533 page_handler_found = 0;
2534 if (error_handler != NULL) {
2535 for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
2536 switch (scope) {
2537 case 1: /* Handler for specific error, e.g. 404 error */
2538 mg_snprintf(conn,
2539 &truncated,
2540 buf,
2541 sizeof(buf) - 32,
2542 "%serror%03u.",
2543 error_handler,
2544 status);
2545 break;
2546 case 2: /* Handler for error group, e.g., 5xx error handler
2547 * for all server errors (500-599) */
2548 mg_snprintf(conn,
2549 &truncated,
2550 buf,
2551 sizeof(buf) - 32,
2552 "%serror%01uxx.",
2553 error_handler,
2554 status / 100);
2555 break;
2556 default: /* Handler for all errors */
2557 mg_snprintf(conn,
2558 &truncated,
2559 buf,
2560 sizeof(buf) - 32,
2561 "%serror.",
2562 error_handler);
2563 break;
2564 }
2565
2566 /* String truncation in buf may only occur if error_handler
2567 * is too long. This string is from the config, not from a
2568 * client. */
2569 (void)truncated;
2570
2571 len = (int)strlen(buf);
2572
2573 tstr = strchr(error_page_file_ext, '.');
2574
2575 while (tstr) {
2576 for (i = 1; i < 32 && tstr[i] != 0 && tstr[i] != ',';
2577 i++)
2578 buf[len + i - 1] = tstr[i];
2579 buf[len + i - 1] = 0;
2580 if (mg_stat(conn, buf, &error_page_file)) {
2581 page_handler_found = 1;
2582 break;
2583 }
2584 tstr = strchr(tstr + i, '.');
2585 }
2586 }
2587 }
2588
2589 if (page_handler_found) {
2590 conn->in_error_handler = 1;
2591 handle_file_based_request(conn, buf, &error_page_file);
2592 conn->in_error_handler = 0;
2593 return;
2594 }
2595 }
2596
2597 /* No custom error page. Send default error page. */
2598 gmt_time_string(date, sizeof(date), &curtime);
2599
2600 conn->must_close = 1;
2601 mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
2602 send_no_cache_header(conn);
2603 mg_printf(conn,
2604 "Date: %s\r\n"
2605 "Connection: close\r\n\r\n",
2606 date);
2607
2608 /* Errors 1xx, 204 and 304 MUST NOT send a body */
2609 if (status > 199 && status != 204 && status != 304) {
2610
2611 mg_printf(conn, "Error %d: %s\n", status, status_text);
2612
2613 if (fmt != NULL) {
2614 va_start(ap, fmt);
2615 mg_vsnprintf(conn, NULL, buf, sizeof(buf), fmt, ap);
2616 va_end(ap);
2617 mg_write(conn, buf, strlen(buf));
2618 DEBUG_TRACE("Error %i - [%s]", status, buf);
2619 }
2620
2621 } else {
2622 /* No body allowed. Close the connection. */
2623 DEBUG_TRACE("Error %i", status);
2624 }
2625 }
2626 }
2627
2628 #if defined(_WIN32) && !defined(__SYMBIAN32__)
2629 /* Create substitutes for POSIX functions in Win32. */
2630
2631 #if defined(__MINGW32__)
2632 /* Show no warning in case system functions are not used. */
2633 #pragma GCC diagnostic push
2634 #pragma GCC diagnostic ignored "-Wunused-function"
2635 #endif
2636
2637
2638 static int
2639 pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
2640 {
2641 (void)unused;
2642 *mutex = CreateMutex(NULL, FALSE, NULL);
2643 return *mutex == NULL ? -1 : 0;
2644 }
2645
2646
2647 static int
2648 pthread_mutex_destroy(pthread_mutex_t *mutex)
2649 {
2650 return CloseHandle(*mutex) == 0 ? -1 : 0;
2651 }
2652
2653
2654 static int
2655 pthread_mutex_lock(pthread_mutex_t *mutex)
2656 {
2657 return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
2658 }
2659
2660
2661 #ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS
2662 static int
2663 pthread_mutex_trylock(pthread_mutex_t *mutex)
2664 {
2665 switch (WaitForSingleObject(*mutex, 0)) {
2666 case WAIT_OBJECT_0:
2667 return 0;
2668 case WAIT_TIMEOUT:
2669 return -2; /* EBUSY */
2670 }
2671 return -1;
2672 }
2673 #endif
2674
2675
2676 static int
2677 pthread_mutex_unlock(pthread_mutex_t *mutex)
2678 {
2679 return ReleaseMutex(*mutex) == 0 ? -1 : 0;
2680 }
2681
2682
2683 #ifndef WIN_PTHREADS_TIME_H
2684 static int
2685 clock_gettime(clockid_t clk_id, struct timespec *tp)
2686 {
2687 FILETIME ft;
2688 ULARGE_INTEGER li;
2689 BOOL ok = FALSE;
2690 double d;
2691 static double perfcnt_per_sec = 0.0;
2692
2693 if (tp) {
2694 memset(tp, 0, sizeof(*tp));
2695 if (clk_id == CLOCK_REALTIME) {
2696 GetSystemTimeAsFileTime(&ft);
2697 li.LowPart = ft.dwLowDateTime;
2698 li.HighPart = ft.dwHighDateTime;
2699 li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
2700 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
2701 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
2702 ok = TRUE;
2703 } else if (clk_id == CLOCK_MONOTONIC) {
2704 if (perfcnt_per_sec == 0.0) {
2705 QueryPerformanceFrequency((LARGE_INTEGER *)&li);
2706 perfcnt_per_sec = 1.0 / li.QuadPart;
2707 }
2708 if (perfcnt_per_sec != 0.0) {
2709 QueryPerformanceCounter((LARGE_INTEGER *)&li);
2710 d = li.QuadPart * perfcnt_per_sec;
2711 tp->tv_sec = (time_t)d;
2712 d -= tp->tv_sec;
2713 tp->tv_nsec = (long)(d * 1.0E9);
2714 ok = TRUE;
2715 }
2716 }
2717 }
2718
2719 return ok ? 0 : -1;
2720 }
2721 #endif
2722
2723
2724 static int
2725 pthread_cond_init(pthread_cond_t *cv, const void *unused)
2726 {
2727 (void)unused;
2728 InitializeCriticalSection(&cv->threadIdSec);
2729 cv->waitingthreadcount = 0;
2730 cv->waitingthreadhdls =
2731 (pthread_t *)mg_calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
2732 return (cv->waitingthreadhdls != NULL) ? 0 : -1;
2733 }
2734
2735
2736 static int
2737 pthread_cond_timedwait(pthread_cond_t *cv,
2738 pthread_mutex_t *mutex,
2739 const struct timespec *abstime)
2740 {
2741 struct mg_workerTLS *tls =
2742 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
2743 int ok;
2744 struct timespec tsnow;
2745 int64_t nsnow, nswaitabs, nswaitrel;
2746 DWORD mswaitrel;
2747
2748 EnterCriticalSection(&cv->threadIdSec);
2749 assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
2750 cv->waitingthreadhdls[cv->waitingthreadcount] =
2751 tls->pthread_cond_helper_mutex;
2752 cv->waitingthreadcount++;
2753 LeaveCriticalSection(&cv->threadIdSec);
2754
2755 if (abstime) {
2756 clock_gettime(CLOCK_REALTIME, &tsnow);
2757 nsnow = (((int64_t)tsnow.tv_sec) * 1000000000) + tsnow.tv_nsec;
2758 nswaitabs =
2759 (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
2760 nswaitrel = nswaitabs - nsnow;
2761 if (nswaitrel < 0) {
2762 nswaitrel = 0;
2763 }
2764 mswaitrel = (DWORD)(nswaitrel / 1000000);
2765 } else {
2766 mswaitrel = INFINITE;
2767 }
2768
2769 pthread_mutex_unlock(mutex);
2770 ok = (WAIT_OBJECT_0
2771 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
2772 pthread_mutex_lock(mutex);
2773
2774 return ok ? 0 : -1;
2775 }
2776
2777
2778 static int
2779 pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
2780 {
2781 return pthread_cond_timedwait(cv, mutex, NULL);
2782 }
2783
2784
2785 static int
2786 pthread_cond_signal(pthread_cond_t *cv)
2787 {
2788 int i;
2789 HANDLE wkup = NULL;
2790 BOOL ok = FALSE;
2791
2792 EnterCriticalSection(&cv->threadIdSec);
2793 if (cv->waitingthreadcount) {
2794 wkup = cv->waitingthreadhdls[0];
2795 ok = SetEvent(wkup);
2796
2797 for (i = 1; i < cv->waitingthreadcount; i++) {
2798 cv->waitingthreadhdls[i - 1] = cv->waitingthreadhdls[i];
2799 }
2800 cv->waitingthreadcount--;
2801
2802 assert(ok);
2803 }
2804 LeaveCriticalSection(&cv->threadIdSec);
2805
2806 return ok ? 0 : 1;
2807 }
2808
2809
2810 static int
2811 pthread_cond_broadcast(pthread_cond_t *cv)
2812 {
2813 EnterCriticalSection(&cv->threadIdSec);
2814 while (cv->waitingthreadcount) {
2815 pthread_cond_signal(cv);
2816 }
2817 LeaveCriticalSection(&cv->threadIdSec);
2818
2819 return 0;
2820 }
2821
2822
2823 static int
2824 pthread_cond_destroy(pthread_cond_t *cv)
2825 {
2826 EnterCriticalSection(&cv->threadIdSec);
2827 assert(cv->waitingthreadcount == 0);
2828 mg_free(cv->waitingthreadhdls);
2829 cv->waitingthreadhdls = 0;
2830 LeaveCriticalSection(&cv->threadIdSec);
2831 DeleteCriticalSection(&cv->threadIdSec);
2832
2833 return 0;
2834 }
2835
2836
2837 #if defined(__MINGW32__)
2838 /* Enable unused function warning again */
2839 #pragma GCC diagnostic pop
2840 #endif
2841
2842
2843 /* For Windows, change all slashes to backslashes in path names. */
2844 static void
2845 change_slashes_to_backslashes(char *path)
2846 {
2847 int i;
2848
2849 for (i = 0; path[i] != '\0'; i++) {
2850 if (path[i] == '/') {
2851 path[i] = '\\';
2852 }
2853
2854 /* remove double backslash (check i > 0 to preserve UNC paths,
2855 * like \\server\file.txt) */
2856 if ((path[i] == '\\') && (i > 0)) {
2857 while (path[i + 1] == '\\' || path[i + 1] == '/') {
2858 (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
2859 }
2860 }
2861 }
2862 }
2863
2864
2865 static int
2866 mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
2867 {
2868 int diff;
2869
2870 do {
2871 diff = tolower(*s1) - tolower(*s2);
2872 s1++;
2873 s2++;
2874 } while (diff == 0 && s1[-1] != '\0');
2875
2876 return diff;
2877 }
2878
2879
2880 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
2881 * wbuf and wbuf_len is a target buffer and its length. */
2882 static void
2883 path_to_unicode(const struct mg_connection *conn,
2884 const char *path,
2885 wchar_t *wbuf,
2886 size_t wbuf_len)
2887 {
2888 char buf[PATH_MAX], buf2[PATH_MAX];
2889 wchar_t wbuf2[MAX_PATH + 1];
2890 DWORD long_len, err;
2891 int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
2892
2893 mg_strlcpy(buf, path, sizeof(buf));
2894 change_slashes_to_backslashes(buf);
2895
2896 /* Convert to Unicode and back. If doubly-converted string does not
2897 * match the original, something is fishy, reject. */
2898 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
2899 MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
2900 WideCharToMultiByte(
2901 CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
2902 if (strcmp(buf, buf2) != 0) {
2903 wbuf[0] = L'\0';
2904 }
2905
2906 /* TODO: Add a configuration to switch between case sensitive and
2907 * case insensitive URIs for Windows server. */
2908 /*
2909 if (conn) {
2910 if (conn->ctx->config[WINDOWS_CASE_SENSITIVE]) {
2911 fcompare = wcscmp;
2912 }
2913 }
2914 */
2915 (void)conn; /* conn is currently unused */
2916
2917 /* Only accept a full file path, not a Windows short (8.3) path. */
2918 memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
2919 long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
2920 if (long_len == 0) {
2921 err = GetLastError();
2922 if (err == ERROR_FILE_NOT_FOUND) {
2923 /* File does not exist. This is not always a problem here. */
2924 return;
2925 }
2926 }
2927 if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
2928 /* Short name is used. */
2929 wbuf[0] = L'\0';
2930 }
2931 }
2932
2933
2934 #if defined(_WIN32_WCE)
2935 /* Create substitutes for POSIX functions in Win32. */
2936
2937 #if defined(__MINGW32__)
2938 /* Show no warning in case system functions are not used. */
2939 #pragma GCC diagnostic push
2940 #pragma GCC diagnostic ignored "-Wunused-function"
2941 #endif
2942
2943
2944 static time_t
2945 time(time_t *ptime)
2946 {
2947 time_t t;
2948 SYSTEMTIME st;
2949 FILETIME ft;
2950
2951 GetSystemTime(&st);
2952 SystemTimeToFileTime(&st, &ft);
2953 t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
2954
2955 if (ptime != NULL) {
2956 *ptime = t;
2957 }
2958
2959 return t;
2960 }
2961
2962
2963 static struct tm *
2964 localtime(const time_t *ptime, struct tm *ptm)
2965 {
2966 int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
2967 FILETIME ft, lft;
2968 SYSTEMTIME st;
2969 TIME_ZONE_INFORMATION tzinfo;
2970
2971 if (ptm == NULL) {
2972 return NULL;
2973 }
2974
2975 *(int64_t *)&ft = t;
2976 FileTimeToLocalFileTime(&ft, &lft);
2977 FileTimeToSystemTime(&lft, &st);
2978 ptm->tm_year = st.wYear - 1900;
2979 ptm->tm_mon = st.wMonth - 1;
2980 ptm->tm_wday = st.wDayOfWeek;
2981 ptm->tm_mday = st.wDay;
2982 ptm->tm_hour = st.wHour;
2983 ptm->tm_min = st.wMinute;
2984 ptm->tm_sec = st.wSecond;
2985 ptm->tm_yday = 0; /* hope nobody uses this */
2986 ptm->tm_isdst =
2987 GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
2988
2989 return ptm;
2990 }
2991
2992
2993 static struct tm *
2994 gmtime(const time_t *ptime, struct tm *ptm)
2995 {
2996 /* FIXME(lsm): fix this. */
2997 return localtime(ptime, ptm);
2998 }
2999
3000
3001 static size_t
3002 strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
3003 {
3004 (void)mg_snprintf(NULL, dst, dst_size, "implement strftime() for WinCE");
3005 return 0;
3006 }
3007
3008
3009 #if defined(__MINGW32__)
3010 /* Enable unused function warning again */
3011 #pragma GCC diagnostic pop
3012 #endif
3013
3014 #endif
3015
3016
3017 /* Windows happily opens files with some garbage at the end of file name.
3018 * For example, fopen("a.cgi ", "r") on Windows successfully opens
3019 * "a.cgi", despite one would expect an error back.
3020 * This function returns non-0 if path ends with some garbage. */
3021 static int
3022 path_cannot_disclose_cgi(const char *path)
3023 {
3024 static const char *allowed_last_characters = "_-";
3025 int last = path[strlen(path) - 1];
3026 return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
3027 }
3028
3029
3030 static int
3031 mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3032 {
3033 wchar_t wbuf[PATH_MAX];
3034 WIN32_FILE_ATTRIBUTE_DATA info;
3035 time_t creation_time;
3036
3037 if (!filep) {
3038 return 0;
3039 }
3040 memset(filep, 0, sizeof(*filep));
3041
3042 if (conn && is_file_in_memory(conn, path, filep)) {
3043 /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
3044 * memset */
3045 filep->last_modified = time(NULL);
3046 /* last_modified = now ... assumes the file may change during runtime,
3047 * so every mg_fopen call may return different data */
3048 /* last_modified = conn->ctx.start_time;
3049 * May be used it the data does not change during runtime. This allows
3050 * browser caching. Since we do not know, we have to assume the file
3051 * in memory may change. */
3052 return 1;
3053 }
3054
3055 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3056 if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
3057 filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
3058 filep->last_modified =
3059 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
3060 info.ftLastWriteTime.dwHighDateTime);
3061
3062 /* On Windows, the file creation time can be higher than the
3063 * modification time, e.g. when a file is copied.
3064 * Since the Last-Modified timestamp is used for caching
3065 * it should be based on the most recent timestamp. */
3066 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
3067 info.ftCreationTime.dwHighDateTime);
3068 if (creation_time > filep->last_modified) {
3069 filep->last_modified = creation_time;
3070 }
3071
3072 filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3073 /* If file name is fishy, reset the file structure and return
3074 * error.
3075 * Note it is important to reset, not just return the error, cause
3076 * functions like is_file_opened() check the struct. */
3077 if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
3078 memset(filep, 0, sizeof(*filep));
3079 return 0;
3080 }
3081
3082 return 1;
3083 }
3084
3085 return 0;
3086 }
3087
3088
3089 static int
3090 mg_remove(const struct mg_connection *conn, const char *path)
3091 {
3092 wchar_t wbuf[PATH_MAX];
3093 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3094 return DeleteFileW(wbuf) ? 0 : -1;
3095 }
3096
3097
3098 static int
3099 mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
3100 {
3101 wchar_t wbuf[PATH_MAX];
3102 (void)mode;
3103 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3104 return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
3105 }
3106
3107
3108 /* Create substitutes for POSIX functions in Win32. */
3109
3110 #if defined(__MINGW32__)
3111 /* Show no warning in case system functions are not used. */
3112 #pragma GCC diagnostic push
3113 #pragma GCC diagnostic ignored "-Wunused-function"
3114 #endif
3115
3116
3117 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
3118 static DIR *
3119 mg_opendir(const struct mg_connection *conn, const char *name)
3120 {
3121 DIR *dir = NULL;
3122 wchar_t wpath[PATH_MAX];
3123 DWORD attrs;
3124
3125 if (name == NULL) {
3126 SetLastError(ERROR_BAD_ARGUMENTS);
3127 } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
3128 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3129 } else {
3130 path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
3131 attrs = GetFileAttributesW(wpath);
3132 if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
3133 == FILE_ATTRIBUTE_DIRECTORY)) {
3134 (void)wcscat(wpath, L"\\*");
3135 dir->handle = FindFirstFileW(wpath, &dir->info);
3136 dir->result.d_name[0] = '\0';
3137 } else {
3138 mg_free(dir);
3139 dir = NULL;
3140 }
3141 }
3142
3143 return dir;
3144 }
3145
3146
3147 static int
3148 mg_closedir(DIR *dir)
3149 {
3150 int result = 0;
3151
3152 if (dir != NULL) {
3153 if (dir->handle != INVALID_HANDLE_VALUE)
3154 result = FindClose(dir->handle) ? 0 : -1;
3155
3156 mg_free(dir);
3157 } else {
3158 result = -1;
3159 SetLastError(ERROR_BAD_ARGUMENTS);
3160 }
3161
3162 return result;
3163 }
3164
3165
3166 static struct dirent *
3167 mg_readdir(DIR *dir)
3168 {
3169 struct dirent *result = 0;
3170
3171 if (dir) {
3172 if (dir->handle != INVALID_HANDLE_VALUE) {
3173 result = &dir->result;
3174 (void)WideCharToMultiByte(CP_UTF8,
3175 0,
3176 dir->info.cFileName,
3177 -1,
3178 result->d_name,
3179 sizeof(result->d_name),
3180 NULL,
3181 NULL);
3182
3183 if (!FindNextFileW(dir->handle, &dir->info)) {
3184 (void)FindClose(dir->handle);
3185 dir->handle = INVALID_HANDLE_VALUE;
3186 }
3187
3188 } else {
3189 SetLastError(ERROR_FILE_NOT_FOUND);
3190 }
3191 } else {
3192 SetLastError(ERROR_BAD_ARGUMENTS);
3193 }
3194
3195 return result;
3196 }
3197
3198
3199 #ifndef HAVE_POLL
3200 static int
3201 poll(struct pollfd *pfd, unsigned int n, int milliseconds)
3202 {
3203 struct timeval tv;
3204 fd_set set;
3205 unsigned int i;
3206 int result;
3207 SOCKET maxfd = 0;
3208
3209 memset(&tv, 0, sizeof(tv));
3210 tv.tv_sec = milliseconds / 1000;
3211 tv.tv_usec = (milliseconds % 1000) * 1000;
3212 FD_ZERO(&set);
3213
3214 for (i = 0; i < n; i++) {
3215 FD_SET((SOCKET)pfd[i].fd, &set);
3216 pfd[i].revents = 0;
3217
3218 if (pfd[i].fd > maxfd) {
3219 maxfd = pfd[i].fd;
3220 }
3221 }
3222
3223 if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
3224 for (i = 0; i < n; i++) {
3225 if (FD_ISSET(pfd[i].fd, &set)) {
3226 pfd[i].revents = POLLIN;
3227 }
3228 }
3229 }
3230
3231 return result;
3232 }
3233 #endif /* HAVE_POLL */
3234
3235 #if defined(__MINGW32__)
3236 /* Enable unused function warning again */
3237 #pragma GCC diagnostic pop
3238 #endif
3239
3240
3241 static void
3242 set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
3243 {
3244 (void)conn; /* Unused. */
3245 (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
3246 }
3247
3248
3249 int
3250 mg_start_thread(mg_thread_func_t f, void *p)
3251 {
3252 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3253 /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384
3254 */
3255 return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
3256 == ((uintptr_t)(-1L)))
3257 ? -1
3258 : 0);
3259 #else
3260 return (
3261 (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
3262 ? -1
3263 : 0);
3264 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3265 }
3266
3267
3268 /* Start a thread storing the thread context. */
3269 static int
3270 mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
3271 void *p,
3272 pthread_t *threadidptr)
3273 {
3274 uintptr_t uip;
3275 HANDLE threadhandle;
3276 int result = -1;
3277
3278 uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
3279 threadhandle = (HANDLE)uip;
3280 if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
3281 *threadidptr = threadhandle;
3282 result = 0;
3283 }
3284
3285 return result;
3286 }
3287
3288
3289 /* Wait for a thread to finish. */
3290 static int
3291 mg_join_thread(pthread_t threadid)
3292 {
3293 int result;
3294 DWORD dwevent;
3295
3296 result = -1;
3297 dwevent = WaitForSingleObject(threadid, INFINITE);
3298 if (dwevent == WAIT_FAILED) {
3299 DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
3300 } else {
3301 if (dwevent == WAIT_OBJECT_0) {
3302 CloseHandle(threadid);
3303 result = 0;
3304 }
3305 }
3306
3307 return result;
3308 }
3309
3310 #if !defined(NO_SSL_DL)
3311 /* Create substitutes for POSIX functions in Win32. */
3312
3313 #if defined(__MINGW32__)
3314 /* Show no warning in case system functions are not used. */
3315 #pragma GCC diagnostic push
3316 #pragma GCC diagnostic ignored "-Wunused-function"
3317 #endif
3318
3319
3320 static HANDLE
3321 dlopen(const char *dll_name, int flags)
3322 {
3323 wchar_t wbuf[PATH_MAX];
3324 (void)flags;
3325 path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
3326 return LoadLibraryW(wbuf);
3327 }
3328
3329
3330 static int
3331 dlclose(void *handle)
3332 {
3333 int result;
3334
3335 if (FreeLibrary((HMODULE)handle) != 0) {
3336 result = 0;
3337 } else {
3338 result = -1;
3339 }
3340
3341 return result;
3342 }
3343
3344
3345 #if defined(__MINGW32__)
3346 /* Enable unused function warning again */
3347 #pragma GCC diagnostic pop
3348 #endif
3349
3350 #endif
3351
3352
3353 #if !defined(NO_CGI)
3354 #define SIGKILL (0)
3355
3356 static int
3357 kill(pid_t pid, int sig_num)
3358 {
3359 (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
3360 (void)CloseHandle((HANDLE)pid);
3361 return 0;
3362 }
3363
3364
3365 static void
3366 trim_trailing_whitespaces(char *s)
3367 {
3368 char *e = s + strlen(s) - 1;
3369 while (e > s && isspace(*(unsigned char *)e)) {
3370 *e-- = '\0';
3371 }
3372 }
3373
3374
3375 static pid_t
3376 spawn_process(struct mg_connection *conn,
3377 const char *prog,
3378 char *envblk,
3379 char *envp[],
3380 int fdin[2],
3381 int fdout[2],
3382 int fderr[2],
3383 const char *dir)
3384 {
3385 HANDLE me;
3386 char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
3387 cmdline[PATH_MAX], buf[PATH_MAX];
3388 int truncated;
3389 struct file file = STRUCT_FILE_INITIALIZER;
3390 STARTUPINFOA si;
3391 PROCESS_INFORMATION pi = {0};
3392
3393 (void)envp;
3394
3395 memset(&si, 0, sizeof(si));
3396 si.cb = sizeof(si);
3397
3398 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3399 si.wShowWindow = SW_HIDE;
3400
3401 me = GetCurrentProcess();
3402 DuplicateHandle(me,
3403 (HANDLE)_get_osfhandle(fdin[0]),
3404 me,
3405 &si.hStdInput,
3406 0,
3407 TRUE,
3408 DUPLICATE_SAME_ACCESS);
3409 DuplicateHandle(me,
3410 (HANDLE)_get_osfhandle(fdout[1]),
3411 me,
3412 &si.hStdOutput,
3413 0,
3414 TRUE,
3415 DUPLICATE_SAME_ACCESS);
3416 DuplicateHandle(me,
3417 (HANDLE)_get_osfhandle(fderr[1]),
3418 me,
3419 &si.hStdError,
3420 0,
3421 TRUE,
3422 DUPLICATE_SAME_ACCESS);
3423
3424 /* Mark handles that should not be inherited. See
3425 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
3426 */
3427 SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
3428 HANDLE_FLAG_INHERIT,
3429 0);
3430 SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
3431 HANDLE_FLAG_INHERIT,
3432 0);
3433 SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
3434 HANDLE_FLAG_INHERIT,
3435 0);
3436
3437 /* If CGI file is a script, try to read the interpreter line */
3438 interp = conn->ctx->config[CGI_INTERPRETER];
3439 if (interp == NULL) {
3440 buf[0] = buf[1] = '\0';
3441
3442 /* Read the first line of the script into the buffer */
3443 mg_snprintf(
3444 conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
3445
3446 if (truncated) {
3447 pi.hProcess = (pid_t)-1;
3448 goto spawn_cleanup;
3449 }
3450
3451 if (mg_fopen(conn, cmdline, "r", &file)) {
3452 p = (char *)file.membuf;
3453 mg_fgets(buf, sizeof(buf), &file, &p);
3454 mg_fclose(&file);
3455 buf[sizeof(buf) - 1] = '\0';
3456 }
3457
3458 if (buf[0] == '#' && buf[1] == '!') {
3459 trim_trailing_whitespaces(buf + 2);
3460 } else {
3461 buf[2] = '\0';
3462 }
3463 interp = buf + 2;
3464 }
3465
3466 if (interp[0] != '\0') {
3467 GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
3468 interp = full_interp;
3469 }
3470 GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
3471
3472 if (interp[0] != '\0') {
3473 mg_snprintf(conn,
3474 &truncated,
3475 cmdline,
3476 sizeof(cmdline),
3477 "\"%s\" \"%s\\%s\"",
3478 interp,
3479 full_dir,
3480 prog);
3481 } else {
3482 mg_snprintf(conn,
3483 &truncated,
3484 cmdline,
3485 sizeof(cmdline),
3486 "\"%s\\%s\"",
3487 full_dir,
3488 prog);
3489 }
3490
3491 if (truncated) {
3492 pi.hProcess = (pid_t)-1;
3493 goto spawn_cleanup;
3494 }
3495
3496 DEBUG_TRACE("Running [%s]", cmdline);
3497 if (CreateProcessA(NULL,
3498 cmdline,
3499 NULL,
3500 NULL,
3501 TRUE,
3502 CREATE_NEW_PROCESS_GROUP,
3503 envblk,
3504 NULL,
3505 &si,
3506 &pi) == 0) {
3507 mg_cry(
3508 conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
3509 pi.hProcess = (pid_t)-1;
3510 /* goto spawn_cleanup; */
3511 }
3512
3513 spawn_cleanup:
3514 (void)CloseHandle(si.hStdOutput);
3515 (void)CloseHandle(si.hStdError);
3516 (void)CloseHandle(si.hStdInput);
3517 if (pi.hThread != NULL) {
3518 (void)CloseHandle(pi.hThread);
3519 }
3520
3521 return (pid_t)pi.hProcess;
3522 }
3523 #endif /* !NO_CGI */
3524
3525
3526 static int
3527 set_non_blocking_mode(SOCKET sock)
3528 {
3529 unsigned long on = 1;
3530 return ioctlsocket(sock, (long)FIONBIO, &on);
3531 }
3532
3533 #else
3534
3535 static int
3536 mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3537 {
3538 struct stat st;
3539 if (!filep) {
3540 return 0;
3541 }
3542 memset(filep, 0, sizeof(*filep));
3543
3544 if (conn && is_file_in_memory(conn, path, filep)) {
3545 return 1;
3546 }
3547
3548 if (0 == stat(path, &st)) {
3549 filep->size = (uint64_t)(st.st_size);
3550 filep->last_modified = st.st_mtime;
3551 filep->is_directory = S_ISDIR(st.st_mode);
3552 return 1;
3553 }
3554
3555 return 0;
3556 }
3557
3558
3559 static void
3560 set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
3561 {
3562 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
3563 if (conn) {
3564 mg_cry(conn,
3565 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
3566 __func__,
3567 strerror(ERRNO));
3568 }
3569 }
3570 }
3571
3572
3573 int
3574 mg_start_thread(mg_thread_func_t func, void *param)
3575 {
3576 pthread_t thread_id;
3577 pthread_attr_t attr;
3578 int result;
3579
3580 (void)pthread_attr_init(&attr);
3581 (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3582
3583 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3584 /* Compile-time option to control stack size,
3585 * e.g. -DUSE_STACK_SIZE=16384 */
3586 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3587 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3588
3589 result = pthread_create(&thread_id, &attr, func, param);
3590 pthread_attr_destroy(&attr);
3591
3592 return result;
3593 }
3594
3595
3596 /* Start a thread storing the thread context. */
3597 static int
3598 mg_start_thread_with_id(mg_thread_func_t func,
3599 void *param,
3600 pthread_t *threadidptr)
3601 {
3602 pthread_t thread_id;
3603 pthread_attr_t attr;
3604 int result;
3605
3606 (void)pthread_attr_init(&attr);
3607
3608 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3609 /* Compile-time option to control stack size,
3610 * e.g. -DUSE_STACK_SIZE=16384 */
3611 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3612 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
3613
3614 result = pthread_create(&thread_id, &attr, func, param);
3615 pthread_attr_destroy(&attr);
3616 if ((result == 0) && (threadidptr != NULL)) {
3617 *threadidptr = thread_id;
3618 }
3619 return result;
3620 }
3621
3622
3623 /* Wait for a thread to finish. */
3624 static int
3625 mg_join_thread(pthread_t threadid)
3626 {
3627 int result;
3628
3629 result = pthread_join(threadid, NULL);
3630 return result;
3631 }
3632
3633
3634 #ifndef NO_CGI
3635 static pid_t
3636 spawn_process(struct mg_connection *conn,
3637 const char *prog,
3638 char *envblk,
3639 char *envp[],
3640 int fdin[2],
3641 int fdout[2],
3642 int fderr[2],
3643 const char *dir)
3644 {
3645 pid_t pid;
3646 const char *interp;
3647
3648 (void)envblk;
3649
3650 if (conn == NULL) {
3651 return 0;
3652 }
3653
3654 if ((pid = fork()) == -1) {
3655 /* Parent */
3656 send_http_error(conn,
3657 500,
3658 "Error: Creating CGI process\nfork(): %s",
3659 strerror(ERRNO));
3660 } else if (pid == 0) {
3661 /* Child */
3662 if (chdir(dir) != 0) {
3663 mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
3664 } else if (dup2(fdin[0], 0) == -1) {
3665 mg_cry(conn,
3666 "%s: dup2(%d, 0): %s",
3667 __func__,
3668 fdin[0],
3669 strerror(ERRNO));
3670 } else if (dup2(fdout[1], 1) == -1) {
3671 mg_cry(conn,
3672 "%s: dup2(%d, 1): %s",
3673 __func__,
3674 fdout[1],
3675 strerror(ERRNO));
3676 } else if (dup2(fderr[1], 2) == -1) {
3677 mg_cry(conn,
3678 "%s: dup2(%d, 2): %s",
3679 __func__,
3680 fderr[1],
3681 strerror(ERRNO));
3682 } else {
3683 /* Keep stderr and stdout in two different pipes.
3684 * Stdout will be sent back to the client,
3685 * stderr should go into a server error log. */
3686 (void)close(fdin[0]);
3687 (void)close(fdout[1]);
3688 (void)close(fderr[1]);
3689
3690 /* Close write end fdin and read end fdout and fderr */
3691 (void)close(fdin[1]);
3692 (void)close(fdout[0]);
3693 (void)close(fderr[0]);
3694
3695 /* After exec, all signal handlers are restored to their default
3696 * values, with one exception of SIGCHLD. According to
3697 * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
3698 * leave unchanged after exec if it was set to be ignored. Restore
3699 * it to default action. */
3700 signal(SIGCHLD, SIG_DFL);
3701
3702 interp = conn->ctx->config[CGI_INTERPRETER];
3703 if (interp == NULL) {
3704 (void)execle(prog, prog, NULL, envp);
3705 mg_cry(conn,
3706 "%s: execle(%s): %s",
3707 __func__,
3708 prog,
3709 strerror(ERRNO));
3710 } else {
3711 (void)execle(interp, interp, prog, NULL, envp);
3712 mg_cry(conn,
3713 "%s: execle(%s %s): %s",
3714 __func__,
3715 interp,
3716 prog,
3717 strerror(ERRNO));
3718 }
3719 }
3720 exit(EXIT_FAILURE);
3721 }
3722
3723 return pid;
3724 }
3725 #endif /* !NO_CGI */
3726
3727
3728 static int
3729 set_non_blocking_mode(SOCKET sock)
3730 {
3731 int flags;
3732
3733 flags = fcntl(sock, F_GETFL, 0);
3734 (void)fcntl(sock, F_SETFL, flags | O_NONBLOCK);
3735
3736 return 0;
3737 }
3738 #endif /* _WIN32 */
3739 /* End of initial operating system specific define block. */
3740
3741
3742 /* Get a random number (independent of C rand function) */
3743 static uint64_t
3744 get_random(void)
3745 {
3746 static uint64_t lfsr = 0; /* Linear feedback shift register */
3747 static uint64_t lcg = 0; /* Linear congruential generator */
3748 struct timespec now;
3749
3750 memset(&now, 0, sizeof(now));
3751 clock_gettime(CLOCK_MONOTONIC, &now);
3752
3753 if (lfsr == 0) {
3754 /* lfsr will be only 0 if has not been initialized,
3755 * so this code is called only once. */
3756 lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec)
3757 ^ ((uint64_t)(ptrdiff_t)&now) ^ (((uint64_t)time(NULL)) << 33);
3758 lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec
3759 + (uint64_t)(ptrdiff_t)&now;
3760 } else {
3761 /* Get the next step of both random number generators. */
3762 lfsr = (lfsr >> 1)
3763 | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
3764 << 63);
3765 lcg = lcg * 6364136223846793005 + 1442695040888963407;
3766 }
3767
3768 /* Combining two pseudo-random number generators and a high resolution part
3769 * of the current server time will make it hard (impossible?) to guess the
3770 * next number. */
3771 return (lfsr ^ lcg ^ (uint64_t)now.tv_nsec);
3772 }
3773
3774
3775 /* Write data to the IO channel - opened file descriptor, socket or SSL
3776 * descriptor. Return number of bytes written. */
3777 static int
3778 push(struct mg_context *ctx,
3779 FILE *fp,
3780 SOCKET sock,
3781 SSL *ssl,
3782 const char *buf,
3783 int len,
3784 double timeout)
3785 {
3786 struct timespec start, now;
3787 int n, err;
3788
3789 #ifdef _WIN32
3790 typedef int len_t;
3791 #else
3792 typedef size_t len_t;
3793 #endif
3794
3795 if (timeout > 0) {
3796 memset(&start, 0, sizeof(start));
3797 memset(&now, 0, sizeof(now));
3798 clock_gettime(CLOCK_MONOTONIC, &start);
3799 }
3800
3801 if (ctx == NULL) {
3802 return -1;
3803 }
3804
3805 #ifdef NO_SSL
3806 if (ssl) {
3807 return -1;
3808 }
3809 #endif
3810
3811 do {
3812
3813 #ifndef NO_SSL
3814 if (ssl != NULL) {
3815 n = SSL_write(ssl, buf, len);
3816 if (n <= 0) {
3817 err = SSL_get_error(ssl, n);
3818 if ((err == 5 /* SSL_ERROR_SYSCALL */) && (n == -1)) {
3819 err = ERRNO;
3820 } else {
3821 DEBUG_TRACE("SSL_write() failed, error %d", err);
3822 return -1;
3823 }
3824 } else {
3825 err = 0;
3826 }
3827 } else
3828 #endif
3829 if (fp != NULL) {
3830 n = (int)fwrite(buf, 1, (size_t)len, fp);
3831 if (ferror(fp)) {
3832 n = -1;
3833 err = ERRNO;
3834 } else {
3835 err = 0;
3836 }
3837 } else {
3838 n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
3839 err = (n < 0) ? ERRNO : 0;
3840 }
3841
3842 if (ctx->stop_flag) {
3843 return -1;
3844 }
3845
3846 if ((n > 0) || (n == 0 && len == 0)) {
3847 /* some data has been read, or no data was requested */
3848 return n;
3849 }
3850 if (n == 0) {
3851 /* shutdown of the socket at client side */
3852 return -1;
3853 }
3854 if (n < 0) {
3855 /* socket error - check errno */
3856 DEBUG_TRACE("send() failed, error %d", err);
3857
3858 /* TODO: error handling depending on the error code.
3859 * These codes are different between Windows and Linux.
3860 */
3861 return -1;
3862 }
3863
3864 /* This code is not reached in the moment.
3865 * ==> Fix the TODOs above first. */
3866
3867 if (timeout > 0) {
3868 clock_gettime(CLOCK_MONOTONIC, &now);
3869 }
3870
3871 } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
3872
3873 (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
3874 used */
3875
3876 return -1;
3877 }
3878
3879
3880 static int64_t
3881 push_all(struct mg_context *ctx,
3882 FILE *fp,
3883 SOCKET sock,
3884 SSL *ssl,
3885 const char *buf,
3886 int64_t len)
3887 {
3888 double timeout = -1.0;
3889 int64_t n, nwritten = 0;
3890
3891 if (ctx == NULL) {
3892 return -1;
3893 }
3894
3895 if (ctx->config[REQUEST_TIMEOUT]) {
3896 timeout = atoi(ctx->config[REQUEST_TIMEOUT]) / 1000.0;
3897 }
3898
3899 while (len > 0 && ctx->stop_flag == 0) {
3900 n = push(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
3901 if (n < 0) {
3902 if (nwritten == 0) {
3903 nwritten = n; /* Propagate the error */
3904 }
3905 break;
3906 } else if (n == 0) {
3907 break; /* No more data to write */
3908 } else {
3909 nwritten += n;
3910 len -= n;
3911 }
3912 }
3913
3914 return nwritten;
3915 }
3916
3917
3918 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
3919 * Return negative value on error, or number of bytes read on success. */
3920 static int
3921 pull(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
3922 {
3923 int nread, err;
3924 struct timespec start, now;
3925
3926 #ifdef _WIN32
3927 typedef int len_t;
3928 #else
3929 typedef size_t len_t;
3930 #endif
3931
3932 if (timeout > 0) {
3933 memset(&start, 0, sizeof(start));
3934 memset(&now, 0, sizeof(now));
3935 clock_gettime(CLOCK_MONOTONIC, &start);
3936 }
3937
3938 do {
3939 if (fp != NULL) {
3940 /* Use read() instead of fread(), because if we're reading from the
3941 * CGI pipe, fread() may block until IO buffer is filled up. We
3942 * cannot afford to block and must pass all read bytes immediately
3943 * to the client. */
3944 nread = (int)read(fileno(fp), buf, (size_t)len);
3945 err = (nread < 0) ? ERRNO : 0;
3946
3947 #ifndef NO_SSL
3948 } else if (conn->ssl != NULL) {
3949 nread = SSL_read(conn->ssl, buf, len);
3950 if (nread <= 0) {
3951 err = SSL_get_error(conn->ssl, nread);
3952 if ((err == 5 /* SSL_ERROR_SYSCALL */) && (nread == -1)) {
3953 err = ERRNO;
3954 } else {
3955 DEBUG_TRACE("SSL_read() failed, error %d", err);
3956 return -1;
3957 }
3958 } else {
3959 err = 0;
3960 }
3961 #endif
3962
3963 } else {
3964 nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
3965 err = (nread < 0) ? ERRNO : 0;
3966 }
3967
3968 if (conn->ctx->stop_flag) {
3969 return -1;
3970 }
3971
3972 if ((nread > 0) || (nread == 0 && len == 0)) {
3973 /* some data has been read, or no data was requested */
3974 return nread;
3975 }
3976 if (nread == 0) {
3977 /* shutdown of the socket at client side */
3978 return -1;
3979 }
3980 if (nread < 0) {
3981 /* socket error - check errno */
3982 #ifdef _WIN32
3983 if (err == WSAEWOULDBLOCK) {
3984 /* standard case if called from close_socket_gracefully */
3985 return -1;
3986 } else if (err == WSAETIMEDOUT) {
3987 /* timeout is handled by the while loop */
3988 } else {
3989 DEBUG_TRACE("recv() failed, error %d", err);
3990 return -1;
3991 }
3992 #else
3993 /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
3994 * if the timeout is reached and if the socket was set to non-
3995 * blocking in close_socket_gracefully, so we can not distinguish
3996 * here. We have to wait for the timeout in both cases for now.
3997 */
3998 if (err == EAGAIN || err == EWOULDBLOCK || err == EINTR) {
3999 /* EAGAIN/EWOULDBLOCK:
4000 * standard case if called from close_socket_gracefully
4001 * => should return -1 */
4002 /* or timeout occured
4003 * => the code must stay in the while loop */
4004
4005 /* EINTR can be generated on a socket with a timeout set even
4006 * when SA_RESTART is effective for all relevant signals
4007 * (see signal(7)).
4008 * => stay in the while loop */
4009 } else {
4010 DEBUG_TRACE("recv() failed, error %d", err);
4011 return -1;
4012 }
4013 #endif
4014 }
4015 if (timeout > 0) {
4016 clock_gettime(CLOCK_MONOTONIC, &now);
4017 }
4018 } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
4019
4020 /* Timeout occured, but no data available. */
4021 return -1;
4022 }
4023
4024
4025 static int
4026 pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
4027 {
4028 int n, nread = 0;
4029 double timeout = -1.0;
4030
4031 if (conn->ctx->config[REQUEST_TIMEOUT]) {
4032 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
4033 }
4034
4035 while (len > 0 && conn->ctx->stop_flag == 0) {
4036 n = pull(fp, conn, buf + nread, len, timeout);
4037 if (n < 0) {
4038 if (nread == 0) {
4039 nread = n; /* Propagate the error */
4040 }
4041 break;
4042 } else if (n == 0) {
4043 break; /* No more data to read */
4044 } else {
4045 conn->consumed_content += n;
4046 nread += n;
4047 len -= n;
4048 }
4049 }
4050
4051 return nread;
4052 }
4053
4054
4055 static void
4056 discard_unread_request_data(struct mg_connection *conn)
4057 {
4058 char buf[MG_BUF_LEN];
4059 size_t to_read;
4060 int nread;
4061
4062 if (conn == NULL) {
4063 return;
4064 }
4065
4066 to_read = sizeof(buf);
4067
4068 if (conn->is_chunked) {
4069 /* Chunked encoding: 1=chunk not read completely, 2=chunk read
4070 * completely */
4071 while (conn->is_chunked == 1) {
4072 nread = mg_read(conn, buf, to_read);
4073 if (nread <= 0) {
4074 break;
4075 }
4076 }
4077
4078 } else {
4079 /* Not chunked: content length is known */
4080 while (conn->consumed_content < conn->content_len) {
4081 if (to_read
4082 > (size_t)(conn->content_len - conn->consumed_content)) {
4083 to_read = (size_t)(conn->content_len - conn->consumed_content);
4084 }
4085
4086 nread = mg_read(conn, buf, to_read);
4087 if (nread <= 0) {
4088 break;
4089 }
4090 }
4091 }
4092 }
4093
4094
4095 static int
4096 mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
4097 {
4098 int64_t n, buffered_len, nread;
4099 int64_t len64 =
4100 (int64_t)(len > INT_MAX ? INT_MAX : len); /* since the return value is
4101 * int, we may not read more
4102 * bytes */
4103 const char *body;
4104
4105 if (conn == NULL) {
4106 return 0;
4107 }
4108
4109 /* If Content-Length is not set for a PUT or POST request, read until
4110 * socket is closed */
4111 if (conn->consumed_content == 0 && conn->content_len == -1) {
4112 conn->content_len = INT64_MAX;
4113 conn->must_close = 1;
4114 }
4115
4116 nread = 0;
4117 if (conn->consumed_content < conn->content_len) {
4118 /* Adjust number of bytes to read. */
4119 int64_t left_to_read = conn->content_len - conn->consumed_content;
4120 if (left_to_read < len64) {
4121 /* Do not read more than the total content length of the request.
4122 */
4123 len64 = left_to_read;
4124 }
4125
4126 /* Return buffered data */
4127 buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
4128 - conn->consumed_content;
4129 if (buffered_len > 0) {
4130 if (len64 < buffered_len) {
4131 buffered_len = len64;
4132 }
4133 body = conn->buf + conn->request_len + conn->consumed_content;
4134 memcpy(buf, body, (size_t)buffered_len);
4135 len64 -= buffered_len;
4136 conn->consumed_content += buffered_len;
4137 nread += buffered_len;
4138 buf = (char *)buf + buffered_len;
4139 }
4140
4141 /* We have returned all buffered data. Read new data from the remote
4142 * socket.
4143 */
4144 if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
4145 nread += n;
4146 } else {
4147 nread = (nread > 0 ? nread : n);
4148 }
4149 }
4150 return (int)nread;
4151 }
4152
4153
4154 static char
4155 mg_getc(struct mg_connection *conn)
4156 {
4157 char c;
4158 if (conn == NULL) {
4159 return 0;
4160 }
4161 conn->content_len++;
4162 if (mg_read_inner(conn, &c, 1) <= 0) {
4163 return (char)0;
4164 }
4165 return c;
4166 }
4167
4168
4169 int
4170 mg_read(struct mg_connection *conn, void *buf, size_t len)
4171 {
4172 if (len > INT_MAX) {
4173 len = INT_MAX;
4174 }
4175
4176 if (conn == NULL) {
4177 return 0;
4178 }
4179
4180 if (conn->is_chunked) {
4181 size_t all_read = 0;
4182
4183 while (len > 0) {
4184
4185 if (conn->is_chunked == 2) {
4186 /* No more data left to read */
4187 return 0;
4188 }
4189
4190 if (conn->chunk_remainder) {
4191 /* copy from the remainder of the last received chunk */
4192 long read_ret;
4193 size_t read_now =
4194 ((conn->chunk_remainder > len) ? (len)
4195 : (conn->chunk_remainder));
4196
4197 conn->content_len += (int)read_now;
4198 read_ret =
4199 mg_read_inner(conn, (char *)buf + all_read, read_now);
4200 all_read += (size_t)read_ret;
4201
4202 conn->chunk_remainder -= read_now;
4203 len -= read_now;
4204
4205 if (conn->chunk_remainder == 0) {
4206 /* the rest of the data in the current chunk has been read
4207 */
4208 if ((mg_getc(conn) != '\r') || (mg_getc(conn) != '\n')) {
4209 /* Protocol violation */
4210 return -1;
4211 }
4212 }
4213
4214 } else {
4215 /* fetch a new chunk */
4216 int i = 0;
4217 char lenbuf[64];
4218 char *end = 0;
4219 unsigned long chunkSize = 0;
4220
4221 for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
4222 lenbuf[i] = mg_getc(conn);
4223 if (i > 0 && lenbuf[i] == '\r' && lenbuf[i - 1] != '\r') {
4224 continue;
4225 }
4226 if (i > 1 && lenbuf[i] == '\n' && lenbuf[i - 1] == '\r') {
4227 lenbuf[i + 1] = 0;
4228 chunkSize = strtoul(lenbuf, &end, 16);
4229 if (chunkSize == 0) {
4230 /* regular end of content */
4231 conn->is_chunked = 2;
4232 }
4233 break;
4234 }
4235 if (!isalnum(lenbuf[i])) {
4236 /* illegal character for chunk length */
4237 return -1;
4238 }
4239 }
4240 if ((end == NULL) || (*end != '\r')) {
4241 /* chunksize not set correctly */
4242 return -1;
4243 }
4244 if (chunkSize == 0) {
4245 break;
4246 }
4247
4248 conn->chunk_remainder = chunkSize;
4249 }
4250 }
4251
4252 return (int)all_read;
4253 }
4254 return mg_read_inner(conn, buf, len);
4255 }
4256
4257
4258 int
4259 mg_write(struct mg_connection *conn, const void *buf, size_t len)
4260 {
4261 time_t now;
4262 int64_t n, total, allowed;
4263
4264 if (conn == NULL) {
4265 return 0;
4266 }
4267
4268 if (conn->throttle > 0) {
4269 if ((now = time(NULL)) != conn->last_throttle_time) {
4270 conn->last_throttle_time = now;
4271 conn->last_throttle_bytes = 0;
4272 }
4273 allowed = conn->throttle - conn->last_throttle_bytes;
4274 if (allowed > (int64_t)len) {
4275 allowed = (int64_t)len;
4276 }
4277 if ((total = push_all(conn->ctx,
4278 NULL,
4279 conn->client.sock,
4280 conn->ssl,
4281 (const char *)buf,
4282 (int64_t)allowed)) == allowed) {
4283 buf = (const char *)buf + total;
4284 conn->last_throttle_bytes += total;
4285 while (total < (int64_t)len && conn->ctx->stop_flag == 0) {
4286 allowed = conn->throttle > (int64_t)len - total
4287 ? (int64_t)len - total
4288 : conn->throttle;
4289 if ((n = push_all(conn->ctx,
4290 NULL,
4291 conn->client.sock,
4292 conn->ssl,
4293 (const char *)buf,
4294 (int64_t)allowed)) != allowed) {
4295 break;
4296 }
4297 sleep(1);
4298 conn->last_throttle_bytes = allowed;
4299 conn->last_throttle_time = time(NULL);
4300 buf = (const char *)buf + n;
4301 total += n;
4302 }
4303 }
4304 } else {
4305 total = push_all(conn->ctx,
4306 NULL,
4307 conn->client.sock,
4308 conn->ssl,
4309 (const char *)buf,
4310 (int64_t)len);
4311 }
4312 return (int)total;
4313 }
4314
4315
4316 /* Alternative alloc_vprintf() for non-compliant C runtimes */
4317 static int
4318 alloc_vprintf2(char **buf, const char *fmt, va_list ap)
4319 {
4320 va_list ap_copy;
4321 size_t size = MG_BUF_LEN / 4;
4322 int len = -1;
4323
4324 *buf = NULL;
4325 while (len < 0) {
4326 if (*buf) {
4327 mg_free(*buf);
4328 }
4329
4330 size *= 4;
4331 *buf = (char *)mg_malloc(size);
4332 if (!*buf) {
4333 break;
4334 }
4335
4336 va_copy(ap_copy, ap);
4337 len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
4338 va_end(ap_copy);
4339 (*buf)[size - 1] = 0;
4340 }
4341
4342 return len;
4343 }
4344
4345
4346 /* Print message to buffer. If buffer is large enough to hold the message,
4347 * return buffer. If buffer is to small, allocate large enough buffer on heap,
4348 * and return allocated buffer. */
4349 static int
4350 alloc_vprintf(char **out_buf,
4351 char *prealloc_buf,
4352 size_t prealloc_size,
4353 const char *fmt,
4354 va_list ap)
4355 {
4356 va_list ap_copy;
4357 int len;
4358
4359 /* Windows is not standard-compliant, and vsnprintf() returns -1 if
4360 * buffer is too small. Also, older versions of msvcrt.dll do not have
4361 * _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
4362 * Therefore, we make two passes: on first pass, get required message
4363 * length.
4364 * On second pass, actually print the message. */
4365 va_copy(ap_copy, ap);
4366 len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
4367 va_end(ap_copy);
4368
4369 if (len < 0) {
4370 /* C runtime is not standard compliant, vsnprintf() returned -1.
4371 * Switch to alternative code path that uses incremental allocations.
4372 */
4373 va_copy(ap_copy, ap);
4374 len = alloc_vprintf2(out_buf, fmt, ap);
4375 va_end(ap_copy);
4376
4377 } else if ((size_t)(len) >= prealloc_size) {
4378 /* The pre-allocated buffer not large enough. */
4379 /* Allocate a new buffer. */
4380 *out_buf = (char *)mg_malloc((size_t)(len) + 1);
4381 if (!*out_buf) {
4382 /* Allocation failed. Return -1 as "out of memory" error. */
4383 return -1;
4384 }
4385 /* Buffer allocation successful. Store the string there. */
4386 va_copy(ap_copy, ap);
4387 IGNORE_UNUSED_RESULT(
4388 vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
4389 va_end(ap_copy);
4390
4391 } else {
4392 /* The pre-allocated buffer is large enough.
4393 * Use it to store the string and return the address. */
4394 va_copy(ap_copy, ap);
4395 IGNORE_UNUSED_RESULT(
4396 vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
4397 va_end(ap_copy);
4398 *out_buf = prealloc_buf;
4399 }
4400
4401 return len;
4402 }
4403
4404
4405 static int
4406 mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
4407 {
4408 char mem[MG_BUF_LEN];
4409 char *buf = NULL;
4410 int len;
4411
4412 if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
4413 len = mg_write(conn, buf, (size_t)len);
4414 }
4415 if (buf != mem && buf != NULL) {
4416 mg_free(buf);
4417 }
4418
4419 return len;
4420 }
4421
4422
4423 int
4424 mg_printf(struct mg_connection *conn, const char *fmt, ...)
4425 {
4426 va_list ap;
4427 int result;
4428
4429 va_start(ap, fmt);
4430 result = mg_vprintf(conn, fmt, ap);
4431 va_end(ap);
4432
4433 return result;
4434 }
4435
4436
4437 int
4438 mg_url_decode(const char *src,
4439 int src_len,
4440 char *dst,
4441 int dst_len,
4442 int is_form_url_encoded)
4443 {
4444 int i, j, a, b;
4445 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
4446
4447 for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
4448 if (i < src_len - 2 && src[i] == '%'
4449 && isxdigit(*(const unsigned char *)(src + i + 1))
4450 && isxdigit(*(const unsigned char *)(src + i + 2))) {
4451 a = tolower(*(const unsigned char *)(src + i + 1));
4452 b = tolower(*(const unsigned char *)(src + i + 2));
4453 dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
4454 i += 2;
4455 } else if (is_form_url_encoded && src[i] == '+') {
4456 dst[j] = ' ';
4457 } else {
4458 dst[j] = src[i];
4459 }
4460 }
4461
4462 dst[j] = '\0'; /* Null-terminate the destination */
4463
4464 return i >= src_len ? j : -1;
4465 }
4466
4467
4468 int
4469 mg_get_var(const char *data,
4470 size_t data_len,
4471 const char *name,
4472 char *dst,
4473 size_t dst_len)
4474 {
4475 return mg_get_var2(data, data_len, name, dst, dst_len, 0);
4476 }
4477
4478
4479 int
4480 mg_get_var2(const char *data,
4481 size_t data_len,
4482 const char *name,
4483 char *dst,
4484 size_t dst_len,
4485 size_t occurrence)
4486 {
4487 const char *p, *e, *s;
4488 size_t name_len;
4489 int len;
4490
4491 if (dst == NULL || dst_len == 0) {
4492 len = -2;
4493 } else if (data == NULL || name == NULL || data_len == 0) {
4494 len = -1;
4495 dst[0] = '\0';
4496 } else {
4497 name_len = strlen(name);
4498 e = data + data_len;
4499 len = -1;
4500 dst[0] = '\0';
4501
4502 /* data is "var1=val1&var2=val2...". Find variable first */
4503 for (p = data; p + name_len < e; p++) {
4504 if ((p == data || p[-1] == '&') && p[name_len] == '='
4505 && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
4506 /* Point p to variable value */
4507 p += name_len + 1;
4508
4509 /* Point s to the end of the value */
4510 s = (const char *)memchr(p, '&', (size_t)(e - p));
4511 if (s == NULL) {
4512 s = e;
4513 }
4514 /* assert(s >= p); */
4515 if (s < p) {
4516 return -3;
4517 }
4518
4519 /* Decode variable into destination buffer */
4520 len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
4521
4522 /* Redirect error code from -1 to -2 (destination buffer too
4523 * small). */
4524 if (len == -1) {
4525 len = -2;
4526 }
4527 break;
4528 }
4529 }
4530 }
4531
4532 return len;
4533 }
4534
4535
4536 int
4537 mg_get_cookie(const char *cookie_header,
4538 const char *var_name,
4539 char *dst,
4540 size_t dst_size)
4541 {
4542 const char *s, *p, *end;
4543 int name_len, len = -1;
4544
4545 if (dst == NULL || dst_size == 0) {
4546 len = -2;
4547 } else if (var_name == NULL || (s = cookie_header) == NULL) {
4548 len = -1;
4549 dst[0] = '\0';
4550 } else {
4551 name_len = (int)strlen(var_name);
4552 end = s + strlen(s);
4553 dst[0] = '\0';
4554
4555 for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
4556 if (s[name_len] == '=') {
4557 s += name_len + 1;
4558 if ((p = strchr(s, ' ')) == NULL) {
4559 p = end;
4560 }
4561 if (p[-1] == ';') {
4562 p--;
4563 }
4564 if (*s == '"' && p[-1] == '"' && p > s + 1) {
4565 s++;
4566 p--;
4567 }
4568 if ((size_t)(p - s) < dst_size) {
4569 len = (int)(p - s);
4570 mg_strlcpy(dst, s, (size_t)len + 1);
4571 } else {
4572 len = -3;
4573 }
4574 break;
4575 }
4576 }
4577 }
4578 return len;
4579 }
4580
4581
4582 #if defined(USE_WEBSOCKET) || defined(USE_LUA)
4583 static void
4584 base64_encode(const unsigned char *src, int src_len, char *dst)
4585 {
4586 static const char *b64 =
4587 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4588 int i, j, a, b, c;
4589
4590 for (i = j = 0; i < src_len; i += 3) {
4591 a = src[i];
4592 b = i + 1 >= src_len ? 0 : src[i + 1];
4593 c = i + 2 >= src_len ? 0 : src[i + 2];
4594
4595 dst[j++] = b64[a >> 2];
4596 dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
4597 if (i + 1 < src_len) {
4598 dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
4599 }
4600 if (i + 2 < src_len) {
4601 dst[j++] = b64[c & 63];
4602 }
4603 }
4604 while (j % 4 != 0) {
4605 dst[j++] = '=';
4606 }
4607 dst[j++] = '\0';
4608 }
4609 #endif
4610
4611
4612 #if defined(USE_LUA)
4613 static unsigned char
4614 b64reverse(char letter)
4615 {
4616 if (letter >= 'A' && letter <= 'Z') {
4617 return letter - 'A';
4618 }
4619 if (letter >= 'a' && letter <= 'z') {
4620 return letter - 'a' + 26;
4621 }
4622 if (letter >= '0' && letter <= '9') {
4623 return letter - '0' + 52;
4624 }
4625 if (letter == '+') {
4626 return 62;
4627 }
4628 if (letter == '/') {
4629 return 63;
4630 }
4631 if (letter == '=') {
4632 return 255; /* normal end */
4633 }
4634 return 254; /* error */
4635 }
4636
4637
4638 static int
4639 base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
4640 {
4641 int i;
4642 unsigned char a, b, c, d;
4643
4644 *dst_len = 0;
4645
4646 for (i = 0; i < src_len; i += 4) {
4647 a = b64reverse(src[i]);
4648 if (a >= 254) {
4649 return i;
4650 }
4651
4652 b = b64reverse(i + 1 >= src_len ? 0 : src[i + 1]);
4653 if (b >= 254) {
4654 return i + 1;
4655 }
4656
4657 c = b64reverse(i + 2 >= src_len ? 0 : src[i + 2]);
4658 if (c == 254) {
4659 return i + 2;
4660 }
4661
4662 d = b64reverse(i + 3 >= src_len ? 0 : src[i + 3]);
4663 if (d == 254) {
4664 return i + 3;
4665 }
4666
4667 dst[(*dst_len)++] = (a << 2) + (b >> 4);
4668 if (c != 255) {
4669 dst[(*dst_len)++] = (b << 4) + (c >> 2);
4670 if (d != 255) {
4671 dst[(*dst_len)++] = (c << 6) + d;
4672 }
4673 }
4674 }
4675 return -1;
4676 }
4677 #endif
4678
4679
4680 static int
4681 is_put_or_delete_method(const struct mg_connection *conn)
4682 {
4683 if (conn) {
4684 const char *s = conn->request_info.request_method;
4685 return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
4686 || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
4687 }
4688 return 0;
4689 }
4690
4691
4692 static void
4693 interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */
4694 char *filename, /* out: filename */
4695 size_t filename_buf_len, /* in: size of filename buffer */
4696 struct file *filep, /* out: file structure */
4697 int *is_found, /* out: file is found (directly) */
4698 int *is_script_resource, /* out: handled by a script? */
4699 int *is_websocket_request, /* out: websocket connetion? */
4700 int *is_put_or_delete_request /* out: put/delete a file? */
4701 )
4702 {
4703 /* TODO (high): Restructure this function */
4704
4705 #if !defined(NO_FILES)
4706 const char *uri = conn->request_info.local_uri;
4707 const char *root = conn->ctx->config[DOCUMENT_ROOT];
4708 const char *rewrite;
4709 struct vec a, b;
4710 int match_len;
4711 char gz_path[PATH_MAX];
4712 char const *accept_encoding;
4713 int truncated;
4714 #if !defined(NO_CGI) || defined(USE_LUA)
4715 char *p;
4716 #endif
4717 #else
4718 (void)filename_buf_len; /* unused if NO_FILES is defined */
4719 #endif
4720
4721 memset(filep, 0, sizeof(*filep));
4722 *filename = 0;
4723 *is_found = 0;
4724 *is_script_resource = 0;
4725 *is_put_or_delete_request = is_put_or_delete_method(conn);
4726
4727 #if defined(USE_WEBSOCKET)
4728 *is_websocket_request = is_websocket_protocol(conn);
4729 #if !defined(NO_FILES)
4730 if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
4731 root = conn->ctx->config[WEBSOCKET_ROOT];
4732 }
4733 #endif /* !NO_FILES */
4734 #else /* USE_WEBSOCKET */
4735 *is_websocket_request = 0;
4736 #endif /* USE_WEBSOCKET */
4737
4738 #if !defined(NO_FILES)
4739 /* Note that root == NULL is a regular use case here. This occurs,
4740 * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
4741 * config is not required. */
4742 if (root == NULL) {
4743 /* all file related outputs have already been set to 0, just return
4744 */
4745 return;
4746 }
4747
4748 /* Using buf_len - 1 because memmove() for PATH_INFO may shift part
4749 * of the path one byte on the right.
4750 * If document_root is NULL, leave the file empty. */
4751 mg_snprintf(
4752 conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
4753
4754 if (truncated) {
4755 goto interpret_cleanup;
4756 }
4757
4758 rewrite = conn->ctx->config[REWRITE];
4759 while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
4760 if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
4761 mg_snprintf(conn,
4762 &truncated,
4763 filename,
4764 filename_buf_len - 1,
4765 "%.*s%s",
4766 (int)b.len,
4767 b.ptr,
4768 uri + match_len);
4769 break;
4770 }
4771 }
4772
4773 if (truncated) {
4774 goto interpret_cleanup;
4775 }
4776
4777 /* Local file path and name, corresponding to requested URI
4778 * is now stored in "filename" variable. */
4779 if (mg_stat(conn, filename, filep)) {
4780 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4781 /* File exists. Check if it is a script type. */
4782 if (0
4783 #if !defined(NO_CGI)
4784 || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4785 strlen(conn->ctx->config[CGI_EXTENSIONS]),
4786 filename) > 0
4787 #endif
4788 #if defined(USE_LUA)
4789 || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4790 strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4791 filename) > 0
4792 #endif
4793 #if defined(USE_DUKTAPE)
4794 || match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4795 strlen(
4796 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4797 filename) > 0
4798 #endif
4799 ) {
4800 /* The request addresses a CGI script or a Lua script. The URI
4801 * corresponds to the script itself (like /path/script.cgi),
4802 * and there is no additional resource path
4803 * (like /path/script.cgi/something).
4804 * Requests that modify (replace or delete) a resource, like
4805 * PUT and DELETE requests, should replace/delete the script
4806 * file.
4807 * Requests that read or write from/to a resource, like GET and
4808 * POST requests, should call the script and return the
4809 * generated response. */
4810 *is_script_resource = !*is_put_or_delete_request;
4811 }
4812 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4813 *is_found = 1;
4814 return;
4815 }
4816
4817 /* If we can't find the actual file, look for the file
4818 * with the same name but a .gz extension. If we find it,
4819 * use that and set the gzipped flag in the file struct
4820 * to indicate that the response need to have the content-
4821 * encoding: gzip header.
4822 * We can only do this if the browser declares support. */
4823 if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
4824 if (strstr(accept_encoding, "gzip") != NULL) {
4825 mg_snprintf(
4826 conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
4827
4828 if (truncated) {
4829 goto interpret_cleanup;
4830 }
4831
4832 if (mg_stat(conn, gz_path, filep)) {
4833 if (filep) {
4834 filep->gzipped = 1;
4835 *is_found = 1;
4836 }
4837 /* Currently gz files can not be scripts. */
4838 return;
4839 }
4840 }
4841 }
4842
4843 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4844 /* Support PATH_INFO for CGI scripts. */
4845 for (p = filename + strlen(filename); p > filename + 1; p--) {
4846 if (*p == '/') {
4847 *p = '\0';
4848 if ((0
4849 #if !defined(NO_CGI)
4850 || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4851 strlen(conn->ctx->config[CGI_EXTENSIONS]),
4852 filename) > 0
4853 #endif
4854 #if defined(USE_LUA)
4855 || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4856 strlen(
4857 conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4858 filename) > 0
4859 #endif
4860 #if defined(USE_DUKTAPE)
4861 || match_prefix(
4862 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4863 strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4864 filename) > 0
4865 #endif
4866 ) && mg_stat(conn, filename, filep)) {
4867 /* Shift PATH_INFO block one character right, e.g.
4868 * "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
4869 * conn->path_info is pointing to the local variable "path"
4870 * declared in handle_request(), so PATH_INFO is not valid
4871 * after handle_request returns. */
4872 conn->path_info = p + 1;
4873 memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
4874 * trailing \0 */
4875 p[1] = '/';
4876 *is_script_resource = 1;
4877 break;
4878 } else {
4879 *p = '/';
4880 }
4881 }
4882 }
4883 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4884 #endif /* !defined(NO_FILES) */
4885 return;
4886
4887 #if !defined(NO_FILES)
4888 /* Reset all outputs */
4889 interpret_cleanup:
4890 memset(filep, 0, sizeof(*filep));
4891 *filename = 0;
4892 *is_found = 0;
4893 *is_script_resource = 0;
4894 *is_websocket_request = 0;
4895 *is_put_or_delete_request = 0;
4896 #endif /* !defined(NO_FILES) */
4897 }
4898
4899
4900 /* Check whether full request is buffered. Return:
4901 * -1 if request is malformed
4902 * 0 if request is not yet fully buffered
4903 * >0 actual request length, including last \r\n\r\n */
4904 static int
4905 get_request_len(const char *buf, int buflen)
4906 {
4907 const char *s, *e;
4908 int len = 0;
4909 int in_content = 0;
4910
4911 for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++) {
4912 /* Control characters are not allowed but >=128 is. */
4913 if (!in_content && !isprint(*(const unsigned char *)s) && *s != '\r'
4914 && *s != '\n'
4915 && *(const unsigned char *)s < 128) {
4916 len = -1;
4917 break; /* [i_a] abort scan as soon as one malformed character is
4918 * found; */
4919 /* don't let subsequent \r\n\r\n win us over anyhow */
4920 } else if (s[0] == '\n' && s[1] == '\n') {
4921 len = (int)(s - buf) + 2;
4922 } else if (s[0] == '\n' && &s[1] < e && s[1] == '\r' && s[2] == '\n') {
4923 len = (int)(s - buf) + 3;
4924 in_content = 0;
4925 }
4926
4927 if (!in_content && *s == ':') {
4928 in_content = 1;
4929 }
4930 }
4931
4932 return len;
4933 }
4934
4935
4936 #if !defined(NO_CACHING)
4937 /* Convert month to the month number. Return -1 on error, or month number */
4938 static int
4939 get_month_index(const char *s)
4940 {
4941 size_t i;
4942
4943 for (i = 0; i < ARRAY_SIZE(month_names); i++) {
4944 if (!strcmp(s, month_names[i])) {
4945 return (int)i;
4946 }
4947 }
4948
4949 return -1;
4950 }
4951
4952
4953 /* Parse UTC date-time string, and return the corresponding time_t value. */
4954 static time_t
4955 parse_date_string(const char *datetime)
4956 {
4957 char month_str[32] = {0};
4958 int second, minute, hour, day, month, year;
4959 time_t result = (time_t)0;
4960 struct tm tm;
4961
4962 if ((sscanf(datetime,
4963 "%d/%3s/%d %d:%d:%d",
4964 &day,
4965 month_str,
4966 &year,
4967 &hour,
4968 &minute,
4969 &second) == 6) || (sscanf(datetime,
4970 "%d %3s %d %d:%d:%d",
4971 &day,
4972 month_str,
4973 &year,
4974 &hour,
4975 &minute,
4976 &second) == 6)
4977 || (sscanf(datetime,
4978 "%*3s, %d %3s %d %d:%d:%d",
4979 &day,
4980 month_str,
4981 &year,
4982 &hour,
4983 &minute,
4984 &second) == 6) || (sscanf(datetime,
4985 "%d-%3s-%d %d:%d:%d",
4986 &day,
4987 month_str,
4988 &year,
4989 &hour,
4990 &minute,
4991 &second) == 6)) {
4992 month = get_month_index(month_str);
4993 if ((month >= 0) && (year >= 1970)) {
4994 memset(&tm, 0, sizeof(tm));
4995 tm.tm_year = year - 1900;
4996 tm.tm_mon = month;
4997 tm.tm_mday = day;
4998 tm.tm_hour = hour;
4999 tm.tm_min = minute;
5000 tm.tm_sec = second;
5001 result = timegm(&tm);
5002 }
5003 }
5004
5005 return result;
5006 }
5007 #endif /* !NO_CACHING */
5008
5009
5010 /* Protect against directory disclosure attack by removing '..',
5011 * excessive '/' and '\' characters */
5012 static void
5013 remove_double_dots_and_double_slashes(char *s)
5014 {
5015 char *p = s;
5016
5017 while (*s != '\0') {
5018 *p++ = *s++;
5019 if (s[-1] == '/' || s[-1] == '\\') {
5020 /* Skip all following slashes, backslashes and double-dots */
5021 while (s[0] != '\0') {
5022 if (s[0] == '/' || s[0] == '\\') {
5023 s++;
5024 } else if (s[0] == '.' && s[1] == '.') {
5025 s += 2;
5026 } else {
5027 break;
5028 }
5029 }
5030 }
5031 }
5032 *p = '\0';
5033 }
5034
5035
5036 static const struct {
5037 const char *extension;
5038 size_t ext_len;
5039 const char *mime_type;
5040 } builtin_mime_types[] = {
5041 /* IANA registered MIME types (http://www.iana.org/assignments/media-types)
5042 * application types */
5043 {".doc", 4, "application/msword"},
5044 {".eps", 4, "application/postscript"},
5045 {".exe", 4, "application/octet-stream"},
5046 {".js", 3, "application/javascript"},
5047 {".json", 5, "application/json"},
5048 {".pdf", 4, "application/pdf"},
5049 {".ps", 3, "application/postscript"},
5050 {".rtf", 4, "application/rtf"},
5051 {".xhtml", 6, "application/xhtml+xml"},
5052 {".xsl", 4, "application/xml"},
5053 {".xslt", 5, "application/xml"},
5054
5055 /* fonts */
5056 {".ttf", 4, "application/font-sfnt"},
5057 {".cff", 4, "application/font-sfnt"},
5058 {".otf", 4, "application/font-sfnt"},
5059 {".aat", 4, "application/font-sfnt"},
5060 {".sil", 4, "application/font-sfnt"},
5061 {".pfr", 4, "application/font-tdpfr"},
5062 {".woff", 5, "application/font-woff"},
5063
5064 /* audio */
5065 {".mp3", 4, "audio/mpeg"},
5066 {".oga", 4, "audio/ogg"},
5067 {".ogg", 4, "audio/ogg"},
5068
5069 /* image */
5070 {".gif", 4, "image/gif"},
5071 {".ief", 4, "image/ief"},
5072 {".jpeg", 5, "image/jpeg"},
5073 {".jpg", 4, "image/jpeg"},
5074 {".jpm", 4, "image/jpm"},
5075 {".jpx", 4, "image/jpx"},
5076 {".png", 4, "image/png"},
5077 {".svg", 4, "image/svg+xml"},
5078 {".tif", 4, "image/tiff"},
5079 {".tiff", 5, "image/tiff"},
5080
5081 /* model */
5082 {".wrl", 4, "model/vrml"},
5083
5084 /* text */
5085 {".css", 4, "text/css"},
5086 {".csv", 4, "text/csv"},
5087 {".htm", 4, "text/html"},
5088 {".html", 5, "text/html"},
5089 {".sgm", 4, "text/sgml"},
5090 {".shtm", 5, "text/html"},
5091 {".shtml", 6, "text/html"},
5092 {".txt", 4, "text/plain"},
5093 {".xml", 4, "text/xml"},
5094
5095 /* video */
5096 {".mov", 4, "video/quicktime"},
5097 {".mp4", 4, "video/mp4"},
5098 {".mpeg", 5, "video/mpeg"},
5099 {".mpg", 4, "video/mpeg"},
5100 {".ogv", 4, "video/ogg"},
5101 {".qt", 3, "video/quicktime"},
5102
5103 /* not registered types
5104 * (http://reference.sitepoint.com/html/mime-types-full,
5105 * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
5106 {".arj", 4, "application/x-arj-compressed"},
5107 {".gz", 3, "application/x-gunzip"},
5108 {".rar", 4, "application/x-arj-compressed"},
5109 {".swf", 4, "application/x-shockwave-flash"},
5110 {".tar", 4, "application/x-tar"},
5111 {".tgz", 4, "application/x-tar-gz"},
5112 {".torrent", 8, "application/x-bittorrent"},
5113 {".ppt", 4, "application/x-mspowerpoint"},
5114 {".xls", 4, "application/x-msexcel"},
5115 {".zip", 4, "application/x-zip-compressed"},
5116 {".aac",
5117 4,
5118 "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
5119 {".aif", 4, "audio/x-aif"},
5120 {".m3u", 4, "audio/x-mpegurl"},
5121 {".mid", 4, "audio/x-midi"},
5122 {".ra", 3, "audio/x-pn-realaudio"},
5123 {".ram", 4, "audio/x-pn-realaudio"},
5124 {".wav", 4, "audio/x-wav"},
5125 {".bmp", 4, "image/bmp"},
5126 {".ico", 4, "image/x-icon"},
5127 {".pct", 4, "image/x-pct"},
5128 {".pict", 5, "image/pict"},
5129 {".rgb", 4, "image/x-rgb"},
5130 {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
5131 {".asf", 4, "video/x-ms-asf"},
5132 {".avi", 4, "video/x-msvideo"},
5133 {".m4v", 4, "video/x-m4v"},
5134 {NULL, 0, NULL}};
5135
5136
5137 const char *
5138 mg_get_builtin_mime_type(const char *path)
5139 {
5140 const char *ext;
5141 size_t i, path_len;
5142
5143 path_len = strlen(path);
5144
5145 for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
5146 ext = path + (path_len - builtin_mime_types[i].ext_len);
5147 if (path_len > builtin_mime_types[i].ext_len
5148 && mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
5149 return builtin_mime_types[i].mime_type;
5150 }
5151 }
5152
5153 return "text/plain";
5154 }
5155
5156
5157 /* Look at the "path" extension and figure what mime type it has.
5158 * Store mime type in the vector. */
5159 static void
5160 get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
5161 {
5162 struct vec ext_vec, mime_vec;
5163 const char *list, *ext;
5164 size_t path_len;
5165
5166 path_len = strlen(path);
5167
5168 if (ctx == NULL || vec == NULL) {
5169 return;
5170 }
5171
5172 /* Scan user-defined mime types first, in case user wants to
5173 * override default mime types. */
5174 list = ctx->config[EXTRA_MIME_TYPES];
5175 while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
5176 /* ext now points to the path suffix */
5177 ext = path + path_len - ext_vec.len;
5178 if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
5179 *vec = mime_vec;
5180 return;
5181 }
5182 }
5183
5184 vec->ptr = mg_get_builtin_mime_type(path);
5185 vec->len = strlen(vec->ptr);
5186 }
5187
5188
5189 /* Stringify binary data. Output buffer must be twice as big as input,
5190 * because each byte takes 2 bytes in string representation */
5191 static void
5192 bin2str(char *to, const unsigned char *p, size_t len)
5193 {
5194 static const char *hex = "0123456789abcdef";
5195
5196 for (; len--; p++) {
5197 *to++ = hex[p[0] >> 4];
5198 *to++ = hex[p[0] & 0x0f];
5199 }
5200 *to = '\0';
5201 }
5202
5203
5204 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */
5205 char *
5206 mg_md5(char buf[33], ...)
5207 {
5208 md5_byte_t hash[16];
5209 const char *p;
5210 va_list ap;
5211 md5_state_t ctx;
5212
5213 md5_init(&ctx);
5214
5215 va_start(ap, buf);
5216 while ((p = va_arg(ap, const char *)) != NULL) {
5217 md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
5218 }
5219 va_end(ap);
5220
5221 md5_finish(&ctx, hash);
5222 bin2str(buf, hash, sizeof(hash));
5223 return buf;
5224 }
5225
5226
5227 /* Check the user's password, return 1 if OK */
5228 static int
5229 check_password(const char *method,
5230 const char *ha1,
5231 const char *uri,
5232 const char *nonce,
5233 const char *nc,
5234 const char *cnonce,
5235 const char *qop,
5236 const char *response)
5237 {
5238 char ha2[32 + 1], expected_response[32 + 1];
5239
5240 /* Some of the parameters may be NULL */
5241 if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL
5242 || qop == NULL
5243 || response == NULL) {
5244 return 0;
5245 }
5246
5247 /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
5248 if (strlen(response) != 32) {
5249 return 0;
5250 }
5251
5252 mg_md5(ha2, method, ":", uri, NULL);
5253 mg_md5(expected_response,
5254 ha1,
5255 ":",
5256 nonce,
5257 ":",
5258 nc,
5259 ":",
5260 cnonce,
5261 ":",
5262 qop,
5263 ":",
5264 ha2,
5265 NULL);
5266
5267 return mg_strcasecmp(response, expected_response) == 0;
5268 }
5269
5270
5271 /* Use the global passwords file, if specified by auth_gpass option,
5272 * or search for .htpasswd in the requested directory. */
5273 static void
5274 open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
5275 {
5276 if (conn != NULL && conn->ctx != NULL) {
5277 char name[PATH_MAX];
5278 const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
5279 struct file file = STRUCT_FILE_INITIALIZER;
5280 int truncated;
5281
5282 if (gpass != NULL) {
5283 /* Use global passwords file */
5284 if (!mg_fopen(conn, gpass, "r", filep)) {
5285 #ifdef DEBUG
5286 mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
5287 #endif
5288 }
5289 /* Important: using local struct file to test path for is_directory
5290 * flag. If filep is used, mg_stat() makes it appear as if auth file
5291 * was opened. */
5292 } else if (mg_stat(conn, path, &file) && file.is_directory) {
5293 mg_snprintf(conn,
5294 &truncated,
5295 name,
5296 sizeof(name),
5297 "%s/%s",
5298 path,
5299 PASSWORDS_FILE_NAME);
5300
5301 if (truncated || !mg_fopen(conn, name, "r", filep)) {
5302 #ifdef DEBUG
5303 mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5304 #endif
5305 }
5306 } else {
5307 /* Try to find .htpasswd in requested directory. */
5308 for (p = path, e = p + strlen(p) - 1; e > p; e--) {
5309 if (e[0] == '/') {
5310 break;
5311 }
5312 }
5313 mg_snprintf(conn,
5314 &truncated,
5315 name,
5316 sizeof(name),
5317 "%.*s/%s",
5318 (int)(e - p),
5319 p,
5320 PASSWORDS_FILE_NAME);
5321
5322 if (truncated || !mg_fopen(conn, name, "r", filep)) {
5323 #ifdef DEBUG
5324 mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5325 #endif
5326 }
5327 }
5328 }
5329 }
5330
5331
5332 /* Parsed Authorization header */
5333 struct ah {
5334 char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
5335 };
5336
5337
5338 /* Return 1 on success. Always initializes the ah structure. */
5339 static int
5340 parse_auth_header(struct mg_connection *conn,
5341 char *buf,
5342 size_t buf_size,
5343 struct ah *ah)
5344 {
5345 char *name, *value, *s;
5346 const char *auth_header;
5347 uint64_t nonce;
5348
5349 if (!ah || !conn) {
5350 return 0;
5351 }
5352
5353 (void)memset(ah, 0, sizeof(*ah));
5354 if ((auth_header = mg_get_header(conn, "Authorization")) == NULL
5355 || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
5356 return 0;
5357 }
5358
5359 /* Make modifiable copy of the auth header */
5360 (void)mg_strlcpy(buf, auth_header + 7, buf_size);
5361 s = buf;
5362
5363 /* Parse authorization header */
5364 for (;;) {
5365 /* Gobble initial spaces */
5366 while (isspace(*(unsigned char *)s)) {
5367 s++;
5368 }
5369 name = skip_quoted(&s, "=", " ", 0);
5370 /* Value is either quote-delimited, or ends at first comma or space. */
5371 if (s[0] == '\"') {
5372 s++;
5373 value = skip_quoted(&s, "\"", " ", '\\');
5374 if (s[0] == ',') {
5375 s++;
5376 }
5377 } else {
5378 value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
5379 * spaces */
5380 }
5381 if (*name == '\0') {
5382 break;
5383 }
5384
5385 if (!strcmp(name, "username")) {
5386 ah->user = value;
5387 } else if (!strcmp(name, "cnonce")) {
5388 ah->cnonce = value;
5389 } else if (!strcmp(name, "response")) {
5390 ah->response = value;
5391 } else if (!strcmp(name, "uri")) {
5392 ah->uri = value;
5393 } else if (!strcmp(name, "qop")) {
5394 ah->qop = value;
5395 } else if (!strcmp(name, "nc")) {
5396 ah->nc = value;
5397 } else if (!strcmp(name, "nonce")) {
5398 ah->nonce = value;
5399 }
5400 }
5401
5402 #ifndef NO_NONCE_CHECK
5403 /* Read the nonce from the response. */
5404 if (ah->nonce == NULL) {
5405 return 0;
5406 }
5407 s = NULL;
5408 nonce = strtoull(ah->nonce, &s, 10);
5409 if ((s == NULL) || (*s != 0)) {
5410 return 0;
5411 }
5412
5413 /* Convert the nonce from the client to a number. */
5414 nonce ^= conn->ctx->auth_nonce_mask;
5415
5416 /* The converted number corresponds to the time the nounce has been
5417 * created. This should not be earlier than the server start. */
5418 /* Server side nonce check is valuable in all situations but one:
5419 * if the server restarts frequently, but the client should not see
5420 * that, so the server should accept nonces from previous starts. */
5421 /* However, the reasonable default is to not accept a nonce from a
5422 * previous start, so if anyone changed the access rights between
5423 * two restarts, a new login is required. */
5424 if (nonce < (uint64_t)conn->ctx->start_time) {
5425 /* nonce is from a previous start of the server and no longer valid
5426 * (replay attack?) */
5427 return 0;
5428 }
5429 /* Check if the nonce is too high, so it has not (yet) been used by the
5430 * server. */
5431 if (nonce >= ((uint64_t)conn->ctx->start_time + conn->ctx->nonce_count)) {
5432 return 0;
5433 }
5434 #endif
5435
5436 /* CGI needs it as REMOTE_USER */
5437 if (ah->user != NULL) {
5438 conn->request_info.remote_user = mg_strdup(ah->user);
5439 } else {
5440 return 0;
5441 }
5442
5443 return 1;
5444 }
5445
5446
5447 static const char *
5448 mg_fgets(char *buf, size_t size, struct file *filep, char **p)
5449 {
5450 const char *eof;
5451 size_t len;
5452 const char *memend;
5453
5454 if (!filep) {
5455 return NULL;
5456 }
5457
5458 if (filep->membuf != NULL && *p != NULL) {
5459 memend = (const char *)&filep->membuf[filep->size];
5460 /* Search for \n from p till the end of stream */
5461 eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
5462 if (eof != NULL) {
5463 eof += 1; /* Include \n */
5464 } else {
5465 eof = memend; /* Copy remaining data */
5466 }
5467 len = (size_t)(eof - *p) > size - 1 ? size - 1 : (size_t)(eof - *p);
5468 memcpy(buf, *p, len);
5469 buf[len] = '\0';
5470 *p += len;
5471 return len ? eof : NULL;
5472 } else if (filep->fp != NULL) {
5473 return fgets(buf, (int)size, filep->fp);
5474 } else {
5475 return NULL;
5476 }
5477 }
5478
5479 struct read_auth_file_struct {
5480 struct mg_connection *conn;
5481 struct ah ah;
5482 char *domain;
5483 char buf[256 + 256 + 40];
5484 char *f_user;
5485 char *f_domain;
5486 char *f_ha1;
5487 };
5488
5489
5490 static int
5491 read_auth_file(struct file *filep, struct read_auth_file_struct *workdata)
5492 {
5493 char *p;
5494 int is_authorized = 0;
5495 struct file fp;
5496 size_t l;
5497
5498 if (!filep || !workdata) {
5499 return 0;
5500 }
5501
5502 /* Loop over passwords file */
5503 p = (char *)filep->membuf;
5504 while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
5505 l = strlen(workdata->buf);
5506 while (l > 0) {
5507 if (isspace(workdata->buf[l - 1])
5508 || iscntrl(workdata->buf[l - 1])) {
5509 l--;
5510 workdata->buf[l] = 0;
5511 } else
5512 break;
5513 }
5514 if (l < 1) {
5515 continue;
5516 }
5517
5518 workdata->f_user = workdata->buf;
5519
5520 if (workdata->f_user[0] == ':') {
5521 /* user names may not contain a ':' and may not be empty,
5522 * so lines starting with ':' may be used for a special purpose */
5523 if (workdata->f_user[1] == '#') {
5524 /* :# is a comment */
5525 continue;
5526 } else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
5527 if (mg_fopen(workdata->conn, workdata->f_user + 9, "r", &fp)) {
5528 is_authorized = read_auth_file(&fp, workdata);
5529 mg_fclose(&fp);
5530 } else {
5531 mg_cry(workdata->conn,
5532 "%s: cannot open authorization file: %s",
5533 __func__,
5534 workdata->buf);
5535 }
5536 continue;
5537 }
5538 /* everything is invalid for the moment (might change in the
5539 * future) */
5540 mg_cry(workdata->conn,
5541 "%s: syntax error in authorization file: %s",
5542 __func__,
5543 workdata->buf);
5544 continue;
5545 }
5546
5547 workdata->f_domain = strchr(workdata->f_user, ':');
5548 if (workdata->f_domain == NULL) {
5549 mg_cry(workdata->conn,
5550 "%s: syntax error in authorization file: %s",
5551 __func__,
5552 workdata->buf);
5553 continue;
5554 }
5555 *(workdata->f_domain) = 0;
5556 (workdata->f_domain)++;
5557
5558 workdata->f_ha1 = strchr(workdata->f_domain, ':');
5559 if (workdata->f_ha1 == NULL) {
5560 mg_cry(workdata->conn,
5561 "%s: syntax error in authorization file: %s",
5562 __func__,
5563 workdata->buf);
5564 continue;
5565 }
5566 *(workdata->f_ha1) = 0;
5567 (workdata->f_ha1)++;
5568
5569 if (!strcmp(workdata->ah.user, workdata->f_user)
5570 && !strcmp(workdata->domain, workdata->f_domain)) {
5571 return check_password(workdata->conn->request_info.request_method,
5572 workdata->f_ha1,
5573 workdata->ah.uri,
5574 workdata->ah.nonce,
5575 workdata->ah.nc,
5576 workdata->ah.cnonce,
5577 workdata->ah.qop,
5578 workdata->ah.response);
5579 }
5580 }
5581
5582 return is_authorized;
5583 }
5584
5585
5586 /* Authorize against the opened passwords file. Return 1 if authorized. */
5587 static int
5588 authorize(struct mg_connection *conn, struct file *filep)
5589 {
5590 struct read_auth_file_struct workdata;
5591 char buf[MG_BUF_LEN];
5592
5593 if (!conn || !conn->ctx) {
5594 return 0;
5595 }
5596
5597 memset(&workdata, 0, sizeof(workdata));
5598 workdata.conn = conn;
5599
5600 if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
5601 return 0;
5602 }
5603 workdata.domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
5604
5605 return read_auth_file(filep, &workdata);
5606 }
5607
5608
5609 /* Return 1 if request is authorised, 0 otherwise. */
5610 static int
5611 check_authorization(struct mg_connection *conn, const char *path)
5612 {
5613 char fname[PATH_MAX];
5614 struct vec uri_vec, filename_vec;
5615 const char *list;
5616 struct file file = STRUCT_FILE_INITIALIZER;
5617 int authorized = 1, truncated;
5618
5619 if (!conn || !conn->ctx) {
5620 return 0;
5621 }
5622
5623 list = conn->ctx->config[PROTECT_URI];
5624 while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
5625 if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
5626 mg_snprintf(conn,
5627 &truncated,
5628 fname,
5629 sizeof(fname),
5630 "%.*s",
5631 (int)filename_vec.len,
5632 filename_vec.ptr);
5633
5634 if (truncated || !mg_fopen(conn, fname, "r", &file)) {
5635 mg_cry(conn,
5636 "%s: cannot open %s: %s",
5637 __func__,
5638 fname,
5639 strerror(errno));
5640 }
5641 break;
5642 }
5643 }
5644
5645 if (!is_file_opened(&file)) {
5646 open_auth_file(conn, path, &file);
5647 }
5648
5649 if (is_file_opened(&file)) {
5650 authorized = authorize(conn, &file);
5651 mg_fclose(&file);
5652 }
5653
5654 return authorized;
5655 }
5656
5657
5658 static void
5659 send_authorization_request(struct mg_connection *conn)
5660 {
5661 char date[64];
5662 time_t curtime = time(NULL);
5663
5664 if (conn && conn->ctx) {
5665 uint64_t nonce = (uint64_t)(conn->ctx->start_time);
5666
5667 (void)pthread_mutex_lock(&conn->ctx->nonce_mutex);
5668 nonce += conn->ctx->nonce_count;
5669 ++conn->ctx->nonce_count;
5670 (void)pthread_mutex_unlock(&conn->ctx->nonce_mutex);
5671
5672 nonce ^= conn->ctx->auth_nonce_mask;
5673 conn->status_code = 401;
5674 conn->must_close = 1;
5675
5676 gmt_time_string(date, sizeof(date), &curtime);
5677
5678 mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
5679 send_no_cache_header(conn);
5680 mg_printf(conn,
5681 "Date: %s\r\n"
5682 "Connection: %s\r\n"
5683 "Content-Length: 0\r\n"
5684 "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
5685 "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
5686 date,
5687 suggest_connection_header(conn),
5688 conn->ctx->config[AUTHENTICATION_DOMAIN],
5689 nonce);
5690 }
5691 }
5692
5693
5694 #if !defined(NO_FILES)
5695 static int
5696 is_authorized_for_put(struct mg_connection *conn)
5697 {
5698 if (conn) {
5699 struct file file = STRUCT_FILE_INITIALIZER;
5700 const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
5701 int ret = 0;
5702
5703 if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) {
5704 ret = authorize(conn, &file);
5705 mg_fclose(&file);
5706 }
5707
5708 return ret;
5709 }
5710 return 0;
5711 }
5712 #endif
5713
5714
5715 int
5716 mg_modify_passwords_file(const char *fname,
5717 const char *domain,
5718 const char *user,
5719 const char *pass)
5720 {
5721 int found, i;
5722 char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
5723 FILE *fp, *fp2;
5724
5725 found = 0;
5726 fp = fp2 = NULL;
5727
5728 /* Regard empty password as no password - remove user record. */
5729 if (pass != NULL && pass[0] == '\0') {
5730 pass = NULL;
5731 }
5732
5733 /* Other arguments must not be empty */
5734 if (fname == NULL || domain == NULL || user == NULL) {
5735 return 0;
5736 }
5737
5738 /* Using the given file format, user name and domain must not contain ':'
5739 */
5740 if (strchr(user, ':') != NULL) {
5741 return 0;
5742 }
5743 if (strchr(domain, ':') != NULL) {
5744 return 0;
5745 }
5746
5747 /* Do not allow control characters like newline in user name and domain.
5748 * Do not allow excessively long names either. */
5749 for (i = 0; i < 255 && user[i] != 0; i++) {
5750 if (iscntrl(user[i])) {
5751 return 0;
5752 }
5753 }
5754 if (user[i]) {
5755 return 0;
5756 }
5757 for (i = 0; i < 255 && domain[i] != 0; i++) {
5758 if (iscntrl(domain[i])) {
5759 return 0;
5760 }
5761 }
5762 if (domain[i]) {
5763 return 0;
5764 }
5765
5766 /* The maximum length of the path to the password file is limited */
5767 if ((strlen(fname) + 4) >= PATH_MAX) {
5768 return 0;
5769 }
5770
5771 /* Create a temporary file name. Length has been checked before. */
5772 strcpy(tmp, fname);
5773 strcat(tmp, ".tmp");
5774
5775 /* Create the file if does not exist */
5776 /* Use of fopen here is OK, since fname is only ASCII */
5777 if ((fp = fopen(fname, "a+")) != NULL) {
5778 (void)fclose(fp);
5779 }
5780
5781 /* Open the given file and temporary file */
5782 if ((fp = fopen(fname, "r")) == NULL) {
5783 return 0;
5784 } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
5785 fclose(fp);
5786 return 0;
5787 }
5788
5789 /* Copy the stuff to temporary file */
5790 while (fgets(line, sizeof(line), fp) != NULL) {
5791 if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
5792 continue;
5793 }
5794 u[255] = 0;
5795 d[255] = 0;
5796
5797 if (!strcmp(u, user) && !strcmp(d, domain)) {
5798 found++;
5799 if (pass != NULL) {
5800 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5801 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5802 }
5803 } else {
5804 fprintf(fp2, "%s", line);
5805 }
5806 }
5807
5808 /* If new user, just add it */
5809 if (!found && pass != NULL) {
5810 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5811 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5812 }
5813
5814 /* Close files */
5815 fclose(fp);
5816 fclose(fp2);
5817
5818 /* Put the temp file in place of real file */
5819 IGNORE_UNUSED_RESULT(remove(fname));
5820 IGNORE_UNUSED_RESULT(rename(tmp, fname));
5821
5822 return 1;
5823 }
5824
5825
5826 static int
5827 is_valid_port(unsigned long port)
5828 {
5829 return port < 0xffff;
5830 }
5831
5832
5833 static int
5834 mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
5835 {
5836 struct addrinfo hints, *res, *ressave;
5837 int func_ret = 0;
5838 int gai_ret;
5839
5840 memset(&hints, 0, sizeof(struct addrinfo));
5841 hints.ai_family = af;
5842
5843 gai_ret = getaddrinfo(src, NULL, &hints, &res);
5844 if (gai_ret != 0) {
5845 /* gai_strerror could be used to convert gai_ret to a string */
5846 /* POSIX return values: see
5847 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
5848 */
5849 /* Windows return values: see
5850 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
5851 */
5852 return 0;
5853 }
5854
5855 ressave = res;
5856
5857 while (res) {
5858 if (dstlen >= res->ai_addrlen) {
5859 memcpy(dst, res->ai_addr, res->ai_addrlen);
5860 func_ret = 1;
5861 }
5862 res = res->ai_next;
5863 }
5864
5865 freeaddrinfo(ressave);
5866 return func_ret;
5867 }
5868
5869
5870 static int
5871 connect_socket(struct mg_context *ctx /* may be NULL */,
5872 const char *host,
5873 int port,
5874 int use_ssl,
5875 char *ebuf,
5876 size_t ebuf_len,
5877 SOCKET *sock /* output: socket, must not be NULL */,
5878 union usa *sa /* output: socket address, must not be NULL */
5879 )
5880 {
5881 int ip_ver = 0;
5882 *sock = INVALID_SOCKET;
5883 memset(sa, 0, sizeof(*sa));
5884
5885 if (ebuf_len > 0) {
5886 *ebuf = 0;
5887 }
5888
5889 if (host == NULL) {
5890 mg_snprintf(NULL,
5891 NULL, /* No truncation check for ebuf */
5892 ebuf,
5893 ebuf_len,
5894 "%s",
5895 "NULL host");
5896 return 0;
5897 }
5898
5899 if (port < 0 || !is_valid_port((unsigned)port)) {
5900 mg_snprintf(NULL,
5901 NULL, /* No truncation check for ebuf */
5902 ebuf,
5903 ebuf_len,
5904 "%s",
5905 "invalid port");
5906 return 0;
5907 }
5908
5909 #ifndef NO_SSL_DL
5910 if (use_ssl && (SSLv23_client_method == NULL)) {
5911 mg_snprintf(NULL,
5912 NULL, /* No truncation check for ebuf */
5913 ebuf,
5914 ebuf_len,
5915 "%s",
5916 "SSL is not initialized");
5917 return 0;
5918 }
5919 #endif
5920
5921 if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
5922 sa->sin.sin_port = htons((uint16_t)port);
5923 ip_ver = 4;
5924 #ifdef USE_IPV6
5925 } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
5926 sa->sin6.sin6_port = htons((uint16_t)port);
5927 ip_ver = 6;
5928 } else if (host[0] == '[') {
5929 /* While getaddrinfo on Windows will work with [::1],
5930 * getaddrinfo on Linux only works with ::1 (without []). */
5931 size_t l = strlen(host + 1);
5932 char *h = l > 1 ? mg_strdup(host + 1) : NULL;
5933 if (h) {
5934 h[l - 1] = 0;
5935 if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
5936 sa->sin6.sin6_port = htons((uint16_t)port);
5937 ip_ver = 6;
5938 }
5939 mg_free(h);
5940 }
5941 #endif
5942 }
5943
5944 if (ip_ver == 0) {
5945 mg_snprintf(NULL,
5946 NULL, /* No truncation check for ebuf */
5947 ebuf,
5948 ebuf_len,
5949 "%s",
5950 "host not found");
5951 return 0;
5952 }
5953
5954 if (ip_ver == 4) {
5955 *sock = socket(PF_INET, SOCK_STREAM, 0);
5956 }
5957 #ifdef USE_IPV6
5958 else if (ip_ver == 6) {
5959 *sock = socket(PF_INET6, SOCK_STREAM, 0);
5960 }
5961 #endif
5962
5963 if (*sock == INVALID_SOCKET) {
5964 mg_snprintf(NULL,
5965 NULL, /* No truncation check for ebuf */
5966 ebuf,
5967 ebuf_len,
5968 "socket(): %s",
5969 strerror(ERRNO));
5970 return 0;
5971 }
5972
5973 set_close_on_exec(*sock, fc(ctx));
5974
5975 if ((ip_ver == 4)
5976 && (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
5977 == 0)) {
5978 /* connected with IPv4 */
5979 return 1;
5980 }
5981
5982 #ifdef USE_IPV6
5983 if ((ip_ver == 6)
5984 && (connect(*sock, (struct sockaddr *)&sa->sin6, sizeof(sa->sin6))
5985 == 0)) {
5986 /* connected with IPv6 */
5987 return 1;
5988 }
5989 #endif
5990
5991 /* Not connected */
5992 mg_snprintf(NULL,
5993 NULL, /* No truncation check for ebuf */
5994 ebuf,
5995 ebuf_len,
5996 "connect(%s:%d): %s",
5997 host,
5998 port,
5999 strerror(ERRNO));
6000 closesocket(*sock);
6001 *sock = INVALID_SOCKET;
6002 return 0;
6003 }
6004
6005
6006 int
6007 mg_url_encode(const char *src, char *dst, size_t dst_len)
6008 {
6009 static const char *dont_escape = "._-$,;~()";
6010 static const char *hex = "0123456789abcdef";
6011 char *pos = dst;
6012 const char *end = dst + dst_len - 1;
6013
6014 for (; *src != '\0' && pos < end; src++, pos++) {
6015 if (isalnum(*(const unsigned char *)src)
6016 || strchr(dont_escape, *(const unsigned char *)src) != NULL) {
6017 *pos = *src;
6018 } else if (pos + 2 < end) {
6019 pos[0] = '%';
6020 pos[1] = hex[(*(const unsigned char *)src) >> 4];
6021 pos[2] = hex[(*(const unsigned char *)src) & 0xf];
6022 pos += 2;
6023 } else {
6024 break;
6025 }
6026 }
6027
6028 *pos = '\0';
6029 return (*src == '\0') ? (int)(pos - dst) : -1;
6030 }
6031
6032
6033 static void
6034 print_dir_entry(struct de *de)
6035 {
6036 char size[64], mod[64], href[PATH_MAX];
6037 struct tm *tm;
6038
6039 if (de->file.is_directory) {
6040 mg_snprintf(de->conn,
6041 NULL, /* Buffer is big enough */
6042 size,
6043 sizeof(size),
6044 "%s",
6045 "[DIRECTORY]");
6046 } else {
6047 /* We use (signed) cast below because MSVC 6 compiler cannot
6048 * convert unsigned __int64 to double. Sigh. */
6049 if (de->file.size < 1024) {
6050 mg_snprintf(de->conn,
6051 NULL, /* Buffer is big enough */
6052 size,
6053 sizeof(size),
6054 "%d",
6055 (int)de->file.size);
6056 } else if (de->file.size < 0x100000) {
6057 mg_snprintf(de->conn,
6058 NULL, /* Buffer is big enough */
6059 size,
6060 sizeof(size),
6061 "%.1fk",
6062 (double)de->file.size / 1024.0);
6063 } else if (de->file.size < 0x40000000) {
6064 mg_snprintf(de->conn,
6065 NULL, /* Buffer is big enough */
6066 size,
6067 sizeof(size),
6068 "%.1fM",
6069 (double)de->file.size / 1048576);
6070 } else {
6071 mg_snprintf(de->conn,
6072 NULL, /* Buffer is big enough */
6073 size,
6074 sizeof(size),
6075 "%.1fG",
6076 (double)de->file.size / 1073741824);
6077 }
6078 }
6079
6080 /* Note: mg_snprintf will not cause a buffer overflow above.
6081 * So, string truncation checks are not required here. */
6082
6083 tm = localtime(&de->file.last_modified);
6084 if (tm != NULL) {
6085 strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
6086 } else {
6087 mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
6088 mod[sizeof(mod) - 1] = '\0';
6089 }
6090 mg_url_encode(de->file_name, href, sizeof(href));
6091 de->conn->num_bytes_sent +=
6092 mg_printf(de->conn,
6093 "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
6094 "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6095 de->conn->request_info.local_uri,
6096 href,
6097 de->file.is_directory ? "/" : "",
6098 de->file_name,
6099 de->file.is_directory ? "/" : "",
6100 mod,
6101 size);
6102 }
6103
6104
6105 /* This function is called from send_directory() and used for
6106 * sorting directory entries by size, or name, or modification time.
6107 * On windows, __cdecl specification is needed in case if project is built
6108 * with __stdcall convention. qsort always requires __cdels callback. */
6109 static int WINCDECL
6110 compare_dir_entries(const void *p1, const void *p2)
6111 {
6112 if (p1 && p2) {
6113 const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
6114 const char *query_string = a->conn->request_info.query_string;
6115 int cmp_result = 0;
6116
6117 if (query_string == NULL) {
6118 query_string = "na";
6119 }
6120
6121 if (a->file.is_directory && !b->file.is_directory) {
6122 return -1; /* Always put directories on top */
6123 } else if (!a->file.is_directory && b->file.is_directory) {
6124 return 1; /* Always put directories on top */
6125 } else if (*query_string == 'n') {
6126 cmp_result = strcmp(a->file_name, b->file_name);
6127 } else if (*query_string == 's') {
6128 cmp_result = a->file.size == b->file.size
6129 ? 0
6130 : a->file.size > b->file.size ? 1 : -1;
6131 } else if (*query_string == 'd') {
6132 cmp_result =
6133 (a->file.last_modified == b->file.last_modified)
6134 ? 0
6135 : ((a->file.last_modified > b->file.last_modified) ? 1
6136 : -1);
6137 }
6138
6139 return query_string[1] == 'd' ? -cmp_result : cmp_result;
6140 }
6141 return 0;
6142 }
6143
6144
6145 static int
6146 must_hide_file(struct mg_connection *conn, const char *path)
6147 {
6148 if (conn && conn->ctx) {
6149 const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
6150 const char *pattern = conn->ctx->config[HIDE_FILES];
6151 return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
6152 || (pattern != NULL
6153 && match_prefix(pattern, strlen(pattern), path) > 0);
6154 }
6155 return 0;
6156 }
6157
6158
6159 static int
6160 scan_directory(struct mg_connection *conn,
6161 const char *dir,
6162 void *data,
6163 void (*cb)(struct de *, void *))
6164 {
6165 char path[PATH_MAX];
6166 struct dirent *dp;
6167 DIR *dirp;
6168 struct de de;
6169 int truncated;
6170
6171 if ((dirp = mg_opendir(conn, dir)) == NULL) {
6172 return 0;
6173 } else {
6174 de.conn = conn;
6175
6176 while ((dp = mg_readdir(dirp)) != NULL) {
6177 /* Do not show current dir and hidden files */
6178 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
6179 || must_hide_file(conn, dp->d_name)) {
6180 continue;
6181 }
6182
6183 mg_snprintf(
6184 conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6185
6186 /* If we don't memset stat structure to zero, mtime will have
6187 * garbage and strftime() will segfault later on in
6188 * print_dir_entry(). memset is required only if mg_stat()
6189 * fails. For more details, see
6190 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6191 memset(&de.file, 0, sizeof(de.file));
6192
6193 if (truncated) {
6194 /* If the path is not complete, skip processing. */
6195 continue;
6196 }
6197
6198 if (!mg_stat(conn, path, &de.file)) {
6199 mg_cry(conn,
6200 "%s: mg_stat(%s) failed: %s",
6201 __func__,
6202 path,
6203 strerror(ERRNO));
6204 }
6205 de.file_name = dp->d_name;
6206 cb(&de, data);
6207 }
6208 (void)mg_closedir(dirp);
6209 }
6210 return 1;
6211 }
6212
6213
6214 #if !defined(NO_FILES)
6215 static int
6216 remove_directory(struct mg_connection *conn, const char *dir)
6217 {
6218 char path[PATH_MAX];
6219 struct dirent *dp;
6220 DIR *dirp;
6221 struct de de;
6222 int truncated;
6223 int ok = 1;
6224
6225 if ((dirp = mg_opendir(conn, dir)) == NULL) {
6226 return 0;
6227 } else {
6228 de.conn = conn;
6229
6230 while ((dp = mg_readdir(dirp)) != NULL) {
6231 /* Do not show current dir (but show hidden files as they will
6232 * also be removed) */
6233 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
6234 continue;
6235 }
6236
6237 mg_snprintf(
6238 conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6239
6240 /* If we don't memset stat structure to zero, mtime will have
6241 * garbage and strftime() will segfault later on in
6242 * print_dir_entry(). memset is required only if mg_stat()
6243 * fails. For more details, see
6244 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6245 memset(&de.file, 0, sizeof(de.file));
6246
6247 if (truncated) {
6248 /* Do not delete anything shorter */
6249 ok = 0;
6250 continue;
6251 }
6252
6253 if (!mg_stat(conn, path, &de.file)) {
6254 mg_cry(conn,
6255 "%s: mg_stat(%s) failed: %s",
6256 __func__,
6257 path,
6258 strerror(ERRNO));
6259 ok = 0;
6260 }
6261 if (de.file.membuf == NULL) {
6262 /* file is not in memory */
6263 if (de.file.is_directory) {
6264 if (remove_directory(conn, path) == 0) {
6265 ok = 0;
6266 }
6267 } else {
6268 if (mg_remove(conn, path) == 0) {
6269 ok = 0;
6270 }
6271 }
6272 } else {
6273 /* file is in memory. It can not be deleted. */
6274 ok = 0;
6275 }
6276 }
6277 (void)mg_closedir(dirp);
6278
6279 IGNORE_UNUSED_RESULT(rmdir(dir));
6280 }
6281
6282 return ok;
6283 }
6284 #endif
6285
6286
6287 struct dir_scan_data {
6288 struct de *entries;
6289 unsigned int num_entries;
6290 unsigned int arr_size;
6291 };
6292
6293
6294 /* Behaves like realloc(), but frees original pointer on failure */
6295 static void *
6296 realloc2(void *ptr, size_t size)
6297 {
6298 void *new_ptr = mg_realloc(ptr, size);
6299 if (new_ptr == NULL) {
6300 mg_free(ptr);
6301 }
6302 return new_ptr;
6303 }
6304
6305
6306 static void
6307 dir_scan_callback(struct de *de, void *data)
6308 {
6309 struct dir_scan_data *dsd = (struct dir_scan_data *)data;
6310
6311 if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
6312 dsd->arr_size *= 2;
6313 dsd->entries =
6314 (struct de *)realloc2(dsd->entries,
6315 dsd->arr_size * sizeof(dsd->entries[0]));
6316 }
6317 if (dsd->entries == NULL) {
6318 /* TODO(lsm, low): propagate an error to the caller */
6319 dsd->num_entries = 0;
6320 } else {
6321 dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
6322 dsd->entries[dsd->num_entries].file = de->file;
6323 dsd->entries[dsd->num_entries].conn = de->conn;
6324 dsd->num_entries++;
6325 }
6326 }
6327
6328
6329 static void
6330 handle_directory_request(struct mg_connection *conn, const char *dir)
6331 {
6332 unsigned int i;
6333 int sort_direction;
6334 struct dir_scan_data data = {NULL, 0, 128};
6335 char date[64];
6336 time_t curtime = time(NULL);
6337
6338 if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
6339 send_http_error(conn,
6340 500,
6341 "Error: Cannot open directory\nopendir(%s): %s",
6342 dir,
6343 strerror(ERRNO));
6344 return;
6345 }
6346
6347 gmt_time_string(date, sizeof(date), &curtime);
6348
6349 if (!conn) {
6350 return;
6351 }
6352
6353 sort_direction = conn->request_info.query_string != NULL
6354 && conn->request_info.query_string[1] == 'd'
6355 ? 'a'
6356 : 'd';
6357
6358 conn->must_close = 1;
6359 mg_printf(conn, "HTTP/1.1 200 OK\r\n");
6360 send_static_cache_header(conn);
6361 mg_printf(conn,
6362 "Date: %s\r\n"
6363 "Connection: close\r\n"
6364 "Content-Type: text/html; charset=utf-8\r\n\r\n",
6365 date);
6366
6367 conn->num_bytes_sent +=
6368 mg_printf(conn,
6369 "<html><head><title>Index of %s</title>"
6370 "<style>th {text-align: left;}</style></head>"
6371 "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
6372 "<tr><th><a href=\"?n%c\">Name</a></th>"
6373 "<th><a href=\"?d%c\">Modified</a></th>"
6374 "<th><a href=\"?s%c\">Size</a></th></tr>"
6375 "<tr><td colspan=\"3\"><hr></td></tr>",
6376 conn->request_info.local_uri,
6377 conn->request_info.local_uri,
6378 sort_direction,
6379 sort_direction,
6380 sort_direction);
6381
6382 /* Print first entry - link to a parent directory */
6383 conn->num_bytes_sent +=
6384 mg_printf(conn,
6385 "<tr><td><a href=\"%s%s\">%s</a></td>"
6386 "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6387 conn->request_info.local_uri,
6388 "..",
6389 "Parent directory",
6390 "-",
6391 "-");
6392
6393 /* Sort and print directory entries */
6394 if (data.entries != NULL) {
6395 qsort(data.entries,
6396 (size_t)data.num_entries,
6397 sizeof(data.entries[0]),
6398 compare_dir_entries);
6399 for (i = 0; i < data.num_entries; i++) {
6400 print_dir_entry(&data.entries[i]);
6401 mg_free(data.entries[i].file_name);
6402 }
6403 mg_free(data.entries);
6404 }
6405
6406 conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
6407 conn->status_code = 200;
6408 }
6409
6410
6411 /* Send len bytes from the opened file to the client. */
6412 static void
6413 send_file_data(struct mg_connection *conn,
6414 struct file *filep,
6415 int64_t offset,
6416 int64_t len)
6417 {
6418 char buf[MG_BUF_LEN];
6419 int to_read, num_read, num_written;
6420 int64_t size;
6421
6422 if (!filep || !conn) {
6423 return;
6424 }
6425
6426 /* Sanity check the offset */
6427 size = filep->size > INT64_MAX ? INT64_MAX : (int64_t)(filep->size);
6428 offset = offset < 0 ? 0 : offset > size ? size : offset;
6429
6430 if (len > 0 && filep->membuf != NULL && size > 0) {
6431 /* file stored in memory */
6432 if (len > size - offset) {
6433 len = size - offset;
6434 }
6435 mg_write(conn, filep->membuf + offset, (size_t)len);
6436 } else if (len > 0 && filep->fp != NULL) {
6437 /* file stored on disk */
6438 #if defined(__linux__)
6439 /* sendfile is only available for Linux */
6440 if (conn->throttle == 0 && conn->ssl == 0) {
6441 off_t sf_offs = (off_t)offset;
6442 ssize_t sf_sent;
6443 int sf_file = fileno(filep->fp);
6444 int loop_cnt = 0;
6445
6446 do {
6447 /* 2147479552 (0x7FFFF000) is a limit found by experiment on
6448 * 64 bit Linux (2^31 minus one memory page of 4k?). */
6449 size_t sf_tosend =
6450 (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
6451 sf_sent =
6452 sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
6453 if (sf_sent > 0) {
6454 conn->num_bytes_sent += sf_sent;
6455 len -= sf_sent;
6456 offset += sf_sent;
6457 } else if (loop_cnt == 0) {
6458 /* This file can not be sent using sendfile.
6459 * This might be the case for pseudo-files in the
6460 * /sys/ and /proc/ file system.
6461 * Use the regular user mode copy code instead. */
6462 break;
6463 } else if (sf_sent == 0) {
6464 /* No error, but 0 bytes sent. May be EOF? */
6465 return;
6466 }
6467 loop_cnt++;
6468
6469 } while ((len > 0) && (sf_sent >= 0));
6470
6471 if (sf_sent > 0) {
6472 return; /* OK */
6473 }
6474
6475 /* sf_sent<0 means error, thus fall back to the classic way */
6476 /* This is always the case, if sf_file is not a "normal" file,
6477 * e.g., for sending data from the output of a CGI process. */
6478 offset = (int64_t)sf_offs;
6479 }
6480 #endif
6481 if ((offset > 0) && (fseeko(filep->fp, offset, SEEK_SET) != 0)) {
6482 mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
6483 send_http_error(
6484 conn,
6485 500,
6486 "%s",
6487 "Error: Unable to access file at requested position.");
6488 } else {
6489 while (len > 0) {
6490 /* Calculate how much to read from the file in the buffer */
6491 to_read = sizeof(buf);
6492 if ((int64_t)to_read > len) {
6493 to_read = (int)len;
6494 }
6495
6496 /* Read from file, exit the loop on error */
6497 if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp))
6498 <= 0) {
6499 break;
6500 }
6501
6502 /* Send read bytes to the client, exit the loop on error */
6503 if ((num_written = mg_write(conn, buf, (size_t)num_read))
6504 != num_read) {
6505 break;
6506 }
6507
6508 /* Both read and were successful, adjust counters */
6509 conn->num_bytes_sent += num_written;
6510 len -= num_written;
6511 }
6512 }
6513 }
6514 }
6515
6516
6517 static int
6518 parse_range_header(const char *header, int64_t *a, int64_t *b)
6519 {
6520 return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
6521 }
6522
6523
6524 static void
6525 construct_etag(char *buf, size_t buf_len, const struct file *filep)
6526 {
6527 if (filep != NULL && buf != NULL) {
6528 mg_snprintf(NULL,
6529 NULL, /* All calls to construct_etag use 64 byte buffer */
6530 buf,
6531 buf_len,
6532 "\"%lx.%" INT64_FMT "\"",
6533 (unsigned long)filep->last_modified,
6534 filep->size);
6535 }
6536 }
6537
6538
6539 static void
6540 fclose_on_exec(struct file *filep, struct mg_connection *conn)
6541 {
6542 if (filep != NULL && filep->fp != NULL) {
6543 #ifdef _WIN32
6544 (void)conn; /* Unused. */
6545 #else
6546 if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
6547 mg_cry(conn,
6548 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
6549 __func__,
6550 strerror(ERRNO));
6551 }
6552 #endif
6553 }
6554 }
6555
6556
6557 static void
6558 handle_static_file_request(struct mg_connection *conn,
6559 const char *path,
6560 struct file *filep,
6561 const char *mime_type)
6562 {
6563 char date[64], lm[64], etag[64];
6564 char range[128]; /* large enough, so there will be no overflow */
6565 const char *msg = "OK", *hdr;
6566 time_t curtime = time(NULL);
6567 int64_t cl, r1, r2;
6568 struct vec mime_vec;
6569 int n, truncated;
6570 char gz_path[PATH_MAX];
6571 const char *encoding = "";
6572 const char *cors1, *cors2, *cors3;
6573
6574 if (conn == NULL || conn->ctx == NULL || filep == NULL) {
6575 return;
6576 }
6577
6578 if (mime_type == NULL) {
6579 get_mime_type(conn->ctx, path, &mime_vec);
6580 } else {
6581 mime_vec.ptr = mime_type;
6582 mime_vec.len = strlen(mime_type);
6583 }
6584 if (filep->size > INT64_MAX) {
6585 send_http_error(conn,
6586 500,
6587 "Error: File size is too large to send\n%" INT64_FMT,
6588 filep->size);
6589 }
6590 cl = (int64_t)filep->size;
6591 conn->status_code = 200;
6592 range[0] = '\0';
6593
6594 /* if this file is in fact a pre-gzipped file, rewrite its filename
6595 * it's important to rewrite the filename after resolving
6596 * the mime type from it, to preserve the actual file's type */
6597 if (filep->gzipped) {
6598 mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
6599
6600 if (truncated) {
6601 send_http_error(conn,
6602 500,
6603 "Error: Path of zipped file too long (%s)",
6604 path);
6605 return;
6606 }
6607
6608 path = gz_path;
6609 encoding = "Content-Encoding: gzip\r\n";
6610 }
6611
6612 if (!mg_fopen(conn, path, "rb", filep)) {
6613 send_http_error(conn,
6614 500,
6615 "Error: Cannot open file\nfopen(%s): %s",
6616 path,
6617 strerror(ERRNO));
6618 return;
6619 }
6620
6621 fclose_on_exec(filep, conn);
6622
6623 /* If Range: header specified, act accordingly */
6624 r1 = r2 = 0;
6625 hdr = mg_get_header(conn, "Range");
6626 if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && r1 >= 0
6627 && r2 >= 0) {
6628 /* actually, range requests don't play well with a pre-gzipped
6629 * file (since the range is specified in the uncompressed space) */
6630 if (filep->gzipped) {
6631 send_http_error(
6632 conn,
6633 501,
6634 "%s",
6635 "Error: Range requests in gzipped files are not supported");
6636 mg_fclose(filep);
6637 return;
6638 }
6639 conn->status_code = 206;
6640 cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1 : cl - r1;
6641 mg_snprintf(conn,
6642 NULL, /* range buffer is big enough */
6643 range,
6644 sizeof(range),
6645 "Content-Range: bytes "
6646 "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
6647 r1,
6648 r1 + cl - 1,
6649 filep->size);
6650 msg = "Partial Content";
6651 }
6652
6653 hdr = mg_get_header(conn, "Origin");
6654 if (hdr) {
6655 /* Cross-origin resource sharing (CORS), see
6656 * http://www.html5rocks.com/en/tutorials/cors/,
6657 * http://www.html5rocks.com/static/images/cors_server_flowchart.png -
6658 * preflight is not supported for files. */
6659 cors1 = "Access-Control-Allow-Origin: ";
6660 cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
6661 cors3 = "\r\n";
6662 } else {
6663 cors1 = cors2 = cors3 = "";
6664 }
6665
6666 /* Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
6667 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
6668 gmt_time_string(date, sizeof(date), &curtime);
6669 gmt_time_string(lm, sizeof(lm), &filep->last_modified);
6670 construct_etag(etag, sizeof(etag), filep);
6671
6672 (void)mg_printf(conn,
6673 "HTTP/1.1 %d %s\r\n"
6674 "%s%s%s"
6675 "Date: %s\r\n",
6676 conn->status_code,
6677 msg,
6678 cors1,
6679 cors2,
6680 cors3,
6681 date);
6682 send_static_cache_header(conn);
6683 (void)mg_printf(conn,
6684 "Last-Modified: %s\r\n"
6685 "Etag: %s\r\n"
6686 "Content-Type: %.*s\r\n"
6687 "Content-Length: %" INT64_FMT "\r\n"
6688 "Connection: %s\r\n"
6689 "Accept-Ranges: bytes\r\n"
6690 "%s%s\r\n",
6691 lm,
6692 etag,
6693 (int)mime_vec.len,
6694 mime_vec.ptr,
6695 cl,
6696 suggest_connection_header(conn),
6697 range,
6698 encoding);
6699
6700 if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
6701 send_file_data(conn, filep, r1, cl);
6702 }
6703 mg_fclose(filep);
6704 }
6705
6706
6707 void
6708 mg_send_file(struct mg_connection *conn, const char *path)
6709 {
6710 mg_send_mime_file(conn, path, NULL);
6711 }
6712
6713
6714 void
6715 mg_send_mime_file(struct mg_connection *conn,
6716 const char *path,
6717 const char *mime_type)
6718 {
6719 struct file file = STRUCT_FILE_INITIALIZER;
6720 if (mg_stat(conn, path, &file)) {
6721 if (file.is_directory) {
6722 if (!conn) {
6723 return;
6724 }
6725 if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
6726 "yes")) {
6727 handle_directory_request(conn, path);
6728 } else {
6729 send_http_error(conn,
6730 403,
6731 "%s",
6732 "Error: Directory listing denied");
6733 }
6734 } else {
6735 handle_static_file_request(conn, path, &file, mime_type);
6736 }
6737 } else {
6738 send_http_error(conn, 404, "%s", "Error: File not found");
6739 }
6740 }
6741
6742
6743 /* For a given PUT path, create all intermediate subdirectories.
6744 * Return 0 if the path itself is a directory.
6745 * Return 1 if the path leads to a file.
6746 * Return -1 for if the path is too long.
6747 * Return -2 if path can not be created.
6748 */
6749 static int
6750 put_dir(struct mg_connection *conn, const char *path)
6751 {
6752 char buf[PATH_MAX];
6753 const char *s, *p;
6754 struct file file = STRUCT_FILE_INITIALIZER;
6755 size_t len;
6756 int res = 1;
6757
6758 for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
6759 len = (size_t)(p - path);
6760 if (len >= sizeof(buf)) {
6761 /* path too long */
6762 res = -1;
6763 break;
6764 }
6765 memcpy(buf, path, len);
6766 buf[len] = '\0';
6767
6768 /* Try to create intermediate directory */
6769 DEBUG_TRACE("mkdir(%s)", buf);
6770 if (!mg_stat(conn, buf, &file) && mg_mkdir(conn, buf, 0755) != 0) {
6771 /* path does not exixt and can not be created */
6772 res = -2;
6773 break;
6774 }
6775
6776 /* Is path itself a directory? */
6777 if (p[1] == '\0') {
6778 res = 0;
6779 }
6780 }
6781
6782 return res;
6783 }
6784
6785
6786 static void
6787 remove_bad_file(const struct mg_connection *conn, const char *path)
6788 {
6789 int r = mg_remove(conn, path);
6790 if (r != 0) {
6791 mg_cry(conn, "%s: Cannot remove invalid file %s", __func__, path);
6792 }
6793 }
6794
6795
6796 long long
6797 mg_store_body(struct mg_connection *conn, const char *path)
6798 {
6799 char buf[MG_BUF_LEN];
6800 long long len = 0;
6801 int ret, n;
6802 struct file fi;
6803
6804 if (conn->consumed_content != 0) {
6805 mg_cry(conn, "%s: Contents already consumed", __func__);
6806 return -11;
6807 }
6808
6809 ret = put_dir(conn, path);
6810 if (ret < 0) {
6811 /* -1 for path too long,
6812 * -2 for path can not be created. */
6813 return ret;
6814 }
6815 if (ret != 1) {
6816 /* Return 0 means, path itself is a directory. */
6817 return 0;
6818 }
6819
6820 if (mg_fopen(conn, path, "w", &fi) == 0) {
6821 return -12;
6822 }
6823
6824 ret = mg_read(conn, buf, sizeof(buf));
6825 while (ret > 0) {
6826 n = (int)fwrite(buf, 1, (size_t)ret, fi.fp);
6827 if (n != ret) {
6828 mg_fclose(&fi);
6829 remove_bad_file(conn, path);
6830 return -13;
6831 }
6832 ret = mg_read(conn, buf, sizeof(buf));
6833 }
6834
6835 /* TODO: mg_fclose should return an error,
6836 * and every caller should check and handle it. */
6837 if (fclose(fi.fp) != 0) {
6838 remove_bad_file(conn, path);
6839 return -14;
6840 }
6841
6842 return len;
6843 }
6844
6845
6846 /* Parse HTTP headers from the given buffer, advance buffer to the point
6847 * where parsing stopped. */
6848 static void
6849 parse_http_headers(char **buf, struct mg_request_info *ri)
6850 {
6851 int i;
6852
6853 if (!ri) {
6854 return;
6855 }
6856
6857 ri->num_headers = 0;
6858
6859 for (i = 0; i < (int)ARRAY_SIZE(ri->http_headers); i++) {
6860 char *dp = *buf;
6861 while ((*dp != ':') && (*dp != '\r') && (*dp != 0)) {
6862 dp++;
6863 }
6864 if (!*dp) {
6865 /* neither : nor \r\n. This is not a valid field. */
6866 break;
6867 }
6868 if (*dp == '\r') {
6869 if (dp[1] == '\n') {
6870 /* \r\n */
6871 ri->http_headers[i].name = *buf;
6872 ri->http_headers[i].value = 0;
6873 *buf = dp;
6874 } else {
6875 /* stray \r. This is not valid. */
6876 break;
6877 }
6878 } else {
6879 /* (*dp == ':') */
6880 *dp = 0;
6881 ri->http_headers[i].name = *buf;
6882 do {
6883 dp++;
6884 } while (*dp == ' ');
6885
6886 ri->http_headers[i].value = dp;
6887 *buf = strstr(dp, "\r\n");
6888 }
6889
6890 ri->num_headers = i + 1;
6891 if (*buf) {
6892 (*buf)[0] = 0;
6893 (*buf)[1] = 0;
6894 *buf += 2;
6895 } else {
6896 *buf = dp;
6897 break;
6898 }
6899
6900 if (*buf[0] == '\r') {
6901 /* This is the end of the header */
6902 break;
6903 }
6904 }
6905 }
6906
6907
6908 static int
6909 is_valid_http_method(const char *method)
6910 {
6911 return !strcmp(method, "GET") /* HTTP (RFC 2616) */
6912 || !strcmp(method, "POST") /* HTTP (RFC 2616) */
6913 || !strcmp(method, "HEAD") /* HTTP (RFC 2616) */
6914 || !strcmp(method, "PUT") /* HTTP (RFC 2616) */
6915 || !strcmp(method, "DELETE") /* HTTP (RFC 2616) */
6916 || !strcmp(method, "OPTIONS") /* HTTP (RFC 2616) */
6917 /* TRACE method (RFC 2616) is not supported for security reasons */
6918 || !strcmp(method, "CONNECT") /* HTTP (RFC 2616) */
6919
6920 || !strcmp(method, "PROPFIND") /* WEBDAV (RFC 2518) */
6921 || !strcmp(method, "MKCOL") /* WEBDAV (RFC 2518) */
6922
6923 /* Unsupported WEBDAV Methods: */
6924 /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
6925 /* + 11 methods from RFC 3253 */
6926 /* ORDERPATCH (RFC 3648) */
6927 /* ACL (RFC 3744) */
6928 /* SEARCH (RFC 5323) */
6929 /* + MicroSoft extensions
6930 * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
6931
6932 /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
6933 || !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
6934 }
6935
6936
6937 /* Parse HTTP request, fill in mg_request_info structure.
6938 * This function modifies the buffer by NUL-terminating
6939 * HTTP request components, header names and header values. */
6940 static int
6941 parse_http_message(int check_method,
6942 char *buf,
6943 int len,
6944 struct mg_request_info *ri)
6945 {
6946 int is_request, request_length;
6947
6948 if (!ri) {
6949 return 0;
6950 }
6951
6952 request_length = get_request_len(buf, len);
6953
6954 if (request_length > 0) {
6955 /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
6956 * remote_port */
6957 ri->remote_user = ri->request_method = ri->request_uri =
6958 ri->http_version = NULL;
6959 ri->num_headers = 0;
6960
6961 buf[request_length - 1] = '\0';
6962
6963 /* RFC says that all initial whitespaces should be ingored */
6964 while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
6965 buf++;
6966 }
6967 ri->request_method = skip(&buf, " ");
6968 ri->request_uri = skip(&buf, " ");
6969 ri->http_version = skip(&buf, "\r\n");
6970
6971 /* HTTP message could be either HTTP request or HTTP response, e.g.
6972 * "GET / HTTP/1.0 ...." or "HTTP/1.0 200 OK ..." */
6973 is_request =
6974 check_method ? is_valid_http_method(ri->request_method) : 1;
6975 if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
6976 || (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
6977 request_length = -1;
6978 } else {
6979 if (is_request) {
6980 ri->http_version += 5;
6981 }
6982 parse_http_headers(&buf, ri);
6983 }
6984 }
6985 return request_length;
6986 }
6987
6988
6989 /* Keep reading the input (either opened file descriptor fd, or socket sock,
6990 * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
6991 * buffer (which marks the end of HTTP request). Buffer buf may already
6992 * have some data. The length of the data is stored in nread.
6993 * Upon every read operation, increase nread by the number of bytes read. */
6994 static int
6995 read_request(FILE *fp,
6996 struct mg_connection *conn,
6997 char *buf,
6998 int bufsiz,
6999 int *nread)
7000 {
7001 int request_len, n = 0;
7002 struct timespec last_action_time;
7003 double request_timeout;
7004
7005 if (!conn) {
7006 return 0;
7007 }
7008
7009 memset(&last_action_time, 0, sizeof(last_action_time));
7010
7011 if (conn->ctx->config[REQUEST_TIMEOUT]) {
7012 /* value of request_timeout is in seconds, config in milliseconds */
7013 request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7014 } else {
7015 request_timeout = -1.0;
7016 }
7017
7018 request_len = get_request_len(buf, *nread);
7019
7020 /* first time reading from this connection */
7021 clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7022
7023 while (
7024 (conn->ctx->stop_flag == 0) && (*nread < bufsiz) && (request_len == 0)
7025 && ((mg_difftimespec(&last_action_time, &(conn->req_time))
7026 <= request_timeout) || (request_timeout < 0))
7027 && ((n = pull(fp, conn, buf + *nread, bufsiz - *nread, request_timeout))
7028 > 0)) {
7029 *nread += n;
7030 /* assert(*nread <= bufsiz); */
7031 if (*nread > bufsiz) {
7032 return -2;
7033 }
7034 request_len = get_request_len(buf, *nread);
7035 if (request_timeout > 0.0) {
7036 clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7037 }
7038 }
7039
7040 return (request_len <= 0 && n <= 0) ? -1 : request_len;
7041 }
7042
7043 #if !defined(NO_FILES)
7044 /* For given directory path, substitute it to valid index file.
7045 * Return 1 if index file has been found, 0 if not found.
7046 * If the file is found, it's stats is returned in stp. */
7047 static int
7048 substitute_index_file(struct mg_connection *conn,
7049 char *path,
7050 size_t path_len,
7051 struct file *filep)
7052 {
7053 if (conn && conn->ctx) {
7054 const char *list = conn->ctx->config[INDEX_FILES];
7055 struct file file = STRUCT_FILE_INITIALIZER;
7056 struct vec filename_vec;
7057 size_t n = strlen(path);
7058 int found = 0;
7059
7060 /* The 'path' given to us points to the directory. Remove all trailing
7061 * directory separator characters from the end of the path, and
7062 * then append single directory separator character. */
7063 while (n > 0 && path[n - 1] == '/') {
7064 n--;
7065 }
7066 path[n] = '/';
7067
7068 /* Traverse index files list. For each entry, append it to the given
7069 * path and see if the file exists. If it exists, break the loop */
7070 while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7071 /* Ignore too long entries that may overflow path buffer */
7072 if (filename_vec.len > path_len - (n + 2)) {
7073 continue;
7074 }
7075
7076 /* Prepare full path to the index file */
7077 mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7078
7079 /* Does it exist? */
7080 if (mg_stat(conn, path, &file)) {
7081 /* Yes it does, break the loop */
7082 *filep = file;
7083 found = 1;
7084 break;
7085 }
7086 }
7087
7088 /* If no index file exists, restore directory path */
7089 if (!found) {
7090 path[n] = '\0';
7091 }
7092
7093 return found;
7094 }
7095 return 0;
7096 }
7097 #endif
7098
7099
7100 #if !defined(NO_CACHING)
7101 /* Return True if we should reply 304 Not Modified. */
7102 static int
7103 is_not_modified(const struct mg_connection *conn, const struct file *filep)
7104 {
7105 char etag[64];
7106 const char *ims = mg_get_header(conn, "If-Modified-Since");
7107 const char *inm = mg_get_header(conn, "If-None-Match");
7108 construct_etag(etag, sizeof(etag), filep);
7109 if (!filep) {
7110 return 0;
7111 }
7112 return (inm != NULL && !mg_strcasecmp(etag, inm))
7113 || (ims != NULL && (filep->last_modified <= parse_date_string(ims)));
7114 }
7115 #endif /* !NO_CACHING */
7116
7117
7118 #if !defined(NO_CGI) || !defined(NO_FILES)
7119 static int
7120 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
7121 {
7122 const char *expect, *body;
7123 char buf[MG_BUF_LEN];
7124 int to_read, nread, success = 0;
7125 int64_t buffered_len;
7126 double timeout = -1.0;
7127
7128 if (!conn) {
7129 return 0;
7130 }
7131 if (conn->ctx->config[REQUEST_TIMEOUT]) {
7132 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7133 }
7134
7135 expect = mg_get_header(conn, "Expect");
7136 /* assert(fp != NULL); */
7137 if (!fp) {
7138 send_http_error(conn, 500, "%s", "Error: NULL File");
7139 return 0;
7140 }
7141
7142 if (conn->content_len == -1 && !conn->is_chunked) {
7143 /* Content length is not specified by the client. */
7144 send_http_error(conn,
7145 411,
7146 "%s",
7147 "Error: Client did not specify content length");
7148 } else if ((expect != NULL)
7149 && (mg_strcasecmp(expect, "100-continue") != 0)) {
7150 /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
7151 send_http_error(conn,
7152 417,
7153 "Error: Can not fulfill expectation %s",
7154 expect);
7155 } else {
7156 if (expect != NULL) {
7157 (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
7158 conn->status_code = 100;
7159 } else {
7160 conn->status_code = 200;
7161 }
7162
7163 buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
7164 - conn->consumed_content;
7165
7166 /* assert(buffered_len >= 0); */
7167 /* assert(conn->consumed_content == 0); */
7168
7169 if ((buffered_len < 0) || (conn->consumed_content != 0)) {
7170 send_http_error(conn, 500, "%s", "Error: Size mismatch");
7171 return 0;
7172 }
7173
7174 if (buffered_len > 0) {
7175 if ((int64_t)buffered_len > conn->content_len) {
7176 buffered_len = (int)conn->content_len;
7177 }
7178 body = conn->buf + conn->request_len + conn->consumed_content;
7179 push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
7180 conn->consumed_content += buffered_len;
7181 }
7182
7183 nread = 0;
7184 while (conn->consumed_content < conn->content_len) {
7185 to_read = sizeof(buf);
7186 if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
7187 to_read = (int)(conn->content_len - conn->consumed_content);
7188 }
7189 nread = pull(NULL, conn, buf, to_read, timeout);
7190 if (nread <= 0
7191 || push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
7192 break;
7193 }
7194 conn->consumed_content += nread;
7195 }
7196
7197 if (conn->consumed_content == conn->content_len) {
7198 success = (nread >= 0);
7199 }
7200
7201 /* Each error code path in this function must send an error */
7202 if (!success) {
7203 /* NOTE: Maybe some data has already been sent. */
7204 /* TODO (low): If some data has been sent, a correct error
7205 * reply can no longer be sent, so just close the connection */
7206 send_http_error(conn, 500, "%s", "");
7207 }
7208 }
7209
7210 return success;
7211 }
7212 #endif
7213
7214 #if !defined(NO_CGI)
7215 /* This structure helps to create an environment for the spawned CGI program.
7216 * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
7217 * last element must be NULL.
7218 * However, on Windows there is a requirement that all these VARIABLE=VALUE\0
7219 * strings must reside in a contiguous buffer. The end of the buffer is
7220 * marked by two '\0' characters.
7221 * We satisfy both worlds: we create an envp array (which is vars), all
7222 * entries are actually pointers inside buf. */
7223 struct cgi_environment {
7224 struct mg_connection *conn;
7225 /* Data block */
7226 char *buf; /* Environment buffer */
7227 size_t buflen; /* Space available in buf */
7228 size_t bufused; /* Space taken in buf */
7229 /* Index block */
7230 char **var; /* char **envp */
7231 size_t varlen; /* Number of variables available in var */
7232 size_t varused; /* Number of variables stored in var */
7233 };
7234
7235
7236 static void addenv(struct cgi_environment *env,
7237 PRINTF_FORMAT_STRING(const char *fmt),
7238 ...) PRINTF_ARGS(2, 3);
7239
7240 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
7241 * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
7242 static void
7243 addenv(struct cgi_environment *env, const char *fmt, ...)
7244 {
7245 size_t n, space;
7246 int truncated;
7247 char *added;
7248 va_list ap;
7249
7250 /* Calculate how much space is left in the buffer */
7251 space = (env->buflen - env->bufused);
7252
7253 /* Calculate an estimate for the required space */
7254 n = strlen(fmt) + 2 + 128;
7255
7256 do {
7257 if (space <= n) {
7258 /* Allocate new buffer */
7259 n = env->buflen + CGI_ENVIRONMENT_SIZE;
7260 added = (char *)mg_realloc(env->buf, n);
7261 if (!added) {
7262 /* Out of memory */
7263 mg_cry(env->conn,
7264 "%s: Cannot allocate memory for CGI variable [%s]",
7265 __func__,
7266 fmt);
7267 return;
7268 }
7269 env->buf = added;
7270 env->buflen = n;
7271 space = (env->buflen - env->bufused);
7272 }
7273
7274 /* Make a pointer to the free space int the buffer */
7275 added = env->buf + env->bufused;
7276
7277 /* Copy VARIABLE=VALUE\0 string into the free space */
7278 va_start(ap, fmt);
7279 mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
7280 va_end(ap);
7281
7282 /* Do not add truncated strings to the environment */
7283 if (truncated) {
7284 /* Reallocate the buffer */
7285 space = 0;
7286 n = 1;
7287 }
7288 } while (truncated);
7289
7290 /* Calculate number of bytes added to the environment */
7291 n = strlen(added) + 1;
7292 env->bufused += n;
7293
7294 /* Now update the variable index */
7295 space = (env->varlen - env->varused);
7296 if (space < 2) {
7297 mg_cry(env->conn,
7298 "%s: Cannot register CGI variable [%s]",
7299 __func__,
7300 fmt);
7301 return;
7302 }
7303
7304 /* Append a pointer to the added string into the envp array */
7305 env->var[env->varused] = added;
7306 env->varused++;
7307 }
7308
7309
7310 static void
7311 prepare_cgi_environment(struct mg_connection *conn,
7312 const char *prog,
7313 struct cgi_environment *env)
7314 {
7315 const char *s;
7316 struct vec var_vec;
7317 char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
7318 int i, truncated;
7319
7320 if (conn == NULL || prog == NULL || env == NULL) {
7321 return;
7322 }
7323
7324 env->conn = conn;
7325 env->buflen = CGI_ENVIRONMENT_SIZE;
7326 env->bufused = 0;
7327 env->buf = (char *)mg_malloc(env->buflen);
7328 env->varlen = MAX_CGI_ENVIR_VARS;
7329 env->varused = 0;
7330 env->var = (char **)mg_malloc(env->buflen * sizeof(char *));
7331
7332 addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
7333 addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7334 addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7335 addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
7336
7337 /* Prepare the environment block */
7338 addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
7339 addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
7340 addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
7341
7342 #if defined(USE_IPV6)
7343 if (conn->client.lsa.sa.sa_family == AF_INET6) {
7344 addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
7345 } else
7346 #endif
7347 {
7348 addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
7349 }
7350
7351 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
7352 addenv(env, "REMOTE_ADDR=%s", src_addr);
7353
7354 addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
7355 addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
7356
7357 addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
7358 addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
7359
7360 /* SCRIPT_NAME */
7361 addenv(env,
7362 "SCRIPT_NAME=%.*s",
7363 (int)strlen(conn->request_info.local_uri)
7364 - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)),
7365 conn->request_info.local_uri);
7366
7367 addenv(env, "SCRIPT_FILENAME=%s", prog);
7368 if (conn->path_info == NULL) {
7369 addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
7370 } else {
7371 addenv(env,
7372 "PATH_TRANSLATED=%s%s",
7373 conn->ctx->config[DOCUMENT_ROOT],
7374 conn->path_info);
7375 }
7376
7377 addenv(env, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
7378
7379 if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
7380 addenv(env, "CONTENT_TYPE=%s", s);
7381 }
7382 if (conn->request_info.query_string != NULL) {
7383 addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
7384 }
7385 if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
7386 addenv(env, "CONTENT_LENGTH=%s", s);
7387 }
7388 if ((s = getenv("PATH")) != NULL) {
7389 addenv(env, "PATH=%s", s);
7390 }
7391 if (conn->path_info != NULL) {
7392 addenv(env, "PATH_INFO=%s", conn->path_info);
7393 }
7394
7395 if (conn->status_code > 0) {
7396 /* CGI error handler should show the status code */
7397 addenv(env, "STATUS=%d", conn->status_code);
7398 }
7399
7400 #if defined(_WIN32)
7401 if ((s = getenv("COMSPEC")) != NULL) {
7402 addenv(env, "COMSPEC=%s", s);
7403 }
7404 if ((s = getenv("SYSTEMROOT")) != NULL) {
7405 addenv(env, "SYSTEMROOT=%s", s);
7406 }
7407 if ((s = getenv("SystemDrive")) != NULL) {
7408 addenv(env, "SystemDrive=%s", s);
7409 }
7410 if ((s = getenv("ProgramFiles")) != NULL) {
7411 addenv(env, "ProgramFiles=%s", s);
7412 }
7413 if ((s = getenv("ProgramFiles(x86)")) != NULL) {
7414 addenv(env, "ProgramFiles(x86)=%s", s);
7415 }
7416 #else
7417 if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
7418 addenv(env, "LD_LIBRARY_PATH=%s", s);
7419 }
7420 #endif /* _WIN32 */
7421
7422 if ((s = getenv("PERLLIB")) != NULL) {
7423 addenv(env, "PERLLIB=%s", s);
7424 }
7425
7426 if (conn->request_info.remote_user != NULL) {
7427 addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
7428 addenv(env, "%s", "AUTH_TYPE=Digest");
7429 }
7430
7431 /* Add all headers as HTTP_* variables */
7432 for (i = 0; i < conn->request_info.num_headers; i++) {
7433
7434 (void)mg_snprintf(conn,
7435 &truncated,
7436 http_var_name,
7437 sizeof(http_var_name),
7438 "HTTP_%s",
7439 conn->request_info.http_headers[i].name);
7440
7441 if (truncated) {
7442 mg_cry(conn,
7443 "%s: HTTP header variable too long [%s]",
7444 __func__,
7445 conn->request_info.http_headers[i].name);
7446 continue;
7447 }
7448
7449 /* Convert variable name into uppercase, and change - to _ */
7450 for (p = http_var_name; *p != '\0'; p++) {
7451 if (*p == '-') {
7452 *p = '_';
7453 }
7454 *p = (char)toupper(*(unsigned char *)p);
7455 }
7456
7457 addenv(env,
7458 "%s=%s",
7459 http_var_name,
7460 conn->request_info.http_headers[i].value);
7461 }
7462
7463 /* Add user-specified variables */
7464 s = conn->ctx->config[CGI_ENVIRONMENT];
7465 while ((s = next_option(s, &var_vec, NULL)) != NULL) {
7466 addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
7467 }
7468
7469 env->var[env->varused] = NULL;
7470 env->buf[env->bufused] = '\0';
7471 }
7472
7473
7474 static void
7475 handle_cgi_request(struct mg_connection *conn, const char *prog)
7476 {
7477 char *buf;
7478 size_t buflen;
7479 int headers_len, data_len, i, truncated;
7480 int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
7481 const char *status, *status_text, *connection_state;
7482 char *pbuf, dir[PATH_MAX], *p;
7483 struct mg_request_info ri;
7484 struct cgi_environment blk;
7485 FILE *in = NULL, *out = NULL, *err = NULL;
7486 struct file fout = STRUCT_FILE_INITIALIZER;
7487 pid_t pid = (pid_t)-1;
7488
7489 if (conn == NULL) {
7490 return;
7491 }
7492
7493 buf = NULL;
7494 buflen = 16384;
7495 prepare_cgi_environment(conn, prog, &blk);
7496
7497 /* CGI must be executed in its own directory. 'dir' must point to the
7498 * directory containing executable program, 'p' must point to the
7499 * executable program name relative to 'dir'. */
7500 (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
7501
7502 if (truncated) {
7503 mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
7504 send_http_error(conn, 500, "Error: %s", "CGI path too long");
7505 goto done;
7506 }
7507
7508 if ((p = strrchr(dir, '/')) != NULL) {
7509 *p++ = '\0';
7510 } else {
7511 dir[0] = '.', dir[1] = '\0';
7512 p = (char *)prog;
7513 }
7514
7515 if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) {
7516 status = strerror(ERRNO);
7517 mg_cry(conn,
7518 "Error: CGI program \"%s\": Can not create CGI pipes: %s",
7519 prog,
7520 status);
7521 send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status);
7522 goto done;
7523 }
7524
7525 pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
7526
7527 if (pid == (pid_t)-1) {
7528 status = strerror(ERRNO);
7529 mg_cry(conn,
7530 "Error: CGI program \"%s\": Can not spawn CGI process: %s",
7531 prog,
7532 status);
7533 send_http_error(conn,
7534 500,
7535 "Error: Cannot spawn CGI process [%s]: %s",
7536 prog,
7537 status);
7538 goto done;
7539 }
7540
7541 /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
7542 set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
7543 set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
7544 set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
7545 set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
7546 set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
7547 set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
7548
7549 /* Parent closes only one side of the pipes.
7550 * If we don't mark them as closed, close() attempt before
7551 * return from this function throws an exception on Windows.
7552 * Windows does not like when closed descriptor is closed again. */
7553 (void)close(fdin[0]);
7554 (void)close(fdout[1]);
7555 (void)close(fderr[1]);
7556 fdin[0] = fdout[1] = fderr[1] = -1;
7557
7558 if ((in = fdopen(fdin[1], "wb")) == NULL) {
7559 status = strerror(ERRNO);
7560 mg_cry(conn,
7561 "Error: CGI program \"%s\": Can not open stdin: %s",
7562 prog,
7563 status);
7564 send_http_error(conn,
7565 500,
7566 "Error: CGI can not open fdin\nfopen: %s",
7567 status);
7568 goto done;
7569 }
7570
7571 if ((out = fdopen(fdout[0], "rb")) == NULL) {
7572 status = strerror(ERRNO);
7573 mg_cry(conn,
7574 "Error: CGI program \"%s\": Can not open stdout: %s",
7575 prog,
7576 status);
7577 send_http_error(conn,
7578 500,
7579 "Error: CGI can not open fdout\nfopen: %s",
7580 status);
7581 goto done;
7582 }
7583
7584 if ((err = fdopen(fderr[0], "rb")) == NULL) {
7585 status = strerror(ERRNO);
7586 mg_cry(conn,
7587 "Error: CGI program \"%s\": Can not open stderr: %s",
7588 prog,
7589 status);
7590 send_http_error(conn,
7591 500,
7592 "Error: CGI can not open fdout\nfopen: %s",
7593 status);
7594 goto done;
7595 }
7596
7597 setbuf(in, NULL);
7598 setbuf(out, NULL);
7599 setbuf(err, NULL);
7600 fout.fp = out;
7601
7602 if ((conn->request_info.content_length > 0) || conn->is_chunked) {
7603 /* This is a POST/PUT request, or another request with body data. */
7604 if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
7605 /* Error sending the body data */
7606 mg_cry(conn,
7607 "Error: CGI program \"%s\": Forward body data failed",
7608 prog);
7609 goto done;
7610 }
7611 }
7612
7613 /* Close so child gets an EOF. */
7614 fclose(in);
7615 in = NULL;
7616 fdin[1] = -1;
7617
7618 /* Now read CGI reply into a buffer. We need to set correct
7619 * status code, thus we need to see all HTTP headers first.
7620 * Do not send anything back to client, until we buffer in all
7621 * HTTP headers. */
7622 data_len = 0;
7623 buf = (char *)mg_malloc(buflen);
7624 if (buf == NULL) {
7625 send_http_error(conn,
7626 500,
7627 "Error: Not enough memory for CGI buffer (%u bytes)",
7628 (unsigned int)buflen);
7629 mg_cry(conn,
7630 "Error: CGI program \"%s\": Not enough memory for buffer (%u "
7631 "bytes)",
7632 prog,
7633 (unsigned int)buflen);
7634 goto done;
7635 }
7636 headers_len = read_request(out, conn, buf, (int)buflen, &data_len);
7637 if (headers_len <= 0) {
7638
7639 /* Could not parse the CGI response. Check if some error message on
7640 * stderr. */
7641 i = pull_all(err, conn, buf, (int)buflen);
7642 if (i > 0) {
7643 mg_cry(conn,
7644 "Error: CGI program \"%s\" sent error "
7645 "message: [%.*s]",
7646 prog,
7647 i,
7648 buf);
7649 send_http_error(conn,
7650 500,
7651 "Error: CGI program \"%s\" sent error "
7652 "message: [%.*s]",
7653 prog,
7654 i,
7655 buf);
7656 } else {
7657 mg_cry(conn,
7658 "Error: CGI program sent malformed or too big "
7659 "(>%u bytes) HTTP headers: [%.*s]",
7660 (unsigned)buflen,
7661 data_len,
7662 buf);
7663
7664 send_http_error(conn,
7665 500,
7666 "Error: CGI program sent malformed or too big "
7667 "(>%u bytes) HTTP headers: [%.*s]",
7668 (unsigned)buflen,
7669 data_len,
7670 buf);
7671 }
7672
7673 goto done;
7674 }
7675 pbuf = buf;
7676 buf[headers_len - 1] = '\0';
7677 parse_http_headers(&pbuf, &ri);
7678
7679 /* Make up and send the status line */
7680 status_text = "OK";
7681 if ((status = get_header(&ri, "Status")) != NULL) {
7682 conn->status_code = atoi(status);
7683 status_text = status;
7684 while (isdigit(*(const unsigned char *)status_text)
7685 || *status_text == ' ') {
7686 status_text++;
7687 }
7688 } else if (get_header(&ri, "Location") != NULL) {
7689 conn->status_code = 302;
7690 } else {
7691 conn->status_code = 200;
7692 }
7693 connection_state = get_header(&ri, "Connection");
7694 if (!header_has_option(connection_state, "keep-alive")) {
7695 conn->must_close = 1;
7696 }
7697 (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
7698
7699 /* Send headers */
7700 for (i = 0; i < ri.num_headers; i++) {
7701 mg_printf(conn,
7702 "%s: %s\r\n",
7703 ri.http_headers[i].name,
7704 ri.http_headers[i].value);
7705 }
7706 mg_write(conn, "\r\n", 2);
7707
7708 /* Send chunk of data that may have been read after the headers */
7709 conn->num_bytes_sent +=
7710 mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
7711
7712 /* Read the rest of CGI output and send to the client */
7713 send_file_data(conn, &fout, 0, INT64_MAX);
7714
7715 done:
7716 mg_free(blk.var);
7717 mg_free(blk.buf);
7718
7719 if (pid != (pid_t)-1) {
7720 kill(pid, SIGKILL);
7721 #if !defined(_WIN32)
7722 {
7723 int st;
7724 while (waitpid(pid, &st, 0) != -1)
7725 ; /* clean zombies */
7726 }
7727 #endif
7728 }
7729 if (fdin[0] != -1) {
7730 close(fdin[0]);
7731 }
7732 if (fdout[1] != -1) {
7733 close(fdout[1]);
7734 }
7735
7736 if (in != NULL) {
7737 fclose(in);
7738 } else if (fdin[1] != -1) {
7739 close(fdin[1]);
7740 }
7741
7742 if (out != NULL) {
7743 fclose(out);
7744 } else if (fdout[0] != -1) {
7745 close(fdout[0]);
7746 }
7747
7748 if (err != NULL) {
7749 fclose(err);
7750 } else if (fderr[0] != -1) {
7751 close(fderr[0]);
7752 }
7753
7754 if (buf != NULL) {
7755 mg_free(buf);
7756 }
7757 }
7758 #endif /* !NO_CGI */
7759
7760
7761 #if !defined(NO_FILES)
7762 static void
7763 mkcol(struct mg_connection *conn, const char *path)
7764 {
7765 int rc, body_len;
7766 struct de de;
7767 char date[64];
7768 time_t curtime = time(NULL);
7769
7770 if (conn == NULL) {
7771 return;
7772 }
7773
7774 /* TODO (mid): Check the send_http_error situations in this function */
7775
7776 memset(&de.file, 0, sizeof(de.file));
7777 if (!mg_stat(conn, path, &de.file)) {
7778 mg_cry(conn,
7779 "%s: mg_stat(%s) failed: %s",
7780 __func__,
7781 path,
7782 strerror(ERRNO));
7783 }
7784
7785 if (de.file.last_modified) {
7786 /* TODO (high): This check does not seem to make any sense ! */
7787 send_http_error(
7788 conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7789 return;
7790 }
7791
7792 body_len = conn->data_len - conn->request_len;
7793 if (body_len > 0) {
7794 send_http_error(
7795 conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7796 return;
7797 }
7798
7799 rc = mg_mkdir(conn, path, 0755);
7800
7801 if (rc == 0) {
7802 conn->status_code = 201;
7803 gmt_time_string(date, sizeof(date), &curtime);
7804 mg_printf(conn,
7805 "HTTP/1.1 %d Created\r\n"
7806 "Date: %s\r\n",
7807 conn->status_code,
7808 date);
7809 send_static_cache_header(conn);
7810 mg_printf(conn,
7811 "Content-Length: 0\r\n"
7812 "Connection: %s\r\n\r\n",
7813 suggest_connection_header(conn));
7814 } else if (rc == -1) {
7815 if (errno == EEXIST) {
7816 send_http_error(
7817 conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7818 } else if (errno == EACCES) {
7819 send_http_error(
7820 conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7821 } else if (errno == ENOENT) {
7822 send_http_error(
7823 conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7824 } else {
7825 send_http_error(conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
7826 }
7827 }
7828 }
7829
7830
7831 static void
7832 put_file(struct mg_connection *conn, const char *path)
7833 {
7834 struct file file = STRUCT_FILE_INITIALIZER;
7835 const char *range;
7836 int64_t r1, r2;
7837 int rc;
7838 char date[64];
7839 time_t curtime = time(NULL);
7840
7841 if (conn == NULL) {
7842 return;
7843 }
7844
7845 if (mg_stat(conn, path, &file)) {
7846 /* File already exists */
7847 conn->status_code = 200;
7848
7849 if (file.is_directory) {
7850 /* This is an already existing directory,
7851 * so there is nothing to do for the server. */
7852 rc = 0;
7853
7854 } else {
7855 /* File exists and is not a directory. */
7856 /* Can it be replaced? */
7857
7858 if (file.membuf != NULL) {
7859 /* This is an "in-memory" file, that can not be replaced */
7860 send_http_error(
7861 conn,
7862 405,
7863 "Error: Put not possible\nReplacing %s is not supported",
7864 path);
7865 return;
7866 }
7867
7868 /* Check if the server may write this file */
7869 if (access(path, W_OK) == 0) {
7870 /* Access granted */
7871 conn->status_code = 200;
7872 rc = 1;
7873 } else {
7874 send_http_error(
7875 conn,
7876 403,
7877 "Error: Put not possible\nReplacing %s is not allowed",
7878 path);
7879 return;
7880 }
7881 }
7882 } else {
7883 /* File should be created */
7884 conn->status_code = 201;
7885 rc = put_dir(conn, path);
7886 }
7887
7888 if (rc == 0) {
7889 /* put_dir returns 0 if path is a directory */
7890 gmt_time_string(date, sizeof(date), &curtime);
7891 mg_printf(conn,
7892 "HTTP/1.1 %d %s\r\n",
7893 conn->status_code,
7894 mg_get_response_code_text(NULL, conn->status_code));
7895 send_no_cache_header(conn);
7896 mg_printf(conn,
7897 "Date: %s\r\n"
7898 "Content-Length: 0\r\n"
7899 "Connection: %s\r\n\r\n",
7900 date,
7901 suggest_connection_header(conn));
7902
7903 /* Request to create a directory has been fulfilled successfully.
7904 * No need to put a file. */
7905 return;
7906 }
7907
7908 if (rc == -1) {
7909 /* put_dir returns -1 if the path is too long */
7910 send_http_error(conn,
7911 414,
7912 "Error: Path too long\nput_dir(%s): %s",
7913 path,
7914 strerror(ERRNO));
7915 return;
7916 }
7917
7918 if (rc == -2) {
7919 /* put_dir returns -2 if the directory can not be created */
7920 send_http_error(conn,
7921 500,
7922 "Error: Can not create directory\nput_dir(%s): %s",
7923 path,
7924 strerror(ERRNO));
7925 return;
7926 }
7927
7928 /* A file should be created or overwritten. */
7929 if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
7930 mg_fclose(&file);
7931 send_http_error(conn,
7932 500,
7933 "Error: Can not create file\nfopen(%s): %s",
7934 path,
7935 strerror(ERRNO));
7936 return;
7937 }
7938
7939 fclose_on_exec(&file, conn);
7940 range = mg_get_header(conn, "Content-Range");
7941 r1 = r2 = 0;
7942 if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
7943 conn->status_code = 206; /* Partial content */
7944 fseeko(file.fp, r1, SEEK_SET);
7945 }
7946
7947 if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
7948 /* forward_body_data failed.
7949 * The error code has already been sent to the client,
7950 * and conn->status_code is already set. */
7951 mg_fclose(&file);
7952 return;
7953 }
7954
7955 gmt_time_string(date, sizeof(date), &curtime);
7956 mg_printf(conn,
7957 "HTTP/1.1 %d %s\r\n",
7958 conn->status_code,
7959 mg_get_response_code_text(NULL, conn->status_code));
7960 send_no_cache_header(conn);
7961 mg_printf(conn,
7962 "Date: %s\r\n"
7963 "Content-Length: 0\r\n"
7964 "Connection: %s\r\n\r\n",
7965 date,
7966 suggest_connection_header(conn));
7967
7968 mg_fclose(&file);
7969 }
7970
7971
7972 static void
7973 delete_file(struct mg_connection *conn, const char *path)
7974 {
7975 struct de de;
7976 memset(&de.file, 0, sizeof(de.file));
7977 if (!mg_stat(conn, path, &de.file)) {
7978 /* mg_stat returns 0 if the file does not exist */
7979 send_http_error(conn,
7980 404,
7981 "Error: Cannot delete file\nFile %s not found",
7982 path);
7983 return;
7984 }
7985
7986 if (de.file.membuf != NULL) {
7987 /* the file is cached in memory */
7988 send_http_error(
7989 conn,
7990 405,
7991 "Error: Delete not possible\nDeleting %s is not supported",
7992 path);
7993 return;
7994 }
7995
7996 if (de.file.is_directory) {
7997 if (remove_directory(conn, path)) {
7998 /* Delete is successful: Return 204 without content. */
7999 send_http_error(conn, 204, "%s", "");
8000 } else {
8001 /* Delete is not successful: Return 500 (Server error). */
8002 send_http_error(conn, 500, "Error: Could not delete %s", path);
8003 }
8004 return;
8005 }
8006
8007 /* This is an existing file (not a directory).
8008 * Check if write permission is granted. */
8009 if (access(path, W_OK) != 0) {
8010 /* File is read only */
8011 send_http_error(
8012 conn,
8013 403,
8014 "Error: Delete not possible\nDeleting %s is not allowed",
8015 path);
8016 return;
8017 }
8018
8019 /* Try to delete it. */
8020 if (mg_remove(conn, path) == 0) {
8021 /* Delete was successful: Return 204 without content. */
8022 send_http_error(conn, 204, "%s", "");
8023 } else {
8024 /* Delete not successful (file locked). */
8025 send_http_error(conn,
8026 423,
8027 "Error: Cannot delete file\nremove(%s): %s",
8028 path,
8029 strerror(ERRNO));
8030 }
8031 }
8032 #endif /* !NO_FILES */
8033
8034
8035 static void
8036 send_ssi_file(struct mg_connection *, const char *, struct file *, int);
8037
8038
8039 static void
8040 do_ssi_include(struct mg_connection *conn,
8041 const char *ssi,
8042 char *tag,
8043 int include_level)
8044 {
8045 char file_name[MG_BUF_LEN], path[512], *p;
8046 struct file file = STRUCT_FILE_INITIALIZER;
8047 size_t len;
8048 int truncated = 0;
8049
8050 if (conn == NULL) {
8051 return;
8052 }
8053
8054 /* sscanf() is safe here, since send_ssi_file() also uses buffer
8055 * of size MG_BUF_LEN to get the tag. So strlen(tag) is
8056 * always < MG_BUF_LEN. */
8057 if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
8058 /* File name is relative to the webserver root */
8059 file_name[511] = 0;
8060 (void)mg_snprintf(conn,
8061 &truncated,
8062 path,
8063 sizeof(path),
8064 "%s/%s",
8065 conn->ctx->config[DOCUMENT_ROOT],
8066 file_name);
8067
8068 } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
8069 /* File name is relative to the webserver working directory
8070 * or it is absolute system path */
8071 file_name[511] = 0;
8072 (void)
8073 mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
8074
8075 } else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1
8076 || sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
8077 /* File name is relative to the currect document */
8078 file_name[511] = 0;
8079 (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
8080
8081 if (!truncated) {
8082 if ((p = strrchr(path, '/')) != NULL) {
8083 p[1] = '\0';
8084 }
8085 len = strlen(path);
8086 (void)mg_snprintf(conn,
8087 &truncated,
8088 path + len,
8089 sizeof(path) - len,
8090 "%s",
8091 file_name);
8092 }
8093
8094 } else {
8095 mg_cry(conn, "Bad SSI #include: [%s]", tag);
8096 return;
8097 }
8098
8099 if (truncated) {
8100 mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
8101 return;
8102 }
8103
8104 if (!mg_fopen(conn, path, "rb", &file)) {
8105 mg_cry(conn,
8106 "Cannot open SSI #include: [%s]: fopen(%s): %s",
8107 tag,
8108 path,
8109 strerror(ERRNO));
8110 } else {
8111 fclose_on_exec(&file, conn);
8112 if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
8113 strlen(conn->ctx->config[SSI_EXTENSIONS]),
8114 path) > 0) {
8115 send_ssi_file(conn, path, &file, include_level + 1);
8116 } else {
8117 send_file_data(conn, &file, 0, INT64_MAX);
8118 }
8119 mg_fclose(&file);
8120 }
8121 }
8122
8123
8124 #if !defined(NO_POPEN)
8125 static void
8126 do_ssi_exec(struct mg_connection *conn, char *tag)
8127 {
8128 char cmd[1024] = "";
8129 struct file file = STRUCT_FILE_INITIALIZER;
8130
8131 if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
8132 mg_cry(conn, "Bad SSI #exec: [%s]", tag);
8133 } else {
8134 cmd[1023] = 0;
8135 if ((file.fp = popen(cmd, "r")) == NULL) {
8136 mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
8137 } else {
8138 send_file_data(conn, &file, 0, INT64_MAX);
8139 pclose(file.fp);
8140 }
8141 }
8142 }
8143 #endif /* !NO_POPEN */
8144
8145
8146 static int
8147 mg_fgetc(struct file *filep, int offset)
8148 {
8149 if (filep == NULL) {
8150 return EOF;
8151 }
8152 if (filep->membuf != NULL && offset >= 0
8153 && ((unsigned int)(offset)) < filep->size) {
8154 return ((const unsigned char *)filep->membuf)[offset];
8155 } else if (filep->fp != NULL) {
8156 return fgetc(filep->fp);
8157 } else {
8158 return EOF;
8159 }
8160 }
8161
8162
8163 static void
8164 send_ssi_file(struct mg_connection *conn,
8165 const char *path,
8166 struct file *filep,
8167 int include_level)
8168 {
8169 char buf[MG_BUF_LEN];
8170 int ch, offset, len, in_ssi_tag;
8171
8172 if (include_level > 10) {
8173 mg_cry(conn, "SSI #include level is too deep (%s)", path);
8174 return;
8175 }
8176
8177 in_ssi_tag = len = offset = 0;
8178 while ((ch = mg_fgetc(filep, offset)) != EOF) {
8179 if (in_ssi_tag && ch == '>') {
8180 in_ssi_tag = 0;
8181 buf[len++] = (char)ch;
8182 buf[len] = '\0';
8183 /* assert(len <= (int) sizeof(buf)); */
8184 if (len > (int)sizeof(buf)) {
8185 break;
8186 }
8187 if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
8188 /* Not an SSI tag, pass it */
8189 (void)mg_write(conn, buf, (size_t)len);
8190 } else {
8191 if (!memcmp(buf + 5, "include", 7)) {
8192 do_ssi_include(conn, path, buf + 12, include_level);
8193 #if !defined(NO_POPEN)
8194 } else if (!memcmp(buf + 5, "exec", 4)) {
8195 do_ssi_exec(conn, buf + 9);
8196 #endif /* !NO_POPEN */
8197 } else {
8198 mg_cry(conn,
8199 "%s: unknown SSI "
8200 "command: \"%s\"",
8201 path,
8202 buf);
8203 }
8204 }
8205 len = 0;
8206 } else if (in_ssi_tag) {
8207 if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
8208 /* Not an SSI tag */
8209 in_ssi_tag = 0;
8210 } else if (len == (int)sizeof(buf) - 2) {
8211 mg_cry(conn, "%s: SSI tag is too large", path);
8212 len = 0;
8213 }
8214 buf[len++] = (char)(ch & 0xff);
8215 } else if (ch == '<') {
8216 in_ssi_tag = 1;
8217 if (len > 0) {
8218 mg_write(conn, buf, (size_t)len);
8219 }
8220 len = 0;
8221 buf[len++] = (char)(ch & 0xff);
8222 } else {
8223 buf[len++] = (char)(ch & 0xff);
8224 if (len == (int)sizeof(buf)) {
8225 mg_write(conn, buf, (size_t)len);
8226 len = 0;
8227 }
8228 }
8229 }
8230
8231 /* Send the rest of buffered data */
8232 if (len > 0) {
8233 mg_write(conn, buf, (size_t)len);
8234 }
8235 }
8236
8237
8238 static void
8239 handle_ssi_file_request(struct mg_connection *conn,
8240 const char *path,
8241 struct file *filep)
8242 {
8243 char date[64];
8244 time_t curtime = time(NULL);
8245 const char *cors1, *cors2, *cors3;
8246
8247 if (conn == NULL || path == NULL || filep == NULL) {
8248 return;
8249 }
8250
8251 if (mg_get_header(conn, "Origin")) {
8252 /* Cross-origin resource sharing (CORS). */
8253 cors1 = "Access-Control-Allow-Origin: ";
8254 cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
8255 cors3 = "\r\n";
8256 } else {
8257 cors1 = cors2 = cors3 = "";
8258 }
8259
8260 if (!mg_fopen(conn, path, "rb", filep)) {
8261 /* File exists (precondition for calling this function),
8262 * but can not be opened by the server. */
8263 send_http_error(conn,
8264 500,
8265 "Error: Cannot read file\nfopen(%s): %s",
8266 path,
8267 strerror(ERRNO));
8268 } else {
8269 conn->must_close = 1;
8270 gmt_time_string(date, sizeof(date), &curtime);
8271 fclose_on_exec(filep, conn);
8272 mg_printf(conn, "HTTP/1.1 200 OK\r\n");
8273 send_no_cache_header(conn);
8274 mg_printf(conn,
8275 "%s%s%s"
8276 "Date: %s\r\n"
8277 "Content-Type: text/html\r\n"
8278 "Connection: %s\r\n\r\n",
8279 cors1,
8280 cors2,
8281 cors3,
8282 date,
8283 suggest_connection_header(conn));
8284 send_ssi_file(conn, path, filep, 0);
8285 mg_fclose(filep);
8286 }
8287 }
8288
8289
8290 #if !defined(NO_FILES)
8291 static void
8292 send_options(struct mg_connection *conn)
8293 {
8294 char date[64];
8295 time_t curtime = time(NULL);
8296
8297 if (!conn) {
8298 return;
8299 }
8300
8301 conn->status_code = 200;
8302 conn->must_close = 1;
8303 gmt_time_string(date, sizeof(date), &curtime);
8304
8305 mg_printf(conn,
8306 "HTTP/1.1 200 OK\r\n"
8307 "Date: %s\r\n"
8308 /* TODO: "Cache-Control" (?) */
8309 "Connection: %s\r\n"
8310 "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
8311 "PROPFIND, MKCOL\r\n"
8312 "DAV: 1\r\n\r\n",
8313 date,
8314 suggest_connection_header(conn));
8315 }
8316
8317
8318 /* Writes PROPFIND properties for a collection element */
8319 static void
8320 print_props(struct mg_connection *conn, const char *uri, struct file *filep)
8321 {
8322 char mtime[64];
8323
8324 if (conn == NULL || uri == NULL || filep == NULL) {
8325 return;
8326 }
8327
8328 gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
8329 conn->num_bytes_sent +=
8330 mg_printf(conn,
8331 "<d:response>"
8332 "<d:href>%s</d:href>"
8333 "<d:propstat>"
8334 "<d:prop>"
8335 "<d:resourcetype>%s</d:resourcetype>"
8336 "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
8337 "<d:getlastmodified>%s</d:getlastmodified>"
8338 "</d:prop>"
8339 "<d:status>HTTP/1.1 200 OK</d:status>"
8340 "</d:propstat>"
8341 "</d:response>\n",
8342 uri,
8343 filep->is_directory ? "<d:collection/>" : "",
8344 filep->size,
8345 mtime);
8346 }
8347
8348
8349 static void
8350 print_dav_dir_entry(struct de *de, void *data)
8351 {
8352 char href[PATH_MAX];
8353 char href_encoded[PATH_MAX];
8354 int truncated;
8355
8356 struct mg_connection *conn = (struct mg_connection *)data;
8357 if (!de || !conn) {
8358 return;
8359 }
8360 mg_snprintf(conn,
8361 &truncated,
8362 href,
8363 sizeof(href),
8364 "%s%s",
8365 conn->request_info.local_uri,
8366 de->file_name);
8367
8368 if (!truncated) {
8369 mg_url_encode(href, href_encoded, PATH_MAX - 1);
8370 print_props(conn, href_encoded, &de->file);
8371 }
8372 }
8373
8374
8375 static void
8376 handle_propfind(struct mg_connection *conn,
8377 const char *path,
8378 struct file *filep)
8379 {
8380 const char *depth = mg_get_header(conn, "Depth");
8381 char date[64];
8382 time_t curtime = time(NULL);
8383
8384 gmt_time_string(date, sizeof(date), &curtime);
8385
8386 if (!conn || !path || !filep || !conn->ctx) {
8387 return;
8388 }
8389
8390 conn->must_close = 1;
8391 conn->status_code = 207;
8392 mg_printf(conn,
8393 "HTTP/1.1 207 Multi-Status\r\n"
8394 "Date: %s\r\n",
8395 date);
8396 send_static_cache_header(conn);
8397 mg_printf(conn,
8398 "Connection: %s\r\n"
8399 "Content-Type: text/xml; charset=utf-8\r\n\r\n",
8400 suggest_connection_header(conn));
8401
8402 conn->num_bytes_sent +=
8403 mg_printf(conn,
8404 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
8405 "<d:multistatus xmlns:d='DAV:'>\n");
8406
8407 /* Print properties for the requested resource itself */
8408 print_props(conn, conn->request_info.local_uri, filep);
8409
8410 /* If it is a directory, print directory entries too if Depth is not 0 */
8411 if (filep && filep->is_directory
8412 && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
8413 && (depth == NULL || strcmp(depth, "0") != 0)) {
8414 scan_directory(conn, path, conn, &print_dav_dir_entry);
8415 }
8416
8417 conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
8418 }
8419 #endif
8420
8421 void
8422 mg_lock_connection(struct mg_connection *conn)
8423 {
8424 if (conn) {
8425 (void)pthread_mutex_lock(&conn->mutex);
8426 }
8427 }
8428
8429 void
8430 mg_unlock_connection(struct mg_connection *conn)
8431 {
8432 if (conn) {
8433 (void)pthread_mutex_unlock(&conn->mutex);
8434 }
8435 }
8436
8437 void
8438 mg_lock_context(struct mg_context *ctx)
8439 {
8440 if (ctx) {
8441 (void)pthread_mutex_lock(&ctx->nonce_mutex);
8442 }
8443 }
8444
8445 void
8446 mg_unlock_context(struct mg_context *ctx)
8447 {
8448 if (ctx) {
8449 (void)pthread_mutex_unlock(&ctx->nonce_mutex);
8450 }
8451 }
8452
8453 #if defined(USE_TIMERS)
8454 #include "timer.inl"
8455 #endif /* USE_TIMERS */
8456
8457 #ifdef USE_LUA
8458 #include "mod_lua.inl"
8459 #endif /* USE_LUA */
8460
8461 #ifdef USE_DUKTAPE
8462 #include "mod_duktape.inl"
8463 #endif /* USE_DUKTAPE */
8464
8465 #if defined(USE_WEBSOCKET)
8466
8467 /* START OF SHA-1 code
8468 * Copyright(c) By Steve Reid <steve@edmweb.com> */
8469 #define SHA1HANDSOFF
8470
8471 /* According to current tests (May 2015), the <solarisfixes.h> is not required.
8472 *
8473 * #if defined(__sun)
8474 * #include "solarisfixes.h"
8475 * #endif
8476 */
8477
8478
8479 static int
8480 is_big_endian(void)
8481 {
8482 static const int n = 1;
8483 return ((char *)&n)[0] == 0;
8484 }
8485
8486
8487 union char64long16 {
8488 unsigned char c[64];
8489 uint32_t l[16];
8490 };
8491
8492 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
8493
8494
8495 static uint32_t
8496 blk0(union char64long16 *block, int i)
8497 {
8498 /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
8499 if (!is_big_endian()) {
8500 block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
8501 | (rol(block->l[i], 8) & 0x00FF00FF);
8502 }
8503 return block->l[i];
8504 }
8505
8506 #define blk(i) \
8507 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
8508 ^ block->l[(i + 2) & 15] ^ block->l[i & 15], \
8509 1))
8510 #define R0(v, w, x, y, z, i) \
8511 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
8512 w = rol(w, 30);
8513 #define R1(v, w, x, y, z, i) \
8514 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
8515 w = rol(w, 30);
8516 #define R2(v, w, x, y, z, i) \
8517 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
8518 w = rol(w, 30);
8519 #define R3(v, w, x, y, z, i) \
8520 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
8521 w = rol(w, 30);
8522 #define R4(v, w, x, y, z, i) \
8523 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
8524 w = rol(w, 30);
8525
8526
8527 typedef struct {
8528 uint32_t state[5];
8529 uint32_t count[2];
8530 unsigned char buffer[64];
8531 } SHA1_CTX;
8532
8533
8534 static void
8535 SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
8536 {
8537 uint32_t a, b, c, d, e;
8538 union char64long16 block[1];
8539
8540 memcpy(block, buffer, 64);
8541 a = state[0];
8542 b = state[1];
8543 c = state[2];
8544 d = state[3];
8545 e = state[4];
8546 R0(a, b, c, d, e, 0);
8547 R0(e, a, b, c, d, 1);
8548 R0(d, e, a, b, c, 2);
8549 R0(c, d, e, a, b, 3);
8550 R0(b, c, d, e, a, 4);
8551 R0(a, b, c, d, e, 5);
8552 R0(e, a, b, c, d, 6);
8553 R0(d, e, a, b, c, 7);
8554 R0(c, d, e, a, b, 8);
8555 R0(b, c, d, e, a, 9);
8556 R0(a, b, c, d, e, 10);
8557 R0(e, a, b, c, d, 11);
8558 R0(d, e, a, b, c, 12);
8559 R0(c, d, e, a, b, 13);
8560 R0(b, c, d, e, a, 14);
8561 R0(a, b, c, d, e, 15);
8562 R1(e, a, b, c, d, 16);
8563 R1(d, e, a, b, c, 17);
8564 R1(c, d, e, a, b, 18);
8565 R1(b, c, d, e, a, 19);
8566 R2(a, b, c, d, e, 20);
8567 R2(e, a, b, c, d, 21);
8568 R2(d, e, a, b, c, 22);
8569 R2(c, d, e, a, b, 23);
8570 R2(b, c, d, e, a, 24);
8571 R2(a, b, c, d, e, 25);
8572 R2(e, a, b, c, d, 26);
8573 R2(d, e, a, b, c, 27);
8574 R2(c, d, e, a, b, 28);
8575 R2(b, c, d, e, a, 29);
8576 R2(a, b, c, d, e, 30);
8577 R2(e, a, b, c, d, 31);
8578 R2(d, e, a, b, c, 32);
8579 R2(c, d, e, a, b, 33);
8580 R2(b, c, d, e, a, 34);
8581 R2(a, b, c, d, e, 35);
8582 R2(e, a, b, c, d, 36);
8583 R2(d, e, a, b, c, 37);
8584 R2(c, d, e, a, b, 38);
8585 R2(b, c, d, e, a, 39);
8586 R3(a, b, c, d, e, 40);
8587 R3(e, a, b, c, d, 41);
8588 R3(d, e, a, b, c, 42);
8589 R3(c, d, e, a, b, 43);
8590 R3(b, c, d, e, a, 44);
8591 R3(a, b, c, d, e, 45);
8592 R3(e, a, b, c, d, 46);
8593 R3(d, e, a, b, c, 47);
8594 R3(c, d, e, a, b, 48);
8595 R3(b, c, d, e, a, 49);
8596 R3(a, b, c, d, e, 50);
8597 R3(e, a, b, c, d, 51);
8598 R3(d, e, a, b, c, 52);
8599 R3(c, d, e, a, b, 53);
8600 R3(b, c, d, e, a, 54);
8601 R3(a, b, c, d, e, 55);
8602 R3(e, a, b, c, d, 56);
8603 R3(d, e, a, b, c, 57);
8604 R3(c, d, e, a, b, 58);
8605 R3(b, c, d, e, a, 59);
8606 R4(a, b, c, d, e, 60);
8607 R4(e, a, b, c, d, 61);
8608 R4(d, e, a, b, c, 62);
8609 R4(c, d, e, a, b, 63);
8610 R4(b, c, d, e, a, 64);
8611 R4(a, b, c, d, e, 65);
8612 R4(e, a, b, c, d, 66);
8613 R4(d, e, a, b, c, 67);
8614 R4(c, d, e, a, b, 68);
8615 R4(b, c, d, e, a, 69);
8616 R4(a, b, c, d, e, 70);
8617 R4(e, a, b, c, d, 71);
8618 R4(d, e, a, b, c, 72);
8619 R4(c, d, e, a, b, 73);
8620 R4(b, c, d, e, a, 74);
8621 R4(a, b, c, d, e, 75);
8622 R4(e, a, b, c, d, 76);
8623 R4(d, e, a, b, c, 77);
8624 R4(c, d, e, a, b, 78);
8625 R4(b, c, d, e, a, 79);
8626 state[0] += a;
8627 state[1] += b;
8628 state[2] += c;
8629 state[3] += d;
8630 state[4] += e;
8631 a = b = c = d = e = 0;
8632 memset(block, '\0', sizeof(block));
8633 }
8634
8635
8636 static void
8637 SHA1Init(SHA1_CTX *context)
8638 {
8639 context->state[0] = 0x67452301;
8640 context->state[1] = 0xEFCDAB89;
8641 context->state[2] = 0x98BADCFE;
8642 context->state[3] = 0x10325476;
8643 context->state[4] = 0xC3D2E1F0;
8644 context->count[0] = context->count[1] = 0;
8645 }
8646
8647
8648 static void
8649 SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
8650 {
8651 uint32_t i, j;
8652
8653 j = context->count[0];
8654 if ((context->count[0] += len << 3) < j) {
8655 context->count[1]++;
8656 }
8657 context->count[1] += (len >> 29);
8658 j = (j >> 3) & 63;
8659 if ((j + len) > 63) {
8660 memcpy(&context->buffer[j], data, (i = 64 - j));
8661 SHA1Transform(context->state, context->buffer);
8662 for (; i + 63 < len; i += 64) {
8663 SHA1Transform(context->state, &data[i]);
8664 }
8665 j = 0;
8666 } else
8667 i = 0;
8668 memcpy(&context->buffer[j], &data[i], len - i);
8669 }
8670
8671
8672 static void
8673 SHA1Final(unsigned char digest[20], SHA1_CTX *context)
8674 {
8675 unsigned i;
8676 unsigned char finalcount[8], c;
8677
8678 for (i = 0; i < 8; i++) {
8679 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
8680 >> ((3 - (i & 3)) * 8)) & 255);
8681 }
8682 c = 0200;
8683 SHA1Update(context, &c, 1);
8684 while ((context->count[0] & 504) != 448) {
8685 c = 0000;
8686 SHA1Update(context, &c, 1);
8687 }
8688 SHA1Update(context, finalcount, 8);
8689 for (i = 0; i < 20; i++) {
8690 digest[i] = (unsigned char)((context->state[i >> 2]
8691 >> ((3 - (i & 3)) * 8)) & 255);
8692 }
8693 memset(context, '\0', sizeof(*context));
8694 memset(&finalcount, '\0', sizeof(finalcount));
8695 }
8696 /* END OF SHA1 CODE */
8697
8698
8699 static int
8700 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
8701 {
8702 static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
8703 const char *protocol = NULL;
8704 char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
8705 SHA1_CTX sha_ctx;
8706 int truncated;
8707
8708 /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
8709 mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
8710 if (truncated) {
8711 conn->must_close = 1;
8712 return 0;
8713 }
8714
8715 SHA1Init(&sha_ctx);
8716 SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
8717 SHA1Final((unsigned char *)sha, &sha_ctx);
8718 base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
8719 mg_printf(conn,
8720 "HTTP/1.1 101 Switching Protocols\r\n"
8721 "Upgrade: websocket\r\n"
8722 "Connection: Upgrade\r\n"
8723 "Sec-WebSocket-Accept: %s\r\n",
8724 b64_sha);
8725 protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
8726 if (protocol) {
8727 /* The protocol is a comma seperated list of names. */
8728 /* The server must only return one value from this list. */
8729 /* First check if it is a list or just a single value. */
8730 const char *sep = strchr(protocol, ',');
8731 if (sep == NULL) {
8732 /* Just a single protocol -> accept it. */
8733 mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", protocol);
8734 } else {
8735 /* Multiple protocols -> accept the first one. */
8736 /* This is just a quick fix if the client offers multiple
8737 * protocols. In order to get the behavior intended by
8738 * RFC 6455 (https://tools.ietf.org/rfc/rfc6455.txt), it is
8739 * required to have a list of websocket subprotocols accepted
8740 * by the server. Then the server must either select a subprotocol
8741 * supported by client and server, or the server has to abort the
8742 * handshake by not returning a Sec-Websocket-Protocol header if
8743 * no subprotocol is acceptable.
8744 */
8745 mg_printf(conn,
8746 "Sec-WebSocket-Protocol: %.*s\r\n\r\n",
8747 (int)(sep - protocol),
8748 protocol);
8749 }
8750 /* TODO: Real subprotocol negotiation instead of just taking the first
8751 * websocket subprotocol suggested by the client. */
8752 } else {
8753 mg_printf(conn, "%s", "\r\n");
8754 }
8755
8756 return 1;
8757 }
8758
8759
8760 static void
8761 read_websocket(struct mg_connection *conn,
8762 mg_websocket_data_handler ws_data_handler,
8763 void *callback_data)
8764 {
8765 /* Pointer to the beginning of the portion of the incoming websocket
8766 * message queue.
8767 * The original websocket upgrade request is never removed, so the queue
8768 * begins after it. */
8769 unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
8770 int n, error, exit_by_callback;
8771
8772 /* body_len is the length of the entire queue in bytes
8773 * len is the length of the current message
8774 * data_len is the length of the current message's data payload
8775 * header_len is the length of the current message's header */
8776 size_t i, len, mask_len = 0, data_len = 0, header_len, body_len;
8777
8778 /* "The masking key is a 32-bit value chosen at random by the client."
8779 * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
8780 */
8781 unsigned char mask[4];
8782
8783 /* data points to the place where the message is stored when passed to
8784 * the
8785 * websocket_data callback. This is either mem on the stack, or a
8786 * dynamically allocated buffer if it is too large. */
8787 char mem[4096];
8788 char *data = mem;
8789 unsigned char mop; /* mask flag and opcode */
8790 double timeout = -1.0;
8791
8792 if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
8793 timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
8794 }
8795 if ((timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
8796 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
8797 }
8798
8799 mg_set_thread_name("wsock");
8800
8801 /* Loop continuously, reading messages from the socket, invoking the
8802 * callback, and waiting repeatedly until an error occurs. */
8803 while (!conn->ctx->stop_flag) {
8804 header_len = 0;
8805 assert(conn->data_len >= conn->request_len);
8806 if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
8807 len = buf[1] & 127;
8808 mask_len = buf[1] & 128 ? 4 : 0;
8809 if (len < 126 && body_len >= mask_len) {
8810 data_len = len;
8811 header_len = 2 + mask_len;
8812 } else if (len == 126 && body_len >= 4 + mask_len) {
8813 header_len = 4 + mask_len;
8814 data_len = ((((size_t)buf[2]) << 8) + buf[3]);
8815 } else if (body_len >= 10 + mask_len) {
8816 header_len = 10 + mask_len;
8817 data_len = (((uint64_t)ntohl(*(uint32_t *)(void *)&buf[2]))
8818 << 32) + ntohl(*(uint32_t *)(void *)&buf[6]);
8819 }
8820 }
8821
8822 if (header_len > 0 && body_len >= header_len) {
8823 /* Allocate space to hold websocket payload */
8824 data = mem;
8825 if (data_len > sizeof(mem)) {
8826 data = (char *)mg_malloc(data_len);
8827 if (data == NULL) {
8828 /* Allocation failed, exit the loop and then close the
8829 * connection */
8830 mg_cry(conn, "websocket out of memory; closing connection");
8831 break;
8832 }
8833 }
8834
8835 /* Copy the mask before we shift the queue and destroy it */
8836 if (mask_len > 0) {
8837 memcpy(mask, buf + header_len - mask_len, sizeof(mask));
8838 } else {
8839 memset(mask, 0, sizeof(mask));
8840 }
8841
8842 /* Read frame payload from the first message in the queue into
8843 * data and advance the queue by moving the memory in place. */
8844 assert(body_len >= header_len);
8845 if (data_len + header_len > body_len) {
8846 mop = buf[0]; /* current mask and opcode */
8847 /* Overflow case */
8848 len = body_len - header_len;
8849 memcpy(data, buf + header_len, len);
8850 error = 0;
8851 while (len < data_len) {
8852 n = pull(
8853 NULL, conn, data + len, (int)(data_len - len), timeout);
8854 if (n <= 0) {
8855 error = 1;
8856 break;
8857 }
8858 len += (size_t)n;
8859 }
8860 if (error) {
8861 mg_cry(conn, "Websocket pull failed; closing connection");
8862 break;
8863 }
8864 conn->data_len = conn->request_len;
8865 } else {
8866 mop = buf[0]; /* current mask and opcode, overwritten by
8867 * memmove() */
8868 /* Length of the message being read at the front of the
8869 * queue */
8870 len = data_len + header_len;
8871
8872 /* Copy the data payload into the data pointer for the
8873 * callback */
8874 memcpy(data, buf + header_len, data_len);
8875
8876 /* Move the queue forward len bytes */
8877 memmove(buf, buf + len, body_len - len);
8878
8879 /* Mark the queue as advanced */
8880 conn->data_len -= (int)len;
8881 }
8882
8883 /* Apply mask if necessary */
8884 if (mask_len > 0) {
8885 for (i = 0; i < data_len; ++i) {
8886 data[i] ^= mask[i & 3];
8887 }
8888 }
8889
8890 /* Exit the loop if callback signals to exit (server side),
8891 * or "connection close" opcode received (client side). */
8892 exit_by_callback = 0;
8893 if ((ws_data_handler != NULL)
8894 && !ws_data_handler(conn, mop, data, data_len, callback_data)) {
8895 exit_by_callback = 1;
8896 }
8897
8898 if (data != mem) {
8899 mg_free(data);
8900 }
8901
8902 if (exit_by_callback
8903 || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
8904 /* Opcode == 8, connection close */
8905 break;
8906 }
8907
8908 /* Not breaking the loop, process next websocket frame. */
8909 } else {
8910 /* Read from the socket into the next available location in the
8911 * message queue. */
8912 if ((n = pull(NULL,
8913 conn,
8914 conn->buf + conn->data_len,
8915 conn->buf_size - conn->data_len,
8916 timeout)) <= 0) {
8917 /* Error, no bytes read */
8918 break;
8919 }
8920 conn->data_len += n;
8921 }
8922 }
8923
8924 mg_set_thread_name("worker");
8925 }
8926
8927
8928 static int
8929 mg_websocket_write_exec(struct mg_connection *conn,
8930 int opcode,
8931 const char *data,
8932 size_t dataLen,
8933 uint32_t masking_key)
8934 {
8935 unsigned char header[14];
8936 size_t headerLen = 1;
8937
8938 int retval = -1;
8939
8940 header[0] = 0x80 + (opcode & 0xF);
8941
8942 /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
8943 if (dataLen < 126) {
8944 /* inline 7-bit length field */
8945 header[1] = (unsigned char)dataLen;
8946 headerLen = 2;
8947 } else if (dataLen <= 0xFFFF) {
8948 /* 16-bit length field */
8949 header[1] = 126;
8950 *(uint16_t *)(void *)(header + 2) = htons((uint16_t)dataLen);
8951 headerLen = 4;
8952 } else {
8953 /* 64-bit length field */
8954 header[1] = 127;
8955 *(uint32_t *)(void *)(header + 2) = htonl((uint64_t)dataLen >> 32);
8956 *(uint32_t *)(void *)(header + 6) = htonl(dataLen & 0xFFFFFFFF);
8957 headerLen = 10;
8958 }
8959
8960 if (masking_key) {
8961 /* add mask */
8962 header[1] |= 0x80;
8963 *(uint32_t *)(void *)(header + headerLen) = masking_key;
8964 headerLen += 4;
8965 }
8966
8967
8968 /* Note that POSIX/Winsock's send() is threadsafe
8969 * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
8970 * but mongoose's mg_printf/mg_write is not (because of the loop in
8971 * push(), although that is only a problem if the packet is large or
8972 * outgoing buffer is full). */
8973 (void)mg_lock_connection(conn);
8974 retval = mg_write(conn, header, headerLen);
8975 if (dataLen > 0) {
8976 retval = mg_write(conn, data, dataLen);
8977 }
8978 mg_unlock_connection(conn);
8979
8980 return retval;
8981 }
8982
8983 int
8984 mg_websocket_write(struct mg_connection *conn,
8985 int opcode,
8986 const char *data,
8987 size_t dataLen)
8988 {
8989 return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
8990 }
8991
8992
8993 static void
8994 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
8995 {
8996 size_t i = 0;
8997
8998 i = 0;
8999 if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
9000 /* Convert in 32 bit words, if data is 4 byte aligned */
9001 while (i < (in_len - 3)) {
9002 *(uint32_t *)(void *)(out + i) =
9003 *(uint32_t *)(void *)(in + i) ^ masking_key;
9004 i += 4;
9005 }
9006 }
9007 if (i != in_len) {
9008 /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
9009 while (i < in_len) {
9010 *(uint8_t *)(void *)(out + i) =
9011 *(uint8_t *)(void *)(in + i)
9012 ^ *(((uint8_t *)&masking_key) + (i % 4));
9013 i++;
9014 }
9015 }
9016 }
9017
9018
9019 int
9020 mg_websocket_client_write(struct mg_connection *conn,
9021 int opcode,
9022 const char *data,
9023 size_t dataLen)
9024 {
9025 int retval = -1;
9026 char *masked_data = (char *)mg_malloc(((dataLen + 7) / 4) * 4);
9027 uint32_t masking_key = (uint32_t)get_random();
9028
9029 if (masked_data == NULL) {
9030 /* Return -1 in an error case */
9031 mg_cry(conn,
9032 "Cannot allocate buffer for masked websocket response: "
9033 "Out of memory");
9034 return -1;
9035 }
9036
9037 mask_data(data, dataLen, masking_key, masked_data);
9038
9039 retval = mg_websocket_write_exec(
9040 conn, opcode, masked_data, dataLen, masking_key);
9041 mg_free(masked_data);
9042
9043 return retval;
9044 }
9045
9046
9047 static void
9048 handle_websocket_request(struct mg_connection *conn,
9049 const char *path,
9050 int is_callback_resource,
9051 mg_websocket_connect_handler ws_connect_handler,
9052 mg_websocket_ready_handler ws_ready_handler,
9053 mg_websocket_data_handler ws_data_handler,
9054 mg_websocket_close_handler ws_close_handler,
9055 void *cbData)
9056 {
9057 const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
9058 const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
9059 int lua_websock = 0;
9060
9061 #if !defined(USE_LUA)
9062 (void)path;
9063 #endif
9064
9065 /* Step 1: Check websocket protocol version. */
9066 /* Step 1.1: Check Sec-WebSocket-Key. */
9067 if (!websock_key) {
9068 /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
9069 * requires a Sec-WebSocket-Key header.
9070 */
9071 /* It could be the hixie draft version
9072 * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
9073 */
9074 const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
9075 const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
9076 char key3[8];
9077
9078 if ((key1 != NULL) && (key2 != NULL)) {
9079 /* This version uses 8 byte body data in a GET request */
9080 conn->content_len = 8;
9081 if (8 == mg_read(conn, key3, 8)) {
9082 /* This is the hixie version */
9083 send_http_error(conn,
9084 426,
9085 "%s",
9086 "Protocol upgrade to RFC 6455 required");
9087 return;
9088 }
9089 }
9090 /* This is an unknown version */
9091 send_http_error(conn, 400, "%s", "Malformed websocket request");
9092 return;
9093 }
9094
9095 /* Step 1.2: Check websocket protocol version. */
9096 /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
9097 if (version == NULL || strcmp(version, "13") != 0) {
9098 /* Reject wrong versions */
9099 send_http_error(conn, 426, "%s", "Protocol upgrade required");
9100 return;
9101 }
9102
9103 /* Step 1.3: Could check for "Host", but we do not really nead this
9104 * value for anything, so just ignore it. */
9105
9106 /* Step 2: If a callback is responsible, call it. */
9107 if (is_callback_resource) {
9108 if (ws_connect_handler != NULL
9109 && ws_connect_handler(conn, cbData) != 0) {
9110 /* C callback has returned non-zero, do not proceed with
9111 * handshake.
9112 */
9113 /* Note that C callbacks are no longer called when Lua is
9114 * responsible, so C can no longer filter callbacks for Lua. */
9115 return;
9116 }
9117 }
9118 #if defined(USE_LUA)
9119 /* Step 3: No callback. Check if Lua is responsible. */
9120 else {
9121 /* Step 3.1: Check if Lua is responsible. */
9122 if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
9123 lua_websock =
9124 match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
9125 strlen(
9126 conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
9127 path);
9128 }
9129
9130 if (lua_websock) {
9131 /* Step 3.2: Lua is responsible: call it. */
9132 conn->lua_websocket_state = lua_websocket_new(path, conn);
9133 if (!conn->lua_websocket_state) {
9134 /* Lua rejected the new client */
9135 return;
9136 }
9137 }
9138 }
9139 #endif
9140
9141 /* Step 4: Check if there is a responsible websocket handler. */
9142 if (!is_callback_resource && !lua_websock) {
9143 /* There is no callback, an Lua is not responsible either. */
9144 /* Reply with a 404 Not Found or with nothing at all?
9145 * TODO (mid): check the websocket standards, how to reply to
9146 * requests to invalid websocket addresses. */
9147 send_http_error(conn, 404, "%s", "Not found");
9148 return;
9149 }
9150
9151 /* Step 5: The websocket connection has been accepted */
9152 if (!send_websocket_handshake(conn, websock_key)) {
9153 send_http_error(conn, 500, "%s", "Websocket handshake failed");
9154 return;
9155 }
9156
9157 /* Step 6: Call the ready handler */
9158 if (is_callback_resource) {
9159 if (ws_ready_handler != NULL) {
9160 ws_ready_handler(conn, cbData);
9161 }
9162 #if defined(USE_LUA)
9163 } else if (lua_websock) {
9164 if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
9165 /* the ready handler returned false */
9166 return;
9167 }
9168 #endif
9169 }
9170
9171 /* Step 7: Enter the read loop */
9172 if (is_callback_resource) {
9173 read_websocket(conn, ws_data_handler, cbData);
9174 #if defined(USE_LUA)
9175 } else if (lua_websock) {
9176 read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
9177 #endif
9178 }
9179
9180 /* Step 8: Call the close handler */
9181 if (ws_close_handler) {
9182 ws_close_handler(conn, cbData);
9183 }
9184 }
9185
9186
9187 static int
9188 is_websocket_protocol(const struct mg_connection *conn)
9189 {
9190 const char *upgrade, *connection;
9191
9192 /* A websocket protocoll has the following HTTP headers:
9193 *
9194 * Connection: Upgrade
9195 * Upgrade: Websocket
9196 */
9197
9198 upgrade = mg_get_header(conn, "Upgrade");
9199 if (upgrade == NULL) {
9200 return 0; /* fail early, don't waste time checking other header
9201 * fields
9202 */
9203 }
9204 if (!mg_strcasestr(upgrade, "websocket")) {
9205 return 0;
9206 }
9207
9208 connection = mg_get_header(conn, "Connection");
9209 if (connection == NULL) {
9210 return 0;
9211 }
9212 if (!mg_strcasestr(connection, "upgrade")) {
9213 return 0;
9214 }
9215
9216 /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
9217 * "Sec-WebSocket-Version" are also required.
9218 * Don't check them here, since even an unsupported websocket protocol
9219 * request still IS a websocket request (in contrast to a standard HTTP
9220 * request). It will fail later in handle_websocket_request.
9221 */
9222
9223 return 1;
9224 }
9225 #endif /* !USE_WEBSOCKET */
9226
9227
9228 static int
9229 isbyte(int n)
9230 {
9231 return n >= 0 && n <= 255;
9232 }
9233
9234
9235 static int
9236 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
9237 {
9238 int n, a, b, c, d, slash = 32, len = 0;
9239
9240 if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
9241 || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
9242 && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
9243 && slash < 33) {
9244 len = n;
9245 *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
9246 | (uint32_t)d;
9247 *mask = slash ? 0xffffffffU << (32 - slash) : 0;
9248 }
9249
9250 return len;
9251 }
9252
9253
9254 static int
9255 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
9256 {
9257 int throttle = 0;
9258 struct vec vec, val;
9259 uint32_t net, mask;
9260 char mult;
9261 double v;
9262
9263 while ((spec = next_option(spec, &vec, &val)) != NULL) {
9264 mult = ',';
9265 if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0
9266 || (lowercase(&mult) != 'k' && lowercase(&mult) != 'm'
9267 && mult != ',')) {
9268 continue;
9269 }
9270 v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576
9271 : 1;
9272 if (vec.len == 1 && vec.ptr[0] == '*') {
9273 throttle = (int)v;
9274 } else if (parse_net(vec.ptr, &net, &mask) > 0) {
9275 if ((remote_ip & mask) == net) {
9276 throttle = (int)v;
9277 }
9278 } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
9279 throttle = (int)v;
9280 }
9281 }
9282
9283 return throttle;
9284 }
9285
9286
9287 static uint32_t
9288 get_remote_ip(const struct mg_connection *conn)
9289 {
9290 if (!conn) {
9291 return 0;
9292 }
9293 return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
9294 }
9295
9296
9297 /* The mg_upload function is superseeded by mg_handle_form_request. */
9298 #include "handle_form.inl"
9299
9300
9301 #if defined(MG_LEGACY_INTERFACE)
9302 /* Implement the deprecated mg_upload function by calling the new
9303 * mg_handle_form_request function. While mg_upload could only handle
9304 * HTML forms sent as POST request in multipart/form-data format
9305 * containing only file input elements, mg_handle_form_request can
9306 * handle all form input elements and all standard request methods. */
9307 struct mg_upload_user_data {
9308 struct mg_connection *conn;
9309 const char *destination_dir;
9310 int num_uploaded_files;
9311 };
9312
9313
9314 /* Helper function for deprecated mg_upload. */
9315 static int
9316 mg_upload_field_found(const char *key,
9317 const char *filename,
9318 char *path,
9319 size_t pathlen,
9320 void *user_data)
9321 {
9322 int truncated = 0;
9323 struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9324 (void)key;
9325
9326 if (!filename) {
9327 mg_cry(fud->conn, "%s: No filename set", __func__);
9328 return FORM_FIELD_STORAGE_ABORT;
9329 }
9330 mg_snprintf(fud->conn,
9331 &truncated,
9332 path,
9333 pathlen - 1,
9334 "%s/%s",
9335 fud->destination_dir,
9336 filename);
9337 if (!truncated) {
9338 mg_cry(fud->conn, "%s: File path too long", __func__);
9339 return FORM_FIELD_STORAGE_ABORT;
9340 }
9341 return FORM_FIELD_STORAGE_STORE;
9342 }
9343
9344
9345 /* Helper function for deprecated mg_upload. */
9346 static int
9347 mg_upload_field_get(const char *key,
9348 const char *value,
9349 size_t value_size,
9350 void *user_data)
9351 {
9352 /* Function should never be called */
9353 (void)key;
9354 (void)value;
9355 (void)value_size;
9356 (void)user_data;
9357
9358 return 0;
9359 }
9360
9361
9362 /* Helper function for deprecated mg_upload. */
9363 static int
9364 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
9365 {
9366 struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9367 (void)file_size;
9368
9369 fud->num_uploaded_files++;
9370 fud->conn->ctx->callbacks.upload(fud->conn, path);
9371
9372 return 0;
9373 }
9374
9375
9376 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
9377 int
9378 mg_upload(struct mg_connection *conn, const char *destination_dir)
9379 {
9380 struct mg_upload_user_data fud = {conn, destination_dir, 0};
9381 struct mg_form_data_handler fdh = {mg_upload_field_found,
9382 mg_upload_field_get,
9383 mg_upload_field_stored,
9384 0};
9385 int ret;
9386
9387 fdh.user_data = (void *)&fud;
9388 ret = mg_handle_form_request(conn, &fdh);
9389
9390 if (ret < 0) {
9391 mg_cry(conn, "%s: Error while parsing the request", __func__);
9392 }
9393
9394 return fud.num_uploaded_files;
9395 }
9396 #endif
9397
9398
9399 static int
9400 get_first_ssl_listener_index(const struct mg_context *ctx)
9401 {
9402 unsigned int i;
9403 int idx = -1;
9404 if (ctx) {
9405 for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
9406 idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
9407 }
9408 }
9409 return idx;
9410 }
9411
9412
9413 static void
9414 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
9415 {
9416 char host[1025];
9417 const char *host_header;
9418 size_t hostlen;
9419
9420 host_header = mg_get_header(conn, "Host");
9421 hostlen = sizeof(host);
9422 if (host_header != NULL) {
9423 char *pos;
9424
9425 mg_strlcpy(host, host_header, hostlen);
9426 host[hostlen - 1] = '\0';
9427 pos = strchr(host, ':');
9428 if (pos != NULL) {
9429 *pos = '\0';
9430 }
9431 } else {
9432 /* Cannot get host from the Host: header.
9433 * Fallback to our IP address. */
9434 if (conn) {
9435 sockaddr_to_string(host, hostlen, &conn->client.lsa);
9436 }
9437 }
9438
9439 /* Send host, port, uri and (if it exists) ?query_string */
9440 if (conn) {
9441 mg_printf(conn,
9442 "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
9443 host,
9444 (int)ntohs(
9445 conn->ctx->listening_sockets[ssl_index].lsa.sin.sin_port),
9446 conn->request_info.local_uri,
9447 (conn->request_info.query_string == NULL) ? "" : "?",
9448 (conn->request_info.query_string == NULL)
9449 ? ""
9450 : conn->request_info.query_string);
9451 }
9452 }
9453
9454
9455 static void
9456 mg_set_handler_type(struct mg_context *ctx,
9457 const char *uri,
9458 int handler_type,
9459 int is_delete_request,
9460 mg_request_handler handler,
9461 mg_websocket_connect_handler connect_handler,
9462 mg_websocket_ready_handler ready_handler,
9463 mg_websocket_data_handler data_handler,
9464 mg_websocket_close_handler close_handler,
9465 mg_authorization_handler auth_handler,
9466 void *cbdata)
9467 {
9468 struct mg_handler_info *tmp_rh, **lastref;
9469 size_t urilen = strlen(uri);
9470
9471 if (handler_type == WEBSOCKET_HANDLER) {
9472 /* assert(handler == NULL); */
9473 /* assert(is_delete_request || connect_handler!=NULL ||
9474 * ready_handler!=NULL || data_handler!=NULL ||
9475 * close_handler!=NULL);
9476 */
9477 /* assert(auth_handler == NULL); */
9478 if (handler != NULL) {
9479 return;
9480 }
9481 if (!is_delete_request && connect_handler == NULL
9482 && ready_handler == NULL
9483 && data_handler == NULL
9484 && close_handler == NULL) {
9485 return;
9486 }
9487 if (auth_handler != NULL) {
9488 return;
9489 }
9490 } else if (handler_type == REQUEST_HANDLER) {
9491 /* assert(connect_handler==NULL && ready_handler==NULL &&
9492 * data_handler==NULL && close_handler==NULL); */
9493 /* assert(is_delete_request || (handler!=NULL));
9494 */
9495 /* assert(auth_handler == NULL); */
9496 if (connect_handler != NULL || ready_handler != NULL
9497 || data_handler != NULL
9498 || close_handler != NULL) {
9499 return;
9500 }
9501 if (!is_delete_request && (handler == NULL)) {
9502 return;
9503 }
9504 if (auth_handler != NULL) {
9505 return;
9506 }
9507 } else { /* AUTH_HANDLER */
9508 /* assert(handler == NULL); */
9509 /* assert(connect_handler==NULL && ready_handler==NULL &&
9510 * data_handler==NULL && close_handler==NULL); */
9511 /* assert(auth_handler != NULL); */
9512 if (handler != NULL) {
9513 return;
9514 }
9515 if (connect_handler != NULL || ready_handler != NULL
9516 || data_handler != NULL
9517 || close_handler != NULL) {
9518 return;
9519 }
9520 if (!is_delete_request && (auth_handler == NULL)) {
9521 return;
9522 }
9523 }
9524
9525 if (!ctx) {
9526 return;
9527 }
9528
9529 mg_lock_context(ctx);
9530
9531 /* first try to find an existing handler */
9532 lastref = &(ctx->handlers);
9533 for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
9534 if (tmp_rh->handler_type == handler_type) {
9535 if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9536 if (!is_delete_request) {
9537 /* update existing handler */
9538 if (handler_type == REQUEST_HANDLER) {
9539 tmp_rh->handler = handler;
9540 } else if (handler_type == WEBSOCKET_HANDLER) {
9541 tmp_rh->connect_handler = connect_handler;
9542 tmp_rh->ready_handler = ready_handler;
9543 tmp_rh->data_handler = data_handler;
9544 tmp_rh->close_handler = close_handler;
9545 } else { /* AUTH_HANDLER */
9546 tmp_rh->auth_handler = auth_handler;
9547 }
9548 tmp_rh->cbdata = cbdata;
9549 } else {
9550 /* remove existing handler */
9551 *lastref = tmp_rh->next;
9552 mg_free(tmp_rh->uri);
9553 mg_free(tmp_rh);
9554 }
9555 mg_unlock_context(ctx);
9556 return;
9557 }
9558 }
9559 lastref = &(tmp_rh->next);
9560 }
9561
9562 if (is_delete_request) {
9563 /* no handler to set, this was a remove request to a non-existing
9564 * handler */
9565 mg_unlock_context(ctx);
9566 return;
9567 }
9568
9569 tmp_rh =
9570 (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
9571 if (tmp_rh == NULL) {
9572 mg_unlock_context(ctx);
9573 mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9574 return;
9575 }
9576 tmp_rh->uri = mg_strdup(uri);
9577 if (!tmp_rh->uri) {
9578 mg_unlock_context(ctx);
9579 mg_free(tmp_rh);
9580 mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9581 return;
9582 }
9583 tmp_rh->uri_len = urilen;
9584 if (handler_type == REQUEST_HANDLER) {
9585 tmp_rh->handler = handler;
9586 } else if (handler_type == WEBSOCKET_HANDLER) {
9587 tmp_rh->connect_handler = connect_handler;
9588 tmp_rh->ready_handler = ready_handler;
9589 tmp_rh->data_handler = data_handler;
9590 tmp_rh->close_handler = close_handler;
9591 } else { /* AUTH_HANDLER */
9592 tmp_rh->auth_handler = auth_handler;
9593 }
9594 tmp_rh->cbdata = cbdata;
9595 tmp_rh->handler_type = handler_type;
9596 tmp_rh->next = NULL;
9597
9598 *lastref = tmp_rh;
9599 mg_unlock_context(ctx);
9600 }
9601
9602
9603 void
9604 mg_set_request_handler(struct mg_context *ctx,
9605 const char *uri,
9606 mg_request_handler handler,
9607 void *cbdata)
9608 {
9609 mg_set_handler_type(ctx,
9610 uri,
9611 REQUEST_HANDLER,
9612 handler == NULL,
9613 handler,
9614 NULL,
9615 NULL,
9616 NULL,
9617 NULL,
9618 NULL,
9619 cbdata);
9620 }
9621
9622
9623 void
9624 mg_set_websocket_handler(struct mg_context *ctx,
9625 const char *uri,
9626 mg_websocket_connect_handler connect_handler,
9627 mg_websocket_ready_handler ready_handler,
9628 mg_websocket_data_handler data_handler,
9629 mg_websocket_close_handler close_handler,
9630 void *cbdata)
9631 {
9632 int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
9633 && (data_handler == NULL)
9634 && (close_handler == NULL);
9635 mg_set_handler_type(ctx,
9636 uri,
9637 WEBSOCKET_HANDLER,
9638 is_delete_request,
9639 NULL,
9640 connect_handler,
9641 ready_handler,
9642 data_handler,
9643 close_handler,
9644 NULL,
9645 cbdata);
9646 }
9647
9648
9649 void
9650 mg_set_auth_handler(struct mg_context *ctx,
9651 const char *uri,
9652 mg_request_handler handler,
9653 void *cbdata)
9654 {
9655 mg_set_handler_type(ctx,
9656 uri,
9657 AUTH_HANDLER,
9658 handler == NULL,
9659 NULL,
9660 NULL,
9661 NULL,
9662 NULL,
9663 NULL,
9664 handler,
9665 cbdata);
9666 }
9667
9668
9669 static int
9670 get_request_handler(struct mg_connection *conn,
9671 int handler_type,
9672 mg_request_handler *handler,
9673 mg_websocket_connect_handler *connect_handler,
9674 mg_websocket_ready_handler *ready_handler,
9675 mg_websocket_data_handler *data_handler,
9676 mg_websocket_close_handler *close_handler,
9677 mg_authorization_handler *auth_handler,
9678 void **cbdata)
9679 {
9680 const struct mg_request_info *request_info = mg_get_request_info(conn);
9681 if (request_info) {
9682 const char *uri = request_info->local_uri;
9683 size_t urilen = strlen(uri);
9684 struct mg_handler_info *tmp_rh;
9685
9686 if (!conn || !conn->ctx) {
9687 return 0;
9688 }
9689
9690 mg_lock_context(conn->ctx);
9691
9692 /* first try for an exact match */
9693 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9694 tmp_rh = tmp_rh->next) {
9695 if (tmp_rh->handler_type == handler_type) {
9696 if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9697 if (handler_type == WEBSOCKET_HANDLER) {
9698 *connect_handler = tmp_rh->connect_handler;
9699 *ready_handler = tmp_rh->ready_handler;
9700 *data_handler = tmp_rh->data_handler;
9701 *close_handler = tmp_rh->close_handler;
9702 } else if (handler_type == REQUEST_HANDLER) {
9703 *handler = tmp_rh->handler;
9704 } else { /* AUTH_HANDLER */
9705 *auth_handler = tmp_rh->auth_handler;
9706 }
9707 *cbdata = tmp_rh->cbdata;
9708 mg_unlock_context(conn->ctx);
9709 return 1;
9710 }
9711 }
9712 }
9713
9714 /* next try for a partial match, we will accept uri/something */
9715 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9716 tmp_rh = tmp_rh->next) {
9717 if (tmp_rh->handler_type == handler_type) {
9718 if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
9719 && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
9720 if (handler_type == WEBSOCKET_HANDLER) {
9721 *connect_handler = tmp_rh->connect_handler;
9722 *ready_handler = tmp_rh->ready_handler;
9723 *data_handler = tmp_rh->data_handler;
9724 *close_handler = tmp_rh->close_handler;
9725 } else if (handler_type == REQUEST_HANDLER) {
9726 *handler = tmp_rh->handler;
9727 } else { /* AUTH_HANDLER */
9728 *auth_handler = tmp_rh->auth_handler;
9729 }
9730 *cbdata = tmp_rh->cbdata;
9731 mg_unlock_context(conn->ctx);
9732 return 1;
9733 }
9734 }
9735 }
9736
9737 /* finally try for pattern match */
9738 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9739 tmp_rh = tmp_rh->next) {
9740 if (tmp_rh->handler_type == handler_type) {
9741 if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
9742 if (handler_type == WEBSOCKET_HANDLER) {
9743 *connect_handler = tmp_rh->connect_handler;
9744 *ready_handler = tmp_rh->ready_handler;
9745 *data_handler = tmp_rh->data_handler;
9746 *close_handler = tmp_rh->close_handler;
9747 } else if (handler_type == REQUEST_HANDLER) {
9748 *handler = tmp_rh->handler;
9749 } else { /* AUTH_HANDLER */
9750 *auth_handler = tmp_rh->auth_handler;
9751 }
9752 *cbdata = tmp_rh->cbdata;
9753 mg_unlock_context(conn->ctx);
9754 return 1;
9755 }
9756 }
9757 }
9758
9759 mg_unlock_context(conn->ctx);
9760 }
9761 return 0; /* none found */
9762 }
9763
9764
9765 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
9766 static int
9767 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
9768 void *cbdata)
9769 {
9770 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9771 if (pcallbacks->websocket_connect) {
9772 return pcallbacks->websocket_connect(conn);
9773 }
9774 /* No handler set - assume "OK" */
9775 return 0;
9776 }
9777
9778
9779 static void
9780 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
9781 {
9782 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9783 if (pcallbacks->websocket_ready) {
9784 pcallbacks->websocket_ready(conn);
9785 }
9786 }
9787
9788
9789 static int
9790 deprecated_websocket_data_wrapper(struct mg_connection *conn,
9791 int bits,
9792 char *data,
9793 size_t len,
9794 void *cbdata)
9795 {
9796 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9797 if (pcallbacks->websocket_data) {
9798 return pcallbacks->websocket_data(conn, bits, data, len);
9799 }
9800 /* No handler set - assume "OK" */
9801 return 1;
9802 }
9803 #endif
9804
9805
9806 /* This is the heart of the Civetweb's logic.
9807 * This function is called when the request is read, parsed and validated,
9808 * and Civetweb must decide what action to take: serve a file, or
9809 * a directory, or call embedded function, etcetera. */
9810 static void
9811 handle_request(struct mg_connection *conn)
9812 {
9813 if (conn) {
9814 struct mg_request_info *ri = &conn->request_info;
9815 char path[PATH_MAX];
9816 int uri_len, ssl_index;
9817 int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
9818 is_put_or_delete_request = 0, is_callback_resource = 0;
9819 int i;
9820 struct file file = STRUCT_FILE_INITIALIZER;
9821 mg_request_handler callback_handler = NULL;
9822 mg_websocket_connect_handler ws_connect_handler = NULL;
9823 mg_websocket_ready_handler ws_ready_handler = NULL;
9824 mg_websocket_data_handler ws_data_handler = NULL;
9825 mg_websocket_close_handler ws_close_handler = NULL;
9826 void *callback_data = NULL;
9827 mg_authorization_handler auth_handler = NULL;
9828 void *auth_callback_data = NULL;
9829 #if !defined(NO_FILES)
9830 time_t curtime = time(NULL);
9831 char date[64];
9832 #endif
9833
9834 path[0] = 0;
9835
9836 if (!ri) {
9837 return;
9838 }
9839
9840 /* 1. get the request url */
9841 /* 1.1. split into url and query string */
9842 if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
9843 != NULL) {
9844 *((char *)conn->request_info.query_string++) = '\0';
9845 }
9846 uri_len = (int)strlen(ri->local_uri);
9847
9848 /* 1.2. decode url (if config says so) */
9849 if (should_decode_url(conn)) {
9850 mg_url_decode(
9851 ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
9852 }
9853
9854 /* 1.3. clean URIs, so a path like allowed_dir/../forbidden_file is
9855 * not possible (if config says so) */
9856 if (!mg_strcasecmp(conn->ctx->config[CANONICALIZE_URL_PATH], "yes")) {
9857 remove_double_dots_and_double_slashes((char *)ri->local_uri);
9858 }
9859
9860 /* step 1. completed, the url is known now */
9861 DEBUG_TRACE("URL: %s", ri->local_uri);
9862
9863 /* 2. do a https redirect, if required */
9864 if (!conn->client.is_ssl && conn->client.ssl_redir) {
9865 ssl_index = get_first_ssl_listener_index(conn->ctx);
9866 if (ssl_index >= 0) {
9867 redirect_to_https_port(conn, ssl_index);
9868 } else {
9869 /* A http to https forward port has been specified,
9870 * but no https port to forward to. */
9871 send_http_error(conn,
9872 503,
9873 "%s",
9874 "Error: SSL forward not configured properly");
9875 mg_cry(conn, "Can not redirect to SSL, no SSL port available");
9876 }
9877 return;
9878 }
9879
9880 /* 3. if this ip has limited speed, set it for this connection */
9881 conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
9882 get_remote_ip(conn),
9883 ri->local_uri);
9884
9885 /* 4. call a "handle everything" callback, if registered */
9886 if (conn->ctx->callbacks.begin_request != NULL) {
9887 /* Note that since V1.7 the "begin_request" function is called
9888 * before an authorization check. If an authorization check is
9889 * required, use a request_handler instead. */
9890 i = conn->ctx->callbacks.begin_request(conn);
9891 if (i > 0) {
9892 /* callback already processed the request. Store the
9893 return value as a status code for the access log. */
9894 conn->status_code = i;
9895 discard_unread_request_data(conn);
9896 return;
9897 } else if (i == 0) {
9898 /* civetweb should process the request */
9899 } else {
9900 /* unspecified - may change with the next version */
9901 return;
9902 }
9903 }
9904
9905 /* request not yet handled by a handler or redirect, so the request
9906 * is processed here */
9907
9908 /* 5. interpret the url to find out how the request must be handled
9909 */
9910 /* 5.1. first test, if the request targets the regular http(s)://
9911 * protocol namespace or the websocket ws(s):// protocol namespace.
9912 */
9913 is_websocket_request = is_websocket_protocol(conn);
9914
9915 /* 5.2. check if the request will be handled by a callback */
9916 if (get_request_handler(conn,
9917 is_websocket_request ? WEBSOCKET_HANDLER
9918 : REQUEST_HANDLER,
9919 &callback_handler,
9920 &ws_connect_handler,
9921 &ws_ready_handler,
9922 &ws_data_handler,
9923 &ws_close_handler,
9924 NULL,
9925 &callback_data)) {
9926 /* 5.2.1. A callback will handle this request. All requests
9927 * handled
9928 * by a callback have to be considered as requests to a script
9929 * resource. */
9930 is_callback_resource = 1;
9931 is_script_resource = 1;
9932 is_put_or_delete_request = is_put_or_delete_method(conn);
9933 } else {
9934 no_callback_resource:
9935 /* 5.2.2. No callback is responsible for this request. The URI
9936 * addresses a file based resource (static content or Lua/cgi
9937 * scripts in the file system). */
9938 is_callback_resource = 0;
9939 interpret_uri(conn,
9940 path,
9941 sizeof(path),
9942 &file,
9943 &is_found,
9944 &is_script_resource,
9945 &is_websocket_request,
9946 &is_put_or_delete_request);
9947 }
9948
9949 /* 6. authorization check */
9950 /* 6.1. a custom authorization handler is installed */
9951 if (get_request_handler(conn,
9952 AUTH_HANDLER,
9953 NULL,
9954 NULL,
9955 NULL,
9956 NULL,
9957 NULL,
9958 &auth_handler,
9959 &auth_callback_data)) {
9960 if (!auth_handler(conn, auth_callback_data)) {
9961 return;
9962 }
9963 } else if (is_put_or_delete_request && !is_script_resource
9964 && !is_callback_resource) {
9965 /* 6.2. this request is a PUT/DELETE to a real file */
9966 /* 6.2.1. thus, the server must have real files */
9967 #if defined(NO_FILES)
9968 if (1) {
9969 #else
9970 if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
9971 #endif
9972 /* This server does not have any real files, thus the
9973 * PUT/DELETE methods are not valid. */
9974 send_http_error(conn,
9975 405,
9976 "%s method not allowed",
9977 conn->request_info.request_method);
9978 return;
9979 }
9980
9981 #if !defined(NO_FILES)
9982 /* 6.2.2. Check if put authorization for static files is
9983 * available.
9984 */
9985 if (!is_authorized_for_put(conn)) {
9986 send_authorization_request(conn);
9987 return;
9988 }
9989 #endif
9990
9991 } else {
9992 /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
9993 * or it is a PUT or DELETE request to a resource that does not
9994 * correspond to a file. Check authorization. */
9995 if (!check_authorization(conn, path)) {
9996 send_authorization_request(conn);
9997 return;
9998 }
9999 }
10000
10001 /* request is authorized or does not need authorization */
10002
10003 /* 7. check if there are request handlers for this uri */
10004 if (is_callback_resource) {
10005 if (!is_websocket_request) {
10006 i = callback_handler(conn, callback_data);
10007 if (i > 0) {
10008 /* Do nothing, callback has served the request. Store
10009 * the
10010 * return value as status code for the log and discard
10011 * all
10012 * data from the client not used by the callback. */
10013 conn->status_code = i;
10014 discard_unread_request_data(conn);
10015 } else {
10016 /* TODO (high): what if the handler did NOT handle the
10017 * request */
10018 /* The last version did handle this as a file request,
10019 * but
10020 * since a file request is not always a script resource,
10021 * the authorization check might be different */
10022 interpret_uri(conn,
10023 path,
10024 sizeof(path),
10025 &file,
10026 &is_found,
10027 &is_script_resource,
10028 &is_websocket_request,
10029 &is_put_or_delete_request);
10030 callback_handler = NULL;
10031
10032 /* TODO (very low): goto is deprecated but for the
10033 * moment,
10034 * a goto is simpler than some curious loop. */
10035 /* The situation "callback does not handle the request"
10036 * needs to be reconsidered anyway. */
10037 goto no_callback_resource;
10038 }
10039 } else {
10040 #if defined(USE_WEBSOCKET)
10041 handle_websocket_request(conn,
10042 path,
10043 is_callback_resource,
10044 ws_connect_handler,
10045 ws_ready_handler,
10046 ws_data_handler,
10047 ws_close_handler,
10048 callback_data);
10049 #endif
10050 }
10051 return;
10052 }
10053
10054 /* 8. handle websocket requests */
10055 #if defined(USE_WEBSOCKET)
10056 if (is_websocket_request) {
10057 if (is_script_resource) {
10058 /* Websocket Lua script */
10059 handle_websocket_request(conn,
10060 path,
10061 0 /* Lua Script */,
10062 NULL,
10063 NULL,
10064 NULL,
10065 NULL,
10066 &conn->ctx->callbacks);
10067 } else {
10068 #if defined(MG_LEGACY_INTERFACE)
10069 handle_websocket_request(
10070 conn,
10071 path,
10072 !is_script_resource /* could be deprecated global callback */,
10073 deprecated_websocket_connect_wrapper,
10074 deprecated_websocket_ready_wrapper,
10075 deprecated_websocket_data_wrapper,
10076 NULL,
10077 &conn->ctx->callbacks);
10078 #else
10079 send_http_error(conn, 404, "%s", "Not found");
10080 #endif
10081 }
10082 return;
10083 } else
10084 #endif
10085
10086 #if defined(NO_FILES)
10087 /* 9a. In case the server uses only callbacks, this uri is
10088 * unknown.
10089 * Then, all request handling ends here. */
10090 send_http_error(conn, 404, "%s", "Not Found");
10091
10092 #else
10093 /* 9b. This request is either for a static file or resource handled
10094 * by a script file. Thus, a DOCUMENT_ROOT must exist. */
10095 if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10096 send_http_error(conn, 404, "%s", "Not Found");
10097 return;
10098 }
10099
10100 /* 10. File is handled by a script. */
10101 if (is_script_resource) {
10102 handle_file_based_request(conn, path, &file);
10103 return;
10104 }
10105
10106 /* 11. Handle put/delete/mkcol requests */
10107 if (is_put_or_delete_request) {
10108 /* 11.1. PUT method */
10109 if (!strcmp(ri->request_method, "PUT")) {
10110 put_file(conn, path);
10111 return;
10112 }
10113 /* 11.2. DELETE method */
10114 if (!strcmp(ri->request_method, "DELETE")) {
10115 delete_file(conn, path);
10116 return;
10117 }
10118 /* 11.3. MKCOL method */
10119 if (!strcmp(ri->request_method, "MKCOL")) {
10120 mkcol(conn, path);
10121 return;
10122 }
10123 /* 11.4. PATCH method
10124 * This method is not supported for static resources,
10125 * only for scripts (Lua, CGI) and callbacks. */
10126 send_http_error(conn,
10127 405,
10128 "%s method not allowed",
10129 conn->request_info.request_method);
10130 return;
10131 }
10132
10133 /* 11. File does not exist, or it was configured that it should be
10134 * hidden */
10135 if (!is_found || (must_hide_file(conn, path))) {
10136 send_http_error(conn, 404, "%s", "Not found");
10137 return;
10138 }
10139
10140 /* 12. Directory uris should end with a slash */
10141 if (file.is_directory && ri->local_uri[uri_len - 1] != '/') {
10142 gmt_time_string(date, sizeof(date), &curtime);
10143 mg_printf(conn,
10144 "HTTP/1.1 301 Moved Permanently\r\n"
10145 "Location: %s/\r\n"
10146 "Date: %s\r\n"
10147 /* "Cache-Control: private\r\n" (= default) */
10148 "Content-Length: 0\r\n"
10149 "Connection: %s\r\n\r\n",
10150 ri->request_uri,
10151 date,
10152 suggest_connection_header(conn));
10153 return;
10154 }
10155
10156 /* 13. Handle other methods than GET/HEAD */
10157 /* 13.1. Handle PROPFIND */
10158 if (!strcmp(ri->request_method, "PROPFIND")) {
10159 handle_propfind(conn, path, &file);
10160 return;
10161 }
10162 /* 13.2. Handle OPTIONS for files */
10163 if (!strcmp(ri->request_method, "OPTIONS")) {
10164 /* This standard handler is only used for real files.
10165 * Scripts should support the OPTIONS method themselves, to allow a
10166 * maximum flexibility.
10167 * Lua and CGI scripts may fully support CORS this way (including
10168 * preflights). */
10169 send_options(conn);
10170 return;
10171 }
10172 /* 13.3. everything but GET and HEAD (e.g. POST) */
10173 if (0 != strcmp(ri->request_method, "GET")
10174 && 0 != strcmp(ri->request_method, "HEAD")) {
10175 send_http_error(conn,
10176 405,
10177 "%s method not allowed",
10178 conn->request_info.request_method);
10179 return;
10180 }
10181
10182 /* 14. directories */
10183 if (file.is_directory) {
10184 if (substitute_index_file(conn, path, sizeof(path), &file)) {
10185 /* 14.1. use a substitute file */
10186 /* TODO (high): substitute index may be a script resource.
10187 * define what should be possible in this case. */
10188 } else {
10189 /* 14.2. no substitute file */
10190 if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
10191 "yes")) {
10192 handle_directory_request(conn, path);
10193 } else {
10194 send_http_error(conn,
10195 403,
10196 "%s",
10197 "Error: Directory listing denied");
10198 }
10199 return;
10200 }
10201 }
10202
10203 handle_file_based_request(conn, path, &file);
10204 #endif /* !defined(NO_FILES) */
10205
10206 #if 0
10207 /* Perform redirect and auth checks before calling begin_request()
10208 * handler.
10209 * Otherwise, begin_request() would need to perform auth checks and
10210 * redirects. */
10211 #endif
10212 }
10213 return;
10214 }
10215
10216
10217 static void
10218 handle_file_based_request(struct mg_connection *conn,
10219 const char *path,
10220 struct file *file)
10221 {
10222 if (!conn || !conn->ctx) {
10223 return;
10224 }
10225
10226 if (0) {
10227 #ifdef USE_LUA
10228 } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
10229 strlen(
10230 conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
10231 path) > 0) {
10232 /* Lua server page: an SSI like page containing mostly plain html
10233 * code
10234 * plus some tags with server generated contents. */
10235 handle_lsp_request(conn, path, file, NULL);
10236 } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
10237 strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
10238 path) > 0) {
10239 /* Lua in-server module script: a CGI like script used to generate
10240 * the
10241 * entire reply. */
10242 mg_exec_lua_script(conn, path, NULL);
10243 #endif
10244 #if defined(USE_DUKTAPE)
10245 } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
10246 strlen(
10247 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
10248 path) > 0) {
10249 /* Call duktape to generate the page */
10250 mg_exec_duktape_script(conn, path);
10251 #endif
10252 #if !defined(NO_CGI)
10253 } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
10254 strlen(conn->ctx->config[CGI_EXTENSIONS]),
10255 path) > 0) {
10256 /* CGI scripts may support all HTTP methods */
10257 handle_cgi_request(conn, path);
10258 #endif /* !NO_CGI */
10259 } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10260 strlen(conn->ctx->config[SSI_EXTENSIONS]),
10261 path) > 0) {
10262 handle_ssi_file_request(conn, path, file);
10263 #if !defined(NO_CACHING)
10264 } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
10265 /* Send 304 "Not Modified" - this must not send any body data */
10266 send_http_error(conn, 304, "%s", "");
10267 #endif /* !NO_CACHING */
10268 } else {
10269 handle_static_file_request(conn, path, file, NULL);
10270 }
10271 }
10272
10273
10274 static void
10275 close_all_listening_sockets(struct mg_context *ctx)
10276 {
10277 unsigned int i;
10278 if (!ctx) {
10279 return;
10280 }
10281
10282 for (i = 0; i < ctx->num_listening_sockets; i++) {
10283 closesocket(ctx->listening_sockets[i].sock);
10284 ctx->listening_sockets[i].sock = INVALID_SOCKET;
10285 }
10286 mg_free(ctx->listening_sockets);
10287 ctx->listening_sockets = NULL;
10288 mg_free(ctx->listening_ports);
10289 ctx->listening_ports = NULL;
10290 }
10291
10292
10293 /* Valid listening port specification is: [ip_address:]port[s]
10294 * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s
10295 * Examples for IPv6: [::]:80, [::1]:80,
10296 * [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:443s
10297 * see https://tools.ietf.org/html/rfc3513#section-2.2 */
10298 static int
10299 parse_port_string(const struct vec *vec, struct socket *so)
10300 {
10301 unsigned int a, b, c, d, port;
10302 int ch, len;
10303 #if defined(USE_IPV6)
10304 char buf[100] = {0};
10305 #endif
10306
10307 /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
10308 * Also, all-zeroes in the socket address means binding to all addresses
10309 * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
10310 memset(so, 0, sizeof(*so));
10311 so->lsa.sin.sin_family = AF_INET;
10312
10313 if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
10314 == 5) {
10315 /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
10316 so->lsa.sin.sin_addr.s_addr =
10317 htonl((a << 24) | (b << 16) | (c << 8) | d);
10318 so->lsa.sin.sin_port = htons((uint16_t)port);
10319 #if defined(USE_IPV6)
10320 } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
10321 && mg_inet_pton(
10322 AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
10323 /* IPv6 address, examples: see above */
10324 /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
10325 */
10326 so->lsa.sin6.sin6_port = htons((uint16_t)port);
10327 #endif
10328 } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
10329 /* If only port is specified, bind to IPv4, INADDR_ANY */
10330 so->lsa.sin.sin_port = htons((uint16_t)port);
10331 } else {
10332 /* Parsing failure. Make port invalid. */
10333 port = 0;
10334 len = 0;
10335 }
10336
10337 /* sscanf and the option splitting code ensure the following condition
10338 */
10339 if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
10340 return 0;
10341 }
10342 ch = vec->ptr[len]; /* Next character after the port number */
10343 so->is_ssl = (ch == 's');
10344 so->ssl_redir = (ch == 'r');
10345
10346 /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
10347 return is_valid_port(port)
10348 && (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
10349 }
10350
10351
10352 static int
10353 set_ports_option(struct mg_context *ctx)
10354 {
10355 const char *list;
10356 int on = 1;
10357 #if defined(USE_IPV6)
10358 int off = 0;
10359 #endif
10360 struct vec vec;
10361 struct socket so, *ptr;
10362
10363 in_port_t *portPtr;
10364 union usa usa;
10365 socklen_t len;
10366
10367 int portsTotal = 0;
10368 int portsOk = 0;
10369
10370 if (!ctx) {
10371 return 0;
10372 }
10373
10374 memset(&so, 0, sizeof(so));
10375 memset(&usa, 0, sizeof(usa));
10376 len = sizeof(usa);
10377 list = ctx->config[LISTENING_PORTS];
10378 while ((list = next_option(list, &vec, NULL)) != NULL) {
10379
10380 portsTotal++;
10381
10382 if (!parse_port_string(&vec, &so)) {
10383 mg_cry(fc(ctx),
10384 "%.*s: invalid port spec (entry %i). Expecting list of: %s",
10385 (int)vec.len,
10386 vec.ptr,
10387 portsTotal,
10388 "[IP_ADDRESS:]PORT[s|r]");
10389 continue;
10390 }
10391
10392 if (so.is_ssl && ctx->ssl_ctx == NULL) {
10393
10394 mg_cry(fc(ctx),
10395 "Cannot add SSL socket (entry %i). Is -ssl_certificate "
10396 "option set?",
10397 portsTotal);
10398 continue;
10399 }
10400
10401 if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
10402 == INVALID_SOCKET) {
10403
10404 mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
10405 continue;
10406 }
10407
10408 #ifdef _WIN32
10409 /* Windows SO_REUSEADDR lets many procs binds to a
10410 * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
10411 * if someone already has the socket -- DTL */
10412 /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
10413 * Windows might need a few seconds before
10414 * the same port can be used again in the
10415 * same process, so a short Sleep may be
10416 * required between mg_stop and mg_start.
10417 */
10418 if (setsockopt(so.sock,
10419 SOL_SOCKET,
10420 SO_EXCLUSIVEADDRUSE,
10421 (SOCK_OPT_TYPE)&on,
10422 sizeof(on)) != 0) {
10423
10424 mg_cry(fc(ctx),
10425 "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
10426 portsTotal);
10427 }
10428 #else
10429 if (setsockopt(so.sock,
10430 SOL_SOCKET,
10431 SO_REUSEADDR,
10432 (SOCK_OPT_TYPE)&on,
10433 sizeof(on)) != 0) {
10434
10435 mg_cry(fc(ctx),
10436 "cannot set socket option SO_REUSEADDR (entry %i)",
10437 portsTotal);
10438 }
10439 #endif
10440
10441 #if defined(USE_IPV6)
10442 if (so.lsa.sa.sa_family == AF_INET6
10443 && setsockopt(so.sock,
10444 IPPROTO_IPV6,
10445 IPV6_V6ONLY,
10446 (void *)&off,
10447 sizeof(off)) != 0) {
10448
10449 mg_cry(fc(ctx),
10450 "cannot set socket option IPV6_V6ONLY (entry %i)",
10451 portsTotal);
10452 }
10453 #endif
10454
10455 if (so.lsa.sa.sa_family == AF_INET) {
10456
10457 len = sizeof(so.lsa.sin);
10458 if (bind(so.sock, &so.lsa.sa, len) != 0) {
10459 mg_cry(fc(ctx),
10460 "cannot bind to %.*s: %d (%s)",
10461 (int)vec.len,
10462 vec.ptr,
10463 (int)ERRNO,
10464 strerror(errno));
10465 closesocket(so.sock);
10466 so.sock = INVALID_SOCKET;
10467 continue;
10468 }
10469 }
10470 #if defined(USE_IPV6)
10471 else if (so.lsa.sa.sa_family == AF_INET6) {
10472
10473 len = sizeof(so.lsa.sin6);
10474 if (bind(so.sock, &so.lsa.sa, len) != 0) {
10475 mg_cry(fc(ctx),
10476 "cannot bind to IPv6 %.*s: %d (%s)",
10477 (int)vec.len,
10478 vec.ptr,
10479 (int)ERRNO,
10480 strerror(errno));
10481 closesocket(so.sock);
10482 so.sock = INVALID_SOCKET;
10483 continue;
10484 }
10485 }
10486 #endif
10487 else {
10488 mg_cry(fc(ctx),
10489 "cannot bind: address family not supported (entry %i)",
10490 portsTotal);
10491 continue;
10492 }
10493
10494 if (listen(so.sock, SOMAXCONN) != 0) {
10495
10496 mg_cry(fc(ctx),
10497 "cannot listen to %.*s: %d (%s)",
10498 (int)vec.len,
10499 vec.ptr,
10500 (int)ERRNO,
10501 strerror(errno));
10502 closesocket(so.sock);
10503 so.sock = INVALID_SOCKET;
10504 continue;
10505 }
10506
10507 if (getsockname(so.sock, &(usa.sa), &len) != 0) {
10508
10509 int err = (int)ERRNO;
10510 mg_cry(fc(ctx),
10511 "call to getsockname failed %.*s: %d (%s)",
10512 (int)vec.len,
10513 vec.ptr,
10514 err,
10515 strerror(errno));
10516 closesocket(so.sock);
10517 so.sock = INVALID_SOCKET;
10518 continue;
10519 }
10520
10521 if ((ptr = (struct socket *)
10522 mg_realloc(ctx->listening_sockets,
10523 (ctx->num_listening_sockets + 1)
10524 * sizeof(ctx->listening_sockets[0]))) == NULL) {
10525
10526 mg_cry(fc(ctx), "%s", "Out of memory");
10527 closesocket(so.sock);
10528 so.sock = INVALID_SOCKET;
10529 continue;
10530 }
10531
10532 if ((portPtr =
10533 (in_port_t *)mg_realloc(ctx->listening_ports,
10534 (ctx->num_listening_sockets + 1)
10535 * sizeof(ctx->listening_ports[0])))
10536 == NULL) {
10537
10538 mg_cry(fc(ctx), "%s", "Out of memory");
10539 closesocket(so.sock);
10540 so.sock = INVALID_SOCKET;
10541 mg_free(ptr);
10542 continue;
10543 }
10544
10545 set_close_on_exec(so.sock, fc(ctx));
10546 ctx->listening_sockets = ptr;
10547 ctx->listening_sockets[ctx->num_listening_sockets] = so;
10548 ctx->listening_ports = portPtr;
10549 ctx->listening_ports[ctx->num_listening_sockets] =
10550 ntohs(usa.sin.sin_port);
10551 ctx->num_listening_sockets++;
10552 portsOk++;
10553 }
10554
10555 if (portsOk != portsTotal) {
10556 close_all_listening_sockets(ctx);
10557 portsOk = 0;
10558 }
10559
10560 return portsOk;
10561 }
10562
10563
10564 static const char *
10565 header_val(const struct mg_connection *conn, const char *header)
10566 {
10567 const char *header_value;
10568
10569 if ((header_value = mg_get_header(conn, header)) == NULL) {
10570 return "-";
10571 } else {
10572 return header_value;
10573 }
10574 }
10575
10576
10577 static void
10578 log_access(const struct mg_connection *conn)
10579 {
10580 const struct mg_request_info *ri;
10581 struct file fi;
10582 char date[64], src_addr[IP_ADDR_STR_LEN];
10583 struct tm *tm;
10584
10585 const char *referer;
10586 const char *user_agent;
10587
10588 char buf[4096];
10589
10590 if (!conn || !conn->ctx) {
10591 return;
10592 }
10593
10594 if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
10595 if (mg_fopen(conn, conn->ctx->config[ACCESS_LOG_FILE], "a+", &fi)
10596 == 0) {
10597 fi.fp = NULL;
10598 }
10599 } else {
10600 fi.fp = NULL;
10601 }
10602
10603 if (fi.fp == NULL && conn->ctx->callbacks.log_message == NULL) {
10604 return;
10605 }
10606
10607 tm = localtime(&conn->conn_birth_time);
10608 if (tm != NULL) {
10609 strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
10610 } else {
10611 mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
10612 date[sizeof(date) - 1] = '\0';
10613 }
10614
10615 ri = &conn->request_info;
10616
10617 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
10618 referer = header_val(conn, "Referer");
10619 user_agent = header_val(conn, "User-Agent");
10620
10621 mg_snprintf(conn,
10622 NULL, /* Ignore truncation in access log */
10623 buf,
10624 sizeof(buf),
10625 "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
10626 src_addr,
10627 ri->remote_user == NULL ? "-" : ri->remote_user,
10628 date,
10629 ri->request_method ? ri->request_method : "-",
10630 ri->request_uri ? ri->request_uri : "-",
10631 ri->query_string ? "?" : "",
10632 ri->query_string ? ri->query_string : "",
10633 ri->http_version,
10634 conn->status_code,
10635 conn->num_bytes_sent,
10636 referer,
10637 user_agent);
10638
10639 if (conn->ctx->callbacks.log_access) {
10640 conn->ctx->callbacks.log_access(conn, buf);
10641 }
10642
10643 if (fi.fp) {
10644 flockfile(fi.fp);
10645 fprintf(fi.fp, "%s\n", buf);
10646 fflush(fi.fp);
10647 funlockfile(fi.fp);
10648 mg_fclose(&fi);
10649 }
10650 }
10651
10652
10653 /* Verify given socket address against the ACL.
10654 * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
10655 */
10656 static int
10657 check_acl(struct mg_context *ctx, uint32_t remote_ip)
10658 {
10659 int allowed, flag;
10660 uint32_t net, mask;
10661 struct vec vec;
10662
10663 if (ctx) {
10664 const char *list = ctx->config[ACCESS_CONTROL_LIST];
10665
10666 /* If any ACL is set, deny by default */
10667 allowed = list == NULL ? '+' : '-';
10668
10669 while ((list = next_option(list, &vec, NULL)) != NULL) {
10670 flag = vec.ptr[0];
10671 if ((flag != '+' && flag != '-')
10672 || parse_net(&vec.ptr[1], &net, &mask) == 0) {
10673 mg_cry(fc(ctx),
10674 "%s: subnet must be [+|-]x.x.x.x[/x]",
10675 __func__);
10676 return -1;
10677 }
10678
10679 if (net == (remote_ip & mask)) {
10680 allowed = flag;
10681 }
10682 }
10683
10684 return allowed == '+';
10685 }
10686 return -1;
10687 }
10688
10689
10690 #if !defined(_WIN32)
10691 static int
10692 set_uid_option(struct mg_context *ctx)
10693 {
10694 struct passwd *pw;
10695 if (ctx) {
10696 const char *uid = ctx->config[RUN_AS_USER];
10697 int success = 0;
10698
10699 if (uid == NULL) {
10700 success = 1;
10701 } else {
10702 if ((pw = getpwnam(uid)) == NULL) {
10703 mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
10704 } else if (setgid(pw->pw_gid) == -1) {
10705 mg_cry(fc(ctx),
10706 "%s: setgid(%s): %s",
10707 __func__,
10708 uid,
10709 strerror(errno));
10710 } else if (setgroups(0, NULL)) {
10711 mg_cry(fc(ctx),
10712 "%s: setgroups(): %s",
10713 __func__,
10714 strerror(errno));
10715 } else if (setuid(pw->pw_uid) == -1) {
10716 mg_cry(fc(ctx),
10717 "%s: setuid(%s): %s",
10718 __func__,
10719 uid,
10720 strerror(errno));
10721 } else {
10722 success = 1;
10723 }
10724 }
10725
10726 return success;
10727 }
10728 return 0;
10729 }
10730 #endif /* !_WIN32 */
10731
10732
10733 static void
10734 tls_dtor(void *key)
10735 {
10736 struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
10737 /* key == pthread_getspecific(sTlsKey); */
10738
10739 if (tls) {
10740 if (tls->is_master == 2) {
10741 tls->is_master = -3; /* Mark memory as dead */
10742 mg_free(tls);
10743 }
10744 }
10745 pthread_setspecific(sTlsKey, NULL);
10746 }
10747
10748
10749 #if !defined(NO_SSL)
10750
10751 /* Must be set if sizeof(pthread_t) > sizeof(unsigned long) */
10752 static unsigned long
10753 ssl_id_callback(void)
10754 {
10755 #ifdef _WIN32
10756 return GetCurrentThreadId();
10757 #else
10758
10759 #ifdef __clang__
10760 #pragma clang diagnostic push
10761 #pragma clang diagnostic ignored "-Wunreachable-code"
10762 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
10763 * or not, so one of the two conditions will be unreachable by construction.
10764 * Unfortunately the C standard does not define a way to check this at
10765 * compile time, since the #if preprocessor conditions can not use the sizeof
10766 * operator as an argument. */
10767 #endif
10768
10769 if (sizeof(pthread_t) > sizeof(unsigned long)) {
10770 /* This is the problematic case for CRYPTO_set_id_callback:
10771 * The OS pthread_t can not be cast to unsigned long. */
10772 struct mg_workerTLS *tls =
10773 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
10774 if (tls == NULL) {
10775 /* SSL called from an unknown thread: Create some thread index.
10776 */
10777 tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
10778 tls->is_master = -2; /* -2 means "3rd party thread" */
10779 tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
10780 pthread_setspecific(sTlsKey, tls);
10781 }
10782 return tls->thread_idx;
10783 } else {
10784 /* pthread_t may be any data type, so a simple cast to unsigned long
10785 * can rise a warning/error, depending on the platform.
10786 * Here memcpy is used as an anything-to-anything cast. */
10787 unsigned long ret = 0;
10788 pthread_t t = pthread_self();
10789 memcpy(&ret, &t, sizeof(pthread_t));
10790 return ret;
10791 }
10792
10793 #ifdef __clang__
10794 #pragma clang diagnostic pop
10795 #endif
10796
10797 #endif
10798 }
10799
10800
10801 static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
10802 static const char *ssl_error(void);
10803
10804
10805 static int
10806 refresh_trust(struct mg_connection *conn)
10807 {
10808 static int reload_lock = 0;
10809 static long int data_check = 0;
10810
10811 struct stat cert_buf;
10812 long int t;
10813 char *pem;
10814 int should_verify_peer;
10815
10816 if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
10817 && conn->ctx->callbacks.init_ssl == NULL) {
10818 return 0;
10819 }
10820
10821 t = data_check;
10822 if (stat(pem, &cert_buf) != -1) {
10823 t = (long int)cert_buf.st_mtime;
10824 }
10825
10826 if (data_check != t) {
10827 data_check = t;
10828
10829 should_verify_peer =
10830 (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
10831 && (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
10832 == 0);
10833
10834 if (should_verify_peer) {
10835 char *ca_path = conn->ctx->config[SSL_CA_PATH];
10836 char *ca_file = conn->ctx->config[SSL_CA_FILE];
10837 if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
10838 ca_file,
10839 ca_path) != 1) {
10840 mg_cry(fc(conn->ctx),
10841 "SSL_CTX_load_verify_locations error: %s "
10842 "ssl_verify_peer requires setting "
10843 "either ssl_ca_path or ssl_ca_file. Is any of them "
10844 "present in "
10845 "the .conf file?",
10846 ssl_error());
10847 return 0;
10848 }
10849 }
10850
10851 if (!reload_lock) {
10852 reload_lock = 1;
10853 if (ssl_use_pem_file(conn->ctx, pem) == 0) {
10854 return 0;
10855 }
10856 reload_lock = 0;
10857 }
10858 }
10859 /* lock while cert is reloading */
10860 while (reload_lock) {
10861 sleep(1);
10862 }
10863
10864 return 1;
10865 }
10866
10867
10868 static pthread_mutex_t *ssl_mutexes;
10869
10870
10871 static int
10872 sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
10873 {
10874 int ret, err;
10875 int short_trust;
10876
10877 if (!conn) {
10878 return 0;
10879 }
10880
10881 short_trust =
10882 (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
10883 && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
10884
10885 if (short_trust) {
10886 int trust_ret = refresh_trust(conn);
10887 if (!trust_ret) {
10888 return trust_ret;
10889 }
10890 }
10891
10892 conn->ssl = SSL_new(s);
10893 if (conn->ssl == NULL) {
10894 return 0;
10895 }
10896
10897 ret = SSL_set_fd(conn->ssl, conn->client.sock);
10898 if (ret != 1) {
10899 err = SSL_get_error(conn->ssl, ret);
10900 (void)err; /* TODO: set some error message */
10901 SSL_free(conn->ssl);
10902 conn->ssl = NULL;
10903 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10904 /* see
10905 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10906 ERR_remove_state(0);
10907 return 0;
10908 }
10909
10910 ret = func(conn->ssl);
10911 if (ret != 1) {
10912 err = SSL_get_error(conn->ssl, ret);
10913 (void)err; /* TODO: set some error message */
10914 SSL_free(conn->ssl);
10915 conn->ssl = NULL;
10916 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10917 /* see
10918 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10919 ERR_remove_state(0);
10920 return 0;
10921 }
10922
10923 return 1;
10924 }
10925
10926
10927 /* Return OpenSSL error message (from CRYPTO lib) */
10928 static const char *
10929 ssl_error(void)
10930 {
10931 unsigned long err;
10932 err = ERR_get_error();
10933 return err == 0 ? "" : ERR_error_string(err, NULL);
10934 }
10935
10936
10937 static void
10938 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
10939 {
10940 (void)line;
10941 (void)file;
10942
10943 if (mode & 1) {
10944 /* 1 is CRYPTO_LOCK */
10945 (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
10946 } else {
10947 (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
10948 }
10949 }
10950
10951
10952 #if !defined(NO_SSL_DL)
10953 static void *
10954 load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
10955 {
10956 union {
10957 void *p;
10958 void (*fp)(void);
10959 } u;
10960 void *dll_handle;
10961 struct ssl_func *fp;
10962
10963 if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
10964 mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
10965 return NULL;
10966 }
10967
10968 for (fp = sw; fp->name != NULL; fp++) {
10969 #ifdef _WIN32
10970 /* GetProcAddress() returns pointer to function */
10971 u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
10972 #else
10973 /* dlsym() on UNIX returns void *. ISO C forbids casts of data
10974 * pointers to function pointers. We need to use a union to make a
10975 * cast. */
10976 u.p = dlsym(dll_handle, fp->name);
10977 #endif /* _WIN32 */
10978 if (u.fp == NULL) {
10979 mg_cry(fc(ctx),
10980 "%s: %s: cannot find %s",
10981 __func__,
10982 dll_name,
10983 fp->name);
10984 dlclose(dll_handle);
10985 return NULL;
10986 } else {
10987 fp->ptr = u.fp;
10988 }
10989 }
10990
10991 return dll_handle;
10992 }
10993
10994
10995 static void *ssllib_dll_handle; /* Store the ssl library handle. */
10996 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
10997
10998 #endif /* NO_SSL_DL */
10999
11000
11001 #if defined(SSL_ALREADY_INITIALIZED)
11002 static int cryptolib_users = 1; /* Reference counter for crypto library. */
11003 #else
11004 static int cryptolib_users = 0; /* Reference counter for crypto library. */
11005 #endif
11006
11007
11008 static int
11009 initialize_ssl(struct mg_context *ctx)
11010 {
11011 int i;
11012 size_t size;
11013
11014 #if !defined(NO_SSL_DL)
11015 if (!cryptolib_dll_handle) {
11016 cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
11017 if (!cryptolib_dll_handle) {
11018 return 0;
11019 }
11020 }
11021 #endif /* NO_SSL_DL */
11022
11023 if (mg_atomic_inc(&cryptolib_users) > 1) {
11024 return 1;
11025 }
11026
11027 /* Initialize locking callbacks, needed for thread safety.
11028 * http://www.openssl.org/support/faq.html#PROG1
11029 */
11030 i = CRYPTO_num_locks();
11031 if (i < 0) {
11032 i = 0;
11033 }
11034 size = sizeof(pthread_mutex_t) * ((size_t)(i));
11035 if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
11036 mg_cry(fc(ctx),
11037 "%s: cannot allocate mutexes: %s",
11038 __func__,
11039 ssl_error());
11040 return 0;
11041 }
11042
11043 for (i = 0; i < CRYPTO_num_locks(); i++) {
11044 pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
11045 }
11046
11047 CRYPTO_set_locking_callback(&ssl_locking_callback);
11048 CRYPTO_set_id_callback(&ssl_id_callback);
11049
11050 return 1;
11051 }
11052
11053
11054 static int
11055 ssl_use_pem_file(struct mg_context *ctx, const char *pem)
11056 {
11057 if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
11058 mg_cry(fc(ctx),
11059 "%s: cannot open certificate file %s: %s",
11060 __func__,
11061 pem,
11062 ssl_error());
11063 return 0;
11064 }
11065
11066 /* could use SSL_CTX_set_default_passwd_cb_userdata */
11067 if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
11068 mg_cry(fc(ctx),
11069 "%s: cannot open private key file %s: %s",
11070 __func__,
11071 pem,
11072 ssl_error());
11073 return 0;
11074 }
11075
11076 if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
11077 mg_cry(fc(ctx),
11078 "%s: certificate and private key do not match: %s",
11079 __func__,
11080 pem);
11081 return 0;
11082 }
11083
11084 if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
11085 mg_cry(fc(ctx),
11086 "%s: cannot use certificate chain file %s: %s",
11087 __func__,
11088 pem,
11089 ssl_error());
11090 return 0;
11091 }
11092 return 1;
11093 }
11094
11095
11096 static long
11097 ssl_get_protocol(int version_id)
11098 {
11099 long ret = SSL_OP_ALL;
11100 if (version_id > 0)
11101 ret |= SSL_OP_NO_SSLv2;
11102 if (version_id > 1)
11103 ret |= SSL_OP_NO_SSLv3;
11104 if (version_id > 2)
11105 ret |= SSL_OP_NO_TLSv1;
11106 if (version_id > 3)
11107 ret |= SSL_OP_NO_TLSv1_1;
11108 return ret;
11109 }
11110
11111
11112 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
11113 static int
11114 set_ssl_option(struct mg_context *ctx)
11115 {
11116 const char *pem;
11117 int callback_ret;
11118 int should_verify_peer;
11119 const char *ca_path;
11120 const char *ca_file;
11121 int use_default_verify_paths;
11122 int verify_depth;
11123 time_t now_rt = time(NULL);
11124 struct timespec now_mt;
11125 md5_byte_t ssl_context_id[16];
11126 md5_state_t md5state;
11127 int protocol_ver;
11128
11129 /* If PEM file is not specified and the init_ssl callback
11130 * is not specified, skip SSL initialization. */
11131 if (!ctx) {
11132 return 0;
11133 }
11134 if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
11135 && ctx->callbacks.init_ssl == NULL) {
11136 return 1;
11137 }
11138
11139 if (!initialize_ssl(ctx)) {
11140 return 0;
11141 }
11142
11143 #if !defined(NO_SSL_DL)
11144 if (!ssllib_dll_handle) {
11145 ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
11146 if (!ssllib_dll_handle) {
11147 return 0;
11148 }
11149 }
11150 #endif /* NO_SSL_DL */
11151
11152 /* Initialize SSL library */
11153 SSL_library_init();
11154 SSL_load_error_strings();
11155
11156 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
11157 mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
11158 return 0;
11159 }
11160
11161 SSL_CTX_clear_options(ctx->ssl_ctx,
11162 SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1
11163 | SSL_OP_NO_TLSv1_1);
11164 protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
11165 SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
11166 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
11167 SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
11168
11169 /* If a callback has been specified, call it. */
11170 callback_ret =
11171 (ctx->callbacks.init_ssl == NULL)
11172 ? 0
11173 : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
11174
11175 /* If callback returns 0, civetweb sets up the SSL certificate.
11176 * If it returns 1, civetweb assumes the calback already did this.
11177 * If it returns -1, initializing ssl fails. */
11178 if (callback_ret < 0) {
11179 mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
11180 return 0;
11181 }
11182 if (callback_ret > 0) {
11183 if (pem != NULL) {
11184 (void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
11185 }
11186 return 1;
11187 }
11188
11189 /* Use some UID as session context ID. */
11190 md5_init(&md5state);
11191 md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
11192 clock_gettime(CLOCK_MONOTONIC, &now_mt);
11193 md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
11194 md5_append(&md5state,
11195 (const md5_byte_t *)ctx->config[LISTENING_PORTS],
11196 strlen(ctx->config[LISTENING_PORTS]));
11197 md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
11198 md5_finish(&md5state, ssl_context_id);
11199
11200 SSL_CTX_set_session_id_context(ctx->ssl_ctx,
11201 (const unsigned char *)&ssl_context_id,
11202 sizeof(ssl_context_id));
11203
11204 if (pem != NULL) {
11205 if (!ssl_use_pem_file(ctx, pem)) {
11206 return 0;
11207 }
11208 }
11209
11210 should_verify_peer =
11211 (ctx->config[SSL_DO_VERIFY_PEER] != NULL)
11212 && (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
11213
11214 use_default_verify_paths =
11215 (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
11216 && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
11217
11218 if (should_verify_peer) {
11219 ca_path = ctx->config[SSL_CA_PATH];
11220 ca_file = ctx->config[SSL_CA_FILE];
11221 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
11222 != 1) {
11223 mg_cry(fc(ctx),
11224 "SSL_CTX_load_verify_locations error: %s "
11225 "ssl_verify_peer requires setting "
11226 "either ssl_ca_path or ssl_ca_file. Is any of them "
11227 "present in "
11228 "the .conf file?",
11229 ssl_error());
11230 return 0;
11231 }
11232
11233 SSL_CTX_set_verify(ctx->ssl_ctx,
11234 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
11235 NULL);
11236
11237 if (use_default_verify_paths
11238 && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
11239 mg_cry(fc(ctx),
11240 "SSL_CTX_set_default_verify_paths error: %s",
11241 ssl_error());
11242 return 0;
11243 }
11244
11245 if (ctx->config[SSL_VERIFY_DEPTH]) {
11246 verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
11247 SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
11248 }
11249 }
11250
11251 if (ctx->config[SSL_CIPHER_LIST] != NULL) {
11252 if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
11253 != 1) {
11254 mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
11255 }
11256 }
11257
11258 return 1;
11259 }
11260
11261
11262 static void
11263 uninitialize_ssl(struct mg_context *ctx)
11264 {
11265 int i;
11266 (void)ctx;
11267
11268 if (mg_atomic_dec(&cryptolib_users) == 0) {
11269
11270 /* Shutdown according to
11271 * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
11272 * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
11273 */
11274 CRYPTO_set_locking_callback(NULL);
11275 CRYPTO_set_id_callback(NULL);
11276 ENGINE_cleanup();
11277 CONF_modules_unload(1);
11278 ERR_free_strings();
11279 EVP_cleanup();
11280 CRYPTO_cleanup_all_ex_data();
11281 ERR_remove_state(0);
11282
11283 for (i = 0; i < CRYPTO_num_locks(); i++) {
11284 pthread_mutex_destroy(&ssl_mutexes[i]);
11285 }
11286 mg_free(ssl_mutexes);
11287 ssl_mutexes = NULL;
11288 }
11289 }
11290 #endif /* !NO_SSL */
11291
11292
11293 static int
11294 set_gpass_option(struct mg_context *ctx)
11295 {
11296 if (ctx) {
11297 struct file file = STRUCT_FILE_INITIALIZER;
11298 const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
11299 if (path != NULL && !mg_stat(fc(ctx), path, &file)) {
11300 mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
11301 return 0;
11302 }
11303 return 1;
11304 }
11305 return 0;
11306 }
11307
11308
11309 static int
11310 set_acl_option(struct mg_context *ctx)
11311 {
11312 return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
11313 }
11314
11315
11316 static void
11317 reset_per_request_attributes(struct mg_connection *conn)
11318 {
11319 if (!conn) {
11320 return;
11321 }
11322 conn->path_info = NULL;
11323 conn->num_bytes_sent = conn->consumed_content = 0;
11324 conn->status_code = -1;
11325 conn->is_chunked = 0;
11326 conn->must_close = conn->request_len = conn->throttle = 0;
11327 conn->request_info.content_length = -1;
11328 conn->request_info.remote_user = NULL;
11329 conn->request_info.request_method = NULL;
11330 conn->request_info.request_uri = NULL;
11331 conn->request_info.local_uri = NULL;
11332 conn->request_info.uri = NULL; /* TODO: cleanup uri,
11333 * local_uri and request_uri */
11334 conn->request_info.http_version = NULL;
11335 conn->request_info.num_headers = 0;
11336 conn->data_len = 0;
11337 conn->chunk_remainder = 0;
11338 conn->internal_error = 0;
11339 }
11340
11341
11342 static int
11343 set_sock_timeout(SOCKET sock, int milliseconds)
11344 {
11345 int r0 = 0, r1, r2;
11346
11347 #ifdef _WIN32
11348 /* Windows specific */
11349
11350 DWORD tv = (DWORD)milliseconds;
11351
11352 #else
11353 /* Linux, ... (not Windows) */
11354
11355 struct timeval tv;
11356
11357 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
11358 * max. time waiting for the acknowledged of TCP data before the connection
11359 * will be forcefully closed and ETIMEDOUT is returned to the application.
11360 * If this option is not set, the default timeout of 20-30 minutes is used.
11361 */
11362 /* #define TCP_USER_TIMEOUT (18) */
11363
11364 #if defined(TCP_USER_TIMEOUT)
11365 unsigned int uto = (unsigned int)milliseconds;
11366 r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
11367 #endif
11368
11369 memset(&tv, 0, sizeof(tv));
11370 tv.tv_sec = milliseconds / 1000;
11371 tv.tv_usec = (milliseconds * 1000) % 1000000;
11372
11373 #endif /* _WIN32 */
11374
11375 r1 = setsockopt(
11376 sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11377 r2 = setsockopt(
11378 sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11379
11380 return r0 || r1 || r2;
11381 }
11382
11383
11384 static int
11385 set_tcp_nodelay(SOCKET sock, int nodelay_on)
11386 {
11387 if (setsockopt(sock,
11388 IPPROTO_TCP,
11389 TCP_NODELAY,
11390 (SOCK_OPT_TYPE)&nodelay_on,
11391 sizeof(nodelay_on)) != 0) {
11392 /* Error */
11393 return 1;
11394 }
11395 /* OK */
11396 return 0;
11397 }
11398
11399
11400 static void
11401 close_socket_gracefully(struct mg_connection *conn)
11402 {
11403 #if defined(_WIN32)
11404 char buf[MG_BUF_LEN];
11405 int n;
11406 #endif
11407 struct linger linger;
11408
11409 if (!conn) {
11410 return;
11411 }
11412
11413 /* Set linger option to avoid socket hanging out after close. This
11414 * prevent
11415 * ephemeral port exhaust problem under high QPS. */
11416 linger.l_onoff = 1;
11417 linger.l_linger = 1;
11418
11419 if (setsockopt(conn->client.sock,
11420 SOL_SOCKET,
11421 SO_LINGER,
11422 (char *)&linger,
11423 sizeof(linger)) != 0) {
11424 mg_cry(conn,
11425 "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
11426 __func__,
11427 strerror(ERRNO));
11428 }
11429
11430 /* Send FIN to the client */
11431 shutdown(conn->client.sock, SHUT_WR);
11432 set_non_blocking_mode(conn->client.sock);
11433
11434 #if defined(_WIN32)
11435 /* Read and discard pending incoming data. If we do not do that and
11436 * close
11437 * the socket, the data in the send buffer may be discarded. This
11438 * behaviour is seen on Windows, when client keeps sending data
11439 * when server decides to close the connection; then when client
11440 * does recv() it gets no data back. */
11441 do {
11442 n = pull(
11443 NULL, conn, buf, sizeof(buf), 1E-10 /* TODO: allow 0 as timeout */);
11444 } while (n > 0);
11445 #endif
11446
11447 /* Now we know that our FIN is ACK-ed, safe to close */
11448 closesocket(conn->client.sock);
11449 conn->client.sock = INVALID_SOCKET;
11450 }
11451
11452
11453 static void
11454 close_connection(struct mg_connection *conn)
11455 {
11456 if (!conn || !conn->ctx) {
11457 return;
11458 }
11459
11460 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
11461 if (conn->lua_websocket_state) {
11462 lua_websocket_close(conn, conn->lua_websocket_state);
11463 conn->lua_websocket_state = NULL;
11464 }
11465 #endif
11466
11467 /* call the connection_close callback if assigned */
11468 if ((conn->ctx->callbacks.connection_close != NULL)
11469 && (conn->ctx->context_type == 1)) {
11470 conn->ctx->callbacks.connection_close(conn);
11471 }
11472
11473 mg_lock_connection(conn);
11474
11475 conn->must_close = 1;
11476
11477 #ifndef NO_SSL
11478 if (conn->ssl != NULL) {
11479 /* Run SSL_shutdown twice to ensure completly close SSL connection
11480 */
11481 SSL_shutdown(conn->ssl);
11482 SSL_free(conn->ssl);
11483 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
11484 /* see
11485 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11486 ERR_remove_state(0);
11487 conn->ssl = NULL;
11488 }
11489 #endif
11490 if (conn->client.sock != INVALID_SOCKET) {
11491 close_socket_gracefully(conn);
11492 conn->client.sock = INVALID_SOCKET;
11493 }
11494
11495 mg_unlock_connection(conn);
11496 }
11497
11498 void
11499 mg_close_connection(struct mg_connection *conn)
11500 {
11501 struct mg_context *client_ctx = NULL;
11502 unsigned int i;
11503
11504 if (conn == NULL) {
11505 return;
11506 }
11507
11508 if (conn->ctx->context_type == 2) {
11509 client_ctx = conn->ctx;
11510 /* client context: loops must end */
11511 conn->ctx->stop_flag = 1;
11512 }
11513
11514 #ifndef NO_SSL
11515 if (conn->client_ssl_ctx != NULL) {
11516 SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
11517 }
11518 #endif
11519 close_connection(conn);
11520 if (client_ctx != NULL) {
11521 /* join worker thread and free context */
11522 for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
11523 if (client_ctx->workerthreadids[i] != 0) {
11524 mg_join_thread(client_ctx->workerthreadids[i]);
11525 }
11526 }
11527 mg_free(client_ctx->workerthreadids);
11528 mg_free(client_ctx);
11529 (void)pthread_mutex_destroy(&conn->mutex);
11530 mg_free(conn);
11531 }
11532 }
11533
11534
11535 static struct mg_connection *
11536 mg_connect_client_impl(const struct mg_client_options *client_options,
11537 int use_ssl,
11538 char *ebuf,
11539 size_t ebuf_len)
11540 {
11541 static struct mg_context fake_ctx;
11542 struct mg_connection *conn = NULL;
11543 SOCKET sock;
11544 union usa sa;
11545
11546 if (!connect_socket(&fake_ctx,
11547 client_options->host,
11548 client_options->port,
11549 use_ssl,
11550 ebuf,
11551 ebuf_len,
11552 &sock,
11553 &sa)) {
11554 ;
11555 } else if ((conn = (struct mg_connection *)
11556 mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
11557 mg_snprintf(NULL,
11558 NULL, /* No truncation check for ebuf */
11559 ebuf,
11560 ebuf_len,
11561 "calloc(): %s",
11562 strerror(ERRNO));
11563 closesocket(sock);
11564 #ifndef NO_SSL
11565 } else if (use_ssl
11566 && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
11567 == NULL) {
11568 mg_snprintf(NULL,
11569 NULL, /* No truncation check for ebuf */
11570 ebuf,
11571 ebuf_len,
11572 "SSL_CTX_new error");
11573 closesocket(sock);
11574 mg_free(conn);
11575 conn = NULL;
11576 #endif /* NO_SSL */
11577
11578 } else {
11579
11580 #ifdef USE_IPV6
11581 socklen_t len = (sa.sa.sa_family == AF_INET)
11582 ? sizeof(conn->client.rsa.sin)
11583 : sizeof(conn->client.rsa.sin6);
11584 struct sockaddr *psa =
11585 (sa.sa.sa_family == AF_INET)
11586 ? (struct sockaddr *)&(conn->client.rsa.sin)
11587 : (struct sockaddr *)&(conn->client.rsa.sin6);
11588 #else
11589 socklen_t len = sizeof(conn->client.rsa.sin);
11590 struct sockaddr *psa = (struct sockaddr *)&(conn->client.rsa.sin);
11591 #endif
11592
11593 conn->buf_size = MAX_REQUEST_SIZE;
11594 conn->buf = (char *)(conn + 1);
11595 conn->ctx = &fake_ctx;
11596 conn->client.sock = sock;
11597 conn->client.lsa = sa;
11598
11599 if (getsockname(sock, psa, &len) != 0) {
11600 mg_cry(conn,
11601 "%s: getsockname() failed: %s",
11602 __func__,
11603 strerror(ERRNO));
11604 }
11605
11606 conn->client.is_ssl = use_ssl ? 1 : 0;
11607 (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
11608
11609 #ifndef NO_SSL
11610 if (use_ssl) {
11611 fake_ctx.ssl_ctx = conn->client_ssl_ctx;
11612
11613 /* TODO: Check ssl_verify_peer and ssl_ca_path here.
11614 * SSL_CTX_set_verify call is needed to switch off server
11615 * certificate checking, which is off by default in OpenSSL and
11616 * on in yaSSL. */
11617 /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
11618 * SSL_VERIFY_PEER, verify_ssl_server); */
11619
11620 if (client_options->client_cert) {
11621 if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
11622 mg_snprintf(NULL,
11623 NULL, /* No truncation check for ebuf */
11624 ebuf,
11625 ebuf_len,
11626 "Can not use SSL client certificate");
11627 SSL_CTX_free(conn->client_ssl_ctx);
11628 closesocket(sock);
11629 mg_free(conn);
11630 conn = NULL;
11631 }
11632 }
11633
11634 if (client_options->server_cert) {
11635 SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
11636 client_options->server_cert,
11637 NULL);
11638 SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
11639 } else {
11640 SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
11641 }
11642
11643 if (!sslize(conn, conn->client_ssl_ctx, SSL_connect)) {
11644 mg_snprintf(NULL,
11645 NULL, /* No truncation check for ebuf */
11646 ebuf,
11647 ebuf_len,
11648 "SSL connection error");
11649 SSL_CTX_free(conn->client_ssl_ctx);
11650 closesocket(sock);
11651 mg_free(conn);
11652 conn = NULL;
11653 }
11654 }
11655 #endif
11656 }
11657
11658 return conn;
11659 }
11660
11661
11662 CIVETWEB_API struct mg_connection *
11663 mg_connect_client_secure(const struct mg_client_options *client_options,
11664 char *error_buffer,
11665 size_t error_buffer_size)
11666 {
11667 return mg_connect_client_impl(client_options,
11668 1,
11669 error_buffer,
11670 error_buffer_size);
11671 }
11672
11673
11674 struct mg_connection *
11675 mg_connect_client(const char *host,
11676 int port,
11677 int use_ssl,
11678 char *error_buffer,
11679 size_t error_buffer_size)
11680 {
11681 struct mg_client_options opts;
11682 memset(&opts, 0, sizeof(opts));
11683 opts.host = host;
11684 opts.port = port;
11685 return mg_connect_client_impl(&opts,
11686 use_ssl,
11687 error_buffer,
11688 error_buffer_size);
11689 }
11690
11691
11692 static const struct {
11693 const char *proto;
11694 size_t proto_len;
11695 unsigned default_port;
11696 } abs_uri_protocols[] = {{"http://", 7, 80},
11697 {"https://", 8, 443},
11698 {"ws://", 5, 80},
11699 {"wss://", 6, 443},
11700 {NULL, 0, 0}};
11701
11702
11703 /* Check if the uri is valid.
11704 * return 0 for invalid uri,
11705 * return 1 for *,
11706 * return 2 for relative uri,
11707 * return 3 for absolute uri without port,
11708 * return 4 for absolute uri with port */
11709 static int
11710 get_uri_type(const char *uri)
11711 {
11712 int i;
11713 char *hostend, *portbegin, *portend;
11714 unsigned long port;
11715
11716 /* According to the HTTP standard
11717 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
11718 * URI can be an asterisk (*) or should start with slash (relative uri),
11719 * or it should start with the protocol (absolute uri). */
11720 if (uri[0] == '*' && uri[1] == '\0') {
11721 /* asterisk */
11722 return 1;
11723 }
11724 if (uri[0] == '/') {
11725 /* relative uri */
11726 return 2;
11727 }
11728
11729 /* It could be an absolute uri: */
11730 /* This function only checks if the uri is valid, not if it is
11731 * addressing the current server. So civetweb can also be used
11732 * as a proxy server. */
11733 for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11734 if (mg_strncasecmp(uri,
11735 abs_uri_protocols[i].proto,
11736 abs_uri_protocols[i].proto_len) == 0) {
11737
11738 hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
11739 if (!hostend) {
11740 return 0;
11741 }
11742 portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
11743 if (!portbegin) {
11744 return 3;
11745 }
11746
11747 port = strtoul(portbegin + 1, &portend, 10);
11748 if ((portend != hostend) || !port || !is_valid_port(port)) {
11749 return 0;
11750 }
11751
11752 return 4;
11753 }
11754 }
11755
11756 return 0;
11757 }
11758
11759
11760 /* Return NULL or the relative uri at the current server */
11761 static const char *
11762 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
11763 {
11764 const char *server_domain;
11765 size_t server_domain_len;
11766 size_t request_domain_len = 0;
11767 unsigned long port = 0;
11768 int i, auth_domain_check_enabled;
11769 const char *hostbegin = NULL;
11770 const char *hostend = NULL;
11771 const char *portbegin;
11772 char *portend;
11773
11774 auth_domain_check_enabled =
11775 !strcmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],"yes");
11776 /* DNS is case insensitive, so use case insensitive string compare here
11777 */
11778 server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
11779 if (!server_domain && auth_domain_check_enabled) {
11780 return 0;
11781 }
11782 server_domain_len = strlen(server_domain);
11783 if (!server_domain_len) {
11784 return 0;
11785 }
11786
11787 for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11788 if (mg_strncasecmp(uri,
11789 abs_uri_protocols[i].proto,
11790 abs_uri_protocols[i].proto_len) == 0) {
11791
11792 hostbegin = uri + abs_uri_protocols[i].proto_len;
11793 hostend = strchr(hostbegin, '/');
11794 if (!hostend) {
11795 return 0;
11796 }
11797 portbegin = strchr(hostbegin, ':');
11798 if ((!portbegin) || (portbegin > hostend)) {
11799 port = abs_uri_protocols[i].default_port;
11800 request_domain_len = (size_t)(hostend - hostbegin);
11801 } else {
11802 port = strtoul(portbegin + 1, &portend, 10);
11803 if ((portend != hostend) || !port || !is_valid_port(port)) {
11804 return 0;
11805 }
11806 request_domain_len = (size_t)(portbegin - hostbegin);
11807 }
11808 /* protocol found, port set */
11809 break;
11810 }
11811 }
11812
11813 if (!port) {
11814 /* port remains 0 if the protocol is not found */
11815 return 0;
11816 }
11817
11818 /* Check if the request is directed to a different server. */
11819 /* First check if the port is the same (IPv4 and IPv6). */
11820 #if defined(USE_IPV6)
11821 if (conn->client.lsa.sa.sa_family == AF_INET6) {
11822 if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
11823 /* Request is directed to a different port */
11824 return 0;
11825 }
11826 } else
11827 #endif
11828 {
11829 if (ntohs(conn->client.lsa.sin.sin_port) != port) {
11830 /* Request is directed to a different port */
11831 return 0;
11832 }
11833 }
11834
11835 /* Finally check if the server corresponds to the authentication
11836 * domain of the server (the server domain).
11837 * Allow full matches (like http://mydomain.com/path/file.ext), and
11838 * allow subdomain matches (like http://www.mydomain.com/path/file.ext),
11839 * but do not allow substrings (like http://notmydomain.com/path/file.ext
11840 * or http://mydomain.com.fake/path/file.ext).
11841 */
11842 if (auth_domain_check_enabled) {
11843 if ((request_domain_len == server_domain_len)
11844 && (!memcmp(server_domain, hostbegin, server_domain_len))) {
11845 /* Request is directed to this server - full name match. */
11846 } else {
11847 if (request_domain_len < (server_domain_len + 2)) {
11848 /* Request is directed to another server: The server name is longer
11849 * than
11850 * the request name. Drop this case here to avoid overflows in the
11851 * following checks. */
11852 return 0;
11853 }
11854 if (hostbegin[request_domain_len - server_domain_len - 1] != '.') {
11855 /* Request is directed to another server: It could be a substring
11856 * like notmyserver.com */
11857 return 0;
11858 }
11859 if (0 != memcmp(server_domain,
11860 hostbegin + request_domain_len - server_domain_len,
11861 server_domain_len)) {
11862 /* Request is directed to another server:
11863 * The server name is different. */
11864 return 0;
11865 }
11866 }
11867 }
11868
11869 return hostend;
11870 }
11871
11872
11873 static int
11874 getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
11875 {
11876 const char *cl;
11877 int check_method = should_validate_http_method(conn);
11878
11879 if (ebuf_len > 0) {
11880 ebuf[0] = '\0';
11881 }
11882 *err = 0;
11883
11884 reset_per_request_attributes(conn);
11885
11886 if (!conn) {
11887 mg_snprintf(conn,
11888 NULL, /* No truncation check for ebuf */
11889 ebuf,
11890 ebuf_len,
11891 "%s",
11892 "Internal error");
11893 *err = 500;
11894 return 0;
11895 }
11896 /* Set the time the request was received. This value should be used for
11897 * timeouts. */
11898 clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
11899
11900 conn->request_len =
11901 read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
11902 /* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
11903 */
11904 if (conn->request_len >= 0 && conn->data_len < conn->request_len) {
11905 mg_snprintf(conn,
11906 NULL, /* No truncation check for ebuf */
11907 ebuf,
11908 ebuf_len,
11909 "%s",
11910 "Invalid request size");
11911 *err = 500;
11912 return 0;
11913 }
11914
11915 if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
11916 mg_snprintf(conn,
11917 NULL, /* No truncation check for ebuf */
11918 ebuf,
11919 ebuf_len,
11920 "%s",
11921 "Request Too Large");
11922 *err = 413;
11923 return 0;
11924 } else if (conn->request_len <= 0) {
11925 if (conn->data_len > 0) {
11926 mg_snprintf(conn,
11927 NULL, /* No truncation check for ebuf */
11928 ebuf,
11929 ebuf_len,
11930 "%s",
11931 "Client sent malformed request");
11932 *err = 400;
11933 } else {
11934 /* Server did not send anything -> just close the connection */
11935 conn->must_close = 1;
11936 mg_snprintf(conn,
11937 NULL, /* No truncation check for ebuf */
11938 ebuf,
11939 ebuf_len,
11940 "%s",
11941 "Client did not send a request");
11942 *err = 0;
11943 }
11944 return 0;
11945 } else if (parse_http_message(
11946 check_method, conn->buf, conn->buf_size, &conn->request_info)
11947 <= 0) {
11948 mg_snprintf(conn,
11949 NULL, /* No truncation check for ebuf */
11950 ebuf,
11951 ebuf_len,
11952 "%s",
11953 "Bad Request");
11954 *err = 400;
11955 return 0;
11956 } else {
11957 /* Message is a valid request or response */
11958 if ((cl = get_header(&conn->request_info, "Transfer-Encoding"))
11959 != NULL
11960 && !mg_strcasecmp(cl, "chunked")) {
11961 conn->is_chunked = 1;
11962 conn->content_len = 0;
11963 } else if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
11964 /* Request/response has content length set */
11965 char *endptr = NULL;
11966 conn->content_len = strtoll(cl, &endptr, 10);
11967 if (endptr == cl) {
11968 mg_snprintf(conn,
11969 NULL, /* No truncation check for ebuf */
11970 ebuf,
11971 ebuf_len,
11972 "%s",
11973 "Bad Request");
11974 *err = 400;
11975 return 0;
11976 }
11977 /* Publish the content length back to the request info. */
11978 conn->request_info.content_length = conn->content_len;
11979 } else if (!mg_strcasecmp(conn->request_info.request_method, "POST")
11980 || !mg_strcasecmp(conn->request_info.request_method,
11981 "PUT")) {
11982 /* POST or PUT request without content length set */
11983 conn->content_len = -1;
11984 } else if (!mg_strncasecmp(conn->request_info.request_method,
11985 "HTTP/",
11986 5)) {
11987 /* Response without content length set */
11988 conn->content_len = -1;
11989 } else {
11990 /* Other request */
11991 conn->content_len = 0;
11992 }
11993 }
11994 return 1;
11995 }
11996
11997
11998 int
11999 mg_get_response(struct mg_connection *conn,
12000 char *ebuf,
12001 size_t ebuf_len,
12002 int timeout)
12003 {
12004 if (conn) {
12005 /* Implementation of API function for HTTP clients */
12006 int err, ret;
12007 struct mg_context *octx = conn->ctx;
12008 struct mg_context rctx = *(conn->ctx);
12009 char txt[32]; /* will not overflow */
12010
12011 if (timeout >= 0) {
12012 mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
12013 rctx.config[REQUEST_TIMEOUT] = txt;
12014 set_sock_timeout(conn->client.sock, timeout);
12015 } else {
12016 rctx.config[REQUEST_TIMEOUT] = NULL;
12017 }
12018
12019 conn->ctx = &rctx;
12020 ret = getreq(conn, ebuf, ebuf_len, &err);
12021 conn->ctx = octx;
12022
12023 /* TODO: 1) uri is deprecated;
12024 * 2) here, ri.uri is the http response code */
12025 conn->request_info.uri = conn->request_info.request_uri;
12026
12027 /* TODO (mid): Define proper return values - maybe return length?
12028 * For the first test use <0 for error and >0 for OK */
12029 return (ret == 0) ? -1 : +1;
12030 }
12031 return -1;
12032 }
12033
12034
12035 struct mg_connection *
12036 mg_download(const char *host,
12037 int port,
12038 int use_ssl,
12039 char *ebuf,
12040 size_t ebuf_len,
12041 const char *fmt,
12042 ...)
12043 {
12044 struct mg_connection *conn;
12045 va_list ap;
12046 int i;
12047 int reqerr;
12048
12049 va_start(ap, fmt);
12050 ebuf[0] = '\0';
12051
12052 /* open a connection */
12053 conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
12054
12055 if (conn != NULL) {
12056 i = mg_vprintf(conn, fmt, ap);
12057 if (i <= 0) {
12058 mg_snprintf(conn,
12059 NULL, /* No truncation check for ebuf */
12060 ebuf,
12061 ebuf_len,
12062 "%s",
12063 "Error sending request");
12064 } else {
12065 getreq(conn, ebuf, ebuf_len, &reqerr);
12066
12067 /* TODO: 1) uri is deprecated;
12068 * 2) here, ri.uri is the http response code */
12069 conn->request_info.uri = conn->request_info.request_uri;
12070 }
12071 }
12072
12073 /* if an error occured, close the connection */
12074 if (ebuf[0] != '\0' && conn != NULL) {
12075 mg_close_connection(conn);
12076 conn = NULL;
12077 }
12078
12079 va_end(ap);
12080 return conn;
12081 }
12082
12083
12084 struct websocket_client_thread_data {
12085 struct mg_connection *conn;
12086 mg_websocket_data_handler data_handler;
12087 mg_websocket_close_handler close_handler;
12088 void *callback_data;
12089 };
12090
12091
12092 #if defined(USE_WEBSOCKET)
12093 #ifdef _WIN32
12094 static unsigned __stdcall websocket_client_thread(void *data)
12095 #else
12096 static void *
12097 websocket_client_thread(void *data)
12098 #endif
12099 {
12100 struct websocket_client_thread_data *cdata =
12101 (struct websocket_client_thread_data *)data;
12102
12103 mg_set_thread_name("ws-client");
12104
12105 if (cdata->conn->ctx) {
12106 if (cdata->conn->ctx->callbacks.init_thread) {
12107 /* 3 indicates a websocket client thread */
12108 /* TODO: check if conn->ctx can be set */
12109 cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
12110 }
12111 }
12112
12113 read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
12114
12115 DEBUG_TRACE("%s", "Websocket client thread exited\n");
12116
12117 if (cdata->close_handler != NULL) {
12118 cdata->close_handler(cdata->conn, cdata->callback_data);
12119 }
12120
12121 mg_free((void *)cdata);
12122
12123 #ifdef _WIN32
12124 return 0;
12125 #else
12126 return NULL;
12127 #endif
12128 }
12129 #endif
12130
12131
12132 struct mg_connection *
12133 mg_connect_websocket_client(const char *host,
12134 int port,
12135 int use_ssl,
12136 char *error_buffer,
12137 size_t error_buffer_size,
12138 const char *path,
12139 const char *origin,
12140 mg_websocket_data_handler data_func,
12141 mg_websocket_close_handler close_func,
12142 void *user_data)
12143 {
12144 struct mg_connection *conn = NULL;
12145
12146 #if defined(USE_WEBSOCKET)
12147 struct mg_context *newctx = NULL;
12148 struct websocket_client_thread_data *thread_data;
12149 static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
12150 static const char *handshake_req;
12151
12152 if (origin != NULL) {
12153 handshake_req = "GET %s HTTP/1.1\r\n"
12154 "Host: %s\r\n"
12155 "Upgrade: websocket\r\n"
12156 "Connection: Upgrade\r\n"
12157 "Sec-WebSocket-Key: %s\r\n"
12158 "Sec-WebSocket-Version: 13\r\n"
12159 "Origin: %s\r\n"
12160 "\r\n";
12161 } else {
12162 handshake_req = "GET %s HTTP/1.1\r\n"
12163 "Host: %s\r\n"
12164 "Upgrade: websocket\r\n"
12165 "Connection: Upgrade\r\n"
12166 "Sec-WebSocket-Key: %s\r\n"
12167 "Sec-WebSocket-Version: 13\r\n"
12168 "\r\n";
12169 }
12170
12171 /* Establish the client connection and request upgrade */
12172 conn = mg_download(host,
12173 port,
12174 use_ssl,
12175 error_buffer,
12176 error_buffer_size,
12177 handshake_req,
12178 path,
12179 host,
12180 magic,
12181 origin);
12182
12183 /* Connection object will be null if something goes wrong */
12184 if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) {
12185 if (!*error_buffer) {
12186 /* if there is a connection, but it did not return 101,
12187 * error_buffer is not yet set */
12188 mg_snprintf(conn,
12189 NULL, /* No truncation check for ebuf */
12190 error_buffer,
12191 error_buffer_size,
12192 "Unexpected server reply");
12193 }
12194 DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
12195 if (conn != NULL) {
12196 mg_free(conn);
12197 conn = NULL;
12198 }
12199 return conn;
12200 }
12201
12202 /* For client connections, mg_context is fake. Since we need to set a
12203 * callback function, we need to create a copy and modify it. */
12204 newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
12205 memcpy(newctx, conn->ctx, sizeof(struct mg_context));
12206 newctx->user_data = user_data;
12207 newctx->context_type = 2; /* client context type */
12208 newctx->cfg_worker_threads = 1; /* one worker thread will be created */
12209 newctx->workerthreadids =
12210 (pthread_t *)mg_calloc(newctx->cfg_worker_threads, sizeof(pthread_t));
12211 conn->ctx = newctx;
12212 thread_data = (struct websocket_client_thread_data *)
12213 mg_calloc(sizeof(struct websocket_client_thread_data), 1);
12214 thread_data->conn = conn;
12215 thread_data->data_handler = data_func;
12216 thread_data->close_handler = close_func;
12217 thread_data->callback_data = NULL;
12218
12219 /* Start a thread to read the websocket client connection
12220 * This thread will automatically stop when mg_disconnect is
12221 * called on the client connection */
12222 if (mg_start_thread_with_id(websocket_client_thread,
12223 (void *)thread_data,
12224 newctx->workerthreadids) != 0) {
12225 mg_free((void *)thread_data);
12226 mg_free((void *)newctx->workerthreadids);
12227 mg_free((void *)newctx);
12228 mg_free((void *)conn);
12229 conn = NULL;
12230 DEBUG_TRACE("%s",
12231 "Websocket client connect thread could not be started\r\n");
12232 }
12233 #else
12234 /* Appease "unused parameter" warnings */
12235 (void)host;
12236 (void)port;
12237 (void)use_ssl;
12238 (void)error_buffer;
12239 (void)error_buffer_size;
12240 (void)path;
12241 (void)origin;
12242 (void)user_data;
12243 (void)data_func;
12244 (void)close_func;
12245 #endif
12246
12247 return conn;
12248 }
12249
12250
12251 static void
12252 process_new_connection(struct mg_connection *conn)
12253 {
12254 if (conn && conn->ctx) {
12255 struct mg_request_info *ri = &conn->request_info;
12256 int keep_alive_enabled, keep_alive, discard_len;
12257 char ebuf[100];
12258 const char *hostend;
12259 int reqerr, uri_type;
12260
12261 keep_alive_enabled =
12262 !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
12263
12264 /* Important: on new connection, reset the receiving buffer. Credit
12265 * goes to crule42. */
12266 conn->data_len = 0;
12267 do {
12268 if (!getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
12269 /* The request sent by the client could not be understood by
12270 * the server, or it was incomplete or a timeout. Send an
12271 * error message and close the connection. */
12272 if (reqerr > 0) {
12273 /*assert(ebuf[0] != '\0');*/
12274 send_http_error(conn, reqerr, "%s", ebuf);
12275 }
12276 } else if (strcmp(ri->http_version, "1.0")
12277 && strcmp(ri->http_version, "1.1")) {
12278 mg_snprintf(conn,
12279 NULL, /* No truncation check for ebuf */
12280 ebuf,
12281 sizeof(ebuf),
12282 "Bad HTTP version: [%s]",
12283 ri->http_version);
12284 send_http_error(conn, 505, "%s", ebuf);
12285 }
12286
12287 if (ebuf[0] == '\0') {
12288 uri_type = get_uri_type(conn->request_info.request_uri);
12289 switch (uri_type) {
12290 case 1:
12291 /* Asterisk */
12292 conn->request_info.local_uri = NULL;
12293 break;
12294 case 2:
12295 /* relative uri */
12296 conn->request_info.local_uri =
12297 conn->request_info.request_uri;
12298 break;
12299 case 3:
12300 case 4:
12301 /* absolute uri (with/without port) */
12302 hostend = get_rel_url_at_current_server(
12303 conn->request_info.request_uri, conn);
12304 if (hostend) {
12305 conn->request_info.local_uri = hostend;
12306 } else {
12307 conn->request_info.local_uri = NULL;
12308 }
12309 break;
12310 default:
12311 mg_snprintf(conn,
12312 NULL, /* No truncation check for ebuf */
12313 ebuf,
12314 sizeof(ebuf),
12315 "Invalid URI: [%s]",
12316 ri->request_uri);
12317 send_http_error(conn, 400, "%s", ebuf);
12318 break;
12319 }
12320
12321 /* TODO: cleanup uri, local_uri and request_uri */
12322 conn->request_info.uri = conn->request_info.local_uri;
12323 }
12324
12325 if (ebuf[0] == '\0') {
12326 if (conn->request_info.local_uri) {
12327 /* handle request to local server */
12328 handle_request(conn);
12329 if (conn->ctx->callbacks.end_request != NULL) {
12330 conn->ctx->callbacks.end_request(conn,
12331 conn->status_code);
12332 }
12333 log_access(conn);
12334 } else {
12335 /* TODO: handle non-local request (PROXY) */
12336 conn->must_close = 1;
12337 }
12338 } else {
12339 conn->must_close = 1;
12340 }
12341
12342 if (ri->remote_user != NULL) {
12343 mg_free((void *)ri->remote_user);
12344 /* Important! When having connections with and without auth
12345 * would cause double free and then crash */
12346 ri->remote_user = NULL;
12347 }
12348
12349 /* NOTE(lsm): order is important here. should_keep_alive() call
12350 * is
12351 * using parsed request, which will be invalid after memmove's
12352 * below.
12353 * Therefore, memorize should_keep_alive() result now for later
12354 * use
12355 * in loop exit condition. */
12356 keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled
12357 && conn->content_len >= 0 && should_keep_alive(conn);
12358
12359 /* Discard all buffered data for this request */
12360 discard_len = conn->content_len >= 0 && conn->request_len > 0
12361 && conn->request_len + conn->content_len
12362 < (int64_t)conn->data_len
12363 ? (int)(conn->request_len + conn->content_len)
12364 : conn->data_len;
12365 /*assert(discard_len >= 0);*/
12366 if (discard_len < 0)
12367 break;
12368 conn->data_len -= discard_len;
12369 if (conn->data_len > 0) {
12370 memmove(conn->buf,
12371 conn->buf + discard_len,
12372 (size_t)conn->data_len);
12373 }
12374
12375 /* assert(conn->data_len >= 0); */
12376 /* assert(conn->data_len <= conn->buf_size); */
12377
12378 if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
12379 break;
12380 }
12381
12382 } while (keep_alive);
12383 }
12384 }
12385
12386
12387 /* Worker threads take accepted socket from the queue */
12388 static int
12389 consume_socket(struct mg_context *ctx, struct socket *sp)
12390 {
12391 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12392 if (!ctx) {
12393 return 0;
12394 }
12395
12396 (void)pthread_mutex_lock(&ctx->thread_mutex);
12397 DEBUG_TRACE("%s", "going idle");
12398
12399 /* If the queue is empty, wait. We're idle at this point. */
12400 while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
12401 pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
12402 }
12403
12404 /* If we're stopping, sq_head may be equal to sq_tail. */
12405 if (ctx->sq_head > ctx->sq_tail) {
12406 /* Copy socket from the queue and increment tail */
12407 *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
12408 ctx->sq_tail++;
12409
12410 DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
12411
12412 /* Wrap pointers if needed */
12413 while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
12414 ctx->sq_tail -= QUEUE_SIZE(ctx);
12415 ctx->sq_head -= QUEUE_SIZE(ctx);
12416 }
12417 }
12418
12419 (void)pthread_cond_signal(&ctx->sq_empty);
12420 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12421
12422 return !ctx->stop_flag;
12423 #undef QUEUE_SIZE
12424 }
12425
12426
12427 static void *
12428 worker_thread_run(void *thread_func_param)
12429 {
12430 struct mg_context *ctx = (struct mg_context *)thread_func_param;
12431 struct mg_connection *conn;
12432 struct mg_workerTLS tls;
12433 #if defined(MG_LEGACY_INTERFACE)
12434 uint32_t addr;
12435 #endif
12436
12437 mg_set_thread_name("worker");
12438
12439 tls.is_master = 0;
12440 tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12441 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12442 tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12443 #endif
12444
12445 if (ctx->callbacks.init_thread) {
12446 /* call init_thread for a worker thread (type 1) */
12447 ctx->callbacks.init_thread(ctx, 1);
12448 }
12449
12450 conn =
12451 (struct mg_connection *)mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
12452 if (conn == NULL) {
12453 mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
12454 } else {
12455 pthread_setspecific(sTlsKey, &tls);
12456 conn->buf_size = MAX_REQUEST_SIZE;
12457 conn->buf = (char *)(conn + 1);
12458 conn->ctx = ctx;
12459 conn->request_info.user_data = ctx->user_data;
12460 /* Allocate a mutex for this connection to allow communication both
12461 * within the request handler and from elsewhere in the application
12462 */
12463 (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
12464
12465 /* Call consume_socket() even when ctx->stop_flag > 0, to let it
12466 * signal sq_empty condvar to wake up the master waiting in
12467 * produce_socket() */
12468 while (consume_socket(ctx, &conn->client)) {
12469 conn->conn_birth_time = time(NULL);
12470
12471 /* Fill in IP, port info early so even if SSL setup below fails,
12472 * error handler would have the corresponding info.
12473 * Thanks to Johannes Winkelmann for the patch.
12474 */
12475 #if defined(USE_IPV6)
12476 if (conn->client.rsa.sa.sa_family == AF_INET6) {
12477 conn->request_info.remote_port =
12478 ntohs(conn->client.rsa.sin6.sin6_port);
12479 } else
12480 #endif
12481 {
12482 conn->request_info.remote_port =
12483 ntohs(conn->client.rsa.sin.sin_port);
12484 }
12485
12486 sockaddr_to_string(conn->request_info.remote_addr,
12487 sizeof(conn->request_info.remote_addr),
12488 &conn->client.rsa);
12489
12490 #if defined(MG_LEGACY_INTERFACE)
12491 /* This legacy interface only works for the IPv4 case */
12492 addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
12493 memcpy(&conn->request_info.remote_ip, &addr, 4);
12494 #endif
12495
12496 conn->request_info.is_ssl = conn->client.is_ssl;
12497
12498 if (!conn->client.is_ssl
12499 #ifndef NO_SSL
12500 || sslize(conn, conn->ctx->ssl_ctx, SSL_accept)
12501 #endif
12502 ) {
12503
12504
12505 process_new_connection(conn);
12506 }
12507
12508 close_connection(conn);
12509 }
12510 }
12511
12512 /* Signal master that we're done with connection and exiting */
12513 (void)pthread_mutex_lock(&ctx->thread_mutex);
12514 ctx->running_worker_threads--;
12515 (void)pthread_cond_signal(&ctx->thread_cond);
12516 /* assert(ctx->running_worker_threads >= 0); */
12517 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12518
12519 pthread_setspecific(sTlsKey, NULL);
12520 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12521 CloseHandle(tls.pthread_cond_helper_mutex);
12522 #endif
12523 pthread_mutex_destroy(&conn->mutex);
12524 mg_free(conn);
12525
12526 DEBUG_TRACE("%s", "exiting");
12527 return NULL;
12528 }
12529
12530
12531 /* Threads have different return types on Windows and Unix. */
12532 #ifdef _WIN32
12533 static unsigned __stdcall worker_thread(void *thread_func_param)
12534 {
12535 worker_thread_run(thread_func_param);
12536 return 0;
12537 }
12538 #else
12539 static void *
12540 worker_thread(void *thread_func_param)
12541 {
12542 worker_thread_run(thread_func_param);
12543 return NULL;
12544 }
12545 #endif /* _WIN32 */
12546
12547
12548 /* Master thread adds accepted socket to a queue */
12549 static void
12550 produce_socket(struct mg_context *ctx, const struct socket *sp)
12551 {
12552 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12553 if (!ctx) {
12554 return;
12555 }
12556 (void)pthread_mutex_lock(&ctx->thread_mutex);
12557
12558 /* If the queue is full, wait */
12559 while (ctx->stop_flag == 0
12560 && ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
12561 (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
12562 }
12563
12564 if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
12565 /* Copy socket to the queue and increment head */
12566 ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
12567 ctx->sq_head++;
12568 DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
12569 }
12570
12571 (void)pthread_cond_signal(&ctx->sq_full);
12572 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12573 #undef QUEUE_SIZE
12574 }
12575
12576
12577 static void
12578 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
12579 {
12580 struct socket so;
12581 char src_addr[IP_ADDR_STR_LEN];
12582 socklen_t len = sizeof(so.rsa);
12583 int on = 1;
12584 int timeout;
12585
12586 if (!listener) {
12587 return;
12588 }
12589
12590 if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
12591 == INVALID_SOCKET) {
12592 } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
12593 sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
12594 mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
12595 closesocket(so.sock);
12596 so.sock = INVALID_SOCKET;
12597 } else {
12598 /* Put so socket structure into the queue */
12599 DEBUG_TRACE("Accepted socket %d", (int)so.sock);
12600 set_close_on_exec(so.sock, fc(ctx));
12601 so.is_ssl = listener->is_ssl;
12602 so.ssl_redir = listener->ssl_redir;
12603 if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
12604 mg_cry(fc(ctx),
12605 "%s: getsockname() failed: %s",
12606 __func__,
12607 strerror(ERRNO));
12608 }
12609
12610 /* Set TCP keep-alive. This is needed because if HTTP-level
12611 * keep-alive
12612 * is enabled, and client resets the connection, server won't get
12613 * TCP FIN or RST and will keep the connection open forever. With
12614 * TCP keep-alive, next keep-alive handshake will figure out that
12615 * the client is down and will close the server end.
12616 * Thanks to Igor Klopov who suggested the patch. */
12617 if (setsockopt(so.sock,
12618 SOL_SOCKET,
12619 SO_KEEPALIVE,
12620 (SOCK_OPT_TYPE)&on,
12621 sizeof(on)) != 0) {
12622 mg_cry(fc(ctx),
12623 "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
12624 __func__,
12625 strerror(ERRNO));
12626 }
12627
12628
12629 /* Disable TCP Nagle's algorithm. Normally TCP packets are
12630 * coalesced
12631 * to effectively fill up the underlying IP packet payload and
12632 * reduce
12633 * the overhead of sending lots of small buffers. However this hurts
12634 * the server's throughput (ie. operations per second) when HTTP 1.1
12635 * persistent connections are used and the responses are relatively
12636 * small (eg. less than 1400 bytes).
12637 */
12638 if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
12639 && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
12640 if (set_tcp_nodelay(so.sock, 1) != 0) {
12641 mg_cry(fc(ctx),
12642 "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
12643 __func__,
12644 strerror(ERRNO));
12645 }
12646 }
12647
12648 if (ctx && ctx->config[REQUEST_TIMEOUT]) {
12649 timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
12650 } else {
12651 timeout = -1;
12652 }
12653
12654 /* Set socket timeout to the given value, but not more than a
12655 * a certain limit (SOCKET_TIMEOUT_QUANTUM, default 10 seconds),
12656 * so the server can exit after that time if requested. */
12657 if ((timeout > 0) && (timeout < SOCKET_TIMEOUT_QUANTUM)) {
12658 set_sock_timeout(so.sock, timeout);
12659 } else {
12660 set_sock_timeout(so.sock, SOCKET_TIMEOUT_QUANTUM);
12661 }
12662
12663 produce_socket(ctx, &so);
12664 }
12665 }
12666
12667
12668 static void
12669 master_thread_run(void *thread_func_param)
12670 {
12671 struct mg_context *ctx = (struct mg_context *)thread_func_param;
12672 struct mg_workerTLS tls;
12673 struct pollfd *pfd;
12674 unsigned int i;
12675 unsigned int workerthreadcount;
12676
12677 if (!ctx) {
12678 return;
12679 }
12680
12681 mg_set_thread_name("master");
12682
12683 /* Increase priority of the master thread */
12684 #if defined(_WIN32)
12685 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
12686 #elif defined(USE_MASTER_THREAD_PRIORITY)
12687 int min_prio = sched_get_priority_min(SCHED_RR);
12688 int max_prio = sched_get_priority_max(SCHED_RR);
12689 if ((min_prio >= 0) && (max_prio >= 0)
12690 && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
12691 && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
12692 struct sched_param sched_param = {0};
12693 sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
12694 pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
12695 }
12696 #endif
12697
12698 /* Initialize thread local storage */
12699 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12700 tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12701 #endif
12702 tls.is_master = 1;
12703 pthread_setspecific(sTlsKey, &tls);
12704
12705 if (ctx->callbacks.init_thread) {
12706 /* Callback for the master thread (type 0) */
12707 ctx->callbacks.init_thread(ctx, 0);
12708 }
12709
12710 /* Server starts *now* */
12711 ctx->start_time = time(NULL);
12712
12713 /* Allocate memory for the listening sockets, and start the server */
12714 pfd =
12715 (struct pollfd *)mg_calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
12716 while (pfd != NULL && ctx->stop_flag == 0) {
12717 for (i = 0; i < ctx->num_listening_sockets; i++) {
12718 pfd[i].fd = ctx->listening_sockets[i].sock;
12719 pfd[i].events = POLLIN;
12720 }
12721
12722 if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
12723 for (i = 0; i < ctx->num_listening_sockets; i++) {
12724 /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
12725 * successful poll, and POLLIN is defined as
12726 * (POLLRDNORM | POLLRDBAND)
12727 * Therefore, we're checking pfd[i].revents & POLLIN, not
12728 * pfd[i].revents == POLLIN. */
12729 if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
12730 accept_new_connection(&ctx->listening_sockets[i], ctx);
12731 }
12732 }
12733 }
12734 }
12735 mg_free(pfd);
12736 DEBUG_TRACE("%s", "stopping workers");
12737
12738 /* Stop signal received: somebody called mg_stop. Quit. */
12739 close_all_listening_sockets(ctx);
12740
12741 /* Wakeup workers that are waiting for connections to handle. */
12742 pthread_cond_broadcast(&ctx->sq_full);
12743
12744 /* Wait until all threads finish */
12745 (void)pthread_mutex_lock(&ctx->thread_mutex);
12746 while (ctx->running_worker_threads > 0) {
12747 (void)pthread_cond_wait(&ctx->thread_cond, &ctx->thread_mutex);
12748 }
12749 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12750
12751 /* Join all worker threads to avoid leaking threads. */
12752 workerthreadcount = ctx->cfg_worker_threads;
12753 for (i = 0; i < workerthreadcount; i++) {
12754 if (ctx->workerthreadids[i] != 0) {
12755 mg_join_thread(ctx->workerthreadids[i]);
12756 }
12757 }
12758
12759 #if !defined(NO_SSL)
12760 if (ctx->ssl_ctx != NULL) {
12761 uninitialize_ssl(ctx);
12762 }
12763 #endif
12764 DEBUG_TRACE("%s", "exiting");
12765
12766 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12767 CloseHandle(tls.pthread_cond_helper_mutex);
12768 #endif
12769 pthread_setspecific(sTlsKey, NULL);
12770
12771 /* Signal mg_stop() that we're done.
12772 * WARNING: This must be the very last thing this
12773 * thread does, as ctx becomes invalid after this line. */
12774 ctx->stop_flag = 2;
12775 }
12776
12777
12778 /* Threads have different return types on Windows and Unix. */
12779 #ifdef _WIN32
12780 static unsigned __stdcall master_thread(void *thread_func_param)
12781 {
12782 master_thread_run(thread_func_param);
12783 return 0;
12784 }
12785 #else
12786 static void *
12787 master_thread(void *thread_func_param)
12788 {
12789 master_thread_run(thread_func_param);
12790 return NULL;
12791 }
12792 #endif /* _WIN32 */
12793
12794
12795 static void
12796 free_context(struct mg_context *ctx)
12797 {
12798 int i;
12799 struct mg_handler_info *tmp_rh;
12800
12801 if (ctx == NULL) {
12802 return;
12803 }
12804
12805 if (ctx->callbacks.exit_context) {
12806 ctx->callbacks.exit_context(ctx);
12807 }
12808
12809 /* All threads exited, no sync is needed. Destroy thread mutex and
12810 * condvars
12811 */
12812 (void)pthread_mutex_destroy(&ctx->thread_mutex);
12813 (void)pthread_cond_destroy(&ctx->thread_cond);
12814 (void)pthread_cond_destroy(&ctx->sq_empty);
12815 (void)pthread_cond_destroy(&ctx->sq_full);
12816
12817 /* Destroy other context global data structures mutex */
12818 (void)pthread_mutex_destroy(&ctx->nonce_mutex);
12819
12820 #if defined(USE_TIMERS)
12821 timers_exit(ctx);
12822 #endif
12823
12824 /* Deallocate config parameters */
12825 for (i = 0; i < NUM_OPTIONS; i++) {
12826 if (ctx->config[i] != NULL) {
12827 #if defined(_MSC_VER)
12828 #pragma warning(suppress : 6001)
12829 #endif
12830 mg_free(ctx->config[i]);
12831 }
12832 }
12833
12834 /* Deallocate request handlers */
12835 while (ctx->handlers) {
12836 tmp_rh = ctx->handlers;
12837 ctx->handlers = tmp_rh->next;
12838 mg_free(tmp_rh->uri);
12839 mg_free(tmp_rh);
12840 }
12841
12842 #ifndef NO_SSL
12843 /* Deallocate SSL context */
12844 if (ctx->ssl_ctx != NULL) {
12845 SSL_CTX_free(ctx->ssl_ctx);
12846 }
12847 #endif /* !NO_SSL */
12848
12849 /* Deallocate worker thread ID array */
12850 if (ctx->workerthreadids != NULL) {
12851 mg_free(ctx->workerthreadids);
12852 }
12853
12854 /* Deallocate the tls variable */
12855 if (mg_atomic_dec(&sTlsInit) == 0) {
12856 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12857 DeleteCriticalSection(&global_log_file_lock);
12858 #endif /* _WIN32 && !__SYMBIAN32__ */
12859 #if !defined(_WIN32)
12860 pthread_mutexattr_destroy(&pthread_mutex_attr);
12861 #endif
12862
12863 pthread_key_delete(sTlsKey);
12864 }
12865
12866 /* deallocate system name string */
12867 mg_free(ctx->systemName);
12868
12869 /* Deallocate context itself */
12870 mg_free(ctx);
12871 }
12872
12873
12874 void
12875 mg_stop(struct mg_context *ctx)
12876 {
12877 pthread_t mt;
12878 if (!ctx) {
12879 return;
12880 }
12881
12882 /* We don't use a lock here. Calling mg_stop with the same ctx from
12883 * two threads is not allowed. */
12884 mt = ctx->masterthreadid;
12885 if (mt == 0) {
12886 return;
12887 }
12888
12889 ctx->masterthreadid = 0;
12890 ctx->stop_flag = 1;
12891
12892 /* Wait until mg_fini() stops */
12893 while (ctx->stop_flag != 2) {
12894 (void)mg_sleep(10);
12895 }
12896
12897 mg_join_thread(mt);
12898 free_context(ctx);
12899
12900 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12901 (void)WSACleanup();
12902 #endif /* _WIN32 && !__SYMBIAN32__ */
12903 }
12904
12905
12906 static void
12907 get_system_name(char **sysName)
12908 {
12909 #if defined(_WIN32)
12910 #if !defined(__SYMBIAN32__)
12911 char name[128];
12912 DWORD dwVersion = 0;
12913 DWORD dwMajorVersion = 0;
12914 DWORD dwMinorVersion = 0;
12915 DWORD dwBuild = 0;
12916
12917 #ifdef _MSC_VER
12918 #pragma warning(push)
12919 // GetVersion was declared deprecated
12920 #pragma warning(disable : 4996)
12921 #endif
12922 dwVersion = GetVersion();
12923 #ifdef _MSC_VER
12924 #pragma warning(pop)
12925 #endif
12926
12927 dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12928 dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
12929 dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
12930 (void)dwBuild;
12931
12932 sprintf(name,
12933 "Windows %u.%u",
12934 (unsigned)dwMajorVersion,
12935 (unsigned)dwMinorVersion);
12936 *sysName = mg_strdup(name);
12937 #else
12938 *sysName = mg_strdup("Symbian");
12939 #endif
12940 #else
12941 struct utsname name;
12942 memset(&name, 0, sizeof(name));
12943 uname(&name);
12944 *sysName = mg_strdup(name.sysname);
12945 #endif
12946 }
12947
12948
12949 struct mg_context *
12950 mg_start(const struct mg_callbacks *callbacks,
12951 void *user_data,
12952 const char **options)
12953 {
12954 struct mg_context *ctx;
12955 const char *name, *value, *default_value;
12956 int idx, ok, workerthreadcount;
12957 unsigned int i;
12958 void (*exit_callback)(const struct mg_context *ctx) = 0;
12959
12960 struct mg_workerTLS tls;
12961
12962 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12963 WSADATA data;
12964 WSAStartup(MAKEWORD(2, 2), &data);
12965 #endif /* _WIN32 && !__SYMBIAN32__ */
12966
12967 /* Allocate context and initialize reasonable general case defaults. */
12968 if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
12969 return NULL;
12970 }
12971
12972 /* Random number generator will initialize at the first call */
12973 ctx->auth_nonce_mask =
12974 (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
12975
12976 if (mg_atomic_inc(&sTlsInit) == 1) {
12977
12978 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12979 InitializeCriticalSection(&global_log_file_lock);
12980 #endif /* _WIN32 && !__SYMBIAN32__ */
12981 #if !defined(_WIN32)
12982 pthread_mutexattr_init(&pthread_mutex_attr);
12983 pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
12984 #endif
12985
12986 if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
12987 /* Fatal error - abort start. However, this situation should
12988 * never
12989 * occur in practice. */
12990 mg_atomic_dec(&sTlsInit);
12991 mg_cry(fc(ctx), "Cannot initialize thread local storage");
12992 mg_free(ctx);
12993 return NULL;
12994 }
12995 } else {
12996 /* TODO (low): istead of sleeping, check if sTlsKey is already
12997 * initialized. */
12998 mg_sleep(1);
12999 }
13000
13001 tls.is_master = -1;
13002 tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
13003 #if defined(_WIN32) && !defined(__SYMBIAN32__)
13004 tls.pthread_cond_helper_mutex = NULL;
13005 #endif
13006 pthread_setspecific(sTlsKey, &tls);
13007
13008 #if defined(USE_LUA)
13009 lua_init_optional_libraries();
13010 #endif
13011
13012 ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
13013 ok &= 0 == pthread_cond_init(&ctx->thread_cond, NULL);
13014 ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
13015 ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
13016 ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
13017 if (!ok) {
13018 /* Fatal error - abort start. However, this situation should never
13019 * occur in practice. */
13020 mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
13021 mg_free(ctx);
13022 pthread_setspecific(sTlsKey, NULL);
13023 return NULL;
13024 }
13025
13026 if (callbacks) {
13027 ctx->callbacks = *callbacks;
13028 exit_callback = callbacks->exit_context;
13029 ctx->callbacks.exit_context = 0;
13030 }
13031 ctx->user_data = user_data;
13032 ctx->handlers = NULL;
13033
13034 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
13035 ctx->shared_lua_websockets = 0;
13036 #endif
13037
13038 while (options && (name = *options++) != NULL) {
13039 if ((idx = get_option_index(name)) == -1) {
13040 mg_cry(fc(ctx), "Invalid option: %s", name);
13041 free_context(ctx);
13042 pthread_setspecific(sTlsKey, NULL);
13043 return NULL;
13044 } else if ((value = *options++) == NULL) {
13045 mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
13046 free_context(ctx);
13047 pthread_setspecific(sTlsKey, NULL);
13048 return NULL;
13049 }
13050 if (ctx->config[idx] != NULL) {
13051 mg_cry(fc(ctx), "warning: %s: duplicate option", name);
13052 mg_free(ctx->config[idx]);
13053 }
13054 ctx->config[idx] = mg_strdup(value);
13055 DEBUG_TRACE("[%s] -> [%s]", name, value);
13056 }
13057
13058 /* Set default value if needed */
13059 for (i = 0; config_options[i].name != NULL; i++) {
13060 default_value = config_options[i].default_value;
13061 if (ctx->config[i] == NULL && default_value != NULL) {
13062 ctx->config[i] = mg_strdup(default_value);
13063 }
13064 }
13065
13066 #if defined(NO_FILES)
13067 if (ctx->config[DOCUMENT_ROOT] != NULL) {
13068 mg_cry(fc(ctx), "%s", "Document root must not be set");
13069 free_context(ctx);
13070 pthread_setspecific(sTlsKey, NULL);
13071 return NULL;
13072 }
13073 #endif
13074
13075 get_system_name(&ctx->systemName);
13076
13077 /* NOTE(lsm): order is important here. SSL certificates must
13078 * be initialized before listening ports. UID must be set last. */
13079 if (!set_gpass_option(ctx) ||
13080 #if !defined(NO_SSL)
13081 !set_ssl_option(ctx) ||
13082 #endif
13083 !set_ports_option(ctx) ||
13084 #if !defined(_WIN32)
13085 !set_uid_option(ctx) ||
13086 #endif
13087 !set_acl_option(ctx)) {
13088 free_context(ctx);
13089 pthread_setspecific(sTlsKey, NULL);
13090 return NULL;
13091 }
13092
13093 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
13094 /* Ignore SIGPIPE signal, so if browser cancels the request, it
13095 * won't kill the whole process. */
13096 (void)signal(SIGPIPE, SIG_IGN);
13097 #endif /* !_WIN32 && !__SYMBIAN32__ */
13098
13099 workerthreadcount = atoi(ctx->config[NUM_THREADS]);
13100
13101 if (workerthreadcount > MAX_WORKER_THREADS) {
13102 mg_cry(fc(ctx), "Too many worker threads");
13103 free_context(ctx);
13104 pthread_setspecific(sTlsKey, NULL);
13105 return NULL;
13106 }
13107
13108 if (workerthreadcount > 0) {
13109 ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
13110 ctx->workerthreadids =
13111 (pthread_t *)mg_calloc(ctx->cfg_worker_threads, sizeof(pthread_t));
13112 if (ctx->workerthreadids == NULL) {
13113 mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
13114 free_context(ctx);
13115 pthread_setspecific(sTlsKey, NULL);
13116 return NULL;
13117 }
13118 }
13119
13120 #if defined(USE_TIMERS)
13121 if (timers_init(ctx) != 0) {
13122 mg_cry(fc(ctx), "Error creating timers");
13123 free_context(ctx);
13124 pthread_setspecific(sTlsKey, NULL);
13125 return NULL;
13126 }
13127 #endif
13128
13129 /* Context has been created - init user libraries */
13130 if (ctx->callbacks.init_context) {
13131 ctx->callbacks.init_context(ctx);
13132 }
13133 ctx->callbacks.exit_context = exit_callback;
13134 ctx->context_type = 1; /* server context */
13135
13136 /* Start master (listening) thread */
13137 mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
13138
13139 /* Start worker threads */
13140 for (i = 0; i < ctx->cfg_worker_threads; i++) {
13141 (void)pthread_mutex_lock(&ctx->thread_mutex);
13142 ctx->running_worker_threads++;
13143 (void)pthread_mutex_unlock(&ctx->thread_mutex);
13144 if (mg_start_thread_with_id(worker_thread,
13145 ctx,
13146 &ctx->workerthreadids[i]) != 0) {
13147 (void)pthread_mutex_lock(&ctx->thread_mutex);
13148 ctx->running_worker_threads--;
13149 (void)pthread_mutex_unlock(&ctx->thread_mutex);
13150 if (i > 0) {
13151 mg_cry(fc(ctx),
13152 "Cannot start worker thread %i: error %ld",
13153 i + 1,
13154 (long)ERRNO);
13155 } else {
13156 mg_cry(fc(ctx),
13157 "Cannot create threads: error %ld",
13158 (long)ERRNO);
13159 free_context(ctx);
13160 pthread_setspecific(sTlsKey, NULL);
13161 return NULL;
13162 }
13163 break;
13164 }
13165 }
13166
13167 pthread_setspecific(sTlsKey, NULL);
13168 return ctx;
13169 }
13170
13171
13172 /* Feature check API function */
13173 unsigned
13174 mg_check_feature(unsigned feature)
13175 {
13176 static const unsigned feature_set = 0
13177 /* Set bits for available features according to API documentation.
13178 * This bit mask is created at compile time, according to the active
13179 * preprocessor defines. It is a single const value at runtime. */
13180 #if !defined(NO_FILES)
13181 | 0x0001u
13182 #endif
13183 #if !defined(NO_SSL)
13184 | 0x0002u
13185 #endif
13186 #if !defined(NO_CGI)
13187 | 0x0004u
13188 #endif
13189 #if defined(USE_IPV6)
13190 | 0x0008u
13191 #endif
13192 #if defined(USE_WEBSOCKET)
13193 | 0x0010u
13194 #endif
13195 #if defined(USE_LUA)
13196 | 0x0020u
13197 #endif
13198 #if defined(USE_DUKTAPE)
13199 | 0x0040u
13200 #endif
13201 #if !defined(NO_CACHING)
13202 | 0x0080u
13203 #endif
13204
13205 /* Set some extra bits not defined in the API documentation.
13206 * These bits may change without further notice. */
13207 #if defined(MG_LEGACY_INTERFACE)
13208 | 0x8000u
13209 #endif
13210 #if defined(MEMORY_DEBUGGING)
13211 | 0x0100u
13212 #endif
13213 #if defined(USE_TIMERS)
13214 | 0x0200u
13215 #endif
13216 #if !defined(NO_NONCE_CHECK)
13217 | 0x0400u
13218 #endif
13219 #if !defined(NO_POPEN)
13220 | 0x0800u
13221 #endif
13222 ;
13223 return (feature & feature_set);
13224 }