2 * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
30 This file incorporates code from securityd_files.c (iOS) and iOSforOSX.c (OSX).
33 #include <TargetConditionals.h>
34 #include <AssertMacros.h>
35 #include <CoreFoundation/CFPriv.h>
36 #include <CoreFoundation/CFString.h>
37 #include <CoreFoundation/CFURL.h>
38 #include <CoreFoundation/CFUtilities.h>
39 #include <utilities/SecCFWrappers.h>
40 #include <utilities/SecCFRelease.h>
42 #include <sys/param.h>
43 #include <sys/errno.h>
44 #include <uuid/uuid.h>
48 #include "SecFileLocations.h"
50 static CFURLRef sCustomHomeURL
= NULL
;
52 CFURLRef
SecCopyHomeURL(void)
54 // This returns a CFURLRef so that it can be passed as the second parameter
55 // to CFURLCreateCopyAppendingPathComponent
57 CFURLRef homeURL
= sCustomHomeURL
;
61 homeURL
= CFCopyHomeDirectoryURL();
68 static const char * get_host_uuid()
70 static uuid_string_t hostuuid
= {};
71 static dispatch_once_t onceToken
;
72 dispatch_once(&onceToken
, ^{
73 struct timespec timeout
= {30, 0};
75 if (gethostuuid(uuid
, &timeout
) == 0) {
76 uuid_unparse(uuid
, hostuuid
);
78 secerror("failed to get host uuid");
85 static CFStringRef
copy_keychain_uuid_path(CFURLRef keyChainBaseURL
)
87 CFStringRef baseURLString
= NULL
;
88 CFStringRef uuid_path
= NULL
;
90 require(keyChainBaseURL
, done
);
92 baseURLString
= CFURLCopyFileSystemPath(keyChainBaseURL
, kCFURLPOSIXPathStyle
);
93 require(baseURLString
, done
);
95 uuid_path
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@/%s"), baseURLString
, get_host_uuid());
98 CFReleaseSafe(baseURLString
);
102 // See _kb_verify_create_path in securityd
103 static bool keychain_verify_create_path(const char *keychainBasePath
)
105 bool created
= false;
106 struct stat st_info
= {};
107 char new_path
[PATH_MAX
] = {};
108 char kb_path
[PATH_MAX
] = {};
109 snprintf(kb_path
, sizeof(kb_path
), "%s", keychainBasePath
);
110 if (lstat(kb_path
, &st_info
) == 0) {
111 if (S_ISDIR(st_info
.st_mode
)) {
114 secerror("invalid directory at '%s' moving aside", kb_path
);
115 snprintf(new_path
, sizeof(new_path
), "%s-invalid", kb_path
);
117 if (rename(kb_path
, new_path
) != 0) {
118 secerror("failed to rename file: %s (%s)", kb_path
, strerror(errno
));
124 errno_t err
= mkpath_np(kb_path
, 0700);
125 require_action(err
== 0 || err
== EEXIST
, done
, secerror("could not create path: %s (%s)", kb_path
, strerror(err
)));
132 #endif /* TARGET_OS_OSX */
134 static CFURLRef
SecCopyBaseFilesURL(bool system
)
136 CFURLRef baseURL
= sCustomHomeURL
;
142 baseURL
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/"), kCFURLPOSIXPathStyle
, true);
144 baseURL
= SecCopyHomeURL();
146 #elif TARGET_OS_SIMULATOR
147 baseURL
= SecCopyHomeURL();
149 baseURL
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/"), kCFURLPOSIXPathStyle
, true);
155 static CFURLRef
SecCopyURLForFileInBaseDirectory(bool system
, CFStringRef directoryPath
, CFStringRef fileName
)
157 CFURLRef fileURL
= NULL
;
158 CFStringRef suffix
= NULL
;
159 CFURLRef homeURL
= SecCopyBaseFilesURL(system
);
162 suffix
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@/%@"), directoryPath
, fileName
);
165 suffix
= CFStringCreateCopy(kCFAllocatorDefault
, directoryPath
);
167 if (homeURL
&& suffix
)
168 fileURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault
, homeURL
, suffix
, false);
169 CFReleaseSafe(suffix
);
170 CFReleaseSafe(homeURL
);
174 CFURLRef
SecCopyURLForFileInKeychainDirectory(CFStringRef fileName
)
177 // need to tack on uuid here
178 Boolean isDirectory
= (fileName
== NULL
);
179 CFURLRef resultURL
= NULL
;
180 CFStringRef resultStr
= NULL
;
181 __block
bool directoryExists
= false;
183 CFURLRef keyChainBaseURL
= SecCopyURLForFileInBaseDirectory(false, CFSTR("Library/Keychains"), NULL
);
184 CFStringRef uuid_path
= copy_keychain_uuid_path(keyChainBaseURL
);
185 CFStringPerformWithCString(uuid_path
, ^(const char *utf8Str
) {
186 directoryExists
= keychain_verify_create_path(utf8Str
);
188 require(directoryExists
, done
);
190 resultStr
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@/%@"), uuid_path
, fileName
);
192 resultStr
= CFStringCreateCopy(kCFAllocatorDefault
, uuid_path
);
195 CFReleaseSafe(uuid_path
);
196 CFReleaseSafe(keyChainBaseURL
);
199 resultURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, resultStr
, kCFURLPOSIXPathStyle
, isDirectory
);
200 CFRelease(resultStr
);
203 #else /* !TARGET_OS_OSX */
204 return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains"), fileName
);
208 CFURLRef
SecCopyURLForFileInSystemKeychainDirectory(CFStringRef fileName
) {
209 return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains"), fileName
);
212 CFURLRef
SecCopyURLForFileInUserCacheDirectory(CFStringRef fileName
)
215 Boolean isDirectory
= (fileName
== NULL
);
216 CFURLRef resultURL
= NULL
;
217 CFStringRef cacheDirStr
= NULL
;
218 char strBuffer
[PATH_MAX
+ 1];
219 size_t result
= confstr(_CS_DARWIN_USER_CACHE_DIR
, strBuffer
, sizeof(strBuffer
));
221 syslog(LOG_CRIT
, "SecCopyURLForFileInUserCacheDirectory: confstr on _CS_DARWIN_USER_CACHE_DIR failed: %d", errno
);
224 cacheDirStr
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s/%@"), strBuffer
, fileName
);
226 resultURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, cacheDirStr
, kCFURLPOSIXPathStyle
, isDirectory
);
228 CFReleaseSafe(cacheDirStr
);
231 return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Caches"), fileName
);
235 CFURLRef
SecCopyURLForFileInPreferencesDirectory(CFStringRef fileName
)
237 return SecCopyURLForFileInBaseDirectory(false, CFSTR("Library/Preferences"), fileName
);
240 CFURLRef
SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName
)
242 CFURLRef resultURL
= NULL
;
244 CFStringRef userName
;
246 userName
= CFCopyUserName();
248 userName
= CFStringCreateWithCString(kCFAllocatorDefault
, "mobile", kCFStringEncodingASCII
);
252 CFStringRef path
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("/Library/Managed Preferences/%@/%@"), userName
, fileName
);
254 resultURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, path
, kCFURLPOSIXPathStyle
, false);
257 CFReleaseSafe(userName
);
263 CFURLRef
SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName
)
265 return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains/crls/"), fileName
);
268 static void WithPathInDirectory(CFURLRef fileURL
, void(^operation
)(const char *utf8String
))
270 /* Ownership of fileURL is taken by this function and so we release it. */
272 UInt8 buffer
[PATH_MAX
];
273 CFURLGetFileSystemRepresentation(fileURL
, false, buffer
, sizeof(buffer
));
275 operation((const char*)buffer
);
280 void WithPathInRevocationInfoDirectory(CFStringRef fileName
, void(^operation
)(const char *utf8String
))
282 WithPathInDirectory(SecCopyURLForFileInRevocationInfoDirectory(fileName
), operation
);
285 void WithPathInKeychainDirectory(CFStringRef fileName
, void(^operation
)(const char *utf8String
))
287 WithPathInDirectory(SecCopyURLForFileInKeychainDirectory(fileName
), operation
);
290 void WithPathInUserCacheDirectory(CFStringRef fileName
, void(^operation
)(const char *utf8String
))
292 WithPathInDirectory(SecCopyURLForFileInUserCacheDirectory(fileName
), operation
);
295 void SetCustomHomeURL(CFURLRef url
)
297 sCustomHomeURL
= CFRetainSafe(url
);
301 void SetCustomHomeURLString(CFStringRef home_path
)
303 CFReleaseNull(sCustomHomeURL
);
305 sCustomHomeURL
= CFURLCreateWithFileSystemPath(NULL
, home_path
, kCFURLPOSIXPathStyle
, true);
309 void SetCustomHomePath(const char* path
)
312 CFStringRef path_cf
= CFStringCreateWithCStringNoCopy(NULL
, path
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
313 SetCustomHomeURLString(path_cf
);
314 CFReleaseSafe(path_cf
);
316 SetCustomHomeURLString(NULL
);