Chromium Code Reviews| Index: chrome/browser/mac/security_wrappers.cc |
| =================================================================== |
| --- chrome/browser/mac/security_wrappers.cc (revision 0) |
| +++ chrome/browser/mac/security_wrappers.cc (revision 0) |
| @@ -0,0 +1,416 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/mac/security_wrappers.h" |
| + |
| +#include "base/mac/foundation_util.h" |
| +#include "base/mac/mac_logging.h" |
| + |
| +#if !defined(MAC_OS_X_VERSION_10_5) || \ |
| + MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 |
| + |
| +enum { |
| + // New Security.framework code uses errSecSuccess instead of noErr, but the |
| + // constant is new in 10.6. |
| + errSecSuccess = 0 |
| +}; |
| + |
| +// This exists on 10.5 for linking, but but because |
| +// <Security/SecRequirement.h> did not ship in the SDK in that version, no |
| +// declaration is present. This declaration is correct on 10.5, see |
| +// 10.5.0 libsecurity_codesigning-32568/lib/SecRequirement.h. |
| +extern "C" { |
| +OSStatus SecRequirementCopyString(SecRequirementRef requirement, |
| + SecCSFlags flags, |
| + CFStringRef* text); |
| +} // extern "C" |
| + |
| +#endif |
| + |
| +extern "C" { |
| +OSStatus SecTrustedApplicationCopyRequirement( |
| + SecTrustedApplicationRef application, |
| + SecRequirementRef* requirement); |
| +} // extern "C" |
| + |
| +namespace chrome { |
| +namespace browser { |
| +namespace mac { |
| + |
| +ScopedSecKeychainSetUserInteractionAllowed:: |
| + ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed) { |
| + OSStatus status = SecKeychainGetUserInteractionAllowed(&old_allowed_); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainGetUserInteractionAllowed"; |
|
stuartmorgan
2012/05/10 06:50:54
I thought having static strings on non-debug LOG s
|
| + old_allowed_ = TRUE; |
| + } |
| + |
| + status = SecKeychainSetUserInteractionAllowed(allowed); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainSetUserInteractionAllowed"; |
| + } |
| +} |
| + |
| +ScopedSecKeychainSetUserInteractionAllowed:: |
| + ~ScopedSecKeychainSetUserInteractionAllowed() { |
| + OSStatus status = SecKeychainSetUserInteractionAllowed(old_allowed_); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainSetUserInteractionAllowed"; |
| + } |
| +} |
| + |
| +CrSKeychainItemAndAccess::CrSKeychainItemAndAccess(SecKeychainItemRef item, |
| + SecAccessRef access) |
| + : item_(item), |
| + access_(access) { |
| + CFRetain(item_); |
|
stuartmorgan
2012/05/10 06:50:54
Can you at least comment this pattern? I had to go
|
| + CFRetain(access_); |
| +} |
| + |
| +CrSKeychainItemAndAccess::CrSKeychainItemAndAccess( |
| + const CrSKeychainItemAndAccess& that) |
| + : item_(that.item_.get()), |
| + access_(that.access_.get()) { |
| + CFRetain(item_); |
| + CFRetain(access_); |
| +} |
| + |
| +CrSKeychainItemAndAccess::~CrSKeychainItemAndAccess() { |
| +} |
| + |
| +void CrSKeychainItemAndAccess::operator=(const CrSKeychainItemAndAccess& that) { |
| + CFRetain(that.item_); |
| + item_.reset(that.item_); |
| + |
| + CFRetain(that.access_); |
| + access_.reset(that.access_); |
| +} |
| + |
| +CrSACLSimpleContents::CrSACLSimpleContents() { |
| +} |
| + |
| +CrSACLSimpleContents::~CrSACLSimpleContents() { |
| +} |
| + |
| +ScopedSecKeychainAttributeInfo::ScopedSecKeychainAttributeInfo( |
| + SecKeychainAttributeInfo* attribute_info) |
| + : attribute_info_(attribute_info) { |
| +} |
| + |
| +ScopedSecKeychainAttributeInfo::~ScopedSecKeychainAttributeInfo() { |
| + OSStatus status = SecKeychainFreeAttributeInfo(attribute_info_); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainFreeAttributeInfo"; |
| + } |
| +} |
| + |
| +ScopedCrSKeychainItemAttributesAndData::ScopedCrSKeychainItemAttributesAndData( |
| + CrSKeychainItemAttributesAndData* attributes_and_data) |
| + : attributes_and_data_(attributes_and_data) { |
| +} |
| + |
| +ScopedCrSKeychainItemAttributesAndData:: |
| + ~ScopedCrSKeychainItemAttributesAndData() { |
| + if (attributes_and_data_.get()) { |
| + CrSKeychainItemFreeAttributesAndData( |
| + attributes_and_data_->attribute_list, attributes_and_data_->data); |
| + } |
| +} |
| + |
| +SecKeychainSearchRef CrSKeychainSearchCreateFromAttributes( |
| + CFTypeRef keychain_or_array, |
| + SecItemClass item_class, |
| + const SecKeychainAttributeList* attribute_list) { |
| + SecKeychainSearchRef search; |
| + OSStatus status = SecKeychainSearchCreateFromAttributes(keychain_or_array, |
| + item_class, |
| + attribute_list, |
| + &search); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainSearchCreateFromAttributes"; |
| + return NULL; |
| + } |
| + |
| + return search; |
| +} |
| + |
| +SecKeychainItemRef CrSKeychainSearchCopyNext(SecKeychainSearchRef search) { |
| + if (!search) { |
| + return NULL; |
| + } |
| + |
| + SecKeychainItemRef item; |
| + OSStatus status = SecKeychainSearchCopyNext(search, &item); |
| + if (status != errSecSuccess) { |
| + if (status != errSecItemNotFound) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainSearchCopyNext"; |
| + } |
| + return NULL; |
| + } |
| + |
| + return item; |
| +} |
| + |
| +void CrSKeychainItemFreeAttributesAndData( |
| + SecKeychainAttributeList* attribute_list, |
| + void* data) { |
| + OSStatus status = SecKeychainItemFreeAttributesAndData(attribute_list, data); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemFreeAttributesAndData"; |
| + } |
| +} |
| + |
| +bool CrSKeychainItemTestAccess(SecKeychainItemRef item) { |
| + UInt32 length; |
| + void* data; |
| + OSStatus status = SecKeychainItemCopyAttributesAndData(item, |
| + NULL, |
| + NULL, |
| + NULL, |
| + &length, |
| + &data); |
| + if (status != errSecSuccess) { |
| + if (status != errSecAuthFailed) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; |
| + } |
| + return false; |
| + } |
| + |
| + CrSKeychainItemFreeAttributesAndData(NULL, data); |
| + |
| + return true; |
| +} |
| + |
| +SecAccessRef CrSKeychainItemCopyAccess(SecKeychainItemRef item) { |
| + SecAccessRef access; |
| + OSStatus status = SecKeychainItemCopyAccess(item, &access); |
| + if (status != errSecSuccess) { |
| + if (status != errSecNoAccessForItem) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAccess"; |
| + } |
| + return NULL; |
| + } |
| + |
| + return access; |
| +} |
| + |
| +CFArrayRef CrSAccessCopyACLList(SecAccessRef access) { |
| + if (!access) { |
| + return NULL; |
| + } |
| + |
| + CFArrayRef acl_list; |
| + OSStatus status = SecAccessCopyACLList(access, &acl_list); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecAccessCopyACLList"; |
| + return NULL; |
| + } |
| + |
| + return acl_list; |
| +} |
| + |
| +CrSACLSimpleContents* CrSACLCopySimpleContents(SecACLRef acl) { |
| + if (!acl) { |
| + return NULL; |
| + } |
| + |
| + scoped_ptr<CrSACLSimpleContents> acl_simple_contents( |
| + new CrSACLSimpleContents()); |
| + CFArrayRef application_list; |
| + CFStringRef description; |
| + OSStatus status = |
| + SecACLCopySimpleContents(acl, |
| + &application_list, |
| + &description, |
| + &acl_simple_contents->prompt_selector); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecACLCopySimpleContents"; |
| + return NULL; |
| + } |
| + |
| + acl_simple_contents->application_list.reset(application_list); |
| + acl_simple_contents->description.reset(description); |
| + |
| + return acl_simple_contents.release(); |
| +} |
| + |
| +SecRequirementRef CrSTrustedApplicationCopyRequirement( |
| + SecTrustedApplicationRef application) { |
| + if (!application) { |
| + return NULL; |
| + } |
| + |
| + SecRequirementRef requirement; |
| + OSStatus status = SecTrustedApplicationCopyRequirement(application, |
| + &requirement); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecTrustedApplicationCopyRequirement"; |
| + return NULL; |
| + } |
| + |
| + return requirement; |
| +} |
| + |
| +CFStringRef CrSRequirementCopyString(SecRequirementRef requirement, |
| + SecCSFlags flags) { |
| + if (!requirement) { |
| + return NULL; |
| + } |
| + |
| + CFStringRef requirement_string; |
| + OSStatus status = SecRequirementCopyString(requirement, |
| + flags, |
| + &requirement_string); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecRequirementCopyString"; |
| + return NULL; |
| + } |
| + |
| + return requirement_string; |
| +} |
| + |
| +SecTrustedApplicationRef CrSTrustedApplicationCreateFromPath(const char* path) { |
| + SecTrustedApplicationRef application; |
| + OSStatus status = SecTrustedApplicationCreateFromPath(path, &application); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecTrustedApplicationCreateFromPath"; |
| + return NULL; |
| + } |
| + |
| + return application; |
| +} |
| + |
| +bool CrSACLSetSimpleContents(SecACLRef acl, |
| + const CrSACLSimpleContents& acl_simple_contents) { |
| + OSStatus status = |
| + SecACLSetSimpleContents(acl, |
| + acl_simple_contents.application_list, |
| + acl_simple_contents.description, |
| + &acl_simple_contents.prompt_selector); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecACLSetSimpleContents"; |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +SecKeychainRef CrSKeychainItemCopyKeychain(SecKeychainItemRef item) { |
| + SecKeychainRef keychain; |
| + OSStatus status = SecKeychainItemCopyKeychain(item, &keychain); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyKeychain"; |
| + return NULL; |
| + } |
| + |
| + return keychain; |
| +} |
| + |
| +SecKeychainAttributeInfo* CrSKeychainAttributeInfoForItemID( |
| + SecKeychainRef keychain, |
| + UInt32 item_id) { |
| + SecKeychainAttributeInfo* attribute_info; |
| + OSStatus status = SecKeychainAttributeInfoForItemID(keychain, |
| + item_id, |
| + &attribute_info); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainAttributeInfoForItemID"; |
| + return NULL; |
| + } |
| + |
| + return attribute_info; |
| +} |
| + |
| +CrSKeychainItemAttributesAndData* CrSKeychainItemCopyAttributesAndData( |
| + SecKeychainRef keychain, |
| + SecKeychainItemRef item) { |
| + ScopedCrSKeychainItemAttributesAndData attributes_and_data( |
| + new CrSKeychainItemAttributesAndData()); |
| + OSStatus status = |
| + SecKeychainItemCopyAttributesAndData(item, |
| + NULL, |
| + attributes_and_data.item_class_ptr(), |
| + NULL, |
| + NULL, |
| + NULL); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; |
| + return NULL; |
| + } |
| + |
| + // This looks really weird, but it's right. See 10.7.3 |
| + // libsecurity_keychain-55044 lib/SecItem.cpp |
| + // _CreateAttributesDictionaryFromKeyItem and 10.7.3 SecurityTool-55002 |
| + // keychain_utilities.c print_keychain_item_attributes. |
| + UInt32 item_id; |
| + switch (attributes_and_data.item_class()) { |
| + case kSecInternetPasswordItemClass: |
| + item_id = CSSM_DL_DB_RECORD_INTERNET_PASSWORD; |
| + break; |
| + case kSecGenericPasswordItemClass: |
| + item_id = CSSM_DL_DB_RECORD_GENERIC_PASSWORD; |
| + break; |
| + case kSecAppleSharePasswordItemClass: |
| + item_id = CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD; |
| + break; |
| + default: |
| + item_id = attributes_and_data.item_class(); |
| + break; |
| + } |
| + |
| + ScopedSecKeychainAttributeInfo attribute_info( |
| + CrSKeychainAttributeInfoForItemID(keychain, item_id)); |
| + if (!attribute_info) { |
| + return NULL; |
| + } |
| + |
| + status = SecKeychainItemCopyAttributesAndData( |
| + item, |
| + attribute_info, |
| + attributes_and_data.item_class_ptr(), |
| + attributes_and_data.attribute_list_ptr(), |
| + attributes_and_data.length_ptr(), |
| + attributes_and_data.data_ptr()); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCopyAttributesAndData"; |
| + return NULL; |
| + } |
| + |
| + return attributes_and_data.release(); |
| +} |
| + |
| +bool CrSKeychainItemDelete(SecKeychainItemRef item) { |
| + OSStatus status = SecKeychainItemDelete(item); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemDelete"; |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +SecKeychainItemRef CrSKeychainItemCreateFromContent( |
| + const CrSKeychainItemAttributesAndData& attributes_and_data, |
| + SecKeychainRef keychain, |
| + SecAccessRef access) { |
| + SecKeychainItemRef item; |
| + OSStatus status = |
| + SecKeychainItemCreateFromContent(attributes_and_data.item_class, |
| + attributes_and_data.attribute_list, |
| + attributes_and_data.length, |
| + attributes_and_data.data, |
| + keychain, |
| + access, |
| + &item); |
| + if (status != errSecSuccess) { |
| + OSSTATUS_LOG(ERROR, status) << "SecKeychainItemCreateFromContent"; |
| + return NULL; |
| + } |
| + |
| + return item; |
| +} |
| + |
| +} // namespace mac |
| +} // namespace browser |
| +} // namespace chrome |