9 #include "singleItemPicker.h"
10 #include <Security/SecKeychainItemExtendedAttributes.h>
11 #include <Security/SecKeychainItemPriv.h>
12 #include <Security/cssmapple.h>
14 #define DEFAULT_ATTR_NAME "someAttr"
16 static void usage(char **argv
)
18 printf("usage: %s op [options]\n", argv
[0]);
19 printf("Op: set, get, delete, getall, dump\n");
21 printf(" -t itemType -- type = priv|pub|cert; default is public\n");
22 printf(" -k keychain -- default is default KC list\n");
23 printf(" -p -- use item picker; default is first matching item in keychain\n");
24 printf(" -a attrName -- default is %s\n", DEFAULT_ATTR_NAME
);
25 printf(" -A attrValue\n");
26 printf(" -n -- no values retrieved on op getall\n");
27 printf(" -l -- loop/pause for malloc debug\n");
31 #define CFRELEASE(cf) if(cf) { CFRelease(cf); }
34 * Print contents of a CFData assuming it's printable
36 static void printCfData(CFDataRef cfd
)
38 CFIndex len
= CFDataGetLength(cfd
);
39 const UInt8
*cp
= CFDataGetBytePtr(cfd
);
40 for(CFIndex dex
=0; dex
<len
; dex
++) {
51 /* print the contents of a CFString */
55 CFDataRef strData
= CFStringCreateExternalRepresentation(NULL
, cfstr
,
56 kCFStringEncodingUTF8
, true);
58 printf("<<string decode error>>");
61 const char *cp
= (const char *)CFDataGetBytePtr(strData
);
62 CFIndex len
= CFDataGetLength(strData
);
63 for(CFIndex dex
=0; dex
<len
; dex
++) {
70 * Print contents of a SecKeychainAttribute assuming it's printable
72 static void printAttribute(SecKeychainAttribute
*kca
)
74 unsigned len
= kca
->length
;
75 const char *cp
= (const char *)kca
->data
;
76 for(unsigned dex
=0; dex
<len
; dex
++) {
88 * Print parallel arrays of CFStringRefs (attribute names) and optional CFDataRefs
91 static int printAttrs(
93 CFArrayRef valuesArray
) /* optional */
95 CFIndex numNames
= CFArrayGetCount(nameArray
);
97 if(numNames
!= CFArrayGetCount(valuesArray
)) {
98 printf("***Mismatch on sizes of nameArray (%ld) and valuesArray (%ld)\n",
99 numNames
, CFArrayGetCount(valuesArray
));
104 for(CFIndex dex
=0; dex
<numNames
; dex
++) {
105 printf("Attribute %ld:\n", (long)dex
);
106 CFStringRef attrName
= (CFStringRef
)CFArrayGetValueAtIndex(nameArray
, dex
);
108 printCfStr(attrName
);
111 CFDataRef attrValue
= (CFDataRef
)CFArrayGetValueAtIndex(valuesArray
, dex
);
113 printCfData(attrValue
);
120 /* entry in a table to map a uint32 to a string */
126 /* declare one entry in a table of nameValuePairs */
127 #define NVP(attr) {attr, #attr}
129 /* the NULL entry which terminates all nameValuePair tables */
130 #define NVP_END {0, NULL}
132 /* CSSM_DB_RECORDTYPE names */
133 const NameValuePair recordTypeNames
[] =
135 NVP(CSSM_DL_DB_SCHEMA_INFO
),
136 NVP(CSSM_DL_DB_SCHEMA_INDEXES
),
137 NVP(CSSM_DL_DB_SCHEMA_ATTRIBUTES
),
138 NVP(CSSM_DL_DB_SCHEMA_PARSING_MODULE
),
139 NVP(CSSM_DL_DB_RECORD_ANY
),
140 NVP(CSSM_DL_DB_RECORD_CERT
),
141 NVP(CSSM_DL_DB_RECORD_CRL
),
142 NVP(CSSM_DL_DB_RECORD_POLICY
),
143 NVP(CSSM_DL_DB_RECORD_GENERIC
),
144 NVP(CSSM_DL_DB_RECORD_PUBLIC_KEY
),
145 NVP(CSSM_DL_DB_RECORD_PRIVATE_KEY
),
146 NVP(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
),
147 NVP(CSSM_DL_DB_RECORD_ALL_KEYS
),
149 NVP(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
),
150 NVP(CSSM_DL_DB_RECORD_INTERNET_PASSWORD
),
151 NVP(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD
),
152 NVP(CSSM_DL_DB_RECORD_X509_CERTIFICATE
),
153 NVP(CSSM_DL_DB_RECORD_X509_CRL
),
154 NVP(CSSM_DL_DB_RECORD_USER_TRUST
),
155 /* private to Sec layer */
156 NVP(CSSM_DL_DB_RECORD_UNLOCK_REFERRAL
),
160 static void printRecordType(
161 const void *recordTypeAttr
)
163 UInt32 recordType
= *((UInt32
*)recordTypeAttr
);
164 for(const NameValuePair
*nvp
=recordTypeNames
; nvp
->name
; nvp
++) {
165 if(recordType
== nvp
->value
) {
166 printf("%s", nvp
->name
);
170 printf("Unknown recordType (0x%x)\n", (unsigned)recordType
);
175 static int dumpExtendAttrRecords(
176 SecKeychainRef kcRef
)
179 SecKeychainSearchRef srchRef
= NULL
;
181 ortn
= SecKeychainSearchCreateFromAttributes(kcRef
,
182 CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE
,
183 NULL
, // no attrs - give me everything
186 cssmPerror("SecKeychainSearchCreateFromAttributes", ortn
);
190 SecKeychainItemRef itemRef
= NULL
;
191 unsigned numItems
= 0;
193 ortn
= SecKeychainSearchCopyNext(srchRef
, &itemRef
);
195 if(ortn
== errSecItemNotFound
) {
196 /* normal end of search */
200 cssmPerror("SecKeychainSearchCopyNext", ortn
);
205 /* get some info about the EA record - RecordType (that it's bound to) and
207 UInt32 tags
[2] = { kExtendedAttrRecordTypeAttr
, kExtendedAttrAttributeNameAttr
};
208 UInt32 formats
[2] = {0};
209 SecKeychainAttributeList
*attrList
= NULL
;
210 SecKeychainAttributeInfo attrInfo
= {2, tags
, formats
};
211 ortn
= SecKeychainItemCopyAttributesAndData(itemRef
, &attrInfo
,
212 NULL
, &attrList
, NULL
, NULL
);
214 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn
);
217 printf("Extended Attribute %u:\n", numItems
);
218 for(unsigned dex
=0; dex
<2; dex
++) {
219 SecKeychainAttribute
*attr
= &attrList
->attr
[dex
];
221 case kExtendedAttrRecordTypeAttr
:
222 printf(" Record type : ");
223 printRecordType(attr
->data
);
227 case kExtendedAttrAttributeNameAttr
:
228 printf(" Attribute Name : ");
229 printAttribute(attr
);
234 /* should never happen, right? */
235 printf("***Unexpected attr tag when parsing an ExtendedAttr record\n");
240 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
244 printf("...no Extended Attribute records found.\n");
256 OP_Dump
// search for EXTENDED_ATTRIBUTE records, dump contents
259 int main(int argc
, char **argv
)
261 const char *attrName
= DEFAULT_ATTR_NAME
;
262 const char *attrValue
= NULL
;
263 const char *kcName
= NULL
;
264 KP_ItemType itemType
= KPI_PublicKey
;
265 bool takeFirst
= true;
266 bool noValues
= false;
267 bool loopPause
= false;
273 if(!strcmp(argv
[1], "set")) {
276 else if(!strcmp(argv
[1], "get")) {
279 else if(!strcmp(argv
[1], "delete")) {
282 else if(!strcmp(argv
[1], "getall")) {
285 else if(!strcmp(argv
[1], "dump")) {
297 while ((arg
= getopt(argc
, argv
, "t:k:pa:A:nlh")) != -1) {
300 if(!strcmp(optarg
, "priv")) {
301 itemType
= KPI_PrivateKey
;
303 else if(!strcmp(optarg
, "pub")) {
304 itemType
= KPI_PublicKey
;
306 else if(!strcmp(optarg
, "cert")) {
310 printf("***Bad itemType specification.\n");
340 if((op
== OP_Set
) && (attrValue
== NULL
)) {
341 printf("***I Need an attribute values (-A) to set\n");
346 SecKeychainItemRef theItem
= NULL
;
347 SecKeychainRef kcRef
= NULL
;
350 ortn
= SecKeychainOpen(kcName
, &kcRef
);
352 cssmPerror("SecKeychainOpen", ortn
);
358 /* we're ready to roll */
359 return dumpExtendAttrRecords(kcRef
);
361 ortn
= singleItemPicker(kcRef
, itemType
, takeFirst
, &theItem
);
363 printf("***Error picking item. Aborting.\n");
367 CFStringRef attrNameStr
= NULL
;
368 CFDataRef attrValueData
= NULL
;
369 if(op
!= OP_GetAll
) {
370 attrNameStr
= CFStringCreateWithCString(NULL
, attrName
, kCFStringEncodingASCII
);
376 attrValueData
= CFDataCreate(NULL
, (const UInt8
*)attrValue
, strlen(attrValue
));
377 ortn
= SecKeychainItemSetExtendedAttribute(theItem
, attrNameStr
, attrValueData
);
379 cssmPerror("SecKeychainItemSetExtendedAttribute", ortn
);
382 printf("attribute '%s' set to '%s'.\n", attrName
, attrValue
);
386 ortn
= SecKeychainItemCopyExtendedAttribute(theItem
,
387 attrNameStr
, &attrValueData
);
389 cssmPerror("SecKeychainItemCopyExtendedAttribute", ortn
);
392 printf("Attribute '%s' found; value = '", attrName
);
393 printCfData(attrValueData
);
398 ortn
= SecKeychainItemSetExtendedAttribute(theItem
, attrNameStr
, NULL
);
400 cssmPerror("SecKeychainItemSetExtendedAttribute", ortn
);
403 printf("attribute '%s' deleted.\n", attrName
);
408 CFArrayRef nameArray
= NULL
;
409 CFArrayRef valuesArray
= NULL
;
410 CFArrayRef
*valuesArrayPtr
= noValues
? NULL
: &valuesArray
;
412 ortn
= SecKeychainItemCopyAllExtendedAttributes(theItem
,
413 &nameArray
, valuesArrayPtr
);
415 cssmPerror("SecKeychainItemCopyAllExtendedAttributes", ortn
);
418 if(nameArray
== NULL
) {
419 printf("***NULL nameArray after successful "
420 "SecKeychainItemCopyAllExtendedAttributes\n");
425 if(valuesArray
== NULL
) {
426 printf("***NULL valuesArray after successful "
427 "SecKeychainItemCopyAllExtendedAttributes\n");
432 ortn
= printAttrs(nameArray
, valuesArray
);
433 CFRELEASE(nameArray
);
434 CFRELEASE(valuesArray
);
438 /* already handled this; satisfy compiler */
441 printf("***BRRRZAP!\n");
447 CFRELEASE(attrValueData
);
448 attrValueData
= NULL
;
452 printf("End of loop; a to abort, anything else to continue: ");
453 if(getchar() == 'a') {
458 return ortn
? -1 : 0;