7 Commits

5 changed files with 51 additions and 34 deletions

View File

@@ -5,6 +5,7 @@ Necronda web server
## Features
* Full IPv4 and IPv6 support
* TLS Server Name Inspection (SNI)
* Serving local files via HTTP and HTTPS
* File compression ([gzip](https://www.gzip.org/), [Brotli](https://www.brotli.org/)) and disk cache for compressed files
* Reverse proxy for other HTTP and HTTPS servers
@@ -22,23 +23,25 @@ See [docs/example.conf](docs/example.conf) for more details.
### Global directives
* `certificate` - path to SSL certificate (or certificate chain)
* `private_key` - path to SSL private key
* `geoip_dir` (optional) - path to a directory containing GeoIP databases
* `dns_server` (optional) - address of a DNS server
### Virtual host configuration
### Configuration
* `[<host>]` - begins section for the virtual host `<host>`
* Local
* `webroot` - path to the root directory
* `dir_mode` - specify the behaviour for directories without an `index.html` or `index.php`
* `forbidden` - the server will respond with `403 Forbidden`
* `info` - try passing *path info* to an upper `.php` file.
* `list` - list contents of directory (**not implemented yet**)
* Reverse proxy
* `hostname` - hostname of server to be reverse proxy of
* `port` - port to be used
* `http` - use HTTP to communicate with server
* `https` - use HTTPS to communicate with server
* `[cert <cert-name]` - begins section for a certificate
* `certificate` - path to SSL certificate (or certificate chain)
* `private_key` - path to SSL private key
* `[host <host>]` - begins section for the virtual host `<host>`
* `cert` - the name of the certificate to use
* Local
* `webroot` - path to the root directory
* `dir_mode` - specify the behaviour for directories without an `index.html` or `index.php`
* `forbidden` - the server will respond with `403 Forbidden`
* `info` - try passing *path info* to an upper `.php` file.
* `list` - list contents of directory (**not implemented yet**)
* Reverse proxy
* `hostname` - hostname of server to be reverse proxy of
* `port` - port to be used
* `http` - use HTTP to communicate with server
* `https` - use HTTPS to communicate with server

View File

@@ -37,6 +37,10 @@ host_config *get_host_config(const char *host) {
host_config *hc = &config->hosts[i];
if (hc->type == CONFIG_TYPE_UNSET) break;
if (strcmp(hc->name, host) == 0) return hc;
if (hc->name[0] == '*' && hc->name[1] == '.') {
const char *pos = strstr(host, hc->name + 1);
if (pos != NULL && strlen(pos) == strlen(hc->name + 1)) return hc;
}
}
return NULL;
}
@@ -568,7 +572,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
char *rev_proxy_doc = "";
if (conf != NULL && conf->type == CONFIG_TYPE_REVERSE_PROXY) {
const http_status *status = http_get_status(ctx.status);
char stat_str[4];
char stat_str[8];
sprintf(stat_str, "%03i", ctx.status);
sprintf(msg_pre_buf_2, http_rev_proxy_document,
" success",

View File

@@ -68,8 +68,9 @@ int config_load(const char *filename) {
fseek(file, 0, SEEK_END);
unsigned long len = ftell(file);
fseek(file, 0, SEEK_SET);
char *conf = malloc(len);
char *conf = alloca(len + 1);
fread(conf, 1, len, file);
conf[len] = 0;
fclose(file);
t_config *tmp_config = malloc(sizeof(t_config));
@@ -77,16 +78,28 @@ int config_load(const char *filename) {
int i = 0;
int j = 0;
int line = 0;
int mode = 0;
char section = 0;
char *ptr = NULL;
char *source, *target;
while ((ptr = strtok(ptr == NULL ? conf : NULL, "\n")) != NULL) {
while ((ptr = strsep(&conf, "\r\n")) != NULL) {
line++;
char *comment = strchr(ptr, '#');
if (comment != NULL) comment[0] = 0;
len = strlen(ptr);
char *end_ptr = ptr + len - 1;
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') {
end_ptr[0] = 0;
end_ptr--;
}
len = strlen(ptr);
if (len == 0) continue;
if (ptr[0] == '[') {
if (ptr[len - 1] != ']') goto err;
ptr++;
int l = 0;
if (strncmp(ptr, "host", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
ptr += 4;
@@ -115,6 +128,8 @@ int config_load(const char *filename) {
} else if (len > 11 && strncmp(ptr, "dns_server", 10) == 0 && (ptr[10] == ' ' || ptr[10] == '\t')) {
source = ptr + 10;
target = dns_server;
} else {
goto err;
}
} else if (section == 'c') {
cert_config *cc = &tmp_config->certs[j - 1];
@@ -124,6 +139,8 @@ int config_load(const char *filename) {
} else if (len > 12 && strncmp(ptr, "private_key", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
source = ptr + 11;
target = cc->priv_key;
} else {
goto err;
}
} else if (section == 'h') {
host_config *hc = &tmp_config->hosts[i - 1];
@@ -180,21 +197,21 @@ int config_load(const char *filename) {
hc->rev_proxy.enc = 1;
}
continue;
} else {
goto err;
}
} else {
goto err;
}
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) {
if (strlen(source) == 0) {
err:
free(conf);
free(tmp_config);
fprintf(stderr, ERR_STR "Unable to parse config file" CLR_STR "\n");
fprintf(stderr, ERR_STR "Unable to parse config file (line %i)" CLR_STR "\n", line);
return -2;
}
end_ptr[1] = 0;
if (target != NULL) {
strcpy(target, source);
} else if (mode == 1) {
@@ -211,7 +228,6 @@ int config_load(const char *filename) {
tmp_config->hosts[i - 1].rev_proxy.port = (unsigned short) strtoul(source, NULL, 10);
}
}
free(conf);
for (int k = 0; k < i; k++) {
host_config *hc = &tmp_config->hosts[k];

View File

@@ -50,14 +50,8 @@ void openssl_init() {
static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) {
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (servername != NULL) {
for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
const host_config *conf = &config->hosts[i];
if (conf->type == CONFIG_TYPE_UNSET) break;
if (strcmp(conf->name, servername) == 0) {
SSL_set_SSL_CTX(ssl, contexts[conf->cert]);
break;
}
}
const host_config *conf = get_host_config(servername);
if (conf != NULL) SSL_set_SSL_CTX(ssl, contexts[conf->cert]);
}
return SSL_TLSEXT_ERR_OK;
}

View File

@@ -8,7 +8,7 @@
#ifndef NECRONDA_SERVER_NECRONDA_H
#define NECRONDA_SERVER_NECRONDA_H
#define NECRONDA_VERSION "4.4"
#define NECRONDA_VERSION "4.5"
#define SERVER_STR "Necronda/" NECRONDA_VERSION
#define SERVER_STR_HTML "Necronda&nbsp;web&nbsp;server&nbsp;" NECRONDA_VERSION