2 * Copyright (c) 2003-2010,2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include "keychain_find.h"
28 #include "keychain_utilities.h"
36 #include <libkern/OSByteOrder.h>
37 #include <Security/SecKeychainItem.h>
38 #include <Security/SecKeychainSearch.h>
39 #include <Security/SecCertificate.h>
40 #include <CoreFoundation/CFString.h>
44 // SecDigestGetData, SecKeychainSearchCreateForCertificateByEmail, SecCertificateFindByEmail
45 #include <Security/SecCertificatePriv.h>
47 Boolean gDeleteIt
= 0;
49 // find_first_generic_password
51 // Returns a SecKeychainItemRef for the first item
52 // which matches the specified attributes. Caller is
53 // responsible for releasing the item (with CFRelease).
56 find_first_generic_password(CFTypeRef keychainOrArray
,
57 FourCharCode itemCreator
,
58 FourCharCode itemType
,
63 const char *serviceName
,
64 const char *accountName
)
66 OSStatus status
= noErr
;
67 SecKeychainSearchRef searchRef
= NULL
;
68 SecKeychainItemRef itemRef
= NULL
;
70 SecKeychainAttribute attrs
[8]; // maximum number of searchable attributes
71 SecKeychainAttributeList attrList
= { 0, attrs
};
73 // the primary key for a generic password item (i.e. the combination of
74 // attributes which determine whether the item is unique) consists of:
75 // { kSecAccountItemAttr, kSecServiceItemAttr }
77 // if we have a primary key, we don't need to search on other attributes
78 // (and we don't want to, if non-primary attributes are being updated)
79 Boolean primaryKey
= (accountName
&& serviceName
);
81 // build the attribute list for searching
82 if ((UInt32
)itemCreator
!= 0 && !primaryKey
) {
83 attrs
[attrList
.count
].tag
= kSecCreatorItemAttr
;
84 attrs
[attrList
.count
].length
= sizeof(FourCharCode
);
85 attrs
[attrList
.count
].data
= (FourCharCode
*)&itemCreator
;
88 if ((UInt32
)itemType
!= 0 && !primaryKey
) {
89 attrs
[attrList
.count
].tag
= kSecTypeItemAttr
;
90 attrs
[attrList
.count
].length
= sizeof(FourCharCode
);
91 attrs
[attrList
.count
].data
= (FourCharCode
*)&itemType
;
94 if (kind
!= NULL
&& !primaryKey
) {
95 attrs
[attrList
.count
].tag
= kSecDescriptionItemAttr
;
96 attrs
[attrList
.count
].length
= strlen(kind
);
97 attrs
[attrList
.count
].data
= (void*)kind
;
100 if (value
!= NULL
&& !primaryKey
) {
101 attrs
[attrList
.count
].tag
= kSecGenericItemAttr
;
102 attrs
[attrList
.count
].length
= strlen(value
);
103 attrs
[attrList
.count
].data
= (void*)value
;
106 if (comment
!= NULL
&& !primaryKey
) {
107 attrs
[attrList
.count
].tag
= kSecCommentItemAttr
;
108 attrs
[attrList
.count
].length
= strlen(comment
);
109 attrs
[attrList
.count
].data
= (void*)comment
;
112 if (label
!= NULL
&& !primaryKey
) {
113 attrs
[attrList
.count
].tag
= kSecLabelItemAttr
;
114 attrs
[attrList
.count
].length
= strlen(label
);
115 attrs
[attrList
.count
].data
= (void*)label
;
118 if (serviceName
!= NULL
) {
119 attrs
[attrList
.count
].tag
= kSecServiceItemAttr
;
120 attrs
[attrList
.count
].length
= strlen(serviceName
);
121 attrs
[attrList
.count
].data
= (void*)serviceName
;
124 if (accountName
!= NULL
) {
125 attrs
[attrList
.count
].tag
= kSecAccountItemAttr
;
126 attrs
[attrList
.count
].length
= strlen(accountName
);
127 attrs
[attrList
.count
].data
= (void*)accountName
;
131 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
, kSecGenericPasswordItemClass
, &attrList
, &searchRef
);
133 sec_perror("SecKeychainSearchCreateFromAttributes", status
);
136 // we're only interested in the first match, if there is a match at all
137 status
= SecKeychainSearchCopyNext(searchRef
, &itemRef
);
144 CFRelease(searchRef
);
149 // find_first_internet_password
151 // Returns a SecKeychainItemRef for the first item
152 // which matches the specified attributes. Caller is
153 // responsible for releasing the item (with CFRelease).
156 find_first_internet_password(CFTypeRef keychainOrArray
,
157 FourCharCode itemCreator
,
158 FourCharCode itemType
,
162 const char *serverName
,
163 const char *securityDomain
,
164 const char *accountName
,
167 SecProtocolType protocol
,
168 SecAuthenticationType authenticationType
)
170 OSStatus status
= noErr
;
171 SecKeychainSearchRef searchRef
= NULL
;
172 SecKeychainItemRef itemRef
= NULL
;
174 SecKeychainAttribute attrs
[12]; // maximum number of searchable attributes
175 SecKeychainAttributeList attrList
= { 0, attrs
};
177 // the primary key for an internet password item (i.e. the combination of
178 // attributes which determine whether the item is unique) consists of:
179 // { kSecAccountItemAttr, kSecSecurityDomainItemAttr, kSecServerItemAttr,
180 // kSecProtocolItemAttr, kSecAuthenticationTypeItemAttr,
181 // kSecPortItemAttr, kSecPathItemAttr }
183 // if we have a primary key, we don't need to search on other attributes.
184 // (and we don't want to, if non-primary attributes are being updated)
185 Boolean primaryKey
= (accountName
&& securityDomain
&& serverName
&&
186 protocol
&& authenticationType
&& port
&& path
);
188 // build the attribute list for searching
189 if ((UInt32
)itemCreator
!= 0 && !primaryKey
) {
190 attrs
[attrList
.count
].tag
= kSecCreatorItemAttr
;
191 attrs
[attrList
.count
].length
= sizeof(FourCharCode
);
192 attrs
[attrList
.count
].data
= (FourCharCode
*)&itemCreator
;
195 if ((UInt32
)itemType
!= 0 && !primaryKey
) {
196 attrs
[attrList
.count
].tag
= kSecTypeItemAttr
;
197 attrs
[attrList
.count
].length
= sizeof(FourCharCode
);
198 attrs
[attrList
.count
].data
= (FourCharCode
*)&itemType
;
201 if (kind
!= NULL
&& !primaryKey
) {
202 attrs
[attrList
.count
].tag
= kSecDescriptionItemAttr
;
203 attrs
[attrList
.count
].length
= strlen(kind
);
204 attrs
[attrList
.count
].data
= (void*)kind
;
207 if (comment
!= NULL
&& !primaryKey
) {
208 attrs
[attrList
.count
].tag
= kSecCommentItemAttr
;
209 attrs
[attrList
.count
].length
= strlen(comment
);
210 attrs
[attrList
.count
].data
= (void*)comment
;
213 if (label
!= NULL
&& !primaryKey
) {
214 attrs
[attrList
.count
].tag
= kSecLabelItemAttr
;
215 attrs
[attrList
.count
].length
= strlen(label
);
216 attrs
[attrList
.count
].data
= (void*)label
;
219 if (serverName
!= NULL
) {
220 attrs
[attrList
.count
].tag
= kSecServerItemAttr
;
221 attrs
[attrList
.count
].length
= strlen(serverName
);
222 attrs
[attrList
.count
].data
= (void*)serverName
;
225 if (securityDomain
!= NULL
) {
226 attrs
[attrList
.count
].tag
= kSecSecurityDomainItemAttr
;
227 attrs
[attrList
.count
].length
= strlen(securityDomain
);
228 attrs
[attrList
.count
].data
= (void *)securityDomain
;
231 if (accountName
!= NULL
) {
232 attrs
[attrList
.count
].tag
= kSecAccountItemAttr
;
233 attrs
[attrList
.count
].length
= strlen(accountName
);
234 attrs
[attrList
.count
].data
= (void *)accountName
;
238 attrs
[attrList
.count
].tag
= kSecPathItemAttr
;
239 attrs
[attrList
.count
].length
= strlen(path
);
240 attrs
[attrList
.count
].data
= (void *)path
;
244 attrs
[attrList
.count
].tag
= kSecPortItemAttr
;
245 attrs
[attrList
.count
].length
= sizeof(UInt16
);
246 attrs
[attrList
.count
].data
= (UInt16
*)&port
;
249 if ((UInt32
)protocol
!= 0) {
250 attrs
[attrList
.count
].tag
= kSecProtocolItemAttr
;
251 attrs
[attrList
.count
].length
= sizeof(SecProtocolType
);
252 attrs
[attrList
.count
].data
= (SecProtocolType
*)&protocol
;
255 if ((UInt32
)authenticationType
!= 0) {
256 attrs
[attrList
.count
].tag
= kSecAuthenticationTypeItemAttr
;
257 attrs
[attrList
.count
].length
= sizeof(SecAuthenticationType
);
258 attrs
[attrList
.count
].data
= (SecAuthenticationType
*)&authenticationType
;
262 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
, kSecInternetPasswordItemClass
, &attrList
, &searchRef
);
264 sec_perror("SecKeychainSearchCreateFromAttributes", status
);
267 // we're only interested in the first match, if there is a match at all
268 status
= SecKeychainSearchCopyNext(searchRef
, &itemRef
);
275 CFRelease(searchRef
);
280 // find_unique_certificate
282 // Returns a SecKeychainItemRef for the certificate
283 // in the specified keychain (or keychain list)
284 // which is a unique match for either the specified name
285 // or SHA-1 hash. If more than one match exists, the
286 // certificate is not unique and none are returned. Caller is
287 // responsible for releasing the item (with CFRelease).
290 find_unique_certificate(CFTypeRef keychainOrArray
,
294 OSStatus status
= noErr
;
295 SecKeychainSearchRef searchRef
= NULL
;
296 SecKeychainItemRef uniqueItemRef
= NULL
;
298 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
, kSecCertificateItemClass
, NULL
, &searchRef
);
300 return uniqueItemRef
;
303 // check input hash string and convert to data
304 CSSM_DATA hashData
= { 0, NULL
};
306 CSSM_SIZE len
= strlen(hash
)/2;
307 hashData
.Length
= len
;
308 hashData
.Data
= (uint8
*)malloc(hashData
.Length
);
309 fromHex(hash
, &hashData
);
312 // filter candidates against the hash (or the name, if no hash provided)
313 CFStringRef matchRef
= (name
) ? CFStringCreateWithCString(NULL
, name
, kCFStringEncodingUTF8
) : NULL
;
314 Boolean exactMatch
= FALSE
;
316 CSSM_DATA certData
= { 0, NULL
};
317 SecKeychainItemRef candidate
= NULL
;
319 while (SecKeychainSearchCopyNext(searchRef
, &candidate
) == noErr
) {
320 SecCertificateRef cert
= (SecCertificateRef
)candidate
;
321 if (SecCertificateGetData(cert
, &certData
) != noErr
) {
322 safe_CFRelease(&candidate
);
326 uint8 candidate_sha1_hash
[20];
328 digest
.Length
= sizeof(candidate_sha1_hash
);
329 digest
.Data
= candidate_sha1_hash
;
330 if ((SecDigestGetData(CSSM_ALGID_SHA1
, &digest
, &certData
) == CSSM_OK
) &&
331 (hashData
.Length
== digest
.Length
) &&
332 (!memcmp(hashData
.Data
, digest
.Data
, digest
.Length
))) {
334 uniqueItemRef
= candidate
; // currently retained
335 break; // we're done - can't get more exact than this
338 // copy certificate name
339 CFStringRef nameRef
= NULL
;
340 if ((SecCertificateCopyCommonName(cert
, &nameRef
) != noErr
) || nameRef
== NULL
) {
341 safe_CFRelease(&candidate
);
342 continue; // no name, so no match is possible
344 CFIndex nameLen
= CFStringGetLength(nameRef
);
345 CFIndex bufLen
= 1 + CFStringGetMaximumSizeForEncoding(nameLen
, kCFStringEncodingUTF8
);
346 char *nameBuf
= (char *)malloc(bufLen
);
347 if (!CFStringGetCString(nameRef
, nameBuf
, bufLen
-1, kCFStringEncodingUTF8
))
350 CFRange find
= { kCFNotFound
, 0 };
351 if (nameRef
&& matchRef
)
352 find
= CFStringFind(nameRef
, matchRef
, kCFCompareCaseInsensitive
| kCFCompareNonliteral
);
353 Boolean isExact
= (find
.location
== 0 && find
.length
== nameLen
);
354 if (find
.location
== kCFNotFound
) {
356 safe_CFRelease(&nameRef
);
357 safe_CFRelease(&candidate
);
358 continue; // no match
360 if (uniqueItemRef
) { // got two matches
361 if (exactMatch
&& !isExact
) { // prior is better; ignore this one
363 safe_CFRelease(&nameRef
);
364 safe_CFRelease(&candidate
);
367 if (exactMatch
== isExact
) { // same class of match
368 if (CFEqual(uniqueItemRef
, candidate
)) { // same certificate
370 safe_CFRelease(&nameRef
);
371 safe_CFRelease(&candidate
);
374 // ambiguity - must fail
375 sec_error("\"%s\" is ambiguous, matches more than one certificate", name
);
377 safe_CFRelease(&nameRef
);
378 safe_CFRelease(&candidate
);
379 safe_CFRelease(&uniqueItemRef
);
382 safe_CFRelease(&uniqueItemRef
); // about to replace with this one
384 uniqueItemRef
= candidate
; // currently retained
385 exactMatch
= isExact
;
387 safe_CFRelease(&nameRef
);
391 safe_CFRelease(&searchRef
);
392 safe_CFRelease(&matchRef
);
397 return uniqueItemRef
;
401 do_password_item_printing( SecKeychainItemRef itemRef
,
402 Boolean get_password
,
403 Boolean password_stdout
)
405 OSStatus result
= noErr
;
406 void *passwordData
= NULL
;
407 UInt32 passwordLength
= 0;
410 result
= SecKeychainItemCopyContent(itemRef
, NULL
, NULL
, &passwordLength
, &passwordData
);
411 if(result
!= noErr
) return result
;
413 if(!password_stdout
) {
414 print_keychain_item_attributes(stdout
, itemRef
, FALSE
, FALSE
, FALSE
, FALSE
);
416 fputs("password: ", stderr
);
417 print_buffer(stderr
, passwordLength
, passwordData
);
421 char *password
= (char *) passwordData
;
423 for(int i
=0; i
<passwordLength
; i
++) if(!isprint(password
[i
])) doHex
= 1;
425 for(int i
=0; i
<passwordLength
; i
++) printf("%02x", password
[i
]);
427 for(int i
=0; i
<passwordLength
; i
++) putchar(password
[i
]);
432 if (passwordData
) SecKeychainItemFreeContent(NULL
, passwordData
);
438 do_keychain_find_generic_password(CFTypeRef keychainOrArray
,
439 FourCharCode itemCreator
,
440 FourCharCode itemType
,
445 const char *serviceName
,
446 const char *accountName
,
447 Boolean get_password
,
448 Boolean password_stdout
)
450 OSStatus result
= noErr
;
451 SecKeychainItemRef itemRef
= NULL
;
453 itemRef
= find_first_generic_password(keychainOrArray
,
464 result
= do_password_item_printing(itemRef
, get_password
, password_stdout
);
466 result
= errSecItemNotFound
;
467 sec_perror("SecKeychainSearchCopyNext", result
);
470 if (itemRef
) CFRelease(itemRef
);
476 do_keychain_delete_generic_password(CFTypeRef keychainOrArray
,
477 FourCharCode itemCreator
,
478 FourCharCode itemType
,
483 const char *serviceName
,
484 const char *accountName
)
486 OSStatus result
= noErr
;
487 SecKeychainItemRef itemRef
= NULL
;
488 void *passwordData
= NULL
;
490 itemRef
= find_first_generic_password(keychainOrArray
,
500 result
= errSecItemNotFound
;
501 sec_perror("SecKeychainSearchCopyNext", result
);
505 print_keychain_item_attributes(stdout
, itemRef
, FALSE
, FALSE
, FALSE
, FALSE
);
507 result
= SecKeychainItemDelete(itemRef
);
509 fputs("password has been deleted.\n", stderr
);
513 SecKeychainItemFreeContent(NULL
, passwordData
);
521 do_keychain_find_internet_password(CFTypeRef keychainOrArray
,
522 FourCharCode itemCreator
,
523 FourCharCode itemType
,
527 const char *serverName
,
528 const char *securityDomain
,
529 const char *accountName
,
532 SecProtocolType protocol
,
533 SecAuthenticationType authenticationType
,
534 Boolean get_password
,
535 Boolean password_stdout
)
537 OSStatus result
= noErr
;
538 SecKeychainItemRef itemRef
= NULL
;
540 itemRef
= find_first_internet_password(keychainOrArray
,
554 result
= do_password_item_printing(itemRef
, get_password
, password_stdout
);
556 result
= errSecItemNotFound
;
557 sec_perror("SecKeychainSearchCopyNext", result
);
564 do_keychain_delete_internet_password(CFTypeRef keychainOrArray
,
565 FourCharCode itemCreator
,
566 FourCharCode itemType
,
570 const char *serverName
,
571 const char *securityDomain
,
572 const char *accountName
,
575 SecProtocolType protocol
,
576 SecAuthenticationType authenticationType
)
578 OSStatus result
= noErr
;
579 SecKeychainItemRef itemRef
= NULL
;
580 void *passwordData
= NULL
;
582 itemRef
= find_first_internet_password(keychainOrArray
,
596 result
= errSecItemNotFound
;
597 sec_perror("SecKeychainSearchCopyNext", result
);
601 print_keychain_item_attributes(stdout
, itemRef
, FALSE
, FALSE
, FALSE
, FALSE
);
603 result
= SecKeychainItemDelete(itemRef
);
605 fputs("password has been deleted.\n", stderr
);
609 SecKeychainItemFreeContent(NULL
, passwordData
);
617 do_keychain_find_certificate(CFTypeRef keychainOrArray
,
619 const char *emailAddress
,
625 OSStatus result
= noErr
;
626 SecCertificateRef certificateRef
= NULL
;
627 SecKeychainSearchRef searchRef
= NULL
;
628 CFStringRef matchRef
= (name
) ? CFStringCreateWithCString(NULL
, name
, kCFStringEncodingUTF8
) : NULL
;
630 if (find_all
&& emailAddress
) {
631 result
= SecKeychainSearchCreateForCertificateByEmail(keychainOrArray
, emailAddress
, &searchRef
);
633 sec_perror("SecKeychainSearchCreateForCertificateByEmail", result
);
637 result
= SecKeychainSearchCreateFromAttributes(keychainOrArray
, kSecCertificateItemClass
, NULL
, &searchRef
);
639 sec_perror("SecKeychainSearchCreateFromAttributes", result
);
647 SecKeychainItemRef itemRef
= NULL
;
648 result
= SecKeychainSearchCopyNext(searchRef
, &itemRef
);
649 if (result
== errSecItemNotFound
) {
654 sec_perror("SecKeychainSearchCopyNext", result
);
658 if (!emailAddress
&& name
) {
659 // match name in common name
660 CFStringRef nameRef
= NULL
;
661 if (SecCertificateCopyCommonName((SecCertificateRef
)itemRef
, &nameRef
) != noErr
) {
662 safe_CFRelease(&itemRef
);
663 continue; // no name, so no match is possible
665 CFRange find
= { kCFNotFound
, 0 };
666 if (nameRef
&& matchRef
)
667 find
= CFStringFind(nameRef
, matchRef
, kCFCompareCaseInsensitive
| kCFCompareNonliteral
);
668 if (find
.location
== kCFNotFound
) {
669 safe_CFRelease(&nameRef
);
670 safe_CFRelease(&itemRef
);
671 continue; // no match
673 safe_CFRelease(&nameRef
);
675 safe_CFRelease(&certificateRef
);
676 certificateRef
= (SecCertificateRef
) itemRef
;
678 else { // only want the first match
680 result
= SecCertificateFindByEmail(keychainOrArray
, emailAddress
, &certificateRef
);
682 sec_perror("SecCertificateFindByEmail", result
);
686 SecKeychainItemRef itemRef
= NULL
;
687 while ((result
= SecKeychainSearchCopyNext(searchRef
, &itemRef
)) != errSecItemNotFound
) {
689 // match name in common name
690 CFStringRef nameRef
= NULL
;
691 if (SecCertificateCopyCommonName((SecCertificateRef
)itemRef
, &nameRef
) != noErr
) {
692 safe_CFRelease(&itemRef
);
693 continue; // no name, so no match is possible
695 CFRange find
= { kCFNotFound
, 0 };
696 if (nameRef
&& matchRef
)
697 find
= CFStringFind(nameRef
, matchRef
, kCFCompareCaseInsensitive
| kCFCompareNonliteral
);
698 if (find
.location
== kCFNotFound
) {
699 safe_CFRelease(&nameRef
);
700 safe_CFRelease(&itemRef
);
701 continue; // no match
703 safe_CFRelease(&nameRef
);
705 break; // we have a match!
707 if (result
== errSecItemNotFound
) {
708 sec_perror("SecKeychainSearchCopyNext", result
);
711 certificateRef
= (SecCertificateRef
) itemRef
;
715 // process the found certificate
721 digest
.Length
= sizeof(sha1_hash
);
722 digest
.Data
= sha1_hash
;
723 if ((SecCertificateGetData(certificateRef
, &data
) == noErr
) &&
724 (SecDigestGetData(CSSM_ALGID_SHA1
, &digest
, &data
) == CSSM_OK
)) {
726 uint32 len
= digest
.Length
;
727 uint8
*cp
= digest
.Data
;
728 fprintf(stdout
, "SHA-1 hash: ");
729 for(i
=0; i
<len
; i
++) {
730 fprintf(stdout
, "%02X", ((unsigned char *)cp
)[i
]);
732 fprintf(stdout
, "\n");
738 CFArrayRef emailAddresses
= NULL
;
740 result
= SecCertificateCopyEmailAddresses(certificateRef
, &emailAddresses
);
743 sec_perror("SecCertificateCopyEmailAddresses", result
);
747 count
= CFArrayGetCount(emailAddresses
);
748 fputs("email addresses: ", stdout
);
749 for (ix
= 0; ix
< count
; ++ix
)
751 CFStringRef emailAddress
= (CFStringRef
)CFArrayGetValueAtIndex(emailAddresses
, ix
);
758 addr
= CFStringGetCStringPtr(emailAddress
, kCFStringEncodingUTF8
);
761 if (CFStringGetCString(emailAddress
, buffer
, sizeof(buffer
), kCFStringEncodingUTF8
))
765 fprintf(stdout
, "%s", addr
);
769 CFRelease(emailAddresses
);
774 CSSM_DATA certData
= {};
775 result
= SecCertificateGetData(certificateRef
, &certData
);
778 sec_perror("SecCertificateGetData", result
);
782 print_buffer_pem(stdout
, "CERTIFICATE", certData
.Length
, certData
.Data
);
786 print_keychain_item_attributes(stdout
, (SecKeychainItemRef
)certificateRef
, FALSE
, FALSE
, FALSE
, FALSE
);
791 safe_CFRelease(&searchRef
);
792 safe_CFRelease(&certificateRef
);
793 safe_CFRelease(&matchRef
);
799 keychain_delete_internet_password(int argc
, char * const *argv
)
801 char *serverName
= NULL
, *securityDomain
= NULL
, *accountName
= NULL
, *path
= NULL
;
802 char *kind
= NULL
, *label
= NULL
, *comment
= NULL
;
803 FourCharCode itemCreator
= 0, itemType
= 0;
805 SecProtocolType protocol
= 0;
806 SecAuthenticationType authenticationType
= 0;
807 CFTypeRef keychainOrArray
= NULL
;
811 * " -a Match \"account\" string\n"
812 * " -c Match \"creator\" (four-character code)\n"
813 * " -C Match \"type\" (four-character code)\n"
814 * " -d Match \"securityDomain\" string\n"
815 * " -D Match \"kind\" string\n"
816 * " -j Match \"comment\" string\n"
817 * " -l Match \"label\" string\n"
818 * " -p Match \"path\" string\n"
819 * " -P Match port number\n"
820 * " -r Match \"protocol\" (four-character code)\n"
821 * " -s Match \"server\" string\n"
822 * " -t Match \"authenticationType\" (four-character code)\n"
825 while ((ch
= getopt(argc
, argv
, "ha:c:C:d:D:hgj:l:p:P:r:s:t:")) != -1)
830 accountName
= optarg
;
833 result
= parse_fourcharcode(optarg
, &itemCreator
);
834 if (result
) goto cleanup
;
837 result
= parse_fourcharcode(optarg
, &itemType
);
838 if (result
) goto cleanup
;
841 securityDomain
= optarg
;
859 result
= parse_fourcharcode(optarg
, &protocol
);
860 if (result
) goto cleanup
;
866 result
= parse_fourcharcode(optarg
, &authenticationType
);
867 if (result
) goto cleanup
;
871 result
= 2; /* @@@ Return 2 triggers usage message. */
879 keychainOrArray
= keychain_create_array(argc
, argv
);
881 result
= do_keychain_delete_internet_password(keychainOrArray
,
896 CFRelease(keychainOrArray
);
902 keychain_find_internet_password(int argc
, char * const *argv
)
904 char *serverName
= NULL
, *securityDomain
= NULL
, *accountName
= NULL
, *path
= NULL
;
905 char *kind
= NULL
, *label
= NULL
, *comment
= NULL
;
906 FourCharCode itemCreator
= 0, itemType
= 0;
908 SecProtocolType protocol
= 0;
909 SecAuthenticationType authenticationType
= 0;
910 CFTypeRef keychainOrArray
= NULL
;
912 Boolean get_password
= FALSE
;
913 Boolean password_stdout
= FALSE
;
916 * " -a Match \"account\" string\n"
917 * " -c Match \"creator\" (four-character code)\n"
918 * " -C Match \"type\" (four-character code)\n"
919 * " -d Match \"securityDomain\" string\n"
920 * " -D Match \"kind\" string\n"
921 * " -j Match \"comment\" string\n"
922 * " -l Match \"label\" string\n"
923 * " -p Match \"path\" string\n"
924 * " -P Match port number\n"
925 * " -r Match \"protocol\" (four-character code)\n"
926 * " -s Match \"server\" string\n"
927 * " -t Match \"authenticationType\" (four-character code)\n"
928 * " -g Display the password for the item found\n"
929 * " -w Display the password(only) for the item(s) found\n"
932 while ((ch
= getopt(argc
, argv
, "ha:c:C:d:D:hgj:l:p:P:r:s:wt:")) != -1)
937 accountName
= optarg
;
940 result
= parse_fourcharcode(optarg
, &itemCreator
);
941 if (result
) goto cleanup
;
944 result
= parse_fourcharcode(optarg
, &itemType
);
945 if (result
) goto cleanup
;
948 securityDomain
= optarg
;
969 result
= parse_fourcharcode(optarg
, &protocol
);
970 if (result
) goto cleanup
;
977 password_stdout
= TRUE
;
980 result
= parse_fourcharcode(optarg
, &authenticationType
);
981 if (result
) goto cleanup
;
982 /* auth type attribute is special */
983 authenticationType
= OSSwapHostToBigInt32(authenticationType
);
987 result
= 2; /* @@@ Return 2 triggers usage message. */
995 keychainOrArray
= keychain_create_array(argc
, argv
);
997 result
= do_keychain_find_internet_password(keychainOrArray
,
1013 if (keychainOrArray
)
1014 CFRelease(keychainOrArray
);
1020 keychain_delete_generic_password(int argc
, char * const *argv
)
1022 char *serviceName
= NULL
, *accountName
= NULL
;
1023 char *kind
= NULL
, *label
= NULL
, *value
= NULL
, *comment
= NULL
;
1024 FourCharCode itemCreator
= 0, itemType
= 0;
1025 CFTypeRef keychainOrArray
= nil
;
1029 * " -a Match \"account\" string\n"
1030 * " -c Match \"creator\" (four-character code)\n"
1031 * " -C Match \"type\" (four-character code)\n"
1032 * " -D Match \"kind\" string\n"
1033 * " -G Match \"value\" string (generic attribute)\n"
1034 * " -j Match \"comment\" string\n"
1035 * " -l Match \"label\" string\n"
1036 * " -s Match \"service\" string\n"
1039 while ((ch
= getopt(argc
, argv
, "ha:c:C:D:G:j:l:s:g")) != -1)
1044 accountName
= optarg
;
1047 result
= parse_fourcharcode(optarg
, &itemCreator
);
1048 if (result
) goto cleanup
;
1051 result
= parse_fourcharcode(optarg
, &itemType
);
1052 if (result
) goto cleanup
;
1067 serviceName
= optarg
;
1071 result
= 2; /* @@@ Return 2 triggers usage message. */
1079 keychainOrArray
= keychain_create_array(argc
, argv
);
1081 result
= do_keychain_delete_generic_password(keychainOrArray
,
1091 if (keychainOrArray
)
1092 CFRelease(keychainOrArray
);
1098 keychain_find_generic_password(int argc
, char * const *argv
)
1100 char *serviceName
= NULL
, *accountName
= NULL
;
1101 char *kind
= NULL
, *label
= NULL
, *value
= NULL
, *comment
= NULL
;
1102 FourCharCode itemCreator
= 0, itemType
= 0;
1103 CFTypeRef keychainOrArray
= nil
;
1105 Boolean get_password
= FALSE
;
1106 Boolean password_stdout
= FALSE
;
1109 * " -a Match \"account\" string\n"
1110 * " -c Match \"creator\" (four-character code)\n"
1111 * " -C Match \"type\" (four-character code)\n"
1112 * " -D Match \"kind\" string\n"
1113 * " -G Match \"value\" string (generic attribute)\n"
1114 * " -j Match \"comment\" string\n"
1115 * " -l Match \"label\" string\n"
1116 * " -s Match \"service\" string\n"
1117 * " -g Display the password for the item(s) found\n"
1118 * " -w Display the password(only) for the item(s) found\n"
1121 while ((ch
= getopt(argc
, argv
, "ha:c:C:D:G:j:l:s:wg")) != -1)
1126 accountName
= optarg
;
1129 result
= parse_fourcharcode(optarg
, &itemCreator
);
1130 if (result
) goto cleanup
;
1133 result
= parse_fourcharcode(optarg
, &itemType
);
1134 if (result
) goto cleanup
;
1149 serviceName
= optarg
;
1152 password_stdout
= TRUE
;
1153 get_password
= TRUE
;
1156 get_password
= TRUE
;
1160 result
= 2; /* @@@ Return 2 triggers usage message. */
1168 keychainOrArray
= keychain_create_array(argc
, argv
);
1170 result
= do_keychain_find_generic_password(keychainOrArray
,
1182 if (keychainOrArray
)
1183 CFRelease(keychainOrArray
);
1190 keychain_find_certificate(int argc
, char * const *argv
)
1192 char *emailAddress
= NULL
;
1195 CFTypeRef keychainOrArray
= nil
;
1196 Boolean output_pem
= FALSE
;
1197 Boolean find_all
= FALSE
;
1198 Boolean print_hash
= FALSE
;
1199 Boolean print_email
= FALSE
;
1201 while ((ch
= getopt(argc
, argv
, "hac:e:mpZ")) != -1)
1212 emailAddress
= optarg
;
1225 result
= 2; /* @@@ Return 2 triggers usage message. */
1233 keychainOrArray
= keychain_create_array(argc
, argv
);
1235 result
= do_keychain_find_certificate(keychainOrArray
, name
, emailAddress
, print_hash
, output_pem
, find_all
, print_email
);
1238 if (keychainOrArray
)
1239 CFRelease(keychainOrArray
);
1246 do_keychain_dump_class(FILE *stream
, CFTypeRef keychainOrArray
, SecItemClass itemClass
, Boolean show_data
, Boolean show_raw_data
, Boolean show_acl
, Boolean interactive
)
1248 SecKeychainItemRef item
;
1249 SecKeychainSearchRef search
= NULL
;
1253 status
= SecKeychainSearchCreateFromAttributes(keychainOrArray
, itemClass
, NULL
, &search
);
1256 sec_perror("SecKeychainSearchCreateFromAttributes", status
);
1261 while ((status
= SecKeychainSearchCopyNext(search
, &item
)) == 0)
1263 print_keychain_item_attributes(stream
, item
, show_data
, show_raw_data
, show_acl
, interactive
);
1267 if (status
!= errSecItemNotFound
)
1269 sec_perror("SecKeychainSearchCopyNext", status
);
1282 do_keychain_dump(FILE *stream
, CFTypeRef keychainOrArray
, Boolean show_data
, Boolean show_raw_data
, Boolean show_acl
, Boolean interactive
)
1284 return do_keychain_dump_class(stream
, keychainOrArray
, CSSM_DL_DB_RECORD_ANY
, show_data
, show_raw_data
, show_acl
, interactive
);
1288 keychain_dump(int argc
, char * const *argv
)
1291 Boolean show_data
= FALSE
, show_raw_data
= FALSE
, show_acl
= FALSE
, interactive
= FALSE
;
1292 CFTypeRef keychainOrArray
= NULL
;
1293 const char *outputFilename
= NULL
;
1296 while ((ch
= getopt(argc
, argv
, "adhiro:")) != -1)
1311 show_raw_data
= TRUE
;
1314 outputFilename
= optarg
;
1318 return 2; /* @@@ Return 2 triggers usage message. */
1325 keychainOrArray
= keychain_create_array(argc
, argv
);
1328 output
= fopen(outputFilename
, "w");
1332 result
= do_keychain_dump(output
, keychainOrArray
, show_data
, show_raw_data
, show_acl
, interactive
);
1337 if (keychainOrArray
)
1338 CFRelease(keychainOrArray
);