mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 04:18:55 +00:00
ssl option for config
This commit is contained in:
parent
aaf97aa645
commit
a9f91af3da
6 changed files with 247 additions and 44 deletions
4
Makefile
4
Makefile
|
@ -8,11 +8,11 @@ BIN_NAME = cfloor
|
|||
OBJS = obj/networking.o obj/linked.o obj/logging.o obj/signals.o obj/headers.o obj/misc.o obj/status.o obj/files.o obj/mime.o obj/cgi.o obj/util.o obj/ssl.o obj/config.o
|
||||
DEPS = $(OBJS:%.o=%.d)
|
||||
|
||||
all: $(BIN_NAME)
|
||||
all: $(BIN_NAME) test
|
||||
|
||||
ssl: CFLAGS += -DSSL_SUPPORT -Icrypto
|
||||
ssl: LDFLAGS += -lcrypto -lssl
|
||||
ssl: obj/ssl.o $(BIN_NAME)
|
||||
ssl: obj/ssl.o $(BIN_NAME) test
|
||||
|
||||
$(BIN_NAME): obj/main.o $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o $@ $^
|
||||
|
|
206
src/config.c
206
src/config.c
|
@ -9,6 +9,10 @@
|
|||
#include "util.h"
|
||||
#include "networking.h"
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
#include "ssl.h"
|
||||
#endif
|
||||
|
||||
#define LENGTH_OF_TOFREE_ARRAY (256)
|
||||
#define MAX_TOKEN_LENGTH (128)
|
||||
|
||||
|
@ -44,22 +48,28 @@ struct config* config_parse(FILE* file) {
|
|||
|
||||
|
||||
#define BIND (0)
|
||||
#define BIND_VALUE (1)
|
||||
#define BIND_BRACKETS_OPEN (2)
|
||||
#define BIND_CONTENT (4)
|
||||
#define SITE_BRACKETS_OPEN (5)
|
||||
#define SITE_CONTENT (7)
|
||||
#define SITE_HOST_EQUALS (8)
|
||||
#define SITE_HOST_VALUE (9)
|
||||
#define SITE_ROOT_EQUALS (10)
|
||||
#define SITE_ROOT_VALUE (11)
|
||||
#define HANDLER_VALUE (12)
|
||||
#define HANDLER_BRACKETS_OPEN (13)
|
||||
#define HANDLER_CONTENT (15)
|
||||
#define TYPE_EQUALS (16)
|
||||
#define TYPE_VALUE (17)
|
||||
#define INDEX_EQUALS (18)
|
||||
#define INDEX_VALUE (19)
|
||||
#define BIND_VALUE (10)
|
||||
#define BIND_BRACKETS_OPEN (11)
|
||||
#define BIND_CONTENT (12)
|
||||
#define SSL_BRACKETS_OPEN (130)
|
||||
#define SSL_CONTENT (131)
|
||||
#define SSL_KEY_EQUALS (132)
|
||||
#define SSL_KEY_VALUE (133)
|
||||
#define SSL_CERT_EQUALS (134)
|
||||
#define SSL_CERT_VALUE (135)
|
||||
#define SITE_BRACKETS_OPEN (140)
|
||||
#define SITE_CONTENT (141)
|
||||
#define SITE_HOST_EQUALS (142)
|
||||
#define SITE_HOST_VALUE (143)
|
||||
#define SITE_ROOT_EQUALS (144)
|
||||
#define SITE_ROOT_VALUE (145)
|
||||
#define HANDLER_VALUE (1460)
|
||||
#define HANDLER_BRACKETS_OPEN (1461)
|
||||
#define HANDLER_CONTENT (1462)
|
||||
#define TYPE_EQUALS (1463)
|
||||
#define TYPE_VALUE (1464)
|
||||
#define INDEX_EQUALS (1465)
|
||||
#define INDEX_VALUE (1466)
|
||||
int state = BIND;
|
||||
|
||||
struct config_bind* currentBind = NULL;
|
||||
|
@ -83,6 +93,9 @@ struct config* config_parse(FILE* file) {
|
|||
|
||||
currentToken[currentTokenLength] = '\0';
|
||||
|
||||
char* tmp;
|
||||
char** tmpArray;
|
||||
|
||||
switch(state) {
|
||||
case BIND:
|
||||
if (strcmp(currentToken, "bind") != 0) {
|
||||
|
@ -100,15 +113,15 @@ struct config* config_parse(FILE* file) {
|
|||
replaceOrAdd(toFree, &toFreeLength, NULL, currentBind);
|
||||
|
||||
config->nrBinds++;
|
||||
struct config_bind** tmp = realloc(config->binds, config->nrBinds * sizeof(struct config_bind*));
|
||||
if (tmp == NULL) {
|
||||
struct config_bind** tmpBind = realloc(config->binds, config->nrBinds * sizeof(struct config_bind*));
|
||||
if (tmpBind == NULL) {
|
||||
error("config: couldn't reallocate for bind array: %s", strerror(errno));
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
replaceOrAdd(toFree, &toFreeLength, config->binds, tmp);
|
||||
config->binds = tmp;
|
||||
replaceOrAdd(toFree, &toFreeLength, config->binds, tmpBind);
|
||||
config->binds = tmpBind;
|
||||
config->binds[config->nrBinds - 1] = currentBind;
|
||||
|
||||
currentBind->nrSites = 0;
|
||||
|
@ -116,6 +129,10 @@ struct config* config_parse(FILE* file) {
|
|||
currentBind->addr = NULL;
|
||||
currentBind->port = NULL;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
currentBind->ssl = NULL;
|
||||
#endif
|
||||
|
||||
state = BIND_VALUE;
|
||||
|
||||
break;
|
||||
|
@ -196,12 +213,103 @@ struct config* config_parse(FILE* file) {
|
|||
state = SITE_BRACKETS_OPEN;
|
||||
} else if (strcmp(currentToken, "}") == 0) {
|
||||
state = BIND;
|
||||
} else if (strcmp(currentToken, "ssl") == 0) {
|
||||
#ifdef SSL_SUPPORT
|
||||
if (currentBind->ssl != NULL) {
|
||||
error("config: ssl settings for this bind already defined; line %d", currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
currentBind->ssl = malloc(sizeof(struct ssl_settings));
|
||||
if (currentBind->ssl == NULL) {
|
||||
error("config: couldn't allocate for ssl settings: %s", strerror(errno));
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, currentBind->ssl);
|
||||
|
||||
currentBind->ssl->privateKey = NULL;
|
||||
currentBind->ssl->certificate = NULL;
|
||||
|
||||
state = SSL_BRACKETS_OPEN;
|
||||
#else
|
||||
error("config: not compiled with ssl support");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
#endif
|
||||
} else {
|
||||
error("config: Unknown property '%s' on line %d.", currentToken, currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#ifdef SSL_SUPPORT
|
||||
case SSL_BRACKETS_OPEN:
|
||||
if (strcmp(currentToken, "{") != 0) {
|
||||
error("config: Unexpected token '%s' on line %d. '{' expected", currentToken, currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = SSL_CONTENT;
|
||||
break;
|
||||
case SSL_CONTENT:
|
||||
if (strcmp(currentToken, "key") == 0) {
|
||||
state = SSL_KEY_EQUALS;
|
||||
} else if (strcmp(currentToken, "cert") == 0) {
|
||||
state = SSL_CERT_EQUALS;
|
||||
} else if (strcmp(currentToken, "}") == 0) {
|
||||
state = BIND_CONTENT;
|
||||
} else {
|
||||
error("config: Unknown property '%s' on line %d.", currentToken, currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case SSL_KEY_EQUALS:
|
||||
if (strcmp(currentToken, "=") != 0) {
|
||||
error("config: Unexpected token '%s' on line %d. '=' expected", currentToken, currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
state = SSL_KEY_VALUE;
|
||||
break;
|
||||
case SSL_KEY_VALUE: ;
|
||||
tmp = strclone(currentToken);
|
||||
if (tmp == NULL) {
|
||||
error("config: error cloning ssl key string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, tmp);
|
||||
|
||||
currentBind->ssl->privateKey = tmp;
|
||||
|
||||
state = SSL_CONTENT;
|
||||
break;
|
||||
case SSL_CERT_EQUALS:
|
||||
if (strcmp(currentToken, "=") != 0) {
|
||||
error("config: Unexpected token '%s' on line %d. '=' expected", currentToken, currentLine);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
state = SSL_CERT_VALUE;
|
||||
break;
|
||||
case SSL_CERT_VALUE: ;
|
||||
tmp = strclone(currentToken);
|
||||
if (tmp == NULL) {
|
||||
error("config: error cloning ssl cert string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, tmp);
|
||||
|
||||
currentBind->ssl->certificate = tmp;
|
||||
|
||||
state = SSL_CONTENT;
|
||||
break;
|
||||
#endif
|
||||
case SITE_BRACKETS_OPEN:
|
||||
if (strcmp(currentToken, "{") != 0) {
|
||||
error("config: Unexpected token '%s' on line %d. '{' expected", currentToken, currentLine);
|
||||
|
@ -260,9 +368,9 @@ struct config* config_parse(FILE* file) {
|
|||
}
|
||||
state = SITE_HOST_VALUE;
|
||||
break;
|
||||
case SITE_HOST_VALUE: ;
|
||||
char** tmpArray = realloc(currentSite->hostnames, ++currentSite->nrHostnames * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
case SITE_HOST_VALUE:
|
||||
tmpArray = realloc(currentSite->hostnames, ++currentSite->nrHostnames * sizeof(char*));
|
||||
if (tmpArray == NULL) {
|
||||
error("config: error allocating hostname array");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
|
@ -270,15 +378,15 @@ struct config* config_parse(FILE* file) {
|
|||
replaceOrAdd(toFree, &toFreeLength, currentSite->hostnames, tmpArray);
|
||||
currentSite->hostnames = tmpArray;
|
||||
|
||||
char* clone = strclone(currentToken);
|
||||
if (clone == NULL) {
|
||||
tmp = strclone(currentToken);
|
||||
if (tmp == NULL) {
|
||||
error("config: error cloning hostname string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, clone);
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, tmp);
|
||||
|
||||
currentSite->hostnames[currentSite->nrHostnames - 1] = clone;
|
||||
currentSite->hostnames[currentSite->nrHostnames - 1] = tmp;
|
||||
|
||||
state = SITE_CONTENT;
|
||||
break;
|
||||
|
@ -291,21 +399,21 @@ struct config* config_parse(FILE* file) {
|
|||
state = SITE_ROOT_VALUE;
|
||||
break;
|
||||
case SITE_ROOT_VALUE:
|
||||
clone = strclone(currentToken);
|
||||
if (clone == NULL) {
|
||||
tmp = strclone(currentToken);
|
||||
if (tmp == NULL) {
|
||||
error("config: error cloning document root string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, clone);
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, tmp);
|
||||
|
||||
currentSite->documentRoot = clone;
|
||||
currentSite->documentRoot = tmp;
|
||||
|
||||
state = SITE_CONTENT;
|
||||
break;
|
||||
case HANDLER_VALUE:
|
||||
currentHandler->dir = strclone(currentToken);
|
||||
if (clone == NULL) {
|
||||
if (currentHandler->dir == NULL) {
|
||||
error("config: error cloning handle directory string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
|
@ -374,7 +482,7 @@ struct config* config_parse(FILE* file) {
|
|||
struct fileSettings* settings = &(currentHandler->settings.fileSettings);
|
||||
|
||||
tmpArray = realloc(settings->indexfiles.files, ++(settings->indexfiles.number) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
if (tmpArray == NULL) {
|
||||
error("config: error allocating hostname array");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
|
@ -382,15 +490,15 @@ struct config* config_parse(FILE* file) {
|
|||
replaceOrAdd(toFree, &toFreeLength, settings->indexfiles.files, tmpArray);
|
||||
settings->indexfiles.files = tmpArray;
|
||||
|
||||
clone = strclone(currentToken);
|
||||
if (clone == NULL) {
|
||||
tmp = strclone(currentToken);
|
||||
if (tmp == NULL) {
|
||||
error("config: error cloning hostname string");
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, clone);
|
||||
replaceOrAdd(toFree, &toFreeLength, NULL, tmp);
|
||||
|
||||
settings->indexfiles.files[settings->indexfiles.number - 1] = clone;
|
||||
settings->indexfiles.files[settings->indexfiles.number - 1] = tmp;
|
||||
|
||||
state = HANDLER_CONTENT;
|
||||
break;
|
||||
|
@ -416,6 +524,22 @@ struct config* config_parse(FILE* file) {
|
|||
|
||||
for (int i = 0; i < config->nrBinds; i++) {
|
||||
currentBind = config->binds[i];
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (currentBind->ssl != NULL) {
|
||||
if (currentBind->ssl->privateKey == NULL) {
|
||||
error("config: ssl private key missing for %s:%s", currentBind->addr, currentBind->port);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
if (currentBind->ssl->certificate == NULL) {
|
||||
error("config: ssl certificate missing for %s:%s", currentBind->addr, currentBind->port);
|
||||
freeEverything(toFree, toFreeLength);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int j = 0; j < currentBind->nrSites; j++) {
|
||||
currentSite = currentBind->sites[j];
|
||||
|
||||
|
@ -478,6 +602,14 @@ void config_destroy(struct config* config) {
|
|||
free(currentBind->addr);
|
||||
free(currentBind->port);
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (currentBind->ssl != NULL) {
|
||||
free(currentBind->ssl->privateKey);
|
||||
free(currentBind->ssl->certificate);
|
||||
free(currentBind->ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int j = 0; j < currentBind->nrSites; j++) {
|
||||
currentSite = currentBind->sites[j];
|
||||
|
||||
|
|
13
src/config.h
13
src/config.h
|
@ -8,11 +8,20 @@
|
|||
#include "files.h"
|
||||
#include "cgi.h"
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
#include "ssl.h"
|
||||
#endif
|
||||
|
||||
struct config {
|
||||
int nrBinds;
|
||||
struct config_bind {
|
||||
char* addr;
|
||||
char* port;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
struct ssl_settings* ssl;
|
||||
#endif
|
||||
|
||||
int nrSites;
|
||||
struct config_site {
|
||||
int nrHostnames;
|
||||
|
@ -36,6 +45,10 @@ struct config {
|
|||
config format
|
||||
|
||||
bind [addr]:[port] {
|
||||
ssl {
|
||||
key = file
|
||||
cert = certfile
|
||||
}
|
||||
site {
|
||||
hostname|alias = "[host]"
|
||||
root = "/"
|
||||
|
|
|
@ -15,8 +15,8 @@ struct ssl_connection {
|
|||
};
|
||||
|
||||
struct ssl_settings {
|
||||
const char* privateKey;
|
||||
const char* certificate;
|
||||
char* privateKey;
|
||||
char* certificate;
|
||||
struct {
|
||||
SSL_CTX* ctx;
|
||||
} _private;
|
||||
|
|
40
src/test.c
40
src/test.c
|
@ -238,10 +238,24 @@ void testHeaders() {
|
|||
}
|
||||
|
||||
void testConfig() {
|
||||
struct config* config = config_parse(fopen("test.conf", "r"));
|
||||
FILE* file;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
file = fopen("test-with-ssl.conf", "r");
|
||||
#else
|
||||
file = fopen("test.conf", "r");
|
||||
#endif
|
||||
|
||||
struct config* config = config_parse(file);
|
||||
|
||||
checkNull(config, "null check");
|
||||
checkInt(config->nrBinds, 1, "bind no check");
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
checkInt(config->nrBinds, 2, "bind no check");
|
||||
#else
|
||||
checkInt(config->nrBinds, 1, "bind no check");
|
||||
#endif
|
||||
|
||||
checkString(config->binds[0]->addr, "0.0.0.0", "bind addr check");
|
||||
checkString(config->binds[0]->port, "80", "bind port check");
|
||||
checkInt(config->binds[0]->nrSites, 1, "site no check");
|
||||
|
@ -256,7 +270,27 @@ void testConfig() {
|
|||
checkInt(config->binds[0]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.number, 1, "handler settings index no");
|
||||
checkString(config->binds[0]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.files[0], "index.html", "handler settings index check");
|
||||
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
checkString(config->binds[1]->addr, "0.0.0.0", "bind addr check");
|
||||
checkString(config->binds[1]->port, "443", "bind port check");
|
||||
checkNull(config->binds[1]->ssl, "ssl null check");
|
||||
checkString(config->binds[1]->ssl->privateKey, "ssl.key", "ssl key check");
|
||||
checkString(config->binds[1]->ssl->certificate, "ssl.crt", "ssl cert check");
|
||||
checkInt(config->binds[1]->nrSites, 1, "site no check");
|
||||
checkInt(config->binds[1]->sites[0]->nrHostnames, 1, "site hostname no check");
|
||||
checkString(config->binds[1]->sites[0]->hostnames[0], "example.com", "site hostname check");
|
||||
checkString(config->binds[1]->sites[0]->documentRoot, "/var/www", "site document root check");
|
||||
checkInt(config->binds[1]->sites[0]->nrHandlers, 1, "handler no check");
|
||||
checkString(config->binds[1]->sites[0]->handlers[0]->dir, "/", "handler dir check");
|
||||
checkInt(config->binds[1]->sites[0]->handlers[0]->type, FILE_HANDLER_NO, "handler type no check");
|
||||
checkVoid(config->binds[1]->sites[0]->handlers[0]->handler, &fileHandler, "handler ptr check");
|
||||
checkString(config->binds[1]->sites[0]->handlers[0]->settings.fileSettings.documentRoot, "/var/www", "handler settings root check");
|
||||
checkInt(config->binds[1]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.number, 1, "handler settings index no");
|
||||
checkString(config->binds[1]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.files[0], "index.html", "handler settings index check");
|
||||
#endif
|
||||
|
||||
fclose(file);
|
||||
|
||||
config_destroy(config);
|
||||
}
|
||||
|
||||
|
|
24
test-with-ssl.conf
Normal file
24
test-with-ssl.conf
Normal file
|
@ -0,0 +1,24 @@
|
|||
bind 0.0.0.0:80 {
|
||||
site {
|
||||
hostname = example.com
|
||||
root = /var/www
|
||||
handler / {
|
||||
type = file
|
||||
index = index.html
|
||||
}
|
||||
}
|
||||
}
|
||||
bind 0.0.0.0:443 {
|
||||
ssl {
|
||||
key = ssl.key
|
||||
cert = ssl.crt
|
||||
}
|
||||
site {
|
||||
hostname = example.com
|
||||
root = /var/www
|
||||
handler / {
|
||||
type = file
|
||||
index = index.html
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue