#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/io.h"
#include "../util/util.h"
#include "../../ucx/utils.h"
#include "../safs/common.h"
#include "func.h"
#include "config.h"
#include "configmanager.h"
#include "httplistener.h"
#include "webserver.h"
#include "log.h"
#include "auth.h"
#include "srvctrl.h"
extern struct FuncStruct webserver_funcs[];
static RestartCallback *atrestart;
int webserver_init() {
systhread_init(
"webserver");
if(ws_init_ssl()) {
return -
1;
}
func_init();
add_functions(webserver_funcs);
if(load_init_conf(
"config/init.conf")) {
return -
1;
}
init_configuration_manager();
ServerConfiguration *cfg;
if(cfgmgr_load_config(&cfg) !=
0) {
fprintf(stderr,
"Cannot load configuration\n");
return -
1;
}
auth_cache_init();
common_saf_init();
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_WARN,
"globalvars->Vuserpw is null");
}
if(changeuid && ws_uid ==
0) {
if(setgid(vars->Vuserpw->pw_gid) !=
0) {
log_ereport(
LOG_FAILURE,
"setgid(%d) failed",
vars->Vuserpw->pw_gid);
}
else {
if(initgroups(vars->Vuserpw->pw_name, vars->Vuserpw->pw_gid)!=
0) {
log_ereport(
LOG_FAILURE,
"initgroups failed");
}
}
if(setuid(vars->Vuserpw->pw_uid)) {
log_ereport(
LOG_FAILURE,
"setuid(%d) failed",
vars->Vuserpw->pw_uid);
}
}
else if(vars->Vuserpw) {
log_ereport(
LOG_WARN,
"server must be started as root to change uid");
}
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");
pid_t pid = getpid();
fprintf(pidfile,
"%d", pid);
fclose(pidfile);
free(pid_file_path);
sstr_t tmp_priv = ucx_sprintf(
"%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 0;
}
}
else {
log_ereport(
LOG_CATASTROPHE,
"cannot create tmp dir %s:",
tmp_priv.ptr,
strerror(errno));
return -
1;
}
}
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();
RestartCallback *re = atrestart;
while(re) {
re->func(re->data);
re = re->next;
}
}
int webserver_reconfig() {
if(cfgmgr_load_config(
NULL) !=
0) {
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;
}
}
int nsapi_runtime_version() {
return 303;
}
int ws_init_ssl() {
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
return 0;
}