static VALUE rb_default_keychain(VALUE self){ SecKeychainRef keychain=NULL; OSStatus result =SecKeychainCopyDefault(&keychain); CheckOSStatusOrRaise(result); return KeychainFromSecKeychainRef(keychain); }
static void get_password_from_keychain(Pop3 pc, const char *username, const char *servername, /*@out@ */ char *password, /*@out@ */ unsigned char *password_len) { SecKeychainRef kc; OSStatus rc; char *secpwd; UInt32 pwdlen; rc = SecKeychainCopyDefault(&kc); if (rc != noErr) { DM(pc, DEBUG_ERROR, "passmgr: unable to open keychain, exiting\n"); exit(EXIT_FAILURE); } rc = SecKeychainFindInternetPassword(kc, strlen(servername), servername, 0, NULL, strlen(username), username, 0, NULL, 0, NULL, kSecAuthenticationTypeDefault, &pwdlen, (void **) &secpwd, NULL); if (rc != noErr) { DM(pc, DEBUG_ERROR, "passmgr: keychain password grab for %s at %s failed, exiting\n", username, servername); DM(pc, DEBUG_ERROR, "passmgr: (perhaps you pressed 'deny')\n"); /* this seems like the sanest thing to do, for now */ exit(EXIT_FAILURE); } if (pwdlen < *password_len) { strncpy(password, secpwd, pwdlen); password[pwdlen] = '\0'; *password_len = pwdlen; } else { DM(pc, DEBUG_ERROR, "passmgr: warning: your password appears longer (%lu) than expected (%d)\n", strlen(secpwd), *password_len - 1); } rc = SecKeychainItemFreeContent(NULL, secpwd); return; }
void* CopyDefaultAndReleaseInSingleThread(void* arg) { OSStatus result; double endTime = GetTimeOfDay() + kTestLength; do { SecKeychainRef kc; result = SecKeychainCopyDefault(&kc); CFRelease(kc); if (result != noErr) { return NULL; } } while (GetTimeOfDay() < endTime); return NULL; }
/* * Convert a keychain name (which may be NULL) into the CFArrayRef required * by SSLSetCertificate. This is a bare-bones example of this operation, * since it requires and assumes that there is exactly one SecIdentity * in the keychain - i.e., there is exactly one matching cert/private key * pair. A real world server would probably search a keychain for a SecIdentity * matching some specific criteria. */ CFArrayRef getSslCerts( const char *kcName, // may be NULL, i.e., use default bool encryptOnly, bool completeCertChain, const char *anchorFile, // optional trusted anchor SecKeychainRef *pKcRef) // RETURNED { #if 0 SecKeychainRef kcRef = nil; OSStatus ortn; *pKcRef = nil; /* pick a keychain */ if(kcName) { ortn = SecKeychainOpen(kcName, &kcRef); if(ortn) { printf("SecKeychainOpen returned %d.\n", (int)ortn); printf("Cannot open keychain at %s. Aborting.\n", kcName); return NULL; } } else { /* use default keychain */ ortn = SecKeychainCopyDefault(&kcRef); if(ortn) { printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); return nil; } } *pKcRef = kcRef; return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); #else SecCertificateRef cert = NULL; SecIdentityRef identity = NULL; CFMutableArrayRef certificates = NULL, result = NULL; CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; SecTrustRef trust = NULL; SecKeyRef key = NULL; CFTypeRef pkdigest = NULL; // Find the first private key in the keychain and return both it's // attributes and a ref to it. require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), errOut); require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), errOut); require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), errOut); // Find the first certificate that has the same public key hash as the // returned private key and return it as a ref. require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); // Create an identity from the key and certificate. require(identity = SecIdentityCreate(NULL, cert, key), errOut); // Build a (partial) certificate chain from cert require(certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut); CFArrayAppendValue(certificates, cert); require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), errOut); SecTrustResultType tresult; require_noerr(SecTrustEvaluate(trust, &tresult), errOut); CFIndex certCount, ix; // We need at least 1 certificate require(certCount = SecTrustGetCertificateCount(trust), errOut); // Build a result where element 0 is the identity and the other elements // are the certs in the chain starting at the first intermediate up to the // anchor, if we found one, or as far as we were able to build the chain // if not. require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), errOut); // We are commited to returning a result now, so do not use require below // this line without setting result to NULL again. CFArrayAppendValue(result, identity); for (ix = 1; ix < certCount; ++ix) { CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); } errOut: CFReleaseSafe(trust); CFReleaseSafe(certificates); CFReleaseSafe(identity); CFReleaseSafe(cert); CFReleaseSafe(certQuery); CFReleaseSafe(keyResult); CFReleaseSafe(keyQuery); return result; #endif }
SecKeyRef SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) { OSStatus result = paramErr; // default result for an early exit SecKeyRef key = NULL; SecKeychainRef keychain = NULL; SecAccessRef access; CFStringRef label; CFStringRef appLabel; CFStringRef appTag; CFStringRef dateLabel = NULL; CSSM_ALGORITHMS algorithm; uint32 keySizeInBits; CSSM_KEYUSE keyUsage; uint32 keyAttr = CSSM_KEYATTR_RETURN_DEFAULT; CSSM_KEYCLASS keyClass; CFTypeRef value; Boolean isPermanent; Boolean isExtractable; // verify keychain parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain)) keychain = NULL; else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) { keychain = NULL; goto errorExit; } else CFRetain(keychain); // verify permanent parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsPermanent, (const void **)&value)) isPermanent = false; else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value))) goto errorExit; else isPermanent = CFEqual(kCFBooleanTrue, value); if (isPermanent) { if (keychain == NULL) { // no keychain was specified, so use the default keychain result = SecKeychainCopyDefault(&keychain); } keyAttr |= CSSM_KEYATTR_PERMANENT; } // verify extractable parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value)) isExtractable = true; // default to extractable if value not specified else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value))) goto errorExit; else isExtractable = CFEqual(kCFBooleanTrue, value); if (isExtractable) keyAttr |= CSSM_KEYATTR_EXTRACTABLE; // verify access parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&access)) access = NULL; else if (SecAccessGetTypeID() != CFGetTypeID(access)) goto errorExit; // verify label parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrLabel, (const void **)&label)) label = (dateLabel = utilCopyDefaultKeyLabel()); // no label provided, so use default else if (CFStringGetTypeID() != CFGetTypeID(label)) goto errorExit; // verify application label parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationLabel, (const void **)&appLabel)) appLabel = (dateLabel) ? dateLabel : (dateLabel = utilCopyDefaultKeyLabel()); else if (CFStringGetTypeID() != CFGetTypeID(appLabel)) goto errorExit; // verify application tag parameter if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationTag, (const void **)&appTag)) appTag = NULL; else if (CFStringGetTypeID() != CFGetTypeID(appTag)) goto errorExit; utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass); if (!keychain) { // the generated key will not be stored in any keychain result = SecKeyGenerate(keychain, algorithm, keySizeInBits, 0, keyUsage, keyAttr, access, &key); } else { // we can set the label attributes on the generated key if it's a keychain item size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 0; char *labelBuf = (char *)malloc(labelBufLen); size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 0; char *appLabelBuf = (char *)malloc(appLabelBufLen); size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 0; char *appTagBuf = (char *)malloc(appTagBufLen); if (label && !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8)) labelBuf[0]=0; if (appLabel && !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8)) appLabelBuf[0]=0; if (appTag && !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8)) appTagBuf[0]=0; SecKeychainAttribute attrs[] = { { kSecKeyPrintName, strlen(labelBuf), (char *)labelBuf }, { kSecKeyLabel, strlen(appLabelBuf), (char *)appLabelBuf }, { kSecKeyApplicationTag, strlen(appTagBuf), (char *)appTagBuf } }; SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; if (!appTag) --attributes.count; result = SecKeyGenerateWithAttributes(&attributes, keychain, algorithm, keySizeInBits, 0, keyUsage, keyAttr, access, &key); free(labelBuf); free(appLabelBuf); free(appTagBuf); } errorExit: if (result && error) { *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, NULL); } if (dateLabel) CFRelease(dateLabel); if (keychain) CFRelease(keychain); return key; }
OSStatus SecCertificateRequestGetResult( SecCertificateRequestRef certRequestRef, SecKeychainRef keychain, sint32 *estimatedTime, SecCertificateRef *certificateRef) { BEGIN_SECAPI CssmData certData; *certificateRef = NULL; CertificateRequest::required(certRequestRef)->getResult(estimatedTime, certData); if(certData.data() != NULL) { /* * Convert to SecCertifcateRef, optionally import. */ CFDataRef cfCert = CFDataCreate(NULL, (UInt8 *)certData.data(), certData.Length); SecExternalItemType itemType = kSecItemTypeCertificate; CFArrayRef outItems = NULL; bool freeKcRef = false; OSStatus ortn; if(keychain == NULL) { /* * Unlike most Sec* calls, if the keychain argument to SecKeychainItemImport() * is NULL, the item is not imported to the default keychain. At our * interface, however, a NULL keychain means "import to the default * keychain". */ ortn = SecKeychainCopyDefault(&keychain); if(ortn) { certReqDbg("GetResult: SecKeychainCopyDefault failure"); /* oh well, there's nothing we can do about this */ } else { freeKcRef = true; } } ortn = SecKeychainItemImport(cfCert, NULL, NULL, // format, don't care &itemType, 0, // flags NULL, // keyParams keychain, // optional, like ours &outItems); CFRelease(cfCert); if(freeKcRef) { CFRelease(keychain); } if(ortn) { certReqDbg("SecCertificateRequestGetResult: SecKeychainItemImport failure"); MacOSError::throwMe(ortn); } CFIndex numItems = CFArrayGetCount(outItems); switch(numItems) { case 0: certReqDbg("SecCertificateRequestGetResult: import zero items"); MacOSError::throwMe(errSecInternalComponent); default: certReqDbg("SecCertificateRequestGetResult: import %d items", (int)numItems); /* but drop thru anyway, take the first one */ case 1: SecCertificateRef certRef = (SecCertificateRef)(CFArrayGetValueAtIndex(outItems, 0)); if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { certReqDbg("SecCertificateRequestGetResult: bad type"); } else { CFRetain(certRef); *certificateRef = certRef; } } CFRelease(outItems); } END_SECAPI }
int main(int argc, char * const argv[]) { int verbose = 0; int dryRun = 0; int version = 0; char *toKeychainPath = NULL; struct option longopts[] = { { "dry-run", no_argument, &dryRun, 1 }, { "to-keychain", required_argument, NULL, 'k' }, { "verbose", no_argument, &verbose, 1 }, { "version", no_argument, &version, 1 }, { NULL, 0, NULL, 0 } }; int ch; while ((ch = getopt_long(argc, argv, "dk:v", longopts, NULL)) != -1) { switch (ch) { case 'k': toKeychainPath = optarg; break; case 'd': dryRun = 1; break; case 'v': verbose = 1; break; case 0: // Handle long-only options break; default: SRPrintUsage(); exit(EX_USAGE); } } argc -= optind; argv += optind; if (version) { fprintf(stderr, "splitring 1.1\nCopyright (C) 2013 Phil Calvin\n"); exit(0); } if (!argc) { SRPrintUsage(); exit(EX_USAGE); } CFMutableArrayRef keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // Iterate the passed keychain paths, opening each one for (int i = 0; i < argc; i++) { char* path = realpath(argv[i], NULL); if (path) { SecKeychainRef keychain = SROpenKeychain(path); CFArrayAppendValue(keychains, keychain); CFRelease(keychain); free(path); } else { fprintf(stderr, "Unable to find keychain: %s\n", argv[i]); } } // Unlock each of the keychains for (int i = 0; i < CFArrayGetCount(keychains); i++) { SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i); // Unlock it; might not need to do this if (verbose) { UInt32 bufferSize = 4096; char keychainPath[bufferSize]; SecKeychainGetPath(keychain, &bufferSize, keychainPath); fprintf(stderr, "Unlocking keychain at path: %s\n", keychainPath); } OSStatus status = SecKeychainUnlock(keychain, 0, NULL, FALSE); SRHandleError(status, true); } SecKeychainRef targetKeychain = NULL; if (toKeychainPath) { // Convert this to a canonical path char* canonicalPath = realpath(toKeychainPath, NULL); if (canonicalPath) { // Import to the specified keychain targetKeychain = SROpenKeychain(canonicalPath); free(canonicalPath); } else { fprintf(stderr, "Unable to find keychain: %s\n", toKeychainPath); exit(EX_IOERR); } } else { // Import to the default keychain if one wasn't specified OSStatus status = SecKeychainCopyDefault(&targetKeychain); SRHandleError(status, true); status = SecKeychainUnlock(targetKeychain, 0, NULL, FALSE); SRHandleError(status, true); } // Search for all items CFMutableArrayRef classes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(classes, kSecClassGenericPassword); CFArrayAppendValue(classes, kSecClassInternetPassword); //CFArrayAppendValue(classes, kSecClassCertificate); //CFArrayAppendValue(classes, kSecClassIdentity); //CFArrayAppendValue(classes, kSecClassKey); CFArrayRef items = SRCopyItems(keychains, classes); if (verbose) { UInt32 bufferSize = 4096; char defaultKeychainPath[bufferSize]; SecKeychainGetPath(targetKeychain, &bufferSize, defaultKeychainPath); fprintf(stderr, "Importing %li items to keychain at path: %s\n", CFArrayGetCount(items), defaultKeychainPath); } SRCopyItemsToKeychain(items, targetKeychain, verbose, dryRun); CFRelease(items); CFRelease(targetKeychain); CFRelease(keychains); return 0; }
/* * XXXX the following needs to be done in the S/MIME layer code * after signature of a signerinfo is verified */ OSStatus SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo) { SecCertificateRef cert = NULL; CSSM_DATA_PTR profile = NULL; SecCmsAttribute *attr; CSSM_DATA_PTR utc_stime = NULL; CSSM_DATA_PTR ekp; int save_error; OSStatus rv; Boolean must_free_cert = PR_FALSE; OSStatus status; SecKeychainRef keychainOrArray; status = SecKeychainCopyDefault(&keychainOrArray); /* sanity check - see if verification status is ok (unverified does not count...) */ if (signerinfo->verificationStatus != SecCmsVSGoodSignature) return SECFailure; /* find preferred encryption cert */ if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) && (attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL) { /* we have a SMIME_ENCRYPTION_KEY_PREFERENCE attribute! */ ekp = SecCmsAttributeGetValue(attr); if (ekp == NULL) return SECFailure; /* we assume that all certs coming with the message have been imported to the */ /* temporary database */ cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, ekp); if (cert == NULL) return SECFailure; must_free_cert = PR_TRUE; } if (cert == NULL) { /* no preferred cert found? * find the cert the signerinfo is signed with instead */ CFStringRef emailAddress=NULL; cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray); if (cert == NULL) return SECFailure; if (SecCertificateGetEmailAddress(cert,&emailAddress)) return SECFailure; } /* verify this cert for encryption (has been verified for signing so far) */ /* don't verify this cert for encryption. It may just be a signing cert. * that's OK, we can still save the S/MIME profile. The encryption cert * should have already been saved */ #ifdef notdef if (CERT_VerifyCert(keychainOrArray, cert, certUsageEmailRecipient, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) { if (must_free_cert) CERT_DestroyCertificate(cert); return SECFailure; } #endif /* XXX store encryption cert permanently? */ /* * Remember the current error set because we do not care about * anything set by the functions we are about to call. */ save_error = PORT_GetError(); if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, SEC_OID_PKCS9_SMIME_CAPABILITIES, PR_TRUE); profile = SecCmsAttributeGetValue(attr); attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); utc_stime = SecCmsAttributeGetValue(attr); } rv = CERT_SaveSMimeProfile (cert, profile, utc_stime); if (must_free_cert) CERT_DestroyCertificate(cert); /* * Restore the saved error in case the calls above set a new * one that we do not actually care about. */ PORT_SetError (save_error); return rv; }