]> git.saurik.com Git - apple/security.git/blob - Keychain/SecKeychain.cpp
a90e4ad49bd337a1b4c5d4170766c906b44cc803
[apple/security.git] / Keychain / SecKeychain.cpp
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18 #include <Security/SecKeychainAPIPriv.h>
19 #include <Security/SecKeychain.h>
20 #include <Security/cssmdata.h>
21 #include <Security/KCExceptions.h>
22 #include "SecBridge.h"
23 #include "CCallbackMgr.h"
24 #include "Schema.h"
25
26
27 CFTypeID
28 SecKeychainGetTypeID(void)
29 {
30 BEGIN_SECAPI
31
32 return gTypes().keychain.typeId;
33
34 END_SECAPI1(_kCFRuntimeNotATypeID)
35 }
36
37
38 OSStatus
39 SecKeychainGetVersion(UInt32 *returnVers)
40 {
41 if (!returnVers)
42 return noErr;
43
44 *returnVers = 0x02028000;
45 return noErr;
46 }
47
48
49 OSStatus
50 SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef)
51 {
52 BEGIN_SECAPI
53
54 RequiredParam(keychainRef)=gTypes().keychain.handle(*globals().storageManager.make(pathName));
55
56 END_SECAPI
57 }
58
59
60 OSStatus
61 SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password,
62 Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef)
63 {
64 BEGIN_SECAPI
65
66 KCThrowParamErrIf_(!pathName);
67 Keychain keychain = globals().storageManager.make(pathName);
68
69 // @@@ the call to StorageManager::make above leaves keychain the the cache.
70 // If the create below fails we should probably remove it.
71 if(promptUser)
72 keychain->create();
73 else
74 {
75 KCThrowParamErrIf_(!password);
76 keychain->create(passwordLength, password);
77 }
78 RequiredParam(keychainRef)=gTypes().keychain.handle(*keychain);
79
80 END_SECAPI
81 }
82
83
84 OSStatus
85 SecKeychainDelete(SecKeychainRef keychainOrArray)
86 {
87 BEGIN_SECAPI
88
89 StorageManager::KeychainList keychains;
90 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
91 globals().storageManager.remove(keychains, true);
92
93 END_SECAPI
94 }
95
96
97 OSStatus
98 SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings)
99 {
100 BEGIN_SECAPI
101
102 Keychain keychain = Keychain::optional(keychainRef);
103 if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
104 {
105 UInt32 lockInterval=newSettings->lockInterval;
106 bool lockOnSleep=newSettings->lockOnSleep;
107 keychain->setSettings(lockInterval, lockOnSleep);
108 }
109
110 END_SECAPI
111 }
112
113
114 OSStatus
115 SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings)
116 {
117 BEGIN_SECAPI
118
119 Keychain keychain = Keychain::optional(keychainRef);
120 if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
121 {
122 UInt32 lockInterval;
123 bool lockOnSleep;
124
125 keychain->getSettings(lockInterval, lockOnSleep);
126 outSettings->lockInterval=lockInterval;
127 outSettings->lockOnSleep=lockOnSleep;
128 }
129
130 END_SECAPI
131 }
132
133
134 OSStatus
135 SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, void *password, Boolean usePassword)
136 {
137 BEGIN_SECAPI
138
139 Keychain keychain = Keychain::optional(keychainRef);
140
141 if(usePassword)
142 keychain->unlock(CssmData(password,passwordLength));
143 else
144 keychain->unlock();
145
146 END_SECAPI
147 }
148
149
150 OSStatus
151 SecKeychainLock(SecKeychainRef keychainRef)
152 {
153 BEGIN_SECAPI
154
155 Keychain keychain = Keychain::optional(keychainRef);
156 keychain->lock();
157
158 END_SECAPI
159 }
160
161
162 OSStatus
163 SecKeychainLockAll(void)
164 {
165 BEGIN_SECAPI
166
167 globals().storageManager.lockAll();
168
169 END_SECAPI
170 }
171
172
173 OSStatus
174 SecKeychainCopyDefault(SecKeychainRef *keychainRef)
175 {
176 BEGIN_SECAPI
177
178 RequiredParam(keychainRef)=gTypes().keychain.handle(*globals().defaultKeychain.keychain());
179
180 END_SECAPI
181 }
182
183
184 OSStatus
185 SecKeychainSetDefault(SecKeychainRef keychainRef)
186 {
187 BEGIN_SECAPI
188
189 globals().defaultKeychain.keychain(Keychain::optional(keychainRef));
190
191 END_SECAPI
192 }
193
194 OSStatus SecKeychainCopySearchList(CFArrayRef* searchList)
195 {
196 BEGIN_SECAPI
197
198 RequiredParam(searchList);
199 StorageManager &smr = globals().storageManager;
200 StorageManager::KeychainList keychainList;
201 smr.getSearchList(keychainList);
202 *searchList = smr.convertFromKeychainList(keychainList);
203
204 END_SECAPI
205 }
206
207 OSStatus SecKeychainSetSearchList(CFArrayRef searchList)
208 {
209 BEGIN_SECAPI
210
211 RequiredParam(searchList);
212 StorageManager &smr = globals().storageManager;
213 StorageManager::KeychainList keychainList;
214 smr.convertToKeychainList(searchList, keychainList);
215 smr.setSearchList(keychainList);
216
217 END_SECAPI
218 }
219
220 OSStatus
221 SecKeychainGetStatus(SecKeychainRef keychainRef, SecKeychainStatus *keychainStatus)
222 {
223 BEGIN_SECAPI
224
225 RequiredParam(keychainStatus) = (SecKeychainStatus)Keychain::optional(keychainRef)->status();
226
227 END_SECAPI
228 }
229
230
231 OSStatus
232 SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 * ioPathLength, char *pathName)
233 {
234 BEGIN_SECAPI
235
236 RequiredParam(pathName);
237
238 const char *name = Keychain::optional(keychainRef)->name();
239 UInt32 nameLen = strlen(name);
240 if (nameLen+1 > *ioPathLength) // if the client's buffer is too small (including null-termination), throw
241 CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL);
242 strncpy(pathName, name, nameLen);
243 pathName[nameLen] = 0;
244 *ioPathLength = nameLen; // set the length.
245
246 END_SECAPI
247 }
248
249
250 // @@@ Depricated
251 UInt16
252 SecKeychainListGetCount(void)
253 {
254 BEGIN_SECAPI
255
256 return globals().storageManager.size();
257
258 END_SECAPI1(0)
259 }
260
261
262 // @@@ Depricated
263 OSStatus
264 SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef)
265 {
266 BEGIN_SECAPI
267
268 KeychainCore::StorageManager &smgr=KeychainCore::globals().storageManager;
269 RequiredParam(keychainRef)=gTypes().keychain.handle(*smgr[index]);
270
271 END_SECAPI
272 }
273
274
275 // @@@ Depricated
276 OSStatus
277 SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef)
278 {
279 BEGIN_SECAPI
280
281 Required(keychainRef);
282 Keychain keychain = Keychain::optional(*keychainRef);
283 StorageManager::KeychainList keychainList;
284 keychainList.push_back(keychain);
285 globals().storageManager.remove(keychainList);
286 *keychainRef = NULL;
287
288 END_SECAPI
289 }
290
291
292 OSStatus
293 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef, UInt32 itemID, SecKeychainAttributeInfo **info)
294 {
295 BEGIN_SECAPI
296
297 Keychain keychain = Keychain::optional(keychainRef);
298 keychain->getAttributeInfoForItemID(itemID, info);
299
300 END_SECAPI
301 }
302
303
304 OSStatus
305 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info)
306 {
307 BEGIN_SECAPI
308
309 KeychainImpl::freeAttributeInfo(info);
310
311 END_SECAPI
312 }
313
314
315 pascal OSStatus
316 SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext)
317 {
318 BEGIN_SECAPI
319
320 RequiredParam(callbackFunction);
321 CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext);
322
323 END_SECAPI
324 }
325
326
327 OSStatus
328 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction)
329 {
330 BEGIN_SECAPI
331
332 RequiredParam(callbackFunction);
333 CCallbackMgr::RemoveCallback(callbackFunction);
334
335 END_SECAPI
336 }
337
338
339 OSStatus
340 SecKeychainAddInternetPassword(SecKeychainRef keychainRef, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef)
341 {
342 BEGIN_SECAPI
343
344 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
345 // @@@ Get real itemClass
346 Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData);
347
348 if (serverName && serverNameLength)
349 item->setAttribute(Schema::attributeInfo(kSecServerItemAttr),
350 CssmData(const_cast<void *>(reinterpret_cast<const void *>(serverName)), serverNameLength));
351
352 if (accountName && accountNameLength)
353 {
354 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
355 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
356 // @@@ We should probably leave setting of label up to lower level code.
357 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account);
358 }
359
360 if (securityDomain && securityDomainLength)
361 item->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr),
362 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain)), securityDomainLength));
363
364 item->setAttribute(Schema::attributeInfo(kSecPortItemAttr), UInt32(port));
365 item->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr), protocol);
366 item->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr), authenticationType);
367
368 if (path && pathLength)
369 item->setAttribute(Schema::attributeInfo(kSecPathItemAttr),
370 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path)), pathLength));
371
372 Keychain::optional(keychainRef)->add(item);
373 if (itemRef)
374 *itemRef = gTypes().item.handle(*item);
375
376 END_SECAPI
377 }
378
379
380 OSStatus
381 SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef)
382
383 {
384 BEGIN_SECAPI
385
386 StorageManager::KeychainList keychains;
387 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
388 KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL);
389
390 if (serverName && serverNameLength)
391 {
392 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServerItemAttr),
393 CssmData(const_cast<char *>(serverName), serverNameLength));
394 }
395
396 if (securityDomain && securityDomainLength)
397 {
398 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecSecurityDomainItemAttr),
399 CssmData (const_cast<char*>(securityDomain), securityDomainLength));
400 }
401
402 if (accountName && accountNameLength)
403 {
404 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
405 CssmData (const_cast<char*>(accountName), accountNameLength));
406 }
407
408 if (port)
409 {
410 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPortItemAttr),
411 UInt32(port));
412 }
413
414 if (protocol)
415 {
416 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecProtocolItemAttr),
417 protocol);
418 }
419
420 if (authenticationType)
421 {
422 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAuthenticationTypeItemAttr),
423 authenticationType);
424 }
425
426 if (path && pathLength)
427 {
428 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPathItemAttr), path);
429 }
430
431 Item item;
432 if (!cursor->next(item))
433 return errSecItemNotFound;
434
435 // Get its data (only if necessary)
436 if (passwordData || passwordLength)
437 {
438 CssmDataContainer outData;
439 item->getData(outData);
440 *passwordLength=outData.length();
441 outData.Length=0;
442 *passwordData=outData.data();
443 outData.Data=NULL;
444 }
445
446 if (itemRef)
447 *itemRef=gTypes().item.handle(*item);
448
449 END_SECAPI
450 }
451
452
453 OSStatus
454 SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef)
455
456 {
457 BEGIN_SECAPI
458
459 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
460 // @@@ Get real itemClass
461 Item item(kSecGenericPasswordItemClass, 'aapl', passwordLength, passwordData);
462
463 if (serviceName && serviceNameLength)
464 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), CssmData(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength));
465
466 if (accountName && accountNameLength)
467 {
468 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
469 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
470 // @@@ We should probably leave setting of label up to lower level code.
471 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account);
472 }
473
474 Keychain::optional(keychainRef)->add(item);
475 if (itemRef)
476 *itemRef = gTypes().item.handle(*item);
477
478 END_SECAPI
479 }
480
481
482 OSStatus
483 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef)
484
485 {
486 BEGIN_SECAPI
487
488 StorageManager::KeychainList keychains;
489 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
490 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
491
492 if (serviceName && serviceNameLength)
493 {
494 cursor->add (CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr),
495 const_cast<char*>(serviceName));
496 }
497
498 if (accountName && accountNameLength)
499 {
500 cursor->add (CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
501 const_cast<char*>(accountName));
502 }
503
504 Item item;
505 if (!cursor->next(item))
506 return errSecItemNotFound;
507
508 // Get its data (only if necessary)
509 if (passwordData || passwordLength)
510 {
511 CssmDataContainer outData;
512 item->getData(outData);
513 *passwordLength=outData.length();
514 outData.Length=0;
515 *passwordData=outData.data();
516 outData.Data=NULL;
517 }
518
519 if (itemRef)
520 *itemRef=gTypes().item.handle(*item);
521
522 END_SECAPI
523 }
524
525
526 OSStatus
527 SecKeychainSetUserInteractionAllowed(Boolean state)
528 {
529 BEGIN_SECAPI
530
531 globals().setUserInteractionAllowed(state);
532
533 END_SECAPI
534 }
535
536
537 OSStatus
538 SecKeychainGetUserInteractionAllowed(Boolean *state)
539 {
540 BEGIN_SECAPI
541
542 Required(state)=globals().getUserInteractionAllowed();
543
544 END_SECAPI
545 }
546
547
548 OSStatus
549 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle)
550 {
551 BEGIN_SECAPI
552
553 RequiredParam(dldbHandle);
554
555 Keychain keychain = Keychain::optional(keychainRef);
556 *dldbHandle = keychain->database()->handle();
557
558 END_SECAPI
559 }
560
561
562 OSStatus
563 SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
564 {
565 BEGIN_SECAPI
566
567 RequiredParam(cspHandle);
568
569 Keychain keychain = Keychain::optional(keychainRef);
570 *cspHandle = keychain->csp()->handle();
571
572 END_SECAPI
573 }
574
575
576 OSStatus
577 SecKeychainCopyAccess(SecKeychainRef keychainRef, SecAccessRef *accessRef)
578 {
579 BEGIN_SECAPI
580
581 MacOSError::throwMe(unimpErr);//%%%for now
582
583 END_SECAPI
584 }
585
586
587 OSStatus
588 SecKeychainSetAccess(SecKeychainRef keychainRef, SecAccessRef accessRef)
589 {
590 BEGIN_SECAPI
591
592 MacOSError::throwMe(unimpErr);//%%%for now
593
594 END_SECAPI
595 }
596
597
598 #pragma mark ---- Private API ----
599
600
601 OSStatus
602 SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword)
603 {
604 BEGIN_SECAPI
605
606 Keychain keychain = Keychain::optional(keychainRef);
607 keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword);
608
609 END_SECAPI
610 }
611
612
613 OSStatus
614 SecKeychainCopyLogin(SecKeychainRef *keychainRef)
615 {
616 BEGIN_SECAPI
617
618 // NOTE: operates on default Keychain! It shouldn't... we want to
619 // have code that operates of a login keychain.
620 RequiredParam(keychainRef)=gTypes().keychain.handle(*globals().defaultKeychain.keychain());
621
622 END_SECAPI
623 }
624
625
626 OSStatus
627 SecKeychainLogin(UInt32 nameLength, void* name, UInt32 passwordLength, void* password)
628 {
629 BEGIN_SECAPI
630
631 globals().storageManager.login(nameLength, name, passwordLength, password);
632
633 END_SECAPI
634 }
635
636
637 OSStatus
638 SecKeychainLogout()
639 {
640 BEGIN_SECAPI
641
642 globals().storageManager.logout();
643
644 END_SECAPI
645 }