mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
New code for secure (encrypted) inter-host distrinuted objects.
This commit is contained in:
parent
e2cbf5e871
commit
e42d9fdc6b
5 changed files with 392 additions and 46 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2021-05-31 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/GNUstepBase/GSTLS.h: ([GSTLSCredentials selfSigned:])
|
||||
* Source/GSTLS.m: Add new method to use certtool to generate a
|
||||
key and a self-signed certificate. Use the new method to set up
|
||||
server sessions if no certificate/key is configured.
|
||||
* Headers/Foundation/NSPort.h: ([NSSocketPost setOptionsForTLS:])
|
||||
* Source/NSSocketPort.m: New methods to configure socket ports to
|
||||
use TLS so that inter-host distributed object connections can be
|
||||
securely encrypted. The class method should turn on encryption
|
||||
for all subsequent connections using socket ports (the instance
|
||||
method can be used to override the effects of the class method
|
||||
for an individual instance).
|
||||
|
||||
2021-05-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSStream.m:
|
||||
|
|
|
@ -208,6 +208,7 @@ GS_EXPORT_CLASS
|
|||
uint16_t portNum; /* TCP port in host byte order. */
|
||||
SOCKET listener;
|
||||
NSMapTable *handles; /* Handles indexed by socket. */
|
||||
NSDictionary *tlsopts; /* TLS options */
|
||||
#if defined(_WIN32)
|
||||
WSAEVENT eventListener;
|
||||
NSMapTable *events;
|
||||
|
@ -273,6 +274,21 @@ GS_EXPORT_CLASS
|
|||
* Returns port number of underlying socket.
|
||||
*/
|
||||
- (uint16_t) portNumber;
|
||||
|
||||
#if !NO_GNUSTEP
|
||||
/** Sets the default options for use of TLS by socket ports.<br />
|
||||
* Setting nil (the default) means that TLS is not used.<br />
|
||||
* Setting an empty dictionary means that TLS is used with normal options.
|
||||
*/
|
||||
+ (void) setOptionsForTLS: (NSDictionary*)opts;
|
||||
|
||||
/** Overrides the default options for use of TLS by the receiver.<br />
|
||||
* Setting nil (the default) means that TLS is not used.<br />
|
||||
* Setting an empty dictionary means that TLS is used with normal options.<br />
|
||||
* This method has no effect on network sessions which are already established.
|
||||
*/
|
||||
- (void) setOptionsForTLS: (NSDictionary*)opts;
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ GS_EXPORT_CLASS
|
|||
certificateKeyPassword: (NSString*)cp
|
||||
asClient: (BOOL)client
|
||||
debug: (BOOL)debug;
|
||||
+ (GSTLSCredentials*) selfSigned: (BOOL)debug;
|
||||
- (gnutls_certificate_credentials_t) credentials;
|
||||
- (GSTLSPrivateKey*) key;
|
||||
- (GSTLSCertificateList*) list;
|
||||
|
|
156
Source/GSTLS.m
156
Source/GSTLS.m
|
@ -35,8 +35,10 @@
|
|||
#import "Foundation/NSNotification.h"
|
||||
#import "Foundation/NSProcessInfo.h"
|
||||
#import "Foundation/NSStream.h"
|
||||
#import "Foundation/NSTask.h"
|
||||
#import "Foundation/NSThread.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
#import "Foundation/NSUUID.h"
|
||||
|
||||
#import "GNUstepBase/GSTLS.h"
|
||||
|
||||
|
@ -1091,6 +1093,89 @@ static NSMutableDictionary *credentialsCache = nil;
|
|||
}
|
||||
}
|
||||
|
||||
+ (GSTLSCredentials*) selfSigned: (BOOL)debug
|
||||
{
|
||||
NSString *crtPath = standardizedPath(@"self-signed-crt");
|
||||
NSString *keyPath = standardizedPath(@"self-signed-key");
|
||||
NSData *crt = [self dataForTLSFile: crtPath];
|
||||
NSData *key = [self dataForTLSFile: keyPath];
|
||||
|
||||
if (nil == crt || nil == key)
|
||||
{
|
||||
static NSString *tmp = @"organization = SelfSigned\n"
|
||||
@"state = Example\n"
|
||||
@"country = EX\n"
|
||||
@"cn = SelfSigned\n"
|
||||
@"serial = 007\n"
|
||||
@"expiration_days = 730\n"
|
||||
@"dns_name = server.selfsigned.com\n"
|
||||
@"tls_www_server\n"
|
||||
@"encryption_key\n";
|
||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||
NSString *path = NSTemporaryDirectory();
|
||||
NSTask *task;
|
||||
NSString *tmpPath;
|
||||
|
||||
path = [path stringByAppendingPathComponent: [[NSUUID UUID] UUIDString]];
|
||||
keyPath = [path stringByAppendingPathExtension: @"key"];
|
||||
tmpPath = [path stringByAppendingPathExtension: @"tmp"];
|
||||
crtPath = [path stringByAppendingPathExtension: @"crt"];
|
||||
[tmp writeToFile: tmpPath atomically: NO];
|
||||
|
||||
task = [NSTask new];
|
||||
[task setLaunchPath: @"certtool"];
|
||||
[task setArguments: [NSArray arrayWithObjects:
|
||||
@"--generate-privkey", @"--sec-param", @"high", @"--outfile", keyPath,
|
||||
nil]];
|
||||
[task setStandardOutput: [NSFileHandle fileHandleWithNullDevice]];
|
||||
[task setStandardError: [NSFileHandle fileHandleWithNullDevice]];
|
||||
[task launch];
|
||||
[task waitUntilExit];
|
||||
RELEASE(task);
|
||||
key = [NSData dataWithContentsOfFile: keyPath];
|
||||
|
||||
task = [NSTask new];
|
||||
[task setLaunchPath: @"certtool"];
|
||||
[task setArguments: [NSArray arrayWithObjects:
|
||||
@"--generate-self-signed", @"--load-privkey", keyPath,
|
||||
@"--template", tmpPath, @"--outfile", crtPath,
|
||||
nil]];
|
||||
[task setStandardOutput: [NSFileHandle fileHandleWithNullDevice]];
|
||||
[task setStandardError: [NSFileHandle fileHandleWithNullDevice]];
|
||||
[task launch];
|
||||
[task waitUntilExit];
|
||||
crt = [NSData dataWithContentsOfFile: crtPath];
|
||||
|
||||
[mgr removeFileAtPath: keyPath handler: nil];
|
||||
[mgr removeFileAtPath: tmpPath handler: nil];
|
||||
[mgr removeFileAtPath: crtPath handler: nil];
|
||||
if (nil == key)
|
||||
{
|
||||
NSLog(@"Failed to make self-signed certificate key using 'certtool'");
|
||||
return nil;
|
||||
}
|
||||
if (nil == crt)
|
||||
{
|
||||
NSLog(@"Failed to make self-signed certificate using 'certtool'");
|
||||
return nil;
|
||||
}
|
||||
keyPath = standardizedPath(@"self-signed-key");
|
||||
[self setData: key forTLSFile: keyPath];
|
||||
crtPath = standardizedPath(@"self-signed-crt-");
|
||||
[self setData: crt forTLSFile: crtPath];
|
||||
}
|
||||
|
||||
return [self credentialsFromCAFile: nil
|
||||
defaultCAFile: nil
|
||||
revokeFile: nil
|
||||
defaultRevokeFile: nil
|
||||
certificateFile: crtPath
|
||||
certificateKeyFile: keyPath
|
||||
certificateKeyPassword: nil
|
||||
asClient: NO
|
||||
debug: debug];
|
||||
}
|
||||
|
||||
+ (GSTLSCredentials*) credentialsFromCAFile: (NSString*)ca
|
||||
defaultCAFile: (NSString*)dca
|
||||
revokeFile: (NSString*)rv
|
||||
|
@ -1322,6 +1407,7 @@ static NSMutableDictionary *credentialsCache = nil;
|
|||
return [c autorelease];
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (nil != name)
|
||||
|
@ -1539,17 +1625,18 @@ retrieve_callback(gnutls_session_t session,
|
|||
{
|
||||
if (nil != (self = [super init]))
|
||||
{
|
||||
NSString *ca;
|
||||
NSString *dca;
|
||||
NSString *rv;
|
||||
NSString *drv;
|
||||
NSString *cf;
|
||||
NSString *ck;
|
||||
NSString *cp;
|
||||
NSString *pri;
|
||||
NSString *str;
|
||||
BOOL trust;
|
||||
BOOL verify;
|
||||
GSTLSCredentials *cr;
|
||||
NSString *ca;
|
||||
NSString *dca;
|
||||
NSString *rv;
|
||||
NSString *drv;
|
||||
NSString *cf;
|
||||
NSString *ck;
|
||||
NSString *cp;
|
||||
NSString *pri;
|
||||
NSString *str;
|
||||
BOOL trust;
|
||||
BOOL verify;
|
||||
|
||||
created = [NSDate timeIntervalSinceReferenceDate];
|
||||
opts = [options copy];
|
||||
|
@ -1632,28 +1719,41 @@ retrieve_callback(gnutls_session_t session,
|
|||
}
|
||||
setup = YES;
|
||||
|
||||
ca = [opts objectForKey: GSTLSCAFile];
|
||||
dca = caFile;
|
||||
rv = [opts objectForKey: GSTLSRevokeFile];
|
||||
drv = revokeFile;
|
||||
cf = [opts objectForKey: GSTLSCertificateFile];
|
||||
ck = [opts objectForKey: GSTLSCertificateKeyFile];
|
||||
cp = [opts objectForKey: GSTLSCertificateKeyPassword];
|
||||
|
||||
credentials = [[GSTLSCredentials credentialsFromCAFile: ca
|
||||
defaultCAFile: dca
|
||||
revokeFile: rv
|
||||
defaultRevokeFile: drv
|
||||
certificateFile: cf
|
||||
certificateKeyFile: ck
|
||||
certificateKeyPassword: cp
|
||||
asClient: outgoing
|
||||
debug: debug] retain];
|
||||
if (nil == cf && NO == outgoing)
|
||||
{
|
||||
/* Server with no certiticate supplied: generate self signed one.
|
||||
*/
|
||||
cr = [GSTLSCredentials selfSigned: debug];
|
||||
}
|
||||
else
|
||||
{
|
||||
ca = [opts objectForKey: GSTLSCAFile];
|
||||
dca = caFile;
|
||||
rv = [opts objectForKey: GSTLSRevokeFile];
|
||||
drv = revokeFile;
|
||||
ck = [opts objectForKey: GSTLSCertificateKeyFile];
|
||||
cp = [opts objectForKey: GSTLSCertificateKeyPassword];
|
||||
|
||||
cr = [GSTLSCredentials credentialsFromCAFile: ca
|
||||
defaultCAFile: dca
|
||||
revokeFile: rv
|
||||
defaultRevokeFile: drv
|
||||
certificateFile: cf
|
||||
certificateKeyFile: ck
|
||||
certificateKeyPassword: cp
|
||||
asClient: outgoing
|
||||
debug: debug];
|
||||
}
|
||||
|
||||
if (nil == credentials)
|
||||
if (cr)
|
||||
{
|
||||
[self release];
|
||||
ASSIGN(credentials, cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define EXPOSE_NSPort_IVARS 1
|
||||
#define EXPOSE_NSSocketPort_IVARS 1
|
||||
#import "GNUstepBase/GSLock.h"
|
||||
#import "GNUstepBase/GSTLS.h"
|
||||
#import "Foundation/NSArray.h"
|
||||
#import "Foundation/NSNotification.h"
|
||||
#import "Foundation/NSNotificationQueue.h"
|
||||
|
@ -122,6 +123,10 @@
|
|||
*/
|
||||
static uint32_t maxDataLength = 32 * 1024 * 1024;
|
||||
|
||||
/* Options for TLS encryption of connections
|
||||
*/
|
||||
static NSDictionary *tlsOptions;
|
||||
|
||||
#if 0
|
||||
#define M_LOCK(X) {NSDebugMLLog(@"GSTcpHandleLock",@"lock %@ in %@",X,[NSThread currentThread]); [X lock];}
|
||||
#define M_UNLOCK(X) {NSDebugMLLog(@"GSTcpHandleLock",@"unlock %@ in %@",X,[NSThread currentThread]); [X unlock];}
|
||||
|
@ -200,9 +205,15 @@ typedef enum {
|
|||
GS_H_CONNECTED // Currently connected.
|
||||
} GSHandleState;
|
||||
|
||||
@interface NSSocketPort (GSTcpHandle)
|
||||
- (NSDictionary*) optionsForTLS;
|
||||
@end
|
||||
|
||||
@interface GSTcpHandle : NSObject <RunLoopEvents>
|
||||
{
|
||||
SOCKET desc; /* File descriptor for I/O. */
|
||||
NSData *cData; /* Connection data. */
|
||||
unsigned cLength; /* Connection data written. */
|
||||
unsigned wItem; /* Index of item being written. */
|
||||
NSMutableData *wData; /* Data object being written. */
|
||||
unsigned wLength; /* Ammount written so far. */
|
||||
|
@ -223,7 +234,6 @@ typedef enum {
|
|||
BOOL inReplyMode; /* Indicate when have addEvent self */
|
||||
BOOL readyToSend; /* Indicate when send */
|
||||
#endif
|
||||
|
||||
@public
|
||||
NSRecursiveLock *myLock; /* Lock for this handle. */
|
||||
BOOL caller; /* Did we connect to other end? */
|
||||
|
@ -232,6 +242,7 @@ typedef enum {
|
|||
NSSocketPort *sendPort;
|
||||
struct sockaddr sockAddr; /* Far end of connection. */
|
||||
NSString *defaultAddress;
|
||||
GSTLSSession *session; /* Session for encryption. */
|
||||
}
|
||||
|
||||
+ (GSTcpHandle*) handleWithDescriptor: (SOCKET)d;
|
||||
|
@ -253,9 +264,95 @@ typedef enum {
|
|||
- (NSSocketPort*) sendPort;
|
||||
- (void) setState: (GSHandleState)s;
|
||||
- (GSHandleState) state;
|
||||
- (void) setupTLS: (NSSocketPort*)opts asClient: (BOOL)outgoing;
|
||||
@end
|
||||
|
||||
|
||||
#if defined(HAVE_GNUTLS)
|
||||
|
||||
/* Callback to allow the TLS code to pull data from the remote system.
|
||||
* If the operation fails, this sets the error number.
|
||||
*/
|
||||
static ssize_t
|
||||
GSTLSHandlePull(gnutls_transport_ptr_t handle, void *buffer, size_t len)
|
||||
{
|
||||
ssize_t result = 0;
|
||||
GSTcpHandle *tls = (GSTcpHandle*)handle;
|
||||
int descriptor = [tls descriptor];
|
||||
|
||||
result = recv(descriptor, buffer, len, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
#if HAVE_GNUTLS_TRANSPORT_SET_ERRNO
|
||||
if (tls->session && tls->session->session)
|
||||
{
|
||||
int e;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* For windows, we need to map winsock errors to unix ones that
|
||||
* gnutls understands.
|
||||
*/
|
||||
e = WSAGetLastError();
|
||||
if (WSAEWOULDBLOCK == e)
|
||||
{
|
||||
e = EAGAIN;
|
||||
}
|
||||
else if (WSAEINTR == e)
|
||||
{
|
||||
e = EINTR;
|
||||
}
|
||||
#else
|
||||
e = errno;
|
||||
#endif
|
||||
gnutls_transport_set_errno (tls->session->session, e);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Callback to allow the TLS code to push data to the remote system.
|
||||
* If the operation fails, this sets the error number.
|
||||
*/
|
||||
static ssize_t
|
||||
GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
|
||||
{
|
||||
ssize_t result = 0;
|
||||
GSTcpHandle *tls = (GSTcpHandle*)handle;
|
||||
int descriptor = [tls descriptor];
|
||||
|
||||
result = send(descriptor, buffer, len, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
#if HAVE_GNUTLS_TRANSPORT_SET_ERRNO
|
||||
if (tls->session && tls->session->session)
|
||||
{
|
||||
int e;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* For windows, we need to map winsock errors to unix ones that
|
||||
* gnutls understands.
|
||||
*/
|
||||
e = WSAGetLastError();
|
||||
if (WSAEWOULDBLOCK == e)
|
||||
{
|
||||
e = EAGAIN;
|
||||
}
|
||||
else if (WSAEINTR == e)
|
||||
{
|
||||
e = EINTR;
|
||||
}
|
||||
#else
|
||||
e = errno;
|
||||
#endif
|
||||
gnutls_transport_set_errno(tls->session->session, e);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility functions for encoding and decoding ports.
|
||||
*/
|
||||
|
@ -696,6 +793,7 @@ static Class runLoopClass;
|
|||
{
|
||||
[self finalize];
|
||||
DESTROY(defaultAddress);
|
||||
DESTROY(cData);
|
||||
DESTROY(rData);
|
||||
DESTROY(rItems);
|
||||
DESTROY(wMsgs);
|
||||
|
@ -724,6 +822,11 @@ static Class runLoopClass;
|
|||
- (void) finalize
|
||||
{
|
||||
[self invalidate];
|
||||
if (session)
|
||||
{
|
||||
[session disconnect: NO];
|
||||
DESTROY(session);
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
if (event != WSA_INVALID_EVENT)
|
||||
{
|
||||
|
@ -804,7 +907,21 @@ static Class runLoopClass;
|
|||
* Now try to fill the buffer with data.
|
||||
*/
|
||||
bytes = [rData mutableBytes];
|
||||
res = recv(desc, bytes + rLength, want - rLength, 0);
|
||||
if (session)
|
||||
{
|
||||
if ([session handshake])
|
||||
{
|
||||
res = [session read: bytes + rLength length: want - rLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = recv(desc, bytes + rLength, want - rLength, 0);
|
||||
}
|
||||
if (res <= 0)
|
||||
{
|
||||
if (res == 0)
|
||||
|
@ -1070,7 +1187,7 @@ static Class runLoopClass;
|
|||
if (shouldDispatch == YES)
|
||||
{
|
||||
NSPortMessage *pm;
|
||||
NSSocketPort *rp = [self recvPort];
|
||||
NSSocketPort *rp = [self recvPort];
|
||||
|
||||
pm = [portMessageClass allocWithZone: NSDefaultMallocZone()];
|
||||
pm = [pm initWithSendPort: [self sendPort]
|
||||
|
@ -1123,29 +1240,72 @@ static Class runLoopClass;
|
|||
}
|
||||
else
|
||||
{
|
||||
NSData *d = newDataWithEncodedPort([self recvPort]);
|
||||
unsigned l;
|
||||
const void *b;
|
||||
|
||||
len = send(desc, [d bytes], [d length], 0);
|
||||
if (len == (int)[d length])
|
||||
{
|
||||
ASSIGN(defaultAddress, GSPrivateSockaddrHost(&sockAddr));
|
||||
NSDebugMLLog(@"GSTcpHandle",
|
||||
@"wrote %d bytes on 0x%"PRIxPTR, len, (NSUInteger)self);
|
||||
state = GS_H_CONNECTED;
|
||||
if (nil == cData)
|
||||
{
|
||||
ASSIGN(cData, newDataWithEncodedPort([self recvPort]));
|
||||
cLength = 0;
|
||||
}
|
||||
b = [cData bytes];
|
||||
l = [cData length];
|
||||
|
||||
if (session)
|
||||
{
|
||||
if ([session handshake])
|
||||
{
|
||||
len = [session write: b + cLength length: l - cLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state = GS_H_UNCON;
|
||||
NSLog(@"connect write attempt failed - %@",
|
||||
[NSError _last]);
|
||||
len = send(desc, b + cLength, l - cLength, 0);
|
||||
}
|
||||
if (len <= 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (WSAGetLastError() != WSAEINTR
|
||||
&& WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
#else
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
#endif /* !_WIN32 */
|
||||
{
|
||||
DESTROY(cData);
|
||||
state = GS_H_UNCON;
|
||||
NSLog(@"connect write attempt failed - %@",
|
||||
[NSError _last]);
|
||||
return;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
readyToSend = NO;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
}
|
||||
else
|
||||
{
|
||||
cLength += len;
|
||||
if (cLength >= l)
|
||||
{
|
||||
DESTROY(cData);
|
||||
ASSIGN(defaultAddress, GSPrivateSockaddrHost(&sockAddr));
|
||||
NSDebugMLLog(@"GSTcpHandle",
|
||||
@"wrote %d bytes on 0x%"PRIxPTR, len, (NSUInteger)self);
|
||||
state = GS_H_CONNECTED;
|
||||
}
|
||||
}
|
||||
RELEASE(d);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int res;
|
||||
unsigned l;
|
||||
unsigned l;
|
||||
const void *b;
|
||||
|
||||
if (wData == nil)
|
||||
|
@ -1165,7 +1325,21 @@ static Class runLoopClass;
|
|||
}
|
||||
b = [wData bytes];
|
||||
l = [wData length];
|
||||
res = send(desc, b + wLength, l - wLength, 0);
|
||||
if (session)
|
||||
{
|
||||
if ([session handshake])
|
||||
{
|
||||
res = [session write: b + wLength length: l - wLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = send(desc, b + wLength, l - wLength, 0);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -1424,6 +1598,20 @@ static Class runLoopClass;
|
|||
state = s;
|
||||
}
|
||||
|
||||
- (void) setupTLS: (NSSocketPort*)port asClient: (BOOL)outgoing
|
||||
{
|
||||
NSDictionary *opts;
|
||||
|
||||
if (nil == session && (opts = [port optionsForTLS]) != nil)
|
||||
{
|
||||
session = [[GSTLSSession alloc] initWithOptions: opts
|
||||
direction: outgoing
|
||||
transport: (void*)self
|
||||
push: GSTLSHandlePush
|
||||
pull: GSTLSHandlePull];
|
||||
}
|
||||
}
|
||||
|
||||
- (GSHandleState) state
|
||||
{
|
||||
return state;
|
||||
|
@ -1700,6 +1888,7 @@ static Class tcpPortClass;
|
|||
NSMapInsert(thePorts, (void*)aHost, (void*)port);
|
||||
NSDebugMLLog(@"NSPort", @"Created speaking port: %@", port);
|
||||
}
|
||||
[port setOptionsForTLS: tlsOptions];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1712,6 +1901,11 @@ static Class tcpPortClass;
|
|||
return port;
|
||||
}
|
||||
|
||||
+ (void) setOptionsForTLS: (NSDictionary*)options
|
||||
{
|
||||
ASSIGNCOPY(tlsOptions, options);
|
||||
}
|
||||
|
||||
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send
|
||||
{
|
||||
M_LOCK(myLock);
|
||||
|
@ -1774,6 +1968,7 @@ static Class tcpPortClass;
|
|||
NSFreeMapTable(handles);
|
||||
handles = 0;
|
||||
}
|
||||
DESTROY(tlsopts);
|
||||
DESTROY(host);
|
||||
TEST_RELEASE(address);
|
||||
DESTROY(myLock);
|
||||
|
@ -1959,6 +2154,7 @@ static Class tcpPortClass;
|
|||
}
|
||||
else
|
||||
{
|
||||
[handle setupTLS: self asClient: YES];
|
||||
[recvPort addHandle: handle forSend: NO];
|
||||
}
|
||||
M_UNLOCK(myLock);
|
||||
|
@ -2085,6 +2281,16 @@ static Class tcpPortClass;
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (NSDictionary*) optionsForTLS
|
||||
{
|
||||
NSDictionary *opts;
|
||||
|
||||
M_LOCK(myLock);
|
||||
opts = RETAIN(tlsopts);
|
||||
M_UNLOCK(myLock);
|
||||
return AUTORELEASE(opts);
|
||||
}
|
||||
|
||||
- (uint16_t) portNumber
|
||||
{
|
||||
return portNum;
|
||||
|
@ -2142,8 +2348,8 @@ static Class tcpPortClass;
|
|||
handle = [GSTcpHandle handleWithDescriptor: desc];
|
||||
memcpy(&handle->sockAddr, &sockAddr, sizeof(sockAddr));
|
||||
ASSIGN(handle->defaultAddress, GSPrivateSockaddrHost(&sockAddr));
|
||||
|
||||
[handle setState: GS_H_ACCEPT];
|
||||
[handle setupTLS: self asClient: NO];
|
||||
[self addHandle: handle forSend: NO];
|
||||
}
|
||||
}
|
||||
|
@ -2437,4 +2643,13 @@ static Class tcpPortClass;
|
|||
return sent;
|
||||
}
|
||||
|
||||
/** Sets the TLS options for network connections created by this port.
|
||||
*/
|
||||
- (void) setOptionsForTLS: (NSDictionary*)options
|
||||
{
|
||||
M_LOCK(myLock);
|
||||
ASSIGNCOPY(tlsopts, options);
|
||||
M_UNLOCK(myLock);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue