diff --git a/FirebaseCore/Sources/FIRApp.m b/FirebaseCore/Sources/FIRApp.m index 922d93ff7a2..a6ac0f724a9 100644 --- a/FirebaseCore/Sources/FIRApp.m +++ b/FirebaseCore/Sources/FIRApp.m @@ -573,10 +573,11 @@ - (void)checkExpectedBundleID { #pragma mark - private - App ID Validation /** - * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. - * This is the main method for validating app ID. + * Validates the format of app ID and its included bundle ID hash contained in GOOGLE_APP_ID in the + * plist file. This is the main method for validating app ID. * - * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + * @return YES if the app ID fulfills the expected format and contains a hashed bundle ID, NO + * otherwise. */ - (BOOL)isAppIDValid { NSString *appID = _options.googleAppID; @@ -597,7 +598,7 @@ - (BOOL)isAppIDValid { + (BOOL)validateAppID:(NSString *)appID { // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not - // have a valid fingerprint, otherwise we just warn about the potential issue. + // have a valid hashed bundle ID, otherwise we just warn about the potential issue. if (!appID.length) { return NO; } @@ -627,7 +628,7 @@ + (BOOL)validateAppID:(NSString *)appID { return NO; } - if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + if (![self validateBundleIDHashWithinAppID:appID forVersion:appIDVersion]) { return NO; } @@ -643,7 +644,7 @@ + (NSString *)actualBundleID { * The version must end in ":". * * For v1 app ids the format is expected to be - * '::ios:'. + * '::ios:'. * * This method does not verify that the contents of the app id are correct, just that they fulfill * the expected format. @@ -661,21 +662,21 @@ + (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { stringScanner.charactersToBeSkipped = nil; // Skip version part - // '**::ios:' + // '**::ios:' if (![stringScanner scanString:version intoString:NULL]) { // The version part is missing or mismatched return NO; } // Validate version part (see part between '*' symbols below) - // '*:*:ios:' + // '*:*:ios:' if (![stringScanner scanString:@":" intoString:NULL]) { // appIDVersion must be separated by ":" return NO; } // Validate version part (see part between '*' symbols below) - // ':**:ios:'. + // ':**:ios:'. NSInteger projectNumber = NSNotFound; if (![stringScanner scanInteger:&projectNumber]) { // NO project number found. @@ -683,14 +684,14 @@ + (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { } // Validate version part (see part between '*' symbols below) - // ':*:*ios:'. + // ':*:*ios:'. if (![stringScanner scanString:@":" intoString:NULL]) { // The project number must be separated by ":" return NO; } // Validate version part (see part between '*' symbols below) - // '::*ios*:'. + // '::*ios*:'. NSString *platform; if (![stringScanner scanUpToString:@":" intoString:&platform]) { return NO; @@ -702,22 +703,22 @@ + (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { } // Validate version part (see part between '*' symbols below) - // '::ios*:*'. + // '::ios*:*'. if (![stringScanner scanString:@":" intoString:NULL]) { // The platform must be separated by ":" return NO; } // Validate version part (see part between '*' symbols below) - // '::ios:**'. - unsigned long long fingerprint = NSNotFound; - if (![stringScanner scanHexLongLong:&fingerprint]) { - // Fingerprint part is missing + // '::ios:**'. + unsigned long long bundleIDHash = NSNotFound; + if (![stringScanner scanHexLongLong:&bundleIDHash]) { + // Hashed bundleID part is missing return NO; } if (!stringScanner.isAtEnd) { - // There are not allowed characters in the fingerprint part + // There are not allowed characters in the hashed bundle ID part return NO; } @@ -725,34 +726,34 @@ + (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { } /** - * Validates that the fingerprint of the app ID string is what is expected based on the supplied - * version. + * Validates that the hashed bundle ID included in the app ID string is what is expected based on + * the supplied version. * * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. * * @param appID Contents of GOOGLE_APP_ID from the plist file. * @param version Indicates what version of the app id format this string should be. - * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * @return YES if provided string fufills the expected hashed bundle ID and the version is known, NO * otherwise. */ -+ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { - // Extract the supplied fingerprint from the supplied app ID. - // This assumes the app ID format is the same for all known versions below. If the app ID format - // changes in future versions, the tokenizing of the app ID format will need to take into account - // the version of the app ID. ++ (BOOL)validateBundleIDHashWithinAppID:(NSString *)appID forVersion:(NSString *)version { + // Extract the hashed bundle ID from the given app ID. + // This assumes the app ID format is the same for all known versions below. + // If the app ID format changes in future versions, the tokenizing of the app + // ID format will need to take into account the version of the app ID. NSArray *components = [appID componentsSeparatedByString:@":"]; if (components.count != 4) { return NO; } - NSString *suppliedFingerprintString = components[3]; - if (!suppliedFingerprintString.length) { + NSString *suppliedBundleIDHashString = components[3]; + if (!suppliedBundleIDHashString.length) { return NO; } - uint64_t suppliedFingerprint; - NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; - if (![scanner scanHexLongLong:&suppliedFingerprint]) { + uint64_t suppliedBundleIDHash; + NSScanner *scanner = [NSScanner scannerWithString:suppliedBundleIDHashString]; + if (![scanner scanHexLongLong:&suppliedBundleIDHash]) { return NO; } diff --git a/FirebaseCore/Tests/Unit/FIRAppTest.m b/FirebaseCore/Tests/Unit/FIRAppTest.m index da4a002d1c2..4434742b9ab 100644 --- a/FirebaseCore/Tests/Unit/FIRAppTest.m +++ b/FirebaseCore/Tests/Unit/FIRAppTest.m @@ -55,7 +55,7 @@ + (BOOL)writeString:(NSString *)string toURL:(NSURL *)filePathURL; + (void)logAppInfo:(NSNotification *)notification; + (BOOL)validateAppID:(NSString *)appID; + (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version; -+ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version; ++ (BOOL)validateBundleIDHashWithinAppID:(NSString *)appID forVersion:(NSString *)version; + (nullable NSNumber *)readDataCollectionSwitchFromPlist; + (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app; @@ -423,33 +423,34 @@ - (void)testOptionsLocking { #pragma mark - App ID v1 - (void)testAppIDV1 { - // Missing separator between platform:fingerprint. + // Missing separator between platform:hashed bundle ID. XCTAssertFalse([FIRApp validateAppID:@"1:1337:iosdeadbeef"]); // Wrong platform "android". XCTAssertFalse([FIRApp validateAppID:@"1:1337:android:deadbeef"]); - // The fingerprint, aka 4th field, should only contain hex characters. + // The hashed bundle ID, aka 4th field, should only contain hex characters. XCTAssertFalse([FIRApp validateAppID:@"1:1337:ios:123abcxyz"]); - // The fingerprint, aka 4th field, is not tested in V1, so a bad value shouldn't cause a failure. + // The hashed bundle ID, aka 4th field, is not tested in V1, so a bad value shouldn't cause a + // failure. XCTAssertTrue([FIRApp validateAppID:@"1:1337:ios:deadbeef"]); } #pragma mark - App ID v2 - (void)testAppIDV2 { - // Missing separator between platform:fingerprint. + // Missing separator between platform:hashed bundle ID. XCTAssertTrue([FIRApp validateAppID:@"2:1337:ios5e18052ab54fbfec"]); // Unknown versions may contain anything. XCTAssertTrue([FIRApp validateAppID:@"2:1337:ios:123abcxyz"]); XCTAssertTrue([FIRApp validateAppID:@"2:thisdoesn'teven_m:a:t:t:e:r_"]); - // Known good fingerprint. + // Known good hashed bundle ID. XCTAssertTrue([FIRApp validateAppID:@"2:1337:ios:5e18052ab54fbfec"]); - // Unknown fingerprint, not tested so shouldn't cause a failure. + // Unknown hashed bundle ID, not tested so shouldn't cause a failure. XCTAssertTrue([FIRApp validateAppID:@"2:1337:ios:deadbeef"]); } @@ -571,36 +572,36 @@ - (void)testAppIDFormatInvalid { XCTAssertFalse([FIRApp validateAppIDFormat:@"1:1337:ios:deadbeef:ab" withVersion:kGoodVersionV1]); } -- (void)testAppIDFingerprintInvalid { +- (void)testAppIDContainsInvalidBundleIDHash { OCMStub([self.appClassMock actualBundleID]).andReturn(@"com.google.bundleID"); - // Some direct tests of the validateAppIDFingerprint:withVersion: method. + // Some direct tests of the validateBundleIDHashWithinAppID:forVersion: method. // Sanity checks first. NSString *const kGoodAppIDV1 = @"1:1337:ios:deadbeef"; NSString *const kGoodVersionV1 = @"1"; - XCTAssertTrue([FIRApp validateAppIDFingerprint:kGoodAppIDV1 withVersion:kGoodVersionV1]); + XCTAssertTrue([FIRApp validateBundleIDHashWithinAppID:kGoodAppIDV1 forVersion:kGoodVersionV1]); NSString *const kGoodAppIDV2 = @"2:1337:ios:5e18052ab54fbfec"; NSString *const kGoodVersionV2 = @"2"; XCTAssertTrue([FIRApp validateAppIDFormat:kGoodAppIDV2 withVersion:kGoodVersionV2]); // Nil or empty strings. - XCTAssertFalse([FIRApp validateAppIDFingerprint:kGoodAppIDV1 withVersion:nil]); - XCTAssertFalse([FIRApp validateAppIDFingerprint:kGoodAppIDV1 withVersion:@""]); - XCTAssertFalse([FIRApp validateAppIDFingerprint:nil withVersion:kGoodVersionV1]); - XCTAssertFalse([FIRApp validateAppIDFingerprint:@"" withVersion:kGoodVersionV1]); - XCTAssertFalse([FIRApp validateAppIDFingerprint:nil withVersion:nil]); - XCTAssertFalse([FIRApp validateAppIDFingerprint:@"" withVersion:@""]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:kGoodAppIDV1 forVersion:nil]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:kGoodAppIDV1 forVersion:@""]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:nil forVersion:kGoodVersionV1]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:@"" forVersion:kGoodVersionV1]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:nil forVersion:nil]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:@"" forVersion:@""]); // App ID contains only the version prefix. - XCTAssertFalse([FIRApp validateAppIDFingerprint:kGoodVersionV1 withVersion:kGoodVersionV1]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:kGoodVersionV1 forVersion:kGoodVersionV1]); // The version is the entire app ID. - XCTAssertFalse([FIRApp validateAppIDFingerprint:kGoodAppIDV1 withVersion:kGoodAppIDV1]); + XCTAssertFalse([FIRApp validateBundleIDHashWithinAppID:kGoodAppIDV1 forVersion:kGoodAppIDV1]); } // Uncomment if you need to measure performance of [FIRApp validateAppID:]. // It is commented because measures are heavily dependent on a build agent configuration, // so it cannot produce reliable resault on CI -//- (void)testAppIDFingerprintPerfomance { +//- (void)testAppIDValidationPerfomance { // [self measureBlock:^{ // for (NSInteger i = 0; i < 100; ++i) { // [self testAppIDPrefix];