cherry-pick Merge branch 'charlesmchen/logSdp'

pull/1/head
Matthew Chen 7 years ago committed by Michael Kirk
parent d57c2f5157
commit 9ab4da5c81

@ -407,6 +407,8 @@ private class SignalCallData: NSObject {
throw CallError.obsoleteCall(description: "Missing peerConnectionClient in \(#function)") throw CallError.obsoleteCall(description: "Missing peerConnectionClient in \(#function)")
} }
Logger.info("session description for outgoing call: \(call.identifiersForLogs), sdp: \(sessionDescription.logSafeDescription).")
return peerConnectionClient.setLocalSessionDescription(sessionDescription).then { return peerConnectionClient.setLocalSessionDescription(sessionDescription).then {
do { do {
let offerBuilder = SSKProtoCallMessageOffer.SSKProtoCallMessageOfferBuilder(id: call.signalingId, let offerBuilder = SSKProtoCallMessageOffer.SSKProtoCallMessageOfferBuilder(id: call.signalingId,
@ -708,12 +710,12 @@ private class SignalCallData: NSObject {
// Find a sessionDescription compatible with my constraints and the remote sessionDescription // Find a sessionDescription compatible with my constraints and the remote sessionDescription
return peerConnectionClient.negotiateSessionDescription(remoteDescription: offerSessionDescription, constraints: constraints) return peerConnectionClient.negotiateSessionDescription(remoteDescription: offerSessionDescription, constraints: constraints)
}.then { (negotiatedSessionDescription: HardenedRTCSessionDescription) in }.then { (negotiatedSessionDescription: HardenedRTCSessionDescription) in
Logger.debug("\(self.logTag) set the remote description for: \(newCall.identifiersForLogs)")
guard self.call == newCall else { guard self.call == newCall else {
throw CallError.obsoleteCall(description: "negotiateSessionDescription() response for obsolete call") throw CallError.obsoleteCall(description: "negotiateSessionDescription() response for obsolete call")
} }
Logger.info("session description for incoming call: \(newCall.identifiersForLogs), sdp: \(negotiatedSessionDescription.logSafeDescription).")
do { do {
let answerBuilder = SSKProtoCallMessageAnswer.SSKProtoCallMessageAnswerBuilder(id: newCall.signalingId, let answerBuilder = SSKProtoCallMessageAnswer.SSKProtoCallMessageAnswerBuilder(id: newCall.signalingId,
sessionDescription: negotiatedSessionDescription.sdp) sessionDescription: negotiatedSessionDescription.sdp)

@ -1115,6 +1115,58 @@ class HardenedRTCSessionDescription {
return RTCSessionDescription.init(type: rtcSessionDescription.type, sdp: description) return RTCSessionDescription.init(type: rtcSessionDescription.type, sdp: description)
} }
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")
let lines = text.components(separatedBy: "\n")
let filteredLines: [String] = lines.map { line in
guard !line.contains("ice-pwd") else {
return "[ REDACTED ice-pwd ]"
}
return line
}
let filteredText = filteredLines.joined(separator: "\n")
return filteredText
#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
}
} }
protocol VideoCaptureSettingsDelegate: class { protocol VideoCaptureSettingsDelegate: class {

@ -130,7 +130,7 @@ class PeerConnectionClientTest: XCTestCase {
XCTAssertEqual(1, clientDelegate.dataChannelMessages.count) XCTAssertEqual(1, clientDelegate.dataChannelMessages.count)
let dataChannelMessageProto = clientDelegate.dataChannelMessages[0] let dataChannelMessageProto = clientDelegate.dataChannelMessages[0]
XCTAssert(dataChannelMessageProto.hasHangup) XCTAssertNotNil(dataChannelMessageProto.hangup)
let hangupProto = dataChannelMessageProto.hangup! let hangupProto = dataChannelMessageProto.hangup!
XCTAssertEqual(123, hangupProto.id) XCTAssertEqual(123, hangupProto.id)

@ -1,5 +1,5 @@
// //
// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
#import "OWSScrubbingLogFormatter.h" #import "OWSScrubbingLogFormatter.h"
@ -9,22 +9,36 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSScrubbingLogFormatterTest : XCTestCase @interface OWSScrubbingLogFormatterTest : XCTestCase
@property (nonatomic) NSDate *testDate;
@end @end
@implementation OWSScrubbingLogFormatterTest @implementation OWSScrubbingLogFormatterTest
- (void)setUp
{
[super setUp];
self.testDate = [NSDate new];
}
- (void)tearDown
{
[super tearDown];
}
- (DDLogMessage *)messageWithString:(NSString *)string - (DDLogMessage *)messageWithString:(NSString *)string
{ {
return [[DDLogMessage alloc] initWithMessage:string return [[DDLogMessage alloc] initWithMessage:string
level:DDLogLevelInfo level:DDLogLevelInfo
flag:0 flag:0
context:0 context:0
file:nil file:@"mock file name"
function:nil function:@"mock function name"
line:0 line:0
tag:nil tag:nil
options:0 options:0
timestamp:[NSDate new]]; timestamp:self.testDate];
} }
- (void)testDataScrubbed - (void)testDataScrubbed
@ -75,7 +89,7 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (void)testNonPhonenumberNotScrubbed - (void)testNonPhoneNumberNotScrubbed
{ {
OWSScrubbingLogFormatter *formatter = [OWSScrubbingLogFormatter new]; OWSScrubbingLogFormatter *formatter = [OWSScrubbingLogFormatter new];
NSString *actual = NSString *actual =
@ -85,6 +99,50 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertNotEqual(NSNotFound, redactedRange.location, "Shouldn't touch non phone string."); XCTAssertNotEqual(NSNotFound, redactedRange.location, "Shouldn't touch non phone string.");
} }
- (void)testIPAddressesScrubbed
{
id<DDLogFormatter> scrubbingFormatter = [OWSScrubbingLogFormatter new];
id<DDLogFormatter> defaultFormatter = [DDLogFileFormatterDefault new];
NSDictionary<NSString *, NSString *> *valueMap = @{
@"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<NSString *> *messageFormats = @[
@"a%@b",
@"http://%@",
@"http://%@/",
@"%@ and %@ and %@",
@"%@",
@"%@ %@",
@"no ip address!",
@"",
];
for (NSString *ipAddress in valueMap) {
NSString *redactedIPAddress = valueMap[ipAddress];
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, @"Scrubbing failed for message: %@", unredactedMessage);
NSRange ipAddressRange = [redactedMessage rangeOfString:ipAddress];
XCTAssertEqual(NSNotFound, ipAddressRange.location, "Failed to redact IP address: %@", unredactedMessage);
}
}
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -1,5 +1,5 @@
// //
// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
#import "OWSScrubbingLogFormatter.h" #import "OWSScrubbingLogFormatter.h"
@ -8,14 +8,60 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSScrubbingLogFormatter @implementation OWSScrubbingLogFormatter
- (NSRegularExpression *)phoneRegex
{
static NSRegularExpression *regex = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSError *error;
regex = [NSRegularExpression regularExpressionWithPattern:@"\\+\\d{7,12}(\\d{3})"
options:NSRegularExpressionCaseInsensitive
error:&error];
if (error || !regex) {
OWSFail(@"%@ could not compile regular expression: %@", self.logTag, error);
}
});
return regex;
}
- (NSRegularExpression *)dataRegex
{
static NSRegularExpression *regex = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSError *error;
regex = [NSRegularExpression regularExpressionWithPattern:@"<([\\da-f]{2})[\\da-f]{6}( [\\da-f]{8})*>"
options:NSRegularExpressionCaseInsensitive
error:&error];
if (error || !regex) {
OWSFail(@"%@ could not compile regular expression: %@", self.logTag, error);
}
});
return regex;
}
- (NSRegularExpression *)ipV4AddressRegex
{
static NSRegularExpression *regex = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// NOTE: The group matches the last quad of the IPv4 address.
NSError *error;
regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+\\.\\d+\\.\\d+\\.(\\d+)"
options:NSRegularExpressionCaseInsensitive
error:&error];
if (error || !regex) {
OWSFail(@"%@ could not compile regular expression: %@", self.logTag, error);
}
});
return regex;
}
- (NSString *__nullable)formatLogMessage:(DDLogMessage *)logMessage - (NSString *__nullable)formatLogMessage:(DDLogMessage *)logMessage
{ {
NSString *logString = [super formatLogMessage:logMessage]; NSString *logString = [super formatLogMessage:logMessage];
NSRegularExpression *phoneRegex =
[NSRegularExpression regularExpressionWithPattern:@"\\+\\d{7,12}(\\d{3})"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSRegularExpression *phoneRegex = self.phoneRegex;
logString = [phoneRegex stringByReplacingMatchesInString:logString logString = [phoneRegex stringByReplacingMatchesInString:logString
options:0 options:0
range:NSMakeRange(0, [logString length]) range:NSMakeRange(0, [logString length])
@ -25,16 +71,18 @@ NS_ASSUME_NONNULL_BEGIN
// We capture only the first two characters of the hex string for logging. // We capture only the first two characters of the hex string for logging.
// example log line: "Called someFunction with nsData: <01234567 89abcdef>" // example log line: "Called someFunction with nsData: <01234567 89abcdef>"
// scrubbed output: "Called someFunction with nsData: [ REDACTED_DATA:01 ]" // scrubbed output: "Called someFunction with nsData: [ REDACTED_DATA:01 ]"
NSRegularExpression *dataRegex = NSRegularExpression *dataRegex = self.dataRegex;
[NSRegularExpression regularExpressionWithPattern:@"<([\\da-f]{2})[\\da-f]{6}( [\\da-f]{8})*>"
options:NSRegularExpressionCaseInsensitive
error:nil];
logString = [dataRegex stringByReplacingMatchesInString:logString logString = [dataRegex stringByReplacingMatchesInString:logString
options:0 options:0
range:NSMakeRange(0, [logString length]) range:NSMakeRange(0, [logString length])
withTemplate:@"[ REDACTED_DATA:$1... ]"]; withTemplate:@"[ REDACTED_DATA:$1... ]"];
NSRegularExpression *ipV4AddressRegex = self.ipV4AddressRegex;
logString = [ipV4AddressRegex stringByReplacingMatchesInString:logString
options:0
range:NSMakeRange(0, [logString length])
withTemplate:@"[ REDACTED_IPV4_ADDRESS:...$1 ]"];
return logString; return logString;
} }

@ -18,28 +18,15 @@
@implementation PhoneNumberUtil @implementation PhoneNumberUtil
+ (NSObject *)sharedLock
{
static dispatch_once_t onceToken;
static NSObject *lock = nil;
dispatch_once(&onceToken, ^{
lock = [NSObject new];
});
return lock;
}
+ (PhoneNumberUtil *)sharedThreadLocal + (PhoneNumberUtil *)sharedThreadLocal
{ {
@synchronized(self.sharedLock) NSString *key = PhoneNumberUtil.logTag;
{ PhoneNumberUtil *_Nullable threadLocal = NSThread.currentThread.threadDictionary[key];
NSString *key = PhoneNumberUtil.logTag; if (!threadLocal) {
PhoneNumberUtil *_Nullable threadLocal = NSThread.currentThread.threadDictionary[key]; threadLocal = [PhoneNumberUtil new];
if (!threadLocal) { NSThread.currentThread.threadDictionary[key] = threadLocal;
threadLocal = [PhoneNumberUtil new];
NSThread.currentThread.threadDictionary[key] = threadLocal;
}
return threadLocal;
} }
return threadLocal;
} }
- (instancetype)init { - (instancetype)init {

Loading…
Cancel
Save