Skip to content

Commit 1cba49a

Browse files
committed
Adding experiment support for certificate pinning
1 parent 3365b25 commit 1cba49a

2 files changed

Lines changed: 83 additions & 3 deletions

File tree

SocketRocket/SRWebSocket.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616

1717
#import <Foundation/Foundation.h>
18+
#import <Security/SecCertificate.h>
1819

1920
typedef enum {
2021
SR_CONNECTING = 0,
@@ -60,3 +61,17 @@ extern NSString *const SRWebSocketErrorDomain;
6061
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
6162

6263
@end
64+
65+
66+
@interface NSURLRequest (CertificateAdditions)
67+
68+
@property (nonatomic, retain, readonly) NSArray *SR_SSLPinnedCertificates;
69+
70+
@end
71+
72+
73+
@interface NSMutableURLRequest (CertificateAdditions)
74+
75+
@property (nonatomic, retain) NSArray *SR_SSLPinnedCertificates;
76+
77+
@end

SocketRocket/SRWebSocket.m

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,14 +488,24 @@ - (void)_connectToHost:(NSString *)host port:(NSInteger)port;
488488
_outputStream = CFBridgingRelease(writeStream);
489489
_inputStream = CFBridgingRelease(readStream);
490490

491+
491492
if (_secure) {
493+
NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init];
494+
492495
[_outputStream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel];
496+
497+
// If we're using pinned certs, don't validate the certificate chain
498+
if ([_urlRequest SR_SSLPinnedCertificates].count) {
499+
[SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
500+
}
501+
493502
#if DEBUG
503+
[SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain];
494504
NSLog(@"SocketRocket: In debug mode. Allowing connection to any root cert");
495-
[_outputStream setProperty:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
496-
forKey:(__bridge id)kCFStreamSSLAllowsAnyRoot]
497-
forKey:(__bridge id)kCFStreamPropertySSLSettings];
498505
#endif
506+
507+
[_outputStream setProperty:SSLOptions
508+
forKey:(__bridge id)kCFStreamPropertySSLSettings];
499509
}
500510

501511
_inputStream.delegate = self;
@@ -1232,6 +1242,10 @@ - (void)_sendFrameWithOpcode:(SROpCode)opcode data:(id)data;
12321242
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;
12331243
{
12341244
// SRFastLog(@"%@ Got stream event %d", aStream, eventCode);
1245+
if (eventCode == NSStreamEventErrorOccurred || eventCode == NSStreamEventErrorOccurred) {
1246+
1247+
1248+
}
12351249
dispatch_async(_workQueue, ^{
12361250
switch (eventCode) {
12371251
case NSStreamEventOpenCompleted: {
@@ -1240,6 +1254,35 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;
12401254
return;
12411255
}
12421256

1257+
1258+
if (_secure && aStream == _outputStream) {
1259+
NSArray *sslCerts = [_urlRequest SR_SSLPinnedCertificates];
1260+
if (sslCerts) {
1261+
SecTrustRef secTrust = (__bridge SecTrustRef)[aStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust];
1262+
BOOL found = NO;
1263+
if (secTrust) {
1264+
NSInteger numCerts = SecTrustGetCertificateCount(secTrust);
1265+
for (NSInteger i = 0; i < numCerts && !found; i++) {
1266+
SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrust, i);
1267+
NSData *certData = CFBridgingRelease(SecCertificateCopyData(cert));
1268+
1269+
for (id ref in sslCerts) {
1270+
SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref;
1271+
NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert));
1272+
1273+
if ([trustedCertData isEqualToData:certData]) {
1274+
found = YES;
1275+
}
1276+
}
1277+
}
1278+
}
1279+
1280+
if (!found) {
1281+
[self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:23556 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Invalid server cert"] forKey:NSLocalizedDescriptionKey]]];
1282+
}
1283+
}
1284+
1285+
}
12431286
assert(_readBuffer);
12441287

12451288
if (self.readyState == SR_CONNECTING && aStream == _inputStream) {
@@ -1347,4 +1390,26 @@ - (id)initWithScanner:(stream_scanner)scanner handler:(data_callback)handler byt
13471390
@end
13481391

13491392

1393+
@implementation NSURLRequest (CertificateAdditions)
1394+
1395+
- (NSArray *)SR_SSLPinnedCertificates;
1396+
{
1397+
return [NSURLProtocol propertyForKey:@"SR_SSLPinnedCertificates" inRequest:self];
1398+
}
1399+
1400+
@end
1401+
1402+
@implementation NSMutableURLRequest (CertificateAdditions)
1403+
1404+
- (NSArray *)SR_SSLPinnedCertificates;
1405+
{
1406+
return [NSURLProtocol propertyForKey:@"SR_SSLPinnedCertificates" inRequest:self];
1407+
}
1408+
1409+
- (void)setSR_SSLPinnedCertificates:(NSArray *)SR_SSLPinnedCertificates;
1410+
{
1411+
[NSURLProtocol setProperty:SR_SSLPinnedCertificates forKey:@"SR_SSLPinnedCertificates" inRequest:self];
1412+
}
1413+
1414+
@end
13501415

0 commit comments

Comments
 (0)