Annotation of embedaddon/lighttpd/src/configfile.c, revision 1.1.1.1
1.1 misho 1: #include "server.h"
2: #include "log.h"
3: #include "stream.h"
4: #include "plugin.h"
5:
6: #include "configparser.h"
7: #include "configfile.h"
8: #include "proc_open.h"
9:
10: #include <sys/stat.h>
11:
12: #include <stdlib.h>
13: #include <fcntl.h>
14: #include <unistd.h>
15: #include <errno.h>
16: #include <string.h>
17: #include <stdio.h>
18: #include <ctype.h>
19: #include <limits.h>
20: #include <assert.h>
21:
22:
23: static int config_insert(server *srv) {
24: size_t i;
25: int ret = 0;
26: buffer *stat_cache_string;
27:
28: config_values_t cv[] = {
29: { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
30: { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
31: { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
32: { "server.chroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 */
33: { "server.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 */
34: { "server.groupname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 */
35: { "server.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 */
36: { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
37: { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
38: { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
39:
40: { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
41: { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
42: { "server.max-request-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
43: { "server.max-worker", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 13 */
44: { "server.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
45: { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 15 */
46: { "debug.log-condition-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 16 */
47: { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },/* 17 */
48: { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
49: { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
50:
51: { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
52: { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
53: { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
54: { "server.max-fds", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 23 */
55: #ifdef HAVE_LSTAT
56: { "server.follow-symlink", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */
57: #else
58: { "server.follow-symlink",
59: "Your system lacks lstat(). We can not differ symlinks from files."
60: "Please remove server.follow-symlinks from your config.",
61: T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 24 */
62: #endif
63: { "server.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 25 */
64: { "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */
65: { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
66: { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
67: { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
68:
69: { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
70:
71: { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
72: { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
73: { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
74: { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
75: { "debug.log-ssl-noise", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
76:
77: { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
78: { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
79: { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 38 */
80: { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 39 */
81:
82: { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 40 */
83: { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
84: { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 42 */
85: { "server.max-connections", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 43 */
86: { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
87: { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
88: { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 46 */
89: { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 47 */
90: { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 48 */
91: { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */
92: { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */
93: { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */
94: { "server.reject-expect-100-with-417", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 52 */
95: { "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */
96: { "server.defer-accept", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 54 */
97: { "server.breakagelog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 55 */
98: { "ssl.verifyclient.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 56 */
99: { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 57 */
100: { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 58 */
101: { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 59 */
102: { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */
103:
104: { "server.set-v6only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */
105: { "ssl.use-sslv3", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 62 */
106: { "ssl.dh-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 63 */
107: { "ssl.ec-curve", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 64 */
108: { "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 65 */
109: { "ssl.honor-cipher-order", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 66 */
110: { "ssl.empty-fragments", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 67 */
111:
112: { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
113: { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
114: { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
115: { "server.virtual-default-host", "load mod_simple_vhost and use simple-vhost.default-host instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
116: { "server.virtual-docroot", "load mod_simple_vhost and use simple-vhost.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
117: { "server.userid", "use server.username instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
118: { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
119: { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
120: { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
121:
122: { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
123: };
124:
125:
126: /* 0 */
127: cv[0].destination = srv->srvconf.bindhost;
128: cv[1].destination = srv->srvconf.errorlog_file;
129: cv[3].destination = srv->srvconf.changeroot;
130: cv[4].destination = srv->srvconf.username;
131: cv[5].destination = srv->srvconf.groupname;
132: cv[6].destination = &(srv->srvconf.port);
133:
134: cv[9].destination = srv->srvconf.modules;
135: cv[10].destination = srv->srvconf.event_handler;
136: cv[11].destination = srv->srvconf.pid_file;
137:
138: cv[13].destination = &(srv->srvconf.max_worker);
139: cv[23].destination = &(srv->srvconf.max_fds);
140: cv[37].destination = &(srv->srvconf.log_request_header_on_error);
141: cv[38].destination = &(srv->srvconf.log_state_handling);
142:
143: cv[40].destination = &(srv->srvconf.errorlog_use_syslog);
144:
145: stat_cache_string = buffer_init();
146: cv[42].destination = stat_cache_string;
147: cv[44].destination = srv->srvconf.network_backend;
148: cv[45].destination = srv->srvconf.upload_tempdirs;
149: cv[46].destination = &(srv->srvconf.enable_cores);
150:
151: cv[43].destination = &(srv->srvconf.max_conns);
152: cv[12].destination = &(srv->srvconf.max_request_size);
153: cv[52].destination = &(srv->srvconf.reject_expect_100_with_417);
154: cv[55].destination = srv->srvconf.breakagelog_file;
155:
156: srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
157:
158: assert(srv->config_storage);
159:
160: for (i = 0; i < srv->config_context->used; i++) {
161: specific_config *s;
162:
163: s = calloc(1, sizeof(specific_config));
164: assert(s);
165: s->document_root = buffer_init();
166: s->mimetypes = array_init();
167: s->server_name = buffer_init();
168: s->ssl_pemfile = buffer_init();
169: s->ssl_ca_file = buffer_init();
170: s->error_handler = buffer_init();
171: s->server_tag = buffer_init();
172: s->ssl_cipher_list = buffer_init();
173: s->ssl_dh_file = buffer_init();
174: s->ssl_ec_curve = buffer_init();
175: s->errorfile_prefix = buffer_init();
176: s->max_keep_alive_requests = 16;
177: s->max_keep_alive_idle = 5;
178: s->max_read_idle = 60;
179: s->max_write_idle = 360;
180: s->use_xattr = 0;
181: s->ssl_enabled = 0;
182: s->ssl_honor_cipher_order = 1;
183: s->ssl_empty_fragments = 0;
184: s->ssl_use_sslv2 = 0;
185: s->ssl_use_sslv3 = 1;
186: s->use_ipv6 = 0;
187: s->set_v6only = 1;
188: s->defer_accept = 0;
189: #ifdef HAVE_LSTAT
190: s->follow_symlink = 1;
191: #endif
192: s->kbytes_per_second = 0;
193: s->allow_http11 = 1;
194: s->etag_use_inode = 1;
195: s->etag_use_mtime = 1;
196: s->etag_use_size = 1;
197: s->range_requests = 1;
198: s->force_lowercase_filenames = (i == 0) ? 2 : 0; /* we wan't to detect later if user changed this for global section */
199: s->global_kbytes_per_second = 0;
200: s->global_bytes_per_second_cnt = 0;
201: s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
202: s->ssl_verifyclient = 0;
203: s->ssl_verifyclient_enforce = 1;
204: s->ssl_verifyclient_username = buffer_init();
205: s->ssl_verifyclient_depth = 9;
206: s->ssl_verifyclient_export_cert = 0;
207: s->ssl_disable_client_renegotiation = 1;
208:
209: cv[2].destination = s->errorfile_prefix;
210:
211: cv[7].destination = s->server_tag;
212: cv[8].destination = &(s->use_ipv6);
213: cv[61].destination = &(s->set_v6only);
214: cv[54].destination = &(s->defer_accept);
215:
216:
217: /* 13 max-worker */
218: cv[14].destination = s->document_root;
219: cv[15].destination = &(s->force_lowercase_filenames);
220: cv[16].destination = &(s->log_condition_handling);
221: cv[17].destination = &(s->max_keep_alive_requests);
222: cv[18].destination = s->server_name;
223: cv[19].destination = &(s->max_keep_alive_idle);
224: cv[20].destination = &(s->max_read_idle);
225: cv[21].destination = &(s->max_write_idle);
226: cv[22].destination = s->error_handler;
227: #ifdef HAVE_LSTAT
228: cv[24].destination = &(s->follow_symlink);
229: #endif
230: /* 23 -> max-fds */
231: cv[25].destination = &(s->global_kbytes_per_second);
232: cv[26].destination = &(s->kbytes_per_second);
233: cv[27].destination = &(s->use_xattr);
234: cv[28].destination = s->mimetypes;
235: cv[29].destination = s->ssl_pemfile;
236: cv[30].destination = &(s->ssl_enabled);
237:
238: cv[31].destination = &(s->log_file_not_found);
239: cv[32].destination = &(s->log_request_handling);
240: cv[33].destination = &(s->log_response_header);
241: cv[34].destination = &(s->log_request_header);
242: cv[35].destination = &(s->log_ssl_noise);
243: cv[53].destination = &(s->log_timeouts);
244:
245: cv[36].destination = &(s->allow_http11);
246: cv[39].destination = s->ssl_ca_file;
247: cv[41].destination = &(s->range_requests);
248:
249: cv[47].destination = s->ssl_cipher_list;
250: cv[48].destination = &(s->ssl_use_sslv2);
251: cv[62].destination = &(s->ssl_use_sslv3);
252: cv[63].destination = s->ssl_dh_file;
253: cv[64].destination = s->ssl_ec_curve;
254: cv[66].destination = &(s->ssl_honor_cipher_order);
255: cv[67].destination = &(s->ssl_empty_fragments);
256:
257: cv[49].destination = &(s->etag_use_inode);
258: cv[50].destination = &(s->etag_use_mtime);
259: cv[51].destination = &(s->etag_use_size);
260:
261: /* ssl.verify */
262: cv[56].destination = &(s->ssl_verifyclient);
263: cv[57].destination = &(s->ssl_verifyclient_enforce);
264: cv[58].destination = &(s->ssl_verifyclient_depth);
265: cv[59].destination = s->ssl_verifyclient_username;
266: cv[60].destination = &(s->ssl_verifyclient_export_cert);
267: cv[65].destination = &(s->ssl_disable_client_renegotiation);
268:
269: srv->config_storage[i] = s;
270:
271: if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
272: break;
273: }
274: }
275:
276: if (buffer_is_empty(stat_cache_string)) {
277: srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
278: } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
279: srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
280: #ifdef HAVE_FAM_H
281: } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("fam"))) {
282: srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_FAM;
283: #endif
284: } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
285: srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
286: } else {
287: log_error_write(srv, __FILE__, __LINE__, "sb",
288: "server.stat-cache-engine can be one of \"disable\", \"simple\","
289: #ifdef HAVE_FAM_H
290: " \"fam\","
291: #endif
292: " but not:", stat_cache_string);
293: ret = HANDLER_ERROR;
294: }
295:
296: buffer_free(stat_cache_string);
297:
298: return ret;
299:
300: }
301:
302:
303: #define PATCH(x) con->conf.x = s->x
304: int config_setup_connection(server *srv, connection *con) {
305: specific_config *s = srv->config_storage[0];
306:
307: PATCH(allow_http11);
308: PATCH(mimetypes);
309: PATCH(document_root);
310: PATCH(max_keep_alive_requests);
311: PATCH(max_keep_alive_idle);
312: PATCH(max_read_idle);
313: PATCH(max_write_idle);
314: PATCH(use_xattr);
315: PATCH(error_handler);
316: PATCH(errorfile_prefix);
317: #ifdef HAVE_LSTAT
318: PATCH(follow_symlink);
319: #endif
320: PATCH(server_tag);
321: PATCH(kbytes_per_second);
322: PATCH(global_kbytes_per_second);
323: PATCH(global_bytes_per_second_cnt);
324:
325: con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
326: buffer_copy_string_buffer(con->server_name, s->server_name);
327:
328: PATCH(log_request_header);
329: PATCH(log_response_header);
330: PATCH(log_request_handling);
331: PATCH(log_condition_handling);
332: PATCH(log_file_not_found);
333: PATCH(log_ssl_noise);
334: PATCH(log_timeouts);
335:
336: PATCH(range_requests);
337: PATCH(force_lowercase_filenames);
338: PATCH(ssl_enabled);
339:
340: PATCH(ssl_pemfile);
341: #ifdef USE_OPENSSL
342: PATCH(ssl_ctx);
343: #endif
344: PATCH(ssl_ca_file);
345: PATCH(ssl_cipher_list);
346: PATCH(ssl_dh_file);
347: PATCH(ssl_ec_curve);
348: PATCH(ssl_honor_cipher_order);
349: PATCH(ssl_empty_fragments);
350: PATCH(ssl_use_sslv2);
351: PATCH(ssl_use_sslv3);
352: PATCH(etag_use_inode);
353: PATCH(etag_use_mtime);
354: PATCH(etag_use_size);
355:
356: PATCH(ssl_verifyclient);
357: PATCH(ssl_verifyclient_enforce);
358: PATCH(ssl_verifyclient_depth);
359: PATCH(ssl_verifyclient_username);
360: PATCH(ssl_verifyclient_export_cert);
361: PATCH(ssl_disable_client_renegotiation);
362:
363: return 0;
364: }
365:
366: int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
367: size_t i, j;
368:
369: con->conditional_is_valid[comp] = 1;
370:
371: /* skip the first, the global context */
372: for (i = 1; i < srv->config_context->used; i++) {
373: data_config *dc = (data_config *)srv->config_context->data[i];
374: specific_config *s = srv->config_storage[i];
375:
376: /* condition didn't match */
377: if (!config_check_cond(srv, con, dc)) continue;
378:
379: /* merge config */
380: for (j = 0; j < dc->value->used; j++) {
381: data_unset *du = dc->value->data[j];
382:
383: if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
384: PATCH(document_root);
385: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
386: PATCH(range_requests);
387: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) {
388: PATCH(error_handler);
389: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) {
390: PATCH(errorfile_prefix);
391: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) {
392: PATCH(mimetypes);
393: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) {
394: PATCH(max_keep_alive_requests);
395: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) {
396: PATCH(max_keep_alive_idle);
397: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) {
398: PATCH(max_write_idle);
399: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) {
400: PATCH(max_read_idle);
401: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) {
402: PATCH(use_xattr);
403: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) {
404: PATCH(etag_use_inode);
405: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) {
406: PATCH(etag_use_mtime);
407: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) {
408: PATCH(etag_use_size);
409: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
410: PATCH(ssl_pemfile);
411: #ifdef USE_OPENSSL
412: PATCH(ssl_ctx);
413: #endif
414: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
415: PATCH(ssl_ca_file);
416: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) {
417: PATCH(ssl_honor_cipher_order);
418: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) {
419: PATCH(ssl_empty_fragments);
420: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
421: PATCH(ssl_use_sslv2);
422: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) {
423: PATCH(ssl_use_sslv3);
424: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
425: PATCH(ssl_cipher_list);
426: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
427: PATCH(ssl_enabled);
428: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) {
429: PATCH(ssl_dh_file);
430: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) {
431: PATCH(ssl_ec_curve);
432: #ifdef HAVE_LSTAT
433: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
434: PATCH(follow_symlink);
435: #endif
436: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
437: buffer_copy_string_buffer(con->server_name, s->server_name);
438: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {
439: PATCH(server_tag);
440: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) {
441: PATCH(kbytes_per_second);
442: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) {
443: PATCH(log_request_handling);
444: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) {
445: PATCH(log_request_header);
446: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) {
447: PATCH(log_response_header);
448: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
449: PATCH(log_condition_handling);
450: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
451: PATCH(log_file_not_found);
452: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) {
453: PATCH(log_ssl_noise);
454: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) {
455: PATCH(log_timeouts);
456: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
457: PATCH(allow_http11);
458: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
459: PATCH(force_lowercase_filenames);
460: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
461: PATCH(global_kbytes_per_second);
462: PATCH(global_bytes_per_second_cnt);
463: con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
464: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) {
465: PATCH(ssl_verifyclient);
466: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) {
467: PATCH(ssl_verifyclient_enforce);
468: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) {
469: PATCH(ssl_verifyclient_depth);
470: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) {
471: PATCH(ssl_verifyclient_username);
472: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) {
473: PATCH(ssl_verifyclient_export_cert);
474: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) {
475: PATCH(ssl_disable_client_renegotiation);
476: }
477: }
478: }
479:
480: con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) |
481: (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) |
482: (con->conf.etag_use_size ? ETAG_USE_SIZE : 0);
483:
484: return 0;
485: }
486: #undef PATCH
487:
488: typedef struct {
489: int foo;
490: int bar;
491:
492: const buffer *source;
493: const char *input;
494: size_t offset;
495: size_t size;
496:
497: int line_pos;
498: int line;
499:
500: int in_key;
501: int in_brace;
502: int in_cond;
503: } tokenizer_t;
504:
505: #if 0
506: static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
507: if (buffer_is_empty(basedir) ||
508: (fn[0] == '/' || fn[0] == '\\') ||
509: (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
510: t->file = buffer_init_string(fn);
511: } else {
512: t->file = buffer_init_buffer(basedir);
513: buffer_append_string(t->file, fn);
514: }
515:
516: if (0 != stream_open(&(t->s), t->file)) {
517: log_error_write(srv, __FILE__, __LINE__, "sbss",
518: "opening configfile ", t->file, "failed:", strerror(errno));
519: buffer_free(t->file);
520: return -1;
521: }
522:
523: t->input = t->s.start;
524: t->offset = 0;
525: t->size = t->s.size;
526: t->line = 1;
527: t->line_pos = 1;
528:
529: t->in_key = 1;
530: t->in_brace = 0;
531: t->in_cond = 0;
532: return 0;
533: }
534:
535: static int tokenizer_close(server *srv, tokenizer_t *t) {
536: UNUSED(srv);
537:
538: buffer_free(t->file);
539: return stream_close(&(t->s));
540: }
541: #endif
542: static int config_skip_newline(tokenizer_t *t) {
543: int skipped = 1;
544: assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
545: if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') {
546: skipped ++;
547: t->offset ++;
548: }
549: t->offset ++;
550: return skipped;
551: }
552:
553: static int config_skip_comment(tokenizer_t *t) {
554: int i;
555: assert(t->input[t->offset] == '#');
556: for (i = 1; t->input[t->offset + i] &&
557: (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
558: i++);
559: t->offset += i;
560: return i;
561: }
562:
563: static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
564: int tid = 0;
565: size_t i;
566:
567: for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
568: char c = t->input[t->offset];
569: const char *start = NULL;
570:
571: switch (c) {
572: case '=':
573: if (t->in_brace) {
574: if (t->input[t->offset + 1] == '>') {
575: t->offset += 2;
576:
577: buffer_copy_string_len(token, CONST_STR_LEN("=>"));
578:
579: tid = TK_ARRAY_ASSIGN;
580: } else {
581: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
582: "source:", t->source,
583: "line:", t->line, "pos:", t->line_pos,
584: "use => for assignments in arrays");
585: return -1;
586: }
587: } else if (t->in_cond) {
588: if (t->input[t->offset + 1] == '=') {
589: t->offset += 2;
590:
591: buffer_copy_string_len(token, CONST_STR_LEN("=="));
592:
593: tid = TK_EQ;
594: } else if (t->input[t->offset + 1] == '~') {
595: t->offset += 2;
596:
597: buffer_copy_string_len(token, CONST_STR_LEN("=~"));
598:
599: tid = TK_MATCH;
600: } else {
601: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
602: "source:", t->source,
603: "line:", t->line, "pos:", t->line_pos,
604: "only =~ and == are allowed in the condition");
605: return -1;
606: }
607: t->in_key = 1;
608: t->in_cond = 0;
609: } else if (t->in_key) {
610: tid = TK_ASSIGN;
611:
612: buffer_copy_string_len(token, t->input + t->offset, 1);
613:
614: t->offset++;
615: t->line_pos++;
616: } else {
617: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
618: "source:", t->source,
619: "line:", t->line, "pos:", t->line_pos,
620: "unexpected equal-sign: =");
621: return -1;
622: }
623:
624: break;
625: case '!':
626: if (t->in_cond) {
627: if (t->input[t->offset + 1] == '=') {
628: t->offset += 2;
629:
630: buffer_copy_string_len(token, CONST_STR_LEN("!="));
631:
632: tid = TK_NE;
633: } else if (t->input[t->offset + 1] == '~') {
634: t->offset += 2;
635:
636: buffer_copy_string_len(token, CONST_STR_LEN("!~"));
637:
638: tid = TK_NOMATCH;
639: } else {
640: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
641: "source:", t->source,
642: "line:", t->line, "pos:", t->line_pos,
643: "only !~ and != are allowed in the condition");
644: return -1;
645: }
646: t->in_key = 1;
647: t->in_cond = 0;
648: } else {
649: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
650: "source:", t->source,
651: "line:", t->line, "pos:", t->line_pos,
652: "unexpected exclamation-marks: !");
653: return -1;
654: }
655:
656: break;
657: case '\t':
658: case ' ':
659: t->offset++;
660: t->line_pos++;
661: break;
662: case '\n':
663: case '\r':
664: if (t->in_brace == 0) {
665: int done = 0;
666: while (!done && t->offset < t->size) {
667: switch (t->input[t->offset]) {
668: case '\r':
669: case '\n':
670: config_skip_newline(t);
671: t->line_pos = 1;
672: t->line++;
673: break;
674:
675: case '#':
676: t->line_pos += config_skip_comment(t);
677: break;
678:
679: case '\t':
680: case ' ':
681: t->offset++;
682: t->line_pos++;
683: break;
684:
685: default:
686: done = 1;
687: }
688: }
689: t->in_key = 1;
690: tid = TK_EOL;
691: buffer_copy_string_len(token, CONST_STR_LEN("(EOL)"));
692: } else {
693: config_skip_newline(t);
694: t->line_pos = 1;
695: t->line++;
696: }
697: break;
698: case ',':
699: if (t->in_brace > 0) {
700: tid = TK_COMMA;
701:
702: buffer_copy_string_len(token, CONST_STR_LEN("(COMMA)"));
703: }
704:
705: t->offset++;
706: t->line_pos++;
707: break;
708: case '"':
709: /* search for the terminating " */
710: start = t->input + t->offset + 1;
711: buffer_copy_string_len(token, CONST_STR_LEN(""));
712:
713: for (i = 1; t->input[t->offset + i]; i++) {
714: if (t->input[t->offset + i] == '\\' &&
715: t->input[t->offset + i + 1] == '"') {
716:
717: buffer_append_string_len(token, start, t->input + t->offset + i - start);
718:
719: start = t->input + t->offset + i + 1;
720:
721: /* skip the " */
722: i++;
723: continue;
724: }
725:
726:
727: if (t->input[t->offset + i] == '"') {
728: tid = TK_STRING;
729:
730: buffer_append_string_len(token, start, t->input + t->offset + i - start);
731:
732: break;
733: }
734: }
735:
736: if (t->input[t->offset + i] == '\0') {
737: /* ERROR */
738:
739: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
740: "source:", t->source,
741: "line:", t->line, "pos:", t->line_pos,
742: "missing closing quote");
743:
744: return -1;
745: }
746:
747: t->offset += i + 1;
748: t->line_pos += i + 1;
749:
750: break;
751: case '(':
752: t->offset++;
753: t->in_brace++;
754:
755: tid = TK_LPARAN;
756:
757: buffer_copy_string_len(token, CONST_STR_LEN("("));
758: break;
759: case ')':
760: t->offset++;
761: t->in_brace--;
762:
763: tid = TK_RPARAN;
764:
765: buffer_copy_string_len(token, CONST_STR_LEN(")"));
766: break;
767: case '$':
768: t->offset++;
769:
770: tid = TK_DOLLAR;
771: t->in_cond = 1;
772: t->in_key = 0;
773:
774: buffer_copy_string_len(token, CONST_STR_LEN("$"));
775:
776: break;
777:
778: case '+':
779: if (t->input[t->offset + 1] == '=') {
780: t->offset += 2;
781: buffer_copy_string_len(token, CONST_STR_LEN("+="));
782: tid = TK_APPEND;
783: } else {
784: t->offset++;
785: tid = TK_PLUS;
786: buffer_copy_string_len(token, CONST_STR_LEN("+"));
787: }
788: break;
789:
790: case '{':
791: t->offset++;
792:
793: tid = TK_LCURLY;
794:
795: buffer_copy_string_len(token, CONST_STR_LEN("{"));
796:
797: break;
798:
799: case '}':
800: t->offset++;
801:
802: tid = TK_RCURLY;
803:
804: buffer_copy_string_len(token, CONST_STR_LEN("}"));
805:
806: break;
807:
808: case '[':
809: t->offset++;
810:
811: tid = TK_LBRACKET;
812:
813: buffer_copy_string_len(token, CONST_STR_LEN("["));
814:
815: break;
816:
817: case ']':
818: t->offset++;
819:
820: tid = TK_RBRACKET;
821:
822: buffer_copy_string_len(token, CONST_STR_LEN("]"));
823:
824: break;
825: case '#':
826: t->line_pos += config_skip_comment(t);
827:
828: break;
829: default:
830: if (t->in_cond) {
831: for (i = 0; t->input[t->offset + i] &&
832: (isalpha((unsigned char)t->input[t->offset + i])
833: ); i++);
834:
835: if (i && t->input[t->offset + i]) {
836: tid = TK_SRVVARNAME;
837: buffer_copy_string_len(token, t->input + t->offset, i);
838:
839: t->offset += i;
840: t->line_pos += i;
841: } else {
842: /* ERROR */
843: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
844: "source:", t->source,
845: "line:", t->line, "pos:", t->line_pos,
846: "invalid character in condition");
847: return -1;
848: }
849: } else if (isdigit((unsigned char)c)) {
850: /* take all digits */
851: for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
852:
853: /* was there it least a digit ? */
854: if (i) {
855: tid = TK_INTEGER;
856:
857: buffer_copy_string_len(token, t->input + t->offset, i);
858:
859: t->offset += i;
860: t->line_pos += i;
861: }
862: } else {
863: /* the key might consist of [-.0-9a-z] */
864: for (i = 0; t->input[t->offset + i] &&
865: (isalnum((unsigned char)t->input[t->offset + i]) ||
866: t->input[t->offset + i] == '.' ||
867: t->input[t->offset + i] == '_' || /* for env.* */
868: t->input[t->offset + i] == '-'
869: ); i++);
870:
871: if (i && t->input[t->offset + i]) {
872: buffer_copy_string_len(token, t->input + t->offset, i);
873:
874: if (strcmp(token->ptr, "include") == 0) {
875: tid = TK_INCLUDE;
876: } else if (strcmp(token->ptr, "include_shell") == 0) {
877: tid = TK_INCLUDE_SHELL;
878: } else if (strcmp(token->ptr, "global") == 0) {
879: tid = TK_GLOBAL;
880: } else if (strcmp(token->ptr, "else") == 0) {
881: tid = TK_ELSE;
882: } else {
883: tid = TK_LKEY;
884: }
885:
886: t->offset += i;
887: t->line_pos += i;
888: } else {
889: /* ERROR */
890: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
891: "source:", t->source,
892: "line:", t->line, "pos:", t->line_pos,
893: "invalid character in variable name");
894: return -1;
895: }
896: }
897: break;
898: }
899: }
900:
901: if (tid) {
902: *token_id = tid;
903: #if 0
904: log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
905: "source:", t->source,
906: "line:", t->line, "pos:", t->line_pos,
907: token, token->used - 1, tid);
908: #endif
909:
910: return 1;
911: } else if (t->offset < t->size) {
912: fprintf(stderr, "%s.%d: %d, %s\n",
913: __FILE__, __LINE__,
914: tid, token->ptr);
915: }
916: return 0;
917: }
918:
919: static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
920: void *pParser;
921: int token_id;
922: buffer *token, *lasttoken;
923: int ret;
924:
925: pParser = configparserAlloc( malloc );
926: lasttoken = buffer_init();
927: token = buffer_init();
928: while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
929: buffer_copy_string_buffer(lasttoken, token);
930: configparser(pParser, token_id, token, context);
931:
932: token = buffer_init();
933: }
934: buffer_free(token);
935:
936: if (ret != -1 && context->ok) {
937: /* add an EOL at EOF, better than say sorry */
938: configparser(pParser, TK_EOL, buffer_init_string("(EOL)"), context);
939: if (context->ok) {
940: configparser(pParser, 0, NULL, context);
941: }
942: }
943: configparserFree(pParser, free);
944:
945: if (ret == -1) {
946: log_error_write(srv, __FILE__, __LINE__, "sb",
947: "configfile parser failed at:", lasttoken);
948: } else if (context->ok == 0) {
949: log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
950: "source:", t->source,
951: "line:", t->line, "pos:", t->line_pos,
952: "parser failed somehow near here:", lasttoken);
953: ret = -1;
954: }
955: buffer_free(lasttoken);
956:
957: return ret == -1 ? -1 : 0;
958: }
959:
960: static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
961:
962: t->source = source;
963: t->input = input;
964: t->size = size;
965: t->offset = 0;
966: t->line = 1;
967: t->line_pos = 1;
968:
969: t->in_key = 1;
970: t->in_brace = 0;
971: t->in_cond = 0;
972: return 0;
973: }
974:
975: int config_parse_file(server *srv, config_t *context, const char *fn) {
976: tokenizer_t t;
977: stream s;
978: int ret;
979: buffer *filename;
980:
981: if (buffer_is_empty(context->basedir) ||
982: (fn[0] == '/' || fn[0] == '\\') ||
983: (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
984: filename = buffer_init_string(fn);
985: } else {
986: filename = buffer_init_buffer(context->basedir);
987: buffer_append_string(filename, fn);
988: }
989:
990: if (0 != stream_open(&s, filename)) {
991: if (s.size == 0) {
992: /* the file was empty, nothing to parse */
993: ret = 0;
994: } else {
995: log_error_write(srv, __FILE__, __LINE__, "sbss",
996: "opening configfile ", filename, "failed:", strerror(errno));
997: ret = -1;
998: }
999: } else {
1000: tokenizer_init(&t, filename, s.start, s.size);
1001: ret = config_parse(srv, context, &t);
1002: }
1003:
1004: stream_close(&s);
1005: buffer_free(filename);
1006: return ret;
1007: }
1008:
1009: static char* getCWD(void) {
1010: char *s, *s1;
1011: size_t len;
1012: #ifdef PATH_MAX
1013: len = PATH_MAX;
1014: #else
1015: len = 4096;
1016: #endif
1017:
1018: s = malloc(len);
1019: if (!s) return NULL;
1020: while (NULL == getcwd(s, len)) {
1021: if (errno != ERANGE || SSIZE_MAX - len < len) return NULL;
1022: len *= 2;
1023: s1 = realloc(s, len);
1024: if (!s1) {
1025: free(s);
1026: return NULL;
1027: }
1028: s = s1;
1029: }
1030: return s;
1031: }
1032:
1033: int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
1034: tokenizer_t t;
1035: int ret;
1036: buffer *source;
1037: buffer *out;
1038: char *oldpwd;
1039:
1040: if (NULL == (oldpwd = getCWD())) {
1041: log_error_write(srv, __FILE__, __LINE__, "s",
1042: "cannot get cwd", strerror(errno));
1043: return -1;
1044: }
1045:
1046: source = buffer_init_string(cmd);
1047: out = buffer_init();
1048:
1049: if (!buffer_is_empty(context->basedir)) {
1050: chdir(context->basedir->ptr);
1051: }
1052:
1053: if (0 != proc_open_buffer(cmd, NULL, out, NULL)) {
1054: log_error_write(srv, __FILE__, __LINE__, "sbss",
1055: "opening", source, "failed:", strerror(errno));
1056: ret = -1;
1057: } else {
1058: tokenizer_init(&t, source, out->ptr, out->used);
1059: ret = config_parse(srv, context, &t);
1060: }
1061:
1062: buffer_free(source);
1063: buffer_free(out);
1064: chdir(oldpwd);
1065: free(oldpwd);
1066: return ret;
1067: }
1068:
1069: static void context_init(server *srv, config_t *context) {
1070: context->srv = srv;
1071: context->ok = 1;
1072: context->configs_stack = array_init();
1073: context->configs_stack->is_weakref = 1;
1074: context->basedir = buffer_init();
1075: }
1076:
1077: static void context_free(config_t *context) {
1078: array_free(context->configs_stack);
1079: buffer_free(context->basedir);
1080: }
1081:
1082: int config_read(server *srv, const char *fn) {
1083: config_t context;
1084: data_config *dc;
1085: data_integer *dpid;
1086: data_string *dcwd;
1087: int ret;
1088: char *pos;
1089: data_array *modules;
1090:
1091: context_init(srv, &context);
1092: context.all_configs = srv->config_context;
1093:
1094: #ifdef __WIN32
1095: pos = strrchr(fn, '\\');
1096: #else
1097: pos = strrchr(fn, '/');
1098: #endif
1099: if (pos) {
1100: buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
1101: fn = pos + 1;
1102: }
1103:
1104: dc = data_config_init();
1105: buffer_copy_string_len(dc->key, CONST_STR_LEN("global"));
1106:
1107: assert(context.all_configs->used == 0);
1108: dc->context_ndx = context.all_configs->used;
1109: array_insert_unique(context.all_configs, (data_unset *)dc);
1110: context.current = dc;
1111:
1112: /* default context */
1113: srv->config = dc->value;
1114: dpid = data_integer_init();
1115: dpid->value = getpid();
1116: buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID"));
1117: array_insert_unique(srv->config, (data_unset *)dpid);
1118:
1119: dcwd = data_string_init();
1120: buffer_prepare_copy(dcwd->value, 1024);
1121: if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
1122: dcwd->value->used = strlen(dcwd->value->ptr) + 1;
1123: buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD"));
1124: array_insert_unique(srv->config, (data_unset *)dcwd);
1125: }
1126:
1127: ret = config_parse_file(srv, &context, fn);
1128:
1129: /* remains nothing if parser is ok */
1130: assert(!(0 == ret && context.ok && 0 != context.configs_stack->used));
1131: context_free(&context);
1132:
1133: if (0 != ret) {
1134: return ret;
1135: }
1136:
1137: if (NULL != (dc = (data_config *)array_get_element(srv->config_context, "global"))) {
1138: srv->config = dc->value;
1139: } else {
1140: return -1;
1141: }
1142:
1143: if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
1144: data_string *ds;
1145: data_array *prepends;
1146:
1147: if (modules->type != TYPE_ARRAY) {
1148: fprintf(stderr, "server.modules must be an array");
1149: return -1;
1150: }
1151:
1152: prepends = data_array_init();
1153:
1154: /* prepend default modules */
1155: if (NULL == array_get_element(modules->value, "mod_indexfile")) {
1156: ds = data_string_init();
1157: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
1158: array_insert_unique(prepends->value, (data_unset *)ds);
1159: }
1160:
1161: prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules);
1162: buffer_copy_string_buffer(prepends->key, modules->key);
1163: array_replace(srv->config, (data_unset *)prepends);
1164: modules->free((data_unset *)modules);
1165: modules = prepends;
1166:
1167: /* append default modules */
1168: if (NULL == array_get_element(modules->value, "mod_dirlisting")) {
1169: ds = data_string_init();
1170: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
1171: array_insert_unique(modules->value, (data_unset *)ds);
1172: }
1173:
1174: if (NULL == array_get_element(modules->value, "mod_staticfile")) {
1175: ds = data_string_init();
1176: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
1177: array_insert_unique(modules->value, (data_unset *)ds);
1178: }
1179: } else {
1180: data_string *ds;
1181:
1182: modules = data_array_init();
1183:
1184: /* server.modules is not set */
1185: ds = data_string_init();
1186: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
1187: array_insert_unique(modules->value, (data_unset *)ds);
1188:
1189: ds = data_string_init();
1190: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
1191: array_insert_unique(modules->value, (data_unset *)ds);
1192:
1193: ds = data_string_init();
1194: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
1195: array_insert_unique(modules->value, (data_unset *)ds);
1196:
1197: buffer_copy_string_len(modules->key, CONST_STR_LEN("server.modules"));
1198: array_insert_unique(srv->config, (data_unset *)modules);
1199: }
1200:
1201:
1202: if (0 != config_insert(srv)) {
1203: return -1;
1204: }
1205:
1206: return 0;
1207: }
1208:
1209: int config_set_defaults(server *srv) {
1210: size_t i;
1211: specific_config *s = srv->config_storage[0];
1212: struct stat st1, st2;
1213:
1214: struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
1215: {
1216: /* - epoll is most reliable
1217: * - select works everywhere
1218: */
1219: #ifdef USE_LINUX_EPOLL
1220: { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
1221: #endif
1222: #ifdef USE_POLL
1223: { FDEVENT_HANDLER_POLL, "poll" },
1224: #endif
1225: #ifdef USE_SELECT
1226: { FDEVENT_HANDLER_SELECT, "select" },
1227: #endif
1228: #ifdef USE_LIBEV
1229: { FDEVENT_HANDLER_LIBEV, "libev" },
1230: #endif
1231: #ifdef USE_SOLARIS_DEVPOLL
1232: { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
1233: #endif
1234: #ifdef USE_SOLARIS_PORT
1235: { FDEVENT_HANDLER_SOLARIS_PORT, "solaris-eventports" },
1236: #endif
1237: #ifdef USE_FREEBSD_KQUEUE
1238: { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
1239: { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
1240: #endif
1241: { FDEVENT_HANDLER_UNSET, NULL }
1242: };
1243:
1244: if (!buffer_is_empty(srv->srvconf.changeroot)) {
1245: if (-1 == stat(srv->srvconf.changeroot->ptr, &st1)) {
1246: log_error_write(srv, __FILE__, __LINE__, "sb",
1247: "server.chroot doesn't exist:", srv->srvconf.changeroot);
1248: return -1;
1249: }
1250: if (!S_ISDIR(st1.st_mode)) {
1251: log_error_write(srv, __FILE__, __LINE__, "sb",
1252: "server.chroot isn't a directory:", srv->srvconf.changeroot);
1253: return -1;
1254: }
1255: }
1256:
1257: if (buffer_is_empty(s->document_root)) {
1258: log_error_write(srv, __FILE__, __LINE__, "s",
1259: "a default document-root has to be set");
1260:
1261: return -1;
1262: }
1263:
1264: buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
1265:
1266: buffer_to_lower(srv->tmp_buf);
1267:
1268: if (2 == s->force_lowercase_filenames) { /* user didn't configure it in global section? */
1269: s->force_lowercase_filenames = 0; /* default to 0 */
1270:
1271: if (0 == stat(srv->tmp_buf->ptr, &st1)) {
1272: int is_lower = 0;
1273:
1274: is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
1275:
1276: /* lower-case existed, check upper-case */
1277: buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
1278:
1279: buffer_to_upper(srv->tmp_buf);
1280:
1281: /* we have to handle the special case that upper and lower-casing results in the same filename
1282: * as in server.document-root = "/" or "/12345/" */
1283:
1284: if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
1285: /* lower-casing and upper-casing didn't result in
1286: * an other filename, no need to stat(),
1287: * just assume it is case-sensitive. */
1288:
1289: s->force_lowercase_filenames = 0;
1290: } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
1291:
1292: /* upper case exists too, doesn't the FS handle this ? */
1293:
1294: /* upper and lower have the same inode -> case-insensitve FS */
1295:
1296: if (st1.st_ino == st2.st_ino) {
1297: /* upper and lower have the same inode -> case-insensitve FS */
1298:
1299: s->force_lowercase_filenames = 1;
1300: }
1301: }
1302: }
1303: }
1304:
1305: if (srv->srvconf.port == 0) {
1306: srv->srvconf.port = s->ssl_enabled ? 443 : 80;
1307: }
1308:
1309: if (srv->srvconf.event_handler->used == 0) {
1310: /* choose a good default
1311: *
1312: * the event_handler list is sorted by 'goodness'
1313: * taking the first available should be the best solution
1314: */
1315: srv->event_handler = event_handlers[0].et;
1316:
1317: if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
1318: log_error_write(srv, __FILE__, __LINE__, "s",
1319: "sorry, there is no event handler for this system");
1320:
1321: return -1;
1322: }
1323: } else {
1324: /*
1325: * User override
1326: */
1327:
1328: for (i = 0; event_handlers[i].name; i++) {
1329: if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
1330: srv->event_handler = event_handlers[i].et;
1331: break;
1332: }
1333: }
1334:
1335: if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
1336: log_error_write(srv, __FILE__, __LINE__, "sb",
1337: "the selected event-handler in unknown or not supported:",
1338: srv->srvconf.event_handler );
1339:
1340: return -1;
1341: }
1342: }
1343:
1344: if (s->ssl_enabled) {
1345: if (buffer_is_empty(s->ssl_pemfile)) {
1346: /* PEM file is require */
1347:
1348: log_error_write(srv, __FILE__, __LINE__, "s",
1349: "ssl.pemfile has to be set");
1350: return -1;
1351: }
1352:
1353: #ifndef USE_OPENSSL
1354: log_error_write(srv, __FILE__, __LINE__, "s",
1355: "ssl support is missing, recompile with --with-openssl");
1356:
1357: return -1;
1358: #endif
1359: }
1360:
1361: return 0;
1362: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>