#ifdef __gnu_linux__
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "../public/nsapi.h"
#include "../public/auth.h"
#include "../util/systhr.h"
#include "../util/pblock.h"
#include "../util/util.h"
#include <cx/utils.h>
#include <cx/printf.h>
#include <cx/compare.h>
#include "../safs/common.h"
#include "func.h"
#include "config.h"
#include "configmanager.h"
#include "httplistener.h"
#include "webserver.h"
#include "auth.h"
#include "srvctrl.h"
#include "resourcepool.h"
#include "ldap_resource.h"
extern struct FuncStruct webserver_funcs[];
static RestartCallback *atrestart;
int webserver_init() {
systhread_init(
"webserver");
log_ereport(
LOG_VERBOSE,
"webserver_init");
if(ws_init_ssl()) {
log_ereport(
LOG_FAILURE,
"ssl init failed");
return -
1;
}
if(http_listener_global_init()) {
log_ereport(
LOG_FAILURE,
"listener global init failed");
return -
1;
}
pblock_init_default_keys();
atexit(pblock_free_default_keys);
func_init();
add_functions(webserver_funcs);
if(init_resource_pools()) {
log_ereport(
LOG_FAILURE,
"resource pool init failed");
return -
1;
}
if(resourcepool_register_type(
"ldap", ldap_get_resource_type())) {
log_ereport(
LOG_FAILURE,
"webserver-init: Cannot register ldap resourcepool type");
return -
1;
}
InitConfig *init_config = load_init_conf(
"config/init.conf");
if(!init_config) {
return -
1;
}
init_configuration_manager();
CfgManager mgr;
if(cfgmgr_load_config(&mgr) !=
0) {
return 1;
}
log_ereport(
LOG_VERBOSE,
"cfgmgr_load_config stage 1 successful");
ServerConfiguration *cfg = mgr.cfg;
conf_global_vars_s *vars = conf_getglobals();
WSBool changeuid =
FALSE;
uid_t ws_uid = geteuid();
setpwent();
char *pwbuf = malloc(
DEF_PWBUF);
vars->Vuserpw = malloc(
sizeof(
struct passwd));
if(cfg->user.ptr) {
if(!util_getpwnam(cfg->user.ptr, vars->Vuserpw, pwbuf,
DEF_PWBUF)) {
log_ereport(
LOG_MISCONFIG,
"user %s does not exist!",
cfg->user.ptr);
free(vars->Vuserpw);
vars->Vuserpw =
NULL;
}
else {
changeuid =
TRUE;
}
}
else {
if(!util_getpwuid(ws_uid, vars->Vuserpw, pwbuf,
DEF_PWBUF)) {
log_ereport(
LOG_FAILURE,
"webserver_init: cannot get passwd data");
free(vars->Vuserpw);
vars->Vuserpw =
NULL;
}
}
if(!vars->Vuserpw) {
log_ereport(
LOG_VERBOSE,
"globalvars->Vuserpw is null");
}
if(changeuid && ws_uid ==
0) {
log_ereport(
LOG_VERBOSE,
"setgid(%d)", vars->Vuserpw->pw_gid);
if(setgid(vars->Vuserpw->pw_gid) !=
0) {
log_ereport(
LOG_FAILURE,
"setgid(%d) failed",
vars->Vuserpw->pw_gid);
return -
1;
}
else {
if(initgroups(vars->Vuserpw->pw_name, vars->Vuserpw->pw_gid)!=
0) {
log_ereport(
LOG_FAILURE,
"initgroups failed");
return -
1;
}
}
log_ereport(
LOG_VERBOSE,
"setuid(%d)", vars->Vuserpw->pw_uid);
if(setuid(vars->Vuserpw->pw_uid)) {
log_ereport(
LOG_FAILURE,
"setuid(%d) failed",
vars->Vuserpw->pw_uid);
return -
1;
}
}
else if(vars->Vuserpw) {
log_ereport(
LOG_WARN,
"server must be started as root to change uid");
}
int err = apply_init_conf(init_config);
free_init_conf(init_config);
if(err) {
log_ereport(
LOG_FAILURE,
"server init failed");
return 1;
}
auth_cache_init();
common_saf_init();
if(cfgmgr_apply_config(&mgr)) {
log_ereport(
LOG_FAILURE,
"load config stage 2 failed");
return -
1;
}
char *mkdir_cmd =
NULL;
asprintf(&mkdir_cmd,
"mkdir -p %s", cfg->tmp.ptr);
system(mkdir_cmd);
free(mkdir_cmd);
char *pid_file_path =
NULL;
asprintf(&pid_file_path,
"%s/pid", cfg->tmp.ptr);
FILE *pidfile = fopen(pid_file_path,
"w");
if(!pidfile) {
log_ereport(
LOG_FAILURE,
"cannot open pid file %s: %s", pid_file_path, strerror(errno));
return -
1;
}
pid_t pid = getpid();
fprintf(pidfile,
"%d", pid);
fclose(pidfile);
free(pid_file_path);
cxmutstr tmp_priv = cx_asprintf(
"%s/private", cfg->tmp.ptr);
if(mkdir(tmp_priv.ptr,
S_IRWXU)) {
if(errno ==
EEXIST) {
if(chmod(tmp_priv.ptr,
S_IRWXU)) {
log_ereport(
LOG_CATASTROPHE,
"cannot change permissions of tmp dir %s:",
tmp_priv.ptr,
strerror(errno));
return -
1;
}
}
else {
log_ereport(
LOG_CATASTROPHE,
"cannot create tmp dir %s:",
tmp_priv.ptr,
strerror(errno));
return -
1;
}
}
free(tmp_priv.ptr);
if(srvctrl_init(cfg)) {
return -
1;
}
return 0;
}
int webserver_run() {
log_ereport(
LOG_VERBOSE,
"webserver_run");
if(start_all_listener() !=
0) {
fprintf(stderr,
"Error: Cannot start http listener\n");
}
log_ereport(
LOG_INFORM,
"webserver started");
return 0;
}
void webserver_shutdown() {
log_ereport(
LOG_INFORM,
"webserver shutdown");
srvctrl_shutdown();
}
void webserver_end() {
RestartCallback *re = atrestart;
while(re) {
re->func(re->data);
re = re->next;
}
shutdown_threadpools();
shutdown_eventhandlers_wait();
webserver_destroy();
}
int webserver_reconfig() {
CfgManager mgr;
if(cfgmgr_load_config(&mgr) !=
0) {
log_ereport(
LOG_FAILURE,
"cannot reload server.conf");
return 1;
}
else {
if(cfgmgr_apply_config(&mgr)) {
log_ereport(
LOG_FAILURE,
"cannot reload config");
return 1;
}
}
start_all_listener();
return 0;
}
void webserver_atrestart(
void (*fn)(
void *),
void *data) {
RestartCallback *cb = malloc(
sizeof(RestartCallback));
cb->func = fn;
cb->data = data;
cb->next =
NULL;
if(atrestart) {
RestartCallback *elm = atrestart;
while(elm) {
if(!elm->next) {
elm->next = cb;
break;
}
elm = elm->next;
}
}
else {
atrestart = cb;
}
}
void webserver_destroy() {
pool_destroy(cfg_get_init_pool());
}
int nsapi_runtime_version() {
return 303;
}
int ws_init_ssl() {
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
return 0;
}