1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "../public/nsapi.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39
40 #include <ucx/string.h>
41 #include <ucx/utils.h>
42
43 #include "httplistener.h"
44 #include "config.h"
45 #include "func.h"
46 #include "log.h"
47 #include "event.h"
48 #include "threadpools.h"
49 #include "ldap_auth.h"
50 #include "configmanager.h"
51
52 #include "vserver.h"
53 #include "../util/pblock.h"
54 #include "../util/util.h"
55 #include "../util/atomic.h"
56 #include "ucx/buffer.h"
57
58 pool_handle_t *cfg_pool;
59
60
61
62
63 int load_init_conf(
char *file) {
64 log_ereport(
LOG_VERBOSE,
"load_init_conf");
65
66 InitConfig *cfg = load_init_config(file);
67 if(cfg ==
NULL) {
68 log_ereport(
LOG_FAILURE,
"Cannot load init.conf");
69 return 1;
70 }
71 UcxAllocator *mp = cfg->parser.mp;
72
73 cfg_pool = pool_create();
74 UcxList *dirs = cfg->directives;
75 while(dirs !=
NULL) {
76 ConfigDirective *dir = dirs->data;
77
78
79 directive *d = malloc(
sizeof(directive));
80 d->param = pblock_create_pool(cfg_pool,
8);
81 UcxList *param = cfg_param_list(dir->value, mp);
82 while(param !=
NULL) {
83 ConfigParam *p = param->data;
84 pblock_nvlinsert(
85 p->name.ptr,
86 p->name.length,
87 p->value.ptr,
88 p->value.length,
89 d->param);
90
91 param = param->next;
92 }
93
94
95 char *func_name = pblock_findval(
"fn", d->param);
96 d->func = get_function(func_name);
97 if(d->func ==
NULL) {
98 pblock_free(d->param);
99 free(d);
100
101 log_ereport(
102 LOG_MISCONFIG,
103 "Cannot find Init function %s",
104 func_name);
105 return 1;
106 }
107
108
109 int ret = d->func->func(d->param,
NULL,
NULL);
110 if(ret !=
REQ_PROCEED && ret !=
REQ_NOACTION) {
111 log_ereport(
112 LOG_FAILURE,
113 "Error running Init function %s",
114 func_name);
115 pblock_free(d->param);
116 free(d);
117 return 1;
118 }
119
120 pblock_free(d->param);
121 free(d);
122 dirs = dirs->next;
123 }
124
125 free_init_config(cfg);
126
127 return 0;
128 }
129
130 ServerConfiguration* load_server_conf(ServerConfiguration *old,
char *file) {
131 log_ereport(
LOG_VERBOSE,
"load_server_conf");
132
133 ServerConfig *serverconf = load_server_config(file);
134 if(serverconf ==
NULL) {
135 log_ereport(
LOG_FAILURE,
"Cannot load server.conf");
136 }
137 ServerConfiguration *serverconfig = calloc(
1,
sizeof(ServerConfiguration));
138 serverconfig->ref =
1;
139 serverconfig->pool = pool_create();
140 serverconfig->listeners =
NULL;
141 serverconfig->host_vs = ucx_map_new(
16);
142 serverconfig->authdbs = ucx_map_new(
16);
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 UcxList *lfl = ucx_map_sstr_get(serverconf->objects, sstrn(
"LogFile",
7));
165 if(lfl !=
NULL) {
166 ServerConfigObject *logobj = lfl->data;
167 if(logobj ==
NULL) {
168
169 return NULL;
170 }
171
172 int ret = cfg_handle_logfile(serverconfig, logobj);
173 if(ret !=
0) {
174
175 return NULL;
176 }
177 }
else {
178
179 return NULL;
180 }
181
182 UcxList *list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Runtime",
7));
183 UCX_FOREACH(elm, list) {
184 ServerConfigObject *scfgobj = elm->data;
185 if(cfg_handle_runtime(serverconfig, scfgobj)) {
186
187 return NULL;
188 }
189 }
190
191 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Threadpool",
10));
192 UCX_FOREACH(elm, list) {
193 if(cfg_handle_threadpool(serverconfig, elm->data)) {
194 return NULL;
195 }
196 }
197
198 if(check_thread_pool_cfg() !=
0) {
199
200 return NULL;
201 }
202
203 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"EventHandler",
12));
204 UCX_FOREACH(elm, list) {
205 if(cfg_handle_eventhandler(
206 serverconfig, (ServerConfigObject*)elm->data)) {
207
208 return NULL;
209 }
210 }
211
212 if(check_event_handler_cfg() !=
0) {
213
214 return NULL;
215 }
216
217 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"AccessLog",
9));
218 UCX_FOREACH(elm, list) {
219 ServerConfigObject *scfgobj = elm->data;
220 if(cfg_handle_accesslog(serverconfig, scfgobj)) {
221 return NULL;
222 }
223 }
224
225 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"AuthDB",
6));
226 UCX_FOREACH(elm, list) {
227 ServerConfigObject *scfgobj = elm->data;
228 if(cfg_handle_authdb(serverconfig, scfgobj)) {
229 return NULL;
230 }
231 }
232
233 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Listener",
8));
234 UCX_FOREACH(elm, list) {
235 ServerConfigObject *scfgobj = elm->data;
236 if(cfg_handle_listener(serverconfig, scfgobj)) {
237 return NULL;
238 }
239 }
240
241 list = ucx_map_sstr_get(serverconf->objects, sstrn(
"VirtualServer",
13));
242 UCX_FOREACH(elm, list) {
243 ServerConfigObject *scfgobj = elm->data;
244 if(cfg_handle_vs(serverconfig, scfgobj)) {
245 return NULL;
246 }
247 }
248
249
250
251 UcxList *ls = serverconfig->listeners;
252 while(ls) {
253 HttpListener *listener = ls->data;
254
255 sstr_t vsname = sstr(listener->default_vs.vs_name);
256
257
258
259 UcxMapIterator iter = ucx_map_iterator(serverconfig->host_vs);
260 VirtualServer *vs;
261 UCX_MAP_FOREACH(key, vs, iter) {
262 if(!sstrcmp(vsname, vs->name)) {
263 listener->default_vs.vs = vs;
264 break;
265 }
266 }
267
268 ls = ls->next;
269 }
270
271 free_server_config(serverconf);
272 return serverconfig;
273 }
274
275 void cfg_ref(ServerConfiguration *cfg) {
276 ws_atomic_inc32(&cfg->ref);
277 }
278
279 void cfg_unref(ServerConfiguration *cfg) {
280 uint32_t ref = ws_atomic_dec32(&cfg->ref);
281 if(ref ==
0) {
282
283 printf(
"free ServerConfiguration %""\n"PRIxPTR, (
intptr_t)cfg);
284 }
285 }
286
287
288 void init_server_config_parser() {
289
290 }
291
292 int cfg_handle_runtime(ServerConfiguration *cfg, ServerConfigObject *obj) {
293 sstr_t user = cfg_directivelist_get_str(obj->directives, sstr(
"User"));
294 if(user.ptr) {
295 cfg->user = sstrdup_pool(cfg->pool, user);
296 }
297 sstr_t tmp = cfg_directivelist_get_str(obj->directives, sstr(
"Temp"));
298 if(tmp.ptr) {
299 cfg->tmp = sstrdup_pool(cfg->pool, tmp);
300 }
else {
301 log_ereport(
LOG_MISCONFIG,
"no temporary directory specified");
302 return -
1;
303 }
304
305
306 sstr_t mf = cfg_directivelist_get_str(obj->directives, sstr(
"MimeFile"));
307 sstr_t base = sstr(
"config/");
308 sstr_t file = sstrcat(
2, base, mf);
309
310 ConfigFile *f = cfgmgr_get_file(file);
311 if(f ==
NULL) {
312 f = malloc(
sizeof(ConfigFile));
313 f->data =
NULL;
314 f->file = sstrdup(file);
315 f->reload = mime_conf_reload;
316 f->last_modified =
0;
317
318
319
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
332 free(file.ptr);
333 return 0;
334 }
335
336 int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj) {
337 sstr_t file = cfg_directivelist_get_str(obj->directives, sstr(
"File"));
338 sstr_t lvl = cfg_directivelist_get_str(obj->directives, sstr(
"Level"));
339
340 if(file.ptr ==
NULL || lvl.ptr ==
NULL) {
341
342 return -
1;
343 }
344
345 LogConfig logcfg;
346 logcfg.file = sstrdup(file).ptr;
347 logcfg.level = sstrdup(lvl).ptr;
348 logcfg.log_stdout =
0;
349 logcfg.log_stderr =
0;
350
351
352 int ret = init_log_file(&logcfg);
353
354 free(logcfg.file);
355 free(logcfg.level);
356
357 return ret;
358 }
359
360 int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj) {
361 ThreadPoolConfig poolcfg;
362 poolcfg.min_threads =
4;
363 poolcfg.min_threads =
4;
364 poolcfg.max_threads =
8;
365 poolcfg.queue_size =
64;
366 poolcfg.stack_size =
262144;
367
368 sstr_t name = cfg_directivelist_get_str(
369 obj->directives,
370 sstr(
"Name"));
371 sstr_t min = cfg_directivelist_get_str(
372 obj->directives,
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
384
385 if(name.length ==
0) {
386
387 return 1;
388 }
389
390 if(min.length !=
0) {
391 min = sstrdup(min);
392 poolcfg.min_threads = atoi(min.ptr);
393 free(min.ptr);
394 }
395
396 if(max.length !=
0) {
397 max = sstrdup(max);
398 poolcfg.max_threads = atoi(max.ptr);
399 free(max.ptr);
400 }
401
402 if(stack.length !=
0) {
403 stack = sstrdup(stack);
404 poolcfg.stack_size = atoi(stack.ptr);
405 free(stack.ptr);
406 }
407
408 if(queue.length !=
0) {
409 queue = sstrdup(queue);
410 poolcfg.queue_size = atoi(queue.ptr);
411 free(queue.ptr);
412 }
413
414 create_threadpool(name, &poolcfg);
415
416 return 0;
417 }
418
419 int cfg_handle_eventhandler(ServerConfiguration *c, ServerConfigObject *obj) {
420 EventHandlerConfig evcfg;
421
422 sstr_t name = cfg_directivelist_get_str(obj->directives, sstr(
"Name"));
423 sstr_t threads = cfg_directivelist_get_str(
424 obj->directives,
425 sstr(
"Threads"));
426 sstr_t isdefault = cfg_directivelist_get_str(
427 obj->directives,
428 sstr(
"Default"));
429
430 evcfg.name = name;
431
432 sstr_t s = sstrdup(threads);
433 evcfg.nthreads = atoi(s.ptr);
434 free(s.ptr);
435
436 evcfg.isdefault = util_getboolean(isdefault.ptr,
0);
437
438 return create_event_handler(&evcfg);
439 }
440
441 int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj) {
442
443
444 sstr_t file = cfg_directivelist_get_str(obj->directives, sstr(
"File"));
445 if(file.ptr ==
NULL) {
446 return 0;
447 }
448 sstr_t format;
449 format.ptr =
NULL;
450 format.length =
0;
451
452
453 LogFile *log_file = get_access_log_file(file);
454 if(!log_file) {
455
456 return 0;
457 }
458 AccessLog *log = pool_malloc(cfg->pool,
sizeof(AccessLog));
459 log->file = sstrdup_pool(cfg->pool, file);
460 log->format = format;
461 log->log = log_file;
462 cfg->logfiles = ucx_list_append(cfg->logfiles, log);
463
464 if(!cfg->default_log) {
465 cfg->default_log = log;
466 }
467
468 return 0;
469 }
470
471 int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) {
472 sstr_t name = cfg_directivelist_get_str(obj->directives, sstr(
"Name"));
473 sstr_t type = cfg_directivelist_get_str(obj->directives, sstr(
"Type"));
474
475 if(!sstrcmp(type, sstr(
"ldap"))) {
476 LDAPConfig conf;
477
478 sstr_t host = cfg_directivelist_get_str(
479 obj->directives,
480 sstr(
"Host"));
481 sstr_t port = cfg_directivelist_get_str(
482 obj->directives,
483 sstr(
"Port"));
484 sstr_t basedn = cfg_directivelist_get_str(
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);
502 conf.basedn = basedn.ptr;
503 conf.binddn = binddn.ptr;
504 conf.bindpw = basepw.ptr;
505
506 name = sstrdup(name);
507
508 AuthDB *authdb = create_ldap_authdb(name.ptr, &conf);
509 ucx_map_sstr_put(cfg->authdbs, name, authdb);
510
511
512
513
514
515
516
517
518
519
520
521 }
else if(!sstrcmp(type, sstr(
"keyfile"))) {
522
523 sstr_t file = cfg_directivelist_get_str(
524 obj->directives,
525 sstr(
"File"));
526 if(file.length ==
0) {
527 log_ereport(
528 LOG_MISCONFIG,
529 "missing File parameter for keyfile authdb");
530 return 1;
531 }
532
533
534 ConfigFile *f = cfgmgr_get_file(file);
535 if(f ==
NULL) {
536 f = malloc(
sizeof(ConfigFile));
537 f->data =
NULL;
538 f->file = sstrdup(file);
539 f->reload = keyfile_reload;
540 f->last_modified =
0;
541
542 if(cfgmgr_reload_file(f, cfg,
NULL)) {
543 free(f->file.ptr);
544 free(f);
545 return -
1;
546 }
547 cfgmgr_attach_file(f);
548 }
549
550
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;
557 }
558
559 int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj) {
560 ListenerConfig lc;
561 ZERO(&lc,
sizeof(ListenerConfig));
562 lc.cfg = cfg;
563 lc.port =
8080;
564 lc.nacceptors =
1;
565
566
567 lc.name = sstrdup(cfg_directivelist_get_str(
568 obj->directives,
569 sstr(
"Name")));
570 lc.port = atoi(cfg_directivelist_get_str(
571 obj->directives,
572 sstr(
"Port")).ptr);
573 lc.vs = sstrdup(cfg_directivelist_get_str(
574 obj->directives,
575 sstr(
"DefaultVS")));
576 lc.threadpool = sstrdup(cfg_directivelist_get_str(
577 obj->directives,
578 sstr(
"Threadpool")));
579
580 sstr_t blockingio = cfg_directivelist_get_str(
581 obj->directives,
582 sstr(
"BlockingIO"));
583 if(blockingio.ptr) {
584 lc.blockingio = util_getboolean_s(blockingio,
WS_FALSE);
585 }
586
587 sstr_t ssl = cfg_directivelist_get_str(obj->directives,
S(
"SSL"));
588 if(util_getboolean_s(ssl,
WS_FALSE)) {
589 sstr_t cert = cfg_directivelist_get_str(obj->directives,
S(
"Cert"));
590 sstr_t privkey = cfg_directivelist_get_str(obj->directives,
S(
"Key"));
591 sstr_t chain = cfg_directivelist_get_str(obj->directives,
S(
"CertChain"));
592 sstr_t disableprot = cfg_directivelist_get_str(
593 obj->directives,
594 S(
"SSLDisableProtocol"));
595
596 WSBool config_ok =
WS_TRUE;
597
598 if(!cert.ptr && !chain.ptr) {
599 log_ereport(
600 LOG_MISCONFIG,
601 "SSL Listener %s: Missing Cert or ChainCert directive",
602 lc.name.ptr);
603 config_ok =
WS_FALSE;
604 }
605 if(!privkey.ptr) {
606 log_ereport(
607 LOG_MISCONFIG,
608 "SSL Listener %s: Missing Key directive",
609 lc.name.ptr);
610 config_ok =
WS_FALSE;
611 }
612
613 if(config_ok) {
614 lc.certfile = cert;
615 lc.privkeyfile = privkey;
616 lc.chainfile = chain;
617 lc.disable_proto = disableprot;
618 lc.ssl =
WS_TRUE;
619 }
620 }
else {
621 lc.ssl =
WS_FALSE;
622 }
623
624
625
626 HttpListener *listener = http_listener_create(&lc);
627 if(!listener) {
628 return 1;
629 }
630
631 listener->default_vs.vs_name = lc.vs.ptr;
632 cfg->listeners = ucx_list_append(cfg->listeners, listener);
633
634 return 0;
635 }
636
637 int cfg_handle_vs(ServerConfiguration *cfg, ServerConfigObject *obj) {
638 VirtualServer *vs = vs_new();
639
640 vs->name = sstrdup(cfg_directivelist_get_str(
641 obj->directives,
642 sstr(
"Name")));
643 vs->host = sstrdup(cfg_directivelist_get_str(
644 obj->directives,
645 sstr(
"Host")));
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
656
657 sstr_t base = sstr(
"config/");
658 sstr_t file = sstrcat(
2, base, objfile);
659 file = sstrcat(
2, base, objfile);
660
661
662 ConfigFile *f = cfgmgr_get_file(file);
663 if(f ==
NULL) {
664 f = malloc(
sizeof(ConfigFile));
665 f->data =
NULL;
666 f->file = sstrdup(file);
667 f->reload = object_conf_reload;
668 f->last_modified =
0;
669
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
683
684
685 file = sstrcat(
2, base, aclfile);
686
687 ConfigFile *aclf = cfgmgr_get_file(file);
688 if(aclf ==
NULL) {
689 aclf = malloc(
sizeof(ConfigFile));
690 aclf->data =
NULL;
691 aclf->file = sstrdup(file);
692 aclf->reload = acl_conf_reload;
693 aclf->last_modified =
0;
694
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);
706
707
708
709 vs->log = cfg->default_log;
710
711 ucx_map_sstr_put(cfg->host_vs, vs->host, vs);
712
713 return 0;
714 }
715
716
717 int object_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
718 HTTPObjectConfig *old_conf = file->data;
719 file->data = load_obj_conf(file->file.ptr);
720 if(old_conf) {
721 object_conf_unref(old_conf);
722 }
723 if(file->data) {
724 return 0;
725 }
else {
726 return 1;
727 }
728 }
729
730 void object_conf_ref(HTTPObjectConfig *conf) {
731 if(conf) {
732 ws_atomic_inc32(&conf->ref);
733 }
734 }
735
736 void object_conf_unref(HTTPObjectConfig *conf) {
737 uint32_t ref = ws_atomic_dec32(&conf->ref);
738 if(ref ==
0) {
739 printf(
"free HTTPObjectConfig %""\n"PRIxPTR, (
intptr_t)conf);
740 pool_destroy(conf->pool);
741 }
742 }
743
744 HTTPObjectConfig* load_obj_conf(
char *file) {
745 log_ereport(
LOG_VERBOSE,
"load_obj_conf");
746
747
748 ObjectConfig *cfg = load_object_config(file);
749 UcxAllocator *mp = cfg->parser.mp;
750 if(cfg ==
NULL) {
751 return NULL;
752 }
753
754
755 pool_handle_t *pool = pool_create();
756 HTTPObjectConfig *conf = pool_calloc(pool,
sizeof(HTTPObjectConfig),
1);
757 conf->pool = pool;
758
759
760
761
762 conf->nobj = ucx_list_size(cfg->objects);
763 conf->objects = pool_calloc(pool, conf->nobj,
sizeof(httpd_object*));
764
765 UcxList *objlist = cfg->objects;
766 int i =
0;
767 while(objlist !=
NULL) {
768 ConfigObject *cob = objlist->data;
769
770
771 char *name =
NULL;
772 char *ppath =
NULL;
773 if(cob->name.length >
0) {
774 name = sstrdup_pool(pool, cob->name).ptr;
775 }
776 if(cob->ppath.length >
0) {
777 ppath = sstrdup_pool(pool, cob->ppath).ptr;
778 }
779
780
781 httpd_object *obj = object_new(pool, name);
782 obj->path =
NULL;
783
784 conf->objects[i] = obj;
785
786
787 for(
int j=
0;j<
NUM_NSAPI_TYPES-
1;j++) {
788 UcxList *dirs = cob->directives[j];
789 while(dirs !=
NULL) {
790 ConfigDirective *cfgdir = dirs->data;
791
792 directive *d = pool_malloc(pool,
sizeof(directive));
793 if(cfgdir->condition) {
794 sstr_t expr = cfgdir->condition->param_str;
795 d->cond = condition_from_str(pool, expr.ptr, expr.length);
796 }
else {
797 d->cond =
NULL;
798 }
799 d->param = pblock_create_pool(pool,
8);
800
801
802 UcxList *param = cfg_param_list(cfgdir->value, mp);
803 while(param !=
NULL) {
804 ConfigParam *p = param->data;
805 pblock_nvlinsert(
806 p->name.ptr,
807 p->name.length,
808 p->value.ptr,
809 p->value.length,
810 d->param);
811 param = param->next;
812 }
813
814
815 char *func_name = pblock_findval(
"fn", d->param);
816 if(!func_name) {
817 log_ereport(
LOG_MISCONFIG,
"%s: Missing fn parameter", file);
818 return NULL;
819 }
820 d->func = get_function(func_name);
821 if(!d->func) {
822 log_ereport(
LOG_MISCONFIG,
"func %s not found", func_name);
823 return NULL;
824 }
825
826 dirs = dirs->next;
827
828
829 object_add_directive(obj, d, cfgdir->type_num);
830 }
831 }
832
833
834 i++;
835 objlist = objlist->next;
836 }
837
838 free_object_config(cfg);
839
840 return conf;
841 }
842
843 int mime_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
844 MimeConfig *mimecfg = load_mime_config(file->file.ptr);
845 MimeMap *old_conf = file->data;
846
847 MimeMap *mimemap = malloc(
sizeof(MimeMap));
848 mimemap->ref =
1;
849 UcxMap *map = ucx_map_new((mimecfg->ntypes *
3) /
2);
850 mimemap->map = map;
851
852
853 UCX_FOREACH(md, mimecfg->directives) {
854 MimeDirective *d = md->data;
855
856 UCX_FOREACH(xl, d->exts) {
857 sstr_t ext = sstr(xl->data);
858 sstr_t value = sstrdup(d->type);
859 ucx_map_sstr_put(map, ext, value.ptr);
860 }
861 }
862
863 file->data = mimemap;
864
865 if(old_conf) {
866 mime_conf_unref(old_conf);
867 }
868
869 free_mime_config(mimecfg);
870 return 0;
871 }
872
873 void mime_conf_ref(MimeMap *conf) {
874 if(conf) {
875 ws_atomic_inc32(&conf->ref);
876 }
877 }
878
879 void mime_conf_unref(MimeMap *conf) {
880 uint32_t ref = ws_atomic_dec32(&conf->ref);
881 if(ref ==
0) {
882 printf(
"free MimeConfig %""\n"PRIxPTR, (
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) {
898 ACLConfig *ac = elm->data;
899 ACLList *acl = acl_config_convert(cfg, ac);
900 log_ereport(
LOG_VERBOSE,
"add acl: %.*s", (
int)ac->id.length, ac->id.ptr);
901 ucx_map_sstr_put(acldata->namedACLs, ac->id, acl);
902 }
903 free_acl_file(aclfile);
904
905 ACLData *old_data = file->data;
906 file->data = acldata;
907 if(old_data) {
908 acl_data_unref(old_data);
909 }
910
911 return 0;
912 }
913
914 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) {
915 WSAcl *acllist = malloc(
sizeof(WSAcl));
916 acllist->acl.check = (acl_check_f)wsacl_check;
917 acllist->acl.authdb =
NULL;
918 acllist->acl.authprompt =
NULL;
919 acllist->acl.isextern =
0;
920 acllist->ace =
NULL;
921 acllist->ece =
NULL;
922
923 if(acl->type.ptr && !sstrcmp(acl->type, sstr(
"fs"))) {
924 acllist->acl.isextern =
1;
925 }
926
927 size_t s = ucx_list_size(acl->entries);
928 WSAce **aces = calloc(s,
sizeof(WSAce*));
929 WSAce **eces = calloc(s,
sizeof(WSAce*));
930 int ai =
0;
931 int ei =
0;
932
933
934 UCX_FOREACH(elm, acl->entries) {
935 ACEConfig *acecfg = elm->data;
936
937
938 WSAce *ace = malloc(
sizeof(WSAce));
939 ace->access_mask = acecfg->access_mask;
940 ace->flags = acecfg->flags;
941 ace->type = acecfg->type;
942 ace->who = sstrdup(acecfg->who).ptr;
943
944
945 if(ace->type >=
ACL_TYPE_AUDIT) {
946 eces[ei] = ace;
947 ei++;
948 }
else {
949 aces[ai] = ace;
950 ai++;
951 }
952 }
953
954
955 if(ai >
0) {
956 acllist->ace = calloc(ai,
sizeof(WSAce*));
957 }
958 if(ei >
0) {
959 acllist->ece = calloc(ei,
sizeof(WSAce*));
960 }
961 memcpy(acllist->ace, aces, ai*
sizeof(WSAce*));
962 memcpy(acllist->ece, eces, ei*
sizeof(WSAce*));
963 acllist->acenum = ai;
964 acllist->ecenum = ei;
965
966 free(aces);
967 free(eces);
968
969
970 if(acl->authparam) {
971 sstr_t authdb_str = cfg_param_get(acl->authparam, sstr(
"authdb"));
972 sstr_t prompt_str = cfg_param_get(acl->authparam, sstr(
"prompt"));
973
974 if(authdb_str.ptr) {
975 AuthDB *authdb = ucx_map_sstr_get(cfg->authdbs, authdb_str);
976 acllist->acl.authdb = authdb;
977 if(authdb && prompt_str.ptr) {
978 acllist->acl.authprompt = sstrdup(prompt_str).ptr;
979 }
980 }
981 }
982
983 return &acllist->acl;
984 }
985
986 int keyfile_reload(ConfigFile *file, ServerConfiguration *cfg) {
987 KeyfileConfig *conf = load_keyfile_config(file->file.ptr);
988 if(!conf) {
989 return 1;
990 }
991
992 Keyfile *keyfile = keyfile_new();
993
994 UCX_FOREACH(elm, conf->users) {
995 KeyfileEntry *user = elm->data;
996 keyfile_add_user(
997 keyfile,
998 user->name,
999 user->hashtype,
1000 user->hashdata,
1001 user->groups,
1002 user->numgroups);
1003 }
1004
1005 free_keyfile_config(conf);
1006
1007 Keyfile *old_data = file->data;
1008 file->data = keyfile;
1009 if(old_data) {
1010 keyfile_unref(old_data);
1011 }
1012
1013 return 0;
1014 }
1015
1016
1017 sstr_t cfg_load_file(
sstr_t file) {
1018 sstr_t r;
1019 r.ptr =
NULL;
1020 r.length =
0;
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 }
1052