static int do_lock(const char *keychainName) { SecKeychainRef keychain = NULL; OSStatus result; if (keychainName) { keychain = keychain_open(keychainName); if (!keychain) { result = 1; goto loser; } } result = SecKeychainLock(keychain); if (result) { sec_error("SecKeychainLock %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result)); } loser: if (keychain) CFRelease(keychain); return result; }
static int do_keychain_set_settings(const char *keychainName, SecKeychainSettings newKeychainSettings) { SecKeychainRef keychain = NULL; OSStatus result; if (keychainName) { keychain = keychain_open(keychainName); if (!keychain) { result = 1; goto cleanup; } } result = SecKeychainSetSettings(keychain, &newKeychainSettings); if (result) { sec_error("SecKeychainSetSettings %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result)); } cleanup: if (keychain) CFRelease(keychain); return result; }
static int do_keychain_show_info(const char *keychainName) { SecKeychainRef keychain = NULL; SecKeychainSettings keychainSettings = { SEC_KEYCHAIN_SETTINGS_VERS1 }; OSStatus result; if (keychainName) { keychain = keychain_open(keychainName); if (!keychain) { result = 1; goto loser; } } result = SecKeychainCopySettings(keychain, &keychainSettings); if (result) { sec_error("SecKeychainCopySettings %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result)); goto loser; } fprintf(stderr,"Keychain \"%s\"%s%s", keychainName ? keychainName : "<NULL>", keychainSettings.lockOnSleep ? " lock-on-sleep" : "", keychainSettings.useLockInterval ? " use-lock-interval" : ""); if (keychainSettings.lockInterval == INT_MAX) fprintf(stderr," no-timeout\n"); else fprintf(stderr," timeout=%ds\n", (int)keychainSettings.lockInterval); loser: if (keychain) CFRelease(keychain); return result; }
int keychain_import(int argc, char * const *argv) { int ch, result = 0; char *inFile = NULL; char *kcName = NULL; SecKeychainRef kcRef = NULL; SecExternalFormat externFormat = kSecFormatUnknown; SecExternalItemType itemType = kSecItemTypeUnknown; Boolean wrapped = FALSE; Boolean nonExtractable = FALSE; const char *passphrase = NULL; unsigned char *inFileData = NULL; unsigned inFileLen = 0; CFDataRef inData = NULL; unsigned numExtendedAttributes = 0; char **attrNames = NULL; char **attrValues = NULL; Boolean access_specified = FALSE; Boolean always_allow = FALSE; SecAccessRef access = NULL; CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); if(argc < 2) { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } inFile = argv[1]; if((argc == 2) && (inFile[0] == '-')) { result = 2; goto cleanup; } optind = 2; while ((ch = getopt(argc, argv, "k:t:f:P:wxa:hAT:")) != -1) { switch (ch) { case 'k': kcName = optarg; break; case 't': if(!strcmp("pub", optarg)) { itemType = kSecItemTypePublicKey; } else if(!strcmp("priv", optarg)) { itemType = kSecItemTypePrivateKey; } else if(!strcmp("session", optarg)) { itemType = kSecItemTypeSessionKey; } else if(!strcmp("cert", optarg)) { itemType = kSecItemTypeCertificate; } else if(!strcmp("agg", optarg)) { itemType = kSecItemTypeAggregate; } else { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } break; case 'f': if(!strcmp("openssl", optarg)) { externFormat = kSecFormatOpenSSL; } else if(!strcmp("openssh1", optarg)) { externFormat = kSecFormatSSH; } else if(!strcmp("openssh2", optarg)) { externFormat = kSecFormatSSHv2; } else if(!strcmp("bsafe", optarg)) { externFormat = kSecFormatBSAFE; } else if(!strcmp("raw", optarg)) { externFormat = kSecFormatRawKey; } else if(!strcmp("pkcs7", optarg)) { externFormat = kSecFormatPKCS7; } else if(!strcmp("pkcs8", optarg)) { externFormat = kSecFormatWrappedPKCS8; } else if(!strcmp("pkcs12", optarg)) { externFormat = kSecFormatPKCS12; } else if(!strcmp("netscape", optarg)) { externFormat = kSecFormatNetscapeCertSequence; } else if(!strcmp("x509", optarg)) { externFormat = kSecFormatX509Cert; } else if(!strcmp("pemseq", optarg)) { externFormat = kSecFormatPEMSequence; } else { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } break; case 'w': wrapped = TRUE; break; case 'x': nonExtractable = TRUE; break; case 'P': passphrase = optarg; break; case 'a': /* this takes an additional argument */ if(optind > (argc - 1)) { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } attrNames = (char **)realloc(attrNames, numExtendedAttributes * sizeof(char *)); attrValues = (char **)realloc(attrValues, numExtendedAttributes * sizeof(char *)); attrNames[numExtendedAttributes] = optarg; attrValues[numExtendedAttributes] = argv[optind]; numExtendedAttributes++; optind++; break; case 'A': always_allow = TRUE; access_specified = TRUE; break; case 'T': if (optarg[0]) { SecTrustedApplicationRef app = NULL; OSStatus status = noErr; /* check whether the argument specifies an application group */ const char *groupPrefix = "group://"; size_t prefixLen = strlen(groupPrefix); if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) { const char *groupName = &optarg[prefixLen]; if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) { sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status)); } } else { if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) { sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); } } if (status) { result = 1; goto cleanup; } CFArrayAppendValue(trusted_list, app); CFRelease(app); } access_specified = TRUE; break; case '?': default: result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } } if(wrapped) { switch(externFormat) { case kSecFormatOpenSSL: case kSecFormatUnknown: // i.e., use default externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatSSH: externFormat = kSecFormatWrappedSSH; break; case kSecFormatSSHv2: /* there is no wrappedSSHv2 */ externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatWrappedPKCS8: /* proceed */ break; default: fprintf(stderr, "Don't know how to wrap in specified format/type\n"); result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } } if(kcName) { kcRef = keychain_open(kcName); if(kcRef == NULL) { return 1; } } if(readFile(inFile, &inFileData, &inFileLen)) { sec_error("Error reading infile %s: %s", inFile, strerror(errno)); result = 1; goto cleanup; } inData = CFDataCreate(NULL, inFileData, inFileLen); if(inData == NULL) { result = 1; goto cleanup; } free(inFileData); if(access_specified) { char *accessName = NULL; CFStringRef fileStr = CFStringCreateWithCString(NULL, inFile, kCFStringEncodingUTF8); if (fileStr) { CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE); if (fileURL) { CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL); if (nameStr) { CFIndex nameLen = CFStringGetLength(nameStr); CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); accessName = (char *)malloc(bufLen); if (!CFStringGetCString(nameStr, accessName, bufLen-1, kCFStringEncodingUTF8)) accessName[0]=0; nameLen = strlen(accessName); char *p = &accessName[nameLen]; // initially points to terminating null while (--nameLen > 0) { if (*p == '.') { // strip extension, if any *p = '\0'; break; } p--; } safe_CFRelease(&nameStr); } safe_CFRelease(&fileURL); } safe_CFRelease(&fileStr); } result = create_access(accessName, always_allow, trusted_list, &access); if (accessName) { free(accessName); } if (result != 0) { goto cleanup; } } result = do_keychain_import(kcRef, inData, externFormat, itemType, access, nonExtractable, passphrase, inFile, attrNames, attrValues, numExtendedAttributes); cleanup: safe_CFRelease(&trusted_list); safe_CFRelease(&access); safe_CFRelease(&kcRef); safe_CFRelease(&inData); return result; }
static int do_recode(const char *keychainName1, const char *keychainName2) { SecKeychainRef keychain1 = NULL, keychain2 = NULL; CFMutableArrayRef dbBlobArray = NULL; CFDataRef dbBlob = NULL, extraData = NULL; OSStatus result; if (keychainName1) { keychain1 = keychain_open(keychainName1); if (!keychain1) { result = 1; goto loser; } } keychain2 = keychain_open(keychainName2); if (!keychain2) { result = 1; goto loser; } result = SecKeychainCopyBlob(keychain2, &dbBlob); if (result) { sec_error("SecKeychainCopyBlob %s: %s", keychainName2, sec_errstr(result)); goto loser; } extraData = CFDataCreate(NULL, NULL, 0); dbBlobArray = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); if (dbBlobArray) { CFArrayAppendValue(dbBlobArray, dbBlob); } #if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 result = SecKeychainRecodeKeychain(keychain1, dbBlob, extraData); #else result = SecKeychainRecodeKeychain(keychain1, dbBlobArray, extraData); #endif if (result) sec_error("SecKeychainRecodeKeychain %s, %s: %s", keychainName1, keychainName2, sec_errstr(result)); loser: if (dbBlobArray) CFRelease(dbBlobArray); if (dbBlob) CFRelease(dbBlob); if (extraData) CFRelease(extraData); if (keychain1) CFRelease(keychain1); if (keychain2) CFRelease(keychain2); return result; }
int keychain_export(int argc, char * const *argv) { int ch, result = 0; char *outFile = NULL; char *kcName = NULL; SecKeychainRef kcRef = NULL; SecExternalFormat externFormat = kSecFormatUnknown; ItemSpec itemSpec = IS_All; int wrapped = 0; int doPem = 0; const char *passphrase = NULL; while ((ch = getopt(argc, argv, "k:o:t:f:P:wph")) != -1) { switch (ch) { case 'k': kcName = optarg; break; case 'o': outFile = optarg; break; case 't': if(!strcmp("certs", optarg)) { itemSpec = IS_Certs; } else if(!strcmp("allKeys", optarg)) { itemSpec = IS_AllKeys; } else if(!strcmp("pubKeys", optarg)) { itemSpec = IS_PubKeys; } else if(!strcmp("privKeys", optarg)) { itemSpec = IS_PrivKeys; } else if(!strcmp("identities", optarg)) { itemSpec = IS_Identities; } else if(!strcmp("all", optarg)) { itemSpec = IS_All; } else { return 2; /* @@@ Return 2 triggers usage message. */ } break; case 'f': if(!strcmp("openssl", optarg)) { externFormat = kSecFormatOpenSSL; } else if(!strcmp("openssh1", optarg)) { externFormat = kSecFormatSSH; } else if(!strcmp("openssh2", optarg)) { externFormat = kSecFormatSSHv2; } else if(!strcmp("bsafe", optarg)) { externFormat = kSecFormatBSAFE; } else if(!strcmp("raw", optarg)) { externFormat = kSecFormatRawKey; } else if(!strcmp("pkcs7", optarg)) { externFormat = kSecFormatPKCS7; } else if(!strcmp("pkcs8", optarg)) { externFormat = kSecFormatWrappedPKCS8; } else if(!strcmp("pkcs12", optarg)) { externFormat = kSecFormatPKCS12; } else if(!strcmp("netscape", optarg)) { externFormat = kSecFormatNetscapeCertSequence; } else if(!strcmp("x509", optarg)) { externFormat = kSecFormatX509Cert; } else if(!strcmp("pemseq", optarg)) { externFormat = kSecFormatPEMSequence; } else { return 2; /* @@@ Return 2 triggers usage message. */ } break; case 'w': wrapped = 1; break; case 'p': doPem = 1; break; case 'P': passphrase = optarg; break; case '?': default: return 2; /* @@@ Return 2 triggers usage message. */ } } if(wrapped) { switch(externFormat) { case kSecFormatOpenSSL: case kSecFormatUnknown: // i.e., use default externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatSSH: externFormat = kSecFormatWrappedSSH; break; case kSecFormatSSHv2: /* there is no wrappedSSHv2 */ externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatWrappedPKCS8: /* proceed */ break; default: sec_error("Don't know how to wrap in specified format/type"); return 2; /* @@@ Return 2 triggers usage message. */ } } if(kcName) { kcRef = keychain_open(kcName); if(kcRef == NULL) { return 1; } } result = do_keychain_export(kcRef, externFormat, itemSpec, passphrase, doPem, outFile); if(kcRef) { CFRelease(kcRef); } return result; }
static int do_keychain_set_password(const char *keychainName, const char* oldPassword, const char* newPassword) { SecKeychainRef keychain = NULL; OSStatus result = 1; UInt32 oldLen = (oldPassword) ? strlen(oldPassword) : 0; UInt32 newLen = (newPassword) ? strlen(newPassword) : 0; char *oldPass = (oldPassword) ? (char*)oldPassword : NULL; char *newPass = (newPassword) ? (char*)newPassword : NULL; char *oldBuf = NULL; char *newBuf = NULL; if (keychainName) { keychain = keychain_open(keychainName); if (!keychain) { result = 1; goto cleanup; } } if (!oldPass) { /* prompt for old password */ char *pBuf = getpass("Old Password: "******"New Password: "******"Retype New Password: "******"try again"); goto cleanup; } /* lock keychain first to remove existing credentials */ (void)SecKeychainLock(keychain); /* change the password */ result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass); if (result) { sec_error("error changing password for \"%s\": %s", keychainName ? keychainName : "<NULL>", sec_errstr(result)); } cleanup: /* if we allocated password buffers, zero and free them */ if (oldBuf) { bzero(oldBuf, PW_BUF_SIZE); free(oldBuf); } if (newBuf) { bzero(newBuf, PW_BUF_SIZE); free(newBuf); } if (keychain) { CFRelease(keychain); } return result; }