OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/mac/security_wrappers.h" | |
6 | |
7 #include "base/mac/foundation_util.h" | |
8 #include "base/mac/mac_logging.h" | |
9 | |
10 #if !defined(MAC_OS_X_VERSION_10_5) || \ | |
11 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 | |
12 | |
13 enum { | |
14 // New Security.framework code uses errSecSuccess instead of noErr, but the | |
15 // constant is new in 10.6. | |
16 errSecSuccess = 0 | |
17 }; | |
18 | |
19 // This exists on 10.5 for linking, but but because | |
20 // <Security/SecRequirement.h> did not ship in the SDK in that version, no | |
21 // declaration is present. This declaration is correct on 10.5, see | |
22 // 10.5.0 libsecurity_codesigning-32568/lib/SecRequirement.h. | |
23 extern "C" { | |
24 OSStatus SecRequirementCopyString(SecRequirementRef requirement, | |
25 SecCSFlags flags, | |
26 CFStringRef* text); | |
27 } // extern "C" | |
28 | |
29 #endif | |
30 | |
31 extern "C" { | |
32 OSStatus SecTrustedApplicationCopyRequirement( | |
33 SecTrustedApplicationRef application, | |
34 SecRequirementRef* requirement); | |
35 } // extern "C" | |
36 | |
37 namespace chrome { | |
38 namespace browser { | |
39 namespace mac { | |
40 | |
41 ScopedSecKeychainSetUserInteractionAllowed:: | |
42 ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed) { | |
43 OSStatus status = SecKeychainGetUserInteractionAllowed(&old_allowed_); | |
44 if (status != errSecSuccess) { | |
45 OSSTATUS_LOG(ERROR, status) << "SecKeychainGetUserInteractionAllowed"; | |
46 old_allowed_ = TRUE; | |
47 } | |
48 | |
49 status = SecKeychainSetUserInteractionAllowed(allowed); | |
50 if (status != errSecSuccess) { | |
51 OSSTATUS_LOG(ERROR, status) << "SecKeychainSetUserInteractionAllowed"; | |
52 } | |
53 } | |
54 | |
55 ScopedSecKeychainSetUserInteractionAllowed:: | |
56 ~ScopedSecKeychainSetUserInteractionAllowed() { | |
57 OSStatus status = SecKeychainSetUserInteractionAllowed(old_allowed_); | |
58 if (status != errSecSuccess) { | |
59 OSSTATUS_LOG(ERROR, status) << "SecKeychainSetUserInteractionAllowed"; | |
60 } | |
61 } | |
62 | |
63 CrSKeychainItemAndAccess::CrSKeychainItemAndAccess(SecKeychainItemRef item, | |
64 SecAccessRef access) | |
65 : item_(item), | |
Nico
2012/05/08 18:46:25
nit: item_(CFRetain(item)) might be a bit more rea
Mark Mentovai
2012/05/08 20:34:49
Nico wrote:
| |
66 access_(access) { | |
67 CFRetain(item_); | |
68 CFRetain(access_); | |
69 } | |
70 | |
71 CrSKeychainItemAndAccess::CrSKeychainItemAndAccess( | |
72 const CrSKeychainItemAndAccess& that) | |
73 : item_(that.item_.get()), | |
74 access_(that.access_.get()) { | |
75 CFRetain(item_); | |
76 CFRetain(access_); | |
77 } | |
78 | |
79 CrSKeychainItemAndAccess::~CrSKeychainItemAndAccess() { | |
80 } | |
81 | |
82 void CrSKeychainItemAndAccess::operator=(const CrSKeychainItemAndAccess& that) { | |
83 CFRetain(that.item_); | |
84 item_.reset(that.item_); | |
85 | |
86 CFRetain(that.access_); | |
87 access_.reset(that.access_); | |
88 } | |
89 | |
90 CrSACLSimpleContents::CrSACLSimpleContents() { | |
91 } | |
92 | |
93 CrSACLSimpleContents::~CrSACLSimpleContents() { | |
94 } | |
95 | |
96 ScopedSecKeychainAttributeInfo::ScopedSecKeychainAttributeInfo( | |
97 SecKeychainAttributeInfo* attribute_info) | |
98 : attribute_info_(attribute_info) { | |
99 } | |
100 | |
101 ScopedSecKeychainAttributeInfo::~ScopedSecKeychainAttributeInfo() { | |
102 OSStatus status = SecKeychainFreeAttributeInfo(attribute_info_); | |
103 if (status != errSecSuccess) { | |
104 OSSTATUS_LOG(ERROR, status) << "SecKeychainFreeAttributeInfo"; | |
105 } | |
106 } | |
107 | |
108 ScopedCrSKeychainItemAttributesAndData::ScopedCrSKeychainItemAttributesAndData( | |
109 CrSKeychainItemAttributesAndData* attributes_and_data) | |
110 : attributes_and_data_(attributes_and_data) { | |
111 } | |
112 | |
113 ScopedCrSKeychainItemAttributesAndData:: | |
114 ~ScopedCrSKeychainItemAttributesAndData() { | |
115 if (attributes_and_data_.get()) { | |
116 CrSKeychainItemFreeAttributesAndData( | |
117 attributes_and_data_->attribute_list, attributes_and_data_->data); | |
118 } | |
119 } | |
120 | |
121 SecKeychainSearchRef CrSKeychainSearchCreateFromAttributes( | |
122 CFTypeRef keychain_or_array, | |
123 SecItemClass item_class, | |
124 const SecKeychainAttributeList* attribute_list) { | |
125 SecKeychainSearchRef search; | |
126 OSStatus status = SecKeychainSearchCreateFromAttributes(keychain_or_array, | |
127 item_class, | |
128 attribute_list, | |
129 &search); | |
130 if (status != errSecSuccess) { | |
131 OSSTATUS_LOG(ERROR, status) << "SecKeychainSearchCreateFromAttributes"; | |
132 return NULL; | |
133 } | |
134 | |
135 return search; | |
136 } | |
137 | |
138 SecKeychainItemRef CrSKeychainSearchCopyNext(SecKeychainSearchRef search) { | |
139 if (!search) { | |
140 return NULL; | |
141 } | |
142 | |
143 SecKeychainItemRef item; | |
144 OSStatus status = SecKeychainSearchCopyNext(search, &item); | |
145 if (status != errSecSuccess) { | |
146 if (status != errSecItemNotFound) { | |
147 OSSTATUS_LOG(ERROR, status) << "SecKeychainSearchCopyNext"; | |
148 } | |
149 return NULL; | |
150 } | |
151 | |
152 return item; | |
153 } | |
154 | |
155 void CrSKeychainItemFreeAttributesAndData( | |
156 SecKeychainAttributeList* attribute_list, | |
157 void* data) { | |
158 OSStatus status = SecKeychainItemFreeAttributesAndData(attribute_list, data); | |
159 if (status != errSecSuccess) { | |
160 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemFreeAttributesAndData"; | |
161 } | |
162 } | |
163 | |
164 bool CrSKeychainItemTestAccess(SecKeychainItemRef item) { | |
165 UInt32 length; | |
166 void* data; | |
167 OSStatus status = SecKeychainItemCopyAttributesAndData(item, | |
168 NULL, | |
169 NULL, | |
170 NULL, | |
171 &length, | |
172 &data); | |
173 if (status != errSecSuccess) { | |
174 if (status != errSecAuthFailed) { | |
175 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; | |
176 } | |
177 return false; | |
178 } | |
179 | |
180 CrSKeychainItemFreeAttributesAndData(NULL, data); | |
181 | |
182 return true; | |
183 } | |
184 | |
185 SecAccessRef CrSKeychainItemCopyAccess(SecKeychainItemRef item) { | |
186 SecAccessRef access; | |
187 OSStatus status = SecKeychainItemCopyAccess(item, &access); | |
188 if (status != errSecSuccess) { | |
189 if (status != errSecNoAccessForItem) { | |
190 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAccess"; | |
191 } | |
192 return NULL; | |
193 } | |
194 | |
195 return access; | |
196 } | |
197 | |
198 CFArrayRef CrSAccessCopyACLList(SecAccessRef access) { | |
199 if (!access) { | |
200 return NULL; | |
201 } | |
202 | |
203 CFArrayRef acl_list; | |
204 OSStatus status = SecAccessCopyACLList(access, &acl_list); | |
205 if (status != errSecSuccess) { | |
206 OSSTATUS_LOG(ERROR, status) << "SecAccessCopyACLList"; | |
207 return NULL; | |
208 } | |
209 | |
210 return acl_list; | |
211 } | |
212 | |
213 CrSACLSimpleContents* CrSACLCopySimpleContents(SecACLRef acl) { | |
214 if (!acl) { | |
215 return NULL; | |
216 } | |
217 | |
218 scoped_ptr<CrSACLSimpleContents> acl_simple_contents( | |
219 new CrSACLSimpleContents()); | |
220 CFArrayRef application_list; | |
221 CFStringRef description; | |
222 OSStatus status = | |
223 SecACLCopySimpleContents(acl, | |
224 &application_list, | |
225 &description, | |
226 &acl_simple_contents->prompt_selector); | |
227 if (status != errSecSuccess) { | |
228 OSSTATUS_LOG(ERROR, status) << "SecACLCopySimpleContents"; | |
229 return NULL; | |
230 } | |
231 | |
232 acl_simple_contents->application_list.reset(application_list); | |
233 acl_simple_contents->description.reset(description); | |
234 | |
235 return acl_simple_contents.release(); | |
236 } | |
237 | |
238 SecRequirementRef CrSTrustedApplicationCopyRequirement( | |
239 SecTrustedApplicationRef application) { | |
240 if (!application) { | |
241 return NULL; | |
242 } | |
243 | |
244 SecRequirementRef requirement; | |
245 OSStatus status = SecTrustedApplicationCopyRequirement(application, | |
246 &requirement); | |
247 if (status != errSecSuccess) { | |
248 OSSTATUS_LOG(ERROR, status) << "SecTrustedApplicationCopyRequirement"; | |
249 return NULL; | |
250 } | |
251 | |
252 return requirement; | |
253 } | |
254 | |
255 CFStringRef CrSRequirementCopyString(SecRequirementRef requirement, | |
256 SecCSFlags flags) { | |
257 if (!requirement) { | |
258 return NULL; | |
259 } | |
260 | |
261 CFStringRef requirement_string; | |
262 OSStatus status = SecRequirementCopyString(requirement, | |
263 flags, | |
264 &requirement_string); | |
265 if (status != errSecSuccess) { | |
266 OSSTATUS_LOG(ERROR, status) << "SecRequirementCopyString"; | |
267 return NULL; | |
268 } | |
269 | |
270 return requirement_string; | |
271 } | |
272 | |
273 SecTrustedApplicationRef CrSTrustedApplicationCreateFromPath(const char* path) { | |
274 SecTrustedApplicationRef application; | |
275 OSStatus status = SecTrustedApplicationCreateFromPath(path, &application); | |
276 if (status != errSecSuccess) { | |
277 OSSTATUS_LOG(ERROR, status) << "SecTrustedApplicationCreateFromPath"; | |
278 return NULL; | |
279 } | |
280 | |
281 return application; | |
282 } | |
283 | |
284 bool CrSACLSetSimpleContents(SecACLRef acl, | |
285 const CrSACLSimpleContents& acl_simple_contents) { | |
286 OSStatus status = | |
287 SecACLSetSimpleContents(acl, | |
288 acl_simple_contents.application_list, | |
289 acl_simple_contents.description, | |
290 &acl_simple_contents.prompt_selector); | |
291 if (status != errSecSuccess) { | |
292 OSSTATUS_LOG(ERROR, status) << "SecACLSetSimpleContents"; | |
293 return false; | |
294 } | |
295 | |
296 return true; | |
297 } | |
298 | |
299 SecKeychainRef CrSKeychainItemCopyKeychain(SecKeychainItemRef item) { | |
300 SecKeychainRef keychain; | |
301 OSStatus status = SecKeychainItemCopyKeychain(item, &keychain); | |
302 if (status != errSecSuccess) { | |
303 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyKeychain"; | |
304 return NULL; | |
305 } | |
306 | |
307 return keychain; | |
308 } | |
309 | |
310 SecKeychainAttributeInfo* CrSKeychainAttributeInfoForItemID( | |
311 SecKeychainRef keychain, | |
312 UInt32 item_id) { | |
313 SecKeychainAttributeInfo* attribute_info; | |
314 OSStatus status = SecKeychainAttributeInfoForItemID(keychain, | |
315 item_id, | |
316 &attribute_info); | |
317 if (status != errSecSuccess) { | |
318 OSSTATUS_LOG(ERROR, status) << "SecKeychainAttributeInfoForItemID"; | |
319 return NULL; | |
320 } | |
321 | |
322 return attribute_info; | |
323 } | |
324 | |
325 CrSKeychainItemAttributesAndData* CrSKeychainItemCopyAttributesAndData( | |
326 SecKeychainRef keychain, | |
327 SecKeychainItemRef item) { | |
328 ScopedCrSKeychainItemAttributesAndData attributes_and_data( | |
329 new CrSKeychainItemAttributesAndData()); | |
330 OSStatus status = | |
331 SecKeychainItemCopyAttributesAndData(item, | |
332 NULL, | |
333 attributes_and_data.item_class_ptr(), | |
334 NULL, | |
335 NULL, | |
336 NULL); | |
337 if (status != errSecSuccess) { | |
338 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; | |
339 return NULL; | |
340 } | |
341 | |
342 UInt32 item_id; | |
343 switch (attributes_and_data.item_class()) { | |
344 case kSecInternetPasswordItemClass: | |
345 item_id = CSSM_DL_DB_RECORD_INTERNET_PASSWORD; | |
346 break; | |
347 case kSecGenericPasswordItemClass: | |
348 item_id = CSSM_DL_DB_RECORD_GENERIC_PASSWORD; | |
349 break; | |
350 case kSecAppleSharePasswordItemClass: | |
351 item_id = CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD; | |
352 break; | |
353 default: | |
354 item_id = attributes_and_data.item_class(); | |
Nico
2012/05/08 18:46:25
I thought this looked suspicious, but apple's keyc
Mark Mentovai
2012/05/08 20:34:49
Nico wrote:
| |
355 break; | |
356 } | |
357 | |
358 ScopedSecKeychainAttributeInfo attribute_info( | |
359 CrSKeychainAttributeInfoForItemID(keychain, item_id)); | |
360 if (!attribute_info) { | |
361 return NULL; | |
362 } | |
363 | |
364 status = SecKeychainItemCopyAttributesAndData( | |
365 item, | |
366 attribute_info, | |
367 attributes_and_data.item_class_ptr(), | |
368 attributes_and_data.attribute_list_ptr(), | |
369 attributes_and_data.length_ptr(), | |
370 attributes_and_data.data_ptr()); | |
371 if (status != errSecSuccess) { | |
372 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; | |
373 return NULL; | |
374 } | |
375 | |
376 return attributes_and_data.release(); | |
377 } | |
378 | |
379 bool CrSKeychainItemDelete(SecKeychainItemRef item) { | |
380 OSStatus status = SecKeychainItemDelete(item); | |
381 if (status != errSecSuccess) { | |
382 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemDelete"; | |
383 return false; | |
384 } | |
385 | |
386 return true; | |
387 } | |
388 | |
389 SecKeychainItemRef CrSKeychainItemCreateFromContent( | |
390 const CrSKeychainItemAttributesAndData& attributes_and_data, | |
391 SecKeychainRef keychain, | |
392 SecAccessRef access) { | |
393 SecKeychainItemRef item; | |
394 OSStatus status = | |
395 SecKeychainItemCreateFromContent(attributes_and_data.item_class, | |
396 attributes_and_data.attribute_list, | |
397 attributes_and_data.length, | |
398 attributes_and_data.data, | |
399 keychain, | |
400 access, | |
401 &item); | |
402 if (status != errSecSuccess) { | |
403 OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCreateFromContent"; | |
404 return NULL; | |
405 } | |
406 | |
407 return item; | |
408 } | |
409 | |
410 } // namespace mac | |
411 } // namespace browser | |
412 } // namespace chrome | |
OLD | NEW |