mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
ssh handshake improvements and consmetic tweaks
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33535 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a64f21744d
commit
497cb2af93
6 changed files with 198 additions and 211 deletions
47
ChangeLog
47
ChangeLog
|
@ -1,7 +1,16 @@
|
|||
2011-07-12 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSFileHandle.m:
|
||||
* SSL/GSSSLHandle.m:
|
||||
* Headers/Foundation/NSFileHandle.h:
|
||||
Fixup to let certificate information contain a chaing with intermediate
|
||||
certificate authorities. Simplify handshake using common routine for
|
||||
non-blocking handshake attempt.
|
||||
|
||||
2011-07-11 14:31 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Source/NSAutoreleasePool.m,
|
||||
libs/base/trunk/Source/NSThread.m: Lazily initialize POSIX
|
||||
* Source/NSAutoreleasePool.m,
|
||||
Source/NSThread.m: Lazily initialize POSIX
|
||||
threads, matching OS X behaviour and stopping us from crashing
|
||||
when calling autorelease from a thread that was not previously
|
||||
registered explicitly (yuck!)
|
||||
|
@ -13,7 +22,7 @@
|
|||
|
||||
2011-07-11 12:36 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Source/NSNumber.m: [NSNumber -init] should not
|
||||
* Source/NSNumber.m: [NSNumber -init] should not
|
||||
destroy itself when called as [super init]. This behaviour was
|
||||
breaking anything that subclassed NSNumber in user code (e.g.
|
||||
PyObjC).
|
||||
|
@ -53,7 +62,7 @@
|
|||
|
||||
2011-07-04 11:31 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Source/NSObject.m:
|
||||
* Source/NSObject.m:
|
||||
Switch the order of the reference count and the zone so that the
|
||||
reference count (in reference counted mode) is always immediately in
|
||||
front of the object. Please test this!!
|
||||
|
@ -66,11 +75,11 @@
|
|||
|
||||
2011-06-30 14:44 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Headers/Foundation/NSArray.h,
|
||||
libs/base/trunk/Headers/Foundation/NSProxy.h,
|
||||
libs/base/trunk/Headers/GNUstepBase/GSVersionMacros.h,
|
||||
libs/base/trunk/Headers/GNUstepBase/preface.h.in,
|
||||
libs/base/trunk/Source/NSProxy.m: Rewrote NSProxy's -retain /
|
||||
* Headers/Foundation/NSArray.h,
|
||||
Headers/Foundation/NSProxy.h,
|
||||
Headers/GNUstepBase/GSVersionMacros.h,
|
||||
Headers/GNUstepBase/preface.h.in,
|
||||
Source/NSProxy.m: Rewrote NSProxy's -retain /
|
||||
-release to be the same as NSObject, not its own ad-hoc thing.
|
||||
|
||||
Added declaration of __bridge for use in non-ARC mode.
|
||||
|
@ -81,25 +90,25 @@
|
|||
|
||||
2011-06-29 15:21 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Headers/Foundation/NSNotification.h,
|
||||
libs/base/trunk/Headers/Foundation/NSZone.h,
|
||||
libs/base/trunk/Headers/GNUstepBase/preface.h.in,
|
||||
libs/base/trunk/Tools/make_strings/make_strings.m: More ARC
|
||||
* Headers/Foundation/NSNotification.h,
|
||||
Headers/Foundation/NSZone.h,
|
||||
Headers/GNUstepBase/preface.h.in,
|
||||
Tools/make_strings/make_strings.m: More ARC
|
||||
fixes. We don't want to be using __strong void* in ARC mode (it
|
||||
only makes sense in GC mode and is invalid in ARC mode).
|
||||
|
||||
2011-06-29 13:13 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Source/NSObject.m: Add support to NSObject for
|
||||
* Source/NSObject.m: Add support to NSObject for
|
||||
automatically zeroing __weak references when using ARC.
|
||||
|
||||
2011-06-29 11:50 David Chisnall <theraven@gna.org>
|
||||
|
||||
* libs/base/trunk/Headers/Foundation/NSAutoreleasePool.h,
|
||||
libs/base/trunk/Headers/Foundation/NSEnumerator.h,
|
||||
libs/base/trunk/Headers/Foundation/NSException.h,
|
||||
libs/base/trunk/Headers/Foundation/NSZone.h,
|
||||
libs/base/trunk/Headers/GNUstepBase/preface.h.in:
|
||||
* Headers/Foundation/NSAutoreleasePool.h,
|
||||
Headers/Foundation/NSEnumerator.h,
|
||||
Headers/Foundation/NSException.h,
|
||||
Headers/Foundation/NSZone.h,
|
||||
Headers/GNUstepBase/preface.h.in:
|
||||
ARC-compatibility tweaks in the headers. ARC will not track
|
||||
objects inside structures and rejects code that uses object types
|
||||
that are not __unsafe_unretained qualified inside structures.
|
||||
|
|
|
@ -236,6 +236,22 @@ GS_EXPORT NSString * const NSFileHandleOperationException;
|
|||
- (BOOL) sslAccept;
|
||||
- (BOOL) sslConnect;
|
||||
- (void) sslDisconnect;
|
||||
/** Make a non-blocking handshake attempt. Calls to this method should be
|
||||
* repeated until the method returns YES indicating that the handshake
|
||||
* completed. If the method returns YES indicating completion of the
|
||||
* handshake, the result indicates whether the handshake succeeded in
|
||||
* establishing a connection or not.
|
||||
*/
|
||||
- (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing;
|
||||
/** Sets certification data for the SSL connection.<br />
|
||||
* The value of certFile is the path to a file containing a PEM encoded
|
||||
* certificate for this host (optionally followed by other PEM encoded
|
||||
* certificates in a chain leading to a root certificate authority).<br />
|
||||
* The value of privatekey is the path of a file containing a PEM encoded key
|
||||
* used to establish handshakes using the host certificate.<br />
|
||||
* The value of PEMpasswd is a string used as the password to access the
|
||||
* content of the key file.
|
||||
*/
|
||||
- (void) sslSetCertificate: (NSString*)certFile
|
||||
privateKey: (NSString*)privateKey
|
||||
PEMpasswd: (NSString*)PEMpasswd;
|
||||
|
|
|
@ -156,6 +156,7 @@ threadid_function()
|
|||
- (BOOL) sslAccept;
|
||||
- (BOOL) sslConnect;
|
||||
- (void) sslDisconnect;
|
||||
- (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing;
|
||||
- (void) sslSetCertificate: (NSString*)certFile
|
||||
privateKey: (NSString*)privateKey
|
||||
PEMpasswd: (NSString*)PEMpasswd;
|
||||
|
@ -236,215 +237,100 @@ static BOOL permitSSLv2 = NO;
|
|||
|
||||
- (BOOL) sslAccept
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
NSRunLoop *loop;
|
||||
BOOL result = NO;
|
||||
|
||||
if (connected == YES)
|
||||
{
|
||||
return YES; /* Already connected. */
|
||||
}
|
||||
if (isStandardFile == YES)
|
||||
if (YES == isStandardFile)
|
||||
{
|
||||
NSLog(@"Attempt to make ssl connection to a standard file");
|
||||
return NO;
|
||||
}
|
||||
if (NO == [self sslHandshakeEstablished: &result outgoing: NO])
|
||||
{
|
||||
NSRunLoop *loop;
|
||||
|
||||
/*
|
||||
* Ensure we have a context and handle to connect with.
|
||||
*/
|
||||
if (ctx == 0)
|
||||
{
|
||||
ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (permitSSLv2 == NO)
|
||||
{
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
||||
}
|
||||
}
|
||||
if (ssl == 0)
|
||||
{
|
||||
ssl = SSL_new(ctx);
|
||||
}
|
||||
/*
|
||||
* Set non-blocking so accept won't hang if remote end goes wrong.
|
||||
*/
|
||||
[self setNonBlocking: YES];
|
||||
IF_NO_GC([self retain];) // Don't get destroyed during runloop
|
||||
loop = [NSRunLoop currentRunLoop];
|
||||
ret = SSL_set_fd(ssl, descriptor);
|
||||
if (ret == 1)
|
||||
{
|
||||
IF_NO_GC([self retain];) // Don't get destroyed during runloop
|
||||
loop = [NSRunLoop currentRunLoop];
|
||||
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
||||
if (ssl == 0)
|
||||
if (NO == [self sslHandshakeEstablished: &result outgoing: NO])
|
||||
{
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
NSDate *final;
|
||||
NSDate *when;
|
||||
NSTimeInterval last = 0.0;
|
||||
NSTimeInterval limit = 0.1;
|
||||
|
||||
final = [[NSDate alloc] initWithTimeIntervalSinceNow: 30.0];
|
||||
when = [NSDate alloc];
|
||||
|
||||
while (NO == [self sslHandshakeEstablished: &result outgoing: NO]
|
||||
&& [final timeIntervalSinceNow] > 0.0)
|
||||
{
|
||||
NSTimeInterval tmp = limit;
|
||||
|
||||
limit += last;
|
||||
last = tmp;
|
||||
if (limit > 0.5)
|
||||
{
|
||||
limit = 0.1;
|
||||
last = 0.1;
|
||||
}
|
||||
when = [when initWithTimeIntervalSinceNow: limit];
|
||||
[loop runUntilDate: when];
|
||||
}
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
}
|
||||
ret = SSL_accept(ssl);
|
||||
DESTROY(self);
|
||||
}
|
||||
if (ret != 1)
|
||||
{
|
||||
NSDate *final;
|
||||
NSDate *when;
|
||||
NSTimeInterval last = 0.0;
|
||||
NSTimeInterval limit = 0.1;
|
||||
|
||||
final = [[NSDate alloc] initWithTimeIntervalSinceNow: 30.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];
|
||||
if (ssl == 0)
|
||||
{
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
}
|
||||
ret = SSL_accept(ssl);
|
||||
if (ret != 1)
|
||||
{
|
||||
err = SSL_get_error(ssl, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = SSL_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
if (err != SSL_ERROR_NONE)
|
||||
{
|
||||
if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE
|
||||
&& (err != SSL_ERROR_SYSCALL || errno != 0))
|
||||
{
|
||||
/*
|
||||
* Some other error ... not just a timeout or disconnect
|
||||
*/
|
||||
NSWarnLog(@"unable to accept SSL connection from %@:%@ - %@",
|
||||
address, service, sslError(err));
|
||||
}
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
connected = YES;
|
||||
DESTROY(self);
|
||||
return YES;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL) sslConnect
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
NSRunLoop *loop;
|
||||
BOOL result = NO;
|
||||
|
||||
if (connected == YES)
|
||||
{
|
||||
return YES; /* Already connected. */
|
||||
}
|
||||
if (isStandardFile == YES)
|
||||
if (YES == isStandardFile)
|
||||
{
|
||||
NSLog(@"Attempt to make ssl connection to a standard file");
|
||||
return NO;
|
||||
}
|
||||
if (NO == [self sslHandshakeEstablished: &result outgoing: YES])
|
||||
{
|
||||
NSRunLoop *loop;
|
||||
|
||||
/*
|
||||
* Ensure we have a context and handle to connect with.
|
||||
*/
|
||||
if (ctx == 0)
|
||||
{
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if (permitSSLv2 == NO)
|
||||
{
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
||||
}
|
||||
}
|
||||
if (ssl == 0)
|
||||
{
|
||||
ssl = SSL_new(ctx);
|
||||
}
|
||||
IF_NO_GC([self retain];) // Don't get destroyed during runloop
|
||||
/*
|
||||
* Set non-blocking so accept won't hang if remote end goes wrong.
|
||||
*/
|
||||
[self setNonBlocking: YES];
|
||||
loop = [NSRunLoop currentRunLoop];
|
||||
ret = SSL_set_fd(ssl, descriptor);
|
||||
if (ret == 1)
|
||||
{
|
||||
IF_NO_GC([self retain];) // Don't get destroyed during runloop
|
||||
loop = [NSRunLoop currentRunLoop];
|
||||
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
||||
if (ssl == 0)
|
||||
if (NO == [self sslHandshakeEstablished: &result outgoing: YES])
|
||||
{
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
NSDate *final;
|
||||
NSDate *when;
|
||||
NSTimeInterval last = 0.0;
|
||||
NSTimeInterval limit = 0.1;
|
||||
|
||||
final = [[NSDate alloc] initWithTimeIntervalSinceNow: 30.0];
|
||||
when = [NSDate alloc];
|
||||
|
||||
while (NO == [self sslHandshakeEstablished: &result outgoing: YES]
|
||||
&& [final timeIntervalSinceNow] > 0.0)
|
||||
{
|
||||
NSTimeInterval tmp = limit;
|
||||
|
||||
limit += last;
|
||||
last = tmp;
|
||||
if (limit > 0.5)
|
||||
{
|
||||
limit = 0.1;
|
||||
last = 0.1;
|
||||
}
|
||||
when = [when initWithTimeIntervalSinceNow: limit];
|
||||
[loop runUntilDate: when];
|
||||
}
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
}
|
||||
ret = SSL_connect(ssl);
|
||||
DESTROY(self);
|
||||
}
|
||||
if (ret != 1)
|
||||
{
|
||||
NSDate *final;
|
||||
NSDate *when;
|
||||
NSTimeInterval last = 0.0;
|
||||
NSTimeInterval limit = 0.1;
|
||||
|
||||
final = [[NSDate alloc] initWithTimeIntervalSinceNow: 30.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];
|
||||
if (ssl == 0)
|
||||
{
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
}
|
||||
ret = SSL_connect(ssl);
|
||||
if (ret != 1)
|
||||
{
|
||||
err = SSL_get_error(ssl, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = SSL_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
RELEASE(when);
|
||||
RELEASE(final);
|
||||
if (err != SSL_ERROR_NONE)
|
||||
{
|
||||
if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
|
||||
{
|
||||
/*
|
||||
* Some other error ... not just a timeout or disconnect
|
||||
*/
|
||||
NSLog(@"unable to make SSL connection to %@:%@ - %@",
|
||||
address, service, sslError(err));
|
||||
}
|
||||
DESTROY(self);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
connected = YES;
|
||||
DESTROY(self);
|
||||
return YES;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) sslDisconnect
|
||||
|
@ -467,6 +353,75 @@ static BOOL permitSSLv2 = NO;
|
|||
connected = NO;
|
||||
}
|
||||
|
||||
- (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
NSAssert(0 != result, NSInvalidArgumentException);
|
||||
|
||||
if (YES == connected)
|
||||
{
|
||||
return YES; /* Already connected. */
|
||||
}
|
||||
if (YES == isStandardFile)
|
||||
{
|
||||
NSLog(@"Attempt to perform ssl handshake with a standard file");
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure we have a context and handle to connect with.
|
||||
*/
|
||||
if (ctx == 0)
|
||||
{
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if (permitSSLv2 == NO)
|
||||
{
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
||||
}
|
||||
}
|
||||
if (ssl == 0)
|
||||
{
|
||||
ssl = SSL_new(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non-blocking so accept won't hang if remote end goes wrong.
|
||||
*/
|
||||
[self setNonBlocking: YES];
|
||||
ret = SSL_set_fd(ssl, descriptor);
|
||||
if (1 == ret)
|
||||
{
|
||||
if (YES == isOutgoing)
|
||||
{
|
||||
ret = SSL_connect(ssl);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SSL_accept(ssl);
|
||||
}
|
||||
}
|
||||
if (1 == ret)
|
||||
{
|
||||
connected = YES;
|
||||
*result = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = SSL_get_error(ssl, ret);
|
||||
if (SSL_ERROR_WANT_READ == err || SSL_ERROR_WANT_WRITE == err)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSLog(@"unable to make SSL connection to %@:%@ - %@",
|
||||
address, service, sslError(err));
|
||||
*result = NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) sslSetCertificate: (NSString*)certFile
|
||||
privateKey: (NSString*)privateKey
|
||||
PEMpasswd: (NSString*)PEMpasswd
|
||||
|
@ -496,8 +451,7 @@ static BOOL permitSSLv2 = NO;
|
|||
}
|
||||
if ([certFile length] > 0)
|
||||
{
|
||||
ret = SSL_CTX_use_certificate_file(ctx, [certFile UTF8String],
|
||||
X509_FILETYPE_PEM);
|
||||
ret = SSL_CTX_use_certificate_chain_file(ctx, [certFile UTF8String]);
|
||||
if (ret != 1)
|
||||
{
|
||||
NSLog(@"Failed to set certificate file to %@ - %@",
|
||||
|
|
|
@ -728,7 +728,7 @@ NSString * const NSFileHandleOperationException
|
|||
/** <override-dummy />
|
||||
* Establishes an SSL connection from the system that the handle
|
||||
* is talking to.<br />
|
||||
* This is implented by an SSL handling subclass.<br />
|
||||
* This is implemented by an SSL handling subclass.<br />
|
||||
* The default implementation just returns NO.
|
||||
*/
|
||||
- (BOOL) sslAccept
|
||||
|
@ -739,7 +739,7 @@ NSString * const NSFileHandleOperationException
|
|||
/** <override-dummy />
|
||||
* Establishes an SSL connection to the system that the handle
|
||||
* is talking to.<br />
|
||||
* This is implented by an SSL handling subclass.<br />
|
||||
* This is implemented by an SSL handling subclass.<br />
|
||||
* The default implementation just returns NO.
|
||||
*/
|
||||
- (BOOL) sslConnect
|
||||
|
@ -755,7 +755,14 @@ NSString * const NSFileHandleOperationException
|
|||
}
|
||||
|
||||
/** <override-dummy />
|
||||
* Sets the certificate to be used to identify this process to the server
|
||||
*/
|
||||
- (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing;
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
/** <override-dummy />
|
||||
* Sets the certificate chain to be used to identify this process to the server
|
||||
* at the opposite end of the network connection.
|
||||
*/
|
||||
- (void) sslSetCertificate: (NSString*)certFile
|
||||
|
@ -763,5 +770,6 @@ NSString * const NSFileHandleOperationException
|
|||
PEMpasswd: (NSString*)PEMpasswd
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -757,7 +757,7 @@ if (aValue >= -1 && aValue <= 12)\
|
|||
return [self stringValue];
|
||||
}
|
||||
|
||||
/* Return nil for an NSNumber that is allocated and initalized without
|
||||
/* Return nil for an NSNumber that is allocated and initialized without
|
||||
* providing a real value. Yes, this seems weird, but it is actually what
|
||||
* happens on OS X.
|
||||
*/
|
||||
|
|
|
@ -331,7 +331,7 @@ GSCurrentThread(void)
|
|||
{
|
||||
assert(GSRegisterCurrentThread() && @"Failed to register thread");
|
||||
thr = pthread_getspecific(thread_object_key);
|
||||
if ((defaultThread == nil) && IS_MAIN_PTHREAD)
|
||||
if ((nil == defaultThread) && IS_MAIN_PTHREAD)
|
||||
{
|
||||
defaultThread = [thr retain];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue