From 47f4dd4fdb82cabb26048bffc1e09d8bc63afc1d Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Mon, 28 Mar 2011 22:05:36 +0200 Subject: [PATCH] Initial import. --- Makefile | 2 + SSLSocket.h | 14 ++++ SSLSocket.m | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 Makefile create mode 100644 SSLSocket.h create mode 100644 SSLSocket.m diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4b430ce --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + objfw-compile --lib 0.0 -o objopenssl *.m -lssl -lcrypto -lz -g -Wall diff --git a/SSLSocket.h b/SSLSocket.h new file mode 100644 index 0000000..ee3c018 --- /dev/null +++ b/SSLSocket.h @@ -0,0 +1,14 @@ +#include + +#import + +@interface SSLSocket: OFTCPSocket +{ + SSL_CTX *ctx; + SSL *ssl; + BOOL handsShaken; +} + +/* Change the return type */ +- (SSLSocket*)accept; +@end diff --git a/SSLSocket.m b/SSLSocket.m new file mode 100644 index 0000000..33ad704 --- /dev/null +++ b/SSLSocket.m @@ -0,0 +1,191 @@ +#include + +#import + +#import "SSLSocket.h" + +#import +#import +#import +#import +#import +#import +#import + +#ifndef INVALID_SOCKET +# define INVALID_SOCKET -1 +#endif + +@implementation SSLSocket ++ (void)load +{ + of_http_request_tls_socket_class = self; +} + ++ (void)initialize +{ + if (self == [SSLSocket class]) + SSL_library_init(); +} + +- init +{ + self = [super init]; + + @try { + if ((ctx = SSL_CTX_new(SSLv23_method())) == NULL) + @throw [OFInitializationFailedException + newWithClass: isa]; + +// if ((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & +// SSL_OP_NO_SSLv2) == 0) +// @throw [OFInitializationFailedException +// newWithClass: isa]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + SSL_CTX *ctx_ = ctx; + SSL *ssl_ = ssl; + + [super dealloc]; + + if (ssl_ != NULL) + SSL_free(ssl_); + if (ctx_ != NULL) + SSL_CTX_free(ctx_); +} + +- (void)connectToHost: (OFString*)host + onPort: (uint16_t)port +{ + [super connectToHost: host + onPort: port]; + + if ((ssl = SSL_new(ctx)) == NULL || !SSL_set_fd(ssl, sock)) { + [self close]; + @throw [OFConnectionFailedException newWithClass: isa + socket: self + host: host + port: port]; + } + + SSL_set_connect_state(ssl); + + if (SSL_connect(ssl) != 1) { + [self close]; + @throw [OFConnectionFailedException newWithClass: isa + socket: self + host: host + port: port]; + } +} + +- (SSLSocket*)accept +{ + SSLSocket *newsock = (SSLSocket*)[super accept]; + + if ((ssl = SSL_new(ctx)) == NULL || !SSL_set_fd(ssl, sock)) { + [self close]; + @throw [OFAcceptFailedException newWithClass: isa + socket: self]; + } + + SSL_set_accept_state(ssl); + + if (SSL_connect(ssl) != 1) { + [self close]; + @throw [OFAcceptFailedException newWithClass: isa + socket: self]; + } + + return newsock; +} + +- (void)close +{ + SSL_shutdown(ssl); + + [super close]; +} + +- (size_t)_readNBytes: (size_t)size + intoBuffer: (char*)buf +{ + ssize_t ret; + + if (size > INT_MAX) + @throw [OFOutOfRangeException newWithClass: isa]; + + if (sock == INVALID_SOCKET) + @throw [OFNotConnectedException newWithClass: isa + socket: self]; + + if (eos) { + OFReadFailedException *e; + + e = [OFReadFailedException newWithClass: isa + stream: self + requestedSize: size]; +#ifndef _WIN32 + e->errNo = ENOTCONN; +#else + e->errNo = WSAENOTCONN; +#endif + + @throw e; + } + + if ((ret = SSL_read(ssl, buf, (int)size)) < 0) + @throw [OFReadFailedException newWithClass: isa + stream: self + requestedSize: size]; + + if (ret == 0) + eos = YES; + + return ret; +} + +- (size_t)_writeNBytes: (size_t)size + fromBuffer: (const char*)buf +{ + ssize_t ret; + + if (size > INT_MAX) + @throw [OFOutOfRangeException newWithClass: isa]; + + if (sock == INVALID_SOCKET) + @throw [OFNotConnectedException newWithClass: isa + socket: self]; + + if (eos) { + OFWriteFailedException *e; + + e = [OFWriteFailedException newWithClass: isa + stream: self + requestedSize: size]; + +#ifndef _WIN32 + e->errNo = ENOTCONN; +#else + e->errNo = WSAENOTCONN; +#endif + + @throw e; + } + + if ((ret = SSL_write(ssl, buf, (int)size)) < 1) + @throw [OFWriteFailedException newWithClass: isa + stream: self + requestedSize: size]; + + return ret; +} +@end