trustApps.cpp   [plain text]


/*
 * trustApps.cpp - set list of trusted apps for specified executable
 */
#include <Security/Security.h>
#include <stdio.h>
#include <stdlib.h>
#include <utilLib/common.h>
#include <clAppUtils/identPicker.h>

static void usage(char **argv)
{
	printf("Usage: %s keychain [-q(uiet)] executable ...\n", argv[0]);
	exit(1);
}

int main(int argc, char **argv)
{
	if(argc < 3) {
		usage(argv);
	}

	const char *keychainName = argv[1];
	int nextArg; 
	bool quiet = false;
	OSStatus ortn;
	
	for(nextArg=2; nextArg<argc; ) {
		char *argp = argv[nextArg];
		if(argp[0] != '-') {
			break;
		}
		switch(argp[2]) {
			case 'q':
				quiet = true;
				break;
			default:
				usage(argv);
		}
	}
	if(nextArg == argc) {
		usage(argv);
	}

	/* create an array of SecTrustedApplications */
	CFMutableArrayRef appList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	for(; nextArg<argc; nextArg++) {
		SecTrustedApplicationRef appRef;
		ortn = SecTrustedApplicationCreateFromPath(argv[nextArg], &appRef);
		if(ortn) {
			cssmPerror("SecTrustedApplicationCreateFromPath", ortn);
			exit(1);
		}
		CFArrayAppendValue(appList, appRef);
	}

	/* Find a signing identity; extract its private key */
	SecKeychainRef kcRef;
	ortn = SecKeychainOpen(keychainName, &kcRef);
	if(ortn) {
		cssmPerror("SecKeychainOpen", ortn);
		exit(1);
	}
	SecIdentityRef identRef;
	ortn = sslSimpleIdentPicker(kcRef, &identRef);
	if(ortn) {
		exit(1);
	}
	
	SecKeyRef keyRef;
	ortn = SecIdentityCopyPrivateKey(identRef, &keyRef);
	if(ortn) {
		cssmPerror("SecIdentityCopyPrivateKey", ortn);
		exit(1);
	}
	
	/*
	 * Get existing ACL list (may be empty)
	 */
	SecAccessRef accessRef;
	CFArrayRef aclList = NULL;
	ortn = SecKeychainItemCopyAccess((SecKeychainItemRef)keyRef, &accessRef);
	if(ortn) {
		cssmPerror("SecIdentityCopyPrivateKey", ortn);
		exit(1);
	}
	ortn = SecAccessCopySelectedACLList(accessRef, CSSM_ACL_AUTHORIZATION_DECRYPT, 
		&aclList);
	if(ortn) {
		cssmPerror("SecAccessCopySelectedACLList", ortn);
		exit(1);
	}
	if((aclList == NULL) || (CFArrayGetCount(aclList) == 0)) {
		printf("No ACL list found. I don't know how to set the trusted app list.\n");
		exit(1);
	}
	
	/* append our app list to each ACL's trusted app list */
	for(int aclDex=0; aclDex<CFArrayGetCount(aclList); aclDex++) {
		
		/* get existing app list */
		SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(aclList, aclDex);
		CFArrayRef existApps = NULL;
		CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
		CFStringRef promptDescription;
		
		ortn = SecACLCopySimpleContents(aclRef, &existApps, &promptDescription, 
			&promptSelector);
		if(ortn) {
			cssmPerror("SecACLCopySimpleContents", ortn);
			exit(1);
		}
		
		/* appends its contents to our list */
		if(existApps != NULL) {
			for(int i=0; i<CFArrayGetCount(existApps); i++) {
				CFArrayAppendValue(appList, CFArrayGetValueAtIndex(existApps, i));
			}
		}
		
		/* turn off possible keychain prompt flag */
		promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE;
		
		/* Update */
		ortn = SecACLSetSimpleContents(aclRef, appList, promptDescription, 
			&promptSelector);
		if(ortn) {
			cssmPerror("SecACLCopySimpleContents", ortn);
			exit(1);
		}
		if(existApps != NULL) {
			CFRelease(existApps);
		}
	}
	
	/* presumably we're been operating on "the" ACL list in "the" SecAccess,
	 * not a separate copy... */
	ortn =	SecKeychainItemSetAccess((SecKeychainItemRef)keyRef, accessRef);
	if(ortn) {
		cssmPerror("SecKeychainItemSetAccess", ortn);
		exit(1);
	}

	/* is that it? */
	CFRelease(appList);
	CFRelease(kcRef);
	CFRelease(identRef);
	CFRelease(keyRef);
	CFRelease(accessRef);
	CFRelease(aclList);
	if(!quiet) {
		printf("...success\n");
	}
}