mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 09:41:15 +00:00
Add support for server side ssl connections.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18055 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ccf66c5058
commit
61cf6fa9e9
4 changed files with 184 additions and 37 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2003-11-05 18:26 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* SSL/GSSSLHandle.m: Add support for server end handles.
|
||||||
|
* Source/NSFileHandle.m: New -sslAccept method for servers.
|
||||||
|
|
||||||
2003-11-05 14:49 Alexander Malmberg <alexander@malmberg.org>
|
2003-11-05 14:49 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/NSSerializer.m (serializeToInfo): Only save a string as
|
* Source/NSSerializer.m (serializeToInfo): Only save a string as
|
||||||
|
|
|
@ -148,14 +148,19 @@ GS_EXPORT NSString * const NSFileHandleOperationException;
|
||||||
/*
|
/*
|
||||||
* Where OpenSSL is available, you can use the subclass returned by +sslClass
|
* Where OpenSSL is available, you can use the subclass returned by +sslClass
|
||||||
* to handle SSL connections.
|
* to handle SSL connections.
|
||||||
|
* The -sslAccept method is used to do SSL handlshake and start an
|
||||||
|
* encrypted session on a channel where the connection was initiated
|
||||||
|
* from the far end.
|
||||||
* The -sslConnect method is used to do SSL handlshake and start an
|
* The -sslConnect method is used to do SSL handlshake and start an
|
||||||
* encrypted session.
|
* encrypted session on a channel where the connection was initiated
|
||||||
|
* from the near end..
|
||||||
* The -sslDisconnect method is used to end the encrypted session.
|
* The -sslDisconnect method is used to end the encrypted session.
|
||||||
* The -sslSetCertificate:privateKey:PEMpasswd: method is used to
|
* The -sslSetCertificate:privateKey:PEMpasswd: method is used to
|
||||||
* establish a client certificate before starting an encrypted session.
|
* establish a client certificate before starting an encrypted session.
|
||||||
*/
|
*/
|
||||||
@interface NSFileHandle (GNUstepOpenSSL)
|
@interface NSFileHandle (GNUstepOpenSSL)
|
||||||
+ (Class) sslClass;
|
+ (Class) sslClass;
|
||||||
|
- (BOOL) sslAccept;
|
||||||
- (BOOL) sslConnect;
|
- (BOOL) sslConnect;
|
||||||
- (void) sslDisconnect;
|
- (void) sslDisconnect;
|
||||||
- (void) sslSetCertificate: (NSString*)certFile
|
- (void) sslSetCertificate: (NSString*)certFile
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
while it is an Objective-C reserved keyword. */
|
while it is an Objective-C reserved keyword. */
|
||||||
#define id id_x_
|
#define id id_x_
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
#undef id
|
#undef id
|
||||||
|
|
||||||
#include <GSConfig.h>
|
#include <GSConfig.h>
|
||||||
|
@ -81,12 +83,53 @@
|
||||||
#endif
|
#endif
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
static NSString*
|
||||||
|
sslError(int err, int e)
|
||||||
|
{
|
||||||
|
NSString *str;
|
||||||
|
|
||||||
|
SSL_load_error_strings();
|
||||||
|
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case SSL_ERROR_NONE:
|
||||||
|
str = @"No error: really helpful";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
str = @"Zero Return error";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
str = @"Want Read Error";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
str = @"Want Write Error";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
str = @"Want X509 Lookup Error";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
str = [NSString stringWithFormat: @"Syscall error %d - %s",
|
||||||
|
e, GSLastErrorStr(e)];
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
str = @"SSL Error: really helpful";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = @"Standard system error: really helpful";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@interface GSSSLHandle : GSFileHandle <GCFinalization>
|
@interface GSSSLHandle : GSFileHandle <GCFinalization>
|
||||||
{
|
{
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
BOOL connected;
|
BOOL connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) sslAccept;
|
||||||
- (BOOL) sslConnect;
|
- (BOOL) sslConnect;
|
||||||
- (void) sslDisconnect;
|
- (void) sslDisconnect;
|
||||||
- (void) sslSetCertificate: (NSString*)certFile
|
- (void) sslSetCertificate: (NSString*)certFile
|
||||||
|
@ -100,6 +143,18 @@
|
||||||
if (self == [GSSSLHandle class])
|
if (self == [GSSSLHandle class])
|
||||||
{
|
{
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no /dev/urandom for ssl to use, we must seed the
|
||||||
|
* random number generator ourselves.
|
||||||
|
*/
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath: @"/dev/urandom"])
|
||||||
|
{
|
||||||
|
const char *inf;
|
||||||
|
|
||||||
|
inf = [[[NSProcessInfo processInfo] globallyUniqueString] UTF8String];
|
||||||
|
RAND_seed(inf, strlen(inf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +179,89 @@
|
||||||
return [super read: buf length: len];
|
return [super read: buf length: len];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) sslAccept
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int err;
|
||||||
|
NSRunLoop *loop;
|
||||||
|
|
||||||
|
if (connected == YES)
|
||||||
|
{
|
||||||
|
return YES; /* Already connected. */
|
||||||
|
}
|
||||||
|
if (isStandardFile == YES)
|
||||||
|
{
|
||||||
|
NSLog(@"Attempt to make ssl connection to a standard file");
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure we have a context and handle to connect with.
|
||||||
|
*/
|
||||||
|
if (ctx == 0)
|
||||||
|
{
|
||||||
|
ctx = SSL_CTX_new(SSLv23_server_method());
|
||||||
|
}
|
||||||
|
if (ssl == 0)
|
||||||
|
{
|
||||||
|
ssl = SSL_new(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
loop = [NSRunLoop currentRunLoop];
|
||||||
|
ret = SSL_set_fd(ssl, descriptor);
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
|
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
||||||
|
ret = SSL_accept(ssl);
|
||||||
|
}
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
int e = errno;
|
||||||
|
NSDate *final;
|
||||||
|
NSDate *when;
|
||||||
|
NSTimeInterval last = 0.0;
|
||||||
|
NSTimeInterval limit = 0.1;
|
||||||
|
|
||||||
|
final = [[NSDate alloc] initWithTimeIntervalSinceNow: 20.0];
|
||||||
|
when = [NSDate alloc];
|
||||||
|
|
||||||
|
err = SSL_get_error(ssl, ret);
|
||||||
|
while ((err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
&& [final timeIntervalSinceNow] > 0.0)
|
||||||
|
{
|
||||||
|
NSTimeInterval tmp = limit;
|
||||||
|
|
||||||
|
limit += last;
|
||||||
|
last = tmp;
|
||||||
|
when = [when initWithTimeIntervalSinceNow: limit];
|
||||||
|
[loop runUntilDate: when];
|
||||||
|
ret = SSL_accept(ssl);
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
e = errno;
|
||||||
|
err = SSL_get_error(ssl, ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = SSL_ERROR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RELEASE(when);
|
||||||
|
RELEASE(final);
|
||||||
|
if (err != SSL_ERROR_NONE)
|
||||||
|
{
|
||||||
|
NSString *str = sslError(err, e);
|
||||||
|
|
||||||
|
NSLog(@"unable to accept SSL connection from %@:%@ - %@",
|
||||||
|
address, service, str);
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connected = YES;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) sslConnect
|
- (BOOL) sslConnect
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -152,10 +290,13 @@
|
||||||
ssl = SSL_new(ctx);
|
ssl = SSL_new(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = SSL_set_fd(ssl, descriptor);
|
|
||||||
loop = [NSRunLoop currentRunLoop];
|
loop = [NSRunLoop currentRunLoop];
|
||||||
|
ret = SSL_set_fd(ssl, descriptor);
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
||||||
ret = SSL_connect(ssl);
|
ret = SSL_connect(ssl);
|
||||||
|
}
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
{
|
{
|
||||||
int e = errno;
|
int e = errno;
|
||||||
|
@ -192,38 +333,11 @@
|
||||||
RELEASE(final);
|
RELEASE(final);
|
||||||
if (err != SSL_ERROR_NONE)
|
if (err != SSL_ERROR_NONE)
|
||||||
{
|
{
|
||||||
NSString *str;
|
NSString *str = sslError(err, e);
|
||||||
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case SSL_ERROR_NONE:
|
|
||||||
str = @"No error: really helpful";
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
|
||||||
str = @"Zero Return error";
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_WANT_READ:
|
|
||||||
str = @"Want Read Error";
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_WANT_WRITE:
|
|
||||||
str = @"Want Write Error";
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
|
||||||
str = @"Want X509 Lookup Error";
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_SYSCALL:
|
|
||||||
str = [NSString stringWithFormat: @"Syscall error %d - %s",
|
|
||||||
e, GSLastErrorStr(e)];
|
|
||||||
break;
|
|
||||||
case SSL_ERROR_SSL:
|
|
||||||
str = @"SSL Error: really helpful";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
str = @"Standard system error: really helpful";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
NSLog(@"unable to make SSL connection to %@:%@ - %@",
|
NSLog(@"unable to make SSL connection to %@:%@ - %@",
|
||||||
address, service, str);
|
address, service, str);
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,6 +369,8 @@
|
||||||
privateKey: (NSString*)privateKey
|
privateKey: (NSString*)privateKey
|
||||||
PEMpasswd: (NSString*)PEMpasswd
|
PEMpasswd: (NSString*)PEMpasswd
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (isStandardFile == YES)
|
if (isStandardFile == YES)
|
||||||
{
|
{
|
||||||
NSLog(@"Attempt to set ssl certificate for a standard file");
|
NSLog(@"Attempt to set ssl certificate for a standard file");
|
||||||
|
@ -265,19 +381,32 @@
|
||||||
*/
|
*/
|
||||||
if (ctx == 0)
|
if (ctx == 0)
|
||||||
{
|
{
|
||||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
ctx = SSL_CTX_new(SSLv23_method());
|
||||||
}
|
}
|
||||||
if ([PEMpasswd length] > 0)
|
if ([PEMpasswd length] > 0)
|
||||||
{
|
{
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ctx, (char*)[PEMpasswd cString]);
|
SSL_CTX_set_default_passwd_cb_userdata(ctx,
|
||||||
|
(char*)[PEMpasswd UTF8String]);
|
||||||
}
|
}
|
||||||
if ([certFile length] > 0)
|
if ([certFile length] > 0)
|
||||||
{
|
{
|
||||||
SSL_CTX_use_certificate_file(ctx, [certFile cString], X509_FILETYPE_PEM);
|
ret = SSL_CTX_use_certificate_file(ctx, [certFile UTF8String],
|
||||||
|
X509_FILETYPE_PEM);
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to set certificate file to %@ - %@",
|
||||||
|
certFile, sslError(ERR_get_error(), errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ([privateKey length] > 0)
|
if ([privateKey length] > 0)
|
||||||
{
|
{
|
||||||
SSL_CTX_use_PrivateKey_file(ctx, [privateKey cString], X509_FILETYPE_PEM);
|
ret = SSL_CTX_use_PrivateKey_file(ctx, [privateKey UTF8String],
|
||||||
|
X509_FILETYPE_PEM);
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to set private key file to %@ - %@",
|
||||||
|
privateKey, sslError(ERR_get_error(), errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -617,6 +617,14 @@ NSString * const NSFileHandleOperationException
|
||||||
return NSFileHandle_ssl_class;
|
return NSFileHandle_ssl_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establishes an SSL connection from the system that the handle is talking to.
|
||||||
|
*/
|
||||||
|
- (BOOL) sslAccept
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establishes an SSL connection to the system that the handle is talking to.
|
* Establishes an SSL connection to the system that the handle is talking to.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue