- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / mac / security_wrappers.cc
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 extern "C" {
11 OSStatus SecTrustedApplicationCopyRequirement(
12     SecTrustedApplicationRef application,
13     SecRequirementRef* requirement);
14 }  // extern "C"
15
16 namespace chrome {
17
18 ScopedSecKeychainSetUserInteractionAllowed::
19     ScopedSecKeychainSetUserInteractionAllowed(Boolean allowed) {
20   OSStatus status = SecKeychainGetUserInteractionAllowed(&old_allowed_);
21   if (status != errSecSuccess) {
22     OSSTATUS_LOG(ERROR, status);
23     old_allowed_ = TRUE;
24   }
25
26   status = SecKeychainSetUserInteractionAllowed(allowed);
27   if (status != errSecSuccess) {
28     OSSTATUS_LOG(ERROR, status);
29   }
30 }
31
32 ScopedSecKeychainSetUserInteractionAllowed::
33     ~ScopedSecKeychainSetUserInteractionAllowed() {
34   OSStatus status = SecKeychainSetUserInteractionAllowed(old_allowed_);
35   if (status != errSecSuccess) {
36     OSSTATUS_LOG(ERROR, status);
37   }
38 }
39
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