| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/mac/security_wrappers.h" | 5 #include "chrome/browser/mac/security_wrappers.h" |
| 6 | 6 |
| 7 #include "base/mac/foundation_util.h" | 7 #include <Security/Security.h> |
| 8 |
| 8 #include "base/mac/mac_logging.h" | 9 #include "base/mac/mac_logging.h" |
| 9 | 10 |
| 10 extern "C" { | |
| 11 OSStatus SecTrustedApplicationCopyRequirement( | |
| 12 SecTrustedApplicationRef application, | |
| 13 SecRequirementRef* requirement); | |
| 14 } // extern "C" | |
| 15 | |
| 16 namespace chrome { | 11 namespace chrome { |
| 17 | 12 |
| 18 ScopedSecKeychainSetUserInteractionAllowed:: | 13 ScopedSecKeychainSetUserInteractionAllowed:: |
| 19 ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed) { | 14 ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed) { |
| 20 OSStatus status = SecKeychainGetUserInteractionAllowed(&old_allowed_); | 15 OSStatus status = SecKeychainGetUserInteractionAllowed(&old_allowed_); |
| 21 if (status != errSecSuccess) { | 16 if (status != errSecSuccess) { |
| 22 OSSTATUS_LOG(ERROR, status); | 17 OSSTATUS_LOG(ERROR, status); |
| 23 old_allowed_ = TRUE; | 18 old_allowed_ = TRUE; |
| 24 } | 19 } |
| 25 | 20 |
| 26 status = SecKeychainSetUserInteractionAllowed(allowed); | 21 status = SecKeychainSetUserInteractionAllowed(allowed); |
| 27 if (status != errSecSuccess) { | 22 if (status != errSecSuccess) { |
| 28 OSSTATUS_LOG(ERROR, status); | 23 OSSTATUS_LOG(ERROR, status); |
| 29 } | 24 } |
| 30 } | 25 } |
| 31 | 26 |
| 32 ScopedSecKeychainSetUserInteractionAllowed:: | 27 ScopedSecKeychainSetUserInteractionAllowed:: |
| 33 ~ScopedSecKeychainSetUserInteractionAllowed() { | 28 ~ScopedSecKeychainSetUserInteractionAllowed() { |
| 34 OSStatus status = SecKeychainSetUserInteractionAllowed(old_allowed_); | 29 OSStatus status = SecKeychainSetUserInteractionAllowed(old_allowed_); |
| 35 if (status != errSecSuccess) { | 30 if (status != errSecSuccess) { |
| 36 OSSTATUS_LOG(ERROR, status); | 31 OSSTATUS_LOG(ERROR, status); |
| 37 } | 32 } |
| 38 } | 33 } |
| 39 | 34 |
| 40 CrSKeychainItemAndAccess::CrSKeychainItemAndAccess(SecKeychainItemRef item, | |
| 41 SecAccessRef access) | |
| 42 : item_(item), | |
| 43 access_(access) { | |
| 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. | |
| 52 CFRetain(item_); | |
| 53 CFRetain(access_); | |
| 54 } | |
| 55 | |
| 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. | |
| 61 CFRetain(item_); | |
| 62 CFRetain(access_); | |
| 63 } | |
| 64 | |
| 65 CrSKeychainItemAndAccess::~CrSKeychainItemAndAccess() { | |
| 66 } | |
| 67 | |
| 68 void CrSKeychainItemAndAccess::operator=(const CrSKeychainItemAndAccess& that) { | |
| 69 // See the comment above in the two-argument constructor. | |
| 70 CFRetain(that.item_); | |
| 71 item_.reset(that.item_); | |
| 72 | |
| 73 CFRetain(that.access_); | |
| 74 access_.reset(that.access_); | |
| 75 } | |
| 76 | |
| 77 CrSACLSimpleContents::CrSACLSimpleContents() { | |
| 78 } | |
| 79 | |
| 80 CrSACLSimpleContents::~CrSACLSimpleContents() { | |
| 81 } | |
| 82 | |
| 83 ScopedSecKeychainAttributeInfo::ScopedSecKeychainAttributeInfo( | |
| 84 SecKeychainAttributeInfo* attribute_info) | |
| 85 : attribute_info_(attribute_info) { | |
| 86 } | |
| 87 | |
| 88 ScopedSecKeychainAttributeInfo::~ScopedSecKeychainAttributeInfo() { | |
| 89 OSStatus status = SecKeychainFreeAttributeInfo(attribute_info_); | |
| 90 if (status != errSecSuccess) { | |
| 91 OSSTATUS_LOG(ERROR, status); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 ScopedCrSKeychainItemAttributesAndData::ScopedCrSKeychainItemAttributesAndData( | |
| 96 CrSKeychainItemAttributesAndData* attributes_and_data) | |
| 97 : attributes_and_data_(attributes_and_data) { | |
| 98 } | |
| 99 | |
| 100 ScopedCrSKeychainItemAttributesAndData:: | |
| 101 ~ScopedCrSKeychainItemAttributesAndData() { | |
| 102 if (attributes_and_data_.get()) { | |
| 103 CrSKeychainItemFreeAttributesAndData( | |
| 104 attributes_and_data_->attribute_list, attributes_and_data_->data); | |
| 105 } | |
| 106 } | |
| 107 | |
| 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, | |
| 114 item_class, | |
| 115 attribute_list, | |
| 116 &search); | |
| 117 if (status != errSecSuccess) { | |
| 118 OSSTATUS_LOG(ERROR, status); | |
| 119 return NULL; | |
| 120 } | |
| 121 | |
| 122 return search; | |
| 123 } | |
| 124 | |
| 125 SecKeychainItemRef CrSKeychainSearchCopyNext(SecKeychainSearchRef search) { | |
| 126 if (!search) { | |
| 127 return NULL; | |
| 128 } | |
| 129 | |
| 130 SecKeychainItemRef item; | |
| 131 OSStatus status = SecKeychainSearchCopyNext(search, &item); | |
| 132 if (status != errSecSuccess) { | |
| 133 if (status != errSecItemNotFound) { | |
| 134 OSSTATUS_LOG(ERROR, status); | |
| 135 } | |
| 136 return NULL; | |
| 137 } | |
| 138 | |
| 139 return item; | |
| 140 } | |
| 141 | |
| 142 void CrSKeychainItemFreeAttributesAndData( | |
| 143 SecKeychainAttributeList* attribute_list, | |
| 144 void* data) { | |
| 145 OSStatus status = SecKeychainItemFreeAttributesAndData(attribute_list, data); | |
| 146 if (status != errSecSuccess) { | |
| 147 OSSTATUS_LOG(ERROR, status); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 bool CrSKeychainItemTestAccess(SecKeychainItemRef item) { | |
| 152 UInt32 length; | |
| 153 void* data; | |
| 154 OSStatus status = SecKeychainItemCopyAttributesAndData(item, | |
| 155 NULL, | |
| 156 NULL, | |
| 157 NULL, | |
| 158 &length, | |
| 159 &data); | |
| 160 if (status != errSecSuccess) { | |
| 161 if (status != errSecAuthFailed) { | |
| 162 OSSTATUS_LOG(ERROR, status); | |
| 163 } | |
| 164 return false; | |
| 165 } | |
| 166 | |
| 167 CrSKeychainItemFreeAttributesAndData(NULL, data); | |
| 168 | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 SecAccessRef CrSKeychainItemCopyAccess(SecKeychainItemRef item) { | |
| 173 SecAccessRef access; | |
| 174 OSStatus status = SecKeychainItemCopyAccess(item, &access); | |
| 175 if (status != errSecSuccess) { | |
| 176 if (status != errSecNoAccessForItem && status != errSecAuthFailed) { | |
| 177 OSSTATUS_LOG(ERROR, status); | |
| 178 } | |
| 179 return NULL; | |
| 180 } | |
| 181 | |
| 182 return access; | |
| 183 } | |
| 184 | |
| 185 CFArrayRef CrSAccessCopyACLList(SecAccessRef access) { | |
| 186 if (!access) { | |
| 187 return NULL; | |
| 188 } | |
| 189 | |
| 190 CFArrayRef acl_list; | |
| 191 OSStatus status = SecAccessCopyACLList(access, &acl_list); | |
| 192 if (status != errSecSuccess) { | |
| 193 OSSTATUS_LOG(ERROR, status); | |
| 194 return NULL; | |
| 195 } | |
| 196 | |
| 197 return acl_list; | |
| 198 } | |
| 199 | |
| 200 CrSACLSimpleContents* CrSACLCopySimpleContents(SecACLRef acl) { | |
| 201 if (!acl) { | |
| 202 return NULL; | |
| 203 } | |
| 204 | |
| 205 scoped_ptr<CrSACLSimpleContents> acl_simple_contents( | |
| 206 new CrSACLSimpleContents()); | |
| 207 CFArrayRef application_list; | |
| 208 CFStringRef description; | |
| 209 OSStatus status = | |
| 210 SecACLCopySimpleContents(acl, | |
| 211 &application_list, | |
| 212 &description, | |
| 213 &acl_simple_contents->prompt_selector); | |
| 214 if (status != errSecSuccess) { | |
| 215 if (status != errSecACLNotSimple) { | |
| 216 OSSTATUS_LOG(ERROR, status); | |
| 217 } | |
| 218 return NULL; | |
| 219 } | |
| 220 | |
| 221 acl_simple_contents->application_list.reset(application_list); | |
| 222 acl_simple_contents->description.reset(description); | |
| 223 | |
| 224 return acl_simple_contents.release(); | |
| 225 } | |
| 226 | |
| 227 SecRequirementRef CrSTrustedApplicationCopyRequirement( | |
| 228 SecTrustedApplicationRef application) { | |
| 229 if (!application) { | |
| 230 return NULL; | |
| 231 } | |
| 232 | |
| 233 SecRequirementRef requirement; | |
| 234 OSStatus status = SecTrustedApplicationCopyRequirement(application, | |
| 235 &requirement); | |
| 236 if (status != errSecSuccess) { | |
| 237 OSSTATUS_LOG(ERROR, status); | |
| 238 return NULL; | |
| 239 } | |
| 240 | |
| 241 return requirement; | |
| 242 } | |
| 243 | |
| 244 CFStringRef CrSRequirementCopyString(SecRequirementRef requirement, | |
| 245 SecCSFlags flags) { | |
| 246 if (!requirement) { | |
| 247 return NULL; | |
| 248 } | |
| 249 | |
| 250 CFStringRef requirement_string; | |
| 251 OSStatus status = SecRequirementCopyString(requirement, | |
| 252 flags, | |
| 253 &requirement_string); | |
| 254 if (status != errSecSuccess) { | |
| 255 OSSTATUS_LOG(ERROR, status); | |
| 256 return NULL; | |
| 257 } | |
| 258 | |
| 259 return requirement_string; | |
| 260 } | |
| 261 | |
| 262 SecTrustedApplicationRef CrSTrustedApplicationCreateFromPath(const char* path) { | |
| 263 SecTrustedApplicationRef application; | |
| 264 OSStatus status = SecTrustedApplicationCreateFromPath(path, &application); | |
| 265 if (status != errSecSuccess) { | |
| 266 OSSTATUS_LOG(ERROR, status); | |
| 267 return NULL; | |
| 268 } | |
| 269 | |
| 270 return application; | |
| 271 } | |
| 272 | |
| 273 bool CrSACLSetSimpleContents(SecACLRef acl, | |
| 274 const CrSACLSimpleContents& acl_simple_contents) { | |
| 275 OSStatus status = | |
| 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); | |
| 282 return false; | |
| 283 } | |
| 284 | |
| 285 return true; | |
| 286 } | |
| 287 | |
| 288 SecKeychainRef CrSKeychainItemCopyKeychain(SecKeychainItemRef item) { | |
| 289 SecKeychainRef keychain; | |
| 290 OSStatus status = SecKeychainItemCopyKeychain(item, &keychain); | |
| 291 if (status != errSecSuccess) { | |
| 292 OSSTATUS_LOG(ERROR, status); | |
| 293 return NULL; | |
| 294 } | |
| 295 | |
| 296 return keychain; | |
| 297 } | |
| 298 | |
| 299 SecKeychainAttributeInfo* CrSKeychainAttributeInfoForItemID( | |
| 300 SecKeychainRef keychain, | |
| 301 UInt32 item_id) { | |
| 302 SecKeychainAttributeInfo* attribute_info; | |
| 303 OSStatus status = SecKeychainAttributeInfoForItemID(keychain, | |
| 304 item_id, | |
| 305 &attribute_info); | |
| 306 if (status != errSecSuccess) { | |
| 307 OSSTATUS_LOG(ERROR, status); | |
| 308 return NULL; | |
| 309 } | |
| 310 | |
| 311 return attribute_info; | |
| 312 } | |
| 313 | |
| 314 CrSKeychainItemAttributesAndData* CrSKeychainItemCopyAttributesAndData( | |
| 315 SecKeychainRef keychain, | |
| 316 SecKeychainItemRef item) { | |
| 317 ScopedCrSKeychainItemAttributesAndData attributes_and_data( | |
| 318 new CrSKeychainItemAttributesAndData()); | |
| 319 OSStatus status = | |
| 320 SecKeychainItemCopyAttributesAndData(item, | |
| 321 NULL, | |
| 322 attributes_and_data.item_class_ptr(), | |
| 323 NULL, | |
| 324 NULL, | |
| 325 NULL); | |
| 326 if (status != errSecSuccess) { | |
| 327 OSSTATUS_LOG(ERROR, status); | |
| 328 return NULL; | |
| 329 } | |
| 330 | |
| 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. | |
| 335 UInt32 item_id; | |
| 336 switch (attributes_and_data.item_class()) { | |
| 337 case kSecInternetPasswordItemClass: | |
| 338 item_id = CSSM_DL_DB_RECORD_INTERNET_PASSWORD; | |
| 339 break; | |
| 340 case kSecGenericPasswordItemClass: | |
| 341 item_id = CSSM_DL_DB_RECORD_GENERIC_PASSWORD; | |
| 342 break; | |
| 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; | |
| 352 break; | |
| 353 default: | |
| 354 item_id = attributes_and_data.item_class(); | |
| 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); | |
| 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); | |
| 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); | |
| 404 return NULL; | |
| 405 } | |
| 406 | |
| 407 return item; | |
| 408 } | |
| 409 | |
| 410 } // namespace chrome | 35 } // namespace chrome |
| OLD | NEW |