]> Nishi Git Mirror - tewi.git/commitdiff
vhost works
authorNishi <nishi@nishi.boats>
Fri, 13 Sep 2024 13:36:03 +0000 (13:36 +0000)
committerNishi <nishi@nishi.boats>
Fri, 13 Sep 2024 13:36:03 +0000 (13:36 +0000)
git-svn-id: file:///raid/svn-personal/tewi/trunk@12 8739d7e6-ffea-ec47-b151-bdff447c6205

Common/log.c
Server/config.c
Server/server.c
Server/ssl.c
Server/tw_config.h
Server/tw_ssl.h
example.conf [new file with mode: 0644]

index 5d812a60b02c836332a3f21dbef6dd233159d836..79298c7059040228aa71edb4b0a91797903a4574 100644 (file)
@@ -37,7 +37,8 @@ void cm_log(const char* name, const char* log, ...) {
                        i++;
                        if(log[i] == 's') {
                                char* tmp = result;
-                               result = cm_strcat(tmp, va_arg(args, char*));
+                               char* c = va_arg(args, char*);
+                               result = cm_strcat(tmp, c == NULL ? "(null)" : c);
                                free(tmp);
                        } else if(log[i] == 'd') {
                                int a = va_arg(args, int);
index 83cb2699759ee0d095569721af6b5ba2ad8f5531..c70847a89b23d213e9f56947f717223625864d89 100644 (file)
@@ -6,17 +6,36 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <cm_string.h>
 #include <cm_log.h>
 
 struct tw_config config;
 
+struct tw_config_entry* tw_vhost_match(const char* name, int port) {
+       int i;
+       for(i = 0; i < config.vhost_count; i++) {
+               if(strcmp(config.vhosts[i].name, name) == 0 && config.vhosts[i].port == port) {
+                       return &config.vhosts[i];
+               }
+       }
+       return &config.root;
+}
+
 void tw_config_init(void) {
        int i;
        for(i = 0; i < MAX_PORTS + 1; i++) {
                config.ports[i] = -1;
        }
+       for(i = 0; i < MAX_VHOSTS; i++) {
+               config.vhosts[i].sslkey = NULL;
+               config.vhosts[i].sslcert = NULL;
+       }
+       config.root.sslkey = NULL;
+       config.root.sslcert = NULL;
+       config.vhost_count = 0;
+       gethostname(config.hostname, 1024);
 }
 
 int tw_config_read(const char* path) {
@@ -29,6 +48,7 @@ int tw_config_read(const char* path) {
                char* line = malloc(1);
                line[0] = 0;
                int stop = 0;
+               struct tw_config_entry* current = &config.root;
                char* vhost = NULL;
                while(stop == 0) {
                        int c = fread(cbuf, 1, 1, f);
@@ -47,23 +67,35 @@ int tw_config_read(const char* path) {
                                                }
                                        } else if(cm_strcaseequ(r[0], "BeginVirtualHost")) {
                                                if(vhost != NULL) {
-                                                       cm_log("Config", "Already in virtual host section");
+                                                       cm_log("Config", "Already in virtual host section at line %d", ln);
                                                        stop = 1;
                                                } else {
                                                        if(r[1] == NULL) {
-                                                               cm_log("Config", "Missing virtual host");
+                                                               cm_log("Config", "Missing virtual host at line %d", ln);
                                                                stop = 1;
                                                        } else {
                                                                vhost = cm_strdup(r[1]);
+                                                               current = &config.vhosts[config.vhost_count++];
+                                                               int i;
+                                                               current->name = cm_strdup(vhost);
+                                                               current->port = 80;
+                                                               for(i = 0; vhost[i] != 0; i++) {
+                                                                       if(vhost[i] == ':') {
+                                                                               current->name[i] = 0;
+                                                                               current->port = atoi(current->name + i + 1);
+                                                                               break;
+                                                                       }
+                                                               }
                                                        }
                                                }
                                        } else if(cm_strcaseequ(r[0], "EndVirtualHost")) {
                                                if(vhost == NULL) {
-                                                       cm_log("Config", "Not in virtual host section");
+                                                       cm_log("Config", "Not in virtual host section at line %d", ln);
                                                        stop = 1;
                                                } else {
                                                        free(vhost);
                                                        vhost = NULL;
+                                                       current = &config.root;
                                                }
                                        } else if(cm_strcaseequ(r[0], "Listen") || cm_strcaseequ(r[0], "ListenSSL")) {
                                                for(i = 1; r[i] != NULL; i++) {
@@ -75,6 +107,22 @@ int tw_config_read(const char* path) {
                                                                ;
                                                        config.ports[j] = port;
                                                }
+                                       } else if(cm_strcaseequ(r[0], "SSLKey")) {
+                                               if(r[1] == NULL) {
+                                                       cm_log("Config", "Missing path at line %d", ln);
+                                                       stop = 1;
+                                               } else {
+                                                       if(current->sslkey != NULL) free(current->sslkey);
+                                                       current->sslkey = cm_strdup(r[1]);
+                                               }
+                                       } else if(cm_strcaseequ(r[0], "SSLCertificate")) {
+                                               if(r[1] == NULL) {
+                                                       cm_log("Config", "Missing path at line %d", ln);
+                                                       stop = 1;
+                                               } else {
+                                                       if(current->sslcert != NULL) free(current->sslcert);
+                                                       current->sslcert = cm_strdup(r[1]);
+                                               }
                                        } else {
                                                if(r[0] != NULL) {
                                                        cm_log("Config", "Unknown directive `%s' at line %d", r[0], ln);
index 32b06583bb4f7007195ccababb415abe17e774a7..9d7d3ff5d19cc2b04d0d8f8fb4015eec7a66a0d0 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "tw_server.h"
 
+#include "tw_ssl.h"
 #include "tw_config.h"
 
 #include <unistd.h>
@@ -114,15 +115,27 @@ int tw_server_init(void) {
 #ifdef __MINGW32__
 struct pass_entry {
        int sock;
+       int port;
        bool ssl;
 };
 
 unsigned int WINAPI tw_server_pass(void* ptr) {
        int sock = ((struct pass_entry*)ptr)->sock;
        bool ssl = ((struct pass_entry*)ptr)->ssl;
+       int port = ((struct pass_entry*)ptR)->port;
+       free(ptr);
 #else
-void tw_server_pass(int sock, bool ssl) {
+void tw_server_pass(int sock, bool ssl, int port) {
 #endif
+       SSL_CTX* ctx = NULL;
+       SSL* s = NULL;
+       if(ssl) {
+               ctx = tw_create_ssl_ctx(port);
+               s = SSL_new(ctx);
+               SSL_set_fd(s, sock);
+               if(SSL_accept(s) <= 0) goto cleanup;
+       }
+cleanup:
        close_socket(sock);
 #ifdef __MINGW32__
        _endthreadex(0);
@@ -150,16 +163,18 @@ void tw_server_loop(void) {
                                        SOCKADDR claddr;
                                        int clen = sizeof(claddr);
                                        int sock = accept(sockets[i], (struct sockaddr*)&claddr, &clen);
+                                       cm_log("Server", "New connection accepted");
 #ifdef __MINGW32__
                                        HANDLE thread;
                                        struct pass_entry* e = malloc(sizeof(*e));
                                        e->sock = sock;
                                        e->ssl = config.ports[i] & (1ULL << 32);
+                                       e->port = config.ports[i];
                                        thread = (HANDLE)_beginthreadex(NULL, 0, tw_server_pass, e, 0, NULL);
 #else
                                        pid_t pid = fork();
                                        if(pid == 0) {
-                                               tw_server_pass(sock, config.ports[i] & (1ULL << 32));
+                                               tw_server_pass(sock, config.ports[i] & (1ULL << 32), config.ports[i]);
                                                _exit(0);
                                        } else {
                                                close_socket(sock);
index fc3ce95e70738828865b2399c6f244b99bcf5d14..e5bb8d3481e1e0b6655b1af3d78d472617111cf6 100644 (file)
@@ -1,3 +1,35 @@
 /* $Id$ */
 
 #include "tw_ssl.h"
+
+#include "tw_config.h"
+
+#include <stdio.h>
+
+#include <cm_log.h>
+
+extern struct tw_config config;
+
+int tw_ssl_cert_cb(SSL* ssl, void* arg) {
+       const char* s = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+       if(s != NULL) {
+               cm_log("SSL", "Certificate request for %s", s);
+       } else {
+               s = config.hostname;
+               cm_log("SSL", "Could not get the servername, defaulting to the hostname: %s", s);
+       }
+       struct tw_config_entry* e = tw_vhost_match(s, (uint64_t)arg);
+       if(e != NULL && e->sslkey != NULL && e->sslcert != NULL) {
+               SSL_use_PrivateKey_file(ssl, e->sslkey, SSL_FILETYPE_PEM);
+               SSL_use_certificate_file(ssl, e->sslcert, SSL_FILETYPE_PEM);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+SSL_CTX* tw_create_ssl_ctx(uint64_t port) {
+       SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
+       SSL_CTX_set_cert_cb(ctx, tw_ssl_cert_cb, (void*)port);
+       return ctx;
+}
index d3be0e061dea8bd447fd3e9b365e86feb22db55c..2aa1bb568257bd3e64e959207219f6ff74286f71 100644 (file)
@@ -5,17 +5,27 @@
 
 #include <stdint.h>
 
-/* I don't think you would listen to 1024 ports */
 #define MAX_PORTS 1024
 
-struct tw_config_entry {};
+#define MAX_VHOSTS 1024
+
+struct tw_config_entry {
+       char* name;
+       int port;
+       char* sslkey;
+       char* sslcert;
+};
 
 struct tw_config {
        uint64_t ports[MAX_PORTS + 1]; /* If port & (1 << 32) is non-zero, it is SSL */
+       char hostname[1025];
        struct tw_config_entry root;
+       struct tw_config_entry vhosts[MAX_VHOSTS];
+       int vhost_count;
 };
 
 void tw_config_init(void);
 int tw_config_read(const char* path);
+struct tw_config_entry* tw_vhost_match(const char* name, int port);
 
 #endif
index ce1d2af22181ee7ced94b6b2ec3cb028cdef3dc3..0e2b2462c446f7e7a6c0dc35cb8c1e5f471365b6 100644 (file)
@@ -3,4 +3,8 @@
 #ifndef __TW_SSL_H__
 #define __TW_SSL_H__
 
+#include <openssl/ssl.h>
+
+SSL_CTX* tw_create_ssl_ctx(uint64_t port);
+
 #endif
diff --git a/example.conf b/example.conf
new file mode 100644 (file)
index 0000000..2d9b0a7
--- /dev/null
@@ -0,0 +1,11 @@
+# $Id$
+# This is an example config
+
+Listen 8000 8001 8002 8003 8004
+ListenSSL 8443 8444 8445 8446 8447
+
+SSLKey key.pem
+SSLCertificate cert.pem
+
+BeginVirtualHost nishinbsd-ssd:8443
+EndVirtualHost