]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/extendAttrTool/singleItemPicker.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / extendAttrTool / singleItemPicker.cpp
1 /*
2 * Copyright (c) 2004,2006 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * singleItemPicker.cpp - select a key or cert from a keychain
26 */
27
28 #include <clAppUtils/keyPicker.h>
29 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
30 #include <Security/Security.h>
31 #include <stdexcept>
32 #include <ctype.h>
33 #include <clAppUtils/identPicker.h> /* for kcFileName() */
34 #include <clAppUtils/keyPicker.h> /* for getKcItemAttr() */
35 #include <vector>
36 #include "singleItemPicker.h"
37
38 /*
39 * Class representing one item in the keychain.
40 */
41 class SimplePickerItem
42 {
43 public:
44 SimplePickerItem(SecKeychainItemRef itemRef);
45 ~SimplePickerItem();
46
47 CFDataRef getPrintName() { return mPrintName; }
48 SecKeychainItemRef itemRef() { return mItemRef; }
49 char *kcFile() { return mKcFile; }
50
51 private:
52 SecKeychainItemRef mItemRef;
53 CFDataRef mPrintName;
54 char *mKcFile; // file name of keychain this lives on
55 };
56
57 SimplePickerItem::SimplePickerItem(SecKeychainItemRef itemRef)
58 : mItemRef(itemRef),
59 mPrintName(NULL),
60 mKcFile(NULL)
61 {
62 OSStatus ortn = getKcItemAttr(itemRef, WA_PrintName, &mPrintName);
63 if(ortn) {
64 throw std::invalid_argument("printName attr not available");
65 }
66
67 /* stash name of the keychain this lives on */
68 SecKeychainRef kcRef;
69 ortn = SecKeychainItemCopyKeychain(itemRef, &kcRef);
70 if(ortn) {
71 cssmPerror("SecKeychainItemCopyKeychain", ortn);
72 mKcFile = strdup("Unnamed keychain");
73 }
74 else {
75 mKcFile = kcFileName(kcRef);
76 }
77
78 mItemRef = mItemRef;
79 CFRetain(mItemRef);
80 }
81
82 SimplePickerItem::~SimplePickerItem()
83 {
84 if(mItemRef) {
85 CFRelease(mItemRef);
86 }
87 if(mPrintName) {
88 CFRelease(mPrintName);
89 }
90 if(mKcFile) {
91 free(mKcFile);
92 }
93 }
94
95 typedef std::vector<SimplePickerItem *> ItemVector;
96
97 /*
98 * add SimplePickerItem objects of specified type to a ItemVector.
99 */
100 static void getPickerItems(
101 SecKeychainRef kcRef,
102 SecItemClass itemClass, // CSSM_DL_DB_RECORD_{PRIVATE,PRIVATE}_KEY, etc.
103 ItemVector &itemVector)
104 {
105 SecKeychainSearchRef srchRef = NULL;
106 SecKeychainItemRef kcItem;
107
108 OSStatus ortn = SecKeychainSearchCreateFromAttributes(kcRef,
109 itemClass,
110 NULL, // any attrs
111 &srchRef);
112 if(ortn) {
113 cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
114 return;
115 }
116 do {
117 ortn = SecKeychainSearchCopyNext(srchRef, &kcItem);
118 if(ortn) {
119 break;
120 }
121 try {
122 SimplePickerItem *pickerItem = new SimplePickerItem(kcItem);
123 itemVector.push_back(pickerItem);
124 }
125 catch(...) {
126 printf("**** item failed SimplePickerItem constructor ***\n");
127 /* but keep going */
128 }
129 /* SimplePickerKey holds a ref */
130 CFRelease(kcItem);
131 } while(ortn == noErr);
132 CFRelease(srchRef);
133 }
134
135 /*
136 * Print contents of a CFData assuming it's printable
137 */
138 static void printCfData(CFDataRef cfd)
139 {
140 CFIndex len = CFDataGetLength(cfd);
141 const UInt8 *cp = CFDataGetBytePtr(cfd);
142 for(CFIndex dex=0; dex<len; dex++) {
143 char c = cp[dex];
144 if(isprint(c)) {
145 putchar(c);
146 }
147 else {
148 printf(".%02X.", c);
149 }
150 }
151 }
152
153 OSStatus singleItemPicker(
154 SecKeychainRef kcRef, // NULL means the default list
155 KP_ItemType itemType,
156 bool takeFirst, // take first key found
157 SecKeychainItemRef *itemRef) // RETURNED
158 {
159
160 SecItemClass itemClass;
161 OSStatus ortn = noErr;
162 int ires;
163 int dex;
164 int numItems = 0;
165 std::vector<SimplePickerItem *> items;
166
167 switch(itemType) {
168 case KPI_PrivateKey:
169 itemClass = kSecPrivateKeyItemClass;
170 break;
171 case KPI_PublicKey:
172 itemClass = kSecPublicKeyItemClass;
173 break;
174 case KPI_Cert:
175 itemClass = kSecCertificateItemClass;
176 break;
177 default:
178 printf("***BRRZAP! Wrong ItemType for singleItemPicker()\n");
179 return paramErr;
180 }
181 /* First create a arrays of all of the items, parsed and ready for use */
182 getPickerItems(kcRef, itemClass, items);
183 numItems = items.size();
184
185 if(numItems == 0) {
186 printf("...singleItemPicker: no keys found\n");
187 return errSecItemNotFound;
188 }
189 if(takeFirst) {
190 *itemRef = items[0]->itemRef();
191 CFRetain(*itemRef);
192 goto done;
193 }
194
195 for(dex=0; dex<numItems; dex++) {
196 /* display */
197 SimplePickerItem *pi = items[dex];
198 printf("[%d] item : ", dex);
199 printCfData(pi->getPrintName());
200 printf("\n");
201 printf(" keychain : %s\n", pi->kcFile());
202 }
203 while(1) {
204 fpurge(stdin);
205 printf("\nEnter item number or CR to quit : ");
206 fflush(stdout);
207 char resp[64];
208 getString(resp, sizeof(resp));
209 if(resp[0] == '\0') {
210 ortn = CSSMERR_CSSM_USER_CANCELED;
211 break;
212 }
213 ires = atoi(resp);
214 if((ires < 0) || (ires >= numItems)) {
215 printf("***Invalid entry. Type a number between 0 and %d\n", numItems);
216 continue;
217 }
218 break;
219 }
220
221 if(ortn == noErr) {
222 *itemRef = items[ires]->itemRef();
223 CFRetain(*itemRef);
224 }
225
226 done:
227 /* clean out SimplePickerItem array */
228 for(dex=0; dex<numItems; dex++) {
229 delete items[dex];
230 }
231 return ortn;
232 }
233