X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/6b200bc335dc93c5516ccb52f14bd896d8c7fad7..02b2aca600d4a0fe6fb259262bd6808ef889acde:/OSX/libsecurity_keychain/lib/SecIdentity.cpp diff --git a/OSX/libsecurity_keychain/lib/SecIdentity.cpp b/OSX/libsecurity_keychain/lib/SecIdentity.cpp index c870ec73..533ecabf 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentity.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentity.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include "LegacyAPICounts.h" /* private function declarations */ OSStatus @@ -121,6 +123,9 @@ SecIdentityCopyCertificate( SecCertificateRef *certificateRef) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentityCopyCertificate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); if (!identityRef || !certificateRef) { return errSecParam; @@ -179,6 +184,9 @@ SecIdentityCopyPrivateKey( SecKeyRef *privateKeyRef) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentityCopyPrivateKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); Required(privateKeyRef) = (SecKeyRef)CFRetain(Identity::required(identityRef)->privateKeyRef()); @@ -209,6 +217,7 @@ SecIdentityCreate( SecCertificateRef certificate, SecKeyRef privateKey) { + COUNTLEGACYAPI SecIdentityRef identityRef = NULL; OSStatus __secapiresult; SecCertificateRef __itemImplRef = NULL; @@ -237,38 +246,6 @@ SecIdentityCreate( return identityRef; } -CFComparisonResult -SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) -{ - if (!identity1 || !identity2) - { - if (identity1 == identity2) - return kCFCompareEqualTo; - else if (identity1 < identity2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } - - try { - SecPointer id1(Identity::required(identity1)); - SecPointer id2(Identity::required(identity2)); - - if (id1 == id2) - return kCFCompareEqualTo; - else if (id1 < id2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } catch(...) - {} - - return kCFCompareGreaterThan; -} - static CFArrayRef _SecIdentityCopyPossiblePaths( CFStringRef name) @@ -394,8 +371,9 @@ OSStatus _SecIdentityCopyPreferenceMatchingName( FourCharCode itemType = 'iprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item prefItem; if (!cursor->next(prefItem)) @@ -461,14 +439,19 @@ OSStatus SecIdentityCopyPreference( // (Note that behavior is unchanged if the specified name is not a URL.) BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentityCopyPreference", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); CFTypeRef val = (CFTypeRef)CFPreferencesCopyValue(CFSTR("LogIdentityPreferenceLookup"), CFSTR("com.apple.security"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); Boolean logging = false; - if (val && CFGetTypeID(val) == CFBooleanGetTypeID()) { - logging = CFBooleanGetValue((CFBooleanRef)val); + if (val) { + if (CFGetTypeID(val) == CFBooleanGetTypeID()) { + logging = CFBooleanGetValue((CFBooleanRef)val); + } } CFReleaseNull(val); @@ -556,8 +539,15 @@ OSStatus SecIdentitySetPreference( } BEGIN_SECAPI - - SecPointer certificate(Identity::required(identity)->certificate()); + os_activity_t activity = os_activity_create("SecIdentitySetPreference", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); + + CFRef certRef; + OSStatus status = SecIdentityCopyCertificate(identity, certRef.take()); + if(status != errSecSuccess) { + MacOSError::throwMe(status); + } // determine the account attribute // @@ -569,7 +559,7 @@ OSStatus SecIdentitySetPreference( // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. // CFStringRef labelStr = nil; - certificate->inferLabel(false, &labelStr); + SecCertificateInferLabel(certRef.get(), &labelStr); if (!labelStr) { MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" } @@ -577,21 +567,29 @@ OSStatus SecIdentitySetPreference( const char *templateStr = "%s [key usage 0x%X]"; const int keyUsageMaxStrLen = 8; accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char accountUTF8[accountUTF8Len]; + char *accountUTF8 = (char *)malloc(accountUTF8Len); + if (!accountUTF8) { + MacOSError::throwMe(errSecMemoryError); + } if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) accountUTF8[0] = (char)'\0'; if (keyUsage) snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmData account(const_cast(accountUTF8), strlen(accountUTF8)); + CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); + free(accountUTF8); CFRelease(labelStr); // service attribute (name provided by the caller) CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; - char serviceUTF8[serviceUTF8Len]; + char *serviceUTF8 = (char *)malloc(serviceUTF8Len); + if (!serviceUTF8) { + MacOSError::throwMe(errSecMemoryError); + } if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) serviceUTF8[0] = (char)'\0'; - CssmData service(const_cast(serviceUTF8), strlen(serviceUTF8)); + CssmDataContainer service(const_cast(serviceUTF8), strlen(serviceUTF8)); + free(serviceUTF8); // look for existing identity preference item, in case this is an update StorageManager::KeychainList keychains; @@ -617,7 +615,7 @@ OSStatus SecIdentitySetPreference( // generic attribute (store persistent certificate reference) CFDataRef pItemRef = nil; - certificate->copyPersistentReference(pItemRef); + SecKeychainItemCreatePersistentReference((SecKeychainItemRef)certRef.get(), &pItemRef); if (!pItemRef) { MacOSError::throwMe(errSecInvalidItemRef); } @@ -654,47 +652,11 @@ OSStatus SecIdentitySetPreference( OSStatus SecIdentitySetPreferred(SecIdentityRef identity, CFStringRef name, CFArrayRef keyUsage) { + COUNTLEGACYAPI CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); return SecIdentitySetPreference(identity, name, keyUse); } -OSStatus -SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - BEGIN_SECAPI - - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList(keychainOrArray, keychains); - KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); - - char idUTF8[MAXPATHLEN]; - idUTF8[0] = (char)'\0'; - if (idString) - { - if (!CFStringGetCString(idString, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) - idUTF8[0] = (char)'\0'; - } - size_t idUTF8Len = strlen(idUTF8); - if (!idUTF8Len) - MacOSError::throwMe(errSecParam); - - CssmData service(const_cast(idUTF8), idUTF8Len); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - - Item item; - if (!cursor->next(item)) - MacOSError::throwMe(errSecItemNotFound); - - if (itemRef) - *itemRef=item->handle(); - - END_SECAPI -} - OSStatus SecIdentityFindPreferenceItemWithNameAndKeyUsage( CFTypeRef keychainOrArray, @@ -703,6 +665,9 @@ SecIdentityFindPreferenceItemWithNameAndKeyUsage( SecKeychainItemRef *itemRef) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentityFindPreferenceItemWithNameAndKeyUsage", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); StorageManager::KeychainList keychains; globals().storageManager.optionalSearchList(keychainOrArray, keychains); @@ -722,8 +687,9 @@ SecIdentityFindPreferenceItemWithNameAndKeyUsage( CssmData service(const_cast(idUTF8), idUTF8Len); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item item; if (!cursor->next(item)) @@ -740,6 +706,7 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( CFStringRef name, int32_t keyUsage) { + COUNTLEGACYAPI // when a specific key usage is passed, we'll only match & delete that pref; // when a key usage of 0 is passed, all matching prefs should be deleted. // maxUsages represents the most matches there could theoretically be, so @@ -760,274 +727,6 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( return (status == errSecItemNotFound) ? errSecSuccess : status; } - -static -OSStatus _SecIdentityAddPreferenceItemWithName( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - // this is NOT exported, and called only from SecIdentityAddPreferenceItem (below), so no BEGIN/END macros here; - // caller must handle exceptions - - if (!identityRef || !idString) - return errSecParam; - SecPointer cert(Identity::required(identityRef)->certificate()); - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); - sint32 keyUsage = 0; - - // determine the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - cert->inferLabel(false, &labelStr); - if (!labelStr) { - return errSecDataTooLarge; // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char accountUTF8[accountUTF8Len]; - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmData account(const_cast(accountUTF8), strlen(accountUTF8)); - CFRelease(labelStr); - - // service attribute (name provided by the caller) - CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(idString), kCFStringEncodingUTF8) + 1;; - char serviceUTF8[serviceUTF8Len]; - if (!CFStringGetCString(idString, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) - serviceUTF8[0] = (char)'\0'; - CssmData service(const_cast(serviceUTF8), strlen(serviceUTF8)); - - // set item attribute values - item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), keyUsage); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - return status; - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - Keychain keychain = nil; - try { - keychain = Keychain::optional(keychainRef); - if (!keychain->exists()) - MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. - } - catch(...) { - keychain = globals().storageManager.defaultKeychainUI(item); - } - - try { - keychain->add(item); - } - catch (const MacOSError &err) { - if (err.osStatus() != errSecDuplicateItem) - throw; // if item already exists, fall through to update - } - - item->update(); - - if (itemRef) - *itemRef = item->handle(); - - return status; -} - -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - // The original implementation of SecIdentityAddPreferenceItem adds the exact string only. - // That implementation has been moved to _SecIdentityAddPreferenceItemWithName (above), - // and this function is a wrapper which calls it, so that existing clients will get the - // extended behavior of server domain matching for items that specify URLs. - // (Note that behavior is unchanged if the specified idString is not a URL.) - - BEGIN_SECAPI - - OSStatus status = errSecInternalComponent; - CFArrayRef names = _SecIdentityCopyPossiblePaths(idString); - if (!names) { - return status; - } - - CFIndex total = CFArrayGetCount(names); - if (total > 0) { - // add item for name (first element in array) - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, 0); - try { - status = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); - } - catch (const MacOSError &err) { status=err.osStatus(); } - catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { status=errSecAllocate; } - catch (...) { status=errSecInternalComponent; } - } - if (total > 2) { - Boolean setDomainDefaultIdentity = FALSE; - CFTypeRef val = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SetDomainDefaultIdentity"), - CFSTR("com.apple.security.identities"), - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - if (val) { - if (CFGetTypeID(val) == CFBooleanGetTypeID()) - setDomainDefaultIdentity = CFBooleanGetValue((CFBooleanRef)val) ? TRUE : FALSE; - CFRelease(val); - } - if (setDomainDefaultIdentity) { - // add item for domain (second-to-last element in array, e.g. "*.apple.com") - OSStatus tmpStatus = errSecSuccess; - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, total-2); - try { - tmpStatus = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); - } - catch (const MacOSError &err) { tmpStatus=err.osStatus(); } - catch (const CommonError &err) { tmpStatus=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { tmpStatus=errSecAllocate; } - catch (...) { tmpStatus=errSecInternalComponent; } - } - } - - CFRelease(names); - return status; - - END_SECAPI -} - -/* deprecated in 10.5 */ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) -{ - BEGIN_SECAPI - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - SecPointer certificate(Identity::required(identityRef)->certificate()); - Item prefItem = ItemImpl::required(itemRef); - - // get the current key usage value for this item - sint32 keyUsage = 0; - UInt32 actLen = 0; - SecKeychainAttribute attr = { kSecScriptCodeItemAttr, sizeof(sint32), &keyUsage }; - try { - prefItem->getAttribute(attr, &actLen); - } - catch(...) { - keyUsage = 0; - }; - - // set the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - certificate->inferLabel(false, &labelStr); - if (!labelStr) { - MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char accountUTF8[accountUTF8Len]; - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmData account(const_cast(accountUTF8), strlen(accountUTF8)); - prefItem->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - CFRelease(labelStr); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)certificate->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - MacOSError::throwMe(status); - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - prefItem->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - prefItem->update(); - - END_SECAPI -} - -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) -{ - BEGIN_SECAPI - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - Item prefItem = ItemImpl::required(itemRef); - - // get persistent certificate reference - SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; - SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; - prefItem->getContent(NULL, &itemAttrList, NULL, NULL); - - // find certificate, given persistent reference data - CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); - SecKeychainItemRef certItemRef = nil; - OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl - prefItem->freeContent(&itemAttrList, NULL); - if (pItemRef) - CFRelease(pItemRef); - if (status) - return status; - - // create identity reference, given certificate - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList((CFTypeRef)NULL, keychains); - Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef)); - SecPointer certificate(static_cast(certItem.get())); - SecPointer identity(new Identity(keychains, certificate)); - if (certItemRef) - CFRelease(certItemRef); - - Required(identityRef) = identity->handle(); - - END_SECAPI -} - /* * System Identity Support. */ @@ -1055,9 +754,12 @@ OSStatus SecIdentityCopySystemIdentity( CFStringRef *actualDomain) /* optional */ { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentityCopySystemIdentity", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); StLock _(systemIdentityLock()); - auto_ptr identDict; + unique_ptr identDict; /* get top-level dictionary - if not present, we're done */ Dictionary* d = Dictionary::CreateDictionary(IDENTITY_DOMAIN, Dictionary::US_System); @@ -1123,13 +825,16 @@ OSStatus SecIdentitySetSystemIdentity( SecIdentityRef idRef) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecIdentitySetSystemIdentity", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_scope(activity); + os_release(activity); StLock _(systemIdentityLock()); if(geteuid() != 0) { MacOSError::throwMe(errSecAuthFailed); } - auto_ptr identDict; + unique_ptr identDict; MutableDictionary *d = MutableDictionary::CreateMutableDictionary(IDENTITY_DOMAIN, Dictionary::US_System); if (d) {