Check-in [5ea7bc0001]
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
68
69
70
71
72
73
74
75









76
77
78
79
80
81
82
83
84
	This is an internal option and should only be used during development.

   4. Differing HTTP semantics (CFLAGS, -DFILED_NONBLOCK_HTTP=1)
	It is possible that some HTTP clients may not process the HTTP stream
	being delivered if they cannot write to the HTTP stream itself.  This
	has not been observed yet, but it is possible.  If these semantics are
	needed (and they should not be) then they can be enabled with this
	flag at the cost of performance










   5. MIME Types (MIMETYPES)
	For single-file convience "filed" compiles the mapping of file
	extensions (the string in the filename following its last dot ("."))
	into the executable.  This mapping comes from a file in the format of
		type1   type1_extension1 type1_extension2...
		type2   type2_extension1 type2_extension2...
		...
	However it may not be desirable to include this mapping, or it may be
	desirable to use your own mapping rather than the default one.  This







|

>
>
>
>
>
>
>
>
>
|
|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	This is an internal option and should only be used during development.

   4. Differing HTTP semantics (CFLAGS, -DFILED_NONBLOCK_HTTP=1)
	It is possible that some HTTP clients may not process the HTTP stream
	being delivered if they cannot write to the HTTP stream itself.  This
	has not been observed yet, but it is possible.  If these semantics are
	needed (and they should not be) then they can be enabled with this
	flag at the cost of performance.

   5. Differing chroot() semantics (CFLAGS, -DFILED_FAKE_CHROOT=1)
        In some cases it is desirable to mangle paths with a path prefix
        rather than call chroot() at startup.  This is less secure and slower
        and should be generally avoided -- however it may be necessary to do.
        In these cases the executable may be compiled with the
        FILED_FAKE_CHROOT C preprocessor macro defined and instead of calling
        chroot() all HTTP requests will have the root suffix specified as the
        argument to the "-r" or "--root" option prepended to them.

   6. MIME Types (MIMETYPES)
	For single-file convenience "filed" compiles the mapping of file
	extensions (the string in the filename following its last dot ("."))
	into the executable.  This mapping comes from a file in the format of
		type1   type1_extension1 type1_extension2...
		type2   type2_extension1 type2_extension2...
		...
	However it may not be desirable to include this mapping, or it may be
	desirable to use your own mapping rather than the default one.  This

Modified filed.c from [7391155930] to [e20f1f0a83].

115
116
117
118
119
120
121

122
123
124
125
126
127
128
	attr = attr;
}
#endif

/* Configuration options that work threads need to be aware of */
struct filed_options {
	int vhosts_enabled;

};

/* Arguments for worker threads */
struct filed_worker_thread_args {
	int fd;
	struct filed_options options;
};







>







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	attr = attr;
}
#endif

/* Configuration options that work threads need to be aware of */
struct filed_options {
	int vhosts_enabled;
	const char *fake_newroot;
};

/* Arguments for worker threads */
struct filed_worker_thread_args {
	int fd;
	struct filed_options options;
};
862
863
864
865
866
867
868
869













































870
871
872
873
874
875
876
877
878
		(unsigned long long) time(NULL),
		(unsigned long long) random(),
		(unsigned long long) random(),
		(unsigned long long) random(),
		(unsigned long long) random()
	);
}














































/* Open a file and return file information */
static struct filed_fileinfo *filed_open_file(const char *path, struct filed_fileinfo *buffer) {
	struct filed_fileinfo *cache;
	unsigned int cache_idx;
	off_t len;
	int fd;

	if (filed_fileinfo_fdcache_size != 0) {
		cache_idx = filed_hash((const unsigned char *) path, filed_fileinfo_fdcache_size);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
		(unsigned long long) time(NULL),
		(unsigned long long) random(),
		(unsigned long long) random(),
		(unsigned long long) random(),
		(unsigned long long) random()
	);
}

#ifdef FILED_FAKE_CHROOT
/* Translate a path into a fake chroot path */
static const char *filed_path_translate(const char *path, struct filed_options *options) {
	static __thread char pathBuffer[8192];
	int snprintf_ret;

	/* If no alternative root is specified, return the unadorned path */
	if (!options->fake_newroot) {
		return(path);
	}

	/* Verify that this request will not go outside of the specified root */
	if (strstr(path, "/../") != NULL || path[0] != '/') {
		filed_log_msg_debug("Unable to translate path \"%s\", contains invalid characters", path);

		return(options->fake_newroot);
	}

	/* Create the new path into our local (TLS) static buffer */
	snprintf_ret = snprintf(pathBuffer, sizeof(pathBuffer), "%s/%s", options->fake_newroot, path);
	if (snprintf_ret < 0 || ((unsigned int) snprintf_ret) >= sizeof(pathBuffer)) {
		filed_log_msg_debug("Unable to translate path \"%s\", will not fit into new buffer", path);

		return(options->fake_newroot);
	}

	filed_log_msg_debug("Translating path \"%s\" into \"%s\"", path, pathBuffer);

	/* Return the new path */
	return(pathBuffer);
}

static void filed_path_translate_set_root(const char *var, struct filed_options *options, const char *val) {
	options->fake_newroot = strdup(val);

	return;

	/* var is only used in the macro -- discard it here */
	var = var;
}
#else
#define filed_path_translate(path, options) path
#define filed_path_translate_set_root(var, options, val) var = strdup(val)
#endif

/* Open a file and return file information */
static struct filed_fileinfo *filed_open_file(const char *path, struct filed_fileinfo *buffer, struct filed_options *options) {
	struct filed_fileinfo *cache;
	unsigned int cache_idx;
	off_t len;
	int fd;

	if (filed_fileinfo_fdcache_size != 0) {
		cache_idx = filed_hash((const unsigned char *) path, filed_fileinfo_fdcache_size);
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
		cache->path[0] = '\0';
		cache->fd = -1;
	}

	if (strcmp(path, cache->path) != 0) {
		filed_log_msg_debug("Cache miss for idx: %lu: OLD \"%s\", NEW \"%s\"", (unsigned long) cache_idx, cache->path, path);

		fd = open(path, O_RDONLY | O_LARGEFILE);
		if (fd < 0) {
			if (filed_fileinfo_fdcache_size != 0) {
				pthread_mutex_unlock(&cache->mutex);
			}

			return(NULL);
		}







|







936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
		cache->path[0] = '\0';
		cache->fd = -1;
	}

	if (strcmp(path, cache->path) != 0) {
		filed_log_msg_debug("Cache miss for idx: %lu: OLD \"%s\", NEW \"%s\"", (unsigned long) cache_idx, cache->path, path);

		fd = open(filed_path_translate(path, options), O_RDONLY | O_LARGEFILE);
		if (fd < 0) {
			if (filed_fileinfo_fdcache_size != 0) {
				pthread_mutex_unlock(&cache->mutex);
			}

			return(NULL);
		}
941
942
943
944
945
946
947



948
949
950
951
952
953
954
		memcpy(buffer->etag, cache->etag, sizeof(buffer->etag));
		buffer->lastmod = buffer->lastmod_b + (cache->lastmod - cache->lastmod_b);

		pthread_mutex_unlock(&cache->mutex);
	}

	return(buffer);



}

/* Process an HTTP request and return the path requested */
static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st, struct filed_options *options) {
	char *method, *path;
	char *buffer, *workbuffer, *workbuffer_next;
	char *fgets_ret;







>
>
>







987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
		memcpy(buffer->etag, cache->etag, sizeof(buffer->etag));
		buffer->lastmod = buffer->lastmod_b + (cache->lastmod - cache->lastmod_b);

		pthread_mutex_unlock(&cache->mutex);
	}

	return(buffer);

	/* options is only used if fake chroot is enabled, confuse the compiler */
	options = options;
}

/* Process an HTTP request and return the path requested */
static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st, struct filed_options *options) {
	char *method, *path;
	char *buffer, *workbuffer, *workbuffer_next;
	char *fgets_ret;
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
	/* If the requested path is a directory, redirect to index page */
	if (request->type == FILED_REQUEST_TYPE_DIRECTORY) {
		filed_redirect_index(fp, date_current, path, log);

		return(FILED_CONNECTION_CLOSE);
	}

	fileinfo = filed_open_file(path, &request->fileinfo);
	if (fileinfo == NULL) {
		filed_error_page(fp, date_current, 404, request->method, "open_failed", log);

		return(FILED_CONNECTION_CLOSE);
	}

	if (request->headers.range.present) {







|







1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
	/* If the requested path is a directory, redirect to index page */
	if (request->type == FILED_REQUEST_TYPE_DIRECTORY) {
		filed_redirect_index(fp, date_current, path, log);

		return(FILED_CONNECTION_CLOSE);
	}

	fileinfo = filed_open_file(path, &request->fileinfo, options);
	if (fileinfo == NULL) {
		filed_error_page(fp, date_current, 404, request->method, "open_failed", log);

		return(FILED_CONNECTION_CLOSE);
	}

	if (request->headers.range.present) {
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706

	return(0);
}

/* Run process */
int main(int argc, char **argv) {
	struct option options[12];
	struct filed_options thread_options;
	const char *bind_addr = BIND_ADDR, *newroot = NULL, *log_file = LOG_FILE;
	FILE *log_fp;
	uid_t user = 0;
	int port = PORT, thread_count = THREAD_COUNT;
	int cache_size = CACHE_SIZE;
	int init_ret, chroot_ret, setuid_ret, lookup_ret, chdir_ret;
	int setuid_enabled = 0, daemon_enabled = 0;
	int ch;
	int fd;

	/* Set default values */
	thread_options.vhosts_enabled = 0;

	/* Process arguments */
	filed_getopt_long_setopt(&options[0], "port", required_argument, 'p');
	filed_getopt_long_setopt(&options[1], "threads", required_argument, 't');
	filed_getopt_long_setopt(&options[2], "cache", required_argument, 'c');
	filed_getopt_long_setopt(&options[3], "bind", required_argument, 'b');
	filed_getopt_long_setopt(&options[4], "user", required_argument, 'u');
	filed_getopt_long_setopt(&options[5], "root", required_argument, 'r');







|










<
<
<







1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745



1746
1747
1748
1749
1750
1751
1752

	return(0);
}

/* Run process */
int main(int argc, char **argv) {
	struct option options[12];
	struct filed_options thread_options = {0};
	const char *bind_addr = BIND_ADDR, *newroot = NULL, *log_file = LOG_FILE;
	FILE *log_fp;
	uid_t user = 0;
	int port = PORT, thread_count = THREAD_COUNT;
	int cache_size = CACHE_SIZE;
	int init_ret, chroot_ret, setuid_ret, lookup_ret, chdir_ret;
	int setuid_enabled = 0, daemon_enabled = 0;
	int ch;
	int fd;




	/* Process arguments */
	filed_getopt_long_setopt(&options[0], "port", required_argument, 'p');
	filed_getopt_long_setopt(&options[1], "threads", required_argument, 't');
	filed_getopt_long_setopt(&options[2], "cache", required_argument, 'c');
	filed_getopt_long_setopt(&options[3], "bind", required_argument, 'b');
	filed_getopt_long_setopt(&options[4], "user", required_argument, 'u');
	filed_getopt_long_setopt(&options[5], "root", required_argument, 'r');
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
				if (lookup_ret != 0) {
					filed_print_help(stderr, 0, "Invalid username specified");

					return(1);
				}
				break;
			case 'r':
				newroot = strdup(optarg);
				break;
			case 'l':
				log_file = strdup(optarg);
				break;
			case 'd':
				daemon_enabled = 1;
				break;







|







1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
				if (lookup_ret != 0) {
					filed_print_help(stderr, 0, "Invalid username specified");

					return(1);
				}
				break;
			case 'r':
				filed_path_translate_set_root(newroot, &thread_options, optarg);
				break;
			case 'l':
				log_file = strdup(optarg);
				break;
			case 'd':
				daemon_enabled = 1;
				break;