Reorganise a bit to ensure that TLS is properly shut down before the network

connection it relies on is closed.  Needed in case information is buffered
in the TLS layer and needs flushing to the remote end before shutdown.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@37390 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2013-11-21 15:13:14 +00:00
parent f368388449
commit 971a8374a8
4 changed files with 38 additions and 18 deletions

View file

@ -1,3 +1,10 @@
2013-11-21 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSFileHandle.m: Do an -sslDisconnect while finalising
(before underlying network connection is closed).
* Source/NSFileHandle.m: Add assertion to check that TLS has been
shut down by concrete subclass dealloc.
2013-11-20 Richard Frith-Macdonald <rfm@gnu.org> 2013-11-20 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSUserDefaults.m: Fix for bug 40620 * Source/NSUserDefaults.m: Fix for bug 40620

View file

@ -214,8 +214,7 @@ static NSString* NotificationKey = @"NSFileHandleNotificationKey";
[self ignoreWriteDescriptor]; [self ignoreWriteDescriptor];
#if USE_ZLIB #if USE_ZLIB
/* /* The gzDescriptor should always be closed when we have done with it.
* The gzDescriptor should always be closed when we have done with it.
*/ */
if (gzDescriptor != 0) if (gzDescriptor != 0)
{ {
@ -223,6 +222,14 @@ static NSString* NotificationKey = @"NSFileHandleNotificationKey";
gzDescriptor = 0; gzDescriptor = 0;
} }
#endif #endif
/* Ensure any SSL/TLS connection has been properly shut down.
*/
[self sslDisconnect];
/* Close file descriptor if necessary (setting correct non-blocking
* characteristics since we may have changed them).
*/
if (descriptor != -1) if (descriptor != -1)
{ {
[self setNonBlocking: wasNonBlocking]; [self setNonBlocking: wasNonBlocking];
@ -232,6 +239,7 @@ static NSString* NotificationKey = @"NSFileHandleNotificationKey";
descriptor = -1; descriptor = -1;
} }
} }
[super finalize];
} }
// Initializing a GSFileHandle Object // Initializing a GSFileHandle Object

View file

@ -953,29 +953,22 @@ GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
- (void) closeFile - (void) closeFile
{ {
[self sslDisconnect]; [self sslDisconnect]; // Shut down TLS before closing socket
[super closeFile]; [super closeFile];
} }
- (void) dealloc - (void) dealloc
{ {
// TLS may need to read data during teardown, and we need to wait for it. /* Any TLS connection needs to be shut down before the network connection
[self setNonBlocking: NO]; * is closed, which means that the concrete subclass must do that.
// Don't DESTROY ivars below. First release them, then set nil, because * Therefore, the session should be inactive by the time we get here.
// `session' may need this back-reference during TLS teardown. */
TEST_RELEASE(opts); NSAssert(NO == [session active], NSInternalInconsistencyException);
TEST_RELEASE(session); DESTROY(session);
opts = nil; DESTROY(opts);
session = nil;
[super dealloc]; [super dealloc];
} }
- (void) finalize
{
[self sslDisconnect];
[super finalize];
}
- (NSInteger) read: (void*)buf length: (NSUInteger)len - (NSInteger) read: (void*)buf length: (NSUInteger)len
{ {
if (YES == [session active]) if (YES == [session active])
@ -987,7 +980,14 @@ GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
- (void) sslDisconnect - (void) sslDisconnect
{ {
[session disconnect]; if (nil != session)
{
// TLS may need to read data during teardown, and we need to wait for it.
[self setNonBlocking: NO];
[session disconnect];
DESTROY(session);
}
DESTROY(opts);
} }
- (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing - (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing

View file

@ -270,6 +270,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
gzclose(gzDescriptor); gzclose(gzDescriptor);
} }
#endif #endif
/* Ensure any SSL/TLS connection has been properly shut down.
*/
[self sslDisconnect];
if (descriptor != -1) if (descriptor != -1)
{ {
[self setNonBlocking: wasNonBlocking]; [self setNonBlocking: wasNonBlocking];