Skip to content

Commit 193da17

Browse files
committed
Improve TLS handling
1 parent 0b52058 commit 193da17

8 files changed

Lines changed: 93 additions & 42 deletions

File tree

ChangeLog

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
2026-05-09 Richard Frith-Macdonald <rfm@gnu.org>
2+
3+
* Source/GSSocketStream.m:
4+
* Source/GSTLS.m:
5+
* Source/NSFileHandle.m:
6+
* Source/NSURLProtocol.m:
7+
* Source/unix/NSStream.m:
8+
* Source/win32/NSStream.m:
9+
* Tests/base/NSStream/socket.m:
10+
Usability tweaks, including setting the host name requested for the
11+
TLS connection automatically if not specified. This is needed for
12+
servers with multiple names which want to know which hostname a
13+
request was intended for.
14+
115
2026-05-08 Richard Frith-Macdonald <rfm@gnu.org>
216

317
* Source/GSTLS.m: Enable strict host certificate verification by

Source/GSSocketStream.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,11 @@ - (id) propertyForKey: (NSString *)key
18101810
{
18111811
result = GSPrivateSockaddrHost((struct sockaddr*)&sin);
18121812
}
1813+
else
1814+
{
1815+
// Assume we are not yet connected.
1816+
result = GSPrivateSockaddrHost((struct sockaddr*)&_address);
1817+
}
18131818
}
18141819
else if ([key isEqualToString: GSStreamRemotePortKey])
18151820
{

Source/GSTLS.m

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,8 +1524,7 @@ - (BOOL) trust
15241524
m = [NSMutableString stringWithCapacity: 2000];
15251525
for (i = 0; i < count; i++)
15261526
{
1527-
[GSTLSCertificateList certInfo: crts[i]
1528-
to: m];
1527+
[GSTLSCertificateList certInfo: crts[i] to: m];
15291528
}
15301529
if (0 == count)
15311530
{
@@ -2319,19 +2318,31 @@ - (NSString*) sessionInfo
23192318
{
23202319
unsigned int cert_list_size = 0;
23212320
const gnutls_datum_t *cert_list;
2322-
gnutls_x509_crt_t cert;
23232321

23242322
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
2323+
[str appendString: @"- "];
23252324
if (0 == cert_list_size)
23262325
{
2327-
[str appendString: _(@"- Peer provided no certificate.\n")];
2326+
[str appendString: _(@"Peer provided no certificate.")];
2327+
[str appendString: @"\n"];
23282328
}
23292329
else
23302330
{
23312331
int cert_num;
23322332

2333+
if (cert_list_size > 1)
2334+
{
2335+
[str appendString: _(@"Peer certificates")];
2336+
}
2337+
else
2338+
{
2339+
[str appendString: _(@"Peer certificate")];
2340+
}
2341+
[str appendString: @"\n"];
23332342
for (cert_num = 0; cert_num < cert_list_size; cert_num++)
23342343
{
2344+
gnutls_x509_crt_t cert;
2345+
23352346
gnutls_x509_crt_init(&cert);
23362347
/* NB. the list of peer certificate is in memory in native
23372348
* format (DER) rather than the normal file format (PEM).
@@ -2373,6 +2384,7 @@ - (NSString*) sessionInfo
23732384
- (int) verify
23742385
{
23752386
NSArray *names;
2387+
NSString *nameList;
23762388
NSString *str;
23772389
NSMutableString *ci;
23782390
unsigned int status;
@@ -2494,16 +2506,16 @@ - (int) verify
24942506
ci = [NSMutableString stringWithCapacity: 2000];
24952507
[GSTLSCertificateList certInfo: cert to: ci];
24962508

2497-
str = [opts objectForKey: GSTLSRemoteHosts];
2498-
if (nil == str)
2509+
nameList = [opts objectForKey: GSTLSRemoteHosts];
2510+
if (nil == nameList)
24992511
{
25002512
/* If nothing is specified, assume the connection host name
25012513
* (if any) should be used for verification.
25022514
*/
2503-
str = [opts objectForKey: GSTLSServerName];
2504-
if ([str length] > 0)
2515+
nameList = [opts objectForKey: GSTLSServerName];
2516+
if ([nameList length] > 0)
25052517
{
2506-
names = [NSArray arrayWithObject: str];
2518+
names = [NSArray arrayWithObject: nameList];
25072519
}
25082520
else
25092521
{
@@ -2515,7 +2527,7 @@ - (int) verify
25152527
/* The string is a comma separated list of permitted host names.
25162528
* If explicitly set to be empty, no host verification is done.
25172529
*/
2518-
names = [str componentsSeparatedByString: @","];
2530+
names = [nameList componentsSeparatedByString: @","];
25192531
if ([names count] == 0)
25202532
{
25212533
names = nil;
@@ -2540,7 +2552,7 @@ - (int) verify
25402552
{
25412553
str = [NSString stringWithFormat:
25422554
@"TLS verification: hostname does not match '%@' in %@",
2543-
names, ci];
2555+
nameList, ci];
25442556
ASSIGN(problem, str);
25452557
gnutls_x509_crt_deinit(cert);
25462558
if (YES == debug) NSLog(@"%p %@", handle, problem);

Source/NSFileHandle.m

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#import "common.h"
2828
#define EXPOSE_NSFileHandle_IVARS 1
29+
#import "Foundation/NSAutoreleasePool.h"
2930
#import "Foundation/NSData.h"
3031
#import "Foundation/NSException.h"
3132
#import "Foundation/NSHost.h"
@@ -1137,26 +1138,20 @@ - (BOOL) sslHandshakeEstablished: (BOOL*)result outgoing: (BOOL)isOutgoing
11371138
*/
11381139
if (nil == session)
11391140
{
1140-
/* If No value is specified for GSTLSRemoteHosts, make a comma separated
1141-
* list of all known names for the remote host and use that.
1141+
/* If no value is specified for GSTLSServerName, try to use any name of
1142+
* the remote host in case the remote server requres a name.
11421143
*/
1143-
if (nil == [opts objectForKey: GSTLSRemoteHosts])
1144+
if (nil == [opts objectForKey: GSTLSServerName])
11441145
{
11451146
NSHost *host = [NSHost hostWithAddress: [self socketAddress]];
1146-
NSString *s = [[host names] description];
1147+
NSString *name = [host name];
11471148

1148-
s = [s stringByReplacingString: @"\"" withString: @""];
1149-
if ([s length] > 1)
1149+
if (name)
11501150
{
1151-
s = [s substringWithRange: NSMakeRange(1, [s length] - 2)];
1152-
}
1153-
if ([s length] > 0)
1154-
{
1155-
NSMutableDictionary *d = [opts mutableCopy];
1151+
NSMutableDictionary *d = AUTORELEASE([opts mutableCopy]);
11561152

1157-
[d setObject:s forKey: GSTLSRemoteHosts];
1153+
[d setObject: name forKey: GSTLSRemoteHosts];
11581154
ASSIGNCOPY(opts, d);
1159-
[d release];
11601155
}
11611156
}
11621157
[self setNonBlocking: YES];

Source/NSURLProtocol.m

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,8 @@ - (void) startLoading
987987
{
988988
static NSArray *keys;
989989
NSUInteger count;
990+
NSString *key;
991+
NSString *val;
990992

991993
[this->input setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
992994
forKey: NSStreamSocketSecurityLevelKey];
@@ -1009,29 +1011,34 @@ - (void) startLoading
10091011
GSTLSVerify,
10101012
nil];
10111013
}
1012-
count = [keys count];
1013-
while (count-- > 0)
1014-
{
1015-
NSString *key = [keys objectAtIndex: count];
1016-
NSString *str = [this->request _propertyForKey: key];
1017-
1018-
if (nil != str)
1019-
{
1020-
[this->output setProperty: str forKey: key];
1021-
}
1022-
}
10231014
/* If there is no value set for the server name, and the host in the
10241015
* URL is a domain name rather than an address, we use that.
10251016
*/
1026-
if (nil == [this->output propertyForKey: GSTLSServerName])
1017+
key = GSTLSServerName;
1018+
if (nil == (val = [this->request _propertyForKey: key]))
10271019
{
10281020
NSString *host = [url host];
10291021
unichar c;
10301022

10311023
c = [host length] == 0 ? 0 : [host characterAtIndex: 0];
10321024
if (c != 0 && c != ':' && !isdigit(c))
10331025
{
1034-
[this->output setProperty: host forKey: GSTLSServerName];
1026+
[this->output setProperty: host forKey: key];
1027+
}
1028+
}
1029+
else
1030+
{
1031+
[this->output setProperty: val forKey: key];
1032+
}
1033+
count = [keys count];
1034+
while (count-- > 0)
1035+
{
1036+
key = [keys objectAtIndex: count];
1037+
val = [this->request _propertyForKey: key];
1038+
1039+
if (nil != val)
1040+
{
1041+
[this->output setProperty: val forKey: key];
10351042
}
10361043
}
10371044
if (_debug) [this->output setProperty: @"YES" forKey: GSTLSDebug];

Source/unix/NSStream.m

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#import "Foundation/NSByteOrder.h"
4949
#import "Foundation/NSURL.h"
5050
#import "GNUstepBase/NSObject+GNUstepBase.h"
51+
#import "GNUstepBase/GSTLS.h"
5152

5253
#import "../GSPrivate.h"
5354
#import "../GSStream.h"
@@ -401,9 +402,10 @@ + (void) getStreamsToHost: (NSHost *)host
401402
inputStream: (NSInputStream **)inputStream
402403
outputStream: (NSOutputStream **)outputStream
403404
{
404-
NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
405-
id ins = nil;
406-
id outs = nil;
405+
NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
406+
NSString *name = [host name];
407+
id ins = nil;
408+
id outs = nil;
407409

408410
// try ipv4 first
409411
ins = AUTORELEASE([[GSInetInputStream alloc]
@@ -419,6 +421,11 @@ + (void) getStreamsToHost: (NSHost *)host
419421
initToAddr: address port: port]);
420422
#endif
421423
}
424+
if (name)
425+
{
426+
if (ins) [ins setProperty: name forKey: GSTLSServerName];
427+
if (outs) [outs setProperty: name forKey: GSTLSServerName];
428+
}
422429

423430
if (inputStream)
424431
{

Source/win32/NSStream.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#import "Foundation/NSByteOrder.h"
3636
#import "Foundation/NSURL.h"
3737
#import "GNUstepBase/NSObject+GNUstepBase.h"
38+
#import "GNUstepBase/GSTLS.h"
3839

3940
#import "../GSPrivate.h"
4041
#import "../GSStream.h"
@@ -939,7 +940,8 @@ + (void) getStreamsToHost: (NSHost *)host
939940
inputStream: (NSInputStream **)inputStream
940941
outputStream: (NSOutputStream **)outputStream
941942
{
942-
NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
943+
NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
944+
NSString *name = [host name];
943945
GSSocketStream *ins = nil;
944946
GSSocketStream *outs = nil;
945947
int sock;
@@ -959,6 +961,11 @@ + (void) getStreamsToHost: (NSHost *)host
959961
initToAddr: address port: port]);
960962
#endif
961963
}
964+
if (name)
965+
{
966+
if (ins) [ins setProperty: name forKey: GSTLSServerName];
967+
if (outs) [outs setProperty: name forKey: GSTLSServerName];
968+
}
962969

963970
/*
964971
* Windows only permits a single event to be associated with a socket

Tests/base/NSStream/socket.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ int main()
164164
[defaultOutput setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
165165
forKey: NSStreamSocketSecurityLevelKey];
166166

167-
[defaultOutput setProperty: name forKey: GSTLSServerName];
167+
/* Our getStreamsToHost:port:inputStream:outputStream: does this using some
168+
* randomly selected name fo the host. To use a specific name we may want
169+
* an override here.
170+
* [defaultOutput setProperty: name forKey: GSTLSServerName];
171+
*/
168172
[defaultInput open];
169173
[defaultOutput open];
170174

0 commit comments

Comments
 (0)