X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/acltool/acltool.cpp diff --git a/SecurityTests/cspxutils/acltool/acltool.cpp b/SecurityTests/cspxutils/acltool/acltool.cpp new file mode 100644 index 00000000..9c6a5d69 --- /dev/null +++ b/SecurityTests/cspxutils/acltool/acltool.cpp @@ -0,0 +1,327 @@ +/* + * acltool.cpp - display and manipluate ACLs on SecKeychainItems + */ + +#include +#include +#include +#include +#include +#include "aclUtils.h" + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("op:\n"); + printf(" d -- display ACL\n"); + printf(" a -- add ACL\n"); + printf(" l -- lookup, dump label; no ACL operation\n"); + printf(" m -- modify data (only allowed for password items; must specify -p)\n"); + printf("Options:\n"); + printf(" -k keychain\n"); + printf(" -t itemType : k=privateKey, b=publicKey s=sessionKey, p=password; default is sessionKey\n"); + printf(" -l label_or_printName\n"); + printf(" -p new_password_data\n"); + printf(" -d -- dump data\n"); + printf(" -e -- edit ACL entries\n"); + printf(" -s -- simulate StickyRecord ACL\n"); + /* etc. */ + exit(1); +} + + +/* print an item's label and (optionally) its data */ +static OSStatus printItemLabelAndData( + SecKeychainItemRef itemRef, + SecItemAttr labelAttr, + bool dumpData) +{ + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + UInt32 length = 0; + void *outData = NULL; + + attr.tag = labelAttr; + attr.length = 0; + attr.data = NULL; + attrList.count = 1; + attrList.attr = &attr; + + OSStatus ortn = SecKeychainItemCopyContent(itemRef, + NULL, // itemClass - we know + &attrList, // for label + dumpData ? &length : 0, + dumpData ? &outData : NULL); + if(ortn) { + cssmPerror("SecKeychainItemCopyContent", ortn); + printf("***Error fetching label %s\n", dumpData ? "and data" : ""); + return ortn; + } + + if(attr.data == NULL) { + printf("**No label attribute found\n"); + } + else { + printf("Label: "); + print_buffer(stdout, attr.length, attr.data); + printf("\n"); + } + if(dumpData) { + if(outData == NULL) { + printf("***Asked for data but none found\n"); + } + else { + printf("Data : "); + print_buffer(stdout, length, outData); + printf("\n"); + } + } + SecKeychainItemFreeContent(&attrList, outData); + return noErr; +} + +/* + * Lookup by itemClass and optional label. Then do one or more of: + * + * -- dump label (always done) + * -- dump ACLs + * -- edit acl + * -- dump data + * -- set (modify) data + */ +static OSStatus dumpAcls( + SecKeychainRef kcRef, + + /* item specification */ + SecItemClass itemClass, + SecItemAttr labelAttr, // to look up by label if specified + const char *label, + + /* what we do with the item(s) found */ + bool dumpData, + bool dumpAcl, + bool editAcl, + bool simulateStickyRecord, + const unsigned char *newData, // if non-NULL, set/modify new data + unsigned newDataLen) +{ + OSStatus ortn; + SecKeychainSearchRef srchRef; + SecKeychainAttributeList attrList; + SecKeychainAttributeList *attrListP = NULL; + SecKeychainAttribute attr; + unsigned numFound = 0; + + /* searching by label, or blindly? */ + if(label) { + attr.tag = labelAttr; + attr.length = strlen(label); + attr.data = (void *)label; + attrList.count = 1; + attrList.attr = &attr; + attrListP = &attrList; + } + ortn = SecKeychainSearchCreateFromAttributes(kcRef, + itemClass, + attrListP, + &srchRef); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + for(;;) { + SecKeychainItemRef itemRef; + ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); + if(ortn) { + if(ortn == errSecItemNotFound) { + /* normal search end */ + ortn = noErr; + } + else { + cssmPerror("SecKeychainSearchCopyNext", ortn); + } + break; + } + + printf("Item %u:\n", numFound++); + printItemLabelAndData(itemRef, labelAttr, dumpData); + + if(newData) { + ortn = SecKeychainItemModifyAttributesAndData(itemRef, + NULL, // attrList - we don't change any attrs + newDataLen, + newData); + if(ortn) { + cssmPerror("SecKeychainItemModifyAttributesAndData", ortn); + printf("***Cannot modify data of this item***\n"); + goto endOfLoop; + } + } + if(dumpAcl) { + SecAccessRef accessRef = nil; + ortn = SecKeychainItemCopyAccess(itemRef, &accessRef); + if(ortn) { + cssmPerror("SecKeychainItemCopyAccess", ortn); + printf("***No SecAccessRef found***\n"); + goto endOfLoop; + } + print_access(stdout, accessRef, editAcl); + if(simulateStickyRecord) { + ortn = stickyRecordUpdateAcl(accessRef); + if(ortn) { + goto endOfLoop; + } + } + if(editAcl || simulateStickyRecord) { + ortn = SecKeychainItemSetAccess(itemRef, accessRef); + if(ortn) { + cssmPerror("SecKeychainItemSetAccess", ortn); + } + } + } +endOfLoop: + CFRelease(itemRef); + if(ortn) { + break; + } + } + CFRelease(srchRef); + printf("...%u items found\n", numFound); + return ortn; +} + +typedef enum { + AO_Dump, + AO_Add, + AO_Lookup, + AO_ModifyPassword +} AclOp; + +int main(int argc, char **argv) +{ + /* user spec'd variables */ + const char *kcName = NULL; + const char *labelOrName = NULL; // attribute type varies per + AclOp op = AO_Dump; + SecItemClass itemClass = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + /* FIXME why does this work like this for keys? doc says kSecKeyPrintName but that doesn't work */ + SecItemAttr labelAttr = kSecLabelItemAttr; + bool dumpData = false; + bool editAcl = false; + bool dumpAcl = true; + bool simulateStickyRecord = false; + const char *newPassword = NULL; + unsigned newPasswordLen = 0; + + SecKeychainRef kcRef = nil; + OSStatus ortn; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'd': + op = AO_Dump; + break; + case 'a': + op = AO_Add; + break; + case 'l': + op = AO_Lookup; + dumpAcl = false; + break; + case 'm': + op = AO_ModifyPassword; + dumpAcl = false; + break; + default: + usage(argv); + } + + extern char *optarg; + int arg; + extern int optind; + optind = 2; + while ((arg = getopt(argc, argv, "k:t:l:dep:sh")) != -1) { + switch (arg) { + case 'k': + kcName = optarg; + break; + case 't': + switch(optarg[0]) { + case 'k': + itemClass = CSSM_DL_DB_RECORD_PRIVATE_KEY; + break; + case 's': + itemClass = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + break; + case 'b': + itemClass = CSSM_DL_DB_RECORD_PUBLIC_KEY; + break; + case 'p': + itemClass = kSecGenericPasswordItemClass; + labelAttr = kSecLabelItemAttr; + break; + default: + usage(argv); + } + break; + case 'l': + labelOrName = optarg; + break; + case 'd': + dumpData = true; + break; + case 'e': + editAcl = true; + break; + case 'p': + newPassword = optarg; + newPasswordLen = strlen(newPassword); + break; + case 's': + simulateStickyRecord = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + if(op == AO_ModifyPassword) { + if(itemClass != kSecGenericPasswordItemClass) { + printf("***You can only modify data on a password item.\n"); + exit(1); + } + if(newPassword == NULL) { + printf("***You must supply new password data for this operation.\n"); + exit(1); + } + } + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + printf("***Error opening keychain %s. Aborting.\n", kcName); + exit(1); + } + } + + switch(op) { + case AO_Dump: + case AO_Lookup: + case AO_ModifyPassword: + ortn = dumpAcls(kcRef, itemClass, labelAttr, labelOrName, dumpData, dumpAcl, editAcl, + simulateStickyRecord, (unsigned char *)newPassword, newPasswordLen); + break; + case AO_Add: + printf("Add ACL op to be implemented real soon now\n"); + ortn = -1; + break; + } + if(kcRef) { + CFRelease(kcRef); + } + return (int)ortn; +}