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);
#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) {
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);
}
} 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++) {
;
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);
#include "tw_server.h"
+#include "tw_ssl.h"
#include "tw_config.h"
#include <unistd.h>
#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);
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);
/* $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;
+}
#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
#ifndef __TW_SSL_H__
#define __TW_SSL_H__
+#include <openssl/ssl.h>
+
+SSL_CTX* tw_create_ssl_ctx(uint64_t port);
+
#endif
--- /dev/null
+# $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