Overview
Comment: | Added compile-time support for a fake chroot mode instead of using a real chroot (this may change into a runtime option one day) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | 5ea7bc000130190bc06ffe49d09549bfe879bc36 |
User & Date: | rkeene on 2016-08-17 16:21:30 |
Other Links: | manifest | tags |
Context
2016-08-17
| ||
16:22 | Filed 1.18 check-in: a78878e047 user: rkeene tags: trunk, 1.18 | |
16:21 | Added compile-time support for a fake chroot mode instead of using a real chroot (this may change into a runtime option one day) check-in: 5ea7bc0001 user: rkeene tags: trunk | |
2016-08-09
| ||
16:51 | Disabled -Werror, it is a bad idea for releases to include check-in: 1a822c0ca5 user: rkeene tags: trunk | |
Changes
Modified README from [d62e07fe87] to [8ec76224c9].
67 67 This is an internal option and should only be used during development. 68 68 69 69 4. Differing HTTP semantics (CFLAGS, -DFILED_NONBLOCK_HTTP=1) 70 70 It is possible that some HTTP clients may not process the HTTP stream 71 71 being delivered if they cannot write to the HTTP stream itself. This 72 72 has not been observed yet, but it is possible. If these semantics are 73 73 needed (and they should not be) then they can be enabled with this 74 - flag at the cost of performance 74 + flag at the cost of performance. 75 + 76 + 5. Differing chroot() semantics (CFLAGS, -DFILED_FAKE_CHROOT=1) 77 + In some cases it is desirable to mangle paths with a path prefix 78 + rather than call chroot() at startup. This is less secure and slower 79 + and should be generally avoided -- however it may be necessary to do. 80 + In these cases the executable may be compiled with the 81 + FILED_FAKE_CHROOT C preprocessor macro defined and instead of calling 82 + chroot() all HTTP requests will have the root suffix specified as the 83 + argument to the "-r" or "--root" option prepended to them. 75 84 76 - 5. MIME Types (MIMETYPES) 77 - For single-file convience "filed" compiles the mapping of file 85 + 6. MIME Types (MIMETYPES) 86 + For single-file convenience "filed" compiles the mapping of file 78 87 extensions (the string in the filename following its last dot (".")) 79 88 into the executable. This mapping comes from a file in the format of 80 89 type1 type1_extension1 type1_extension2... 81 90 type2 type2_extension1 type2_extension2... 82 91 ... 83 92 However it may not be desirable to include this mapping, or it may be 84 93 desirable to use your own mapping rather than the default one. This
Modified filed.c from [7391155930] to [e20f1f0a83].
115 115 attr = attr; 116 116 } 117 117 #endif 118 118 119 119 /* Configuration options that work threads need to be aware of */ 120 120 struct filed_options { 121 121 int vhosts_enabled; 122 + const char *fake_newroot; 122 123 }; 123 124 124 125 /* Arguments for worker threads */ 125 126 struct filed_worker_thread_args { 126 127 int fd; 127 128 struct filed_options options; 128 129 }; ................................................................................ 862 863 (unsigned long long) time(NULL), 863 864 (unsigned long long) random(), 864 865 (unsigned long long) random(), 865 866 (unsigned long long) random(), 866 867 (unsigned long long) random() 867 868 ); 868 869 } 870 + 871 +#ifdef FILED_FAKE_CHROOT 872 +/* Translate a path into a fake chroot path */ 873 +static const char *filed_path_translate(const char *path, struct filed_options *options) { 874 + static __thread char pathBuffer[8192]; 875 + int snprintf_ret; 876 + 877 + /* If no alternative root is specified, return the unadorned path */ 878 + if (!options->fake_newroot) { 879 + return(path); 880 + } 881 + 882 + /* Verify that this request will not go outside of the specified root */ 883 + if (strstr(path, "/../") != NULL || path[0] != '/') { 884 + filed_log_msg_debug("Unable to translate path \"%s\", contains invalid characters", path); 885 + 886 + return(options->fake_newroot); 887 + } 888 + 889 + /* Create the new path into our local (TLS) static buffer */ 890 + snprintf_ret = snprintf(pathBuffer, sizeof(pathBuffer), "%s/%s", options->fake_newroot, path); 891 + if (snprintf_ret < 0 || ((unsigned int) snprintf_ret) >= sizeof(pathBuffer)) { 892 + filed_log_msg_debug("Unable to translate path \"%s\", will not fit into new buffer", path); 893 + 894 + return(options->fake_newroot); 895 + } 896 + 897 + filed_log_msg_debug("Translating path \"%s\" into \"%s\"", path, pathBuffer); 898 + 899 + /* Return the new path */ 900 + return(pathBuffer); 901 +} 902 + 903 +static void filed_path_translate_set_root(const char *var, struct filed_options *options, const char *val) { 904 + options->fake_newroot = strdup(val); 905 + 906 + return; 907 + 908 + /* var is only used in the macro -- discard it here */ 909 + var = var; 910 +} 911 +#else 912 +#define filed_path_translate(path, options) path 913 +#define filed_path_translate_set_root(var, options, val) var = strdup(val) 914 +#endif 869 915 870 916 /* Open a file and return file information */ 871 -static struct filed_fileinfo *filed_open_file(const char *path, struct filed_fileinfo *buffer) { 917 +static struct filed_fileinfo *filed_open_file(const char *path, struct filed_fileinfo *buffer, struct filed_options *options) { 872 918 struct filed_fileinfo *cache; 873 919 unsigned int cache_idx; 874 920 off_t len; 875 921 int fd; 876 922 877 923 if (filed_fileinfo_fdcache_size != 0) { 878 924 cache_idx = filed_hash((const unsigned char *) path, filed_fileinfo_fdcache_size); ................................................................................ 890 936 cache->path[0] = '\0'; 891 937 cache->fd = -1; 892 938 } 893 939 894 940 if (strcmp(path, cache->path) != 0) { 895 941 filed_log_msg_debug("Cache miss for idx: %lu: OLD \"%s\", NEW \"%s\"", (unsigned long) cache_idx, cache->path, path); 896 942 897 - fd = open(path, O_RDONLY | O_LARGEFILE); 943 + fd = open(filed_path_translate(path, options), O_RDONLY | O_LARGEFILE); 898 944 if (fd < 0) { 899 945 if (filed_fileinfo_fdcache_size != 0) { 900 946 pthread_mutex_unlock(&cache->mutex); 901 947 } 902 948 903 949 return(NULL); 904 950 } ................................................................................ 941 987 memcpy(buffer->etag, cache->etag, sizeof(buffer->etag)); 942 988 buffer->lastmod = buffer->lastmod_b + (cache->lastmod - cache->lastmod_b); 943 989 944 990 pthread_mutex_unlock(&cache->mutex); 945 991 } 946 992 947 993 return(buffer); 994 + 995 + /* options is only used if fake chroot is enabled, confuse the compiler */ 996 + options = options; 948 997 } 949 998 950 999 /* Process an HTTP request and return the path requested */ 951 1000 static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st, struct filed_options *options) { 952 1001 char *method, *path; 953 1002 char *buffer, *workbuffer, *workbuffer_next; 954 1003 char *fgets_ret; ................................................................................ 1235 1284 /* If the requested path is a directory, redirect to index page */ 1236 1285 if (request->type == FILED_REQUEST_TYPE_DIRECTORY) { 1237 1286 filed_redirect_index(fp, date_current, path, log); 1238 1287 1239 1288 return(FILED_CONNECTION_CLOSE); 1240 1289 } 1241 1290 1242 - fileinfo = filed_open_file(path, &request->fileinfo); 1291 + fileinfo = filed_open_file(path, &request->fileinfo, options); 1243 1292 if (fileinfo == NULL) { 1244 1293 filed_error_page(fp, date_current, 404, request->method, "open_failed", log); 1245 1294 1246 1295 return(FILED_CONNECTION_CLOSE); 1247 1296 } 1248 1297 1249 1298 if (request->headers.range.present) { ................................................................................ 1679 1728 1680 1729 return(0); 1681 1730 } 1682 1731 1683 1732 /* Run process */ 1684 1733 int main(int argc, char **argv) { 1685 1734 struct option options[12]; 1686 - struct filed_options thread_options; 1735 + struct filed_options thread_options = {0}; 1687 1736 const char *bind_addr = BIND_ADDR, *newroot = NULL, *log_file = LOG_FILE; 1688 1737 FILE *log_fp; 1689 1738 uid_t user = 0; 1690 1739 int port = PORT, thread_count = THREAD_COUNT; 1691 1740 int cache_size = CACHE_SIZE; 1692 1741 int init_ret, chroot_ret, setuid_ret, lookup_ret, chdir_ret; 1693 1742 int setuid_enabled = 0, daemon_enabled = 0; 1694 1743 int ch; 1695 1744 int fd; 1696 1745 1697 - /* Set default values */ 1698 - thread_options.vhosts_enabled = 0; 1699 - 1700 1746 /* Process arguments */ 1701 1747 filed_getopt_long_setopt(&options[0], "port", required_argument, 'p'); 1702 1748 filed_getopt_long_setopt(&options[1], "threads", required_argument, 't'); 1703 1749 filed_getopt_long_setopt(&options[2], "cache", required_argument, 'c'); 1704 1750 filed_getopt_long_setopt(&options[3], "bind", required_argument, 'b'); 1705 1751 filed_getopt_long_setopt(&options[4], "user", required_argument, 'u'); 1706 1752 filed_getopt_long_setopt(&options[5], "root", required_argument, 'r'); ................................................................................ 1730 1776 if (lookup_ret != 0) { 1731 1777 filed_print_help(stderr, 0, "Invalid username specified"); 1732 1778 1733 1779 return(1); 1734 1780 } 1735 1781 break; 1736 1782 case 'r': 1737 - newroot = strdup(optarg); 1783 + filed_path_translate_set_root(newroot, &thread_options, optarg); 1738 1784 break; 1739 1785 case 'l': 1740 1786 log_file = strdup(optarg); 1741 1787 break; 1742 1788 case 'd': 1743 1789 daemon_enabled = 1; 1744 1790 break;