]> git.saurik.com Git - apple/security.git/blob - trust/trustd/SecTrustStoreServer.c
Security-59754.80.3.tar.gz
[apple/security.git] / trust / trustd / SecTrustStoreServer.c
1 /*
2 * Copyright (c) 2007-2010,2012-2015 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 * SecTrustStoreServer.c - CertificateSource API to a system root certificate store
26 */
27 #include "SecTrustStoreServer.h"
28
29 #include <Security/SecCertificateInternal.h>
30 #include <Security/SecFramework.h>
31 #include <errno.h>
32 #include <limits.h>
33 #include <dispatch/dispatch.h>
34 #include <sqlite3.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <CoreFoundation/CFData.h>
42 #include <CoreFoundation/CFPropertyList.h>
43 #include <CoreFoundation/CFURL.h>
44 #include <AssertMacros.h>
45 #include <utilities/debugging.h>
46 #include <Security/SecBasePriv.h>
47 #include <Security/SecInternal.h>
48 #include <ipc/securityd_client.h>
49 #include "trust/trustd/SecTrustStoreServer.h"
50 #include "utilities/sqlutils.h"
51 #include "utilities/SecDb.h"
52 #include <utilities/SecCFError.h>
53 #include "utilities/SecFileLocations.h"
54 #include <utilities/SecDispatchRelease.h>
55 #include "trust/trustd/SecTrustLoggingServer.h"
56 #include <os/variant_private.h>
57 #include <dirent.h>
58 #include <utilities/SecCFWrappers.h>
59 #include <utilities/SecInternalReleasePriv.h>
60
61 /* uid of the _securityd user. */
62 #define SECURTYD_UID 64
63
64 static dispatch_once_t kSecTrustStoreUserOnce;
65 static SecTrustStoreRef kSecTrustStoreUser = NULL;
66
67 #if TARGET_OS_IPHONE
68 static const char copyParentsSQL[] = "SELECT data FROM tsettings WHERE subj=?";
69 static const char containsSQL[] = "SELECT tset FROM tsettings WHERE sha1=?";
70 static const char insertSQL[] = "INSERT OR REPLACE INTO tsettings(sha1,subj,tset,data)VALUES(?,?,?,?)";
71 static const char deleteSQL[] = "DELETE FROM tsettings WHERE sha1=?";
72 static const char deleteAllSQL[] = "BEGIN EXCLUSIVE TRANSACTION; DELETE from tsettings; COMMIT TRANSACTION; VACUUM;";
73 static const char copyAllSQL[] = "SELECT data,tset FROM tsettings ORDER BY sha1";
74 static const char countAllSQL[] = "SELECT COUNT(*) FROM tsettings";
75 #endif
76
77 #define kSecTrustStoreName CFSTR("TrustStore")
78 #define kSecTrustStoreDbExtension CFSTR("sqlite3")
79
80 #define kTrustStoreFileName CFSTR("TrustStore.sqlite3")
81
82
83 struct __SecTrustStore {
84 dispatch_queue_t queue;
85 sqlite3 *s3h;
86 sqlite3_stmt *copyParents;
87 sqlite3_stmt *contains;
88 bool readOnly;
89 bool containsSettings; // For optimization of high-use calls.
90 };
91
92 // MARK: -
93 // MARK: Corporate Root functions
94
95 // MARK: -
96 // MARK: Trust store functions
97 #if TARGET_OS_IPHONE
98 static int sec_create_path(const char *path)
99 {
100 char pathbuf[PATH_MAX];
101 size_t pos, len = strlen(path);
102 if (len == 0 || len > PATH_MAX)
103 return SQLITE_CANTOPEN;
104 memcpy(pathbuf, path, len);
105 for (pos = len-1; pos > 0; --pos)
106 {
107 /* Search backwards for trailing '/'. */
108 if (pathbuf[pos] == '/')
109 {
110 pathbuf[pos] = '\0';
111 /* Attempt to create parent directories of the database. */
112 if (!mkdir(pathbuf, 0777))
113 break;
114 else
115 {
116 int err = errno;
117 if (err == EEXIST)
118 return 0;
119 if (err == ENOTDIR)
120 return SQLITE_CANTOPEN;
121 if (err == EROFS)
122 return SQLITE_READONLY;
123 if (err == EACCES)
124 return SQLITE_PERM;
125 if (err == ENOSPC || err == EDQUOT)
126 return SQLITE_FULL;
127 if (err == EIO)
128 return SQLITE_IOERR;
129
130 /* EFAULT || ELOOP | ENAMETOOLONG || something else */
131 return SQLITE_INTERNAL;
132 }
133 }
134 }
135 return SQLITE_OK;
136 }
137
138 static int sec_sqlite3_open(const char *db_name, sqlite3 **s3h,
139 bool create_path)
140 {
141 int s3e;
142 s3e = sqlite3_open(db_name, s3h);
143 if (s3e == SQLITE_CANTOPEN && create_path) {
144 /* Make sure the path to db_name exists and is writable, then
145 try again. */
146 s3e = sec_create_path(db_name);
147 if (!s3e)
148 s3e = sqlite3_open(db_name, s3h);
149 }
150
151 return s3e;
152 }
153
154 static int64_t SecTrustStoreCountAll(SecTrustStoreRef ts) {
155 __block int64_t result = -1;
156 require_quiet(ts, errOutNotLocked);
157 dispatch_sync(ts->queue, ^{
158 sqlite3_stmt *countAllStmt = NULL;
159 int s3e = sqlite3_prepare_v2(ts->s3h, countAllSQL, sizeof(countAllSQL),
160 &countAllStmt, NULL);
161 if (s3e == SQLITE_OK) {
162 s3e = sqlite3_step(countAllStmt);
163 if (s3e == SQLITE_ROW) {
164 result = sqlite3_column_int64(countAllStmt, 0);
165 }
166 }
167
168 if (countAllStmt) {
169 verify_noerr(sqlite3_finalize(countAllStmt));
170 }
171 });
172
173 errOutNotLocked:
174 return result;
175 }
176
177 static SecTrustStoreRef SecTrustStoreCreate(const char *db_name,
178 bool create) {
179 SecTrustStoreRef ts;
180 int s3e = SQLITE_OK;
181
182 require(ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)), errOut);
183 ts->queue = dispatch_queue_create("truststore", DISPATCH_QUEUE_SERIAL);
184 require_noerr(s3e = sec_sqlite3_open(db_name, &ts->s3h, create), errOut);
185
186 s3e = sqlite3_prepare_v3(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL),
187 SQLITE_PREPARE_PERSISTENT, &ts->copyParents, NULL);
188 if (create && s3e == SQLITE_ERROR) {
189 /* sqlite3_prepare returns SQLITE_ERROR if the table we are
190 compiling this statement for doesn't exist. */
191 char *errmsg = NULL;
192 s3e = sqlite3_exec(ts->s3h,
193 "CREATE TABLE tsettings("
194 "sha1 BLOB NOT NULL DEFAULT '',"
195 "subj BLOB NOT NULL DEFAULT '',"
196 "tset BLOB,"
197 "data BLOB,"
198 "PRIMARY KEY(sha1)"
199 ");"
200 "CREATE INDEX isubj ON tsettings(subj);"
201 , NULL, NULL, &errmsg);
202 if (errmsg) {
203 secwarning("CREATE TABLE cert: %s", errmsg);
204 sqlite3_free(errmsg);
205 }
206 require_noerr(s3e, errOut);
207 s3e = sqlite3_prepare_v3(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL),
208 SQLITE_PREPARE_PERSISTENT, &ts->copyParents, NULL);
209 }
210 require_noerr(s3e, errOut);
211 require_noerr(s3e = sqlite3_prepare_v3(ts->s3h, containsSQL, sizeof(containsSQL), SQLITE_PREPARE_PERSISTENT,
212 &ts->contains, NULL), errOut);
213
214 if (SecTrustStoreCountAll(ts) == 0) {
215 ts->containsSettings = false;
216 } else {
217 /* In the error case where SecTrustStoreCountAll returns a negative result,
218 * we'll pretend there are contents in the trust store so that we still do
219 * DB operations */
220 ts->containsSettings = true;
221 }
222
223
224 return ts;
225
226 errOut:
227 if (ts) {
228 sqlite3_close(ts->s3h);
229 dispatch_release_safe(ts->queue);
230 free(ts);
231 }
232 secerror("Failed to create trust store database: %d", s3e);
233 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationCreate, TAFatalError, s3e);
234
235 return NULL;
236 }
237
238 static bool SecExtractFilesystemPathForKeychainFile(CFStringRef file, UInt8 *buffer, CFIndex maxBufLen)
239 {
240 bool translated = false;
241 CFURLRef fileURL = SecCopyURLForFileInKeychainDirectory(file);
242
243 if (fileURL && CFURLGetFileSystemRepresentation(fileURL, false, buffer, maxBufLen))
244 translated = true;
245 CFReleaseSafe(fileURL);
246
247 return translated;
248 }
249
250 static void SecTrustStoreInitUser(void) {
251 const char path[MAXPATHLEN];
252
253 if (SecExtractFilesystemPathForKeychainFile(kTrustStoreFileName, (UInt8*) path, (CFIndex) sizeof(path)))
254 {
255 kSecTrustStoreUser = SecTrustStoreCreate(path, true);
256 if (kSecTrustStoreUser)
257 kSecTrustStoreUser->readOnly = false;
258 }
259 }
260
261 /* AUDIT[securityd](done):
262 domainName (ok) is a caller provided string of any length (might be 0), only
263 its cf type has been checked.
264 */
265 SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) {
266 if (CFEqual(CFSTR("user"), domainName)) {
267 dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); });
268 return kSecTrustStoreUser;
269 } else {
270 SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName);
271 return NULL;
272 }
273 }
274
275 /* AUDIT[securityd](done):
276 ts (ok) might be NULL.
277 certificate (ok) is a valid SecCertificateRef.
278 trustSettingsDictOrArray (checked by CFPropertyListCreateXMLData) is either
279 NULL, a dictionary or an array, but its contents have not been checked.
280 */
281 bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
282 SecCertificateRef certificate,
283 CFTypeRef tsdoa, CFErrorRef *error) {
284 __block bool ok;
285 require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("truststore is NULL")));
286 require_action_quiet(!ts->readOnly, errOutNotLocked, ok = SecError(errSecReadOnly, error, CFSTR("truststore is readOnly")));
287 dispatch_sync(ts->queue, ^{
288 CFTypeRef trustSettingsDictOrArray = tsdoa;
289 sqlite3_stmt *insert = NULL;
290 CFDataRef xmlData = NULL;
291 CFArrayRef array = NULL;
292
293 CFDataRef subject;
294 require_action_quiet(subject = SecCertificateGetNormalizedSubjectContent(certificate),
295 errOut, ok = SecError(errSecParam, error, CFSTR("get normalized subject failed")));
296 CFDataRef digest;
297 require_action_quiet(digest = SecCertificateGetSHA1Digest(certificate), errOut, ok = SecError(errSecParam, error, CFSTR("get sha1 digest failed")));
298
299 /* Do some basic checks on the trust settings passed in. */
300 if (trustSettingsDictOrArray == NULL) {
301 require_action_quiet(array = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks), errOut, ok = SecError(errSecAllocate, error, CFSTR("CFArrayCreate failed")));
302 trustSettingsDictOrArray = array;
303 }
304 else if(CFGetTypeID(trustSettingsDictOrArray) == CFDictionaryGetTypeID()) {
305 /* array-ize it */
306 array = CFArrayCreate(NULL, &trustSettingsDictOrArray, 1,
307 &kCFTypeArrayCallBacks);
308 trustSettingsDictOrArray = array;
309 }
310 else {
311 require_action_quiet(CFGetTypeID(trustSettingsDictOrArray) == CFArrayGetTypeID(), errOut, ok = SecError(errSecParam, error, CFSTR("trustSettingsDictOrArray neither dict nor array")));
312 }
313
314 require_action_quiet(xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
315 trustSettingsDictOrArray), errOut, ok = SecError(errSecParam, error, CFSTR("xml encode failed")));
316
317 int s3e = sqlite3_exec(ts->s3h, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL);
318 require_action_quiet(s3e == SQLITE_OK, errOut, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
319
320 /* Parameter order is sha1,subj,tset,data. */
321 require_noerr_action_quiet(s3e = sqlite3_prepare_v2(ts->s3h, insertSQL, sizeof(insertSQL),
322 &insert, NULL), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
323 require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(insert, 1,
324 CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
325 errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
326 require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(insert, 2,
327 CFDataGetBytePtr(subject), CFDataGetLength(subject),
328 SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
329 require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(insert, 3,
330 CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData),
331 SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
332 require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(insert, 4,
333 SecCertificateGetBytePtr(certificate),
334 SecCertificateGetLength(certificate), SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
335 s3e = sqlite3_step(insert);
336 if (s3e == SQLITE_DONE) {
337 /* Great the insert worked. */
338 ok = true;
339 ts->containsSettings = true;
340 } else {
341 require_noerr_action_quiet(s3e, errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
342 ok = true;
343 }
344
345 errOutSql:
346 if (insert) {
347 s3e = sqlite3_finalize(insert);
348 }
349
350 if (ok && s3e == SQLITE_OK) {
351 s3e = sqlite3_exec(ts->s3h, "COMMIT TRANSACTION", NULL, NULL, NULL);
352 }
353
354 if (!ok || s3e != SQLITE_OK) {
355 secerror("Failed to update trust store: (%d) %@", s3e, error ? *error : NULL);
356 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationWrite, TAFatalError, s3e);
357 sqlite3_exec(ts->s3h, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
358 if (ok) {
359 ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e);
360 }
361 }
362
363 errOut:
364 CFReleaseSafe(xmlData);
365 CFReleaseSafe(array);
366 });
367 errOutNotLocked:
368 return ok;
369 }
370
371 /* AUDIT[securityd](done):
372 ts (ok) might be NULL.
373 digest (ok) is a data of any length (might be 0).
374 */
375 bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts,
376 CFDataRef digest, CFErrorRef *error) {
377 require_quiet(ts, errOutNotLocked);
378 require(!ts->readOnly, errOutNotLocked);
379 dispatch_sync(ts->queue, ^{
380 int s3e = SQLITE_OK;
381 sqlite3_stmt *deleteStmt = NULL;
382
383 require_noerr(s3e = sqlite3_prepare_v2(ts->s3h, deleteSQL, sizeof(deleteSQL),
384 &deleteStmt, NULL), errOut);
385 require_noerr(s3e = sqlite3_bind_blob_wrapper(deleteStmt, 1,
386 CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
387 errOut);
388 s3e = sqlite3_step(deleteStmt);
389
390 errOut:
391 if (deleteStmt) {
392 verify_noerr(sqlite3_finalize(deleteStmt));
393 }
394 if (s3e != SQLITE_OK && s3e != SQLITE_DONE) {
395 secerror("Removal of certificate from trust store failed: %d", s3e);
396 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationWrite, TAFatalError, s3e);
397 }
398 });
399 errOutNotLocked:
400 return true;
401 }
402
403 bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error)
404 {
405 __block bool removed_all = false;
406 require(ts, errOutNotLocked);
407 require(!ts->readOnly, errOutNotLocked);
408 dispatch_sync(ts->queue, ^{
409 int s3e =sqlite3_exec(ts->s3h, deleteAllSQL, NULL, NULL, NULL);
410 if (s3e == SQLITE_OK) {
411 removed_all = true;
412 ts->containsSettings = false;
413 } else {
414 secerror("Clearing of trust store failed: %d", s3e);
415 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationWrite, TAFatalError, s3e);
416 }
417
418 /* prepared statements become unusable after deleteAllSQL, reset them */
419 if (ts->copyParents)
420 sqlite3_finalize(ts->copyParents);
421 sqlite3_prepare_v3(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL), SQLITE_PREPARE_PERSISTENT,
422 &ts->copyParents, NULL);
423 if (ts->contains)
424 sqlite3_finalize(ts->contains);
425 sqlite3_prepare_v3(ts->s3h, containsSQL, sizeof(containsSQL), SQLITE_PREPARE_PERSISTENT,
426 &ts->contains, NULL);
427 });
428 errOutNotLocked:
429 return removed_all;
430 }
431
432 CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts,
433 SecCertificateRef certificate, CFErrorRef *error) {
434 __block CFMutableArrayRef parents = NULL;
435 require(ts, errOutNotLocked);
436 dispatch_sync(ts->queue, ^{
437 int s3e = SQLITE_OK;
438 CFDataRef issuer = NULL;
439 require(issuer = SecCertificateGetNormalizedIssuerContent(certificate),
440 errOut);
441 require_quiet(ts->containsSettings, ok);
442 /* @@@ Might have to use SQLITE_TRANSIENT */
443 require_noerr(s3e = sqlite3_bind_blob_wrapper(ts->copyParents, 1,
444 CFDataGetBytePtr(issuer), CFDataGetLength(issuer),
445 SQLITE_STATIC), errOut);
446
447 require(parents = CFArrayCreateMutable(kCFAllocatorDefault, 0,
448 &kCFTypeArrayCallBacks), errOut);
449 for (;;) {
450 s3e = sqlite3_step(ts->copyParents);
451 if (s3e == SQLITE_ROW) {
452 SecCertificateRef cert;
453 require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault,
454 sqlite3_column_blob(ts->copyParents, 0),
455 sqlite3_column_bytes(ts->copyParents, 0)), errOut);
456 CFArrayAppendValue(parents, cert);
457 CFRelease(cert);
458 } else {
459 require(s3e == SQLITE_DONE || s3e == SQLITE_OK, errOut);
460 break;
461 }
462 }
463
464 goto ok;
465 errOut:
466 secerror("Failed to read parents from trust store: %d", s3e);
467 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationRead, TAFatalError, s3e);
468 if (parents) {
469 CFRelease(parents);
470 parents = NULL;
471 }
472 ok:
473 verify_noerr(sqlite3_reset(ts->copyParents));
474 verify_noerr(sqlite3_clear_bindings(ts->copyParents));
475 });
476 errOutNotLocked:
477 return parents;
478 }
479
480 static bool SecTrustStoreQueryCertificateWithDigest(SecTrustStoreRef ts,
481 CFDataRef digest, bool *contains, CFArrayRef *usageConstraints, CFErrorRef *error) {
482 if (contains)
483 *contains = false;
484 __block bool ok = true;
485 require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("ts is NULL")));
486 dispatch_sync(ts->queue, ^{
487 CFDataRef xmlData = NULL;
488 CFPropertyListRef trustSettings = NULL;
489 int s3e = SQLITE_OK;
490 require_action_quiet(ts->containsSettings, errOut, ok = true);
491 require_noerr_action(s3e = sqlite3_bind_blob_wrapper(ts->contains, 1,
492 CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
493 errOut, ok = SecDbErrorWithStmt(s3e, ts->contains, error, CFSTR("sqlite3_bind_blob failed")));
494 s3e = sqlite3_step(ts->contains);
495 if (s3e == SQLITE_ROW) {
496 if (contains)
497 *contains = true;
498 if (usageConstraints) {
499 require_action(xmlData = CFDataCreate(NULL,
500 sqlite3_column_blob(ts->contains, 0),
501 sqlite3_column_bytes(ts->contains, 0)), errOut, ok = false);
502 require_action(trustSettings = CFPropertyListCreateWithData(NULL,
503 xmlData,
504 kCFPropertyListImmutable,
505 NULL, error), errOut, ok = false);
506 require_action(CFGetTypeID(trustSettings) == CFArrayGetTypeID(), errOut, ok = false);
507 *usageConstraints = CFRetain(trustSettings);
508 }
509 } else {
510 require_action(s3e == SQLITE_DONE || s3e == SQLITE_OK, errOut,
511 ok = SecDbErrorWithStmt(s3e, ts->contains, error, CFSTR("sqlite3_step failed")));
512 }
513
514 errOut:
515 if (!ok) {
516 secerror("Failed to query for cert in trust store: %d", s3e);
517 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationRead, TAFatalError, s3e);
518 }
519 verify_noerr(sqlite3_reset(ts->contains));
520 verify_noerr(sqlite3_clear_bindings(ts->contains));
521 CFReleaseNull(xmlData);
522 CFReleaseNull(trustSettings);
523 });
524 errOutNotLocked:
525 return ok;
526 }
527
528 bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts,
529 CFDataRef digest, bool *contains, CFErrorRef *error) {
530 return SecTrustStoreQueryCertificateWithDigest(ts, digest, contains, NULL, error);
531 }
532
533 bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts,
534 CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) {
535 return SecTrustStoreQueryCertificateWithDigest(ts, digest, NULL, usageConstraints, error);
536 }
537
538 bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) {
539 __block bool ok = true;
540 __block CFMutableArrayRef CertsAndSettings = NULL;
541 require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("ts is NULL")));
542 require_action_quiet(trustStoreContents, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("trustStoreContents is NULL")));
543 dispatch_sync(ts->queue, ^{
544 sqlite3_stmt *copyAllStmt = NULL;
545 CFDataRef cert = NULL;
546 CFDataRef xmlData = NULL;
547 CFPropertyListRef trustSettings = NULL;
548 CFArrayRef certSettingsPair = NULL;
549 int s3e = SQLITE_OK;
550 require_noerr(s3e = sqlite3_prepare_v2(ts->s3h, copyAllSQL, sizeof(copyAllSQL),
551 &copyAllStmt, NULL), errOut);
552 require(CertsAndSettings = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut);
553 for(;;) {
554 s3e = sqlite3_step(copyAllStmt);
555 if (s3e == SQLITE_ROW) {
556 require(cert = CFDataCreate(kCFAllocatorDefault,
557 sqlite3_column_blob(copyAllStmt, 0),
558 sqlite3_column_bytes(copyAllStmt, 0)), errOut);
559 require(xmlData = CFDataCreate(NULL,
560 sqlite3_column_blob(copyAllStmt, 1),
561 sqlite3_column_bytes(copyAllStmt, 1)), errOut);
562 require(trustSettings = CFPropertyListCreateWithData(NULL,
563 xmlData,
564 kCFPropertyListImmutable,
565 NULL, error), errOut);
566 const void *pair[] = { cert , trustSettings };
567 require(certSettingsPair = CFArrayCreate(NULL, pair, 2, &kCFTypeArrayCallBacks), errOut);
568 CFArrayAppendValue(CertsAndSettings, certSettingsPair);
569
570 CFReleaseNull(cert);
571 CFReleaseNull(xmlData);
572 CFReleaseNull(trustSettings);
573 CFReleaseNull(certSettingsPair);
574 } else {
575 require_action(s3e == SQLITE_DONE || s3e == SQLITE_OK, errOut, ok = SecDbErrorWithStmt(s3e, copyAllStmt, error, CFSTR("sqlite3_step failed")));
576 break;
577 }
578 }
579 goto ok;
580
581 errOut:
582 secerror("Failed to query for all certs in trust store: %d", s3e);
583 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore, TAOperationRead, TAFatalError, s3e);
584 CFReleaseNull(cert);
585 CFReleaseNull(xmlData);
586 CFReleaseNull(trustSettings);
587 CFReleaseNull(certSettingsPair);
588 ok:
589 if (copyAllStmt) {
590 verify_noerr(sqlite3_finalize(copyAllStmt));
591 }
592 if (CertsAndSettings) {
593 *trustStoreContents = CertsAndSettings;
594 }
595 });
596 errOutNotLocked:
597 return ok;
598 }
599
600 #else // !TARGET_OS_IPHONE
601 /* On macOS the trust store has nothing in it by default */
602 static void SecTrustStoreInitUser(void) {
603 SecTrustStoreRef ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore));
604 memset(ts, 0, sizeof(struct __SecTrustStore));
605 ts->readOnly = true;
606 kSecTrustStoreUser = ts;
607 }
608
609 SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) {
610 if (CFEqual(CFSTR("user"), domainName)) {
611 dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); });
612 return kSecTrustStoreUser;
613 } else {
614 SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName);
615 return NULL;
616 }
617 }
618
619 bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
620 SecCertificateRef certificate,
621 CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) {
622 return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
623 }
624
625 bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error) {
626 return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
627 }
628
629 bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error) {
630 return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
631 }
632
633 CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts,
634 SecCertificateRef certificate, CFErrorRef *error) {
635 CFArrayRef parents = NULL;
636 return parents;
637 }
638
639 bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef *error) {
640 if (contains) {
641 *contains = false;
642 }
643 return true;
644 }
645
646 bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) {
647 return true;
648 }
649
650 bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) {
651 CFMutableArrayRef CertsAndSettings = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
652 if (CertsAndSettings) {
653 *trustStoreContents = CertsAndSettings;
654 }
655 return true;
656 }
657 #endif