]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_plugin/lib/Database.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_plugin / lib / Database.cpp
1 /*
2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 #ifdef __MWERKS__
20 #define _CPP_DATABASE
21 #endif
22 #include <security_cdsa_plugin/Database.h>
23 #include <Security/cssmerr.h>
24 #include <security_cdsa_plugin/DbContext.h>
25 #include <memory>
26
27 DatabaseManager::DatabaseManager ()
28 {
29 }
30
31 DatabaseManager::~DatabaseManager ()
32 {
33 }
34
35 Database *
36 DatabaseManager::get (const DbName &inDbName)
37 {
38 StLock<Mutex> _(mDatabaseMapLock);
39 DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName);
40 if (anIterator == mDatabaseMap.end())
41 {
42 unique_ptr<Database> aDatabase(make(inDbName));
43 mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get()));
44 return aDatabase.release();
45 }
46
47 return anIterator->second;
48 }
49
50 void
51 DatabaseManager::removeIfUnused(Database &inDatabase)
52 {
53 StLock<Mutex> _(mDatabaseMapLock);
54 if (!inDatabase.hasDbContexts()) {
55 mDatabaseMap.erase(inDatabase.mDbName);
56 delete &inDatabase;
57 }
58 }
59
60 DbContext &
61 DatabaseManager::dbOpen(DatabaseSession &inDatabaseSession,
62 const DbName &inDbName,
63 CSSM_DB_ACCESS_TYPE inAccessRequest,
64 const AccessCredentials *inAccessCred,
65 const void *inOpenParameters)
66 {
67 Database &aDatabase = *get(inDbName);
68 try
69 {
70 return aDatabase._dbOpen(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters);
71 }
72 catch (...)
73 {
74 removeIfUnused(aDatabase);
75 throw;
76 }
77 }
78
79 DbContext &
80 DatabaseManager::dbCreate(DatabaseSession &inDatabaseSession,
81 const DbName &inDbName,
82 const CSSM_DBINFO &inDBInfo,
83 CSSM_DB_ACCESS_TYPE inAccessRequest,
84 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
85 const void *inOpenParameters)
86 {
87 Database &aDatabase = *get(inDbName);
88 try
89 {
90 return aDatabase._dbCreate(inDatabaseSession, inDBInfo, inAccessRequest,
91 inCredAndAclEntry, inOpenParameters);
92 }
93 catch (...)
94 {
95 removeIfUnused(aDatabase);
96 throw;
97 }
98 }
99
100 // Delete a DbContext instance created by calling dbOpen or dbCreate.
101 void
102 DatabaseManager::dbClose(DbContext &inDbContext)
103 {
104 Database &aDatabase = inDbContext.mDatabase;
105 aDatabase._dbClose(inDbContext);
106 removeIfUnused(aDatabase);
107 }
108
109 // Delete a database.
110 void
111 DatabaseManager::dbDelete(DatabaseSession &inDatabaseSession,
112 const DbName &inDbName,
113 const AccessCredentials *inAccessCred)
114 {
115 Database &aDatabase = *get(inDbName);
116 try
117 {
118 aDatabase.dbDelete(inDatabaseSession, inAccessCred);
119 }
120 catch (...)
121 {
122 removeIfUnused(aDatabase);
123 throw;
124 }
125
126 removeIfUnused(aDatabase);
127 }
128
129 // List all available databases.
130 CSSM_NAME_LIST_PTR
131 DatabaseManager::getDbNames(DatabaseSession &inDatabaseSession)
132 {
133 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
134 }
135
136 void
137 DatabaseManager::freeNameList(DatabaseSession &inDatabaseSession,
138 CSSM_NAME_LIST &inNameList)
139 {
140 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
141 }
142
143 // Start of Database implementation.
144
145 Database::Database (const DbName &inDbName)
146 : mDbName(inDbName)
147 {
148 }
149
150 Database::~Database ()
151 {
152 }
153
154 bool
155 Database::hasDbContexts()
156 {
157 StLock<Mutex> _(mDbContextSetLock);
158 return !mDbContextSet.empty();
159 }
160
161 DbContext &
162 Database::_dbOpen(DatabaseSession &inDatabaseSession,
163 CSSM_DB_ACCESS_TYPE inAccessRequest,
164 const AccessCredentials *inAccessCred,
165 const void *inOpenParameters)
166 {
167 unique_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
168 inAccessRequest,
169 inAccessCred,
170 inOpenParameters));
171 {
172 StLock<Mutex> _(mDbContextSetLock);
173 mDbContextSet.insert(aDbContext.get());
174 // Release the mDbContextSetLock
175 }
176
177 try
178 {
179 dbOpen(*aDbContext);
180 }
181 catch (...)
182 {
183 StLock<Mutex> _(mDbContextSetLock);
184 mDbContextSet.erase(aDbContext.get());
185 throw;
186 }
187
188 return *aDbContext.release();
189 }
190
191 DbContext &
192 Database::_dbCreate(DatabaseSession &inDatabaseSession,
193 const CSSM_DBINFO &inDBInfo,
194 CSSM_DB_ACCESS_TYPE inAccessRequest,
195 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
196 const void *inOpenParameters)
197 {
198 unique_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
199 inAccessRequest,
200 (inCredAndAclEntry
201 ? AccessCredentials::optional(inCredAndAclEntry->AccessCred)
202 : NULL),
203 inOpenParameters));
204 {
205 StLock<Mutex> _(mDbContextSetLock);
206 mDbContextSet.insert(aDbContext.get());
207 // Release the mDbContextSetLock
208 }
209
210 try
211 {
212 dbCreate(*aDbContext, inDBInfo,
213 inCredAndAclEntry ? &inCredAndAclEntry->InitialAclEntry : NULL);
214 }
215 catch (...)
216 {
217 StLock<Mutex> _(mDbContextSetLock);
218 mDbContextSet.erase(aDbContext.get());
219 throw;
220 }
221
222 return *aDbContext.release();
223 }
224
225 void
226 Database::_dbClose(DbContext &dbContext)
227 {
228 StLock<Mutex> _(mDbContextSetLock);
229 mDbContextSet.erase(&dbContext);
230 if (mDbContextSet.empty())
231 dbClose();
232 }