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.
5 #include "chrome/browser/mac/security_wrappers.h"
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/mac_logging.h"
11 OSStatus
SecTrustedApplicationCopyRequirement(
12 SecTrustedApplicationRef application
,
13 SecRequirementRef
* requirement
);
18 ScopedSecKeychainSetUserInteractionAllowed::
19 ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed
) {
20 OSStatus status
= SecKeychainGetUserInteractionAllowed(&old_allowed_
);
21 if (status
!= errSecSuccess
) {
22 OSSTATUS_LOG(ERROR
, status
);
26 status
= SecKeychainSetUserInteractionAllowed(allowed
);
27 if (status
!= errSecSuccess
) {
28 OSSTATUS_LOG(ERROR
, status
);
32 ScopedSecKeychainSetUserInteractionAllowed::
33 ~ScopedSecKeychainSetUserInteractionAllowed() {
34 OSStatus status
= SecKeychainSetUserInteractionAllowed(old_allowed_
);
35 if (status
!= errSecSuccess
) {
36 OSSTATUS_LOG(ERROR
, status
);
40 CrSKeychainItemAndAccess::CrSKeychainItemAndAccess(SecKeychainItemRef item
,
44 // These CFRetain calls aren't leaks. They're balanced by an implicit
45 // CFRelease at destruction because the fields are of type ScopedCFTypeRef.
46 // These fields are retained on construction (unlike the typical
47 // ScopedCFTypeRef pattern) because this class is intended for use as an STL
48 // type adapter to keep two related objects together, and thus must
49 // implement proper reference counting in the methods required for STL
50 // container use. This class and is not intended to act as a scoper for the
51 // underlying objects in user code. For that, just use ScopedCFTypeRef.
56 CrSKeychainItemAndAccess::CrSKeychainItemAndAccess(
57 const CrSKeychainItemAndAccess
& that
)
58 : item_(that
.item_
.get()),
59 access_(that
.access_
.get()) {
60 // See the comment above in the two-argument constructor.
65 CrSKeychainItemAndAccess::~CrSKeychainItemAndAccess() {
68 void CrSKeychainItemAndAccess::operator=(const CrSKeychainItemAndAccess
& that
) {
69 // See the comment above in the two-argument constructor.
71 item_
.reset(that
.item_
);
73 CFRetain(that
.access_
);
74 access_
.reset(that
.access_
);
77 CrSACLSimpleContents::CrSACLSimpleContents() {
80 CrSACLSimpleContents::~CrSACLSimpleContents() {
83 ScopedSecKeychainAttributeInfo::ScopedSecKeychainAttributeInfo(
84 SecKeychainAttributeInfo
* attribute_info
)
85 : attribute_info_(attribute_info
) {
88 ScopedSecKeychainAttributeInfo::~ScopedSecKeychainAttributeInfo() {
89 OSStatus status
= SecKeychainFreeAttributeInfo(attribute_info_
);
90 if (status
!= errSecSuccess
) {
91 OSSTATUS_LOG(ERROR
, status
);
95 ScopedCrSKeychainItemAttributesAndData::ScopedCrSKeychainItemAttributesAndData(
96 CrSKeychainItemAttributesAndData
* attributes_and_data
)
97 : attributes_and_data_(attributes_and_data
) {
100 ScopedCrSKeychainItemAttributesAndData::
101 ~ScopedCrSKeychainItemAttributesAndData() {
102 if (attributes_and_data_
.get()) {
103 CrSKeychainItemFreeAttributesAndData(
104 attributes_and_data_
->attribute_list
, attributes_and_data_
->data
);
108 SecKeychainSearchRef
CrSKeychainSearchCreateFromAttributes(
109 CFTypeRef keychain_or_array
,
110 SecItemClass item_class
,
111 const SecKeychainAttributeList
* attribute_list
) {
112 SecKeychainSearchRef search
;
113 OSStatus status
= SecKeychainSearchCreateFromAttributes(keychain_or_array
,
117 if (status
!= errSecSuccess
) {
118 OSSTATUS_LOG(ERROR
, status
);
125 SecKeychainItemRef
CrSKeychainSearchCopyNext(SecKeychainSearchRef search
) {
130 SecKeychainItemRef item
;
131 OSStatus status
= SecKeychainSearchCopyNext(search
, &item
);
132 if (status
!= errSecSuccess
) {
133 if (status
!= errSecItemNotFound
) {
134 OSSTATUS_LOG(ERROR
, status
);
142 void CrSKeychainItemFreeAttributesAndData(
143 SecKeychainAttributeList
* attribute_list
,
145 OSStatus status
= SecKeychainItemFreeAttributesAndData(attribute_list
, data
);
146 if (status
!= errSecSuccess
) {
147 OSSTATUS_LOG(ERROR
, status
);
151 bool CrSKeychainItemTestAccess(SecKeychainItemRef item
) {
154 OSStatus status
= SecKeychainItemCopyAttributesAndData(item
,
160 if (status
!= errSecSuccess
) {
161 if (status
!= errSecAuthFailed
) {
162 OSSTATUS_LOG(ERROR
, status
);
167 CrSKeychainItemFreeAttributesAndData(NULL
, data
);
172 SecAccessRef
CrSKeychainItemCopyAccess(SecKeychainItemRef item
) {
174 OSStatus status
= SecKeychainItemCopyAccess(item
, &access
);
175 if (status
!= errSecSuccess
) {
176 if (status
!= errSecNoAccessForItem
&& status
!= errSecAuthFailed
) {
177 OSSTATUS_LOG(ERROR
, status
);
185 CFArrayRef
CrSAccessCopyACLList(SecAccessRef access
) {
191 OSStatus status
= SecAccessCopyACLList(access
, &acl_list
);
192 if (status
!= errSecSuccess
) {
193 OSSTATUS_LOG(ERROR
, status
);
200 CrSACLSimpleContents
* CrSACLCopySimpleContents(SecACLRef acl
) {
205 scoped_ptr
<CrSACLSimpleContents
> acl_simple_contents(
206 new CrSACLSimpleContents());
207 CFArrayRef application_list
;
208 CFStringRef description
;
210 SecACLCopySimpleContents(acl
,
213 &acl_simple_contents
->prompt_selector
);
214 if (status
!= errSecSuccess
) {
215 if (status
!= errSecACLNotSimple
) {
216 OSSTATUS_LOG(ERROR
, status
);
221 acl_simple_contents
->application_list
.reset(application_list
);
222 acl_simple_contents
->description
.reset(description
);
224 return acl_simple_contents
.release();
227 SecRequirementRef
CrSTrustedApplicationCopyRequirement(
228 SecTrustedApplicationRef application
) {
233 SecRequirementRef requirement
;
234 OSStatus status
= SecTrustedApplicationCopyRequirement(application
,
236 if (status
!= errSecSuccess
) {
237 OSSTATUS_LOG(ERROR
, status
);
244 CFStringRef
CrSRequirementCopyString(SecRequirementRef requirement
,
250 CFStringRef requirement_string
;
251 OSStatus status
= SecRequirementCopyString(requirement
,
253 &requirement_string
);
254 if (status
!= errSecSuccess
) {
255 OSSTATUS_LOG(ERROR
, status
);
259 return requirement_string
;
262 SecTrustedApplicationRef
CrSTrustedApplicationCreateFromPath(const char* path
) {
263 SecTrustedApplicationRef application
;
264 OSStatus status
= SecTrustedApplicationCreateFromPath(path
, &application
);
265 if (status
!= errSecSuccess
) {
266 OSSTATUS_LOG(ERROR
, status
);
273 bool CrSACLSetSimpleContents(SecACLRef acl
,
274 const CrSACLSimpleContents
& acl_simple_contents
) {
276 SecACLSetSimpleContents(acl
,
277 acl_simple_contents
.application_list
,
278 acl_simple_contents
.description
,
279 &acl_simple_contents
.prompt_selector
);
280 if (status
!= errSecSuccess
) {
281 OSSTATUS_LOG(ERROR
, status
);
288 SecKeychainRef
CrSKeychainItemCopyKeychain(SecKeychainItemRef item
) {
289 SecKeychainRef keychain
;
290 OSStatus status
= SecKeychainItemCopyKeychain(item
, &keychain
);
291 if (status
!= errSecSuccess
) {
292 OSSTATUS_LOG(ERROR
, status
);
299 SecKeychainAttributeInfo
* CrSKeychainAttributeInfoForItemID(
300 SecKeychainRef keychain
,
302 SecKeychainAttributeInfo
* attribute_info
;
303 OSStatus status
= SecKeychainAttributeInfoForItemID(keychain
,
306 if (status
!= errSecSuccess
) {
307 OSSTATUS_LOG(ERROR
, status
);
311 return attribute_info
;
314 CrSKeychainItemAttributesAndData
* CrSKeychainItemCopyAttributesAndData(
315 SecKeychainRef keychain
,
316 SecKeychainItemRef item
) {
317 ScopedCrSKeychainItemAttributesAndData
attributes_and_data(
318 new CrSKeychainItemAttributesAndData());
320 SecKeychainItemCopyAttributesAndData(item
,
322 attributes_and_data
.item_class_ptr(),
326 if (status
!= errSecSuccess
) {
327 OSSTATUS_LOG(ERROR
, status
);
331 // This looks really weird, but it's right. See 10.7.3
332 // libsecurity_keychain-55044 lib/SecItem.cpp
333 // _CreateAttributesDictionaryFromKeyItem and 10.7.3 SecurityTool-55002
334 // keychain_utilities.c print_keychain_item_attributes.
336 switch (attributes_and_data
.item_class()) {
337 case kSecInternetPasswordItemClass
:
338 item_id
= CSSM_DL_DB_RECORD_INTERNET_PASSWORD
;
340 case kSecGenericPasswordItemClass
:
341 item_id
= CSSM_DL_DB_RECORD_GENERIC_PASSWORD
;
343 // kSecInternetPasswordItemClass is marked as deprecated in the 10.9 sdk,
344 // but the files in libsecurity_keychain from 10.7 referenced above still
345 // use it. Also see rdar://14281375 /
346 // http://openradar.appspot.com/radar?id=3143412 .
347 #pragma clang diagnostic push
348 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
349 case kSecAppleSharePasswordItemClass
:
350 #pragma clang diagnostic pop
351 item_id
= CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD
;
354 item_id
= attributes_and_data
.item_class();
358 ScopedSecKeychainAttributeInfo
attribute_info(
359 CrSKeychainAttributeInfoForItemID(keychain
, item_id
));
360 if (!attribute_info
) {
364 status
= SecKeychainItemCopyAttributesAndData(
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
);
376 return attributes_and_data
.release();
379 bool CrSKeychainItemDelete(SecKeychainItemRef item
) {
380 OSStatus status
= SecKeychainItemDelete(item
);
381 if (status
!= errSecSuccess
) {
382 OSSTATUS_LOG(ERROR
, status
);
389 SecKeychainItemRef
CrSKeychainItemCreateFromContent(
390 const CrSKeychainItemAttributesAndData
& attributes_and_data
,
391 SecKeychainRef keychain
,
392 SecAccessRef access
) {
393 SecKeychainItemRef item
;
395 SecKeychainItemCreateFromContent(attributes_and_data
.item_class
,
396 attributes_and_data
.attribute_list
,
397 attributes_and_data
.length
,
398 attributes_and_data
.data
,
402 if (status
!= errSecSuccess
) {
403 OSSTATUS_LOG(ERROR
, status
);
410 } // namespace chrome