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 |