]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/SecFileLocations.c
Security-58286.51.6.tar.gz
[apple/security.git] / OSX / utilities / src / SecFileLocations.c
1 /*
2 * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 //
25 // SecFileLocations.c
26 // utilities
27 //
28
29 /*
30 This file incorporates code from securityd_files.c (iOS) and iOSforOSX.c (OSX).
31 */
32
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>
41 #include <sys/stat.h>
42 #include <sys/param.h>
43 #include <sys/errno.h>
44 #include <uuid/uuid.h>
45 #include <copyfile.h>
46 #include <syslog.h>
47
48 #include "SecFileLocations.h"
49
50 static CFURLRef sCustomHomeURL = NULL;
51
52 CFURLRef SecCopyHomeURL(void)
53 {
54 // This returns a CFURLRef so that it can be passed as the second parameter
55 // to CFURLCreateCopyAppendingPathComponent
56
57 CFURLRef homeURL = sCustomHomeURL;
58 if (homeURL) {
59 CFRetain(homeURL);
60 } else {
61 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
62 // We would use CFCopyHomeDirectoryURL but it doesn't exist on MACOS.
63 // This does the same.
64 homeURL = CFCopyHomeDirectoryURLForUser(NULL);
65 #else
66 homeURL = CFCopyHomeDirectoryURL();
67 #endif
68 }
69
70 return homeURL;
71 }
72
73 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
74 static const char * get_host_uuid()
75 {
76 static uuid_string_t hostuuid = {};
77 static dispatch_once_t onceToken;
78 dispatch_once(&onceToken, ^{
79 struct timespec timeout = {30, 0};
80 uuid_t uuid = {};
81 if (gethostuuid(uuid, &timeout) == 0) {
82 uuid_unparse(uuid, hostuuid);
83 } else {
84 secerror("failed to get host uuid");
85 }
86 });
87
88 return hostuuid;
89 }
90
91 static CFStringRef copy_keychain_uuid_path(CFURLRef keyChainBaseURL)
92 {
93 CFStringRef baseURLString = NULL;
94 CFStringRef uuid_path = NULL;
95
96 require(keyChainBaseURL, done);
97
98 baseURLString = CFURLCopyFileSystemPath(keyChainBaseURL, kCFURLPOSIXPathStyle);
99 require(baseURLString, done);
100
101 uuid_path = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@/%s"), baseURLString, get_host_uuid());
102
103 done:
104 CFReleaseSafe(baseURLString);
105 return uuid_path;
106 }
107
108 // See _kb_verify_create_path in securityd
109 static bool keychain_verify_create_path(const char *keychainBasePath)
110 {
111 bool created = false;
112 struct stat st_info = {};
113 char new_path[PATH_MAX] = {};
114 char kb_path[PATH_MAX] = {};
115 snprintf(kb_path, sizeof(kb_path), "%s", keychainBasePath);
116 if (lstat(kb_path, &st_info) == 0) {
117 if (S_ISDIR(st_info.st_mode)) {
118 created = true;
119 } else {
120 secerror("invalid directory at '%s' moving aside", kb_path);
121 snprintf(new_path, sizeof(new_path), "%s-invalid", kb_path);
122 unlink(new_path);
123 if (rename(kb_path, new_path) != 0) {
124 secerror("failed to rename file: %s (%s)", kb_path, strerror(errno));
125 goto done;
126 }
127 }
128 }
129 if (!created) {
130 require_action(mkpath_np(kb_path, 0700) == 0, done, secerror("could not create path: %s (%s)", kb_path, strerror(errno)));
131 created = true;
132 }
133
134 done:
135 return created;
136 }
137 #endif /*(TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
138
139 static CFURLRef SecCopyBaseFilesURL()
140 {
141 CFURLRef baseURL = sCustomHomeURL;
142 if (baseURL) {
143 CFRetain(baseURL);
144 } else {
145 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED))
146 baseURL = SecCopyHomeURL();
147 #else
148 baseURL = CFURLCreateWithFileSystemPath(NULL, CFSTR("/"), kCFURLPOSIXPathStyle, true);
149 #endif
150 }
151 return baseURL;
152 }
153
154 static CFURLRef SecCopyURLForFileInBaseDirectory(CFStringRef directoryPath, CFStringRef fileName)
155 {
156 CFURLRef fileURL = NULL;
157 CFStringRef suffix = NULL;
158 CFURLRef homeURL = SecCopyBaseFilesURL();
159
160 if (fileName)
161 suffix = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@/%@"), directoryPath, fileName);
162 else
163 if (directoryPath)
164 suffix = CFStringCreateCopy(kCFAllocatorDefault, directoryPath);
165
166 if (homeURL && suffix)
167 fileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, homeURL, suffix, false);
168 CFReleaseSafe(suffix);
169 CFReleaseSafe(homeURL);
170 return fileURL;
171 }
172
173 CFURLRef SecCopyURLForFileInKeychainDirectory(CFStringRef fileName)
174 {
175 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
176 // need to tack on uuid here
177 Boolean isDirectory = (fileName == NULL);
178 CFURLRef resultURL = NULL;
179 CFStringRef resultStr = NULL;
180 __block bool directoryExists = false;
181
182 CFURLRef keyChainBaseURL = SecCopyURLForFileInBaseDirectory(CFSTR("Library/Keychains"), NULL);
183 CFStringRef uuid_path = copy_keychain_uuid_path(keyChainBaseURL);
184 CFStringPerformWithCString(uuid_path, ^(const char *utf8Str) {
185 directoryExists = keychain_verify_create_path(utf8Str);
186 });
187 require(directoryExists, done);
188 if (fileName)
189 resultStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@/%@"), uuid_path, fileName);
190 else
191 resultStr = CFStringCreateCopy(kCFAllocatorDefault, uuid_path);
192
193 done:
194 CFReleaseSafe(uuid_path);
195 CFReleaseSafe(keyChainBaseURL);
196 if (resultStr)
197 {
198 resultURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, resultStr, kCFURLPOSIXPathStyle, isDirectory);
199 CFRelease(resultStr);
200 }
201 return resultURL;
202 #else
203 return SecCopyURLForFileInBaseDirectory(CFSTR("Library/Keychains"), fileName);
204 #endif
205 }
206
207 CFURLRef SecCopyURLForFileInUserCacheDirectory(CFStringRef fileName)
208 {
209 #if TARGET_OS_OSX
210 Boolean isDirectory = (fileName == NULL);
211 CFURLRef resultURL = NULL;
212 CFStringRef cacheDirStr = NULL;
213 char strBuffer[PATH_MAX + 1];
214 size_t result = confstr(_CS_DARWIN_USER_CACHE_DIR, strBuffer, sizeof(strBuffer));
215 if (result == 0) {
216 syslog(LOG_CRIT, "SecCopyURLForFileInUserCacheDirectory: confstr on _CS_DARWIN_USER_CACHE_DIR failed: %d", errno);
217 return resultURL;
218 }
219 cacheDirStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/%@"), strBuffer, fileName);
220 if (cacheDirStr) {
221 resultURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cacheDirStr, kCFURLPOSIXPathStyle, isDirectory);
222 }
223 CFReleaseSafe(cacheDirStr);
224 return resultURL;
225 #else
226 return SecCopyURLForFileInBaseDirectory(CFSTR("Library/Caches"), fileName);
227 #endif
228 }
229
230 CFURLRef SecCopyURLForFileInPreferencesDirectory(CFStringRef fileName)
231 {
232 return SecCopyURLForFileInBaseDirectory(CFSTR("Library/Preferences"), fileName);
233 }
234
235 CFURLRef SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName)
236 {
237 CFURLRef resultURL = NULL;
238
239 CFStringRef userName;
240 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
241 userName = CFCopyUserName();
242 #else
243 userName = CFStringCreateWithCString(kCFAllocatorDefault, "mobile", kCFStringEncodingASCII);
244 #endif
245
246 if (userName) {
247 CFStringRef path = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/Library/Managed Preferences/%@/%@"), userName, fileName);
248 if (path) {
249 resultURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, false);
250 CFReleaseSafe(path);
251 }
252 CFReleaseSafe(userName);
253 }
254
255 return resultURL;
256 }
257
258 CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName)
259 {
260 CFURLRef resultURL = NULL;
261 CFStringRef path = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/Library/Keychains/crls/%@"), fileName);
262 if (path) {
263 resultURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, false);
264 CFReleaseSafe(path);
265 }
266 return resultURL;
267 }
268
269 static void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String))
270 {
271 /* Ownership of fileURL is taken by this function and so we release it. */
272 if (fileURL) {
273 UInt8 buffer[PATH_MAX];
274 CFURLGetFileSystemRepresentation(fileURL, false, buffer, sizeof(buffer));
275
276 operation((const char*)buffer);
277 CFRelease(fileURL);
278 }
279 }
280
281 void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String))
282 {
283 WithPathInDirectory(SecCopyURLForFileInRevocationInfoDirectory(fileName), operation);
284 }
285
286 void WithPathInKeychainDirectory(CFStringRef fileName, void(^operation)(const char *utf8String))
287 {
288 WithPathInDirectory(SecCopyURLForFileInKeychainDirectory(fileName), operation);
289 }
290
291 void WithPathInUserCacheDirectory(CFStringRef fileName, void(^operation)(const char *utf8String))
292 {
293 WithPathInDirectory(SecCopyURLForFileInUserCacheDirectory(fileName), operation);
294 }
295
296 void SetCustomHomeURL(CFURLRef url)
297 {
298 sCustomHomeURL = CFRetainSafe(url);
299 }
300
301
302 void SetCustomHomeURLString(CFStringRef home_path)
303 {
304 CFReleaseNull(sCustomHomeURL);
305 if (home_path) {
306 sCustomHomeURL = CFURLCreateWithFileSystemPath(NULL, home_path, kCFURLPOSIXPathStyle, true);
307 }
308 }
309
310 void SetCustomHomePath(const char* path)
311 {
312 if (path) {
313 CFStringRef path_cf = CFStringCreateWithCStringNoCopy(NULL, path, kCFStringEncodingUTF8, kCFAllocatorNull);
314 SetCustomHomeURLString(path_cf);
315 CFReleaseSafe(path_cf);
316 } else {
317 SetCustomHomeURLString(NULL);
318 }
319 }
320
321