summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@heap.zone>2019-03-03 14:27:21 +0100
committerJonathan Schleifer <js@heap.zone>2019-03-03 14:27:21 +0100
commit609dacb6b006fd70f3b1af32e85d942db683221a (patch)
treeddb46a76b5cb7ec7f343202cca5d8681bd0435b6
parent237b373cb242ece3e583afc56ab2f7ba93eea879 (diff)
Add support for TLS
-rw-r--r--.gitignore2
-rw-r--r--ConfigParser.h19
-rw-r--r--ConfigParser.m59
-rw-r--r--Makefile4
-rw-r--r--ObjWebServer.m41
-rw-r--r--ObjWebServer.xml10
6 files changed, 96 insertions, 39 deletions
diff --git a/.gitignore b/.gitignore
index 62d289d..e134fad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@
*~
ObjWebServer
htdocs
+localhost.crt
+localhost.key
modules
diff --git a/ConfigParser.h b/ConfigParser.h
index 7251578..b5bc95a 100644
--- a/ConfigParser.h
+++ b/ConfigParser.h
@@ -18,15 +18,26 @@
#import <ObjFW/ObjFW.h>
+@interface ListenConfig: OFObject
+{
+ OFString *_host;
+ uint16_t _port;
+ OFString *_TLSCertificateFile, *_TLSKeyFile;
+}
+
+@property (copy, nonatomic) OFString *host;
+@property (nonatomic) uint16_t port;
+@property (copy, nonatomic) OFString *TLSCertificateFile, *TLSKeyFile;
+@end
+
@interface ConfigParser: OFObject
{
- OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFNumber *) *)
- *_listenHosts;
+ OFArray OF_GENERIC(ListenConfig *) *_listenConfigs;
OFArray OF_GENERIC(OFXMLElement *) *_modules;
}
-@property (readonly, nonatomic) OFArray OF_GENERIC(
- OFPair OF_GENERIC(OFString *, OFNumber *) *) *listenHosts;
+@property (readonly, nonatomic) OFArray OF_GENERIC(ListenConfig *)
+ *listenConfigs;
@property (readonly, nonatomic) OFArray OF_GENERIC(OFXMLElement *) *modules;
- (instancetype)init OF_UNAVAILABLE;
diff --git a/ConfigParser.m b/ConfigParser.m
index ff9f46e..53346ad 100644
--- a/ConfigParser.m
+++ b/ConfigParser.m
@@ -25,8 +25,23 @@
- (void)_invalidConfig: (OFString *)message;
@end
+@implementation ListenConfig
+@synthesize host = _host, port = _port;
+@synthesize TLSCertificateFile = _TLSCertificateFile;
+@synthesize TLSKeyFile = _TLSKeyFile;
+
+- (void)dealloc
+{
+ [_host release];
+ [_TLSCertificateFile release];
+ [_TLSKeyFile release];
+
+ [super dealloc];
+}
+@end
+
@implementation ConfigParser
-@synthesize listenHosts = _listenHosts, modules = _modules;
+@synthesize listenConfigs = _listenConfigs, modules = _modules;
- (instancetype)init
{
@@ -55,7 +70,7 @@
- (void)dealloc
{
- [_listenHosts release];
+ [_listenConfigs release];
[super dealloc];
}
@@ -76,15 +91,17 @@
- (void)_parseListens: (OFArray OF_GENERIC(OFXMLElement *) *)elements
{
- OFMutableArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFNumber *) *)
- *listenHosts = [OFMutableArray array];
+ OFMutableArray OF_GENERIC(ListenConfig *) *listenConfigs =
+ [OFMutableArray array];
for (OFXMLElement *element in elements) {
+ ListenConfig *listenConfig =
+ [[[ListenConfig alloc] init] autorelease];
OFString *host = [[element
attributeForName: @"host"] stringValue];
OFString *portString = [[element
attributeForName: @"port"] stringValue];
- OFNumber *port;
+ OFXMLElement *TLS = [element elementForName: @"tls"];
if (host == nil)
[self _invalidConfig:
@@ -93,22 +110,40 @@
[self _invalidConfig:
@"<listen/> is missing port attribute"];
+ [listenConfig setHost: host];
+
@try {
- intmax_t tmp = [portString decimalValue];
- if (tmp < 0 || tmp > 65535)
+ intmax_t port = [portString decimalValue];
+ if (port < 0 || port > 65535)
@throw [OFInvalidFormatException exception];
- port = [OFNumber numberWithUInt16: (uint16_t)tmp];
+ [listenConfig setPort: port];
} @catch (OFInvalidFormatException *e) {
[self _invalidConfig: @"<listen/> has invalid port"];
}
- [listenHosts addObject: [OFPair pairWithFirstObject: host
- secondObject: port]];
+ if (TLS != nil) {
+ OFString *certificateFile =
+ [[TLS attributeForName: @"cert"] stringValue];
+ OFString *keyFile =
+ [[TLS attributeForName: @"key"] stringValue];
+
+ if (certificateFile == nil)
+ [self _invalidConfig:
+ @"<tls/> has no cert attribute"];
+ if (keyFile == nil)
+ [self _invalidConfig:
+ @"<tls/> has no key attribute"];
+
+ [listenConfig setTLSCertificateFile: certificateFile];
+ [listenConfig setTLSKeyFile: keyFile];
+ }
+
+ [listenConfigs addObject: listenConfig];
}
- [listenHosts makeImmutable];
- _listenHosts = [listenHosts copy];
+ [listenConfigs makeImmutable];
+ _listenConfigs = [listenConfigs copy];
}
- (void)_parseModules: (OFArray OF_GENERIC(OFXMLElement *) *)elements
diff --git a/Makefile b/Makefile
index 0535ade..825f85b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
all:
- @objfw-compile --package ObjOpenSSL -o ObjWebServer \
- ConfigParser.m \
+ @objfw-compile -Werror --package ObjOpenSSL -o ObjWebServer \
+ ConfigParser.m \
ObjWebServer.m
@mkdir -p modules
@objfw-compile --plugin -o modules/static StaticModule.m
diff --git a/ObjWebServer.m b/ObjWebServer.m
index 9c0dbea..9bad080 100644
--- a/ObjWebServer.m
+++ b/ObjWebServer.m
@@ -32,8 +32,7 @@
- (OFPlugin <Module> *)loadModuleAtPath: (OFString *)path
withConfig: (OFXMLElement *)config;
-- (void)startWebserverOnHost: (OFString *)host
- port: (uint16_t)port;
+- (void)startWebserverWithListenConfig: (ListenConfig *)listenConfig;
@end
OF_APPLICATION_DELEGATE(ObjWebServer)
@@ -62,14 +61,8 @@ OF_APPLICATION_DELEGATE(ObjWebServer)
[modules makeImmutable];
_modules = [modules copy];
- for (OFPair OF_GENERIC(OFString *, OFNumber *) *listenHost in
- [_config listenHosts]) {
- OFString *host = [listenHost firstObject];
- OFNumber *port = [listenHost secondObject];
-
- [self startWebserverOnHost: host
- port: [port uInt16Value]];
- }
+ for (ListenConfig *listenConfig in [_config listenConfigs])
+ [self startWebserverWithListenConfig: listenConfig];
}
- (OFPlugin <Module> *)loadModuleAtPath: (OFString *)path
@@ -85,16 +78,24 @@ OF_APPLICATION_DELEGATE(ObjWebServer)
return module;
}
-- (void)startWebserverOnHost: (OFString *)host
- port: (uint16_t)port
+- (void)startWebserverWithListenConfig: (ListenConfig *)listenConfig
{
OFHTTPServer *server = [OFHTTPServer server];
- [server setHost: host];
- [server setPort: port];
- [server setDelegate: self];
+ [server setHost: [listenConfig host]];
+ [server setPort: [listenConfig port]];
+
+ if ([listenConfig TLSCertificateFile] != nil &&
+ [listenConfig TLSKeyFile] != nil) {
+ [server setUsesTLS: true];
+ [server setCertificateFile: [listenConfig TLSCertificateFile]];
+ [server setPrivateKeyFile: [listenConfig TLSKeyFile]];
+ }
+
[server setNumberOfThreads: [OFSystemInfo numberOfCPUs] + 1];
+ [server setDelegate: self];
- of_log(@"Starting server on host %@ port %" PRIu16, host, port);
+ of_log(@"Starting server on host %@ port %" PRIu16,
+ [listenConfig host], [listenConfig port]);
[server start];
}
@@ -115,4 +116,12 @@ OF_APPLICATION_DELEGATE(ObjWebServer)
response: response])
return;
}
+
+- (bool)server: (OFHTTPServer *)server
+ didReceiveExceptionOnListeningSocket: (id)exception
+{
+ of_log(@"Exception on listening socket: %@", exception);
+
+ return true;
+}
@end
diff --git a/ObjWebServer.xml b/ObjWebServer.xml
index 9001f90..c416070 100644
--- a/ObjWebServer.xml
+++ b/ObjWebServer.xml
@@ -1,10 +1,10 @@
<ObjWebServer>
- <listen host='0.0.0.0' port='1234'>
- <tls cert='test.crt' key='test.key'/>
- </listen>
- <listen host='::' port='1234'>
- <tls cert='test.crt' key='test.key'/>
+ <listen host='127.0.0.1' port='1234'>
+ <tls cert='localhost.crt' key='localhost.key'/>
</listen>
+ <!--listen host='::1' port='1234'>
+ <tls cert='localhost.crt' key='localhost.key'/>
+ </listen-->
<module prefix='/' path='modules/static'>
<root>htdocs</root>
<mime-type extension='' type='application/octet-stream'/>