2  * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 #include "debugging.h" 
  29 #include <sqlite3_private.h> 
  30 #include <CoreFoundation/CoreFoundation.h> 
  34 #include <AssertMacros.h> 
  35 #include "SecCFWrappers.h" 
  36 #include "SecCFError.h" 
  37 #include "SecIOFormat.h" 
  39 #include "Security/SecBase.h" 
  40 #include "SecAutorelease.h" 
  41 #include <os/assumes.h> 
  42 #include <xpc/private.h>    // xpc_transaction_exit_clean() 
  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) 
  50 #include "keychain/SecureObjectSync/SOSDigestVector.h" 
  51 #include "keychain/SecureObjectSync/SOSManifest.h" 
  53 #define SECDB_DEBUGGING 0 
  55 struct __OpaqueSecDbStatement 
{ 
  58     SecDbConnectionRef dbconn
; 
  62 struct __OpaqueSecDbConnection 
{ 
  65     //CFMutableDictionaryRef statements; 
  67     SecDbRef db
;     // NONRETAINED, since db or block retains us 
  70     SecDbTransactionSource source
; 
  72     int maybeCorruptedCode
; 
  74     CFErrorRef corruptionError
; 
  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
; 
  84 struct __OpaqueSecDb 
{ 
  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
; 
  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); 
 106 // MARK: Error domains and error helper functions 
 108 CFStringRef kSecDbErrorDomain 
= CFSTR("com.apple.utilities.sqlite3"); 
 110 bool SecDbError(int sql_code
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 111     if (sql_code 
== SQLITE_OK
) return true; 
 115         CFIndex code 
= sql_code
; 
 116         CFErrorRef previousError 
= *error
; 
 119         va_start(args
, format
); 
 120         SecCFCreateErrorWithFormatAndArguments(code
, kSecDbErrorDomain
, previousError
, error
, NULL
, format
, args
); 
 126 bool SecDbErrorWithDb(int sql_code
, sqlite3 
*db
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 127     if (sql_code 
== SQLITE_OK
) return true; 
 130         va_start(args
, format
); 
 131         CFStringRef message 
= CFStringCreateWithFormatAndArguments(kCFAllocatorDefault
, NULL
, format
, args
); 
 133         CFStringRef errno_code 
= NULL
; 
 135         if (sql_code 
== SQLITE_CANTOPEN
) { 
 136             int errno_number 
= sqlite3_system_errno(db
); 
 137             errno_code 
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), errno_number
); 
 139             errno_code 
= CFRetain(CFSTR("")); 
 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
)); 
 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
); 
 153 bool SecDbErrorWithStmt(int sql_code
, sqlite3_stmt 
*stmt
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 154     if (sql_code 
== SQLITE_OK
) return true; 
 157         va_start(args
, format
); 
 158         CFStringRef message 
= CFStringCreateWithFormatAndArguments(kCFAllocatorDefault
, NULL
, format
, args
); 
 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
); 
 167             SecDbError(sql_code
, error
, CFSTR("%@: [%d->%d] %s sql: %s"), message
, sql_code
, extended_code
, sqlite3_errmsg(db
), sql
); 
 168         CFReleaseSafe(message
); 
 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
); 
 178 void _SecDbServerSetup(void) 
 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
); 
 191 // MARK: Static helper functions 
 193 static bool SecDbOpenHandle(SecDbConnectionRef dbconn
, bool *created
, CFErrorRef 
*error
); 
 194 static bool SecDbHandleCorrupt(SecDbConnectionRef dbconn
, int rc
, CFErrorRef 
*error
); 
 197 #pragma mark SecDbRef 
 200 SecDbCopyFormatDescription(CFTypeRef value
, CFDictionaryRef formatOptions
) 
 202     SecDbRef db 
= (SecDbRef
)value
; 
 203     return CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("<SecDb path:%@ connections: %@>"), db
->db_path
, db
->connections
); 
 208 SecDbDestroy(CFTypeRef value
) 
 210     SecDbRef db 
= (SecDbRef
)value
; 
 211     CFReleaseNull(db
->connections
); 
 212     CFReleaseNull(db
->db_path
); 
 214         dispatch_release(db
->queue
); 
 217     if (db
->commitQueue
) { 
 218         dispatch_release(db
->commitQueue
); 
 219         db
->commitQueue 
= NULL
; 
 221     if (db
->read_semaphore
) { 
 222         dispatch_release(db
->read_semaphore
); 
 223         db
->read_semaphore 
= NULL
; 
 225     if (db
->write_semaphore
) { 
 226         dispatch_release(db
->write_semaphore
); 
 227         db
->write_semaphore 
= NULL
; 
 230         Block_release(db
->opened
); 
 233     CFReleaseNull(db
->notifyPhase
); 
 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
)) 
 244     db 
= CFTypeAllocate(SecDb
, struct __OpaqueSecDb
, kCFAllocatorDefault
); 
 245     require(db 
!= NULL
, done
); 
 247     CFStringPerformWithCString(dbName
, ^(const char *dbNameStr
) { 
 248         db
->queue 
= dispatch_queue_create(dbNameStr
, DISPATCH_QUEUE_SERIAL
); 
 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
); 
 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"); 
 263         db
->db_path 
= CFSTR("file::memory:?cache=shared"); 
 265         db
->db_path 
= CFStringCreateCopy(kCFAllocatorDefault
, dbName
); 
 268     db
->readWrite 
= readWrite
; 
 269     db
->allowRepair 
= allowRepair
; 
 271     db
->useRobotVacuum 
= useRobotVacuum
; 
 272     db
->maxIdleHandles 
= maxIdleHandles
; 
 273     db
->corruptionReset 
= NULL
; 
 280 SecDbIdleConnectionCount(SecDbRef db
) { 
 281     __block CFIndex count 
= 0; 
 282     dispatch_sync(db
->queue
, ^{ 
 283         count 
= CFArrayGetCount(db
->connections
); 
 288 void SecDbAddNotifyPhaseBlock(SecDbRef db
, SecDBNotifyBlock notifyPhase
) 
 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
); 
 296         CFArrayAppendValue(db
->notifyPhase
, block
); 
 297         Block_release(block
); 
 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
); 
 311         CFReleaseSafe(changes
); 
 315 static void SecDbOnNotify(SecDbConnectionRef dbconn
, void (^perform
)(void)) { 
 319 CFStringRef 
SecDbGetPath(SecDbRef db
) { 
 328 #pragma mark SecDbConnectionRef 
 330 static bool SecDbCheckCorrupted(SecDbConnectionRef dbconn
) 
 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) { 
 340                 secerror("SecDBCheckCorrupted integrity_check returned %s", (result
) ? result 
: "NULL"); 
 346         // An error occurred in SecDbPrepare before we could run the block. 
 348             CFIndex code 
= CFErrorGetCode(error
); 
 349             if (SQLITE_CORRUPT 
== code 
|| SQLITE_NOTADB 
== code
) { 
 352             secinfo("#SecDB", "#SecDB warning error %{public}@ when running integrity check", error
); 
 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. 
 359             secinfo("#SecDB", "#SecDB warning: failed to run integrity check due to corruption"); 
 364             secerror("SecDBCheckCorrupted ran integrity_check, and that didn't return ok"); 
 366             secerror("SecDBCheckCorrupted failed to run integrity check"); 
 369     CFReleaseNull(error
); 
 374 static bool SecDbDidCreateFirstConnection(SecDbConnectionRef dbconn
, bool didCreate
, CFErrorRef 
*error
) 
 376     secinfo("#SecDB", "#SecDB starting maintenance"); 
 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. 
 382     if (!dbconn
->isCorrupted 
&& dbconn
->db
->opened
) { 
 383         CFErrorRef localError 
= NULL
; 
 385         dbconn
->db
->callOpenedHandlerForNextConnection 
= false; 
 386         ok 
= dbconn
->db
->opened(dbconn
->db
, dbconn
, didCreate
, &dbconn
->db
->callOpenedHandlerForNextConnection
, &localError
); 
 389             secerror("opened block failed: %@", localError
); 
 391         if (!dbconn
->isCorrupted 
&& error 
&& *error 
== NULL
) { 
 396                 secerror("opened block failed: error (%@) is being released and lost", localError
); 
 397             CFReleaseNull(localError
); 
 401     if (dbconn
->isCorrupted
) { 
 402         ok 
= SecDbHandleCorrupt(dbconn
, 0, error
); 
 405     secinfo("#SecDB", "#SecDB starting maintenance"); 
 409 void SecDbCorrupt(SecDbConnectionRef dbconn
, CFErrorRef error
) 
 411     if (__security_simulatecrash_enabled()) { 
 412         os_log_fault(secLogObjForScope("SecEmergency"), "SecDBCorrupt: %@", error
); 
 414     dbconn
->isCorrupted 
= true; 
 415     CFRetainAssign(dbconn
->corruptionError
, error
); 
 419 static uint8_t knownDbPathIndex(SecDbConnectionRef dbconn
) 
 422     if(CFEqual(dbconn
->db
->db_path
, CFSTR("/Library/Keychains/keychain-2.db"))) 
 424     if(CFEqual(dbconn
->db
->db_path
, CFSTR("/Library/Keychains/ocspcache.sqlite3"))) 
 426     if(CFEqual(dbconn
->db
->db_path
, CFSTR("/Library/Keychains/TrustStore.sqlite3"))) 
 428     if(CFEqual(dbconn
->db
->db_path
, CFSTR("/Library/Keychains/caissuercache.sqlite3"))) 
 431     /* Unknown DB path */ 
 435 static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn
, int code
, CFErrorRef 
*error
, CFStringRef desc
, ...) 
 436     CF_FORMAT_FUNCTION(4, 5); 
 438 // Return true if there was no error, returns false otherwise and set *error to an appropriate CFErrorRef. 
 439 static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn
, int code
, CFErrorRef 
*error
, CFStringRef desc
, ...) { 
 440     if (code 
== SQLITE_OK 
|| code 
== SQLITE_DONE
) 
 445         va_start(args
, desc
); 
 446         CFStringRef msg 
= CFStringCreateWithFormatAndArguments(kCFAllocatorDefault
, NULL
, desc
, args
); 
 448         SecDbErrorWithDb(code
, dbconn
->handle
, error
, CFSTR("%@"), msg
); 
 452     dbconn
->hasIOFailure 
|= (SQLITE_IOERR 
== code
); 
 454     /* If it's already corrupted, don't try to recover */ 
 455     if (dbconn
->isCorrupted
) { 
 456         CFStringRef reason 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, 
 457                                                       CFSTR("SQL DB %@ is corrupted already. Corruption error was: %d (previously %d)"), 
 458                                                       dbconn
->db
->db_path
, code
, dbconn
->maybeCorruptedCode
); 
 459         secerror("%@",reason
); 
 460         __security_simulatecrash(reason
, __sec_exception_code_TwiceCorruptDb(knownDbPathIndex(dbconn
))); 
 461         CFReleaseSafe(reason
); 
 462         // We can't fall through to the checking case because it eventually calls SecDbConnectionCheckCode again. 
 463         // However, this is the second time we're seeing corruption so let's take the ultimate measure. 
 464         if ((SQLITE_CORRUPT 
== code
) || (SQLITE_NOTADB 
== code
)) { 
 465             secerror("SecDbConnectionCheckCode detected corruption twice: going to handle corrupt DB"); 
 466             (void)SecDbHandleCorrupt(dbconn
, code
, error
); 
 471     // NOTADB means file is garbage, so it's functionally equivalent to corruption 
 472     dbconn
->isCorrupted 
= (SQLITE_CORRUPT 
== code
) || (SQLITE_NOTADB 
== code
); 
 473     if (dbconn
->isCorrupted
) { 
 474         /* Run integrity check and only make dbconn->isCorrupted true and 
 475            run the corruption handler if the integrity check conclusively fails. */ 
 476         dbconn
->maybeCorruptedCode 
= code
; 
 477         dbconn
->isCorrupted 
= SecDbCheckCorrupted(dbconn
); 
 478         if (dbconn
->isCorrupted
) { 
 479             secerror("operation returned code: %d integrity check=fail", code
); 
 480             (void)SecDbHandleCorrupt(dbconn
, code
, error
); 
 482             secerror("operation returned code: %d: integrity check=pass", code
); 
 489 #define BUSY_TIMEOUT_MS (5 * 60 * 1000)  /* 5 minutes */ 
 491 static int sleepBackoff
[] = { 10, 20, 50, 100, 250 }; 
 492 static int sumBackoff
[]   = { 10, 30, 80, 180, 430 }; 
 493 static int NumberOfSleepBackoff 
= sizeof(sleepBackoff
)/sizeof(sleepBackoff
[0]); 
 495 // Use these as silly hacks to encode the SQLite return code in the backtrace, for hang debugging purposes 
 496 static void __attribute__((noinline
)) SecDbLockSleep(int ms
) { 
 500 static void __attribute__((noinline
)) SecDbBusySleep(int ms
) { 
 504 // Return true causes the operation to be tried again. 
 505 // Note that we set sqlite3_busy_timeout on the connection, so anytime you're in here, it's likely due to SQLITE_LOCKED. 
 506 static bool SecDbWaitIfNeeded(SecDbConnectionRef dbconn
, int s3e
, sqlite3_stmt 
*stmt
, CFStringRef desc
, int nTries
, CFErrorRef 
*error
) { 
 507     if (((0xFF & s3e
) == SQLITE_BUSY
) || ((0xFF & s3e
) == SQLITE_LOCKED
)) { 
 508         int totaltimeout
, timeout
; 
 510         _Static_assert(sizeof(sumBackoff
) == sizeof(sleepBackoff
), "matching arrays not matching"); 
 511         _Static_assert(sizeof(sumBackoff
[0]) == sizeof(sleepBackoff
[0]), "matching arrays not matching"); 
 513         if (nTries 
< NumberOfSleepBackoff
) { 
 514             timeout 
= sleepBackoff
[nTries
]; 
 515             totaltimeout 
= sumBackoff
[nTries
]; 
 517             timeout 
= sleepBackoff
[NumberOfSleepBackoff 
- 1]; 
 518             totaltimeout 
= sumBackoff
[NumberOfSleepBackoff 
- 1] + (timeout 
* (nTries 
- NumberOfSleepBackoff
)); 
 520         if (totaltimeout 
< BUSY_TIMEOUT_MS
) { 
 521             secinfo("#SecDB", "sqlite busy/locked: %d ntries: %d totaltimeout: %d", s3e
, nTries
, totaltimeout
); 
 522             if(((0xFF & s3e
) == SQLITE_LOCKED
)) { 
 523                 SecDbLockSleep(timeout
); 
 525                 SecDbBusySleep(timeout
); 
 529             secinfo("#SecDB", "sqlite busy/locked: too long: %d ms, giving up", totaltimeout
); 
 533     return SecDbConnectionCheckCode(dbconn
, s3e
, error
, CFSTR("%@"), desc
); 
 536 enum SecDbStepResult 
{ 
 541 typedef enum SecDbStepResult SecDbStepResult
; 
 543 static SecDbStepResult 
_SecDbStep(SecDbConnectionRef dbconn
, sqlite3_stmt 
*stmt
, CFErrorRef 
*error
) { 
 544     assert(stmt 
!= NULL
); 
 548         if (SecDbConnectionIsReadOnly(dbconn
) && !sqlite3_stmt_readonly(stmt
)) { 
 549             secerror("_SecDbStep: SecDbConnection is readonly but we're about to write: %s", sqlite3_sql(stmt
)); 
 551         s3e 
= sqlite3_step(stmt
); 
 552         if (s3e 
== SQLITE_ROW
) { 
 553             return kSecDbRowStep
; 
 554         } else if (s3e 
== SQLITE_DONE
) { 
 556              ** ^[SQLITE_DONE] means that the statement has finished executing 
 557              ** successfully.  sqlite3_step() should not be called again on this virtual 
 558              ** machine without first calling [] to reset the virtual 
 559              ** machine back to its initial state. 
 562             return kSecDbDoneStep
; 
 563         } else if (!SecDbWaitIfNeeded(dbconn
, s3e
, stmt
, CFSTR("step"), ntries
, error
)) { 
 564             return kSecDbErrorStep
; 
 571 SecDbExec(SecDbConnectionRef dbconn
, CFStringRef sql
, CFErrorRef 
*error
) 
 576         CFStringRef tail 
= NULL
; 
 578             sqlite3_stmt 
*stmt 
= SecDbCopyStmt(dbconn
, sql
, &tail
, error
); 
 582                 while ((sr 
= _SecDbStep(dbconn
, stmt
, error
)) == kSecDbRowStep
); 
 583                 if (sr 
== kSecDbErrorStep
) 
 585                 ok 
&= SecDbReleaseCachedStmt(dbconn
, sql
, stmt
, error
); 
 588             // TODO We already have an error here we really just want the left over sql in it's userData 
 589             ok 
= SecDbError(SQLITE_ERROR
, error
, CFSTR("Error with unexecuted sql remaining %@"), sql
); 
 597 static int SecDBGetInteger(SecDbConnectionRef dbconn
, CFStringRef sql
) 
 599     __block 
int number 
= -1; 
 600     __block CFErrorRef error 
= NULL
; 
 602     (void)SecDbWithSQL(dbconn
, sql
, &error
, ^bool(sqlite3_stmt 
*sqlStmt
) { 
 603         (void)SecDbStep(dbconn
, sqlStmt
, &error
, ^(bool *stop
) { 
 604             number 
= sqlite3_column_int(sqlStmt
, 0); 
 609     CFReleaseNull(error
); 
 614 void SecDBManagementTasks(SecDbConnectionRef dbconn
) 
 616     int64_t page_count 
= SecDBGetInteger(dbconn
, CFSTR("pragma page_count")); 
 617     if (page_count 
<= 0) { 
 620     int64_t free_count 
= SecDBGetInteger(dbconn
, CFSTR("pragma freelist_count")); 
 621     if (free_count 
< 0) { 
 625     int64_t max_free 
= 8192; 
 627     int64_t pages_in_use 
= page_count 
- free_count
; 
 628     double loadFactor 
= ((double)pages_in_use
/(double)page_count
); 
 629     if (0.85 < loadFactor 
&& free_count 
< max_free
) { 
 632         int64_t pages_to_free 
= (int64_t)(0.2 * free_count
); 
 633         if (0.4 > loadFactor
) { 
 634             pages_to_free 
= free_count
; 
 637         char *formatString 
= NULL
; 
 638         asprintf(&formatString
, "pragma incremental_vacuum(%d)", (int)pages_to_free
); 
 640             char *sqlerror 
= NULL
; 
 641             int rc 
= sqlite3_exec(dbconn
->handle
, formatString
, NULL
, NULL
, &sqlerror
); 
 643                 secerror("incremental_vacuum failed with: (%d) %{public}s", rc
, sqlerror
); 
 645             sqlite3_free(sqlerror
); 
 652 static bool SecDbBeginTransaction(SecDbConnectionRef dbconn
, SecDbTransactionType type
, CFErrorRef 
*error
) 
 657         case kSecDbImmediateTransactionType
: 
 658             secdebug("db", "SecDbBeginTransaction SecDbBeginTransaction %p", dbconn
); 
 659             query 
= CFSTR("BEGIN IMMEDIATE"); 
 661         case kSecDbExclusiveRemoteSOSTransactionType
: 
 662             secdebug("db", "SecDbBeginTransaction kSecDbExclusiveRemoteSOSTransactionType %p", dbconn
); 
 663             dbconn
->source 
= kSecDbSOSTransaction
; 
 664             query 
= CFSTR("BEGIN EXCLUSIVE"); 
 666         case kSecDbExclusiveRemoteCKKSTransactionType
: 
 667             secdebug("db", "SecDbBeginTransaction kSecDbExclusiveRemoteCKKSTransactionType %p", dbconn
); 
 668             dbconn
->source 
= kSecDbCKKSTransaction
; 
 669             query 
= CFSTR("BEGIN EXCLUSIVE"); 
 671         case kSecDbExclusiveTransactionType
: 
 672             if (type
==kSecDbExclusiveTransactionType
) 
 673                 secdebug("db", "SecDbBeginTransaction kSecDbExclusiveTransactionType %p", dbconn
); 
 674             query 
= CFSTR("BEGIN EXCLUSIVE"); 
 676         case kSecDbNormalTransactionType
: 
 677             secdebug("db", "SecDbBeginTransaction kSecDbNormalTransactionType %p", dbconn
); 
 678             query 
= CFSTR("BEGIN"); 
 681             secdebug("db", "SecDbBeginTransaction invalid transaction type %lu", type
); 
 682             ok 
= SecDbError(SQLITE_ERROR
, error
, CFSTR("invalid transaction type %d"), (int)type
); 
 687     if (query 
!= NULL 
&& sqlite3_get_autocommit(dbconn
->handle
) != 0) { 
 688         ok 
= SecDbExec(dbconn
, query
, error
); 
 691         dbconn
->inTransaction 
= true; 
 696 static bool SecDbEndTransaction(SecDbConnectionRef dbconn
, bool commit
, CFErrorRef 
*error
) 
 698     __block 
bool ok 
= true; 
 699     __block 
bool commited 
= false; 
 701     dispatch_block_t notifyAndExec 
= ^{ 
 703             //secdebug("db", "SecDbEndTransaction kSecDbTransactionWillCommit %p", dbconn); 
 704             SecDbNotifyPhase(dbconn
, kSecDbTransactionWillCommit
); 
 705             commited 
= ok 
= SecDbExec(dbconn
, CFSTR("END"), error
); 
 706             //secdebug("db", "SecDbEndTransaction kSecDbTransactionWillCommit %p (after notify)", dbconn); 
 708             ok 
= SecDbExec(dbconn
, CFSTR("ROLLBACK"), error
); 
 711         dbconn
->inTransaction 
= false; 
 712         SecDbNotifyPhase(dbconn
, commited 
? kSecDbTransactionDidCommit 
: kSecDbTransactionDidRollback
); 
 713         secdebug("db", "SecDbEndTransaction %s %p", commited 
? "kSecDbTransactionDidCommit" : "kSecDbTransactionDidRollback", dbconn
); 
 714         dbconn
->source 
= kSecDbAPITransaction
; 
 716         if (commit 
&& dbconn
->db
->useRobotVacuum
) { 
 717             SecDBManagementTasks(dbconn
); 
 721     SecDbPerformOnCommitQueue(dbconn
, true, notifyAndExec
); 
 726 bool SecDbTransaction(SecDbConnectionRef dbconn
, SecDbTransactionType type
, 
 727                       CFErrorRef 
*error
, void (^transaction
)(bool *commit
)) 
 732     if (dbconn
->inTransaction
) { 
 733         transaction(&commit
); 
 735             secinfo("#SecDB", "#SecDB nested transaction asked to not be committed"); 
 738         ok 
= SecDbBeginTransaction(dbconn
, type
, error
); 
 740             transaction(&commit
); 
 741             ok 
= SecDbEndTransaction(dbconn
, commit
, error
); 
 748 sqlite3 
*SecDbHandle(SecDbConnectionRef dbconn
) { 
 749     return dbconn
->handle
; 
 752 bool SecDbStep(SecDbConnectionRef dbconn
, sqlite3_stmt 
*stmt
, CFErrorRef 
*error
, void (^row
)(bool *stop
)) { 
 754         switch (_SecDbStep(dbconn
, stmt
, error
)) { 
 755             case kSecDbErrorStep
: 
 756                 secdebug("db", "kSecDbErrorStep %@", error 
? *error 
: NULL
); 
 760                 secdebug("db", "kSecDbRowStep %@", error 
? *error 
: NULL
); 
 763                     __block 
bool stop 
= false; 
 764                     SecAutoreleaseInvokeWithPool(^{ 
 771                 SecDbError(SQLITE_ERROR
, error
, CFSTR("SecDbStep SQLITE_ROW returned without a row handler")); 
 775                 secdebug("db", "kSecDbDoneStep %@", error 
? *error 
: NULL
); 
 782 bool SecDbCheckpoint(SecDbConnectionRef dbconn
, CFErrorRef 
*error
) 
 784     return SecDbConnectionCheckCode(dbconn
, sqlite3_wal_checkpoint(dbconn
->handle
, NULL
), error
, CFSTR("wal_checkpoint")); 
 787 static bool SecDbFileControl(SecDbConnectionRef dbconn
, int op
, void *arg
, CFErrorRef 
*error
) { 
 788     return SecDbConnectionCheckCode(dbconn
, sqlite3_file_control(dbconn
->handle
, NULL
, op
, arg
), error
, CFSTR("file_control")); 
 791 static sqlite3 
*_SecDbOpenV2(const char *path
, 
 796     sqlite3 
*handle 
= NULL
; 
 797     int s3e 
= sqlite3_open_v2(path
, &handle
, flags
, NULL
); 
 800             SecDbErrorWithDb(s3e
, handle
, error
, CFSTR("open_v2 \"%s\" 0x%X"), path
, flags
); 
 801             sqlite3_close(handle
); 
 804             SecDbError(s3e
, error
, CFSTR("open_v2 \"%s\" 0x%X"), path
, flags
); 
 806     } else if (SQLITE_OPEN_READWRITE 
== (flags 
& SQLITE_OPEN_READWRITE
)) { 
 807         if (useRobotVacuum
) { 
 808 #define SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL 2 
 809             sqlite3_stmt 
*stmt 
= NULL
; 
 813              * Setting auto_vacuum = incremental on a database that is not empty requires 
 814              * a VACCUUM, so check if the vacuum mode is not INCREMENTAL, and if its not, 
 815              * set it to incremental and vacuum. 
 818             s3e 
= sqlite3_prepare_v2(handle
, "PRAGMA auto_vacuum", -1, &stmt
, NULL
); 
 820                 s3e 
= sqlite3_step(stmt
); 
 821                 if (s3e 
== SQLITE_ROW
) { 
 822                     vacuumMode 
= sqlite3_column_int(stmt
, 0); 
 824                 (void)sqlite3_finalize(stmt
); 
 827             if (vacuumMode 
!= SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL
) { 
 828                 (void)sqlite3_exec(handle
, "PRAGMA auto_vacuum = incremental", NULL
, NULL
, NULL
); 
 829                 (void)sqlite3_exec(handle
, "VACUUM", NULL
, NULL
, NULL
); 
 833             (void)sqlite3_exec(handle
, "PRAGMA journal_mode = WAL", NULL
, NULL
, NULL
); 
 836         // Let SQLite handle timeouts. 
 837         sqlite3_busy_timeout(handle
, 5*1000); 
 842 static bool SecDbOpenV2(SecDbConnectionRef dbconn
, const char *path
, int flags
, CFErrorRef 
*error
) { 
 843     return (dbconn
->handle 
= _SecDbOpenV2(path
, flags
, dbconn
->db
->useWAL
, dbconn
->db
->useRobotVacuum
, error
)) != NULL
; 
 846 // This construction lets tests not exit here 
 847 static void SecDbProductionCorruptionExitHandler(void) 
 851 void (*SecDbCorruptionExitHandler
)(void) = SecDbProductionCorruptionExitHandler
; 
 853 void SecDbResetCorruptionExitHandler(void) 
 855     SecDbCorruptionExitHandler 
= SecDbProductionCorruptionExitHandler
; 
 859  There's not much to do in here because we should only ever be here when 
 860  SQLite tells us the DB is corrupt, or the DB is unrecoverable because of 
 861  some fatal logic problem. But we can't shoot it dead either due to client 
 862  connections. So, first we create a marker to tell ourselves things are bad, 
 863  then we'll die. When we come back up we'll notice the marker and remove the DB. 
 865 static bool SecDbHandleCorrupt(SecDbConnectionRef dbconn
, int rc
, CFErrorRef 
*error
) 
 867     if (!dbconn
->db
->allowRepair
) { 
 868         SecCFCreateErrorWithFormat(rc
, kSecErrnoDomain
, NULL
, error
, NULL
, 
 869                                    CFSTR("SecDbHandleCorrupt not allowed to repair, handled error: [%d] %s"), rc
, strerror(rc
)); 
 870         dbconn
->isCorrupted 
= false; 
 874     CFStringPerformWithCString(dbconn
->db
->db_path
, ^(const char *db_path
) { 
 875         char marker
[PATH_MAX
+1]; 
 876         snprintf(marker
, sizeof(marker
), "%s-iscorrupt", db_path
); 
 877         struct stat info 
= {}; 
 878         if (0 == stat(marker
, &info
)) { 
 879             secerror("SecDbHandleCorrupt: Tried to write corruption marker %s but one already exists", marker
); 
 882         FILE* file 
= fopen(marker
, "w"); 
 884             secerror("SecDbHandleCorrupt: Unable (%{darwin.errno}d) to create corruption marker %{public}s", errno
, marker
); 
 890     secwarning("SecDbHandleCorrupt: killing self so that successor might cleanly delete corrupt db"); 
 892     // Call through function pointer so tests can replace it and call a SecKeychainDbReset instead 
 893     SecDbCorruptionExitHandler(); 
 897 static bool SecDbProcessCorruptionMarker(CFStringRef db_path
) { 
 898     __block 
bool ok 
= true; 
 899     CFStringPerformWithCString(db_path
, ^(const char *db_path
) { 
 900         char marker
[PATH_MAX
+1]; 
 901         snprintf(marker
, sizeof(marker
), "%s-iscorrupt", db_path
); 
 902         struct stat info 
= {}; 
 903         int result 
= stat(marker
, &info
); 
 904         if (result 
!= 0 && errno 
== ENOENT
) { 
 906         } else if (result 
!= 0) { 
 907             secerror("SecDbSecDbProcessCorruptionMarker: Unable to check for corruption marker: %{darwin.errno}d", errno
); 
 911         secwarning("SecDbSecDbProcessCorruptionMarker: found corruption marker %s", marker
); 
 912         if (remove(marker
)) { 
 913             secerror("SecDbSecDbProcessCorruptionMarker: Unable (%{darwin.errno}d) to delete corruption marker", errno
); 
 915         } else if (remove(db_path
) && errno 
!= ENOENT
) {    // Not sure how we'd get ENOENT but it would suit us just fine 
 916             secerror("SecDbSecDbProcessCorruptionMarker: Unable (%{darwin.errno}d) to delete db %{public}s", errno
, db_path
); 
 919             secwarning("SecDbSecDbProcessCorruptionMarker: deleted corrupt db %{public}s", db_path
); 
 926 SecDbSetCorruptionReset(SecDbRef db
, void (^corruptionReset
)(void)) 
 928     if (db
->corruptionReset
) { 
 929         Block_release(db
->corruptionReset
); 
 930         db
->corruptionReset 
= NULL
; 
 932     if (corruptionReset
) { 
 933         db
->corruptionReset 
= Block_copy(corruptionReset
); 
 937 static bool SecDbLoggingEnabled(CFStringRef type
) 
 939     CFTypeRef profile 
= NULL
; 
 940     bool enabled 
= false; 
 942     if (csr_check(CSR_ALLOW_APPLE_INTERNAL
) != 0) 
 945     profile 
= (CFNumberRef
)CFPreferencesCopyValue(CFSTR("SQLProfile"), CFSTR("com.apple.security"), kCFPreferencesAnyUser
, kCFPreferencesAnyHost
); 
 950     if (CFGetTypeID(profile
) == CFBooleanGetTypeID()) { 
 951         enabled 
= CFBooleanGetValue((CFBooleanRef
)profile
); 
 952     } else if (CFGetTypeID(profile
) == CFNumberGetTypeID()) { 
 954         CFNumberGetValue(profile
, kCFNumberSInt32Type
, &num
); 
 958     CFReleaseSafe(profile
); 
 964 SecDbProfileMask(void) 
 966     static dispatch_once_t onceToken
; 
 967     static unsigned profile_mask 
= 0; 
 969     // sudo defaults write /Library/Preferences/com.apple.security SQLProfile -bool true 
 970     dispatch_once(&onceToken
, ^{ 
 971         if (SecDbLoggingEnabled(CFSTR("SQLProfile"))) 
 972             profile_mask 
= SQLITE_TRACE_PROFILE
; 
 974         profile_mask 
|= SQLITE_TRACE_STMT
; 
 976         if (SecDbLoggingEnabled(CFSTR("SQLTrace"))) 
 977             profile_mask 
= SQLITE_TRACE_STMT
; 
 979         if (SecDbLoggingEnabled(CFSTR("SQLRow"))) 
 980             profile_mask 
= SQLITE_TRACE_ROW
; 
 981         secinfo("#SecDB", "sqlDb: sql trace mask: 0x%08x", profile_mask
); 
 987 SecDbTraceV2(unsigned mask
, void *ctx
, void *p
, void *x
) { 
 988     SecDbConnectionRef dbconn __unused 
= ctx
; 
 989     const char *trace 
= "unknown"; 
 991     if (mask 
== SQLITE_TRACE_PROFILE
) 
 992         trace 
= sqlite3_sql(p
); 
 993     else if (mask 
== SQLITE_TRACE_STMT
) { 
 994         trace 
= sqlite3_sql(p
); 
 995     } else if (mask 
== SQLITE_TRACE_ROW
) { 
 996         trace 
= sqlite3_expanded_sql(p
); 
1000     secinfo("#SecDB", "#SecDB %{public}s", trace
); 
1006 static bool SecDbOpenHandle(SecDbConnectionRef dbconn
, bool *created
, CFErrorRef 
*error
) 
1008     __block 
bool ok 
= true; 
1010     // This is pretty terrible because now what? We know we have a corrupt DB 
1011     // and now we can't get rid of it. 
1012     if (!SecDbProcessCorruptionMarker(dbconn
->db
->db_path
)) { 
1013         SecCFCreateErrorWithFormat(errno
, kSecErrnoDomain
, NULL
, error
, NULL
, CFSTR("Unable to process corruption marker: %{darwin.errno}d"), errno
); 
1017     CFStringPerformWithCString(dbconn
->db
->db_path
, ^(const char *db_path
) { 
1018         int flags 
= (dbconn
->db
->readWrite
) ? SQLITE_OPEN_READWRITE 
: SQLITE_OPEN_READONLY
; 
1019         ok 
= created 
&& SecDbOpenV2(dbconn
, db_path
, flags
, NULL
); 
1023                 char *tmp 
= dirname((char *)db_path
); 
1025                     mode_t omode 
= dbconn
->db
->mode
; 
1026                     if (omode 
& S_IRUSR
) { omode 
|= S_IXUSR
; } // owner can read 
1027                     if (omode 
& S_IRGRP
) { omode 
|= S_IXGRP
; } // group can read 
1028                     if (omode 
& S_IROTH
) { omode 
|= S_IXOTH
; } // other can read 
1029                     int errnum 
= mkpath_np(tmp
, omode
); 
1030                     if (errnum 
!= 0 && errnum 
!= EEXIST
) { 
1031                         SecCFCreateErrorWithFormat(errnum
, kSecErrnoDomain
, NULL
, error
, NULL
, 
1032                                                    CFSTR("mkpath_np %s: [%d] %s"), tmp
, errnum
, strerror(errnum
)); 
1037             // if the enclosing directory is ok, try to create the database. 
1038             // this forces us to open it read-write, so we'll need to be the owner here. 
1039             ok 
= ok 
&& SecDbOpenV2(dbconn
, db_path
, SQLITE_OPEN_READWRITE 
| SQLITE_OPEN_CREATE
, error
); 
1041                 chmod(db_path
, dbconn
->db
->mode
); // default: 0600 (S_IRUSR | S_IWUSR) 
1048             unsigned mask 
= SecDbProfileMask(); 
1050                 (void)sqlite3_trace_v2(dbconn
->handle
, 
1061 static SecDbConnectionRef
 
1062 SecDbConnectionCreate(SecDbRef db
, bool readOnly
, CFErrorRef 
*error
) 
1064     SecDbConnectionRef dbconn 
= NULL
; 
1066     dbconn 
= CFTypeAllocate(SecDbConnection
, struct __OpaqueSecDbConnection
, kCFAllocatorDefault
); 
1067     require(dbconn 
!= NULL
, done
); 
1070     dbconn
->readOnly 
= readOnly
; 
1071     dbconn
->inTransaction 
= false; 
1072     dbconn
->source 
= kSecDbInvalidTransaction
; 
1073     dbconn
->isCorrupted 
= false; 
1074     dbconn
->maybeCorruptedCode 
= 0; 
1075     dbconn
->hasIOFailure 
= false; 
1076     dbconn
->corruptionError 
= NULL
; 
1077     dbconn
->handle 
= NULL
; 
1078     dbconn
->changes 
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
); 
1084 bool SecDbConnectionIsReadOnly(SecDbConnectionRef dbconn
) { 
1085     return dbconn
->readOnly
; 
1088 static void SecDbConectionSetReadOnly(SecDbConnectionRef dbconn
, bool readOnly
) { 
1089     dbconn
->readOnly 
= readOnly
; 
1092 /* Read only connections go to the end of the queue, writeable connections 
1093  go to the start of the queue. */ 
1094 SecDbConnectionRef 
SecDbConnectionAcquire(SecDbRef db
, bool readOnly
, CFErrorRef 
*error
) { 
1095     SecDbConnectionRef dbconn 
= NULL
; 
1096     SecDbConnectionAcquireRefMigrationSafe(db
, readOnly
, &dbconn
, error
); 
1100 bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db
, bool readOnly
, SecDbConnectionRef
* dbconnRef
, CFErrorRef 
*error
) 
1104     secinfo("dbconn", "acquire %s connection", readOnly 
? "ro" : "rw"); 
1106     dispatch_semaphore_wait(readOnly 
? db
->read_semaphore 
: db
->write_semaphore
, DISPATCH_TIME_FOREVER
); 
1107     __block SecDbConnectionRef dbconn 
= NULL
; 
1108     __block 
bool ok 
= true; 
1109     __block 
bool ranOpenedHandler 
= false; 
1111     bool (^assignDbConn
)(SecDbConnectionRef
) = ^bool(SecDbConnectionRef connection
) { 
1112         dbconn 
= connection
; 
1114             *dbconnRef 
= connection
; 
1117         return dbconn 
!= NULL
; 
1120     dispatch_sync(db
->queue
, ^{ 
1121         if (!db
->didFirstOpen
) { 
1122             bool didCreate 
= false; 
1123             ok 
= assignDbConn(SecDbConnectionCreate(db
, false, error
)); 
1124             CFErrorRef localError 
= NULL
; 
1125             if (ok 
&& !SecDbOpenHandle(dbconn
, &didCreate
, &localError
)) { 
1126                 secerror("Unable to create database: %@", localError
); 
1127                 if (localError 
&& CFEqual(CFErrorGetDomain(localError
), kSecDbErrorDomain
)) { 
1128                     int code 
= (int)CFErrorGetCode(localError
); 
1129                     dbconn
->isCorrupted 
= (SQLITE_CORRUPT 
== code
) || (SQLITE_NOTADB 
== code
); 
1131                 // If the open failure isn't due to corruption, propagate the error. 
1132                 ok 
= dbconn
->isCorrupted
; 
1133                 if (!ok 
&& error 
&& *error 
== NULL
) { 
1134                     *error 
= localError
; 
1138             CFReleaseNull(localError
); 
1141                 db
->didFirstOpen 
= ok 
= SecDbDidCreateFirstConnection(dbconn
, didCreate
, error
); 
1142                 ranOpenedHandler 
= true; 
1145                 CFReleaseNull(dbconn
); 
1147             /* Try to get one from the cache */ 
1148             CFIndex count 
= CFArrayGetCount(db
->connections
); 
1149             while (count 
&& !dbconn
) { 
1150                 CFIndex ix 
= readOnly 
? count 
- 1 : 0; 
1151                 if (assignDbConn((SecDbConnectionRef
)CFArrayGetValueAtIndex(db
->connections
, ix
))) 
1152                     CFRetainSafe(dbconn
); 
1154                     secerror("got NULL dbconn at index: %" PRIdCFIndex 
" skipping", ix
); 
1155                 CFArrayRemoveValueAtIndex(db
->connections
, ix
); 
1161         /* Make sure the connection we found has the right access */ 
1162         if (SecDbConnectionIsReadOnly(dbconn
) != readOnly
) { 
1163             SecDbConectionSetReadOnly(dbconn
, readOnly
); 
1166         /* Nothing found in cache, create a new connection */ 
1167         bool created 
= false; 
1168         if (assignDbConn(SecDbConnectionCreate(db
, readOnly
, error
)) && !SecDbOpenHandle(dbconn
, &created
, error
)) { 
1169             CFReleaseNull(dbconn
); 
1174     if (dbconn 
&& !ranOpenedHandler 
&& dbconn
->db
->opened
) { 
1175         dispatch_sync(db
->queue
, ^{ 
1176             if (dbconn
->db
->callOpenedHandlerForNextConnection
) { 
1177                 dbconn
->db
->callOpenedHandlerForNextConnection 
= false; 
1178                 if (!dbconn
->db
->opened(db
, dbconn
, false, &dbconn
->db
->callOpenedHandlerForNextConnection
, error
)) { 
1179                     if (!dbconn
->isCorrupted 
|| !SecDbHandleCorrupt(dbconn
, 0, error
)) { 
1180                         CFReleaseNull(dbconn
); 
1188         *dbconnRef 
= dbconn
; 
1192         // If acquire fails we need to signal the semaphore again. 
1193         dispatch_semaphore_signal(readOnly 
? db
->read_semaphore 
: db
->write_semaphore
); 
1197     return dbconn 
? true : false; 
1200 void SecDbConnectionRelease(SecDbConnectionRef dbconn
) { 
1202         secerror("called with NULL dbconn"); 
1205     SecDbRef db 
= dbconn
->db
; 
1207     secinfo("dbconn", "release %@", dbconn
); 
1209     dispatch_sync(db
->queue
, ^{ 
1210         bool readOnly 
= SecDbConnectionIsReadOnly(dbconn
); 
1211         if (dbconn
->hasIOFailure
) { 
1212             // Something wrong on the file layer (e.g. revoked file descriptor for networked home) 
1213             // so we don't trust our existing connections anymore. 
1214             CFArrayRemoveAllValues(db
->connections
); 
1216             CFIndex count 
= CFArrayGetCount(db
->connections
); 
1217             // Add back possible writable dbconn to the pool. 
1218             CFArrayInsertValueAtIndex(db
->connections
, readOnly 
? count 
: 0, dbconn
); 
1219             // Remove the last (probably read-only) dbconn from the pool. 
1220             if (count 
>= db
->maxIdleHandles
) { 
1221                 CFArrayRemoveValueAtIndex(db
->connections
, count
); 
1224         // Signal after we have put the connection back in the pool of connections 
1225         dispatch_semaphore_signal(readOnly 
? db
->read_semaphore 
: db
->write_semaphore
); 
1231 void SecDbReleaseAllConnections(SecDbRef db
) { 
1232     // Force all connections to be removed (e.g. file descriptor no longer valid) 
1234         secerror("called with NULL db"); 
1237     dispatch_sync(db
->queue
, ^{ 
1238         CFArrayRemoveAllValues(db
->connections
); 
1239         dispatch_semaphore_signal(db
->write_semaphore
); 
1240         dispatch_semaphore_signal(db
->read_semaphore
); 
1244 // Please make sure you want to do this. Any use of the outstanding connections to this DB will cause a crash. 
1245 void SecDbForceClose(SecDbRef db
) { 
1246     dispatch_sync(db
->queue
, ^{ 
1247         CFArrayForEach(db
->connections
, ^(const void* p
) { 
1248             SecDbConnectionRef connection 
= (SecDbConnectionRef
)p
; 
1250             // this pointer is claimed to be nonretained 
1251             connection
->db 
= NULL
; 
1253             if(connection
->handle
) { 
1254                 sqlite3_close(connection
->handle
); 
1255                 connection
->handle 
= NULL
; 
1258         CFArrayRemoveAllValues(db
->connections
); 
1259         dispatch_semaphore_signal(db
->write_semaphore
); 
1260         dispatch_semaphore_signal(db
->read_semaphore
); 
1264 bool SecDbPerformRead(SecDbRef db
, CFErrorRef 
*error
, void (^perform
)(SecDbConnectionRef dbconn
)) { 
1265     SecDbConnectionRef dbconn 
= SecDbConnectionAcquire(db
, true, error
); 
1266     bool success 
= false; 
1270         SecDbConnectionRelease(dbconn
); 
1275 bool SecDbPerformWrite(SecDbRef db
, CFErrorRef 
*error
, void (^perform
)(SecDbConnectionRef dbconn
)) { 
1277         SecError(errSecNotAvailable
, error
, CFSTR("failed to get a db handle")); 
1280     SecDbConnectionRef dbconn 
= SecDbConnectionAcquire(db
, false, error
); 
1281     bool success 
= false; 
1285         SecDbConnectionRelease(dbconn
); 
1291 SecDbConnectionCopyFormatDescription(CFTypeRef value
, CFDictionaryRef formatOptions
) 
1293     SecDbConnectionRef dbconn 
= (SecDbConnectionRef
)value
; 
1294     return CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("<SecDbConnection %s %s>"), 
1295                                     dbconn
->readOnly 
? "ro" : "rw", dbconn
->handle 
? "open" : "closed"); 
1299 SecDbConnectionDestroy(CFTypeRef value
) 
1301     SecDbConnectionRef dbconn 
= (SecDbConnectionRef
)value
; 
1302     if (dbconn
->handle
) { 
1303         int s3e 
= sqlite3_close(dbconn
->handle
); 
1304         if (s3e 
!= SQLITE_OK
) { 
1305             secerror("failed to close database connection (%d) for %@: %s", s3e
, dbconn
->db
->db_path
, sqlite3_errmsg(dbconn
->handle
)); 
1307         os_assert(s3e 
== SQLITE_OK
); // Crash now or jetsam later 
1310     CFReleaseNull(dbconn
->changes
); 
1311     CFReleaseNull(dbconn
->corruptionError
); 
1315 void SecDbPerformOnCommitQueue(SecDbConnectionRef dbconn
, bool barrier
, dispatch_block_t perform
) { 
1317         dispatch_barrier_sync(dbconn
->db
->commitQueue
, ^{ 
1321         dispatch_sync(dbconn
->db
->commitQueue
, ^{ 
1328 // MARK: Bind helpers 
1330 // Logging binds is very spammy when debug logging is on (~90% of log lines), and isn't often useful. 
1331 // Enable this in your local build if you actually want every single SQL variable bind logged for debugging. 
1332 #define LOG_SECDB_BINDS 0 
1334 bool SecDbBindBlob(sqlite3_stmt 
*stmt
, int param
, const void *zData
, size_t n
, void(*xDel
)(void*), CFErrorRef 
*error
) { 
1336         return SecDbErrorWithStmt(SQLITE_TOOBIG
, stmt
, error
, 
1337                                   CFSTR("bind_blob[%d]: blob bigger than INT_MAX"), param
); 
1339     bool ok 
= SecDbErrorWithStmt(sqlite3_bind_blob(stmt
, param
, zData
, (int)n
, xDel
), 
1340                                  stmt
, error
, CFSTR("bind_blob[%d]"), param
); 
1342     secinfo("bind", "bind_blob[%d]: %.*P: %@", param
, (int)n
, zData
, error 
? *error 
: NULL
); 
1347 bool SecDbBindText(sqlite3_stmt 
*stmt
, int param
, const char *zData
, size_t n
, void(*xDel
)(void*), CFErrorRef 
*error
) { 
1349         return SecDbErrorWithStmt(SQLITE_TOOBIG
, stmt
, error
, 
1350                                   CFSTR("bind_text[%d]: text bigger than INT_MAX"), param
); 
1352     bool ok 
= SecDbErrorWithStmt(sqlite3_bind_text(stmt
, param
, zData
, (int)n
, xDel
), stmt
, error
, 
1353                                  CFSTR("bind_text[%d]"), param
); 
1355     secinfo("bind", "bind_text[%d]: \"%s\" error: %@", param
, zData
, error 
? *error 
: NULL
); 
1360 bool SecDbBindDouble(sqlite3_stmt 
*stmt
, int param
, double value
, CFErrorRef 
*error
) { 
1361     bool ok 
= SecDbErrorWithStmt(sqlite3_bind_double(stmt
, param
, value
), stmt
, error
, 
1362                                  CFSTR("bind_double[%d]"), param
); 
1364     secinfo("bind", "bind_double[%d]: %f error: %@", param
, value
, error 
? *error 
: NULL
); 
1369 bool SecDbBindInt(sqlite3_stmt 
*stmt
, int param
, int value
, CFErrorRef 
*error
) { 
1370     bool ok 
= SecDbErrorWithStmt(sqlite3_bind_int(stmt
, param
, value
), stmt
, error
, 
1371                                  CFSTR("bind_int[%d]"), param
); 
1373     secinfo("bind", "bind_int[%d]: %d error: %@", param
, value
, error 
? *error 
: NULL
); 
1378 bool SecDbBindInt64(sqlite3_stmt 
*stmt
, int param
, sqlite3_int64 value
, CFErrorRef 
*error
) { 
1379     bool ok 
= SecDbErrorWithStmt(sqlite3_bind_int64(stmt
, param
, value
), stmt
, error
, 
1380                                  CFSTR("bind_int64[%d]"), param
); 
1382     secinfo("bind", "bind_int64[%d]: %lld error: %@", param
, value
, error 
? *error 
: NULL
); 
1388 /* AUDIT[securityd](done): 
1389  value (ok) is a caller provided, non NULL CFTypeRef. 
1391 bool SecDbBindObject(sqlite3_stmt 
*stmt
, int param
, CFTypeRef value
, CFErrorRef 
*error
) { 
1393     __block 
bool result 
= false; 
1395         /* TODO: Can we use SQLITE_STATIC below everwhere we currently use 
1396      SQLITE_TRANSIENT since we finalize the statement before the value 
1397      goes out of scope? */ 
1398     if (!value 
|| (valueId 
= CFGetTypeID(value
)) == CFNullGetTypeID()) { 
1399         /* Skip bindings for NULL values.  sqlite3 will interpret unbound 
1400          params as NULL which is exactly what we want. */ 
1402     } else if (valueId 
== CFStringGetTypeID()) { 
1403         CFStringPerformWithCStringAndLength(value
, ^(const char *cstr
, size_t clen
) { 
1404             result 
= SecDbBindText(stmt
, param
, cstr
, clen
, SQLITE_TRANSIENT
, error
); 
1406     } else if (valueId 
== CFDataGetTypeID()) { 
1407         CFIndex len 
= CFDataGetLength(value
); 
1409             result 
= SecDbBindBlob(stmt
, param
, CFDataGetBytePtr(value
), 
1410                                    len
, SQLITE_TRANSIENT
, error
); 
1412             result 
= SecDbBindText(stmt
, param
, "", 0, SQLITE_TRANSIENT
, error
); 
1414     } else if (valueId 
== CFDateGetTypeID()) { 
1415         CFAbsoluteTime abs_time 
= CFDateGetAbsoluteTime(value
); 
1416         result 
= SecDbBindDouble(stmt
, param
, abs_time
, error
); 
1417     } else if (valueId 
== CFBooleanGetTypeID()) { 
1418         int bval 
= CFBooleanGetValue(value
); 
1419         result 
= SecDbBindInt(stmt
, param
, bval
, error
); 
1420     } else if (valueId 
== CFNumberGetTypeID()) { 
1422         if (CFNumberIsFloatType(value
)) { 
1424             convertOk 
= CFNumberGetValue(value
, kCFNumberDoubleType
, &nval
); 
1425             result 
= SecDbBindDouble(stmt
, param
, nval
, error
); 
1427             sqlite_int64 nval64
; 
1428             convertOk 
= CFNumberGetValue(value
, kCFNumberSInt64Type
, &nval64
); 
1430                 result 
= SecDbBindInt64(stmt
, param
, nval64
, error
); 
1434             result 
= SecDbError(SQLITE_INTERNAL
, error
, CFSTR("bind CFNumberGetValue failed for %@"), value
); 
1438             CFStringRef valueDesc 
= CFCopyTypeIDDescription(valueId
); 
1439             SecDbError(SQLITE_MISMATCH
, error
, CFSTR("bind unsupported type %@"), valueDesc
); 
1440             CFReleaseSafe(valueDesc
); 
1448 // MARK: SecDbStatementRef 
1450 bool SecDbReset(sqlite3_stmt 
*stmt
, CFErrorRef 
*error
) { 
1451     return SecDbErrorWithStmt(sqlite3_reset(stmt
), stmt
, error
, CFSTR("reset")); 
1454 bool SecDbClearBindings(sqlite3_stmt 
*stmt
, CFErrorRef 
*error
) { 
1455     return SecDbErrorWithStmt(sqlite3_clear_bindings(stmt
), stmt
, error
, CFSTR("clear bindings")); 
1458 bool SecDbFinalize(sqlite3_stmt 
*stmt
, CFErrorRef 
*error
) { 
1459     sqlite3 
*handle 
= sqlite3_db_handle(stmt
); 
1460     int s3e 
= sqlite3_finalize(stmt
); 
1461     return s3e 
== SQLITE_OK 
? true : SecDbErrorWithDb(s3e
, handle
, error
, CFSTR("finalize: %p"), stmt
); 
1464 sqlite3_stmt 
*SecDbPrepareV2(SecDbConnectionRef dbconn
, const char *sql
, size_t sqlLen
, const char **sqlTail
, CFErrorRef 
*error
) { 
1465     sqlite3 
*db 
= SecDbHandle(dbconn
); 
1466     if (sqlLen 
> INT_MAX
) { 
1467         SecDbErrorWithDb(SQLITE_TOOBIG
, db
, error
, CFSTR("prepare_v2: sql bigger than INT_MAX")); 
1472         sqlite3_stmt 
*stmt 
= NULL
; 
1473         int s3e 
= sqlite3_prepare_v2(db
, sql
, (int)sqlLen
, &stmt
, sqlTail
); 
1474         if (s3e 
== SQLITE_OK
) 
1476         else if (!SecDbWaitIfNeeded(dbconn
, s3e
, NULL
, CFSTR("preparev2"), ntries
, error
)) 
1482 static sqlite3_stmt 
*SecDbCopyStatementWithTailRange(SecDbConnectionRef dbconn
, CFStringRef sql
, CFRange 
*sqlTail
, CFErrorRef 
*error
) { 
1483     __block sqlite3_stmt 
*stmt 
= NULL
; 
1484     if (sql
) CFStringPerformWithCStringAndLength(sql
, ^(const char *sqlStr
, size_t sqlLen
) { 
1485         const char *tail 
= NULL
; 
1486         stmt 
= SecDbPrepareV2(dbconn
, sqlStr
, sqlLen
, &tail
, error
); 
1487         if (sqlTail 
&& sqlStr 
< tail 
&& tail 
< sqlStr 
+ sqlLen
) { 
1488             sqlTail
->location 
= tail 
- sqlStr
; 
1489             sqlTail
->length 
= sqlLen 
- sqlTail
->location
; 
1496 sqlite3_stmt 
*SecDbCopyStmt(SecDbConnectionRef dbconn
, CFStringRef sql
, CFStringRef 
*tail
, CFErrorRef 
*error
) { 
1497     // TODO: Add caching and cache lookup of statements 
1498     CFRange sqlTail 
= {}; 
1499     sqlite3_stmt 
*stmt 
= SecDbCopyStatementWithTailRange(dbconn
, sql
, &sqlTail
, error
); 
1500     if (sqlTail
.length 
> 0) { 
1501         CFStringRef excess 
= CFStringCreateWithSubstring(CFGetAllocator(sql
), sql
, sqlTail
); 
1505             SecDbError(SQLITE_INTERNAL
, error
, 
1506                        CFSTR("prepare_v2: %@ unused sql: %@"), 
1508             CFReleaseSafe(excess
); 
1509             SecDbFinalize(stmt
, error
); 
1517  TODO: Could do a hack here with a custom kCFAllocatorNULL allocator for a second CFRuntimeBase inside a SecDbStatement, 
1518  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. */ 
1519 bool SecDbReleaseCachedStmt(SecDbConnectionRef dbconn
, CFStringRef sql
, sqlite3_stmt 
*stmt
, CFErrorRef 
*error
) { 
1521         return SecDbFinalize(stmt
, error
); 
1526 bool SecDbPrepare(SecDbConnectionRef dbconn
, CFStringRef sql
, CFErrorRef 
*error
, void(^exec
)(sqlite3_stmt 
*stmt
)) { 
1527     assert(sql 
!= NULL
); 
1528     sqlite3_stmt 
*stmt 
= SecDbCopyStmt(dbconn
, sql
, NULL
, error
); 
1533     return SecDbReleaseCachedStmt(dbconn
, sql
, stmt
, error
); 
1536 bool SecDbWithSQL(SecDbConnectionRef dbconn
, CFStringRef sql
, CFErrorRef 
*error
, bool(^perform
)(sqlite3_stmt 
*stmt
)) { 
1540         CFStringRef tail 
= NULL
; 
1542             sqlite3_stmt 
*stmt 
= SecDbCopyStmt(dbconn
, sql
, &tail
, error
); 
1548                     // TODO: Use a different error scope here. 
1549                     ok 
= SecError(-50 /* errSecParam */, error
, CFSTR("SecDbWithSQL perform block missing")); 
1551                 ok 
&= SecDbReleaseCachedStmt(dbconn
, sql
, stmt
, error
); 
1554             // TODO We already have an error here we really just want the left over sql in it's userData 
1555             ok 
= SecDbError(SQLITE_ERROR
, error
, CFSTR("Error with unexecuted sql remaining %@"), sql
); 
1563 /* SecDbForEach returns true if all SQLITE_ROW returns of sqlite3_step() return true from the row block. 
1564  If the row block returns false and doesn't set an error (to indicate it has reached a limit), 
1565  this entire function returns false. In that case no error will be set. */ 
1566 bool SecDbForEach(SecDbConnectionRef dbconn
, sqlite3_stmt 
*stmt
, CFErrorRef 
*error
, bool(^row
)(int row_index
)) { 
1567     bool result 
= false; 
1568     for (int row_ix 
= 0;;++row_ix
) { 
1569         if (SecDbConnectionIsReadOnly(dbconn
) && !sqlite3_stmt_readonly(stmt
)) { 
1570             secerror("SecDbForEach: SecDbConnection is readonly but we're about to write: %s", sqlite3_sql(stmt
)); 
1572         int s3e 
= sqlite3_step(stmt
); 
1573         if (s3e 
== SQLITE_ROW
) { 
1579                 // If we have no row block then getting SQLITE_ROW is an error 
1580                 SecDbError(s3e
, error
, 
1581                            CFSTR("step[%d]: %s returned SQLITE_ROW with NULL row block"), 
1582                            row_ix
, sqlite3_sql(stmt
)); 
1585             if (s3e 
== SQLITE_DONE
) { 
1588                 SecDbConnectionCheckCode(dbconn
, s3e
, error
, CFSTR("SecDbForEach step[%d]"), row_ix
); 
1596 void SecDbRecordChange(SecDbConnectionRef dbconn
, CFTypeRef deleted
, CFTypeRef inserted
) { 
1597     if (!dbconn
->db
->notifyPhase
) return; 
1598     CFTypeRef entry 
= SecDbEventCreateWithComponents(deleted
, inserted
); 
1600         CFArrayAppendValue(dbconn
->changes
, entry
); 
1603         if (!dbconn
->inTransaction
) { 
1604             secerror("db %@ changed outside txn", dbconn
); 
1605             // Only notify of DidCommit, since WillCommit code assumes 
1607             SecDbOnNotify(dbconn
, ^{ 
1608                 SecDbNotifyPhase(dbconn
, kSecDbTransactionDidCommit
); 
1615 CFGiblisFor(SecDbConnection
) 
1618 // SecDbEvent Creation and consumption 
1621 static SecDbEventRef 
SecDbEventCreateInsert(CFTypeRef inserted
) { 
1622     return CFRetainSafe(inserted
); 
1625 static SecDbEventRef 
SecDbEventCreateDelete(CFTypeRef deleted
) { 
1626     return CFArrayCreate(kCFAllocatorDefault
, &deleted
, 1, &kCFTypeArrayCallBacks
); 
1629 static SecDbEventRef 
SecDbEventCreateUpdate(CFTypeRef deleted
, CFTypeRef inserted
) { 
1630     const void *values
[2] = { deleted
, inserted 
}; 
1631     return CFArrayCreate(kCFAllocatorDefault
, values
, 2, &kCFTypeArrayCallBacks
); 
1634 SecDbEventRef 
SecDbEventCreateWithComponents(CFTypeRef deleted
, CFTypeRef inserted
) { 
1635     if (deleted 
&& inserted
) 
1636         return SecDbEventCreateUpdate(deleted
, inserted
); 
1638         return SecDbEventCreateDelete(deleted
); 
1640         return SecDbEventCreateInsert(inserted
); 
1645 void SecDbEventTranslateComponents(SecDbEventRef item
, CFTypeRef
* deleted
, CFTypeRef
* inserted
) { 
1646     if(CFGetTypeID(item
) == CFArrayGetTypeID()) { 
1647         // One item: deletion. Two: update. 
1648         CFIndex arraySize 
= CFArrayGetCount(item
); 
1649         if(arraySize 
== 1) { 
1650             if(deleted
) { *deleted 
= CFArrayGetValueAtIndex(item
, 0); } 
1651             if(inserted
) { *inserted 
= NULL
; } 
1652         } else if(arraySize 
== 2) { 
1653             if(deleted
) { *deleted 
= CFArrayGetValueAtIndex(item
, 0); } 
1654             if(inserted
) { *inserted 
= CFArrayGetValueAtIndex(item
, 1); } 
1656             if(deleted
) { *deleted 
= NULL
; } 
1657             if(inserted
) { *inserted 
= NULL
; } 
1660         if(deleted
) { *deleted 
= NULL
; } 
1661         if(inserted
) { *inserted 
= item
; } 
1666 bool SecDbEventGetComponents(SecDbEventRef event
, CFTypeRef 
*deleted
, CFTypeRef 
*inserted
, CFErrorRef 
*error
) { 
1667     if (isArray(event
)) { 
1668         CFArrayRef array 
= event
; 
1669         switch (CFArrayGetCount(array
)) { 
1671                 *deleted 
= CFArrayGetValueAtIndex(array
, 0); 
1672                 *inserted 
= CFArrayGetValueAtIndex(array
, 1); 
1675                 *deleted 
= CFArrayGetValueAtIndex(array
, 0); 
1679                 SecError(errSecParam
, error
, NULL
, CFSTR("invalid entry in changes array: %@"), array
);