+++ /dev/null
-/*
- * extendAttrTool.cpp
- */
-
-#include <stdlib.h>
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include "singleItemPicker.h"
-#include <Security/SecKeychainItemExtendedAttributes.h>
-#include <Security/SecKeychainItemPriv.h>
-#include <Security/cssmapple.h>
-
-#define DEFAULT_ATTR_NAME "someAttr"
-
-static void usage(char **argv)
-{
- printf("usage: %s op [options]\n", argv[0]);
- printf("Op: set, get, delete, getall, dump\n");
- printf("Options:\n");
- printf(" -t itemType -- type = priv|pub|cert; default is public\n");
- printf(" -k keychain -- default is default KC list\n");
- printf(" -p -- use item picker; default is first matching item in keychain\n");
- printf(" -a attrName -- default is %s\n", DEFAULT_ATTR_NAME);
- printf(" -A attrValue\n");
- printf(" -n -- no values retrieved on op getall\n");
- printf(" -l -- loop/pause for malloc debug\n");
- exit(1);
-}
-
-#define CFRELEASE(cf) if(cf) { CFRelease(cf); }
-
-/*
- * Print contents of a CFData assuming it's printable
- */
-static void printCfData(CFDataRef cfd)
-{
- CFIndex len = CFDataGetLength(cfd);
- const UInt8 *cp = CFDataGetBytePtr(cfd);
- for(CFIndex dex=0; dex<len; dex++) {
- char c = cp[dex];
- if(isprint(c)) {
- putchar(c);
- }
- else {
- printf(".%02X.", c);
- }
- }
-}
-
-/* print the contents of a CFString */
-void printCfStr(
- CFStringRef cfstr)
-{
- CFDataRef strData = CFStringCreateExternalRepresentation(NULL, cfstr,
- kCFStringEncodingUTF8, true);
- if(strData == NULL) {
- printf("<<string decode error>>");
- return;
- }
- const char *cp = (const char *)CFDataGetBytePtr(strData);
- CFIndex len = CFDataGetLength(strData);
- for(CFIndex dex=0; dex<len; dex++) {
- putchar(*cp++);
- }
- CFRelease(strData);
-}
-
-/*
- * Print contents of a SecKeychainAttribute assuming it's printable
- */
-static void printAttribute(SecKeychainAttribute *kca)
-{
- unsigned len = kca->length;
- const char *cp = (const char *)kca->data;
- for(unsigned dex=0; dex<len; dex++) {
- char c = cp[dex];
- if(isprint(c)) {
- putchar(c);
- }
- else {
- printf(".%02X.", c);
- }
- }
-}
-
-/*
- * Print parallel arrays of CFStringRefs (attribute names) and optional CFDataRefs
- * (attribute values).
- */
-static int printAttrs(
- CFArrayRef nameArray,
- CFArrayRef valuesArray) /* optional */
-{
- CFIndex numNames = CFArrayGetCount(nameArray);
- if(valuesArray) {
- if(numNames != CFArrayGetCount(valuesArray)) {
- printf("***Mismatch on sizes of nameArray (%ld) and valuesArray (%ld)\n",
- numNames, CFArrayGetCount(valuesArray));
- return -1;
- }
- }
-
- for(CFIndex dex=0; dex<numNames; dex++) {
- printf("Attribute %ld:\n", (long)dex);
- CFStringRef attrName = (CFStringRef)CFArrayGetValueAtIndex(nameArray, dex);
- printf(" name : ");
- printCfStr(attrName);
- printf("\n");
- if(valuesArray) {
- CFDataRef attrValue = (CFDataRef)CFArrayGetValueAtIndex(valuesArray, dex);
- printf(" value : ");
- printCfData(attrValue);
- printf("\n");
- }
- }
- return 0;
-}
-
-/* entry in a table to map a uint32 to a string */
-typedef struct {
- uint32 value;
- const char *name;
-} NameValuePair;
-
-/* declare one entry in a table of nameValuePairs */
-#define NVP(attr) {attr, #attr}
-
-/* the NULL entry which terminates all nameValuePair tables */
-#define NVP_END {0, NULL}
-
-/* CSSM_DB_RECORDTYPE names */
-const NameValuePair recordTypeNames[] =
-{
- NVP(CSSM_DL_DB_SCHEMA_INFO),
- NVP(CSSM_DL_DB_SCHEMA_INDEXES),
- NVP(CSSM_DL_DB_SCHEMA_ATTRIBUTES),
- NVP(CSSM_DL_DB_SCHEMA_PARSING_MODULE),
- NVP(CSSM_DL_DB_RECORD_ANY),
- NVP(CSSM_DL_DB_RECORD_CERT),
- NVP(CSSM_DL_DB_RECORD_CRL),
- NVP(CSSM_DL_DB_RECORD_POLICY),
- NVP(CSSM_DL_DB_RECORD_GENERIC),
- NVP(CSSM_DL_DB_RECORD_PUBLIC_KEY),
- NVP(CSSM_DL_DB_RECORD_PRIVATE_KEY),
- NVP(CSSM_DL_DB_RECORD_SYMMETRIC_KEY),
- NVP(CSSM_DL_DB_RECORD_ALL_KEYS),
- /* Apple-specific */
- NVP(CSSM_DL_DB_RECORD_GENERIC_PASSWORD),
- NVP(CSSM_DL_DB_RECORD_INTERNET_PASSWORD),
- NVP(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD),
- NVP(CSSM_DL_DB_RECORD_X509_CERTIFICATE),
- NVP(CSSM_DL_DB_RECORD_X509_CRL),
- NVP(CSSM_DL_DB_RECORD_USER_TRUST),
- /* private to Sec layer */
- NVP(CSSM_DL_DB_RECORD_UNLOCK_REFERRAL),
- NVP_END
-};
-
-static void printRecordType(
- const void *recordTypeAttr)
-{
- UInt32 recordType = *((UInt32 *)recordTypeAttr);
- for(const NameValuePair *nvp=recordTypeNames; nvp->name; nvp++) {
- if(recordType == nvp->value) {
- printf("%s", nvp->name);
- return;
- }
- }
- printf("Unknown recordType (0x%x)\n", (unsigned)recordType);
- return;
-}
-
-
-static int dumpExtendAttrRecords(
- SecKeychainRef kcRef)
-{
- OSStatus ortn;
- SecKeychainSearchRef srchRef = NULL;
-
- ortn = SecKeychainSearchCreateFromAttributes(kcRef,
- CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE,
- NULL, // no attrs - give me everything
- &srchRef);
- if(ortn) {
- cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
- return -1;
- }
-
- SecKeychainItemRef itemRef = NULL;
- unsigned numItems = 0;
- for(;;) {
- ortn = SecKeychainSearchCopyNext(srchRef, &itemRef);
- if(ortn) {
- if(ortn == errSecItemNotFound) {
- /* normal end of search */
- break;
- }
- else {
- cssmPerror("SecKeychainSearchCopyNext", ortn);
- break;
- }
- }
-
- /* get some info about the EA record - RecordType (that it's bound to) and
- * AttributeName */
- UInt32 tags[2] = { kExtendedAttrRecordTypeAttr, kExtendedAttrAttributeNameAttr };
- UInt32 formats[2] = {0};
- SecKeychainAttributeList *attrList = NULL;
- SecKeychainAttributeInfo attrInfo = {2, tags, formats};
- ortn = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo,
- NULL, &attrList, NULL, NULL);
- if(ortn) {
- cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
- return -1;
- }
- printf("Extended Attribute %u:\n", numItems);
- for(unsigned dex=0; dex<2; dex++) {
- SecKeychainAttribute *attr = &attrList->attr[dex];
- switch(attr->tag) {
- case kExtendedAttrRecordTypeAttr:
- printf(" Record type : ");
- printRecordType(attr->data);
- printf("\n");
- break;
-
- case kExtendedAttrAttributeNameAttr:
- printf(" Attribute Name : ");
- printAttribute(attr);
- printf("\n");
- break;
- break;
- default:
- /* should never happen, right? */
- printf("***Unexpected attr tag when parsing an ExtendedAttr record\n");
- return -1;
- }
- }
- numItems++;
- SecKeychainItemFreeAttributesAndData(attrList, NULL);
- CFRelease(itemRef);
- }
- if(numItems == 0) {
- printf("...no Extended Attribute records found.\n");
- }
- CFRelease(srchRef);
- return 0;
-}
-
-typedef enum {
- OP_None,
- OP_Set,
- OP_Get,
- OP_Delete,
- OP_GetAll,
- OP_Dump // search for EXTENDED_ATTRIBUTE records, dump contents
-} Op;
-
-int main(int argc, char **argv)
-{
- const char *attrName = DEFAULT_ATTR_NAME;
- const char *attrValue = NULL;
- const char *kcName = NULL;
- KP_ItemType itemType = KPI_PublicKey;
- bool takeFirst = true;
- bool noValues = false;
- bool loopPause = false;
- Op op = OP_None;
-
- if(argc < 2) {
- usage(argv);
- }
- if(!strcmp(argv[1], "set")) {
- op = OP_Set;
- }
- else if(!strcmp(argv[1], "get")) {
- op = OP_Get;
- }
- else if(!strcmp(argv[1], "delete")) {
- op = OP_Delete;
- }
- else if(!strcmp(argv[1], "getall")) {
- op = OP_GetAll;
- }
- else if(!strcmp(argv[1], "dump")) {
- op = OP_Dump;
- }
- else {
- usage(argv);
-
- }
-
- extern int optind;
- optind = 2;
- extern char *optarg;
- int arg;
- while ((arg = getopt(argc, argv, "t:k:pa:A:nlh")) != -1) {
- switch (arg) {
- case 't':
- if(!strcmp(optarg, "priv")) {
- itemType = KPI_PrivateKey;
- }
- else if(!strcmp(optarg, "pub")) {
- itemType = KPI_PublicKey;
- }
- else if(!strcmp(optarg, "cert")) {
- itemType = KPI_Cert;
- }
- else {
- printf("***Bad itemType specification.\n");
- usage(argv);
- }
- break;
- case 'k':
- kcName = optarg;
- break;
- case 'p':
- takeFirst = false;
- break;
- case 'a':
- attrName = optarg;
- break;
- case 'A':
- attrValue = optarg;
- break;
- case 'n':
- noValues = true;
- break;
- case 'l':
- loopPause = true;
- break;
- case 'h':
- usage(argv);
- }
- }
- if(optind != argc) {
- usage(argv);
- }
-
- if((op == OP_Set) && (attrValue == NULL)) {
- printf("***I Need an attribute values (-A) to set\n");
- exit(1);
- }
-
- OSStatus ortn;
- SecKeychainItemRef theItem = NULL;
- SecKeychainRef kcRef = NULL;
-
- if(kcName) {
- ortn = SecKeychainOpen(kcName, &kcRef);
- if(ortn) {
- cssmPerror("SecKeychainOpen", ortn);
- exit(1);
- }
- }
-
- if(op == OP_Dump) {
- /* we're ready to roll */
- return dumpExtendAttrRecords(kcRef);
- }
- ortn = singleItemPicker(kcRef, itemType, takeFirst, &theItem);
- if(ortn) {
- printf("***Error picking item. Aborting.\n");
- exit(1);
- }
-
- CFStringRef attrNameStr = NULL;
- CFDataRef attrValueData = NULL;
- if(op != OP_GetAll) {
- attrNameStr = CFStringCreateWithCString(NULL, attrName, kCFStringEncodingASCII);
- }
-
- do {
- switch(op) {
- case OP_Set:
- attrValueData = CFDataCreate(NULL, (const UInt8 *)attrValue, strlen(attrValue));
- ortn = SecKeychainItemSetExtendedAttribute(theItem, attrNameStr, attrValueData);
- if(ortn) {
- cssmPerror("SecKeychainItemSetExtendedAttribute", ortn);
- }
- else {
- printf("attribute '%s' set to '%s'.\n", attrName, attrValue);
- }
- break;
- case OP_Get:
- ortn = SecKeychainItemCopyExtendedAttribute(theItem,
- attrNameStr, &attrValueData);
- if(ortn) {
- cssmPerror("SecKeychainItemCopyExtendedAttribute", ortn);
- }
- else {
- printf("Attribute '%s' found; value = '", attrName);
- printCfData(attrValueData);
- printf("'\n");
- }
- break;
- case OP_Delete:
- ortn = SecKeychainItemSetExtendedAttribute(theItem, attrNameStr, NULL);
- if(ortn) {
- cssmPerror("SecKeychainItemSetExtendedAttribute", ortn);
- }
- else {
- printf("attribute '%s' deleted.\n", attrName);
- }
- break;
- case OP_GetAll:
- {
- CFArrayRef nameArray = NULL;
- CFArrayRef valuesArray = NULL;
- CFArrayRef *valuesArrayPtr = noValues ? NULL : &valuesArray;
-
- ortn = SecKeychainItemCopyAllExtendedAttributes(theItem,
- &nameArray, valuesArrayPtr);
- if(ortn) {
- cssmPerror("SecKeychainItemCopyAllExtendedAttributes", ortn);
- break;
- }
- if(nameArray == NULL) {
- printf("***NULL nameArray after successful "
- "SecKeychainItemCopyAllExtendedAttributes\n");
- ortn = -1;
- break;
- }
- if(!noValues) {
- if(valuesArray == NULL) {
- printf("***NULL valuesArray after successful "
- "SecKeychainItemCopyAllExtendedAttributes\n");
- ortn = -1;
- break;
- }
- }
- ortn = printAttrs(nameArray, valuesArray);
- CFRELEASE(nameArray);
- CFRELEASE(valuesArray);
- break;
- }
- case OP_Dump:
- /* already handled this; satisfy compiler */
- break;
- case OP_None:
- printf("***BRRRZAP!\n");
- exit(1);
- }
- if(ortn) {
- break;
- }
- CFRELEASE(attrValueData);
- attrValueData = NULL;
-
- if(loopPause) {
- fpurge(stdin);
- printf("End of loop; a to abort, anything else to continue: ");
- if(getchar() == 'a') {
- break;
- }
- }
- } while(loopPause);
- return ortn ? -1 : 0;
-}