--- /dev/null
+/*
+ * rootStoreTool.cpp - exercise SecTrustSettings API
+ */
+
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <Security/Security.h>
+#include <Security/SecTrustSettings.h>
+#include <Security/SecTrustPriv.h>
+#include <Security/TrustSettingsSchema.h>
+#include <Security/SecTrustSettingsPriv.h>
+#include <Security/cssmapplePriv.h>
+#include <Security/SecPolicyPriv.h>
+#include <security_cdsa_utils/cuFileIo.h>
+#include <security_utilities/cfutilities.h>
+#include <security_cdsa_utils/cuPrintCert.h>
+#include <security_cdsa_utils/cuOidParser.h>
+#include "parseTrustedRootList.h"
+#include <Security/TrustSettingsSchema.h> /* private header */
+#include "rootUtils.h"
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+#include <pthread.h>
+#include <sys/param.h>
+
+static void usage(char **argv)
+{
+ printf("usage: %s op [options]\n", argv[0]);
+ printf("Op values:\n");
+ printf(" a -- add cert\n");
+ printf(" p -- parse TrustSettings record\n");
+ printf(" r -- get certs from TS & display\n");
+ printf(" d -- delete entries from TS interactively\n");
+ printf(" D -- delete ALL certs from TS (requires -R argument)\n");
+ printf(" R -- remove legacy User Trust setting\n");
+
+ printf("Options:\n");
+ printf(" -c certFile -- specify cert\n");
+ printf(" -s -- system TrustSettings; default is user\n");
+ printf(" -d -- Admin TrustSettings; default is user\n");
+ printf(" -t settingsFile -- settings from file; default is user\n");
+ printf(" -T settingsFileOut -- settings to file\n");
+ printf(" -a appPath -- specify app constraints\n");
+ printf(" -p policy -- specify policy constraint\n");
+ printf(" policy = ssl, smime, swuSign, codeSign, IPSec, iChat\n");
+ printf(" -P appPath policy -- specify app AND policy constraint\n");
+ printf(" -e emailAddress -- specify SMIME policy plus email address\n");
+ printf(" -L hostname -- specify SSL policy plus hostname\n");
+ printf(" -r resultType -- resultType = trust, trustAsRoot, deny, unspecified\n");
+ printf(" -w allowErr -- allowed error, an integer; implies result unspecified\n");
+ printf(" -W allowErr policy -- allowed error AND policy AND implies result unspecified\n");
+ printf(" -u keyUsage -- key usage, an integer\n");
+ printf(" -k keychain -- Default is default keychain.\n");
+ printf(" -R -- Really. For Delete All op.\n");
+ printf(" -v -- verbose cert display\n");
+ printf(" -A -- add cert to keychain\n");
+ printf(" -U -- use SecTrustSetUserTrust\n");
+ printf(" -2 -- use SecTrustSetUserTrustLegacy\n");
+ printf(" -l -- loop and pause for malloc debug\n");
+ printf(" -h -- help\n");
+ exit(1);
+}
+
+/*
+ * Start up a CFRunLoop. This is needed to field keychain event callbacks, used
+ * to maintain root cert cache coherency. This operation is only needed in command
+ * line tools; regular GUI apps already have a CFRunLoop.
+ */
+
+/* first we need something to register so we *have* a run loop */
+static OSStatus kcCacheCallback (
+ SecKeychainEvent keychainEvent,
+ SecKeychainCallbackInfo *info,
+ void *context)
+{
+ return noErr;
+}
+
+/* main thread has to wait for this to be set to know a run loop has been set up */
+static int runLoopInitialized = 0;
+
+/* this is the thread which actually runs the CFRunLoop */
+void *cfRunLoopThread(void *arg)
+{
+ OSStatus ortn = SecKeychainAddCallback(kcCacheCallback,
+ kSecTrustSettingsChangedEventMask, NULL);
+ if(ortn) {
+ printf("registerCacheCallbacks: SecKeychainAddCallback returned %ld", ortn);
+ /* Not sure how this could ever happen - maybe if there is no run loop active? */
+ return NULL;
+ }
+ runLoopInitialized = 1;
+ CFRunLoopRun();
+ /* should not be reached */
+ printf("\n*** Hey! CFRunLoopRun() exited!***\n");
+ return NULL;
+}
+
+static int startCFRunLoop()
+{
+ pthread_t runLoopThread;
+
+ int result = pthread_create(&runLoopThread, NULL, cfRunLoopThread, NULL);
+ if(result) {
+ printf("***pthread_create returned %d, aborting\n", result);
+ return -1;
+ }
+ return 0;
+}
+
+static SecCertificateRef certFromFile(
+ const char *fileName)
+{
+ unsigned char *cp = NULL;
+ unsigned len = 0;
+ if(readFile(fileName, &cp, &len)) {
+ printf("***Error reading file %s\n", fileName);
+ return NULL;
+ }
+ SecCertificateRef certRef;
+ CSSM_DATA certData = {len, cp};
+ OSStatus ortn = SecCertificateCreateFromData(&certData,
+ CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef);
+ if(ortn) {
+ cssmPerror("SecCertificateCreateFromData", ortn);
+ return NULL;
+ }
+ free(cp);
+ return certRef;
+}
+
+/*
+ * Display usage constraints array as obtained from
+ * SecTrustSettingsCopyTrustSettings().
+ */
+static int displayTrustSettings(
+ CFArrayRef trustSettings,
+ OidParser &parser)
+{
+ /* must always be there though it may be empty */
+ if(trustSettings == NULL) {
+ printf("***displayTrustSettings: missing trust settings array");
+ return -1;
+ }
+ if(CFGetTypeID(trustSettings) != CFArrayGetTypeID()) {
+ printf("***displayTrustSettings: malformed trust settings array");
+ return -1;
+ }
+
+ int ourRtn = 0;
+ CFIndex numUseConstraints = CFArrayGetCount(trustSettings);
+ indentIncr();
+ indent(); printf("Number of trust settings : %ld\n", numUseConstraints);
+ OSStatus ortn;
+ SecPolicyRef certPolicy;
+ SecTrustedApplicationRef certApp;
+ CFDictionaryRef ucDict;
+ CFStringRef policyStr;
+ CFNumberRef cfNum;
+
+ /* grind thru the trust settings dictionaries */
+ for(CFIndex ucDex=0; ucDex<numUseConstraints; ucDex++) {
+ indent(); printf("Trust Setting %ld:\n", ucDex);
+ indentIncr();
+
+ ucDict = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, ucDex);
+ if(CFGetTypeID(ucDict) != CFDictionaryGetTypeID()) {
+ printf("***displayTrustSettings: malformed usage constraints dictionary");
+ ourRtn = -1;
+ goto nextAp;
+ }
+
+ /* policy - optional */
+ certPolicy = (SecPolicyRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicy);
+ if(certPolicy != NULL) {
+ if(CFGetTypeID(certPolicy) != SecPolicyGetTypeID()) {
+ printf("***displayTrustSettings: malformed certPolicy");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ CSSM_OID policyOid;
+ ortn = SecPolicyGetOID(certPolicy, &policyOid);
+ if(ortn) {
+ cssmPerror("SecPolicyGetOID", ortn);
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Policy OID : ");
+ printOid(policyOid.Data, policyOid.Length, parser);
+ printf("\n");
+ }
+
+ /* app - optional */
+ certApp = (SecTrustedApplicationRef)CFDictionaryGetValue(ucDict,
+ kSecTrustSettingsApplication);
+ if(certApp != NULL) {
+ if(CFGetTypeID(certApp) != SecTrustedApplicationGetTypeID()) {
+ printf("***displayTrustSettings: malformed certApp");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ CFRef<CFDataRef> appPath;
+ ortn = SecTrustedApplicationCopyData(certApp, appPath.take());
+ if(ortn) {
+ cssmPerror("SecTrustedApplicationCopyData", ortn);
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Application : %s", CFDataGetBytePtr(appPath));
+ printf("\n");
+ }
+
+ /* policy string */
+ policyStr = (CFStringRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicyString);
+ if(policyStr != NULL) {
+ if(CFGetTypeID(policyStr) != CFStringGetTypeID()) {
+ printf("***displayTrustSettings: malformed policyStr");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Policy String : ");
+ printCfStr(policyStr); printf("\n");
+ }
+
+ /* Allowed error */
+ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsAllowedError);
+ if(cfNum != NULL) {
+ if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
+ printf("***displayTrustSettings: malformed allowedError");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Allowed Error : ");
+ printCssmErr(cfNum); printf("\n");
+ }
+
+ /* Result */
+ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsResult);
+ if(cfNum != NULL) {
+ if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
+ printf("***displayTrustSettings: malformed Result");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Result Type : ");
+ printResult(cfNum); printf("\n");
+ }
+
+ /* key usage */
+ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsKeyUsage);
+ if(cfNum != NULL) {
+ if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
+ printf("***displayTrustSettings: malformed keyUsage");
+ ourRtn = -1;
+ goto nextAp;
+ }
+ indent(); printf("Key Usage : ");
+ printKeyUsage(cfNum); printf("\n");
+ }
+
+ nextAp:
+ indentDecr();
+ }
+ indentDecr();
+ return ourRtn;
+}
+
+/* convert an OID to a SecPolicyRef */
+static SecPolicyRef oidToPolicy(
+ const CSSM_OID &oid)
+{
+ SecPolicyRef policyRef = NULL;
+
+ OSStatus ortn = SecPolicyCopy(CSSM_CERT_X_509v3, &oid, &policyRef);
+ if(ortn) {
+ cssmPerror("SecPolicyCopy", ortn);
+ return NULL;
+ }
+ return policyRef;
+}
+
+/* Convert cmdline policy string to SecPolicyRef */
+static SecPolicyRef policyStringToPolicy(
+ const char *policy)
+{
+ if(policy == NULL) {
+ return NULL;
+ }
+ const CSSM_OID *oid = NULL;
+ if(!strcmp(policy, "ssl")) {
+ oid = &CSSMOID_APPLE_TP_SSL;
+ }
+ else if(!strcmp(policy, "smime")) {
+ oid = &CSSMOID_APPLE_TP_SMIME;
+ }
+ else if(!strcmp(policy, "codeSign")) {
+ oid = &CSSMOID_APPLE_TP_CODE_SIGNING;
+ }
+ else if(!strcmp(policy, "swuSign")) {
+ oid = &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING;
+ }
+ else if(!strcmp(policy, "IPSec")) {
+ oid = &CSSMOID_APPLE_TP_IP_SEC;
+ }
+ else if(!strcmp(policy, "iChat")) {
+ oid = &CSSMOID_APPLE_TP_ICHAT;
+ }
+ else {
+ printf("***Unknown policy string (%s)\n", policy);
+ return NULL;
+ }
+
+ /* OID to SecPolicyRef */
+ return oidToPolicy(*oid);
+}
+
+static int appendConstraintToArray(
+ const char *appPath, /* optional, "-" means ensure apArray is nonempty */
+ const char *policy, /* optional (ssl/smime), "-" as above */
+ const char *policyStr, /* optional policy string */
+ const SInt32 *allowErr, /* optional allowed error */
+ const char *resultType, /* optional allow/confirm/deny */
+ SecTrustSettingsKeyUsage keyUse, /* optional key use */
+ CFMutableArrayRef &array) /* result RETURNED here, created if necessary */
+{
+ if(array == NULL) {
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ CFMutableDictionaryRef outDict = CFDictionaryCreateMutable(NULL,
+ 0, // capacity
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if((policy != NULL) && (strcmp(policy, "-"))) {
+
+ /* policy string to SecPolicyRef */
+ SecPolicyRef policyRef = policyStringToPolicy(policy);
+ if(policyRef == NULL) {
+ return -1;
+ }
+ CFDictionaryAddValue(outDict, kSecTrustSettingsPolicy, policyRef);
+ CFRelease(policyRef);
+ }
+
+ /* app string to SecTrustedApplicationRef */
+ if((appPath != NULL) && (strcmp(appPath, "-"))) {
+ SecTrustedApplicationRef appRef;
+ OSStatus ortn = SecTrustedApplicationCreateFromPath(appPath, &appRef);
+ if(ortn) {
+ cssmPerror("SecTrustedApplicationCreateFromPath", ortn);
+ return -1;
+ }
+ CFDictionaryAddValue(outDict, kSecTrustSettingsApplication, appRef);
+ CFRelease(appRef);
+ }
+
+ if(policyStr != NULL) {
+ CFStringRef pstr = CFStringCreateWithCString(NULL, policyStr, kCFStringEncodingASCII);
+ CFDictionaryAddValue(outDict, kSecTrustSettingsPolicyString, pstr);
+ CFRelease(pstr);
+ }
+
+ if(allowErr != NULL) {
+ CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, allowErr);
+ CFDictionaryAddValue(outDict, kSecTrustSettingsAllowedError, cfNum);
+ CFRelease(cfNum);
+ }
+
+ if(keyUse != 0) {
+ SInt32 ku = (SInt32)ku;
+ CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &ku);
+ CFDictionaryAddValue(outDict, kSecTrustSettingsKeyUsage, cfNum);
+ CFRelease(cfNum);
+ }
+
+ if(resultType != NULL) {
+ SInt32 n;
+
+ if(!strcmp(resultType, "trust")) {
+ n = kSecTrustSettingsResultTrustRoot;
+ }
+ else if(!strcmp(resultType, "trustAsRoot")) {
+ n = kSecTrustSettingsResultTrustAsRoot;
+ }
+ else if(!strcmp(resultType, "deny")) {
+ n = kSecTrustSettingsResultDeny;
+ }
+ else if(!strcmp(resultType, "unspecified")) {
+ n = kSecTrustSettingsResultUnspecified;
+ }
+ else {
+ printf("***unknown resultType spec (%s)\n", resultType);
+ return -1;
+ }
+ CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &n);
+ CFDictionaryAddValue(outDict, kSecTrustSettingsResult, cfNum);
+ CFRelease(cfNum);
+ }
+
+ /* append dictionary to output */
+ CFArrayAppendValue(array, outDict);
+ /* array owns the dictionary now */
+ CFRelease(outDict);
+ return 0;
+}
+
+/* read a file --> CFDataRef */
+CFDataRef readFileCFData(
+ const char *fileName)
+{
+ int rtn;
+ unsigned char *fileData = NULL;
+ unsigned fileDataLen = 0;
+
+ rtn = readFile(fileName, &fileData, &fileDataLen);
+ if(rtn) {
+ printf("Error (%d) reading %s.\n", rtn, fileName);
+ return NULL;
+ }
+ CFDataRef cfd = CFDataCreate(NULL, (const UInt8 *)fileData, fileDataLen);
+ free(fileData);
+ return cfd;
+}
+
+static int fetchParseTrustRecord(
+ SecTrustSettingsDomain domain,
+ char *settingsFile) /* optional, ignore domain if present */
+{
+ CFDataRef trustSettings = NULL;
+
+ if(settingsFile) {
+ trustSettings = readFileCFData(settingsFile);
+ if(trustSettings == NULL) {
+ return -1;
+ }
+ }
+ else {
+ OSStatus ortn = SecTrustSettingsCreateExternalRepresentation(domain, &trustSettings);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsCreateExternalRepresentation", ortn);
+ return -1;
+ }
+ }
+ int rtn = parseTrustedRootList(trustSettings);
+ CFRelease(trustSettings);
+ return rtn;
+}
+
+static int copyCertsAndDisplay(
+ bool verbose,
+ SecTrustSettingsDomain domain)
+{
+ OSStatus ortn;
+
+ auto_ptr<OidParser> parser(NULL);
+
+ if(verbose) {
+ parser.reset(new OidParser);
+ }
+
+ CFArrayRef certArray = NULL;
+ ortn = SecTrustSettingsCopyCertificates(domain, &certArray);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsCopyCertificates", ortn);
+ return ortn;
+ }
+
+ CFIndex numCerts = CFArrayGetCount(certArray);
+ indent();
+ printf("Num certs = %ld\n", numCerts);
+ int ourRtn = 0;
+ for(CFIndex dex=0; dex<numCerts; dex++) {
+ SecCertificateRef certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex);
+ if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
+ printf("***Bad CFGetTypeID for cert\n");
+ return -1;
+ }
+ indent();
+ printf("Cert %ld: ", dex);
+ printCertLabel(certRef);
+ printf("\n");
+ if(verbose) {
+ CFRef<CFArrayRef> appPolicies;
+ ortn = SecTrustSettingsCopyTrustSettings(certRef, domain, appPolicies.take());
+ if(ortn) {
+ cssmPerror("SecRootCertificateCopyAppPolicyConstraints", ortn);
+ ourRtn = -1;
+ continue;
+ }
+ if(displayTrustSettings(appPolicies, *parser.get())) {
+ ourRtn = -1;
+ }
+ }
+ }
+ CFRelease(certArray);
+ return ourRtn;
+}
+
+static int deleteCerts(
+ SecTrustSettingsDomain domain,
+ bool deleteAll)
+{
+ OSStatus ortn;
+
+ CFArrayRef certArray = NULL;
+ ortn = SecTrustSettingsCopyCertificates(domain, &certArray);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsCopyCertificates", ortn);
+ return ortn;
+ }
+
+ CFIndex numCerts = CFArrayGetCount(certArray);
+ unsigned numDeleted = 0;
+
+ for(CFIndex dex=0; dex<numCerts; dex++) {
+ SecCertificateRef certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex);
+ if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
+ printf("***Bad CFGetTypeID for cert\n");
+ return -1;
+ }
+ bool doDelete = false;
+
+ if(deleteAll) {
+ printf("DELETING: ");
+ printCertLabel(certRef);
+ printf("\n");
+ doDelete = true;
+ }
+ else {
+ indent();
+ printf("Cert %ld: ", dex);
+ printCertLabel(certRef);
+ printf("\n");
+ fpurge(stdin);
+ printf("Delete (y/anything)? ");
+ char resp = getchar();
+ if(resp == 'y') {
+ doDelete = true;
+ }
+ }
+ if(doDelete) {
+ ortn = SecTrustSettingsRemoveTrustSettings(certRef, domain);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsRemoveTrustSettings", ortn);
+ fpurge(stdin);
+ printf("Continue deleting (y/anything)? ");
+ char resp = getchar();
+ fflush(stdout);
+ if(resp != 'y') {
+ return ortn;
+ }
+ }
+ else {
+ numDeleted++;
+ }
+ }
+ }
+ CFRelease(certArray);
+ printf("...%u certs deleted\n", numDeleted);
+ return noErr;
+}
+
+/* add a cert to trust list */
+static int addCert(
+ SecCertificateRef certRef,
+ SecTrustSettingsDomain domain,
+ bool addToKc, // import cert to keychain
+ const char *kcName, // only for addToKC option
+ CFArrayRef trustSettings,
+ CFDataRef settingsIn, // optional, requires settingsFileOut
+ CFDataRef *settingsOut)
+{
+ OSStatus ortn;
+ char *domainName;
+
+ if(settingsIn && !settingsOut) {
+ printf("Modifying trust settings as file requires output file\n");
+ return -1;
+ }
+ switch(domain) {
+ case kSecTrustSettingsDomainSystem:
+ printf("***Can't modify system trust settings.\n");
+ return -1;
+ case kSecTrustSettingsDomainAdmin:
+ kcName = "/Library/Keychains/System.keychain";
+ domainName = "Admin";
+ break;
+ default:
+ domainName = "User";
+ break;
+ }
+ if(addToKc) {
+ SecKeychainRef kcRef = NULL;
+ if(kcName) {
+ ortn = SecKeychainOpen(kcName, &kcRef);
+ if(ortn) {
+ cssmPerror("SecKeychainOpen", ortn);
+ return -1;
+ }
+ }
+ ortn = SecCertificateAddToKeychain(certRef, kcRef);
+ if(ortn) {
+ cssmPerror("SecCertificateAddToKeychain", ortn);
+ return -1;
+ }
+ printf("...cert added to keychain %s\n", (kcName ? kcName : "<default>"));
+ }
+ if(settingsIn) {
+ ortn = SecTrustSettingsSetTrustSettingsExternal(settingsIn,
+ certRef, trustSettings, settingsOut);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsSetTrustSettingsExternal", ortn);
+ return -1;
+ }
+ }
+ else {
+ ortn = SecTrustSettingsSetTrustSettings(certRef, domain, trustSettings);
+ if(ortn) {
+ cssmPerror("SecTrustSettingsSetTrustSettings", ortn);
+ return -1;
+ }
+ printf("...cert added to %s TrustList.\n", domainName);
+ }
+ return 0;
+}
+
+static int addCertLegacy(
+ SecCertificateRef certRef,
+ const char *policy,
+ const char *resultStr,
+ bool useLegacy)
+{
+ /* OID string to an OID pointer */
+ if(policy == NULL) {
+ printf("***You must specify a policy to set legacy User Trust\n");
+ return 1;
+ }
+ SecPolicyRef policyRef = policyStringToPolicy(policy);
+ if(policyRef == NULL) {
+ return -1;
+ }
+
+ /* result string to legacy SecTrustUserSetting */
+ SecTrustUserSetting setting = kSecTrustResultInvalid;
+ if(resultStr == NULL) {
+ setting = kSecTrustResultProceed;
+ }
+ else if(!strcmp(resultStr, "trust")) {
+ setting = kSecTrustResultProceed;
+ }
+ else if(!strcmp(resultStr, "trustAsRoot")) {
+ setting = kSecTrustResultProceed;
+ }
+ else if(!strcmp(resultStr, "deny")) {
+ setting = kSecTrustResultDeny;
+ }
+ else if (!strcmp(resultStr, "unspecified")) {
+ setting = kSecTrustResultUnspecified;
+ }
+ else {
+ printf("***Can't map %s to a SecTrustUserSetting\n", resultStr);
+ return -1;
+ }
+ OSStatus ortn;
+ if(useLegacy) {
+ ortn = SecTrustSetUserTrustLegacy(certRef, policyRef, setting);
+ if(ortn) {
+ cssmPerror("SecTrustSetUserTrustLegacy", ortn);
+ }
+ else {
+ if(setting == kSecTrustResultUnspecified) {
+ printf("...User Trust removed via SecTrustSetUserTrustLegacy().\n");
+ }
+ else {
+ printf("...User Trust set via SecTrustSetUserTrustLegacy().\n");
+ }
+ }
+ }
+ else {
+ #if 1
+ printf("...Legacy implementation needs Makefile work to avoid deprecation error\n");
+ exit(1);
+ #else
+ ortn = SecTrustSetUserTrust(certRef, policyRef, setting);
+ if(ortn) {
+ cssmPerror("SecTrustSetUserTrust", ortn);
+ }
+ else {
+ printf("...trust setting set via SecTrustSetUserTrust().\n");
+ }
+ #endif
+ }
+ if(policyRef != NULL) {
+ CFRelease(policyRef);
+ }
+ return ortn;
+}
+
+int main(int argc, char **argv)
+{
+ int arg;
+ CFMutableArrayRef appPolicies = NULL;
+ CFDataRef settingsIn = NULL;
+ CFDataRef settingsOut = NULL;
+
+ /* user-spec'd variables */
+ bool loopPause = false;
+ bool really = false;
+ bool verbose = false;
+ char *kcName = NULL;
+ SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser;
+ SecCertificateRef certRef = NULL;
+ bool addToKeychain = false;
+ char *settingsFileIn = NULL;
+ char *settingsFileOut = NULL;
+ bool userTrustLegacy = false;
+ char *policyStr = NULL;
+ char *resultStr = NULL;
+ bool userTrust = false;
+
+ extern char *optarg;
+ extern int optind;
+ optind = 2;
+ while ((arg = getopt(argc, argv, "c:sdt:T:a:p:P:e:L:r:w:W:k:u:RvAU2lh")) != -1) {
+ switch (arg) {
+ case 'c':
+ if(certRef) {
+ printf("***Only one cert at a time, please.\n");
+ usage(argv);
+ }
+ certRef = certFromFile(optarg);
+ if(certRef == NULL) {
+ exit(1);
+ }
+ break;
+ case 's':
+ domain = kSecTrustSettingsDomainSystem;
+ break;
+ case 'd':
+ domain = kSecTrustSettingsDomainAdmin;
+ break;
+ case 't':
+ settingsFileIn = optarg;
+ break;
+ case 'T':
+ settingsFileOut = optarg;
+ break;
+ case 'a':
+ if(appendConstraintToArray(optarg, NULL, NULL, NULL, NULL, 0, appPolicies)) {
+ exit(1);
+ }
+ break;
+ case 'p':
+ if(appendConstraintToArray(NULL, optarg, NULL, NULL, NULL, 0, appPolicies)) {
+ exit(1);
+ }
+ policyStr = optarg;
+ break;
+ case 'P':
+ /* this takes an additional argument */
+ if(optind > (argc - 1)) {
+ usage(argv);
+ }
+ if(appendConstraintToArray(optarg, argv[optind], NULL, NULL, NULL,
+ 0, appPolicies)) {
+ exit(1);
+ }
+ optind++;
+ break;
+ case 'e':
+ if(appendConstraintToArray(NULL, "smime", optarg, NULL, NULL,
+ 0, appPolicies)) {
+ exit(1);
+ }
+ policyStr = "smime";
+ break;
+ case 'L':
+ if(appendConstraintToArray(NULL, "ssl", optarg, NULL, NULL, 0, appPolicies)) {
+ exit(1);
+ }
+ policyStr = "ssl";
+ break;
+ case 'r':
+ if(appendConstraintToArray(NULL, NULL, NULL, NULL, optarg, 0, appPolicies)) {
+ exit(1);
+ }
+ resultStr = optarg;
+ break;
+ case 'w':
+ {
+ SInt32 l = atol(optarg);
+ if(appendConstraintToArray(NULL, NULL, NULL, &l, "unspecified", 0, appPolicies)) {
+ exit(1);
+ }
+ break;
+ }
+ case 'W':
+ {
+ /* this takes an additional argument */
+ if(optind > (argc - 1)) {
+ usage(argv);
+ }
+ SInt32 l = atol(optarg);
+ if(appendConstraintToArray(NULL, argv[optind], NULL, &l, "unspecified", 0,
+ appPolicies)) {
+ exit(1);
+ }
+ optind++;
+ break;
+ }
+ case 'u':
+ {
+ SInt32 l = atol(optarg);
+ SecTrustSettingsKeyUsage ku = (SecTrustSettingsKeyUsage)l;
+ if(appendConstraintToArray(NULL, NULL, NULL, NULL, NULL, ku, appPolicies)) {
+ exit(1);
+ }
+ break;
+ }
+ case 'k':
+ kcName = optarg;
+ break;
+ case 'R':
+ really = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'A':
+ addToKeychain = true;
+ break;
+ case 'l':
+ loopPause = true;
+ break;
+ case '2':
+ userTrustLegacy = true;
+ break;
+ case 'U':
+ userTrust = true;
+ break;
+ default:
+ case 'h':
+ usage(argv);
+ }
+ }
+ if(optind != argc) {
+ usage(argv);
+ }
+ if(startCFRunLoop()) {
+ /* enable reception of KC event messages */
+ exit(1);
+ }
+
+ /* give that thread a chance right now */
+ while(!runLoopInitialized) {
+ usleep(1000);
+ };
+
+ int ortn = 0;
+ do {
+ switch(argv[1][0]) {
+ case 'a':
+ if(certRef == NULL) {
+ printf("You must supply a cert.\n");
+ usage(argv);
+ }
+ if(settingsFileIn) {
+ if(!settingsFileOut) {
+ printf("Modifying trust settings as file requires output file\n");
+ return -1;
+ }
+ settingsIn = readFileCFData(settingsFileIn);
+ if(!settingsIn) {
+ return -1;
+ }
+ }
+ if(userTrustLegacy || userTrust) {
+ ortn = addCertLegacy(certRef, policyStr, resultStr, userTrustLegacy);
+ }
+ else {
+ ortn = addCert(certRef, domain, addToKeychain, kcName, appPolicies,
+ settingsIn, &settingsOut);
+ if((ortn == noErr) && (settingsOut != NULL)) {
+ unsigned len = CFDataGetLength(settingsOut);
+ if(writeFile(settingsFileOut, CFDataGetBytePtr(settingsOut), len)) {
+ printf("***Error writing settings to %s\n", settingsFileOut);
+ }
+ else {
+ printf("...wrote %u bytes to %s\n", len, settingsFileOut);
+ }
+ }
+ }
+ if(settingsIn) {
+ CFRelease(settingsIn);
+ }
+ if(settingsOut) {
+ CFRelease(settingsOut);
+ }
+ break;
+ case 'p':
+ ortn = fetchParseTrustRecord(domain, settingsFileIn);
+ break;
+ case 'r':
+ ortn = copyCertsAndDisplay(verbose, domain);
+ break;
+ case 'd':
+ ortn = deleteCerts(domain, false);
+ break;
+ case 'D':
+ if(!really) {
+ printf("I do not believe you. Specify -D option to delete all roots.\n");
+ exit(1);
+ }
+ ortn = deleteCerts(domain, true);
+ break;
+ case 'R':
+ ortn = addCertLegacy(certRef, policyStr, "unspecified", true);
+ break;
+ default:
+ usage(argv);
+ }
+ if(loopPause) {
+ fpurge(stdin);
+ printf("Pausing for MallocDebug. Hit CR to continue: ");
+ fflush(stdout);
+ getchar();
+ }
+ } while(loopPause);
+ return (int)ortn;
+}