Annotation of embedaddon/lighttpd/src/configfile.c, revision 1.1.1.2
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:
1.1.1.2 ! misho 158: force_assert(srv->config_storage);
1.1 misho 159:
160: for (i = 0; i < srv->config_context->used; i++) {
161: specific_config *s;
162:
163: s = calloc(1, sizeof(specific_config));
1.1.1.2 ! misho 164: force_assert(s);
1.1 misho 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
1.1.1.2 ! misho 342: PATCH(ssl_pemfile_x509);
! 343: PATCH(ssl_pemfile_pkey);
1.1 misho 344: #endif
345: PATCH(ssl_ca_file);
1.1.1.2 ! misho 346: #ifdef USE_OPENSSL
! 347: PATCH(ssl_ca_file_cert_names);
! 348: #endif
1.1 misho 349: PATCH(ssl_cipher_list);
350: PATCH(ssl_dh_file);
351: PATCH(ssl_ec_curve);
352: PATCH(ssl_honor_cipher_order);
353: PATCH(ssl_empty_fragments);
354: PATCH(ssl_use_sslv2);
355: PATCH(ssl_use_sslv3);
356: PATCH(etag_use_inode);
357: PATCH(etag_use_mtime);
358: PATCH(etag_use_size);
359:
360: PATCH(ssl_verifyclient);
361: PATCH(ssl_verifyclient_enforce);
362: PATCH(ssl_verifyclient_depth);
363: PATCH(ssl_verifyclient_username);
364: PATCH(ssl_verifyclient_export_cert);
365: PATCH(ssl_disable_client_renegotiation);
366:
367: return 0;
368: }
369:
370: int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
371: size_t i, j;
372:
373: con->conditional_is_valid[comp] = 1;
374:
375: /* skip the first, the global context */
376: for (i = 1; i < srv->config_context->used; i++) {
377: data_config *dc = (data_config *)srv->config_context->data[i];
378: specific_config *s = srv->config_storage[i];
379:
380: /* condition didn't match */
381: if (!config_check_cond(srv, con, dc)) continue;
382:
383: /* merge config */
384: for (j = 0; j < dc->value->used; j++) {
385: data_unset *du = dc->value->data[j];
386:
387: if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
388: PATCH(document_root);
389: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
390: PATCH(range_requests);
391: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) {
392: PATCH(error_handler);
393: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) {
394: PATCH(errorfile_prefix);
395: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) {
396: PATCH(mimetypes);
397: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) {
398: PATCH(max_keep_alive_requests);
399: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) {
400: PATCH(max_keep_alive_idle);
401: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) {
402: PATCH(max_write_idle);
403: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) {
404: PATCH(max_read_idle);
405: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) {
406: PATCH(use_xattr);
407: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) {
408: PATCH(etag_use_inode);
409: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) {
410: PATCH(etag_use_mtime);
411: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) {
412: PATCH(etag_use_size);
413: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
414: PATCH(ssl_pemfile);
415: #ifdef USE_OPENSSL
1.1.1.2 ! misho 416: PATCH(ssl_pemfile_x509);
! 417: PATCH(ssl_pemfile_pkey);
1.1 misho 418: #endif
419: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
420: PATCH(ssl_ca_file);
1.1.1.2 ! misho 421: #ifdef USE_OPENSSL
! 422: PATCH(ssl_ca_file_cert_names);
! 423: #endif
1.1 misho 424: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) {
425: PATCH(ssl_honor_cipher_order);
426: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) {
427: PATCH(ssl_empty_fragments);
428: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
429: PATCH(ssl_use_sslv2);
430: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) {
431: PATCH(ssl_use_sslv3);
432: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
433: PATCH(ssl_cipher_list);
434: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
435: PATCH(ssl_enabled);
436: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) {
437: PATCH(ssl_dh_file);
438: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) {
439: PATCH(ssl_ec_curve);
440: #ifdef HAVE_LSTAT
441: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
442: PATCH(follow_symlink);
443: #endif
444: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
445: buffer_copy_string_buffer(con->server_name, s->server_name);
446: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {
447: PATCH(server_tag);
448: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) {
449: PATCH(kbytes_per_second);
450: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) {
451: PATCH(log_request_handling);
452: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) {
453: PATCH(log_request_header);
454: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) {
455: PATCH(log_response_header);
456: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
457: PATCH(log_condition_handling);
458: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
459: PATCH(log_file_not_found);
460: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) {
461: PATCH(log_ssl_noise);
462: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) {
463: PATCH(log_timeouts);
464: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
465: PATCH(allow_http11);
466: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
467: PATCH(force_lowercase_filenames);
468: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
469: PATCH(global_kbytes_per_second);
470: PATCH(global_bytes_per_second_cnt);
471: con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
472: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) {
473: PATCH(ssl_verifyclient);
474: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) {
475: PATCH(ssl_verifyclient_enforce);
476: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) {
477: PATCH(ssl_verifyclient_depth);
478: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) {
479: PATCH(ssl_verifyclient_username);
480: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) {
481: PATCH(ssl_verifyclient_export_cert);
482: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) {
483: PATCH(ssl_disable_client_renegotiation);
484: }
485: }
486: }
487:
488: con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) |
489: (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) |
490: (con->conf.etag_use_size ? ETAG_USE_SIZE : 0);
491:
492: return 0;
493: }
494: #undef PATCH
495:
496: typedef struct {
497: int foo;
498: int bar;
499:
500: const buffer *source;
501: const char *input;
502: size_t offset;
503: size_t size;
504:
505: int line_pos;
506: int line;
507:
508: int in_key;
509: int in_brace;
510: int in_cond;
511: } tokenizer_t;
512:
513: #if 0
514: static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
515: if (buffer_is_empty(basedir) ||
516: (fn[0] == '/' || fn[0] == '\\') ||
517: (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
518: t->file = buffer_init_string(fn);
519: } else {
520: t->file = buffer_init_buffer(basedir);
521: buffer_append_string(t->file, fn);
522: }
523:
524: if (0 != stream_open(&(t->s), t->file)) {
525: log_error_write(srv, __FILE__, __LINE__, "sbss",
526: "opening configfile ", t->file, "failed:", strerror(errno));
527: buffer_free(t->file);
528: return -1;
529: }
530:
531: t->input = t->s.start;
532: t->offset = 0;
533: t->size = t->s.size;
534: t->line = 1;
535: t->line_pos = 1;
536:
537: t->in_key = 1;
538: t->in_brace = 0;
539: t->in_cond = 0;
540: return 0;
541: }
542:
543: static int tokenizer_close(server *srv, tokenizer_t *t) {
544: UNUSED(srv);
545:
546: buffer_free(t->file);
547: return stream_close(&(t->s));
548: }
549: #endif
550: static int config_skip_newline(tokenizer_t *t) {
551: int skipped = 1;
1.1.1.2 ! misho 552: force_assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
1.1 misho 553: if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') {
554: skipped ++;
555: t->offset ++;
556: }
557: t->offset ++;
558: return skipped;
559: }
560:
561: static int config_skip_comment(tokenizer_t *t) {
562: int i;
1.1.1.2 ! misho 563: force_assert(t->input[t->offset] == '#');
1.1 misho 564: for (i = 1; t->input[t->offset + i] &&
565: (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
566: i++);
567: t->offset += i;
568: return i;
569: }
570:
571: static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
572: int tid = 0;
573: size_t i;
574:
575: for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
576: char c = t->input[t->offset];
577: const char *start = NULL;
578:
579: switch (c) {
580: case '=':
581: if (t->in_brace) {
582: if (t->input[t->offset + 1] == '>') {
583: t->offset += 2;
584:
585: buffer_copy_string_len(token, CONST_STR_LEN("=>"));
586:
587: tid = TK_ARRAY_ASSIGN;
588: } else {
589: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
590: "source:", t->source,
591: "line:", t->line, "pos:", t->line_pos,
592: "use => for assignments in arrays");
593: return -1;
594: }
595: } else if (t->in_cond) {
596: if (t->input[t->offset + 1] == '=') {
597: t->offset += 2;
598:
599: buffer_copy_string_len(token, CONST_STR_LEN("=="));
600:
601: tid = TK_EQ;
602: } else if (t->input[t->offset + 1] == '~') {
603: t->offset += 2;
604:
605: buffer_copy_string_len(token, CONST_STR_LEN("=~"));
606:
607: tid = TK_MATCH;
608: } else {
609: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
610: "source:", t->source,
611: "line:", t->line, "pos:", t->line_pos,
612: "only =~ and == are allowed in the condition");
613: return -1;
614: }
615: t->in_key = 1;
616: t->in_cond = 0;
617: } else if (t->in_key) {
618: tid = TK_ASSIGN;
619:
620: buffer_copy_string_len(token, t->input + t->offset, 1);
621:
622: t->offset++;
623: t->line_pos++;
624: } else {
625: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
626: "source:", t->source,
627: "line:", t->line, "pos:", t->line_pos,
628: "unexpected equal-sign: =");
629: return -1;
630: }
631:
632: break;
633: case '!':
634: if (t->in_cond) {
635: if (t->input[t->offset + 1] == '=') {
636: t->offset += 2;
637:
638: buffer_copy_string_len(token, CONST_STR_LEN("!="));
639:
640: tid = TK_NE;
641: } else if (t->input[t->offset + 1] == '~') {
642: t->offset += 2;
643:
644: buffer_copy_string_len(token, CONST_STR_LEN("!~"));
645:
646: tid = TK_NOMATCH;
647: } else {
648: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
649: "source:", t->source,
650: "line:", t->line, "pos:", t->line_pos,
651: "only !~ and != are allowed in the condition");
652: return -1;
653: }
654: t->in_key = 1;
655: t->in_cond = 0;
656: } else {
657: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
658: "source:", t->source,
659: "line:", t->line, "pos:", t->line_pos,
660: "unexpected exclamation-marks: !");
661: return -1;
662: }
663:
664: break;
665: case '\t':
666: case ' ':
667: t->offset++;
668: t->line_pos++;
669: break;
670: case '\n':
671: case '\r':
672: if (t->in_brace == 0) {
673: int done = 0;
674: while (!done && t->offset < t->size) {
675: switch (t->input[t->offset]) {
676: case '\r':
677: case '\n':
678: config_skip_newline(t);
679: t->line_pos = 1;
680: t->line++;
681: break;
682:
683: case '#':
684: t->line_pos += config_skip_comment(t);
685: break;
686:
687: case '\t':
688: case ' ':
689: t->offset++;
690: t->line_pos++;
691: break;
692:
693: default:
694: done = 1;
695: }
696: }
697: t->in_key = 1;
698: tid = TK_EOL;
699: buffer_copy_string_len(token, CONST_STR_LEN("(EOL)"));
700: } else {
701: config_skip_newline(t);
702: t->line_pos = 1;
703: t->line++;
704: }
705: break;
706: case ',':
707: if (t->in_brace > 0) {
708: tid = TK_COMMA;
709:
710: buffer_copy_string_len(token, CONST_STR_LEN("(COMMA)"));
711: }
712:
713: t->offset++;
714: t->line_pos++;
715: break;
716: case '"':
717: /* search for the terminating " */
718: start = t->input + t->offset + 1;
719: buffer_copy_string_len(token, CONST_STR_LEN(""));
720:
721: for (i = 1; t->input[t->offset + i]; i++) {
722: if (t->input[t->offset + i] == '\\' &&
723: t->input[t->offset + i + 1] == '"') {
724:
725: buffer_append_string_len(token, start, t->input + t->offset + i - start);
726:
727: start = t->input + t->offset + i + 1;
728:
729: /* skip the " */
730: i++;
731: continue;
732: }
733:
734:
735: if (t->input[t->offset + i] == '"') {
736: tid = TK_STRING;
737:
738: buffer_append_string_len(token, start, t->input + t->offset + i - start);
739:
740: break;
741: }
742: }
743:
744: if (t->input[t->offset + i] == '\0') {
745: /* ERROR */
746:
747: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
748: "source:", t->source,
749: "line:", t->line, "pos:", t->line_pos,
750: "missing closing quote");
751:
752: return -1;
753: }
754:
755: t->offset += i + 1;
756: t->line_pos += i + 1;
757:
758: break;
759: case '(':
760: t->offset++;
761: t->in_brace++;
762:
763: tid = TK_LPARAN;
764:
765: buffer_copy_string_len(token, CONST_STR_LEN("("));
766: break;
767: case ')':
768: t->offset++;
769: t->in_brace--;
770:
771: tid = TK_RPARAN;
772:
773: buffer_copy_string_len(token, CONST_STR_LEN(")"));
774: break;
775: case '$':
776: t->offset++;
777:
778: tid = TK_DOLLAR;
779: t->in_cond = 1;
780: t->in_key = 0;
781:
782: buffer_copy_string_len(token, CONST_STR_LEN("$"));
783:
784: break;
785:
786: case '+':
787: if (t->input[t->offset + 1] == '=') {
788: t->offset += 2;
789: buffer_copy_string_len(token, CONST_STR_LEN("+="));
790: tid = TK_APPEND;
791: } else {
792: t->offset++;
793: tid = TK_PLUS;
794: buffer_copy_string_len(token, CONST_STR_LEN("+"));
795: }
796: break;
797:
798: case '{':
799: t->offset++;
800:
801: tid = TK_LCURLY;
802:
803: buffer_copy_string_len(token, CONST_STR_LEN("{"));
804:
805: break;
806:
807: case '}':
808: t->offset++;
809:
810: tid = TK_RCURLY;
811:
812: buffer_copy_string_len(token, CONST_STR_LEN("}"));
813:
814: break;
815:
816: case '[':
817: t->offset++;
818:
819: tid = TK_LBRACKET;
820:
821: buffer_copy_string_len(token, CONST_STR_LEN("["));
822:
823: break;
824:
825: case ']':
826: t->offset++;
827:
828: tid = TK_RBRACKET;
829:
830: buffer_copy_string_len(token, CONST_STR_LEN("]"));
831:
832: break;
833: case '#':
834: t->line_pos += config_skip_comment(t);
835:
836: break;
837: default:
838: if (t->in_cond) {
839: for (i = 0; t->input[t->offset + i] &&
840: (isalpha((unsigned char)t->input[t->offset + i])
841: ); i++);
842:
843: if (i && t->input[t->offset + i]) {
844: tid = TK_SRVVARNAME;
845: buffer_copy_string_len(token, t->input + t->offset, i);
846:
847: t->offset += i;
848: t->line_pos += i;
849: } else {
850: /* ERROR */
851: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
852: "source:", t->source,
853: "line:", t->line, "pos:", t->line_pos,
854: "invalid character in condition");
855: return -1;
856: }
857: } else if (isdigit((unsigned char)c)) {
858: /* take all digits */
859: for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
860:
861: /* was there it least a digit ? */
862: if (i) {
863: tid = TK_INTEGER;
864:
865: buffer_copy_string_len(token, t->input + t->offset, i);
866:
867: t->offset += i;
868: t->line_pos += i;
869: }
870: } else {
871: /* the key might consist of [-.0-9a-z] */
872: for (i = 0; t->input[t->offset + i] &&
873: (isalnum((unsigned char)t->input[t->offset + i]) ||
874: t->input[t->offset + i] == '.' ||
875: t->input[t->offset + i] == '_' || /* for env.* */
876: t->input[t->offset + i] == '-'
877: ); i++);
878:
879: if (i && t->input[t->offset + i]) {
880: buffer_copy_string_len(token, t->input + t->offset, i);
881:
882: if (strcmp(token->ptr, "include") == 0) {
883: tid = TK_INCLUDE;
884: } else if (strcmp(token->ptr, "include_shell") == 0) {
885: tid = TK_INCLUDE_SHELL;
886: } else if (strcmp(token->ptr, "global") == 0) {
887: tid = TK_GLOBAL;
888: } else if (strcmp(token->ptr, "else") == 0) {
889: tid = TK_ELSE;
890: } else {
891: tid = TK_LKEY;
892: }
893:
894: t->offset += i;
895: t->line_pos += i;
896: } else {
897: /* ERROR */
898: log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
899: "source:", t->source,
900: "line:", t->line, "pos:", t->line_pos,
901: "invalid character in variable name");
902: return -1;
903: }
904: }
905: break;
906: }
907: }
908:
909: if (tid) {
910: *token_id = tid;
911: #if 0
912: log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
913: "source:", t->source,
914: "line:", t->line, "pos:", t->line_pos,
915: token, token->used - 1, tid);
916: #endif
917:
918: return 1;
919: } else if (t->offset < t->size) {
920: fprintf(stderr, "%s.%d: %d, %s\n",
921: __FILE__, __LINE__,
922: tid, token->ptr);
923: }
924: return 0;
925: }
926:
927: static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
928: void *pParser;
929: int token_id;
930: buffer *token, *lasttoken;
931: int ret;
932:
933: pParser = configparserAlloc( malloc );
934: lasttoken = buffer_init();
935: token = buffer_init();
936: while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
937: buffer_copy_string_buffer(lasttoken, token);
938: configparser(pParser, token_id, token, context);
939:
940: token = buffer_init();
941: }
942: buffer_free(token);
943:
944: if (ret != -1 && context->ok) {
945: /* add an EOL at EOF, better than say sorry */
946: configparser(pParser, TK_EOL, buffer_init_string("(EOL)"), context);
947: if (context->ok) {
948: configparser(pParser, 0, NULL, context);
949: }
950: }
951: configparserFree(pParser, free);
952:
953: if (ret == -1) {
954: log_error_write(srv, __FILE__, __LINE__, "sb",
955: "configfile parser failed at:", lasttoken);
956: } else if (context->ok == 0) {
957: log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
958: "source:", t->source,
959: "line:", t->line, "pos:", t->line_pos,
960: "parser failed somehow near here:", lasttoken);
961: ret = -1;
962: }
963: buffer_free(lasttoken);
964:
965: return ret == -1 ? -1 : 0;
966: }
967:
968: static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
969:
970: t->source = source;
971: t->input = input;
972: t->size = size;
973: t->offset = 0;
974: t->line = 1;
975: t->line_pos = 1;
976:
977: t->in_key = 1;
978: t->in_brace = 0;
979: t->in_cond = 0;
980: return 0;
981: }
982:
983: int config_parse_file(server *srv, config_t *context, const char *fn) {
984: tokenizer_t t;
985: stream s;
986: int ret;
987: buffer *filename;
988:
989: if (buffer_is_empty(context->basedir) ||
990: (fn[0] == '/' || fn[0] == '\\') ||
991: (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
992: filename = buffer_init_string(fn);
993: } else {
994: filename = buffer_init_buffer(context->basedir);
995: buffer_append_string(filename, fn);
996: }
997:
998: if (0 != stream_open(&s, filename)) {
999: if (s.size == 0) {
1000: /* the file was empty, nothing to parse */
1001: ret = 0;
1002: } else {
1003: log_error_write(srv, __FILE__, __LINE__, "sbss",
1004: "opening configfile ", filename, "failed:", strerror(errno));
1005: ret = -1;
1006: }
1007: } else {
1008: tokenizer_init(&t, filename, s.start, s.size);
1009: ret = config_parse(srv, context, &t);
1010: }
1011:
1012: stream_close(&s);
1013: buffer_free(filename);
1014: return ret;
1015: }
1016:
1017: static char* getCWD(void) {
1018: char *s, *s1;
1019: size_t len;
1020: #ifdef PATH_MAX
1021: len = PATH_MAX;
1022: #else
1023: len = 4096;
1024: #endif
1025:
1026: s = malloc(len);
1027: if (!s) return NULL;
1028: while (NULL == getcwd(s, len)) {
1.1.1.2 ! misho 1029: if (errno != ERANGE || SSIZE_MAX - len < len) {
! 1030: free(s);
! 1031: return NULL;
! 1032: }
1.1 misho 1033: len *= 2;
1034: s1 = realloc(s, len);
1035: if (!s1) {
1036: free(s);
1037: return NULL;
1038: }
1039: s = s1;
1040: }
1041: return s;
1042: }
1043:
1044: int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
1045: tokenizer_t t;
1046: int ret;
1047: buffer *source;
1048: buffer *out;
1049: char *oldpwd;
1050:
1051: if (NULL == (oldpwd = getCWD())) {
1052: log_error_write(srv, __FILE__, __LINE__, "s",
1053: "cannot get cwd", strerror(errno));
1054: return -1;
1055: }
1056:
1057: source = buffer_init_string(cmd);
1058: out = buffer_init();
1059:
1060: if (!buffer_is_empty(context->basedir)) {
1061: chdir(context->basedir->ptr);
1062: }
1063:
1064: if (0 != proc_open_buffer(cmd, NULL, out, NULL)) {
1065: log_error_write(srv, __FILE__, __LINE__, "sbss",
1066: "opening", source, "failed:", strerror(errno));
1067: ret = -1;
1068: } else {
1069: tokenizer_init(&t, source, out->ptr, out->used);
1070: ret = config_parse(srv, context, &t);
1071: }
1072:
1073: buffer_free(source);
1074: buffer_free(out);
1075: chdir(oldpwd);
1076: free(oldpwd);
1077: return ret;
1078: }
1079:
1080: static void context_init(server *srv, config_t *context) {
1081: context->srv = srv;
1082: context->ok = 1;
1083: context->configs_stack = array_init();
1084: context->configs_stack->is_weakref = 1;
1085: context->basedir = buffer_init();
1086: }
1087:
1088: static void context_free(config_t *context) {
1089: array_free(context->configs_stack);
1090: buffer_free(context->basedir);
1091: }
1092:
1093: int config_read(server *srv, const char *fn) {
1094: config_t context;
1095: data_config *dc;
1096: data_integer *dpid;
1097: data_string *dcwd;
1098: int ret;
1099: char *pos;
1100: data_array *modules;
1101:
1102: context_init(srv, &context);
1103: context.all_configs = srv->config_context;
1104:
1105: #ifdef __WIN32
1106: pos = strrchr(fn, '\\');
1107: #else
1108: pos = strrchr(fn, '/');
1109: #endif
1110: if (pos) {
1111: buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
1112: fn = pos + 1;
1113: }
1114:
1115: dc = data_config_init();
1116: buffer_copy_string_len(dc->key, CONST_STR_LEN("global"));
1117:
1.1.1.2 ! misho 1118: force_assert(context.all_configs->used == 0);
1.1 misho 1119: dc->context_ndx = context.all_configs->used;
1120: array_insert_unique(context.all_configs, (data_unset *)dc);
1121: context.current = dc;
1122:
1123: /* default context */
1124: srv->config = dc->value;
1125: dpid = data_integer_init();
1126: dpid->value = getpid();
1127: buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID"));
1128: array_insert_unique(srv->config, (data_unset *)dpid);
1129:
1130: dcwd = data_string_init();
1131: buffer_prepare_copy(dcwd->value, 1024);
1132: if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
1133: dcwd->value->used = strlen(dcwd->value->ptr) + 1;
1134: buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD"));
1135: array_insert_unique(srv->config, (data_unset *)dcwd);
1.1.1.2 ! misho 1136: } else {
! 1137: dcwd->free((data_unset*) dcwd);
1.1 misho 1138: }
1139:
1140: ret = config_parse_file(srv, &context, fn);
1141:
1142: /* remains nothing if parser is ok */
1.1.1.2 ! misho 1143: force_assert(!(0 == ret && context.ok && 0 != context.configs_stack->used));
1.1 misho 1144: context_free(&context);
1145:
1146: if (0 != ret) {
1147: return ret;
1148: }
1149:
1150: if (NULL != (dc = (data_config *)array_get_element(srv->config_context, "global"))) {
1151: srv->config = dc->value;
1152: } else {
1153: return -1;
1154: }
1155:
1156: if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
1157: data_string *ds;
1158: data_array *prepends;
1159:
1160: if (modules->type != TYPE_ARRAY) {
1161: fprintf(stderr, "server.modules must be an array");
1162: return -1;
1163: }
1164:
1165: prepends = data_array_init();
1166:
1167: /* prepend default modules */
1168: if (NULL == array_get_element(modules->value, "mod_indexfile")) {
1169: ds = data_string_init();
1170: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
1171: array_insert_unique(prepends->value, (data_unset *)ds);
1172: }
1173:
1174: prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules);
1.1.1.2 ! misho 1175: force_assert(NULL != prepends);
1.1 misho 1176: buffer_copy_string_buffer(prepends->key, modules->key);
1177: array_replace(srv->config, (data_unset *)prepends);
1178: modules->free((data_unset *)modules);
1179: modules = prepends;
1180:
1181: /* append default modules */
1182: if (NULL == array_get_element(modules->value, "mod_dirlisting")) {
1183: ds = data_string_init();
1184: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
1185: array_insert_unique(modules->value, (data_unset *)ds);
1186: }
1187:
1188: if (NULL == array_get_element(modules->value, "mod_staticfile")) {
1189: ds = data_string_init();
1190: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
1191: array_insert_unique(modules->value, (data_unset *)ds);
1192: }
1193: } else {
1194: data_string *ds;
1195:
1196: modules = data_array_init();
1197:
1198: /* server.modules is not set */
1199: ds = data_string_init();
1200: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
1201: array_insert_unique(modules->value, (data_unset *)ds);
1202:
1203: ds = data_string_init();
1204: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
1205: array_insert_unique(modules->value, (data_unset *)ds);
1206:
1207: ds = data_string_init();
1208: buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
1209: array_insert_unique(modules->value, (data_unset *)ds);
1210:
1211: buffer_copy_string_len(modules->key, CONST_STR_LEN("server.modules"));
1212: array_insert_unique(srv->config, (data_unset *)modules);
1213: }
1214:
1215:
1216: if (0 != config_insert(srv)) {
1217: return -1;
1218: }
1219:
1220: return 0;
1221: }
1222:
1223: int config_set_defaults(server *srv) {
1224: size_t i;
1225: specific_config *s = srv->config_storage[0];
1226: struct stat st1, st2;
1227:
1228: struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
1229: {
1230: /* - epoll is most reliable
1231: * - select works everywhere
1232: */
1233: #ifdef USE_LINUX_EPOLL
1234: { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
1235: #endif
1236: #ifdef USE_POLL
1237: { FDEVENT_HANDLER_POLL, "poll" },
1238: #endif
1239: #ifdef USE_SELECT
1240: { FDEVENT_HANDLER_SELECT, "select" },
1241: #endif
1242: #ifdef USE_LIBEV
1243: { FDEVENT_HANDLER_LIBEV, "libev" },
1244: #endif
1245: #ifdef USE_SOLARIS_DEVPOLL
1246: { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
1247: #endif
1248: #ifdef USE_SOLARIS_PORT
1249: { FDEVENT_HANDLER_SOLARIS_PORT, "solaris-eventports" },
1250: #endif
1251: #ifdef USE_FREEBSD_KQUEUE
1252: { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
1253: { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
1254: #endif
1255: { FDEVENT_HANDLER_UNSET, NULL }
1256: };
1257:
1258: if (!buffer_is_empty(srv->srvconf.changeroot)) {
1259: if (-1 == stat(srv->srvconf.changeroot->ptr, &st1)) {
1260: log_error_write(srv, __FILE__, __LINE__, "sb",
1261: "server.chroot doesn't exist:", srv->srvconf.changeroot);
1262: return -1;
1263: }
1264: if (!S_ISDIR(st1.st_mode)) {
1265: log_error_write(srv, __FILE__, __LINE__, "sb",
1266: "server.chroot isn't a directory:", srv->srvconf.changeroot);
1267: return -1;
1268: }
1269: }
1270:
1271: if (buffer_is_empty(s->document_root)) {
1272: log_error_write(srv, __FILE__, __LINE__, "s",
1273: "a default document-root has to be set");
1274:
1275: return -1;
1276: }
1277:
1278: buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
1279:
1280: buffer_to_lower(srv->tmp_buf);
1281:
1282: if (2 == s->force_lowercase_filenames) { /* user didn't configure it in global section? */
1283: s->force_lowercase_filenames = 0; /* default to 0 */
1284:
1285: if (0 == stat(srv->tmp_buf->ptr, &st1)) {
1286: int is_lower = 0;
1287:
1288: is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
1289:
1290: /* lower-case existed, check upper-case */
1291: buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
1292:
1293: buffer_to_upper(srv->tmp_buf);
1294:
1295: /* we have to handle the special case that upper and lower-casing results in the same filename
1296: * as in server.document-root = "/" or "/12345/" */
1297:
1298: if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
1299: /* lower-casing and upper-casing didn't result in
1300: * an other filename, no need to stat(),
1301: * just assume it is case-sensitive. */
1302:
1303: s->force_lowercase_filenames = 0;
1304: } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
1305:
1306: /* upper case exists too, doesn't the FS handle this ? */
1307:
1308: /* upper and lower have the same inode -> case-insensitve FS */
1309:
1310: if (st1.st_ino == st2.st_ino) {
1311: /* upper and lower have the same inode -> case-insensitve FS */
1312:
1313: s->force_lowercase_filenames = 1;
1314: }
1315: }
1316: }
1317: }
1318:
1319: if (srv->srvconf.port == 0) {
1320: srv->srvconf.port = s->ssl_enabled ? 443 : 80;
1321: }
1322:
1323: if (srv->srvconf.event_handler->used == 0) {
1324: /* choose a good default
1325: *
1326: * the event_handler list is sorted by 'goodness'
1327: * taking the first available should be the best solution
1328: */
1329: srv->event_handler = event_handlers[0].et;
1330:
1331: if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
1332: log_error_write(srv, __FILE__, __LINE__, "s",
1333: "sorry, there is no event handler for this system");
1334:
1335: return -1;
1336: }
1337: } else {
1338: /*
1339: * User override
1340: */
1341:
1342: for (i = 0; event_handlers[i].name; i++) {
1343: if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
1344: srv->event_handler = event_handlers[i].et;
1345: break;
1346: }
1347: }
1348:
1349: if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
1350: log_error_write(srv, __FILE__, __LINE__, "sb",
1351: "the selected event-handler in unknown or not supported:",
1352: srv->srvconf.event_handler );
1353:
1354: return -1;
1355: }
1356: }
1357:
1358: if (s->ssl_enabled) {
1359: if (buffer_is_empty(s->ssl_pemfile)) {
1360: /* PEM file is require */
1361:
1362: log_error_write(srv, __FILE__, __LINE__, "s",
1363: "ssl.pemfile has to be set");
1364: return -1;
1365: }
1366:
1367: #ifndef USE_OPENSSL
1368: log_error_write(srv, __FILE__, __LINE__, "s",
1369: "ssl support is missing, recompile with --with-openssl");
1370:
1371: return -1;
1372: #endif
1373: }
1374:
1375: return 0;
1376: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>