]>
Commit | Line | Data |
---|---|---|
e3d460c9 A |
1 | /* |
2 | * Copyright (c) 2015 Apple Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | #include "CSPDLTransaction.h" | |
25 | #include <Security/SecBasePriv.h> | |
26 | #include <syslog.h> | |
27 | ||
866f8763 A |
28 | #if TARGET_OS_OSX |
29 | ||
e3d460c9 A |
30 | DLTransaction::DLTransaction(CSSM_DL_DB_HANDLE dldbh) |
31 | : mDldbh(dldbh), mSuccess(false), mFinalized(false), mAutoCommit(CSSM_TRUE) { | |
32 | initialize(); | |
33 | } | |
34 | ||
35 | DLTransaction::DLTransaction() | |
36 | : mSuccess(false), mFinalized(false), mAutoCommit(CSSM_TRUE) { | |
37 | } | |
38 | ||
39 | void DLTransaction::initialize() { | |
40 | // Turn off autocommit on the underlying DL and remember the old state. | |
41 | Security::CssmClient::ObjectImpl::check(CSSM_DL_PassThrough(mDldbh, | |
42 | CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
43 | NULL, reinterpret_cast<void **>(&mAutoCommit))); | |
44 | } | |
45 | ||
46 | DLTransaction::~DLTransaction() { | |
47 | finalize(); | |
48 | } | |
49 | ||
fa7225c8 A |
50 | void DLTransaction::commit() { |
51 | // Commit the transaction, and throw if it fails | |
52 | ||
53 | // If autocommit wasn't on on the database when we started, don't | |
54 | // actually commit. There might be something else going on... | |
55 | if(mAutoCommit) { | |
56 | Security::CssmClient::ObjectImpl::check(CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); | |
57 | CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, reinterpret_cast<const void *>(mAutoCommit), NULL); | |
58 | } | |
59 | ||
60 | // Throwing above means this wasn't a success and we're not finalized. On exit, we'll roll back the transaction. | |
e3d460c9 | 61 | mSuccess = true; |
fa7225c8 A |
62 | mFinalized = true; |
63 | } | |
64 | ||
65 | void DLTransaction::rollback() { | |
66 | // If autocommit wasn't on on the database when we started, don't | |
67 | // actually roll back. There might be something else going on... | |
68 | if(mAutoCommit) { | |
69 | CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); | |
70 | CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
71 | reinterpret_cast<const void *>(mAutoCommit), NULL); | |
72 | } | |
e3d460c9 A |
73 | } |
74 | ||
75 | void DLTransaction::finalize() { | |
76 | if(mFinalized) { | |
77 | return; | |
78 | } | |
79 | ||
fa7225c8 A |
80 | // if this transaction was not a success, roll back. |
81 | if(!mSuccess) { | |
82 | // Note that we're likely (but not necessarily) unwinding the stack for an exception right now. | |
83 | // (If this transaction succeeded, we wouldn't be here. So, it failed, and this code likes to fail with exceptions.) | |
84 | // If this throws an exception, we might crash the whole process. | |
85 | // Swallow exceptions whole, but log them aggressively. | |
86 | try { | |
87 | rollback(); | |
88 | } catch(CssmError cssme) { | |
89 | const char* errStr = cssmErrorString(cssme.error); | |
90 | secnotice("integrity", "caught CssmError during transaction rollback: %d %s", (int) cssme.error, errStr); | |
91 | syslog(LOG_ERR, "ERROR: failed to rollback keychain transaction: %d %s", (int) cssme.error, errStr); | |
e3d460c9 A |
92 | } |
93 | } | |
94 | mFinalized = true; | |
95 | } | |
96 | ||
97 | ||
98 | CSPDLTransaction::CSPDLTransaction(Security::CssmClient::Db& db) | |
99 | : DLTransaction(), mDb(db) { | |
100 | // Get the handle of the DL underlying this CSPDL. | |
101 | mDb->passThrough(CSSM_APPLECSPDL_DB_GET_HANDLE, NULL, | |
102 | reinterpret_cast<void **>(&mDldbh)); | |
103 | ||
104 | initialize(); | |
105 | } | |
106 | ||
107 | CSPDLTransaction::~CSPDLTransaction() { | |
e3d460c9 A |
108 | } |
109 | ||
866f8763 | 110 | #endif //TARGET_OS_OSX |