Add config file
This commit is contained in:
@ -204,9 +204,13 @@ int cache_init() {
|
|||||||
int cache_unload() {
|
int cache_unload() {
|
||||||
int shm_id = shmget(SHM_KEY_CACHE, 0, 0);
|
int shm_id = shmget(SHM_KEY_CACHE, 0, 0);
|
||||||
if (shm_id < 0) {
|
if (shm_id < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
shmdt(cache);
|
||||||
|
return -1;
|
||||||
} else if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
|
} else if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
shmdt(cache);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
shmdt(cache);
|
shmdt(cache);
|
||||||
return 0;
|
return 0;
|
||||||
|
47
src/client.c
47
src/client.c
@ -19,23 +19,13 @@ char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_
|
|||||||
|
|
||||||
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
||||||
|
|
||||||
char *get_webroot(const char *http_host) {
|
host_config *get_host_config(const char *host) {
|
||||||
char *webroot = malloc(strlen(webroot_base) + strlen(http_host) + 1);
|
for (int i = 0; i < MAX_HOST_CONFIG; i++) {
|
||||||
unsigned long len = strlen(webroot_base);
|
host_config *hc = &config[i];
|
||||||
while (webroot_base[len - 1] == '/') len--;
|
if (hc->type == CONFIG_TYPE_UNSET) break;
|
||||||
long pos = strchr(http_host, ':') - http_host;
|
if (strcmp(hc->name, host) == 0) return hc;
|
||||||
sprintf(webroot, "%.*s/%.*s", (int) len, webroot_base, (int) (pos < 0 ? strlen(http_host) : pos), http_host);
|
}
|
||||||
return path_is_directory(webroot) ? webroot : NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
int get_dir_mode(const char *webroot) {
|
|
||||||
char buf[256];
|
|
||||||
struct stat statbuf;
|
|
||||||
sprintf(buf, "%s/.necronda-server/dir_mode_info", webroot);
|
|
||||||
if (stat(buf, &statbuf) == 0) return URI_DIR_MODE_INFO;
|
|
||||||
sprintf(buf, "%s/.necronda-server/dir_mode_list", webroot);
|
|
||||||
if (stat(buf, &statbuf) == 0) return URI_DIR_MODE_LIST;
|
|
||||||
return URI_DIR_MODE_FORBIDDEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_terminate() {
|
void client_terminate() {
|
||||||
@ -49,12 +39,13 @@ int client_websocket_handler() {
|
|||||||
|
|
||||||
int client_request_handler(sock *client, unsigned long client_num, unsigned int req_num) {
|
int client_request_handler(sock *client, unsigned long client_num, unsigned int req_num) {
|
||||||
struct timespec begin, end;
|
struct timespec begin, end;
|
||||||
int ret, client_keep_alive, dir_mode;
|
int ret, client_keep_alive;
|
||||||
char buf0[1024], buf1[1024];
|
char buf0[1024], buf1[1024];
|
||||||
char msg_buf[4096], msg_pre_buf[4096], err_msg[256];
|
char msg_buf[4096], msg_pre_buf[4096], err_msg[256];
|
||||||
char buffer[CHUNK_SIZE];
|
char buffer[CHUNK_SIZE];
|
||||||
err_msg[0] = 0;
|
err_msg[0] = 0;
|
||||||
char host[256], *host_ptr, *hdr_connection, *webroot;
|
char host[256], *host_ptr, *hdr_connection;
|
||||||
|
host_config *conf;
|
||||||
long content_length = 0;
|
long content_length = 0;
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
msg_buf[0] = 0;
|
msg_buf[0] = 0;
|
||||||
@ -133,18 +124,22 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
log_prefix = log_req_prefix;
|
log_prefix = log_req_prefix;
|
||||||
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
||||||
|
|
||||||
// TODO Reverse Proxy
|
conf = get_host_config(host);
|
||||||
webroot = get_webroot(host);
|
if (conf == NULL) {
|
||||||
if (webroot == NULL) {
|
|
||||||
res.status = http_get_status(307);
|
res.status = http_get_status(307);
|
||||||
sprintf(buf0, "https://%s%s", DEFAULT_HOST, req.uri);
|
sprintf(buf0, "https://%s%s", DEFAULT_HOST, req.uri);
|
||||||
http_add_header_field(&res.hdr, "Location", buf0);
|
http_add_header_field(&res.hdr, "Location", buf0);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_mode = get_dir_mode(webroot);
|
if (conf->type != CONFIG_TYPE_LOCAL) {
|
||||||
|
// TODO Reverse Proxy
|
||||||
|
res.status = http_get_status(501);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
http_uri uri;
|
http_uri uri;
|
||||||
ret = uri_init(&uri, webroot, req.uri, dir_mode);
|
ret = uri_init(&uri, conf->local.webroot, req.uri, conf->local.dir_mode);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
sprintf(err_msg, "Invalid URI: has to start with slash.");
|
sprintf(err_msg, "Invalid URI: has to start with slash.");
|
||||||
@ -183,7 +178,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
} else if (uri.filename == NULL || (strlen(uri.pathinfo) > 0 && (int) uri.is_static)) {
|
} else if (uri.filename == NULL || (strlen(uri.pathinfo) > 0 && (int) uri.is_static)) {
|
||||||
res.status = http_get_status(404);
|
res.status = http_get_status(404);
|
||||||
goto respond;
|
goto respond;
|
||||||
} else if (strlen(uri.pathinfo) != 0 && dir_mode != URI_DIR_MODE_INFO) {
|
} else if (strlen(uri.pathinfo) != 0 && conf->local.dir_mode != URI_DIR_MODE_INFO) {
|
||||||
res.status = http_get_status(404);
|
res.status = http_get_status(404);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
@ -460,7 +455,7 @@ int client_connection_handler(sock *client, unsigned long client_num) {
|
|||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &begin);
|
clock_gettime(CLOCK_MONOTONIC, &begin);
|
||||||
|
|
||||||
if (dns_server != NULL) {
|
if (dns_server[0] != 0) {
|
||||||
sprintf(buf, "dig @%s +short +time=1 -x %s", dns_server, client_addr_str);
|
sprintf(buf, "dig @%s +short +time=1 -x %s", dns_server, client_addr_str);
|
||||||
FILE *dig = popen(buf, "r");
|
FILE *dig = popen(buf, "r");
|
||||||
if (dig == NULL) {
|
if (dig == NULL) {
|
||||||
|
171
src/config.c
171
src/config.c
@ -6,12 +6,179 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "uri.h"
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
|
||||||
int config_init() {
|
int config_init() {
|
||||||
|
int shm_id = shmget(SHM_KEY_CONFIG, MAX_HOST_CONFIG * sizeof(host_config), IPC_CREAT | IPC_EXCL | 0640);
|
||||||
|
if (shm_id < 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *shm = shmat(shm_id, NULL, SHM_RDONLY);
|
||||||
|
if (shm == (void *) -1) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to attach shared memory (ro): %s" CLR_STR "\n", strerror(errno));
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
config = shm;
|
||||||
|
|
||||||
|
void *shm_rw = shmat(shm_id, NULL, 0);
|
||||||
|
if (shm_rw == (void *) -1) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
config = shm_rw;
|
||||||
|
memset(config, 0, MAX_HOST_CONFIG * sizeof(host_config));
|
||||||
|
shmdt(shm_rw);
|
||||||
|
config = shm;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_load() {
|
int config_unload() {
|
||||||
|
int shm_id = shmget(SHM_KEY_CONFIG, 0, 0);
|
||||||
|
if (shm_id < 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
shmdt(config);
|
||||||
|
return -1;
|
||||||
|
} else if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
shmdt(config);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
shmdt(config);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_load(const char *filename) {
|
||||||
|
FILE *file = fopen(filename, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to open config file: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
unsigned long len = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
char *conf = malloc(len);
|
||||||
|
fread(conf, 1, len, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
host_config *tmp_config = malloc(MAX_HOST_CONFIG * sizeof(host_config));
|
||||||
|
memset(tmp_config, 0, MAX_HOST_CONFIG * sizeof(host_config));
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int mode = 0;
|
||||||
|
char *ptr = NULL;
|
||||||
|
char host[256], *source, *target;
|
||||||
|
host[0] = 0;
|
||||||
|
while ((ptr = strtok(ptr == NULL ? conf : NULL, "\n")) != NULL) {
|
||||||
|
char *comment = strchr(ptr, '#');
|
||||||
|
if (comment != NULL) comment[0] = 0;
|
||||||
|
len = strlen(ptr);
|
||||||
|
if (ptr[0] == '[') {
|
||||||
|
if (ptr[len - 1] != ']') goto err;
|
||||||
|
strncpy(tmp_config[i].name, ptr + 1, len - 2);
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
} else if (i == 0) {
|
||||||
|
if (len > 12 && strncmp(ptr, "certificate", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
||||||
|
source = ptr + 11;
|
||||||
|
target = cert_file;
|
||||||
|
} else if (len > 12 && strncmp(ptr, "private_key", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
||||||
|
source = ptr + 11;
|
||||||
|
target = key_file;
|
||||||
|
} else if (len > 10 && strncmp(ptr, "geoip_dir", 9) == 0 && (ptr[9] == ' ' || ptr[9] == '\t')) {
|
||||||
|
source = ptr + 9;
|
||||||
|
target = geoip_dir;
|
||||||
|
} else if (len > 11 && strncmp(ptr, "dns_server", 10) == 0 && (ptr[10] == ' ' || ptr[10] == '\t')) {
|
||||||
|
source = ptr + 10;
|
||||||
|
target = dns_server;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
host_config *hc = &tmp_config[i - 1];
|
||||||
|
if (len > 8 && strncmp(ptr, "webroot", 7) == 0 && (ptr[7] == ' ' || ptr[7] == '\t')) {
|
||||||
|
source = ptr + 7;
|
||||||
|
target = hc->local.webroot;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_LOCAL;
|
||||||
|
}
|
||||||
|
} else if (len > 9 && strncmp(ptr, "dir_mode", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
||||||
|
source = ptr + 8;
|
||||||
|
target = NULL;
|
||||||
|
mode = 1;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_LOCAL;
|
||||||
|
}
|
||||||
|
} else if (len > 9 && strncmp(ptr, "hostname", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
||||||
|
source = ptr + 8;
|
||||||
|
target = hc->rev_proxy.hostname;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
}
|
||||||
|
} else if (len > 5 && strncmp(ptr, "port", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
||||||
|
source = ptr + 4;
|
||||||
|
target = NULL;
|
||||||
|
mode = 2;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *end_ptr = source + strlen(source) - 1;
|
||||||
|
while (source[0] == ' ' || source[0] == '\t') source++;
|
||||||
|
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') end_ptr--;
|
||||||
|
if (end_ptr <= source) {
|
||||||
|
err:
|
||||||
|
free(conf);
|
||||||
|
free(tmp_config);
|
||||||
|
fprintf(stderr, ERR_STR "Unable to parse config file" CLR_STR "\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
end_ptr[1] = 0;
|
||||||
|
if (target != NULL) {
|
||||||
|
strcpy(target, source);
|
||||||
|
} else if (mode == 1) {
|
||||||
|
if (strcmp(source, "forbidden") == 0) {
|
||||||
|
tmp_config[i - 1].local.dir_mode = URI_DIR_MODE_FORBIDDEN;
|
||||||
|
} else if (strcmp(source, "info") == 0) {
|
||||||
|
tmp_config[i - 1].local.dir_mode = URI_DIR_MODE_INFO;
|
||||||
|
} else if (strcmp(source, "list") == 0) {
|
||||||
|
tmp_config[i - 1].local.dir_mode = URI_DIR_MODE_LIST;
|
||||||
|
} else {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else if (mode == 2) {
|
||||||
|
tmp_config[i - 1].rev_proxy.port = (unsigned short) strtoul(source, NULL, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(conf);
|
||||||
|
|
||||||
|
int shm_id = shmget(SHM_KEY_CONFIG, 0, 0);
|
||||||
|
if (shm_id < 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
shmdt(config);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *shm_rw = shmat(shm_id, NULL, 0);
|
||||||
|
if (shm_rw == (void *) -1) {
|
||||||
|
free(tmp_config);
|
||||||
|
fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
memcpy(shm_rw, tmp_config, MAX_HOST_CONFIG * sizeof(host_config));
|
||||||
|
free(tmp_config);
|
||||||
|
shmdt(shm_rw);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
19
src/config.h
19
src/config.h
@ -9,24 +9,35 @@
|
|||||||
#ifndef NECRONDA_SERVER_CONFIG_H
|
#ifndef NECRONDA_SERVER_CONFIG_H
|
||||||
#define NECRONDA_SERVER_CONFIG_H
|
#define NECRONDA_SERVER_CONFIG_H
|
||||||
|
|
||||||
|
#define CONFIG_TYPE_UNSET 0
|
||||||
|
#define CONFIG_TYPE_LOCAL 1
|
||||||
|
#define CONFIG_TYPE_REVERSE_PROXY 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int type;
|
int type;
|
||||||
char name[256];
|
char name[256];
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
char address[256];
|
char hostname[256];
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
};
|
} rev_proxy;
|
||||||
struct {
|
struct {
|
||||||
char webroot[256];
|
char webroot[256];
|
||||||
unsigned char dir_mode;
|
unsigned char dir_mode;
|
||||||
};
|
} local;
|
||||||
};
|
};
|
||||||
} host_config;
|
} host_config;
|
||||||
|
|
||||||
|
|
||||||
|
host_config *config;
|
||||||
|
char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
|
||||||
|
|
||||||
|
|
||||||
int config_init();
|
int config_init();
|
||||||
|
|
||||||
int config_load();
|
int config_load(const char *filename);
|
||||||
|
|
||||||
|
int config_unload();
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_CONFIG_H
|
#endif //NECRONDA_SERVER_CONFIG_H
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
|
|
||||||
int active = 1;
|
int active = 1;
|
||||||
|
const char *config_file;
|
||||||
|
|
||||||
|
|
||||||
void openssl_init() {
|
void openssl_init() {
|
||||||
@ -88,6 +89,7 @@ void destroy() {
|
|||||||
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
||||||
}
|
}
|
||||||
cache_unload();
|
cache_unload();
|
||||||
|
config_unload();
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +158,7 @@ void terminate() {
|
|||||||
fprintf(stderr, "Goodbye\n");
|
fprintf(stderr, "Goodbye\n");
|
||||||
}
|
}
|
||||||
cache_unload();
|
cache_unload();
|
||||||
|
config_unload();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,68 +193,42 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
printf("Necronda Web Server\n");
|
printf("Necronda Web Server\n");
|
||||||
|
|
||||||
|
ret = config_init();
|
||||||
|
if (ret != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_file = NULL;
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
unsigned long len = strlen(arg);
|
|
||||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-DIR>] [-d <DNS-SERVER>]\n"
|
printf("Usage: necronda-server [-h] [-c <CONFIG-FILE>]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -c, --cert <CERT-FILE> path to the full chain certificate file\n"
|
" -c, --config <CONFIG-FILE> path to the config file. If not provided, default will be used\n"
|
||||||
" -d, --dns <DNS-SERVER> ip address or hostname of a DNS server for dig\n"
|
" -h, --help print this dialogue\n");
|
||||||
" -g, --geoip <DB-DIR> path to a Maxmind GeoIP Database file\n"
|
config_unload();
|
||||||
" -h, --help print this dialogue\n"
|
|
||||||
" -p, --privkey <KEY-FILE> path to the private key file\n"
|
|
||||||
" -w, --webroot <PATH> path to the web root directory\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (strcmp(arg, "-w") == 0 || strcmp(arg, "--webroot") == 0) {
|
} else if (strcmp(arg, "-c") == 0 || strcmp(arg, "--config") == 0) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --webroot <WEBROOT>" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --config <CONFIG-FILE>" CLR_STR "\n", arg);
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
webroot_base = argv[++i];
|
config_file = argv[++i];
|
||||||
} else if (strcmp(arg, "-c") == 0 || strcmp(arg, "--cert") == 0) {
|
|
||||||
if (i == argc - 1) {
|
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --cert <CERT-FILE>" CLR_STR "\n", arg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
cert_file = argv[++i];
|
|
||||||
} else if (strcmp(arg, "-p") == 0 || strcmp(arg, "--privkey") == 0) {
|
|
||||||
if (i == argc - 1) {
|
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --privkey <KEY-FILE>" CLR_STR "\n", arg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
key_file = argv[++i];
|
|
||||||
} else if (strcmp(arg, "-g") == 0 || strcmp(arg, "--geoip") == 0) {
|
|
||||||
if (i == argc - 1) {
|
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-DIR>" CLR_STR "\n", arg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
geoip_dir = argv[++i];
|
|
||||||
} else if (strcmp(arg, "-d") == 0 || strcmp(arg, "--dns") == 0) {
|
|
||||||
if (i == argc - 1) {
|
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --dns <DNS-SERVER>" CLR_STR "\n", arg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dns_server = argv[++i];
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument '%s'" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument '%s'" CLR_STR "\n", arg);
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webroot_base == NULL) {
|
ret = config_load(config_file == NULL ? DEFAULT_CONFIG_FILE : config_file);
|
||||||
fprintf(stderr, ERR_STR "Error: --webroot is missing" CLR_STR "\n");
|
if (ret != 0) {
|
||||||
return 1;
|
config_unload();
|
||||||
}
|
|
||||||
if (cert_file == NULL) {
|
|
||||||
fprintf(stderr, ERR_STR "Error: --cert is missing" CLR_STR "\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (key_file == NULL) {
|
|
||||||
fprintf(stderr, ERR_STR "Error: --privkey is missing" CLR_STR "\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
printf("%s %s\n", cert_file, key_file);
|
||||||
|
|
||||||
sockets[0] = socket(AF_INET6, SOCK_STREAM, 0);
|
sockets[0] = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
if (sockets[0] < 0) goto socket_err;
|
if (sockets[0] < 0) goto socket_err;
|
||||||
@ -259,12 +236,14 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (sockets[1] < 0) {
|
if (sockets[1] < 0) {
|
||||||
socket_err:
|
socket_err:
|
||||||
fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES)) < 0) {
|
if (setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES)) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to set options for socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to set options for socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,16 +252,18 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (bind(sockets[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) < 0) {
|
if (bind(sockets[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) < 0) {
|
||||||
bind_err:
|
bind_err:
|
||||||
fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGINT, terminate);
|
signal(SIGINT, terminate);
|
||||||
signal(SIGTERM, terminate);
|
signal(SIGTERM, terminate);
|
||||||
|
|
||||||
if (geoip_dir != NULL) {
|
if (geoip_dir[0] != 0) {
|
||||||
DIR *geoip = opendir(geoip_dir);
|
DIR *geoip = opendir(geoip_dir);
|
||||||
if (geoip == NULL) {
|
if (geoip == NULL) {
|
||||||
fprintf(stderr, ERR_STR "Unable to open GeoIP dir: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to open GeoIP dir: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
struct dirent *dir;
|
struct dirent *dir;
|
||||||
@ -291,18 +272,21 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (strcmp(dir->d_name + strlen(dir->d_name) - 5, ".mmdb") != 0) continue;
|
if (strcmp(dir->d_name + strlen(dir->d_name) - 5, ".mmdb") != 0) continue;
|
||||||
if (i >= MAX_MMDB) {
|
if (i >= MAX_MMDB) {
|
||||||
fprintf(stderr, ERR_STR "Too many .mmdb files" CLR_STR "\n");
|
fprintf(stderr, ERR_STR "Too many .mmdb files" CLR_STR "\n");
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sprintf(buf, "%s/%s", geoip_dir, dir->d_name);
|
sprintf(buf, "%s/%s", geoip_dir, dir->d_name);
|
||||||
ret = MMDB_open(buf, 0, &mmdbs[i]);
|
ret = MMDB_open(buf, 0, &mmdbs[i]);
|
||||||
if (ret != MMDB_SUCCESS) {
|
if (ret != MMDB_SUCCESS) {
|
||||||
fprintf(stderr, ERR_STR "Unable to open .mmdb file: %s" CLR_STR "\n", MMDB_strerror(ret));
|
fprintf(stderr, ERR_STR "Unable to open .mmdb file: %s" CLR_STR "\n", MMDB_strerror(ret));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
fprintf(stderr, ERR_STR "No .mmdb files found in %s" CLR_STR "\n", geoip_dir);
|
fprintf(stderr, ERR_STR "No .mmdb files found in %s" CLR_STR "\n", geoip_dir);
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
closedir(geoip);
|
closedir(geoip);
|
||||||
@ -324,17 +308,20 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (SSL_CTX_use_certificate_chain_file(client.ctx, cert_file) != 1) {
|
if (SSL_CTX_use_certificate_chain_file(client.ctx, cert_file) != 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s: %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s: %s" CLR_STR "\n",
|
||||||
ERR_reason_error_string(ERR_get_error()), cert_file);
|
ERR_reason_error_string(ERR_get_error()), cert_file);
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (SSL_CTX_use_PrivateKey_file(client.ctx, key_file, SSL_FILETYPE_PEM) != 1) {
|
if (SSL_CTX_use_PrivateKey_file(client.ctx, key_file, SSL_FILETYPE_PEM) != 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to load private key file: %s: %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to load private key file: %s: %s" CLR_STR "\n",
|
||||||
ERR_reason_error_string(ERR_get_error()), key_file);
|
ERR_reason_error_string(ERR_get_error()), key_file);
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,6 +336,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
ret = cache_init();
|
ret = cache_init();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
} else if (ret != 0) {
|
} else if (ret != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -363,6 +351,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
||||||
if (ready_sockets_num < 0) {
|
if (ready_sockets_num < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
terminate();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define NUM_SOCKETS 2
|
#define NUM_SOCKETS 2
|
||||||
#define MAX_CHILDREN 1024
|
#define MAX_CHILDREN 1024
|
||||||
#define MAX_MMDB 3
|
#define MAX_MMDB 3
|
||||||
|
#define MAX_HOST_CONFIG 64
|
||||||
#define LISTEN_BACKLOG 16
|
#define LISTEN_BACKLOG 16
|
||||||
#define REQ_PER_CONNECTION 100
|
#define REQ_PER_CONNECTION 100
|
||||||
#define CLIENT_TIMEOUT 3600
|
#define CLIENT_TIMEOUT 3600
|
||||||
@ -70,13 +71,14 @@
|
|||||||
#ifndef PHP_FPM_SOCKET
|
#ifndef PHP_FPM_SOCKET
|
||||||
#define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock"
|
#define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef DEFAULT_CONFIG_FILE
|
||||||
|
#define DEFAULT_CONFIG_FILE "/etc/necronda-server/necronda-server.conf"
|
||||||
|
#endif
|
||||||
|
|
||||||
int sockets[NUM_SOCKETS];
|
int sockets[NUM_SOCKETS];
|
||||||
pid_t children[MAX_CHILDREN];
|
pid_t children[MAX_CHILDREN];
|
||||||
MMDB_s mmdbs[MAX_MMDB];
|
MMDB_s mmdbs[MAX_MMDB];
|
||||||
|
|
||||||
const char *cert_file, *key_file, *webroot_base, *geoip_dir, *dns_server;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int enc:1;
|
unsigned int enc:1;
|
||||||
int socket;
|
int socket;
|
||||||
|
Reference in New Issue
Block a user