mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-02-16 10:31:02 +00:00
Require cert pinning for HTTPS
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
@interface HttpManager : NSObject <NSURLSessionDelegate>
|
||||
|
||||
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert;
|
||||
- (void) setServerCert:(NSData*) serverCert;
|
||||
- (NSURLRequest*) newPairRequest:(NSData*)salt clientCert:(NSData*)clientCert;
|
||||
- (NSURLRequest*) newUnpairRequest;
|
||||
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge;
|
||||
@@ -21,6 +22,7 @@
|
||||
- (NSURLRequest*) newPairChallenge;
|
||||
- (NSURLRequest*) newAppListRequest;
|
||||
- (NSURLRequest*) newServerInfoRequest:(bool)fastFail;
|
||||
- (NSURLRequest*) newHttpServerInfoRequest:(bool)fastFail;
|
||||
- (NSURLRequest*) newHttpServerInfoRequest;
|
||||
- (NSURLRequest*) newLaunchRequest:(StreamConfiguration*)config;
|
||||
- (NSURLRequest*) newResumeRequest:(StreamConfiguration*)config;
|
||||
|
||||
@@ -43,6 +43,10 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
return [xmlString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (void) setServerCert:(NSData*) serverCert {
|
||||
_serverCert = serverCert;
|
||||
}
|
||||
|
||||
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert {
|
||||
self = [super init];
|
||||
_uniqueId = uniqueId;
|
||||
@@ -120,6 +124,9 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
}
|
||||
|
||||
- (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];
|
||||
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
||||
[request setTimeoutInterval:timeout];
|
||||
@@ -134,7 +141,7 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
|
||||
@@ -166,13 +173,22 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
}
|
||||
|
||||
- (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];
|
||||
return [self createRequestFromString:urlString timeout:(fastFail ? SHORT_TIMEOUT_SEC : NORMAL_TIMEOUT_SEC)];
|
||||
}
|
||||
|
||||
- (NSURLRequest *)newHttpServerInfoRequest {
|
||||
- (NSURLRequest *)newHttpServerInfoRequest:(bool)fastFail {
|
||||
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 {
|
||||
@@ -259,25 +275,35 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
// Allow untrusted server certificates
|
||||
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
|
||||
{
|
||||
if (_serverCert) {
|
||||
SecCertificateRef actualCert = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0);
|
||||
|
||||
CFDataRef actualCertData;
|
||||
|
||||
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
|
||||
if (SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust) != 1) {
|
||||
Log(LOG_E, @"Server certificate count mismatch");
|
||||
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
completionHandler(NSURLSessionAuthChallengeUseCredential,
|
||||
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
|
||||
|
||||
@@ -78,6 +78,10 @@
|
||||
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];
|
||||
NSData* aesKey;
|
||||
|
||||
@@ -181,7 +185,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
[_callback pairSuccessful: [CryptoManager pemToDer:[Utils hexToBytes:plainCert]]];
|
||||
[_callback pairSuccessful: derCertBytes];
|
||||
}
|
||||
|
||||
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
|
||||
|
||||
Reference in New Issue
Block a user