Compare commits
10 Commits
v4.3
...
10d405e745
Author | SHA1 | Date | |
---|---|---|---|
10d405e745
|
|||
28f163f97a
|
|||
a8914aa981
|
|||
2ada22481d
|
|||
17b25a3596
|
|||
d130474989
|
|||
8dea0cd3fc
|
|||
0406cad0d8
|
|||
21b7ab585a
|
|||
7587e15749
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,7 +1,8 @@
|
|||||||
*
|
*
|
||||||
!src
|
!src
|
||||||
!src/**
|
!src/**
|
||||||
!run.sh
|
!docs
|
||||||
|
!docs/**
|
||||||
!Makefile
|
!Makefile
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!README.md
|
!README.md
|
||||||
|
27
Makefile
27
Makefile
@ -1,19 +1,28 @@
|
|||||||
.DEFAULT_GOAL := install
|
|
||||||
|
CFLAGS=-std=c11 -Wall
|
||||||
|
INCLUDE=-lssl -lcrypto -lmagic -lz -lmaxminddb
|
||||||
|
LIBS=src/lib/*.c
|
||||||
|
|
||||||
|
DEBIAN_OPTS=-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" -D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
@echo "Installing packages..."
|
@echo "Installing packages..."
|
||||||
sudo apt-get install gcc libmagic-dev libssl-dev php-fpm
|
sudo apt install gcc php-fpm libmagic-dev libssl-dev libmaxminddb-dev
|
||||||
@echo "Finished downloading!"
|
@echo "Finished downloading!"
|
||||||
|
|
||||||
|
permit:
|
||||||
|
sudo setcap 'cap_net_bind_service=+ep' "$(shell pwd)/bin/necronda-server"
|
||||||
|
|
||||||
compile:
|
compile:
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb -Wall
|
gcc $(LIBS) -o bin/libnecronda-server.so --shared -fPIC $(CFLAGS) $(INCLUDE)
|
||||||
|
gcc src/necronda-server.c -o bin/necronda-server $(CFLAGS) $(INCLUDE) \
|
||||||
|
-Lbin -lnecronda-server -Wl,-rpath=$(shell pwd)/bin
|
||||||
|
|
||||||
compile-debian:
|
compile-debian:
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb -Wall \
|
gcc $(LIBS) -o bin/libnecronda-server.so --shared -fPIC $(CFLAGS) $(INCLUDE) \
|
||||||
-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" \
|
$(DEBIAN_OPTS)
|
||||||
-D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
|
gcc src/necronda-server.c -o bin/necronda-server $(CFLAGS) $(INCLUDE) \
|
||||||
|
-Lbin -lnecronda-server -Wl,-rpath=$(shell pwd)/bin \
|
||||||
install: | packages compile
|
$(DEBIAN_OPTS)
|
||||||
@echo "Finished!"
|
|
||||||
|
44
README.md
44
README.md
@ -1,2 +1,44 @@
|
|||||||
|
|
||||||
# Necronda web server
|
Necronda web server
|
||||||
|
===================
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Full IPv4 and IPv6 support
|
||||||
|
* Serving local files via HTTP and HTTPS
|
||||||
|
* File compression and disk cache for compressed files
|
||||||
|
* Reverse proxy for other HTTP and HTTPS servers
|
||||||
|
* FastCGI support (e.g. [PHP-FPM](https://php-fpm.org/))
|
||||||
|
* Support for [MaxMind's GeoIP Database](https://www.maxmind.com/en/geoip2-services-and-databases)
|
||||||
|
* DNS reverse lookup for connecting hosts
|
||||||
|
* Automatic URL rewrite (e.g. `/index.html` -> `/`, `/test.php` -> `/test`)
|
||||||
|
* Modern looking and responsive error documents
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
* `[<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
|
||||||
|
19
docs/example.conf
Normal file
19
docs/example.conf
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
certificate /var/cert/cert.pem
|
||||||
|
private_key /var/cert/cert.key
|
||||||
|
#geoip_dir /var/dir
|
||||||
|
#dns_server 192.168.0.1
|
||||||
|
|
||||||
|
[localhost]
|
||||||
|
webroot /var/www/localhost
|
||||||
|
dir_mode forbidden
|
||||||
|
|
||||||
|
[me.local]
|
||||||
|
hostname www.example.com
|
||||||
|
port 80
|
||||||
|
http
|
||||||
|
|
||||||
|
[secure.local]
|
||||||
|
hostname www.example.com
|
||||||
|
port 443
|
||||||
|
https
|
6
run.sh
6
run.sh
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
echo "-- Building and starting Necronda Server..."
|
|
||||||
make compile && \
|
|
||||||
echo "-- Successfully finished compiling!" && \
|
|
||||||
echo "-- Starting Server..." && \
|
|
||||||
./bin/necronda-server $@
|
|
91
src/client.c
91
src/client.c
@ -6,7 +6,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "lib/utils.h"
|
||||||
|
#include "lib/config.h"
|
||||||
|
#include "lib/sock.h"
|
||||||
|
#include "lib/http.h"
|
||||||
|
#include "lib/rev_proxy.h"
|
||||||
|
#include "lib/fastcgi.h"
|
||||||
|
#include "lib/cache.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
int server_keep_alive = 1;
|
||||||
|
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
||||||
|
|
||||||
|
int server_keep_alive;
|
||||||
|
char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
|
||||||
|
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
|
||||||
|
struct timeval client_timeout;
|
||||||
|
|
||||||
host_config *get_host_config(const char *host) {
|
host_config *get_host_config(const char *host) {
|
||||||
for (int i = 0; i < MAX_HOST_CONFIG; i++) {
|
for (int i = 0; i < MAX_HOST_CONFIG; i++) {
|
||||||
@ -174,7 +197,27 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (http_get_header_field(&req.hdr, "Transfer-Encoding") != NULL) {
|
||||||
|
sprintf(err_msg, "This server is unable to process requests with the Transfer-Encoding header field.");
|
||||||
|
res.status = http_get_status(501);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
if (conf->type == CONFIG_TYPE_LOCAL) {
|
if (conf->type == CONFIG_TYPE_LOCAL) {
|
||||||
|
if (strcmp(req.method, "TRACE") == 0) {
|
||||||
|
res.status = http_get_status(200);
|
||||||
|
http_add_header_field(&res.hdr, "Content-Type", "message/http");
|
||||||
|
|
||||||
|
content_length = snprintf(msg_buf, sizeof(msg_buf) - content_length, "%s %s HTTP/%s\r\n",
|
||||||
|
req.method, req.uri, req.version);
|
||||||
|
for (int i = 0; i < req.hdr.field_num; i++) {
|
||||||
|
content_length += snprintf(msg_buf + content_length, sizeof(msg_buf) - content_length, "%s: %s\r\n",
|
||||||
|
req.hdr.fields[i][0], req.hdr.fields[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp(uri.req_path, "/.well-known/", 13) != 0 && strstr(uri.path, "/.") != NULL) {
|
if (strncmp(uri.req_path, "/.well-known/", 13) != 0 && strstr(uri.path, "/.") != NULL) {
|
||||||
res.status = http_get_status(403);
|
res.status = http_get_status(403);
|
||||||
sprintf(err_msg, "Parts of this URI are hidden.");
|
sprintf(err_msg, "Parts of this URI are hidden.");
|
||||||
@ -198,13 +241,18 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
|
|
||||||
if (uri.is_static) {
|
if (uri.is_static) {
|
||||||
res.status = http_get_status(200);
|
res.status = http_get_status(200);
|
||||||
http_add_header_field(&res.hdr, "Allow", "GET, HEAD");
|
|
||||||
http_add_header_field(&res.hdr, "Accept-Ranges", "bytes");
|
http_add_header_field(&res.hdr, "Accept-Ranges", "bytes");
|
||||||
if (strcmp(req.method, "GET") != 0 && strcmp(req.method, "HEAD") != 0) {
|
if (strcmp(req.method, "GET") != 0 && strcmp(req.method, "HEAD") != 0) {
|
||||||
res.status = http_get_status(405);
|
res.status = http_get_status(405);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (http_get_header_field(&req.hdr, "Content-Length") != NULL) {
|
||||||
|
res.status = http_get_status(400);
|
||||||
|
sprintf(err_msg, "A GET request must not contain a payload");
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
ret = uri_cache_init(&uri);
|
ret = uri_cache_init(&uri);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
res.status = http_get_status(500);
|
res.status = http_get_status(500);
|
||||||
@ -227,8 +275,8 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
char *if_modified_since = http_get_header_field(&req.hdr, "If-Modified-Since");
|
char *if_modified_since = http_get_header_field(&req.hdr, "If-Modified-Since");
|
||||||
char *if_none_match = http_get_header_field(&req.hdr, "If-None-Match");
|
char *if_none_match = http_get_header_field(&req.hdr, "If-None-Match");
|
||||||
if ((if_none_match != NULL && strstr(if_none_match, uri.meta->etag) == NULL) ||
|
if ((if_none_match != NULL && strstr(if_none_match, uri.meta->etag) == NULL) ||
|
||||||
(accept_if_modified_since && if_modified_since != NULL &&
|
(accept_if_modified_since && if_modified_since != NULL &&
|
||||||
strcmp(if_modified_since, last_modified) == 0)) {
|
strcmp(if_modified_since, last_modified) == 0)) {
|
||||||
res.status = http_get_status(304);
|
res.status = http_get_status(304);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
@ -279,7 +327,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
|
|
||||||
char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
|
char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
|
||||||
if (uri.meta->filename_comp[0] != 0 && accept_encoding != NULL &&
|
if (uri.meta->filename_comp[0] != 0 && accept_encoding != NULL &&
|
||||||
strstr(accept_encoding, "deflate") != NULL) {
|
strstr(accept_encoding, "deflate") != NULL) {
|
||||||
file = fopen(uri.meta->filename_comp, "rb");
|
file = fopen(uri.meta->filename_comp, "rb");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
cache_filename_comp_invalid(uri.filename);
|
cache_filename_comp_invalid(uri.filename);
|
||||||
@ -306,13 +354,9 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(req.method, "POST") == 0 || strcmp(req.method, "PUT") == 0) {
|
char *client_content_length = http_get_header_field(&req.hdr, "Content-Length");
|
||||||
char *client_content_length = http_get_header_field(&req.hdr, "Content-Length");
|
if (client_content_length != NULL) {
|
||||||
unsigned long client_content_len;
|
unsigned long client_content_len = strtoul(client_content_length, NULL, 10);
|
||||||
if (client_content_length == NULL) {
|
|
||||||
goto fastcgi_end;
|
|
||||||
}
|
|
||||||
client_content_len = strtoul(client_content_length, NULL, 10);
|
|
||||||
ret = fastcgi_receive(&php_fpm, client, client_content_len);
|
ret = fastcgi_receive(&php_fpm, client, client_content_len);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -324,7 +368,6 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fastcgi_end:
|
|
||||||
fastcgi_close_stdin(&php_fpm);
|
fastcgi_close_stdin(&php_fpm);
|
||||||
|
|
||||||
ret = fastcgi_header(&php_fpm, &res, err_msg);
|
ret = fastcgi_header(&php_fpm, &res, err_msg);
|
||||||
@ -351,13 +394,18 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
|
|
||||||
if (accept_encoding != NULL && strstr(accept_encoding, "deflate") != NULL) {
|
|
||||||
http_add_header_field(&res.hdr, "Content-Encoding", "deflate");
|
|
||||||
}
|
|
||||||
|
|
||||||
content_length = -1;
|
content_length = -1;
|
||||||
use_fastcgi = 1;
|
use_fastcgi = 1;
|
||||||
|
|
||||||
|
char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
|
||||||
|
char *content_type = http_get_header_field(&res.hdr, "Content-Type");
|
||||||
|
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
||||||
|
if (mime_is_compressible(content_type) && content_encoding == NULL &&
|
||||||
|
accept_encoding != NULL && strstr(accept_encoding, "deflate") != NULL) {
|
||||||
|
http_add_header_field(&res.hdr, "Content-Encoding", "deflate");
|
||||||
|
use_fastcgi = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (http_get_header_field(&res.hdr, "Content-Length") == NULL) {
|
if (http_get_header_field(&res.hdr, "Content-Length") == NULL) {
|
||||||
http_add_header_field(&res.hdr, "Transfer-Encoding", "chunked");
|
http_add_header_field(&res.hdr, "Transfer-Encoding", "chunked");
|
||||||
}
|
}
|
||||||
@ -375,11 +423,14 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
|
|
||||||
respond:
|
respond:
|
||||||
if (!use_rev_proxy) {
|
if (!use_rev_proxy) {
|
||||||
|
if (conf != NULL && conf->type == CONFIG_TYPE_LOCAL && uri.is_static && res.status->code == 405) {
|
||||||
|
http_add_header_field(&res.hdr, "Allow", "GET, HEAD, TRACE");
|
||||||
|
}
|
||||||
if (http_get_header_field(&res.hdr, "Accept-Ranges") == NULL) {
|
if (http_get_header_field(&res.hdr, "Accept-Ranges") == NULL) {
|
||||||
http_add_header_field(&res.hdr, "Accept-Ranges", "none");
|
http_add_header_field(&res.hdr, "Accept-Ranges", "none");
|
||||||
}
|
}
|
||||||
if (!use_fastcgi && !use_rev_proxy && file == NULL &&
|
if (!use_fastcgi && !use_rev_proxy && file == NULL &&
|
||||||
((res.status->code >= 400 && res.status->code < 600) || err_msg[0] != 0)) {
|
((res.status->code >= 400 && res.status->code < 600) || err_msg[0] != 0)) {
|
||||||
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
|
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
|
||||||
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
|
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
|
||||||
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
|
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
|
||||||
@ -450,9 +501,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
} else if (use_fastcgi) {
|
} else if (use_fastcgi) {
|
||||||
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
||||||
int chunked = transfer_encoding != NULL && strcmp(transfer_encoding, "chunked") == 0;
|
int chunked = transfer_encoding != NULL && strcmp(transfer_encoding, "chunked") == 0;
|
||||||
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
int flags = (chunked ? FASTCGI_CHUNKED : 0) | ((use_fastcgi == 2) ? FASTCGI_COMPRESS : 0);
|
||||||
int comp = content_encoding != NULL && strcmp(content_encoding, "deflate") == 0;
|
|
||||||
int flags = (chunked ? FASTCGI_CHUNKED : 0) | (comp ? FASTCGI_COMPRESS : 0);
|
|
||||||
fastcgi_send(&php_fpm, client, flags);
|
fastcgi_send(&php_fpm, client, flags);
|
||||||
} else if (use_rev_proxy) {
|
} else if (use_rev_proxy) {
|
||||||
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
||||||
|
15
src/client.h
15
src/client.h
@ -8,16 +8,11 @@
|
|||||||
#ifndef NECRONDA_SERVER_CLIENT_H
|
#ifndef NECRONDA_SERVER_CLIENT_H
|
||||||
#define NECRONDA_SERVER_CLIENT_H
|
#define NECRONDA_SERVER_CLIENT_H
|
||||||
|
|
||||||
#include "necronda-server.h"
|
#include <sys/time.h>
|
||||||
#include "utils.h"
|
|
||||||
#include "uri.h"
|
|
||||||
#include "http.h"
|
|
||||||
#include "fastcgi.h"
|
|
||||||
|
|
||||||
|
extern int server_keep_alive;
|
||||||
int server_keep_alive = 1;
|
extern char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
|
||||||
char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
|
extern char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
|
||||||
|
extern struct timeval client_timeout;
|
||||||
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_CLIENT_H
|
#endif //NECRONDA_SERVER_CLIENT_H
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* File cache implementation
|
* File cache implementation
|
||||||
* src/cache.c
|
* src/lib/cache.c
|
||||||
* Lorenz Stechauner, 2020-12-19
|
* Lorenz Stechauner, 2020-12-19
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "../necronda-server.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <magic.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
int cache_continue = 1;
|
||||||
|
magic_t magic;
|
||||||
|
cache_entry *cache;
|
||||||
|
|
||||||
int magic_init() {
|
int magic_init() {
|
||||||
magic = magic_open(MAGIC_MIME);
|
magic = magic_open(MAGIC_MIME);
|
||||||
@ -77,9 +91,7 @@ int cache_process() {
|
|||||||
fprintf(stdout, "[cache] Hashing file %s\n", cache[i].filename);
|
fprintf(stdout, "[cache] Hashing file %s\n", cache[i].filename);
|
||||||
SHA1_Init(&ctx);
|
SHA1_Init(&ctx);
|
||||||
file = fopen(cache[i].filename, "rb");
|
file = fopen(cache[i].filename, "rb");
|
||||||
compress = strncmp(cache[i].meta.type, "text/", 5) == 0 ||
|
compress = mime_is_compressible(cache[i].meta.type);
|
||||||
(strncmp(cache[i].meta.type, "application/", 12) == 0 &&
|
|
||||||
strstr(cache[i].meta.type, "+xml") != NULL);
|
|
||||||
|
|
||||||
int level = NECRONDA_ZLIB_LEVEL;
|
int level = NECRONDA_ZLIB_LEVEL;
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
@ -202,20 +214,18 @@ int cache_init() {
|
|||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
// child
|
// child
|
||||||
if (cache_process() == 0) {
|
if (cache_process() == 0) {
|
||||||
return 1;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return -6;
|
return -6;
|
||||||
}
|
}
|
||||||
} else if (pid > 0) {
|
} else if (pid > 0) {
|
||||||
// parent
|
// parent
|
||||||
fprintf(stderr, "Started child process with PID %i as cache-updater\n", pid);
|
fprintf(stderr, "Started child process with PID %i as cache-updater\n", pid);
|
||||||
children[0] = pid;
|
return pid;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cache_unload() {
|
int cache_unload() {
|
||||||
@ -288,7 +298,7 @@ int cache_filename_comp_invalid(const char *filename) {
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < FILE_CACHE_SIZE; i++) {
|
for (i = 0; i < FILE_CACHE_SIZE; i++) {
|
||||||
if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(filename) &&
|
if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(filename) &&
|
||||||
strcmp(cache[i].filename, filename) == 0) {
|
strcmp(cache[i].filename, filename) == 0) {
|
||||||
if (cache[i].is_updating) {
|
if (cache[i].is_updating) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@ -314,7 +324,7 @@ int uri_cache_init(http_uri *uri) {
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < FILE_CACHE_SIZE; i++) {
|
for (i = 0; i < FILE_CACHE_SIZE; i++) {
|
||||||
if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(uri->filename) &&
|
if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(uri->filename) &&
|
||||||
strcmp(cache[i].filename, uri->filename) == 0) {
|
strcmp(cache[i].filename, uri->filename) == 0) {
|
||||||
uri->meta = &cache[i].meta;
|
uri->meta = &cache[i].meta;
|
||||||
if (cache[i].is_updating) {
|
if (cache[i].is_updating) {
|
||||||
return 0;
|
return 0;
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* File cache implementation (header file)
|
* File cache implementation (header file)
|
||||||
* src/cache.h
|
* src/lib/cache.h
|
||||||
* Lorenz Stechauner, 2020-12-19
|
* Lorenz Stechauner, 2020-12-19
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,15 +10,6 @@
|
|||||||
|
|
||||||
#include "uri.h"
|
#include "uri.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <magic.h>
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
|
|
||||||
|
|
||||||
magic_t magic;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char filename[256];
|
char filename[256];
|
||||||
unsigned char webroot_len;
|
unsigned char webroot_len;
|
||||||
@ -26,9 +17,9 @@ typedef struct {
|
|||||||
meta_data meta;
|
meta_data meta;
|
||||||
} cache_entry;
|
} cache_entry;
|
||||||
|
|
||||||
cache_entry *cache;
|
extern cache_entry *cache;
|
||||||
|
|
||||||
int cache_continue = 1;
|
extern int cache_continue;
|
||||||
|
|
||||||
int magic_init();
|
int magic_init();
|
||||||
|
|
@ -1,12 +1,22 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Configuration file loader
|
* Configuration file loader
|
||||||
* src/config.c
|
* src/lib/config.c
|
||||||
* Lorenz Stechauner, 2021-01-05
|
* Lorenz Stechauner, 2021-01-05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "../necronda-server.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
host_config *config;
|
||||||
|
char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
|
||||||
|
|
||||||
int config_init() {
|
int config_init() {
|
||||||
int shm_id = shmget(SHM_KEY_CONFIG, MAX_HOST_CONFIG * sizeof(host_config), IPC_CREAT | IPC_EXCL | 0640);
|
int shm_id = shmget(SHM_KEY_CONFIG, MAX_HOST_CONFIG * sizeof(host_config), IPC_CREAT | IPC_EXCL | 0640);
|
@ -1,25 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Configuration file loader (header file)
|
* Configuration file loader (header file)
|
||||||
* src/config.h
|
* src/lib/config.h
|
||||||
* Lorenz Stechauner, 2021-01-05
|
* Lorenz Stechauner, 2021-01-05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_CONFIG_H
|
#ifndef NECRONDA_SERVER_CONFIG_H
|
||||||
#define NECRONDA_SERVER_CONFIG_H
|
#define NECRONDA_SERVER_CONFIG_H
|
||||||
|
|
||||||
|
#include "uri.h"
|
||||||
|
|
||||||
#define CONFIG_TYPE_UNSET 0
|
#define CONFIG_TYPE_UNSET 0
|
||||||
#define CONFIG_TYPE_LOCAL 1
|
#define CONFIG_TYPE_LOCAL 1
|
||||||
#define CONFIG_TYPE_REVERSE_PROXY 2
|
#define CONFIG_TYPE_REVERSE_PROXY 2
|
||||||
|
|
||||||
#include "uri.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int type;
|
int type;
|
||||||
char name[256];
|
char name[256];
|
||||||
@ -36,10 +30,8 @@ typedef struct {
|
|||||||
};
|
};
|
||||||
} host_config;
|
} host_config;
|
||||||
|
|
||||||
|
extern host_config *config;
|
||||||
host_config *config;
|
extern char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
|
||||||
char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
|
|
||||||
|
|
||||||
|
|
||||||
int config_init();
|
int config_init();
|
||||||
|
|
@ -1,12 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* FastCGI interface implementation
|
* FastCGI interface implementation
|
||||||
* src/fastcgi.c
|
* src/lib/fastcgi.c
|
||||||
* Lorenz Stechauner, 2020-12-26
|
* Lorenz Stechauner, 2020-12-26
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fastcgi.h"
|
#include "fastcgi.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "../client.h"
|
||||||
|
#include "../necronda-server.h"
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
char *fastcgi_add_param(char *buf, const char *key, const char *value) {
|
char *fastcgi_add_param(char *buf, const char *key, const char *value) {
|
||||||
char *ptr = buf;
|
char *ptr = buf;
|
41
src/lib/fastcgi.h
Normal file
41
src/lib/fastcgi.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Necronda Web Server
|
||||||
|
* FastCGI interface implementation (header file)
|
||||||
|
* src/lib/fastcgi.h
|
||||||
|
* Lorenz Stechauner, 2020-12-26
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NECRONDA_SERVER_FASTCGI_H
|
||||||
|
#define NECRONDA_SERVER_FASTCGI_H
|
||||||
|
|
||||||
|
#include "include/fastcgi.h"
|
||||||
|
#include "http.h"
|
||||||
|
#include "uri.h"
|
||||||
|
|
||||||
|
#define FASTCGI_CHUNKED 1
|
||||||
|
#define FASTCGI_COMPRESS 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int socket;
|
||||||
|
unsigned short req_id;
|
||||||
|
char *out_buf;
|
||||||
|
unsigned short out_len;
|
||||||
|
unsigned short out_off;
|
||||||
|
} fastcgi_conn;
|
||||||
|
|
||||||
|
char *fastcgi_add_param(char *buf, const char *key, const char *value);
|
||||||
|
|
||||||
|
int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_num, const sock *client,
|
||||||
|
const http_req *req, const http_uri *uri);
|
||||||
|
|
||||||
|
int fastcgi_close_stdin(fastcgi_conn *conn);
|
||||||
|
|
||||||
|
int fastcgi_php_error(const char *msg, int msg_len, char *err_msg);
|
||||||
|
|
||||||
|
int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg);
|
||||||
|
|
||||||
|
int fastcgi_send(fastcgi_conn *conn, sock *client, int flags);
|
||||||
|
|
||||||
|
int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len);
|
||||||
|
|
||||||
|
#endif //NECRONDA_SERVER_FASTCGI_H
|
@ -1,12 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* HTTP implementation
|
* HTTP implementation
|
||||||
* src/net/http.c
|
* src/lib/http.c
|
||||||
* Lorenz Stechauner, 2020-12-09
|
* Lorenz Stechauner, 2020-12-09
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "../necronda-server.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void http_to_camel_case(char *str, int mode) {
|
void http_to_camel_case(char *str, int mode) {
|
||||||
char last = '-';
|
char last = '-';
|
||||||
@ -245,7 +247,7 @@ int http_send_request(sock *server, http_req *req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const http_status *http_get_status(unsigned short status_code) {
|
const http_status *http_get_status(unsigned short status_code) {
|
||||||
for (int i = 0; i < sizeof(http_statuses) / sizeof(http_status); i++) {
|
for (int i = 0; i < http_statuses_size / sizeof(http_status); i++) {
|
||||||
if (http_statuses[i].code == status_code) {
|
if (http_statuses[i].code == status_code) {
|
||||||
return &http_statuses[i];
|
return &http_statuses[i];
|
||||||
}
|
}
|
||||||
@ -255,7 +257,7 @@ const http_status *http_get_status(unsigned short status_code) {
|
|||||||
|
|
||||||
const http_status_msg *http_get_error_msg(const http_status *status) {
|
const http_status_msg *http_get_error_msg(const http_status *status) {
|
||||||
unsigned short code = status->code;
|
unsigned short code = status->code;
|
||||||
for (int i = 0; i < sizeof(http_status_messages) / sizeof(http_status_msg); i++) {
|
for (int i = 0; i < http_status_messages_size / sizeof(http_status_msg); i++) {
|
||||||
if (http_status_messages[i].code == code) {
|
if (http_status_messages[i].code == code) {
|
||||||
return &http_status_messages[i];
|
return &http_status_messages[i];
|
||||||
}
|
}
|
111
src/lib/http.h
Normal file
111
src/lib/http.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* Necronda Web Server
|
||||||
|
* HTTP implementation (header file)
|
||||||
|
* src/lib/http.h
|
||||||
|
* Lorenz Stechauner, 2020-12-09
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NECRONDA_SERVER_HTTP_H
|
||||||
|
#define NECRONDA_SERVER_HTTP_H
|
||||||
|
|
||||||
|
#include "sock.h"
|
||||||
|
|
||||||
|
#define HTTP_PRESERVE 0
|
||||||
|
#define HTTP_LOWER 1
|
||||||
|
#define HTTP_CAMEL 2
|
||||||
|
|
||||||
|
#define HTTP_REMOVE_ONE 0
|
||||||
|
#define HTTP_REMOVE_ALL 1
|
||||||
|
#define HTTP_REMOVE_LAST 2
|
||||||
|
|
||||||
|
#define HTTP_COLOR_SUCCESS "#008000"
|
||||||
|
#define HTTP_COLOR_INFO "#606060"
|
||||||
|
#define HTTP_COLOR_WARNING "#E0C000"
|
||||||
|
#define HTTP_COLOR_ERROR "#C00000"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short code;
|
||||||
|
char type[16];
|
||||||
|
char msg[32];
|
||||||
|
} http_status;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short code;
|
||||||
|
const char *msg;
|
||||||
|
} http_status_msg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char mode[8];
|
||||||
|
char color[8];
|
||||||
|
const char *icon;
|
||||||
|
const char *doc;
|
||||||
|
} http_doc_info;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char field_num;
|
||||||
|
char *fields[64][2];
|
||||||
|
} http_hdr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char method[16];
|
||||||
|
char *uri;
|
||||||
|
char version[3];
|
||||||
|
http_hdr hdr;
|
||||||
|
} http_req;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const http_status *status;
|
||||||
|
char version[3];
|
||||||
|
http_hdr hdr;
|
||||||
|
} http_res;
|
||||||
|
|
||||||
|
extern const http_status http_statuses[];
|
||||||
|
extern const http_status_msg http_status_messages[];
|
||||||
|
extern const int http_statuses_size;
|
||||||
|
extern const int http_status_messages_size;
|
||||||
|
|
||||||
|
extern const char http_default_document[];
|
||||||
|
extern const char http_error_document[];
|
||||||
|
extern const char http_error_icon[];
|
||||||
|
extern const char http_warning_document[];
|
||||||
|
extern const char http_warning_icon[];
|
||||||
|
extern const char http_success_document[];
|
||||||
|
extern const char http_success_icon[];
|
||||||
|
extern const char http_info_document[];
|
||||||
|
extern const char http_info_icon[];
|
||||||
|
|
||||||
|
void http_to_camel_case(char *str, int mode);
|
||||||
|
|
||||||
|
void http_free_hdr(http_hdr *hdr);
|
||||||
|
|
||||||
|
void http_free_req(http_req *req);
|
||||||
|
|
||||||
|
void http_free_res(http_res *res);
|
||||||
|
|
||||||
|
int http_receive_request(sock *client, http_req *req);
|
||||||
|
|
||||||
|
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) ;
|
||||||
|
|
||||||
|
char *http_get_header_field(const http_hdr *hdr, const char *field_name);
|
||||||
|
|
||||||
|
void http_add_header_field(http_hdr *hdr, const char *field_name, const char *field_value);
|
||||||
|
|
||||||
|
void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode);
|
||||||
|
|
||||||
|
int http_send_response(sock *client, http_res *res);
|
||||||
|
|
||||||
|
int http_send_request(sock *server, http_req *req);
|
||||||
|
|
||||||
|
const http_status *http_get_status(unsigned short status_code);
|
||||||
|
|
||||||
|
const http_status_msg *http_get_error_msg(const http_status *status);
|
||||||
|
|
||||||
|
const char *http_get_status_color(const http_status *status);
|
||||||
|
|
||||||
|
char *http_format_date(time_t time, char *buf, size_t size);
|
||||||
|
|
||||||
|
char *http_get_date(char *buf, size_t size);
|
||||||
|
|
||||||
|
const http_doc_info *http_get_status_info(const http_status *status);
|
||||||
|
|
||||||
|
#endif //NECRONDA_SERVER_HTTP_H
|
@ -1,67 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* HTTP implementation (header file)
|
* HTTP static implementation
|
||||||
* src/net/http.h
|
* src/lib/http_static.c
|
||||||
* Lorenz Stechauner, 2020-12-09
|
* Lorenz Stechauner, 2021-05-03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_HTTP_H
|
#include "http.h"
|
||||||
#define NECRONDA_SERVER_HTTP_H
|
#include "../necronda-server.h"
|
||||||
|
|
||||||
#define HTTP_PRESERVE 0
|
const http_status http_statuses[] = {
|
||||||
#define HTTP_LOWER 1
|
|
||||||
#define HTTP_CAMEL 2
|
|
||||||
|
|
||||||
#define HTTP_REMOVE_ONE 0
|
|
||||||
#define HTTP_REMOVE_ALL 1
|
|
||||||
#define HTTP_REMOVE_LAST 2
|
|
||||||
|
|
||||||
#define HTTP_COLOR_SUCCESS "#008000"
|
|
||||||
#define HTTP_COLOR_INFO "#606060"
|
|
||||||
#define HTTP_COLOR_WARNING "#E0C000"
|
|
||||||
#define HTTP_COLOR_ERROR "#C00000"
|
|
||||||
|
|
||||||
#include "sock.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned short code;
|
|
||||||
char type[16];
|
|
||||||
char msg[32];
|
|
||||||
} http_status;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned short code;
|
|
||||||
const char *msg;
|
|
||||||
} http_status_msg;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char mode[8];
|
|
||||||
char color[8];
|
|
||||||
const char *icon;
|
|
||||||
const char *doc;
|
|
||||||
} http_doc_info;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char field_num;
|
|
||||||
char *fields[64][2];
|
|
||||||
} http_hdr;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char method[16];
|
|
||||||
char *uri;
|
|
||||||
char version[3];
|
|
||||||
http_hdr hdr;
|
|
||||||
} http_req;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const http_status *status;
|
|
||||||
char version[3];
|
|
||||||
http_hdr hdr;
|
|
||||||
} http_res;
|
|
||||||
|
|
||||||
static const http_status http_statuses[] = {
|
|
||||||
{100, "Informational", "Continue"},
|
{100, "Informational", "Continue"},
|
||||||
{101, "Informational", "Switching Protocols"},
|
{101, "Informational", "Switching Protocols"},
|
||||||
|
|
||||||
@ -109,7 +56,7 @@ static const http_status http_statuses[] = {
|
|||||||
{505, "Server Error", "HTTP Version Not Supported"},
|
{505, "Server Error", "HTTP Version Not Supported"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const http_status_msg http_status_messages[] = {
|
const http_status_msg http_status_messages[] = {
|
||||||
{100, "The client SHOULD continue with its request."},
|
{100, "The client SHOULD continue with its request."},
|
||||||
{101, "The server understands and is willing to comply with the clients request, via the Upgrade message header field, for a change in the application protocol being used on this connection."},
|
{101, "The server understands and is willing to comply with the clients request, via the Upgrade message header field, for a change in the application protocol being used on this connection."},
|
||||||
|
|
||||||
@ -156,7 +103,7 @@ static const http_status_msg http_status_messages[] = {
|
|||||||
{505, "The server does not support, or refuses to support, the HTTP protocol version that was used in the request message."}
|
{505, "The server does not support, or refuses to support, the HTTP protocol version that was used in the request message."}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char http_default_document[] =
|
const char http_default_document[] =
|
||||||
"<!DOCTYPE html>\n"
|
"<!DOCTYPE html>\n"
|
||||||
"<html lang=\"en\">\n"
|
"<html lang=\"en\">\n"
|
||||||
"<head>\n"
|
"<head>\n"
|
||||||
@ -196,90 +143,56 @@ static const char http_default_document[] =
|
|||||||
"</body>\n"
|
"</body>\n"
|
||||||
"</html>\n";
|
"</html>\n";
|
||||||
|
|
||||||
static const char http_error_document[] =
|
const char http_error_document[] =
|
||||||
"\t\t\t<h1>%1$i</h1>\n"
|
"\t\t\t<h1>%1$i</h1>\n"
|
||||||
"\t\t\t<h2>%2$s :(</h2>\n"
|
"\t\t\t<h2>%2$s :(</h2>\n"
|
||||||
"\t\t\t<p>%3$s</p>\n"
|
"\t\t\t<p>%3$s</p>\n"
|
||||||
"\t\t\t<p>%4$s</p>\n";
|
"\t\t\t<p>%4$s</p>\n";
|
||||||
|
|
||||||
static const char http_error_icon[] =
|
const char http_error_icon[] =
|
||||||
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
||||||
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
||||||
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiNDMDAwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiNDMDAwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
||||||
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjooPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjooPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
||||||
|
|
||||||
|
|
||||||
static const char http_warning_document[] =
|
const char http_warning_document[] =
|
||||||
"\t\t\t<h1>%1$i</h1>\n"
|
"\t\t\t<h1>%1$i</h1>\n"
|
||||||
"\t\t\t<h2>%2$s :o</h2>\n"
|
"\t\t\t<h2>%2$s :o</h2>\n"
|
||||||
"\t\t\t<p>%3$s</p>\n"
|
"\t\t\t<p>%3$s</p>\n"
|
||||||
"\t\t\t<p>%4$s</p>\n";
|
"\t\t\t<p>%4$s</p>\n";
|
||||||
|
|
||||||
static const char http_warning_icon[] =
|
const char http_warning_icon[] =
|
||||||
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
||||||
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
||||||
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiNFMEMwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiNFMEMwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
||||||
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjpvPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjpvPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
||||||
|
|
||||||
|
|
||||||
static const char http_success_document[] =
|
const char http_success_document[] =
|
||||||
"\t\t\t<h1>%1$i</h1>\n"
|
"\t\t\t<h1>%1$i</h1>\n"
|
||||||
"\t\t\t<h2>%2$s :)</h2>\n"
|
"\t\t\t<h2>%2$s :)</h2>\n"
|
||||||
"\t\t\t<p>%3$s</p>\n"
|
"\t\t\t<p>%3$s</p>\n"
|
||||||
"\t\t\t<p>%4$s</p>\n";
|
"\t\t\t<p>%4$s</p>\n";
|
||||||
|
|
||||||
static const char http_success_icon[] =
|
const char http_success_icon[] =
|
||||||
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
||||||
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
||||||
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiMwMDgwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiMwMDgwMDAiIHN0eWxlPSJmb250LWZhbWls"
|
||||||
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjopPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjopPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
||||||
|
|
||||||
|
|
||||||
static const char http_info_document[] =
|
const char http_info_document[] =
|
||||||
"\t\t\t<h1>%1$i</h1>\n"
|
"\t\t\t<h1>%1$i</h1>\n"
|
||||||
"\t\t\t<h2>%2$s :)</h2>\n"
|
"\t\t\t<h2>%2$s :)</h2>\n"
|
||||||
"\t\t\t<p>%3$s</p>\n"
|
"\t\t\t<p>%3$s</p>\n"
|
||||||
"\t\t\t<p>%4$s</p>\n";
|
"\t\t\t<p>%4$s</p>\n";
|
||||||
|
|
||||||
static const char http_info_icon[] =
|
const char http_info_icon[] =
|
||||||
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
"\t<link rel=\"alternate icon\" type=\"image/svg+xml\" sizes=\"any\" href=\"data:image/svg+xml;base64,"
|
||||||
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
"PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
|
||||||
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiM2MDYwNjAiIHN0eWxlPSJmb250LWZhbWls"
|
"L3N2ZyI+PHRleHQgeD0iNCIgeT0iMTIiIGZpbGw9IiM2MDYwNjAiIHN0eWxlPSJmb250LWZhbWls"
|
||||||
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjopPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
"eTonQXJpYWwnLHNhbnMtc2VyaWYiPjopPC90ZXh0Pjwvc3ZnPgo=\"/>\n";
|
||||||
|
|
||||||
|
const int http_statuses_size = sizeof(http_statuses);
|
||||||
void http_to_camel_case(char *str, int mode);
|
const int http_status_messages_size = sizeof(http_status_messages);
|
||||||
|
|
||||||
void http_free_hdr(http_hdr *hdr);
|
|
||||||
|
|
||||||
void http_free_req(http_req *req);
|
|
||||||
|
|
||||||
void http_free_res(http_res *res);
|
|
||||||
|
|
||||||
int http_receive_request(sock *client, http_req *req);
|
|
||||||
|
|
||||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) ;
|
|
||||||
|
|
||||||
char *http_get_header_field(const http_hdr *hdr, const char *field_name);
|
|
||||||
|
|
||||||
void http_add_header_field(http_hdr *hdr, const char *field_name, const char *field_value);
|
|
||||||
|
|
||||||
void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode);
|
|
||||||
|
|
||||||
int http_send_response(sock *client, http_res *res);
|
|
||||||
|
|
||||||
int http_send_request(sock *server, http_req *req);
|
|
||||||
|
|
||||||
const http_status *http_get_status(unsigned short status_code);
|
|
||||||
|
|
||||||
const http_status_msg *http_get_error_msg(const http_status *status);
|
|
||||||
|
|
||||||
const char *http_get_status_color(const http_status *status);
|
|
||||||
|
|
||||||
char *http_format_date(time_t time, char *buf, size_t size);
|
|
||||||
|
|
||||||
char *http_get_date(char *buf, size_t size);
|
|
||||||
|
|
||||||
const http_doc_info *http_get_status_info(const http_status *status);
|
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_HTTP_H
|
|
@ -1,48 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* FastCGI interface implementation (header file)
|
* FastCGI header file
|
||||||
* src/fastcgi.h
|
* src/lib/include/fastcgi.h
|
||||||
* Lorenz Stechauner, 2020-12-26
|
* Lorenz Stechauner, 2021-05-03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_FASTCGI_H
|
#ifndef NECRONDA_SERVER_EXTERN_FASTCGI_H
|
||||||
#define NECRONDA_SERVER_FASTCGI_H
|
#define NECRONDA_SERVER_EXTERN_FASTCGI_H
|
||||||
|
|
||||||
#define FASTCGI_CHUNKED 1
|
|
||||||
#define FASTCGI_COMPRESS 2
|
|
||||||
|
|
||||||
#include "necronda-server.h"
|
|
||||||
#include "http.h"
|
|
||||||
#include "uri.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int socket;
|
|
||||||
unsigned short req_id;
|
|
||||||
char *out_buf;
|
|
||||||
unsigned short out_len;
|
|
||||||
unsigned short out_off;
|
|
||||||
} fastcgi_conn;
|
|
||||||
|
|
||||||
char *fastcgi_add_param(char *buf, const char *key, const char *value);
|
|
||||||
|
|
||||||
int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_num, const sock *client,
|
|
||||||
const http_req *req, const http_uri *uri);
|
|
||||||
|
|
||||||
int fastcgi_close_stdin(fastcgi_conn *conn);
|
|
||||||
|
|
||||||
int fastcgi_php_error(const char *msg, int msg_len, char *err_msg);
|
|
||||||
|
|
||||||
int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg);
|
|
||||||
|
|
||||||
int fastcgi_send(fastcgi_conn *conn, sock *client, int flags);
|
|
||||||
|
|
||||||
int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listening socket file number
|
* Listening socket file number
|
||||||
@ -155,4 +119,4 @@ typedef struct {
|
|||||||
FCGI_UnknownTypeBody body;
|
FCGI_UnknownTypeBody body;
|
||||||
} FCGI_UnknownTypeRecord;
|
} FCGI_UnknownTypeRecord;
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_FASTCGI_H
|
#endif //NECRONDA_SERVER_EXTERN_FASTCGI_H
|
@ -1,16 +1,33 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Reverse proxy
|
* Reverse proxy
|
||||||
* src/rev_proxy.c
|
* src/lib/rev_proxy.c
|
||||||
* Lorenz Stechauner, 2021-01-07
|
* Lorenz Stechauner, 2021-01-07
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rev_proxy.h"
|
#include "rev_proxy.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "../client.h"
|
||||||
|
#include "../necronda-server.h"
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
sock rev_proxy;
|
sock rev_proxy;
|
||||||
char *rev_proxy_host = NULL;
|
char *rev_proxy_host = NULL;
|
||||||
struct timeval server_timeout = {.tv_sec = SERVER_TIMEOUT, .tv_usec = 0};
|
struct timeval server_timeout = {.tv_sec = SERVER_TIMEOUT, .tv_usec = 0};
|
||||||
|
|
||||||
|
int rev_proxy_preload() {
|
||||||
|
rev_proxy.buf = NULL;
|
||||||
|
rev_proxy.buf_len = 0;
|
||||||
|
rev_proxy.buf_off = 0;
|
||||||
|
rev_proxy.ctx = SSL_CTX_new(TLS_client_method());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int rev_proxy_request_header(http_req *req, int enc) {
|
int rev_proxy_request_header(http_req *req, int enc) {
|
||||||
char buf1[256];
|
char buf1[256];
|
||||||
char buf2[256];
|
char buf2[256];
|
@ -1,13 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Reverse proxy (header file)
|
* Reverse proxy (header file)
|
||||||
* src/rev_proxy.h
|
* src/lib/rev_proxy.h
|
||||||
* Lorenz Stechauner, 2021-01-07
|
* Lorenz Stechauner, 2021-01-07
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_REV_PROXY_H
|
#ifndef NECRONDA_SERVER_REV_PROXY_H
|
||||||
#define NECRONDA_SERVER_REV_PROXY_H
|
#define NECRONDA_SERVER_REV_PROXY_H
|
||||||
|
|
||||||
|
#include "http.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern sock rev_proxy;
|
||||||
|
|
||||||
|
int rev_proxy_preload();
|
||||||
|
|
||||||
int rev_proxy_request_header(http_req *req, int enc);
|
int rev_proxy_request_header(http_req *req, int enc);
|
||||||
|
|
||||||
int rev_proxy_response_header(http_req *req, http_res *res);
|
int rev_proxy_response_header(http_req *req, http_res *res);
|
@ -1,11 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Basic TCP and TLS socket
|
* Basic TCP and TLS socket
|
||||||
* src/sock.c
|
* src/lib/sock.c
|
||||||
* Lorenz Stechauner, 2021-01-07
|
* Lorenz Stechauner, 2021-01-07
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
const char *sock_strerror(sock *s) {
|
const char *sock_strerror(sock *s) {
|
||||||
if (s->_last_ret == 0) {
|
if (s->_last_ret == 0) {
|
@ -1,19 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Basic TCP and TLS socket (header file)
|
* Basic TCP and TLS socket (header file)
|
||||||
* src/sock.h
|
* src/lib/sock.h
|
||||||
* Lorenz Stechauner, 2021-01-07
|
* Lorenz Stechauner, 2021-01-07
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_SOCK_H
|
#ifndef NECRONDA_SERVER_SOCK_H
|
||||||
#define NECRONDA_SERVER_SOCK_H
|
#define NECRONDA_SERVER_SOCK_H
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/crypto.h>
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/dh.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int enc:1;
|
unsigned int enc:1;
|
@ -1,12 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* URI and path handlers
|
* URI and path handlers
|
||||||
* src/uri.c
|
* src/lib/uri.c
|
||||||
* Lorenz Stechauner, 2020-12-13
|
* Lorenz Stechauner, 2020-12-13
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uri.h"
|
#include "uri.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
int path_is_directory(const char *path) {
|
int path_is_directory(const char *path) {
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
@ -51,12 +53,12 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo
|
|||||||
} else {
|
} else {
|
||||||
query[0] = 0;
|
query[0] = 0;
|
||||||
query++;
|
query++;
|
||||||
ssize_t size = strlen(query) + 1;
|
long size = (long) strlen(query) + 1;
|
||||||
uri->query = malloc(size);
|
uri->query = malloc(size);
|
||||||
strcpy(uri->query, query);
|
strcpy(uri->query, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t size = strlen(uri_str) + 1;
|
long size = (long) strlen(uri_str) + 1;
|
||||||
uri->req_path = malloc(size);
|
uri->req_path = malloc(size);
|
||||||
url_decode(uri_str, uri->req_path, &size);
|
url_decode(uri_str, uri->req_path, &size);
|
||||||
if (query != NULL) {
|
if (query != NULL) {
|
||||||
@ -66,7 +68,7 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = strlen(uri->req_path) + 1;
|
size = (long) strlen(uri->req_path) + 1;
|
||||||
uri->path = malloc(size);
|
uri->path = malloc(size);
|
||||||
uri->pathinfo = malloc(size);
|
uri->pathinfo = malloc(size);
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
parent_dir:
|
parent_dir:
|
||||||
ptr = strrchr(uri->path, '/');
|
ptr = strrchr(uri->path, '/');
|
||||||
size = strlen(ptr);
|
size = (long) strlen(ptr);
|
||||||
sprintf(buf3, "%.*s%s", (int) size, ptr, uri->pathinfo);
|
sprintf(buf3, "%.*s%s", (int) size, ptr, uri->pathinfo);
|
||||||
strcpy(uri->pathinfo, buf3);
|
strcpy(uri->pathinfo, buf3);
|
||||||
ptr[0] = 0;
|
ptr[0] = 0;
|
||||||
@ -122,7 +124,7 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo
|
|||||||
if (path_is_file(buf0)) {
|
if (path_is_file(buf0)) {
|
||||||
uri->filename = malloc(strlen(buf0) + 1);
|
uri->filename = malloc(strlen(buf0) + 1);
|
||||||
strcpy(uri->filename, buf0);
|
strcpy(uri->filename, buf0);
|
||||||
ssize_t len = strlen(uri->path);
|
long len = (long) strlen(uri->path);
|
||||||
if (strcmp(uri->path + len - 5, ".html") == 0) {
|
if (strcmp(uri->path + len - 5, ".html") == 0) {
|
||||||
uri->path[len - 5] = 0;
|
uri->path[len - 5] = 0;
|
||||||
} else if (strcmp(uri->path + len - 4, ".php") == 0) {
|
} else if (strcmp(uri->path + len - 4, ".php") == 0) {
|
@ -1,21 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* URI and path handlers (header file)
|
* URI and path handlers (header file)
|
||||||
* src/uri.h
|
* src/lib/uri.h
|
||||||
* Lorenz Stechauner, 2020-12-13
|
* Lorenz Stechauner, 2020-12-13
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_URI_H
|
#ifndef NECRONDA_SERVER_URI_H
|
||||||
#define NECRONDA_SERVER_URI_H
|
#define NECRONDA_SERVER_URI_H
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define URI_DIR_MODE_NO_VALIDATION 0
|
#define URI_DIR_MODE_NO_VALIDATION 0
|
||||||
#define URI_DIR_MODE_FORBIDDEN 1
|
#define URI_DIR_MODE_FORBIDDEN 1
|
||||||
#define URI_DIR_MODE_LIST 2
|
#define URI_DIR_MODE_LIST 2
|
||||||
#define URI_DIR_MODE_INFO 3
|
#define URI_DIR_MODE_INFO 3
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char etag[64];
|
char etag[64];
|
||||||
char type[24];
|
char type[24];
|
@ -1,12 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Utilities
|
* Utilities
|
||||||
* src/utils.c
|
* src/lib/utils.c
|
||||||
* Lorenz Stechauner, 2020-12-03
|
* Lorenz Stechauner, 2020-12-03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
char *log_prefix;
|
||||||
|
|
||||||
char *format_duration(unsigned long micros, char *buf) {
|
char *format_duration(unsigned long micros, char *buf) {
|
||||||
if (micros < 10000) {
|
if (micros < 10000) {
|
||||||
@ -33,8 +36,8 @@ int url_encode_component(const char *str, char *enc, ssize_t *size) {
|
|||||||
}
|
}
|
||||||
ch = str[i];
|
ch = str[i];
|
||||||
if (ch == ':' || ch == '/' || ch == '?' || ch == '#' || ch == '[' || ch == ']' || ch == '@' || ch == '!' ||
|
if (ch == ':' || ch == '/' || ch == '?' || ch == '#' || ch == '[' || ch == ']' || ch == '@' || ch == '!' ||
|
||||||
ch == '$' || ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
|
ch == '$' || ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
|
||||||
ch == ';' || ch == '=' || ch < ' ' || ch > '~') {
|
ch == ';' || ch == '=' || ch < ' ' || ch > '~') {
|
||||||
if ((ptr - enc + 2) >= *size) {
|
if ((ptr - enc + 2) >= *size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -99,6 +102,20 @@ int url_decode(const char *str, char *dec, ssize_t *size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mime_is_compressible(const char *type) {
|
||||||
|
return
|
||||||
|
strncmp(type, "text/", 5) == 0 ||
|
||||||
|
strncmp(type, "message/", 7) == 0 ||
|
||||||
|
strstr(type, "+xml") != NULL ||
|
||||||
|
strcmp(type, "application/javascript") == 0 ||
|
||||||
|
strcmp(type, "application/json") == 0 ||
|
||||||
|
strcmp(type, "application/xml") == 0 ||
|
||||||
|
strcmp(type, "application/x-www-form-urlencoded") == 0 ||
|
||||||
|
strcmp(type, "application/x-tex") == 0 ||
|
||||||
|
strcmp(type, "application/x-httpd-php") == 0 ||
|
||||||
|
strcmp(type, "application/x-latex") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
|
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
|
||||||
switch (list->entry_data.type) {
|
switch (list->entry_data.type) {
|
||||||
case MMDB_DATA_TYPE_MAP:
|
case MMDB_DATA_TYPE_MAP:
|
@ -1,14 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* Necronda Web Server
|
* Necronda Web Server
|
||||||
* Utilities (header file)
|
* Utilities (header file)
|
||||||
* src/utils.h
|
* src/lib/utils.h
|
||||||
* Lorenz Stechauner, 2020-12-03
|
* Lorenz Stechauner, 2020-12-03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NECRONDA_SERVER_UTILS_H
|
#ifndef NECRONDA_SERVER_UTILS_H
|
||||||
#define NECRONDA_SERVER_UTILS_H
|
#define NECRONDA_SERVER_UTILS_H
|
||||||
|
|
||||||
char *log_prefix;
|
#include <maxminddb.h>
|
||||||
|
|
||||||
|
extern char *log_prefix;
|
||||||
|
|
||||||
#define out_1(fmt) fprintf(stdout, "%s" fmt "\n", log_prefix)
|
#define out_1(fmt) fprintf(stdout, "%s" fmt "\n", log_prefix)
|
||||||
#define out_2(fmt, args...) fprintf(stdout, "%s" fmt "\n", log_prefix, args)
|
#define out_2(fmt, args...) fprintf(stdout, "%s" fmt "\n", log_prefix, args)
|
||||||
@ -28,4 +30,8 @@ int url_encode(const char *str, char *enc, ssize_t *size);
|
|||||||
|
|
||||||
int url_decode(const char *str, char *dec, ssize_t *size);
|
int url_decode(const char *str, char *dec, ssize_t *size);
|
||||||
|
|
||||||
|
int mime_is_compressible(const char *type);
|
||||||
|
|
||||||
|
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len);
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_UTILS_H
|
#endif //NECRONDA_SERVER_UTILS_H
|
@ -8,21 +8,35 @@
|
|||||||
#define _POSIX_C_SOURCE 199309L
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
|
||||||
#include "necronda-server.h"
|
#include "necronda-server.h"
|
||||||
|
|
||||||
#include "config.c"
|
|
||||||
#include "utils.c"
|
|
||||||
#include "uri.c"
|
|
||||||
#include "cache.c"
|
|
||||||
#include "sock.c"
|
|
||||||
#include "http.c"
|
|
||||||
#include "rev_proxy.c"
|
|
||||||
#include "client.c"
|
#include "client.c"
|
||||||
#include "fastcgi.c"
|
|
||||||
|
|
||||||
|
#include "lib/cache.h"
|
||||||
|
#include "lib/config.h"
|
||||||
|
#include "lib/sock.h"
|
||||||
|
#include "lib/rev_proxy.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <wait.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <maxminddb.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
int active = 1;
|
int active = 1;
|
||||||
const char *config_file;
|
const char *config_file;
|
||||||
|
int sockets[NUM_SOCKETS];
|
||||||
|
pid_t children[MAX_CHILDREN];
|
||||||
|
MMDB_s mmdbs[MAX_MMDB];
|
||||||
|
|
||||||
void openssl_init() {
|
void openssl_init() {
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
@ -273,10 +287,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
SSL_CTX_set_cipher_list(client.ctx, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4");
|
SSL_CTX_set_cipher_list(client.ctx, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4");
|
||||||
SSL_CTX_set_ecdh_auto(client.ctx, 1);
|
SSL_CTX_set_ecdh_auto(client.ctx, 1);
|
||||||
|
|
||||||
rev_proxy.buf = NULL;
|
rev_proxy_preload();
|
||||||
rev_proxy.buf_len = 0;
|
|
||||||
rev_proxy.buf_off = 0;
|
|
||||||
rev_proxy.ctx = SSL_CTX_new(TLS_client_method());
|
|
||||||
|
|
||||||
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",
|
||||||
@ -312,6 +323,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
config_unload();
|
config_unload();
|
||||||
return 1;
|
return 1;
|
||||||
} else if (ret != 0) {
|
} else if (ret != 0) {
|
||||||
|
children[0] = ret; // pid
|
||||||
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,26 +8,8 @@
|
|||||||
#ifndef NECRONDA_SERVER_NECRONDA_SERVER_H
|
#ifndef NECRONDA_SERVER_NECRONDA_SERVER_H
|
||||||
#define NECRONDA_SERVER_NECRONDA_SERVER_H
|
#define NECRONDA_SERVER_NECRONDA_SERVER_H
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <wait.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/dh.h>
|
|
||||||
#include <maxminddb.h>
|
#include <maxminddb.h>
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define NUM_SOCKETS 2
|
#define NUM_SOCKETS 2
|
||||||
#define MAX_CHILDREN 1024
|
#define MAX_CHILDREN 1024
|
||||||
@ -77,10 +59,8 @@
|
|||||||
#define DEFAULT_CONFIG_FILE "/etc/necronda-server/necronda-server.conf"
|
#define DEFAULT_CONFIG_FILE "/etc/necronda-server/necronda-server.conf"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int sockets[NUM_SOCKETS];
|
extern int sockets[NUM_SOCKETS];
|
||||||
pid_t children[MAX_CHILDREN];
|
extern pid_t children[MAX_CHILDREN];
|
||||||
MMDB_s mmdbs[MAX_MMDB];
|
extern MMDB_s mmdbs[MAX_MMDB];
|
||||||
|
|
||||||
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
|
|
||||||
|
|
||||||
#endif //NECRONDA_SERVER_NECRONDA_SERVER_H
|
#endif //NECRONDA_SERVER_NECRONDA_SERVER_H
|
||||||
|
Reference in New Issue
Block a user