+++ /dev/null
-/*
- * acltool.cpp - display and manipluate ACLs on SecKeychainItems
- */
-
-#include <stdlib.h>
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#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;
-}