]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/acltool/acltool.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / acltool / acltool.cpp
diff --git a/SecurityTests/cspxutils/acltool/acltool.cpp b/SecurityTests/cspxutils/acltool/acltool.cpp
new file mode 100644 (file)
index 0000000..9c6a5d6
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * 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;
+}