singleItemPicker.cpp [plain text]
#include <clAppUtils/keyPicker.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <Security/Security.h>
#include <stdexcept>
#include <ctype.h>
#include <clAppUtils/identPicker.h>
#include <clAppUtils/keyPicker.h>
#include <vector>
#include "singleItemPicker.h"
class SimplePickerItem
{
public:
SimplePickerItem(SecKeychainItemRef itemRef);
~SimplePickerItem();
CFDataRef getPrintName() { return mPrintName; }
SecKeychainItemRef itemRef() { return mItemRef; }
char *kcFile() { return mKcFile; }
private:
SecKeychainItemRef mItemRef;
CFDataRef mPrintName;
char *mKcFile; };
SimplePickerItem::SimplePickerItem(SecKeychainItemRef itemRef)
: mItemRef(itemRef),
mPrintName(NULL),
mKcFile(NULL)
{
OSStatus ortn = getKcItemAttr(itemRef, WA_PrintName, &mPrintName);
if(ortn) {
throw std::invalid_argument("printName attr not available");
}
SecKeychainRef kcRef;
ortn = SecKeychainItemCopyKeychain(itemRef, &kcRef);
if(ortn) {
cssmPerror("SecKeychainItemCopyKeychain", ortn);
mKcFile = strdup("Unnamed keychain");
}
else {
mKcFile = kcFileName(kcRef);
}
mItemRef = mItemRef;
CFRetain(mItemRef);
}
SimplePickerItem::~SimplePickerItem()
{
if(mItemRef) {
CFRelease(mItemRef);
}
if(mPrintName) {
CFRelease(mPrintName);
}
if(mKcFile) {
free(mKcFile);
}
}
typedef std::vector<SimplePickerItem *> ItemVector;
static void getPickerItems(
SecKeychainRef kcRef,
SecItemClass itemClass, ItemVector &itemVector)
{
SecKeychainSearchRef srchRef = NULL;
SecKeychainItemRef kcItem;
OSStatus ortn = SecKeychainSearchCreateFromAttributes(kcRef,
itemClass,
NULL, &srchRef);
if(ortn) {
cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
return;
}
do {
ortn = SecKeychainSearchCopyNext(srchRef, &kcItem);
if(ortn) {
break;
}
try {
SimplePickerItem *pickerItem = new SimplePickerItem(kcItem);
itemVector.push_back(pickerItem);
}
catch(...) {
printf("**** item failed SimplePickerItem constructor ***\n");
}
CFRelease(kcItem);
} while(ortn == noErr);
CFRelease(srchRef);
}
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);
}
}
}
OSStatus singleItemPicker(
SecKeychainRef kcRef, KP_ItemType itemType,
bool takeFirst, SecKeychainItemRef *itemRef) {
SecItemClass itemClass;
OSStatus ortn = noErr;
int ires;
int dex;
int numItems = 0;
std::vector<SimplePickerItem *> items;
switch(itemType) {
case KPI_PrivateKey:
itemClass = kSecPrivateKeyItemClass;
break;
case KPI_PublicKey:
itemClass = kSecPublicKeyItemClass;
break;
case KPI_Cert:
itemClass = kSecCertificateItemClass;
break;
default:
printf("***BRRZAP! Wrong ItemType for singleItemPicker()\n");
return paramErr;
}
getPickerItems(kcRef, itemClass, items);
numItems = items.size();
if(numItems == 0) {
printf("...singleItemPicker: no keys found\n");
return errSecItemNotFound;
}
if(takeFirst) {
*itemRef = items[0]->itemRef();
CFRetain(*itemRef);
goto done;
}
for(dex=0; dex<numItems; dex++) {
SimplePickerItem *pi = items[dex];
printf("[%d] item : ", dex);
printCfData(pi->getPrintName());
printf("\n");
printf(" keychain : %s\n", pi->kcFile());
}
while(1) {
fpurge(stdin);
printf("\nEnter item number or CR to quit : ");
fflush(stdout);
char resp[64];
getString(resp, sizeof(resp));
if(resp[0] == '\0') {
ortn = CSSMERR_CSSM_USER_CANCELED;
break;
}
ires = atoi(resp);
if((ires < 0) || (ires >= numItems)) {
printf("***Invalid entry. Type a number between 0 and %d\n", numItems);
continue;
}
break;
}
if(ortn == noErr) {
*itemRef = items[ires]->itemRef();
CFRetain(*itemRef);
}
done:
for(dex=0; dex<numItems; dex++) {
delete items[dex];
}
return ortn;
}