diff --git a/Signal/src/call/PeerConnectionClient.swift b/Signal/src/call/PeerConnectionClient.swift index b295c3191..1a07f4ab2 100644 --- a/Signal/src/call/PeerConnectionClient.swift +++ b/Signal/src/call/PeerConnectionClient.swift @@ -1112,6 +1112,16 @@ class HardenedRTCSessionDescription { var logSafeDescription: String { #if DEBUG + return sdp + #else + return redactIPV6(sdp: redactIcePwd(sdp: sdp)) + #endif + } + + private func redactIcePwd(sdp: String) -> String { + #if DEBUG + return sdp + #else var text = sdp text = text.replacingOccurrences(of: "\r", with: "\n") text = text.replacingOccurrences(of: "\n\n", with: "\n") @@ -1124,8 +1134,31 @@ class HardenedRTCSessionDescription { } let filteredText = filteredLines.joined(separator: "\n") return filteredText - #else + #endif + } + + private func redactIPV6(sdp: String) -> String { + #if DEBUG return sdp + #else + + // Example values to match: + // + // * 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + // * 2001:db8:85a3::8a2e:370:7334 + // * ::1 + // * :: + // * ::ffff:192.0.2.128 + // + // See: https://en.wikipedia.org/wiki/IPv6_addresshttps://en.wikipedia.org/wiki/IPv6_address + do { + let regex = try NSRegularExpression(pattern: "[\\da-f]*:[\\da-f]*:[\\da-f:\\.]*", + options: .caseInsensitive) + return regex.stringByReplacingMatches(in: sdp, options: [], range: NSRange(location: 0, length: sdp.count), withTemplate: "[ REDACTED_IPV6_ADDRESS ]") + } catch { + owsFail("Could not redact IPv6 addresses.") + return "[Could not redact IPv6 addresses.]" + } #endif } } diff --git a/Signal/test/util/OWSScrubbingLogFormatterTest.m b/Signal/test/util/OWSScrubbingLogFormatterTest.m index 27964ebeb..6aa0bf4fb 100644 --- a/Signal/test/util/OWSScrubbingLogFormatterTest.m +++ b/Signal/test/util/OWSScrubbingLogFormatterTest.m @@ -105,18 +105,20 @@ NS_ASSUME_NONNULL_BEGIN id defaultFormatter = [DDLogFileFormatterDefault new]; NSDictionary *valueMap = @{ - @"0.0.0.0" : @"[ REDACTED_IP_ADDRESS:...0 ]", - @"127.0.0.1" : @"[ REDACTED_IP_ADDRESS:...1 ]", - @"255.255.255.255" : @"[ REDACTED_IP_ADDRESS:...255 ]", - @"1.2.3.4" : @"[ REDACTED_IP_ADDRESS:...4 ]", - @"0.0.0.0.0.0" : @"[ REDACTED_IP_ADDRESS:...0 ]", - @"255.255.255.255.255.255" : @"[ REDACTED_IP_ADDRESS:...255 ]", + @"0.0.0.0" : @"[ REDACTED_IPV4_ADDRESS:...0 ]", + @"127.0.0.1" : @"[ REDACTED_IPV4_ADDRESS:...1 ]", + @"255.255.255.255" : @"[ REDACTED_IPV4_ADDRESS:...255 ]", + @"1.2.3.4" : @"[ REDACTED_IPV4_ADDRESS:...4 ]", }; NSArray *messageFormats = @[ @"a%@b", @"http://%@", + @"http://%@/", @"%@ and %@ and %@", @"%@", + @"%@ %@", + @"no ip address!", + @"", ]; for (NSString *ipAddress in valueMap) { @@ -125,16 +127,18 @@ NS_ASSUME_NONNULL_BEGIN for (NSString *messageFormat in messageFormats) { NSString *message = [messageFormat stringByReplacingOccurrencesOfString:@"%@" withString:ipAddress]; + NSString *unredactedMessage = [defaultFormatter formatLogMessage:[self messageWithString:messageFormat]]; NSString *expectedRedactedMessage = [defaultFormatter formatLogMessage:[self messageWithString:[messageFormat stringByReplacingOccurrencesOfString:@"%@" withString:redactedIPAddress]]]; NSString *redactedMessage = [scrubbingFormatter formatLogMessage:[self messageWithString:message]]; - XCTAssertEqualObjects(expectedRedactedMessage, redactedMessage); + XCTAssertEqualObjects( + expectedRedactedMessage, redactedMessage, @"Scrubbing failed for message: %@", unredactedMessage); NSRange ipAddressRange = [redactedMessage rangeOfString:ipAddress]; - XCTAssertEqual(NSNotFound, ipAddressRange.location, "Failed to redact IP address: %@", redactedMessage); + XCTAssertEqual(NSNotFound, ipAddressRange.location, "Failed to redact IP address: %@", unredactedMessage); } } } diff --git a/SignalMessaging/utils/OWSScrubbingLogFormatter.m b/SignalMessaging/utils/OWSScrubbingLogFormatter.m index 1cb851f67..c60d14cf0 100644 --- a/SignalMessaging/utils/OWSScrubbingLogFormatter.m +++ b/SignalMessaging/utils/OWSScrubbingLogFormatter.m @@ -40,16 +40,14 @@ NS_ASSUME_NONNULL_BEGIN return regex; } -- (NSRegularExpression *)ipAddressRegex +- (NSRegularExpression *)ipV4AddressRegex { static NSRegularExpression *regex = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - // Match IPv4 and IPv6 addresses. - // - // NOTE: the second group matches the last "quad/hex?" of the IPv4/IPv6 address. + // NOTE: The group matches the last quad of the IPv4 address. NSError *error; - regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d+\\.\\d+\\.)?\\d+\\.\\d+\\.\\d+\\.(\\d+)" + regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+\\.\\d+\\.\\d+\\.(\\d+)" options:NSRegularExpressionCaseInsensitive error:&error]; if (error || !regex) { @@ -79,11 +77,11 @@ NS_ASSUME_NONNULL_BEGIN range:NSMakeRange(0, [logString length]) withTemplate:@"[ REDACTED_DATA:$1... ]"]; - NSRegularExpression *ipAddressRegex = self.ipAddressRegex; - logString = [ipAddressRegex stringByReplacingMatchesInString:logString - options:0 - range:NSMakeRange(0, [logString length]) - withTemplate:@"[ REDACTED_IP_ADDRESS:...$2 ]"]; + NSRegularExpression *ipV4AddressRegex = self.ipV4AddressRegex; + logString = [ipV4AddressRegex stringByReplacingMatchesInString:logString + options:0 + range:NSMakeRange(0, [logString length]) + withTemplate:@"[ REDACTED_IPV4_ADDRESS:...$1 ]"]; return logString; }