]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/civetweb.c
add subtree-ish sources for 12.0.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 SSI_EXTENSIONS,
1074 THROTTLE,
1075 ACCESS_LOG_FILE,
1076 ENABLE_DIRECTORY_LISTING,
1077 ERROR_LOG_FILE,
1078 GLOBAL_PASSWORDS_FILE,
1079 INDEX_FILES,
1080 ENABLE_KEEP_ALIVE,
1081 ACCESS_CONTROL_LIST,
1082 EXTRA_MIME_TYPES,
1083 LISTENING_PORTS,
1084 DOCUMENT_ROOT,
1085 SSL_CERTIFICATE,
1086 NUM_THREADS,
1087 RUN_AS_USER,
1088 REWRITE,
1089 HIDE_FILES,
1090 REQUEST_TIMEOUT,
1091 SSL_DO_VERIFY_PEER,
1092 SSL_CA_PATH,
1093 SSL_CA_FILE,
1094 SSL_VERIFY_DEPTH,
1095 SSL_DEFAULT_VERIFY_PATHS,
1096 SSL_CIPHER_LIST,
1097 SSL_PROTOCOL_VERSION,
1098 SSL_SHORT_TRUST,
1099 #if defined(USE_WEBSOCKET)
1100 WEBSOCKET_TIMEOUT,
1101 #endif
1102 DECODE_URL,
1103
1104 #if defined(USE_LUA)
1105 LUA_PRELOAD_FILE,
1106 LUA_SCRIPT_EXTENSIONS,
1107 LUA_SERVER_PAGE_EXTENSIONS,
1108 #endif
1109 #if defined(USE_DUKTAPE)
1110 DUKTAPE_SCRIPT_EXTENSIONS,
1111 #endif
1112
1113 #if defined(USE_WEBSOCKET)
1114 WEBSOCKET_ROOT,
1115 #endif
1116 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1117 LUA_WEBSOCKET_EXTENSIONS,
1118 #endif
1119 ACCESS_CONTROL_ALLOW_ORIGIN,
1120 ERROR_PAGES,
1121 CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
1122 * socket option typedef TCP_NODELAY. */
1123 #if !defined(NO_CACHING)
1124 STATIC_FILE_MAX_AGE,
1125 #endif
1126 VALIDATE_HTTP_METHOD,
1127 CANONICALIZE_URL_PATH,
1128
1129 NUM_OPTIONS
1130 };
1131
1132
1133 /* Config option name, config types, default value */
1134 static struct mg_option config_options[] = {
1135 {"cgi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
1136 {"cgi_environment", CONFIG_TYPE_STRING, NULL},
1137 {"put_delete_auth_file", CONFIG_TYPE_FILE, NULL},
1138 {"cgi_interpreter", CONFIG_TYPE_FILE, NULL},
1139 {"protect_uri", CONFIG_TYPE_STRING, NULL},
1140 {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"},
1141 {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
1142 {"throttle", CONFIG_TYPE_STRING, NULL},
1143 {"access_log_file", CONFIG_TYPE_FILE, NULL},
1144 {"enable_directory_listing", CONFIG_TYPE_BOOLEAN, "yes"},
1145 {"error_log_file", CONFIG_TYPE_FILE, NULL},
1146 {"global_auth_file", CONFIG_TYPE_FILE, NULL},
1147 {"index_files",
1148 CONFIG_TYPE_STRING,
1149 #ifdef USE_LUA
1150 "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,"
1151 "index.shtml,index.php"},
1152 #else
1153 "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
1154 #endif
1155 {"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
1156 {"access_control_list", CONFIG_TYPE_STRING, NULL},
1157 {"extra_mime_types", CONFIG_TYPE_STRING, NULL},
1158 {"listening_ports", CONFIG_TYPE_STRING, "8080"},
1159 {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
1160 {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
1161 {"num_threads", CONFIG_TYPE_NUMBER, "50"},
1162 {"run_as_user", CONFIG_TYPE_STRING, NULL},
1163 {"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
1164 {"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
1165 {"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1166 {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
1167 {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
1168 {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
1169 {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
1170 {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
1171 {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
1172 {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
1173 {"ssl_short_trust", CONFIG_TYPE_BOOLEAN, "no"},
1174 #if defined(USE_WEBSOCKET)
1175 {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1176 #endif
1177 {"decode_url", CONFIG_TYPE_BOOLEAN, "yes"},
1178
1179 #if defined(USE_LUA)
1180 {"lua_preload_file", CONFIG_TYPE_FILE, NULL},
1181 {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1182 {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
1183 #endif
1184 #if defined(USE_DUKTAPE)
1185 /* The support for duktape is still in alpha version state.
1186 * The name of this config option might change. */
1187 {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
1188 #endif
1189
1190 #if defined(USE_WEBSOCKET)
1191 {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL},
1192 #endif
1193 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1194 {"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1195 #endif
1196 {"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
1197 {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
1198 {"tcp_nodelay", CONFIG_TYPE_NUMBER, "0"},
1199 #if !defined(NO_CACHING)
1200 {"static_file_max_age", CONFIG_TYPE_NUMBER, "3600"},
1201 #endif
1202 {"validate_http_method", CONFIG_TYPE_BOOLEAN, "yes"},
1203 {"canonicalize_url_path", CONFIG_TYPE_BOOLEAN, "yes"},
1204
1205 {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
1206
1207 /* Check if the config_options and the corresponding enum have compatible
1208 * sizes. */
1209 mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
1210 == (NUM_OPTIONS + 1),
1211 "config_options and enum not sync");
1212
1213 enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
1214
1215 struct mg_handler_info {
1216 /* Name/Pattern of the URI. */
1217 char *uri;
1218 size_t uri_len;
1219
1220 /* handler type */
1221 int handler_type;
1222
1223 /* Handler for http/https or authorization requests. */
1224 mg_request_handler handler;
1225
1226 /* Handler for ws/wss (websocket) requests. */
1227 mg_websocket_connect_handler connect_handler;
1228 mg_websocket_ready_handler ready_handler;
1229 mg_websocket_data_handler data_handler;
1230 mg_websocket_close_handler close_handler;
1231
1232 /* Handler for authorization requests */
1233 mg_authorization_handler auth_handler;
1234
1235 /* User supplied argument for the handler function. */
1236 void *cbdata;
1237
1238 /* next handler in a linked list */
1239 struct mg_handler_info *next;
1240 };
1241
1242 struct mg_context {
1243 volatile int stop_flag; /* Should we stop event loop */
1244 SSL_CTX *ssl_ctx; /* SSL context */
1245 char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
1246 struct mg_callbacks callbacks; /* User-defined callback function */
1247 void *user_data; /* User-defined data */
1248 int context_type; /* 1 = server context, 2 = client context */
1249
1250 struct socket *listening_sockets;
1251 in_port_t *listening_ports;
1252 unsigned int num_listening_sockets;
1253
1254 volatile int
1255 running_worker_threads; /* Number of currently running worker threads */
1256 pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
1257 pthread_cond_t thread_cond; /* Condvar for tracking workers terminations */
1258
1259 struct socket queue[MGSQLEN]; /* Accepted sockets */
1260 volatile int sq_head; /* Head of the socket queue */
1261 volatile int sq_tail; /* Tail of the socket queue */
1262 pthread_cond_t sq_full; /* Signaled when socket is produced */
1263 pthread_cond_t sq_empty; /* Signaled when socket is consumed */
1264 pthread_t masterthreadid; /* The master thread ID */
1265 unsigned int
1266 cfg_worker_threads; /* The number of configured worker threads. */
1267 pthread_t *workerthreadids; /* The worker thread IDs */
1268
1269 time_t start_time; /* Server start time, used for authentication */
1270 uint64_t auth_nonce_mask; /* Mask for all nonce values */
1271 pthread_mutex_t nonce_mutex; /* Protects nonce_count */
1272 unsigned long nonce_count; /* Used nonces, used for authentication */
1273
1274 char *systemName; /* What operating system is running */
1275
1276 /* linked list of uri handlers */
1277 struct mg_handler_info *handlers;
1278
1279 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1280 /* linked list of shared lua websockets */
1281 struct mg_shared_lua_websocket_list *shared_lua_websockets;
1282 #endif
1283
1284 #ifdef USE_TIMERS
1285 struct ttimers *timers;
1286 #endif
1287 };
1288
1289
1290 struct mg_connection {
1291 struct mg_request_info request_info;
1292 struct mg_context *ctx;
1293 SSL *ssl; /* SSL descriptor */
1294 SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
1295 struct socket client; /* Connected client */
1296 time_t conn_birth_time; /* Time (wall clock) when connection was
1297 * established */
1298 struct timespec req_time; /* Time (since system start) when the request
1299 * was received */
1300 int64_t num_bytes_sent; /* Total bytes sent to client */
1301 int64_t content_len; /* Content-Length header value */
1302 int64_t consumed_content; /* How many bytes of content have been read */
1303 int is_chunked; /* Transfer-Encoding is chunked: 0=no, 1=yes:
1304 * data available, 2: all data read */
1305 size_t chunk_remainder; /* Unread data from the last chunk */
1306 char *buf; /* Buffer for received data */
1307 char *path_info; /* PATH_INFO part of the URL */
1308
1309 int must_close; /* 1 if connection must be closed */
1310 int in_error_handler; /* 1 if in handler for user defined error
1311 * pages */
1312 int internal_error; /* 1 if an error occured while processing the
1313 * request */
1314
1315 int buf_size; /* Buffer size */
1316 int request_len; /* Size of the request + headers in a buffer */
1317 int data_len; /* Total size of data in a buffer */
1318 int status_code; /* HTTP reply status code, e.g. 200 */
1319 int throttle; /* Throttling, bytes/sec. <= 0 means no
1320 * throttle */
1321 time_t last_throttle_time; /* Last time throttled data was sent */
1322 int64_t last_throttle_bytes; /* Bytes sent this second */
1323 pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
1324 * atomic transmissions for websockets */
1325 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
1326 void *lua_websocket_state; /* Lua_State for a websocket connection */
1327 #endif
1328 };
1329
1330
1331 static pthread_key_t sTlsKey; /* Thread local storage index */
1332 static int sTlsInit = 0;
1333 static int thread_idx_max = 0;
1334
1335
1336 struct mg_workerTLS {
1337 int is_master;
1338 unsigned long thread_idx;
1339 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1340 HANDLE pthread_cond_helper_mutex;
1341 #endif
1342 };
1343
1344 /* Directory entry */
1345 struct de {
1346 struct mg_connection *conn;
1347 char *file_name;
1348 struct file file;
1349 };
1350
1351
1352 #if defined(USE_WEBSOCKET)
1353 static int is_websocket_protocol(const struct mg_connection *conn);
1354 #else
1355 #define is_websocket_protocol(conn) (0)
1356 #endif
1357
1358
1359 static int
1360 mg_atomic_inc(volatile int *addr)
1361 {
1362 int ret;
1363 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1364 /* Depending on the SDK, this function uses either
1365 * (volatile unsigned int *) or (volatile LONG *),
1366 * so whatever you use, the other SDK is likely to raise a warning. */
1367 ret = InterlockedIncrement((volatile long *)addr);
1368 #elif defined(__GNUC__) \
1369 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1370 ret = __sync_add_and_fetch(addr, 1);
1371 #else
1372 ret = (++(*addr));
1373 #endif
1374 return ret;
1375 }
1376
1377
1378 static int
1379 mg_atomic_dec(volatile int *addr)
1380 {
1381 int ret;
1382 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1383 /* Depending on the SDK, this function uses either
1384 * (volatile unsigned int *) or (volatile LONG *),
1385 * so whatever you use, the other SDK is likely to raise a warning. */
1386 ret = InterlockedDecrement((volatile long *)addr);
1387 #elif defined(__GNUC__) \
1388 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1389 ret = __sync_sub_and_fetch(addr, 1);
1390 #else
1391 ret = (--(*addr));
1392 #endif
1393 return ret;
1394 }
1395
1396 #if !defined(NO_THREAD_NAME)
1397 #if defined(_WIN32) && defined(_MSC_VER)
1398 /* Set the thread name for debugging purposes in Visual Studio
1399 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
1400 */
1401 #pragma pack(push, 8)
1402 typedef struct tagTHREADNAME_INFO {
1403 DWORD dwType; /* Must be 0x1000. */
1404 LPCSTR szName; /* Pointer to name (in user addr space). */
1405 DWORD dwThreadID; /* Thread ID (-1=caller thread). */
1406 DWORD dwFlags; /* Reserved for future use, must be zero. */
1407 } THREADNAME_INFO;
1408 #pragma pack(pop)
1409 #elif defined(__linux__)
1410 #include <sys/prctl.h>
1411 #include <sys/sendfile.h>
1412 #endif
1413
1414
1415 static void
1416 mg_set_thread_name(const char *name)
1417 {
1418 char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
1419
1420 mg_snprintf(
1421 NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
1422
1423 #if defined(_WIN32)
1424 #if defined(_MSC_VER)
1425 /* Windows and Visual Studio Compiler */
1426 __try
1427 {
1428 THREADNAME_INFO info;
1429 info.dwType = 0x1000;
1430 info.szName = threadName;
1431 info.dwThreadID = ~0U;
1432 info.dwFlags = 0;
1433
1434 RaiseException(0x406D1388,
1435 0,
1436 sizeof(info) / sizeof(ULONG_PTR),
1437 (ULONG_PTR *)&info);
1438 }
1439 __except(EXCEPTION_EXECUTE_HANDLER)
1440 {
1441 }
1442 #elif defined(__MINGW32__)
1443 /* No option known to set thread name for MinGW */
1444 #endif
1445 #elif defined(__GLIBC__) \
1446 && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
1447 /* pthread_setname_np first appeared in glibc in version 2.12*/
1448 (void)pthread_setname_np(pthread_self(), threadName);
1449 #elif defined(__linux__)
1450 /* on linux we can use the old prctl function */
1451 (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
1452 #endif
1453 }
1454 #else /* !defined(NO_THREAD_NAME) */
1455 void
1456 mg_set_thread_name(const char *threadName)
1457 {
1458 }
1459 #endif
1460
1461
1462 #if defined(MG_LEGACY_INTERFACE)
1463 const char **
1464 mg_get_valid_option_names(void)
1465 {
1466 /* This function is deprecated. Use mg_get_valid_options instead. */
1467 static const char *
1468 data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
1469 int i;
1470
1471 for (i = 0; config_options[i].name != NULL; i++) {
1472 data[i * 2] = config_options[i].name;
1473 data[i * 2 + 1] = config_options[i].default_value;
1474 }
1475
1476 return data;
1477 }
1478 #endif
1479
1480
1481 const struct mg_option *
1482 mg_get_valid_options(void)
1483 {
1484 return config_options;
1485 }
1486
1487
1488 static int
1489 is_file_in_memory(const struct mg_connection *conn,
1490 const char *path,
1491 struct file *filep)
1492 {
1493 size_t size = 0;
1494 if (!conn || !filep) {
1495 return 0;
1496 }
1497
1498 if (conn->ctx->callbacks.open_file) {
1499 filep->membuf = conn->ctx->callbacks.open_file(conn, path, &size);
1500 if (filep->membuf != NULL) {
1501 /* NOTE: override filep->size only on success. Otherwise, it might
1502 * break constructs like if (!mg_stat() || !mg_fopen()) ... */
1503 filep->size = size;
1504 }
1505 }
1506
1507 return filep->membuf != NULL;
1508 }
1509
1510
1511 static int
1512 is_file_opened(const struct file *filep)
1513 {
1514 if (!filep) {
1515 return 0;
1516 }
1517
1518 return filep->membuf != NULL || filep->fp != NULL;
1519 }
1520
1521
1522 /* mg_fopen will open a file either in memory or on the disk.
1523 * The input parameter path is a string in UTF-8 encoding.
1524 * The input parameter mode is the same as for fopen.
1525 * Either fp or membuf will be set in the output struct filep.
1526 * The function returns 1 on success, 0 on error. */
1527 static int
1528 mg_fopen(const struct mg_connection *conn,
1529 const char *path,
1530 const char *mode,
1531 struct file *filep)
1532 {
1533 struct stat st;
1534
1535 if (!filep) {
1536 return 0;
1537 }
1538
1539 /* TODO (high): mg_fopen should only open a file, while mg_stat should
1540 * only get the file status. They should not work on different members of
1541 * the same structure (bad cohesion). */
1542 memset(filep, 0, sizeof(*filep));
1543
1544 if (stat(path, &st) == 0) {
1545 filep->size = (uint64_t)(st.st_size);
1546 }
1547
1548 if (!is_file_in_memory(conn, path, filep)) {
1549 #ifdef _WIN32
1550 wchar_t wbuf[PATH_MAX], wmode[20];
1551 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
1552 MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
1553 filep->fp = _wfopen(wbuf, wmode);
1554 #else
1555 /* Linux et al already use unicode. No need to convert. */
1556 filep->fp = fopen(path, mode);
1557 #endif
1558 }
1559
1560 return is_file_opened(filep);
1561 }
1562
1563
1564 static void
1565 mg_fclose(struct file *filep)
1566 {
1567 if (filep != NULL && filep->fp != NULL) {
1568 fclose(filep->fp);
1569 }
1570 }
1571
1572
1573 static void
1574 mg_strlcpy(register char *dst, register const char *src, size_t n)
1575 {
1576 for (; *src != '\0' && n > 1; n--) {
1577 *dst++ = *src++;
1578 }
1579 *dst = '\0';
1580 }
1581
1582
1583 static int
1584 lowercase(const char *s)
1585 {
1586 return tolower(*(const unsigned char *)s);
1587 }
1588
1589
1590 int
1591 mg_strncasecmp(const char *s1, const char *s2, size_t len)
1592 {
1593 int diff = 0;
1594
1595 if (len > 0) {
1596 do {
1597 diff = lowercase(s1++) - lowercase(s2++);
1598 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
1599 }
1600
1601 return diff;
1602 }
1603
1604
1605 int
1606 mg_strcasecmp(const char *s1, const char *s2)
1607 {
1608 int diff;
1609
1610 do {
1611 diff = lowercase(s1++) - lowercase(s2++);
1612 } while (diff == 0 && s1[-1] != '\0');
1613
1614 return diff;
1615 }
1616
1617
1618 static char *
1619 mg_strndup(const char *ptr, size_t len)
1620 {
1621 char *p;
1622
1623 if ((p = (char *)mg_malloc(len + 1)) != NULL) {
1624 mg_strlcpy(p, ptr, len + 1);
1625 }
1626
1627 return p;
1628 }
1629
1630
1631 static char *
1632 mg_strdup(const char *str)
1633 {
1634 return mg_strndup(str, strlen(str));
1635 }
1636
1637
1638 static const char *
1639 mg_strcasestr(const char *big_str, const char *small_str)
1640 {
1641 size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
1642
1643 if (big_len >= small_len) {
1644 for (i = 0; i <= (big_len - small_len); i++) {
1645 if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
1646 return big_str + i;
1647 }
1648 }
1649 }
1650
1651 return NULL;
1652 }
1653
1654
1655 /* Return null terminated string of given maximum length.
1656 * Report errors if length is exceeded. */
1657 static void
1658 mg_vsnprintf(const struct mg_connection *conn,
1659 int *truncated,
1660 char *buf,
1661 size_t buflen,
1662 const char *fmt,
1663 va_list ap)
1664 {
1665 int n, ok;
1666
1667 if (buflen == 0) {
1668 return;
1669 }
1670
1671 #ifdef __clang__
1672 #pragma clang diagnostic push
1673 #pragma clang diagnostic ignored "-Wformat-nonliteral"
1674 /* Using fmt as a non-literal is intended here, since it is mostly called
1675 * indirectly by mg_snprintf */
1676 #endif
1677
1678 n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
1679 ok = (n >= 0) && ((size_t)n < buflen);
1680
1681 #ifdef __clang__
1682 #pragma clang diagnostic pop
1683 #endif
1684
1685 if (ok) {
1686 if (truncated) {
1687 *truncated = 0;
1688 }
1689 } else {
1690 if (truncated) {
1691 *truncated = 1;
1692 }
1693 mg_cry(conn,
1694 "truncating vsnprintf buffer: [%.*s]",
1695 (int)((buflen > 200) ? 200 : (buflen - 1)),
1696 buf);
1697 n = (int)buflen - 1;
1698 }
1699 buf[n] = '\0';
1700 }
1701
1702
1703 static void
1704 mg_snprintf(const struct mg_connection *conn,
1705 int *truncated,
1706 char *buf,
1707 size_t buflen,
1708 const char *fmt,
1709 ...)
1710 {
1711 va_list ap;
1712
1713 va_start(ap, fmt);
1714 mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
1715 va_end(ap);
1716 }
1717
1718
1719 static int
1720 get_option_index(const char *name)
1721 {
1722 int i;
1723
1724 for (i = 0; config_options[i].name != NULL; i++) {
1725 if (strcmp(config_options[i].name, name) == 0) {
1726 return i;
1727 }
1728 }
1729 return -1;
1730 }
1731
1732
1733 const char *
1734 mg_get_option(const struct mg_context *ctx, const char *name)
1735 {
1736 int i;
1737 if ((i = get_option_index(name)) == -1) {
1738 return NULL;
1739 } else if (!ctx || ctx->config[i] == NULL) {
1740 return "";
1741 } else {
1742 return ctx->config[i];
1743 }
1744 }
1745
1746
1747 struct mg_context *
1748 mg_get_context(const struct mg_connection *conn)
1749 {
1750 return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
1751 }
1752
1753
1754 void *
1755 mg_get_user_data(const struct mg_context *ctx)
1756 {
1757 return (ctx == NULL) ? NULL : ctx->user_data;
1758 }
1759
1760
1761 void
1762 mg_set_user_connection_data(struct mg_connection *conn, void *data)
1763 {
1764 if (conn != NULL) {
1765 conn->request_info.conn_data = data;
1766 }
1767 }
1768
1769
1770 void *
1771 mg_get_user_connection_data(const struct mg_connection *conn)
1772 {
1773 if (conn != NULL) {
1774 return conn->request_info.conn_data;
1775 }
1776 return NULL;
1777 }
1778
1779
1780 size_t
1781 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
1782 {
1783 size_t i;
1784 if (!ctx) {
1785 return 0;
1786 }
1787 for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
1788 ssl[i] = ctx->listening_sockets[i].is_ssl;
1789 ports[i] = ctx->listening_ports[i];
1790 }
1791 return i;
1792 }
1793
1794
1795 int
1796 mg_get_server_ports(const struct mg_context *ctx,
1797 int size,
1798 struct mg_server_ports *ports)
1799 {
1800 int i, cnt = 0;
1801
1802 if (size <= 0) {
1803 return -1;
1804 }
1805 memset(ports, 0, sizeof(*ports) * (size_t)size);
1806 if (!ctx) {
1807 return -1;
1808 }
1809 if (!ctx->listening_sockets || !ctx->listening_ports) {
1810 return -1;
1811 }
1812
1813 for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
1814
1815 ports[cnt].port = ctx->listening_ports[i];
1816 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
1817 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
1818
1819 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
1820 /* IPv4 */
1821 ports[cnt].protocol = 1;
1822 cnt++;
1823 } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
1824 /* IPv6 */
1825 ports[cnt].protocol = 3;
1826 cnt++;
1827 }
1828 }
1829
1830 return cnt;
1831 }
1832
1833
1834 static void
1835 sockaddr_to_string(char *buf, size_t len, const union usa *usa)
1836 {
1837 buf[0] = '\0';
1838
1839 if (!usa) {
1840 return;
1841 }
1842
1843 if (usa->sa.sa_family == AF_INET) {
1844 getnameinfo(&usa->sa,
1845 sizeof(usa->sin),
1846 buf,
1847 (unsigned)len,
1848 NULL,
1849 0,
1850 NI_NUMERICHOST);
1851 }
1852 #if defined(USE_IPV6)
1853 else if (usa->sa.sa_family == AF_INET6) {
1854 getnameinfo(&usa->sa,
1855 sizeof(usa->sin6),
1856 buf,
1857 (unsigned)len,
1858 NULL,
1859 0,
1860 NI_NUMERICHOST);
1861 }
1862 #endif
1863 }
1864
1865
1866 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
1867 * included in all responses other than 100, 101, 5xx. */
1868 static void
1869 gmt_time_string(char *buf, size_t buf_len, time_t *t)
1870 {
1871 struct tm *tm;
1872
1873 tm = ((t != NULL) ? gmtime(t) : NULL);
1874 if (tm != NULL) {
1875 strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
1876 } else {
1877 mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
1878 buf[buf_len - 1] = '\0';
1879 }
1880 }
1881
1882
1883 /* difftime for struct timespec. Return value is in seconds. */
1884 static double
1885 mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
1886 {
1887 return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
1888 + (double)(ts_now->tv_sec - ts_before->tv_sec);
1889 }
1890
1891
1892 /* Print error message to the opened error log stream. */
1893 void
1894 mg_cry(const struct mg_connection *conn, const char *fmt, ...)
1895 {
1896 char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
1897 va_list ap;
1898 struct file fi;
1899 time_t timestamp;
1900
1901 va_start(ap, fmt);
1902 IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
1903 va_end(ap);
1904 buf[sizeof(buf) - 1] = 0;
1905
1906 if (!conn) {
1907 puts(buf);
1908 return;
1909 }
1910
1911 /* Do not lock when getting the callback value, here and below.
1912 * I suppose this is fine, since function cannot disappear in the
1913 * same way string option can. */
1914 if ((conn->ctx->callbacks.log_message == NULL)
1915 || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
1916
1917 if (conn->ctx->config[ERROR_LOG_FILE] != NULL) {
1918 if (mg_fopen(conn, conn->ctx->config[ERROR_LOG_FILE], "a+", &fi)
1919 == 0) {
1920 fi.fp = NULL;
1921 }
1922 } else {
1923 fi.fp = NULL;
1924 }
1925
1926 if (fi.fp != NULL) {
1927 flockfile(fi.fp);
1928 timestamp = time(NULL);
1929
1930 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
1931 fprintf(fi.fp,
1932 "[%010lu] [error] [client %s] ",
1933 (unsigned long)timestamp,
1934 src_addr);
1935
1936 if (conn->request_info.request_method != NULL) {
1937 fprintf(fi.fp,
1938 "%s %s: ",
1939 conn->request_info.request_method,
1940 conn->request_info.request_uri);
1941 }
1942
1943 fprintf(fi.fp, "%s", buf);
1944 fputc('\n', fi.fp);
1945 fflush(fi.fp);
1946 funlockfile(fi.fp);
1947 mg_fclose(&fi);
1948 }
1949 }
1950 }
1951
1952 void
1953 mg_set_http_status(struct mg_connection *conn, int status)
1954 {
1955 conn->status_code = status;
1956 }
1957
1958 /* Return fake connection structure. Used for logging, if connection
1959 * is not applicable at the moment of logging. */
1960 static struct mg_connection *
1961 fc(struct mg_context *ctx)
1962 {
1963 static struct mg_connection fake_connection;
1964 fake_connection.ctx = ctx;
1965 return &fake_connection;
1966 }
1967
1968
1969 const char *
1970 mg_version(void)
1971 {
1972 return CIVETWEB_VERSION;
1973 }
1974
1975
1976 const struct mg_request_info *
1977 mg_get_request_info(const struct mg_connection *conn)
1978 {
1979 if (!conn) {
1980 return NULL;
1981 }
1982 return &conn->request_info;
1983 }
1984
1985
1986 struct sockaddr *
1987 mg_get_local_addr(struct mg_connection *conn)
1988 {
1989 return &conn->client.lsa.sa;
1990 }
1991
1992
1993 /* Skip the characters until one of the delimiters characters found.
1994 * 0-terminate resulting word. Skip the delimiter and following whitespaces.
1995 * Advance pointer to buffer to the next word. Return found 0-terminated word.
1996 * Delimiters can be quoted with quotechar. */
1997 static char *
1998 skip_quoted(char **buf,
1999 const char *delimiters,
2000 const char *whitespace,
2001 char quotechar)
2002 {
2003 char *p, *begin_word, *end_word, *end_whitespace;
2004
2005 begin_word = *buf;
2006 end_word = begin_word + strcspn(begin_word, delimiters);
2007
2008 /* Check for quotechar */
2009 if (end_word > begin_word) {
2010 p = end_word - 1;
2011 while (*p == quotechar) {
2012 /* While the delimiter is quoted, look for the next delimiter. */
2013 /* This happens, e.g., in calls from parse_auth_header,
2014 * if the user name contains a " character. */
2015
2016 /* If there is anything beyond end_word, copy it. */
2017 if (*end_word != '\0') {
2018 size_t end_off = strcspn(end_word + 1, delimiters);
2019 memmove(p, end_word, end_off + 1);
2020 p += end_off; /* p must correspond to end_word - 1 */
2021 end_word += end_off + 1;
2022 } else {
2023 *p = '\0';
2024 break;
2025 }
2026 }
2027 for (p++; p < end_word; p++) {
2028 *p = '\0';
2029 }
2030 }
2031
2032 if (*end_word == '\0') {
2033 *buf = end_word;
2034 } else {
2035 end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
2036
2037 for (p = end_word; p < end_whitespace; p++) {
2038 *p = '\0';
2039 }
2040
2041 *buf = end_whitespace;
2042 }
2043
2044 return begin_word;
2045 }
2046
2047
2048 /* Simplified version of skip_quoted without quote char
2049 * and whitespace == delimiters */
2050 static char *
2051 skip(char **buf, const char *delimiters)
2052 {
2053 return skip_quoted(buf, delimiters, delimiters, 0);
2054 }
2055
2056
2057 /* Return HTTP header value, or NULL if not found. */
2058 static const char *
2059 get_header(const struct mg_request_info *ri, const char *name)
2060 {
2061 int i;
2062 if (ri) {
2063 for (i = 0; i < ri->num_headers; i++) {
2064 if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
2065 return ri->http_headers[i].value;
2066 }
2067 }
2068 }
2069
2070 return NULL;
2071 }
2072
2073
2074 const char *
2075 mg_get_header(const struct mg_connection *conn, const char *name)
2076 {
2077 if (!conn) {
2078 return NULL;
2079 }
2080
2081 return get_header(&conn->request_info, name);
2082 }
2083
2084
2085 /* A helper function for traversing a comma separated list of values.
2086 * It returns a list pointer shifted to the next value, or NULL if the end
2087 * of the list found.
2088 * Value is stored in val vector. If value has form "x=y", then eq_val
2089 * vector is initialized to point to the "y" part, and val vector length
2090 * is adjusted to point only to "x". */
2091 static const char *
2092 next_option(const char *list, struct vec *val, struct vec *eq_val)
2093 {
2094 int end;
2095
2096 reparse:
2097 if (val == NULL || list == NULL || *list == '\0') {
2098 /* End of the list */
2099 list = NULL;
2100 } else {
2101 /* Skip over leading LWS */
2102 while (*list == ' ' || *list == '\t')
2103 list++;
2104
2105 val->ptr = list;
2106 if ((list = strchr(val->ptr, ',')) != NULL) {
2107 /* Comma found. Store length and shift the list ptr */
2108 val->len = ((size_t)(list - val->ptr));
2109 list++;
2110 } else {
2111 /* This value is the last one */
2112 list = val->ptr + strlen(val->ptr);
2113 val->len = ((size_t)(list - val->ptr));
2114 }
2115
2116 /* Adjust length for trailing LWS */
2117 end = (int)val->len - 1;
2118 while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t'))
2119 end--;
2120 val->len = (size_t)(end + 1);
2121
2122 if (val->len == 0) {
2123 /* Ignore any empty entries. */
2124 goto reparse;
2125 }
2126
2127 if (eq_val != NULL) {
2128 /* Value has form "x=y", adjust pointers and lengths
2129 * so that val points to "x", and eq_val points to "y". */
2130 eq_val->len = 0;
2131 eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
2132 if (eq_val->ptr != NULL) {
2133 eq_val->ptr++; /* Skip over '=' character */
2134 eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
2135 val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
2136 }
2137 }
2138 }
2139
2140 return list;
2141 }
2142
2143 /* A helper function for checking if a comma separated list of values contains
2144 * the given option (case insensitvely).
2145 * 'header' can be NULL, in which case false is returned. */
2146 static int
2147 header_has_option(const char *header, const char *option)
2148 {
2149 struct vec opt_vec;
2150 struct vec eq_vec;
2151
2152 assert(option != NULL);
2153 assert(option[0] != '\0');
2154
2155 while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
2156 if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
2157 return 1;
2158 }
2159
2160 return 0;
2161 }
2162
2163 /* Perform case-insensitive match of string against pattern */
2164 static int
2165 match_prefix(const char *pattern, size_t pattern_len, const char *str)
2166 {
2167 const char *or_str;
2168 size_t i;
2169 int j, len, res;
2170
2171 if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
2172 res = match_prefix(pattern, (size_t)(or_str - pattern), str);
2173 return res > 0 ? res : match_prefix(or_str + 1,
2174 (size_t)((pattern + pattern_len)
2175 - (or_str + 1)),
2176 str);
2177 }
2178
2179 for (i = 0, j = 0; i < pattern_len; i++, j++) {
2180 if (pattern[i] == '?' && str[j] != '\0') {
2181 continue;
2182 } else if (pattern[i] == '$') {
2183 return str[j] == '\0' ? j : -1;
2184 } else if (pattern[i] == '*') {
2185 i++;
2186 if (pattern[i] == '*') {
2187 i++;
2188 len = (int)strlen(str + j);
2189 } else {
2190 len = (int)strcspn(str + j, "/");
2191 }
2192 if (i == pattern_len) {
2193 return j + len;
2194 }
2195 do {
2196 res = match_prefix(pattern + i, pattern_len - i, str + j + len);
2197 } while (res == -1 && len-- > 0);
2198 return res == -1 ? -1 : j + res + len;
2199 } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
2200 return -1;
2201 }
2202 }
2203 return j;
2204 }
2205
2206
2207 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
2208 * This function must tolerate situations when connection info is not
2209 * set up, for example if request parsing failed. */
2210 static int
2211 should_keep_alive(const struct mg_connection *conn)
2212 {
2213 if (conn != NULL) {
2214 const char *http_version = conn->request_info.http_version;
2215 const char *header = mg_get_header(conn, "Connection");
2216 if (conn->must_close || conn->internal_error || conn->status_code == 401
2217 || mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0
2218 || (header != NULL && !header_has_option(header, "keep-alive"))
2219 || (header == NULL && http_version
2220 && 0 != strcmp(http_version, "1.1"))) {
2221 return 0;
2222 }
2223 return 1;
2224 }
2225 return 0;
2226 }
2227
2228
2229 static int
2230 should_decode_url(const struct mg_connection *conn)
2231 {
2232 if (!conn || !conn->ctx) {
2233 return 0;
2234 }
2235
2236 return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
2237 }
2238
2239 static int
2240 should_validate_http_method(const struct mg_connection *conn)
2241 {
2242 if (!conn || !conn->ctx || !conn->ctx->config[VALIDATE_HTTP_METHOD]) {
2243 return 1;
2244 }
2245
2246 return (mg_strcasecmp(conn->ctx->config[VALIDATE_HTTP_METHOD], "yes") == 0);
2247 }
2248
2249
2250 static const char *
2251 suggest_connection_header(const struct mg_connection *conn)
2252 {
2253 return should_keep_alive(conn) ? "keep-alive" : "close";
2254 }
2255
2256
2257 static int
2258 send_no_cache_header(struct mg_connection *conn)
2259 {
2260 /* Send all current and obsolete cache opt-out directives. */
2261 return mg_printf(conn,
2262 "Cache-Control: no-cache, no-store, "
2263 "must-revalidate, private, max-age=0\r\n"
2264 "Pragma: no-cache\r\n"
2265 "Expires: 0\r\n");
2266 }
2267
2268
2269 static int
2270 send_static_cache_header(struct mg_connection *conn)
2271 {
2272 #if !defined(NO_CACHING)
2273 /* Read the server config to check how long a file may be cached.
2274 * The configuration is in seconds. */
2275 int max_age = atoi(conn->ctx->config[STATIC_FILE_MAX_AGE]);
2276 if (max_age <= 0) {
2277 /* 0 means "do not cache". All values <0 are reserved
2278 * and may be used differently in the future. */
2279 /* If a file should not be cached, do not only send
2280 * max-age=0, but also pragmas and Expires headers. */
2281 return send_no_cache_header(conn);
2282 }
2283
2284 /* Use "Cache-Control: max-age" instead of "Expires" header.
2285 * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
2286 /* See also https://www.mnot.net/cache_docs/ */
2287 /* According to RFC 2616, Section 14.21, caching times should not exceed
2288 * one year. A year with 365 days corresponds to 31536000 seconds, a leap
2289 * year to 31622400 seconds. For the moment, we just send whatever has
2290 * been configured, still the behavior for >1 year should be considered
2291 * as undefined. */
2292 return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
2293 #else /* NO_CACHING */
2294 return send_no_cache_header(conn);
2295 #endif /* !NO_CACHING */
2296 }
2297
2298
2299 static void handle_file_based_request(struct mg_connection *conn,
2300 const char *path,
2301 struct file *filep);
2302
2303 static int
2304 mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
2305
2306
2307 const char *
2308 mg_get_response_code_text(struct mg_connection *conn, int response_code)
2309 {
2310 /* See IANA HTTP status code assignment:
2311 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
2312 */
2313
2314 switch (response_code) {
2315 /* RFC2616 Section 10.1 - Informational 1xx */
2316 case 100:
2317 return "Continue"; /* RFC2616 Section 10.1.1 */
2318 case 101:
2319 return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
2320 case 102:
2321 return "Processing"; /* RFC2518 Section 10.1 */
2322
2323 /* RFC2616 Section 10.2 - Successful 2xx */
2324 case 200:
2325 return "OK"; /* RFC2616 Section 10.2.1 */
2326 case 201:
2327 return "Created"; /* RFC2616 Section 10.2.2 */
2328 case 202:
2329 return "Accepted"; /* RFC2616 Section 10.2.3 */
2330 case 203:
2331 return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
2332 case 204:
2333 return "No Content"; /* RFC2616 Section 10.2.5 */
2334 case 205:
2335 return "Reset Content"; /* RFC2616 Section 10.2.6 */
2336 case 206:
2337 return "Partial Content"; /* RFC2616 Section 10.2.7 */
2338 case 207:
2339 return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
2340 case 208:
2341 return "Already Reported"; /* RFC5842 Section 7.1 */
2342
2343 case 226:
2344 return "IM used"; /* RFC3229 Section 10.4.1 */
2345
2346 /* RFC2616 Section 10.3 - Redirection 3xx */
2347 case 300:
2348 return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
2349 case 301:
2350 return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
2351 case 302:
2352 return "Found"; /* RFC2616 Section 10.3.3 */
2353 case 303:
2354 return "See Other"; /* RFC2616 Section 10.3.4 */
2355 case 304:
2356 return "Not Modified"; /* RFC2616 Section 10.3.5 */
2357 case 305:
2358 return "Use Proxy"; /* RFC2616 Section 10.3.6 */
2359 case 307:
2360 return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
2361 case 308:
2362 return "Permanent Redirect"; /* RFC7238 Section 3 */
2363
2364 /* RFC2616 Section 10.4 - Client Error 4xx */
2365 case 400:
2366 return "Bad Request"; /* RFC2616 Section 10.4.1 */
2367 case 401:
2368 return "Unauthorized"; /* RFC2616 Section 10.4.2 */
2369 case 402:
2370 return "Payment Required"; /* RFC2616 Section 10.4.3 */
2371 case 403:
2372 return "Forbidden"; /* RFC2616 Section 10.4.4 */
2373 case 404:
2374 return "Not Found"; /* RFC2616 Section 10.4.5 */
2375 case 405:
2376 return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
2377 case 406:
2378 return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
2379 case 407:
2380 return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
2381 case 408:
2382 return "Request Time-out"; /* RFC2616 Section 10.4.9 */
2383 case 409:
2384 return "Conflict"; /* RFC2616 Section 10.4.10 */
2385 case 410:
2386 return "Gone"; /* RFC2616 Section 10.4.11 */
2387 case 411:
2388 return "Length Required"; /* RFC2616 Section 10.4.12 */
2389 case 412:
2390 return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
2391 case 413:
2392 return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
2393 case 414:
2394 return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
2395 case 415:
2396 return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
2397 case 416:
2398 return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
2399 case 417:
2400 return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
2401
2402 case 421:
2403 return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
2404 case 422:
2405 return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
2406 * Section 11.2 */
2407 case 423:
2408 return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
2409 case 424:
2410 return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
2411 * Section 11.4 */
2412
2413 case 426:
2414 return "Upgrade Required"; /* RFC 2817 Section 4 */
2415
2416 case 428:
2417 return "Precondition Required"; /* RFC 6585, Section 3 */
2418 case 429:
2419 return "Too Many Requests"; /* RFC 6585, Section 4 */
2420
2421 case 431:
2422 return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
2423
2424 case 451:
2425 return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
2426 * Section 3 */
2427
2428 /* RFC2616 Section 10.5 - Server Error 5xx */
2429 case 500:
2430 return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
2431 case 501:
2432 return "Not Implemented"; /* RFC2616 Section 10.5.2 */
2433 case 502:
2434 return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
2435 case 503:
2436 return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
2437 case 504:
2438 return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
2439 case 505:
2440 return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
2441 case 506:
2442 return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
2443 case 507:
2444 return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
2445 * Section 11.5 */
2446 case 508:
2447 return "Loop Detected"; /* RFC5842 Section 7.1 */
2448
2449 case 510:
2450 return "Not Extended"; /* RFC 2774, Section 7 */
2451 case 511:
2452 return "Network Authentication Required"; /* RFC 6585, Section 6 */
2453
2454 /* Other status codes, not shown in the IANA HTTP status code assignment.
2455 * E.g., "de facto" standards due to common use, ... */
2456 case 418:
2457 return "I am a teapot"; /* RFC2324 Section 2.3.2 */
2458 case 419:
2459 return "Authentication Timeout"; /* common use */
2460 case 420:
2461 return "Enhance Your Calm"; /* common use */
2462 case 440:
2463 return "Login Timeout"; /* common use */
2464 case 509:
2465 return "Bandwidth Limit Exceeded"; /* common use */
2466
2467 default:
2468 /* This error code is unknown. This should not happen. */
2469 if (conn) {
2470 mg_cry(conn, "Unknown HTTP response code: %u", response_code);
2471 }
2472
2473 /* Return at least a category according to RFC 2616 Section 10. */
2474 if (response_code >= 100 && response_code < 200) {
2475 /* Unknown informational status code */
2476 return "Information";
2477 }
2478 if (response_code >= 200 && response_code < 300) {
2479 /* Unknown success code */
2480 return "Success";
2481 }
2482 if (response_code >= 300 && response_code < 400) {
2483 /* Unknown redirection code */
2484 return "Redirection";
2485 }
2486 if (response_code >= 400 && response_code < 500) {
2487 /* Unknown request error code */
2488 return "Client Error";
2489 }
2490 if (response_code >= 500 && response_code < 600) {
2491 /* Unknown server error code */
2492 return "Server Error";
2493 }
2494
2495 /* Response code not even within reasonable range */
2496 return "";
2497 }
2498 }
2499
2500
2501 static void send_http_error(struct mg_connection *,
2502 int,
2503 PRINTF_FORMAT_STRING(const char *fmt),
2504 ...) PRINTF_ARGS(3, 4);
2505
2506 static void
2507 send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
2508 {
2509 char buf[MG_BUF_LEN];
2510 va_list ap;
2511 int len, i, page_handler_found, scope, truncated;
2512 char date[64];
2513 time_t curtime = time(NULL);
2514 const char *error_handler = NULL;
2515 struct file error_page_file = STRUCT_FILE_INITIALIZER;
2516 const char *error_page_file_ext, *tstr;
2517
2518 const char *status_text = mg_get_response_code_text(conn, status);
2519
2520 if (conn == NULL) {
2521 return;
2522 }
2523
2524 conn->status_code = status;
2525 if (conn->in_error_handler || conn->ctx->callbacks.http_error == NULL
2526 || conn->ctx->callbacks.http_error(conn, status)) {
2527 if (!conn->in_error_handler) {
2528 /* Send user defined error pages, if defined */
2529 error_handler = conn->ctx->config[ERROR_PAGES];
2530 error_page_file_ext = conn->ctx->config[INDEX_FILES];
2531 page_handler_found = 0;
2532 if (error_handler != NULL) {
2533 for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
2534 switch (scope) {
2535 case 1: /* Handler for specific error, e.g. 404 error */
2536 mg_snprintf(conn,
2537 &truncated,
2538 buf,
2539 sizeof(buf) - 32,
2540 "%serror%03u.",
2541 error_handler,
2542 status);
2543 break;
2544 case 2: /* Handler for error group, e.g., 5xx error handler
2545 * for all server errors (500-599) */
2546 mg_snprintf(conn,
2547 &truncated,
2548 buf,
2549 sizeof(buf) - 32,
2550 "%serror%01uxx.",
2551 error_handler,
2552 status / 100);
2553 break;
2554 default: /* Handler for all errors */
2555 mg_snprintf(conn,
2556 &truncated,
2557 buf,
2558 sizeof(buf) - 32,
2559 "%serror.",
2560 error_handler);
2561 break;
2562 }
2563
2564 /* String truncation in buf may only occur if error_handler
2565 * is too long. This string is from the config, not from a
2566 * client. */
2567 (void)truncated;
2568
2569 len = (int)strlen(buf);
2570
2571 tstr = strchr(error_page_file_ext, '.');
2572
2573 while (tstr) {
2574 for (i = 1; i < 32 && tstr[i] != 0 && tstr[i] != ',';
2575 i++)
2576 buf[len + i - 1] = tstr[i];
2577 buf[len + i - 1] = 0;
2578 if (mg_stat(conn, buf, &error_page_file)) {
2579 page_handler_found = 1;
2580 break;
2581 }
2582 tstr = strchr(tstr + i, '.');
2583 }
2584 }
2585 }
2586
2587 if (page_handler_found) {
2588 conn->in_error_handler = 1;
2589 handle_file_based_request(conn, buf, &error_page_file);
2590 conn->in_error_handler = 0;
2591 return;
2592 }
2593 }
2594
2595 /* No custom error page. Send default error page. */
2596 gmt_time_string(date, sizeof(date), &curtime);
2597
2598 conn->must_close = 1;
2599 mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
2600 send_no_cache_header(conn);
2601 mg_printf(conn,
2602 "Date: %s\r\n"
2603 "Connection: close\r\n\r\n",
2604 date);
2605
2606 /* Errors 1xx, 204 and 304 MUST NOT send a body */
2607 if (status > 199 && status != 204 && status != 304) {
2608
2609 mg_printf(conn, "Error %d: %s\n", status, status_text);
2610
2611 if (fmt != NULL) {
2612 va_start(ap, fmt);
2613 mg_vsnprintf(conn, NULL, buf, sizeof(buf), fmt, ap);
2614 va_end(ap);
2615 mg_write(conn, buf, strlen(buf));
2616 DEBUG_TRACE("Error %i - [%s]", status, buf);
2617 }
2618
2619 } else {
2620 /* No body allowed. Close the connection. */
2621 DEBUG_TRACE("Error %i", status);
2622 }
2623 }
2624 }
2625
2626 #if defined(_WIN32) && !defined(__SYMBIAN32__)
2627 /* Create substitutes for POSIX functions in Win32. */
2628
2629 #if defined(__MINGW32__)
2630 /* Show no warning in case system functions are not used. */
2631 #pragma GCC diagnostic push
2632 #pragma GCC diagnostic ignored "-Wunused-function"
2633 #endif
2634
2635
2636 static int
2637 pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
2638 {
2639 (void)unused;
2640 *mutex = CreateMutex(NULL, FALSE, NULL);
2641 return *mutex == NULL ? -1 : 0;
2642 }
2643
2644
2645 static int
2646 pthread_mutex_destroy(pthread_mutex_t *mutex)
2647 {
2648 return CloseHandle(*mutex) == 0 ? -1 : 0;
2649 }
2650
2651
2652 static int
2653 pthread_mutex_lock(pthread_mutex_t *mutex)
2654 {
2655 return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
2656 }
2657
2658
2659 #ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS
2660 static int
2661 pthread_mutex_trylock(pthread_mutex_t *mutex)
2662 {
2663 switch (WaitForSingleObject(*mutex, 0)) {
2664 case WAIT_OBJECT_0:
2665 return 0;
2666 case WAIT_TIMEOUT:
2667 return -2; /* EBUSY */
2668 }
2669 return -1;
2670 }
2671 #endif
2672
2673
2674 static int
2675 pthread_mutex_unlock(pthread_mutex_t *mutex)
2676 {
2677 return ReleaseMutex(*mutex) == 0 ? -1 : 0;
2678 }
2679
2680
2681 #ifndef WIN_PTHREADS_TIME_H
2682 static int
2683 clock_gettime(clockid_t clk_id, struct timespec *tp)
2684 {
2685 FILETIME ft;
2686 ULARGE_INTEGER li;
2687 BOOL ok = FALSE;
2688 double d;
2689 static double perfcnt_per_sec = 0.0;
2690
2691 if (tp) {
2692 memset(tp, 0, sizeof(*tp));
2693 if (clk_id == CLOCK_REALTIME) {
2694 GetSystemTimeAsFileTime(&ft);
2695 li.LowPart = ft.dwLowDateTime;
2696 li.HighPart = ft.dwHighDateTime;
2697 li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
2698 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
2699 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
2700 ok = TRUE;
2701 } else if (clk_id == CLOCK_MONOTONIC) {
2702 if (perfcnt_per_sec == 0.0) {
2703 QueryPerformanceFrequency((LARGE_INTEGER *)&li);
2704 perfcnt_per_sec = 1.0 / li.QuadPart;
2705 }
2706 if (perfcnt_per_sec != 0.0) {
2707 QueryPerformanceCounter((LARGE_INTEGER *)&li);
2708 d = li.QuadPart * perfcnt_per_sec;
2709 tp->tv_sec = (time_t)d;
2710 d -= tp->tv_sec;
2711 tp->tv_nsec = (long)(d * 1.0E9);
2712 ok = TRUE;
2713 }
2714 }
2715 }
2716
2717 return ok ? 0 : -1;
2718 }
2719 #endif
2720
2721
2722 static int
2723 pthread_cond_init(pthread_cond_t *cv, const void *unused)
2724 {
2725 (void)unused;
2726 InitializeCriticalSection(&cv->threadIdSec);
2727 cv->waitingthreadcount = 0;
2728 cv->waitingthreadhdls =
2729 (pthread_t *)mg_calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
2730 return (cv->waitingthreadhdls != NULL) ? 0 : -1;
2731 }
2732
2733
2734 static int
2735 pthread_cond_timedwait(pthread_cond_t *cv,
2736 pthread_mutex_t *mutex,
2737 const struct timespec *abstime)
2738 {
2739 struct mg_workerTLS *tls =
2740 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
2741 int ok;
2742 struct timespec tsnow;
2743 int64_t nsnow, nswaitabs, nswaitrel;
2744 DWORD mswaitrel;
2745
2746 EnterCriticalSection(&cv->threadIdSec);
2747 assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
2748 cv->waitingthreadhdls[cv->waitingthreadcount] =
2749 tls->pthread_cond_helper_mutex;
2750 cv->waitingthreadcount++;
2751 LeaveCriticalSection(&cv->threadIdSec);
2752
2753 if (abstime) {
2754 clock_gettime(CLOCK_REALTIME, &tsnow);
2755 nsnow = (((int64_t)tsnow.tv_sec) * 1000000000) + tsnow.tv_nsec;
2756 nswaitabs =
2757 (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
2758 nswaitrel = nswaitabs - nsnow;
2759 if (nswaitrel < 0) {
2760 nswaitrel = 0;
2761 }
2762 mswaitrel = (DWORD)(nswaitrel / 1000000);
2763 } else {
2764 mswaitrel = INFINITE;
2765 }
2766
2767 pthread_mutex_unlock(mutex);
2768 ok = (WAIT_OBJECT_0
2769 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
2770 pthread_mutex_lock(mutex);
2771
2772 return ok ? 0 : -1;
2773 }
2774
2775
2776 static int
2777 pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
2778 {
2779 return pthread_cond_timedwait(cv, mutex, NULL);
2780 }
2781
2782
2783 static int
2784 pthread_cond_signal(pthread_cond_t *cv)
2785 {
2786 int i;
2787 HANDLE wkup = NULL;
2788 BOOL ok = FALSE;
2789
2790 EnterCriticalSection(&cv->threadIdSec);
2791 if (cv->waitingthreadcount) {
2792 wkup = cv->waitingthreadhdls[0];
2793 ok = SetEvent(wkup);
2794
2795 for (i = 1; i < cv->waitingthreadcount; i++) {
2796 cv->waitingthreadhdls[i - 1] = cv->waitingthreadhdls[i];
2797 }
2798 cv->waitingthreadcount--;
2799
2800 assert(ok);
2801 }
2802 LeaveCriticalSection(&cv->threadIdSec);
2803
2804 return ok ? 0 : 1;
2805 }
2806
2807
2808 static int
2809 pthread_cond_broadcast(pthread_cond_t *cv)
2810 {
2811 EnterCriticalSection(&cv->threadIdSec);
2812 while (cv->waitingthreadcount) {
2813 pthread_cond_signal(cv);
2814 }
2815 LeaveCriticalSection(&cv->threadIdSec);
2816
2817 return 0;
2818 }
2819
2820
2821 static int
2822 pthread_cond_destroy(pthread_cond_t *cv)
2823 {
2824 EnterCriticalSection(&cv->threadIdSec);
2825 assert(cv->waitingthreadcount == 0);
2826 mg_free(cv->waitingthreadhdls);
2827 cv->waitingthreadhdls = 0;
2828 LeaveCriticalSection(&cv->threadIdSec);
2829 DeleteCriticalSection(&cv->threadIdSec);
2830
2831 return 0;
2832 }
2833
2834
2835 #if defined(__MINGW32__)
2836 /* Enable unused function warning again */
2837 #pragma GCC diagnostic pop
2838 #endif
2839
2840
2841 /* For Windows, change all slashes to backslashes in path names. */
2842 static void
2843 change_slashes_to_backslashes(char *path)
2844 {
2845 int i;
2846
2847 for (i = 0; path[i] != '\0'; i++) {
2848 if (path[i] == '/') {
2849 path[i] = '\\';
2850 }
2851
2852 /* remove double backslash (check i > 0 to preserve UNC paths,
2853 * like \\server\file.txt) */
2854 if ((path[i] == '\\') && (i > 0)) {
2855 while (path[i + 1] == '\\' || path[i + 1] == '/') {
2856 (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
2857 }
2858 }
2859 }
2860 }
2861
2862
2863 static int
2864 mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
2865 {
2866 int diff;
2867
2868 do {
2869 diff = tolower(*s1) - tolower(*s2);
2870 s1++;
2871 s2++;
2872 } while (diff == 0 && s1[-1] != '\0');
2873
2874 return diff;
2875 }
2876
2877
2878 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
2879 * wbuf and wbuf_len is a target buffer and its length. */
2880 static void
2881 path_to_unicode(const struct mg_connection *conn,
2882 const char *path,
2883 wchar_t *wbuf,
2884 size_t wbuf_len)
2885 {
2886 char buf[PATH_MAX], buf2[PATH_MAX];
2887 wchar_t wbuf2[MAX_PATH + 1];
2888 DWORD long_len, err;
2889 int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
2890
2891 mg_strlcpy(buf, path, sizeof(buf));
2892 change_slashes_to_backslashes(buf);
2893
2894 /* Convert to Unicode and back. If doubly-converted string does not
2895 * match the original, something is fishy, reject. */
2896 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
2897 MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
2898 WideCharToMultiByte(
2899 CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
2900 if (strcmp(buf, buf2) != 0) {
2901 wbuf[0] = L'\0';
2902 }
2903
2904 /* TODO: Add a configuration to switch between case sensitive and
2905 * case insensitive URIs for Windows server. */
2906 /*
2907 if (conn) {
2908 if (conn->ctx->config[WINDOWS_CASE_SENSITIVE]) {
2909 fcompare = wcscmp;
2910 }
2911 }
2912 */
2913 (void)conn; /* conn is currently unused */
2914
2915 /* Only accept a full file path, not a Windows short (8.3) path. */
2916 memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
2917 long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
2918 if (long_len == 0) {
2919 err = GetLastError();
2920 if (err == ERROR_FILE_NOT_FOUND) {
2921 /* File does not exist. This is not always a problem here. */
2922 return;
2923 }
2924 }
2925 if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
2926 /* Short name is used. */
2927 wbuf[0] = L'\0';
2928 }
2929 }
2930
2931
2932 #if defined(_WIN32_WCE)
2933 /* Create substitutes for POSIX functions in Win32. */
2934
2935 #if defined(__MINGW32__)
2936 /* Show no warning in case system functions are not used. */
2937 #pragma GCC diagnostic push
2938 #pragma GCC diagnostic ignored "-Wunused-function"
2939 #endif
2940
2941
2942 static time_t
2943 time(time_t *ptime)
2944 {
2945 time_t t;
2946 SYSTEMTIME st;
2947 FILETIME ft;
2948
2949 GetSystemTime(&st);
2950 SystemTimeToFileTime(&st, &ft);
2951 t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
2952
2953 if (ptime != NULL) {
2954 *ptime = t;
2955 }
2956
2957 return t;
2958 }
2959
2960
2961 static struct tm *
2962 localtime(const time_t *ptime, struct tm *ptm)
2963 {
2964 int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
2965 FILETIME ft, lft;
2966 SYSTEMTIME st;
2967 TIME_ZONE_INFORMATION tzinfo;
2968
2969 if (ptm == NULL) {
2970 return NULL;
2971 }
2972
2973 *(int64_t *)&ft = t;
2974 FileTimeToLocalFileTime(&ft, &lft);
2975 FileTimeToSystemTime(&lft, &st);
2976 ptm->tm_year = st.wYear - 1900;
2977 ptm->tm_mon = st.wMonth - 1;
2978 ptm->tm_wday = st.wDayOfWeek;
2979 ptm->tm_mday = st.wDay;
2980 ptm->tm_hour = st.wHour;
2981 ptm->tm_min = st.wMinute;
2982 ptm->tm_sec = st.wSecond;
2983 ptm->tm_yday = 0; /* hope nobody uses this */
2984 ptm->tm_isdst =
2985 GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
2986
2987 return ptm;
2988 }
2989
2990
2991 static struct tm *
2992 gmtime(const time_t *ptime, struct tm *ptm)
2993 {
2994 /* FIXME(lsm): fix this. */
2995 return localtime(ptime, ptm);
2996 }
2997
2998
2999 static size_t
3000 strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
3001 {
3002 (void)mg_snprintf(NULL, dst, dst_size, "implement strftime() for WinCE");
3003 return 0;
3004 }
3005
3006
3007 #if defined(__MINGW32__)
3008 /* Enable unused function warning again */
3009 #pragma GCC diagnostic pop
3010 #endif
3011
3012 #endif
3013
3014
3015 /* Windows happily opens files with some garbage at the end of file name.
3016 * For example, fopen("a.cgi ", "r") on Windows successfully opens
3017 * "a.cgi", despite one would expect an error back.
3018 * This function returns non-0 if path ends with some garbage. */
3019 static int
3020 path_cannot_disclose_cgi(const char *path)
3021 {
3022 static const char *allowed_last_characters = "_-";
3023 int last = path[strlen(path) - 1];
3024 return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
3025 }
3026
3027
3028 static int
3029 mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3030 {
3031 wchar_t wbuf[PATH_MAX];
3032 WIN32_FILE_ATTRIBUTE_DATA info;
3033 time_t creation_time;
3034
3035 if (!filep) {
3036 return 0;
3037 }
3038 memset(filep, 0, sizeof(*filep));
3039
3040 if (conn && is_file_in_memory(conn, path, filep)) {
3041 /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
3042 * memset */
3043 filep->last_modified = time(NULL);
3044 /* last_modified = now ... assumes the file may change during runtime,
3045 * so every mg_fopen call may return different data */
3046 /* last_modified = conn->ctx.start_time;
3047 * May be used it the data does not change during runtime. This allows
3048 * browser caching. Since we do not know, we have to assume the file
3049 * in memory may change. */
3050 return 1;
3051 }
3052
3053 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3054 if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
3055 filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
3056 filep->last_modified =
3057 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
3058 info.ftLastWriteTime.dwHighDateTime);
3059
3060 /* On Windows, the file creation time can be higher than the
3061 * modification time, e.g. when a file is copied.
3062 * Since the Last-Modified timestamp is used for caching
3063 * it should be based on the most recent timestamp. */
3064 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
3065 info.ftCreationTime.dwHighDateTime);
3066 if (creation_time > filep->last_modified) {
3067 filep->last_modified = creation_time;
3068 }
3069
3070 filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3071 /* If file name is fishy, reset the file structure and return
3072 * error.
3073 * Note it is important to reset, not just return the error, cause
3074 * functions like is_file_opened() check the struct. */
3075 if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
3076 memset(filep, 0, sizeof(*filep));
3077 return 0;
3078 }
3079
3080 return 1;
3081 }
3082
3083 return 0;
3084 }
3085
3086
3087 static int
3088 mg_remove(const struct mg_connection *conn, const char *path)
3089 {
3090 wchar_t wbuf[PATH_MAX];
3091 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3092 return DeleteFileW(wbuf) ? 0 : -1;
3093 }
3094
3095
3096 static int
3097 mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
3098 {
3099 wchar_t wbuf[PATH_MAX];
3100 (void)mode;
3101 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3102 return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
3103 }
3104
3105
3106 /* Create substitutes for POSIX functions in Win32. */
3107
3108 #if defined(__MINGW32__)
3109 /* Show no warning in case system functions are not used. */
3110 #pragma GCC diagnostic push
3111 #pragma GCC diagnostic ignored "-Wunused-function"
3112 #endif
3113
3114
3115 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
3116 static DIR *
3117 mg_opendir(const struct mg_connection *conn, const char *name)
3118 {
3119 DIR *dir = NULL;
3120 wchar_t wpath[PATH_MAX];
3121 DWORD attrs;
3122
3123 if (name == NULL) {
3124 SetLastError(ERROR_BAD_ARGUMENTS);
3125 } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
3126 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3127 } else {
3128 path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
3129 attrs = GetFileAttributesW(wpath);
3130 if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
3131 == FILE_ATTRIBUTE_DIRECTORY)) {
3132 (void)wcscat(wpath, L"\\*");
3133 dir->handle = FindFirstFileW(wpath, &dir->info);
3134 dir->result.d_name[0] = '\0';
3135 } else {
3136 mg_free(dir);
3137 dir = NULL;
3138 }
3139 }
3140
3141 return dir;
3142 }
3143
3144
3145 static int
3146 mg_closedir(DIR *dir)
3147 {
3148 int result = 0;
3149
3150 if (dir != NULL) {
3151 if (dir->handle != INVALID_HANDLE_VALUE)
3152 result = FindClose(dir->handle) ? 0 : -1;
3153
3154 mg_free(dir);
3155 } else {
3156 result = -1;
3157 SetLastError(ERROR_BAD_ARGUMENTS);
3158 }
3159
3160 return result;
3161 }
3162
3163
3164 static struct dirent *
3165 mg_readdir(DIR *dir)
3166 {
3167 struct dirent *result = 0;
3168
3169 if (dir) {
3170 if (dir->handle != INVALID_HANDLE_VALUE) {
3171 result = &dir->result;
3172 (void)WideCharToMultiByte(CP_UTF8,
3173 0,
3174 dir->info.cFileName,
3175 -1,
3176 result->d_name,
3177 sizeof(result->d_name),
3178 NULL,
3179 NULL);
3180
3181 if (!FindNextFileW(dir->handle, &dir->info)) {
3182 (void)FindClose(dir->handle);
3183 dir->handle = INVALID_HANDLE_VALUE;
3184 }
3185
3186 } else {
3187 SetLastError(ERROR_FILE_NOT_FOUND);
3188 }
3189 } else {
3190 SetLastError(ERROR_BAD_ARGUMENTS);
3191 }
3192
3193 return result;
3194 }
3195
3196
3197 #ifndef HAVE_POLL
3198 static int
3199 poll(struct pollfd *pfd, unsigned int n, int milliseconds)
3200 {
3201 struct timeval tv;
3202 fd_set set;
3203 unsigned int i;
3204 int result;
3205 SOCKET maxfd = 0;
3206
3207 memset(&tv, 0, sizeof(tv));
3208 tv.tv_sec = milliseconds / 1000;
3209 tv.tv_usec = (milliseconds % 1000) * 1000;
3210 FD_ZERO(&set);
3211
3212 for (i = 0; i < n; i++) {
3213 FD_SET((SOCKET)pfd[i].fd, &set);
3214 pfd[i].revents = 0;
3215
3216 if (pfd[i].fd > maxfd) {
3217 maxfd = pfd[i].fd;
3218 }
3219 }
3220
3221 if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
3222 for (i = 0; i < n; i++) {
3223 if (FD_ISSET(pfd[i].fd, &set)) {
3224 pfd[i].revents = POLLIN;
3225 }
3226 }
3227 }
3228
3229 return result;
3230 }
3231 #endif /* HAVE_POLL */
3232
3233 #if defined(__MINGW32__)
3234 /* Enable unused function warning again */
3235 #pragma GCC diagnostic pop
3236 #endif
3237
3238
3239 static void
3240 set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
3241 {
3242 (void)conn; /* Unused. */
3243 (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
3244 }
3245
3246
3247 int
3248 mg_start_thread(mg_thread_func_t f, void *p)
3249 {
3250 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3251 /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384
3252 */
3253 return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
3254 == ((uintptr_t)(-1L)))
3255 ? -1
3256 : 0);
3257 #else
3258 return (
3259 (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
3260 ? -1
3261 : 0);
3262 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3263 }
3264
3265
3266 /* Start a thread storing the thread context. */
3267 static int
3268 mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
3269 void *p,
3270 pthread_t *threadidptr)
3271 {
3272 uintptr_t uip;
3273 HANDLE threadhandle;
3274 int result = -1;
3275
3276 uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
3277 threadhandle = (HANDLE)uip;
3278 if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
3279 *threadidptr = threadhandle;
3280 result = 0;
3281 }
3282
3283 return result;
3284 }
3285
3286
3287 /* Wait for a thread to finish. */
3288 static int
3289 mg_join_thread(pthread_t threadid)
3290 {
3291 int result;
3292 DWORD dwevent;
3293
3294 result = -1;
3295 dwevent = WaitForSingleObject(threadid, INFINITE);
3296 if (dwevent == WAIT_FAILED) {
3297 DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
3298 } else {
3299 if (dwevent == WAIT_OBJECT_0) {
3300 CloseHandle(threadid);
3301 result = 0;
3302 }
3303 }
3304
3305 return result;
3306 }
3307
3308 #if !defined(NO_SSL_DL)
3309 /* Create substitutes for POSIX functions in Win32. */
3310
3311 #if defined(__MINGW32__)
3312 /* Show no warning in case system functions are not used. */
3313 #pragma GCC diagnostic push
3314 #pragma GCC diagnostic ignored "-Wunused-function"
3315 #endif
3316
3317
3318 static HANDLE
3319 dlopen(const char *dll_name, int flags)
3320 {
3321 wchar_t wbuf[PATH_MAX];
3322 (void)flags;
3323 path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
3324 return LoadLibraryW(wbuf);
3325 }
3326
3327
3328 static int
3329 dlclose(void *handle)
3330 {
3331 int result;
3332
3333 if (FreeLibrary((HMODULE)handle) != 0) {
3334 result = 0;
3335 } else {
3336 result = -1;
3337 }
3338
3339 return result;
3340 }
3341
3342
3343 #if defined(__MINGW32__)
3344 /* Enable unused function warning again */
3345 #pragma GCC diagnostic pop
3346 #endif
3347
3348 #endif
3349
3350
3351 #if !defined(NO_CGI)
3352 #define SIGKILL (0)
3353
3354 static int
3355 kill(pid_t pid, int sig_num)
3356 {
3357 (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
3358 (void)CloseHandle((HANDLE)pid);
3359 return 0;
3360 }
3361
3362
3363 static void
3364 trim_trailing_whitespaces(char *s)
3365 {
3366 char *e = s + strlen(s) - 1;
3367 while (e > s && isspace(*(unsigned char *)e)) {
3368 *e-- = '\0';
3369 }
3370 }
3371
3372
3373 static pid_t
3374 spawn_process(struct mg_connection *conn,
3375 const char *prog,
3376 char *envblk,
3377 char *envp[],
3378 int fdin[2],
3379 int fdout[2],
3380 int fderr[2],
3381 const char *dir)
3382 {
3383 HANDLE me;
3384 char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
3385 cmdline[PATH_MAX], buf[PATH_MAX];
3386 int truncated;
3387 struct file file = STRUCT_FILE_INITIALIZER;
3388 STARTUPINFOA si;
3389 PROCESS_INFORMATION pi = {0};
3390
3391 (void)envp;
3392
3393 memset(&si, 0, sizeof(si));
3394 si.cb = sizeof(si);
3395
3396 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3397 si.wShowWindow = SW_HIDE;
3398
3399 me = GetCurrentProcess();
3400 DuplicateHandle(me,
3401 (HANDLE)_get_osfhandle(fdin[0]),
3402 me,
3403 &si.hStdInput,
3404 0,
3405 TRUE,
3406 DUPLICATE_SAME_ACCESS);
3407 DuplicateHandle(me,
3408 (HANDLE)_get_osfhandle(fdout[1]),
3409 me,
3410 &si.hStdOutput,
3411 0,
3412 TRUE,
3413 DUPLICATE_SAME_ACCESS);
3414 DuplicateHandle(me,
3415 (HANDLE)_get_osfhandle(fderr[1]),
3416 me,
3417 &si.hStdError,
3418 0,
3419 TRUE,
3420 DUPLICATE_SAME_ACCESS);
3421
3422 /* Mark handles that should not be inherited. See
3423 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
3424 */
3425 SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
3426 HANDLE_FLAG_INHERIT,
3427 0);
3428 SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
3429 HANDLE_FLAG_INHERIT,
3430 0);
3431 SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
3432 HANDLE_FLAG_INHERIT,
3433 0);
3434
3435 /* If CGI file is a script, try to read the interpreter line */
3436 interp = conn->ctx->config[CGI_INTERPRETER];
3437 if (interp == NULL) {
3438 buf[0] = buf[1] = '\0';
3439
3440 /* Read the first line of the script into the buffer */
3441 mg_snprintf(
3442 conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
3443
3444 if (truncated) {
3445 pi.hProcess = (pid_t)-1;
3446 goto spawn_cleanup;
3447 }
3448
3449 if (mg_fopen(conn, cmdline, "r", &file)) {
3450 p = (char *)file.membuf;
3451 mg_fgets(buf, sizeof(buf), &file, &p);
3452 mg_fclose(&file);
3453 buf[sizeof(buf) - 1] = '\0';
3454 }
3455
3456 if (buf[0] == '#' && buf[1] == '!') {
3457 trim_trailing_whitespaces(buf + 2);
3458 } else {
3459 buf[2] = '\0';
3460 }
3461 interp = buf + 2;
3462 }
3463
3464 if (interp[0] != '\0') {
3465 GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
3466 interp = full_interp;
3467 }
3468 GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
3469
3470 if (interp[0] != '\0') {
3471 mg_snprintf(conn,
3472 &truncated,
3473 cmdline,
3474 sizeof(cmdline),
3475 "\"%s\" \"%s\\%s\"",
3476 interp,
3477 full_dir,
3478 prog);
3479 } else {
3480 mg_snprintf(conn,
3481 &truncated,
3482 cmdline,
3483 sizeof(cmdline),
3484 "\"%s\\%s\"",
3485 full_dir,
3486 prog);
3487 }
3488
3489 if (truncated) {
3490 pi.hProcess = (pid_t)-1;
3491 goto spawn_cleanup;
3492 }
3493
3494 DEBUG_TRACE("Running [%s]", cmdline);
3495 if (CreateProcessA(NULL,
3496 cmdline,
3497 NULL,
3498 NULL,
3499 TRUE,
3500 CREATE_NEW_PROCESS_GROUP,
3501 envblk,
3502 NULL,
3503 &si,
3504 &pi) == 0) {
3505 mg_cry(
3506 conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
3507 pi.hProcess = (pid_t)-1;
3508 /* goto spawn_cleanup; */
3509 }
3510
3511 spawn_cleanup:
3512 (void)CloseHandle(si.hStdOutput);
3513 (void)CloseHandle(si.hStdError);
3514 (void)CloseHandle(si.hStdInput);
3515 if (pi.hThread != NULL) {
3516 (void)CloseHandle(pi.hThread);
3517 }
3518
3519 return (pid_t)pi.hProcess;
3520 }
3521 #endif /* !NO_CGI */
3522
3523
3524 static int
3525 set_non_blocking_mode(SOCKET sock)
3526 {
3527 unsigned long on = 1;
3528 return ioctlsocket(sock, (long)FIONBIO, &on);
3529 }
3530
3531 #else
3532
3533 static int
3534 mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3535 {
3536 struct stat st;
3537 if (!filep) {
3538 return 0;
3539 }
3540 memset(filep, 0, sizeof(*filep));
3541
3542 if (conn && is_file_in_memory(conn, path, filep)) {
3543 return 1;
3544 }
3545
3546 if (0 == stat(path, &st)) {
3547 filep->size = (uint64_t)(st.st_size);
3548 filep->last_modified = st.st_mtime;
3549 filep->is_directory = S_ISDIR(st.st_mode);
3550 return 1;
3551 }
3552
3553 return 0;
3554 }
3555
3556
3557 static void
3558 set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
3559 {
3560 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
3561 if (conn) {
3562 mg_cry(conn,
3563 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
3564 __func__,
3565 strerror(ERRNO));
3566 }
3567 }
3568 }
3569
3570
3571 int
3572 mg_start_thread(mg_thread_func_t func, void *param)
3573 {
3574 pthread_t thread_id;
3575 pthread_attr_t attr;
3576 int result;
3577
3578 (void)pthread_attr_init(&attr);
3579 (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3580
3581 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3582 /* Compile-time option to control stack size,
3583 * e.g. -DUSE_STACK_SIZE=16384 */
3584 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3585 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3586
3587 result = pthread_create(&thread_id, &attr, func, param);
3588 pthread_attr_destroy(&attr);
3589
3590 return result;
3591 }
3592
3593
3594 /* Start a thread storing the thread context. */
3595 static int
3596 mg_start_thread_with_id(mg_thread_func_t func,
3597 void *param,
3598 pthread_t *threadidptr)
3599 {
3600 pthread_t thread_id;
3601 pthread_attr_t attr;
3602 int result;
3603
3604 (void)pthread_attr_init(&attr);
3605
3606 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3607 /* Compile-time option to control stack size,
3608 * e.g. -DUSE_STACK_SIZE=16384 */
3609 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3610 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
3611
3612 result = pthread_create(&thread_id, &attr, func, param);
3613 pthread_attr_destroy(&attr);
3614 if ((result == 0) && (threadidptr != NULL)) {
3615 *threadidptr = thread_id;
3616 }
3617 return result;
3618 }
3619
3620
3621 /* Wait for a thread to finish. */
3622 static int
3623 mg_join_thread(pthread_t threadid)
3624 {
3625 int result;
3626
3627 result = pthread_join(threadid, NULL);
3628 return result;
3629 }
3630
3631
3632 #ifndef NO_CGI
3633 static pid_t
3634 spawn_process(struct mg_connection *conn,
3635 const char *prog,
3636 char *envblk,
3637 char *envp[],
3638 int fdin[2],
3639 int fdout[2],
3640 int fderr[2],
3641 const char *dir)
3642 {
3643 pid_t pid;
3644 const char *interp;
3645
3646 (void)envblk;
3647
3648 if (conn == NULL) {
3649 return 0;
3650 }
3651
3652 if ((pid = fork()) == -1) {
3653 /* Parent */
3654 send_http_error(conn,
3655 500,
3656 "Error: Creating CGI process\nfork(): %s",
3657 strerror(ERRNO));
3658 } else if (pid == 0) {
3659 /* Child */
3660 if (chdir(dir) != 0) {
3661 mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
3662 } else if (dup2(fdin[0], 0) == -1) {
3663 mg_cry(conn,
3664 "%s: dup2(%d, 0): %s",
3665 __func__,
3666 fdin[0],
3667 strerror(ERRNO));
3668 } else if (dup2(fdout[1], 1) == -1) {
3669 mg_cry(conn,
3670 "%s: dup2(%d, 1): %s",
3671 __func__,
3672 fdout[1],
3673 strerror(ERRNO));
3674 } else if (dup2(fderr[1], 2) == -1) {
3675 mg_cry(conn,
3676 "%s: dup2(%d, 2): %s",
3677 __func__,
3678 fderr[1],
3679 strerror(ERRNO));
3680 } else {
3681 /* Keep stderr and stdout in two different pipes.
3682 * Stdout will be sent back to the client,
3683 * stderr should go into a server error log. */
3684 (void)close(fdin[0]);
3685 (void)close(fdout[1]);
3686 (void)close(fderr[1]);
3687
3688 /* Close write end fdin and read end fdout and fderr */
3689 (void)close(fdin[1]);
3690 (void)close(fdout[0]);
3691 (void)close(fderr[0]);
3692
3693 /* After exec, all signal handlers are restored to their default
3694 * values, with one exception of SIGCHLD. According to
3695 * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
3696 * leave unchanged after exec if it was set to be ignored. Restore
3697 * it to default action. */
3698 signal(SIGCHLD, SIG_DFL);
3699
3700 interp = conn->ctx->config[CGI_INTERPRETER];
3701 if (interp == NULL) {
3702 (void)execle(prog, prog, NULL, envp);
3703 mg_cry(conn,
3704 "%s: execle(%s): %s",
3705 __func__,
3706 prog,
3707 strerror(ERRNO));
3708 } else {
3709 (void)execle(interp, interp, prog, NULL, envp);
3710 mg_cry(conn,
3711 "%s: execle(%s %s): %s",
3712 __func__,
3713 interp,
3714 prog,
3715 strerror(ERRNO));
3716 }
3717 }
3718 exit(EXIT_FAILURE);
3719 }
3720
3721 return pid;
3722 }
3723 #endif /* !NO_CGI */
3724
3725
3726 static int
3727 set_non_blocking_mode(SOCKET sock)
3728 {
3729 int flags;
3730
3731 flags = fcntl(sock, F_GETFL, 0);
3732 (void)fcntl(sock, F_SETFL, flags | O_NONBLOCK);
3733
3734 return 0;
3735 }
3736 #endif /* _WIN32 */
3737 /* End of initial operating system specific define block. */
3738
3739
3740 /* Get a random number (independent of C rand function) */
3741 static uint64_t
3742 get_random(void)
3743 {
3744 static uint64_t lfsr = 0; /* Linear feedback shift register */
3745 static uint64_t lcg = 0; /* Linear congruential generator */
3746 struct timespec now;
3747
3748 memset(&now, 0, sizeof(now));
3749 clock_gettime(CLOCK_MONOTONIC, &now);
3750
3751 if (lfsr == 0) {
3752 /* lfsr will be only 0 if has not been initialized,
3753 * so this code is called only once. */
3754 lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec)
3755 ^ ((uint64_t)(ptrdiff_t)&now) ^ (((uint64_t)time(NULL)) << 33);
3756 lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec
3757 + (uint64_t)(ptrdiff_t)&now;
3758 } else {
3759 /* Get the next step of both random number generators. */
3760 lfsr = (lfsr >> 1)
3761 | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
3762 << 63);
3763 lcg = lcg * 6364136223846793005 + 1442695040888963407;
3764 }
3765
3766 /* Combining two pseudo-random number generators and a high resolution part
3767 * of the current server time will make it hard (impossible?) to guess the
3768 * next number. */
3769 return (lfsr ^ lcg ^ (uint64_t)now.tv_nsec);
3770 }
3771
3772
3773 /* Write data to the IO channel - opened file descriptor, socket or SSL
3774 * descriptor. Return number of bytes written. */
3775 static int
3776 push(struct mg_context *ctx,
3777 FILE *fp,
3778 SOCKET sock,
3779 SSL *ssl,
3780 const char *buf,
3781 int len,
3782 double timeout)
3783 {
3784 struct timespec start, now;
3785 int n, err;
3786
3787 #ifdef _WIN32
3788 typedef int len_t;
3789 #else
3790 typedef size_t len_t;
3791 #endif
3792
3793 if (timeout > 0) {
3794 memset(&start, 0, sizeof(start));
3795 memset(&now, 0, sizeof(now));
3796 clock_gettime(CLOCK_MONOTONIC, &start);
3797 }
3798
3799 if (ctx == NULL) {
3800 return -1;
3801 }
3802
3803 #ifdef NO_SSL
3804 if (ssl) {
3805 return -1;
3806 }
3807 #endif
3808
3809 do {
3810
3811 #ifndef NO_SSL
3812 if (ssl != NULL) {
3813 n = SSL_write(ssl, buf, len);
3814 if (n <= 0) {
3815 err = SSL_get_error(ssl, n);
3816 if ((err == 5 /* SSL_ERROR_SYSCALL */) && (n == -1)) {
3817 err = ERRNO;
3818 } else {
3819 DEBUG_TRACE("SSL_write() failed, error %d", err);
3820 return -1;
3821 }
3822 } else {
3823 err = 0;
3824 }
3825 } else
3826 #endif
3827 if (fp != NULL) {
3828 n = (int)fwrite(buf, 1, (size_t)len, fp);
3829 if (ferror(fp)) {
3830 n = -1;
3831 err = ERRNO;
3832 } else {
3833 err = 0;
3834 }
3835 } else {
3836 n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
3837 err = (n < 0) ? ERRNO : 0;
3838 }
3839
3840 if (ctx->stop_flag) {
3841 return -1;
3842 }
3843
3844 if ((n > 0) || (n == 0 && len == 0)) {
3845 /* some data has been read, or no data was requested */
3846 return n;
3847 }
3848 if (n == 0) {
3849 /* shutdown of the socket at client side */
3850 return -1;
3851 }
3852 if (n < 0) {
3853 /* socket error - check errno */
3854 DEBUG_TRACE("send() failed, error %d", err);
3855
3856 /* TODO: error handling depending on the error code.
3857 * These codes are different between Windows and Linux.
3858 */
3859 return -1;
3860 }
3861
3862 /* This code is not reached in the moment.
3863 * ==> Fix the TODOs above first. */
3864
3865 if (timeout > 0) {
3866 clock_gettime(CLOCK_MONOTONIC, &now);
3867 }
3868
3869 } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
3870
3871 (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
3872 used */
3873
3874 return -1;
3875 }
3876
3877
3878 static int64_t
3879 push_all(struct mg_context *ctx,
3880 FILE *fp,
3881 SOCKET sock,
3882 SSL *ssl,
3883 const char *buf,
3884 int64_t len)
3885 {
3886 double timeout = -1.0;
3887 int64_t n, nwritten = 0;
3888
3889 if (ctx == NULL) {
3890 return -1;
3891 }
3892
3893 if (ctx->config[REQUEST_TIMEOUT]) {
3894 timeout = atoi(ctx->config[REQUEST_TIMEOUT]) / 1000.0;
3895 }
3896
3897 while (len > 0 && ctx->stop_flag == 0) {
3898 n = push(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
3899 if (n < 0) {
3900 if (nwritten == 0) {
3901 nwritten = n; /* Propagate the error */
3902 }
3903 break;
3904 } else if (n == 0) {
3905 break; /* No more data to write */
3906 } else {
3907 nwritten += n;
3908 len -= n;
3909 }
3910 }
3911
3912 return nwritten;
3913 }
3914
3915
3916 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
3917 * Return negative value on error, or number of bytes read on success. */
3918 static int
3919 pull(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
3920 {
3921 int nread, err;
3922 struct timespec start, now;
3923
3924 #ifdef _WIN32
3925 typedef int len_t;
3926 #else
3927 typedef size_t len_t;
3928 #endif
3929
3930 if (timeout > 0) {
3931 memset(&start, 0, sizeof(start));
3932 memset(&now, 0, sizeof(now));
3933 clock_gettime(CLOCK_MONOTONIC, &start);
3934 }
3935
3936 do {
3937 if (fp != NULL) {
3938 /* Use read() instead of fread(), because if we're reading from the
3939 * CGI pipe, fread() may block until IO buffer is filled up. We
3940 * cannot afford to block and must pass all read bytes immediately
3941 * to the client. */
3942 nread = (int)read(fileno(fp), buf, (size_t)len);
3943 err = (nread < 0) ? ERRNO : 0;
3944
3945 #ifndef NO_SSL
3946 } else if (conn->ssl != NULL) {
3947 nread = SSL_read(conn->ssl, buf, len);
3948 if (nread <= 0) {
3949 err = SSL_get_error(conn->ssl, nread);
3950 if ((err == 5 /* SSL_ERROR_SYSCALL */) && (nread == -1)) {
3951 err = ERRNO;
3952 } else {
3953 DEBUG_TRACE("SSL_read() failed, error %d", err);
3954 return -1;
3955 }
3956 } else {
3957 err = 0;
3958 }
3959 #endif
3960
3961 } else {
3962 nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
3963 err = (nread < 0) ? ERRNO : 0;
3964 }
3965
3966 if (conn->ctx->stop_flag) {
3967 return -1;
3968 }
3969
3970 if ((nread > 0) || (nread == 0 && len == 0)) {
3971 /* some data has been read, or no data was requested */
3972 return nread;
3973 }
3974 if (nread == 0) {
3975 /* shutdown of the socket at client side */
3976 return -1;
3977 }
3978 if (nread < 0) {
3979 /* socket error - check errno */
3980 #ifdef _WIN32
3981 if (err == WSAEWOULDBLOCK) {
3982 /* standard case if called from close_socket_gracefully */
3983 return -1;
3984 } else if (err == WSAETIMEDOUT) {
3985 /* timeout is handled by the while loop */
3986 } else {
3987 DEBUG_TRACE("recv() failed, error %d", err);
3988 return -1;
3989 }
3990 #else
3991 /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
3992 * if the timeout is reached and if the socket was set to non-
3993 * blocking in close_socket_gracefully, so we can not distinguish
3994 * here. We have to wait for the timeout in both cases for now.
3995 */
3996 if (err == EAGAIN || err == EWOULDBLOCK || err == EINTR) {
3997 /* EAGAIN/EWOULDBLOCK:
3998 * standard case if called from close_socket_gracefully
3999 * => should return -1 */
4000 /* or timeout occured
4001 * => the code must stay in the while loop */
4002
4003 /* EINTR can be generated on a socket with a timeout set even
4004 * when SA_RESTART is effective for all relevant signals
4005 * (see signal(7)).
4006 * => stay in the while loop */
4007 } else {
4008 DEBUG_TRACE("recv() failed, error %d", err);
4009 return -1;
4010 }
4011 #endif
4012 }
4013 if (timeout > 0) {
4014 clock_gettime(CLOCK_MONOTONIC, &now);
4015 }
4016 } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
4017
4018 /* Timeout occured, but no data available. */
4019 return -1;
4020 }
4021
4022
4023 static int
4024 pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
4025 {
4026 int n, nread = 0;
4027 double timeout = -1.0;
4028
4029 if (conn->ctx->config[REQUEST_TIMEOUT]) {
4030 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
4031 }
4032
4033 while (len > 0 && conn->ctx->stop_flag == 0) {
4034 n = pull(fp, conn, buf + nread, len, timeout);
4035 if (n < 0) {
4036 if (nread == 0) {
4037 nread = n; /* Propagate the error */
4038 }
4039 break;
4040 } else if (n == 0) {
4041 break; /* No more data to read */
4042 } else {
4043 conn->consumed_content += n;
4044 nread += n;
4045 len -= n;
4046 }
4047 }
4048
4049 return nread;
4050 }
4051
4052
4053 static void
4054 discard_unread_request_data(struct mg_connection *conn)
4055 {
4056 char buf[MG_BUF_LEN];
4057 size_t to_read;
4058 int nread;
4059
4060 if (conn == NULL) {
4061 return;
4062 }
4063
4064 to_read = sizeof(buf);
4065
4066 if (conn->is_chunked) {
4067 /* Chunked encoding: 1=chunk not read completely, 2=chunk read
4068 * completely */
4069 while (conn->is_chunked == 1) {
4070 nread = mg_read(conn, buf, to_read);
4071 if (nread <= 0) {
4072 break;
4073 }
4074 }
4075
4076 } else {
4077 /* Not chunked: content length is known */
4078 while (conn->consumed_content < conn->content_len) {
4079 if (to_read
4080 > (size_t)(conn->content_len - conn->consumed_content)) {
4081 to_read = (size_t)(conn->content_len - conn->consumed_content);
4082 }
4083
4084 nread = mg_read(conn, buf, to_read);
4085 if (nread <= 0) {
4086 break;
4087 }
4088 }
4089 }
4090 }
4091
4092
4093 static int
4094 mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
4095 {
4096 int64_t n, buffered_len, nread;
4097 int64_t len64 =
4098 (int64_t)(len > INT_MAX ? INT_MAX : len); /* since the return value is
4099 * int, we may not read more
4100 * bytes */
4101 const char *body;
4102
4103 if (conn == NULL) {
4104 return 0;
4105 }
4106
4107 /* If Content-Length is not set for a PUT or POST request, read until
4108 * socket is closed */
4109 if (conn->consumed_content == 0 && conn->content_len == -1) {
4110 conn->content_len = INT64_MAX;
4111 conn->must_close = 1;
4112 }
4113
4114 nread = 0;
4115 if (conn->consumed_content < conn->content_len) {
4116 /* Adjust number of bytes to read. */
4117 int64_t left_to_read = conn->content_len - conn->consumed_content;
4118 if (left_to_read < len64) {
4119 /* Do not read more than the total content length of the request.
4120 */
4121 len64 = left_to_read;
4122 }
4123
4124 /* Return buffered data */
4125 buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
4126 - conn->consumed_content;
4127 if (buffered_len > 0) {
4128 if (len64 < buffered_len) {
4129 buffered_len = len64;
4130 }
4131 body = conn->buf + conn->request_len + conn->consumed_content;
4132 memcpy(buf, body, (size_t)buffered_len);
4133 len64 -= buffered_len;
4134 conn->consumed_content += buffered_len;
4135 nread += buffered_len;
4136 buf = (char *)buf + buffered_len;
4137 }
4138
4139 /* We have returned all buffered data. Read new data from the remote
4140 * socket.
4141 */
4142 if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
4143 nread += n;
4144 } else {
4145 nread = (nread > 0 ? nread : n);
4146 }
4147 }
4148 return (int)nread;
4149 }
4150
4151
4152 static char
4153 mg_getc(struct mg_connection *conn)
4154 {
4155 char c;
4156 if (conn == NULL) {
4157 return 0;
4158 }
4159 conn->content_len++;
4160 if (mg_read_inner(conn, &c, 1) <= 0) {
4161 return (char)0;
4162 }
4163 return c;
4164 }
4165
4166
4167 int
4168 mg_read(struct mg_connection *conn, void *buf, size_t len)
4169 {
4170 if (len > INT_MAX) {
4171 len = INT_MAX;
4172 }
4173
4174 if (conn == NULL) {
4175 return 0;
4176 }
4177
4178 if (conn->is_chunked) {
4179 size_t all_read = 0;
4180
4181 while (len > 0) {
4182
4183 if (conn->is_chunked == 2) {
4184 /* No more data left to read */
4185 return 0;
4186 }
4187
4188 if (conn->chunk_remainder) {
4189 /* copy from the remainder of the last received chunk */
4190 long read_ret;
4191 size_t read_now =
4192 ((conn->chunk_remainder > len) ? (len)
4193 : (conn->chunk_remainder));
4194
4195 conn->content_len += (int)read_now;
4196 read_ret =
4197 mg_read_inner(conn, (char *)buf + all_read, read_now);
4198 all_read += (size_t)read_ret;
4199
4200 conn->chunk_remainder -= read_now;
4201 len -= read_now;
4202
4203 if (conn->chunk_remainder == 0) {
4204 /* the rest of the data in the current chunk has been read
4205 */
4206 if ((mg_getc(conn) != '\r') || (mg_getc(conn) != '\n')) {
4207 /* Protocol violation */
4208 return -1;
4209 }
4210 }
4211
4212 } else {
4213 /* fetch a new chunk */
4214 int i = 0;
4215 char lenbuf[64];
4216 char *end = 0;
4217 unsigned long chunkSize = 0;
4218
4219 for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
4220 lenbuf[i] = mg_getc(conn);
4221 if (i > 0 && lenbuf[i] == '\r' && lenbuf[i - 1] != '\r') {
4222 continue;
4223 }
4224 if (i > 1 && lenbuf[i] == '\n' && lenbuf[i - 1] == '\r') {
4225 lenbuf[i + 1] = 0;
4226 chunkSize = strtoul(lenbuf, &end, 16);
4227 if (chunkSize == 0) {
4228 /* regular end of content */
4229 conn->is_chunked = 2;
4230 }
4231 break;
4232 }
4233 if (!isalnum(lenbuf[i])) {
4234 /* illegal character for chunk length */
4235 return -1;
4236 }
4237 }
4238 if ((end == NULL) || (*end != '\r')) {
4239 /* chunksize not set correctly */
4240 return -1;
4241 }
4242 if (chunkSize == 0) {
4243 break;
4244 }
4245
4246 conn->chunk_remainder = chunkSize;
4247 }
4248 }
4249
4250 return (int)all_read;
4251 }
4252 return mg_read_inner(conn, buf, len);
4253 }
4254
4255
4256 int
4257 mg_write(struct mg_connection *conn, const void *buf, size_t len)
4258 {
4259 time_t now;
4260 int64_t n, total, allowed;
4261
4262 if (conn == NULL) {
4263 return 0;
4264 }
4265
4266 if (conn->throttle > 0) {
4267 if ((now = time(NULL)) != conn->last_throttle_time) {
4268 conn->last_throttle_time = now;
4269 conn->last_throttle_bytes = 0;
4270 }
4271 allowed = conn->throttle - conn->last_throttle_bytes;
4272 if (allowed > (int64_t)len) {
4273 allowed = (int64_t)len;
4274 }
4275 if ((total = push_all(conn->ctx,
4276 NULL,
4277 conn->client.sock,
4278 conn->ssl,
4279 (const char *)buf,
4280 (int64_t)allowed)) == allowed) {
4281 buf = (const char *)buf + total;
4282 conn->last_throttle_bytes += total;
4283 while (total < (int64_t)len && conn->ctx->stop_flag == 0) {
4284 allowed = conn->throttle > (int64_t)len - total
4285 ? (int64_t)len - total
4286 : conn->throttle;
4287 if ((n = push_all(conn->ctx,
4288 NULL,
4289 conn->client.sock,
4290 conn->ssl,
4291 (const char *)buf,
4292 (int64_t)allowed)) != allowed) {
4293 break;
4294 }
4295 sleep(1);
4296 conn->last_throttle_bytes = allowed;
4297 conn->last_throttle_time = time(NULL);
4298 buf = (const char *)buf + n;
4299 total += n;
4300 }
4301 }
4302 } else {
4303 total = push_all(conn->ctx,
4304 NULL,
4305 conn->client.sock,
4306 conn->ssl,
4307 (const char *)buf,
4308 (int64_t)len);
4309 }
4310 return (int)total;
4311 }
4312
4313
4314 /* Alternative alloc_vprintf() for non-compliant C runtimes */
4315 static int
4316 alloc_vprintf2(char **buf, const char *fmt, va_list ap)
4317 {
4318 va_list ap_copy;
4319 size_t size = MG_BUF_LEN / 4;
4320 int len = -1;
4321
4322 *buf = NULL;
4323 while (len < 0) {
4324 if (*buf) {
4325 mg_free(*buf);
4326 }
4327
4328 size *= 4;
4329 *buf = (char *)mg_malloc(size);
4330 if (!*buf) {
4331 break;
4332 }
4333
4334 va_copy(ap_copy, ap);
4335 len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
4336 va_end(ap_copy);
4337 (*buf)[size - 1] = 0;
4338 }
4339
4340 return len;
4341 }
4342
4343
4344 /* Print message to buffer. If buffer is large enough to hold the message,
4345 * return buffer. If buffer is to small, allocate large enough buffer on heap,
4346 * and return allocated buffer. */
4347 static int
4348 alloc_vprintf(char **out_buf,
4349 char *prealloc_buf,
4350 size_t prealloc_size,
4351 const char *fmt,
4352 va_list ap)
4353 {
4354 va_list ap_copy;
4355 int len;
4356
4357 /* Windows is not standard-compliant, and vsnprintf() returns -1 if
4358 * buffer is too small. Also, older versions of msvcrt.dll do not have
4359 * _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
4360 * Therefore, we make two passes: on first pass, get required message
4361 * length.
4362 * On second pass, actually print the message. */
4363 va_copy(ap_copy, ap);
4364 len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
4365 va_end(ap_copy);
4366
4367 if (len < 0) {
4368 /* C runtime is not standard compliant, vsnprintf() returned -1.
4369 * Switch to alternative code path that uses incremental allocations.
4370 */
4371 va_copy(ap_copy, ap);
4372 len = alloc_vprintf2(out_buf, fmt, ap);
4373 va_end(ap_copy);
4374
4375 } else if ((size_t)(len) >= prealloc_size) {
4376 /* The pre-allocated buffer not large enough. */
4377 /* Allocate a new buffer. */
4378 *out_buf = (char *)mg_malloc((size_t)(len) + 1);
4379 if (!*out_buf) {
4380 /* Allocation failed. Return -1 as "out of memory" error. */
4381 return -1;
4382 }
4383 /* Buffer allocation successful. Store the string there. */
4384 va_copy(ap_copy, ap);
4385 IGNORE_UNUSED_RESULT(
4386 vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
4387 va_end(ap_copy);
4388
4389 } else {
4390 /* The pre-allocated buffer is large enough.
4391 * Use it to store the string and return the address. */
4392 va_copy(ap_copy, ap);
4393 IGNORE_UNUSED_RESULT(
4394 vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
4395 va_end(ap_copy);
4396 *out_buf = prealloc_buf;
4397 }
4398
4399 return len;
4400 }
4401
4402
4403 static int
4404 mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
4405 {
4406 char mem[MG_BUF_LEN];
4407 char *buf = NULL;
4408 int len;
4409
4410 if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
4411 len = mg_write(conn, buf, (size_t)len);
4412 }
4413 if (buf != mem && buf != NULL) {
4414 mg_free(buf);
4415 }
4416
4417 return len;
4418 }
4419
4420
4421 int
4422 mg_printf(struct mg_connection *conn, const char *fmt, ...)
4423 {
4424 va_list ap;
4425 int result;
4426
4427 va_start(ap, fmt);
4428 result = mg_vprintf(conn, fmt, ap);
4429 va_end(ap);
4430
4431 return result;
4432 }
4433
4434
4435 int
4436 mg_url_decode(const char *src,
4437 int src_len,
4438 char *dst,
4439 int dst_len,
4440 int is_form_url_encoded)
4441 {
4442 int i, j, a, b;
4443 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
4444
4445 for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
4446 if (i < src_len - 2 && src[i] == '%'
4447 && isxdigit(*(const unsigned char *)(src + i + 1))
4448 && isxdigit(*(const unsigned char *)(src + i + 2))) {
4449 a = tolower(*(const unsigned char *)(src + i + 1));
4450 b = tolower(*(const unsigned char *)(src + i + 2));
4451 dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
4452 i += 2;
4453 } else if (is_form_url_encoded && src[i] == '+') {
4454 dst[j] = ' ';
4455 } else {
4456 dst[j] = src[i];
4457 }
4458 }
4459
4460 dst[j] = '\0'; /* Null-terminate the destination */
4461
4462 return i >= src_len ? j : -1;
4463 }
4464
4465
4466 int
4467 mg_get_var(const char *data,
4468 size_t data_len,
4469 const char *name,
4470 char *dst,
4471 size_t dst_len)
4472 {
4473 return mg_get_var2(data, data_len, name, dst, dst_len, 0);
4474 }
4475
4476
4477 int
4478 mg_get_var2(const char *data,
4479 size_t data_len,
4480 const char *name,
4481 char *dst,
4482 size_t dst_len,
4483 size_t occurrence)
4484 {
4485 const char *p, *e, *s;
4486 size_t name_len;
4487 int len;
4488
4489 if (dst == NULL || dst_len == 0) {
4490 len = -2;
4491 } else if (data == NULL || name == NULL || data_len == 0) {
4492 len = -1;
4493 dst[0] = '\0';
4494 } else {
4495 name_len = strlen(name);
4496 e = data + data_len;
4497 len = -1;
4498 dst[0] = '\0';
4499
4500 /* data is "var1=val1&var2=val2...". Find variable first */
4501 for (p = data; p + name_len < e; p++) {
4502 if ((p == data || p[-1] == '&') && p[name_len] == '='
4503 && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
4504 /* Point p to variable value */
4505 p += name_len + 1;
4506
4507 /* Point s to the end of the value */
4508 s = (const char *)memchr(p, '&', (size_t)(e - p));
4509 if (s == NULL) {
4510 s = e;
4511 }
4512 /* assert(s >= p); */
4513 if (s < p) {
4514 return -3;
4515 }
4516
4517 /* Decode variable into destination buffer */
4518 len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
4519
4520 /* Redirect error code from -1 to -2 (destination buffer too
4521 * small). */
4522 if (len == -1) {
4523 len = -2;
4524 }
4525 break;
4526 }
4527 }
4528 }
4529
4530 return len;
4531 }
4532
4533
4534 int
4535 mg_get_cookie(const char *cookie_header,
4536 const char *var_name,
4537 char *dst,
4538 size_t dst_size)
4539 {
4540 const char *s, *p, *end;
4541 int name_len, len = -1;
4542
4543 if (dst == NULL || dst_size == 0) {
4544 len = -2;
4545 } else if (var_name == NULL || (s = cookie_header) == NULL) {
4546 len = -1;
4547 dst[0] = '\0';
4548 } else {
4549 name_len = (int)strlen(var_name);
4550 end = s + strlen(s);
4551 dst[0] = '\0';
4552
4553 for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
4554 if (s[name_len] == '=') {
4555 s += name_len + 1;
4556 if ((p = strchr(s, ' ')) == NULL) {
4557 p = end;
4558 }
4559 if (p[-1] == ';') {
4560 p--;
4561 }
4562 if (*s == '"' && p[-1] == '"' && p > s + 1) {
4563 s++;
4564 p--;
4565 }
4566 if ((size_t)(p - s) < dst_size) {
4567 len = (int)(p - s);
4568 mg_strlcpy(dst, s, (size_t)len + 1);
4569 } else {
4570 len = -3;
4571 }
4572 break;
4573 }
4574 }
4575 }
4576 return len;
4577 }
4578
4579
4580 #if defined(USE_WEBSOCKET) || defined(USE_LUA)
4581 static void
4582 base64_encode(const unsigned char *src, int src_len, char *dst)
4583 {
4584 static const char *b64 =
4585 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4586 int i, j, a, b, c;
4587
4588 for (i = j = 0; i < src_len; i += 3) {
4589 a = src[i];
4590 b = i + 1 >= src_len ? 0 : src[i + 1];
4591 c = i + 2 >= src_len ? 0 : src[i + 2];
4592
4593 dst[j++] = b64[a >> 2];
4594 dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
4595 if (i + 1 < src_len) {
4596 dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
4597 }
4598 if (i + 2 < src_len) {
4599 dst[j++] = b64[c & 63];
4600 }
4601 }
4602 while (j % 4 != 0) {
4603 dst[j++] = '=';
4604 }
4605 dst[j++] = '\0';
4606 }
4607 #endif
4608
4609
4610 #if defined(USE_LUA)
4611 static unsigned char
4612 b64reverse(char letter)
4613 {
4614 if (letter >= 'A' && letter <= 'Z') {
4615 return letter - 'A';
4616 }
4617 if (letter >= 'a' && letter <= 'z') {
4618 return letter - 'a' + 26;
4619 }
4620 if (letter >= '0' && letter <= '9') {
4621 return letter - '0' + 52;
4622 }
4623 if (letter == '+') {
4624 return 62;
4625 }
4626 if (letter == '/') {
4627 return 63;
4628 }
4629 if (letter == '=') {
4630 return 255; /* normal end */
4631 }
4632 return 254; /* error */
4633 }
4634
4635
4636 static int
4637 base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
4638 {
4639 int i;
4640 unsigned char a, b, c, d;
4641
4642 *dst_len = 0;
4643
4644 for (i = 0; i < src_len; i += 4) {
4645 a = b64reverse(src[i]);
4646 if (a >= 254) {
4647 return i;
4648 }
4649
4650 b = b64reverse(i + 1 >= src_len ? 0 : src[i + 1]);
4651 if (b >= 254) {
4652 return i + 1;
4653 }
4654
4655 c = b64reverse(i + 2 >= src_len ? 0 : src[i + 2]);
4656 if (c == 254) {
4657 return i + 2;
4658 }
4659
4660 d = b64reverse(i + 3 >= src_len ? 0 : src[i + 3]);
4661 if (d == 254) {
4662 return i + 3;
4663 }
4664
4665 dst[(*dst_len)++] = (a << 2) + (b >> 4);
4666 if (c != 255) {
4667 dst[(*dst_len)++] = (b << 4) + (c >> 2);
4668 if (d != 255) {
4669 dst[(*dst_len)++] = (c << 6) + d;
4670 }
4671 }
4672 }
4673 return -1;
4674 }
4675 #endif
4676
4677
4678 static int
4679 is_put_or_delete_method(const struct mg_connection *conn)
4680 {
4681 if (conn) {
4682 const char *s = conn->request_info.request_method;
4683 return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
4684 || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
4685 }
4686 return 0;
4687 }
4688
4689
4690 static void
4691 interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */
4692 char *filename, /* out: filename */
4693 size_t filename_buf_len, /* in: size of filename buffer */
4694 struct file *filep, /* out: file structure */
4695 int *is_found, /* out: file is found (directly) */
4696 int *is_script_resource, /* out: handled by a script? */
4697 int *is_websocket_request, /* out: websocket connetion? */
4698 int *is_put_or_delete_request /* out: put/delete a file? */
4699 )
4700 {
4701 /* TODO (high): Restructure this function */
4702
4703 #if !defined(NO_FILES)
4704 const char *uri = conn->request_info.local_uri;
4705 const char *root = conn->ctx->config[DOCUMENT_ROOT];
4706 const char *rewrite;
4707 struct vec a, b;
4708 int match_len;
4709 char gz_path[PATH_MAX];
4710 char const *accept_encoding;
4711 int truncated;
4712 #if !defined(NO_CGI) || defined(USE_LUA)
4713 char *p;
4714 #endif
4715 #else
4716 (void)filename_buf_len; /* unused if NO_FILES is defined */
4717 #endif
4718
4719 memset(filep, 0, sizeof(*filep));
4720 *filename = 0;
4721 *is_found = 0;
4722 *is_script_resource = 0;
4723 *is_put_or_delete_request = is_put_or_delete_method(conn);
4724
4725 #if defined(USE_WEBSOCKET)
4726 *is_websocket_request = is_websocket_protocol(conn);
4727 #if !defined(NO_FILES)
4728 if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
4729 root = conn->ctx->config[WEBSOCKET_ROOT];
4730 }
4731 #endif /* !NO_FILES */
4732 #else /* USE_WEBSOCKET */
4733 *is_websocket_request = 0;
4734 #endif /* USE_WEBSOCKET */
4735
4736 #if !defined(NO_FILES)
4737 /* Note that root == NULL is a regular use case here. This occurs,
4738 * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
4739 * config is not required. */
4740 if (root == NULL) {
4741 /* all file related outputs have already been set to 0, just return
4742 */
4743 return;
4744 }
4745
4746 /* Using buf_len - 1 because memmove() for PATH_INFO may shift part
4747 * of the path one byte on the right.
4748 * If document_root is NULL, leave the file empty. */
4749 mg_snprintf(
4750 conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
4751
4752 if (truncated) {
4753 goto interpret_cleanup;
4754 }
4755
4756 rewrite = conn->ctx->config[REWRITE];
4757 while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
4758 if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
4759 mg_snprintf(conn,
4760 &truncated,
4761 filename,
4762 filename_buf_len - 1,
4763 "%.*s%s",
4764 (int)b.len,
4765 b.ptr,
4766 uri + match_len);
4767 break;
4768 }
4769 }
4770
4771 if (truncated) {
4772 goto interpret_cleanup;
4773 }
4774
4775 /* Local file path and name, corresponding to requested URI
4776 * is now stored in "filename" variable. */
4777 if (mg_stat(conn, filename, filep)) {
4778 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4779 /* File exists. Check if it is a script type. */
4780 if (0
4781 #if !defined(NO_CGI)
4782 || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4783 strlen(conn->ctx->config[CGI_EXTENSIONS]),
4784 filename) > 0
4785 #endif
4786 #if defined(USE_LUA)
4787 || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4788 strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4789 filename) > 0
4790 #endif
4791 #if defined(USE_DUKTAPE)
4792 || match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4793 strlen(
4794 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4795 filename) > 0
4796 #endif
4797 ) {
4798 /* The request addresses a CGI script or a Lua script. The URI
4799 * corresponds to the script itself (like /path/script.cgi),
4800 * and there is no additional resource path
4801 * (like /path/script.cgi/something).
4802 * Requests that modify (replace or delete) a resource, like
4803 * PUT and DELETE requests, should replace/delete the script
4804 * file.
4805 * Requests that read or write from/to a resource, like GET and
4806 * POST requests, should call the script and return the
4807 * generated response. */
4808 *is_script_resource = !*is_put_or_delete_request;
4809 }
4810 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4811 *is_found = 1;
4812 return;
4813 }
4814
4815 /* If we can't find the actual file, look for the file
4816 * with the same name but a .gz extension. If we find it,
4817 * use that and set the gzipped flag in the file struct
4818 * to indicate that the response need to have the content-
4819 * encoding: gzip header.
4820 * We can only do this if the browser declares support. */
4821 if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
4822 if (strstr(accept_encoding, "gzip") != NULL) {
4823 mg_snprintf(
4824 conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
4825
4826 if (truncated) {
4827 goto interpret_cleanup;
4828 }
4829
4830 if (mg_stat(conn, gz_path, filep)) {
4831 if (filep) {
4832 filep->gzipped = 1;
4833 *is_found = 1;
4834 }
4835 /* Currently gz files can not be scripts. */
4836 return;
4837 }
4838 }
4839 }
4840
4841 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4842 /* Support PATH_INFO for CGI scripts. */
4843 for (p = filename + strlen(filename); p > filename + 1; p--) {
4844 if (*p == '/') {
4845 *p = '\0';
4846 if ((0
4847 #if !defined(NO_CGI)
4848 || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4849 strlen(conn->ctx->config[CGI_EXTENSIONS]),
4850 filename) > 0
4851 #endif
4852 #if defined(USE_LUA)
4853 || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4854 strlen(
4855 conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4856 filename) > 0
4857 #endif
4858 #if defined(USE_DUKTAPE)
4859 || match_prefix(
4860 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4861 strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4862 filename) > 0
4863 #endif
4864 ) && mg_stat(conn, filename, filep)) {
4865 /* Shift PATH_INFO block one character right, e.g.
4866 * "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
4867 * conn->path_info is pointing to the local variable "path"
4868 * declared in handle_request(), so PATH_INFO is not valid
4869 * after handle_request returns. */
4870 conn->path_info = p + 1;
4871 memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
4872 * trailing \0 */
4873 p[1] = '/';
4874 *is_script_resource = 1;
4875 break;
4876 } else {
4877 *p = '/';
4878 }
4879 }
4880 }
4881 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4882 #endif /* !defined(NO_FILES) */
4883 return;
4884
4885 #if !defined(NO_FILES)
4886 /* Reset all outputs */
4887 interpret_cleanup:
4888 memset(filep, 0, sizeof(*filep));
4889 *filename = 0;
4890 *is_found = 0;
4891 *is_script_resource = 0;
4892 *is_websocket_request = 0;
4893 *is_put_or_delete_request = 0;
4894 #endif /* !defined(NO_FILES) */
4895 }
4896
4897
4898 /* Check whether full request is buffered. Return:
4899 * -1 if request is malformed
4900 * 0 if request is not yet fully buffered
4901 * >0 actual request length, including last \r\n\r\n */
4902 static int
4903 get_request_len(const char *buf, int buflen)
4904 {
4905 const char *s, *e;
4906 int len = 0;
4907 int in_content = 0;
4908
4909 for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++) {
4910 /* Control characters are not allowed but >=128 is. */
4911 if (!in_content && !isprint(*(const unsigned char *)s) && *s != '\r'
4912 && *s != '\n'
4913 && *(const unsigned char *)s < 128) {
4914 len = -1;
4915 break; /* [i_a] abort scan as soon as one malformed character is
4916 * found; */
4917 /* don't let subsequent \r\n\r\n win us over anyhow */
4918 } else if (s[0] == '\n' && s[1] == '\n') {
4919 len = (int)(s - buf) + 2;
4920 } else if (s[0] == '\n' && &s[1] < e && s[1] == '\r' && s[2] == '\n') {
4921 len = (int)(s - buf) + 3;
4922 in_content = 0;
4923 }
4924
4925 if (!in_content && *s == ':') {
4926 in_content = 1;
4927 }
4928 }
4929
4930 return len;
4931 }
4932
4933
4934 #if !defined(NO_CACHING)
4935 /* Convert month to the month number. Return -1 on error, or month number */
4936 static int
4937 get_month_index(const char *s)
4938 {
4939 size_t i;
4940
4941 for (i = 0; i < ARRAY_SIZE(month_names); i++) {
4942 if (!strcmp(s, month_names[i])) {
4943 return (int)i;
4944 }
4945 }
4946
4947 return -1;
4948 }
4949
4950
4951 /* Parse UTC date-time string, and return the corresponding time_t value. */
4952 static time_t
4953 parse_date_string(const char *datetime)
4954 {
4955 char month_str[32] = {0};
4956 int second, minute, hour, day, month, year;
4957 time_t result = (time_t)0;
4958 struct tm tm;
4959
4960 if ((sscanf(datetime,
4961 "%d/%3s/%d %d:%d:%d",
4962 &day,
4963 month_str,
4964 &year,
4965 &hour,
4966 &minute,
4967 &second) == 6) || (sscanf(datetime,
4968 "%d %3s %d %d:%d:%d",
4969 &day,
4970 month_str,
4971 &year,
4972 &hour,
4973 &minute,
4974 &second) == 6)
4975 || (sscanf(datetime,
4976 "%*3s, %d %3s %d %d:%d:%d",
4977 &day,
4978 month_str,
4979 &year,
4980 &hour,
4981 &minute,
4982 &second) == 6) || (sscanf(datetime,
4983 "%d-%3s-%d %d:%d:%d",
4984 &day,
4985 month_str,
4986 &year,
4987 &hour,
4988 &minute,
4989 &second) == 6)) {
4990 month = get_month_index(month_str);
4991 if ((month >= 0) && (year >= 1970)) {
4992 memset(&tm, 0, sizeof(tm));
4993 tm.tm_year = year - 1900;
4994 tm.tm_mon = month;
4995 tm.tm_mday = day;
4996 tm.tm_hour = hour;
4997 tm.tm_min = minute;
4998 tm.tm_sec = second;
4999 result = timegm(&tm);
5000 }
5001 }
5002
5003 return result;
5004 }
5005 #endif /* !NO_CACHING */
5006
5007
5008 /* Protect against directory disclosure attack by removing '..',
5009 * excessive '/' and '\' characters */
5010 static void
5011 remove_double_dots_and_double_slashes(char *s)
5012 {
5013 char *p = s;
5014
5015 while (*s != '\0') {
5016 *p++ = *s++;
5017 if (s[-1] == '/' || s[-1] == '\\') {
5018 /* Skip all following slashes, backslashes and double-dots */
5019 while (s[0] != '\0') {
5020 if (s[0] == '/' || s[0] == '\\') {
5021 s++;
5022 } else if (s[0] == '.' && s[1] == '.') {
5023 s += 2;
5024 } else {
5025 break;
5026 }
5027 }
5028 }
5029 }
5030 *p = '\0';
5031 }
5032
5033
5034 static const struct {
5035 const char *extension;
5036 size_t ext_len;
5037 const char *mime_type;
5038 } builtin_mime_types[] = {
5039 /* IANA registered MIME types (http://www.iana.org/assignments/media-types)
5040 * application types */
5041 {".doc", 4, "application/msword"},
5042 {".eps", 4, "application/postscript"},
5043 {".exe", 4, "application/octet-stream"},
5044 {".js", 3, "application/javascript"},
5045 {".json", 5, "application/json"},
5046 {".pdf", 4, "application/pdf"},
5047 {".ps", 3, "application/postscript"},
5048 {".rtf", 4, "application/rtf"},
5049 {".xhtml", 6, "application/xhtml+xml"},
5050 {".xsl", 4, "application/xml"},
5051 {".xslt", 5, "application/xml"},
5052
5053 /* fonts */
5054 {".ttf", 4, "application/font-sfnt"},
5055 {".cff", 4, "application/font-sfnt"},
5056 {".otf", 4, "application/font-sfnt"},
5057 {".aat", 4, "application/font-sfnt"},
5058 {".sil", 4, "application/font-sfnt"},
5059 {".pfr", 4, "application/font-tdpfr"},
5060 {".woff", 5, "application/font-woff"},
5061
5062 /* audio */
5063 {".mp3", 4, "audio/mpeg"},
5064 {".oga", 4, "audio/ogg"},
5065 {".ogg", 4, "audio/ogg"},
5066
5067 /* image */
5068 {".gif", 4, "image/gif"},
5069 {".ief", 4, "image/ief"},
5070 {".jpeg", 5, "image/jpeg"},
5071 {".jpg", 4, "image/jpeg"},
5072 {".jpm", 4, "image/jpm"},
5073 {".jpx", 4, "image/jpx"},
5074 {".png", 4, "image/png"},
5075 {".svg", 4, "image/svg+xml"},
5076 {".tif", 4, "image/tiff"},
5077 {".tiff", 5, "image/tiff"},
5078
5079 /* model */
5080 {".wrl", 4, "model/vrml"},
5081
5082 /* text */
5083 {".css", 4, "text/css"},
5084 {".csv", 4, "text/csv"},
5085 {".htm", 4, "text/html"},
5086 {".html", 5, "text/html"},
5087 {".sgm", 4, "text/sgml"},
5088 {".shtm", 5, "text/html"},
5089 {".shtml", 6, "text/html"},
5090 {".txt", 4, "text/plain"},
5091 {".xml", 4, "text/xml"},
5092
5093 /* video */
5094 {".mov", 4, "video/quicktime"},
5095 {".mp4", 4, "video/mp4"},
5096 {".mpeg", 5, "video/mpeg"},
5097 {".mpg", 4, "video/mpeg"},
5098 {".ogv", 4, "video/ogg"},
5099 {".qt", 3, "video/quicktime"},
5100
5101 /* not registered types
5102 * (http://reference.sitepoint.com/html/mime-types-full,
5103 * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
5104 {".arj", 4, "application/x-arj-compressed"},
5105 {".gz", 3, "application/x-gunzip"},
5106 {".rar", 4, "application/x-arj-compressed"},
5107 {".swf", 4, "application/x-shockwave-flash"},
5108 {".tar", 4, "application/x-tar"},
5109 {".tgz", 4, "application/x-tar-gz"},
5110 {".torrent", 8, "application/x-bittorrent"},
5111 {".ppt", 4, "application/x-mspowerpoint"},
5112 {".xls", 4, "application/x-msexcel"},
5113 {".zip", 4, "application/x-zip-compressed"},
5114 {".aac",
5115 4,
5116 "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
5117 {".aif", 4, "audio/x-aif"},
5118 {".m3u", 4, "audio/x-mpegurl"},
5119 {".mid", 4, "audio/x-midi"},
5120 {".ra", 3, "audio/x-pn-realaudio"},
5121 {".ram", 4, "audio/x-pn-realaudio"},
5122 {".wav", 4, "audio/x-wav"},
5123 {".bmp", 4, "image/bmp"},
5124 {".ico", 4, "image/x-icon"},
5125 {".pct", 4, "image/x-pct"},
5126 {".pict", 5, "image/pict"},
5127 {".rgb", 4, "image/x-rgb"},
5128 {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
5129 {".asf", 4, "video/x-ms-asf"},
5130 {".avi", 4, "video/x-msvideo"},
5131 {".m4v", 4, "video/x-m4v"},
5132 {NULL, 0, NULL}};
5133
5134
5135 const char *
5136 mg_get_builtin_mime_type(const char *path)
5137 {
5138 const char *ext;
5139 size_t i, path_len;
5140
5141 path_len = strlen(path);
5142
5143 for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
5144 ext = path + (path_len - builtin_mime_types[i].ext_len);
5145 if (path_len > builtin_mime_types[i].ext_len
5146 && mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
5147 return builtin_mime_types[i].mime_type;
5148 }
5149 }
5150
5151 return "text/plain";
5152 }
5153
5154
5155 /* Look at the "path" extension and figure what mime type it has.
5156 * Store mime type in the vector. */
5157 static void
5158 get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
5159 {
5160 struct vec ext_vec, mime_vec;
5161 const char *list, *ext;
5162 size_t path_len;
5163
5164 path_len = strlen(path);
5165
5166 if (ctx == NULL || vec == NULL) {
5167 return;
5168 }
5169
5170 /* Scan user-defined mime types first, in case user wants to
5171 * override default mime types. */
5172 list = ctx->config[EXTRA_MIME_TYPES];
5173 while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
5174 /* ext now points to the path suffix */
5175 ext = path + path_len - ext_vec.len;
5176 if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
5177 *vec = mime_vec;
5178 return;
5179 }
5180 }
5181
5182 vec->ptr = mg_get_builtin_mime_type(path);
5183 vec->len = strlen(vec->ptr);
5184 }
5185
5186
5187 /* Stringify binary data. Output buffer must be twice as big as input,
5188 * because each byte takes 2 bytes in string representation */
5189 static void
5190 bin2str(char *to, const unsigned char *p, size_t len)
5191 {
5192 static const char *hex = "0123456789abcdef";
5193
5194 for (; len--; p++) {
5195 *to++ = hex[p[0] >> 4];
5196 *to++ = hex[p[0] & 0x0f];
5197 }
5198 *to = '\0';
5199 }
5200
5201
5202 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */
5203 char *
5204 mg_md5(char buf[33], ...)
5205 {
5206 md5_byte_t hash[16];
5207 const char *p;
5208 va_list ap;
5209 md5_state_t ctx;
5210
5211 md5_init(&ctx);
5212
5213 va_start(ap, buf);
5214 while ((p = va_arg(ap, const char *)) != NULL) {
5215 md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
5216 }
5217 va_end(ap);
5218
5219 md5_finish(&ctx, hash);
5220 bin2str(buf, hash, sizeof(hash));
5221 return buf;
5222 }
5223
5224
5225 /* Check the user's password, return 1 if OK */
5226 static int
5227 check_password(const char *method,
5228 const char *ha1,
5229 const char *uri,
5230 const char *nonce,
5231 const char *nc,
5232 const char *cnonce,
5233 const char *qop,
5234 const char *response)
5235 {
5236 char ha2[32 + 1], expected_response[32 + 1];
5237
5238 /* Some of the parameters may be NULL */
5239 if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL
5240 || qop == NULL
5241 || response == NULL) {
5242 return 0;
5243 }
5244
5245 /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
5246 if (strlen(response) != 32) {
5247 return 0;
5248 }
5249
5250 mg_md5(ha2, method, ":", uri, NULL);
5251 mg_md5(expected_response,
5252 ha1,
5253 ":",
5254 nonce,
5255 ":",
5256 nc,
5257 ":",
5258 cnonce,
5259 ":",
5260 qop,
5261 ":",
5262 ha2,
5263 NULL);
5264
5265 return mg_strcasecmp(response, expected_response) == 0;
5266 }
5267
5268
5269 /* Use the global passwords file, if specified by auth_gpass option,
5270 * or search for .htpasswd in the requested directory. */
5271 static void
5272 open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
5273 {
5274 if (conn != NULL && conn->ctx != NULL) {
5275 char name[PATH_MAX];
5276 const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
5277 struct file file = STRUCT_FILE_INITIALIZER;
5278 int truncated;
5279
5280 if (gpass != NULL) {
5281 /* Use global passwords file */
5282 if (!mg_fopen(conn, gpass, "r", filep)) {
5283 #ifdef DEBUG
5284 mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
5285 #endif
5286 }
5287 /* Important: using local struct file to test path for is_directory
5288 * flag. If filep is used, mg_stat() makes it appear as if auth file
5289 * was opened. */
5290 } else if (mg_stat(conn, path, &file) && file.is_directory) {
5291 mg_snprintf(conn,
5292 &truncated,
5293 name,
5294 sizeof(name),
5295 "%s/%s",
5296 path,
5297 PASSWORDS_FILE_NAME);
5298
5299 if (truncated || !mg_fopen(conn, name, "r", filep)) {
5300 #ifdef DEBUG
5301 mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5302 #endif
5303 }
5304 } else {
5305 /* Try to find .htpasswd in requested directory. */
5306 for (p = path, e = p + strlen(p) - 1; e > p; e--) {
5307 if (e[0] == '/') {
5308 break;
5309 }
5310 }
5311 mg_snprintf(conn,
5312 &truncated,
5313 name,
5314 sizeof(name),
5315 "%.*s/%s",
5316 (int)(e - p),
5317 p,
5318 PASSWORDS_FILE_NAME);
5319
5320 if (truncated || !mg_fopen(conn, name, "r", filep)) {
5321 #ifdef DEBUG
5322 mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5323 #endif
5324 }
5325 }
5326 }
5327 }
5328
5329
5330 /* Parsed Authorization header */
5331 struct ah {
5332 char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
5333 };
5334
5335
5336 /* Return 1 on success. Always initializes the ah structure. */
5337 static int
5338 parse_auth_header(struct mg_connection *conn,
5339 char *buf,
5340 size_t buf_size,
5341 struct ah *ah)
5342 {
5343 char *name, *value, *s;
5344 const char *auth_header;
5345 uint64_t nonce;
5346
5347 if (!ah || !conn) {
5348 return 0;
5349 }
5350
5351 (void)memset(ah, 0, sizeof(*ah));
5352 if ((auth_header = mg_get_header(conn, "Authorization")) == NULL
5353 || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
5354 return 0;
5355 }
5356
5357 /* Make modifiable copy of the auth header */
5358 (void)mg_strlcpy(buf, auth_header + 7, buf_size);
5359 s = buf;
5360
5361 /* Parse authorization header */
5362 for (;;) {
5363 /* Gobble initial spaces */
5364 while (isspace(*(unsigned char *)s)) {
5365 s++;
5366 }
5367 name = skip_quoted(&s, "=", " ", 0);
5368 /* Value is either quote-delimited, or ends at first comma or space. */
5369 if (s[0] == '\"') {
5370 s++;
5371 value = skip_quoted(&s, "\"", " ", '\\');
5372 if (s[0] == ',') {
5373 s++;
5374 }
5375 } else {
5376 value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
5377 * spaces */
5378 }
5379 if (*name == '\0') {
5380 break;
5381 }
5382
5383 if (!strcmp(name, "username")) {
5384 ah->user = value;
5385 } else if (!strcmp(name, "cnonce")) {
5386 ah->cnonce = value;
5387 } else if (!strcmp(name, "response")) {
5388 ah->response = value;
5389 } else if (!strcmp(name, "uri")) {
5390 ah->uri = value;
5391 } else if (!strcmp(name, "qop")) {
5392 ah->qop = value;
5393 } else if (!strcmp(name, "nc")) {
5394 ah->nc = value;
5395 } else if (!strcmp(name, "nonce")) {
5396 ah->nonce = value;
5397 }
5398 }
5399
5400 #ifndef NO_NONCE_CHECK
5401 /* Read the nonce from the response. */
5402 if (ah->nonce == NULL) {
5403 return 0;
5404 }
5405 s = NULL;
5406 nonce = strtoull(ah->nonce, &s, 10);
5407 if ((s == NULL) || (*s != 0)) {
5408 return 0;
5409 }
5410
5411 /* Convert the nonce from the client to a number. */
5412 nonce ^= conn->ctx->auth_nonce_mask;
5413
5414 /* The converted number corresponds to the time the nounce has been
5415 * created. This should not be earlier than the server start. */
5416 /* Server side nonce check is valuable in all situations but one:
5417 * if the server restarts frequently, but the client should not see
5418 * that, so the server should accept nonces from previous starts. */
5419 /* However, the reasonable default is to not accept a nonce from a
5420 * previous start, so if anyone changed the access rights between
5421 * two restarts, a new login is required. */
5422 if (nonce < (uint64_t)conn->ctx->start_time) {
5423 /* nonce is from a previous start of the server and no longer valid
5424 * (replay attack?) */
5425 return 0;
5426 }
5427 /* Check if the nonce is too high, so it has not (yet) been used by the
5428 * server. */
5429 if (nonce >= ((uint64_t)conn->ctx->start_time + conn->ctx->nonce_count)) {
5430 return 0;
5431 }
5432 #endif
5433
5434 /* CGI needs it as REMOTE_USER */
5435 if (ah->user != NULL) {
5436 conn->request_info.remote_user = mg_strdup(ah->user);
5437 } else {
5438 return 0;
5439 }
5440
5441 return 1;
5442 }
5443
5444
5445 static const char *
5446 mg_fgets(char *buf, size_t size, struct file *filep, char **p)
5447 {
5448 const char *eof;
5449 size_t len;
5450 const char *memend;
5451
5452 if (!filep) {
5453 return NULL;
5454 }
5455
5456 if (filep->membuf != NULL && *p != NULL) {
5457 memend = (const char *)&filep->membuf[filep->size];
5458 /* Search for \n from p till the end of stream */
5459 eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
5460 if (eof != NULL) {
5461 eof += 1; /* Include \n */
5462 } else {
5463 eof = memend; /* Copy remaining data */
5464 }
5465 len = (size_t)(eof - *p) > size - 1 ? size - 1 : (size_t)(eof - *p);
5466 memcpy(buf, *p, len);
5467 buf[len] = '\0';
5468 *p += len;
5469 return len ? eof : NULL;
5470 } else if (filep->fp != NULL) {
5471 return fgets(buf, (int)size, filep->fp);
5472 } else {
5473 return NULL;
5474 }
5475 }
5476
5477 struct read_auth_file_struct {
5478 struct mg_connection *conn;
5479 struct ah ah;
5480 char *domain;
5481 char buf[256 + 256 + 40];
5482 char *f_user;
5483 char *f_domain;
5484 char *f_ha1;
5485 };
5486
5487
5488 static int
5489 read_auth_file(struct file *filep, struct read_auth_file_struct *workdata)
5490 {
5491 char *p;
5492 int is_authorized = 0;
5493 struct file fp;
5494 size_t l;
5495
5496 if (!filep || !workdata) {
5497 return 0;
5498 }
5499
5500 /* Loop over passwords file */
5501 p = (char *)filep->membuf;
5502 while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
5503 l = strlen(workdata->buf);
5504 while (l > 0) {
5505 if (isspace(workdata->buf[l - 1])
5506 || iscntrl(workdata->buf[l - 1])) {
5507 l--;
5508 workdata->buf[l] = 0;
5509 } else
5510 break;
5511 }
5512 if (l < 1) {
5513 continue;
5514 }
5515
5516 workdata->f_user = workdata->buf;
5517
5518 if (workdata->f_user[0] == ':') {
5519 /* user names may not contain a ':' and may not be empty,
5520 * so lines starting with ':' may be used for a special purpose */
5521 if (workdata->f_user[1] == '#') {
5522 /* :# is a comment */
5523 continue;
5524 } else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
5525 if (mg_fopen(workdata->conn, workdata->f_user + 9, "r", &fp)) {
5526 is_authorized = read_auth_file(&fp, workdata);
5527 mg_fclose(&fp);
5528 } else {
5529 mg_cry(workdata->conn,
5530 "%s: cannot open authorization file: %s",
5531 __func__,
5532 workdata->buf);
5533 }
5534 continue;
5535 }
5536 /* everything is invalid for the moment (might change in the
5537 * future) */
5538 mg_cry(workdata->conn,
5539 "%s: syntax error in authorization file: %s",
5540 __func__,
5541 workdata->buf);
5542 continue;
5543 }
5544
5545 workdata->f_domain = strchr(workdata->f_user, ':');
5546 if (workdata->f_domain == NULL) {
5547 mg_cry(workdata->conn,
5548 "%s: syntax error in authorization file: %s",
5549 __func__,
5550 workdata->buf);
5551 continue;
5552 }
5553 *(workdata->f_domain) = 0;
5554 (workdata->f_domain)++;
5555
5556 workdata->f_ha1 = strchr(workdata->f_domain, ':');
5557 if (workdata->f_ha1 == NULL) {
5558 mg_cry(workdata->conn,
5559 "%s: syntax error in authorization file: %s",
5560 __func__,
5561 workdata->buf);
5562 continue;
5563 }
5564 *(workdata->f_ha1) = 0;
5565 (workdata->f_ha1)++;
5566
5567 if (!strcmp(workdata->ah.user, workdata->f_user)
5568 && !strcmp(workdata->domain, workdata->f_domain)) {
5569 return check_password(workdata->conn->request_info.request_method,
5570 workdata->f_ha1,
5571 workdata->ah.uri,
5572 workdata->ah.nonce,
5573 workdata->ah.nc,
5574 workdata->ah.cnonce,
5575 workdata->ah.qop,
5576 workdata->ah.response);
5577 }
5578 }
5579
5580 return is_authorized;
5581 }
5582
5583
5584 /* Authorize against the opened passwords file. Return 1 if authorized. */
5585 static int
5586 authorize(struct mg_connection *conn, struct file *filep)
5587 {
5588 struct read_auth_file_struct workdata;
5589 char buf[MG_BUF_LEN];
5590
5591 if (!conn || !conn->ctx) {
5592 return 0;
5593 }
5594
5595 memset(&workdata, 0, sizeof(workdata));
5596 workdata.conn = conn;
5597
5598 if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
5599 return 0;
5600 }
5601 workdata.domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
5602
5603 return read_auth_file(filep, &workdata);
5604 }
5605
5606
5607 /* Return 1 if request is authorised, 0 otherwise. */
5608 static int
5609 check_authorization(struct mg_connection *conn, const char *path)
5610 {
5611 char fname[PATH_MAX];
5612 struct vec uri_vec, filename_vec;
5613 const char *list;
5614 struct file file = STRUCT_FILE_INITIALIZER;
5615 int authorized = 1, truncated;
5616
5617 if (!conn || !conn->ctx) {
5618 return 0;
5619 }
5620
5621 list = conn->ctx->config[PROTECT_URI];
5622 while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
5623 if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
5624 mg_snprintf(conn,
5625 &truncated,
5626 fname,
5627 sizeof(fname),
5628 "%.*s",
5629 (int)filename_vec.len,
5630 filename_vec.ptr);
5631
5632 if (truncated || !mg_fopen(conn, fname, "r", &file)) {
5633 mg_cry(conn,
5634 "%s: cannot open %s: %s",
5635 __func__,
5636 fname,
5637 strerror(errno));
5638 }
5639 break;
5640 }
5641 }
5642
5643 if (!is_file_opened(&file)) {
5644 open_auth_file(conn, path, &file);
5645 }
5646
5647 if (is_file_opened(&file)) {
5648 authorized = authorize(conn, &file);
5649 mg_fclose(&file);
5650 }
5651
5652 return authorized;
5653 }
5654
5655
5656 static void
5657 send_authorization_request(struct mg_connection *conn)
5658 {
5659 char date[64];
5660 time_t curtime = time(NULL);
5661
5662 if (conn && conn->ctx) {
5663 uint64_t nonce = (uint64_t)(conn->ctx->start_time);
5664
5665 (void)pthread_mutex_lock(&conn->ctx->nonce_mutex);
5666 nonce += conn->ctx->nonce_count;
5667 ++conn->ctx->nonce_count;
5668 (void)pthread_mutex_unlock(&conn->ctx->nonce_mutex);
5669
5670 nonce ^= conn->ctx->auth_nonce_mask;
5671 conn->status_code = 401;
5672 conn->must_close = 1;
5673
5674 gmt_time_string(date, sizeof(date), &curtime);
5675
5676 mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
5677 send_no_cache_header(conn);
5678 mg_printf(conn,
5679 "Date: %s\r\n"
5680 "Connection: %s\r\n"
5681 "Content-Length: 0\r\n"
5682 "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
5683 "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
5684 date,
5685 suggest_connection_header(conn),
5686 conn->ctx->config[AUTHENTICATION_DOMAIN],
5687 nonce);
5688 }
5689 }
5690
5691
5692 #if !defined(NO_FILES)
5693 static int
5694 is_authorized_for_put(struct mg_connection *conn)
5695 {
5696 if (conn) {
5697 struct file file = STRUCT_FILE_INITIALIZER;
5698 const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
5699 int ret = 0;
5700
5701 if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) {
5702 ret = authorize(conn, &file);
5703 mg_fclose(&file);
5704 }
5705
5706 return ret;
5707 }
5708 return 0;
5709 }
5710 #endif
5711
5712
5713 int
5714 mg_modify_passwords_file(const char *fname,
5715 const char *domain,
5716 const char *user,
5717 const char *pass)
5718 {
5719 int found, i;
5720 char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
5721 FILE *fp, *fp2;
5722
5723 found = 0;
5724 fp = fp2 = NULL;
5725
5726 /* Regard empty password as no password - remove user record. */
5727 if (pass != NULL && pass[0] == '\0') {
5728 pass = NULL;
5729 }
5730
5731 /* Other arguments must not be empty */
5732 if (fname == NULL || domain == NULL || user == NULL) {
5733 return 0;
5734 }
5735
5736 /* Using the given file format, user name and domain must not contain ':'
5737 */
5738 if (strchr(user, ':') != NULL) {
5739 return 0;
5740 }
5741 if (strchr(domain, ':') != NULL) {
5742 return 0;
5743 }
5744
5745 /* Do not allow control characters like newline in user name and domain.
5746 * Do not allow excessively long names either. */
5747 for (i = 0; i < 255 && user[i] != 0; i++) {
5748 if (iscntrl(user[i])) {
5749 return 0;
5750 }
5751 }
5752 if (user[i]) {
5753 return 0;
5754 }
5755 for (i = 0; i < 255 && domain[i] != 0; i++) {
5756 if (iscntrl(domain[i])) {
5757 return 0;
5758 }
5759 }
5760 if (domain[i]) {
5761 return 0;
5762 }
5763
5764 /* The maximum length of the path to the password file is limited */
5765 if ((strlen(fname) + 4) >= PATH_MAX) {
5766 return 0;
5767 }
5768
5769 /* Create a temporary file name. Length has been checked before. */
5770 strcpy(tmp, fname);
5771 strcat(tmp, ".tmp");
5772
5773 /* Create the file if does not exist */
5774 /* Use of fopen here is OK, since fname is only ASCII */
5775 if ((fp = fopen(fname, "a+")) != NULL) {
5776 (void)fclose(fp);
5777 }
5778
5779 /* Open the given file and temporary file */
5780 if ((fp = fopen(fname, "r")) == NULL) {
5781 return 0;
5782 } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
5783 fclose(fp);
5784 return 0;
5785 }
5786
5787 /* Copy the stuff to temporary file */
5788 while (fgets(line, sizeof(line), fp) != NULL) {
5789 if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
5790 continue;
5791 }
5792 u[255] = 0;
5793 d[255] = 0;
5794
5795 if (!strcmp(u, user) && !strcmp(d, domain)) {
5796 found++;
5797 if (pass != NULL) {
5798 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5799 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5800 }
5801 } else {
5802 fprintf(fp2, "%s", line);
5803 }
5804 }
5805
5806 /* If new user, just add it */
5807 if (!found && pass != NULL) {
5808 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5809 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5810 }
5811
5812 /* Close files */
5813 fclose(fp);
5814 fclose(fp2);
5815
5816 /* Put the temp file in place of real file */
5817 IGNORE_UNUSED_RESULT(remove(fname));
5818 IGNORE_UNUSED_RESULT(rename(tmp, fname));
5819
5820 return 1;
5821 }
5822
5823
5824 static int
5825 is_valid_port(unsigned long port)
5826 {
5827 return port < 0xffff;
5828 }
5829
5830
5831 static int
5832 mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
5833 {
5834 struct addrinfo hints, *res, *ressave;
5835 int func_ret = 0;
5836 int gai_ret;
5837
5838 memset(&hints, 0, sizeof(struct addrinfo));
5839 hints.ai_family = af;
5840
5841 gai_ret = getaddrinfo(src, NULL, &hints, &res);
5842 if (gai_ret != 0) {
5843 /* gai_strerror could be used to convert gai_ret to a string */
5844 /* POSIX return values: see
5845 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
5846 */
5847 /* Windows return values: see
5848 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
5849 */
5850 return 0;
5851 }
5852
5853 ressave = res;
5854
5855 while (res) {
5856 if (dstlen >= res->ai_addrlen) {
5857 memcpy(dst, res->ai_addr, res->ai_addrlen);
5858 func_ret = 1;
5859 }
5860 res = res->ai_next;
5861 }
5862
5863 freeaddrinfo(ressave);
5864 return func_ret;
5865 }
5866
5867
5868 static int
5869 connect_socket(struct mg_context *ctx /* may be NULL */,
5870 const char *host,
5871 int port,
5872 int use_ssl,
5873 char *ebuf,
5874 size_t ebuf_len,
5875 SOCKET *sock /* output: socket, must not be NULL */,
5876 union usa *sa /* output: socket address, must not be NULL */
5877 )
5878 {
5879 int ip_ver = 0;
5880 *sock = INVALID_SOCKET;
5881 memset(sa, 0, sizeof(*sa));
5882
5883 if (ebuf_len > 0) {
5884 *ebuf = 0;
5885 }
5886
5887 if (host == NULL) {
5888 mg_snprintf(NULL,
5889 NULL, /* No truncation check for ebuf */
5890 ebuf,
5891 ebuf_len,
5892 "%s",
5893 "NULL host");
5894 return 0;
5895 }
5896
5897 if (port < 0 || !is_valid_port((unsigned)port)) {
5898 mg_snprintf(NULL,
5899 NULL, /* No truncation check for ebuf */
5900 ebuf,
5901 ebuf_len,
5902 "%s",
5903 "invalid port");
5904 return 0;
5905 }
5906
5907 #ifndef NO_SSL_DL
5908 if (use_ssl && (SSLv23_client_method == NULL)) {
5909 mg_snprintf(NULL,
5910 NULL, /* No truncation check for ebuf */
5911 ebuf,
5912 ebuf_len,
5913 "%s",
5914 "SSL is not initialized");
5915 return 0;
5916 }
5917 #endif
5918
5919 if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
5920 sa->sin.sin_port = htons((uint16_t)port);
5921 ip_ver = 4;
5922 #ifdef USE_IPV6
5923 } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
5924 sa->sin6.sin6_port = htons((uint16_t)port);
5925 ip_ver = 6;
5926 } else if (host[0] == '[') {
5927 /* While getaddrinfo on Windows will work with [::1],
5928 * getaddrinfo on Linux only works with ::1 (without []). */
5929 size_t l = strlen(host + 1);
5930 char *h = l > 1 ? mg_strdup(host + 1) : NULL;
5931 if (h) {
5932 h[l - 1] = 0;
5933 if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
5934 sa->sin6.sin6_port = htons((uint16_t)port);
5935 ip_ver = 6;
5936 }
5937 mg_free(h);
5938 }
5939 #endif
5940 }
5941
5942 if (ip_ver == 0) {
5943 mg_snprintf(NULL,
5944 NULL, /* No truncation check for ebuf */
5945 ebuf,
5946 ebuf_len,
5947 "%s",
5948 "host not found");
5949 return 0;
5950 }
5951
5952 if (ip_ver == 4) {
5953 *sock = socket(PF_INET, SOCK_STREAM, 0);
5954 }
5955 #ifdef USE_IPV6
5956 else if (ip_ver == 6) {
5957 *sock = socket(PF_INET6, SOCK_STREAM, 0);
5958 }
5959 #endif
5960
5961 if (*sock == INVALID_SOCKET) {
5962 mg_snprintf(NULL,
5963 NULL, /* No truncation check for ebuf */
5964 ebuf,
5965 ebuf_len,
5966 "socket(): %s",
5967 strerror(ERRNO));
5968 return 0;
5969 }
5970
5971 set_close_on_exec(*sock, fc(ctx));
5972
5973 if ((ip_ver == 4)
5974 && (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
5975 == 0)) {
5976 /* connected with IPv4 */
5977 return 1;
5978 }
5979
5980 #ifdef USE_IPV6
5981 if ((ip_ver == 6)
5982 && (connect(*sock, (struct sockaddr *)&sa->sin6, sizeof(sa->sin6))
5983 == 0)) {
5984 /* connected with IPv6 */
5985 return 1;
5986 }
5987 #endif
5988
5989 /* Not connected */
5990 mg_snprintf(NULL,
5991 NULL, /* No truncation check for ebuf */
5992 ebuf,
5993 ebuf_len,
5994 "connect(%s:%d): %s",
5995 host,
5996 port,
5997 strerror(ERRNO));
5998 closesocket(*sock);
5999 *sock = INVALID_SOCKET;
6000 return 0;
6001 }
6002
6003
6004 int
6005 mg_url_encode(const char *src, char *dst, size_t dst_len)
6006 {
6007 static const char *dont_escape = "._-$,;~()";
6008 static const char *hex = "0123456789abcdef";
6009 char *pos = dst;
6010 const char *end = dst + dst_len - 1;
6011
6012 for (; *src != '\0' && pos < end; src++, pos++) {
6013 if (isalnum(*(const unsigned char *)src)
6014 || strchr(dont_escape, *(const unsigned char *)src) != NULL) {
6015 *pos = *src;
6016 } else if (pos + 2 < end) {
6017 pos[0] = '%';
6018 pos[1] = hex[(*(const unsigned char *)src) >> 4];
6019 pos[2] = hex[(*(const unsigned char *)src) & 0xf];
6020 pos += 2;
6021 } else {
6022 break;
6023 }
6024 }
6025
6026 *pos = '\0';
6027 return (*src == '\0') ? (int)(pos - dst) : -1;
6028 }
6029
6030
6031 static void
6032 print_dir_entry(struct de *de)
6033 {
6034 char size[64], mod[64], href[PATH_MAX];
6035 struct tm *tm;
6036
6037 if (de->file.is_directory) {
6038 mg_snprintf(de->conn,
6039 NULL, /* Buffer is big enough */
6040 size,
6041 sizeof(size),
6042 "%s",
6043 "[DIRECTORY]");
6044 } else {
6045 /* We use (signed) cast below because MSVC 6 compiler cannot
6046 * convert unsigned __int64 to double. Sigh. */
6047 if (de->file.size < 1024) {
6048 mg_snprintf(de->conn,
6049 NULL, /* Buffer is big enough */
6050 size,
6051 sizeof(size),
6052 "%d",
6053 (int)de->file.size);
6054 } else if (de->file.size < 0x100000) {
6055 mg_snprintf(de->conn,
6056 NULL, /* Buffer is big enough */
6057 size,
6058 sizeof(size),
6059 "%.1fk",
6060 (double)de->file.size / 1024.0);
6061 } else if (de->file.size < 0x40000000) {
6062 mg_snprintf(de->conn,
6063 NULL, /* Buffer is big enough */
6064 size,
6065 sizeof(size),
6066 "%.1fM",
6067 (double)de->file.size / 1048576);
6068 } else {
6069 mg_snprintf(de->conn,
6070 NULL, /* Buffer is big enough */
6071 size,
6072 sizeof(size),
6073 "%.1fG",
6074 (double)de->file.size / 1073741824);
6075 }
6076 }
6077
6078 /* Note: mg_snprintf will not cause a buffer overflow above.
6079 * So, string truncation checks are not required here. */
6080
6081 tm = localtime(&de->file.last_modified);
6082 if (tm != NULL) {
6083 strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
6084 } else {
6085 mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
6086 mod[sizeof(mod) - 1] = '\0';
6087 }
6088 mg_url_encode(de->file_name, href, sizeof(href));
6089 de->conn->num_bytes_sent +=
6090 mg_printf(de->conn,
6091 "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
6092 "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6093 de->conn->request_info.local_uri,
6094 href,
6095 de->file.is_directory ? "/" : "",
6096 de->file_name,
6097 de->file.is_directory ? "/" : "",
6098 mod,
6099 size);
6100 }
6101
6102
6103 /* This function is called from send_directory() and used for
6104 * sorting directory entries by size, or name, or modification time.
6105 * On windows, __cdecl specification is needed in case if project is built
6106 * with __stdcall convention. qsort always requires __cdels callback. */
6107 static int WINCDECL
6108 compare_dir_entries(const void *p1, const void *p2)
6109 {
6110 if (p1 && p2) {
6111 const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
6112 const char *query_string = a->conn->request_info.query_string;
6113 int cmp_result = 0;
6114
6115 if (query_string == NULL) {
6116 query_string = "na";
6117 }
6118
6119 if (a->file.is_directory && !b->file.is_directory) {
6120 return -1; /* Always put directories on top */
6121 } else if (!a->file.is_directory && b->file.is_directory) {
6122 return 1; /* Always put directories on top */
6123 } else if (*query_string == 'n') {
6124 cmp_result = strcmp(a->file_name, b->file_name);
6125 } else if (*query_string == 's') {
6126 cmp_result = a->file.size == b->file.size
6127 ? 0
6128 : a->file.size > b->file.size ? 1 : -1;
6129 } else if (*query_string == 'd') {
6130 cmp_result =
6131 (a->file.last_modified == b->file.last_modified)
6132 ? 0
6133 : ((a->file.last_modified > b->file.last_modified) ? 1
6134 : -1);
6135 }
6136
6137 return query_string[1] == 'd' ? -cmp_result : cmp_result;
6138 }
6139 return 0;
6140 }
6141
6142
6143 static int
6144 must_hide_file(struct mg_connection *conn, const char *path)
6145 {
6146 if (conn && conn->ctx) {
6147 const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
6148 const char *pattern = conn->ctx->config[HIDE_FILES];
6149 return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
6150 || (pattern != NULL
6151 && match_prefix(pattern, strlen(pattern), path) > 0);
6152 }
6153 return 0;
6154 }
6155
6156
6157 static int
6158 scan_directory(struct mg_connection *conn,
6159 const char *dir,
6160 void *data,
6161 void (*cb)(struct de *, void *))
6162 {
6163 char path[PATH_MAX];
6164 struct dirent *dp;
6165 DIR *dirp;
6166 struct de de;
6167 int truncated;
6168
6169 if ((dirp = mg_opendir(conn, dir)) == NULL) {
6170 return 0;
6171 } else {
6172 de.conn = conn;
6173
6174 while ((dp = mg_readdir(dirp)) != NULL) {
6175 /* Do not show current dir and hidden files */
6176 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
6177 || must_hide_file(conn, dp->d_name)) {
6178 continue;
6179 }
6180
6181 mg_snprintf(
6182 conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6183
6184 /* If we don't memset stat structure to zero, mtime will have
6185 * garbage and strftime() will segfault later on in
6186 * print_dir_entry(). memset is required only if mg_stat()
6187 * fails. For more details, see
6188 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6189 memset(&de.file, 0, sizeof(de.file));
6190
6191 if (truncated) {
6192 /* If the path is not complete, skip processing. */
6193 continue;
6194 }
6195
6196 if (!mg_stat(conn, path, &de.file)) {
6197 mg_cry(conn,
6198 "%s: mg_stat(%s) failed: %s",
6199 __func__,
6200 path,
6201 strerror(ERRNO));
6202 }
6203 de.file_name = dp->d_name;
6204 cb(&de, data);
6205 }
6206 (void)mg_closedir(dirp);
6207 }
6208 return 1;
6209 }
6210
6211
6212 #if !defined(NO_FILES)
6213 static int
6214 remove_directory(struct mg_connection *conn, const char *dir)
6215 {
6216 char path[PATH_MAX];
6217 struct dirent *dp;
6218 DIR *dirp;
6219 struct de de;
6220 int truncated;
6221 int ok = 1;
6222
6223 if ((dirp = mg_opendir(conn, dir)) == NULL) {
6224 return 0;
6225 } else {
6226 de.conn = conn;
6227
6228 while ((dp = mg_readdir(dirp)) != NULL) {
6229 /* Do not show current dir (but show hidden files as they will
6230 * also be removed) */
6231 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
6232 continue;
6233 }
6234
6235 mg_snprintf(
6236 conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6237
6238 /* If we don't memset stat structure to zero, mtime will have
6239 * garbage and strftime() will segfault later on in
6240 * print_dir_entry(). memset is required only if mg_stat()
6241 * fails. For more details, see
6242 * http://code.google.com/p/mongoose/issues/detail?id=79 */
6243 memset(&de.file, 0, sizeof(de.file));
6244
6245 if (truncated) {
6246 /* Do not delete anything shorter */
6247 ok = 0;
6248 continue;
6249 }
6250
6251 if (!mg_stat(conn, path, &de.file)) {
6252 mg_cry(conn,
6253 "%s: mg_stat(%s) failed: %s",
6254 __func__,
6255 path,
6256 strerror(ERRNO));
6257 ok = 0;
6258 }
6259 if (de.file.membuf == NULL) {
6260 /* file is not in memory */
6261 if (de.file.is_directory) {
6262 if (remove_directory(conn, path) == 0) {
6263 ok = 0;
6264 }
6265 } else {
6266 if (mg_remove(conn, path) == 0) {
6267 ok = 0;
6268 }
6269 }
6270 } else {
6271 /* file is in memory. It can not be deleted. */
6272 ok = 0;
6273 }
6274 }
6275 (void)mg_closedir(dirp);
6276
6277 IGNORE_UNUSED_RESULT(rmdir(dir));
6278 }
6279
6280 return ok;
6281 }
6282 #endif
6283
6284
6285 struct dir_scan_data {
6286 struct de *entries;
6287 unsigned int num_entries;
6288 unsigned int arr_size;
6289 };
6290
6291
6292 /* Behaves like realloc(), but frees original pointer on failure */
6293 static void *
6294 realloc2(void *ptr, size_t size)
6295 {
6296 void *new_ptr = mg_realloc(ptr, size);
6297 if (new_ptr == NULL) {
6298 mg_free(ptr);
6299 }
6300 return new_ptr;
6301 }
6302
6303
6304 static void
6305 dir_scan_callback(struct de *de, void *data)
6306 {
6307 struct dir_scan_data *dsd = (struct dir_scan_data *)data;
6308
6309 if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
6310 dsd->arr_size *= 2;
6311 dsd->entries =
6312 (struct de *)realloc2(dsd->entries,
6313 dsd->arr_size * sizeof(dsd->entries[0]));
6314 }
6315 if (dsd->entries == NULL) {
6316 /* TODO(lsm, low): propagate an error to the caller */
6317 dsd->num_entries = 0;
6318 } else {
6319 dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
6320 dsd->entries[dsd->num_entries].file = de->file;
6321 dsd->entries[dsd->num_entries].conn = de->conn;
6322 dsd->num_entries++;
6323 }
6324 }
6325
6326
6327 static void
6328 handle_directory_request(struct mg_connection *conn, const char *dir)
6329 {
6330 unsigned int i;
6331 int sort_direction;
6332 struct dir_scan_data data = {NULL, 0, 128};
6333 char date[64];
6334 time_t curtime = time(NULL);
6335
6336 if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
6337 send_http_error(conn,
6338 500,
6339 "Error: Cannot open directory\nopendir(%s): %s",
6340 dir,
6341 strerror(ERRNO));
6342 return;
6343 }
6344
6345 gmt_time_string(date, sizeof(date), &curtime);
6346
6347 if (!conn) {
6348 return;
6349 }
6350
6351 sort_direction = conn->request_info.query_string != NULL
6352 && conn->request_info.query_string[1] == 'd'
6353 ? 'a'
6354 : 'd';
6355
6356 conn->must_close = 1;
6357 mg_printf(conn, "HTTP/1.1 200 OK\r\n");
6358 send_static_cache_header(conn);
6359 mg_printf(conn,
6360 "Date: %s\r\n"
6361 "Connection: close\r\n"
6362 "Content-Type: text/html; charset=utf-8\r\n\r\n",
6363 date);
6364
6365 conn->num_bytes_sent +=
6366 mg_printf(conn,
6367 "<html><head><title>Index of %s</title>"
6368 "<style>th {text-align: left;}</style></head>"
6369 "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
6370 "<tr><th><a href=\"?n%c\">Name</a></th>"
6371 "<th><a href=\"?d%c\">Modified</a></th>"
6372 "<th><a href=\"?s%c\">Size</a></th></tr>"
6373 "<tr><td colspan=\"3\"><hr></td></tr>",
6374 conn->request_info.local_uri,
6375 conn->request_info.local_uri,
6376 sort_direction,
6377 sort_direction,
6378 sort_direction);
6379
6380 /* Print first entry - link to a parent directory */
6381 conn->num_bytes_sent +=
6382 mg_printf(conn,
6383 "<tr><td><a href=\"%s%s\">%s</a></td>"
6384 "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6385 conn->request_info.local_uri,
6386 "..",
6387 "Parent directory",
6388 "-",
6389 "-");
6390
6391 /* Sort and print directory entries */
6392 if (data.entries != NULL) {
6393 qsort(data.entries,
6394 (size_t)data.num_entries,
6395 sizeof(data.entries[0]),
6396 compare_dir_entries);
6397 for (i = 0; i < data.num_entries; i++) {
6398 print_dir_entry(&data.entries[i]);
6399 mg_free(data.entries[i].file_name);
6400 }
6401 mg_free(data.entries);
6402 }
6403
6404 conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
6405 conn->status_code = 200;
6406 }
6407
6408
6409 /* Send len bytes from the opened file to the client. */
6410 static void
6411 send_file_data(struct mg_connection *conn,
6412 struct file *filep,
6413 int64_t offset,
6414 int64_t len)
6415 {
6416 char buf[MG_BUF_LEN];
6417 int to_read, num_read, num_written;
6418 int64_t size;
6419
6420 if (!filep || !conn) {
6421 return;
6422 }
6423
6424 /* Sanity check the offset */
6425 size = filep->size > INT64_MAX ? INT64_MAX : (int64_t)(filep->size);
6426 offset = offset < 0 ? 0 : offset > size ? size : offset;
6427
6428 if (len > 0 && filep->membuf != NULL && size > 0) {
6429 /* file stored in memory */
6430 if (len > size - offset) {
6431 len = size - offset;
6432 }
6433 mg_write(conn, filep->membuf + offset, (size_t)len);
6434 } else if (len > 0 && filep->fp != NULL) {
6435 /* file stored on disk */
6436 #if defined(__linux__)
6437 /* sendfile is only available for Linux */
6438 if (conn->throttle == 0 && conn->ssl == 0) {
6439 off_t sf_offs = (off_t)offset;
6440 ssize_t sf_sent;
6441 int sf_file = fileno(filep->fp);
6442 int loop_cnt = 0;
6443
6444 do {
6445 /* 2147479552 (0x7FFFF000) is a limit found by experiment on
6446 * 64 bit Linux (2^31 minus one memory page of 4k?). */
6447 size_t sf_tosend =
6448 (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
6449 sf_sent =
6450 sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
6451 if (sf_sent > 0) {
6452 conn->num_bytes_sent += sf_sent;
6453 len -= sf_sent;
6454 offset += sf_sent;
6455 } else if (loop_cnt == 0) {
6456 /* This file can not be sent using sendfile.
6457 * This might be the case for pseudo-files in the
6458 * /sys/ and /proc/ file system.
6459 * Use the regular user mode copy code instead. */
6460 break;
6461 } else if (sf_sent == 0) {
6462 /* No error, but 0 bytes sent. May be EOF? */
6463 return;
6464 }
6465 loop_cnt++;
6466
6467 } while ((len > 0) && (sf_sent >= 0));
6468
6469 if (sf_sent > 0) {
6470 return; /* OK */
6471 }
6472
6473 /* sf_sent<0 means error, thus fall back to the classic way */
6474 /* This is always the case, if sf_file is not a "normal" file,
6475 * e.g., for sending data from the output of a CGI process. */
6476 offset = (int64_t)sf_offs;
6477 }
6478 #endif
6479 if ((offset > 0) && (fseeko(filep->fp, offset, SEEK_SET) != 0)) {
6480 mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
6481 send_http_error(
6482 conn,
6483 500,
6484 "%s",
6485 "Error: Unable to access file at requested position.");
6486 } else {
6487 while (len > 0) {
6488 /* Calculate how much to read from the file in the buffer */
6489 to_read = sizeof(buf);
6490 if ((int64_t)to_read > len) {
6491 to_read = (int)len;
6492 }
6493
6494 /* Read from file, exit the loop on error */
6495 if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp))
6496 <= 0) {
6497 break;
6498 }
6499
6500 /* Send read bytes to the client, exit the loop on error */
6501 if ((num_written = mg_write(conn, buf, (size_t)num_read))
6502 != num_read) {
6503 break;
6504 }
6505
6506 /* Both read and were successful, adjust counters */
6507 conn->num_bytes_sent += num_written;
6508 len -= num_written;
6509 }
6510 }
6511 }
6512 }
6513
6514
6515 static int
6516 parse_range_header(const char *header, int64_t *a, int64_t *b)
6517 {
6518 return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
6519 }
6520
6521
6522 static void
6523 construct_etag(char *buf, size_t buf_len, const struct file *filep)
6524 {
6525 if (filep != NULL && buf != NULL) {
6526 mg_snprintf(NULL,
6527 NULL, /* All calls to construct_etag use 64 byte buffer */
6528 buf,
6529 buf_len,
6530 "\"%lx.%" INT64_FMT "\"",
6531 (unsigned long)filep->last_modified,
6532 filep->size);
6533 }
6534 }
6535
6536
6537 static void
6538 fclose_on_exec(struct file *filep, struct mg_connection *conn)
6539 {
6540 if (filep != NULL && filep->fp != NULL) {
6541 #ifdef _WIN32
6542 (void)conn; /* Unused. */
6543 #else
6544 if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
6545 mg_cry(conn,
6546 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
6547 __func__,
6548 strerror(ERRNO));
6549 }
6550 #endif
6551 }
6552 }
6553
6554
6555 static void
6556 handle_static_file_request(struct mg_connection *conn,
6557 const char *path,
6558 struct file *filep,
6559 const char *mime_type)
6560 {
6561 char date[64], lm[64], etag[64];
6562 char range[128]; /* large enough, so there will be no overflow */
6563 const char *msg = "OK", *hdr;
6564 time_t curtime = time(NULL);
6565 int64_t cl, r1, r2;
6566 struct vec mime_vec;
6567 int n, truncated;
6568 char gz_path[PATH_MAX];
6569 const char *encoding = "";
6570 const char *cors1, *cors2, *cors3;
6571
6572 if (conn == NULL || conn->ctx == NULL || filep == NULL) {
6573 return;
6574 }
6575
6576 if (mime_type == NULL) {
6577 get_mime_type(conn->ctx, path, &mime_vec);
6578 } else {
6579 mime_vec.ptr = mime_type;
6580 mime_vec.len = strlen(mime_type);
6581 }
6582 if (filep->size > INT64_MAX) {
6583 send_http_error(conn,
6584 500,
6585 "Error: File size is too large to send\n%" INT64_FMT,
6586 filep->size);
6587 }
6588 cl = (int64_t)filep->size;
6589 conn->status_code = 200;
6590 range[0] = '\0';
6591
6592 /* if this file is in fact a pre-gzipped file, rewrite its filename
6593 * it's important to rewrite the filename after resolving
6594 * the mime type from it, to preserve the actual file's type */
6595 if (filep->gzipped) {
6596 mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
6597
6598 if (truncated) {
6599 send_http_error(conn,
6600 500,
6601 "Error: Path of zipped file too long (%s)",
6602 path);
6603 return;
6604 }
6605
6606 path = gz_path;
6607 encoding = "Content-Encoding: gzip\r\n";
6608 }
6609
6610 if (!mg_fopen(conn, path, "rb", filep)) {
6611 send_http_error(conn,
6612 500,
6613 "Error: Cannot open file\nfopen(%s): %s",
6614 path,
6615 strerror(ERRNO));
6616 return;
6617 }
6618
6619 fclose_on_exec(filep, conn);
6620
6621 /* If Range: header specified, act accordingly */
6622 r1 = r2 = 0;
6623 hdr = mg_get_header(conn, "Range");
6624 if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && r1 >= 0
6625 && r2 >= 0) {
6626 /* actually, range requests don't play well with a pre-gzipped
6627 * file (since the range is specified in the uncompressed space) */
6628 if (filep->gzipped) {
6629 send_http_error(
6630 conn,
6631 501,
6632 "%s",
6633 "Error: Range requests in gzipped files are not supported");
6634 mg_fclose(filep);
6635 return;
6636 }
6637 conn->status_code = 206;
6638 cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1 : cl - r1;
6639 mg_snprintf(conn,
6640 NULL, /* range buffer is big enough */
6641 range,
6642 sizeof(range),
6643 "Content-Range: bytes "
6644 "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
6645 r1,
6646 r1 + cl - 1,
6647 filep->size);
6648 msg = "Partial Content";
6649 }
6650
6651 hdr = mg_get_header(conn, "Origin");
6652 if (hdr) {
6653 /* Cross-origin resource sharing (CORS), see
6654 * http://www.html5rocks.com/en/tutorials/cors/,
6655 * http://www.html5rocks.com/static/images/cors_server_flowchart.png -
6656 * preflight is not supported for files. */
6657 cors1 = "Access-Control-Allow-Origin: ";
6658 cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
6659 cors3 = "\r\n";
6660 } else {
6661 cors1 = cors2 = cors3 = "";
6662 }
6663
6664 /* Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
6665 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
6666 gmt_time_string(date, sizeof(date), &curtime);
6667 gmt_time_string(lm, sizeof(lm), &filep->last_modified);
6668 construct_etag(etag, sizeof(etag), filep);
6669
6670 (void)mg_printf(conn,
6671 "HTTP/1.1 %d %s\r\n"
6672 "%s%s%s"
6673 "Date: %s\r\n",
6674 conn->status_code,
6675 msg,
6676 cors1,
6677 cors2,
6678 cors3,
6679 date);
6680 send_static_cache_header(conn);
6681 (void)mg_printf(conn,
6682 "Last-Modified: %s\r\n"
6683 "Etag: %s\r\n"
6684 "Content-Type: %.*s\r\n"
6685 "Content-Length: %" INT64_FMT "\r\n"
6686 "Connection: %s\r\n"
6687 "Accept-Ranges: bytes\r\n"
6688 "%s%s\r\n",
6689 lm,
6690 etag,
6691 (int)mime_vec.len,
6692 mime_vec.ptr,
6693 cl,
6694 suggest_connection_header(conn),
6695 range,
6696 encoding);
6697
6698 if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
6699 send_file_data(conn, filep, r1, cl);
6700 }
6701 mg_fclose(filep);
6702 }
6703
6704
6705 void
6706 mg_send_file(struct mg_connection *conn, const char *path)
6707 {
6708 mg_send_mime_file(conn, path, NULL);
6709 }
6710
6711
6712 void
6713 mg_send_mime_file(struct mg_connection *conn,
6714 const char *path,
6715 const char *mime_type)
6716 {
6717 struct file file = STRUCT_FILE_INITIALIZER;
6718 if (mg_stat(conn, path, &file)) {
6719 if (file.is_directory) {
6720 if (!conn) {
6721 return;
6722 }
6723 if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
6724 "yes")) {
6725 handle_directory_request(conn, path);
6726 } else {
6727 send_http_error(conn,
6728 403,
6729 "%s",
6730 "Error: Directory listing denied");
6731 }
6732 } else {
6733 handle_static_file_request(conn, path, &file, mime_type);
6734 }
6735 } else {
6736 send_http_error(conn, 404, "%s", "Error: File not found");
6737 }
6738 }
6739
6740
6741 /* For a given PUT path, create all intermediate subdirectories.
6742 * Return 0 if the path itself is a directory.
6743 * Return 1 if the path leads to a file.
6744 * Return -1 for if the path is too long.
6745 * Return -2 if path can not be created.
6746 */
6747 static int
6748 put_dir(struct mg_connection *conn, const char *path)
6749 {
6750 char buf[PATH_MAX];
6751 const char *s, *p;
6752 struct file file = STRUCT_FILE_INITIALIZER;
6753 size_t len;
6754 int res = 1;
6755
6756 for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
6757 len = (size_t)(p - path);
6758 if (len >= sizeof(buf)) {
6759 /* path too long */
6760 res = -1;
6761 break;
6762 }
6763 memcpy(buf, path, len);
6764 buf[len] = '\0';
6765
6766 /* Try to create intermediate directory */
6767 DEBUG_TRACE("mkdir(%s)", buf);
6768 if (!mg_stat(conn, buf, &file) && mg_mkdir(conn, buf, 0755) != 0) {
6769 /* path does not exixt and can not be created */
6770 res = -2;
6771 break;
6772 }
6773
6774 /* Is path itself a directory? */
6775 if (p[1] == '\0') {
6776 res = 0;
6777 }
6778 }
6779
6780 return res;
6781 }
6782
6783
6784 static void
6785 remove_bad_file(const struct mg_connection *conn, const char *path)
6786 {
6787 int r = mg_remove(conn, path);
6788 if (r != 0) {
6789 mg_cry(conn, "%s: Cannot remove invalid file %s", __func__, path);
6790 }
6791 }
6792
6793
6794 long long
6795 mg_store_body(struct mg_connection *conn, const char *path)
6796 {
6797 char buf[MG_BUF_LEN];
6798 long long len = 0;
6799 int ret, n;
6800 struct file fi;
6801
6802 if (conn->consumed_content != 0) {
6803 mg_cry(conn, "%s: Contents already consumed", __func__);
6804 return -11;
6805 }
6806
6807 ret = put_dir(conn, path);
6808 if (ret < 0) {
6809 /* -1 for path too long,
6810 * -2 for path can not be created. */
6811 return ret;
6812 }
6813 if (ret != 1) {
6814 /* Return 0 means, path itself is a directory. */
6815 return 0;
6816 }
6817
6818 if (mg_fopen(conn, path, "w", &fi) == 0) {
6819 return -12;
6820 }
6821
6822 ret = mg_read(conn, buf, sizeof(buf));
6823 while (ret > 0) {
6824 n = (int)fwrite(buf, 1, (size_t)ret, fi.fp);
6825 if (n != ret) {
6826 mg_fclose(&fi);
6827 remove_bad_file(conn, path);
6828 return -13;
6829 }
6830 ret = mg_read(conn, buf, sizeof(buf));
6831 }
6832
6833 /* TODO: mg_fclose should return an error,
6834 * and every caller should check and handle it. */
6835 if (fclose(fi.fp) != 0) {
6836 remove_bad_file(conn, path);
6837 return -14;
6838 }
6839
6840 return len;
6841 }
6842
6843
6844 /* Parse HTTP headers from the given buffer, advance buffer to the point
6845 * where parsing stopped. */
6846 static void
6847 parse_http_headers(char **buf, struct mg_request_info *ri)
6848 {
6849 int i;
6850
6851 if (!ri) {
6852 return;
6853 }
6854
6855 ri->num_headers = 0;
6856
6857 for (i = 0; i < (int)ARRAY_SIZE(ri->http_headers); i++) {
6858 char *dp = *buf;
6859 while ((*dp != ':') && (*dp != '\r') && (*dp != 0)) {
6860 dp++;
6861 }
6862 if (!*dp) {
6863 /* neither : nor \r\n. This is not a valid field. */
6864 break;
6865 }
6866 if (*dp == '\r') {
6867 if (dp[1] == '\n') {
6868 /* \r\n */
6869 ri->http_headers[i].name = *buf;
6870 ri->http_headers[i].value = 0;
6871 *buf = dp;
6872 } else {
6873 /* stray \r. This is not valid. */
6874 break;
6875 }
6876 } else {
6877 /* (*dp == ':') */
6878 *dp = 0;
6879 ri->http_headers[i].name = *buf;
6880 do {
6881 dp++;
6882 } while (*dp == ' ');
6883
6884 ri->http_headers[i].value = dp;
6885 *buf = strstr(dp, "\r\n");
6886 }
6887
6888 ri->num_headers = i + 1;
6889 if (*buf) {
6890 (*buf)[0] = 0;
6891 (*buf)[1] = 0;
6892 *buf += 2;
6893 } else {
6894 *buf = dp;
6895 break;
6896 }
6897
6898 if (*buf[0] == '\r') {
6899 /* This is the end of the header */
6900 break;
6901 }
6902 }
6903 }
6904
6905
6906 static int
6907 is_valid_http_method(const char *method)
6908 {
6909 return !strcmp(method, "GET") /* HTTP (RFC 2616) */
6910 || !strcmp(method, "POST") /* HTTP (RFC 2616) */
6911 || !strcmp(method, "HEAD") /* HTTP (RFC 2616) */
6912 || !strcmp(method, "PUT") /* HTTP (RFC 2616) */
6913 || !strcmp(method, "DELETE") /* HTTP (RFC 2616) */
6914 || !strcmp(method, "OPTIONS") /* HTTP (RFC 2616) */
6915 /* TRACE method (RFC 2616) is not supported for security reasons */
6916 || !strcmp(method, "CONNECT") /* HTTP (RFC 2616) */
6917
6918 || !strcmp(method, "PROPFIND") /* WEBDAV (RFC 2518) */
6919 || !strcmp(method, "MKCOL") /* WEBDAV (RFC 2518) */
6920
6921 /* Unsupported WEBDAV Methods: */
6922 /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
6923 /* + 11 methods from RFC 3253 */
6924 /* ORDERPATCH (RFC 3648) */
6925 /* ACL (RFC 3744) */
6926 /* SEARCH (RFC 5323) */
6927 /* + MicroSoft extensions
6928 * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
6929
6930 /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
6931 || !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
6932 }
6933
6934
6935 /* Parse HTTP request, fill in mg_request_info structure.
6936 * This function modifies the buffer by NUL-terminating
6937 * HTTP request components, header names and header values. */
6938 static int
6939 parse_http_message(int check_method,
6940 char *buf,
6941 int len,
6942 struct mg_request_info *ri)
6943 {
6944 int is_request, request_length;
6945
6946 if (!ri) {
6947 return 0;
6948 }
6949
6950 request_length = get_request_len(buf, len);
6951
6952 if (request_length > 0) {
6953 /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
6954 * remote_port */
6955 ri->remote_user = ri->request_method = ri->request_uri =
6956 ri->http_version = NULL;
6957 ri->num_headers = 0;
6958
6959 buf[request_length - 1] = '\0';
6960
6961 /* RFC says that all initial whitespaces should be ingored */
6962 while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
6963 buf++;
6964 }
6965 ri->request_method = skip(&buf, " ");
6966 ri->request_uri = skip(&buf, " ");
6967 ri->http_version = skip(&buf, "\r\n");
6968
6969 /* HTTP message could be either HTTP request or HTTP response, e.g.
6970 * "GET / HTTP/1.0 ...." or "HTTP/1.0 200 OK ..." */
6971 is_request =
6972 check_method ? is_valid_http_method(ri->request_method) : 1;
6973 if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
6974 || (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
6975 request_length = -1;
6976 } else {
6977 if (is_request) {
6978 ri->http_version += 5;
6979 }
6980 parse_http_headers(&buf, ri);
6981 }
6982 }
6983 return request_length;
6984 }
6985
6986
6987 /* Keep reading the input (either opened file descriptor fd, or socket sock,
6988 * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
6989 * buffer (which marks the end of HTTP request). Buffer buf may already
6990 * have some data. The length of the data is stored in nread.
6991 * Upon every read operation, increase nread by the number of bytes read. */
6992 static int
6993 read_request(FILE *fp,
6994 struct mg_connection *conn,
6995 char *buf,
6996 int bufsiz,
6997 int *nread)
6998 {
6999 int request_len, n = 0;
7000 struct timespec last_action_time;
7001 double request_timeout;
7002
7003 if (!conn) {
7004 return 0;
7005 }
7006
7007 memset(&last_action_time, 0, sizeof(last_action_time));
7008
7009 if (conn->ctx->config[REQUEST_TIMEOUT]) {
7010 /* value of request_timeout is in seconds, config in milliseconds */
7011 request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7012 } else {
7013 request_timeout = -1.0;
7014 }
7015
7016 request_len = get_request_len(buf, *nread);
7017
7018 /* first time reading from this connection */
7019 clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7020
7021 while (
7022 (conn->ctx->stop_flag == 0) && (*nread < bufsiz) && (request_len == 0)
7023 && ((mg_difftimespec(&last_action_time, &(conn->req_time))
7024 <= request_timeout) || (request_timeout < 0))
7025 && ((n = pull(fp, conn, buf + *nread, bufsiz - *nread, request_timeout))
7026 > 0)) {
7027 *nread += n;
7028 /* assert(*nread <= bufsiz); */
7029 if (*nread > bufsiz) {
7030 return -2;
7031 }
7032 request_len = get_request_len(buf, *nread);
7033 if (request_timeout > 0.0) {
7034 clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7035 }
7036 }
7037
7038 return (request_len <= 0 && n <= 0) ? -1 : request_len;
7039 }
7040
7041 #if !defined(NO_FILES)
7042 /* For given directory path, substitute it to valid index file.
7043 * Return 1 if index file has been found, 0 if not found.
7044 * If the file is found, it's stats is returned in stp. */
7045 static int
7046 substitute_index_file(struct mg_connection *conn,
7047 char *path,
7048 size_t path_len,
7049 struct file *filep)
7050 {
7051 if (conn && conn->ctx) {
7052 const char *list = conn->ctx->config[INDEX_FILES];
7053 struct file file = STRUCT_FILE_INITIALIZER;
7054 struct vec filename_vec;
7055 size_t n = strlen(path);
7056 int found = 0;
7057
7058 /* The 'path' given to us points to the directory. Remove all trailing
7059 * directory separator characters from the end of the path, and
7060 * then append single directory separator character. */
7061 while (n > 0 && path[n - 1] == '/') {
7062 n--;
7063 }
7064 path[n] = '/';
7065
7066 /* Traverse index files list. For each entry, append it to the given
7067 * path and see if the file exists. If it exists, break the loop */
7068 while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7069 /* Ignore too long entries that may overflow path buffer */
7070 if (filename_vec.len > path_len - (n + 2)) {
7071 continue;
7072 }
7073
7074 /* Prepare full path to the index file */
7075 mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7076
7077 /* Does it exist? */
7078 if (mg_stat(conn, path, &file)) {
7079 /* Yes it does, break the loop */
7080 *filep = file;
7081 found = 1;
7082 break;
7083 }
7084 }
7085
7086 /* If no index file exists, restore directory path */
7087 if (!found) {
7088 path[n] = '\0';
7089 }
7090
7091 return found;
7092 }
7093 return 0;
7094 }
7095 #endif
7096
7097
7098 #if !defined(NO_CACHING)
7099 /* Return True if we should reply 304 Not Modified. */
7100 static int
7101 is_not_modified(const struct mg_connection *conn, const struct file *filep)
7102 {
7103 char etag[64];
7104 const char *ims = mg_get_header(conn, "If-Modified-Since");
7105 const char *inm = mg_get_header(conn, "If-None-Match");
7106 construct_etag(etag, sizeof(etag), filep);
7107 if (!filep) {
7108 return 0;
7109 }
7110 return (inm != NULL && !mg_strcasecmp(etag, inm))
7111 || (ims != NULL && (filep->last_modified <= parse_date_string(ims)));
7112 }
7113 #endif /* !NO_CACHING */
7114
7115
7116 #if !defined(NO_CGI) || !defined(NO_FILES)
7117 static int
7118 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
7119 {
7120 const char *expect, *body;
7121 char buf[MG_BUF_LEN];
7122 int to_read, nread, success = 0;
7123 int64_t buffered_len;
7124 double timeout = -1.0;
7125
7126 if (!conn) {
7127 return 0;
7128 }
7129 if (conn->ctx->config[REQUEST_TIMEOUT]) {
7130 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7131 }
7132
7133 expect = mg_get_header(conn, "Expect");
7134 /* assert(fp != NULL); */
7135 if (!fp) {
7136 send_http_error(conn, 500, "%s", "Error: NULL File");
7137 return 0;
7138 }
7139
7140 if (conn->content_len == -1 && !conn->is_chunked) {
7141 /* Content length is not specified by the client. */
7142 send_http_error(conn,
7143 411,
7144 "%s",
7145 "Error: Client did not specify content length");
7146 } else if ((expect != NULL)
7147 && (mg_strcasecmp(expect, "100-continue") != 0)) {
7148 /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
7149 send_http_error(conn,
7150 417,
7151 "Error: Can not fulfill expectation %s",
7152 expect);
7153 } else {
7154 if (expect != NULL) {
7155 (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
7156 conn->status_code = 100;
7157 } else {
7158 conn->status_code = 200;
7159 }
7160
7161 buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
7162 - conn->consumed_content;
7163
7164 /* assert(buffered_len >= 0); */
7165 /* assert(conn->consumed_content == 0); */
7166
7167 if ((buffered_len < 0) || (conn->consumed_content != 0)) {
7168 send_http_error(conn, 500, "%s", "Error: Size mismatch");
7169 return 0;
7170 }
7171
7172 if (buffered_len > 0) {
7173 if ((int64_t)buffered_len > conn->content_len) {
7174 buffered_len = (int)conn->content_len;
7175 }
7176 body = conn->buf + conn->request_len + conn->consumed_content;
7177 push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
7178 conn->consumed_content += buffered_len;
7179 }
7180
7181 nread = 0;
7182 while (conn->consumed_content < conn->content_len) {
7183 to_read = sizeof(buf);
7184 if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
7185 to_read = (int)(conn->content_len - conn->consumed_content);
7186 }
7187 nread = pull(NULL, conn, buf, to_read, timeout);
7188 if (nread <= 0
7189 || push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
7190 break;
7191 }
7192 conn->consumed_content += nread;
7193 }
7194
7195 if (conn->consumed_content == conn->content_len) {
7196 success = (nread >= 0);
7197 }
7198
7199 /* Each error code path in this function must send an error */
7200 if (!success) {
7201 /* NOTE: Maybe some data has already been sent. */
7202 /* TODO (low): If some data has been sent, a correct error
7203 * reply can no longer be sent, so just close the connection */
7204 send_http_error(conn, 500, "%s", "");
7205 }
7206 }
7207
7208 return success;
7209 }
7210 #endif
7211
7212 #if !defined(NO_CGI)
7213 /* This structure helps to create an environment for the spawned CGI program.
7214 * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
7215 * last element must be NULL.
7216 * However, on Windows there is a requirement that all these VARIABLE=VALUE\0
7217 * strings must reside in a contiguous buffer. The end of the buffer is
7218 * marked by two '\0' characters.
7219 * We satisfy both worlds: we create an envp array (which is vars), all
7220 * entries are actually pointers inside buf. */
7221 struct cgi_environment {
7222 struct mg_connection *conn;
7223 /* Data block */
7224 char *buf; /* Environment buffer */
7225 size_t buflen; /* Space available in buf */
7226 size_t bufused; /* Space taken in buf */
7227 /* Index block */
7228 char **var; /* char **envp */
7229 size_t varlen; /* Number of variables available in var */
7230 size_t varused; /* Number of variables stored in var */
7231 };
7232
7233
7234 static void addenv(struct cgi_environment *env,
7235 PRINTF_FORMAT_STRING(const char *fmt),
7236 ...) PRINTF_ARGS(2, 3);
7237
7238 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
7239 * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
7240 static void
7241 addenv(struct cgi_environment *env, const char *fmt, ...)
7242 {
7243 size_t n, space;
7244 int truncated;
7245 char *added;
7246 va_list ap;
7247
7248 /* Calculate how much space is left in the buffer */
7249 space = (env->buflen - env->bufused);
7250
7251 /* Calculate an estimate for the required space */
7252 n = strlen(fmt) + 2 + 128;
7253
7254 do {
7255 if (space <= n) {
7256 /* Allocate new buffer */
7257 n = env->buflen + CGI_ENVIRONMENT_SIZE;
7258 added = (char *)mg_realloc(env->buf, n);
7259 if (!added) {
7260 /* Out of memory */
7261 mg_cry(env->conn,
7262 "%s: Cannot allocate memory for CGI variable [%s]",
7263 __func__,
7264 fmt);
7265 return;
7266 }
7267 env->buf = added;
7268 env->buflen = n;
7269 space = (env->buflen - env->bufused);
7270 }
7271
7272 /* Make a pointer to the free space int the buffer */
7273 added = env->buf + env->bufused;
7274
7275 /* Copy VARIABLE=VALUE\0 string into the free space */
7276 va_start(ap, fmt);
7277 mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
7278 va_end(ap);
7279
7280 /* Do not add truncated strings to the environment */
7281 if (truncated) {
7282 /* Reallocate the buffer */
7283 space = 0;
7284 n = 1;
7285 }
7286 } while (truncated);
7287
7288 /* Calculate number of bytes added to the environment */
7289 n = strlen(added) + 1;
7290 env->bufused += n;
7291
7292 /* Now update the variable index */
7293 space = (env->varlen - env->varused);
7294 if (space < 2) {
7295 mg_cry(env->conn,
7296 "%s: Cannot register CGI variable [%s]",
7297 __func__,
7298 fmt);
7299 return;
7300 }
7301
7302 /* Append a pointer to the added string into the envp array */
7303 env->var[env->varused] = added;
7304 env->varused++;
7305 }
7306
7307
7308 static void
7309 prepare_cgi_environment(struct mg_connection *conn,
7310 const char *prog,
7311 struct cgi_environment *env)
7312 {
7313 const char *s;
7314 struct vec var_vec;
7315 char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
7316 int i, truncated;
7317
7318 if (conn == NULL || prog == NULL || env == NULL) {
7319 return;
7320 }
7321
7322 env->conn = conn;
7323 env->buflen = CGI_ENVIRONMENT_SIZE;
7324 env->bufused = 0;
7325 env->buf = (char *)mg_malloc(env->buflen);
7326 env->varlen = MAX_CGI_ENVIR_VARS;
7327 env->varused = 0;
7328 env->var = (char **)mg_malloc(env->buflen * sizeof(char *));
7329
7330 addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
7331 addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7332 addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7333 addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
7334
7335 /* Prepare the environment block */
7336 addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
7337 addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
7338 addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
7339
7340 #if defined(USE_IPV6)
7341 if (conn->client.lsa.sa.sa_family == AF_INET6) {
7342 addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
7343 } else
7344 #endif
7345 {
7346 addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
7347 }
7348
7349 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
7350 addenv(env, "REMOTE_ADDR=%s", src_addr);
7351
7352 addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
7353 addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
7354
7355 addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
7356 addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
7357
7358 /* SCRIPT_NAME */
7359 addenv(env,
7360 "SCRIPT_NAME=%.*s",
7361 (int)strlen(conn->request_info.local_uri)
7362 - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)),
7363 conn->request_info.local_uri);
7364
7365 addenv(env, "SCRIPT_FILENAME=%s", prog);
7366 if (conn->path_info == NULL) {
7367 addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
7368 } else {
7369 addenv(env,
7370 "PATH_TRANSLATED=%s%s",
7371 conn->ctx->config[DOCUMENT_ROOT],
7372 conn->path_info);
7373 }
7374
7375 addenv(env, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
7376
7377 if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
7378 addenv(env, "CONTENT_TYPE=%s", s);
7379 }
7380 if (conn->request_info.query_string != NULL) {
7381 addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
7382 }
7383 if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
7384 addenv(env, "CONTENT_LENGTH=%s", s);
7385 }
7386 if ((s = getenv("PATH")) != NULL) {
7387 addenv(env, "PATH=%s", s);
7388 }
7389 if (conn->path_info != NULL) {
7390 addenv(env, "PATH_INFO=%s", conn->path_info);
7391 }
7392
7393 if (conn->status_code > 0) {
7394 /* CGI error handler should show the status code */
7395 addenv(env, "STATUS=%d", conn->status_code);
7396 }
7397
7398 #if defined(_WIN32)
7399 if ((s = getenv("COMSPEC")) != NULL) {
7400 addenv(env, "COMSPEC=%s", s);
7401 }
7402 if ((s = getenv("SYSTEMROOT")) != NULL) {
7403 addenv(env, "SYSTEMROOT=%s", s);
7404 }
7405 if ((s = getenv("SystemDrive")) != NULL) {
7406 addenv(env, "SystemDrive=%s", s);
7407 }
7408 if ((s = getenv("ProgramFiles")) != NULL) {
7409 addenv(env, "ProgramFiles=%s", s);
7410 }
7411 if ((s = getenv("ProgramFiles(x86)")) != NULL) {
7412 addenv(env, "ProgramFiles(x86)=%s", s);
7413 }
7414 #else
7415 if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
7416 addenv(env, "LD_LIBRARY_PATH=%s", s);
7417 }
7418 #endif /* _WIN32 */
7419
7420 if ((s = getenv("PERLLIB")) != NULL) {
7421 addenv(env, "PERLLIB=%s", s);
7422 }
7423
7424 if (conn->request_info.remote_user != NULL) {
7425 addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
7426 addenv(env, "%s", "AUTH_TYPE=Digest");
7427 }
7428
7429 /* Add all headers as HTTP_* variables */
7430 for (i = 0; i < conn->request_info.num_headers; i++) {
7431
7432 (void)mg_snprintf(conn,
7433 &truncated,
7434 http_var_name,
7435 sizeof(http_var_name),
7436 "HTTP_%s",
7437 conn->request_info.http_headers[i].name);
7438
7439 if (truncated) {
7440 mg_cry(conn,
7441 "%s: HTTP header variable too long [%s]",
7442 __func__,
7443 conn->request_info.http_headers[i].name);
7444 continue;
7445 }
7446
7447 /* Convert variable name into uppercase, and change - to _ */
7448 for (p = http_var_name; *p != '\0'; p++) {
7449 if (*p == '-') {
7450 *p = '_';
7451 }
7452 *p = (char)toupper(*(unsigned char *)p);
7453 }
7454
7455 addenv(env,
7456 "%s=%s",
7457 http_var_name,
7458 conn->request_info.http_headers[i].value);
7459 }
7460
7461 /* Add user-specified variables */
7462 s = conn->ctx->config[CGI_ENVIRONMENT];
7463 while ((s = next_option(s, &var_vec, NULL)) != NULL) {
7464 addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
7465 }
7466
7467 env->var[env->varused] = NULL;
7468 env->buf[env->bufused] = '\0';
7469 }
7470
7471
7472 static void
7473 handle_cgi_request(struct mg_connection *conn, const char *prog)
7474 {
7475 char *buf;
7476 size_t buflen;
7477 int headers_len, data_len, i, truncated;
7478 int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
7479 const char *status, *status_text, *connection_state;
7480 char *pbuf, dir[PATH_MAX], *p;
7481 struct mg_request_info ri;
7482 struct cgi_environment blk;
7483 FILE *in = NULL, *out = NULL, *err = NULL;
7484 struct file fout = STRUCT_FILE_INITIALIZER;
7485 pid_t pid = (pid_t)-1;
7486
7487 if (conn == NULL) {
7488 return;
7489 }
7490
7491 buf = NULL;
7492 buflen = 16384;
7493 prepare_cgi_environment(conn, prog, &blk);
7494
7495 /* CGI must be executed in its own directory. 'dir' must point to the
7496 * directory containing executable program, 'p' must point to the
7497 * executable program name relative to 'dir'. */
7498 (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
7499
7500 if (truncated) {
7501 mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
7502 send_http_error(conn, 500, "Error: %s", "CGI path too long");
7503 goto done;
7504 }
7505
7506 if ((p = strrchr(dir, '/')) != NULL) {
7507 *p++ = '\0';
7508 } else {
7509 dir[0] = '.', dir[1] = '\0';
7510 p = (char *)prog;
7511 }
7512
7513 if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) {
7514 status = strerror(ERRNO);
7515 mg_cry(conn,
7516 "Error: CGI program \"%s\": Can not create CGI pipes: %s",
7517 prog,
7518 status);
7519 send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status);
7520 goto done;
7521 }
7522
7523 pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
7524
7525 if (pid == (pid_t)-1) {
7526 status = strerror(ERRNO);
7527 mg_cry(conn,
7528 "Error: CGI program \"%s\": Can not spawn CGI process: %s",
7529 prog,
7530 status);
7531 send_http_error(conn,
7532 500,
7533 "Error: Cannot spawn CGI process [%s]: %s",
7534 prog,
7535 status);
7536 goto done;
7537 }
7538
7539 /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
7540 set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
7541 set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
7542 set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
7543 set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
7544 set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
7545 set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
7546
7547 /* Parent closes only one side of the pipes.
7548 * If we don't mark them as closed, close() attempt before
7549 * return from this function throws an exception on Windows.
7550 * Windows does not like when closed descriptor is closed again. */
7551 (void)close(fdin[0]);
7552 (void)close(fdout[1]);
7553 (void)close(fderr[1]);
7554 fdin[0] = fdout[1] = fderr[1] = -1;
7555
7556 if ((in = fdopen(fdin[1], "wb")) == NULL) {
7557 status = strerror(ERRNO);
7558 mg_cry(conn,
7559 "Error: CGI program \"%s\": Can not open stdin: %s",
7560 prog,
7561 status);
7562 send_http_error(conn,
7563 500,
7564 "Error: CGI can not open fdin\nfopen: %s",
7565 status);
7566 goto done;
7567 }
7568
7569 if ((out = fdopen(fdout[0], "rb")) == NULL) {
7570 status = strerror(ERRNO);
7571 mg_cry(conn,
7572 "Error: CGI program \"%s\": Can not open stdout: %s",
7573 prog,
7574 status);
7575 send_http_error(conn,
7576 500,
7577 "Error: CGI can not open fdout\nfopen: %s",
7578 status);
7579 goto done;
7580 }
7581
7582 if ((err = fdopen(fderr[0], "rb")) == NULL) {
7583 status = strerror(ERRNO);
7584 mg_cry(conn,
7585 "Error: CGI program \"%s\": Can not open stderr: %s",
7586 prog,
7587 status);
7588 send_http_error(conn,
7589 500,
7590 "Error: CGI can not open fdout\nfopen: %s",
7591 status);
7592 goto done;
7593 }
7594
7595 setbuf(in, NULL);
7596 setbuf(out, NULL);
7597 setbuf(err, NULL);
7598 fout.fp = out;
7599
7600 if ((conn->request_info.content_length > 0) || conn->is_chunked) {
7601 /* This is a POST/PUT request, or another request with body data. */
7602 if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
7603 /* Error sending the body data */
7604 mg_cry(conn,
7605 "Error: CGI program \"%s\": Forward body data failed",
7606 prog);
7607 goto done;
7608 }
7609 }
7610
7611 /* Close so child gets an EOF. */
7612 fclose(in);
7613 in = NULL;
7614 fdin[1] = -1;
7615
7616 /* Now read CGI reply into a buffer. We need to set correct
7617 * status code, thus we need to see all HTTP headers first.
7618 * Do not send anything back to client, until we buffer in all
7619 * HTTP headers. */
7620 data_len = 0;
7621 buf = (char *)mg_malloc(buflen);
7622 if (buf == NULL) {
7623 send_http_error(conn,
7624 500,
7625 "Error: Not enough memory for CGI buffer (%u bytes)",
7626 (unsigned int)buflen);
7627 mg_cry(conn,
7628 "Error: CGI program \"%s\": Not enough memory for buffer (%u "
7629 "bytes)",
7630 prog,
7631 (unsigned int)buflen);
7632 goto done;
7633 }
7634 headers_len = read_request(out, conn, buf, (int)buflen, &data_len);
7635 if (headers_len <= 0) {
7636
7637 /* Could not parse the CGI response. Check if some error message on
7638 * stderr. */
7639 i = pull_all(err, conn, buf, (int)buflen);
7640 if (i > 0) {
7641 mg_cry(conn,
7642 "Error: CGI program \"%s\" sent error "
7643 "message: [%.*s]",
7644 prog,
7645 i,
7646 buf);
7647 send_http_error(conn,
7648 500,
7649 "Error: CGI program \"%s\" sent error "
7650 "message: [%.*s]",
7651 prog,
7652 i,
7653 buf);
7654 } else {
7655 mg_cry(conn,
7656 "Error: CGI program sent malformed or too big "
7657 "(>%u bytes) HTTP headers: [%.*s]",
7658 (unsigned)buflen,
7659 data_len,
7660 buf);
7661
7662 send_http_error(conn,
7663 500,
7664 "Error: CGI program sent malformed or too big "
7665 "(>%u bytes) HTTP headers: [%.*s]",
7666 (unsigned)buflen,
7667 data_len,
7668 buf);
7669 }
7670
7671 goto done;
7672 }
7673 pbuf = buf;
7674 buf[headers_len - 1] = '\0';
7675 parse_http_headers(&pbuf, &ri);
7676
7677 /* Make up and send the status line */
7678 status_text = "OK";
7679 if ((status = get_header(&ri, "Status")) != NULL) {
7680 conn->status_code = atoi(status);
7681 status_text = status;
7682 while (isdigit(*(const unsigned char *)status_text)
7683 || *status_text == ' ') {
7684 status_text++;
7685 }
7686 } else if (get_header(&ri, "Location") != NULL) {
7687 conn->status_code = 302;
7688 } else {
7689 conn->status_code = 200;
7690 }
7691 connection_state = get_header(&ri, "Connection");
7692 if (!header_has_option(connection_state, "keep-alive")) {
7693 conn->must_close = 1;
7694 }
7695 (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
7696
7697 /* Send headers */
7698 for (i = 0; i < ri.num_headers; i++) {
7699 mg_printf(conn,
7700 "%s: %s\r\n",
7701 ri.http_headers[i].name,
7702 ri.http_headers[i].value);
7703 }
7704 mg_write(conn, "\r\n", 2);
7705
7706 /* Send chunk of data that may have been read after the headers */
7707 conn->num_bytes_sent +=
7708 mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
7709
7710 /* Read the rest of CGI output and send to the client */
7711 send_file_data(conn, &fout, 0, INT64_MAX);
7712
7713 done:
7714 mg_free(blk.var);
7715 mg_free(blk.buf);
7716
7717 if (pid != (pid_t)-1) {
7718 kill(pid, SIGKILL);
7719 #if !defined(_WIN32)
7720 {
7721 int st;
7722 while (waitpid(pid, &st, 0) != -1)
7723 ; /* clean zombies */
7724 }
7725 #endif
7726 }
7727 if (fdin[0] != -1) {
7728 close(fdin[0]);
7729 }
7730 if (fdout[1] != -1) {
7731 close(fdout[1]);
7732 }
7733
7734 if (in != NULL) {
7735 fclose(in);
7736 } else if (fdin[1] != -1) {
7737 close(fdin[1]);
7738 }
7739
7740 if (out != NULL) {
7741 fclose(out);
7742 } else if (fdout[0] != -1) {
7743 close(fdout[0]);
7744 }
7745
7746 if (err != NULL) {
7747 fclose(err);
7748 } else if (fderr[0] != -1) {
7749 close(fderr[0]);
7750 }
7751
7752 if (buf != NULL) {
7753 mg_free(buf);
7754 }
7755 }
7756 #endif /* !NO_CGI */
7757
7758
7759 #if !defined(NO_FILES)
7760 static void
7761 mkcol(struct mg_connection *conn, const char *path)
7762 {
7763 int rc, body_len;
7764 struct de de;
7765 char date[64];
7766 time_t curtime = time(NULL);
7767
7768 if (conn == NULL) {
7769 return;
7770 }
7771
7772 /* TODO (mid): Check the send_http_error situations in this function */
7773
7774 memset(&de.file, 0, sizeof(de.file));
7775 if (!mg_stat(conn, path, &de.file)) {
7776 mg_cry(conn,
7777 "%s: mg_stat(%s) failed: %s",
7778 __func__,
7779 path,
7780 strerror(ERRNO));
7781 }
7782
7783 if (de.file.last_modified) {
7784 /* TODO (high): This check does not seem to make any sense ! */
7785 send_http_error(
7786 conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7787 return;
7788 }
7789
7790 body_len = conn->data_len - conn->request_len;
7791 if (body_len > 0) {
7792 send_http_error(
7793 conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7794 return;
7795 }
7796
7797 rc = mg_mkdir(conn, path, 0755);
7798
7799 if (rc == 0) {
7800 conn->status_code = 201;
7801 gmt_time_string(date, sizeof(date), &curtime);
7802 mg_printf(conn,
7803 "HTTP/1.1 %d Created\r\n"
7804 "Date: %s\r\n",
7805 conn->status_code,
7806 date);
7807 send_static_cache_header(conn);
7808 mg_printf(conn,
7809 "Content-Length: 0\r\n"
7810 "Connection: %s\r\n\r\n",
7811 suggest_connection_header(conn));
7812 } else if (rc == -1) {
7813 if (errno == EEXIST) {
7814 send_http_error(
7815 conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7816 } else if (errno == EACCES) {
7817 send_http_error(
7818 conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7819 } else if (errno == ENOENT) {
7820 send_http_error(
7821 conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7822 } else {
7823 send_http_error(conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
7824 }
7825 }
7826 }
7827
7828
7829 static void
7830 put_file(struct mg_connection *conn, const char *path)
7831 {
7832 struct file file = STRUCT_FILE_INITIALIZER;
7833 const char *range;
7834 int64_t r1, r2;
7835 int rc;
7836 char date[64];
7837 time_t curtime = time(NULL);
7838
7839 if (conn == NULL) {
7840 return;
7841 }
7842
7843 if (mg_stat(conn, path, &file)) {
7844 /* File already exists */
7845 conn->status_code = 200;
7846
7847 if (file.is_directory) {
7848 /* This is an already existing directory,
7849 * so there is nothing to do for the server. */
7850 rc = 0;
7851
7852 } else {
7853 /* File exists and is not a directory. */
7854 /* Can it be replaced? */
7855
7856 if (file.membuf != NULL) {
7857 /* This is an "in-memory" file, that can not be replaced */
7858 send_http_error(
7859 conn,
7860 405,
7861 "Error: Put not possible\nReplacing %s is not supported",
7862 path);
7863 return;
7864 }
7865
7866 /* Check if the server may write this file */
7867 if (access(path, W_OK) == 0) {
7868 /* Access granted */
7869 conn->status_code = 200;
7870 rc = 1;
7871 } else {
7872 send_http_error(
7873 conn,
7874 403,
7875 "Error: Put not possible\nReplacing %s is not allowed",
7876 path);
7877 return;
7878 }
7879 }
7880 } else {
7881 /* File should be created */
7882 conn->status_code = 201;
7883 rc = put_dir(conn, path);
7884 }
7885
7886 if (rc == 0) {
7887 /* put_dir returns 0 if path is a directory */
7888 gmt_time_string(date, sizeof(date), &curtime);
7889 mg_printf(conn,
7890 "HTTP/1.1 %d %s\r\n",
7891 conn->status_code,
7892 mg_get_response_code_text(NULL, conn->status_code));
7893 send_no_cache_header(conn);
7894 mg_printf(conn,
7895 "Date: %s\r\n"
7896 "Content-Length: 0\r\n"
7897 "Connection: %s\r\n\r\n",
7898 date,
7899 suggest_connection_header(conn));
7900
7901 /* Request to create a directory has been fulfilled successfully.
7902 * No need to put a file. */
7903 return;
7904 }
7905
7906 if (rc == -1) {
7907 /* put_dir returns -1 if the path is too long */
7908 send_http_error(conn,
7909 414,
7910 "Error: Path too long\nput_dir(%s): %s",
7911 path,
7912 strerror(ERRNO));
7913 return;
7914 }
7915
7916 if (rc == -2) {
7917 /* put_dir returns -2 if the directory can not be created */
7918 send_http_error(conn,
7919 500,
7920 "Error: Can not create directory\nput_dir(%s): %s",
7921 path,
7922 strerror(ERRNO));
7923 return;
7924 }
7925
7926 /* A file should be created or overwritten. */
7927 if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
7928 mg_fclose(&file);
7929 send_http_error(conn,
7930 500,
7931 "Error: Can not create file\nfopen(%s): %s",
7932 path,
7933 strerror(ERRNO));
7934 return;
7935 }
7936
7937 fclose_on_exec(&file, conn);
7938 range = mg_get_header(conn, "Content-Range");
7939 r1 = r2 = 0;
7940 if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
7941 conn->status_code = 206; /* Partial content */
7942 fseeko(file.fp, r1, SEEK_SET);
7943 }
7944
7945 if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
7946 /* forward_body_data failed.
7947 * The error code has already been sent to the client,
7948 * and conn->status_code is already set. */
7949 mg_fclose(&file);
7950 return;
7951 }
7952
7953 gmt_time_string(date, sizeof(date), &curtime);
7954 mg_printf(conn,
7955 "HTTP/1.1 %d %s\r\n",
7956 conn->status_code,
7957 mg_get_response_code_text(NULL, conn->status_code));
7958 send_no_cache_header(conn);
7959 mg_printf(conn,
7960 "Date: %s\r\n"
7961 "Content-Length: 0\r\n"
7962 "Connection: %s\r\n\r\n",
7963 date,
7964 suggest_connection_header(conn));
7965
7966 mg_fclose(&file);
7967 }
7968
7969
7970 static void
7971 delete_file(struct mg_connection *conn, const char *path)
7972 {
7973 struct de de;
7974 memset(&de.file, 0, sizeof(de.file));
7975 if (!mg_stat(conn, path, &de.file)) {
7976 /* mg_stat returns 0 if the file does not exist */
7977 send_http_error(conn,
7978 404,
7979 "Error: Cannot delete file\nFile %s not found",
7980 path);
7981 return;
7982 }
7983
7984 if (de.file.membuf != NULL) {
7985 /* the file is cached in memory */
7986 send_http_error(
7987 conn,
7988 405,
7989 "Error: Delete not possible\nDeleting %s is not supported",
7990 path);
7991 return;
7992 }
7993
7994 if (de.file.is_directory) {
7995 if (remove_directory(conn, path)) {
7996 /* Delete is successful: Return 204 without content. */
7997 send_http_error(conn, 204, "%s", "");
7998 } else {
7999 /* Delete is not successful: Return 500 (Server error). */
8000 send_http_error(conn, 500, "Error: Could not delete %s", path);
8001 }
8002 return;
8003 }
8004
8005 /* This is an existing file (not a directory).
8006 * Check if write permission is granted. */
8007 if (access(path, W_OK) != 0) {
8008 /* File is read only */
8009 send_http_error(
8010 conn,
8011 403,
8012 "Error: Delete not possible\nDeleting %s is not allowed",
8013 path);
8014 return;
8015 }
8016
8017 /* Try to delete it. */
8018 if (mg_remove(conn, path) == 0) {
8019 /* Delete was successful: Return 204 without content. */
8020 send_http_error(conn, 204, "%s", "");
8021 } else {
8022 /* Delete not successful (file locked). */
8023 send_http_error(conn,
8024 423,
8025 "Error: Cannot delete file\nremove(%s): %s",
8026 path,
8027 strerror(ERRNO));
8028 }
8029 }
8030 #endif /* !NO_FILES */
8031
8032
8033 static void
8034 send_ssi_file(struct mg_connection *, const char *, struct file *, int);
8035
8036
8037 static void
8038 do_ssi_include(struct mg_connection *conn,
8039 const char *ssi,
8040 char *tag,
8041 int include_level)
8042 {
8043 char file_name[MG_BUF_LEN], path[512], *p;
8044 struct file file = STRUCT_FILE_INITIALIZER;
8045 size_t len;
8046 int truncated = 0;
8047
8048 if (conn == NULL) {
8049 return;
8050 }
8051
8052 /* sscanf() is safe here, since send_ssi_file() also uses buffer
8053 * of size MG_BUF_LEN to get the tag. So strlen(tag) is
8054 * always < MG_BUF_LEN. */
8055 if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
8056 /* File name is relative to the webserver root */
8057 file_name[511] = 0;
8058 (void)mg_snprintf(conn,
8059 &truncated,
8060 path,
8061 sizeof(path),
8062 "%s/%s",
8063 conn->ctx->config[DOCUMENT_ROOT],
8064 file_name);
8065
8066 } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
8067 /* File name is relative to the webserver working directory
8068 * or it is absolute system path */
8069 file_name[511] = 0;
8070 (void)
8071 mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
8072
8073 } else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1
8074 || sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
8075 /* File name is relative to the currect document */
8076 file_name[511] = 0;
8077 (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
8078
8079 if (!truncated) {
8080 if ((p = strrchr(path, '/')) != NULL) {
8081 p[1] = '\0';
8082 }
8083 len = strlen(path);
8084 (void)mg_snprintf(conn,
8085 &truncated,
8086 path + len,
8087 sizeof(path) - len,
8088 "%s",
8089 file_name);
8090 }
8091
8092 } else {
8093 mg_cry(conn, "Bad SSI #include: [%s]", tag);
8094 return;
8095 }
8096
8097 if (truncated) {
8098 mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
8099 return;
8100 }
8101
8102 if (!mg_fopen(conn, path, "rb", &file)) {
8103 mg_cry(conn,
8104 "Cannot open SSI #include: [%s]: fopen(%s): %s",
8105 tag,
8106 path,
8107 strerror(ERRNO));
8108 } else {
8109 fclose_on_exec(&file, conn);
8110 if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
8111 strlen(conn->ctx->config[SSI_EXTENSIONS]),
8112 path) > 0) {
8113 send_ssi_file(conn, path, &file, include_level + 1);
8114 } else {
8115 send_file_data(conn, &file, 0, INT64_MAX);
8116 }
8117 mg_fclose(&file);
8118 }
8119 }
8120
8121
8122 #if !defined(NO_POPEN)
8123 static void
8124 do_ssi_exec(struct mg_connection *conn, char *tag)
8125 {
8126 char cmd[1024] = "";
8127 struct file file = STRUCT_FILE_INITIALIZER;
8128
8129 if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
8130 mg_cry(conn, "Bad SSI #exec: [%s]", tag);
8131 } else {
8132 cmd[1023] = 0;
8133 if ((file.fp = popen(cmd, "r")) == NULL) {
8134 mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
8135 } else {
8136 send_file_data(conn, &file, 0, INT64_MAX);
8137 pclose(file.fp);
8138 }
8139 }
8140 }
8141 #endif /* !NO_POPEN */
8142
8143
8144 static int
8145 mg_fgetc(struct file *filep, int offset)
8146 {
8147 if (filep == NULL) {
8148 return EOF;
8149 }
8150 if (filep->membuf != NULL && offset >= 0
8151 && ((unsigned int)(offset)) < filep->size) {
8152 return ((const unsigned char *)filep->membuf)[offset];
8153 } else if (filep->fp != NULL) {
8154 return fgetc(filep->fp);
8155 } else {
8156 return EOF;
8157 }
8158 }
8159
8160
8161 static void
8162 send_ssi_file(struct mg_connection *conn,
8163 const char *path,
8164 struct file *filep,
8165 int include_level)
8166 {
8167 char buf[MG_BUF_LEN];
8168 int ch, offset, len, in_ssi_tag;
8169
8170 if (include_level > 10) {
8171 mg_cry(conn, "SSI #include level is too deep (%s)", path);
8172 return;
8173 }
8174
8175 in_ssi_tag = len = offset = 0;
8176 while ((ch = mg_fgetc(filep, offset)) != EOF) {
8177 if (in_ssi_tag && ch == '>') {
8178 in_ssi_tag = 0;
8179 buf[len++] = (char)ch;
8180 buf[len] = '\0';
8181 /* assert(len <= (int) sizeof(buf)); */
8182 if (len > (int)sizeof(buf)) {
8183 break;
8184 }
8185 if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
8186 /* Not an SSI tag, pass it */
8187 (void)mg_write(conn, buf, (size_t)len);
8188 } else {
8189 if (!memcmp(buf + 5, "include", 7)) {
8190 do_ssi_include(conn, path, buf + 12, include_level);
8191 #if !defined(NO_POPEN)
8192 } else if (!memcmp(buf + 5, "exec", 4)) {
8193 do_ssi_exec(conn, buf + 9);
8194 #endif /* !NO_POPEN */
8195 } else {
8196 mg_cry(conn,
8197 "%s: unknown SSI "
8198 "command: \"%s\"",
8199 path,
8200 buf);
8201 }
8202 }
8203 len = 0;
8204 } else if (in_ssi_tag) {
8205 if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
8206 /* Not an SSI tag */
8207 in_ssi_tag = 0;
8208 } else if (len == (int)sizeof(buf) - 2) {
8209 mg_cry(conn, "%s: SSI tag is too large", path);
8210 len = 0;
8211 }
8212 buf[len++] = (char)(ch & 0xff);
8213 } else if (ch == '<') {
8214 in_ssi_tag = 1;
8215 if (len > 0) {
8216 mg_write(conn, buf, (size_t)len);
8217 }
8218 len = 0;
8219 buf[len++] = (char)(ch & 0xff);
8220 } else {
8221 buf[len++] = (char)(ch & 0xff);
8222 if (len == (int)sizeof(buf)) {
8223 mg_write(conn, buf, (size_t)len);
8224 len = 0;
8225 }
8226 }
8227 }
8228
8229 /* Send the rest of buffered data */
8230 if (len > 0) {
8231 mg_write(conn, buf, (size_t)len);
8232 }
8233 }
8234
8235
8236 static void
8237 handle_ssi_file_request(struct mg_connection *conn,
8238 const char *path,
8239 struct file *filep)
8240 {
8241 char date[64];
8242 time_t curtime = time(NULL);
8243 const char *cors1, *cors2, *cors3;
8244
8245 if (conn == NULL || path == NULL || filep == NULL) {
8246 return;
8247 }
8248
8249 if (mg_get_header(conn, "Origin")) {
8250 /* Cross-origin resource sharing (CORS). */
8251 cors1 = "Access-Control-Allow-Origin: ";
8252 cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
8253 cors3 = "\r\n";
8254 } else {
8255 cors1 = cors2 = cors3 = "";
8256 }
8257
8258 if (!mg_fopen(conn, path, "rb", filep)) {
8259 /* File exists (precondition for calling this function),
8260 * but can not be opened by the server. */
8261 send_http_error(conn,
8262 500,
8263 "Error: Cannot read file\nfopen(%s): %s",
8264 path,
8265 strerror(ERRNO));
8266 } else {
8267 conn->must_close = 1;
8268 gmt_time_string(date, sizeof(date), &curtime);
8269 fclose_on_exec(filep, conn);
8270 mg_printf(conn, "HTTP/1.1 200 OK\r\n");
8271 send_no_cache_header(conn);
8272 mg_printf(conn,
8273 "%s%s%s"
8274 "Date: %s\r\n"
8275 "Content-Type: text/html\r\n"
8276 "Connection: %s\r\n\r\n",
8277 cors1,
8278 cors2,
8279 cors3,
8280 date,
8281 suggest_connection_header(conn));
8282 send_ssi_file(conn, path, filep, 0);
8283 mg_fclose(filep);
8284 }
8285 }
8286
8287
8288 #if !defined(NO_FILES)
8289 static void
8290 send_options(struct mg_connection *conn)
8291 {
8292 char date[64];
8293 time_t curtime = time(NULL);
8294
8295 if (!conn) {
8296 return;
8297 }
8298
8299 conn->status_code = 200;
8300 conn->must_close = 1;
8301 gmt_time_string(date, sizeof(date), &curtime);
8302
8303 mg_printf(conn,
8304 "HTTP/1.1 200 OK\r\n"
8305 "Date: %s\r\n"
8306 /* TODO: "Cache-Control" (?) */
8307 "Connection: %s\r\n"
8308 "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
8309 "PROPFIND, MKCOL\r\n"
8310 "DAV: 1\r\n\r\n",
8311 date,
8312 suggest_connection_header(conn));
8313 }
8314
8315
8316 /* Writes PROPFIND properties for a collection element */
8317 static void
8318 print_props(struct mg_connection *conn, const char *uri, struct file *filep)
8319 {
8320 char mtime[64];
8321
8322 if (conn == NULL || uri == NULL || filep == NULL) {
8323 return;
8324 }
8325
8326 gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
8327 conn->num_bytes_sent +=
8328 mg_printf(conn,
8329 "<d:response>"
8330 "<d:href>%s</d:href>"
8331 "<d:propstat>"
8332 "<d:prop>"
8333 "<d:resourcetype>%s</d:resourcetype>"
8334 "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
8335 "<d:getlastmodified>%s</d:getlastmodified>"
8336 "</d:prop>"
8337 "<d:status>HTTP/1.1 200 OK</d:status>"
8338 "</d:propstat>"
8339 "</d:response>\n",
8340 uri,
8341 filep->is_directory ? "<d:collection/>" : "",
8342 filep->size,
8343 mtime);
8344 }
8345
8346
8347 static void
8348 print_dav_dir_entry(struct de *de, void *data)
8349 {
8350 char href[PATH_MAX];
8351 char href_encoded[PATH_MAX];
8352 int truncated;
8353
8354 struct mg_connection *conn = (struct mg_connection *)data;
8355 if (!de || !conn) {
8356 return;
8357 }
8358 mg_snprintf(conn,
8359 &truncated,
8360 href,
8361 sizeof(href),
8362 "%s%s",
8363 conn->request_info.local_uri,
8364 de->file_name);
8365
8366 if (!truncated) {
8367 mg_url_encode(href, href_encoded, PATH_MAX - 1);
8368 print_props(conn, href_encoded, &de->file);
8369 }
8370 }
8371
8372
8373 static void
8374 handle_propfind(struct mg_connection *conn,
8375 const char *path,
8376 struct file *filep)
8377 {
8378 const char *depth = mg_get_header(conn, "Depth");
8379 char date[64];
8380 time_t curtime = time(NULL);
8381
8382 gmt_time_string(date, sizeof(date), &curtime);
8383
8384 if (!conn || !path || !filep || !conn->ctx) {
8385 return;
8386 }
8387
8388 conn->must_close = 1;
8389 conn->status_code = 207;
8390 mg_printf(conn,
8391 "HTTP/1.1 207 Multi-Status\r\n"
8392 "Date: %s\r\n",
8393 date);
8394 send_static_cache_header(conn);
8395 mg_printf(conn,
8396 "Connection: %s\r\n"
8397 "Content-Type: text/xml; charset=utf-8\r\n\r\n",
8398 suggest_connection_header(conn));
8399
8400 conn->num_bytes_sent +=
8401 mg_printf(conn,
8402 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
8403 "<d:multistatus xmlns:d='DAV:'>\n");
8404
8405 /* Print properties for the requested resource itself */
8406 print_props(conn, conn->request_info.local_uri, filep);
8407
8408 /* If it is a directory, print directory entries too if Depth is not 0 */
8409 if (filep && filep->is_directory
8410 && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
8411 && (depth == NULL || strcmp(depth, "0") != 0)) {
8412 scan_directory(conn, path, conn, &print_dav_dir_entry);
8413 }
8414
8415 conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
8416 }
8417 #endif
8418
8419 void
8420 mg_lock_connection(struct mg_connection *conn)
8421 {
8422 if (conn) {
8423 (void)pthread_mutex_lock(&conn->mutex);
8424 }
8425 }
8426
8427 void
8428 mg_unlock_connection(struct mg_connection *conn)
8429 {
8430 if (conn) {
8431 (void)pthread_mutex_unlock(&conn->mutex);
8432 }
8433 }
8434
8435 void
8436 mg_lock_context(struct mg_context *ctx)
8437 {
8438 if (ctx) {
8439 (void)pthread_mutex_lock(&ctx->nonce_mutex);
8440 }
8441 }
8442
8443 void
8444 mg_unlock_context(struct mg_context *ctx)
8445 {
8446 if (ctx) {
8447 (void)pthread_mutex_unlock(&ctx->nonce_mutex);
8448 }
8449 }
8450
8451 #if defined(USE_TIMERS)
8452 #include "timer.inl"
8453 #endif /* USE_TIMERS */
8454
8455 #ifdef USE_LUA
8456 #include "mod_lua.inl"
8457 #endif /* USE_LUA */
8458
8459 #ifdef USE_DUKTAPE
8460 #include "mod_duktape.inl"
8461 #endif /* USE_DUKTAPE */
8462
8463 #if defined(USE_WEBSOCKET)
8464
8465 /* START OF SHA-1 code
8466 * Copyright(c) By Steve Reid <steve@edmweb.com> */
8467 #define SHA1HANDSOFF
8468
8469 /* According to current tests (May 2015), the <solarisfixes.h> is not required.
8470 *
8471 * #if defined(__sun)
8472 * #include "solarisfixes.h"
8473 * #endif
8474 */
8475
8476
8477 static int
8478 is_big_endian(void)
8479 {
8480 static const int n = 1;
8481 return ((char *)&n)[0] == 0;
8482 }
8483
8484
8485 union char64long16 {
8486 unsigned char c[64];
8487 uint32_t l[16];
8488 };
8489
8490 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
8491
8492
8493 static uint32_t
8494 blk0(union char64long16 *block, int i)
8495 {
8496 /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
8497 if (!is_big_endian()) {
8498 block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
8499 | (rol(block->l[i], 8) & 0x00FF00FF);
8500 }
8501 return block->l[i];
8502 }
8503
8504 #define blk(i) \
8505 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
8506 ^ block->l[(i + 2) & 15] ^ block->l[i & 15], \
8507 1))
8508 #define R0(v, w, x, y, z, i) \
8509 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
8510 w = rol(w, 30);
8511 #define R1(v, w, x, y, z, i) \
8512 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
8513 w = rol(w, 30);
8514 #define R2(v, w, x, y, z, i) \
8515 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
8516 w = rol(w, 30);
8517 #define R3(v, w, x, y, z, i) \
8518 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
8519 w = rol(w, 30);
8520 #define R4(v, w, x, y, z, i) \
8521 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
8522 w = rol(w, 30);
8523
8524
8525 typedef struct {
8526 uint32_t state[5];
8527 uint32_t count[2];
8528 unsigned char buffer[64];
8529 } SHA1_CTX;
8530
8531
8532 static void
8533 SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
8534 {
8535 uint32_t a, b, c, d, e;
8536 union char64long16 block[1];
8537
8538 memcpy(block, buffer, 64);
8539 a = state[0];
8540 b = state[1];
8541 c = state[2];
8542 d = state[3];
8543 e = state[4];
8544 R0(a, b, c, d, e, 0);
8545 R0(e, a, b, c, d, 1);
8546 R0(d, e, a, b, c, 2);
8547 R0(c, d, e, a, b, 3);
8548 R0(b, c, d, e, a, 4);
8549 R0(a, b, c, d, e, 5);
8550 R0(e, a, b, c, d, 6);
8551 R0(d, e, a, b, c, 7);
8552 R0(c, d, e, a, b, 8);
8553 R0(b, c, d, e, a, 9);
8554 R0(a, b, c, d, e, 10);
8555 R0(e, a, b, c, d, 11);
8556 R0(d, e, a, b, c, 12);
8557 R0(c, d, e, a, b, 13);
8558 R0(b, c, d, e, a, 14);
8559 R0(a, b, c, d, e, 15);
8560 R1(e, a, b, c, d, 16);
8561 R1(d, e, a, b, c, 17);
8562 R1(c, d, e, a, b, 18);
8563 R1(b, c, d, e, a, 19);
8564 R2(a, b, c, d, e, 20);
8565 R2(e, a, b, c, d, 21);
8566 R2(d, e, a, b, c, 22);
8567 R2(c, d, e, a, b, 23);
8568 R2(b, c, d, e, a, 24);
8569 R2(a, b, c, d, e, 25);
8570 R2(e, a, b, c, d, 26);
8571 R2(d, e, a, b, c, 27);
8572 R2(c, d, e, a, b, 28);
8573 R2(b, c, d, e, a, 29);
8574 R2(a, b, c, d, e, 30);
8575 R2(e, a, b, c, d, 31);
8576 R2(d, e, a, b, c, 32);
8577 R2(c, d, e, a, b, 33);
8578 R2(b, c, d, e, a, 34);
8579 R2(a, b, c, d, e, 35);
8580 R2(e, a, b, c, d, 36);
8581 R2(d, e, a, b, c, 37);
8582 R2(c, d, e, a, b, 38);
8583 R2(b, c, d, e, a, 39);
8584 R3(a, b, c, d, e, 40);
8585 R3(e, a, b, c, d, 41);
8586 R3(d, e, a, b, c, 42);
8587 R3(c, d, e, a, b, 43);
8588 R3(b, c, d, e, a, 44);
8589 R3(a, b, c, d, e, 45);
8590 R3(e, a, b, c, d, 46);
8591 R3(d, e, a, b, c, 47);
8592 R3(c, d, e, a, b, 48);
8593 R3(b, c, d, e, a, 49);
8594 R3(a, b, c, d, e, 50);
8595 R3(e, a, b, c, d, 51);
8596 R3(d, e, a, b, c, 52);
8597 R3(c, d, e, a, b, 53);
8598 R3(b, c, d, e, a, 54);
8599 R3(a, b, c, d, e, 55);
8600 R3(e, a, b, c, d, 56);
8601 R3(d, e, a, b, c, 57);
8602 R3(c, d, e, a, b, 58);
8603 R3(b, c, d, e, a, 59);
8604 R4(a, b, c, d, e, 60);
8605 R4(e, a, b, c, d, 61);
8606 R4(d, e, a, b, c, 62);
8607 R4(c, d, e, a, b, 63);
8608 R4(b, c, d, e, a, 64);
8609 R4(a, b, c, d, e, 65);
8610 R4(e, a, b, c, d, 66);
8611 R4(d, e, a, b, c, 67);
8612 R4(c, d, e, a, b, 68);
8613 R4(b, c, d, e, a, 69);
8614 R4(a, b, c, d, e, 70);
8615 R4(e, a, b, c, d, 71);
8616 R4(d, e, a, b, c, 72);
8617 R4(c, d, e, a, b, 73);
8618 R4(b, c, d, e, a, 74);
8619 R4(a, b, c, d, e, 75);
8620 R4(e, a, b, c, d, 76);
8621 R4(d, e, a, b, c, 77);
8622 R4(c, d, e, a, b, 78);
8623 R4(b, c, d, e, a, 79);
8624 state[0] += a;
8625 state[1] += b;
8626 state[2] += c;
8627 state[3] += d;
8628 state[4] += e;
8629 a = b = c = d = e = 0;
8630 memset(block, '\0', sizeof(block));
8631 }
8632
8633
8634 static void
8635 SHA1Init(SHA1_CTX *context)
8636 {
8637 context->state[0] = 0x67452301;
8638 context->state[1] = 0xEFCDAB89;
8639 context->state[2] = 0x98BADCFE;
8640 context->state[3] = 0x10325476;
8641 context->state[4] = 0xC3D2E1F0;
8642 context->count[0] = context->count[1] = 0;
8643 }
8644
8645
8646 static void
8647 SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
8648 {
8649 uint32_t i, j;
8650
8651 j = context->count[0];
8652 if ((context->count[0] += len << 3) < j) {
8653 context->count[1]++;
8654 }
8655 context->count[1] += (len >> 29);
8656 j = (j >> 3) & 63;
8657 if ((j + len) > 63) {
8658 memcpy(&context->buffer[j], data, (i = 64 - j));
8659 SHA1Transform(context->state, context->buffer);
8660 for (; i + 63 < len; i += 64) {
8661 SHA1Transform(context->state, &data[i]);
8662 }
8663 j = 0;
8664 } else
8665 i = 0;
8666 memcpy(&context->buffer[j], &data[i], len - i);
8667 }
8668
8669
8670 static void
8671 SHA1Final(unsigned char digest[20], SHA1_CTX *context)
8672 {
8673 unsigned i;
8674 unsigned char finalcount[8], c;
8675
8676 for (i = 0; i < 8; i++) {
8677 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
8678 >> ((3 - (i & 3)) * 8)) & 255);
8679 }
8680 c = 0200;
8681 SHA1Update(context, &c, 1);
8682 while ((context->count[0] & 504) != 448) {
8683 c = 0000;
8684 SHA1Update(context, &c, 1);
8685 }
8686 SHA1Update(context, finalcount, 8);
8687 for (i = 0; i < 20; i++) {
8688 digest[i] = (unsigned char)((context->state[i >> 2]
8689 >> ((3 - (i & 3)) * 8)) & 255);
8690 }
8691 memset(context, '\0', sizeof(*context));
8692 memset(&finalcount, '\0', sizeof(finalcount));
8693 }
8694 /* END OF SHA1 CODE */
8695
8696
8697 static int
8698 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
8699 {
8700 static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
8701 const char *protocol = NULL;
8702 char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
8703 SHA1_CTX sha_ctx;
8704 int truncated;
8705
8706 /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
8707 mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
8708 if (truncated) {
8709 conn->must_close = 1;
8710 return 0;
8711 }
8712
8713 SHA1Init(&sha_ctx);
8714 SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
8715 SHA1Final((unsigned char *)sha, &sha_ctx);
8716 base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
8717 mg_printf(conn,
8718 "HTTP/1.1 101 Switching Protocols\r\n"
8719 "Upgrade: websocket\r\n"
8720 "Connection: Upgrade\r\n"
8721 "Sec-WebSocket-Accept: %s\r\n",
8722 b64_sha);
8723 protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
8724 if (protocol) {
8725 /* The protocol is a comma seperated list of names. */
8726 /* The server must only return one value from this list. */
8727 /* First check if it is a list or just a single value. */
8728 const char *sep = strchr(protocol, ',');
8729 if (sep == NULL) {
8730 /* Just a single protocol -> accept it. */
8731 mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", protocol);
8732 } else {
8733 /* Multiple protocols -> accept the first one. */
8734 /* This is just a quick fix if the client offers multiple
8735 * protocols. In order to get the behavior intended by
8736 * RFC 6455 (https://tools.ietf.org/rfc/rfc6455.txt), it is
8737 * required to have a list of websocket subprotocols accepted
8738 * by the server. Then the server must either select a subprotocol
8739 * supported by client and server, or the server has to abort the
8740 * handshake by not returning a Sec-Websocket-Protocol header if
8741 * no subprotocol is acceptable.
8742 */
8743 mg_printf(conn,
8744 "Sec-WebSocket-Protocol: %.*s\r\n\r\n",
8745 (int)(sep - protocol),
8746 protocol);
8747 }
8748 /* TODO: Real subprotocol negotiation instead of just taking the first
8749 * websocket subprotocol suggested by the client. */
8750 } else {
8751 mg_printf(conn, "%s", "\r\n");
8752 }
8753
8754 return 1;
8755 }
8756
8757
8758 static void
8759 read_websocket(struct mg_connection *conn,
8760 mg_websocket_data_handler ws_data_handler,
8761 void *callback_data)
8762 {
8763 /* Pointer to the beginning of the portion of the incoming websocket
8764 * message queue.
8765 * The original websocket upgrade request is never removed, so the queue
8766 * begins after it. */
8767 unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
8768 int n, error, exit_by_callback;
8769
8770 /* body_len is the length of the entire queue in bytes
8771 * len is the length of the current message
8772 * data_len is the length of the current message's data payload
8773 * header_len is the length of the current message's header */
8774 size_t i, len, mask_len = 0, data_len = 0, header_len, body_len;
8775
8776 /* "The masking key is a 32-bit value chosen at random by the client."
8777 * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
8778 */
8779 unsigned char mask[4];
8780
8781 /* data points to the place where the message is stored when passed to
8782 * the
8783 * websocket_data callback. This is either mem on the stack, or a
8784 * dynamically allocated buffer if it is too large. */
8785 char mem[4096];
8786 char *data = mem;
8787 unsigned char mop; /* mask flag and opcode */
8788 double timeout = -1.0;
8789
8790 if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
8791 timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
8792 }
8793 if ((timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
8794 timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
8795 }
8796
8797 mg_set_thread_name("wsock");
8798
8799 /* Loop continuously, reading messages from the socket, invoking the
8800 * callback, and waiting repeatedly until an error occurs. */
8801 while (!conn->ctx->stop_flag) {
8802 header_len = 0;
8803 assert(conn->data_len >= conn->request_len);
8804 if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
8805 len = buf[1] & 127;
8806 mask_len = buf[1] & 128 ? 4 : 0;
8807 if (len < 126 && body_len >= mask_len) {
8808 data_len = len;
8809 header_len = 2 + mask_len;
8810 } else if (len == 126 && body_len >= 4 + mask_len) {
8811 header_len = 4 + mask_len;
8812 data_len = ((((size_t)buf[2]) << 8) + buf[3]);
8813 } else if (body_len >= 10 + mask_len) {
8814 header_len = 10 + mask_len;
8815 data_len = (((uint64_t)ntohl(*(uint32_t *)(void *)&buf[2]))
8816 << 32) + ntohl(*(uint32_t *)(void *)&buf[6]);
8817 }
8818 }
8819
8820 if (header_len > 0 && body_len >= header_len) {
8821 /* Allocate space to hold websocket payload */
8822 data = mem;
8823 if (data_len > sizeof(mem)) {
8824 data = (char *)mg_malloc(data_len);
8825 if (data == NULL) {
8826 /* Allocation failed, exit the loop and then close the
8827 * connection */
8828 mg_cry(conn, "websocket out of memory; closing connection");
8829 break;
8830 }
8831 }
8832
8833 /* Copy the mask before we shift the queue and destroy it */
8834 if (mask_len > 0) {
8835 memcpy(mask, buf + header_len - mask_len, sizeof(mask));
8836 } else {
8837 memset(mask, 0, sizeof(mask));
8838 }
8839
8840 /* Read frame payload from the first message in the queue into
8841 * data and advance the queue by moving the memory in place. */
8842 assert(body_len >= header_len);
8843 if (data_len + header_len > body_len) {
8844 mop = buf[0]; /* current mask and opcode */
8845 /* Overflow case */
8846 len = body_len - header_len;
8847 memcpy(data, buf + header_len, len);
8848 error = 0;
8849 while (len < data_len) {
8850 n = pull(
8851 NULL, conn, data + len, (int)(data_len - len), timeout);
8852 if (n <= 0) {
8853 error = 1;
8854 break;
8855 }
8856 len += (size_t)n;
8857 }
8858 if (error) {
8859 mg_cry(conn, "Websocket pull failed; closing connection");
8860 break;
8861 }
8862 conn->data_len = conn->request_len;
8863 } else {
8864 mop = buf[0]; /* current mask and opcode, overwritten by
8865 * memmove() */
8866 /* Length of the message being read at the front of the
8867 * queue */
8868 len = data_len + header_len;
8869
8870 /* Copy the data payload into the data pointer for the
8871 * callback */
8872 memcpy(data, buf + header_len, data_len);
8873
8874 /* Move the queue forward len bytes */
8875 memmove(buf, buf + len, body_len - len);
8876
8877 /* Mark the queue as advanced */
8878 conn->data_len -= (int)len;
8879 }
8880
8881 /* Apply mask if necessary */
8882 if (mask_len > 0) {
8883 for (i = 0; i < data_len; ++i) {
8884 data[i] ^= mask[i & 3];
8885 }
8886 }
8887
8888 /* Exit the loop if callback signals to exit (server side),
8889 * or "connection close" opcode received (client side). */
8890 exit_by_callback = 0;
8891 if ((ws_data_handler != NULL)
8892 && !ws_data_handler(conn, mop, data, data_len, callback_data)) {
8893 exit_by_callback = 1;
8894 }
8895
8896 if (data != mem) {
8897 mg_free(data);
8898 }
8899
8900 if (exit_by_callback
8901 || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
8902 /* Opcode == 8, connection close */
8903 break;
8904 }
8905
8906 /* Not breaking the loop, process next websocket frame. */
8907 } else {
8908 /* Read from the socket into the next available location in the
8909 * message queue. */
8910 if ((n = pull(NULL,
8911 conn,
8912 conn->buf + conn->data_len,
8913 conn->buf_size - conn->data_len,
8914 timeout)) <= 0) {
8915 /* Error, no bytes read */
8916 break;
8917 }
8918 conn->data_len += n;
8919 }
8920 }
8921
8922 mg_set_thread_name("worker");
8923 }
8924
8925
8926 static int
8927 mg_websocket_write_exec(struct mg_connection *conn,
8928 int opcode,
8929 const char *data,
8930 size_t dataLen,
8931 uint32_t masking_key)
8932 {
8933 unsigned char header[14];
8934 size_t headerLen = 1;
8935
8936 int retval = -1;
8937
8938 header[0] = 0x80 + (opcode & 0xF);
8939
8940 /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
8941 if (dataLen < 126) {
8942 /* inline 7-bit length field */
8943 header[1] = (unsigned char)dataLen;
8944 headerLen = 2;
8945 } else if (dataLen <= 0xFFFF) {
8946 /* 16-bit length field */
8947 header[1] = 126;
8948 *(uint16_t *)(void *)(header + 2) = htons((uint16_t)dataLen);
8949 headerLen = 4;
8950 } else {
8951 /* 64-bit length field */
8952 header[1] = 127;
8953 *(uint32_t *)(void *)(header + 2) = htonl((uint64_t)dataLen >> 32);
8954 *(uint32_t *)(void *)(header + 6) = htonl(dataLen & 0xFFFFFFFF);
8955 headerLen = 10;
8956 }
8957
8958 if (masking_key) {
8959 /* add mask */
8960 header[1] |= 0x80;
8961 *(uint32_t *)(void *)(header + headerLen) = masking_key;
8962 headerLen += 4;
8963 }
8964
8965
8966 /* Note that POSIX/Winsock's send() is threadsafe
8967 * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
8968 * but mongoose's mg_printf/mg_write is not (because of the loop in
8969 * push(), although that is only a problem if the packet is large or
8970 * outgoing buffer is full). */
8971 (void)mg_lock_connection(conn);
8972 retval = mg_write(conn, header, headerLen);
8973 if (dataLen > 0) {
8974 retval = mg_write(conn, data, dataLen);
8975 }
8976 mg_unlock_connection(conn);
8977
8978 return retval;
8979 }
8980
8981 int
8982 mg_websocket_write(struct mg_connection *conn,
8983 int opcode,
8984 const char *data,
8985 size_t dataLen)
8986 {
8987 return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
8988 }
8989
8990
8991 static void
8992 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
8993 {
8994 size_t i = 0;
8995
8996 i = 0;
8997 if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
8998 /* Convert in 32 bit words, if data is 4 byte aligned */
8999 while (i < (in_len - 3)) {
9000 *(uint32_t *)(void *)(out + i) =
9001 *(uint32_t *)(void *)(in + i) ^ masking_key;
9002 i += 4;
9003 }
9004 }
9005 if (i != in_len) {
9006 /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
9007 while (i < in_len) {
9008 *(uint8_t *)(void *)(out + i) =
9009 *(uint8_t *)(void *)(in + i)
9010 ^ *(((uint8_t *)&masking_key) + (i % 4));
9011 i++;
9012 }
9013 }
9014 }
9015
9016
9017 int
9018 mg_websocket_client_write(struct mg_connection *conn,
9019 int opcode,
9020 const char *data,
9021 size_t dataLen)
9022 {
9023 int retval = -1;
9024 char *masked_data = (char *)mg_malloc(((dataLen + 7) / 4) * 4);
9025 uint32_t masking_key = (uint32_t)get_random();
9026
9027 if (masked_data == NULL) {
9028 /* Return -1 in an error case */
9029 mg_cry(conn,
9030 "Cannot allocate buffer for masked websocket response: "
9031 "Out of memory");
9032 return -1;
9033 }
9034
9035 mask_data(data, dataLen, masking_key, masked_data);
9036
9037 retval = mg_websocket_write_exec(
9038 conn, opcode, masked_data, dataLen, masking_key);
9039 mg_free(masked_data);
9040
9041 return retval;
9042 }
9043
9044
9045 static void
9046 handle_websocket_request(struct mg_connection *conn,
9047 const char *path,
9048 int is_callback_resource,
9049 mg_websocket_connect_handler ws_connect_handler,
9050 mg_websocket_ready_handler ws_ready_handler,
9051 mg_websocket_data_handler ws_data_handler,
9052 mg_websocket_close_handler ws_close_handler,
9053 void *cbData)
9054 {
9055 const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
9056 const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
9057 int lua_websock = 0;
9058
9059 #if !defined(USE_LUA)
9060 (void)path;
9061 #endif
9062
9063 /* Step 1: Check websocket protocol version. */
9064 /* Step 1.1: Check Sec-WebSocket-Key. */
9065 if (!websock_key) {
9066 /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
9067 * requires a Sec-WebSocket-Key header.
9068 */
9069 /* It could be the hixie draft version
9070 * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
9071 */
9072 const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
9073 const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
9074 char key3[8];
9075
9076 if ((key1 != NULL) && (key2 != NULL)) {
9077 /* This version uses 8 byte body data in a GET request */
9078 conn->content_len = 8;
9079 if (8 == mg_read(conn, key3, 8)) {
9080 /* This is the hixie version */
9081 send_http_error(conn,
9082 426,
9083 "%s",
9084 "Protocol upgrade to RFC 6455 required");
9085 return;
9086 }
9087 }
9088 /* This is an unknown version */
9089 send_http_error(conn, 400, "%s", "Malformed websocket request");
9090 return;
9091 }
9092
9093 /* Step 1.2: Check websocket protocol version. */
9094 /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
9095 if (version == NULL || strcmp(version, "13") != 0) {
9096 /* Reject wrong versions */
9097 send_http_error(conn, 426, "%s", "Protocol upgrade required");
9098 return;
9099 }
9100
9101 /* Step 1.3: Could check for "Host", but we do not really nead this
9102 * value for anything, so just ignore it. */
9103
9104 /* Step 2: If a callback is responsible, call it. */
9105 if (is_callback_resource) {
9106 if (ws_connect_handler != NULL
9107 && ws_connect_handler(conn, cbData) != 0) {
9108 /* C callback has returned non-zero, do not proceed with
9109 * handshake.
9110 */
9111 /* Note that C callbacks are no longer called when Lua is
9112 * responsible, so C can no longer filter callbacks for Lua. */
9113 return;
9114 }
9115 }
9116 #if defined(USE_LUA)
9117 /* Step 3: No callback. Check if Lua is responsible. */
9118 else {
9119 /* Step 3.1: Check if Lua is responsible. */
9120 if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
9121 lua_websock =
9122 match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
9123 strlen(
9124 conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
9125 path);
9126 }
9127
9128 if (lua_websock) {
9129 /* Step 3.2: Lua is responsible: call it. */
9130 conn->lua_websocket_state = lua_websocket_new(path, conn);
9131 if (!conn->lua_websocket_state) {
9132 /* Lua rejected the new client */
9133 return;
9134 }
9135 }
9136 }
9137 #endif
9138
9139 /* Step 4: Check if there is a responsible websocket handler. */
9140 if (!is_callback_resource && !lua_websock) {
9141 /* There is no callback, an Lua is not responsible either. */
9142 /* Reply with a 404 Not Found or with nothing at all?
9143 * TODO (mid): check the websocket standards, how to reply to
9144 * requests to invalid websocket addresses. */
9145 send_http_error(conn, 404, "%s", "Not found");
9146 return;
9147 }
9148
9149 /* Step 5: The websocket connection has been accepted */
9150 if (!send_websocket_handshake(conn, websock_key)) {
9151 send_http_error(conn, 500, "%s", "Websocket handshake failed");
9152 return;
9153 }
9154
9155 /* Step 6: Call the ready handler */
9156 if (is_callback_resource) {
9157 if (ws_ready_handler != NULL) {
9158 ws_ready_handler(conn, cbData);
9159 }
9160 #if defined(USE_LUA)
9161 } else if (lua_websock) {
9162 if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
9163 /* the ready handler returned false */
9164 return;
9165 }
9166 #endif
9167 }
9168
9169 /* Step 7: Enter the read loop */
9170 if (is_callback_resource) {
9171 read_websocket(conn, ws_data_handler, cbData);
9172 #if defined(USE_LUA)
9173 } else if (lua_websock) {
9174 read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
9175 #endif
9176 }
9177
9178 /* Step 8: Call the close handler */
9179 if (ws_close_handler) {
9180 ws_close_handler(conn, cbData);
9181 }
9182 }
9183
9184
9185 static int
9186 is_websocket_protocol(const struct mg_connection *conn)
9187 {
9188 const char *upgrade, *connection;
9189
9190 /* A websocket protocoll has the following HTTP headers:
9191 *
9192 * Connection: Upgrade
9193 * Upgrade: Websocket
9194 */
9195
9196 upgrade = mg_get_header(conn, "Upgrade");
9197 if (upgrade == NULL) {
9198 return 0; /* fail early, don't waste time checking other header
9199 * fields
9200 */
9201 }
9202 if (!mg_strcasestr(upgrade, "websocket")) {
9203 return 0;
9204 }
9205
9206 connection = mg_get_header(conn, "Connection");
9207 if (connection == NULL) {
9208 return 0;
9209 }
9210 if (!mg_strcasestr(connection, "upgrade")) {
9211 return 0;
9212 }
9213
9214 /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
9215 * "Sec-WebSocket-Version" are also required.
9216 * Don't check them here, since even an unsupported websocket protocol
9217 * request still IS a websocket request (in contrast to a standard HTTP
9218 * request). It will fail later in handle_websocket_request.
9219 */
9220
9221 return 1;
9222 }
9223 #endif /* !USE_WEBSOCKET */
9224
9225
9226 static int
9227 isbyte(int n)
9228 {
9229 return n >= 0 && n <= 255;
9230 }
9231
9232
9233 static int
9234 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
9235 {
9236 int n, a, b, c, d, slash = 32, len = 0;
9237
9238 if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
9239 || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
9240 && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
9241 && slash < 33) {
9242 len = n;
9243 *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
9244 | (uint32_t)d;
9245 *mask = slash ? 0xffffffffU << (32 - slash) : 0;
9246 }
9247
9248 return len;
9249 }
9250
9251
9252 static int
9253 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
9254 {
9255 int throttle = 0;
9256 struct vec vec, val;
9257 uint32_t net, mask;
9258 char mult;
9259 double v;
9260
9261 while ((spec = next_option(spec, &vec, &val)) != NULL) {
9262 mult = ',';
9263 if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0
9264 || (lowercase(&mult) != 'k' && lowercase(&mult) != 'm'
9265 && mult != ',')) {
9266 continue;
9267 }
9268 v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576
9269 : 1;
9270 if (vec.len == 1 && vec.ptr[0] == '*') {
9271 throttle = (int)v;
9272 } else if (parse_net(vec.ptr, &net, &mask) > 0) {
9273 if ((remote_ip & mask) == net) {
9274 throttle = (int)v;
9275 }
9276 } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
9277 throttle = (int)v;
9278 }
9279 }
9280
9281 return throttle;
9282 }
9283
9284
9285 static uint32_t
9286 get_remote_ip(const struct mg_connection *conn)
9287 {
9288 if (!conn) {
9289 return 0;
9290 }
9291 return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
9292 }
9293
9294
9295 /* The mg_upload function is superseeded by mg_handle_form_request. */
9296 #include "handle_form.inl"
9297
9298
9299 #if defined(MG_LEGACY_INTERFACE)
9300 /* Implement the deprecated mg_upload function by calling the new
9301 * mg_handle_form_request function. While mg_upload could only handle
9302 * HTML forms sent as POST request in multipart/form-data format
9303 * containing only file input elements, mg_handle_form_request can
9304 * handle all form input elements and all standard request methods. */
9305 struct mg_upload_user_data {
9306 struct mg_connection *conn;
9307 const char *destination_dir;
9308 int num_uploaded_files;
9309 };
9310
9311
9312 /* Helper function for deprecated mg_upload. */
9313 static int
9314 mg_upload_field_found(const char *key,
9315 const char *filename,
9316 char *path,
9317 size_t pathlen,
9318 void *user_data)
9319 {
9320 int truncated = 0;
9321 struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9322 (void)key;
9323
9324 if (!filename) {
9325 mg_cry(fud->conn, "%s: No filename set", __func__);
9326 return FORM_FIELD_STORAGE_ABORT;
9327 }
9328 mg_snprintf(fud->conn,
9329 &truncated,
9330 path,
9331 pathlen - 1,
9332 "%s/%s",
9333 fud->destination_dir,
9334 filename);
9335 if (!truncated) {
9336 mg_cry(fud->conn, "%s: File path too long", __func__);
9337 return FORM_FIELD_STORAGE_ABORT;
9338 }
9339 return FORM_FIELD_STORAGE_STORE;
9340 }
9341
9342
9343 /* Helper function for deprecated mg_upload. */
9344 static int
9345 mg_upload_field_get(const char *key,
9346 const char *value,
9347 size_t value_size,
9348 void *user_data)
9349 {
9350 /* Function should never be called */
9351 (void)key;
9352 (void)value;
9353 (void)value_size;
9354 (void)user_data;
9355
9356 return 0;
9357 }
9358
9359
9360 /* Helper function for deprecated mg_upload. */
9361 static int
9362 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
9363 {
9364 struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9365 (void)file_size;
9366
9367 fud->num_uploaded_files++;
9368 fud->conn->ctx->callbacks.upload(fud->conn, path);
9369
9370 return 0;
9371 }
9372
9373
9374 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
9375 int
9376 mg_upload(struct mg_connection *conn, const char *destination_dir)
9377 {
9378 struct mg_upload_user_data fud = {conn, destination_dir, 0};
9379 struct mg_form_data_handler fdh = {mg_upload_field_found,
9380 mg_upload_field_get,
9381 mg_upload_field_stored,
9382 0};
9383 int ret;
9384
9385 fdh.user_data = (void *)&fud;
9386 ret = mg_handle_form_request(conn, &fdh);
9387
9388 if (ret < 0) {
9389 mg_cry(conn, "%s: Error while parsing the request", __func__);
9390 }
9391
9392 return fud.num_uploaded_files;
9393 }
9394 #endif
9395
9396
9397 static int
9398 get_first_ssl_listener_index(const struct mg_context *ctx)
9399 {
9400 unsigned int i;
9401 int idx = -1;
9402 if (ctx) {
9403 for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
9404 idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
9405 }
9406 }
9407 return idx;
9408 }
9409
9410
9411 static void
9412 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
9413 {
9414 char host[1025];
9415 const char *host_header;
9416 size_t hostlen;
9417
9418 host_header = mg_get_header(conn, "Host");
9419 hostlen = sizeof(host);
9420 if (host_header != NULL) {
9421 char *pos;
9422
9423 mg_strlcpy(host, host_header, hostlen);
9424 host[hostlen - 1] = '\0';
9425 pos = strchr(host, ':');
9426 if (pos != NULL) {
9427 *pos = '\0';
9428 }
9429 } else {
9430 /* Cannot get host from the Host: header.
9431 * Fallback to our IP address. */
9432 if (conn) {
9433 sockaddr_to_string(host, hostlen, &conn->client.lsa);
9434 }
9435 }
9436
9437 /* Send host, port, uri and (if it exists) ?query_string */
9438 if (conn) {
9439 mg_printf(conn,
9440 "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
9441 host,
9442 (int)ntohs(
9443 conn->ctx->listening_sockets[ssl_index].lsa.sin.sin_port),
9444 conn->request_info.local_uri,
9445 (conn->request_info.query_string == NULL) ? "" : "?",
9446 (conn->request_info.query_string == NULL)
9447 ? ""
9448 : conn->request_info.query_string);
9449 }
9450 }
9451
9452
9453 static void
9454 mg_set_handler_type(struct mg_context *ctx,
9455 const char *uri,
9456 int handler_type,
9457 int is_delete_request,
9458 mg_request_handler handler,
9459 mg_websocket_connect_handler connect_handler,
9460 mg_websocket_ready_handler ready_handler,
9461 mg_websocket_data_handler data_handler,
9462 mg_websocket_close_handler close_handler,
9463 mg_authorization_handler auth_handler,
9464 void *cbdata)
9465 {
9466 struct mg_handler_info *tmp_rh, **lastref;
9467 size_t urilen = strlen(uri);
9468
9469 if (handler_type == WEBSOCKET_HANDLER) {
9470 /* assert(handler == NULL); */
9471 /* assert(is_delete_request || connect_handler!=NULL ||
9472 * ready_handler!=NULL || data_handler!=NULL ||
9473 * close_handler!=NULL);
9474 */
9475 /* assert(auth_handler == NULL); */
9476 if (handler != NULL) {
9477 return;
9478 }
9479 if (!is_delete_request && connect_handler == NULL
9480 && ready_handler == NULL
9481 && data_handler == NULL
9482 && close_handler == NULL) {
9483 return;
9484 }
9485 if (auth_handler != NULL) {
9486 return;
9487 }
9488 } else if (handler_type == REQUEST_HANDLER) {
9489 /* assert(connect_handler==NULL && ready_handler==NULL &&
9490 * data_handler==NULL && close_handler==NULL); */
9491 /* assert(is_delete_request || (handler!=NULL));
9492 */
9493 /* assert(auth_handler == NULL); */
9494 if (connect_handler != NULL || ready_handler != NULL
9495 || data_handler != NULL
9496 || close_handler != NULL) {
9497 return;
9498 }
9499 if (!is_delete_request && (handler == NULL)) {
9500 return;
9501 }
9502 if (auth_handler != NULL) {
9503 return;
9504 }
9505 } else { /* AUTH_HANDLER */
9506 /* assert(handler == NULL); */
9507 /* assert(connect_handler==NULL && ready_handler==NULL &&
9508 * data_handler==NULL && close_handler==NULL); */
9509 /* assert(auth_handler != NULL); */
9510 if (handler != NULL) {
9511 return;
9512 }
9513 if (connect_handler != NULL || ready_handler != NULL
9514 || data_handler != NULL
9515 || close_handler != NULL) {
9516 return;
9517 }
9518 if (!is_delete_request && (auth_handler == NULL)) {
9519 return;
9520 }
9521 }
9522
9523 if (!ctx) {
9524 return;
9525 }
9526
9527 mg_lock_context(ctx);
9528
9529 /* first try to find an existing handler */
9530 lastref = &(ctx->handlers);
9531 for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
9532 if (tmp_rh->handler_type == handler_type) {
9533 if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9534 if (!is_delete_request) {
9535 /* update existing handler */
9536 if (handler_type == REQUEST_HANDLER) {
9537 tmp_rh->handler = handler;
9538 } else if (handler_type == WEBSOCKET_HANDLER) {
9539 tmp_rh->connect_handler = connect_handler;
9540 tmp_rh->ready_handler = ready_handler;
9541 tmp_rh->data_handler = data_handler;
9542 tmp_rh->close_handler = close_handler;
9543 } else { /* AUTH_HANDLER */
9544 tmp_rh->auth_handler = auth_handler;
9545 }
9546 tmp_rh->cbdata = cbdata;
9547 } else {
9548 /* remove existing handler */
9549 *lastref = tmp_rh->next;
9550 mg_free(tmp_rh->uri);
9551 mg_free(tmp_rh);
9552 }
9553 mg_unlock_context(ctx);
9554 return;
9555 }
9556 }
9557 lastref = &(tmp_rh->next);
9558 }
9559
9560 if (is_delete_request) {
9561 /* no handler to set, this was a remove request to a non-existing
9562 * handler */
9563 mg_unlock_context(ctx);
9564 return;
9565 }
9566
9567 tmp_rh =
9568 (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
9569 if (tmp_rh == NULL) {
9570 mg_unlock_context(ctx);
9571 mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9572 return;
9573 }
9574 tmp_rh->uri = mg_strdup(uri);
9575 if (!tmp_rh->uri) {
9576 mg_unlock_context(ctx);
9577 mg_free(tmp_rh);
9578 mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9579 return;
9580 }
9581 tmp_rh->uri_len = urilen;
9582 if (handler_type == REQUEST_HANDLER) {
9583 tmp_rh->handler = handler;
9584 } else if (handler_type == WEBSOCKET_HANDLER) {
9585 tmp_rh->connect_handler = connect_handler;
9586 tmp_rh->ready_handler = ready_handler;
9587 tmp_rh->data_handler = data_handler;
9588 tmp_rh->close_handler = close_handler;
9589 } else { /* AUTH_HANDLER */
9590 tmp_rh->auth_handler = auth_handler;
9591 }
9592 tmp_rh->cbdata = cbdata;
9593 tmp_rh->handler_type = handler_type;
9594 tmp_rh->next = NULL;
9595
9596 *lastref = tmp_rh;
9597 mg_unlock_context(ctx);
9598 }
9599
9600
9601 void
9602 mg_set_request_handler(struct mg_context *ctx,
9603 const char *uri,
9604 mg_request_handler handler,
9605 void *cbdata)
9606 {
9607 mg_set_handler_type(ctx,
9608 uri,
9609 REQUEST_HANDLER,
9610 handler == NULL,
9611 handler,
9612 NULL,
9613 NULL,
9614 NULL,
9615 NULL,
9616 NULL,
9617 cbdata);
9618 }
9619
9620
9621 void
9622 mg_set_websocket_handler(struct mg_context *ctx,
9623 const char *uri,
9624 mg_websocket_connect_handler connect_handler,
9625 mg_websocket_ready_handler ready_handler,
9626 mg_websocket_data_handler data_handler,
9627 mg_websocket_close_handler close_handler,
9628 void *cbdata)
9629 {
9630 int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
9631 && (data_handler == NULL)
9632 && (close_handler == NULL);
9633 mg_set_handler_type(ctx,
9634 uri,
9635 WEBSOCKET_HANDLER,
9636 is_delete_request,
9637 NULL,
9638 connect_handler,
9639 ready_handler,
9640 data_handler,
9641 close_handler,
9642 NULL,
9643 cbdata);
9644 }
9645
9646
9647 void
9648 mg_set_auth_handler(struct mg_context *ctx,
9649 const char *uri,
9650 mg_request_handler handler,
9651 void *cbdata)
9652 {
9653 mg_set_handler_type(ctx,
9654 uri,
9655 AUTH_HANDLER,
9656 handler == NULL,
9657 NULL,
9658 NULL,
9659 NULL,
9660 NULL,
9661 NULL,
9662 handler,
9663 cbdata);
9664 }
9665
9666
9667 static int
9668 get_request_handler(struct mg_connection *conn,
9669 int handler_type,
9670 mg_request_handler *handler,
9671 mg_websocket_connect_handler *connect_handler,
9672 mg_websocket_ready_handler *ready_handler,
9673 mg_websocket_data_handler *data_handler,
9674 mg_websocket_close_handler *close_handler,
9675 mg_authorization_handler *auth_handler,
9676 void **cbdata)
9677 {
9678 const struct mg_request_info *request_info = mg_get_request_info(conn);
9679 if (request_info) {
9680 const char *uri = request_info->local_uri;
9681 size_t urilen = strlen(uri);
9682 struct mg_handler_info *tmp_rh;
9683
9684 if (!conn || !conn->ctx) {
9685 return 0;
9686 }
9687
9688 mg_lock_context(conn->ctx);
9689
9690 /* first try for an exact match */
9691 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9692 tmp_rh = tmp_rh->next) {
9693 if (tmp_rh->handler_type == handler_type) {
9694 if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9695 if (handler_type == WEBSOCKET_HANDLER) {
9696 *connect_handler = tmp_rh->connect_handler;
9697 *ready_handler = tmp_rh->ready_handler;
9698 *data_handler = tmp_rh->data_handler;
9699 *close_handler = tmp_rh->close_handler;
9700 } else if (handler_type == REQUEST_HANDLER) {
9701 *handler = tmp_rh->handler;
9702 } else { /* AUTH_HANDLER */
9703 *auth_handler = tmp_rh->auth_handler;
9704 }
9705 *cbdata = tmp_rh->cbdata;
9706 mg_unlock_context(conn->ctx);
9707 return 1;
9708 }
9709 }
9710 }
9711
9712 /* next try for a partial match, we will accept uri/something */
9713 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9714 tmp_rh = tmp_rh->next) {
9715 if (tmp_rh->handler_type == handler_type) {
9716 if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
9717 && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
9718 if (handler_type == WEBSOCKET_HANDLER) {
9719 *connect_handler = tmp_rh->connect_handler;
9720 *ready_handler = tmp_rh->ready_handler;
9721 *data_handler = tmp_rh->data_handler;
9722 *close_handler = tmp_rh->close_handler;
9723 } else if (handler_type == REQUEST_HANDLER) {
9724 *handler = tmp_rh->handler;
9725 } else { /* AUTH_HANDLER */
9726 *auth_handler = tmp_rh->auth_handler;
9727 }
9728 *cbdata = tmp_rh->cbdata;
9729 mg_unlock_context(conn->ctx);
9730 return 1;
9731 }
9732 }
9733 }
9734
9735 /* finally try for pattern match */
9736 for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9737 tmp_rh = tmp_rh->next) {
9738 if (tmp_rh->handler_type == handler_type) {
9739 if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
9740 if (handler_type == WEBSOCKET_HANDLER) {
9741 *connect_handler = tmp_rh->connect_handler;
9742 *ready_handler = tmp_rh->ready_handler;
9743 *data_handler = tmp_rh->data_handler;
9744 *close_handler = tmp_rh->close_handler;
9745 } else if (handler_type == REQUEST_HANDLER) {
9746 *handler = tmp_rh->handler;
9747 } else { /* AUTH_HANDLER */
9748 *auth_handler = tmp_rh->auth_handler;
9749 }
9750 *cbdata = tmp_rh->cbdata;
9751 mg_unlock_context(conn->ctx);
9752 return 1;
9753 }
9754 }
9755 }
9756
9757 mg_unlock_context(conn->ctx);
9758 }
9759 return 0; /* none found */
9760 }
9761
9762
9763 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
9764 static int
9765 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
9766 void *cbdata)
9767 {
9768 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9769 if (pcallbacks->websocket_connect) {
9770 return pcallbacks->websocket_connect(conn);
9771 }
9772 /* No handler set - assume "OK" */
9773 return 0;
9774 }
9775
9776
9777 static void
9778 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
9779 {
9780 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9781 if (pcallbacks->websocket_ready) {
9782 pcallbacks->websocket_ready(conn);
9783 }
9784 }
9785
9786
9787 static int
9788 deprecated_websocket_data_wrapper(struct mg_connection *conn,
9789 int bits,
9790 char *data,
9791 size_t len,
9792 void *cbdata)
9793 {
9794 struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9795 if (pcallbacks->websocket_data) {
9796 return pcallbacks->websocket_data(conn, bits, data, len);
9797 }
9798 /* No handler set - assume "OK" */
9799 return 1;
9800 }
9801 #endif
9802
9803
9804 /* This is the heart of the Civetweb's logic.
9805 * This function is called when the request is read, parsed and validated,
9806 * and Civetweb must decide what action to take: serve a file, or
9807 * a directory, or call embedded function, etcetera. */
9808 static void
9809 handle_request(struct mg_connection *conn)
9810 {
9811 if (conn) {
9812 struct mg_request_info *ri = &conn->request_info;
9813 char path[PATH_MAX];
9814 int uri_len, ssl_index;
9815 int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
9816 is_put_or_delete_request = 0, is_callback_resource = 0;
9817 int i;
9818 struct file file = STRUCT_FILE_INITIALIZER;
9819 mg_request_handler callback_handler = NULL;
9820 mg_websocket_connect_handler ws_connect_handler = NULL;
9821 mg_websocket_ready_handler ws_ready_handler = NULL;
9822 mg_websocket_data_handler ws_data_handler = NULL;
9823 mg_websocket_close_handler ws_close_handler = NULL;
9824 void *callback_data = NULL;
9825 mg_authorization_handler auth_handler = NULL;
9826 void *auth_callback_data = NULL;
9827 #if !defined(NO_FILES)
9828 time_t curtime = time(NULL);
9829 char date[64];
9830 #endif
9831
9832 path[0] = 0;
9833
9834 if (!ri) {
9835 return;
9836 }
9837
9838 /* 1. get the request url */
9839 /* 1.1. split into url and query string */
9840 if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
9841 != NULL) {
9842 *((char *)conn->request_info.query_string++) = '\0';
9843 }
9844 uri_len = (int)strlen(ri->local_uri);
9845
9846 /* 1.2. decode url (if config says so) */
9847 if (should_decode_url(conn)) {
9848 mg_url_decode(
9849 ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
9850 }
9851
9852 /* 1.3. clean URIs, so a path like allowed_dir/../forbidden_file is
9853 * not possible (if config says so) */
9854 if (!mg_strcasecmp(conn->ctx->config[CANONICALIZE_URL_PATH], "yes")) {
9855 remove_double_dots_and_double_slashes((char *)ri->local_uri);
9856 }
9857
9858 /* step 1. completed, the url is known now */
9859 DEBUG_TRACE("URL: %s", ri->local_uri);
9860
9861 /* 2. do a https redirect, if required */
9862 if (!conn->client.is_ssl && conn->client.ssl_redir) {
9863 ssl_index = get_first_ssl_listener_index(conn->ctx);
9864 if (ssl_index >= 0) {
9865 redirect_to_https_port(conn, ssl_index);
9866 } else {
9867 /* A http to https forward port has been specified,
9868 * but no https port to forward to. */
9869 send_http_error(conn,
9870 503,
9871 "%s",
9872 "Error: SSL forward not configured properly");
9873 mg_cry(conn, "Can not redirect to SSL, no SSL port available");
9874 }
9875 return;
9876 }
9877
9878 /* 3. if this ip has limited speed, set it for this connection */
9879 conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
9880 get_remote_ip(conn),
9881 ri->local_uri);
9882
9883 /* 4. call a "handle everything" callback, if registered */
9884 if (conn->ctx->callbacks.begin_request != NULL) {
9885 /* Note that since V1.7 the "begin_request" function is called
9886 * before an authorization check. If an authorization check is
9887 * required, use a request_handler instead. */
9888 i = conn->ctx->callbacks.begin_request(conn);
9889 if (i > 0) {
9890 /* callback already processed the request. Store the
9891 return value as a status code for the access log. */
9892 conn->status_code = i;
9893 discard_unread_request_data(conn);
9894 return;
9895 } else if (i == 0) {
9896 /* civetweb should process the request */
9897 } else {
9898 /* unspecified - may change with the next version */
9899 return;
9900 }
9901 }
9902
9903 /* request not yet handled by a handler or redirect, so the request
9904 * is processed here */
9905
9906 /* 5. interpret the url to find out how the request must be handled
9907 */
9908 /* 5.1. first test, if the request targets the regular http(s)://
9909 * protocol namespace or the websocket ws(s):// protocol namespace.
9910 */
9911 is_websocket_request = is_websocket_protocol(conn);
9912
9913 /* 5.2. check if the request will be handled by a callback */
9914 if (get_request_handler(conn,
9915 is_websocket_request ? WEBSOCKET_HANDLER
9916 : REQUEST_HANDLER,
9917 &callback_handler,
9918 &ws_connect_handler,
9919 &ws_ready_handler,
9920 &ws_data_handler,
9921 &ws_close_handler,
9922 NULL,
9923 &callback_data)) {
9924 /* 5.2.1. A callback will handle this request. All requests
9925 * handled
9926 * by a callback have to be considered as requests to a script
9927 * resource. */
9928 is_callback_resource = 1;
9929 is_script_resource = 1;
9930 is_put_or_delete_request = is_put_or_delete_method(conn);
9931 } else {
9932 no_callback_resource:
9933 /* 5.2.2. No callback is responsible for this request. The URI
9934 * addresses a file based resource (static content or Lua/cgi
9935 * scripts in the file system). */
9936 is_callback_resource = 0;
9937 interpret_uri(conn,
9938 path,
9939 sizeof(path),
9940 &file,
9941 &is_found,
9942 &is_script_resource,
9943 &is_websocket_request,
9944 &is_put_or_delete_request);
9945 }
9946
9947 /* 6. authorization check */
9948 /* 6.1. a custom authorization handler is installed */
9949 if (get_request_handler(conn,
9950 AUTH_HANDLER,
9951 NULL,
9952 NULL,
9953 NULL,
9954 NULL,
9955 NULL,
9956 &auth_handler,
9957 &auth_callback_data)) {
9958 if (!auth_handler(conn, auth_callback_data)) {
9959 return;
9960 }
9961 } else if (is_put_or_delete_request && !is_script_resource
9962 && !is_callback_resource) {
9963 /* 6.2. this request is a PUT/DELETE to a real file */
9964 /* 6.2.1. thus, the server must have real files */
9965 #if defined(NO_FILES)
9966 if (1) {
9967 #else
9968 if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
9969 #endif
9970 /* This server does not have any real files, thus the
9971 * PUT/DELETE methods are not valid. */
9972 send_http_error(conn,
9973 405,
9974 "%s method not allowed",
9975 conn->request_info.request_method);
9976 return;
9977 }
9978
9979 #if !defined(NO_FILES)
9980 /* 6.2.2. Check if put authorization for static files is
9981 * available.
9982 */
9983 if (!is_authorized_for_put(conn)) {
9984 send_authorization_request(conn);
9985 return;
9986 }
9987 #endif
9988
9989 } else {
9990 /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
9991 * or it is a PUT or DELETE request to a resource that does not
9992 * correspond to a file. Check authorization. */
9993 if (!check_authorization(conn, path)) {
9994 send_authorization_request(conn);
9995 return;
9996 }
9997 }
9998
9999 /* request is authorized or does not need authorization */
10000
10001 /* 7. check if there are request handlers for this uri */
10002 if (is_callback_resource) {
10003 if (!is_websocket_request) {
10004 i = callback_handler(conn, callback_data);
10005 if (i > 0) {
10006 /* Do nothing, callback has served the request. Store
10007 * the
10008 * return value as status code for the log and discard
10009 * all
10010 * data from the client not used by the callback. */
10011 conn->status_code = i;
10012 discard_unread_request_data(conn);
10013 } else {
10014 /* TODO (high): what if the handler did NOT handle the
10015 * request */
10016 /* The last version did handle this as a file request,
10017 * but
10018 * since a file request is not always a script resource,
10019 * the authorization check might be different */
10020 interpret_uri(conn,
10021 path,
10022 sizeof(path),
10023 &file,
10024 &is_found,
10025 &is_script_resource,
10026 &is_websocket_request,
10027 &is_put_or_delete_request);
10028 callback_handler = NULL;
10029
10030 /* TODO (very low): goto is deprecated but for the
10031 * moment,
10032 * a goto is simpler than some curious loop. */
10033 /* The situation "callback does not handle the request"
10034 * needs to be reconsidered anyway. */
10035 goto no_callback_resource;
10036 }
10037 } else {
10038 #if defined(USE_WEBSOCKET)
10039 handle_websocket_request(conn,
10040 path,
10041 is_callback_resource,
10042 ws_connect_handler,
10043 ws_ready_handler,
10044 ws_data_handler,
10045 ws_close_handler,
10046 callback_data);
10047 #endif
10048 }
10049 return;
10050 }
10051
10052 /* 8. handle websocket requests */
10053 #if defined(USE_WEBSOCKET)
10054 if (is_websocket_request) {
10055 if (is_script_resource) {
10056 /* Websocket Lua script */
10057 handle_websocket_request(conn,
10058 path,
10059 0 /* Lua Script */,
10060 NULL,
10061 NULL,
10062 NULL,
10063 NULL,
10064 &conn->ctx->callbacks);
10065 } else {
10066 #if defined(MG_LEGACY_INTERFACE)
10067 handle_websocket_request(
10068 conn,
10069 path,
10070 !is_script_resource /* could be deprecated global callback */,
10071 deprecated_websocket_connect_wrapper,
10072 deprecated_websocket_ready_wrapper,
10073 deprecated_websocket_data_wrapper,
10074 NULL,
10075 &conn->ctx->callbacks);
10076 #else
10077 send_http_error(conn, 404, "%s", "Not found");
10078 #endif
10079 }
10080 return;
10081 } else
10082 #endif
10083
10084 #if defined(NO_FILES)
10085 /* 9a. In case the server uses only callbacks, this uri is
10086 * unknown.
10087 * Then, all request handling ends here. */
10088 send_http_error(conn, 404, "%s", "Not Found");
10089
10090 #else
10091 /* 9b. This request is either for a static file or resource handled
10092 * by a script file. Thus, a DOCUMENT_ROOT must exist. */
10093 if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10094 send_http_error(conn, 404, "%s", "Not Found");
10095 return;
10096 }
10097
10098 /* 10. File is handled by a script. */
10099 if (is_script_resource) {
10100 handle_file_based_request(conn, path, &file);
10101 return;
10102 }
10103
10104 /* 11. Handle put/delete/mkcol requests */
10105 if (is_put_or_delete_request) {
10106 /* 11.1. PUT method */
10107 if (!strcmp(ri->request_method, "PUT")) {
10108 put_file(conn, path);
10109 return;
10110 }
10111 /* 11.2. DELETE method */
10112 if (!strcmp(ri->request_method, "DELETE")) {
10113 delete_file(conn, path);
10114 return;
10115 }
10116 /* 11.3. MKCOL method */
10117 if (!strcmp(ri->request_method, "MKCOL")) {
10118 mkcol(conn, path);
10119 return;
10120 }
10121 /* 11.4. PATCH method
10122 * This method is not supported for static resources,
10123 * only for scripts (Lua, CGI) and callbacks. */
10124 send_http_error(conn,
10125 405,
10126 "%s method not allowed",
10127 conn->request_info.request_method);
10128 return;
10129 }
10130
10131 /* 11. File does not exist, or it was configured that it should be
10132 * hidden */
10133 if (!is_found || (must_hide_file(conn, path))) {
10134 send_http_error(conn, 404, "%s", "Not found");
10135 return;
10136 }
10137
10138 /* 12. Directory uris should end with a slash */
10139 if (file.is_directory && ri->local_uri[uri_len - 1] != '/') {
10140 gmt_time_string(date, sizeof(date), &curtime);
10141 mg_printf(conn,
10142 "HTTP/1.1 301 Moved Permanently\r\n"
10143 "Location: %s/\r\n"
10144 "Date: %s\r\n"
10145 /* "Cache-Control: private\r\n" (= default) */
10146 "Content-Length: 0\r\n"
10147 "Connection: %s\r\n\r\n",
10148 ri->request_uri,
10149 date,
10150 suggest_connection_header(conn));
10151 return;
10152 }
10153
10154 /* 13. Handle other methods than GET/HEAD */
10155 /* 13.1. Handle PROPFIND */
10156 if (!strcmp(ri->request_method, "PROPFIND")) {
10157 handle_propfind(conn, path, &file);
10158 return;
10159 }
10160 /* 13.2. Handle OPTIONS for files */
10161 if (!strcmp(ri->request_method, "OPTIONS")) {
10162 /* This standard handler is only used for real files.
10163 * Scripts should support the OPTIONS method themselves, to allow a
10164 * maximum flexibility.
10165 * Lua and CGI scripts may fully support CORS this way (including
10166 * preflights). */
10167 send_options(conn);
10168 return;
10169 }
10170 /* 13.3. everything but GET and HEAD (e.g. POST) */
10171 if (0 != strcmp(ri->request_method, "GET")
10172 && 0 != strcmp(ri->request_method, "HEAD")) {
10173 send_http_error(conn,
10174 405,
10175 "%s method not allowed",
10176 conn->request_info.request_method);
10177 return;
10178 }
10179
10180 /* 14. directories */
10181 if (file.is_directory) {
10182 if (substitute_index_file(conn, path, sizeof(path), &file)) {
10183 /* 14.1. use a substitute file */
10184 /* TODO (high): substitute index may be a script resource.
10185 * define what should be possible in this case. */
10186 } else {
10187 /* 14.2. no substitute file */
10188 if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
10189 "yes")) {
10190 handle_directory_request(conn, path);
10191 } else {
10192 send_http_error(conn,
10193 403,
10194 "%s",
10195 "Error: Directory listing denied");
10196 }
10197 return;
10198 }
10199 }
10200
10201 handle_file_based_request(conn, path, &file);
10202 #endif /* !defined(NO_FILES) */
10203
10204 #if 0
10205 /* Perform redirect and auth checks before calling begin_request()
10206 * handler.
10207 * Otherwise, begin_request() would need to perform auth checks and
10208 * redirects. */
10209 #endif
10210 }
10211 return;
10212 }
10213
10214
10215 static void
10216 handle_file_based_request(struct mg_connection *conn,
10217 const char *path,
10218 struct file *file)
10219 {
10220 if (!conn || !conn->ctx) {
10221 return;
10222 }
10223
10224 if (0) {
10225 #ifdef USE_LUA
10226 } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
10227 strlen(
10228 conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
10229 path) > 0) {
10230 /* Lua server page: an SSI like page containing mostly plain html
10231 * code
10232 * plus some tags with server generated contents. */
10233 handle_lsp_request(conn, path, file, NULL);
10234 } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
10235 strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
10236 path) > 0) {
10237 /* Lua in-server module script: a CGI like script used to generate
10238 * the
10239 * entire reply. */
10240 mg_exec_lua_script(conn, path, NULL);
10241 #endif
10242 #if defined(USE_DUKTAPE)
10243 } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
10244 strlen(
10245 conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
10246 path) > 0) {
10247 /* Call duktape to generate the page */
10248 mg_exec_duktape_script(conn, path);
10249 #endif
10250 #if !defined(NO_CGI)
10251 } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
10252 strlen(conn->ctx->config[CGI_EXTENSIONS]),
10253 path) > 0) {
10254 /* CGI scripts may support all HTTP methods */
10255 handle_cgi_request(conn, path);
10256 #endif /* !NO_CGI */
10257 } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10258 strlen(conn->ctx->config[SSI_EXTENSIONS]),
10259 path) > 0) {
10260 handle_ssi_file_request(conn, path, file);
10261 #if !defined(NO_CACHING)
10262 } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
10263 /* Send 304 "Not Modified" - this must not send any body data */
10264 send_http_error(conn, 304, "%s", "");
10265 #endif /* !NO_CACHING */
10266 } else {
10267 handle_static_file_request(conn, path, file, NULL);
10268 }
10269 }
10270
10271
10272 static void
10273 close_all_listening_sockets(struct mg_context *ctx)
10274 {
10275 unsigned int i;
10276 if (!ctx) {
10277 return;
10278 }
10279
10280 for (i = 0; i < ctx->num_listening_sockets; i++) {
10281 closesocket(ctx->listening_sockets[i].sock);
10282 ctx->listening_sockets[i].sock = INVALID_SOCKET;
10283 }
10284 mg_free(ctx->listening_sockets);
10285 ctx->listening_sockets = NULL;
10286 mg_free(ctx->listening_ports);
10287 ctx->listening_ports = NULL;
10288 }
10289
10290
10291 /* Valid listening port specification is: [ip_address:]port[s]
10292 * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s
10293 * Examples for IPv6: [::]:80, [::1]:80,
10294 * [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:443s
10295 * see https://tools.ietf.org/html/rfc3513#section-2.2 */
10296 static int
10297 parse_port_string(const struct vec *vec, struct socket *so)
10298 {
10299 unsigned int a, b, c, d, port;
10300 int ch, len;
10301 #if defined(USE_IPV6)
10302 char buf[100] = {0};
10303 #endif
10304
10305 /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
10306 * Also, all-zeroes in the socket address means binding to all addresses
10307 * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
10308 memset(so, 0, sizeof(*so));
10309 so->lsa.sin.sin_family = AF_INET;
10310
10311 if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
10312 == 5) {
10313 /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
10314 so->lsa.sin.sin_addr.s_addr =
10315 htonl((a << 24) | (b << 16) | (c << 8) | d);
10316 so->lsa.sin.sin_port = htons((uint16_t)port);
10317 #if defined(USE_IPV6)
10318 } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
10319 && mg_inet_pton(
10320 AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
10321 /* IPv6 address, examples: see above */
10322 /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
10323 */
10324 so->lsa.sin6.sin6_port = htons((uint16_t)port);
10325 #endif
10326 } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
10327 /* If only port is specified, bind to IPv4, INADDR_ANY */
10328 so->lsa.sin.sin_port = htons((uint16_t)port);
10329 } else {
10330 /* Parsing failure. Make port invalid. */
10331 port = 0;
10332 len = 0;
10333 }
10334
10335 /* sscanf and the option splitting code ensure the following condition
10336 */
10337 if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
10338 return 0;
10339 }
10340 ch = vec->ptr[len]; /* Next character after the port number */
10341 so->is_ssl = (ch == 's');
10342 so->ssl_redir = (ch == 'r');
10343
10344 /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
10345 return is_valid_port(port)
10346 && (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
10347 }
10348
10349
10350 static int
10351 set_ports_option(struct mg_context *ctx)
10352 {
10353 const char *list;
10354 int on = 1;
10355 #if defined(USE_IPV6)
10356 int off = 0;
10357 #endif
10358 struct vec vec;
10359 struct socket so, *ptr;
10360
10361 in_port_t *portPtr;
10362 union usa usa;
10363 socklen_t len;
10364
10365 int portsTotal = 0;
10366 int portsOk = 0;
10367
10368 if (!ctx) {
10369 return 0;
10370 }
10371
10372 memset(&so, 0, sizeof(so));
10373 memset(&usa, 0, sizeof(usa));
10374 len = sizeof(usa);
10375 list = ctx->config[LISTENING_PORTS];
10376 while ((list = next_option(list, &vec, NULL)) != NULL) {
10377
10378 portsTotal++;
10379
10380 if (!parse_port_string(&vec, &so)) {
10381 mg_cry(fc(ctx),
10382 "%.*s: invalid port spec (entry %i). Expecting list of: %s",
10383 (int)vec.len,
10384 vec.ptr,
10385 portsTotal,
10386 "[IP_ADDRESS:]PORT[s|r]");
10387 continue;
10388 }
10389
10390 if (so.is_ssl && ctx->ssl_ctx == NULL) {
10391
10392 mg_cry(fc(ctx),
10393 "Cannot add SSL socket (entry %i). Is -ssl_certificate "
10394 "option set?",
10395 portsTotal);
10396 continue;
10397 }
10398
10399 if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
10400 == INVALID_SOCKET) {
10401
10402 mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
10403 continue;
10404 }
10405
10406 #ifdef _WIN32
10407 /* Windows SO_REUSEADDR lets many procs binds to a
10408 * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
10409 * if someone already has the socket -- DTL */
10410 /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
10411 * Windows might need a few seconds before
10412 * the same port can be used again in the
10413 * same process, so a short Sleep may be
10414 * required between mg_stop and mg_start.
10415 */
10416 if (setsockopt(so.sock,
10417 SOL_SOCKET,
10418 SO_EXCLUSIVEADDRUSE,
10419 (SOCK_OPT_TYPE)&on,
10420 sizeof(on)) != 0) {
10421
10422 mg_cry(fc(ctx),
10423 "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
10424 portsTotal);
10425 }
10426 #else
10427 if (setsockopt(so.sock,
10428 SOL_SOCKET,
10429 SO_REUSEADDR,
10430 (SOCK_OPT_TYPE)&on,
10431 sizeof(on)) != 0) {
10432
10433 mg_cry(fc(ctx),
10434 "cannot set socket option SO_REUSEADDR (entry %i)",
10435 portsTotal);
10436 }
10437 #endif
10438
10439 #if defined(USE_IPV6)
10440 if (so.lsa.sa.sa_family == AF_INET6
10441 && setsockopt(so.sock,
10442 IPPROTO_IPV6,
10443 IPV6_V6ONLY,
10444 (void *)&off,
10445 sizeof(off)) != 0) {
10446
10447 mg_cry(fc(ctx),
10448 "cannot set socket option IPV6_V6ONLY (entry %i)",
10449 portsTotal);
10450 }
10451 #endif
10452
10453 if (so.lsa.sa.sa_family == AF_INET) {
10454
10455 len = sizeof(so.lsa.sin);
10456 if (bind(so.sock, &so.lsa.sa, len) != 0) {
10457 mg_cry(fc(ctx),
10458 "cannot bind to %.*s: %d (%s)",
10459 (int)vec.len,
10460 vec.ptr,
10461 (int)ERRNO,
10462 strerror(errno));
10463 closesocket(so.sock);
10464 so.sock = INVALID_SOCKET;
10465 continue;
10466 }
10467 }
10468 #if defined(USE_IPV6)
10469 else if (so.lsa.sa.sa_family == AF_INET6) {
10470
10471 len = sizeof(so.lsa.sin6);
10472 if (bind(so.sock, &so.lsa.sa, len) != 0) {
10473 mg_cry(fc(ctx),
10474 "cannot bind to IPv6 %.*s: %d (%s)",
10475 (int)vec.len,
10476 vec.ptr,
10477 (int)ERRNO,
10478 strerror(errno));
10479 closesocket(so.sock);
10480 so.sock = INVALID_SOCKET;
10481 continue;
10482 }
10483 }
10484 #endif
10485 else {
10486 mg_cry(fc(ctx),
10487 "cannot bind: address family not supported (entry %i)",
10488 portsTotal);
10489 continue;
10490 }
10491
10492 if (listen(so.sock, SOMAXCONN) != 0) {
10493
10494 mg_cry(fc(ctx),
10495 "cannot listen to %.*s: %d (%s)",
10496 (int)vec.len,
10497 vec.ptr,
10498 (int)ERRNO,
10499 strerror(errno));
10500 closesocket(so.sock);
10501 so.sock = INVALID_SOCKET;
10502 continue;
10503 }
10504
10505 if (getsockname(so.sock, &(usa.sa), &len) != 0) {
10506
10507 int err = (int)ERRNO;
10508 mg_cry(fc(ctx),
10509 "call to getsockname failed %.*s: %d (%s)",
10510 (int)vec.len,
10511 vec.ptr,
10512 err,
10513 strerror(errno));
10514 closesocket(so.sock);
10515 so.sock = INVALID_SOCKET;
10516 continue;
10517 }
10518
10519 if ((ptr = (struct socket *)
10520 mg_realloc(ctx->listening_sockets,
10521 (ctx->num_listening_sockets + 1)
10522 * sizeof(ctx->listening_sockets[0]))) == NULL) {
10523
10524 mg_cry(fc(ctx), "%s", "Out of memory");
10525 closesocket(so.sock);
10526 so.sock = INVALID_SOCKET;
10527 continue;
10528 }
10529
10530 if ((portPtr =
10531 (in_port_t *)mg_realloc(ctx->listening_ports,
10532 (ctx->num_listening_sockets + 1)
10533 * sizeof(ctx->listening_ports[0])))
10534 == NULL) {
10535
10536 mg_cry(fc(ctx), "%s", "Out of memory");
10537 closesocket(so.sock);
10538 so.sock = INVALID_SOCKET;
10539 mg_free(ptr);
10540 continue;
10541 }
10542
10543 set_close_on_exec(so.sock, fc(ctx));
10544 ctx->listening_sockets = ptr;
10545 ctx->listening_sockets[ctx->num_listening_sockets] = so;
10546 ctx->listening_ports = portPtr;
10547 ctx->listening_ports[ctx->num_listening_sockets] =
10548 ntohs(usa.sin.sin_port);
10549 ctx->num_listening_sockets++;
10550 portsOk++;
10551 }
10552
10553 if (portsOk != portsTotal) {
10554 close_all_listening_sockets(ctx);
10555 portsOk = 0;
10556 }
10557
10558 return portsOk;
10559 }
10560
10561
10562 static const char *
10563 header_val(const struct mg_connection *conn, const char *header)
10564 {
10565 const char *header_value;
10566
10567 if ((header_value = mg_get_header(conn, header)) == NULL) {
10568 return "-";
10569 } else {
10570 return header_value;
10571 }
10572 }
10573
10574
10575 static void
10576 log_access(const struct mg_connection *conn)
10577 {
10578 const struct mg_request_info *ri;
10579 struct file fi;
10580 char date[64], src_addr[IP_ADDR_STR_LEN];
10581 struct tm *tm;
10582
10583 const char *referer;
10584 const char *user_agent;
10585
10586 char buf[4096];
10587
10588 if (!conn || !conn->ctx) {
10589 return;
10590 }
10591
10592 if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
10593 if (mg_fopen(conn, conn->ctx->config[ACCESS_LOG_FILE], "a+", &fi)
10594 == 0) {
10595 fi.fp = NULL;
10596 }
10597 } else {
10598 fi.fp = NULL;
10599 }
10600
10601 if (fi.fp == NULL && conn->ctx->callbacks.log_message == NULL) {
10602 return;
10603 }
10604
10605 tm = localtime(&conn->conn_birth_time);
10606 if (tm != NULL) {
10607 strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
10608 } else {
10609 mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
10610 date[sizeof(date) - 1] = '\0';
10611 }
10612
10613 ri = &conn->request_info;
10614
10615 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
10616 referer = header_val(conn, "Referer");
10617 user_agent = header_val(conn, "User-Agent");
10618
10619 mg_snprintf(conn,
10620 NULL, /* Ignore truncation in access log */
10621 buf,
10622 sizeof(buf),
10623 "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
10624 src_addr,
10625 ri->remote_user == NULL ? "-" : ri->remote_user,
10626 date,
10627 ri->request_method ? ri->request_method : "-",
10628 ri->request_uri ? ri->request_uri : "-",
10629 ri->query_string ? "?" : "",
10630 ri->query_string ? ri->query_string : "",
10631 ri->http_version,
10632 conn->status_code,
10633 conn->num_bytes_sent,
10634 referer,
10635 user_agent);
10636
10637 if (conn->ctx->callbacks.log_access) {
10638 conn->ctx->callbacks.log_access(conn, buf);
10639 }
10640
10641 if (fi.fp) {
10642 flockfile(fi.fp);
10643 fprintf(fi.fp, "%s\n", buf);
10644 fflush(fi.fp);
10645 funlockfile(fi.fp);
10646 mg_fclose(&fi);
10647 }
10648 }
10649
10650
10651 /* Verify given socket address against the ACL.
10652 * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
10653 */
10654 static int
10655 check_acl(struct mg_context *ctx, uint32_t remote_ip)
10656 {
10657 int allowed, flag;
10658 uint32_t net, mask;
10659 struct vec vec;
10660
10661 if (ctx) {
10662 const char *list = ctx->config[ACCESS_CONTROL_LIST];
10663
10664 /* If any ACL is set, deny by default */
10665 allowed = list == NULL ? '+' : '-';
10666
10667 while ((list = next_option(list, &vec, NULL)) != NULL) {
10668 flag = vec.ptr[0];
10669 if ((flag != '+' && flag != '-')
10670 || parse_net(&vec.ptr[1], &net, &mask) == 0) {
10671 mg_cry(fc(ctx),
10672 "%s: subnet must be [+|-]x.x.x.x[/x]",
10673 __func__);
10674 return -1;
10675 }
10676
10677 if (net == (remote_ip & mask)) {
10678 allowed = flag;
10679 }
10680 }
10681
10682 return allowed == '+';
10683 }
10684 return -1;
10685 }
10686
10687
10688 #if !defined(_WIN32)
10689 static int
10690 set_uid_option(struct mg_context *ctx)
10691 {
10692 struct passwd *pw;
10693 if (ctx) {
10694 const char *uid = ctx->config[RUN_AS_USER];
10695 int success = 0;
10696
10697 if (uid == NULL) {
10698 success = 1;
10699 } else {
10700 if ((pw = getpwnam(uid)) == NULL) {
10701 mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
10702 } else if (setgid(pw->pw_gid) == -1) {
10703 mg_cry(fc(ctx),
10704 "%s: setgid(%s): %s",
10705 __func__,
10706 uid,
10707 strerror(errno));
10708 } else if (setgroups(0, NULL)) {
10709 mg_cry(fc(ctx),
10710 "%s: setgroups(): %s",
10711 __func__,
10712 strerror(errno));
10713 } else if (setuid(pw->pw_uid) == -1) {
10714 mg_cry(fc(ctx),
10715 "%s: setuid(%s): %s",
10716 __func__,
10717 uid,
10718 strerror(errno));
10719 } else {
10720 success = 1;
10721 }
10722 }
10723
10724 return success;
10725 }
10726 return 0;
10727 }
10728 #endif /* !_WIN32 */
10729
10730
10731 static void
10732 tls_dtor(void *key)
10733 {
10734 struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
10735 /* key == pthread_getspecific(sTlsKey); */
10736
10737 if (tls) {
10738 if (tls->is_master == 2) {
10739 tls->is_master = -3; /* Mark memory as dead */
10740 mg_free(tls);
10741 }
10742 }
10743 pthread_setspecific(sTlsKey, NULL);
10744 }
10745
10746
10747 #if !defined(NO_SSL)
10748
10749 /* Must be set if sizeof(pthread_t) > sizeof(unsigned long) */
10750 static unsigned long
10751 ssl_id_callback(void)
10752 {
10753 #ifdef _WIN32
10754 return GetCurrentThreadId();
10755 #else
10756
10757 #ifdef __clang__
10758 #pragma clang diagnostic push
10759 #pragma clang diagnostic ignored "-Wunreachable-code"
10760 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
10761 * or not, so one of the two conditions will be unreachable by construction.
10762 * Unfortunately the C standard does not define a way to check this at
10763 * compile time, since the #if preprocessor conditions can not use the sizeof
10764 * operator as an argument. */
10765 #endif
10766
10767 if (sizeof(pthread_t) > sizeof(unsigned long)) {
10768 /* This is the problematic case for CRYPTO_set_id_callback:
10769 * The OS pthread_t can not be cast to unsigned long. */
10770 struct mg_workerTLS *tls =
10771 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
10772 if (tls == NULL) {
10773 /* SSL called from an unknown thread: Create some thread index.
10774 */
10775 tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
10776 tls->is_master = -2; /* -2 means "3rd party thread" */
10777 tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
10778 pthread_setspecific(sTlsKey, tls);
10779 }
10780 return tls->thread_idx;
10781 } else {
10782 /* pthread_t may be any data type, so a simple cast to unsigned long
10783 * can rise a warning/error, depending on the platform.
10784 * Here memcpy is used as an anything-to-anything cast. */
10785 unsigned long ret = 0;
10786 pthread_t t = pthread_self();
10787 memcpy(&ret, &t, sizeof(pthread_t));
10788 return ret;
10789 }
10790
10791 #ifdef __clang__
10792 #pragma clang diagnostic pop
10793 #endif
10794
10795 #endif
10796 }
10797
10798
10799 static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
10800 static const char *ssl_error(void);
10801
10802
10803 static int
10804 refresh_trust(struct mg_connection *conn)
10805 {
10806 static int reload_lock = 0;
10807 static long int data_check = 0;
10808
10809 struct stat cert_buf;
10810 long int t;
10811 char *pem;
10812 int should_verify_peer;
10813
10814 if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
10815 && conn->ctx->callbacks.init_ssl == NULL) {
10816 return 0;
10817 }
10818
10819 t = data_check;
10820 if (stat(pem, &cert_buf) != -1) {
10821 t = (long int)cert_buf.st_mtime;
10822 }
10823
10824 if (data_check != t) {
10825 data_check = t;
10826
10827 should_verify_peer =
10828 (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
10829 && (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
10830 == 0);
10831
10832 if (should_verify_peer) {
10833 char *ca_path = conn->ctx->config[SSL_CA_PATH];
10834 char *ca_file = conn->ctx->config[SSL_CA_FILE];
10835 if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
10836 ca_file,
10837 ca_path) != 1) {
10838 mg_cry(fc(conn->ctx),
10839 "SSL_CTX_load_verify_locations error: %s "
10840 "ssl_verify_peer requires setting "
10841 "either ssl_ca_path or ssl_ca_file. Is any of them "
10842 "present in "
10843 "the .conf file?",
10844 ssl_error());
10845 return 0;
10846 }
10847 }
10848
10849 if (!reload_lock) {
10850 reload_lock = 1;
10851 if (ssl_use_pem_file(conn->ctx, pem) == 0) {
10852 return 0;
10853 }
10854 reload_lock = 0;
10855 }
10856 }
10857 /* lock while cert is reloading */
10858 while (reload_lock) {
10859 sleep(1);
10860 }
10861
10862 return 1;
10863 }
10864
10865
10866 static pthread_mutex_t *ssl_mutexes;
10867
10868
10869 static int
10870 sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
10871 {
10872 int ret, err;
10873 int short_trust;
10874
10875 if (!conn) {
10876 return 0;
10877 }
10878
10879 short_trust =
10880 (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
10881 && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
10882
10883 if (short_trust) {
10884 int trust_ret = refresh_trust(conn);
10885 if (!trust_ret) {
10886 return trust_ret;
10887 }
10888 }
10889
10890 conn->ssl = SSL_new(s);
10891 if (conn->ssl == NULL) {
10892 return 0;
10893 }
10894
10895 ret = SSL_set_fd(conn->ssl, conn->client.sock);
10896 if (ret != 1) {
10897 err = SSL_get_error(conn->ssl, ret);
10898 (void)err; /* TODO: set some error message */
10899 SSL_free(conn->ssl);
10900 conn->ssl = NULL;
10901 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10902 /* see
10903 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10904 ERR_remove_state(0);
10905 return 0;
10906 }
10907
10908 ret = func(conn->ssl);
10909 if (ret != 1) {
10910 err = SSL_get_error(conn->ssl, ret);
10911 (void)err; /* TODO: set some error message */
10912 SSL_free(conn->ssl);
10913 conn->ssl = NULL;
10914 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10915 /* see
10916 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10917 ERR_remove_state(0);
10918 return 0;
10919 }
10920
10921 return 1;
10922 }
10923
10924
10925 /* Return OpenSSL error message (from CRYPTO lib) */
10926 static const char *
10927 ssl_error(void)
10928 {
10929 unsigned long err;
10930 err = ERR_get_error();
10931 return err == 0 ? "" : ERR_error_string(err, NULL);
10932 }
10933
10934
10935 static void
10936 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
10937 {
10938 (void)line;
10939 (void)file;
10940
10941 if (mode & 1) {
10942 /* 1 is CRYPTO_LOCK */
10943 (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
10944 } else {
10945 (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
10946 }
10947 }
10948
10949
10950 #if !defined(NO_SSL_DL)
10951 static void *
10952 load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
10953 {
10954 union {
10955 void *p;
10956 void (*fp)(void);
10957 } u;
10958 void *dll_handle;
10959 struct ssl_func *fp;
10960
10961 if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
10962 mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
10963 return NULL;
10964 }
10965
10966 for (fp = sw; fp->name != NULL; fp++) {
10967 #ifdef _WIN32
10968 /* GetProcAddress() returns pointer to function */
10969 u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
10970 #else
10971 /* dlsym() on UNIX returns void *. ISO C forbids casts of data
10972 * pointers to function pointers. We need to use a union to make a
10973 * cast. */
10974 u.p = dlsym(dll_handle, fp->name);
10975 #endif /* _WIN32 */
10976 if (u.fp == NULL) {
10977 mg_cry(fc(ctx),
10978 "%s: %s: cannot find %s",
10979 __func__,
10980 dll_name,
10981 fp->name);
10982 dlclose(dll_handle);
10983 return NULL;
10984 } else {
10985 fp->ptr = u.fp;
10986 }
10987 }
10988
10989 return dll_handle;
10990 }
10991
10992
10993 static void *ssllib_dll_handle; /* Store the ssl library handle. */
10994 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
10995
10996 #endif /* NO_SSL_DL */
10997
10998
10999 #if defined(SSL_ALREADY_INITIALIZED)
11000 static int cryptolib_users = 1; /* Reference counter for crypto library. */
11001 #else
11002 static int cryptolib_users = 0; /* Reference counter for crypto library. */
11003 #endif
11004
11005
11006 static int
11007 initialize_ssl(struct mg_context *ctx)
11008 {
11009 int i;
11010 size_t size;
11011
11012 #if !defined(NO_SSL_DL)
11013 if (!cryptolib_dll_handle) {
11014 cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
11015 if (!cryptolib_dll_handle) {
11016 return 0;
11017 }
11018 }
11019 #endif /* NO_SSL_DL */
11020
11021 if (mg_atomic_inc(&cryptolib_users) > 1) {
11022 return 1;
11023 }
11024
11025 /* Initialize locking callbacks, needed for thread safety.
11026 * http://www.openssl.org/support/faq.html#PROG1
11027 */
11028 i = CRYPTO_num_locks();
11029 if (i < 0) {
11030 i = 0;
11031 }
11032 size = sizeof(pthread_mutex_t) * ((size_t)(i));
11033 if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
11034 mg_cry(fc(ctx),
11035 "%s: cannot allocate mutexes: %s",
11036 __func__,
11037 ssl_error());
11038 return 0;
11039 }
11040
11041 for (i = 0; i < CRYPTO_num_locks(); i++) {
11042 pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
11043 }
11044
11045 CRYPTO_set_locking_callback(&ssl_locking_callback);
11046 CRYPTO_set_id_callback(&ssl_id_callback);
11047
11048 return 1;
11049 }
11050
11051
11052 static int
11053 ssl_use_pem_file(struct mg_context *ctx, const char *pem)
11054 {
11055 if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
11056 mg_cry(fc(ctx),
11057 "%s: cannot open certificate file %s: %s",
11058 __func__,
11059 pem,
11060 ssl_error());
11061 return 0;
11062 }
11063
11064 /* could use SSL_CTX_set_default_passwd_cb_userdata */
11065 if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
11066 mg_cry(fc(ctx),
11067 "%s: cannot open private key file %s: %s",
11068 __func__,
11069 pem,
11070 ssl_error());
11071 return 0;
11072 }
11073
11074 if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
11075 mg_cry(fc(ctx),
11076 "%s: certificate and private key do not match: %s",
11077 __func__,
11078 pem);
11079 return 0;
11080 }
11081
11082 if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
11083 mg_cry(fc(ctx),
11084 "%s: cannot use certificate chain file %s: %s",
11085 __func__,
11086 pem,
11087 ssl_error());
11088 return 0;
11089 }
11090 return 1;
11091 }
11092
11093
11094 static long
11095 ssl_get_protocol(int version_id)
11096 {
11097 long ret = SSL_OP_ALL;
11098 if (version_id > 0)
11099 ret |= SSL_OP_NO_SSLv2;
11100 if (version_id > 1)
11101 ret |= SSL_OP_NO_SSLv3;
11102 if (version_id > 2)
11103 ret |= SSL_OP_NO_TLSv1;
11104 if (version_id > 3)
11105 ret |= SSL_OP_NO_TLSv1_1;
11106 return ret;
11107 }
11108
11109
11110 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
11111 static int
11112 set_ssl_option(struct mg_context *ctx)
11113 {
11114 const char *pem;
11115 int callback_ret;
11116 int should_verify_peer;
11117 const char *ca_path;
11118 const char *ca_file;
11119 int use_default_verify_paths;
11120 int verify_depth;
11121 time_t now_rt = time(NULL);
11122 struct timespec now_mt;
11123 md5_byte_t ssl_context_id[16];
11124 md5_state_t md5state;
11125 int protocol_ver;
11126
11127 /* If PEM file is not specified and the init_ssl callback
11128 * is not specified, skip SSL initialization. */
11129 if (!ctx) {
11130 return 0;
11131 }
11132 if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
11133 && ctx->callbacks.init_ssl == NULL) {
11134 return 1;
11135 }
11136
11137 if (!initialize_ssl(ctx)) {
11138 return 0;
11139 }
11140
11141 #if !defined(NO_SSL_DL)
11142 if (!ssllib_dll_handle) {
11143 ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
11144 if (!ssllib_dll_handle) {
11145 return 0;
11146 }
11147 }
11148 #endif /* NO_SSL_DL */
11149
11150 /* Initialize SSL library */
11151 SSL_library_init();
11152 SSL_load_error_strings();
11153
11154 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
11155 mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
11156 return 0;
11157 }
11158
11159 SSL_CTX_clear_options(ctx->ssl_ctx,
11160 SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1
11161 | SSL_OP_NO_TLSv1_1);
11162 protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
11163 SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
11164 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
11165 SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
11166
11167 /* If a callback has been specified, call it. */
11168 callback_ret =
11169 (ctx->callbacks.init_ssl == NULL)
11170 ? 0
11171 : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
11172
11173 /* If callback returns 0, civetweb sets up the SSL certificate.
11174 * If it returns 1, civetweb assumes the calback already did this.
11175 * If it returns -1, initializing ssl fails. */
11176 if (callback_ret < 0) {
11177 mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
11178 return 0;
11179 }
11180 if (callback_ret > 0) {
11181 if (pem != NULL) {
11182 (void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
11183 }
11184 return 1;
11185 }
11186
11187 /* Use some UID as session context ID. */
11188 md5_init(&md5state);
11189 md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
11190 clock_gettime(CLOCK_MONOTONIC, &now_mt);
11191 md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
11192 md5_append(&md5state,
11193 (const md5_byte_t *)ctx->config[LISTENING_PORTS],
11194 strlen(ctx->config[LISTENING_PORTS]));
11195 md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
11196 md5_finish(&md5state, ssl_context_id);
11197
11198 SSL_CTX_set_session_id_context(ctx->ssl_ctx,
11199 (const unsigned char *)&ssl_context_id,
11200 sizeof(ssl_context_id));
11201
11202 if (pem != NULL) {
11203 if (!ssl_use_pem_file(ctx, pem)) {
11204 return 0;
11205 }
11206 }
11207
11208 should_verify_peer =
11209 (ctx->config[SSL_DO_VERIFY_PEER] != NULL)
11210 && (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
11211
11212 use_default_verify_paths =
11213 (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
11214 && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
11215
11216 if (should_verify_peer) {
11217 ca_path = ctx->config[SSL_CA_PATH];
11218 ca_file = ctx->config[SSL_CA_FILE];
11219 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
11220 != 1) {
11221 mg_cry(fc(ctx),
11222 "SSL_CTX_load_verify_locations error: %s "
11223 "ssl_verify_peer requires setting "
11224 "either ssl_ca_path or ssl_ca_file. Is any of them "
11225 "present in "
11226 "the .conf file?",
11227 ssl_error());
11228 return 0;
11229 }
11230
11231 SSL_CTX_set_verify(ctx->ssl_ctx,
11232 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
11233 NULL);
11234
11235 if (use_default_verify_paths
11236 && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
11237 mg_cry(fc(ctx),
11238 "SSL_CTX_set_default_verify_paths error: %s",
11239 ssl_error());
11240 return 0;
11241 }
11242
11243 if (ctx->config[SSL_VERIFY_DEPTH]) {
11244 verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
11245 SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
11246 }
11247 }
11248
11249 if (ctx->config[SSL_CIPHER_LIST] != NULL) {
11250 if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
11251 != 1) {
11252 mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
11253 }
11254 }
11255
11256 return 1;
11257 }
11258
11259
11260 static void
11261 uninitialize_ssl(struct mg_context *ctx)
11262 {
11263 int i;
11264 (void)ctx;
11265
11266 if (mg_atomic_dec(&cryptolib_users) == 0) {
11267
11268 /* Shutdown according to
11269 * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
11270 * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
11271 */
11272 CRYPTO_set_locking_callback(NULL);
11273 CRYPTO_set_id_callback(NULL);
11274 ENGINE_cleanup();
11275 CONF_modules_unload(1);
11276 ERR_free_strings();
11277 EVP_cleanup();
11278 CRYPTO_cleanup_all_ex_data();
11279 ERR_remove_state(0);
11280
11281 for (i = 0; i < CRYPTO_num_locks(); i++) {
11282 pthread_mutex_destroy(&ssl_mutexes[i]);
11283 }
11284 mg_free(ssl_mutexes);
11285 ssl_mutexes = NULL;
11286 }
11287 }
11288 #endif /* !NO_SSL */
11289
11290
11291 static int
11292 set_gpass_option(struct mg_context *ctx)
11293 {
11294 if (ctx) {
11295 struct file file = STRUCT_FILE_INITIALIZER;
11296 const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
11297 if (path != NULL && !mg_stat(fc(ctx), path, &file)) {
11298 mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
11299 return 0;
11300 }
11301 return 1;
11302 }
11303 return 0;
11304 }
11305
11306
11307 static int
11308 set_acl_option(struct mg_context *ctx)
11309 {
11310 return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
11311 }
11312
11313
11314 static void
11315 reset_per_request_attributes(struct mg_connection *conn)
11316 {
11317 if (!conn) {
11318 return;
11319 }
11320 conn->path_info = NULL;
11321 conn->num_bytes_sent = conn->consumed_content = 0;
11322 conn->status_code = -1;
11323 conn->is_chunked = 0;
11324 conn->must_close = conn->request_len = conn->throttle = 0;
11325 conn->request_info.content_length = -1;
11326 conn->request_info.remote_user = NULL;
11327 conn->request_info.request_method = NULL;
11328 conn->request_info.request_uri = NULL;
11329 conn->request_info.local_uri = NULL;
11330 conn->request_info.uri = NULL; /* TODO: cleanup uri,
11331 * local_uri and request_uri */
11332 conn->request_info.http_version = NULL;
11333 conn->request_info.num_headers = 0;
11334 conn->data_len = 0;
11335 conn->chunk_remainder = 0;
11336 conn->internal_error = 0;
11337 }
11338
11339
11340 static int
11341 set_sock_timeout(SOCKET sock, int milliseconds)
11342 {
11343 int r0 = 0, r1, r2;
11344
11345 #ifdef _WIN32
11346 /* Windows specific */
11347
11348 DWORD tv = (DWORD)milliseconds;
11349
11350 #else
11351 /* Linux, ... (not Windows) */
11352
11353 struct timeval tv;
11354
11355 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
11356 * max. time waiting for the acknowledged of TCP data before the connection
11357 * will be forcefully closed and ETIMEDOUT is returned to the application.
11358 * If this option is not set, the default timeout of 20-30 minutes is used.
11359 */
11360 /* #define TCP_USER_TIMEOUT (18) */
11361
11362 #if defined(TCP_USER_TIMEOUT)
11363 unsigned int uto = (unsigned int)milliseconds;
11364 r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
11365 #endif
11366
11367 memset(&tv, 0, sizeof(tv));
11368 tv.tv_sec = milliseconds / 1000;
11369 tv.tv_usec = (milliseconds * 1000) % 1000000;
11370
11371 #endif /* _WIN32 */
11372
11373 r1 = setsockopt(
11374 sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11375 r2 = setsockopt(
11376 sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11377
11378 return r0 || r1 || r2;
11379 }
11380
11381
11382 static int
11383 set_tcp_nodelay(SOCKET sock, int nodelay_on)
11384 {
11385 if (setsockopt(sock,
11386 IPPROTO_TCP,
11387 TCP_NODELAY,
11388 (SOCK_OPT_TYPE)&nodelay_on,
11389 sizeof(nodelay_on)) != 0) {
11390 /* Error */
11391 return 1;
11392 }
11393 /* OK */
11394 return 0;
11395 }
11396
11397
11398 static void
11399 close_socket_gracefully(struct mg_connection *conn)
11400 {
11401 #if defined(_WIN32)
11402 char buf[MG_BUF_LEN];
11403 int n;
11404 #endif
11405 struct linger linger;
11406
11407 if (!conn) {
11408 return;
11409 }
11410
11411 /* Set linger option to avoid socket hanging out after close. This
11412 * prevent
11413 * ephemeral port exhaust problem under high QPS. */
11414 linger.l_onoff = 1;
11415 linger.l_linger = 1;
11416
11417 if (setsockopt(conn->client.sock,
11418 SOL_SOCKET,
11419 SO_LINGER,
11420 (char *)&linger,
11421 sizeof(linger)) != 0) {
11422 mg_cry(conn,
11423 "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
11424 __func__,
11425 strerror(ERRNO));
11426 }
11427
11428 /* Send FIN to the client */
11429 shutdown(conn->client.sock, SHUT_WR);
11430 set_non_blocking_mode(conn->client.sock);
11431
11432 #if defined(_WIN32)
11433 /* Read and discard pending incoming data. If we do not do that and
11434 * close
11435 * the socket, the data in the send buffer may be discarded. This
11436 * behaviour is seen on Windows, when client keeps sending data
11437 * when server decides to close the connection; then when client
11438 * does recv() it gets no data back. */
11439 do {
11440 n = pull(
11441 NULL, conn, buf, sizeof(buf), 1E-10 /* TODO: allow 0 as timeout */);
11442 } while (n > 0);
11443 #endif
11444
11445 /* Now we know that our FIN is ACK-ed, safe to close */
11446 closesocket(conn->client.sock);
11447 conn->client.sock = INVALID_SOCKET;
11448 }
11449
11450
11451 static void
11452 close_connection(struct mg_connection *conn)
11453 {
11454 if (!conn || !conn->ctx) {
11455 return;
11456 }
11457
11458 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
11459 if (conn->lua_websocket_state) {
11460 lua_websocket_close(conn, conn->lua_websocket_state);
11461 conn->lua_websocket_state = NULL;
11462 }
11463 #endif
11464
11465 /* call the connection_close callback if assigned */
11466 if ((conn->ctx->callbacks.connection_close != NULL)
11467 && (conn->ctx->context_type == 1)) {
11468 conn->ctx->callbacks.connection_close(conn);
11469 }
11470
11471 mg_lock_connection(conn);
11472
11473 conn->must_close = 1;
11474
11475 #ifndef NO_SSL
11476 if (conn->ssl != NULL) {
11477 /* Run SSL_shutdown twice to ensure completly close SSL connection
11478 */
11479 SSL_shutdown(conn->ssl);
11480 SSL_free(conn->ssl);
11481 /* maybe not? CRYPTO_cleanup_all_ex_data(); */
11482 /* see
11483 * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11484 ERR_remove_state(0);
11485 conn->ssl = NULL;
11486 }
11487 #endif
11488 if (conn->client.sock != INVALID_SOCKET) {
11489 close_socket_gracefully(conn);
11490 conn->client.sock = INVALID_SOCKET;
11491 }
11492
11493 mg_unlock_connection(conn);
11494 }
11495
11496 void
11497 mg_close_connection(struct mg_connection *conn)
11498 {
11499 struct mg_context *client_ctx = NULL;
11500 unsigned int i;
11501
11502 if (conn == NULL) {
11503 return;
11504 }
11505
11506 if (conn->ctx->context_type == 2) {
11507 client_ctx = conn->ctx;
11508 /* client context: loops must end */
11509 conn->ctx->stop_flag = 1;
11510 }
11511
11512 #ifndef NO_SSL
11513 if (conn->client_ssl_ctx != NULL) {
11514 SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
11515 }
11516 #endif
11517 close_connection(conn);
11518 if (client_ctx != NULL) {
11519 /* join worker thread and free context */
11520 for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
11521 if (client_ctx->workerthreadids[i] != 0) {
11522 mg_join_thread(client_ctx->workerthreadids[i]);
11523 }
11524 }
11525 mg_free(client_ctx->workerthreadids);
11526 mg_free(client_ctx);
11527 (void)pthread_mutex_destroy(&conn->mutex);
11528 mg_free(conn);
11529 }
11530 }
11531
11532
11533 static struct mg_connection *
11534 mg_connect_client_impl(const struct mg_client_options *client_options,
11535 int use_ssl,
11536 char *ebuf,
11537 size_t ebuf_len)
11538 {
11539 static struct mg_context fake_ctx;
11540 struct mg_connection *conn = NULL;
11541 SOCKET sock;
11542 union usa sa;
11543
11544 if (!connect_socket(&fake_ctx,
11545 client_options->host,
11546 client_options->port,
11547 use_ssl,
11548 ebuf,
11549 ebuf_len,
11550 &sock,
11551 &sa)) {
11552 ;
11553 } else if ((conn = (struct mg_connection *)
11554 mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
11555 mg_snprintf(NULL,
11556 NULL, /* No truncation check for ebuf */
11557 ebuf,
11558 ebuf_len,
11559 "calloc(): %s",
11560 strerror(ERRNO));
11561 closesocket(sock);
11562 #ifndef NO_SSL
11563 } else if (use_ssl
11564 && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
11565 == NULL) {
11566 mg_snprintf(NULL,
11567 NULL, /* No truncation check for ebuf */
11568 ebuf,
11569 ebuf_len,
11570 "SSL_CTX_new error");
11571 closesocket(sock);
11572 mg_free(conn);
11573 conn = NULL;
11574 #endif /* NO_SSL */
11575
11576 } else {
11577
11578 #ifdef USE_IPV6
11579 socklen_t len = (sa.sa.sa_family == AF_INET)
11580 ? sizeof(conn->client.rsa.sin)
11581 : sizeof(conn->client.rsa.sin6);
11582 struct sockaddr *psa =
11583 (sa.sa.sa_family == AF_INET)
11584 ? (struct sockaddr *)&(conn->client.rsa.sin)
11585 : (struct sockaddr *)&(conn->client.rsa.sin6);
11586 #else
11587 socklen_t len = sizeof(conn->client.rsa.sin);
11588 struct sockaddr *psa = (struct sockaddr *)&(conn->client.rsa.sin);
11589 #endif
11590
11591 conn->buf_size = MAX_REQUEST_SIZE;
11592 conn->buf = (char *)(conn + 1);
11593 conn->ctx = &fake_ctx;
11594 conn->client.sock = sock;
11595 conn->client.lsa = sa;
11596
11597 if (getsockname(sock, psa, &len) != 0) {
11598 mg_cry(conn,
11599 "%s: getsockname() failed: %s",
11600 __func__,
11601 strerror(ERRNO));
11602 }
11603
11604 conn->client.is_ssl = use_ssl ? 1 : 0;
11605 (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
11606
11607 #ifndef NO_SSL
11608 if (use_ssl) {
11609 fake_ctx.ssl_ctx = conn->client_ssl_ctx;
11610
11611 /* TODO: Check ssl_verify_peer and ssl_ca_path here.
11612 * SSL_CTX_set_verify call is needed to switch off server
11613 * certificate checking, which is off by default in OpenSSL and
11614 * on in yaSSL. */
11615 /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
11616 * SSL_VERIFY_PEER, verify_ssl_server); */
11617
11618 if (client_options->client_cert) {
11619 if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
11620 mg_snprintf(NULL,
11621 NULL, /* No truncation check for ebuf */
11622 ebuf,
11623 ebuf_len,
11624 "Can not use SSL client certificate");
11625 SSL_CTX_free(conn->client_ssl_ctx);
11626 closesocket(sock);
11627 mg_free(conn);
11628 conn = NULL;
11629 }
11630 }
11631
11632 if (client_options->server_cert) {
11633 SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
11634 client_options->server_cert,
11635 NULL);
11636 SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
11637 } else {
11638 SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
11639 }
11640
11641 if (!sslize(conn, conn->client_ssl_ctx, SSL_connect)) {
11642 mg_snprintf(NULL,
11643 NULL, /* No truncation check for ebuf */
11644 ebuf,
11645 ebuf_len,
11646 "SSL connection error");
11647 SSL_CTX_free(conn->client_ssl_ctx);
11648 closesocket(sock);
11649 mg_free(conn);
11650 conn = NULL;
11651 }
11652 }
11653 #endif
11654 }
11655
11656 return conn;
11657 }
11658
11659
11660 CIVETWEB_API struct mg_connection *
11661 mg_connect_client_secure(const struct mg_client_options *client_options,
11662 char *error_buffer,
11663 size_t error_buffer_size)
11664 {
11665 return mg_connect_client_impl(client_options,
11666 1,
11667 error_buffer,
11668 error_buffer_size);
11669 }
11670
11671
11672 struct mg_connection *
11673 mg_connect_client(const char *host,
11674 int port,
11675 int use_ssl,
11676 char *error_buffer,
11677 size_t error_buffer_size)
11678 {
11679 struct mg_client_options opts;
11680 memset(&opts, 0, sizeof(opts));
11681 opts.host = host;
11682 opts.port = port;
11683 return mg_connect_client_impl(&opts,
11684 use_ssl,
11685 error_buffer,
11686 error_buffer_size);
11687 }
11688
11689
11690 static const struct {
11691 const char *proto;
11692 size_t proto_len;
11693 unsigned default_port;
11694 } abs_uri_protocols[] = {{"http://", 7, 80},
11695 {"https://", 8, 443},
11696 {"ws://", 5, 80},
11697 {"wss://", 6, 443},
11698 {NULL, 0, 0}};
11699
11700
11701 /* Check if the uri is valid.
11702 * return 0 for invalid uri,
11703 * return 1 for *,
11704 * return 2 for relative uri,
11705 * return 3 for absolute uri without port,
11706 * return 4 for absolute uri with port */
11707 static int
11708 get_uri_type(const char *uri)
11709 {
11710 int i;
11711 char *hostend, *portbegin, *portend;
11712 unsigned long port;
11713
11714 /* According to the HTTP standard
11715 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
11716 * URI can be an asterisk (*) or should start with slash (relative uri),
11717 * or it should start with the protocol (absolute uri). */
11718 if (uri[0] == '*' && uri[1] == '\0') {
11719 /* asterisk */
11720 return 1;
11721 }
11722 if (uri[0] == '/') {
11723 /* relative uri */
11724 return 2;
11725 }
11726
11727 /* It could be an absolute uri: */
11728 /* This function only checks if the uri is valid, not if it is
11729 * addressing the current server. So civetweb can also be used
11730 * as a proxy server. */
11731 for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11732 if (mg_strncasecmp(uri,
11733 abs_uri_protocols[i].proto,
11734 abs_uri_protocols[i].proto_len) == 0) {
11735
11736 hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
11737 if (!hostend) {
11738 return 0;
11739 }
11740 portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
11741 if (!portbegin) {
11742 return 3;
11743 }
11744
11745 port = strtoul(portbegin + 1, &portend, 10);
11746 if ((portend != hostend) || !port || !is_valid_port(port)) {
11747 return 0;
11748 }
11749
11750 return 4;
11751 }
11752 }
11753
11754 return 0;
11755 }
11756
11757
11758 /* Return NULL or the relative uri at the current server */
11759 static const char *
11760 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
11761 {
11762 const char *server_domain;
11763 size_t server_domain_len;
11764 size_t request_domain_len = 0;
11765 unsigned long port = 0;
11766 int i;
11767 const char *hostbegin = NULL;
11768 const char *hostend = NULL;
11769 const char *portbegin;
11770 char *portend;
11771
11772 /* DNS is case insensitive, so use case insensitive string compare here
11773 */
11774 server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
11775 if (!server_domain) {
11776 return 0;
11777 }
11778 server_domain_len = strlen(server_domain);
11779 if (!server_domain_len) {
11780 return 0;
11781 }
11782
11783 for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11784 if (mg_strncasecmp(uri,
11785 abs_uri_protocols[i].proto,
11786 abs_uri_protocols[i].proto_len) == 0) {
11787
11788 hostbegin = uri + abs_uri_protocols[i].proto_len;
11789 hostend = strchr(hostbegin, '/');
11790 if (!hostend) {
11791 return 0;
11792 }
11793 portbegin = strchr(hostbegin, ':');
11794 if ((!portbegin) || (portbegin > hostend)) {
11795 port = abs_uri_protocols[i].default_port;
11796 request_domain_len = (size_t)(hostend - hostbegin);
11797 } else {
11798 port = strtoul(portbegin + 1, &portend, 10);
11799 if ((portend != hostend) || !port || !is_valid_port(port)) {
11800 return 0;
11801 }
11802 request_domain_len = (size_t)(portbegin - hostbegin);
11803 }
11804 /* protocol found, port set */
11805 break;
11806 }
11807 }
11808
11809 if (!port) {
11810 /* port remains 0 if the protocol is not found */
11811 return 0;
11812 }
11813
11814 #if defined(USE_IPV6)
11815 if (conn->client.lsa.sa.sa_family == AF_INET6) {
11816 if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
11817 /* Request is directed to a different port */
11818 return 0;
11819 }
11820 } else
11821 #endif
11822 {
11823 if (ntohs(conn->client.lsa.sin.sin_port) != port) {
11824 /* Request is directed to a different port */
11825 return 0;
11826 }
11827 }
11828
11829 if ((request_domain_len != server_domain_len)
11830 || (0 != memcmp(server_domain, hostbegin, server_domain_len))) {
11831 /* Request is directed to another server */
11832 return 0;
11833 }
11834
11835 return hostend;
11836 }
11837
11838
11839 static int
11840 getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
11841 {
11842 const char *cl;
11843 int check_method = should_validate_http_method(conn);
11844
11845 if (ebuf_len > 0) {
11846 ebuf[0] = '\0';
11847 }
11848 *err = 0;
11849
11850 reset_per_request_attributes(conn);
11851
11852 if (!conn) {
11853 mg_snprintf(conn,
11854 NULL, /* No truncation check for ebuf */
11855 ebuf,
11856 ebuf_len,
11857 "%s",
11858 "Internal error");
11859 *err = 500;
11860 return 0;
11861 }
11862 /* Set the time the request was received. This value should be used for
11863 * timeouts. */
11864 clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
11865
11866 conn->request_len =
11867 read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
11868 /* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
11869 */
11870 if (conn->request_len >= 0 && conn->data_len < conn->request_len) {
11871 mg_snprintf(conn,
11872 NULL, /* No truncation check for ebuf */
11873 ebuf,
11874 ebuf_len,
11875 "%s",
11876 "Invalid request size");
11877 *err = 500;
11878 return 0;
11879 }
11880
11881 if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
11882 mg_snprintf(conn,
11883 NULL, /* No truncation check for ebuf */
11884 ebuf,
11885 ebuf_len,
11886 "%s",
11887 "Request Too Large");
11888 *err = 413;
11889 return 0;
11890 } else if (conn->request_len <= 0) {
11891 if (conn->data_len > 0) {
11892 mg_snprintf(conn,
11893 NULL, /* No truncation check for ebuf */
11894 ebuf,
11895 ebuf_len,
11896 "%s",
11897 "Client sent malformed request");
11898 *err = 400;
11899 } else {
11900 /* Server did not send anything -> just close the connection */
11901 conn->must_close = 1;
11902 mg_snprintf(conn,
11903 NULL, /* No truncation check for ebuf */
11904 ebuf,
11905 ebuf_len,
11906 "%s",
11907 "Client did not send a request");
11908 *err = 0;
11909 }
11910 return 0;
11911 } else if (parse_http_message(
11912 check_method, conn->buf, conn->buf_size, &conn->request_info)
11913 <= 0) {
11914 mg_snprintf(conn,
11915 NULL, /* No truncation check for ebuf */
11916 ebuf,
11917 ebuf_len,
11918 "%s",
11919 "Bad Request");
11920 *err = 400;
11921 return 0;
11922 } else {
11923 /* Message is a valid request or response */
11924 if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
11925 /* Request/response has content length set */
11926 char *endptr = NULL;
11927 conn->content_len = strtoll(cl, &endptr, 10);
11928 if (endptr == cl) {
11929 mg_snprintf(conn,
11930 NULL, /* No truncation check for ebuf */
11931 ebuf,
11932 ebuf_len,
11933 "%s",
11934 "Bad Request");
11935 *err = 400;
11936 return 0;
11937 }
11938 /* Publish the content length back to the request info. */
11939 conn->request_info.content_length = conn->content_len;
11940 } else if ((cl = get_header(&conn->request_info, "Transfer-Encoding"))
11941 != NULL
11942 && !mg_strcasecmp(cl, "chunked")) {
11943 conn->is_chunked = 1;
11944 } else if (!mg_strcasecmp(conn->request_info.request_method, "POST")
11945 || !mg_strcasecmp(conn->request_info.request_method,
11946 "PUT")) {
11947 /* POST or PUT request without content length set */
11948 conn->content_len = -1;
11949 } else if (!mg_strncasecmp(conn->request_info.request_method,
11950 "HTTP/",
11951 5)) {
11952 /* Response without content length set */
11953 conn->content_len = -1;
11954 } else {
11955 /* Other request */
11956 conn->content_len = 0;
11957 }
11958 }
11959 return 1;
11960 }
11961
11962
11963 int
11964 mg_get_response(struct mg_connection *conn,
11965 char *ebuf,
11966 size_t ebuf_len,
11967 int timeout)
11968 {
11969 if (conn) {
11970 /* Implementation of API function for HTTP clients */
11971 int err, ret;
11972 struct mg_context *octx = conn->ctx;
11973 struct mg_context rctx = *(conn->ctx);
11974 char txt[32]; /* will not overflow */
11975
11976 if (timeout >= 0) {
11977 mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
11978 rctx.config[REQUEST_TIMEOUT] = txt;
11979 set_sock_timeout(conn->client.sock, timeout);
11980 } else {
11981 rctx.config[REQUEST_TIMEOUT] = NULL;
11982 }
11983
11984 conn->ctx = &rctx;
11985 ret = getreq(conn, ebuf, ebuf_len, &err);
11986 conn->ctx = octx;
11987
11988 /* TODO: 1) uri is deprecated;
11989 * 2) here, ri.uri is the http response code */
11990 conn->request_info.uri = conn->request_info.request_uri;
11991
11992 /* TODO (mid): Define proper return values - maybe return length?
11993 * For the first test use <0 for error and >0 for OK */
11994 return (ret == 0) ? -1 : +1;
11995 }
11996 return -1;
11997 }
11998
11999
12000 struct mg_connection *
12001 mg_download(const char *host,
12002 int port,
12003 int use_ssl,
12004 char *ebuf,
12005 size_t ebuf_len,
12006 const char *fmt,
12007 ...)
12008 {
12009 struct mg_connection *conn;
12010 va_list ap;
12011 int i;
12012 int reqerr;
12013
12014 va_start(ap, fmt);
12015 ebuf[0] = '\0';
12016
12017 /* open a connection */
12018 conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
12019
12020 if (conn != NULL) {
12021 i = mg_vprintf(conn, fmt, ap);
12022 if (i <= 0) {
12023 mg_snprintf(conn,
12024 NULL, /* No truncation check for ebuf */
12025 ebuf,
12026 ebuf_len,
12027 "%s",
12028 "Error sending request");
12029 } else {
12030 getreq(conn, ebuf, ebuf_len, &reqerr);
12031
12032 /* TODO: 1) uri is deprecated;
12033 * 2) here, ri.uri is the http response code */
12034 conn->request_info.uri = conn->request_info.request_uri;
12035 }
12036 }
12037
12038 /* if an error occured, close the connection */
12039 if (ebuf[0] != '\0' && conn != NULL) {
12040 mg_close_connection(conn);
12041 conn = NULL;
12042 }
12043
12044 va_end(ap);
12045 return conn;
12046 }
12047
12048
12049 struct websocket_client_thread_data {
12050 struct mg_connection *conn;
12051 mg_websocket_data_handler data_handler;
12052 mg_websocket_close_handler close_handler;
12053 void *callback_data;
12054 };
12055
12056
12057 #if defined(USE_WEBSOCKET)
12058 #ifdef _WIN32
12059 static unsigned __stdcall websocket_client_thread(void *data)
12060 #else
12061 static void *
12062 websocket_client_thread(void *data)
12063 #endif
12064 {
12065 struct websocket_client_thread_data *cdata =
12066 (struct websocket_client_thread_data *)data;
12067
12068 mg_set_thread_name("ws-client");
12069
12070 if (cdata->conn->ctx) {
12071 if (cdata->conn->ctx->callbacks.init_thread) {
12072 /* 3 indicates a websocket client thread */
12073 /* TODO: check if conn->ctx can be set */
12074 cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
12075 }
12076 }
12077
12078 read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
12079
12080 DEBUG_TRACE("%s", "Websocket client thread exited\n");
12081
12082 if (cdata->close_handler != NULL) {
12083 cdata->close_handler(cdata->conn, cdata->callback_data);
12084 }
12085
12086 mg_free((void *)cdata);
12087
12088 #ifdef _WIN32
12089 return 0;
12090 #else
12091 return NULL;
12092 #endif
12093 }
12094 #endif
12095
12096
12097 struct mg_connection *
12098 mg_connect_websocket_client(const char *host,
12099 int port,
12100 int use_ssl,
12101 char *error_buffer,
12102 size_t error_buffer_size,
12103 const char *path,
12104 const char *origin,
12105 mg_websocket_data_handler data_func,
12106 mg_websocket_close_handler close_func,
12107 void *user_data)
12108 {
12109 struct mg_connection *conn = NULL;
12110
12111 #if defined(USE_WEBSOCKET)
12112 struct mg_context *newctx = NULL;
12113 struct websocket_client_thread_data *thread_data;
12114 static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
12115 static const char *handshake_req;
12116
12117 if (origin != NULL) {
12118 handshake_req = "GET %s HTTP/1.1\r\n"
12119 "Host: %s\r\n"
12120 "Upgrade: websocket\r\n"
12121 "Connection: Upgrade\r\n"
12122 "Sec-WebSocket-Key: %s\r\n"
12123 "Sec-WebSocket-Version: 13\r\n"
12124 "Origin: %s\r\n"
12125 "\r\n";
12126 } else {
12127 handshake_req = "GET %s HTTP/1.1\r\n"
12128 "Host: %s\r\n"
12129 "Upgrade: websocket\r\n"
12130 "Connection: Upgrade\r\n"
12131 "Sec-WebSocket-Key: %s\r\n"
12132 "Sec-WebSocket-Version: 13\r\n"
12133 "\r\n";
12134 }
12135
12136 /* Establish the client connection and request upgrade */
12137 conn = mg_download(host,
12138 port,
12139 use_ssl,
12140 error_buffer,
12141 error_buffer_size,
12142 handshake_req,
12143 path,
12144 host,
12145 magic,
12146 origin);
12147
12148 /* Connection object will be null if something goes wrong */
12149 if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) {
12150 if (!*error_buffer) {
12151 /* if there is a connection, but it did not return 101,
12152 * error_buffer is not yet set */
12153 mg_snprintf(conn,
12154 NULL, /* No truncation check for ebuf */
12155 error_buffer,
12156 error_buffer_size,
12157 "Unexpected server reply");
12158 }
12159 DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
12160 if (conn != NULL) {
12161 mg_free(conn);
12162 conn = NULL;
12163 }
12164 return conn;
12165 }
12166
12167 /* For client connections, mg_context is fake. Since we need to set a
12168 * callback function, we need to create a copy and modify it. */
12169 newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
12170 memcpy(newctx, conn->ctx, sizeof(struct mg_context));
12171 newctx->user_data = user_data;
12172 newctx->context_type = 2; /* client context type */
12173 newctx->cfg_worker_threads = 1; /* one worker thread will be created */
12174 newctx->workerthreadids =
12175 (pthread_t *)mg_calloc(newctx->cfg_worker_threads, sizeof(pthread_t));
12176 conn->ctx = newctx;
12177 thread_data = (struct websocket_client_thread_data *)
12178 mg_calloc(sizeof(struct websocket_client_thread_data), 1);
12179 thread_data->conn = conn;
12180 thread_data->data_handler = data_func;
12181 thread_data->close_handler = close_func;
12182 thread_data->callback_data = NULL;
12183
12184 /* Start a thread to read the websocket client connection
12185 * This thread will automatically stop when mg_disconnect is
12186 * called on the client connection */
12187 if (mg_start_thread_with_id(websocket_client_thread,
12188 (void *)thread_data,
12189 newctx->workerthreadids) != 0) {
12190 mg_free((void *)thread_data);
12191 mg_free((void *)newctx->workerthreadids);
12192 mg_free((void *)newctx);
12193 mg_free((void *)conn);
12194 conn = NULL;
12195 DEBUG_TRACE("%s",
12196 "Websocket client connect thread could not be started\r\n");
12197 }
12198 #else
12199 /* Appease "unused parameter" warnings */
12200 (void)host;
12201 (void)port;
12202 (void)use_ssl;
12203 (void)error_buffer;
12204 (void)error_buffer_size;
12205 (void)path;
12206 (void)origin;
12207 (void)user_data;
12208 (void)data_func;
12209 (void)close_func;
12210 #endif
12211
12212 return conn;
12213 }
12214
12215
12216 static void
12217 process_new_connection(struct mg_connection *conn)
12218 {
12219 if (conn && conn->ctx) {
12220 struct mg_request_info *ri = &conn->request_info;
12221 int keep_alive_enabled, keep_alive, discard_len;
12222 char ebuf[100];
12223 const char *hostend;
12224 int reqerr, uri_type;
12225
12226 keep_alive_enabled =
12227 !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
12228
12229 /* Important: on new connection, reset the receiving buffer. Credit
12230 * goes to crule42. */
12231 conn->data_len = 0;
12232 do {
12233 if (!getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
12234 /* The request sent by the client could not be understood by
12235 * the server, or it was incomplete or a timeout. Send an
12236 * error message and close the connection. */
12237 if (reqerr > 0) {
12238 /*assert(ebuf[0] != '\0');*/
12239 send_http_error(conn, reqerr, "%s", ebuf);
12240 }
12241 } else if (strcmp(ri->http_version, "1.0")
12242 && strcmp(ri->http_version, "1.1")) {
12243 mg_snprintf(conn,
12244 NULL, /* No truncation check for ebuf */
12245 ebuf,
12246 sizeof(ebuf),
12247 "Bad HTTP version: [%s]",
12248 ri->http_version);
12249 send_http_error(conn, 505, "%s", ebuf);
12250 }
12251
12252 if (ebuf[0] == '\0') {
12253 uri_type = get_uri_type(conn->request_info.request_uri);
12254 switch (uri_type) {
12255 case 1:
12256 /* Asterisk */
12257 conn->request_info.local_uri = NULL;
12258 break;
12259 case 2:
12260 /* relative uri */
12261 conn->request_info.local_uri =
12262 conn->request_info.request_uri;
12263 break;
12264 case 3:
12265 case 4:
12266 /* absolute uri (with/without port) */
12267 hostend = get_rel_url_at_current_server(
12268 conn->request_info.request_uri, conn);
12269 if (hostend) {
12270 conn->request_info.local_uri = hostend;
12271 } else {
12272 conn->request_info.local_uri = NULL;
12273 }
12274 break;
12275 default:
12276 mg_snprintf(conn,
12277 NULL, /* No truncation check for ebuf */
12278 ebuf,
12279 sizeof(ebuf),
12280 "Invalid URI: [%s]",
12281 ri->request_uri);
12282 send_http_error(conn, 400, "%s", ebuf);
12283 break;
12284 }
12285
12286 /* TODO: cleanup uri, local_uri and request_uri */
12287 conn->request_info.uri = conn->request_info.local_uri;
12288 }
12289
12290 if (ebuf[0] == '\0') {
12291 if (conn->request_info.local_uri) {
12292 /* handle request to local server */
12293 handle_request(conn);
12294 if (conn->ctx->callbacks.end_request != NULL) {
12295 conn->ctx->callbacks.end_request(conn,
12296 conn->status_code);
12297 }
12298 log_access(conn);
12299 } else {
12300 /* TODO: handle non-local request (PROXY) */
12301 conn->must_close = 1;
12302 }
12303 } else {
12304 conn->must_close = 1;
12305 }
12306
12307 if (ri->remote_user != NULL) {
12308 mg_free((void *)ri->remote_user);
12309 /* Important! When having connections with and without auth
12310 * would cause double free and then crash */
12311 ri->remote_user = NULL;
12312 }
12313
12314 /* NOTE(lsm): order is important here. should_keep_alive() call
12315 * is
12316 * using parsed request, which will be invalid after memmove's
12317 * below.
12318 * Therefore, memorize should_keep_alive() result now for later
12319 * use
12320 * in loop exit condition. */
12321 keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled
12322 && conn->content_len >= 0 && should_keep_alive(conn);
12323
12324 /* Discard all buffered data for this request */
12325 discard_len = conn->content_len >= 0 && conn->request_len > 0
12326 && conn->request_len + conn->content_len
12327 < (int64_t)conn->data_len
12328 ? (int)(conn->request_len + conn->content_len)
12329 : conn->data_len;
12330 /*assert(discard_len >= 0);*/
12331 if (discard_len < 0)
12332 break;
12333 conn->data_len -= discard_len;
12334 if (conn->data_len > 0) {
12335 memmove(conn->buf,
12336 conn->buf + discard_len,
12337 (size_t)conn->data_len);
12338 }
12339
12340 /* assert(conn->data_len >= 0); */
12341 /* assert(conn->data_len <= conn->buf_size); */
12342
12343 if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
12344 break;
12345 }
12346
12347 } while (keep_alive);
12348 }
12349 }
12350
12351
12352 /* Worker threads take accepted socket from the queue */
12353 static int
12354 consume_socket(struct mg_context *ctx, struct socket *sp)
12355 {
12356 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12357 if (!ctx) {
12358 return 0;
12359 }
12360
12361 (void)pthread_mutex_lock(&ctx->thread_mutex);
12362 DEBUG_TRACE("%s", "going idle");
12363
12364 /* If the queue is empty, wait. We're idle at this point. */
12365 while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
12366 pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
12367 }
12368
12369 /* If we're stopping, sq_head may be equal to sq_tail. */
12370 if (ctx->sq_head > ctx->sq_tail) {
12371 /* Copy socket from the queue and increment tail */
12372 *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
12373 ctx->sq_tail++;
12374
12375 DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
12376
12377 /* Wrap pointers if needed */
12378 while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
12379 ctx->sq_tail -= QUEUE_SIZE(ctx);
12380 ctx->sq_head -= QUEUE_SIZE(ctx);
12381 }
12382 }
12383
12384 (void)pthread_cond_signal(&ctx->sq_empty);
12385 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12386
12387 return !ctx->stop_flag;
12388 #undef QUEUE_SIZE
12389 }
12390
12391
12392 static void *
12393 worker_thread_run(void *thread_func_param)
12394 {
12395 struct mg_context *ctx = (struct mg_context *)thread_func_param;
12396 struct mg_connection *conn;
12397 struct mg_workerTLS tls;
12398 #if defined(MG_LEGACY_INTERFACE)
12399 uint32_t addr;
12400 #endif
12401
12402 mg_set_thread_name("worker");
12403
12404 tls.is_master = 0;
12405 tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12406 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12407 tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12408 #endif
12409
12410 if (ctx->callbacks.init_thread) {
12411 /* call init_thread for a worker thread (type 1) */
12412 ctx->callbacks.init_thread(ctx, 1);
12413 }
12414
12415 conn =
12416 (struct mg_connection *)mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
12417 if (conn == NULL) {
12418 mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
12419 } else {
12420 pthread_setspecific(sTlsKey, &tls);
12421 conn->buf_size = MAX_REQUEST_SIZE;
12422 conn->buf = (char *)(conn + 1);
12423 conn->ctx = ctx;
12424 conn->request_info.user_data = ctx->user_data;
12425 /* Allocate a mutex for this connection to allow communication both
12426 * within the request handler and from elsewhere in the application
12427 */
12428 (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
12429
12430 /* Call consume_socket() even when ctx->stop_flag > 0, to let it
12431 * signal sq_empty condvar to wake up the master waiting in
12432 * produce_socket() */
12433 while (consume_socket(ctx, &conn->client)) {
12434 conn->conn_birth_time = time(NULL);
12435
12436 /* Fill in IP, port info early so even if SSL setup below fails,
12437 * error handler would have the corresponding info.
12438 * Thanks to Johannes Winkelmann for the patch.
12439 */
12440 #if defined(USE_IPV6)
12441 if (conn->client.rsa.sa.sa_family == AF_INET6) {
12442 conn->request_info.remote_port =
12443 ntohs(conn->client.rsa.sin6.sin6_port);
12444 } else
12445 #endif
12446 {
12447 conn->request_info.remote_port =
12448 ntohs(conn->client.rsa.sin.sin_port);
12449 }
12450
12451 sockaddr_to_string(conn->request_info.remote_addr,
12452 sizeof(conn->request_info.remote_addr),
12453 &conn->client.rsa);
12454
12455 #if defined(MG_LEGACY_INTERFACE)
12456 /* This legacy interface only works for the IPv4 case */
12457 addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
12458 memcpy(&conn->request_info.remote_ip, &addr, 4);
12459 #endif
12460
12461 conn->request_info.is_ssl = conn->client.is_ssl;
12462
12463 if (!conn->client.is_ssl
12464 #ifndef NO_SSL
12465 || sslize(conn, conn->ctx->ssl_ctx, SSL_accept)
12466 #endif
12467 ) {
12468
12469
12470 process_new_connection(conn);
12471 }
12472
12473 close_connection(conn);
12474 }
12475 }
12476
12477 /* Signal master that we're done with connection and exiting */
12478 (void)pthread_mutex_lock(&ctx->thread_mutex);
12479 ctx->running_worker_threads--;
12480 (void)pthread_cond_signal(&ctx->thread_cond);
12481 /* assert(ctx->running_worker_threads >= 0); */
12482 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12483
12484 pthread_setspecific(sTlsKey, NULL);
12485 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12486 CloseHandle(tls.pthread_cond_helper_mutex);
12487 #endif
12488 pthread_mutex_destroy(&conn->mutex);
12489 mg_free(conn);
12490
12491 DEBUG_TRACE("%s", "exiting");
12492 return NULL;
12493 }
12494
12495
12496 /* Threads have different return types on Windows and Unix. */
12497 #ifdef _WIN32
12498 static unsigned __stdcall worker_thread(void *thread_func_param)
12499 {
12500 worker_thread_run(thread_func_param);
12501 return 0;
12502 }
12503 #else
12504 static void *
12505 worker_thread(void *thread_func_param)
12506 {
12507 worker_thread_run(thread_func_param);
12508 return NULL;
12509 }
12510 #endif /* _WIN32 */
12511
12512
12513 /* Master thread adds accepted socket to a queue */
12514 static void
12515 produce_socket(struct mg_context *ctx, const struct socket *sp)
12516 {
12517 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12518 if (!ctx) {
12519 return;
12520 }
12521 (void)pthread_mutex_lock(&ctx->thread_mutex);
12522
12523 /* If the queue is full, wait */
12524 while (ctx->stop_flag == 0
12525 && ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
12526 (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
12527 }
12528
12529 if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
12530 /* Copy socket to the queue and increment head */
12531 ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
12532 ctx->sq_head++;
12533 DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
12534 }
12535
12536 (void)pthread_cond_signal(&ctx->sq_full);
12537 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12538 #undef QUEUE_SIZE
12539 }
12540
12541
12542 static void
12543 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
12544 {
12545 struct socket so;
12546 char src_addr[IP_ADDR_STR_LEN];
12547 socklen_t len = sizeof(so.rsa);
12548 int on = 1;
12549 int timeout;
12550
12551 if (!listener) {
12552 return;
12553 }
12554
12555 if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
12556 == INVALID_SOCKET) {
12557 } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
12558 sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
12559 mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
12560 closesocket(so.sock);
12561 so.sock = INVALID_SOCKET;
12562 } else {
12563 /* Put so socket structure into the queue */
12564 DEBUG_TRACE("Accepted socket %d", (int)so.sock);
12565 set_close_on_exec(so.sock, fc(ctx));
12566 so.is_ssl = listener->is_ssl;
12567 so.ssl_redir = listener->ssl_redir;
12568 if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
12569 mg_cry(fc(ctx),
12570 "%s: getsockname() failed: %s",
12571 __func__,
12572 strerror(ERRNO));
12573 }
12574
12575 /* Set TCP keep-alive. This is needed because if HTTP-level
12576 * keep-alive
12577 * is enabled, and client resets the connection, server won't get
12578 * TCP FIN or RST and will keep the connection open forever. With
12579 * TCP keep-alive, next keep-alive handshake will figure out that
12580 * the client is down and will close the server end.
12581 * Thanks to Igor Klopov who suggested the patch. */
12582 if (setsockopt(so.sock,
12583 SOL_SOCKET,
12584 SO_KEEPALIVE,
12585 (SOCK_OPT_TYPE)&on,
12586 sizeof(on)) != 0) {
12587 mg_cry(fc(ctx),
12588 "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
12589 __func__,
12590 strerror(ERRNO));
12591 }
12592
12593
12594 /* Disable TCP Nagle's algorithm. Normally TCP packets are
12595 * coalesced
12596 * to effectively fill up the underlying IP packet payload and
12597 * reduce
12598 * the overhead of sending lots of small buffers. However this hurts
12599 * the server's throughput (ie. operations per second) when HTTP 1.1
12600 * persistent connections are used and the responses are relatively
12601 * small (eg. less than 1400 bytes).
12602 */
12603 if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
12604 && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
12605 if (set_tcp_nodelay(so.sock, 1) != 0) {
12606 mg_cry(fc(ctx),
12607 "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
12608 __func__,
12609 strerror(ERRNO));
12610 }
12611 }
12612
12613 if (ctx && ctx->config[REQUEST_TIMEOUT]) {
12614 timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
12615 } else {
12616 timeout = -1;
12617 }
12618
12619 /* Set socket timeout to the given value, but not more than a
12620 * a certain limit (SOCKET_TIMEOUT_QUANTUM, default 10 seconds),
12621 * so the server can exit after that time if requested. */
12622 if ((timeout > 0) && (timeout < SOCKET_TIMEOUT_QUANTUM)) {
12623 set_sock_timeout(so.sock, timeout);
12624 } else {
12625 set_sock_timeout(so.sock, SOCKET_TIMEOUT_QUANTUM);
12626 }
12627
12628 produce_socket(ctx, &so);
12629 }
12630 }
12631
12632
12633 static void
12634 master_thread_run(void *thread_func_param)
12635 {
12636 struct mg_context *ctx = (struct mg_context *)thread_func_param;
12637 struct mg_workerTLS tls;
12638 struct pollfd *pfd;
12639 unsigned int i;
12640 unsigned int workerthreadcount;
12641
12642 if (!ctx) {
12643 return;
12644 }
12645
12646 mg_set_thread_name("master");
12647
12648 /* Increase priority of the master thread */
12649 #if defined(_WIN32)
12650 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
12651 #elif defined(USE_MASTER_THREAD_PRIORITY)
12652 int min_prio = sched_get_priority_min(SCHED_RR);
12653 int max_prio = sched_get_priority_max(SCHED_RR);
12654 if ((min_prio >= 0) && (max_prio >= 0)
12655 && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
12656 && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
12657 struct sched_param sched_param = {0};
12658 sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
12659 pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
12660 }
12661 #endif
12662
12663 /* Initialize thread local storage */
12664 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12665 tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12666 #endif
12667 tls.is_master = 1;
12668 pthread_setspecific(sTlsKey, &tls);
12669
12670 if (ctx->callbacks.init_thread) {
12671 /* Callback for the master thread (type 0) */
12672 ctx->callbacks.init_thread(ctx, 0);
12673 }
12674
12675 /* Server starts *now* */
12676 ctx->start_time = time(NULL);
12677
12678 /* Allocate memory for the listening sockets, and start the server */
12679 pfd =
12680 (struct pollfd *)mg_calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
12681 while (pfd != NULL && ctx->stop_flag == 0) {
12682 for (i = 0; i < ctx->num_listening_sockets; i++) {
12683 pfd[i].fd = ctx->listening_sockets[i].sock;
12684 pfd[i].events = POLLIN;
12685 }
12686
12687 if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
12688 for (i = 0; i < ctx->num_listening_sockets; i++) {
12689 /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
12690 * successful poll, and POLLIN is defined as
12691 * (POLLRDNORM | POLLRDBAND)
12692 * Therefore, we're checking pfd[i].revents & POLLIN, not
12693 * pfd[i].revents == POLLIN. */
12694 if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
12695 accept_new_connection(&ctx->listening_sockets[i], ctx);
12696 }
12697 }
12698 }
12699 }
12700 mg_free(pfd);
12701 DEBUG_TRACE("%s", "stopping workers");
12702
12703 /* Stop signal received: somebody called mg_stop. Quit. */
12704 close_all_listening_sockets(ctx);
12705
12706 /* Wakeup workers that are waiting for connections to handle. */
12707 pthread_cond_broadcast(&ctx->sq_full);
12708
12709 /* Wait until all threads finish */
12710 (void)pthread_mutex_lock(&ctx->thread_mutex);
12711 while (ctx->running_worker_threads > 0) {
12712 (void)pthread_cond_wait(&ctx->thread_cond, &ctx->thread_mutex);
12713 }
12714 (void)pthread_mutex_unlock(&ctx->thread_mutex);
12715
12716 /* Join all worker threads to avoid leaking threads. */
12717 workerthreadcount = ctx->cfg_worker_threads;
12718 for (i = 0; i < workerthreadcount; i++) {
12719 if (ctx->workerthreadids[i] != 0) {
12720 mg_join_thread(ctx->workerthreadids[i]);
12721 }
12722 }
12723
12724 #if !defined(NO_SSL)
12725 if (ctx->ssl_ctx != NULL) {
12726 uninitialize_ssl(ctx);
12727 }
12728 #endif
12729 DEBUG_TRACE("%s", "exiting");
12730
12731 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12732 CloseHandle(tls.pthread_cond_helper_mutex);
12733 #endif
12734 pthread_setspecific(sTlsKey, NULL);
12735
12736 /* Signal mg_stop() that we're done.
12737 * WARNING: This must be the very last thing this
12738 * thread does, as ctx becomes invalid after this line. */
12739 ctx->stop_flag = 2;
12740 }
12741
12742
12743 /* Threads have different return types on Windows and Unix. */
12744 #ifdef _WIN32
12745 static unsigned __stdcall master_thread(void *thread_func_param)
12746 {
12747 master_thread_run(thread_func_param);
12748 return 0;
12749 }
12750 #else
12751 static void *
12752 master_thread(void *thread_func_param)
12753 {
12754 master_thread_run(thread_func_param);
12755 return NULL;
12756 }
12757 #endif /* _WIN32 */
12758
12759
12760 static void
12761 free_context(struct mg_context *ctx)
12762 {
12763 int i;
12764 struct mg_handler_info *tmp_rh;
12765
12766 if (ctx == NULL) {
12767 return;
12768 }
12769
12770 if (ctx->callbacks.exit_context) {
12771 ctx->callbacks.exit_context(ctx);
12772 }
12773
12774 /* All threads exited, no sync is needed. Destroy thread mutex and
12775 * condvars
12776 */
12777 (void)pthread_mutex_destroy(&ctx->thread_mutex);
12778 (void)pthread_cond_destroy(&ctx->thread_cond);
12779 (void)pthread_cond_destroy(&ctx->sq_empty);
12780 (void)pthread_cond_destroy(&ctx->sq_full);
12781
12782 /* Destroy other context global data structures mutex */
12783 (void)pthread_mutex_destroy(&ctx->nonce_mutex);
12784
12785 #if defined(USE_TIMERS)
12786 timers_exit(ctx);
12787 #endif
12788
12789 /* Deallocate config parameters */
12790 for (i = 0; i < NUM_OPTIONS; i++) {
12791 if (ctx->config[i] != NULL) {
12792 #if defined(_MSC_VER)
12793 #pragma warning(suppress : 6001)
12794 #endif
12795 mg_free(ctx->config[i]);
12796 }
12797 }
12798
12799 /* Deallocate request handlers */
12800 while (ctx->handlers) {
12801 tmp_rh = ctx->handlers;
12802 ctx->handlers = tmp_rh->next;
12803 mg_free(tmp_rh->uri);
12804 mg_free(tmp_rh);
12805 }
12806
12807 #ifndef NO_SSL
12808 /* Deallocate SSL context */
12809 if (ctx->ssl_ctx != NULL) {
12810 SSL_CTX_free(ctx->ssl_ctx);
12811 }
12812 #endif /* !NO_SSL */
12813
12814 /* Deallocate worker thread ID array */
12815 if (ctx->workerthreadids != NULL) {
12816 mg_free(ctx->workerthreadids);
12817 }
12818
12819 /* Deallocate the tls variable */
12820 if (mg_atomic_dec(&sTlsInit) == 0) {
12821 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12822 DeleteCriticalSection(&global_log_file_lock);
12823 #endif /* _WIN32 && !__SYMBIAN32__ */
12824 #if !defined(_WIN32)
12825 pthread_mutexattr_destroy(&pthread_mutex_attr);
12826 #endif
12827
12828 pthread_key_delete(sTlsKey);
12829 }
12830
12831 /* deallocate system name string */
12832 mg_free(ctx->systemName);
12833
12834 /* Deallocate context itself */
12835 mg_free(ctx);
12836 }
12837
12838
12839 void
12840 mg_stop(struct mg_context *ctx)
12841 {
12842 pthread_t mt;
12843 if (!ctx) {
12844 return;
12845 }
12846
12847 /* We don't use a lock here. Calling mg_stop with the same ctx from
12848 * two threads is not allowed. */
12849 mt = ctx->masterthreadid;
12850 if (mt == 0) {
12851 return;
12852 }
12853
12854 ctx->masterthreadid = 0;
12855 ctx->stop_flag = 1;
12856
12857 /* Wait until mg_fini() stops */
12858 while (ctx->stop_flag != 2) {
12859 (void)mg_sleep(10);
12860 }
12861
12862 mg_join_thread(mt);
12863 free_context(ctx);
12864
12865 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12866 (void)WSACleanup();
12867 #endif /* _WIN32 && !__SYMBIAN32__ */
12868 }
12869
12870
12871 static void
12872 get_system_name(char **sysName)
12873 {
12874 #if defined(_WIN32)
12875 #if !defined(__SYMBIAN32__)
12876 char name[128];
12877 DWORD dwVersion = 0;
12878 DWORD dwMajorVersion = 0;
12879 DWORD dwMinorVersion = 0;
12880 DWORD dwBuild = 0;
12881
12882 #ifdef _MSC_VER
12883 #pragma warning(push)
12884 // GetVersion was declared deprecated
12885 #pragma warning(disable : 4996)
12886 #endif
12887 dwVersion = GetVersion();
12888 #ifdef _MSC_VER
12889 #pragma warning(pop)
12890 #endif
12891
12892 dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12893 dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
12894 dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
12895 (void)dwBuild;
12896
12897 sprintf(name,
12898 "Windows %u.%u",
12899 (unsigned)dwMajorVersion,
12900 (unsigned)dwMinorVersion);
12901 *sysName = mg_strdup(name);
12902 #else
12903 *sysName = mg_strdup("Symbian");
12904 #endif
12905 #else
12906 struct utsname name;
12907 memset(&name, 0, sizeof(name));
12908 uname(&name);
12909 *sysName = mg_strdup(name.sysname);
12910 #endif
12911 }
12912
12913
12914 struct mg_context *
12915 mg_start(const struct mg_callbacks *callbacks,
12916 void *user_data,
12917 const char **options)
12918 {
12919 struct mg_context *ctx;
12920 const char *name, *value, *default_value;
12921 int idx, ok, workerthreadcount;
12922 unsigned int i;
12923 void (*exit_callback)(const struct mg_context *ctx) = 0;
12924
12925 struct mg_workerTLS tls;
12926
12927 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12928 WSADATA data;
12929 WSAStartup(MAKEWORD(2, 2), &data);
12930 #endif /* _WIN32 && !__SYMBIAN32__ */
12931
12932 /* Allocate context and initialize reasonable general case defaults. */
12933 if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
12934 return NULL;
12935 }
12936
12937 /* Random number generator will initialize at the first call */
12938 ctx->auth_nonce_mask =
12939 (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
12940
12941 if (mg_atomic_inc(&sTlsInit) == 1) {
12942
12943 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12944 InitializeCriticalSection(&global_log_file_lock);
12945 #endif /* _WIN32 && !__SYMBIAN32__ */
12946 #if !defined(_WIN32)
12947 pthread_mutexattr_init(&pthread_mutex_attr);
12948 pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
12949 #endif
12950
12951 if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
12952 /* Fatal error - abort start. However, this situation should
12953 * never
12954 * occur in practice. */
12955 mg_atomic_dec(&sTlsInit);
12956 mg_cry(fc(ctx), "Cannot initialize thread local storage");
12957 mg_free(ctx);
12958 return NULL;
12959 }
12960 } else {
12961 /* TODO (low): istead of sleeping, check if sTlsKey is already
12962 * initialized. */
12963 mg_sleep(1);
12964 }
12965
12966 tls.is_master = -1;
12967 tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12968 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12969 tls.pthread_cond_helper_mutex = NULL;
12970 #endif
12971 pthread_setspecific(sTlsKey, &tls);
12972
12973 #if defined(USE_LUA)
12974 lua_init_optional_libraries();
12975 #endif
12976
12977 ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
12978 ok &= 0 == pthread_cond_init(&ctx->thread_cond, NULL);
12979 ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
12980 ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
12981 ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
12982 if (!ok) {
12983 /* Fatal error - abort start. However, this situation should never
12984 * occur in practice. */
12985 mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
12986 mg_free(ctx);
12987 pthread_setspecific(sTlsKey, NULL);
12988 return NULL;
12989 }
12990
12991 if (callbacks) {
12992 ctx->callbacks = *callbacks;
12993 exit_callback = callbacks->exit_context;
12994 ctx->callbacks.exit_context = 0;
12995 }
12996 ctx->user_data = user_data;
12997 ctx->handlers = NULL;
12998
12999 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
13000 ctx->shared_lua_websockets = 0;
13001 #endif
13002
13003 while (options && (name = *options++) != NULL) {
13004 if ((idx = get_option_index(name)) == -1) {
13005 mg_cry(fc(ctx), "Invalid option: %s", name);
13006 free_context(ctx);
13007 pthread_setspecific(sTlsKey, NULL);
13008 return NULL;
13009 } else if ((value = *options++) == NULL) {
13010 mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
13011 free_context(ctx);
13012 pthread_setspecific(sTlsKey, NULL);
13013 return NULL;
13014 }
13015 if (ctx->config[idx] != NULL) {
13016 mg_cry(fc(ctx), "warning: %s: duplicate option", name);
13017 mg_free(ctx->config[idx]);
13018 }
13019 ctx->config[idx] = mg_strdup(value);
13020 DEBUG_TRACE("[%s] -> [%s]", name, value);
13021 }
13022
13023 /* Set default value if needed */
13024 for (i = 0; config_options[i].name != NULL; i++) {
13025 default_value = config_options[i].default_value;
13026 if (ctx->config[i] == NULL && default_value != NULL) {
13027 ctx->config[i] = mg_strdup(default_value);
13028 }
13029 }
13030
13031 #if defined(NO_FILES)
13032 if (ctx->config[DOCUMENT_ROOT] != NULL) {
13033 mg_cry(fc(ctx), "%s", "Document root must not be set");
13034 free_context(ctx);
13035 pthread_setspecific(sTlsKey, NULL);
13036 return NULL;
13037 }
13038 #endif
13039
13040 get_system_name(&ctx->systemName);
13041
13042 /* NOTE(lsm): order is important here. SSL certificates must
13043 * be initialized before listening ports. UID must be set last. */
13044 if (!set_gpass_option(ctx) ||
13045 #if !defined(NO_SSL)
13046 !set_ssl_option(ctx) ||
13047 #endif
13048 !set_ports_option(ctx) ||
13049 #if !defined(_WIN32)
13050 !set_uid_option(ctx) ||
13051 #endif
13052 !set_acl_option(ctx)) {
13053 free_context(ctx);
13054 pthread_setspecific(sTlsKey, NULL);
13055 return NULL;
13056 }
13057
13058 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
13059 /* Ignore SIGPIPE signal, so if browser cancels the request, it
13060 * won't kill the whole process. */
13061 (void)signal(SIGPIPE, SIG_IGN);
13062 #endif /* !_WIN32 && !__SYMBIAN32__ */
13063
13064 workerthreadcount = atoi(ctx->config[NUM_THREADS]);
13065
13066 if (workerthreadcount > MAX_WORKER_THREADS) {
13067 mg_cry(fc(ctx), "Too many worker threads");
13068 free_context(ctx);
13069 pthread_setspecific(sTlsKey, NULL);
13070 return NULL;
13071 }
13072
13073 if (workerthreadcount > 0) {
13074 ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
13075 ctx->workerthreadids =
13076 (pthread_t *)mg_calloc(ctx->cfg_worker_threads, sizeof(pthread_t));
13077 if (ctx->workerthreadids == NULL) {
13078 mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
13079 free_context(ctx);
13080 pthread_setspecific(sTlsKey, NULL);
13081 return NULL;
13082 }
13083 }
13084
13085 #if defined(USE_TIMERS)
13086 if (timers_init(ctx) != 0) {
13087 mg_cry(fc(ctx), "Error creating timers");
13088 free_context(ctx);
13089 pthread_setspecific(sTlsKey, NULL);
13090 return NULL;
13091 }
13092 #endif
13093
13094 /* Context has been created - init user libraries */
13095 if (ctx->callbacks.init_context) {
13096 ctx->callbacks.init_context(ctx);
13097 }
13098 ctx->callbacks.exit_context = exit_callback;
13099 ctx->context_type = 1; /* server context */
13100
13101 /* Start master (listening) thread */
13102 mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
13103
13104 /* Start worker threads */
13105 for (i = 0; i < ctx->cfg_worker_threads; i++) {
13106 (void)pthread_mutex_lock(&ctx->thread_mutex);
13107 ctx->running_worker_threads++;
13108 (void)pthread_mutex_unlock(&ctx->thread_mutex);
13109 if (mg_start_thread_with_id(worker_thread,
13110 ctx,
13111 &ctx->workerthreadids[i]) != 0) {
13112 (void)pthread_mutex_lock(&ctx->thread_mutex);
13113 ctx->running_worker_threads--;
13114 (void)pthread_mutex_unlock(&ctx->thread_mutex);
13115 if (i > 0) {
13116 mg_cry(fc(ctx),
13117 "Cannot start worker thread %i: error %ld",
13118 i + 1,
13119 (long)ERRNO);
13120 } else {
13121 mg_cry(fc(ctx),
13122 "Cannot create threads: error %ld",
13123 (long)ERRNO);
13124 free_context(ctx);
13125 pthread_setspecific(sTlsKey, NULL);
13126 return NULL;
13127 }
13128 break;
13129 }
13130 }
13131
13132 pthread_setspecific(sTlsKey, NULL);
13133 return ctx;
13134 }
13135
13136
13137 /* Feature check API function */
13138 unsigned
13139 mg_check_feature(unsigned feature)
13140 {
13141 static const unsigned feature_set = 0
13142 /* Set bits for available features according to API documentation.
13143 * This bit mask is created at compile time, according to the active
13144 * preprocessor defines. It is a single const value at runtime. */
13145 #if !defined(NO_FILES)
13146 | 0x0001u
13147 #endif
13148 #if !defined(NO_SSL)
13149 | 0x0002u
13150 #endif
13151 #if !defined(NO_CGI)
13152 | 0x0004u
13153 #endif
13154 #if defined(USE_IPV6)
13155 | 0x0008u
13156 #endif
13157 #if defined(USE_WEBSOCKET)
13158 | 0x0010u
13159 #endif
13160 #if defined(USE_LUA)
13161 | 0x0020u
13162 #endif
13163 #if defined(USE_DUKTAPE)
13164 | 0x0040u
13165 #endif
13166 #if !defined(NO_CACHING)
13167 | 0x0080u
13168 #endif
13169
13170 /* Set some extra bits not defined in the API documentation.
13171 * These bits may change without further notice. */
13172 #if defined(MG_LEGACY_INTERFACE)
13173 | 0x8000u
13174 #endif
13175 #if defined(MEMORY_DEBUGGING)
13176 | 0x0100u
13177 #endif
13178 #if defined(USE_TIMERS)
13179 | 0x0200u
13180 #endif
13181 #if !defined(NO_NONCE_CHECK)
13182 | 0x0400u
13183 #endif
13184 #if !defined(NO_POPEN)
13185 | 0x0800u
13186 #endif
13187 ;
13188 return (feature & feature_set);
13189 }