]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/SecDb.c
dbc32864994988593be1e6339878797aa5558ebf
[apple/security.git] / OSX / utilities / SecDb.c
1 /*
2 * Copyright (c) 2012-2017 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 #include "SecDb.h"
26 #include "debugging.h"
27
28 #include <sqlite3.h>
29 #include <sqlite3_private.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <libgen.h>
32 #include <sys/csr.h>
33 #include <sys/stat.h>
34 #include <AssertMacros.h>
35 #include "SecCFWrappers.h"
36 #include "SecCFError.h"
37 #include "SecIOFormat.h"
38 #include <stdio.h>
39 #include "Security/SecBase.h"
40 #include "SecAutorelease.h"
41 #include <os/assumes.h>
42 #include <xpc/private.h> // xpc_transaction_exit_clean()
43
44
45 //
46 // Architecturally inverted files
47 // These are in SecureObjectSync but utilities depends on them
48 // <rdar://problem/20802079> Fix layer violation (SOSDigestVector, SOSManifest, SecDB.c)
49 //
50 #include "keychain/SecureObjectSync/SOSDigestVector.h"
51 #include "keychain/SecureObjectSync/SOSManifest.h"
52
53 #define SECDB_DEBUGGING 0
54
55 struct __OpaqueSecDbStatement {
56 CFRuntimeBase _base;
57
58 SecDbConnectionRef dbconn;
59 sqlite3_stmt *stmt;
60 };
61
62 struct __OpaqueSecDbConnection {
63 CFRuntimeBase _base;
64
65 //CFMutableDictionaryRef statements;
66
67 SecDbRef db; // NONRETAINED, since db or block retains us
68 bool readOnly;
69 bool inTransaction;
70 SecDbTransactionSource source;
71 bool isCorrupted;
72 int maybeCorruptedCode;
73 bool hasIOFailure;
74 CFErrorRef corruptionError;
75 sqlite3 *handle;
76 // Pending deletions and additions for the current transaction
77 // Entires are either:
78 // 1) a CFArrayRef of 1 element representing a deletion,
79 // 2) a CFArrayRef of 2 elements representing the element 0 having been replaced with element 1
80 // 3) a CFTypeRef that is not a CFArrayRef, representing an add of the element in question.
81 CFMutableArrayRef changes;
82 };
83
84 struct __OpaqueSecDb {
85 CFRuntimeBase _base;
86
87 CFStringRef db_path;
88 dispatch_queue_t queue;
89 dispatch_queue_t commitQueue;
90 CFMutableArrayRef connections;
91 dispatch_semaphore_t write_semaphore;
92 dispatch_semaphore_t read_semaphore;
93 bool didFirstOpen;
94 bool (^opened)(SecDbRef db, SecDbConnectionRef dbconn, bool didCreate, bool *callMeAgainForNextConnection, CFErrorRef *error);
95 bool callOpenedHandlerForNextConnection;
96 CFMutableArrayRef notifyPhase; /* array of SecDBNotifyBlock */
97 mode_t mode; /* database file permissions */
98 bool readWrite; /* open database read-write */
99 bool allowRepair; /* allow database repair */
100 bool useWAL; /* use WAL mode */
101 bool useRobotVacuum; /* use if SecDB should manage vacuum behind your back */
102 uint8_t maxIdleHandles;
103 void (^corruptionReset)(void);
104 };
105
106 // MARK: Error domains and error helper functions
107
108 CFStringRef kSecDbErrorDomain = CFSTR("com.apple.utilities.sqlite3");
109
110 bool SecDbError(int sql_code, CFErrorRef *error, CFStringRef format, ...) {
111 if (sql_code == SQLITE_OK) return true;
112
113 if (error) {
114 va_list args;
115 CFIndex code = sql_code;
116 CFErrorRef previousError = *error;
117
118 *error = NULL;
119 va_start(args, format);
120 SecCFCreateErrorWithFormatAndArguments(code, kSecDbErrorDomain, previousError, error, NULL, format, args);
121 va_end(args);
122 }
123 return false;
124 }
125
126 bool SecDbErrorWithDb(int sql_code, sqlite3 *db, CFErrorRef *error, CFStringRef format, ...) {
127 if (sql_code == SQLITE_OK) return true;
128 if (error) {
129 va_list args;
130 va_start(args, format);
131 CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
132 va_end(args);
133 CFStringRef errno_code = NULL;
134
135 if (sql_code == SQLITE_CANTOPEN) {
136 int errno_number = sqlite3_system_errno(db);
137 errno_code = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), errno_number);
138 } else {
139 errno_code = CFRetain(CFSTR(""));
140 }
141
142 int extended_code = sqlite3_extended_errcode(db);
143 if (sql_code == extended_code)
144 SecDbError(sql_code, error, CFSTR("%@: [%d]%@ %s"), message, sql_code, errno_code, sqlite3_errmsg(db));
145 else
146 SecDbError(sql_code, error, CFSTR("%@: [%d->%d]%@ %s"), message, sql_code, extended_code, errno_code, sqlite3_errmsg(db));
147 CFReleaseSafe(message);
148 CFReleaseSafe(errno_code);
149 }
150 return false;
151 }
152
153 bool SecDbErrorWithStmt(int sql_code, sqlite3_stmt *stmt, CFErrorRef *error, CFStringRef format, ...) {
154 if (sql_code == SQLITE_OK) return true;
155 if (error) {
156 va_list args;
157 va_start(args, format);
158 CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
159 va_end(args);
160
161 sqlite3 *db = sqlite3_db_handle(stmt);
162 const char *sql = sqlite3_sql(stmt);
163 int extended_code = sqlite3_extended_errcode(db);
164 if (sql_code == extended_code)
165 SecDbError(sql_code, error, CFSTR("%@: [%d] %s sql: %s"), message, sql_code, sqlite3_errmsg(db), sql);
166 else
167 SecDbError(sql_code, error, CFSTR("%@: [%d->%d] %s sql: %s"), message, sql_code, extended_code, sqlite3_errmsg(db), sql);
168 CFReleaseSafe(message);
169 }
170 return false;
171 }
172
173 // A callback for the sqlite3_log() interface.
174 static void sqlite3Log(void *pArg, int iErrCode, const char *zMsg){
175 secdebug("sqlite3", "(%d) %s", iErrCode, zMsg);
176 }
177
178 void _SecDbServerSetup(void)
179 {
180 static dispatch_once_t onceToken;
181 dispatch_once(&onceToken, ^{
182 int rx = sqlite3_config(SQLITE_CONFIG_LOG, sqlite3Log, NULL);
183 if (SQLITE_OK != rx) {
184 secwarning("Could not set up sqlite global error logging to syslog: %d", rx);
185 }
186 });
187 }
188
189
190 // MARK: -
191 // MARK: Static helper functions
192
193 static bool SecDbOpenHandle(SecDbConnectionRef dbconn, bool *created, CFErrorRef *error);
194 static bool SecDbHandleCorrupt(SecDbConnectionRef dbconn, int rc, CFErrorRef *error);
195
196 #pragma mark -
197 #pragma mark SecDbRef
198
199 static CFStringRef
200 SecDbCopyFormatDescription(CFTypeRef value, CFDictionaryRef formatOptions)
201 {
202 SecDbRef db = (SecDbRef)value;
203 return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<SecDb path:%@ connections: %@>"), db->db_path, db->connections);
204 }
205
206
207 static void
208 SecDbDestroy(CFTypeRef value)
209 {
210 SecDbRef db = (SecDbRef)value;
211 CFReleaseNull(db->connections);
212 CFReleaseNull(db->db_path);
213 if (db->queue) {
214 dispatch_release(db->queue);
215 db->queue = NULL;
216 }
217 if (db->commitQueue) {
218 dispatch_release(db->commitQueue);
219 db->commitQueue = NULL;
220 }
221 if (db->read_semaphore) {
222 dispatch_release(db->read_semaphore);
223 db->read_semaphore = NULL;
224 }
225 if (db->write_semaphore) {
226 dispatch_release(db->write_semaphore);
227 db->write_semaphore = NULL;
228 }
229 if (db->opened) {
230 Block_release(db->opened);
231 db->opened = NULL;
232 }
233 CFReleaseNull(db->notifyPhase);
234 }
235
236 CFGiblisFor(SecDb)
237
238 SecDbRef
239 SecDbCreate(CFStringRef dbName, mode_t mode, bool readWrite, bool allowRepair, bool useWAL, bool useRobotVacuum, uint8_t maxIdleHandles,
240 bool (^opened)(SecDbRef db, SecDbConnectionRef dbconn, bool didCreate, bool *callMeAgainForNextConnection, CFErrorRef *error))
241 {
242 SecDbRef db = NULL;
243
244 db = CFTypeAllocate(SecDb, struct __OpaqueSecDb, kCFAllocatorDefault);
245 require(db != NULL, done);
246
247 CFStringPerformWithCString(dbName, ^(const char *dbNameStr) {
248 db->queue = dispatch_queue_create(dbNameStr, DISPATCH_QUEUE_SERIAL);
249 });
250 CFStringRef commitQueueStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-commit"), dbName);
251 CFStringPerformWithCString(commitQueueStr, ^(const char *cqNameStr) {
252 db->commitQueue = dispatch_queue_create(cqNameStr, DISPATCH_QUEUE_CONCURRENT);
253 });
254 CFReleaseNull(commitQueueStr);
255 db->read_semaphore = dispatch_semaphore_create(kSecDbMaxReaders);
256 db->write_semaphore = dispatch_semaphore_create(kSecDbMaxWriters);
257 db->connections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
258 db->opened = opened ? Block_copy(opened) : NULL;
259 if (getenv("__OSINSTALL_ENVIRONMENT") != NULL) {
260 // TODO: Move this code out of this layer
261 secinfo("#SecDB", "SecDB: running from installer");
262
263 db->db_path = CFSTR("file::memory:?cache=shared");
264 } else {
265 db->db_path = CFStringCreateCopy(kCFAllocatorDefault, dbName);
266 }
267 db->mode = mode;
268 db->readWrite = readWrite;
269 db->allowRepair = allowRepair;
270 db->useWAL = useWAL;
271 db->useRobotVacuum = useRobotVacuum;
272 db->maxIdleHandles = maxIdleHandles;
273 db->corruptionReset = NULL;
274
275 done:
276 return db;
277 }
278
279 CFIndex
280 SecDbIdleConnectionCount(SecDbRef db) {
281 __block CFIndex count = 0;
282 dispatch_sync(db->queue, ^{
283 count = CFArrayGetCount(db->connections);
284 });
285 return count;
286 }
287
288 void SecDbAddNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase)
289 {
290 // SecDbNotifyPhase seems to mostly be called on the db's commitQueue, and not the db's queue. Therefore, protect the array with that queue.
291 dispatch_sync(db->commitQueue, ^{
292 SecDBNotifyBlock block = Block_copy(notifyPhase); /* Force the block off the stack */
293 if (db->notifyPhase == NULL) {
294 db->notifyPhase = CFArrayCreateMutableForCFTypes(NULL);
295 }
296 CFArrayAppendValue(db->notifyPhase, block);
297 Block_release(block);
298 });
299 }
300
301 static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase phase) {
302 if (CFArrayGetCount(dbconn->changes)) {
303 CFArrayRef changes = dbconn->changes;
304 dbconn->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
305 if (dbconn->db->notifyPhase) {
306 CFArrayForEach(dbconn->db->notifyPhase, ^(const void *value) {
307 SecDBNotifyBlock notifyBlock = (SecDBNotifyBlock)value;
308 notifyBlock(dbconn, phase, dbconn->source, changes);
309 });
310 }
311 CFReleaseSafe(changes);
312 }
313 }
314
315 static void SecDbOnNotify(SecDbConnectionRef dbconn, void (^perform)(void)) {
316 perform();
317 }
318
319 CFStringRef SecDbGetPath(SecDbRef db) {
320 if(!db) {
321 return NULL;
322 }
323 return db->db_path;
324 }
325
326
327 #pragma mark -
328 #pragma mark SecDbConnectionRef
329
330 static bool SecDbCheckCorrupted(SecDbConnectionRef dbconn)
331 {
332 __block bool checkDidRun = false;
333 __block bool isCorrupted = false;
334 __block CFErrorRef error = NULL;
335 SecDbPrepare(dbconn, CFSTR("PRAGMA integrity_check"), &error, ^(sqlite3_stmt *stmt) {
336 SecDbStep(dbconn, stmt, &error, ^(bool *stop) {
337 const char * result = (const char*)sqlite3_column_text(stmt, 0);
338 if (!result || strncasecmp(result, "ok", 3) != 0) {
339 isCorrupted = true;
340 secerror("SecDBCheckCorrupted integrity_check returned %s", (result) ? result : "NULL");
341 }
342 checkDidRun = true;
343 });
344 });
345 if (!checkDidRun) {
346 // An error occurred in SecDbPrepare before we could run the block.
347 if (error) {
348 CFIndex code = CFErrorGetCode(error);
349 if (SQLITE_CORRUPT == code || SQLITE_NOTADB == code) {
350 isCorrupted = true;
351 }
352 secinfo("#SecDB", "#SecDB warning error %{public}@ when running integrity check", error);
353 } else {
354 // We don't have an error ref if SecDbPrepare has called SecDbConnectionCheckCode,
355 // which then called SecDbHandleCorrupt. That code path is only entered when the
356 // original error was SQLITE_CORRUPT or SQLITE_NOTADB. On other errors, the
357 // CFErrorRef is not cleared and we can just check the code above.
358 isCorrupted = true;
359 secinfo("#SecDB", "#SecDB warning: failed to run integrity check due to corruption");
360 }
361 }
362 if (isCorrupted) {
363 if (checkDidRun) {
364 secerror("SecDBCheckCorrupted ran integrity_check, and that didn't return ok");
365 } else {
366 secerror("SecDBCheckCorrupted failed to run integrity check");
367 }
368 }
369 CFReleaseNull(error);
370
371 return isCorrupted;
372 }
373
374 static bool SecDbDidCreateFirstConnection(SecDbConnectionRef dbconn, bool didCreate, CFErrorRef *error)
375 {
376 secinfo("#SecDB", "#SecDB starting maintenance");
377 bool ok = true;
378
379 // Historical note: this used to check for integrity but that became too slow and caused panics at boot.
380 // Now, just react to SQLite errors when doing an operation. If file on disk is borked it'll tell us right away.
381
382 if (!dbconn->isCorrupted && dbconn->db->opened) {
383 CFErrorRef localError = NULL;
384
385 dbconn->db->callOpenedHandlerForNextConnection = false;
386 ok = dbconn->db->opened(dbconn->db, dbconn, didCreate, &dbconn->db->callOpenedHandlerForNextConnection, &localError);
387
388 if (!ok)
389 secerror("opened block failed: %@", localError);
390
391 if (!dbconn->isCorrupted && error && *error == NULL) {
392 *error = localError;
393 localError = NULL;
394 } else {
395 if (localError)
396 secerror("opened block failed: error (%@) is being released and lost", localError);
397 CFReleaseNull(localError);
398 }
399 }
400
401 if (dbconn->isCorrupted) {
402 ok = SecDbHandleCorrupt(dbconn, 0, error);
403 }
404
405 secinfo("#SecDB", "#SecDB starting maintenance");
406 return ok;
407 }
408
409 void SecDbCorrupt(SecDbConnectionRef dbconn, CFErrorRef error)
410 {
411 os_log_fault(secLogObjForScope("SecEmergency"), "SecDBCorrupt: %@", error);
412 dbconn->isCorrupted = true;
413 CFRetainAssign(dbconn->corruptionError, error);
414 }
415
416
417 static uint8_t knownDbPathIndex(SecDbConnectionRef dbconn)
418 {
419
420 if(CFEqual(dbconn->db->db_path, CFSTR("/Library/Keychains/keychain-2.db")))
421 return 1;
422 if(CFEqual(dbconn->db->db_path, CFSTR("/Library/Keychains/ocspcache.sqlite3")))
423 return 2;
424 if(CFEqual(dbconn->db->db_path, CFSTR("/Library/Keychains/TrustStore.sqlite3")))
425 return 3;
426 if(CFEqual(dbconn->db->db_path, CFSTR("/Library/Keychains/caissuercache.sqlite3")))
427 return 4;
428
429 /* Unknown DB path */
430 return 0;
431 }
432
433 static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn, int code, CFErrorRef *error, CFStringRef desc, ...)
434 CF_FORMAT_FUNCTION(4, 5);
435
436 // Return true if there was no error, returns false otherwise and set *error to an appropriate CFErrorRef.
437 static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn, int code, CFErrorRef *error, CFStringRef desc, ...) {
438 if (code == SQLITE_OK || code == SQLITE_DONE)
439 return true;
440
441 if (error) {
442 va_list args;
443 va_start(args, desc);
444 CFStringRef msg = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, desc, args);
445 va_end(args);
446 SecDbErrorWithDb(code, dbconn->handle, error, CFSTR("%@"), msg);
447 CFRelease(msg);
448 }
449
450 dbconn->hasIOFailure |= (SQLITE_IOERR == code);
451
452 /* If it's already corrupted, don't try to recover */
453 if (dbconn->isCorrupted) {
454 CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
455 CFSTR("SQL DB %@ is corrupted already. Corruption error was: %d (previously %d)"),
456 dbconn->db->db_path, code, dbconn->maybeCorruptedCode);
457 secerror("%@",reason);
458 __security_simulatecrash(reason, __sec_exception_code_TwiceCorruptDb(knownDbPathIndex(dbconn)));
459 CFReleaseSafe(reason);
460 // We can't fall through to the checking case because it eventually calls SecDbConnectionCheckCode again.
461 // However, this is the second time we're seeing corruption so let's take the ultimate measure.
462 if ((SQLITE_CORRUPT == code) || (SQLITE_NOTADB == code)) {
463 secerror("SecDbConnectionCheckCode detected corruption twice: going to handle corrupt DB");
464 (void)SecDbHandleCorrupt(dbconn, code, error);
465 }
466 return false;
467 }
468
469 // NOTADB means file is garbage, so it's functionally equivalent to corruption
470 dbconn->isCorrupted = (SQLITE_CORRUPT == code) || (SQLITE_NOTADB == code);
471 if (dbconn->isCorrupted) {
472 /* Run integrity check and only make dbconn->isCorrupted true and
473 run the corruption handler if the integrity check conclusively fails. */
474 dbconn->maybeCorruptedCode = code;
475 dbconn->isCorrupted = SecDbCheckCorrupted(dbconn);
476 if (dbconn->isCorrupted) {
477 secerror("operation returned code: %d integrity check=fail", code);
478 (void)SecDbHandleCorrupt(dbconn, code, error);
479 } else {
480 secerror("operation returned code: %d: integrity check=pass", code);
481 }
482 }
483
484 return false;
485 }
486
487 #define BUSY_TIMEOUT_MS (5 * 60 * 1000) /* 5 minutes */
488
489 static int sleepBackoff[] = { 10, 20, 50, 100, 250 };
490 static int sumBackoff[] = { 10, 30, 80, 180, 430 };
491 static int NumberOfSleepBackoff = sizeof(sleepBackoff)/sizeof(sleepBackoff[0]);
492
493 // Use these as silly hacks to encode the SQLite return code in the backtrace, for hang debugging purposes
494 static void __attribute__((noinline)) SecDbLockSleep(int ms) {
495 sqlite3_sleep(ms);
496 }
497
498 static void __attribute__((noinline)) SecDbBusySleep(int ms) {
499 sqlite3_sleep(ms);
500 }
501
502 // Return true causes the operation to be tried again.
503 // Note that we set sqlite3_busy_timeout on the connection, so anytime you're in here, it's likely due to SQLITE_LOCKED.
504 static bool SecDbWaitIfNeeded(SecDbConnectionRef dbconn, int s3e, sqlite3_stmt *stmt, CFStringRef desc, int nTries, CFErrorRef *error) {
505 if (((0xFF & s3e) == SQLITE_BUSY) || ((0xFF & s3e) == SQLITE_LOCKED)) {
506 int totaltimeout, timeout;
507
508 _Static_assert(sizeof(sumBackoff) == sizeof(sleepBackoff), "matching arrays not matching");
509 _Static_assert(sizeof(sumBackoff[0]) == sizeof(sleepBackoff[0]), "matching arrays not matching");
510
511 if (nTries < NumberOfSleepBackoff) {
512 timeout = sleepBackoff[nTries];
513 totaltimeout = sumBackoff[nTries];
514 } else {
515 timeout = sleepBackoff[NumberOfSleepBackoff - 1];
516 totaltimeout = sumBackoff[NumberOfSleepBackoff - 1] + (timeout * (nTries - NumberOfSleepBackoff));
517 }
518 if (totaltimeout < BUSY_TIMEOUT_MS) {
519 secinfo("#SecDB", "sqlite busy/locked: %d ntries: %d totaltimeout: %d", s3e, nTries, totaltimeout);
520 if(((0xFF & s3e) == SQLITE_LOCKED)) {
521 SecDbLockSleep(timeout);
522 } else {
523 SecDbBusySleep(timeout);
524 }
525 return true;
526 } else {
527 secinfo("#SecDB", "sqlite busy/locked: too long: %d ms, giving up", totaltimeout);
528 }
529 }
530
531 return SecDbConnectionCheckCode(dbconn, s3e, error, CFSTR("%@"), desc);
532 }
533
534 enum SecDbStepResult {
535 kSecDbErrorStep = 0,
536 kSecDbRowStep = 1,
537 kSecDbDoneStep = 2,
538 };
539 typedef enum SecDbStepResult SecDbStepResult;
540
541 static SecDbStepResult _SecDbStep(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error) {
542 assert(stmt != NULL);
543 int s3e;
544 int ntries = 0;
545 for (;;) {
546 if (SecDbConnectionIsReadOnly(dbconn) && !sqlite3_stmt_readonly(stmt)) {
547 secerror("_SecDbStep: SecDbConnection is readonly but we're about to write: %s", sqlite3_sql(stmt));
548 }
549 s3e = sqlite3_step(stmt);
550 if (s3e == SQLITE_ROW) {
551 return kSecDbRowStep;
552 } else if (s3e == SQLITE_DONE) {
553 /*
554 ** ^[SQLITE_DONE] means that the statement has finished executing
555 ** successfully. sqlite3_step() should not be called again on this virtual
556 ** machine without first calling [] to reset the virtual
557 ** machine back to its initial state.
558 */
559 sqlite3_reset(stmt);
560 return kSecDbDoneStep;
561 } else if (!SecDbWaitIfNeeded(dbconn, s3e, stmt, CFSTR("step"), ntries, error)) {
562 return kSecDbErrorStep;
563 }
564 ntries++;
565 };
566 }
567
568 bool
569 SecDbExec(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error)
570 {
571 bool ok = true;
572 CFRetain(sql);
573 while (sql) {
574 CFStringRef tail = NULL;
575 if (ok) {
576 sqlite3_stmt *stmt = SecDbCopyStmt(dbconn, sql, &tail, error);
577 ok = stmt != NULL;
578 if (stmt) {
579 SecDbStepResult sr;
580 while ((sr = _SecDbStep(dbconn, stmt, error)) == kSecDbRowStep);
581 if (sr == kSecDbErrorStep)
582 ok = false;
583 ok &= SecDbReleaseCachedStmt(dbconn, sql, stmt, error);
584 }
585 } else {
586 // TODO We already have an error here we really just want the left over sql in it's userData
587 ok = SecDbError(SQLITE_ERROR, error, CFSTR("Error with unexecuted sql remaining %@"), sql);
588 }
589 CFRelease(sql);
590 sql = tail;
591 }
592 return ok;
593 }
594
595 static int SecDBGetInteger(SecDbConnectionRef dbconn, CFStringRef sql)
596 {
597 __block int number = -1;
598 __block CFErrorRef error = NULL;
599
600 (void)SecDbWithSQL(dbconn, sql, &error, ^bool(sqlite3_stmt *sqlStmt) {
601 (void)SecDbStep(dbconn, sqlStmt, &error, ^(bool *stop) {
602 number = sqlite3_column_int(sqlStmt, 0);
603 *stop = true;
604 });
605 return true;
606 });
607 CFReleaseNull(error);
608 return number;
609 }
610
611
612 void SecDBManagementTasks(SecDbConnectionRef dbconn)
613 {
614 int64_t page_count = SecDBGetInteger(dbconn, CFSTR("pragma page_count"));
615 if (page_count <= 0) {
616 return;
617 }
618 int64_t free_count = SecDBGetInteger(dbconn, CFSTR("pragma freelist_count"));
619 if (free_count < 0) {
620 return;
621 }
622
623 int64_t max_free = 8192;
624
625 int64_t pages_in_use = page_count - free_count;
626 double loadFactor = ((double)pages_in_use/(double)page_count);
627 if (0.85 < loadFactor && free_count < max_free) {
628 /* no work yet */
629 } else {
630 int64_t pages_to_free = (int64_t)(0.2 * free_count);
631 if (0.4 > loadFactor) {
632 pages_to_free = free_count;
633 }
634
635 char *formatString = NULL;
636 asprintf(&formatString, "pragma incremental_vacuum(%d)", (int)pages_to_free);
637 if (formatString) {
638 char *sqlerror = NULL;
639 int rc = sqlite3_exec(dbconn->handle, formatString, NULL, NULL, &sqlerror);
640 if (rc) {
641 secerror("incremental_vacuum failed with: (%d) %{public}s", rc, sqlerror);
642 }
643 sqlite3_free(sqlerror);
644 free(formatString);
645 }
646 }
647 }
648
649
650 static bool SecDbBeginTransaction(SecDbConnectionRef dbconn, SecDbTransactionType type, CFErrorRef *error)
651 {
652 bool ok = true;
653 CFStringRef query;
654 switch (type) {
655 case kSecDbImmediateTransactionType:
656 secdebug("db", "SecDbBeginTransaction SecDbBeginTransaction %p", dbconn);
657 query = CFSTR("BEGIN IMMEDIATE");
658 break;
659 case kSecDbExclusiveRemoteSOSTransactionType:
660 secdebug("db", "SecDbBeginTransaction kSecDbExclusiveRemoteSOSTransactionType %p", dbconn);
661 dbconn->source = kSecDbSOSTransaction;
662 query = CFSTR("BEGIN EXCLUSIVE");
663 break;
664 case kSecDbExclusiveRemoteCKKSTransactionType:
665 secdebug("db", "SecDbBeginTransaction kSecDbExclusiveRemoteCKKSTransactionType %p", dbconn);
666 dbconn->source = kSecDbCKKSTransaction;
667 query = CFSTR("BEGIN EXCLUSIVE");
668 break;
669 case kSecDbExclusiveTransactionType:
670 if (type==kSecDbExclusiveTransactionType)
671 secdebug("db", "SecDbBeginTransaction kSecDbExclusiveTransactionType %p", dbconn);
672 query = CFSTR("BEGIN EXCLUSIVE");
673 break;
674 case kSecDbNormalTransactionType:
675 secdebug("db", "SecDbBeginTransaction kSecDbNormalTransactionType %p", dbconn);
676 query = CFSTR("BEGIN");
677 break;
678 default:
679 secdebug("db", "SecDbBeginTransaction invalid transaction type %lu", type);
680 ok = SecDbError(SQLITE_ERROR, error, CFSTR("invalid transaction type %d"), (int)type);
681 query = NULL;
682 break;
683 }
684
685 if (query != NULL && sqlite3_get_autocommit(dbconn->handle) != 0) {
686 ok = SecDbExec(dbconn, query, error);
687 }
688 if (ok)
689 dbconn->inTransaction = true;
690
691 return ok;
692 }
693
694 static bool SecDbEndTransaction(SecDbConnectionRef dbconn, bool commit, CFErrorRef *error)
695 {
696 __block bool ok = true;
697 __block bool commited = false;
698
699 dispatch_block_t notifyAndExec = ^{
700 if (commit) {
701 //secdebug("db", "SecDbEndTransaction kSecDbTransactionWillCommit %p", dbconn);
702 SecDbNotifyPhase(dbconn, kSecDbTransactionWillCommit);
703 commited = ok = SecDbExec(dbconn, CFSTR("END"), error);
704 //secdebug("db", "SecDbEndTransaction kSecDbTransactionWillCommit %p (after notify)", dbconn);
705 } else {
706 ok = SecDbExec(dbconn, CFSTR("ROLLBACK"), error);
707 commited = false;
708 }
709 dbconn->inTransaction = false;
710 SecDbNotifyPhase(dbconn, commited ? kSecDbTransactionDidCommit : kSecDbTransactionDidRollback);
711 secdebug("db", "SecDbEndTransaction %s %p", commited ? "kSecDbTransactionDidCommit" : "kSecDbTransactionDidRollback", dbconn);
712 dbconn->source = kSecDbAPITransaction;
713
714 if (commit && dbconn->db->useRobotVacuum) {
715 SecDBManagementTasks(dbconn);
716 }
717 };
718
719 SecDbPerformOnCommitQueue(dbconn, true, notifyAndExec);
720
721 return ok;
722 }
723
724 bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType type,
725 CFErrorRef *error, void (^transaction)(bool *commit))
726 {
727 bool ok = true;
728 bool commit = true;
729
730 if (dbconn->inTransaction) {
731 transaction(&commit);
732 if (!commit) {
733 secinfo("#SecDB", "#SecDB nested transaction asked to not be committed");
734 }
735 } else {
736 ok = SecDbBeginTransaction(dbconn, type, error);
737 if (ok) {
738 transaction(&commit);
739 ok = SecDbEndTransaction(dbconn, commit, error);
740 }
741 }
742
743 return ok && commit;
744 }
745
746 sqlite3 *SecDbHandle(SecDbConnectionRef dbconn) {
747 return dbconn->handle;
748 }
749
750 bool SecDbStep(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error, void (^row)(bool *stop)) {
751 for (;;) {
752 switch (_SecDbStep(dbconn, stmt, error)) {
753 case kSecDbErrorStep:
754 secdebug("db", "kSecDbErrorStep %@", error ? *error : NULL);
755 return false;
756 case kSecDbRowStep:
757 #if SECDB_DEBUGGING
758 secdebug("db", "kSecDbRowStep %@", error ? *error : NULL);
759 #endif
760 if (row) {
761 __block bool stop = false;
762 SecAutoreleaseInvokeWithPool(^{
763 row(&stop);
764 });
765 if (stop)
766 return true;
767 break;
768 }
769 SecDbError(SQLITE_ERROR, error, CFSTR("SecDbStep SQLITE_ROW returned without a row handler"));
770 return false;
771 case kSecDbDoneStep:
772 #if SECDB_DEBUGGING
773 secdebug("db", "kSecDbDoneStep %@", error ? *error : NULL);
774 #endif
775 return true;
776 }
777 }
778 }
779
780 bool SecDbCheckpoint(SecDbConnectionRef dbconn, CFErrorRef *error)
781 {
782 return SecDbConnectionCheckCode(dbconn, sqlite3_wal_checkpoint(dbconn->handle, NULL), error, CFSTR("wal_checkpoint"));
783 }
784
785 static bool SecDbFileControl(SecDbConnectionRef dbconn, int op, void *arg, CFErrorRef *error) {
786 return SecDbConnectionCheckCode(dbconn, sqlite3_file_control(dbconn->handle, NULL, op, arg), error, CFSTR("file_control"));
787 }
788
789 static sqlite3 *_SecDbOpenV2(const char *path,
790 int flags,
791 int useWAL,
792 int useRobotVacuum,
793 CFErrorRef *error) {
794 sqlite3 *handle = NULL;
795 int s3e = sqlite3_open_v2(path, &handle, flags, NULL);
796 if (s3e) {
797 if (handle) {
798 SecDbErrorWithDb(s3e, handle, error, CFSTR("open_v2 \"%s\" 0x%X"), path, flags);
799 sqlite3_close(handle);
800 handle = NULL;
801 } else {
802 SecDbError(s3e, error, CFSTR("open_v2 \"%s\" 0x%X"), path, flags);
803 }
804 } else if (SQLITE_OPEN_READWRITE == (flags & SQLITE_OPEN_READWRITE)) {
805 if (useRobotVacuum) {
806 #define SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL 2
807 sqlite3_stmt *stmt = NULL;
808 int vacuumMode = -1;
809
810 /*
811 * Setting auto_vacuum = incremental on a database that is not empty requires
812 * a VACCUUM, so check if the vacuum mode is not INCREMENTAL, and if its not,
813 * set it to incremental and vacuum.
814 */
815
816 s3e = sqlite3_prepare_v2(handle, "PRAGMA auto_vacuum", -1, &stmt, NULL);
817 if (s3e == 0) {
818 s3e = sqlite3_step(stmt);
819 if (s3e == SQLITE_ROW) {
820 vacuumMode = sqlite3_column_int(stmt, 0);
821 }
822 (void)sqlite3_finalize(stmt);
823 }
824
825 if (vacuumMode != SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL) {
826 (void)sqlite3_exec(handle, "PRAGMA auto_vacuum = incremental", NULL, NULL, NULL);
827 (void)sqlite3_exec(handle, "VACUUM", NULL, NULL, NULL);
828 }
829 }
830 if (useWAL) {
831 (void)sqlite3_exec(handle, "PRAGMA journal_mode = WAL", NULL, NULL, NULL);
832 }
833
834 // Let SQLite handle timeouts.
835 sqlite3_busy_timeout(handle, 5*1000);
836 }
837 return handle;
838 }
839
840 static bool SecDbOpenV2(SecDbConnectionRef dbconn, const char *path, int flags, CFErrorRef *error) {
841 return (dbconn->handle = _SecDbOpenV2(path, flags, dbconn->db->useWAL, dbconn->db->useRobotVacuum, error)) != NULL;
842 }
843
844 // This construction lets tests not exit here
845 static void SecDbProductionCorruptionExitHandler(void)
846 {
847 exit(EXIT_FAILURE);
848 }
849 void (*SecDbCorruptionExitHandler)(void) = SecDbProductionCorruptionExitHandler;
850
851 void SecDbResetCorruptionExitHandler(void)
852 {
853 SecDbCorruptionExitHandler = SecDbProductionCorruptionExitHandler;
854 }
855
856 /*
857 There's not much to do in here because we should only ever be here when
858 SQLite tells us the DB is corrupt, or the DB is unrecoverable because of
859 some fatal logic problem. But we can't shoot it dead either due to client
860 connections. So, first we create a marker to tell ourselves things are bad,
861 then we'll die. When we come back up we'll notice the marker and remove the DB.
862 */
863 static bool SecDbHandleCorrupt(SecDbConnectionRef dbconn, int rc, CFErrorRef *error)
864 {
865 if (!dbconn->db->allowRepair) {
866 SecCFCreateErrorWithFormat(rc, kSecErrnoDomain, NULL, error, NULL,
867 CFSTR("SecDbHandleCorrupt not allowed to repair, handled error: [%d] %s"), rc, strerror(rc));
868 dbconn->isCorrupted = false;
869 return false;
870 }
871
872 CFStringPerformWithCString(dbconn->db->db_path, ^(const char *db_path) {
873 char marker[PATH_MAX+1];
874 snprintf(marker, sizeof(marker), "%s-iscorrupt", db_path);
875 struct stat info = {};
876 if (0 == stat(marker, &info)) {
877 secerror("SecDbHandleCorrupt: Tried to write corruption marker %s but one already exists", marker);
878 }
879
880 FILE* file = fopen(marker, "w");
881 if (file == NULL) {
882 secerror("SecDbHandleCorrupt: Unable (%{darwin.errno}d) to create corruption marker %{public}s", errno, marker);
883 } else {
884 fclose(file);
885 }
886 });
887
888 secwarning("SecDbHandleCorrupt: killing self so that successor might cleanly delete corrupt db");
889
890 // Call through function pointer so tests can replace it and call a SecKeychainDbReset instead
891 SecDbCorruptionExitHandler();
892 return true;
893 }
894
895 static bool SecDbProcessCorruptionMarker(CFStringRef db_path) {
896 __block bool ok = true;
897 CFStringPerformWithCString(db_path, ^(const char *db_path) {
898 char marker[PATH_MAX+1];
899 snprintf(marker, sizeof(marker), "%s-iscorrupt", db_path);
900 struct stat info = {};
901 int result = stat(marker, &info);
902 if (result != 0 && errno == ENOENT) {
903 return;
904 } else if (result != 0) {
905 secerror("SecDbSecDbProcessCorruptionMarker: Unable to check for corruption marker: %{darwin.errno}d", errno);
906 return;
907 }
908
909 secwarning("SecDbSecDbProcessCorruptionMarker: found corruption marker %s", marker);
910 if (remove(marker)) {
911 secerror("SecDbSecDbProcessCorruptionMarker: Unable (%{darwin.errno}d) to delete corruption marker", errno);
912 ok = false;
913 } else if (remove(db_path) && errno != ENOENT) { // Not sure how we'd get ENOENT but it would suit us just fine
914 secerror("SecDbSecDbProcessCorruptionMarker: Unable (%{darwin.errno}d) to delete db %{public}s", errno, db_path);
915 ok = false;
916 } else {
917 secwarning("SecDbSecDbProcessCorruptionMarker: deleted corrupt db %{public}s", db_path);
918 }
919 });
920 return ok;
921 }
922
923 void
924 SecDbSetCorruptionReset(SecDbRef db, void (^corruptionReset)(void))
925 {
926 if (db->corruptionReset) {
927 Block_release(db->corruptionReset);
928 db->corruptionReset = NULL;
929 }
930 if (corruptionReset) {
931 db->corruptionReset = Block_copy(corruptionReset);
932 }
933 }
934
935 static bool SecDbLoggingEnabled(CFStringRef type)
936 {
937 CFTypeRef profile = NULL;
938 bool enabled = false;
939
940 if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0)
941 return false;
942
943 profile = (CFNumberRef)CFPreferencesCopyValue(CFSTR("SQLProfile"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesAnyHost);
944
945 if (profile == NULL)
946 return false;
947
948 if (CFGetTypeID(profile) == CFBooleanGetTypeID()) {
949 enabled = CFBooleanGetValue((CFBooleanRef)profile);
950 } else if (CFGetTypeID(profile) == CFNumberGetTypeID()) {
951 int32_t num = 0;
952 CFNumberGetValue(profile, kCFNumberSInt32Type, &num);
953 enabled = !!num;
954 }
955
956 CFReleaseSafe(profile);
957
958 return enabled;
959 }
960
961 static unsigned
962 SecDbProfileMask(void)
963 {
964 static dispatch_once_t onceToken;
965 static unsigned profile_mask = 0;
966
967 // sudo defaults write /Library/Preferences/com.apple.security SQLProfile -bool true
968 dispatch_once(&onceToken, ^{
969 if (SecDbLoggingEnabled(CFSTR("SQLProfile")))
970 profile_mask = SQLITE_TRACE_PROFILE;
971 #if DEBUG
972 profile_mask |= SQLITE_TRACE_STMT;
973 #else
974 if (SecDbLoggingEnabled(CFSTR("SQLTrace")))
975 profile_mask = SQLITE_TRACE_STMT;
976 #endif
977 if (SecDbLoggingEnabled(CFSTR("SQLRow")))
978 profile_mask = SQLITE_TRACE_ROW;
979 secinfo("#SecDB", "sqlDb: sql trace mask: 0x%08x", profile_mask);
980 });
981 return profile_mask;
982 }
983
984 static int
985 SecDbTraceV2(unsigned mask, void *ctx, void *p, void *x) {
986 SecDbConnectionRef dbconn __unused = ctx;
987 const char *trace = "unknown";
988
989 if (mask == SQLITE_TRACE_PROFILE)
990 trace = sqlite3_sql(p);
991 else if (mask == SQLITE_TRACE_STMT) {
992 trace = sqlite3_sql(p);
993 } else if (mask == SQLITE_TRACE_ROW) {
994 trace = sqlite3_expanded_sql(p);
995 }
996
997 #if SECDB_DEBUGGING
998 secinfo("#SecDB", "#SecDB %{public}s", trace);
999 #endif
1000 return 0;
1001 }
1002
1003
1004 static bool SecDbOpenHandle(SecDbConnectionRef dbconn, bool *created, CFErrorRef *error)
1005 {
1006 __block bool ok = true;
1007
1008 // This is pretty terrible because now what? We know we have a corrupt DB
1009 // and now we can't get rid of it.
1010 if (!SecDbProcessCorruptionMarker(dbconn->db->db_path)) {
1011 SecCFCreateErrorWithFormat(errno, kSecErrnoDomain, NULL, error, NULL, CFSTR("Unable to process corruption marker: %{darwin.errno}d"), errno);
1012 return false;
1013 }
1014
1015 CFStringPerformWithCString(dbconn->db->db_path, ^(const char *db_path) {
1016 int flags = (dbconn->db->readWrite) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
1017 ok = created && SecDbOpenV2(dbconn, db_path, flags, NULL);
1018 if (!ok) {
1019 ok = true;
1020 if (created) {
1021 char *tmp = dirname((char *)db_path);
1022 if (tmp) {
1023 mode_t omode = dbconn->db->mode;
1024 if (omode & S_IRUSR) { omode |= S_IXUSR; } // owner can read
1025 if (omode & S_IRGRP) { omode |= S_IXGRP; } // group can read
1026 if (omode & S_IROTH) { omode |= S_IXOTH; } // other can read
1027 int errnum = mkpath_np(tmp, omode);
1028 if (errnum != 0 && errnum != EEXIST) {
1029 SecCFCreateErrorWithFormat(errnum, kSecErrnoDomain, NULL, error, NULL,
1030 CFSTR("mkpath_np %s: [%d] %s"), tmp, errnum, strerror(errnum));
1031 ok = false;
1032 }
1033 }
1034 }
1035 // if the enclosing directory is ok, try to create the database.
1036 // this forces us to open it read-write, so we'll need to be the owner here.
1037 ok = ok && SecDbOpenV2(dbconn, db_path, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, error);
1038 if (ok) {
1039 chmod(db_path, dbconn->db->mode); // default: 0600 (S_IRUSR | S_IWUSR)
1040 if (created)
1041 *created = true;
1042 }
1043 }
1044
1045 if (ok) {
1046 unsigned mask = SecDbProfileMask();
1047 if (mask) {
1048 (void)sqlite3_trace_v2(dbconn->handle,
1049 mask,
1050 SecDbTraceV2,
1051 dbconn);
1052 }
1053 }
1054 });
1055
1056 return ok;
1057 }
1058
1059 static SecDbConnectionRef
1060 SecDbConnectionCreate(SecDbRef db, bool readOnly, CFErrorRef *error)
1061 {
1062 SecDbConnectionRef dbconn = NULL;
1063
1064 dbconn = CFTypeAllocate(SecDbConnection, struct __OpaqueSecDbConnection, kCFAllocatorDefault);
1065 require(dbconn != NULL, done);
1066
1067 dbconn->db = db;
1068 dbconn->readOnly = readOnly;
1069 dbconn->inTransaction = false;
1070 dbconn->source = kSecDbInvalidTransaction;
1071 dbconn->isCorrupted = false;
1072 dbconn->maybeCorruptedCode = 0;
1073 dbconn->hasIOFailure = false;
1074 dbconn->corruptionError = NULL;
1075 dbconn->handle = NULL;
1076 dbconn->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
1077
1078 done:
1079 return dbconn;
1080 }
1081
1082 bool SecDbConnectionIsReadOnly(SecDbConnectionRef dbconn) {
1083 return dbconn->readOnly;
1084 }
1085
1086 static void SecDbConectionSetReadOnly(SecDbConnectionRef dbconn, bool readOnly) {
1087 dbconn->readOnly = readOnly;
1088 }
1089
1090 /* Read only connections go to the end of the queue, writeable connections
1091 go to the start of the queue. */
1092 SecDbConnectionRef SecDbConnectionAcquire(SecDbRef db, bool readOnly, CFErrorRef *error) {
1093 SecDbConnectionRef dbconn = NULL;
1094 SecDbConnectionAcquireRefMigrationSafe(db, readOnly, &dbconn, error);
1095 return dbconn;
1096 }
1097
1098 bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbConnectionRef* dbconnRef, CFErrorRef *error)
1099 {
1100 CFRetain(db);
1101 #if SECDB_DEBUGGING
1102 secinfo("dbconn", "acquire %s connection", readOnly ? "ro" : "rw");
1103 #endif
1104 dispatch_semaphore_wait(readOnly ? db->read_semaphore : db->write_semaphore, DISPATCH_TIME_FOREVER);
1105 __block SecDbConnectionRef dbconn = NULL;
1106 __block bool ok = true;
1107 __block bool ranOpenedHandler = false;
1108
1109 bool (^assignDbConn)(SecDbConnectionRef) = ^bool(SecDbConnectionRef connection) {
1110 dbconn = connection;
1111 if (dbconnRef) {
1112 *dbconnRef = connection;
1113 }
1114
1115 return dbconn != NULL;
1116 };
1117
1118 dispatch_sync(db->queue, ^{
1119 if (!db->didFirstOpen) {
1120 bool didCreate = false;
1121 ok = assignDbConn(SecDbConnectionCreate(db, false, error));
1122 CFErrorRef localError = NULL;
1123 if (ok && !SecDbOpenHandle(dbconn, &didCreate, &localError)) {
1124 secerror("Unable to create database: %@", localError);
1125 if (localError && CFEqual(CFErrorGetDomain(localError), kSecDbErrorDomain)) {
1126 int code = (int)CFErrorGetCode(localError);
1127 dbconn->isCorrupted = (SQLITE_CORRUPT == code) || (SQLITE_NOTADB == code);
1128 }
1129 // If the open failure isn't due to corruption, propagate the error.
1130 ok = dbconn->isCorrupted;
1131 if (!ok && error && *error == NULL) {
1132 *error = localError;
1133 localError = NULL;
1134 }
1135 }
1136 CFReleaseNull(localError);
1137
1138 if (ok) {
1139 db->didFirstOpen = ok = SecDbDidCreateFirstConnection(dbconn, didCreate, error);
1140 ranOpenedHandler = true;
1141 }
1142 if (!ok)
1143 CFReleaseNull(dbconn);
1144 } else {
1145 /* Try to get one from the cache */
1146 CFIndex count = CFArrayGetCount(db->connections);
1147 while (count && !dbconn) {
1148 CFIndex ix = readOnly ? count - 1 : 0;
1149 if (assignDbConn((SecDbConnectionRef)CFArrayGetValueAtIndex(db->connections, ix)))
1150 CFRetainSafe(dbconn);
1151 else
1152 secerror("got NULL dbconn at index: %" PRIdCFIndex " skipping", ix);
1153 CFArrayRemoveValueAtIndex(db->connections, ix);
1154 }
1155 }
1156 });
1157
1158 if (dbconn) {
1159 /* Make sure the connection we found has the right access */
1160 if (SecDbConnectionIsReadOnly(dbconn) != readOnly) {
1161 SecDbConectionSetReadOnly(dbconn, readOnly);
1162 }
1163 } else if (ok) {
1164 /* Nothing found in cache, create a new connection */
1165 bool created = false;
1166 if (assignDbConn(SecDbConnectionCreate(db, readOnly, error)) && !SecDbOpenHandle(dbconn, &created, error)) {
1167 CFReleaseNull(dbconn);
1168 }
1169 }
1170
1171
1172 if (dbconn && !ranOpenedHandler && dbconn->db->opened) {
1173 dispatch_sync(db->queue, ^{
1174 if (dbconn->db->callOpenedHandlerForNextConnection) {
1175 dbconn->db->callOpenedHandlerForNextConnection = false;
1176 if (!dbconn->db->opened(db, dbconn, false, &dbconn->db->callOpenedHandlerForNextConnection, error)) {
1177 if (!dbconn->isCorrupted || !SecDbHandleCorrupt(dbconn, 0, error)) {
1178 CFReleaseNull(dbconn);
1179 }
1180 }
1181 }
1182 });
1183 }
1184
1185 if (dbconnRef) {
1186 *dbconnRef = dbconn;
1187 }
1188
1189 if (!dbconn) {
1190 // If acquire fails we need to signal the semaphore again.
1191 dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore);
1192 CFRelease(db);
1193 }
1194
1195 return dbconn ? true : false;
1196 }
1197
1198 void SecDbConnectionRelease(SecDbConnectionRef dbconn) {
1199 if (!dbconn) {
1200 secerror("called with NULL dbconn");
1201 return;
1202 }
1203 SecDbRef db = dbconn->db;
1204 #if SECDB_DEBUGGING
1205 secinfo("dbconn", "release %@", dbconn);
1206 #endif
1207 dispatch_sync(db->queue, ^{
1208 bool readOnly = SecDbConnectionIsReadOnly(dbconn);
1209 if (dbconn->hasIOFailure) {
1210 // Something wrong on the file layer (e.g. revoked file descriptor for networked home)
1211 // so we don't trust our existing connections anymore.
1212 CFArrayRemoveAllValues(db->connections);
1213 } else {
1214 CFIndex count = CFArrayGetCount(db->connections);
1215 // Add back possible writable dbconn to the pool.
1216 CFArrayInsertValueAtIndex(db->connections, readOnly ? count : 0, dbconn);
1217 // Remove the last (probably read-only) dbconn from the pool.
1218 if (count >= db->maxIdleHandles) {
1219 CFArrayRemoveValueAtIndex(db->connections, count);
1220 }
1221 }
1222 // Signal after we have put the connection back in the pool of connections
1223 dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore);
1224 CFRelease(dbconn);
1225 CFRelease(db);
1226 });
1227 }
1228
1229 void SecDbReleaseAllConnections(SecDbRef db) {
1230 // Force all connections to be removed (e.g. file descriptor no longer valid)
1231 if (!db) {
1232 secerror("called with NULL db");
1233 return;
1234 }
1235 dispatch_sync(db->queue, ^{
1236 CFArrayRemoveAllValues(db->connections);
1237 dispatch_semaphore_signal(db->write_semaphore);
1238 dispatch_semaphore_signal(db->read_semaphore);
1239 });
1240 }
1241
1242 bool SecDbPerformRead(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)) {
1243 SecDbConnectionRef dbconn = SecDbConnectionAcquire(db, true, error);
1244 bool success = false;
1245 if (dbconn) {
1246 perform(dbconn);
1247 success = true;
1248 SecDbConnectionRelease(dbconn);
1249 }
1250 return success;
1251 }
1252
1253 bool SecDbPerformWrite(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)) {
1254 if(!db) {
1255 SecError(errSecNotAvailable, error, CFSTR("failed to get a db handle"));
1256 return false;
1257 }
1258 SecDbConnectionRef dbconn = SecDbConnectionAcquire(db, false, error);
1259 bool success = false;
1260 if (dbconn) {
1261 perform(dbconn);
1262 success = true;
1263 SecDbConnectionRelease(dbconn);
1264 }
1265 return success;
1266 }
1267
1268 static CFStringRef
1269 SecDbConnectionCopyFormatDescription(CFTypeRef value, CFDictionaryRef formatOptions)
1270 {
1271 SecDbConnectionRef dbconn = (SecDbConnectionRef)value;
1272 return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<SecDbConnection %s %s>"),
1273 dbconn->readOnly ? "ro" : "rw", dbconn->handle ? "open" : "closed");
1274 }
1275
1276 static void
1277 SecDbConnectionDestroy(CFTypeRef value)
1278 {
1279 SecDbConnectionRef dbconn = (SecDbConnectionRef)value;
1280 if (dbconn->handle) {
1281 int s3e = sqlite3_close(dbconn->handle);
1282 if (s3e != SQLITE_OK) {
1283 secerror("failed to close database connection (%d) for %@: %s", s3e, dbconn->db->db_path, sqlite3_errmsg(dbconn->handle));
1284 }
1285 os_assert(s3e == SQLITE_OK); // Crash now or jetsam later
1286 }
1287 dbconn->db = NULL;
1288 CFReleaseNull(dbconn->changes);
1289 CFReleaseNull(dbconn->corruptionError);
1290
1291 }
1292
1293 void SecDbPerformOnCommitQueue(SecDbConnectionRef dbconn, bool barrier, dispatch_block_t perform) {
1294 if (barrier) {
1295 dispatch_barrier_sync(dbconn->db->commitQueue, ^{
1296 perform();
1297 });
1298 } else {
1299 dispatch_sync(dbconn->db->commitQueue, ^{
1300 perform();
1301 });
1302 }
1303 }
1304
1305 // MARK: -
1306 // MARK: Bind helpers
1307
1308 // Logging binds is very spammy when debug logging is on (~90% of log lines), and isn't often useful.
1309 // Enable this in your local build if you actually want every single SQL variable bind logged for debugging.
1310 #define LOG_SECDB_BINDS 0
1311
1312 bool SecDbBindBlob(sqlite3_stmt *stmt, int param, const void *zData, size_t n, void(*xDel)(void*), CFErrorRef *error) {
1313 if (n > INT_MAX) {
1314 return SecDbErrorWithStmt(SQLITE_TOOBIG, stmt, error,
1315 CFSTR("bind_blob[%d]: blob bigger than INT_MAX"), param);
1316 }
1317 bool ok = SecDbErrorWithStmt(sqlite3_bind_blob(stmt, param, zData, (int)n, xDel),
1318 stmt, error, CFSTR("bind_blob[%d]"), param);
1319 #if LOG_SECDB_BINDS
1320 secinfo("bind", "bind_blob[%d]: %.*P: %@", param, (int)n, zData, error ? *error : NULL);
1321 #endif
1322 return ok;
1323 }
1324
1325 bool SecDbBindText(sqlite3_stmt *stmt, int param, const char *zData, size_t n, void(*xDel)(void*), CFErrorRef *error) {
1326 if (n > INT_MAX) {
1327 return SecDbErrorWithStmt(SQLITE_TOOBIG, stmt, error,
1328 CFSTR("bind_text[%d]: text bigger than INT_MAX"), param);
1329 }
1330 bool ok = SecDbErrorWithStmt(sqlite3_bind_text(stmt, param, zData, (int)n, xDel), stmt, error,
1331 CFSTR("bind_text[%d]"), param);
1332 #if LOG_SECDB_BINDS
1333 secinfo("bind", "bind_text[%d]: \"%s\" error: %@", param, zData, error ? *error : NULL);
1334 #endif
1335 return ok;
1336 }
1337
1338 bool SecDbBindDouble(sqlite3_stmt *stmt, int param, double value, CFErrorRef *error) {
1339 bool ok = SecDbErrorWithStmt(sqlite3_bind_double(stmt, param, value), stmt, error,
1340 CFSTR("bind_double[%d]"), param);
1341 #if LOG_SECDB_BINDS
1342 secinfo("bind", "bind_double[%d]: %f error: %@", param, value, error ? *error : NULL);
1343 #endif
1344 return ok;
1345 }
1346
1347 bool SecDbBindInt(sqlite3_stmt *stmt, int param, int value, CFErrorRef *error) {
1348 bool ok = SecDbErrorWithStmt(sqlite3_bind_int(stmt, param, value), stmt, error,
1349 CFSTR("bind_int[%d]"), param);
1350 #if LOG_SECDB_BINDS
1351 secinfo("bind", "bind_int[%d]: %d error: %@", param, value, error ? *error : NULL);
1352 #endif
1353 return ok;
1354 }
1355
1356 bool SecDbBindInt64(sqlite3_stmt *stmt, int param, sqlite3_int64 value, CFErrorRef *error) {
1357 bool ok = SecDbErrorWithStmt(sqlite3_bind_int64(stmt, param, value), stmt, error,
1358 CFSTR("bind_int64[%d]"), param);
1359 #if LOG_SECDB_BINDS
1360 secinfo("bind", "bind_int64[%d]: %lld error: %@", param, value, error ? *error : NULL);
1361 #endif
1362 return ok;
1363 }
1364
1365
1366 /* AUDIT[securityd](done):
1367 value (ok) is a caller provided, non NULL CFTypeRef.
1368 */
1369 bool SecDbBindObject(sqlite3_stmt *stmt, int param, CFTypeRef value, CFErrorRef *error) {
1370 CFTypeID valueId;
1371 __block bool result = false;
1372
1373 /* TODO: Can we use SQLITE_STATIC below everwhere we currently use
1374 SQLITE_TRANSIENT since we finalize the statement before the value
1375 goes out of scope? */
1376 if (!value || (valueId = CFGetTypeID(value)) == CFNullGetTypeID()) {
1377 /* Skip bindings for NULL values. sqlite3 will interpret unbound
1378 params as NULL which is exactly what we want. */
1379 result = true;
1380 } else if (valueId == CFStringGetTypeID()) {
1381 CFStringPerformWithCStringAndLength(value, ^(const char *cstr, size_t clen) {
1382 result = SecDbBindText(stmt, param, cstr, clen, SQLITE_TRANSIENT, error);
1383 });
1384 } else if (valueId == CFDataGetTypeID()) {
1385 CFIndex len = CFDataGetLength(value);
1386 if (len) {
1387 result = SecDbBindBlob(stmt, param, CFDataGetBytePtr(value),
1388 len, SQLITE_TRANSIENT, error);
1389 } else {
1390 result = SecDbBindText(stmt, param, "", 0, SQLITE_TRANSIENT, error);
1391 }
1392 } else if (valueId == CFDateGetTypeID()) {
1393 CFAbsoluteTime abs_time = CFDateGetAbsoluteTime(value);
1394 result = SecDbBindDouble(stmt, param, abs_time, error);
1395 } else if (valueId == CFBooleanGetTypeID()) {
1396 int bval = CFBooleanGetValue(value);
1397 result = SecDbBindInt(stmt, param, bval, error);
1398 } else if (valueId == CFNumberGetTypeID()) {
1399 Boolean convertOk;
1400 if (CFNumberIsFloatType(value)) {
1401 double nval;
1402 convertOk = CFNumberGetValue(value, kCFNumberDoubleType, &nval);
1403 result = SecDbBindDouble(stmt, param, nval, error);
1404 } else {
1405 sqlite_int64 nval64;
1406 convertOk = CFNumberGetValue(value, kCFNumberSInt64Type, &nval64);
1407 if (convertOk) {
1408 result = SecDbBindInt64(stmt, param, nval64, error);
1409 }
1410 }
1411 if (!convertOk) {
1412 result = SecDbError(SQLITE_INTERNAL, error, CFSTR("bind CFNumberGetValue failed for %@"), value);
1413 }
1414 } else {
1415 if (error) {
1416 CFStringRef valueDesc = CFCopyTypeIDDescription(valueId);
1417 SecDbError(SQLITE_MISMATCH, error, CFSTR("bind unsupported type %@"), valueDesc);
1418 CFReleaseSafe(valueDesc);
1419 }
1420 }
1421
1422 return result;
1423 }
1424
1425 // MARK: -
1426 // MARK: SecDbStatementRef
1427
1428 bool SecDbReset(sqlite3_stmt *stmt, CFErrorRef *error) {
1429 return SecDbErrorWithStmt(sqlite3_reset(stmt), stmt, error, CFSTR("reset"));
1430 }
1431
1432 bool SecDbClearBindings(sqlite3_stmt *stmt, CFErrorRef *error) {
1433 return SecDbErrorWithStmt(sqlite3_clear_bindings(stmt), stmt, error, CFSTR("clear bindings"));
1434 }
1435
1436 bool SecDbFinalize(sqlite3_stmt *stmt, CFErrorRef *error) {
1437 sqlite3 *handle = sqlite3_db_handle(stmt);
1438 int s3e = sqlite3_finalize(stmt);
1439 return s3e == SQLITE_OK ? true : SecDbErrorWithDb(s3e, handle, error, CFSTR("finalize: %p"), stmt);
1440 }
1441
1442 sqlite3_stmt *SecDbPrepareV2(SecDbConnectionRef dbconn, const char *sql, size_t sqlLen, const char **sqlTail, CFErrorRef *error) {
1443 sqlite3 *db = SecDbHandle(dbconn);
1444 if (sqlLen > INT_MAX) {
1445 SecDbErrorWithDb(SQLITE_TOOBIG, db, error, CFSTR("prepare_v2: sql bigger than INT_MAX"));
1446 return NULL;
1447 }
1448 int ntries = 0;
1449 for (;;) {
1450 sqlite3_stmt *stmt = NULL;
1451 int s3e = sqlite3_prepare_v2(db, sql, (int)sqlLen, &stmt, sqlTail);
1452 if (s3e == SQLITE_OK)
1453 return stmt;
1454 else if (!SecDbWaitIfNeeded(dbconn, s3e, NULL, CFSTR("preparev2"), ntries, error))
1455 return NULL;
1456 ntries++;
1457 }
1458 }
1459
1460 static sqlite3_stmt *SecDbCopyStatementWithTailRange(SecDbConnectionRef dbconn, CFStringRef sql, CFRange *sqlTail, CFErrorRef *error) {
1461 __block sqlite3_stmt *stmt = NULL;
1462 if (sql) CFStringPerformWithCStringAndLength(sql, ^(const char *sqlStr, size_t sqlLen) {
1463 const char *tail = NULL;
1464 stmt = SecDbPrepareV2(dbconn, sqlStr, sqlLen, &tail, error);
1465 if (sqlTail && sqlStr < tail && tail < sqlStr + sqlLen) {
1466 sqlTail->location = tail - sqlStr;
1467 sqlTail->length = sqlLen - sqlTail->location;
1468 }
1469 });
1470
1471 return stmt;
1472 }
1473
1474 sqlite3_stmt *SecDbCopyStmt(SecDbConnectionRef dbconn, CFStringRef sql, CFStringRef *tail, CFErrorRef *error) {
1475 // TODO: Add caching and cache lookup of statements
1476 CFRange sqlTail = {};
1477 sqlite3_stmt *stmt = SecDbCopyStatementWithTailRange(dbconn, sql, &sqlTail, error);
1478 if (sqlTail.length > 0) {
1479 CFStringRef excess = CFStringCreateWithSubstring(CFGetAllocator(sql), sql, sqlTail);
1480 if (tail) {
1481 *tail = excess;
1482 } else {
1483 SecDbError(SQLITE_INTERNAL, error,
1484 CFSTR("prepare_v2: %@ unused sql: %@"),
1485 sql, excess);
1486 CFReleaseSafe(excess);
1487 SecDbFinalize(stmt, error);
1488 stmt = NULL;
1489 }
1490 }
1491 return stmt;
1492 }
1493
1494 /*
1495 TODO: Could do a hack here with a custom kCFAllocatorNULL allocator for a second CFRuntimeBase inside a SecDbStatement,
1496 TODO: Better yet make a full blow SecDbStatement instance whenever SecDbCopyStmt is called. Then, when the statement is released, in the Dispose method, we Reset and ClearBindings the sqlite3_stmt * and hand it back to the SecDb with the original CFStringRef for the sql (or hash thereof) as an argument. */
1497 bool SecDbReleaseCachedStmt(SecDbConnectionRef dbconn, CFStringRef sql, sqlite3_stmt *stmt, CFErrorRef *error) {
1498 if (stmt) {
1499 return SecDbFinalize(stmt, error);
1500 }
1501 return true;
1502 }
1503
1504 bool SecDbPrepare(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, void(^exec)(sqlite3_stmt *stmt)) {
1505 assert(sql != NULL);
1506 sqlite3_stmt *stmt = SecDbCopyStmt(dbconn, sql, NULL, error);
1507 if (!stmt)
1508 return false;
1509
1510 exec(stmt);
1511 return SecDbReleaseCachedStmt(dbconn, sql, stmt, error);
1512 }
1513
1514 bool SecDbWithSQL(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, bool(^perform)(sqlite3_stmt *stmt)) {
1515 bool ok = true;
1516 CFRetain(sql);
1517 while (sql) {
1518 CFStringRef tail = NULL;
1519 if (ok) {
1520 sqlite3_stmt *stmt = SecDbCopyStmt(dbconn, sql, &tail, error);
1521 ok = stmt != NULL;
1522 if (stmt) {
1523 if (perform) {
1524 ok = perform(stmt);
1525 } else {
1526 // TODO: Use a different error scope here.
1527 ok = SecError(-50 /* errSecParam */, error, CFSTR("SecDbWithSQL perform block missing"));
1528 }
1529 ok &= SecDbReleaseCachedStmt(dbconn, sql, stmt, error);
1530 }
1531 } else {
1532 // TODO We already have an error here we really just want the left over sql in it's userData
1533 ok = SecDbError(SQLITE_ERROR, error, CFSTR("Error with unexecuted sql remaining %@"), sql);
1534 }
1535 CFRelease(sql);
1536 sql = tail;
1537 }
1538 return ok;
1539 }
1540
1541 /* SecDbForEach returns true if all SQLITE_ROW returns of sqlite3_step() return true from the row block.
1542 If the row block returns false and doesn't set an error (to indicate it has reached a limit),
1543 this entire function returns false. In that case no error will be set. */
1544 bool SecDbForEach(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error, bool(^row)(int row_index)) {
1545 bool result = false;
1546 for (int row_ix = 0;;++row_ix) {
1547 if (SecDbConnectionIsReadOnly(dbconn) && !sqlite3_stmt_readonly(stmt)) {
1548 secerror("SecDbForEach: SecDbConnection is readonly but we're about to write: %s", sqlite3_sql(stmt));
1549 }
1550 int s3e = sqlite3_step(stmt);
1551 if (s3e == SQLITE_ROW) {
1552 if (row) {
1553 if (!row(row_ix)) {
1554 break;
1555 }
1556 } else {
1557 // If we have no row block then getting SQLITE_ROW is an error
1558 SecDbError(s3e, error,
1559 CFSTR("step[%d]: %s returned SQLITE_ROW with NULL row block"),
1560 row_ix, sqlite3_sql(stmt));
1561 }
1562 } else {
1563 if (s3e == SQLITE_DONE) {
1564 result = true;
1565 } else {
1566 SecDbConnectionCheckCode(dbconn, s3e, error, CFSTR("SecDbForEach step[%d]"), row_ix);
1567 }
1568 break;
1569 }
1570 }
1571 return result;
1572 }
1573
1574 void SecDbRecordChange(SecDbConnectionRef dbconn, CFTypeRef deleted, CFTypeRef inserted) {
1575 if (!dbconn->db->notifyPhase) return;
1576 CFTypeRef entry = SecDbEventCreateWithComponents(deleted, inserted);
1577 if (entry) {
1578 CFArrayAppendValue(dbconn->changes, entry);
1579 CFRelease(entry);
1580
1581 if (!dbconn->inTransaction) {
1582 secerror("db %@ changed outside txn", dbconn);
1583 // Only notify of DidCommit, since WillCommit code assumes
1584 // we are in a txn.
1585 SecDbOnNotify(dbconn, ^{
1586 SecDbNotifyPhase(dbconn, kSecDbTransactionDidCommit);
1587 });
1588 }
1589 }
1590 }
1591
1592
1593 CFGiblisFor(SecDbConnection)
1594
1595 //
1596 // SecDbEvent Creation and consumption
1597 //
1598
1599 static SecDbEventRef SecDbEventCreateInsert(CFTypeRef inserted) {
1600 return CFRetainSafe(inserted);
1601 }
1602
1603 static SecDbEventRef SecDbEventCreateDelete(CFTypeRef deleted) {
1604 return CFArrayCreate(kCFAllocatorDefault, &deleted, 1, &kCFTypeArrayCallBacks);
1605 }
1606
1607 static SecDbEventRef SecDbEventCreateUpdate(CFTypeRef deleted, CFTypeRef inserted) {
1608 const void *values[2] = { deleted, inserted };
1609 return CFArrayCreate(kCFAllocatorDefault, values, 2, &kCFTypeArrayCallBacks);
1610 }
1611
1612 SecDbEventRef SecDbEventCreateWithComponents(CFTypeRef deleted, CFTypeRef inserted) {
1613 if (deleted && inserted)
1614 return SecDbEventCreateUpdate(deleted, inserted);
1615 else if (deleted)
1616 return SecDbEventCreateDelete(deleted);
1617 else if (inserted)
1618 return SecDbEventCreateInsert(inserted);
1619 else
1620 return NULL;
1621 }
1622
1623 void SecDbEventTranslateComponents(SecDbEventRef item, CFTypeRef* deleted, CFTypeRef* inserted) {
1624 if(CFGetTypeID(item) == CFArrayGetTypeID()) {
1625 // One item: deletion. Two: update.
1626 CFIndex arraySize = CFArrayGetCount(item);
1627 if(arraySize == 1) {
1628 if(deleted) { *deleted = CFArrayGetValueAtIndex(item, 0); }
1629 if(inserted) { *inserted = NULL; }
1630 } else if(arraySize == 2) {
1631 if(deleted) { *deleted = CFArrayGetValueAtIndex(item, 0); }
1632 if(inserted) { *inserted = CFArrayGetValueAtIndex(item, 1); }
1633 } else {
1634 if(deleted) { *deleted = NULL; }
1635 if(inserted) { *inserted = NULL; }
1636 }
1637 } else {
1638 if(deleted) { *deleted = NULL; }
1639 if(inserted) { *inserted = item; }
1640 }
1641
1642 }
1643
1644 bool SecDbEventGetComponents(SecDbEventRef event, CFTypeRef *deleted, CFTypeRef *inserted, CFErrorRef *error) {
1645 if (isArray(event)) {
1646 CFArrayRef array = event;
1647 switch (CFArrayGetCount(array)) {
1648 case 2:
1649 *deleted = CFArrayGetValueAtIndex(array, 0);
1650 *inserted = CFArrayGetValueAtIndex(array, 1);
1651 break;
1652 case 1:
1653 *deleted = CFArrayGetValueAtIndex(array, 0);
1654 *inserted = NULL;
1655 break;
1656 default:
1657 SecError(errSecParam, error, NULL, CFSTR("invalid entry in changes array: %@"), array);
1658 break;
1659 }
1660 } else {
1661 *deleted = NULL;
1662 *inserted = event;
1663 }
1664 return true;
1665 }