]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/SecIdentity.cpp
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecIdentity.cpp
index 7939d6b6f3b044457d03bf1af347b1a1caeaa0e9..5d21959bc243ca61b3488e330d91e9f1fb0974f6 100644 (file)
 #include <security_keychain/KCCursor.h>
 #include <security_cdsa_utilities/Schema.h>
 #include <security_utilities/simpleprefs.h>
+#include <utilities/SecCFRelease.h>
 #include <sys/param.h>
 #include <syslog.h>
+#include <os/activity.h>
 
 /* private function declarations */
 OSStatus
@@ -120,30 +122,56 @@ 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);
 
-       SecPointer<Certificate> certificatePtr(Identity::required(identityRef)->certificate());
-       Required(certificateRef) = certificatePtr->handle();
-
-#if SECTRUST_OSX
-       /* convert outgoing item to a unified SecCertificateRef */
-       CssmData certData = certificatePtr->data();
-       CFDataRef data = NULL;
-       if (certData.Data && certData.Length) {
-               data = CFDataCreate(NULL, certData.Data, certData.Length);
+       if (!identityRef || !certificateRef) {
+               return errSecParam;
+       }
+       CFTypeID itemType = CFGetTypeID(identityRef);
+       if (itemType == SecIdentityGetTypeID()) {
+               SecPointer<Certificate> certificatePtr(Identity::required(identityRef)->certificate());
+               Required(certificateRef) = certificatePtr->handle();
+
+               /* convert outgoing certificate item to a unified SecCertificateRef */
+               CssmData certData = certificatePtr->data();
+               CFDataRef data = NULL;
+               if (certData.Data && certData.Length) {
+                       data = CFDataCreate(NULL, certData.Data, certData.Length);
+               }
+               if (!data) {
+                       *certificateRef = NULL;
+                       syslog(LOG_ERR, "ERROR: SecIdentityCopyCertificate failed to retrieve certificate data (length=%ld, data=0x%lX)",
+                                       (long)certData.Length, (uintptr_t)certData.Data);
+                       return errSecInternal;
+               }
+               SecCertificateRef tmpRef = *certificateRef;
+               *certificateRef = SecCertificateCreateWithKeychainItem(NULL, data, tmpRef);
+               if (data) {
+                       CFRelease(data);
+               }
+               if (tmpRef) {
+                       CFRelease(tmpRef);
+               }
+       }
+       else if (itemType == SecCertificateGetTypeID()) {
+               // rdar://24483382
+               // reconstituting a persistent identity reference could return the certificate
+               SecCertificateRef certificate = (SecCertificateRef)identityRef;
+
+               /* convert outgoing certificate item to a unified SecCertificateRef, if needed */
+               if (SecCertificateIsItemImplInstance(certificate)) {
+                       *certificateRef = SecCertificateCreateFromItemImplInstance(certificate);
+               }
+               else {
+                       *certificateRef = (SecCertificateRef) CFRetain(certificate);
+               }
+               return errSecSuccess;
        }
-       if (!data) {
-               *certificateRef = NULL;
-               syslog(LOG_ERR, "ERROR: SecIdentityCopyCertificate failed to retrieve certificate data (length=%ld, data=0x%lX)",
-                       (long)certData.Length, (uintptr_t)certData.Data);
-               return errSecInternal;
+       else {
+               return errSecParam;
        }
-       SecCertificateRef tmpRef = *certificateRef;
-       *certificateRef = SecCertificateCreateWithKeychainItem(NULL, data, tmpRef);
-       if (data)
-        CFRelease(data);
-       if (tmpRef)
-        CFRelease(tmpRef);
-#endif
 
        END_SECAPI
 }
@@ -155,9 +183,11 @@ 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);
 
-       SecPointer<KeyItem> keyItemPtr(Identity::required(identityRef)->privateKey());
-       Required(privateKeyRef) = keyItemPtr->handle();
+       Required(privateKeyRef) = (SecKeyRef)CFRetain(Identity::required(identityRef)->privateKeyRef());
 
     END_SECAPI
 }
@@ -188,11 +218,20 @@ SecIdentityCreate(
 {
        SecIdentityRef identityRef = NULL;
        OSStatus __secapiresult;
-       SecCertificateRef __itemImplRef=SecCertificateCreateItemImplInstance(certificate);
+       SecCertificateRef __itemImplRef = NULL;
+       if (SecCertificateIsItemImplInstance(certificate)) {
+               __itemImplRef=(SecCertificateRef)CFRetain(certificate);
+       }
+       if (!__itemImplRef && certificate) {
+               __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate);
+       }
+       if (!__itemImplRef && certificate) {
+               __itemImplRef=SecCertificateCreateItemImplInstance(certificate);
+               (void)SecCertificateSetKeychainItem(certificate,__itemImplRef);
+       }
        try {
                SecPointer<Certificate> certificatePtr(Certificate::required(__itemImplRef));
-               SecPointer<KeyItem> keyItemPtr(KeyItem::required(privateKey));
-               SecPointer<Identity> identityPtr(new Identity(keyItemPtr, certificatePtr));
+               SecPointer<Identity> identityPtr(new Identity(privateKey, certificatePtr));
                identityRef = identityPtr->handle();
 
                __secapiresult=errSecSuccess;
@@ -201,6 +240,7 @@ SecIdentityCreate(
        catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
        catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
        catch (...) { __secapiresult=errSecInternalComponent; }
+       if (__itemImplRef) { CFRelease(__itemImplRef); }
        return identityRef;
 }
 
@@ -220,19 +260,20 @@ SecIdentityCompare(
                        return kCFCompareGreaterThan;
        }
 
-       BEGIN_SECAPI
-
-       SecPointer<Identity> id1(Identity::required(identity1));
-       SecPointer<Identity> id2(Identity::required(identity2));
-
-       if (id1 == id2)
-               return kCFCompareEqualTo;
-       else if (id1 < id2)
-               return kCFCompareLessThan;
-       else
-               return kCFCompareGreaterThan;
-
-       END_SECAPI1(kCFCompareGreaterThan);
+    try {
+        SecPointer<Identity> id1(Identity::required(identity1));
+        SecPointer<Identity> id2(Identity::required(identity2));
+
+        if (id1 == id2)
+            return kCFCompareEqualTo;
+        else if (id1 < id2)
+            return kCFCompareLessThan;
+        else
+            return kCFCompareGreaterThan;
+    } catch(...)
+    {}
+
+    return kCFCompareGreaterThan;
 }
 
 static
@@ -388,25 +429,12 @@ OSStatus _SecIdentityCopyPreferenceMatchingName(
     }
 
        // create identity reference, given certificate
-#if SECTRUST_OSX
-    status = SecIdentityCreateWithCertificate(NULL, (SecCertificateRef)certItemRef, identity);
-#else
-    try {
-        Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef));
-        SecPointer<Certificate> certificate(static_cast<Certificate *>(certItem.get()));
-        SecPointer<Identity> identity_ptr(new Identity(keychains, certificate));
-        if (certItemRef) {
-            CFRelease(certItemRef); // retained by identity
-        }
-        Required(identity) = identity_ptr->handle();
-    }
-    catch (const MacOSError &err)   { status=err.osStatus(); }
-    catch (const CommonError &err)  { status=SecKeychainErrFromOSStatus(err.osStatus()); }
-    catch (const std::bad_alloc &)  { status=errSecAllocate; }
-    catch (...)                     { status=errSecInvalidItemRef; }
-#endif
+       status = SecIdentityCreateWithCertificate(NULL, (SecCertificateRef)certItemRef, identity);
+       if (certItemRef) {
+               CFRelease(certItemRef);
+       }
 
-    return status;
+       return status;
 }
 
 SecIdentityRef SecIdentityCopyPreferred(CFStringRef name, CFArrayRef keyUsage, CFArrayRef validIssuers)
@@ -440,16 +468,21 @@ 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);
-        CFRelease(val);
+    if (val) {
+        if (CFGetTypeID(val) == CFBooleanGetTypeID()) {
+            logging = CFBooleanGetValue((CFBooleanRef)val);
+        }
     }
+     CFReleaseNull(val);
 
     OSStatus status = errSecItemNotFound;
     CFArrayRef names = _SecIdentityCopyPossiblePaths(name);
@@ -535,8 +568,15 @@ OSStatus SecIdentitySetPreference(
        }
 
     BEGIN_SECAPI
-
-       SecPointer<Certificate> 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<SecCertificateRef>  certRef;
+    OSStatus status = SecIdentityCopyCertificate(identity, certRef.take());
+    if(status != errSecSuccess) {
+        MacOSError::throwMe(status);
+    }
 
        // determine the account attribute
        //
@@ -548,7 +588,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"
        }
@@ -556,21 +596,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<char *>(accountUTF8), strlen(accountUTF8));
+    CssmDataContainer account(const_cast<char *>(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<char *>(serviceUTF8), strlen(serviceUTF8));
+    CssmDataContainer service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
+    free(serviceUTF8);
 
     // look for existing identity preference item, in case this is an update
        StorageManager::KeychainList keychains;
@@ -596,7 +644,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);
     }
@@ -644,6 +692,9 @@ SecIdentityFindPreferenceItem(
        SecKeychainItemRef *itemRef)
 {
     BEGIN_SECAPI
+    os_activity_t activity = os_activity_create("SecIdentityFindPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
        StorageManager::KeychainList keychains;
        globals().storageManager.optionalSearchList(keychainOrArray, keychains);
@@ -682,6 +733,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);
@@ -725,7 +779,7 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage(
        // cut things off at that point if we're still finding items (if they can't
        // be deleted for some reason, we'd never break out of the loop.)
 
-       OSStatus status;
+       OSStatus status = errSecInternalError;
        SecKeychainItemRef item = NULL;
        int count = 0, maxUsages = 12;
        while (++count <= maxUsages &&
@@ -774,21 +828,29 @@ OSStatus _SecIdentityAddPreferenceItemWithName(
        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<char *>(accountUTF8), strlen(accountUTF8));
+    CssmDataContainer account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
+    free(accountUTF8);
     CFRelease(labelStr);
 
        // service attribute (name provided by the caller)
        CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(idString), kCFStringEncodingUTF8) + 1;;
-       char serviceUTF8[serviceUTF8Len];
+       char *serviceUTF8 = (char *)malloc(serviceUTF8Len);
+       if (!serviceUTF8) {
+               MacOSError::throwMe(errSecMemoryError);
+       }
     if (!CFStringGetCString(idString, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
         serviceUTF8[0] = (char)'\0';
-    CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
+    CssmDataContainer service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
+    free(serviceUTF8);
 
        // set item attribute values
        item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
@@ -849,6 +911,9 @@ OSStatus SecIdentityAddPreferenceItem(
     // (Note that behavior is unchanged if the specified idString is not a URL.)
 
     BEGIN_SECAPI
+    os_activity_t activity = os_activity_create("SecIdentityAddPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
     OSStatus status = errSecInternalComponent;
     CFArrayRef names = _SecIdentityCopyPossiblePaths(idString);
@@ -905,6 +970,9 @@ OSStatus SecIdentityUpdatePreferenceItem(
                        SecIdentityRef identityRef)
 {
     BEGIN_SECAPI
+    os_activity_t activity = os_activity_create("SecIdentityUpdatePreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
        if (!itemRef || !identityRef)
                MacOSError::throwMe(errSecParam);
@@ -940,15 +1008,19 @@ OSStatus SecIdentityUpdatePreferenceItem(
        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))
+       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<char *>(accountUTF8), strlen(accountUTF8));
+       CssmDataContainer account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
        prefItem->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
-    CFRelease(labelStr);
+       free(accountUTF8);
+       CFRelease(labelStr);
 
        // generic attribute (store persistent certificate reference)
        CFDataRef pItemRef = nil;
@@ -973,6 +1045,9 @@ OSStatus SecIdentityCopyFromPreferenceItem(
                        SecIdentityRef *identityRef)
 {
     BEGIN_SECAPI
+    os_activity_t activity = os_activity_create("SecIdentityCopyFromPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+    os_activity_scope(activity);
+    os_release(activity);
 
        if (!itemRef || !identityRef)
                MacOSError::throwMe(errSecParam);
@@ -1034,6 +1109,9 @@ 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<Mutex> _(systemIdentityLock());
        auto_ptr<Dictionary> identDict;
@@ -1102,6 +1180,9 @@ 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<Mutex> _(systemIdentityLock());
        if(geteuid() != 0) {