3 // SecurityUtilityTests
6 #import <XCTest/XCTest.h>
7 #import "utilities/SecXPCHelper.h"
9 @interface UnsafeType : NSObject
10 @property(class, readonly) BOOL supportsSecureCoding;
11 - (id)initWithCoder:(NSCoder *)decoder;
14 @implementation UnsafeType
20 + (BOOL)supportsSecureCoding {
24 - (id)initWithCoder:(NSCoder *)decoder {
25 return [[UnsafeType alloc] init];
30 @interface SafeType : NSObject
31 @property(class, readonly) BOOL supportsSecureCoding;
32 - (id)initWithCoder:(NSCoder *)decoder;
35 @implementation SafeType
41 + (BOOL)supportsSecureCoding {
45 - (id)initWithCoder:(NSCoder *)decoder {
46 return [[SafeType alloc] init];
51 @interface SecXPCHelperTests : XCTestCase
54 @implementation SecXPCHelperTests
56 - (void)testSanitizerWithNilError {
57 XCTAssertNil([SecXPCHelper cleanseErrorForXPC:nil]);
60 - (void)testSanitizerWithCleanError {
61 NSDictionary *cleanInfo = @{@"Key" : @"Safe String"};
62 NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:-1 userInfo:cleanInfo];
63 NSError *cleansed = [SecXPCHelper cleanseErrorForXPC:error];
64 XCTAssertNotNil(cleansed);
65 XCTAssertTrue(cleansed.code == error.code);
66 XCTAssertTrue(cleansed.domain == error.domain);
67 XCTAssertTrue([cleansed.userInfo isEqualToDictionary:cleanInfo]);
70 - (void)testSanitizerWithSafeCodingError {
71 SafeType *safe = [[SafeType alloc] init];
72 NSDictionary *cleanInfo = @{@"Key" : safe};
73 NSDictionary *sanitizedInfo = @{@"Key" : [[safe class] description]};
74 NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:-1 userInfo:cleanInfo];
75 NSError *cleansed = [SecXPCHelper cleanseErrorForXPC:error];
76 XCTAssertNotNil(cleansed);
77 XCTAssertTrue(cleansed.code == error.code);
78 XCTAssertTrue(cleansed.domain == error.domain);
79 XCTAssertTrue([cleansed.userInfo isEqualToDictionary:sanitizedInfo]);
82 - (void)testSanitizerWithDirtyUnsafeError {
83 UnsafeType *unsafe = [[UnsafeType alloc] init];
84 NSDictionary *cleanInfo = @{@"Key" : unsafe};
85 NSDictionary *sanitizedInfo = @{@"Key" : [[unsafe class] description]};
86 NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:-1 userInfo:cleanInfo];
87 NSError *cleansed = [SecXPCHelper cleanseErrorForXPC:error];
88 XCTAssertNotNil(cleansed);
89 XCTAssertTrue(cleansed.code == error.code);
90 XCTAssertTrue(cleansed.domain == error.domain);
91 XCTAssertTrue([cleansed.userInfo isEqualToDictionary:sanitizedInfo]);
94 - (void)testErrorEncodingUnsafe {
95 NSDictionary *unsafeInfo = @{ @"info" : [[NSObject alloc] init] };
96 NSError *unsafeError = [NSError errorWithDomain:@"domain" code:23 userInfo:unsafeInfo];
97 NSData *unsafeEncodedData = nil;
98 bool exceptionCaught = false;
100 unsafeEncodedData = [SecXPCHelper encodedDataFromError:unsafeError];
101 } @catch (NSException *e) {
103 XCTAssertEqualObjects(e.name, NSInvalidUnarchiveOperationException);
104 exceptionCaught = true;
106 XCTAssertTrue(exceptionCaught);
107 XCTAssertNil(unsafeEncodedData);
110 - (void)testErrorEncodingSafe {
111 NSDictionary *safeInfo = @{ @"info" : @(57) };
112 NSError *safeError = [NSError errorWithDomain:@"domain" code:19 userInfo:safeInfo];
113 NSData *safeEncodedData = [SecXPCHelper encodedDataFromError:safeError];
114 XCTAssertNotNil(safeEncodedData);
115 NSError *decodedSafeError = [SecXPCHelper errorFromEncodedData:safeEncodedData];
116 XCTAssertNotNil(decodedSafeError);
117 XCTAssertEqualObjects(decodedSafeError.domain, safeError.domain);
118 XCTAssertEqual(decodedSafeError.code, safeError.code);
119 XCTAssertEqualObjects(decodedSafeError.userInfo, safeError.userInfo);
121 /* Double-check the archive key */
122 NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:safeEncodedData error:NULL];
123 XCTAssertNotNil(unarchiver);
124 XCTAssertTrue([unarchiver containsValueForKey:@"error"], "missing expected key (this is a wire format!)");