Compare commits
6 Commits
456deeae20
...
v4.4
Author | SHA1 | Date | |
---|---|---|---|
43c512dc5a
|
|||
3f5eee236d
|
|||
0b157bcb74
|
|||
30b163c6fa
|
|||
cf2c0de697
|
|||
7aa47cac61
|
4
Makefile
4
Makefile
@ -22,7 +22,7 @@ compile:
|
||||
compile-debian:
|
||||
@mkdir -p bin
|
||||
gcc $(LIBS) -o bin/libnecronda-server.so --shared -fPIC $(CFLAGS) $(INCLUDE) \
|
||||
$(DEBIAN_OPTS)
|
||||
$(DEBIAN_OPTS) -O3
|
||||
gcc src/necronda-server.c -o bin/necronda-server $(CFLAGS) $(INCLUDE) \
|
||||
-Lbin -lnecronda-server -Wl,-rpath=$(shell pwd)/bin \
|
||||
$(DEBIAN_OPTS)
|
||||
$(DEBIAN_OPTS) -O3
|
||||
|
35
src/client.c
35
src/client.c
@ -102,15 +102,15 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
if (ret < 0) {
|
||||
goto abort;
|
||||
} else if (ret == 1) {
|
||||
sprintf(err_msg, "Unable to parse header: Invalid header format.");
|
||||
sprintf(err_msg, "Unable to parse http header: Invalid header format.");
|
||||
} else if (ret == 2) {
|
||||
sprintf(err_msg, "Unable to parse header: Invalid method.");
|
||||
sprintf(err_msg, "Unable to parse http header: Invalid method.");
|
||||
} else if (ret == 3) {
|
||||
sprintf(err_msg, "Unable to parse header: Invalid version.");
|
||||
sprintf(err_msg, "Unable to parse http header: Invalid version.");
|
||||
} else if (ret == 4) {
|
||||
sprintf(err_msg, "Unable to parse header: Header contains illegal characters.");
|
||||
sprintf(err_msg, "Unable to parse http header: Header contains illegal characters.");
|
||||
} else if (ret == 5) {
|
||||
sprintf(err_msg, "Unable to parse header: End of header not found.");
|
||||
sprintf(err_msg, "Unable to parse http header: End of header not found.");
|
||||
}
|
||||
res.status = http_get_status(400);
|
||||
goto respond;
|
||||
@ -138,7 +138,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
strcpy(host, host_ptr);
|
||||
}
|
||||
|
||||
sprintf(log_req_prefix, "[%s%24s%s]%s ", BLD_STR, host, CLR_STR, log_client_prefix);
|
||||
sprintf(log_req_prefix, "[%6i][%s%24s%s]%s ", getpid(), BLD_STR, host, CLR_STR, log_client_prefix);
|
||||
log_prefix = log_req_prefix;
|
||||
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
||||
|
||||
@ -219,6 +219,10 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
goto respond;
|
||||
}
|
||||
|
||||
if (strncmp(uri.req_path, "/.well-known/", 13) == 0) {
|
||||
http_add_header_field(&res.hdr, "Access-Control-Allow-Origin", "*");
|
||||
}
|
||||
|
||||
if (strncmp(uri.req_path, "/.well-known/", 13) != 0 && strstr(uri.path, "/.") != NULL) {
|
||||
res.status = http_get_status(403);
|
||||
sprintf(err_msg, "Parts of this URI are hidden.");
|
||||
@ -286,6 +290,9 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
enc = COMPRESS_GZ;
|
||||
}
|
||||
}
|
||||
if (enc != 0) {
|
||||
http_add_header_field(&res.hdr, "Vary", "Accept-Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
if (uri.meta->etag[0] != 0) {
|
||||
@ -421,12 +428,16 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
use_fastcgi = 1;
|
||||
|
||||
int http_comp = http_get_compression(&req, &res);
|
||||
if (http_comp & COMPRESS) {
|
||||
if (http_comp & COMPRESS_BR) {
|
||||
use_fastcgi |= FASTCGI_COMPRESS_BR;
|
||||
http_add_header_field(&res.hdr, "Content-Encoding", "br");
|
||||
sprintf(buf0, "br");
|
||||
} else if (http_comp & COMPRESS_GZ) {
|
||||
use_fastcgi |= FASTCGI_COMPRESS_GZ;
|
||||
http_add_header_field(&res.hdr, "Content-Encoding", "gzip");
|
||||
sprintf(buf0, "gzip");
|
||||
}
|
||||
http_add_header_field(&res.hdr, "Vary", "Accept-Encoding");
|
||||
http_add_header_field(&res.hdr, "Content-Encoding", buf0);
|
||||
}
|
||||
|
||||
if (http_get_header_field(&res.hdr, "Content-Length") == NULL) {
|
||||
@ -441,6 +452,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
ret = rev_proxy_init(&req, &res, conf, client, &custom_status, err_msg);
|
||||
use_rev_proxy = (ret == 0);
|
||||
|
||||
/*
|
||||
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
||||
if (use_rev_proxy && content_encoding == NULL) {
|
||||
int http_comp = http_get_compression(&req, &res);
|
||||
@ -449,7 +461,6 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
} else if (http_comp & COMPRESS_GZ) {
|
||||
use_rev_proxy |= REV_PROXY_COMPRESS_GZ;
|
||||
}
|
||||
use_rev_proxy &= ~REV_PROXY_COMPRESS;
|
||||
}
|
||||
|
||||
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
||||
@ -463,6 +474,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
if (ret > 0) {
|
||||
http_add_header_field(&res.hdr, "Transfer-Encoding", buf0);
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
print(ERR_STR "Unknown host type: %i" CLR_STR, conf->type);
|
||||
res.status = http_get_status(501);
|
||||
@ -699,6 +711,7 @@ int client_connection_handler(sock *client, unsigned long client_num) {
|
||||
client->_ssl_error = ERR_get_error();
|
||||
if (ret <= 0) {
|
||||
print(ERR_STR "Unable to perform handshake: %s" CLR_STR, sock_strerror(client));
|
||||
ret = -1;
|
||||
goto close;
|
||||
}
|
||||
}
|
||||
@ -761,12 +774,13 @@ int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *
|
||||
ntohs(client_addr->sin6_port), CLR_STR);
|
||||
|
||||
log_conn_prefix = malloc(256);
|
||||
sprintf(log_conn_prefix, "[%24s]%s ", server_addr_str, log_client_prefix);
|
||||
sprintf(log_conn_prefix, "[%6i][%24s]%s ", getpid(), server_addr_str, log_client_prefix);
|
||||
log_prefix = log_conn_prefix;
|
||||
|
||||
print("Started child process with PID %i", getpid());
|
||||
|
||||
ret = client_connection_handler(client, client_num);
|
||||
|
||||
free(client_addr_str_ptr);
|
||||
client_addr_str_ptr = NULL;
|
||||
free(server_addr_str_ptr);
|
||||
@ -781,5 +795,6 @@ int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *
|
||||
log_req_prefix = NULL;
|
||||
free(log_client_prefix);
|
||||
log_client_prefix = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -291,11 +291,11 @@ int cache_update_entry(int entry_num, const char *filename, const char *webroot)
|
||||
const char *type = magic_file(magic, filename);
|
||||
char type_new[24];
|
||||
sprintf(type_new, "%s", type);
|
||||
if (strcmp(type, "text/plain") == 0) {
|
||||
if (strncmp(type, "text/", 5) == 0) {
|
||||
if (strcmp(filename + strlen(filename) - 4, ".css") == 0) {
|
||||
sprintf(type_new, "text/css");
|
||||
} else if (strcmp(filename + strlen(filename) - 3, ".js") == 0) {
|
||||
sprintf(type_new, "text/javascript");
|
||||
sprintf(type_new, "application/javascript");
|
||||
}
|
||||
}
|
||||
strcpy(cache[entry_num].meta.type, type_new);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#define COMPRESS_GZ 1
|
||||
#define COMPRESS_BR 2
|
||||
#define COMPRESS 3
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
|
@ -278,7 +278,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
||||
FCGI_Header header;
|
||||
char *content;
|
||||
unsigned short content_len, req_id;
|
||||
int ret;
|
||||
long ret;
|
||||
int err = 0;
|
||||
|
||||
while (1) {
|
||||
@ -372,7 +372,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
||||
}
|
||||
|
||||
ret = http_parse_header_field(&res->hdr, ptr, pos0);
|
||||
if (ret != 0) return ret;
|
||||
if (ret != 0) return (int) ret;
|
||||
if (pos0[2] == '\r' && pos0[3] == '\n') {
|
||||
return 0;
|
||||
}
|
||||
@ -423,6 +423,7 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
|
||||
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
req_id = (header.requestIdB1 << 8) | header.requestIdB0;
|
||||
content_len = (header.contentLengthB1 << 8) | header.contentLengthB0;
|
||||
content = malloc(content_len + header.paddingLength);
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "http.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
#include "../necronda-server.h"
|
||||
#include <string.h>
|
||||
|
||||
void http_to_camel_case(char *str, int mode) {
|
||||
@ -34,7 +33,7 @@ void http_free_hdr(http_hdr *hdr) {
|
||||
}
|
||||
|
||||
void http_free_req(http_req *req) {
|
||||
if (req->uri == NULL) free(req->uri);
|
||||
if (req->uri != NULL) free(req->uri);
|
||||
req->uri = NULL;
|
||||
http_free_hdr(&req->hdr);
|
||||
}
|
||||
@ -86,19 +85,19 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
while (1) {
|
||||
rcv_len = sock_recv(client, buf, CLIENT_MAX_HEADER_SIZE, 0);
|
||||
if (rcv_len <= 0) {
|
||||
print("Unable to receive: %s", sock_strerror(client));
|
||||
print("Unable to receive http header: %s", sock_strerror(client));
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long header_len = strstr(buf, "\r\n\r\n") - buf + 4;
|
||||
if (header_len <= 0) {
|
||||
print(ERR_STR "Unable to parse header: End of header not found" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: End of header not found" CLR_STR);
|
||||
return 5;
|
||||
}
|
||||
|
||||
for (int i = 0; i < header_len; i++) {
|
||||
if ((buf[i] >= 0x00 && buf[i] <= 0x1F && buf[i] != '\r' && buf[i] != '\n') || buf[i] == 0x7F) {
|
||||
print(ERR_STR "Unable to parse header: Header contains illegal characters" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Header contains illegal characters" CLR_STR);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@ -107,7 +106,7 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
while (header_len > (ptr - buf + 2)) {
|
||||
pos0 = strstr(ptr, "\r\n");
|
||||
if (pos0 == NULL) {
|
||||
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Invalid header format" CLR_STR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -116,13 +115,13 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
if (pos1 == NULL) goto err_hdr_fmt;
|
||||
|
||||
if (pos1 - ptr - 1 >= sizeof(req->method)) {
|
||||
print(ERR_STR "Unable to parse header: Method name too long" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Method name too long" CLR_STR);
|
||||
return 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (pos1 - ptr - 1); i++) {
|
||||
if (ptr[i] < 'A' || ptr[i] > 'Z') {
|
||||
print(ERR_STR "Unable to parse header: Invalid method" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Invalid method" CLR_STR);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@ -131,12 +130,12 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
pos2 = memchr(pos1, ' ', rcv_len - (pos1 - buf)) + 1;
|
||||
if (pos2 == NULL) {
|
||||
err_hdr_fmt:
|
||||
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Invalid header format" CLR_STR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (memcmp(pos2, "HTTP/", 5) != 0 || memcmp(pos2 + 8, "\r\n", 2) != 0) {
|
||||
print(ERR_STR "Unable to parse header: Invalid version" CLR_STR);
|
||||
print(ERR_STR "Unable to parse http header: Invalid version" CLR_STR);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#define HTTP_COLOR_WARNING "#E0C000"
|
||||
#define HTTP_COLOR_ERROR "#C00000"
|
||||
|
||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||
|
||||
#ifndef SERVER_STR
|
||||
# define SERVER_STR "Necronda"
|
||||
#endif
|
||||
@ -63,13 +65,13 @@ typedef struct {
|
||||
typedef struct {
|
||||
char method[16];
|
||||
char *uri;
|
||||
char version[3];
|
||||
char version[4];
|
||||
http_hdr hdr;
|
||||
} http_req;
|
||||
|
||||
typedef struct {
|
||||
const http_status *status;
|
||||
char version[3];
|
||||
char version[4];
|
||||
http_hdr hdr;
|
||||
} http_res;
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
* Lorenz Stechauner, 2021-05-03
|
||||
*/
|
||||
|
||||
#include "../necronda.h"
|
||||
#include "http.h"
|
||||
#include "utils.h"
|
||||
|
||||
const http_status http_statuses[] = {
|
||||
{100, "Informational", "Continue"},
|
||||
|
@ -404,18 +404,21 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
|
||||
}
|
||||
|
||||
do {
|
||||
snd_len = 0;
|
||||
if (flags & REV_PROXY_CHUNKED) {
|
||||
char *pos;
|
||||
ret = sock_recv(&rev_proxy, buffer, 16, MSG_PEEK);
|
||||
if (ret <= 0) {
|
||||
print("Unable to receive: %s", sock_strerror(&rev_proxy));
|
||||
break;
|
||||
}
|
||||
if (ret <= 0) goto err0;
|
||||
|
||||
len_to_send = strtol(buffer, NULL, 16);
|
||||
char *pos = strstr(buffer, "\r\n");
|
||||
pos = strstr(buffer, "\r\n");
|
||||
len = pos - buffer + 2;
|
||||
sock_recv(&rev_proxy, buffer, len, 0);
|
||||
if (ret <= 0) break;
|
||||
if (ret <= 0) {
|
||||
err0:
|
||||
print("Unable to receive from server: %s", sock_strerror(&rev_proxy));
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_to_send == 0 && (flags & REV_PROXY_COMPRESS)) {
|
||||
finish_comp = 1;
|
||||
@ -425,10 +428,14 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
|
||||
compress_free(&comp_ctx);
|
||||
}
|
||||
}
|
||||
snd_len = 0;
|
||||
while (snd_len < len_to_send) {
|
||||
unsigned long avail_in, avail_out;
|
||||
len = sock_recv(&rev_proxy, buffer, CHUNK_SIZE < (len_to_send - snd_len) ? CHUNK_SIZE : len_to_send - snd_len, 0);
|
||||
ret = sock_recv(&rev_proxy, buffer, CHUNK_SIZE < (len_to_send - snd_len) ? CHUNK_SIZE : len_to_send - snd_len, 0);
|
||||
if (ret <= 0) {
|
||||
print("Unable to receive from server: %s", sock_strerror(&rev_proxy));
|
||||
break;
|
||||
}
|
||||
len = ret;
|
||||
ptr = buffer;
|
||||
out:
|
||||
avail_in = len;
|
||||
@ -466,8 +473,14 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
|
||||
if (flags & REV_PROXY_CHUNKED) sock_recv(&rev_proxy, buffer, 2, 0);
|
||||
} while ((flags & REV_PROXY_CHUNKED) && len_to_send > 0);
|
||||
|
||||
if (ret <= 0) return (int) -1;
|
||||
|
||||
if (flags & REV_PROXY_CHUNKED) {
|
||||
sock_send(client, "0\r\n\r\n", 5, 0);
|
||||
ret = sock_send(client, "0\r\n\r\n", 5, 0);
|
||||
if (ret <= 0) {
|
||||
print(ERR_STR "Unable to send: %s" CLR_STR, sock_strerror(client));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -52,12 +52,12 @@ long sock_send(sock *s, void *buf, unsigned long len, int flags) {
|
||||
long ret;
|
||||
if (s->enc) {
|
||||
ret = SSL_write(s->ssl, buf, (int) len);
|
||||
s->_ssl_error = ERR_get_error();
|
||||
} else {
|
||||
ret = send(s->socket, buf, len, flags);
|
||||
}
|
||||
s->_last_ret = ret;
|
||||
s->_errno = errno;
|
||||
s->_ssl_error = ERR_get_error();
|
||||
return ret >= 0 ? ret : -1;
|
||||
}
|
||||
|
||||
@ -69,12 +69,12 @@ long sock_recv(sock *s, void *buf, unsigned long len, int flags) {
|
||||
} else {
|
||||
ret = SSL_read(s->ssl, buf, (int) len);
|
||||
}
|
||||
s->_ssl_error = ERR_get_error();
|
||||
} else {
|
||||
ret = recv(s->socket, buf, len, flags);
|
||||
}
|
||||
s->_last_ret = ret;
|
||||
s->_errno = errno;
|
||||
s->_ssl_error = ERR_get_error();
|
||||
return ret >= 0 ? ret : -1;
|
||||
}
|
||||
|
||||
@ -97,14 +97,14 @@ long sock_splice(sock *dst, sock *src, void *buf, unsigned long buf_len, unsigne
|
||||
|
||||
int sock_close(sock *s) {
|
||||
if ((int) s->enc && s->ssl != NULL) {
|
||||
SSL_shutdown(s->ssl);
|
||||
if (s->_last_ret >= 0) SSL_shutdown(s->ssl);
|
||||
SSL_free(s->ssl);
|
||||
s->ssl = NULL;
|
||||
}
|
||||
shutdown(s->socket, SHUT_RDWR);
|
||||
close(s->socket);
|
||||
s->socket = 0;
|
||||
s->enc = 0;
|
||||
s->ssl = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ int url_decode(const char *str, char *dec, long *size) {
|
||||
int mime_is_compressible(const char *type) {
|
||||
if (type == NULL) return 0;
|
||||
char type_parsed[64];
|
||||
strncpy(type_parsed, type, sizeof(type_parsed));
|
||||
strncpy(type_parsed, type, sizeof(type_parsed) - 1);
|
||||
char *pos = strchr(type_parsed, ';');
|
||||
if (pos != NULL) pos[0] = 0;
|
||||
return
|
||||
|
@ -15,12 +15,11 @@
|
||||
#define MAX_CHILDREN 1024
|
||||
#define MAX_MMDB 3
|
||||
#define LISTEN_BACKLOG 16
|
||||
#define REQ_PER_CONNECTION 100
|
||||
#define REQ_PER_CONNECTION 200
|
||||
#define CLIENT_TIMEOUT 3600
|
||||
#define SERVER_TIMEOUT 4
|
||||
|
||||
#define CHUNK_SIZE 8192
|
||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||
|
||||
#ifndef DEFAULT_HOST
|
||||
# define DEFAULT_HOST "www.necronda.net"
|
||||
|
Reference in New Issue
Block a user