diff --git a/Limelight/Crypto/CryptoManager.h b/Limelight/Crypto/CryptoManager.h
index 6e84804..b1fc76d 100644
--- a/Limelight/Crypto/CryptoManager.h
+++ b/Limelight/Crypto/CryptoManager.h
@@ -13,7 +13,7 @@
+ (NSData*) readKeyFromFile;
+ (NSData*) readP12FromFile;
+ (NSData*) getSignatureFromCert:(NSData*)cert;
-+ (NSData*) nullTerminateString:(NSData*)data;
++ (NSData*) pemToDer:(NSData*)pemCertBytes;
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
diff --git a/Limelight/Crypto/CryptoManager.m b/Limelight/Crypto/CryptoManager.m
index 5e5367e..9f7c5db 100644
--- a/Limelight/Crypto/CryptoManager.m
+++ b/Limelight/Crypto/CryptoManager.m
@@ -87,17 +87,28 @@ static NSData* p12 = nil;
return (((int)[data length] + 15) / 16) * 16;
}
-+ (NSData*) nullTerminateString:(NSData*)data {
- NSMutableData* mutData = [NSMutableData dataWithData:data];
- [mutData appendBytes:"" length:1];
- return mutData;
++ (NSData*) pemToDer:(NSData*)pemCertBytes {
+ X509* x509;
+
+ BIO* bio = BIO_new_mem_buf([pemCertBytes bytes], (int)[pemCertBytes length]);
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+
+ bio = BIO_new(BIO_s_mem());
+ i2d_X509_bio(bio, x509);
+
+ BUF_MEM* mem;
+ BIO_get_mem_ptr(bio, &mem);
+
+ NSData* ret = [[NSData alloc] initWithBytes:mem->data length:mem->length];
+ BIO_free(bio);
+
+ return ret;
}
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert {
- const char* buffer = [[CryptoManager nullTerminateString:cert] bytes];
X509* x509;
- BIO* bio = BIO_new(BIO_s_mem());
- BIO_puts(bio, buffer);
+ BIO* bio = BIO_new_mem_buf([cert bytes], (int)[cert length]);
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
BIO_free(bio);
@@ -122,9 +133,7 @@ static NSData* p12 = nil;
}
- (NSData *)signData:(NSData *)data withKey:(NSData *)key {
- const char* buffer = [[CryptoManager nullTerminateString:key] bytes];
- BIO* bio = BIO_new(BIO_s_mem());
- BIO_puts(bio, buffer);
+ BIO* bio = BIO_new_mem_buf([key bytes], (int)[key length]);
EVP_PKEY* pkey;
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
@@ -211,11 +220,8 @@ static NSData* p12 = nil;
}
+ (NSData *)getSignatureFromCert:(NSData *)cert {
- const char* buffer = [[CryptoManager nullTerminateString:cert] bytes];
- X509* x509;
- BIO* bio = BIO_new(BIO_s_mem());
- BIO_puts(bio, buffer);
- x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO* bio = BIO_new_mem_buf([cert bytes], (int)[cert length]);
+ X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (!x509) {
Log(LOG_E, @"Unable to parse certificate in memory!");
diff --git a/Limelight/Database/TemporaryHost.h b/Limelight/Database/TemporaryHost.h
index 6062cda..f029427 100644
--- a/Limelight/Database/TemporaryHost.h
+++ b/Limelight/Database/TemporaryHost.h
@@ -16,15 +16,17 @@
@property (nonatomic, nullable) NSString * activeAddress;
@property (nonatomic, nullable) NSString * currentGame;
+@property (nonatomic, nullable, retain) NSData *serverCert;
+@property (nonatomic, nullable, retain) NSString *address;
+@property (nonatomic, nullable, retain) NSString *externalAddress;
+@property (nonatomic, nullable, retain) NSString *localAddress;
+@property (nonatomic, nullable, retain) NSString *mac;
+@property (nonatomic) int serverCodecModeSupport;
+
NS_ASSUME_NONNULL_BEGIN
-@property (nonatomic, retain) NSString *address;
-@property (nonatomic, retain) NSString *externalAddress;
-@property (nonatomic, retain) NSString *localAddress;
-@property (nonatomic, retain) NSString *mac;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *uuid;
-@property (nonatomic) int serverCodecModeSupport;
@property (nonatomic, retain) NSMutableSet *appList;
- (id) initFromHost:(Host*)host;
diff --git a/Limelight/Database/TemporaryHost.m b/Limelight/Database/TemporaryHost.m
index c8d6ccb..4b9988f 100644
--- a/Limelight/Database/TemporaryHost.m
+++ b/Limelight/Database/TemporaryHost.m
@@ -31,6 +31,7 @@
self.uuid = host.uuid;
self.pairState = [host.pairState intValue];
self.serverCodecModeSupport = host.serverCodecModeSupport;
+ self.serverCert = host.serverCert;
NSMutableSet *appList = [[NSMutableSet alloc] init];
@@ -60,6 +61,9 @@
if (self.mac != nil) {
parentHost.mac = self.mac;
}
+ if (self.serverCert != nil) {
+ parentHost.serverCert = self.serverCert;
+ }
parentHost.name = self.name;
parentHost.uuid = self.uuid;
parentHost.serverCodecModeSupport = self.serverCodecModeSupport;
diff --git a/Limelight/Limelight.xcdatamodeld/.xccurrentversion b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
index 3bc8a00..fe08733 100644
--- a/Limelight/Limelight.xcdatamodeld/.xccurrentversion
+++ b/Limelight/Limelight.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- Moonlight v1.2.xcdatamodel
+ Moonlight v1.3.xcdatamodel
diff --git a/Limelight/Limelight.xcdatamodeld/Moonlight v1.3.xcdatamodel/contents b/Limelight/Limelight.xcdatamodeld/Moonlight v1.3.xcdatamodel/contents
new file mode 100644
index 0000000..9eee4f1
--- /dev/null
+++ b/Limelight/Limelight.xcdatamodeld/Moonlight v1.3.xcdatamodel/contents
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Limelight/Network/AppAssetRetriever.m b/Limelight/Network/AppAssetRetriever.m
index 30dce85..6888383 100644
--- a/Limelight/Network/AppAssetRetriever.m
+++ b/Limelight/Network/AppAssetRetriever.m
@@ -20,7 +20,7 @@ static const int MAX_ATTEMPTS = 5;
- (void) main {
int attempts = 0;
while (![self isCancelled] && attempts++ < MAX_ATTEMPTS) {
- HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[IdManager getUniqueId] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
+ HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[IdManager getUniqueId] serverCert:_host.serverCert];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
diff --git a/Limelight/Network/ConnectionHelper.h b/Limelight/Network/ConnectionHelper.h
index 65cc0d3..52fa67b 100644
--- a/Limelight/Network/ConnectionHelper.h
+++ b/Limelight/Network/ConnectionHelper.h
@@ -14,7 +14,7 @@
@interface ConnectionHelper : NSObject
-+(AppListResponse*) getAppListForHostWithHostIP:(NSString*) hostIP deviceName:(NSString*)deviceName cert:(NSData*) cert uniqueID:(NSString*) uniqueId;
++(AppListResponse*) getAppListForHostWithHostIP:(NSString*) hostIP serverCert:(NSData*) serverCert uniqueID:(NSString*) uniqueId;
@end
diff --git a/Limelight/Network/ConnectionHelper.m b/Limelight/Network/ConnectionHelper.m
index 83cc3bf..bb41539 100644
--- a/Limelight/Network/ConnectionHelper.m
+++ b/Limelight/Network/ConnectionHelper.m
@@ -14,8 +14,8 @@
@implementation ConnectionHelper
-+(AppListResponse*) getAppListForHostWithHostIP:(NSString*) hostIP deviceName:(NSString*)deviceName cert:(NSData*) cert uniqueID:(NSString*) uniqueId {
- HttpManager* hMan = [[HttpManager alloc] initWithHost:hostIP uniqueId:uniqueId deviceName:deviceName cert:cert];
++(AppListResponse*) getAppListForHostWithHostIP:(NSString*) hostIP serverCert:(NSData*) cert uniqueID:(NSString*) uniqueId {
+ HttpManager* hMan = [[HttpManager alloc] initWithHost:hostIP uniqueId:uniqueId serverCert:cert];
// Try up to 5 times to get the app list
AppListResponse* appListResp;
diff --git a/Limelight/Network/DiscoveryManager.m b/Limelight/Network/DiscoveryManager.m
index bc1cf41..ad19273 100644
--- a/Limelight/Network/DiscoveryManager.m
+++ b/Limelight/Network/DiscoveryManager.m
@@ -48,7 +48,7 @@
}
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(TemporaryHost *, NSString*))callback {
- HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
+ HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId serverCert:nil];
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest:false] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
@@ -183,7 +183,7 @@
}
- (NSOperation*) createWorkerForHost:(TemporaryHost*)host {
- DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
+ DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId];
return worker;
}
diff --git a/Limelight/Network/DiscoveryWorker.h b/Limelight/Network/DiscoveryWorker.h
index 40c4711..da6491d 100644
--- a/Limelight/Network/DiscoveryWorker.h
+++ b/Limelight/Network/DiscoveryWorker.h
@@ -10,7 +10,7 @@
@interface DiscoveryWorker : NSOperation
-- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
+- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId;
- (void) discoverHost;
- (TemporaryHost*) getHost;
diff --git a/Limelight/Network/DiscoveryWorker.m b/Limelight/Network/DiscoveryWorker.m
index 1a2e00f..9095146 100644
--- a/Limelight/Network/DiscoveryWorker.m
+++ b/Limelight/Network/DiscoveryWorker.m
@@ -16,16 +16,14 @@
@implementation DiscoveryWorker {
TemporaryHost* _host;
NSString* _uniqueId;
- NSData* _cert;
}
static const float POLL_RATE = 2.0f; // Poll every 2 seconds
-- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
+- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId {
self = [super init];
_host = host;
_uniqueId = uniqueId;
- _cert = cert;
return self;
}
@@ -98,7 +96,7 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
return;
}
- ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:address];
+ ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:address cert:_host.serverCert];
receivedResponse = [self checkResponse:serverInfoResp];
if (receivedResponse) {
[serverInfoResp populateHost:_host];
@@ -123,11 +121,10 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
}
}
-- (ServerInfoResponse*) requestInfoAtAddress:(NSString*)address {
+- (ServerInfoResponse*) requestInfoAtAddress:(NSString*)address cert:(NSData*)cert {
HttpManager* hMan = [[HttpManager alloc] initWithHost:address
uniqueId:_uniqueId
- deviceName:deviceName
- cert:_cert];
+ serverCert:cert];
ServerInfoResponse* response = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:response
withUrlRequest:[hMan newServerInfoRequest:true]
diff --git a/Limelight/Network/HttpManager.h b/Limelight/Network/HttpManager.h
index 3299c38..8328ded 100644
--- a/Limelight/Network/HttpManager.h
+++ b/Limelight/Network/HttpManager.h
@@ -12,8 +12,8 @@
@interface HttpManager : NSObject
-- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert;
-- (NSURLRequest*) newPairRequest:(NSData*)salt;
+- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert;
+- (NSURLRequest*) newPairRequest:(NSData*)salt clientCert:(NSData*)clientCert;
- (NSURLRequest*) newUnpairRequest;
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge;
- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp;
diff --git a/Limelight/Network/HttpManager.m b/Limelight/Network/HttpManager.m
index eca8387..6f679cc 100644
--- a/Limelight/Network/HttpManager.m
+++ b/Limelight/Network/HttpManager.m
@@ -25,12 +25,12 @@
NSString* _baseHTTPSURL;
NSString* _uniqueId;
NSString* _deviceName;
- NSData* _cert;
+ NSData* _serverCert;
NSMutableData* _respData;
NSData* _requestResp;
dispatch_semaphore_t _requestLock;
- BOOL _errorOccurred;
+ NSError* _error;
}
static const NSString* HTTP_PORT = @"47989";
@@ -43,11 +43,11 @@ static const NSString* HTTPS_PORT = @"47984";
return [xmlString dataUsingEncoding:NSUTF8StringEncoding];
}
-- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert {
+- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId serverCert:(NSData*) serverCert {
self = [super init];
_uniqueId = uniqueId;
_deviceName = deviceName;
- _cert = cert;
+ _serverCert = serverCert;
_requestLock = dispatch_semaphore_create(0);
_respData = [[NSMutableData alloc] init];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
@@ -68,13 +68,15 @@ static const NSString* HTTPS_PORT = @"47984";
}
- (void) executeRequestSynchronously:(HttpRequest*)request {
- Log(LOG_D, @"Making Request: %@", request);
[_respData setLength:0];
+ _error = nil;
+
+ Log(LOG_D, @"Making Request: %@", request);
[[_urlSession dataTaskWithRequest:request.request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
if (error != NULL) {
Log(LOG_D, @"Connection error: %@", error);
- self->_errorOccurred = true;
+ self->_error = error;
}
else {
Log(LOG_D, @"Received response: %@", response);
@@ -94,7 +96,7 @@ static const NSString* HTTPS_PORT = @"47984";
}] resume];
dispatch_semaphore_wait(_requestLock, DISPATCH_TIME_FOREVER);
- if (!_errorOccurred && request.response) {
+ if (!_error && request.response) {
[request.response populateWithData:_requestResp];
// If the fallback error code was detected, issue the fallback request
@@ -106,7 +108,15 @@ static const NSString* HTTPS_PORT = @"47984";
[self executeRequestSynchronously:request];
}
}
- _errorOccurred = false;
+ else if (_error && [_error code] == NSURLErrorServerCertificateUntrusted && request.fallbackRequest) {
+ // This will fall back to HTTP on serverinfo queries to allow us to pair again
+ // and get the server cert updated.
+ Log(LOG_D, @"Attempting fallback request after certificate trust failure");
+ request.request = request.fallbackRequest;
+ request.fallbackError = 0;
+ request.fallbackRequest = NULL;
+ [self executeRequestSynchronously:request];
+ }
}
- (NSURLRequest*) createRequestFromString:(NSString*) urlString timeout:(int)timeout {
@@ -116,9 +126,9 @@ static const NSString* HTTPS_PORT = @"47984";
return request;
}
-- (NSURLRequest*) newPairRequest:(NSData*)salt {
+- (NSURLRequest*) newPairRequest:(NSData*)salt clientCert:(NSData*)clientCert {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@",
- _baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
+ _baseHTTPURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:clientCert]];
// This call blocks while waiting for the user to input the PIN on the PC
return [self createRequestFromString:urlString timeout:EXTRA_LONG_TIMEOUT_SEC];
}
@@ -130,18 +140,18 @@ static const NSString* HTTPS_PORT = @"47984";
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@",
- _baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
+ _baseHTTPURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
}
- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@",
- _baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
+ _baseHTTPURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
}
- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret {
- NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseHTTPSURL, _uniqueId, _deviceName, clientPairSecret];
+ NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseHTTPURL, _uniqueId, _deviceName, clientPairSecret];
return [self createRequestFromString:urlString timeout:NORMAL_TIMEOUT_SEC];
}
@@ -249,6 +259,26 @@ 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
+ }
+
+ // Allow TLS handshake to proceed
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
}
diff --git a/Limelight/Network/PairManager.h b/Limelight/Network/PairManager.h
index bf1e84f..c137ff4 100644
--- a/Limelight/Network/PairManager.h
+++ b/Limelight/Network/PairManager.h
@@ -11,14 +11,14 @@
@protocol PairCallback
- (void) showPIN:(NSString*)PIN;
-- (void) pairSuccessful;
+- (void) pairSuccessful:(NSData*)serverCert;
- (void) pairFailed:(NSString*)message;
- (void) alreadyPaired;
@end
@interface PairManager : NSOperation
-- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id)callback;
+- (id) initWithManager:(HttpManager*)httpManager clientCert:(NSData*)clientCert callback:(id)callback;
- (NSString*) generatePIN;
- (NSData*) saltPIN:(NSString*)PIN;
- (void) initiatePair:(int)serverMajorVersion;
diff --git a/Limelight/Network/PairManager.m b/Limelight/Network/PairManager.m
index 6a55a26..cae5081 100644
--- a/Limelight/Network/PairManager.m
+++ b/Limelight/Network/PairManager.m
@@ -17,14 +17,14 @@
@implementation PairManager {
HttpManager* _httpManager;
- NSData* _cert;
+ NSData* _clientCert;
id _callback;
}
-- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id)callback {
+- (id) initWithManager:(HttpManager*)httpManager clientCert:(NSData*)clientCert callback:(id)callback {
self = [super init];
_httpManager = httpManager;
- _cert = cert;
+ _clientCert = clientCert;
_callback = callback;
return self;
}
@@ -62,7 +62,7 @@
[_callback showPIN:PIN];
HttpResponse* pairResp = [[HttpResponse alloc] init];
- [_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:pairResp withUrlRequest:[_httpManager newPairRequest:salt]]];
+ [_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:pairResp withUrlRequest:[_httpManager newPairRequest:salt clientCert:_clientCert]]];
if (![self verifyResponseStatus:pairResp]) {
return;
}
@@ -113,7 +113,7 @@
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(hashLength, 16)];
NSData* clientSecret = [Utils randomBytes:16];
- NSData* challengeRespHashInput = [self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret];
+ NSData* challengeRespHashInput = [self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_clientCert]] with:clientSecret];
NSData* challengeRespHash;
if (serverMajorVersion >= 7) {
challengeRespHash = [cryptoMan SHA256HashData: challengeRespHashInput];
@@ -180,7 +180,8 @@
[_callback pairFailed:@"Pairing stage #5 failed"];
return;
}
- [_callback pairSuccessful];
+
+ [_callback pairSuccessful: [CryptoManager pemToDer:[Utils hexToBytes:plainCert]]];
}
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
diff --git a/Limelight/Stream/StreamConfiguration.h b/Limelight/Stream/StreamConfiguration.h
index 8bf8ee8..7c8ec33 100644
--- a/Limelight/Stream/StreamConfiguration.h
+++ b/Limelight/Stream/StreamConfiguration.h
@@ -28,5 +28,6 @@
@property BOOL enableHdr;
@property BOOL multiController;
@property BOOL allowHevc;
+@property NSData* serverCert;
@end
diff --git a/Limelight/Stream/StreamConfiguration.m b/Limelight/Stream/StreamConfiguration.m
index 3efa33a..45ab688 100644
--- a/Limelight/Stream/StreamConfiguration.m
+++ b/Limelight/Stream/StreamConfiguration.m
@@ -9,5 +9,5 @@
#import "StreamConfiguration.h"
@implementation StreamConfiguration
-@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, streamingRemotely, appName, optimizeGameSettings, playAudioOnPC, audioChannelMask, audioChannelCount, enableHdr, multiController, allowHevc;
+@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, streamingRemotely, appName, optimizeGameSettings, playAudioOnPC, audioChannelMask, audioChannelCount, enableHdr, multiController, allowHevc, serverCert;
@end
diff --git a/Limelight/Stream/StreamManager.m b/Limelight/Stream/StreamManager.m
index 48f14ac..223abbc 100644
--- a/Limelight/Stream/StreamManager.m
+++ b/Limelight/Stream/StreamManager.m
@@ -38,12 +38,10 @@
- (void)main {
[CryptoManager generateKeyPairUsingSSL];
NSString* uniqueId = [IdManager getUniqueId];
- NSData* cert = [CryptoManager readCertFromFile];
HttpManager* hMan = [[HttpManager alloc] initWithHost:_config.host
uniqueId:uniqueId
- deviceName:deviceName
- cert:cert];
+ serverCert:_config.serverCert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest:false]
diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m
index 75a4ff8..5fac30d 100644
--- a/Limelight/ViewControllers/MainFrameViewController.m
+++ b/Limelight/ViewControllers/MainFrameViewController.m
@@ -37,7 +37,7 @@
NSOperationQueue* _opQueue;
TemporaryHost* _selectedHost;
NSString* _uniqueId;
- NSData* _cert;
+ NSData* _clientCert;
DiscoveryManager* _discMan;
AppAssetManager* _appManager;
StreamConfiguration* _streamConfig;
@@ -98,11 +98,14 @@ static NSMutableSet* hostList;
});
}
-- (void)pairSuccessful {
+- (void)pairSuccessful:(NSData*)serverCert {
dispatch_async(dispatch_get_main_queue(), ^{
+ // Store the cert from pairing with the host
+ self->_selectedHost.serverCert = serverCert;
+
[self->_pairAlert dismissViewControllerAnimated:YES completion:nil];
self->_pairAlert = nil;
-
+
[self->_discMan startDiscovery];
[self alreadyPaired];
});
@@ -139,7 +142,7 @@ static NSMutableSet* hostList;
// Exempt this host from discovery while handling the applist query
[self->_discMan removeHostFromDiscovery:host];
- AppListResponse* appListResp = [ConnectionHelper getAppListForHostWithHostIP:host.activeAddress deviceName:deviceName cert:self->_cert uniqueID:self->_uniqueId];
+ AppListResponse* appListResp = [ConnectionHelper getAppListForHostWithHostIP:host.activeAddress serverCert:host.serverCert uniqueID:self->_uniqueId];
[self->_discMan addHostToDiscovery:host];
@@ -307,7 +310,7 @@ static NSMutableSet* hostList;
[self showLoadingFrame: ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:self->_uniqueId deviceName:deviceName cert:self->_cert];
+ HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:self->_uniqueId serverCert:host.serverCert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
// Exempt this host from discovery while handling the serverinfo request
@@ -352,7 +355,7 @@ static NSMutableSet* hostList;
Log(LOG_I, @"Trying to pair");
// Polling the server while pairing causes the server to screw up
[self->_discMan stopDiscoveryBlocking];
- PairManager* pMan = [[PairManager alloc] initWithManager:hMan andCert:self->_cert callback:self];
+ PairManager* pMan = [[PairManager alloc] initWithManager:hMan clientCert:self->_clientCert callback:self];
[self->_opQueue addOperation:pMan];
}
else {
@@ -457,6 +460,7 @@ static NSMutableSet* hostList;
_streamConfig.host = app.host.activeAddress;
_streamConfig.appID = app.id;
_streamConfig.appName = app.name;
+ _streamConfig.serverCert = app.host.serverCert;
DataManager* dataMan = [[DataManager alloc] init];
TemporarySettings* streamSettings = [dataMan getSettings];
@@ -524,7 +528,7 @@ static NSMutableSet* hostList;
Log(LOG_I, @"Quitting application: %@", currentApp.name);
[self showLoadingFrame: ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- HttpManager* hMan = [[HttpManager alloc] initWithHost:app.host.activeAddress uniqueId:self->_uniqueId deviceName:deviceName cert:self->_cert];
+ HttpManager* hMan = [[HttpManager alloc] initWithHost:app.host.activeAddress uniqueId:self->_uniqueId serverCert:app.host.serverCert];
HttpResponse* quitResponse = [[HttpResponse alloc] init];
HttpRequest* quitRequest = [HttpRequest requestForResponse: quitResponse withUrlRequest:[hMan newQuitAppRequest]];
@@ -700,7 +704,7 @@ static NSMutableSet* hostList;
// Set up crypto
[CryptoManager generateKeyPairUsingSSL];
_uniqueId = [IdManager getUniqueId];
- _cert = [CryptoManager readCertFromFile];
+ _clientCert = [CryptoManager readCertFromFile];
_appManager = [[AppAssetManager alloc] initWithCallback:self];
_opQueue = [[NSOperationQueue alloc] init];
diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj
index eba09b5..a8c34f4 100644
--- a/Moonlight.xcodeproj/project.pbxproj
+++ b/Moonlight.xcodeproj/project.pbxproj
@@ -165,6 +165,7 @@
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.1.xcdatamodel"; sourceTree = ""; };
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryApp.h; path = Database/TemporaryApp.h; sourceTree = ""; };
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryApp.m; path = Database/TemporaryApp.m; sourceTree = ""; };
+ 98517B1B21CE0A9000481377 /* Moonlight v1.3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.3.xcdatamodel"; sourceTree = ""; };
9865DC3B2132922E0005B9B9 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.4.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.2.xcdatamodel"; sourceTree = ""; };
98878AE0206A226D00586E90 /* OSPortabilityDefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSPortabilityDefs.h; sourceTree = ""; };
@@ -1504,6 +1505,7 @@
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ 98517B1B21CE0A9000481377 /* Moonlight v1.3.xcdatamodel */,
986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */,
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */,
FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */,
@@ -1512,7 +1514,7 @@
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
);
- currentVersion = 986CCE6C2133E45300168291 /* Moonlight v1.2.xcdatamodel */;
+ currentVersion = 98517B1B21CE0A9000481377 /* Moonlight v1.3.xcdatamodel */;
path = Limelight.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;