├── security-trust-settings-tools.xcodeproj ├── .gitignore └── project.pbxproj ├── README.md ├── security-trust-settings-merge └── main.m ├── LICENSE └── security-trust-settings-blacklist └── main.m /security-trust-settings-tools.xcodeproj/.gitignore: -------------------------------------------------------------------------------- 1 | *.xcworkspace 2 | xcuserdata 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # security-trust-settings-tools 2 | 3 | OS X Keychain Trust Settings Tools. 4 | 5 | ## Usage 6 | 7 | ### Blacklist Certificates 8 | 9 | ``` sh 10 | security-trust-settings-blacklist [fingerprint ...] TrustSettings.plist 11 | ``` 12 | 13 | Generate blacklist for any certificate based on SHA1 fingerprint. 14 | 15 | 16 | #### Example 17 | 18 | ``` sh 19 | security-trust-settings-blacklist B94294BF91EA8FB64BE61097C7FB001359B676CB TrustSettings.plist 20 | ``` 21 | 22 | --- 23 | 24 | ### Merge Trust Settings 25 | 26 | ``` sh 27 | security-trust-settings-merge [plist ...] TrustSettings.plist 28 | ``` 29 | 30 | Merge multiple trust settings plists. 31 | 32 | #### Example 33 | 34 | ``` sh 35 | security-trust-settings-merge TrustSettings1.plist TrustSettings2.plist NewTrustSettings.plist 36 | ``` 37 | 38 | --- 39 | 40 | 41 | 42 | ### Export System TrustSettings.plist 43 | 44 | ``` sh 45 | security trust-settings-export -d ExportedTrustSettings.plist 46 | ``` 47 | 48 | ### Import System TrustSettings.plist 49 | 50 | ``` sh 51 | sudo security trust-settings-import -d NewTrustSettings.plist 52 | ``` 53 | 54 | 55 | 56 | ## License 57 | 58 | See [LICENSE](LICENSE). 59 | -------------------------------------------------------------------------------- /security-trust-settings-merge/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // security-trust-settings-merge 4 | // 5 | // Created by 夏目夏樹 on 3/27/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | @autoreleasepool { 13 | if (argc < 2) { 14 | printf("Usage: %s [plist ...] TrustSettings.plist\n", argv[0]); 15 | return 0; 16 | } 17 | 18 | NSDictionary *systemTrustSettings = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/Keychains/SystemTrustSettings.plist"]; 19 | NSMutableDictionary *mutableSystemTrustSettings = [systemTrustSettings mutableCopy]; 20 | NSMutableDictionary *mutableTrustList = [[NSMutableDictionary alloc] init]; 21 | 22 | for (int i = 1; i < argc - 1; ++i) { 23 | [mutableTrustList addEntriesFromDictionary:[[NSDictionary dictionaryWithContentsOfFile:[NSString stringWithUTF8String:argv[i]]] objectForKey:@"trustList"]]; 24 | } 25 | 26 | [mutableSystemTrustSettings setValue:mutableTrustList forKey:@"trustList"]; 27 | [mutableSystemTrustSettings writeToFile:[NSString stringWithUTF8String:argv[argc - 1]] atomically:YES]; 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, なつき 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /security-trust-settings-blacklist/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // security-trust-settings-blacklist 4 | // 5 | // Created by 夏目夏樹 on 3/27/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | @autoreleasepool { 13 | if (argc < 2) { 14 | printf("Usage: %s [fingerprint ...] TrustSettings.plist\n", argv[0]); 15 | return 0; 16 | } 17 | 18 | NSDictionary *systemTrustSettings = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/Keychains/SystemTrustSettings.plist"]; 19 | NSMutableDictionary *mutableSystemTrustSettings = [systemTrustSettings mutableCopy]; 20 | NSMutableDictionary *mutableTrustList = [[NSMutableDictionary alloc] init]; 21 | 22 | for (int i = 1; i < argc - 1; ++i) { 23 | NSString *fingerprint = [[[NSString stringWithUTF8String:argv[i]] stringByReplacingOccurrencesOfString:@" " withString:@""] stringByReplacingOccurrencesOfString:@":" withString:@""]; 24 | if ([fingerprint length] != 40) { 25 | fprintf(stderr, "Error: Invalid SHA1 fingerprint: %s\n", argv[i]); 26 | return 1; 27 | } 28 | [mutableTrustList setValue:@{ 29 | @"issuerName" : [[NSData alloc] init], 30 | @"modDate" : [NSDate date], 31 | @"serialNumber" : [[NSData alloc] init], 32 | @"trustSettings" : @[@{(__bridge NSString *)kSecTrustSettingsResult : [NSNumber numberWithInt:kSecTrustSettingsResultDeny]}], 33 | } forKey:fingerprint]; 34 | } 35 | 36 | [mutableSystemTrustSettings setValue:mutableTrustList forKey:@"trustList"]; 37 | [mutableSystemTrustSettings writeToFile:[NSString stringWithUTF8String:argv[argc - 1]] atomically:YES]; 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /security-trust-settings-tools.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 01451D831AC55E9A00B78857 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 01451D821AC55E9A00B78857 /* main.m */; }; 11 | 01451D8E1AC57C2A00B78857 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 01451D8D1AC57C2A00B78857 /* main.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 01451D7E1AC55E9A00B78857 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | 01451D891AC57C2A00B78857 /* CopyFiles */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = /usr/share/man/man1/; 28 | dstSubfolderSpec = 0; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 1; 32 | }; 33 | /* End PBXCopyFilesBuildPhase section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 01451D801AC55E9A00B78857 /* security-trust-settings-merge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "security-trust-settings-merge"; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 01451D821AC55E9A00B78857 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 38 | 01451D8B1AC57C2A00B78857 /* security-trust-settings-blacklist */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "security-trust-settings-blacklist"; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 01451D8D1AC57C2A00B78857 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | 01451D7D1AC55E9A00B78857 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | ); 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | 01451D881AC57C2A00B78857 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 01451D811AC55E9A00B78857 /* security-trust-settings-merge */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 01451D821AC55E9A00B78857 /* main.m */, 64 | ); 65 | path = "security-trust-settings-merge"; 66 | sourceTree = ""; 67 | }; 68 | 01451D8C1AC57C2A00B78857 /* security-trust-settings-blacklist */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 01451D8D1AC57C2A00B78857 /* main.m */, 72 | ); 73 | path = "security-trust-settings-blacklist"; 74 | sourceTree = ""; 75 | }; 76 | 01F59EB51AC55397000EEA47 = { 77 | isa = PBXGroup; 78 | children = ( 79 | 01451D8C1AC57C2A00B78857 /* security-trust-settings-blacklist */, 80 | 01451D811AC55E9A00B78857 /* security-trust-settings-merge */, 81 | 01F59EBF1AC55397000EEA47 /* Products */, 82 | ); 83 | sourceTree = ""; 84 | }; 85 | 01F59EBF1AC55397000EEA47 /* Products */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 01451D8B1AC57C2A00B78857 /* security-trust-settings-blacklist */, 89 | 01451D801AC55E9A00B78857 /* security-trust-settings-merge */, 90 | ); 91 | name = Products; 92 | sourceTree = ""; 93 | }; 94 | /* End PBXGroup section */ 95 | 96 | /* Begin PBXNativeTarget section */ 97 | 01451D7F1AC55E9A00B78857 /* security-trust-settings-merge */ = { 98 | isa = PBXNativeTarget; 99 | buildConfigurationList = 01451D861AC55E9A00B78857 /* Build configuration list for PBXNativeTarget "security-trust-settings-merge" */; 100 | buildPhases = ( 101 | 01451D7C1AC55E9A00B78857 /* Sources */, 102 | 01451D7D1AC55E9A00B78857 /* Frameworks */, 103 | 01451D7E1AC55E9A00B78857 /* CopyFiles */, 104 | ); 105 | buildRules = ( 106 | ); 107 | dependencies = ( 108 | ); 109 | name = "security-trust-settings-merge"; 110 | productName = "security-trust-settings-merge"; 111 | productReference = 01451D801AC55E9A00B78857 /* security-trust-settings-merge */; 112 | productType = "com.apple.product-type.tool"; 113 | }; 114 | 01451D8A1AC57C2A00B78857 /* security-trust-settings-blacklist */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 01451D911AC57C2A00B78857 /* Build configuration list for PBXNativeTarget "security-trust-settings-blacklist" */; 117 | buildPhases = ( 118 | 01451D871AC57C2A00B78857 /* Sources */, 119 | 01451D881AC57C2A00B78857 /* Frameworks */, 120 | 01451D891AC57C2A00B78857 /* CopyFiles */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = "security-trust-settings-blacklist"; 127 | productName = "security-trust-settings-blacklist"; 128 | productReference = 01451D8B1AC57C2A00B78857 /* security-trust-settings-blacklist */; 129 | productType = "com.apple.product-type.tool"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | 01F59EB61AC55397000EEA47 /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastUpgradeCheck = 0620; 138 | TargetAttributes = { 139 | 01451D7F1AC55E9A00B78857 = { 140 | CreatedOnToolsVersion = 6.2; 141 | }; 142 | 01451D8A1AC57C2A00B78857 = { 143 | CreatedOnToolsVersion = 6.2; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 01F59EB91AC55397000EEA47 /* Build configuration list for PBXProject "security-trust-settings-tools" */; 148 | compatibilityVersion = "Xcode 3.2"; 149 | developmentRegion = English; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | ); 154 | mainGroup = 01F59EB51AC55397000EEA47; 155 | productRefGroup = 01F59EBF1AC55397000EEA47 /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 01451D8A1AC57C2A00B78857 /* security-trust-settings-blacklist */, 160 | 01451D7F1AC55E9A00B78857 /* security-trust-settings-merge */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | 01451D7C1AC55E9A00B78857 /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 01451D831AC55E9A00B78857 /* main.m in Sources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | 01451D871AC57C2A00B78857 /* Sources */ = { 175 | isa = PBXSourcesBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | 01451D8E1AC57C2A00B78857 /* main.m in Sources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXSourcesBuildPhase section */ 183 | 184 | /* Begin XCBuildConfiguration section */ 185 | 01451D841AC55E9A00B78857 /* Debug */ = { 186 | isa = XCBuildConfiguration; 187 | buildSettings = { 188 | GCC_PREPROCESSOR_DEFINITIONS = ( 189 | "DEBUG=1", 190 | "$(inherited)", 191 | ); 192 | PRODUCT_NAME = "$(TARGET_NAME)"; 193 | }; 194 | name = Debug; 195 | }; 196 | 01451D851AC55E9A00B78857 /* Release */ = { 197 | isa = XCBuildConfiguration; 198 | buildSettings = { 199 | PRODUCT_NAME = "$(TARGET_NAME)"; 200 | }; 201 | name = Release; 202 | }; 203 | 01451D8F1AC57C2A00B78857 /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | GCC_PREPROCESSOR_DEFINITIONS = ( 207 | "DEBUG=1", 208 | "$(inherited)", 209 | ); 210 | PRODUCT_NAME = "$(TARGET_NAME)"; 211 | }; 212 | name = Debug; 213 | }; 214 | 01451D901AC57C2A00B78857 /* Release */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | PRODUCT_NAME = "$(TARGET_NAME)"; 218 | }; 219 | name = Release; 220 | }; 221 | 01F59EC31AC55397000EEA47 /* Debug */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | ALWAYS_SEARCH_USER_PATHS = NO; 225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 226 | CLANG_CXX_LIBRARY = "libc++"; 227 | CLANG_ENABLE_MODULES = YES; 228 | CLANG_ENABLE_OBJC_ARC = YES; 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 232 | CLANG_WARN_EMPTY_BODY = YES; 233 | CLANG_WARN_ENUM_CONVERSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | COPY_PHASE_STRIP = NO; 239 | ENABLE_STRICT_OBJC_MSGSEND = YES; 240 | GCC_C_LANGUAGE_STANDARD = gnu99; 241 | GCC_DYNAMIC_NO_PIC = NO; 242 | GCC_OPTIMIZATION_LEVEL = 0; 243 | GCC_PREPROCESSOR_DEFINITIONS = ( 244 | "DEBUG=1", 245 | "$(inherited)", 246 | ); 247 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 248 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 249 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 250 | GCC_WARN_UNDECLARED_SELECTOR = YES; 251 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 252 | GCC_WARN_UNUSED_FUNCTION = YES; 253 | GCC_WARN_UNUSED_VARIABLE = YES; 254 | MACOSX_DEPLOYMENT_TARGET = 10.6; 255 | MTL_ENABLE_DEBUG_INFO = YES; 256 | ONLY_ACTIVE_ARCH = YES; 257 | SDKROOT = macosx; 258 | }; 259 | name = Debug; 260 | }; 261 | 01F59EC41AC55397000EEA47 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | COPY_PHASE_STRIP = YES; 279 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 280 | ENABLE_NS_ASSERTIONS = NO; 281 | ENABLE_STRICT_OBJC_MSGSEND = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu99; 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | MACOSX_DEPLOYMENT_TARGET = 10.6; 290 | MTL_ENABLE_DEBUG_INFO = NO; 291 | SDKROOT = macosx; 292 | }; 293 | name = Release; 294 | }; 295 | /* End XCBuildConfiguration section */ 296 | 297 | /* Begin XCConfigurationList section */ 298 | 01451D861AC55E9A00B78857 /* Build configuration list for PBXNativeTarget "security-trust-settings-merge" */ = { 299 | isa = XCConfigurationList; 300 | buildConfigurations = ( 301 | 01451D841AC55E9A00B78857 /* Debug */, 302 | 01451D851AC55E9A00B78857 /* Release */, 303 | ); 304 | defaultConfigurationIsVisible = 0; 305 | defaultConfigurationName = Release; 306 | }; 307 | 01451D911AC57C2A00B78857 /* Build configuration list for PBXNativeTarget "security-trust-settings-blacklist" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 01451D8F1AC57C2A00B78857 /* Debug */, 311 | 01451D901AC57C2A00B78857 /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | defaultConfigurationName = Release; 315 | }; 316 | 01F59EB91AC55397000EEA47 /* Build configuration list for PBXProject "security-trust-settings-tools" */ = { 317 | isa = XCConfigurationList; 318 | buildConfigurations = ( 319 | 01F59EC31AC55397000EEA47 /* Debug */, 320 | 01F59EC41AC55397000EEA47 /* Release */, 321 | ); 322 | defaultConfigurationIsVisible = 0; 323 | defaultConfigurationName = Release; 324 | }; 325 | /* End XCConfigurationList section */ 326 | }; 327 | rootObject = 01F59EB61AC55397000EEA47 /* Project object */; 328 | } 329 | --------------------------------------------------------------------------------