From 1b02e186f83c02ced9e23dbe0717af844a0f9d85 Mon Sep 17 00:00:00 2001 From: Frederic Jacobs Date: Thu, 24 Dec 2015 18:20:04 +0100 Subject: [PATCH] Fixes #146 #147. --- .gitmodules | 0 Signal/src/AppDelegate.m | 4 + Signal/src/environment/SignalKeyingStorage.m | 9 +- .../network/http/HttpRequestResponseTest.m | 135 +++++++++++------- .../phone/signaling/SessionDescriptorTest.m | 63 ++++---- 5 files changed, 123 insertions(+), 88 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index a52cbe78d..e22420503 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -169,6 +169,10 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; } - (void)applicationDidBecomeActive:(UIApplication *)application { + if (getenv("runningTests_dontStartApp")) { + return; + } + if ([TSAccountManager isRegistered]) { // We're double checking that the app is active, to be sure since we can't verify in production env due to code // signing. diff --git a/Signal/src/environment/SignalKeyingStorage.m b/Signal/src/environment/SignalKeyingStorage.m index f0313875e..30ed082d3 100644 --- a/Signal/src/environment/SignalKeyingStorage.m +++ b/Signal/src/environment/SignalKeyingStorage.m @@ -52,14 +52,7 @@ } + (NSString *)serverAuthPassword { - NSString *password = [self stringForKey:SAVED_PASSWORD_KEY]; - NSData *data = [password decodedAsBase64Data]; - if (data.length != SAVED_PASSWORD_LENGTH) { - DDLogError(@"The server password has incorrect length. Is %lu but should be %d", - (unsigned long)data.length, - SAVED_PASSWORD_LENGTH); - } - return password; + return [self stringForKey:SAVED_PASSWORD_KEY]; } #pragma mark Keychain wrapper methods diff --git a/Signal/test/network/http/HttpRequestResponseTest.m b/Signal/test/network/http/HttpRequestResponseTest.m index 57707667f..1a0a176fa 100644 --- a/Signal/test/network/http/HttpRequestResponseTest.m +++ b/Signal/test/network/http/HttpRequestResponseTest.m @@ -1,7 +1,13 @@ +#import #import -#import "TestUtil.h" #import "HttpSocket.h" +#import "SignalKeyingStorage.h" #import "SignalUtil.h" +#import "TestUtil.h" + +@interface SignalKeyingStorage () ++ (void)storeString:(NSString *)string forKey:(NSString *)key; +@end @interface HttpRequestResponseTest : XCTestCase @@ -9,78 +15,96 @@ @implementation HttpRequestResponseTest -// todo: write production tests for signaling - -//-(void) testRequestToInitiate { -// [Environment setCurrent:testEnv]; -// [SignalKeyingStorage setLocalNumberTo:[PhoneNumber phoneNumberFromE164:@"+12211231235"]]; -// [UICKeyChainStore setString:@"shall_not_password" forKey:@"Password"]; -// [Environment.preferences setValueForKey:@"PasswordCounter" toValue:@2357]; -// HttpRequest* h = [HttpRequest httpRequestToInitiateToRemoteNumber:[PhoneNumber phoneNumberFromE164:@"+19023334444"]]; -// test([[h method] isEqualToString:@"GET"]); -// test([[h location] isEqualToString:@"/session/1/+19023334444"]); -// NSLog(@"HTTP rep: %@", h.toHttp); -// test([h.toHttp isEqualToString:@"GET /session/1/+19023334444 HTTP/1.0\r\nAuthorization: OTP KzE5MDI3Nzc4ODg4OmluQ3lLcE1ZaFRQS0ZwN3BITlN3bUxVMVpCTT06MjM1Nw==\r\n\r\n"]); -// test([h isEqualToHttpRequest:[HttpRequest httpRequestFromData:[h serialize]]]); -//} --(void) testRequestToOpenPort { - HttpRequest* h = [HttpRequest httpRequestToOpenPortWithSessionId:2357]; +- (void)setUp { + [Environment setCurrent:testEnv]; +} + +- (void)testRequestToInitiate { + [SignalKeyingStorage storeString:@"shall_not_password" forKey:SAVED_PASSWORD_KEY]; + [SignalKeyingStorage storeString:[@2356 stringValue] forKey:PASSWORD_COUNTER_KEY]; + [TSStorageManager storePhoneNumber:@"+19027778888"]; + + HttpRequest *h = + [HttpRequest httpRequestToInitiateToRemoteNumber:[PhoneNumber phoneNumberFromE164:@"+19023334444"]]; + test([[h method] isEqualToString:@"GET"]); + test([[h location] isEqualToString:@"/session/1/+19023334444"]); + test([[SignalKeyingStorage serverAuthPassword] isEqualToString:@"shall_not_password"]); + NSLog(@"HTTP rep: %@", [self processStrings:h.toHttp]); + test([h.toHttp isEqualToString:@"GET /session/1/+19023334444 HTTP/1.0\r\nAuthorization: OTP " + @"KzE5MDI3Nzc4ODg4OmluQ3lLcE1ZaFRQS0ZwN3BITlN3bUxVMVpCTT06MjM1Nw==\r\n\r\n"]); + test([h isEqualToHttpRequest:[HttpRequest httpRequestFromData:[h serialize]]]); +} +- (void)testRequestToOpenPort { + HttpRequest *h = [HttpRequest httpRequestToOpenPortWithSessionId:2357]; test([[h method] isEqualToString:@"GET"]); test([[h location] isEqualToString:@"/open/2357"]); test([h.toHttp isEqualToString:@"GET /open/2357 HTTP/1.0\r\n\r\n"]); test([h isEqualToHttpRequest:[HttpRequest httpRequestFromData:[h serialize]]]); } -//-(void) testRequestToRing { -// [Environment setCurrent:testEnv]; -// [SignalKeyingStorage setLocalNumberTo:[PhoneNumber phoneNumberFromE164:@"+19025555555"]]; -// [UICKeyChainStore setString:@"shall_not_password" forKey:@"Password"]; -// [UICKeyChainStore setString:[@0 stringValue] forKey:@"PasswordCounter"]; -// HttpRequest* h = [HttpRequest httpRequestToRingWithSessionId:458847238]; -// test([[h method] isEqualToString:@"RING"]); -// test([[h location] isEqualToString:@"/session/458847238"]); -// test([h.toHttp isEqualToString:@"RING /session/458847238 HTTP/1.0\r\nAuthorization: OTP KzE5MDI1NTU1NTU1OnpOV1owY3k3S3A5S3NNd0RXbnlHZFBNR2ZzTT06MA==\r\n\r\n"]); -// test([h isEqualToHttpRequest:[HttpRequest httpRequestFromData:[h serialize]]]); -//} --(void) testRequestFromData { - HttpRequest* h0 = [HttpRequest httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 0\r\n\r\n" encodedAsUtf8]]; + +- (NSString *)processStrings:(NSString *)something { + return [[[something stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"] + stringByReplacingOccurrencesOfString:@"\t" + withString:@"\\t"] stringByReplacingOccurrencesOfString:@"\r" + withString:@"\\r"]; +} + +- (void)testRequestToRing { + [Environment setCurrent:testEnv]; + [TSStorageManager storePhoneNumber:@"+19025555555"]; + [SignalKeyingStorage storeString:@"shall_not_password" forKey:SAVED_PASSWORD_KEY]; + [SignalKeyingStorage storeString:@"-1" forKey:PASSWORD_COUNTER_KEY]; + HttpRequest *h = [HttpRequest httpRequestToRingWithSessionId:458847238]; + test([[h method] isEqualToString:@"RING"]); + test([[h location] isEqualToString:@"/session/458847238"]); + test([h.toHttp isEqualToString:@"RING /session/458847238 HTTP/1.0\r\nAuthorization: OTP " + @"KzE5MDI1NTU1NTU1OnpOV1owY3k3S3A5S3NNd0RXbnlHZFBNR2ZzTT06MA==\r\n\r\n"]); + test([h isEqualToHttpRequest:[HttpRequest httpRequestFromData:[h serialize]]]); +} + +- (void)testRequestFromData { + HttpRequest *h0 = + [HttpRequest httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 0\r\n\r\n" encodedAsUtf8]]; test([[h0 method] isEqualToString:@"GET"]); test([[h0 location] isEqualToString:@"/index.html"]); test([[h0 headers] count] == 1); test([[h0 headers][@"Content-Length"] isEqualToString:@"0"]); test([[h0 optionalBody] isEqualToString:@""]); - HttpRequest* h1 = [HttpRequest httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 10\r\n\r\nabcdefghij" encodedAsUtf8]]; + HttpRequest *h1 = [HttpRequest + httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 10\r\n\r\nabcdefghij" encodedAsUtf8]]; test([[h1 method] isEqualToString:@"GET"]); test([[h1 location] isEqualToString:@"/index.html"]); test([[h1 headers] count] == 1); test([[h1 headers][@"Content-Length"] isEqualToString:@"10"]); test([[h1 optionalBody] isEqualToString:@"abcdefghij"]); - - HttpRequest* h = [HttpRequest httpRequestFromData:@"GET /index.html HTTP/1.0\r\n\r\n".encodedAsUtf8]; + + HttpRequest *h = [HttpRequest httpRequestFromData:@"GET /index.html HTTP/1.0\r\n\r\n".encodedAsUtf8]; test([[h method] isEqualToString:@"GET"]); test([[h location] isEqualToString:@"/index.html"]); test([[h headers] count] == 0); test([h optionalBody] == nil); - + testThrows([HttpRequest httpRequestFromData:@"GET /index.html HTTP/1.0\r\n".encodedAsUtf8]); - testThrows([HttpRequest httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 10\r\n\r\n" encodedAsUtf8]]); + testThrows( + [HttpRequest httpRequestFromData:[@"GET /index.html HTTP/1.0\r\nContent-Length: 10\r\n\r\n" encodedAsUtf8]]); testThrows([HttpRequest httpRequestFromData:@"GET /index.html\r\n\r\n".encodedAsUtf8]); } --(void) testResponseOk { - HttpResponse* h = [HttpResponse httpResponse200Ok]; +- (void)testResponseOk { + HttpResponse *h = [HttpResponse httpResponse200Ok]; test(h.getStatusCode == 200); test(h.getOptionalBodyText == nil); test([h.getHeaders count] == 0); } --(void) testResponseFromData { - HttpResponse* h = [HttpResponse httpResponseFromData:@"HTTP/1.1 200 OK\r\n\r\n".encodedAsUtf8]; +- (void)testResponseFromData { + HttpResponse *h = [HttpResponse httpResponseFromData:@"HTTP/1.1 200 OK\r\n\r\n".encodedAsUtf8]; test(h.isOkResponse); test(h.getStatusCode == 200); - test([h.getStatusText isEqualToString: @"OK"]); + test([h.getStatusText isEqualToString:@"OK"]); test(h.getOptionalBodyText == nil); test([h.getHeaders count] == 0); - - HttpResponse* h2 = [HttpResponse httpResponseFromData:@"HTTP/1.1 404 Not Found\r\n\r\n".encodedAsUtf8]; + + HttpResponse *h2 = [HttpResponse httpResponseFromData:@"HTTP/1.1 404 Not Found\r\n\r\n".encodedAsUtf8]; test(!h2.isOkResponse); test(h2.getStatusCode == 404); test([h2.getStatusText isEqualToString:@"Not Found"]); @@ -90,9 +114,9 @@ testThrows([HttpResponse httpResponseFromData:@"HTTP/1.1 200 OK\r\n".encodedAsUtf8]); testThrows([HttpResponse httpResponseFromData:@"HTTP/1.1 200\r\n\r\n".encodedAsUtf8]); } --(void) testTryFromPartialData { +- (void)testTryFromPartialData { NSUInteger len; - HttpRequestOrResponse* h; + HttpRequestOrResponse *h; h = [HttpRequestOrResponse tryExtractFromPartialData:@"HTTP/1.1 200".encodedAsUtf8 usedLengthOut:&len]; test(h == nil); h = [HttpRequestOrResponse tryExtractFromPartialData:@"HTTP/1.1 200 OK".encodedAsUtf8 usedLengthOut:&len]; @@ -104,28 +128,35 @@ test(h.isResponse); test([[h response] isOkResponse]); test(len == 19); - - h = [HttpRequestOrResponse tryExtractFromPartialData:[@"HTTP/1.1 200 OK\r\n\r\n*&DY*SWA(TD&(BTNGNSADN" encodedAsUtf8] usedLengthOut:&len]; + + h = [HttpRequestOrResponse + tryExtractFromPartialData:[@"HTTP/1.1 200 OK\r\n\r\n*&DY*SWA(TD&(BTNGNSADN" encodedAsUtf8] + usedLengthOut:&len]; test(h.isResponse); test([[h response] isOkResponse]); test(len == 19); h = [HttpRequestOrResponse tryExtractFromPartialData:@"GET /index.html".encodedAsUtf8 usedLengthOut:&len]; test(h == nil); - h = [HttpRequestOrResponse tryExtractFromPartialData:@"GET /index.html HTTP/1.0\r\n".encodedAsUtf8 usedLengthOut:&len]; + h = [HttpRequestOrResponse tryExtractFromPartialData:@"GET /index.html HTTP/1.0\r\n".encodedAsUtf8 + usedLengthOut:&len]; test(h == nil); - - h = [HttpRequestOrResponse tryExtractFromPartialData:@"GET /index.html HTTP/1.0\r\n\r\n".encodedAsUtf8 usedLengthOut:&len]; + + h = [HttpRequestOrResponse tryExtractFromPartialData:@"GET /index.html HTTP/1.0\r\n\r\n".encodedAsUtf8 + usedLengthOut:&len]; test(h.isRequest); test([[[h request] method] isEqualToString:@"GET"]); test(len == 28); - - h = [HttpRequestOrResponse tryExtractFromPartialData:[@"GET /index.html HTTP/1.0\r\n\r\nU$%#*(NYVYAY*" encodedAsUtf8] usedLengthOut:&len]; + + h = [HttpRequestOrResponse + tryExtractFromPartialData:[@"GET /index.html HTTP/1.0\r\n\r\nU$%#*(NYVYAY*" encodedAsUtf8] + usedLengthOut:&len]; test(h.isRequest); test([[[h request] method] isEqualToString:@"GET"]); test(len == 28); testThrows([HttpRequestOrResponse tryExtractFromPartialData:@"GET\r\n\r\n".encodedAsUtf8 usedLengthOut:&len]); - testThrows([HttpRequestOrResponse tryExtractFromPartialData:@"HTTP/1.1 200\r\n\r\n".encodedAsUtf8 usedLengthOut:&len]); + testThrows( + [HttpRequestOrResponse tryExtractFromPartialData:@"HTTP/1.1 200\r\n\r\n".encodedAsUtf8 usedLengthOut:&len]); } @end diff --git a/Signal/test/phone/signaling/SessionDescriptorTest.m b/Signal/test/phone/signaling/SessionDescriptorTest.m index f1d99fdc1..3692f3726 100644 --- a/Signal/test/phone/signaling/SessionDescriptorTest.m +++ b/Signal/test/phone/signaling/SessionDescriptorTest.m @@ -1,56 +1,63 @@ #import #import "InitiatorSessionDescriptor.h" +#import "ResponderSessionDescriptor.h" +#import "SignalKeyingStorage.h" #import "TestUtil.h" +@interface SignalKeyingStorage () ++ (void)storeData:(NSData *)data forKey:(NSString *)key; +@end + @interface SessionDescriptorTest : XCTestCase @end @implementation SessionDescriptorTest --(void) testInitiatorSessionDescriptionJson { - InitiatorSessionDescriptor* d = [InitiatorSessionDescriptor initiatorSessionDescriptorWithSessionId:5 +- (void)testInitiatorSessionDescriptionJson { + InitiatorSessionDescriptor *d = [InitiatorSessionDescriptor initiatorSessionDescriptorWithSessionId:5 andRelayServerName:@"example.com" andRelayPort:6]; test([d sessionId] == 5); test([d relayUdpPort] == 6); test([d.relayServerName isEqualToString:@"example.com"]); - + // roundtrip - InitiatorSessionDescriptor* d2 = [InitiatorSessionDescriptor initiatorSessionDescriptorFromJson:d.toJson]; + InitiatorSessionDescriptor *d2 = [InitiatorSessionDescriptor initiatorSessionDescriptorFromJson:d.toJson]; test([d2 sessionId] == 5); test([d2 relayUdpPort] == 6); test([d2.relayServerName isEqualToString:@"example.com"]); - + // constant - InitiatorSessionDescriptor* d3 = [InitiatorSessionDescriptor initiatorSessionDescriptorFromJson:@"{\"sessionId\":5,\"serverName\":\"example.com\",\"relayPort\":6}"]; + InitiatorSessionDescriptor *d3 = [InitiatorSessionDescriptor + initiatorSessionDescriptorFromJson:@"{\"sessionId\":5,\"serverName\":\"example.com\",\"relayPort\":6}"]; test([d3 sessionId] == 5); test([d3 relayUdpPort] == 6); test([d3.relayServerName isEqualToString:@"example.com"]); } --(void) testResponderSessionDescriptorFromEncryptedRemoteNotification2 { - - - // todo: Rewrite test to support keychain storage with NSData - -// NSDictionary* notification = @{ -// @"aps":@{@"alert":@"Incoming Call!"}, -// @"m":@"AJV74NzwSbZ1KeV4pRwPfMZQ3a5n0V0/HV7eABUUCJvRVqGe3qFO/2XHKv1nEDwNg2naQDmd/nLOlvk=" -// }; -// -// [Environment setCurrent:testEnv]; -// [[UICKeyChainStore keyChainStore]setValue:[@"0000000000000000000000000000000000000000" decodedAsHexString]forKey:@"Signaling Mac Key"]; -// -// [[UICKeyChainStore keyChainStore] setValue:[@"00000000000000000000000000000000" decodedAsHexString] forKey:@"Signaling Cipher Key"]; -// -// ResponderSessionDescriptor* d = [ResponderSessionDescriptor responderSessionDescriptorFromEncryptedRemoteNotification:notification]; -// -// test(d.interopVersion == 1); -// test(d.relayUdpPort == 11235); -// test(d.sessionId == 2357); -// test([d.relayServerName isEqualToString:@"Test"]); -// test([d.initiatorNumber.toE164 isEqualToString:@"+19027777777"]); +- (void)testResponderSessionDescriptorFromEncryptedRemoteNotification2 { + NSDictionary *notification = @{ + @"aps" : @{@"alert" : @"Incoming Call!"}, + @"m" : @"AJV74NzwSbZ1KeV4pRwPfMZQ3a5n0V0/HV7eABUUCJvRVqGe3qFO/2XHKv1nEDwNg2naQDmd/nLOlvk=" + }; + + [Environment setCurrent:testEnv]; + [[TSStorageManager sharedManager] setupDatabase]; + + [SignalKeyingStorage storeData:[@"0000000000000000000000000000000000000000" decodedAsHexString] + forKey:SIGNALING_MAC_KEY]; + [SignalKeyingStorage storeData:[@"00000000000000000000000000000000" decodedAsHexString] + forKey:SIGNALING_CIPHER_KEY]; + + ResponderSessionDescriptor *d = + [ResponderSessionDescriptor responderSessionDescriptorFromEncryptedRemoteNotification:notification]; + + test(d.interopVersion == 1); + test(d.relayUdpPort == 11235); + test(d.sessionId == 2357); + test([d.relayServerName isEqualToString:@"Test"]); + test([d.initiatorNumber.toE164 isEqualToString:@"+19027777777"]); } @end