More SSL/TLS options support

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35618 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2012-09-30 10:14:00 +00:00
parent 7771aba9e1
commit f4eb5e2726
6 changed files with 137 additions and 30 deletions

View file

@ -1,3 +1,12 @@
2012-09-30 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSSocketStream.m:
* Source/GSTLS.m:
* Source/GSHTTPURLHandle.m:
* Source/NSURLProtocol.m:
* Headers/Foundation/NSFileHandle.h:
Add GNUstep TLS/SSL options when loading HTTPS URLs.
2012-09-26 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSUserDefaults.m: Fix error synchronising from changes in

View file

@ -303,7 +303,7 @@ GS_EXPORT NSString * const NSFileHandleOperationException;
* <term>GSTLSPriority</term>
* <desc>A GNUTLS priority string describing the ciphers etc which may be
* used for the connection. In addition the string may be one of
* SSLv2, SSLv3, or TLSv1 to use the appropriate general settings
* SSLv3, or TLSv1 to use the appropriate general settings
* for negotiating a connection of the specified type.
* </desc>
* <term>GSTLSRemoteHosts</term>

View file

@ -48,6 +48,7 @@
#import "NSCallBacks.h"
#import "GSURLPrivate.h"
#import "GSPrivate.h"
#import "GSTLS.h"
#ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
@ -999,11 +1000,45 @@ debugWrite(GSHTTPURLHandle *handle, NSData *data)
}
if ([[u scheme] isEqualToString: @"https"])
{
static NSArray *keys = nil;
NSMutableDictionary *opts;
NSUInteger count;
/* If we are an https connection, negotiate secure connection.
* Make sure we are not an observer of the file handle while
* it is connecting...
*/
[nc removeObserver: self name: nil object: sock];
if (nil == keys)
{
keys = [[NSArray alloc] initWithObjects:
GSTLSCAFile,
GSTLSCertificateFile,
GSTLSCertificateKeyFile,
GSTLSCertificateKeyPassword,
GSTLSDebug,
GSTLSPriority,
GSTLSRemoteHosts,
GSTLSRevokeFile,
GSTLSVerify,
nil];
}
count = [keys count];
opts = [[NSMutableDictionary alloc] initWithCapacity: count];
while (count-- > 0)
{
NSString *key = [keys objectAtIndex: count];
NSString *str = [request objectForKey: key];
if (nil != str)
{
[opts setObject: str forKey: key];
}
}
if (debug) [opts setObject: @"YES" forKey: GSTLSDebug];
[sock sslSetOptions: opts];
[opts release];
if ([sock sslConnect] == NO)
{
if (debug)

View file

@ -422,9 +422,25 @@ GSTLSPush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
@implementation GSTLSHandler
static NSArray *keys = nil;
+ (void) initialize
{
[GSTLSObject class];
if (nil == keys)
{
keys = [[NSArray alloc] initWithObjects:
GSTLSCAFile,
GSTLSCertificateFile,
GSTLSCertificateKeyFile,
GSTLSCertificateKeyPassword,
GSTLSDebug,
GSTLSPriority,
GSTLSRemoteHosts,
GSTLSRevokeFile,
GSTLSVerify,
nil];
}
}
+ (void) tryInput: (GSSocketInputStream*)i output: (GSSocketOutputStream*)o
@ -496,47 +512,68 @@ GSTLSPush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
- (id) initWithInput: (GSSocketInputStream*)i
output: (GSSocketOutputStream*)o
{
NSString *proto;
NSDictionary *opts;
BOOL server = NO;
NSString *str;
NSMutableDictionary *opts;
NSUInteger count;
BOOL server;
proto = [i propertyForKey: NSStreamSocketSecurityLevelKey];
/* FIXME
if ([[o propertyForKey: NSStreamSocketCertificateServerKey] boolValue] == YES)
{
server = YES;
}
*/
server = [[o propertyForKey: @"IsServer"] boolValue];
if (GSDebugSet(@"NSStream") == YES)
str = [o propertyForKey: NSStreamSocketSecurityLevelKey];
if (nil == str) str = [i propertyForKey: NSStreamSocketSecurityLevelKey];
if ([str isEqual: NSStreamSocketSecurityLevelNone] == YES)
{
gnutls_global_set_log_level (11); // Full debug output
}
else
{
gnutls_global_set_log_level (0); // No debug
}
if ([[o propertyForKey: NSStreamSocketSecurityLevelKey] isEqual: proto] == NO)
{
NSLog(@"NSStreamSocketSecurityLevel on input stream does not match output stream");
GSOnceMLog(@"NSStreamSocketSecurityLevelNone is insecure ..."
@" not implemented");
DESTROY(self);
return nil;
}
opts = [NSDictionary dictionaryWithObjectsAndKeys:
proto, NSStreamSocketSecurityLevelKey,
nil];
else if ([str isEqual: NSStreamSocketSecurityLevelSSLv2] == YES)
{
GSOnceMLog(@"NSStreamSocketSecurityLevelTLSv2 is insecure ..."
@" not implemented");
DESTROY(self);
return nil;
}
else if ([str isEqual: NSStreamSocketSecurityLevelSSLv3] == YES)
{
str = @"SSLv3";
}
else if ([str isEqual: NSStreamSocketSecurityLevelTLSv1] == YES)
{
str = @"TLSV1";
}
else
{
str = nil;
}
if ((self = [super initWithInput: i output: o]) == nil)
{
return nil;
}
/* Create the options dictionary, copying in any option from the stream
* properties. GSTLSPriority overrides NSStreamSocketSecurityLevelKey.
*/
opts = [NSMutableDictionary new];
if (nil != str) [opts setObject: str forKey: GSTLSPriority];
count = [keys count];
while (count-- > 0)
{
NSString *key = [keys objectAtIndex: count];
str = [o propertyForKey: key];
if (nil == str) str = [i propertyForKey: key];
if (nil != str) [opts setObject: str forKey: key];
}
session = [[GSTLSSession alloc] initWithOptions: opts
direction: (server ? NO : YES)
transport: (void*)self
push: GSTLSPush
pull: GSTLSPull];
[opts release];
initialised = YES;
return self;
}
@ -2501,6 +2538,7 @@ setNonBlocking(SOCKET fd)
[outs _setAddress: addr];
[ins _setSock: acceptReturn];
[outs _setSock: acceptReturn];
[ins setProperty: @"YES" forKey: @"IsServer"];
}
if (inputStream)
{

View file

@ -1018,11 +1018,6 @@ static NSMutableDictionary *privateKeyCache1 = nil;
pri = NSStreamSocketSecurityLevelSSLv3;
str = nil;
}
else if (YES == [str isEqual: @"SSLv2"])
{
pri = NSStreamSocketSecurityLevelSSLv2;
str = nil;
}
else if (YES == [str isEqual: @"TLSv1"])
{
pri = NSStreamSocketSecurityLevelTLSv1;

View file

@ -33,6 +33,7 @@
#import "Foundation/NSValue.h"
#import "GSPrivate.h"
#import "GSTLS.h"
#import "GSURLPrivate.h"
#import "GNUstepBase/GSMime.h"
#import "GNUstepBase/NSObject+GNUstepBase.h"
@ -780,10 +781,39 @@ static NSURLProtocol *placeholder = nil;
#endif
if ([[url scheme] isEqualToString: @"https"] == YES)
{
static NSArray *keys;
NSUInteger count;
[this->input setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
forKey: NSStreamSocketSecurityLevelKey];
[this->output setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
forKey: NSStreamSocketSecurityLevelKey];
if (nil == keys)
{
keys = [[NSArray alloc] initWithObjects:
GSTLSCAFile,
GSTLSCertificateFile,
GSTLSCertificateKeyFile,
GSTLSCertificateKeyPassword,
GSTLSDebug,
GSTLSPriority,
GSTLSRemoteHosts,
GSTLSRevokeFile,
GSTLSVerify,
nil];
}
count = [keys count];
while (count-- > 0)
{
NSString *key = [keys objectAtIndex: count];
NSString *str = [this->request _propertyForKey: key];
if (nil != str)
{
[this->output setProperty: str forKey: key];
}
}
if (_debug) [this->output setProperty: @"YES" forKey: GSTLSDebug];
}
[this->input setDelegate: self];
[this->output setDelegate: self];