125 free_init_config(cfg); |
129 free_init_config(cfg); |
126 |
130 |
127 return 0; |
131 return 0; |
128 } |
132 } |
129 |
133 |
130 ServerConfiguration* load_server_conf(ServerConfiguration *old, char *file) { |
134 ServerConfiguration* load_server_conf(char *file) { |
131 log_ereport(LOG_VERBOSE, "load_server_conf"); |
135 log_ereport(LOG_VERBOSE, "load_server_conf"); |
132 |
136 |
133 ServerConfig *serverconf = load_server_config(file); |
137 ServerConfig *serverconf = serverconfig_load(file); |
134 if(serverconf == NULL) { |
138 if(!serverconf) { |
135 log_ereport(LOG_FAILURE, "Cannot load server.conf"); |
139 log_ereport(LOG_FAILURE, "Cannot load server.conf"); |
136 } |
140 return NULL; |
137 ServerConfiguration *serverconfig = calloc(1, sizeof(ServerConfiguration)); |
141 } |
|
142 |
|
143 pool_handle_t *pool = pool_create(); |
|
144 |
|
145 |
|
146 ServerConfiguration *serverconfig = pool_calloc(pool, 1, sizeof(ServerConfiguration)); |
138 serverconfig->ref = 1; |
147 serverconfig->ref = 1; |
139 serverconfig->pool = pool_create(); |
148 serverconfig->pool = pool; |
|
149 |
|
150 UcxAllocator allocator = util_pool_allocator(serverconfig->pool); |
|
151 serverconfig->a = pool_malloc(pool, sizeof(UcxAllocator)); |
|
152 *serverconfig->a = allocator; |
|
153 |
140 serverconfig->listeners = NULL; |
154 serverconfig->listeners = NULL; |
141 serverconfig->host_vs = ucx_map_new(16); |
155 serverconfig->host_vs = ucx_map_new_a(&allocator, 16); |
142 serverconfig->authdbs = ucx_map_new(16); |
156 serverconfig->authdbs = ucx_map_new_a(&allocator, 16); |
|
157 serverconfig->resources = ucx_map_new_a(&allocator, 16); |
|
158 serverconfig->dav = ucx_map_new_a(&allocator, 16); |
|
159 |
|
160 |
|
161 |
143 // TODO: init serverconfig stuff |
162 // TODO: init serverconfig stuff |
144 |
163 |
145 |
164 |
146 /* |
165 /* |
147 * convert ServerConfig to ServerConfiguration |
166 * convert ServerConfig to ServerConfiguration |
159 /* |
178 /* |
160 * free stuff on error |
179 * free stuff on error |
161 */ |
180 */ |
162 |
181 |
163 // init logfile first |
182 // init logfile first |
164 UcxList *lfl = ucx_map_sstr_get(serverconf->objects, sstrn("LogFile", 7)); |
183 UcxList *list = NULL; |
165 if(lfl != NULL) { |
184 |
166 ServerConfigObject *logobj = lfl->data; |
185 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("LogFile")); |
167 if(logobj == NULL) { |
186 if(list) { |
|
187 ConfigNode *logobj = list->data; |
|
188 if(!logobj) { |
168 // error |
189 // error |
169 return NULL; |
190 return NULL; // TODO: fix memory leak |
170 } |
191 } |
171 |
192 |
172 int ret = cfg_handle_logfile(serverconfig, logobj); |
193 int ret = cfg_handle_logfile(serverconfig, logobj); |
173 if(ret != 0) { |
194 if(ret != 0) { |
174 // cannot initialize log file |
195 // cannot initialize log file |
175 return NULL; |
196 return NULL; // TODO: fix memory leak |
176 } |
197 } |
177 } else { |
198 } else { |
178 // horrible error |
199 // horrible error |
179 return NULL; |
200 return NULL; |
180 } |
201 } |
|
202 ucx_list_free(list); |
181 |
203 |
182 UcxList *list = ucx_map_sstr_get(serverconf->objects, sstrn("Runtime", 7)); |
204 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Runtime")); |
183 UCX_FOREACH(elm, list) { |
205 UCX_FOREACH(elm, list) { |
184 ServerConfigObject *scfgobj = elm->data; |
206 ConfigNode *runtimeobj = elm->data; |
185 if(cfg_handle_runtime(serverconfig, scfgobj)) { |
207 if(cfg_handle_runtime(serverconfig, runtimeobj)) { |
186 // error |
208 // error |
187 return NULL; |
209 return NULL; |
188 } |
210 } |
189 } |
211 } |
190 |
212 ucx_list_free(list); |
191 list = ucx_map_sstr_get(serverconf->objects, sstrn("Threadpool", 10)); |
213 |
|
214 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Threadpool")); |
192 UCX_FOREACH(elm, list) { |
215 UCX_FOREACH(elm, list) { |
193 if(cfg_handle_threadpool(serverconfig, elm->data)) { |
216 if(cfg_handle_threadpool(serverconfig, elm->data)) { |
194 return NULL; |
217 return NULL; |
195 } |
218 } |
196 } |
219 } |
|
220 ucx_list_free(list); |
197 // check thread pool config |
221 // check thread pool config |
198 if(check_thread_pool_cfg() != 0) { |
222 if(check_thread_pool_cfg() != 0) { |
199 /* critical error */ |
223 /* critical error */ |
200 return NULL; |
224 return NULL; |
201 } |
225 } |
202 |
226 |
203 list = ucx_map_sstr_get(serverconf->objects, sstrn("EventHandler", 12)); |
227 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("EventHandler")); |
204 UCX_FOREACH(elm, list) { |
228 UCX_FOREACH(elm, list) { |
205 if(cfg_handle_eventhandler( |
229 if(cfg_handle_eventhandler( |
206 serverconfig, (ServerConfigObject*)elm->data)) { |
230 serverconfig, elm->data)) { |
207 // error |
231 // error |
208 return NULL; |
232 return NULL; |
209 } |
233 } |
210 } |
234 } |
211 // check event handler config |
235 // check event handler config |
212 if(check_event_handler_cfg() != 0) { |
236 if(check_event_handler_cfg() != 0) { |
213 /* critical error */ |
237 /* critical error */ |
214 return NULL; |
238 return NULL; |
215 } |
239 } |
216 |
240 ucx_list_free(list); |
217 list = ucx_map_sstr_get(serverconf->objects, sstrn("AccessLog", 9)); |
241 |
|
242 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AccessLog")); |
218 UCX_FOREACH(elm, list) { |
243 UCX_FOREACH(elm, list) { |
219 ServerConfigObject *scfgobj = elm->data; |
244 ConfigNode *scfgobj = elm->data; |
220 if(cfg_handle_accesslog(serverconfig, scfgobj)) { |
245 if(cfg_handle_accesslog(serverconfig, scfgobj)) { |
221 return NULL; |
246 return NULL; |
222 } |
247 } |
223 } |
248 } |
224 |
249 ucx_list_free(list); |
225 list = ucx_map_sstr_get(serverconf->objects, sstrn("AuthDB", 6)); |
250 |
|
251 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AuthDB")); |
226 UCX_FOREACH(elm, list) { |
252 UCX_FOREACH(elm, list) { |
227 ServerConfigObject *scfgobj = elm->data; |
253 ConfigNode *scfgobj = elm->data; |
228 if(cfg_handle_authdb(serverconfig, scfgobj)) { |
254 if(cfg_handle_authdb(serverconfig, scfgobj)) { |
229 return NULL; |
255 return NULL; |
230 } |
256 } |
231 } |
257 } |
232 |
258 ucx_list_free(list); |
233 list = ucx_map_sstr_get(serverconf->objects, sstrn("Listener", 8)); |
259 |
|
260 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Listener")); |
234 UCX_FOREACH(elm, list) { |
261 UCX_FOREACH(elm, list) { |
235 ServerConfigObject *scfgobj = elm->data; |
262 ConfigNode *scfgobj = elm->data; |
236 if(cfg_handle_listener(serverconfig, scfgobj)) { |
263 if(cfg_handle_listener(serverconfig, scfgobj)) { |
237 return NULL; |
264 return NULL; |
238 } |
265 } |
239 } |
266 } |
240 |
267 ucx_list_free(list); |
241 list = ucx_map_sstr_get(serverconf->objects, sstrn("VirtualServer", 13)); |
268 |
|
269 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("VirtualServer")); |
242 UCX_FOREACH(elm, list) { |
270 UCX_FOREACH(elm, list) { |
243 ServerConfigObject *scfgobj = elm->data; |
271 ConfigNode *scfgobj = elm->data; |
244 if(cfg_handle_vs(serverconfig, scfgobj)) { |
272 if(cfg_handle_vs(serverconfig, scfgobj)) { |
245 return NULL; |
273 return NULL; |
246 } |
274 } |
247 } |
275 } |
248 |
276 ucx_list_free(list); |
|
277 |
|
278 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("ResourcePool")); |
|
279 UCX_FOREACH(elm, list) { |
|
280 ConfigNode *scfgobj = elm->data; |
|
281 if(cfg_handle_resourcepool(serverconfig, scfgobj)) { |
|
282 return NULL; |
|
283 } |
|
284 } |
|
285 |
|
286 list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Dav")); |
|
287 UCX_FOREACH(elm, list) { |
|
288 ConfigNode *scfgobj = elm->data; |
|
289 if(cfg_handle_dav(serverconfig, scfgobj)) { |
|
290 return NULL; |
|
291 } |
|
292 } |
249 |
293 |
250 // set VirtualServer for all listeners |
294 // set VirtualServer for all listeners |
251 UcxList *ls = serverconfig->listeners; |
295 UcxList *ls = serverconfig->listeners; |
252 while(ls) { |
296 while(ls) { |
253 HttpListener *listener = ls->data; |
297 HttpListener *listener = ls->data; |
266 } |
310 } |
267 |
311 |
268 ls = ls->next; |
312 ls = ls->next; |
269 } |
313 } |
270 |
314 |
271 free_server_config(serverconf); |
315 serverconfig_free(serverconf); |
|
316 |
272 return serverconfig; |
317 return serverconfig; |
273 } |
318 } |
274 |
319 |
275 void cfg_ref(ServerConfiguration *cfg) { |
320 void cfg_ref(ServerConfiguration *cfg) { |
276 ws_atomic_inc32(&cfg->ref); |
321 ws_atomic_inc32(&cfg->ref); |
277 } |
322 } |
278 |
323 |
279 void cfg_unref(ServerConfiguration *cfg) { |
324 void cfg_unref(ServerConfiguration *cfg) { |
280 uint32_t ref = ws_atomic_dec32(&cfg->ref); |
325 uint32_t ref = ws_atomic_dec32(&cfg->ref); |
281 if(ref == 0) { |
326 if(ref == 0) { |
282 // TODO: free configuration |
327 pool_destroy(cfg->pool); |
283 printf("free ServerConfiguration %"PRIxPTR"\n", (intptr_t)cfg); |
|
284 } |
328 } |
285 } |
329 } |
286 |
330 |
287 |
331 |
288 void init_server_config_parser() { |
332 void init_server_config_parser() { |
289 |
333 |
290 } |
334 } |
291 |
335 |
292 int cfg_handle_runtime(ServerConfiguration *cfg, ServerConfigObject *obj) { |
336 int cfg_handle_runtime(ServerConfiguration *cfg, ConfigNode *obj) { |
293 sstr_t user = cfg_directivelist_get_str(obj->directives, sstr("User")); |
337 scstr_t user = serverconfig_directive_value(obj, SC("User")); |
294 if(user.ptr) { |
338 if(user.ptr) { |
295 cfg->user = sstrdup_pool(cfg->pool, user); |
339 cfg->user = sstrdup_a(cfg->a, user); |
296 } |
340 } |
297 sstr_t tmp = cfg_directivelist_get_str(obj->directives, sstr("Temp")); |
341 scstr_t tmp = serverconfig_directive_value(obj, SC("Temp")); |
298 if(tmp.ptr) { |
342 if(tmp.ptr) { |
299 cfg->tmp = sstrdup_pool(cfg->pool, tmp); |
343 cfg->tmp = sstrdup_a(cfg->a, tmp); |
300 } else { |
344 } else { |
|
345 // TODO: do this check after all config loading is done |
301 log_ereport(LOG_MISCONFIG, "no temporary directory specified"); |
346 log_ereport(LOG_MISCONFIG, "no temporary directory specified"); |
302 return -1; |
347 return -1; |
303 } |
348 } |
304 |
349 |
305 // mime file |
350 // mime file |
306 sstr_t mf = cfg_directivelist_get_str(obj->directives, sstr("MimeFile")); |
351 scstr_t mf = serverconfig_directive_value(obj, SC("MimeFile")); |
307 sstr_t base = sstr("config/"); |
352 scstr_t base = SC("config/"); |
308 sstr_t file = sstrcat(2, base, mf); |
353 sstr_t file = sstrcat(2, base, mf); |
309 |
354 |
310 ConfigFile *f = cfgmgr_get_file(file); |
355 if(mime_conf_load(cfg, file)) { |
311 if(f == NULL) { |
356 return -1; |
312 f = malloc(sizeof(ConfigFile)); |
357 } |
313 f->data = NULL; |
|
314 f->file = sstrdup(file); |
|
315 f->reload = mime_conf_reload; |
|
316 f->last_modified = 0; |
|
317 |
|
318 // load the file content |
|
319 //f->reload(f, cfg); |
|
320 if(cfgmgr_reload_file(f, cfg, NULL)) { |
|
321 free(f->file.ptr); |
|
322 free(f); |
|
323 |
|
324 free(file.ptr); |
|
325 return -1; |
|
326 } |
|
327 cfgmgr_attach_file(f); |
|
328 } |
|
329 |
|
330 cfg->mimetypes = f->data; |
|
331 |
358 |
332 free(file.ptr); |
359 free(file.ptr); |
333 return 0; |
360 return 0; |
334 } |
361 } |
335 |
362 |
336 int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj) { |
363 int cfg_handle_logfile(ServerConfiguration *cfg, ConfigNode *obj) { |
337 sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); |
364 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
338 sstr_t lvl = cfg_directivelist_get_str(obj->directives, sstr("Level")); |
365 scstr_t lvl = serverconfig_directive_value(obj, SC("Level")); |
339 |
366 |
340 if(file.ptr == NULL || lvl.ptr == NULL) { |
367 if(file.ptr == NULL || lvl.ptr == NULL) { |
341 /* missing log file parameters */ |
368 /* missing log file parameters */ |
342 return -1; |
369 return -1; |
343 } |
370 } |
344 |
371 |
345 LogConfig logcfg; |
372 LogConfig logcfg; |
346 logcfg.file = sstrdup(file).ptr; |
373 logcfg.file = file.ptr; |
347 logcfg.level = sstrdup(lvl).ptr; |
374 logcfg.level = lvl.ptr; |
348 logcfg.log_stdout = 0; |
375 logcfg.log_stdout = 0; |
349 logcfg.log_stderr = 0; |
376 logcfg.log_stderr = 0; |
350 /* TODO: stdout, stderr config */ |
377 /* TODO: stdout, stderr config */ |
351 |
378 |
352 int ret = init_log_file(&logcfg); |
379 int ret = init_log_file(&logcfg); |
353 |
|
354 free(logcfg.file); |
|
355 free(logcfg.level); |
|
356 |
380 |
357 return ret; |
381 return ret; |
358 } |
382 } |
359 |
383 |
360 int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj) { |
384 int cfg_handle_threadpool(ServerConfiguration *cfg, ConfigNode *obj) { |
361 ThreadPoolConfig poolcfg; |
385 ThreadPoolConfig poolcfg; |
362 poolcfg.min_threads = 4; |
386 poolcfg.min_threads = 4; |
363 poolcfg.min_threads = 4; |
387 poolcfg.min_threads = 4; |
364 poolcfg.max_threads = 8; |
388 poolcfg.max_threads = 8; |
365 poolcfg.queue_size = 64; |
389 poolcfg.queue_size = 64; |
366 poolcfg.stack_size = 262144; |
390 poolcfg.stack_size = 262144; |
367 |
391 |
368 sstr_t name = cfg_directivelist_get_str( |
392 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
369 obj->directives, |
393 scstr_t min = serverconfig_directive_value(obj, SC("MinThreads")); |
370 sstr("Name")); |
394 scstr_t max = serverconfig_directive_value(obj, SC("MaxThreads")); |
371 sstr_t min = cfg_directivelist_get_str( |
395 scstr_t stack = serverconfig_directive_value(obj, SC("StackSize")); |
372 obj->directives, |
396 scstr_t queue = serverconfig_directive_value(obj, SC("QueueSize")); |
373 sstr("MinThreads")); |
|
374 sstr_t max = cfg_directivelist_get_str( |
|
375 obj->directives, |
|
376 sstr("MaxThreads")); |
|
377 sstr_t stack = cfg_directivelist_get_str( |
|
378 obj->directives, |
|
379 sstr("StackSize")); |
|
380 sstr_t queue = cfg_directivelist_get_str( |
|
381 obj->directives, |
|
382 sstr("QueueSize")); |
|
383 // TODO: Type |
397 // TODO: Type |
384 |
398 |
385 if(name.length == 0) { |
399 if(name.length == 0) { |
386 // TODO: log error |
400 // TODO: log error |
387 return 1; |
401 return 1; |
388 } |
402 } |
389 |
403 |
390 if(min.length != 0) { |
404 if(min.length != 0) { |
391 min = sstrdup(min); |
405 int64_t value; |
392 poolcfg.min_threads = atoi(min.ptr); |
406 if(util_strtoint(min.ptr, &value)) { |
393 free(min.ptr); |
407 poolcfg.min_threads = value; |
|
408 } else { |
|
409 log_ereport(LOG_MISCONFIG, "Threadpool: MinThreads not an integer"); |
|
410 return 1; |
|
411 } |
394 } |
412 } |
395 |
413 |
396 if(max.length != 0) { |
414 if(max.length != 0) { |
397 max = sstrdup(max); |
415 int64_t value; |
398 poolcfg.max_threads = atoi(max.ptr); |
416 if(util_strtoint(max.ptr, &value)) { |
399 free(max.ptr); |
417 poolcfg.max_threads = value; |
|
418 } else { |
|
419 log_ereport(LOG_MISCONFIG, "Threadpool: MaxThreads not an integer"); |
|
420 return 1; |
|
421 } |
400 } |
422 } |
401 |
423 |
402 if(stack.length != 0) { |
424 if(stack.length != 0) { |
403 stack = sstrdup(stack); |
425 int64_t value; |
404 poolcfg.stack_size = atoi(stack.ptr); |
426 if(util_strtoint(stack.ptr, &value)) { |
405 free(stack.ptr); |
427 poolcfg.stack_size = value; |
|
428 } else { |
|
429 log_ereport(LOG_MISCONFIG, "Threadpool: StackSize not an integer"); |
|
430 } |
406 } |
431 } |
407 |
432 |
408 if(queue.length != 0) { |
433 if(queue.length != 0) { |
409 queue = sstrdup(queue); |
434 int64_t value; |
410 poolcfg.queue_size = atoi(queue.ptr); |
435 if(util_strtoint(queue.ptr, &value)) { |
411 free(queue.ptr); |
436 poolcfg.queue_size = value; |
|
437 } else { |
|
438 log_ereport(LOG_MISCONFIG, "Threadpool: QueueSize not an integer"); |
|
439 } |
412 } |
440 } |
413 |
441 |
414 create_threadpool(name, &poolcfg); |
442 create_threadpool(name, &poolcfg); |
415 |
443 |
416 return 0; |
444 return 0; |
417 } |
445 } |
418 |
446 |
419 int cfg_handle_eventhandler(ServerConfiguration *c, ServerConfigObject *obj) { |
447 #define EV_MAX_THREADS 2048 |
|
448 int cfg_handle_eventhandler(ServerConfiguration *c, ConfigNode *obj) { |
420 EventHandlerConfig evcfg; |
449 EventHandlerConfig evcfg; |
421 |
450 |
422 sstr_t name = cfg_directivelist_get_str(obj->directives, sstr("Name")); |
451 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
423 sstr_t threads = cfg_directivelist_get_str( |
452 scstr_t threads = serverconfig_directive_value(obj, SC("Threads")); |
424 obj->directives, |
453 scstr_t isdefault = serverconfig_directive_value(obj, SC("Default")); |
425 sstr("Threads")); |
|
426 sstr_t isdefault = cfg_directivelist_get_str( |
|
427 obj->directives, |
|
428 sstr("Default")); |
|
429 |
454 |
430 evcfg.name = name; |
455 evcfg.name = name; |
431 |
456 |
432 sstr_t s = sstrdup(threads); |
457 int64_t value; |
433 evcfg.nthreads = atoi(s.ptr); |
458 if(!util_strtoint(threads.ptr, &value)) { |
434 free(s.ptr); |
459 log_ereport(LOG_MISCONFIG, "EventHandler: Threads: '%s' is not an integer", threads.ptr); |
|
460 return 1; |
|
461 } |
|
462 if(value < 1 || value > EV_MAX_THREADS) { |
|
463 log_ereport(LOG_MISCONFIG, "EventHandler: Invalid number of threads (1 .. %d)", EV_MAX_THREADS); |
|
464 return 1; |
|
465 } |
|
466 |
|
467 evcfg.nthreads = value; |
435 |
468 |
436 evcfg.isdefault = util_getboolean(isdefault.ptr, 0); |
469 evcfg.isdefault = util_getboolean(isdefault.ptr, 0); |
437 |
470 |
438 return create_event_handler(&evcfg); |
471 return create_event_handler(&evcfg); |
439 } |
472 } |
440 |
473 |
441 int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj) { |
474 int cfg_handle_resourcepool(ServerConfiguration *cfg, ConfigNode *obj) { |
|
475 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
|
476 scstr_t type = serverconfig_directive_value(obj, SC("Type")); |
|
477 |
|
478 int ret = 0; |
|
479 if(resourcepool_new(cfg, type, name, obj)) { |
|
480 ret = 1; |
|
481 } |
|
482 |
|
483 return ret; |
|
484 } |
|
485 |
|
486 int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj) { |
442 // TODO: use a name to identify the log file |
487 // TODO: use a name to identify the log file |
443 |
488 |
444 sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); |
489 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
445 if(file.ptr == NULL) { |
490 if(file.ptr == NULL) { |
446 return 0; |
491 return 0; |
447 } |
492 } |
448 sstr_t format; |
493 sstr_t format; |
449 format.ptr = NULL; |
494 format.ptr = NULL; |
454 if(!log_file) { |
499 if(!log_file) { |
455 // TODO: error/warning |
500 // TODO: error/warning |
456 return 0; |
501 return 0; |
457 } |
502 } |
458 AccessLog *log = pool_malloc(cfg->pool, sizeof(AccessLog)); |
503 AccessLog *log = pool_malloc(cfg->pool, sizeof(AccessLog)); |
459 log->file = sstrdup_pool(cfg->pool, file); |
504 log->file = sstrdup_a(cfg->a, file); |
460 log->format = format; |
505 log->format = format; |
461 log->log = log_file; |
506 log->log = log_file; |
462 cfg->logfiles = ucx_list_append(cfg->logfiles, log); |
507 cfg->logfiles = ucx_list_append_a(cfg->a, cfg->logfiles, log); |
463 |
508 |
464 if(!cfg->default_log) { |
509 if(!cfg->default_log) { |
465 cfg->default_log = log; |
510 cfg->default_log = log; |
466 } |
511 } |
467 |
512 |
468 return 0; |
513 return 0; |
469 } |
514 } |
470 |
515 |
471 int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) { |
516 int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj) { |
472 sstr_t name = cfg_directivelist_get_str(obj->directives, sstr("Name")); |
517 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
473 sstr_t type = cfg_directivelist_get_str(obj->directives, sstr("Type")); |
518 scstr_t type = serverconfig_directive_value(obj, SC("Type")); |
|
519 |
|
520 AuthDB *authdb = NULL; |
474 |
521 |
475 if(!sstrcmp(type, sstr("ldap"))) { |
522 if(!sstrcmp(type, sstr("ldap"))) { |
476 LDAPConfig conf; |
523 LDAPConfig conf; |
477 |
524 |
478 sstr_t host = cfg_directivelist_get_str( |
525 scstr_t host = serverconfig_directive_value(obj, SC("Host")); |
479 obj->directives, |
526 scstr_t port = serverconfig_directive_value( obj, SC("Port")); |
480 sstr("Host")); |
527 scstr_t basedn = serverconfig_directive_value(obj, SC("BaseDN")); |
481 sstr_t port = cfg_directivelist_get_str( |
528 scstr_t binddn = serverconfig_directive_value(obj, SC("BindDN")); |
482 obj->directives, |
529 scstr_t basepw = serverconfig_directive_value(obj, SC("BindPW")); |
483 sstr("Port")); |
530 |
484 sstr_t basedn = cfg_directivelist_get_str( |
531 conf.hostname = sstrdup_a(cfg->a, host).ptr; |
485 obj->directives, |
|
486 sstr("BaseDN")); |
|
487 sstr_t binddn = cfg_directivelist_get_str( |
|
488 obj->directives, |
|
489 sstr("BindDN")); |
|
490 sstr_t basepw = cfg_directivelist_get_str( |
|
491 obj->directives, |
|
492 sstr("BindPW")); |
|
493 |
|
494 host = sstrdup(host); |
|
495 port = sstrdup(port); |
|
496 basedn = sstrdup(basedn); |
|
497 binddn = sstrdup(binddn); |
|
498 basepw = sstrdup(basepw); |
|
499 |
|
500 conf.hostname = host.ptr; |
|
501 conf.port = atoi(port.ptr); |
532 conf.port = atoi(port.ptr); |
502 conf.basedn = basedn.ptr; |
533 conf.basedn = sstrdup_a(cfg->a, basedn).ptr; |
503 conf.binddn = binddn.ptr; |
534 conf.binddn = sstrdup_a(cfg->a, binddn).ptr; |
504 conf.bindpw = basepw.ptr; |
535 conf.bindpw = sstrdup_a(cfg->a, basepw).ptr; |
505 |
536 |
506 name = sstrdup(name); |
537 authdb = create_ldap_authdb(cfg, name.ptr, &conf); |
507 |
|
508 AuthDB *authdb = create_ldap_authdb(name.ptr, &conf); |
|
509 ucx_map_sstr_put(cfg->authdbs, name, authdb); |
|
510 |
|
511 // TODO: create_ldap_authdb should copy the strings |
|
512 /* |
|
513 free(host.ptr); |
|
514 free(port.ptr); |
|
515 free(basedn.ptr); |
|
516 free(binddn.ptr); |
|
517 free(basepw.ptr); |
|
518 free(name.ptr); |
|
519 */ |
|
520 |
|
521 } else if(!sstrcmp(type, sstr("keyfile"))) { |
538 } else if(!sstrcmp(type, sstr("keyfile"))) { |
522 // we only need the file parameter |
539 // we only need the file parameter |
523 sstr_t file = cfg_directivelist_get_str( |
540 scstr_t file = serverconfig_directive_value(obj, SC("File")); |
524 obj->directives, |
|
525 sstr("File")); |
|
526 if(file.length == 0) { |
541 if(file.length == 0) { |
527 log_ereport( |
542 log_ereport( |
528 LOG_MISCONFIG, |
543 LOG_MISCONFIG, |
529 "missing File parameter for keyfile authdb"); |
544 "missing File parameter for keyfile authdb"); |
530 return 1; |
545 return 1; |
531 } |
546 } |
532 |
547 |
533 // load keyfile |
548 // load keyfile |
534 ConfigFile *f = cfgmgr_get_file(file); |
549 authdb = keyfile_load(cfg, file); |
535 if(f == NULL) { |
550 } |
536 f = malloc(sizeof(ConfigFile)); |
551 |
537 f->data = NULL; |
552 if(authdb) { |
538 f->file = sstrdup(file); |
553 if(ucx_map_sstr_put(cfg->authdbs, name, authdb)) { |
539 f->reload = keyfile_reload; |
554 return -1; |
540 f->last_modified = 0; |
555 } |
541 //f->reload(f, cfg); |
556 } |
542 if(cfgmgr_reload_file(f, cfg, NULL)) { |
557 |
543 free(f->file.ptr); |
|
544 free(f); |
|
545 return -1; |
|
546 } |
|
547 cfgmgr_attach_file(f); |
|
548 } |
|
549 |
|
550 // add keyfile authdb |
|
551 Keyfile *keyfile = f->data; |
|
552 keyfile->authdb.name = sstrdup(name).ptr; |
|
553 ucx_map_sstr_put(cfg->authdbs, name, keyfile); |
|
554 } |
|
555 |
|
556 return 0; |
558 return 0; |
557 } |
559 } |
558 |
560 |
559 int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj) { |
561 int cfg_handle_listener(ServerConfiguration *cfg, ConfigNode *obj) { |
560 ListenerConfig lc; |
562 ListenerConfig lc; |
561 ZERO(&lc, sizeof(ListenerConfig)); |
563 ZERO(&lc, sizeof(ListenerConfig)); |
562 lc.cfg = cfg; |
564 lc.cfg = cfg; |
563 lc.port = 8080; |
565 lc.port = 8080; |
564 lc.nacceptors = 1; |
566 lc.nacceptors = 1; |
565 |
567 |
|
568 scstr_t name = serverconfig_directive_value(obj, SC("Name")); |
|
569 scstr_t port = serverconfig_directive_value(obj, SC("Port")); |
|
570 scstr_t vs = serverconfig_directive_value(obj, SC("DefaultVS")); |
|
571 scstr_t thrp = serverconfig_directive_value(obj, SC("Threadpool")); |
|
572 scstr_t blck = serverconfig_directive_value(obj, SC("BlockingIO")); |
|
573 |
566 // TODO: use sstrdup_pool? |
574 // TODO: use sstrdup_pool? |
567 lc.name = sstrdup(cfg_directivelist_get_str( |
575 int64_t port_value; |
568 obj->directives, |
576 if(!util_strtoint(port.ptr, &port_value)) { |
569 sstr("Name"))); |
577 log_ereport(LOG_MISCONFIG, "Listener: Invalid argument for parameter 'Port': '%s'", port.ptr); |
570 lc.port = atoi(cfg_directivelist_get_str( |
578 return 1; |
571 obj->directives, |
579 } |
572 sstr("Port")).ptr); |
580 if(port_value < 1 || port_value > 65535) { |
573 lc.vs = sstrdup(cfg_directivelist_get_str( |
581 log_ereport(LOG_MISCONFIG, "Listener: Port number out of range (1 .. 65535)"); |
574 obj->directives, |
582 return 1; |
575 sstr("DefaultVS"))); |
583 } |
576 lc.threadpool = sstrdup(cfg_directivelist_get_str( |
584 |
577 obj->directives, |
585 lc.name = sstrdup(name); |
578 sstr("Threadpool"))); |
586 lc.port = port_value; |
579 |
587 lc.vs = sstrdup(vs); |
580 sstr_t blockingio = cfg_directivelist_get_str( |
588 lc.threadpool = sstrdup(thrp); |
581 obj->directives, |
589 |
582 sstr("BlockingIO")); |
590 lc.blockingio = util_getboolean_s(blck, WS_FALSE); |
583 if(blockingio.ptr) { |
591 |
584 lc.blockingio = util_getboolean_s(blockingio, WS_FALSE); |
592 scstr_t ssl = serverconfig_directive_value(obj, SC("SSL")); |
585 } |
|
586 |
|
587 sstr_t ssl = cfg_directivelist_get_str(obj->directives, S("SSL")); |
|
588 if(util_getboolean_s(ssl, WS_FALSE)) { |
593 if(util_getboolean_s(ssl, WS_FALSE)) { |
589 sstr_t cert = cfg_directivelist_get_str(obj->directives, S("Cert")); |
594 scstr_t cert = serverconfig_directive_value(obj, SC("Cert")); |
590 sstr_t privkey = cfg_directivelist_get_str(obj->directives, S("Key")); |
595 scstr_t privkey = serverconfig_directive_value(obj, SC("Key")); |
591 sstr_t chain = cfg_directivelist_get_str(obj->directives, S("CertChain")); |
596 scstr_t chain = serverconfig_directive_value(obj, SC("CertChain")); |
592 sstr_t disableprot = cfg_directivelist_get_str( |
597 scstr_t disableprot = serverconfig_directive_value(obj, SC("SSLDisableProtocol")); |
593 obj->directives, |
|
594 S("SSLDisableProtocol")); |
|
595 |
598 |
596 WSBool config_ok = WS_TRUE; |
599 WSBool config_ok = WS_TRUE; |
597 // TODO: log error |
600 // TODO: log error |
598 if(!cert.ptr && !chain.ptr) { |
601 if(!cert.ptr && !chain.ptr) { |
599 log_ereport( |
602 log_ereport( |
626 HttpListener *listener = http_listener_create(&lc); |
629 HttpListener *listener = http_listener_create(&lc); |
627 if(!listener) { |
630 if(!listener) { |
628 return 1; |
631 return 1; |
629 } |
632 } |
630 |
633 |
631 listener->default_vs.vs_name = lc.vs.ptr; |
634 listener->default_vs.vs_name = sstrdup_a(cfg->a, lc.vs).ptr; |
632 cfg->listeners = ucx_list_append(cfg->listeners, listener); |
635 cfg->listeners = ucx_list_append_a(cfg->a, cfg->listeners, listener); |
633 |
636 |
634 return 0; |
637 return 0; |
635 } |
638 } |
636 |
639 |
637 int cfg_handle_vs(ServerConfiguration *cfg, ServerConfigObject *obj) { |
640 int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj) { |
638 VirtualServer *vs = vs_new(); |
641 VirtualServer *vs = vs_new(); |
639 |
642 |
640 vs->name = sstrdup(cfg_directivelist_get_str( |
643 vs->name = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Name"))); |
641 obj->directives, |
644 vs->host = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Host"))); |
642 sstr("Name"))); |
645 vs->document_root = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("DocRoot"))); |
643 vs->host = sstrdup(cfg_directivelist_get_str( |
646 |
644 obj->directives, |
647 scstr_t objfile = serverconfig_directive_value(obj, SC("ObjectFile")); |
645 sstr("Host"))); |
648 scstr_t aclfile = serverconfig_directive_value(obj, SC("ACLFile")); |
646 vs->document_root = sstrdup(cfg_directivelist_get_str( |
|
647 obj->directives, |
|
648 sstr("DocRoot"))); |
|
649 sstr_t objfile = cfg_directivelist_get_str( |
|
650 obj->directives, |
|
651 sstr("ObjectFile")); |
|
652 sstr_t aclfile = cfg_directivelist_get_str( |
|
653 obj->directives, |
|
654 sstr("ACLFile")); |
|
655 |
649 |
656 // load the object config file |
650 // load the object config file |
657 sstr_t base = sstr("config/"); |
651 sstr_t base = sstr("config/"); |
658 sstr_t file = sstrcat(2, base, objfile); |
652 sstr_t file = sstrcat(2, base, objfile); |
659 file = sstrcat(2, base, objfile); |
653 // sstrcat with allocator because we want to keep the string |
660 |
654 file = sstrcat_a(cfg->a, 2, base, objfile); |
661 // the file is managed by the configuration manager |
655 |
662 ConfigFile *f = cfgmgr_get_file(file); |
656 HTTPObjectConfig *httpobj = objconf_load(cfg, file); |
663 if(f == NULL) { |
657 if(!httpobj) { |
664 f = malloc(sizeof(ConfigFile)); |
658 return -1; |
665 f->data = NULL; |
659 } |
666 f->file = sstrdup(file); |
660 vs->objectfile = file; |
667 f->reload = object_conf_reload; |
661 vs->objects = httpobj; |
668 f->last_modified = 0; |
|
669 //f->reload(f, cfg); |
|
670 if(cfgmgr_reload_file(f, cfg, NULL)) { |
|
671 free(f->file.ptr); |
|
672 free(f); |
|
673 |
|
674 free(file.ptr); |
|
675 return -1; |
|
676 } |
|
677 cfgmgr_attach_file(f); |
|
678 } |
|
679 vs->objectfile = sstrdup(file); |
|
680 vs->objects = (HTTPObjectConfig*)f->data; |
|
681 free(file.ptr); |
|
682 |
662 |
683 |
663 |
684 // load acl config file |
664 // load acl config file |
685 file = sstrcat(2, base, aclfile); |
665 file = sstrcat(2, base, aclfile); |
686 |
666 |
687 ConfigFile *aclf = cfgmgr_get_file(file); |
667 ACLData *acldata = acl_conf_load(cfg, file); |
688 if(aclf == NULL) { |
668 if(!acldata) { |
689 aclf = malloc(sizeof(ConfigFile)); |
669 return -1; |
690 aclf->data = NULL; |
670 } |
691 aclf->file = sstrdup(file); |
671 vs->acls = acldata; |
692 aclf->reload = acl_conf_reload; |
672 |
693 aclf->last_modified = 0; |
|
694 //aclf->reload(aclf, cfg); |
|
695 if(cfgmgr_reload_file(aclf, cfg, NULL)) { |
|
696 free(aclf->file.ptr); |
|
697 free(aclf); |
|
698 |
|
699 free(file.ptr); |
|
700 return -1; |
|
701 } |
|
702 cfgmgr_attach_file(aclf); |
|
703 } |
|
704 vs->acls = aclf->data; |
|
705 free(file.ptr); |
673 free(file.ptr); |
706 |
674 |
|
675 |
707 // set the access log for the virtual server |
676 // set the access log for the virtual server |
708 // TODO: don't use always the default |
677 // TODO: don't always use the default |
709 vs->log = cfg->default_log; |
678 vs->log = cfg->default_log; |
710 |
679 |
711 ucx_map_sstr_put(cfg->host_vs, vs->host, vs); |
680 ucx_map_sstr_put(cfg->host_vs, vs->host, vs); |
712 |
681 |
713 return 0; |
682 return 0; |
714 } |
683 } |
715 |
684 |
716 |
685 int cfg_handle_dav(ServerConfiguration *cfg, ConfigNode *obj) { |
717 int object_conf_reload(ConfigFile *file, ServerConfiguration *cfg) { |
686 UcxList *backends = NULL; // list of ConfigArg* |
718 HTTPObjectConfig *old_conf = file->data; |
687 UcxAllocator a = util_pool_allocator(cfg->pool); |
719 file->data = load_obj_conf(file->file.ptr); |
688 int init_error; |
720 if(old_conf) { |
689 |
721 object_conf_unref(old_conf); |
690 // parse args |
722 } |
691 char *uri = NULL; |
723 if(file->data) { |
692 char *ppath = NULL; |
724 return 0; |
693 char *name = NULL; |
725 } else { |
694 UCX_FOREACH(elm, obj->args) { |
|
695 ConfigArg *arg = elm->data; |
|
696 if(arg->name.ptr == NULL) { |
|
697 // default: uri |
|
698 uri = arg->value.ptr; |
|
699 } else if(!sstrcasecmp(arg->name, SC("uri"))) { |
|
700 uri = arg->value.ptr; |
|
701 } else if(!sstrcasecmp(arg->name, SC("ppath"))) { |
|
702 ppath = arg->value.ptr; |
|
703 } else if(!sstrcasecmp(arg->name, SC("name"))) { |
|
704 name = arg->value.ptr; |
|
705 } |
|
706 } |
|
707 if(!uri && !ppath && !name) { |
726 return 1; |
708 return 1; |
727 } |
709 } |
728 } |
710 |
729 |
711 // get a list of all DavBackends |
730 void object_conf_ref(HTTPObjectConfig *conf) { |
712 UCX_FOREACH(elm, obj->children) { |
731 if(conf) { |
713 ConfigNode *node = elm->data; |
732 ws_atomic_inc32(&conf->ref); |
714 if(!sstrcasecmp(node->name, SC("DavBackend"))) { |
733 } |
715 if(node->type == CONFIG_NODE_DIRECTIVE) { |
734 } |
716 if(ucx_list_size(node->args) == 1) { |
735 |
717 ConfigArg *arg = node->args->data; |
736 void object_conf_unref(HTTPObjectConfig *conf) { |
718 backends = ucx_list_append(backends, arg); |
737 uint32_t ref = ws_atomic_dec32(&conf->ref); |
719 } else { |
738 if(ref == 0) { |
720 log_ereport(LOG_MISCONFIG, "DavBackend must have only one value"); |
739 printf("free HTTPObjectConfig %"PRIxPTR"\n", (intptr_t)conf); |
721 ucx_list_free(backends); |
740 pool_destroy(conf->pool); |
722 return 1; |
741 } |
723 } |
742 } |
724 } else { |
743 |
725 log_ereport(LOG_MISCONFIG, "DavBackend must be a directive"); |
744 HTTPObjectConfig* load_obj_conf(char *file) { |
726 ucx_list_free(backends); |
745 log_ereport(LOG_VERBOSE, "load_obj_conf"); |
727 return 1; |
746 |
728 } |
747 // new conf function test |
729 } |
748 ObjectConfig *cfg = load_object_config(file); |
730 } |
749 UcxAllocator *mp = cfg->parser.mp; |
731 |
750 if(cfg == NULL) { |
732 int ret = 0; |
751 return NULL; |
733 WebdavRepository *repository = pool_malloc(cfg->pool, sizeof(WebdavRepository)); |
752 } |
734 repository->vfs = NULL; |
753 |
735 repository->vfsInitData = NULL; |
754 // create object config |
736 repository->davBackends = NULL; |
755 pool_handle_t *pool = pool_create(); |
737 |
756 HTTPObjectConfig *conf = pool_calloc(pool, sizeof(HTTPObjectConfig), 1); |
738 // initialize backends |
757 conf->pool = pool; |
739 UCX_FOREACH(elm, backends) { |
758 |
740 // the DavBackend value should contain the dav class name |
759 // convert ObjectConfig to HTTPObjectConfig |
741 ConfigArg *backendArg = elm->data; |
760 |
742 |
761 // add objects |
743 WebdavType *dav = webdav_get_type((scstr_t){backendArg->value.ptr, backendArg->value.length}); |
762 conf->nobj = ucx_list_size(cfg->objects); |
744 if(!dav) { |
763 conf->objects = pool_calloc(pool, conf->nobj, sizeof(httpd_object*)); |
745 log_ereport(LOG_MISCONFIG, "Unknown webdav backend type '%s'", backendArg->value.ptr); |
|
746 ret = 1; |
|
747 break; |
|
748 } |
|
749 |
|
750 // call backend init |
|
751 // init_data can be NULL, errors will be indicated by init_error |
|
752 void *init_data = webdav_init_backend(cfg, cfg->pool, dav, obj, &init_error); |
|
753 if(init_error) { |
|
754 log_ereport(LOG_FAILURE, "Failed to initialize webdav backend %s", backendArg->value.ptr); |
|
755 ret = 1; |
|
756 break; |
|
757 } |
|
758 |
|
759 WebdavBackendInitData *davInit = pool_malloc(cfg->pool, sizeof(WebdavBackendInitData)); |
|
760 if(!davInit) { |
|
761 log_ereport(LOG_FAILURE, "Failed to initialize webdav backend %s: OOM", backendArg->value.ptr); |
|
762 ret = 1; |
|
763 break; |
|
764 } |
|
765 davInit->davType = dav; |
|
766 davInit->davInitData = init_data; |
|
767 |
|
768 repository->davBackends = ucx_list_append_a(&a, repository->davBackends, davInit); |
|
769 } |
|
770 |
|
771 // initialize vfs |
|
772 scstr_t vfs_class = serverconfig_directive_value(obj, SC("VFS")); |
|
773 if(vfs_class.length > 0) { |
|
774 VfsType *vfs = vfs_get_type((scstr_t){vfs_class.ptr, vfs_class.length}); |
|
775 if(vfs) { |
|
776 repository->vfs = vfs; |
|
777 repository->vfsInitData = vfs_init_backend(cfg, cfg->pool, vfs, obj, &init_error); |
|
778 ret = init_error; |
|
779 } else { |
|
780 log_ereport(LOG_FAILURE, "Unknown vfs type '%s'", vfs_class.ptr); |
|
781 ret = 1; |
|
782 } |
|
783 } |
|
784 |
|
785 scstr_t object = serverconfig_directive_value(obj, SC("Object")); |
|
786 if(object.length > 0) { |
|
787 repository->object = sstrdup_a(&a, object); |
|
788 if(repository->object.length != object.length) { |
|
789 // OOM |
|
790 log_ereport(LOG_FAILURE, "Cannot create webdav repository: OOM"); |
|
791 ret = 1; |
|
792 } |
|
793 } |
|
794 |
|
795 if(!ret) { |
|
796 if(name) { |
|
797 ucx_map_cstr_put(cfg->dav, name, repository); |
|
798 } else { |
|
799 log_ereport(LOG_FAILURE, "TODO: location based dav repositories not implemented"); |
|
800 ret = 1; |
|
801 } |
|
802 } |
|
803 |
|
804 return ret; |
|
805 } |
|
806 |
|
807 static int convert_objconf(ServerConfiguration *scfg, ObjectConfig *cfg, HTTPObjectConfig *conf, sstr_t file) { |
|
808 pool_handle_t *pool = conf->pool; |
764 |
809 |
765 UcxList *objlist = cfg->objects; |
810 UcxList *objlist = cfg->objects; |
766 int i = 0; |
811 int i = 0; |
767 while(objlist != NULL) { |
812 while(objlist != NULL) { |
768 ConfigObject *cob = objlist->data; |
813 ConfigObject *cob = objlist->data; |
770 // get name and ppath |
815 // get name and ppath |
771 char *name = NULL; |
816 char *name = NULL; |
772 char *ppath = NULL; |
817 char *ppath = NULL; |
773 if(cob->name.length > 0) { |
818 if(cob->name.length > 0) { |
774 name = sstrdup_pool(pool, cob->name).ptr; |
819 name = sstrdup_pool(pool, cob->name).ptr; |
|
820 if(!name) return -1; |
775 } |
821 } |
776 if(cob->ppath.length > 0) { |
822 if(cob->ppath.length > 0) { |
777 ppath = sstrdup_pool(pool, cob->ppath).ptr; |
823 ppath = sstrdup_pool(pool, cob->ppath).ptr; |
|
824 if(!ppath) return -1; |
778 } |
825 } |
779 |
826 |
780 // create and add object |
827 // create and add object |
781 httpd_object *obj = object_new(pool, name); |
828 httpd_object *obj = object_new(pool, name); |
|
829 if(!obj) return -1; |
782 obj->path = NULL; |
830 obj->path = NULL; |
783 |
831 |
784 conf->objects[i] = obj; |
832 conf->objects[i] = obj; |
785 |
833 |
786 // add directives |
834 // add directives |
787 for(int j=0;j<NUM_NSAPI_TYPES-1;j++) { |
835 for(int j=0;j<NUM_NSAPI_TYPES-1;j++) { |
788 UcxList *dirs = cob->directives[j]; |
836 UcxList *dirs = cob->directives[j]; |
789 while(dirs != NULL) { |
837 while(dirs != NULL) { |
790 ConfigDirective *cfgdir = dirs->data; |
838 ConfigDirective *cfgdir = dirs->data; |
791 |
839 |
792 directive *d = pool_malloc(pool, sizeof(directive)); |
840 directive *d = pool_malloc(pool, sizeof(directive)); |
|
841 if(!d) return -1; |
793 if(cfgdir->condition) { |
842 if(cfgdir->condition) { |
794 sstr_t expr = cfgdir->condition->param_str; |
843 sstr_t expr = cfgdir->condition->param_str; |
795 d->cond = condition_from_str(pool, expr.ptr, expr.length); |
844 d->cond = condition_from_str(pool, expr.ptr, expr.length); |
796 } else { |
845 } else { |
797 d->cond = NULL; |
846 d->cond = NULL; |
798 } |
847 } |
799 d->param = pblock_create_pool(pool, 8); |
848 d->param = pblock_create_pool(pool, 8); |
800 |
849 |
801 // add params |
850 // add params |
802 UcxList *param = cfg_param_list(cfgdir->value, mp); |
851 UcxList *param = cfg_param_list(cfgdir->value, scfg->a); |
803 while(param != NULL) { |
852 while(param != NULL) { |
804 ConfigParam *p = param->data; |
853 ConfigParam *p = param->data; |
805 pblock_nvlinsert( |
854 pblock_nvlinsert( |
806 p->name.ptr, |
855 p->name.ptr, |
807 p->name.length, |
856 p->name.length, |
832 |
881 |
833 // next |
882 // next |
834 i++; |
883 i++; |
835 objlist = objlist->next; |
884 objlist = objlist->next; |
836 } |
885 } |
|
886 |
|
887 return 0; |
|
888 } |
|
889 |
|
890 HTTPObjectConfig* objconf_load(ServerConfiguration *scfg, sstr_t file) { |
|
891 log_ereport(LOG_VERBOSE, "load_obj_conf"); |
|
892 |
|
893 int ret = 0; |
|
894 |
|
895 // create object config |
|
896 pool_handle_t *pool = scfg->pool; |
|
897 HTTPObjectConfig *conf = pool_calloc(pool, sizeof(HTTPObjectConfig), 1); |
|
898 if(!conf) { |
|
899 return NULL; |
|
900 } |
|
901 conf->pool = pool; |
|
902 |
|
903 // load obj config file |
|
904 ObjectConfig *cfg = load_object_config(file.ptr); |
|
905 if(!cfg) { |
|
906 return NULL; |
|
907 } |
|
908 |
|
909 // convert ObjectConfig to HTTPObjectConfig |
|
910 |
|
911 // add objects |
|
912 conf->nobj = ucx_list_size(cfg->objects); |
|
913 conf->objects = pool_calloc(pool, conf->nobj, sizeof(httpd_object*)); |
|
914 if(conf->objects) { |
|
915 ret = convert_objconf(scfg, cfg, conf, file); |
|
916 } else { |
|
917 ret = -1; |
|
918 } |
837 |
919 |
838 free_object_config(cfg); |
920 free_object_config(cfg); |
839 |
921 |
840 return conf; |
922 return !ret ? conf : NULL; |
841 } |
923 } |
842 |
924 |
843 int mime_conf_reload(ConfigFile *file, ServerConfiguration *cfg) { |
925 int mime_conf_load(ServerConfiguration *cfg, sstr_t file) { |
844 MimeConfig *mimecfg = load_mime_config(file->file.ptr); |
926 MimeConfig *mimecfg = load_mime_config(file.ptr); |
845 MimeMap *old_conf = file->data; |
927 if(!mimecfg) { |
846 |
928 return -1; |
847 MimeMap *mimemap = malloc(sizeof(MimeMap)); |
929 } |
848 mimemap->ref = 1; |
930 |
849 UcxMap *map = ucx_map_new((mimecfg->ntypes * 3) / 2); |
931 int ret = 0; |
850 mimemap->map = map; |
932 |
851 |
933 // cleanup in case of errors is done by the allocator |
852 // add ext type pairs |
934 MimeMap *mimemap = almalloc(cfg->a, sizeof(MimeMap)); |
853 UCX_FOREACH(md, mimecfg->directives) { |
935 UcxMap *map = ucx_map_new_a(cfg->a, (mimecfg->ntypes * 3) / 2); |
854 MimeDirective *d = md->data; |
936 |
855 // add the type for each extension to the map |
937 if(mimemap && map) { |
856 UCX_FOREACH(xl, d->exts) { |
938 mimemap->map = map; |
857 sstr_t ext = sstr(xl->data); |
939 |
858 sstr_t value = sstrdup(d->type); |
940 // add ext type pairs |
859 ucx_map_sstr_put(map, ext, value.ptr); |
941 UCX_FOREACH(md, mimecfg->directives) { |
860 } |
942 MimeDirective *d = md->data; |
861 } |
943 // add the type for each extension to the map |
862 |
944 UCX_FOREACH(xl, d->exts) { |
863 file->data = mimemap; |
945 sstr_t ext = sstr(xl->data); |
864 |
946 sstr_t value = sstrdup(d->type); |
865 if(old_conf) { |
947 if(ucx_map_sstr_put(map, ext, value.ptr)) { |
866 mime_conf_unref(old_conf); |
948 ret = -1; |
|
949 break; |
|
950 } |
|
951 } |
|
952 if(ret) { |
|
953 break; |
|
954 } |
|
955 } |
|
956 |
|
957 cfg->mimetypes = mimemap; |
|
958 } else { |
|
959 ret = -1; |
867 } |
960 } |
868 |
961 |
869 free_mime_config(mimecfg); |
962 free_mime_config(mimecfg); |
870 return 0; |
963 return ret; |
871 } |
964 } |
872 |
965 |
873 void mime_conf_ref(MimeMap *conf) { |
966 |
874 if(conf) { |
967 |
875 ws_atomic_inc32(&conf->ref); |
968 ACLData* acl_conf_load(ServerConfiguration *cfg, sstr_t file) { |
876 } |
969 ACLFile *aclfile = load_acl_file(file.ptr); |
877 } |
970 |
878 |
971 // TODO: malloc return checks |
879 void mime_conf_unref(MimeMap *conf) { |
972 |
880 uint32_t ref = ws_atomic_dec32(&conf->ref); |
973 ACLData *acldata = acl_data_new(cfg->a); |
881 if(ref == 0) { |
|
882 printf("free MimeConfig %"PRIxPTR"\n", (intptr_t)conf); |
|
883 UcxMapIterator i = ucx_map_iterator(conf->map); |
|
884 char *str; |
|
885 UCX_MAP_FOREACH(key, str, i) { |
|
886 free(str); |
|
887 } |
|
888 ucx_map_free(conf->map); |
|
889 free(conf); |
|
890 } |
|
891 } |
|
892 |
|
893 int acl_conf_reload(ConfigFile *file, ServerConfiguration *cfg) { |
|
894 ACLFile *aclfile = load_acl_file(file->file.ptr); |
|
895 |
|
896 ACLData *acldata = acl_data_new(); |
|
897 UCX_FOREACH(elm, aclfile->namedACLs) { |
974 UCX_FOREACH(elm, aclfile->namedACLs) { |
898 ACLConfig *ac = elm->data; |
975 ACLConfig *ac = elm->data; |
899 ACLList *acl = acl_config_convert(cfg, ac); |
976 ACLList *acl = acl_config_convert(cfg, ac); |
900 log_ereport(LOG_VERBOSE, "add acl: %.*s", (int)ac->id.length, ac->id.ptr); |
977 log_ereport(LOG_VERBOSE, "add acl: %.*s", (int)ac->id.length, ac->id.ptr); |
901 ucx_map_sstr_put(acldata->namedACLs, ac->id, acl); |
978 ucx_map_sstr_put(acldata->namedACLs, ac->id, acl); |
902 } |
979 } |
903 free_acl_file(aclfile); |
980 free_acl_file(aclfile); |
904 |
981 |
905 ACLData *old_data = file->data; |
982 return acldata; |
906 file->data = acldata; |
|
907 if(old_data) { |
|
908 acl_data_unref(old_data); |
|
909 } |
|
910 |
|
911 return 0; |
|
912 } |
983 } |
913 |
984 |
914 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) { |
985 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) { |
915 WSAcl *acllist = malloc(sizeof(WSAcl)); |
986 UcxAllocator *a = cfg->a; |
|
987 |
|
988 WSAcl *acllist = almalloc(cfg->a, sizeof(WSAcl)); |
916 acllist->acl.check = (acl_check_f)wsacl_check; |
989 acllist->acl.check = (acl_check_f)wsacl_check; |
917 acllist->acl.authdb = NULL; |
990 acllist->acl.authdb = NULL; |
918 acllist->acl.authprompt = NULL; |
991 acllist->acl.authprompt = NULL; |
919 acllist->acl.isextern = 0; |
992 acllist->acl.isextern = 0; |
920 acllist->ace = NULL; |
993 acllist->ace = NULL; |
923 if(acl->type.ptr && !sstrcmp(acl->type, sstr("fs"))) { |
996 if(acl->type.ptr && !sstrcmp(acl->type, sstr("fs"))) { |
924 acllist->acl.isextern = 1; |
997 acllist->acl.isextern = 1; |
925 } |
998 } |
926 |
999 |
927 size_t s = ucx_list_size(acl->entries); |
1000 size_t s = ucx_list_size(acl->entries); |
928 WSAce **aces = calloc(s, sizeof(WSAce*)); |
1001 WSAce **tmp_aces = calloc(s, sizeof(WSAce*)); |
929 WSAce **eces = calloc(s, sizeof(WSAce*)); |
1002 WSAce **tmp_eces = calloc(s, sizeof(WSAce*)); |
930 int ai = 0; |
1003 int ai = 0; |
931 int ei = 0; |
1004 int ei = 0; |
932 |
1005 |
933 // convert entries |
1006 // convert entries |
934 UCX_FOREACH(elm, acl->entries) { |
1007 UCX_FOREACH(elm, acl->entries) { |
935 ACEConfig *acecfg = elm->data; |
1008 ACEConfig *acecfg = elm->data; |
936 |
1009 |
937 // copy data |
1010 // copy data |
938 WSAce *ace = malloc(sizeof(WSAce)); |
1011 WSAce *ace = almalloc(a, sizeof(WSAce)); |
939 ace->access_mask = acecfg->access_mask; |
1012 ace->access_mask = acecfg->access_mask; |
940 ace->flags = acecfg->flags; |
1013 ace->flags = acecfg->flags; |
941 ace->type = acecfg->type; |
1014 ace->type = acecfg->type; |
942 ace->who = sstrdup(acecfg->who).ptr; |
1015 ace->who = sstrdup_a(a, acecfg->who).ptr; |
943 |
1016 |
944 // add the entry to the correct array |
1017 // add the entry to the correct array |
945 if(ace->type >= ACL_TYPE_AUDIT) { |
1018 if(ace->type >= ACL_TYPE_AUDIT) { |
946 eces[ei] = ace; |
1019 tmp_eces[ei] = ace; |
947 ei++; |
1020 ei++; |
948 } else { |
1021 } else { |
949 aces[ai] = ace; |
1022 tmp_aces[ai] = ace; |
950 ai++; |
1023 ai++; |
951 } |
1024 } |
952 } |
1025 } |
953 |
1026 |
954 // create new entrie arrays with perfect fitting size |
1027 // create new entrie arrays with perfect fitting size |
955 if(ai > 0) { |
1028 if(ai > 0) { |
956 acllist->ace = calloc(ai, sizeof(WSAce*)); |
1029 acllist->ace = alcalloc(a, ai, sizeof(WSAce*)); |
957 } |
1030 } |
958 if(ei > 0) { |
1031 if(ei > 0) { |
959 acllist->ece = calloc(ei, sizeof(WSAce*)); |
1032 acllist->ece = alcalloc(a, ei, sizeof(WSAce*)); |
960 } |
1033 } |
961 memcpy(acllist->ace, aces, ai*sizeof(WSAce*)); |
1034 memcpy(acllist->ace, tmp_aces, ai*sizeof(WSAce*)); |
962 memcpy(acllist->ece, eces, ei*sizeof(WSAce*)); |
1035 memcpy(acllist->ece, tmp_eces, ei*sizeof(WSAce*)); |
963 acllist->acenum = ai; |
1036 acllist->acenum = ai; |
964 acllist->ecenum = ei; |
1037 acllist->ecenum = ei; |
965 |
1038 |
966 free(aces); |
1039 free(tmp_aces); |
967 free(eces); |
1040 free(tmp_eces); |
968 |
1041 |
969 // get authentication information |
1042 // get authentication information |
970 if(acl->authparam) { |
1043 if(acl->authparam) { |
971 sstr_t authdb_str = cfg_param_get(acl->authparam, sstr("authdb")); |
1044 sstr_t authdb_str = cfg_param_get(acl->authparam, sstr("authdb")); |
972 sstr_t prompt_str = cfg_param_get(acl->authparam, sstr("prompt")); |
1045 sstr_t prompt_str = cfg_param_get(acl->authparam, sstr("prompt")); |
973 |
1046 |
974 if(authdb_str.ptr) { |
1047 if(authdb_str.ptr) { |
975 AuthDB *authdb = ucx_map_sstr_get(cfg->authdbs, authdb_str); |
1048 AuthDB *authdb = ucx_map_sstr_get(cfg->authdbs, authdb_str); |
976 acllist->acl.authdb = authdb; |
1049 acllist->acl.authdb = authdb; |
977 if(authdb && prompt_str.ptr) { |
1050 if(authdb && prompt_str.ptr) { |
978 acllist->acl.authprompt = sstrdup(prompt_str).ptr; |
1051 acllist->acl.authprompt = sstrdup_a(a, prompt_str).ptr; |
979 } |
1052 } |
980 } |
1053 } |
981 } |
1054 } |
982 |
1055 |
983 return &acllist->acl; |
1056 return &acllist->acl; |
984 } |
1057 } |
985 |
1058 |
986 int keyfile_reload(ConfigFile *file, ServerConfiguration *cfg) { |
1059 AuthDB* keyfile_load(ServerConfiguration *cfg, scstr_t file) { |
987 KeyfileConfig *conf = load_keyfile_config(file->file.ptr); |
1060 Keyfile *keyfile = keyfile_new(cfg->a); |
|
1061 if(!keyfile) { |
|
1062 return NULL; |
|
1063 } |
|
1064 |
|
1065 KeyfileConfig *conf = load_keyfile_config(file.ptr); |
988 if(!conf) { |
1066 if(!conf) { |
989 return 1; |
1067 return NULL; |
990 } |
1068 } |
991 |
1069 |
992 Keyfile *keyfile = keyfile_new(); |
1070 AuthDB *ret = &keyfile->authdb; |
993 |
1071 |
994 UCX_FOREACH(elm, conf->users) { |
1072 UCX_FOREACH(elm, conf->users) { |
995 KeyfileEntry *user = elm->data; |
1073 KeyfileEntry *user = elm->data; |
996 keyfile_add_user( |
1074 if(keyfile_add_user( |
997 keyfile, |
1075 keyfile, |
998 user->name, |
1076 user->name, |
999 user->hashtype, |
1077 user->hashtype, |
1000 user->hashdata, |
1078 user->hashdata, |
1001 user->groups, |
1079 user->groups, |
1002 user->numgroups); |
1080 user->numgroups)) |
|
1081 { |
|
1082 ret = NULL; |
|
1083 break; |
|
1084 } |
1003 } |
1085 } |
1004 |
1086 |
1005 free_keyfile_config(conf); |
1087 free_keyfile_config(conf); |
1006 |
1088 |
1007 Keyfile *old_data = file->data; |
1089 return ret; |
1008 file->data = keyfile; |
1090 } |
1009 if(old_data) { |
1091 |
1010 keyfile_unref(old_data); |
1092 pblock* config_obj2pblock(pool_handle_t *pool, ConfigNode *obj) { |
1011 } |
1093 pblock *pb = pblock_create_pool(pool, 8); |
1012 |
1094 UCX_FOREACH(elm, obj->children) { |
1013 return 0; |
1095 ConfigNode *d = elm->data; |
1014 } |
1096 if(d->type == CONFIG_NODE_DIRECTIVE && d->name.length > 0 && ucx_list_size(d->args) == 1) { |
1015 |
1097 ConfigArg *arg = d->args->data; |
1016 |
1098 pblock_nvlinsert(d->name.ptr, d->name.length, arg->value.ptr, arg->value.length, pb); |
1017 sstr_t cfg_load_file(sstr_t file) { |
1099 } |
1018 sstr_t r; |
1100 } |
1019 r.ptr = NULL; |
1101 return pb; |
1020 r.length = 0; |
1102 } |
1021 |
|
1022 if(!file.ptr) { |
|
1023 return r; |
|
1024 } |
|
1025 |
|
1026 sstr_t f = sstrdup(file); |
|
1027 FILE *in = fopen(f.ptr, "r"); |
|
1028 if(!in) { |
|
1029 return r; |
|
1030 } |
|
1031 |
|
1032 UcxBuffer *buf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
|
1033 if(!buf) { |
|
1034 fclose(in); |
|
1035 return r; |
|
1036 } |
|
1037 |
|
1038 if(ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write) == 0) { |
|
1039 fclose(in); |
|
1040 ucx_buffer_free(buf); |
|
1041 return r; |
|
1042 } |
|
1043 |
|
1044 r.ptr = buf->space; |
|
1045 r.length = buf->pos; |
|
1046 |
|
1047 free(buf); |
|
1048 fclose(in); |
|
1049 |
|
1050 return r; |
|
1051 } |
|