mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-06-16 21:50:57 +00:00
Require cert pinning for HTTPS
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
@interface HttpManager : NSObject <NSURLSessionDelegate>
|
@interface HttpManager : NSObject <NSURLSessionDelegate>
|
||||||
|
|
||||||
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert;
|
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert;
|
||||||
|
- (void) setServerCert:(NSData*) serverCert;
|
||||||
- (NSURLRequest*) newPairRequest:(NSData*)salt clientCert:(NSData*)clientCert;
|
- (NSURLRequest*) newPairRequest:(NSData*)salt clientCert:(NSData*)clientCert;
|
||||||
- (NSURLRequest*) newUnpairRequest;
|
- (NSURLRequest*) newUnpairRequest;
|
||||||
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge;
|
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge;
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
- (NSURLRequest*) newPairChallenge;
|
- (NSURLRequest*) newPairChallenge;
|
||||||
- (NSURLRequest*) newAppListRequest;
|
- (NSURLRequest*) newAppListRequest;
|
||||||
- (NSURLRequest*) newServerInfoRequest:(bool)fastFail;
|
- (NSURLRequest*) newServerInfoRequest:(bool)fastFail;
|
||||||
|
- (NSURLRequest*) newHttpServerInfoRequest:(bool)fastFail;
|
||||||
- (NSURLRequest*) newHttpServerInfoRequest;
|
- (NSURLRequest*) newHttpServerInfoRequest;
|
||||||
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config;
|
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config;
|
||||||
- (NSURLRequest*) newResumeRequest:(StreamConfiguration*)config;
|
- (NSURLRequest*) newResumeRequest:(StreamConfiguration*)config;
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
return [xmlString dataUsingEncoding:NSUTF8StringEncoding];
|
return [xmlString dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setServerCert:(NSData*) serverCert {
|
||||||
|
_serverCert = serverCert;
|
||||||
|
}
|
||||||
|
|
||||||
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert {
|
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
_uniqueId = uniqueId;
|
_uniqueId = uniqueId;
|
||||||
@@ -120,6 +124,9 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest*) createRequestFromString:(NSString*) urlString timeout:(int)timeout {
|
- (NSURLRequest*) createRequestFromString:(NSString*) urlString timeout:(int)timeout {
|
||||||
|
// Assert that we only issue HTTPS requests with a pinned cert
|
||||||
|
assert([urlString hasPrefix:@"http://"] || _serverCert != nil);
|
||||||
|
|
||||||
NSURL* url = [[NSURL alloc] initWithString:urlString];
|
NSURL* url = [[NSURL alloc] initWithString:urlString];
|
||||||
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
||||||
[request setTimeoutInterval:timeout];
|
[request setTimeoutInterval:timeout];
|
||||||
@@ -134,7 +141,7 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest*) newUnpairRequest {
|
- (NSURLRequest*) newUnpairRequest {
|
||||||
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseHTTPSURL, _uniqueId];
|
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseHTTPURL, _uniqueId];
|
||||||
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
|
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,13 +173,22 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest *)newServerInfoRequest:(bool)fastFail {
|
- (NSURLRequest *)newServerInfoRequest:(bool)fastFail {
|
||||||
|
if (_serverCert == nil) {
|
||||||
|
// Use HTTP if the cert is not pinned yet
|
||||||
|
return [self newHttpServerInfoRequest:fastFail];
|
||||||
|
}
|
||||||
|
|
||||||
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseHTTPSURL, _uniqueId];
|
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseHTTPSURL, _uniqueId];
|
||||||
return [self createRequestFromString:urlString timeout:(fastFail ? SHORT_TIMEOUT_SEC : NORMAL_TIMEOUT_SEC)];
|
return [self createRequestFromString:urlString timeout:(fastFail ? SHORT_TIMEOUT_SEC : NORMAL_TIMEOUT_SEC)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest *)newHttpServerInfoRequest {
|
- (NSURLRequest *)newHttpServerInfoRequest:(bool)fastFail {
|
||||||
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo", _baseHTTPURL];
|
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo", _baseHTTPURL];
|
||||||
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
|
return [self createRequestFromString:urlString timeout:(fastFail ? SHORT_TIMEOUT_SEC : NORMAL_TIMEOUT_SEC)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURLRequest *)newHttpServerInfoRequest {
|
||||||
|
return [self newHttpServerInfoRequest:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config {
|
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config {
|
||||||
@@ -259,25 +275,35 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
// Allow untrusted server certificates
|
// Allow untrusted server certificates
|
||||||
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
|
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
|
||||||
{
|
{
|
||||||
if (_serverCert) {
|
if (SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust) != 1) {
|
||||||
SecCertificateRef actualCert = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0);
|
Log(LOG_E, @"Server certificate count mismatch");
|
||||||
|
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
||||||
CFDataRef actualCertData;
|
return;
|
||||||
|
|
||||||
actualCertData = SecCertificateCopyData(actualCert);
|
|
||||||
|
|
||||||
if (!CFEqual(actualCertData, (__bridge CFDataRef)_serverCert)) {
|
|
||||||
Log(LOG_E, @"Server certificate mismatch");
|
|
||||||
CFRelease(actualCertData);
|
|
||||||
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(actualCertData);
|
|
||||||
|
|
||||||
// Fall-through to TLS success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SecCertificateRef actualCert = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0);
|
||||||
|
if (actualCert == nil) {
|
||||||
|
Log(LOG_E, @"Server certificate parsing error");
|
||||||
|
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFDataRef actualCertData = SecCertificateCopyData(actualCert);
|
||||||
|
if (actualCertData == nil) {
|
||||||
|
Log(LOG_E, @"Server certificate data parsing error");
|
||||||
|
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CFEqual(actualCertData, (__bridge CFDataRef)_serverCert)) {
|
||||||
|
Log(LOG_E, @"Server certificate mismatch");
|
||||||
|
CFRelease(actualCertData);
|
||||||
|
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(actualCertData);
|
||||||
|
|
||||||
// Allow TLS handshake to proceed
|
// Allow TLS handshake to proceed
|
||||||
completionHandler(NSURLSessionAuthChallengeUseCredential,
|
completionHandler(NSURLSessionAuthChallengeUseCredential,
|
||||||
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
|
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
|
||||||
|
|||||||
@@ -78,6 +78,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pin the cert for TLS usage on this host
|
||||||
|
NSData* derCertBytes = [CryptoManager pemToDer:[Utils hexToBytes:plainCert]];
|
||||||
|
[_httpManager setServerCert:derCertBytes];
|
||||||
|
|
||||||
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
|
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
|
||||||
NSData* aesKey;
|
NSData* aesKey;
|
||||||
|
|
||||||
@@ -181,7 +185,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_callback pairSuccessful: [CryptoManager pemToDer:[Utils hexToBytes:plainCert]]];
|
[_callback pairSuccessful: derCertBytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
|
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
|
||||||
|
|||||||
Reference in New Issue
Block a user