#include "../public/nsapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <ucx/string.h>
#include <ucx/utils.h>
#include "httplistener.h"
#include "config.h"
#include "func.h"
#include "log.h"
#include "event.h"
#include "threadpools.h"
#include "ldap_auth.h"
#include "configmanager.h"
#include "vserver.h"
#include "../util/pblock.h"
#include "../util/util.h"
#include "../util/atomic.h"
#include "ucx/buffer.h"
pool_handle_t *cfg_pool;
int load_init_conf(
char *file) {
log_ereport(
LOG_VERBOSE,
"load_init_conf");
InitConfig *cfg = load_init_config(file);
if(cfg ==
NULL) {
log_ereport(
LOG_FAILURE,
"Cannot load init.conf");
return 1;
}
UcxAllocator *mp = cfg->parser.mp;
cfg_pool = pool_create();
UcxList *dirs = cfg->directives;
while(dirs !=
NULL) {
ConfigDirective *dir = dirs->data;
directive *d = malloc(
sizeof(directive));
d->param = pblock_create_pool(cfg_pool,
8);
UcxList *param = cfg_param_list(dir->value, mp);
while(param !=
NULL) {
ConfigParam *p = param->data;
pblock_nvlinsert(
p->name.ptr,
p->name.length,
p->value.ptr,
p->value.length,
d->param);
param = param->next;
}
char *func_name = pblock_findval(
"fn", d->param);
d->func = get_function(func_name);
if(d->func ==
NULL) {
pblock_free(d->param);
free(d);
log_ereport(
LOG_MISCONFIG,
"Cannot find Init function %s",
func_name);
return 1;
}
int ret = d->func->func(d->param,
NULL,
NULL);
if(ret !=
REQ_PROCEED && ret !=
REQ_NOACTION) {
log_ereport(
LOG_FAILURE,
"Error running Init function %s",
func_name);
pblock_free(d->param);
free(d);
return 1;
}
pblock_free(d->param);
free(d);
dirs = dirs->next;
}
free_init_config(cfg);
return 0;
}
ServerConfiguration* load_server_conf(ServerConfiguration *old,
char *file) {
log_ereport(
LOG_VERBOSE,
"load_server_conf");
ServerConfig *serverconf = load_server_config(file);
if(serverconf ==
NULL) {
log_ereport(
LOG_FAILURE,
"Cannot load server.conf");
}
ServerConfiguration *serverconfig = calloc(
1,
sizeof(ServerConfiguration));
serverconfig->ref =
1;
serverconfig->pool = pool_create();
serverconfig->listeners =
NULL;
serverconfig->host_vs = ucx_map_new(
16);
serverconfig->authdbs = ucx_map_new(
16);
UcxList *lfl = ucx_map_sstr_get(serverconf->objects, sstrn(
"LogFile",
7));
if(lfl !=
NULL) {
ServerConfigObject *logobj = lfl->data;
if(logobj ==
NULL) {
return NULL;
}
int ret = cfg_handle_logfile(serverconfig, logobj);
if(ret !=
0) {
return NULL;
}
}
else {
return NULL;
}
UcxList *list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Runtime",
7));
UCX_FOREACH(elm, list) {
ServerConfigObject *scfgobj = elm->data;
if(cfg_handle_runtime(serverconfig, scfgobj)) {
return NULL;
}
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Threadpool",
10));
UCX_FOREACH(elm, list) {
if(cfg_handle_threadpool(serverconfig, elm->data)) {
return NULL;
}
}
if(check_thread_pool_cfg() !=
0) {
return NULL;
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"EventHandler",
12));
UCX_FOREACH(elm, list) {
if(cfg_handle_eventhandler(
serverconfig, (ServerConfigObject*)elm->data)) {
return NULL;
}
}
if(check_event_handler_cfg() !=
0) {
return NULL;
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"AccessLog",
9));
UCX_FOREACH(elm, list) {
ServerConfigObject *scfgobj = elm->data;
if(cfg_handle_accesslog(serverconfig, scfgobj)) {
return NULL;
}
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"AuthDB",
6));
UCX_FOREACH(elm, list) {
ServerConfigObject *scfgobj = elm->data;
if(cfg_handle_authdb(serverconfig, scfgobj)) {
return NULL;
}
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"Listener",
8));
UCX_FOREACH(elm, list) {
ServerConfigObject *scfgobj = elm->data;
if(cfg_handle_listener(serverconfig, scfgobj)) {
return NULL;
}
}
list = ucx_map_sstr_get(serverconf->objects, sstrn(
"VirtualServer",
13));
UCX_FOREACH(elm, list) {
ServerConfigObject *scfgobj = elm->data;
if(cfg_handle_vs(serverconfig, scfgobj)) {
return NULL;
}
}
UcxList *ls = serverconfig->listeners;
while(ls) {
HttpListener *listener = ls->data;
sstr_t vsname = sstr(listener->default_vs.vs_name);
UcxMapIterator iter = ucx_map_iterator(serverconfig->host_vs);
VirtualServer *vs;
UCX_MAP_FOREACH(key, vs, iter) {
if(!sstrcmp(vsname, vs->name)) {
listener->default_vs.vs = vs;
break;
}
}
ls = ls->next;
}
free_server_config(serverconf);
return serverconfig;
}
void cfg_ref(ServerConfiguration *cfg) {
ws_atomic_inc32(&cfg->ref);
}
void cfg_unref(ServerConfiguration *cfg) {
uint32_t ref = ws_atomic_dec32(&cfg->ref);
if(ref ==
0) {
printf(
"free ServerConfiguration %""\n"PRIxPTR, (
intptr_t)cfg);
}
}
void init_server_config_parser() {
}
int cfg_handle_runtime(ServerConfiguration *cfg, ServerConfigObject *obj) {
sstr_t user = cfg_directivelist_get_str(obj->directives, sstr(
"User"));
if(user.ptr) {
cfg->user = sstrdup_pool(cfg->pool, user);
}
sstr_t tmp = cfg_directivelist_get_str(obj->directives, sstr(
"Temp"));
if(tmp.ptr) {
cfg->tmp = sstrdup_pool(cfg->pool, tmp);
}
else {
log_ereport(
LOG_MISCONFIG,
"no temporary directory specified");
return -
1;
}
sstr_t mf = cfg_directivelist_get_str(obj->directives, sstr(
"MimeFile"));
sstr_t base = sstr(
"config/");
sstr_t file = sstrcat(
2, base, mf);
ConfigFile *f = cfgmgr_get_file(file);
if(f ==
NULL) {
f = malloc(
sizeof(ConfigFile));
f->data =
NULL;
f->file = sstrdup(file);
f->reload = mime_conf_reload;
f->last_modified =
0;
if(cfgmgr_reload_file(f, cfg,
NULL)) {
free(f->file.ptr);
free(f);
free(file.ptr);
return -
1;
}
cfgmgr_attach_file(f);
}
cfg->mimetypes = f->data;
free(file.ptr);
return 0;
}
int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj) {
sstr_t file = cfg_directivelist_get_str(obj->directives, sstr(
"File"));
sstr_t lvl = cfg_directivelist_get_str(obj->directives, sstr(
"Level"));
if(file.ptr ==
NULL || lvl.ptr ==
NULL) {
return -
1;
}
LogConfig logcfg;
logcfg.file = sstrdup(file).ptr;
logcfg.level = sstrdup(lvl).ptr;
logcfg.log_stdout =
0;
logcfg.log_stderr =
0;
int ret = init_log_file(&logcfg);
free(logcfg.file);
free(logcfg.level);
return ret;
}
int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj) {
ThreadPoolConfig poolcfg;
poolcfg.min_threads =
4;
poolcfg.min_threads =
4;
poolcfg.max_threads =
8;
poolcfg.queue_size =
64;
poolcfg.stack_size =
262144;
sstr_t name = cfg_directivelist_get_str(
obj->directives,
sstr(
"Name"));
sstr_t min = cfg_directivelist_get_str(
obj->directives,
sstr(
"MinThreads"));
sstr_t max = cfg_directivelist_get_str(
obj->directives,
sstr(
"MaxThreads"));
sstr_t stack = cfg_directivelist_get_str(
obj->directives,
sstr(
"StackSize"));
sstr_t queue = cfg_directivelist_get_str(
obj->directives,
sstr(
"QueueSize"));
if(name.length ==
0) {
return 1;
}
if(min.length !=
0) {
min = sstrdup(min);
poolcfg.min_threads = atoi(min.ptr);
free(min.ptr);
}
if(max.length !=
0) {
max = sstrdup(max);
poolcfg.max_threads = atoi(max.ptr);
free(max.ptr);
}
if(stack.length !=
0) {
stack = sstrdup(stack);
poolcfg.stack_size = atoi(stack.ptr);
free(stack.ptr);
}
if(queue.length !=
0) {
queue = sstrdup(queue);
poolcfg.queue_size = atoi(queue.ptr);
free(queue.ptr);
}
create_threadpool(name, &poolcfg);
return 0;
}
int cfg_handle_eventhandler(ServerConfiguration *c, ServerConfigObject *obj) {
EventHandlerConfig evcfg;
sstr_t name = cfg_directivelist_get_str(obj->directives, sstr(
"Name"));
sstr_t threads = cfg_directivelist_get_str(
obj->directives,
sstr(
"Threads"));
sstr_t isdefault = cfg_directivelist_get_str(
obj->directives,
sstr(
"Default"));
evcfg.name = name;
sstr_t s = sstrdup(threads);
evcfg.nthreads = atoi(s.ptr);
free(s.ptr);
evcfg.isdefault = util_getboolean(isdefault.ptr,
0);
return create_event_handler(&evcfg);
}
int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj) {
sstr_t file = cfg_directivelist_get_str(obj->directives, sstr(
"File"));
if(file.ptr ==
NULL) {
return 0;
}
sstr_t format;
format.ptr =
NULL;
format.length =
0;
LogFile *log_file = get_access_log_file(file);
if(!log_file) {
return 0;
}
AccessLog *log = pool_malloc(cfg->pool,
sizeof(AccessLog));
log->file = sstrdup_pool(cfg->pool, file);
log->format = format;
log->log = log_file;
cfg->logfiles = ucx_list_append(cfg->logfiles, log);
if(!cfg->default_log) {
cfg->default_log = log;
}
return 0;
}
int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) {
sstr_t name = cfg_directivelist_get_str(obj->directives, sstr(
"Name"));
sstr_t type = cfg_directivelist_get_str(obj->directives, sstr(
"Type"));
if(!sstrcmp(type, sstr(
"ldap"))) {
LDAPConfig conf;
sstr_t host = cfg_directivelist_get_str(
obj->directives,
sstr(
"Host"));
sstr_t port = cfg_directivelist_get_str(
obj->directives,
sstr(
"Port"));
sstr_t basedn = cfg_directivelist_get_str(
obj->directives,
sstr(
"BaseDN"));
sstr_t binddn = cfg_directivelist_get_str(
obj->directives,
sstr(
"BindDN"));
sstr_t basepw = cfg_directivelist_get_str(
obj->directives,
sstr(
"BindPW"));
host = sstrdup(host);
port = sstrdup(port);
basedn = sstrdup(basedn);
binddn = sstrdup(binddn);
basepw = sstrdup(basepw);
conf.hostname = host.ptr;
conf.port = atoi(port.ptr);
conf.basedn = basedn.ptr;
conf.binddn = binddn.ptr;
conf.bindpw = basepw.ptr;
name = sstrdup(name);
AuthDB *authdb = create_ldap_authdb(name.ptr, &conf);
ucx_map_sstr_put(cfg->authdbs, name, authdb);
}
else if(!sstrcmp(type, sstr(
"keyfile"))) {
sstr_t file = cfg_directivelist_get_str(
obj->directives,
sstr(
"File"));
if(file.length ==
0) {
log_ereport(
LOG_MISCONFIG,
"missing File parameter for keyfile authdb");
return 1;
}
ConfigFile *f = cfgmgr_get_file(file);
if(f ==
NULL) {
f = malloc(
sizeof(ConfigFile));
f->data =
NULL;
f->file = sstrdup(file);
f->reload = keyfile_reload;
f->last_modified =
0;
if(cfgmgr_reload_file(f, cfg,
NULL)) {
free(f->file.ptr);
free(f);
return -
1;
}
cfgmgr_attach_file(f);
}
Keyfile *keyfile = f->data;
keyfile->authdb.name = sstrdup(name).ptr;
ucx_map_sstr_put(cfg->authdbs, name, keyfile);
}
return 0;
}
int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj) {
ListenerConfig lc;
ZERO(&lc,
sizeof(ListenerConfig));
lc.cfg = cfg;
lc.port =
8080;
lc.nacceptors =
1;
lc.name = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"Name")));
lc.port = atoi(cfg_directivelist_get_str(
obj->directives,
sstr(
"Port")).ptr);
lc.vs = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"DefaultVS")));
lc.threadpool = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"Threadpool")));
sstr_t blockingio = cfg_directivelist_get_str(
obj->directives,
sstr(
"BlockingIO"));
if(blockingio.ptr) {
lc.blockingio = util_getboolean_s(blockingio,
WS_FALSE);
}
sstr_t ssl = cfg_directivelist_get_str(obj->directives,
S(
"SSL"));
if(util_getboolean_s(ssl,
WS_FALSE)) {
sstr_t cert = cfg_directivelist_get_str(obj->directives,
S(
"Cert"));
sstr_t privkey = cfg_directivelist_get_str(obj->directives,
S(
"Key"));
sstr_t chain = cfg_directivelist_get_str(obj->directives,
S(
"CertChain"));
sstr_t disableprot = cfg_directivelist_get_str(
obj->directives,
S(
"SSLDisableProtocol"));
WSBool config_ok =
WS_TRUE;
if(!cert.ptr && !chain.ptr) {
log_ereport(
LOG_MISCONFIG,
"SSL Listener %s: Missing Cert or ChainCert directive",
lc.name.ptr);
config_ok =
WS_FALSE;
}
if(!privkey.ptr) {
log_ereport(
LOG_MISCONFIG,
"SSL Listener %s: Missing Key directive",
lc.name.ptr);
config_ok =
WS_FALSE;
}
if(config_ok) {
lc.certfile = cert;
lc.privkeyfile = privkey;
lc.chainfile = chain;
lc.disable_proto = disableprot;
lc.ssl =
WS_TRUE;
}
}
else {
lc.ssl =
WS_FALSE;
}
HttpListener *listener = http_listener_create(&lc);
if(!listener) {
return 1;
}
listener->default_vs.vs_name = lc.vs.ptr;
cfg->listeners = ucx_list_append(cfg->listeners, listener);
return 0;
}
int cfg_handle_vs(ServerConfiguration *cfg, ServerConfigObject *obj) {
VirtualServer *vs = vs_new();
vs->name = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"Name")));
vs->host = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"Host")));
vs->document_root = sstrdup(cfg_directivelist_get_str(
obj->directives,
sstr(
"DocRoot")));
sstr_t objfile = cfg_directivelist_get_str(
obj->directives,
sstr(
"ObjectFile"));
sstr_t aclfile = cfg_directivelist_get_str(
obj->directives,
sstr(
"ACLFile"));
sstr_t base = sstr(
"config/");
sstr_t file = sstrcat(
2, base, objfile);
file = sstrcat(
2, base, objfile);
ConfigFile *f = cfgmgr_get_file(file);
if(f ==
NULL) {
f = malloc(
sizeof(ConfigFile));
f->data =
NULL;
f->file = sstrdup(file);
f->reload = object_conf_reload;
f->last_modified =
0;
if(cfgmgr_reload_file(f, cfg,
NULL)) {
free(f->file.ptr);
free(f);
free(file.ptr);
return -
1;
}
cfgmgr_attach_file(f);
}
vs->objectfile = sstrdup(file);
vs->objects = (HTTPObjectConfig*)f->data;
free(file.ptr);
file = sstrcat(
2, base, aclfile);
ConfigFile *aclf = cfgmgr_get_file(file);
if(aclf ==
NULL) {
aclf = malloc(
sizeof(ConfigFile));
aclf->data =
NULL;
aclf->file = sstrdup(file);
aclf->reload = acl_conf_reload;
aclf->last_modified =
0;
if(cfgmgr_reload_file(aclf, cfg,
NULL)) {
free(aclf->file.ptr);
free(aclf);
free(file.ptr);
return -
1;
}
cfgmgr_attach_file(aclf);
}
vs->acls = aclf->data;
free(file.ptr);
vs->log = cfg->default_log;
ucx_map_sstr_put(cfg->host_vs, vs->host, vs);
return 0;
}
int object_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
HTTPObjectConfig *old_conf = file->data;
file->data = load_obj_conf(file->file.ptr);
if(old_conf) {
object_conf_unref(old_conf);
}
if(file->data) {
return 0;
}
else {
return 1;
}
}
void object_conf_ref(HTTPObjectConfig *conf) {
if(conf) {
ws_atomic_inc32(&conf->ref);
}
}
void object_conf_unref(HTTPObjectConfig *conf) {
uint32_t ref = ws_atomic_dec32(&conf->ref);
if(ref ==
0) {
printf(
"free HTTPObjectConfig %""\n"PRIxPTR, (
intptr_t)conf);
pool_destroy(conf->pool);
}
}
HTTPObjectConfig* load_obj_conf(
char *file) {
log_ereport(
LOG_VERBOSE,
"load_obj_conf");
ObjectConfig *cfg = load_object_config(file);
UcxAllocator *mp = cfg->parser.mp;
if(cfg ==
NULL) {
return NULL;
}
pool_handle_t *pool = pool_create();
HTTPObjectConfig *conf = pool_calloc(pool,
sizeof(HTTPObjectConfig),
1);
conf->pool = pool;
conf->nobj = ucx_list_size(cfg->objects);
conf->objects = pool_calloc(pool, conf->nobj,
sizeof(httpd_object*));
UcxList *objlist = cfg->objects;
int i =
0;
while(objlist !=
NULL) {
ConfigObject *cob = objlist->data;
char *name =
NULL;
char *ppath =
NULL;
if(cob->name.length >
0) {
name = sstrdup_pool(pool, cob->name).ptr;
}
if(cob->ppath.length >
0) {
ppath = sstrdup_pool(pool, cob->ppath).ptr;
}
httpd_object *obj = object_new(pool, name);
obj->path =
NULL;
conf->objects[i] = obj;
for(
int j=
0;j<
NUM_NSAPI_TYPES-
1;j++) {
UcxList *dirs = cob->directives[j];
while(dirs !=
NULL) {
ConfigDirective *cfgdir = dirs->data;
directive *d = pool_malloc(pool,
sizeof(directive));
if(cfgdir->condition) {
sstr_t expr = cfgdir->condition->param_str;
d->cond = condition_from_str(pool, expr.ptr, expr.length);
}
else {
d->cond =
NULL;
}
d->param = pblock_create_pool(pool,
8);
UcxList *param = cfg_param_list(cfgdir->value, mp);
while(param !=
NULL) {
ConfigParam *p = param->data;
pblock_nvlinsert(
p->name.ptr,
p->name.length,
p->value.ptr,
p->value.length,
d->param);
param = param->next;
}
char *func_name = pblock_findval(
"fn", d->param);
if(!func_name) {
log_ereport(
LOG_MISCONFIG,
"%s: Missing fn parameter", file);
return NULL;
}
d->func = get_function(func_name);
if(!d->func) {
log_ereport(
LOG_MISCONFIG,
"func %s not found", func_name);
return NULL;
}
dirs = dirs->next;
object_add_directive(obj, d, cfgdir->type_num);
}
}
i++;
objlist = objlist->next;
}
free_object_config(cfg);
return conf;
}
int mime_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
MimeConfig *mimecfg = load_mime_config(file->file.ptr);
MimeMap *old_conf = file->data;
MimeMap *mimemap = malloc(
sizeof(MimeMap));
mimemap->ref =
1;
UcxMap *map = ucx_map_new((mimecfg->ntypes *
3) /
2);
mimemap->map = map;
UCX_FOREACH(md, mimecfg->directives) {
MimeDirective *d = md->data;
UCX_FOREACH(xl, d->exts) {
sstr_t ext = sstr(xl->data);
sstr_t value = sstrdup(d->type);
ucx_map_sstr_put(map, ext, value.ptr);
}
}
file->data = mimemap;
if(old_conf) {
mime_conf_unref(old_conf);
}
free_mime_config(mimecfg);
return 0;
}
void mime_conf_ref(MimeMap *conf) {
if(conf) {
ws_atomic_inc32(&conf->ref);
}
}
void mime_conf_unref(MimeMap *conf) {
uint32_t ref = ws_atomic_dec32(&conf->ref);
if(ref ==
0) {
printf(
"free MimeConfig %""\n"PRIxPTR, (
intptr_t)conf);
UcxMapIterator i = ucx_map_iterator(conf->map);
char *str;
UCX_MAP_FOREACH(key, str, i) {
free(str);
}
ucx_map_free(conf->map);
free(conf);
}
}
int acl_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
ACLFile *aclfile = load_acl_file(file->file.ptr);
ACLData *acldata = acl_data_new();
UCX_FOREACH(elm, aclfile->namedACLs) {
ACLConfig *ac = elm->data;
ACLList *acl = acl_config_convert(cfg, ac);
log_ereport(
LOG_VERBOSE,
"add acl: %.*s", (
int)ac->id.length, ac->id.ptr);
ucx_map_sstr_put(acldata->namedACLs, ac->id, acl);
}
free_acl_file(aclfile);
ACLData *old_data = file->data;
file->data = acldata;
if(old_data) {
acl_data_unref(old_data);
}
return 0;
}
ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) {
WSAcl *acllist = malloc(
sizeof(WSAcl));
acllist->acl.check = (acl_check_f)wsacl_check;
acllist->acl.authdb =
NULL;
acllist->acl.authprompt =
NULL;
acllist->acl.isextern =
0;
acllist->ace =
NULL;
acllist->ece =
NULL;
if(acl->type.ptr && !sstrcmp(acl->type, sstr(
"fs"))) {
acllist->acl.isextern =
1;
}
size_t s = ucx_list_size(acl->entries);
WSAce **aces = calloc(s,
sizeof(WSAce*));
WSAce **eces = calloc(s,
sizeof(WSAce*));
int ai =
0;
int ei =
0;
UCX_FOREACH(elm, acl->entries) {
ACEConfig *acecfg = elm->data;
WSAce *ace = malloc(
sizeof(WSAce));
ace->access_mask = acecfg->access_mask;
ace->flags = acecfg->flags;
ace->type = acecfg->type;
ace->who = sstrdup(acecfg->who).ptr;
if(ace->type >=
ACL_TYPE_AUDIT) {
eces[ei] = ace;
ei++;
}
else {
aces[ai] = ace;
ai++;
}
}
if(ai >
0) {
acllist->ace = calloc(ai,
sizeof(WSAce*));
}
if(ei >
0) {
acllist->ece = calloc(ei,
sizeof(WSAce*));
}
memcpy(acllist->ace, aces, ai*
sizeof(WSAce*));
memcpy(acllist->ece, eces, ei*
sizeof(WSAce*));
acllist->acenum = ai;
acllist->ecenum = ei;
free(aces);
free(eces);
if(acl->authparam) {
sstr_t authdb_str = cfg_param_get(acl->authparam, sstr(
"authdb"));
sstr_t prompt_str = cfg_param_get(acl->authparam, sstr(
"prompt"));
if(authdb_str.ptr) {
AuthDB *authdb = ucx_map_sstr_get(cfg->authdbs, authdb_str);
acllist->acl.authdb = authdb;
if(authdb && prompt_str.ptr) {
acllist->acl.authprompt = sstrdup(prompt_str).ptr;
}
}
}
return &acllist->acl;
}
int keyfile_reload(ConfigFile *file, ServerConfiguration *cfg) {
KeyfileConfig *conf = load_keyfile_config(file->file.ptr);
if(!conf) {
return 1;
}
Keyfile *keyfile = keyfile_new();
UCX_FOREACH(elm, conf->users) {
KeyfileEntry *user = elm->data;
keyfile_add_user(
keyfile,
user->name,
user->hashtype,
user->hashdata,
user->groups,
user->numgroups);
}
free_keyfile_config(conf);
Keyfile *old_data = file->data;
file->data = keyfile;
if(old_data) {
keyfile_unref(old_data);
}
return 0;
}
sstr_t cfg_load_file(
sstr_t file) {
sstr_t r;
r.ptr =
NULL;
r.length =
0;
if(!file.ptr) {
return r;
}
sstr_t f = sstrdup(file);
FILE *in = fopen(f.ptr,
"r");
if(!in) {
return r;
}
UcxBuffer *buf = ucx_buffer_new(
NULL,
4096,
UCX_BUFFER_AUTOEXTEND);
if(!buf) {
fclose(in);
return r;
}
if(ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write) ==
0) {
fclose(in);
ucx_buffer_free(buf);
return r;
}
r.ptr = buf->space;
r.length = buf->pos;
free(buf);
fclose(in);
return r;
}