src/server/daemon/config.c

changeset 385
a1f4cb076d2f
parent 373
f78a585e1a2f
child 388
30d29ef5b79a
equal deleted inserted replaced
210:21274e5950af 385:a1f4cb076d2f
46 #include "log.h" 46 #include "log.h"
47 #include "event.h" 47 #include "event.h"
48 #include "threadpools.h" 48 #include "threadpools.h"
49 #include "ldap_auth.h" 49 #include "ldap_auth.h"
50 #include "configmanager.h" 50 #include "configmanager.h"
51 #include "resourcepool.h"
51 52
52 #include "vserver.h" 53 #include "vserver.h"
53 #include "../util/pblock.h" 54 #include "../util/pblock.h"
54 #include "../util/util.h" 55 #include "../util/util.h"
55 #include "../util/atomic.h" 56 #include "../util/atomic.h"
56 #include "ucx/buffer.h" 57 #include "ucx/buffer.h"
57 58
58 pool_handle_t *cfg_pool; 59 pool_handle_t *init_pool;
59 60
60 // TODO: Funktion für ConfigDirective -> directive 61 char* cfg_config_file_path(const char *file) {
61 // TODO: Funktion für UcxList parameter list -> pblock 62 sstr_t base = ST("config/");
63 sstr_t path = sstrcat(2, base, scstr(file));
64 return path.ptr;
65 }
62 66
63 int load_init_conf(char *file) { 67 int load_init_conf(char *file) {
64 log_ereport(LOG_VERBOSE, "load_init_conf"); 68 log_ereport(LOG_VERBOSE, "load_init_conf");
65 69
66 InitConfig *cfg = load_init_config(file); 70 InitConfig *cfg = load_init_config(file);
68 log_ereport(LOG_FAILURE, "Cannot load init.conf"); 72 log_ereport(LOG_FAILURE, "Cannot load init.conf");
69 return 1; 73 return 1;
70 } 74 }
71 UcxAllocator *mp = cfg->parser.mp; 75 UcxAllocator *mp = cfg->parser.mp;
72 76
73 cfg_pool = pool_create(); // one pool for one Configuration 77 init_pool = pool_create(); // one pool for one Configuration
74 UcxList *dirs = cfg->directives; 78 UcxList *dirs = cfg->directives;
75 while(dirs != NULL) { 79 while(dirs != NULL) {
76 ConfigDirective *dir = dirs->data; 80 ConfigDirective *dir = dirs->data;
77 81
78 /* create NSAPI directive */ 82 /* create NSAPI directive */
79 directive *d = malloc(sizeof(directive)); 83 directive *d = malloc(sizeof(directive));
80 d->param = pblock_create_pool(cfg_pool, 8); 84 d->param = pblock_create_pool(init_pool, 8);
81 UcxList *param = cfg_param_list(dir->value, mp); 85 UcxList *param = cfg_param_list(dir->value, mp);
82 while(param != NULL) { 86 while(param != NULL) {
83 ConfigParam *p = param->data; 87 ConfigParam *p = param->data;
84 pblock_nvlinsert( 88 pblock_nvlinsert(
85 p->name.ptr, 89 p->name.ptr,
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,
812 } 861 }
813 862
814 // get function 863 // get function
815 char *func_name = pblock_findval("fn", d->param); 864 char *func_name = pblock_findval("fn", d->param);
816 if(!func_name) { 865 if(!func_name) {
817 log_ereport(LOG_MISCONFIG, "%s: Missing fn parameter", file); 866 log_ereport(LOG_MISCONFIG, "%s: Missing fn parameter", file.ptr);
818 return NULL; 867 return -1;
819 } 868 }
820 d->func = get_function(func_name); 869 d->func = get_function(func_name);
821 if(!d->func) { 870 if(!d->func) {
822 log_ereport(LOG_MISCONFIG, "func %s not found", func_name); 871 log_ereport(LOG_MISCONFIG, "func %s not found", func_name);
823 return NULL; 872 return -1;
824 } 873 }
825 874
826 dirs = dirs->next; 875 dirs = dirs->next;
827 876
828 // add function to dtable 877 // add function to dtable
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 }

mercurial