Compare commits
	
		
			8 Commits
		
	
	
		
			ee8aedce91
			...
			v4.6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a2f4bf57e0 | |||
| 635271ec50 | |||
| 2b4569aabe | |||
| f361fce561 | |||
| c92742275a | |||
| 041e4d43a7 | |||
| 170337d4d5 | |||
| f0b27b3b37 | 
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @@ -11,16 +11,16 @@ packages: | |||||||
| 	@echo "Finished downloading!" | 	@echo "Finished downloading!" | ||||||
|  |  | ||||||
| permit: | permit: | ||||||
| 	sudo setcap 'cap_net_bind_service=+ep' "$(shell pwd)/bin/necronda-server" | 	sudo setcap 'cap_net_bind_service=+ep' "$(shell pwd)/bin/sesimos" | ||||||
|  |  | ||||||
| compile: | compile: | ||||||
| 	@mkdir -p bin | 	@mkdir -p bin | ||||||
| 	$(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS) | 	$(CC) src/lib/*.c -o bin/libsesimos.so --shared -fPIC $(CFLAGS) $(LIBS) | ||||||
| 	$(CC) src/server.c src/client.c -o bin/necronda-server $(CFLAGS) $(LIBS) \ | 	$(CC) src/server.c src/client.c -o bin/sesimos $(CFLAGS) $(LIBS) \ | ||||||
| 		-Lbin -lnecrondaserver -Wl,-rpath=$(shell pwd)/bin | 		-Lbin -lsesimos -Wl,-rpath=$(shell pwd)/bin | ||||||
|  |  | ||||||
| compile-prod: | compile-prod: | ||||||
| 	@mkdir -p bin | 	@mkdir -p bin | ||||||
| 	$(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 | 	$(CC) src/lib/*.c -o bin/libsesimos.so --shared -fPIC $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 | ||||||
| 	$(CC) src/server.c src/client.c -o bin/necronda-server $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 \ | 	$(CC) src/server.c src/client.c -o bin/sesimos $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 \ | ||||||
| 		-Lbin -lnecrondaserver -Wl,-rpath=$(shell pwd)/bin | 		-Lbin -lsesimos -Wl,-rpath=$(shell pwd)/bin | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  |  | ||||||
| Necronda web server | Sesimos – Secure, simple, modern web server | ||||||
| =================== | =========================================== | ||||||
|  |  | ||||||
| ## Features | ## Features | ||||||
|  |  | ||||||
| @@ -10,7 +10,7 @@ Necronda web server | |||||||
|   * File compression ([gzip](https://www.gzip.org/), [Brotli](https://www.brotli.org/)) |   * File compression ([gzip](https://www.gzip.org/), [Brotli](https://www.brotli.org/)) | ||||||
|   * Disk cache for compressed files |   * Disk cache for compressed files | ||||||
| * Reverse proxy for other HTTP and HTTPS servers | * Reverse proxy for other HTTP and HTTPS servers | ||||||
|   * Transparent WebSocket reverse proxy **[WIP]** |   * Transparent WebSocket reverse proxy | ||||||
| * FastCGI support (e.g. [PHP-FPM](https://php-fpm.org/)) | * FastCGI support (e.g. [PHP-FPM](https://php-fpm.org/)) | ||||||
|   * Automatic path info detection (e.g. `/my/file/extra/path` -> script: `/my/file.php`, path info: `extra/path`) |   * Automatic path info detection (e.g. `/my/file/extra/path` -> script: `/my/file.php`, path info: `extra/path`) | ||||||
| * Support for [MaxMind's GeoIP Database](https://www.maxmind.com/en/geoip2-services-and-databases) | * Support for [MaxMind's GeoIP Database](https://www.maxmind.com/en/geoip2-services-and-databases) | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								src/client.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/client.c
									
									
									
									
									
								
							| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Client connection and request handlers |  * Client connection and request handlers | ||||||
|  * src/client.c |  * src/client.c | ||||||
|  * Lorenz Stechauner, 2020-12-03 |  * Lorenz Stechauner, 2020-12-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include "defs.h" | ||||||
| #include "client.h" | #include "client.h" | ||||||
| #include "necronda.h" |  | ||||||
| #include "server.h" | #include "server.h" | ||||||
|  |  | ||||||
| #include "lib/utils.h" | #include "lib/utils.h" | ||||||
| @@ -18,9 +18,9 @@ | |||||||
| #include "lib/cache.h" | #include "lib/cache.h" | ||||||
| #include "lib/geoip.h" | #include "lib/geoip.h" | ||||||
| #include "lib/compress.h" | #include "lib/compress.h" | ||||||
|  | #include "lib/websocket.h" | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <sys/select.h> |  | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <openssl/ssl.h> | #include <openssl/ssl.h> | ||||||
| @@ -28,13 +28,12 @@ | |||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int server_keep_alive = 1; | int server_keep_alive = 1; | ||||||
| struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0}; | 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 *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; | 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 < CONFIG_MAX_HOST_CONFIG; i++) { |     for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) { | ||||||
| @@ -53,11 +52,6 @@ void client_terminate() { | |||||||
|     server_keep_alive = 0; |     server_keep_alive = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int client_websocket_handler() { |  | ||||||
|     // TODO implement client_websocket_handler |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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; | ||||||
|     long ret; |     long ret; | ||||||
| @@ -87,16 +81,12 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|     http_status custom_status; |     http_status custom_status; | ||||||
|  |  | ||||||
|     http_res res = {.version = "1.1", .status = http_get_status(501), .hdr.field_num = 0, .hdr.last_field_num = -1}; |     http_res res = {.version = "1.1", .status = http_get_status(501), .hdr.field_num = 0, .hdr.last_field_num = -1}; | ||||||
|     http_status_ctx ctx = {.status = 0, .origin = NONE}; |     http_status_ctx ctx = {.status = 0, .origin = NONE, .ws_key = NULL}; | ||||||
|  |  | ||||||
|     clock_gettime(CLOCK_MONOTONIC, &begin); |     clock_gettime(CLOCK_MONOTONIC, &begin); | ||||||
|  |  | ||||||
|     fd_set socket_fds; |     ret = sock_poll_read(&client, NULL, 1, CLIENT_TIMEOUT * 1000); | ||||||
|     FD_ZERO(&socket_fds); |  | ||||||
|     FD_SET(client->socket, &socket_fds); |  | ||||||
|     client_timeout.tv_sec = CLIENT_TIMEOUT; |  | ||||||
|     client_timeout.tv_usec = 0; |  | ||||||
|     ret = select(client->socket + 1, &socket_fds, NULL, NULL, &client_timeout); |  | ||||||
|     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))); | ||||||
|     http_add_header_field(&res.hdr, "Server", SERVER_STR); |     http_add_header_field(&res.hdr, "Server", SERVER_STR); | ||||||
|     if (ret <= 0) { |     if (ret <= 0) { | ||||||
| @@ -130,7 +120,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     hdr_connection = http_get_header_field(&req.hdr, "Connection"); |     hdr_connection = http_get_header_field(&req.hdr, "Connection"); | ||||||
|     client_keep_alive = (hdr_connection != NULL && (strcmp(hdr_connection, "keep-alive") == 0 || strcmp(hdr_connection, "Keep-Alive") == 0)); |     client_keep_alive = (hdr_connection != NULL && (strstr(hdr_connection, "keep-alive") != NULL || strstr(hdr_connection, "Keep-Alive") != NULL)); | ||||||
|     host_ptr = http_get_header_field(&req.hdr, "Host"); |     host_ptr = http_get_header_field(&req.hdr, "Host"); | ||||||
|     if (host_ptr != NULL && strlen(host_ptr) > 255) { |     if (host_ptr != NULL && strlen(host_ptr) > 255) { | ||||||
|         host[0] = 0; |         host[0] = 0; | ||||||
| @@ -384,7 +374,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|         } else { |         } else { | ||||||
|             int mode; |             int mode; | ||||||
|             if (strcmp(uri.filename + strlen(uri.filename) - 4, ".ncr") == 0) { |             if (strcmp(uri.filename + strlen(uri.filename) - 4, ".ncr") == 0) { | ||||||
|                 mode = FASTCGI_NECRONDA; |                 mode = FASTCGI_SESIMOS; | ||||||
|             } else if (strcmp(uri.filename + strlen(uri.filename) - 4, ".php") == 0) { |             } else if (strcmp(uri.filename + strlen(uri.filename) - 4, ".php") == 0) { | ||||||
|                 mode = FASTCGI_PHP; |                 mode = FASTCGI_PHP; | ||||||
|             } else { |             } else { | ||||||
| @@ -493,6 +483,25 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|         ret = rev_proxy_init(&req, &res, &ctx, conf, client, &custom_status, err_msg); |         ret = rev_proxy_init(&req, &res, &ctx, conf, client, &custom_status, err_msg); | ||||||
|         use_rev_proxy = (ret == 0); |         use_rev_proxy = (ret == 0); | ||||||
|  |  | ||||||
|  |         if (res.status->code == 101) { | ||||||
|  |             const char *connection = http_get_header_field(&res.hdr, "Connection"); | ||||||
|  |             const char *upgrade = http_get_header_field(&res.hdr, "Upgrade"); | ||||||
|  |             if (connection != NULL && upgrade != NULL && | ||||||
|  |                 (strstr(connection, "upgrade") != NULL || strstr(connection, "Upgrade") != NULL) && | ||||||
|  |                 strcmp(upgrade, "websocket") == 0) | ||||||
|  |             { | ||||||
|  |                 const char *ws_accept = http_get_header_field(&res.hdr, "Sec-WebSocket-Accept"); | ||||||
|  |                 if (ws_calc_accept_key(ctx.ws_key, buf0) == 0) { | ||||||
|  |                     use_rev_proxy = (strcmp(buf0, ws_accept) == 0) ? 2 : 1; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 print("Fail Test1"); | ||||||
|  |                 ctx.status = 101; | ||||||
|  |                 ctx.origin = INTERNAL; | ||||||
|  |                 res.status = http_get_status(501); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // Let 300 be formatted by origin server |         // Let 300 be formatted by origin server | ||||||
|         if (use_rev_proxy && res.status->code >= 301 && res.status->code < 600) { |         if (use_rev_proxy && res.status->code >= 301 && res.status->code < 600) { | ||||||
|             const char *content_type = http_get_header_field(&res.hdr, "Content-Type"); |             const char *content_type = http_get_header_field(&res.hdr, "Content-Type"); | ||||||
| @@ -501,8 +510,10 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|             if (content_encoding == NULL && content_type != NULL && content_length_f != NULL && strncmp(content_type, "text/html", 9) == 0) { |             if (content_encoding == NULL && content_type != NULL && content_length_f != NULL && strncmp(content_type, "text/html", 9) == 0) { | ||||||
|                 long content_len = strtol(content_length_f, NULL, 10); |                 long content_len = strtol(content_length_f, NULL, 10); | ||||||
|                 if (content_len <= sizeof(msg_content) - 1) { |                 if (content_len <= sizeof(msg_content) - 1) { | ||||||
|  |                     if (ctx.status != 101) { | ||||||
|                         ctx.status = res.status->code; |                         ctx.status = res.status->code; | ||||||
|                         ctx.origin = res.status->code >= 400 ? SERVER : NONE; |                         ctx.origin = res.status->code >= 400 ? SERVER : NONE; | ||||||
|  |                     } | ||||||
|                     use_rev_proxy = 0; |                     use_rev_proxy = 0; | ||||||
|                     rev_proxy_dump(msg_content, content_len); |                     rev_proxy_dump(msg_content, content_len); | ||||||
|                 } |                 } | ||||||
| @@ -609,8 +620,10 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     int close_proxy = 0; | ||||||
|  |     if (use_rev_proxy != 2) { | ||||||
|         const char *conn = http_get_header_field(&res.hdr, "Connection"); |         const char *conn = http_get_header_field(&res.hdr, "Connection"); | ||||||
|     int close_proxy = (conn == NULL || (strcmp(conn, "keep-alive") != 0 && strcmp(conn, "Keep-Alive") != 0)); |         close_proxy = (conn == NULL || (strstr(conn, "keep-alive") == NULL && strstr(conn, "Keep-Alive") == NULL)); | ||||||
|         http_remove_header_field(&res.hdr, "Connection", HTTP_REMOVE_ALL); |         http_remove_header_field(&res.hdr, "Connection", HTTP_REMOVE_ALL); | ||||||
|         http_remove_header_field(&res.hdr, "Keep-Alive", HTTP_REMOVE_ALL); |         http_remove_header_field(&res.hdr, "Keep-Alive", HTTP_REMOVE_ALL); | ||||||
|         if (server_keep_alive && client_keep_alive) { |         if (server_keep_alive && client_keep_alive) { | ||||||
| @@ -620,6 +633,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|         } else { |         } else { | ||||||
|             http_add_header_field(&res.hdr, "Connection", "close"); |             http_add_header_field(&res.hdr, "Connection", "close"); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     http_send_response(client, &res); |     http_send_response(client, &res); | ||||||
|     clock_gettime(CLOCK_MONOTONIC, &end); |     clock_gettime(CLOCK_MONOTONIC, &end); | ||||||
| @@ -631,7 +645,17 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int | |||||||
|  |  | ||||||
|     // TODO access/error log file |     // TODO access/error log file | ||||||
|  |  | ||||||
|     if (strcmp(req.method, "HEAD") != 0) { |     if (use_rev_proxy == 2) { | ||||||
|  |         // WebSocket | ||||||
|  |         print("Upgrading connection to WebSocket connection"); | ||||||
|  |         ret = ws_handle_connection(client, &rev_proxy); | ||||||
|  |         if (ret != 0) { | ||||||
|  |             client_keep_alive = 0; | ||||||
|  |             close_proxy = 1; | ||||||
|  |         } | ||||||
|  |         print("WebSocket connection closed"); | ||||||
|  |     } else if (strcmp(req.method, "HEAD") != 0) { | ||||||
|  |         // default response | ||||||
|         unsigned long snd_len = 0; |         unsigned long snd_len = 0; | ||||||
|         unsigned long len; |         unsigned long len; | ||||||
|         if (msg_buf[0] != 0) { |         if (msg_buf[0] != 0) { | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Client connection and request handlers (header file) |  * Client connection and request handlers (header file) | ||||||
|  * src/client.h |  * src/client.h | ||||||
|  * Lorenz Stechauner, 2022-08-16 |  * Lorenz Stechauner, 2022-08-16 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_NECRONDA_CLIENT_H | #ifndef SESIMOS_CLIENT_H | ||||||
| #define NECRONDA_SERVER_NECRONDA_CLIENT_H | #define SESIMOS_CLIENT_H | ||||||
|  |  | ||||||
| #include "lib/config.h" | #include "lib/config.h" | ||||||
| #include "lib/sock.h" | #include "lib/sock.h" | ||||||
| @@ -17,4 +17,4 @@ host_config *get_host_config(const char *host); | |||||||
|  |  | ||||||
| int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *client_addr); | int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *client_addr); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_NECRONDA_CLIENT_H | #endif //SESIMOS_CLIENT_H | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								src/defs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/defs.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | /** | ||||||
|  |  * sesimos - secure, simple, modern web server | ||||||
|  |  * Definitions | ||||||
|  |  * src/defs.h | ||||||
|  |  * Lorenz Stechauner, 2021-05-04 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef SESIMOS_DEF_H | ||||||
|  | #define SESIMOS_DEF_H | ||||||
|  |  | ||||||
|  | #define SERVER_VERSION "4.6" | ||||||
|  | #define SERVER_STR "Sesimos/" SERVER_VERSION | ||||||
|  | #define SERVER_STR_HTML "Sesimos web server " SERVER_VERSION | ||||||
|  |  | ||||||
|  | #define CHUNK_SIZE 8192 | ||||||
|  |  | ||||||
|  | #ifndef DEFAULT_HOST | ||||||
|  | #   define DEFAULT_HOST "www.necronda.net" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef SERVER_NAME | ||||||
|  | #   define SERVER_NAME DEFAULT_HOST | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif //SESIMOS_DEF_H | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * File cache implementation |  * File cache implementation | ||||||
|  * src/lib/cache.c |  * src/lib/cache.c | ||||||
|  * Lorenz Stechauner, 2020-12-19 |  * Lorenz Stechauner, 2020-12-19 | ||||||
| @@ -19,6 +19,7 @@ | |||||||
| #include <openssl/sha.h> | #include <openssl/sha.h> | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int cache_continue = 1; | int cache_continue = 1; | ||||||
| magic_t magic; | magic_t magic; | ||||||
| cache_entry *cache; | cache_entry *cache; | ||||||
| @@ -58,17 +59,17 @@ int cache_process() { | |||||||
|     } |     } | ||||||
|     cache = shm_rw; |     cache = shm_rw; | ||||||
|  |  | ||||||
|     if (mkdir("/var/necronda/", 0755) < 0 && errno != EEXIST) { |     if (mkdir("/var/sesimos/", 0755) < 0 && errno != EEXIST) { | ||||||
|         fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda/': %s" CLR_STR "\n", strerror(errno)); |         fprintf(stderr, ERR_STR "Unable to create directory '/var/sesimos/': %s" CLR_STR "\n", strerror(errno)); | ||||||
|         return -3; |         return -3; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (mkdir("/var/necronda/server/", 0755) < 0 && errno != EEXIST) { |     if (mkdir("/var/sesimos/server/", 0755) < 0 && errno != EEXIST) { | ||||||
|         fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda/server/': %s" CLR_STR "\n", strerror(errno)); |         fprintf(stderr, ERR_STR "Unable to create directory '/var/sesimos/server/': %s" CLR_STR "\n", strerror(errno)); | ||||||
|         return -3; |         return -3; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FILE *cache_file = fopen("/var/necronda/server/cache", "rb"); |     FILE *cache_file = fopen("/var/sesimos/server/cache", "rb"); | ||||||
|     if (cache_file != NULL) { |     if (cache_file != NULL) { | ||||||
|         fread(cache, sizeof(cache_entry), CACHE_ENTRIES, cache_file); |         fread(cache, sizeof(cache_entry), CACHE_ENTRIES, cache_file); | ||||||
|         fclose(cache_file); |         fclose(cache_file); | ||||||
| @@ -103,13 +104,13 @@ int cache_process() { | |||||||
|                 FILE *comp_file_gz = NULL; |                 FILE *comp_file_gz = NULL; | ||||||
|                 FILE *comp_file_br = NULL; |                 FILE *comp_file_br = NULL; | ||||||
|                 if (compress) { |                 if (compress) { | ||||||
|                     sprintf(buf, "%.*s/.necronda-server", cache[i].webroot_len, cache[i].filename); |                     sprintf(buf, "%.*s/.sesimos", cache[i].webroot_len, cache[i].filename); | ||||||
|                     if (mkdir(buf, 0755) != 0 && errno != EEXIST) { |                     if (mkdir(buf, 0755) != 0 && errno != EEXIST) { | ||||||
|                         fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno)); |                         fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno)); | ||||||
|                         goto comp_err; |                         goto comp_err; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     sprintf(buf, "%.*s/.necronda-server/cache", cache[i].webroot_len, cache[i].filename); |                     sprintf(buf, "%.*s/.sesimos/cache", cache[i].webroot_len, cache[i].filename); | ||||||
|                     if (mkdir(buf, 0700) != 0 && errno != EEXIST) { |                     if (mkdir(buf, 0700) != 0 && errno != EEXIST) { | ||||||
|                         fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno)); |                         fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno)); | ||||||
|                         goto comp_err; |                         goto comp_err; | ||||||
| @@ -124,10 +125,10 @@ int cache_process() { | |||||||
|                     buf[strlen(rel_path)] = 0; |                     buf[strlen(rel_path)] = 0; | ||||||
|  |  | ||||||
|                     p_len_gz = snprintf(filename_comp_gz, sizeof(filename_comp_gz), |                     p_len_gz = snprintf(filename_comp_gz, sizeof(filename_comp_gz), | ||||||
|                                         "%.*s/.necronda-server/cache/%s.gz", |                                         "%.*s/.sesimos/cache/%s.gz", | ||||||
|                                         cache[i].webroot_len, cache[i].filename, buf); |                                         cache[i].webroot_len, cache[i].filename, buf); | ||||||
|                     p_len_br = snprintf(filename_comp_br, sizeof(filename_comp_br), |                     p_len_br = snprintf(filename_comp_br, sizeof(filename_comp_br), | ||||||
|                                         "%.*s/.necronda-server/cache/%s.br", |                                         "%.*s/.sesimos/cache/%s.br", | ||||||
|                                         cache[i].webroot_len, cache[i].filename, buf); |                                         cache[i].webroot_len, cache[i].filename, buf); | ||||||
|                     if (p_len_gz < 0 || p_len_gz >= sizeof(filename_comp_gz) || |                     if (p_len_gz < 0 || p_len_gz >= sizeof(filename_comp_gz) || | ||||||
|                         p_len_br < 0 || p_len_br >= sizeof(filename_comp_br)) |                         p_len_br < 0 || p_len_br >= sizeof(filename_comp_br)) | ||||||
| @@ -202,7 +203,7 @@ int cache_process() { | |||||||
|  |  | ||||||
|         if (cache_changed) { |         if (cache_changed) { | ||||||
|             cache_changed = 0; |             cache_changed = 0; | ||||||
|             cache_file = fopen("/var/necronda/server/cache", "wb"); |             cache_file = fopen("/var/sesimos/server/cache", "wb"); | ||||||
|             if (cache_file == NULL) { |             if (cache_file == NULL) { | ||||||
|                 fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno)); |                 fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno)); | ||||||
|                 free(buf); |                 free(buf); | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * File cache implementation (header file) |  * File cache implementation (header file) | ||||||
|  * src/lib/cache.h |  * src/lib/cache.h | ||||||
|  * Lorenz Stechauner, 2020-12-19 |  * Lorenz Stechauner, 2020-12-19 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_CACHE_H | #ifndef SESIMOS_CACHE_H | ||||||
| #define NECRONDA_SERVER_CACHE_H | #define SESIMOS_CACHE_H | ||||||
|  |  | ||||||
| #include "uri.h" | #include "uri.h" | ||||||
|  |  | ||||||
| @@ -46,4 +46,4 @@ int cache_filename_comp_invalid(const char *filename); | |||||||
|  |  | ||||||
| int uri_cache_init(http_uri *uri); | int uri_cache_init(http_uri *uri); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_CACHE_H | #endif //SESIMOS_CACHE_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Compression interface |  * Compression interface | ||||||
|  * src/lib/compress.c |  * src/lib/compress.c | ||||||
|  * Lorenz Stechauner, 2021-05-05 |  * Lorenz Stechauner, 2021-05-05 | ||||||
| @@ -10,6 +10,7 @@ | |||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int compress_init(compress_ctx *ctx, int mode) { | int compress_init(compress_ctx *ctx, int mode) { | ||||||
|     ctx->gzip = NULL; |     ctx->gzip = NULL; | ||||||
|     ctx->brotli = NULL; |     ctx->brotli = NULL; | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Compression interface (header file) |  * Compression interface (header file) | ||||||
|  * src/lib/compress.h |  * src/lib/compress.h | ||||||
|  * Lorenz Stechauner, 2021-05-05 |  * Lorenz Stechauner, 2021-05-05 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_COMPRESS_H | #ifndef SESIMOS_COMPRESS_H | ||||||
| #define NECRONDA_SERVER_COMPRESS_H | #define SESIMOS_COMPRESS_H | ||||||
|  |  | ||||||
| #include <zlib.h> | #include <zlib.h> | ||||||
| #include <brotli/encode.h> | #include <brotli/encode.h> | ||||||
| @@ -34,4 +34,4 @@ int compress_compress_mode(compress_ctx *ctx, int mode, const char *in, unsigned | |||||||
|  |  | ||||||
| int compress_free(compress_ctx *ctx); | int compress_free(compress_ctx *ctx); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_COMPRESS_H | #endif //SESIMOS_COMPRESS_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Configuration file loader |  * Configuration file loader | ||||||
|  * src/lib/config.c |  * src/lib/config.c | ||||||
|  * Lorenz Stechauner, 2021-01-05 |  * Lorenz Stechauner, 2021-01-05 | ||||||
| @@ -15,6 +15,7 @@ | |||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| t_config *config; | t_config *config; | ||||||
| char geoip_dir[256], dns_server[256]; | char geoip_dir[256], dns_server[256]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Configuration file loader (header file) |  * Configuration file loader (header file) | ||||||
|  * src/lib/config.h |  * src/lib/config.h | ||||||
|  * Lorenz Stechauner, 2021-01-05 |  * Lorenz Stechauner, 2021-01-05 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_CONFIG_H | #ifndef SESIMOS_CONFIG_H | ||||||
| #define NECRONDA_SERVER_CONFIG_H | #define SESIMOS_CONFIG_H | ||||||
|  |  | ||||||
| #include "uri.h" | #include "uri.h" | ||||||
|  |  | ||||||
| @@ -19,7 +19,7 @@ | |||||||
| #define CONFIG_TYPE_REVERSE_PROXY 2 | #define CONFIG_TYPE_REVERSE_PROXY 2 | ||||||
|  |  | ||||||
| #ifndef DEFAULT_CONFIG_FILE | #ifndef DEFAULT_CONFIG_FILE | ||||||
| #   define DEFAULT_CONFIG_FILE "/etc/necronda/server.conf" | #   define DEFAULT_CONFIG_FILE "/etc/sesimos/server.conf" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -61,4 +61,4 @@ int config_load(const char *filename); | |||||||
|  |  | ||||||
| int config_unload(); | int config_unload(); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_CONFIG_H | #endif //SESIMOS_CONFIG_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * FastCGI interface implementation |  * FastCGI interface implementation | ||||||
|  * src/lib/fastcgi.c |  * src/lib/fastcgi.c | ||||||
|  * Lorenz Stechauner, 2020-12-26 |  * Lorenz Stechauner, 2020-12-26 | ||||||
| @@ -15,6 +15,7 @@ | |||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <string.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; | ||||||
|     unsigned long key_len = strlen(key); |     unsigned long key_len = strlen(key); | ||||||
| @@ -72,8 +73,8 @@ int fastcgi_init(fastcgi_conn *conn, int mode, unsigned int client_num, unsigned | |||||||
|     conn->socket = fcgi_sock; |     conn->socket = fcgi_sock; | ||||||
|  |  | ||||||
|     struct sockaddr_un sock_addr = {AF_UNIX}; |     struct sockaddr_un sock_addr = {AF_UNIX}; | ||||||
|     if (conn->mode == FASTCGI_NECRONDA) { |     if (conn->mode == FASTCGI_SESIMOS) { | ||||||
|         snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", NECRONDA_BACKEND_SOCKET); |         snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", SESIMOS_BACKEND_SOCKET); | ||||||
|     } else if (conn->mode == FASTCGI_PHP) { |     } else if (conn->mode == FASTCGI_PHP) { | ||||||
|         snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", PHP_FPM_SOCKET); |         snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", PHP_FPM_SOCKET); | ||||||
|     } |     } | ||||||
| @@ -343,7 +344,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) { | |||||||
|             free(content); |             free(content); | ||||||
|             return 1; |             return 1; | ||||||
|         } else if (header.type == FCGI_STDERR) { |         } else if (header.type == FCGI_STDERR) { | ||||||
|             // TODO implement Necronda backend error handling |             // TODO implement Sesimos backend error handling | ||||||
|             if (conn->mode == FASTCGI_PHP) { |             if (conn->mode == FASTCGI_PHP) { | ||||||
|                 err = err || fastcgi_php_error(conn, content, content_len, err_msg); |                 err = err || fastcgi_php_error(conn, content, content_len, err_msg); | ||||||
|             } |             } | ||||||
| @@ -386,7 +387,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) { | |||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ret = http_parse_header_field(&res->hdr, ptr, pos0); |         ret = http_parse_header_field(&res->hdr, ptr, pos0, 0); | ||||||
|         if (ret != 0) return (int) ret; |         if (ret != 0) return (int) ret; | ||||||
|         if (pos0[2] == '\r' && pos0[3] == '\n') { |         if (pos0[2] == '\r' && pos0[3] == '\n') { | ||||||
|             return 0; |             return 0; | ||||||
| @@ -484,7 +485,7 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) { | |||||||
|  |  | ||||||
|             return 0; |             return 0; | ||||||
|         } else if (header.type == FCGI_STDERR) { |         } else if (header.type == FCGI_STDERR) { | ||||||
|             // TODO implement Necronda backend error handling |             // TODO implement Sesimos backend error handling | ||||||
|             if (conn->mode == FASTCGI_PHP) { |             if (conn->mode == FASTCGI_PHP) { | ||||||
|                 fastcgi_php_error(conn, content, content_len, buf0); |                 fastcgi_php_error(conn, content, content_len, buf0); | ||||||
|             } |             } | ||||||
| @@ -570,7 +571,7 @@ int fastcgi_dump(fastcgi_conn *conn, char *buf, long len) { | |||||||
|  |  | ||||||
|             return 0; |             return 0; | ||||||
|         } else if (header.type == FCGI_STDERR) { |         } else if (header.type == FCGI_STDERR) { | ||||||
|             // TODO implement Necronda backend error handling |             // TODO implement Sesimos backend error handling | ||||||
|             if (conn->mode == FASTCGI_PHP) { |             if (conn->mode == FASTCGI_PHP) { | ||||||
|                 fastcgi_php_error(conn, content, content_len, buf0); |                 fastcgi_php_error(conn, content, content_len, buf0); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * FastCGI interface implementation (header file) |  * FastCGI interface implementation (header file) | ||||||
|  * src/lib/fastcgi.h |  * src/lib/fastcgi.h | ||||||
|  * Lorenz Stechauner, 2020-12-26 |  * Lorenz Stechauner, 2020-12-26 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_FASTCGI_H | #ifndef SESIMOS_FASTCGI_H | ||||||
| #define NECRONDA_SERVER_FASTCGI_H | #define SESIMOS_FASTCGI_H | ||||||
|  |  | ||||||
| #include "include/fastcgi.h" | #include "include/fastcgi.h" | ||||||
| #include "http.h" | #include "http.h" | ||||||
| @@ -19,13 +19,13 @@ | |||||||
| #define FASTCGI_COMPRESS_HOLD 8 | #define FASTCGI_COMPRESS_HOLD 8 | ||||||
|  |  | ||||||
| #define FASTCGI_PHP 1 | #define FASTCGI_PHP 1 | ||||||
| #define FASTCGI_NECRONDA 2 | #define FASTCGI_SESIMOS 2 | ||||||
|  |  | ||||||
| #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 | ||||||
|  |  | ||||||
| #define NECRONDA_BACKEND_SOCKET "/var/run/necronda/necronda-backend.sock" | #define SESIMOS_BACKEND_SOCKET "/var/run/sesimos/backend.sock" | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     int mode; |     int mode; | ||||||
| @@ -54,4 +54,4 @@ int fastcgi_dump(fastcgi_conn *conn, char *buf, long len); | |||||||
|  |  | ||||||
| int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len); | int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_FASTCGI_H | #endif //SESIMOS_FASTCGI_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * MaxMind GeoIP Database interface |  * MaxMind GeoIP Database interface | ||||||
|  * src/lib/geoip.c |  * src/lib/geoip.c | ||||||
|  * Lorenz Stechauner, 2021-05-04 |  * Lorenz Stechauner, 2021-05-04 | ||||||
| @@ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| #include "geoip.h" | #include "geoip.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| 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,13 +1,13 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * MaxMind GeoIP Database interface (header file) |  * MaxMind GeoIP Database interface (header file) | ||||||
|  * src/lib/geoip.h |  * src/lib/geoip.h | ||||||
|  * Lorenz Stechauner, 2021-05-04 |  * Lorenz Stechauner, 2021-05-04 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_GEOIP_H | #ifndef SESIMOS_GEOIP_H | ||||||
| #define NECRONDA_SERVER_GEOIP_H | #define SESIMOS_GEOIP_H | ||||||
|  |  | ||||||
| #include <maxminddb.h> | #include <maxminddb.h> | ||||||
|  |  | ||||||
| @@ -15,4 +15,4 @@ | |||||||
|  |  | ||||||
| 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); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_GEOIP_H | #endif //SESIMOS_GEOIP_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * HTTP implementation |  * HTTP implementation | ||||||
|  * src/lib/http.c |  * src/lib/http.c | ||||||
|  * Lorenz Stechauner, 2020-12-09 |  * Lorenz Stechauner, 2020-12-09 | ||||||
| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| void http_to_camel_case(char *str, int mode) { | void http_to_camel_case(char *str, int mode) { | ||||||
|     if (mode == HTTP_PRESERVE) |     if (mode == HTTP_PRESERVE) | ||||||
|         return; |         return; | ||||||
| @@ -83,7 +84,7 @@ void http_free_res(http_res *res) { | |||||||
|     http_free_hdr(&res->hdr); |     http_free_hdr(&res->hdr); | ||||||
| } | } | ||||||
|  |  | ||||||
| int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) { | int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr, int flags) { | ||||||
|     if (hdr->last_field_num > hdr->field_num) { |     if (hdr->last_field_num > hdr->field_num) { | ||||||
|         print(ERR_STR "Unable to parse header: Invalid state" CLR_STR); |         print(ERR_STR "Unable to parse header: Invalid state" CLR_STR); | ||||||
|         return 3; |         return 3; | ||||||
| @@ -116,7 +117,7 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) | |||||||
|  |  | ||||||
|     char field_num = hdr->field_num; |     char field_num = hdr->field_num; | ||||||
|     int found = http_get_header_field_num_len(hdr, buf, len1); |     int found = http_get_header_field_num_len(hdr, buf, len1); | ||||||
|     if (found == -1) { |     if (!(flags & HTTP_MERGE_FIELDS) || found == -1) { | ||||||
|         if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0) { |         if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0) { | ||||||
|             print(ERR_STR "Unable to parse header: Too many header fields" CLR_STR); |             print(ERR_STR "Unable to parse header: Too many header fields" CLR_STR); | ||||||
|             return 3; |             return 3; | ||||||
| @@ -204,7 +205,7 @@ int http_receive_request(sock *client, http_req *req) { | |||||||
|                 sprintf(req->uri, "%.*s", (int) len, pos1); |                 sprintf(req->uri, "%.*s", (int) len, pos1); | ||||||
|                 sprintf(req->version, "%.3s", pos2 + 5); |                 sprintf(req->version, "%.3s", pos2 + 5); | ||||||
|             } else { |             } else { | ||||||
|                 int ret = http_parse_header_field(&req->hdr, ptr, pos0); |                 int ret = http_parse_header_field(&req->hdr, ptr, pos0, HTTP_MERGE_FIELDS); | ||||||
|                 if (ret != 0) return ret; |                 if (ret != 0) return ret; | ||||||
|             } |             } | ||||||
|             ptr = pos0 + 2; |             ptr = pos0 + 2; | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * HTTP implementation (header file) |  * HTTP implementation (header file) | ||||||
|  * src/lib/http.h |  * src/lib/http.h | ||||||
|  * Lorenz Stechauner, 2020-12-09 |  * Lorenz Stechauner, 2020-12-09 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_HTTP_H | #ifndef SESIMOS_HTTP_H | ||||||
| #define NECRONDA_SERVER_HTTP_H | #define SESIMOS_HTTP_H | ||||||
|  |  | ||||||
| #include "sock.h" | #include "sock.h" | ||||||
|  |  | ||||||
| @@ -22,6 +22,8 @@ | |||||||
| #define HTTP_FIELD_EX_VALUE 1 | #define HTTP_FIELD_EX_VALUE 1 | ||||||
| #define HTTP_FIELD_EX_NAME 2 | #define HTTP_FIELD_EX_NAME 2 | ||||||
|  |  | ||||||
|  | #define HTTP_MERGE_FIELDS 1 | ||||||
|  |  | ||||||
| #define HTTP_1XX_STR "\x1B[1;32m" | #define HTTP_1XX_STR "\x1B[1;32m" | ||||||
| #define HTTP_2XX_STR "\x1B[1;32m" | #define HTTP_2XX_STR "\x1B[1;32m" | ||||||
| #define HTTP_3XX_STR "\x1B[1;33m" | #define HTTP_3XX_STR "\x1B[1;33m" | ||||||
| @@ -37,11 +39,11 @@ | |||||||
| #define HTTP_MAX_HEADER_FIELD_NUM 64 | #define HTTP_MAX_HEADER_FIELD_NUM 64 | ||||||
|  |  | ||||||
| #ifndef SERVER_STR | #ifndef SERVER_STR | ||||||
| #   define SERVER_STR "Necronda" | #   define SERVER_STR "Sesimos" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef SERVER_STR_HTML | #ifndef SERVER_STR_HTML | ||||||
| #   define SERVER_STR_HTML "Necronda web server" | #   define SERVER_STR_HTML "Sesimos web server" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
| @@ -106,6 +108,7 @@ typedef enum { | |||||||
| typedef struct { | typedef struct { | ||||||
|     unsigned short status; |     unsigned short status; | ||||||
|     http_error_origin origin; |     http_error_origin origin; | ||||||
|  |     const char* ws_key; | ||||||
| } http_status_ctx; | } http_status_ctx; | ||||||
|  |  | ||||||
| extern const http_status http_statuses[]; | extern const http_status http_statuses[]; | ||||||
| @@ -140,7 +143,7 @@ void http_free_res(http_res *res); | |||||||
|  |  | ||||||
| int http_receive_request(sock *client, http_req *req); | int http_receive_request(sock *client, http_req *req); | ||||||
|  |  | ||||||
| int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) ; | int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr, int flags); | ||||||
|  |  | ||||||
| const char *http_get_header_field(const http_hdr *hdr, const char *field_name); | const char *http_get_header_field(const http_hdr *hdr, const char *field_name); | ||||||
|  |  | ||||||
| @@ -176,4 +179,4 @@ const http_doc_info *http_get_status_info(const http_status *status); | |||||||
|  |  | ||||||
| int http_get_compression(const http_req *req, const http_res *res); | int http_get_compression(const http_req *req, const http_res *res); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_HTTP_H | #endif //SESIMOS_HTTP_H | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * HTTP static implementation |  * HTTP static implementation | ||||||
|  * src/lib/http_static.c |  * src/lib/http_static.c | ||||||
|  * Lorenz Stechauner, 2021-05-03 |  * Lorenz Stechauner, 2021-05-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "../necronda.h" | #include "../defs.h" | ||||||
| #include "http.h" | #include "http.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| const http_status http_statuses[] = { | const http_status http_statuses[] = { | ||||||
|         {100, "Informational", "Continue"}, |         {100, "Informational", "Continue"}, | ||||||
|         {101, "Informational", "Switching Protocols"}, |         {101, "Informational", "Switching Protocols"}, | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * FastCGI header file |  * FastCGI header file | ||||||
|  * src/lib/include/fastcgi.h |  * src/lib/include/fastcgi.h | ||||||
|  * Lorenz Stechauner, 2021-05-03 |  * Lorenz Stechauner, 2021-05-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_EXTERN_FASTCGI_H | #ifndef SESIMOS_EXTERN_FASTCGI_H | ||||||
| #define NECRONDA_SERVER_EXTERN_FASTCGI_H | #define SESIMOS_EXTERN_FASTCGI_H | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Listening socket file number |  * Listening socket file number | ||||||
| @@ -119,4 +119,4 @@ typedef struct { | |||||||
|     FCGI_UnknownTypeBody body; |     FCGI_UnknownTypeBody body; | ||||||
| } FCGI_UnknownTypeRecord; | } FCGI_UnknownTypeRecord; | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_EXTERN_FASTCGI_H | #endif //SESIMOS_EXTERN_FASTCGI_H | ||||||
|   | |||||||
| @@ -1,14 +1,15 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Reverse proxy |  * Reverse proxy | ||||||
|  * src/lib/rev_proxy.c |  * src/lib/rev_proxy.c | ||||||
|  * Lorenz Stechauner, 2021-01-07 |  * Lorenz Stechauner, 2021-01-07 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include "../defs.h" | ||||||
|  | #include "../server.h" | ||||||
| #include "rev_proxy.h" | #include "rev_proxy.h" | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
| #include "compress.h" | #include "compress.h" | ||||||
| #include "../server.h" |  | ||||||
|  |  | ||||||
| #include <openssl/ssl.h> | #include <openssl/ssl.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @@ -17,6 +18,7 @@ | |||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
| #include <sys/time.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}; | ||||||
| @@ -32,8 +34,6 @@ int rev_proxy_preload() { | |||||||
| int rev_proxy_request_header(http_req *req, int enc) { | int rev_proxy_request_header(http_req *req, int enc) { | ||||||
|     char buf1[256], buf2[256]; |     char buf1[256], buf2[256]; | ||||||
|     int p_len; |     int p_len; | ||||||
|     http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL); |  | ||||||
|     http_add_header_field(&req->hdr, "Connection", "keep-alive"); |  | ||||||
|  |  | ||||||
|     const char *via = http_get_header_field(&req->hdr, "Via"); |     const char *via = http_get_header_field(&req->hdr, "Via"); | ||||||
|     sprintf(buf1, "HTTP/%s %s", req->version, SERVER_NAME); |     sprintf(buf1, "HTTP/%s %s", req->version, SERVER_NAME); | ||||||
| @@ -183,12 +183,12 @@ int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) { | |||||||
|  |  | ||||||
| int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client, http_status *custom_status, char *err_msg) { | int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client, http_status *custom_status, char *err_msg) { | ||||||
|     char buffer[CHUNK_SIZE]; |     char buffer[CHUNK_SIZE]; | ||||||
|  |     const char *connection, *upgrade, *ws_version; | ||||||
|     long ret; |     long ret; | ||||||
|     int tries = 0, retry = 0; |     int tries = 0, retry = 0; | ||||||
|  |  | ||||||
|     if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0) { |     if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0) | ||||||
|         goto rev_proxy; |         goto rev_proxy; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     retry: |     retry: | ||||||
|     if (rev_proxy.socket != 0) { |     if (rev_proxy.socket != 0) { | ||||||
| @@ -289,6 +289,22 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf | |||||||
|     print(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i" CLR_STR, buffer, conf->rev_proxy.port); |     print(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i" CLR_STR, buffer, conf->rev_proxy.port); | ||||||
|  |  | ||||||
|     rev_proxy: |     rev_proxy: | ||||||
|  |     connection = http_get_header_field(&req->hdr, "Connection"); | ||||||
|  |     if (connection != NULL && (strstr(connection, "upgrade") != NULL || strstr(connection, "Upgrade") != NULL)) { | ||||||
|  |         upgrade = http_get_header_field(&req->hdr, "Upgrade"); | ||||||
|  |         ws_version = http_get_header_field(&req->hdr, "Sec-WebSocket-Version"); | ||||||
|  |         if (upgrade != NULL && ws_version != NULL && strcmp(upgrade, "websocket") == 0 && strcmp(ws_version, "13") == 0) { | ||||||
|  |             ctx->ws_key = http_get_header_field(&req->hdr, "Sec-WebSocket-Key"); | ||||||
|  |         } else { | ||||||
|  |             res->status = http_get_status(501); | ||||||
|  |             ctx->origin = INTERNAL; | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL); | ||||||
|  |         http_add_header_field(&req->hdr, "Connection", "keep-alive"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     ret = rev_proxy_request_header(req, (int) client->enc); |     ret = rev_proxy_request_header(req, (int) client->enc); | ||||||
|     if (ret != 0) { |     if (ret != 0) { | ||||||
|         res->status = http_get_status(500); |         res->status = http_get_status(500); | ||||||
| @@ -422,7 +438,7 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf | |||||||
|                 goto proxy_err; |                 goto proxy_err; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             ret = http_parse_header_field(&res->hdr, ptr, pos0); |             ret = http_parse_header_field(&res->hdr, ptr, pos0, 0); | ||||||
|             if (ret != 0) { |             if (ret != 0) { | ||||||
|                 res->status = http_get_status(502); |                 res->status = http_get_status(502); | ||||||
|                 ctx->origin = SERVER_RES; |                 ctx->origin = SERVER_RES; | ||||||
| @@ -453,7 +469,6 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf | |||||||
| } | } | ||||||
|  |  | ||||||
| int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) { | int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) { | ||||||
|     // TODO handle websockets |  | ||||||
|     char buffer[CHUNK_SIZE], comp_out[CHUNK_SIZE], buf[256], *ptr; |     char buffer[CHUNK_SIZE], comp_out[CHUNK_SIZE], buf[256], *ptr; | ||||||
|     long ret = 0, len, snd_len; |     long ret = 0, len, snd_len; | ||||||
|     int finish_comp = 0; |     int finish_comp = 0; | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Reverse proxy (header file) |  * Reverse proxy (header file) | ||||||
|  * src/lib/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 SESIMOS_REV_PROXY_H | ||||||
| #define NECRONDA_SERVER_REV_PROXY_H | #define SESIMOS_REV_PROXY_H | ||||||
|  |  | ||||||
| #define REV_PROXY_CHUNKED 1 | #define REV_PROXY_CHUNKED 1 | ||||||
| #define REV_PROXY_COMPRESS_GZ 2 | #define REV_PROXY_COMPRESS_GZ 2 | ||||||
| @@ -35,4 +35,4 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags); | |||||||
|  |  | ||||||
| int rev_proxy_dump(char *buf, long len); | int rev_proxy_dump(char *buf, long len); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_REV_PROXY_H | #endif //SESIMOS_REV_PROXY_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Basic TCP and TLS socket |  * Basic TCP and TLS socket | ||||||
|  * src/lib/sock.c |  * src/lib/sock.c | ||||||
|  * Lorenz Stechauner, 2021-01-07 |  * Lorenz Stechauner, 2021-01-07 | ||||||
| @@ -12,6 +12,8 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <poll.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int sock_enc_error(sock *s) { | int sock_enc_error(sock *s) { | ||||||
|     return (int) s->enc ? SSL_get_error(s->ssl, (int) s->_last_ret) : 0; |     return (int) s->enc ? SSL_get_error(s->ssl, (int) s->_last_ret) : 0; | ||||||
| @@ -117,3 +119,29 @@ int sock_check(sock *s) { | |||||||
|     char buf; |     char buf; | ||||||
|     return recv(s->socket, &buf, 1, MSG_PEEK | MSG_DONTWAIT) == 1; |     return recv(s->socket, &buf, 1, MSG_PEEK | MSG_DONTWAIT) == 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int sock_poll(sock *sockets[], sock *ready[], short events, int n_sock, int timeout_ms) { | ||||||
|  |     struct pollfd fds[n_sock]; | ||||||
|  |     for (int i = 0; i < n_sock; i++) { | ||||||
|  |         fds[i].fd = sockets[i]->socket; | ||||||
|  |         fds[i].events = events; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     int ret = poll(fds, n_sock, timeout_ms); | ||||||
|  |     if (ret < 0 || ready == NULL) return ret; | ||||||
|  |  | ||||||
|  |     int j = 0; | ||||||
|  |     for (int i = 0; i < n_sock; i++) { | ||||||
|  |         if (fds[i].revents & events) | ||||||
|  |             ready[j++] = sockets[i]; | ||||||
|  |     } | ||||||
|  |     return j; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int sock_poll_read(sock *sockets[], sock *readable[], int n_sock, int timeout_ms) { | ||||||
|  |     return sock_poll(sockets, readable, POLLIN, n_sock, timeout_ms); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int sock_poll_write(sock *sockets[], sock *writable[], int n_sock, int timeout_ms) { | ||||||
|  |     return sock_poll(sockets, writable, POLLOUT, n_sock, timeout_ms); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,14 +1,15 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Basic TCP and TLS socket (header file) |  * Basic TCP and TLS socket (header file) | ||||||
|  * src/lib/sock.h |  * src/lib/sock.h | ||||||
|  * Lorenz Stechauner, 2021-01-07 |  * Lorenz Stechauner, 2021-01-07 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_SOCK_H | #ifndef SESIMOS_SOCK_H | ||||||
| #define NECRONDA_SERVER_SOCK_H | #define SESIMOS_SOCK_H | ||||||
|  |  | ||||||
| #include <openssl/crypto.h> | #include <openssl/crypto.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     unsigned int enc:1; |     unsigned int enc:1; | ||||||
| @@ -37,4 +38,10 @@ int sock_close(sock *s); | |||||||
|  |  | ||||||
| int sock_check(sock *s); | int sock_check(sock *s); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_SOCK_H | int sock_poll(sock *sockets[], sock *readable[], short events, int n_sock, int timeout_ms); | ||||||
|  |  | ||||||
|  | int sock_poll_read(sock *sockets[], sock *readable[], int n_sock, int timeout_ms); | ||||||
|  |  | ||||||
|  | int sock_poll_write(sock *sockets[], sock *writable[], int n_sock, int timeout_ms); | ||||||
|  |  | ||||||
|  | #endif //SESIMOS_SOCK_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * URI and path handlers |  * URI and path handlers | ||||||
|  * src/lib/uri.c |  * src/lib/uri.c | ||||||
|  * Lorenz Stechauner, 2020-12-13 |  * Lorenz Stechauner, 2020-12-13 | ||||||
| @@ -11,6 +11,7 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int path_is_directory(const char *path) { | int path_is_directory(const char *path) { | ||||||
|     struct stat statbuf; |     struct stat statbuf; | ||||||
|     return stat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) != 0; |     return stat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) != 0; | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * URI and path handlers (header file) |  * URI and path handlers (header file) | ||||||
|  * src/lib/uri.h |  * src/lib/uri.h | ||||||
|  * Lorenz Stechauner, 2020-12-13 |  * Lorenz Stechauner, 2020-12-13 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_URI_H | #ifndef SESIMOS_URI_H | ||||||
| #define NECRONDA_SERVER_URI_H | #define SESIMOS_URI_H | ||||||
|  |  | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
|  |  | ||||||
| @@ -44,4 +44,4 @@ int uri_init_cache(http_uri *uri); | |||||||
|  |  | ||||||
| void uri_free(http_uri *uri); | void uri_free(http_uri *uri); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_URI_H | #endif //SESIMOS_URI_H | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Utilities |  * Utilities | ||||||
|  * src/lib/utils.c |  * src/lib/utils.c | ||||||
|  * Lorenz Stechauner, 2020-12-03 |  * Lorenz Stechauner, 2020-12-03 | ||||||
| @@ -11,6 +11,7 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| char *log_prefix; | char *log_prefix; | ||||||
|  |  | ||||||
| char *format_duration(unsigned long micros, char *buf) { | char *format_duration(unsigned long micros, char *buf) { | ||||||
| @@ -191,6 +192,7 @@ int base64_encode(void *data, unsigned long data_len, char *output, unsigned lon | |||||||
|  |  | ||||||
|     for (int i = 0; i < base64_mod_table[data_len % 3]; i++) |     for (int i = 0; i < base64_mod_table[data_len % 3]; i++) | ||||||
|         output[out_len - 1 - i] = '='; |         output[out_len - 1 - i] = '='; | ||||||
|  |     output[out_len] = 0; | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Utilities (header file) |  * Utilities (header file) | ||||||
|  * src/lib/utils.h |  * src/lib/utils.h | ||||||
|  * Lorenz Stechauner, 2020-12-03 |  * Lorenz Stechauner, 2020-12-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_UTILS_H | #ifndef SESIMOS_UTILS_H | ||||||
| #define NECRONDA_SERVER_UTILS_H | #define SESIMOS_UTILS_H | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  |  | ||||||
| @@ -52,4 +52,4 @@ int str_trim_lws(char **start, char **end); | |||||||
|  |  | ||||||
| int base64_encode(void *data, unsigned long data_len, char *output, unsigned long *output_len); | int base64_encode(void *data, unsigned long data_len, char *output, unsigned long *output_len); | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_UTILS_H | #endif //SESIMOS_UTILS_H | ||||||
|   | |||||||
							
								
								
									
										201
									
								
								src/lib/websocket.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								src/lib/websocket.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | |||||||
|  | /** | ||||||
|  |  * sesimos - secure, simple, modern web server | ||||||
|  |  * WebSocket reverse proxy | ||||||
|  |  * src/lib/websocket.c | ||||||
|  |  * Lorenz Stechauner, 2022-08-16 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "../defs.h" | ||||||
|  | #include "websocket.h" | ||||||
|  | #include "utils.h" | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  | #include <openssl/sha.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <signal.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int terminate = 0; | ||||||
|  |  | ||||||
|  | void ws_terminate() { | ||||||
|  |     terminate = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ws_calc_accept_key(const char *key, char *accept_key) { | ||||||
|  |     if (key == NULL || accept_key == NULL) | ||||||
|  |         return -1; | ||||||
|  |  | ||||||
|  |     char input[256] = ""; | ||||||
|  |     unsigned char output[SHA_DIGEST_LENGTH]; | ||||||
|  |     strcat(input, key); | ||||||
|  |     strcat(input, ws_key_uuid); | ||||||
|  |  | ||||||
|  |     if (SHA1((unsigned char *) input, strlen(input), output) == NULL) { | ||||||
|  |         return -2; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     base64_encode(output, sizeof(output), accept_key, NULL); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ws_recv_frame_header(sock *s, ws_frame *frame) { | ||||||
|  |     unsigned char buf[12]; | ||||||
|  |  | ||||||
|  |     long ret = sock_recv(s, buf, 2, 0); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         print(ERR_STR "Unable to receive from socket: %s" CLR_STR, strerror(errno)); | ||||||
|  |         return -1; | ||||||
|  |     } else if (ret != 2) { | ||||||
|  |         print(ERR_STR "Unable to receive 2 bytes from socket" CLR_STR); | ||||||
|  |         return -2; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unsigned short bits = (buf[0] << 8) | buf[1]; | ||||||
|  |     frame->f_fin = (bits >> 15) & 1; | ||||||
|  |     frame->f_rsv1 = (bits >> 14) & 1; | ||||||
|  |     frame->f_rsv2 = (bits >> 13) & 1; | ||||||
|  |     frame->f_rsv3 = (bits >> 12) & 1; | ||||||
|  |     frame->opcode = (bits >> 8) & 0xF; | ||||||
|  |     frame->f_mask = (bits >> 7) & 1; | ||||||
|  |     unsigned short len = (bits & 0x7F); | ||||||
|  |  | ||||||
|  |     int remaining = frame->f_mask ? 4 : 0; | ||||||
|  |     if (len == 126) { | ||||||
|  |         remaining += 2; | ||||||
|  |     } else if (len == 127) { | ||||||
|  |         remaining += 8; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = sock_recv(s, buf, remaining, 0); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         print(ERR_STR "Unable to receive from socket: %s" CLR_STR, strerror(errno)); | ||||||
|  |         return -1; | ||||||
|  |     } else if (ret != remaining) { | ||||||
|  |         print(ERR_STR "Unable to receive correct number of bytes from socket" CLR_STR); | ||||||
|  |         return -2; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (len == 126) { | ||||||
|  |         frame->len = (((unsigned long) buf[0]) << 8) | ((unsigned long) buf[1]); | ||||||
|  |     } else if (len == 127) { | ||||||
|  |         frame->len = | ||||||
|  |                 (((unsigned long) buf[0]) << 56) | | ||||||
|  |                 (((unsigned long) buf[1]) << 48) | | ||||||
|  |                 (((unsigned long) buf[2]) << 40) | | ||||||
|  |                 (((unsigned long) buf[3]) << 32) | | ||||||
|  |                 (((unsigned long) buf[4]) << 24) | | ||||||
|  |                 (((unsigned long) buf[5]) << 16) | | ||||||
|  |                 (((unsigned long) buf[6]) << 8) | | ||||||
|  |                 (((unsigned long) buf[7]) << 0); | ||||||
|  |     } else { | ||||||
|  |         frame->len = len; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (frame->f_mask) memcpy(frame->masking_key, buf + (remaining - 4), 4); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ws_send_frame_header(sock *s, ws_frame *frame) { | ||||||
|  |     unsigned char buf[14], *ptr = buf; | ||||||
|  |  | ||||||
|  |     unsigned short len; | ||||||
|  |     if (frame->len > 0x7FFF) { | ||||||
|  |         len = 127; | ||||||
|  |     } else if (frame->len > 125) { | ||||||
|  |         len = 126; | ||||||
|  |     } else { | ||||||
|  |         len = frame->len; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unsigned short bits = | ||||||
|  |             (frame->f_fin << 15) | | ||||||
|  |             (frame->f_rsv1 << 14) | | ||||||
|  |             (frame->f_rsv2 << 13) | | ||||||
|  |             (frame->f_rsv3 << 12) | | ||||||
|  |             (frame->opcode << 8) | | ||||||
|  |             (frame->f_mask << 7) | | ||||||
|  |             len; | ||||||
|  |  | ||||||
|  |     ptr++[0] = bits >> 8; | ||||||
|  |     ptr++[0] = bits & 0xFF; | ||||||
|  |  | ||||||
|  |     if (len >= 126) { | ||||||
|  |         for (int i = (len == 126 ? 2 : 8) - 1; i >= 0; i--) | ||||||
|  |             ptr++[0] = (unsigned char) ((frame->len >> (i * 8)) & 0xFF); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (frame->f_mask) { | ||||||
|  |         memcpy(ptr, frame->masking_key, 4); | ||||||
|  |         ptr += 4; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     long ret = sock_send(s, buf, ptr - buf, frame->len != 0 ? MSG_MORE : 0); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         print(ERR_STR "Unable to send to socket: %s" CLR_STR, strerror(errno)); | ||||||
|  |         return -1; | ||||||
|  |     } else if (ret != ptr - buf) { | ||||||
|  |         print(ERR_STR "Unable to send to socket" CLR_STR); | ||||||
|  |         return -2; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ws_handle_connection(sock *s1, sock *s2) { | ||||||
|  |     sock *poll_socks[2] = {s1, s2}; | ||||||
|  |     sock *readable[2]; | ||||||
|  |     int n_sock = 2; | ||||||
|  |     ws_frame frame; | ||||||
|  |     char buf[CHUNK_SIZE]; | ||||||
|  |     int poll, closes = 0; | ||||||
|  |     long ret; | ||||||
|  |  | ||||||
|  |     signal(SIGINT, ws_terminate); | ||||||
|  |     signal(SIGTERM, ws_terminate); | ||||||
|  |  | ||||||
|  |     while (!terminate && closes != 3) { | ||||||
|  |         poll = sock_poll_read(poll_socks, readable, n_sock, WS_TIMEOUT * 1000); | ||||||
|  |         if (terminate) { | ||||||
|  |             break; | ||||||
|  |         } else if (poll < 0) { | ||||||
|  |             print(ERR_STR "Unable to poll sockets: %s" CLR_STR, strerror(errno)); | ||||||
|  |             return -1; | ||||||
|  |         } else if (poll == 0) { | ||||||
|  |             print(ERR_STR "Connection timed out" CLR_STR); | ||||||
|  |             return -2; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (int i = 0; i < poll; i++) { | ||||||
|  |             sock *s = readable[i]; | ||||||
|  |             sock *o = (s == s1) ? s2 : s1; | ||||||
|  |             if (ws_recv_frame_header(s, &frame) != 0) return -3; | ||||||
|  |  | ||||||
|  |             if (frame.opcode == 0x8) { | ||||||
|  |                 n_sock--; | ||||||
|  |                 if (s == s1) { | ||||||
|  |                     poll_socks[0] = s2; | ||||||
|  |                     closes |= 1; | ||||||
|  |                 } else { | ||||||
|  |                     closes |= 2; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (ws_send_frame_header(o, &frame) != 0) return -3; | ||||||
|  |  | ||||||
|  |             if (frame.len > 0) { | ||||||
|  |                 ret = sock_splice(o, s, buf, sizeof(buf), frame.len); | ||||||
|  |                 if (ret < 0) { | ||||||
|  |                     print(ERR_STR "Unable to forward data in WebSocket: %s" CLR_STR, strerror(errno)); | ||||||
|  |                     return -3; | ||||||
|  |                 } else if (ret != frame.len) { | ||||||
|  |                     print(ERR_STR "Unable to forward correct number of bytes in WebSocket" CLR_STR); | ||||||
|  |                     return -3; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/lib/websocket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/lib/websocket.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | /** | ||||||
|  |  * sesimos - secure, simple, modern web server | ||||||
|  |  * WebSocket reverse proxy (header file) | ||||||
|  |  * src/lib/websocket.h | ||||||
|  |  * Lorenz Stechauner, 2022-08-16 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef SESIMOS_WEBSOCKET_H | ||||||
|  | #define SESIMOS_WEBSOCKET_H | ||||||
|  |  | ||||||
|  | #include "sock.h" | ||||||
|  |  | ||||||
|  | #define WS_TIMEOUT 3600 | ||||||
|  |  | ||||||
|  | const char *ws_key_uuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     unsigned char f_fin:1; | ||||||
|  |     unsigned char f_rsv1:1; | ||||||
|  |     unsigned char f_rsv2:1; | ||||||
|  |     unsigned char f_rsv3:1; | ||||||
|  |     unsigned char opcode:4; | ||||||
|  |     unsigned char f_mask:1; | ||||||
|  |     unsigned long len; | ||||||
|  |     char masking_key[4]; | ||||||
|  | } ws_frame; | ||||||
|  |  | ||||||
|  | int ws_calc_accept_key(const char *key, char *accept_key); | ||||||
|  |  | ||||||
|  | int ws_recv_frame_header(sock *s, ws_frame *frame); | ||||||
|  |  | ||||||
|  | int ws_send_frame_header(sock *s, ws_frame *frame); | ||||||
|  |  | ||||||
|  | int ws_handle_connection(sock *s1, sock *s2); | ||||||
|  |  | ||||||
|  | #endif //SESIMOS_WEBSOCKET_H | ||||||
| @@ -1,23 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Necronda Web Server |  | ||||||
|  * Definitions |  | ||||||
|  * src/necronda.h |  | ||||||
|  * Lorenz Stechauner, 2021-05-04 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_NECRONDA_H |  | ||||||
| #define NECRONDA_SERVER_NECRONDA_H |  | ||||||
|  |  | ||||||
| #define NECRONDA_VERSION "4.5" |  | ||||||
| #define SERVER_STR "Necronda/" NECRONDA_VERSION |  | ||||||
| #define SERVER_STR_HTML "Necronda web server " NECRONDA_VERSION |  | ||||||
|  |  | ||||||
| #ifndef DEFAULT_HOST |  | ||||||
| #   define DEFAULT_HOST "www.necronda.net" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef SERVER_NAME |  | ||||||
| #   define SERVER_NAME DEFAULT_HOST |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_NECRONDA_H |  | ||||||
							
								
								
									
										34
									
								
								src/server.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/server.c
									
									
									
									
									
								
							| @@ -1,13 +1,13 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * Sesimos - secure, simple, modern web server | ||||||
|  * Main executable |  * Main executable | ||||||
|  * src/necronda-server.c |  * src/server.c | ||||||
|  * Lorenz Stechauner, 2020-12-03 |  * Lorenz Stechauner, 2020-12-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #define _POSIX_C_SOURCE 199309L | #define _POSIX_C_SOURCE 199309L | ||||||
|  |  | ||||||
| #include "necronda.h" | #include "defs.h" | ||||||
| #include "server.h" | #include "server.h" | ||||||
| #include "client.h" | #include "client.h" | ||||||
|  |  | ||||||
| @@ -22,7 +22,7 @@ | |||||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <sys/select.h> | #include <poll.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
| @@ -34,6 +34,7 @@ | |||||||
| #include <openssl/conf.h> | #include <openssl/conf.h> | ||||||
| #include <dirent.h> | #include <dirent.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int active = 1; | int active = 1; | ||||||
| const char *config_file; | const char *config_file; | ||||||
| int sockets[NUM_SOCKETS]; | int sockets[NUM_SOCKETS]; | ||||||
| @@ -153,8 +154,7 @@ void terminate() { | |||||||
|  |  | ||||||
| int main(int argc, const char *argv[]) { | int main(int argc, const char *argv[]) { | ||||||
|     const int YES = 1; |     const int YES = 1; | ||||||
|     fd_set socket_fds, read_socket_fds; |     struct pollfd poll_fds[NUM_SOCKETS]; | ||||||
|     int max_socket_fd = 0; |  | ||||||
|     int ready_sockets_num; |     int ready_sockets_num; | ||||||
|     long client_num = 0; |     long client_num = 0; | ||||||
|     char buf[1024]; |     char buf[1024]; | ||||||
| @@ -169,8 +169,6 @@ int main(int argc, const char *argv[]) { | |||||||
|     memset(children, 0, sizeof(children)); |     memset(children, 0, sizeof(children)); | ||||||
|     memset(mmdbs, 0, sizeof(mmdbs)); |     memset(mmdbs, 0, sizeof(mmdbs)); | ||||||
|  |  | ||||||
|     struct timeval timeout; |  | ||||||
|  |  | ||||||
|     const struct sockaddr_in6 addresses[2] = { |     const struct sockaddr_in6 addresses[2] = { | ||||||
|             {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)}, |             {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)}, | ||||||
|             {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)} |             {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)} | ||||||
| @@ -180,7 +178,7 @@ int main(int argc, const char *argv[]) { | |||||||
|         fprintf(stderr, ERR_STR "Unable to set stdout to line-buffered mode: %s" CLR_STR, strerror(errno)); |         fprintf(stderr, ERR_STR "Unable to set stdout to line-buffered mode: %s" CLR_STR, strerror(errno)); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     printf("Necronda Web Server " NECRONDA_VERSION "\n"); |     printf("Sesimos web server " SERVER_VERSION "\n"); | ||||||
|  |  | ||||||
|     ret = config_init(); |     ret = config_init(); | ||||||
|     if (ret != 0) { |     if (ret != 0) { | ||||||
| @@ -191,7 +189,7 @@ int main(int argc, const char *argv[]) { | |||||||
|     for (int i = 1; i < argc; i++) { |     for (int i = 1; i < argc; i++) { | ||||||
|         const char *arg = argv[i]; |         const char *arg = argv[i]; | ||||||
|         if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { |         if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { | ||||||
|             printf("Usage: necronda-server [-h] [-c <CONFIG-FILE>]\n" |             printf("Usage: sesimos [-h] [-c <CONFIG-FILE>]\n" | ||||||
|                    "\n" |                    "\n" | ||||||
|                    "Options:\n" |                    "Options:\n" | ||||||
|                    "  -c, --config <CONFIG-FILE>  path to the config file. If not provided, default will be used\n" |                    "  -c, --config <CONFIG-FILE>  path to the config file. If not provided, default will be used\n" | ||||||
| @@ -338,29 +336,23 @@ int main(int argc, const char *argv[]) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FD_ZERO(&socket_fds); |  | ||||||
|     for (int i = 0; i < NUM_SOCKETS; i++) { |     for (int i = 0; i < NUM_SOCKETS; i++) { | ||||||
|         FD_SET(sockets[i], &socket_fds); |         poll_fds[i].fd = sockets[i]; | ||||||
|         if (sockets[i] > max_socket_fd) { |         poll_fds[i].events = POLLIN; | ||||||
|             max_socket_fd = sockets[i]; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fprintf(stderr, "Ready to accept connections\n"); |     fprintf(stderr, "Ready to accept connections\n"); | ||||||
|  |  | ||||||
|     while (active) { |     while (active) { | ||||||
|         timeout.tv_sec = 1; |         ready_sockets_num = poll(poll_fds, NUM_SOCKETS, 1000); | ||||||
|         timeout.tv_usec = 0; |  | ||||||
|         read_socket_fds = socket_fds; |  | ||||||
|         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 poll sockets: %s" CLR_STR "\n", strerror(errno)); | ||||||
|             terminate(); |             terminate(); | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (int i = 0; i < NUM_SOCKETS; i++) { |         for (int i = 0; i < NUM_SOCKETS; i++) { | ||||||
|             if (FD_ISSET(sockets[i], &read_socket_fds)) { |             if (poll_fds[i].revents & POLLIN) { | ||||||
|                 client_fd = accept(sockets[i], (struct sockaddr *) &client_addr, &client_addr_len); |                 client_fd = accept(sockets[i], (struct sockaddr *) &client_addr, &client_addr_len); | ||||||
|                 if (client_fd < 0) { |                 if (client_fd < 0) { | ||||||
|                     fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno)); |                     fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno)); | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								src/server.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/server.h
									
									
									
									
									
								
							| @@ -1,12 +1,12 @@ | |||||||
| /** | /** | ||||||
|  * Necronda Web Server |  * sesimos - secure, simple, modern web server | ||||||
|  * Main executable (header file) |  * Main executable (header file) | ||||||
|  * src/necronda-server.h |  * src/server.h | ||||||
|  * Lorenz Stechauner, 2020-12-03 |  * Lorenz Stechauner, 2020-12-03 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef NECRONDA_SERVER_SERVER_H | #ifndef SESIMOS_SERVER_H | ||||||
| #define NECRONDA_SERVER_SERVER_H | #define SESIMOS_SERVER_H | ||||||
|  |  | ||||||
| #include <sys/time.h> | #include <sys/time.h> | ||||||
| #include <maxminddb.h> | #include <maxminddb.h> | ||||||
| @@ -20,7 +20,6 @@ | |||||||
| #define SERVER_TIMEOUT_INIT 4 | #define SERVER_TIMEOUT_INIT 4 | ||||||
| #define SERVER_TIMEOUT 3600 | #define SERVER_TIMEOUT 3600 | ||||||
|  |  | ||||||
| #define CHUNK_SIZE 8192 |  | ||||||
|  |  | ||||||
| extern int sockets[NUM_SOCKETS]; | extern int sockets[NUM_SOCKETS]; | ||||||
| extern pid_t children[MAX_CHILDREN]; | extern pid_t children[MAX_CHILDREN]; | ||||||
| @@ -31,4 +30,4 @@ extern 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 char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str; | ||||||
| extern struct timeval client_timeout; | extern struct timeval client_timeout; | ||||||
|  |  | ||||||
| #endif //NECRONDA_SERVER_SERVER_H | #endif //SESIMOS_SERVER_H | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user