X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_transform/lib/SecTransform.cpp diff --git a/Security/libsecurity_transform/lib/SecTransform.cpp b/Security/libsecurity_transform/lib/SecTransform.cpp deleted file mode 100644 index 958d0974..00000000 --- a/Security/libsecurity_transform/lib/SecTransform.cpp +++ /dev/null @@ -1,547 +0,0 @@ -#include "SecTransform.h" -#include "SecTransformInternal.h" - -#include "Transform.h" -#include "Utilities.h" -#include "TransformFactory.h" -#include "GroupTransform.h" -#include "c++utils.h" -#include "SecCollectTransform.h" - - -#include - -using namespace std; - -const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT"); -const CFStringRef kSecTransformOutputAttributeName = CFSTR("OUTPUT"); -const CFStringRef kSecTransformDebugAttributeName = CFSTR("DEBUG"); -const CFStringRef kSecTransformTransformName = CFSTR("NAME"); -//const CFStringRef kSecTransformErrorTransform = CFSTR("TRANSFORM"); -const CFStringRef kSecTransformErrorDomain = CFSTR("com.apple.security.transforms.error"); -const CFStringRef kSecTransformAbortAttributeName = CFSTR("ABORT"); - -CFErrorRef SecTransformConnectTransformsInternal(SecGroupTransformRef groupRef, - SecTransformRef sourceTransformRef, - CFStringRef sourceAttributeName, - SecTransformRef destinationTransformRef, - CFStringRef destinationAttributeName) -{ - Transform* destination = (Transform*) CoreFoundationHolder::ObjectFromCFType(destinationTransformRef); - Transform* source = (Transform*) CoreFoundationHolder::ObjectFromCFType(sourceTransformRef); - - GroupTransform* group = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupRef); - CFErrorRef temp = source->Connect(group, destination, destinationAttributeName, sourceAttributeName); - return temp; -} - - -CFErrorRef SecTransformDisconnectTransforms(SecTransformRef sourceTransformRef, CFStringRef sourceAttributeName, - SecTransformRef destinationTransformRef, CFStringRef destinationAttributeName) -{ - Transform* destination = (Transform*) CoreFoundationHolder::ObjectFromCFType(destinationTransformRef); - Transform* source = (Transform*) CoreFoundationHolder::ObjectFromCFType(sourceTransformRef); - return source->Disconnect(destination, sourceAttributeName, destinationAttributeName); -} - -SecGroupTransformRef SecTransformCreateGroupTransform() -{ - return (SecGroupTransformRef) GroupTransform::Make(); -} - -SecGroupTransformRef SecTransformConnectTransforms(SecTransformRef sourceTransformRef, - CFStringRef sourceAttributeName, - SecTransformRef destinationTransformRef, - CFStringRef destinationAttributeName, - SecGroupTransformRef group, - CFErrorRef *error) -{ - if (group == NULL) - { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformErrorMissingParameter, "Group must not be NULL."); - } - - return NULL; - } - - if (destinationAttributeName == NULL) - { - destinationAttributeName = kSecTransformInputAttributeName; - } - - if (sourceAttributeName == NULL) - { - sourceAttributeName = kSecTransformOutputAttributeName; - } - - GroupTransform* gtr = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(group); - - CFErrorRef temp = SecTransformConnectTransformsInternal(gtr->GetCFObject(), - sourceTransformRef, sourceAttributeName, - destinationTransformRef, destinationAttributeName); - - if (error) - { - *error = temp; - } - - if (temp) // an error happened? - { - return NULL; - } - else - { - return group; - } -} - - - -Boolean SecTransformSetAttribute(SecTransformRef transformRef, - CFStringRef key, - CFTypeRef value, - CFErrorRef *error) -{ - Boolean result = false; // Guilty until proven - Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - - if (CFGetTypeID(transformRef) == GroupTransform::GetCFTypeID() && !transform->getAH(key, false)) - { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformOperationNotSupportedOnGroup, "SecTransformSetAttribute on non-exported attribute: %@ (exported attributes are: %@).", key, transform->GetAllAH()); - } - - return result; - } - - // if the caller is setting the abort attribute, a value must be supplied - if (NULL == value && CFStringCompare(key, kSecTransformAbortAttributeName, 0) == kCFCompareEqualTo) - { - if (error) - { - // XXX: "a parameter"? It has one: NULL. What it requires is a non-NULL value. - *error = CreateSecTransformErrorRef(kSecTransformInvalidArgument, "ABORT requires a parameter."); - } - - return result; - } - - CFErrorRef temp = transform->ExternalSetAttribute(key, value); - result = (temp == NULL); - if (error) - { - *error = temp; - } - else - { - if (temp) - { - CFRelease(temp); - } - } - - return result; -} - - - -CFTypeRef SecTransformGetAttribute(SecTransformRef transformRef, - CFStringRef key) -{ - // if the transform is a group, we really want to operation on its first object - if (CFGetTypeID(transformRef) == GroupTransform::GetCFTypeID()) - { - return NULL; - } - - Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - if (transform->mIsActive) { - return CreateSecTransformErrorRef(kSecTransformTransformIsExecuting, "Can not get the value of attributes during execution (attempt to fetch %@/%@)", transform->GetName(), key); - } - return transform->GetAttribute(key); -} - - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" -static inline GroupTransform* MakeGroupTransformFromTransformRef(SecTransformRef tr) -{ - GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(tr); - return gt; -} -#pragma clang diagnostic pop - -static CFTypeRef InternalSecTransformExecute(SecTransformRef transformRef, - CFErrorRef* errorRef, - dispatch_queue_t deliveryQueue, - SecMessageBlock deliveryBlock) -{ - if (NULL == transformRef || (deliveryBlock && !deliveryQueue)) - { - CFErrorRef localError = CFErrorCreate(kCFAllocatorDefault, kSecTransformErrorDomain, - kSecTransformInvalidArgument, NULL); - - if (NULL != errorRef) - { - *errorRef = localError; - } - else - { - CFRelease(localError); - } - - return (CFTypeRef)NULL; - } - - // if our transform is a group, connect to its first member instead - if (CFGetTypeID(transformRef) == GroupTransform::GetCFTypeID()) - { - GroupTransform* gtsrc = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - transformRef = gtsrc->GetAnyMember(); - } - - Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - return transform->Execute(deliveryQueue, deliveryBlock, errorRef); -} - -CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef) -{ - if (NULL == transformRef) - { - if (errorRef) - { - *errorRef = CreateSecTransformErrorRef(kSecTransformInvalidArgument, "NULL transform can not be executed"); - } - return NULL; - } - - Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - - // transform->Execute will check this, but by then we have attached a collector which causes all manner of issues. - if (transform->mIsActive) - { - if (errorRef) - { - *errorRef = CreateSecTransformErrorRef(kSecTransformTransformIsExecuting, "The %@ transform has already executed, it may not be executed again.", transform->GetName()); - } - return NULL; - } - - SecTransformRef collectTransform = transforms_assume(SecCreateCollectTransform(errorRef)); - SecGroupTransformRef theGroup = NULL; - Boolean releaseTheGroup = false; - GroupTransform* myGroup = NULL; - Boolean needConnection = true; - - // Sniff the type of the transformRef to see if it is a group - if (SecGroupTransformGetTypeID() == CFGetTypeID(transformRef)) - { - theGroup = (SecGroupTransformRef)transformRef; - } - else - { - // Ok TransformRef is a TransformRef so get's it group - - myGroup = transform->mGroup; - - if (NULL == myGroup) - { - theGroup = SecTransformCreateGroupTransform(); - if (NULL == theGroup) - { - if (NULL != errorRef) - { - *errorRef = GetNoMemoryErrorAndRetain(); - } - - return (CFTypeRef)NULL; - - } - - releaseTheGroup = true; - - SecGroupTransformRef connectResult = - SecTransformConnectTransforms(transformRef, - kSecTransformOutputAttributeName, - collectTransform, - kSecTransformInputAttributeName, - theGroup, errorRef); - - if (NULL == connectResult) - { - return (CFTypeRef)NULL; - } - - needConnection = false; - - } - else - { - theGroup = (SecGroupTransformRef)myGroup->GetCFObject(); - } - } - - if (NULL == theGroup || (SecGroupTransformGetTypeID() != CFGetTypeID(theGroup))) - { - if (NULL != errorRef) - { - *errorRef = GetNoMemoryErrorAndRetain(); - } - - return (CFTypeRef)NULL; - - } - - - if (needConnection) - { - // Connect the collectTransform to the group - myGroup = ((GroupTransform*)CoreFoundationHolder::ObjectFromCFType(theGroup))->GetRootGroup(); - if (NULL == myGroup) - { - if (NULL != errorRef) - { - *errorRef = GetNoMemoryErrorAndRetain(); - } - - return (CFTypeRef)NULL; - } - - SecTransformRef outputTransform = myGroup->FindLastTransform(); - - SecGroupTransformRef connectResult = - SecTransformConnectTransforms(outputTransform, - kSecTransformOutputAttributeName, - collectTransform, - kSecTransformInputAttributeName, - myGroup->GetCFObject(), errorRef); - - if (NULL == connectResult) - { - CFRelease(collectTransform); - if (releaseTheGroup) - { - CFRelease(theGroup); - } - return (CFTypeRef)NULL; - } - } - - __block CFTypeRef myResult = NULL; - dispatch_semaphore_t mySem = dispatch_semaphore_create(0L); - dispatch_queue_t myQueue = dispatch_queue_create("com.apple.security.sectransfrom.SecTransformExecute", NULL); - SecMessageBlock myBlock = ^(CFTypeRef message, CFErrorRef error, Boolean isFinal) - { - if (NULL != error) - { - if (NULL != errorRef) - { - CFRetain(error); - *errorRef = error; - } - - if (NULL != myResult) - { - CFRelease(myResult); - myResult = NULL; - } - } - - if (NULL != message) - { - myResult = message; - CFRetain(myResult); - } - - if (isFinal) - { - dispatch_semaphore_signal(mySem); - } - }; - - SecTransformExecuteAsync(theGroup, myQueue, myBlock); - dispatch_semaphore_wait(mySem, DISPATCH_TIME_FOREVER); - dispatch_release(mySem); - dispatch_release(myQueue); - - if (releaseTheGroup) - { - CFRelease(theGroup); - theGroup = NULL; - } - CFRelease(collectTransform); - - return myResult; -} - -void SecTransformExecuteAsync(SecTransformRef transformRef, - dispatch_queue_t deliveryQueue, - SecMessageBlock deliveryBlock) -{ - CFErrorRef localError = NULL; - InternalSecTransformExecute(transformRef, &localError, deliveryQueue, deliveryBlock); - - // if we got an error (usually a transform startup error), we must deliver it - if (localError != NULL) - { - // The monitor treats a NULL queue as running on it's own queue, which from an appication's point of view is - // the same as a default global queue. Chances are there is no monitor at this point, so it is best to just use the - // global queue for this. - dispatch_queue_t effectiveQueue = deliveryQueue ? deliveryQueue : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); - dispatch_async(effectiveQueue, ^{ - deliveryBlock(NULL, localError, true); - }); - } -} - -CFDictionaryRef SecTransformCopyExternalRepresentation(SecTransformRef transformRef) -{ - - Transform* tr = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - return tr->Externalize(NULL); -} - -CFStringRef SecTransformDotForDebugging(SecTransformRef transformRef) -{ - if (CFGetTypeID(transformRef) == SecGroupTransformGetTypeID()) { - GroupTransform* tr = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - return tr->DotForDebugging(); - } else { - return CFSTR("Can only dot debug a group"); - } -} - -SecTransformRef SecTransformCreateFromExternalRepresentation( - CFDictionaryRef dictionary, - CFErrorRef *error) -{ - // The incoming dictionary consists of a list of transforms and - // a list of connections. We start by making the individual - // transforms and storing them in a dictionary so that we can - // efficiently make connections - - CFArrayRef transforms = (CFArrayRef) CFDictionaryGetValue(dictionary, EXTERN_TRANSFORM_TRANSFORM_ARRAY); - if (transforms == NULL) - { - // The dictionary we got is massively malformed! - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "%@ is missing from the dictionary. The dictionary is malformed.", EXTERN_TRANSFORM_TRANSFORM_ARRAY); - return NULL; - } - - CFArrayRef connections = (CFArrayRef) CFDictionaryGetValue(dictionary, EXTERN_TRANSFORM_CONNECTION_ARRAY); - if (connections == NULL) - { - // The dictionary we got is massively malformed! - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "%@ is missing from the dictionary. The dictionary is malformed.", EXTERN_TRANSFORM_CONNECTION_ARRAY); - return NULL; - } - - CFMutableDictionaryRef transformHolder = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFTypeRefHolder _(transformHolder); - - CFIndex numTransforms = CFArrayGetCount(transforms); - CFIndex n; - - SecTransformRef aTransform; - - for (n = 0; n < numTransforms; ++n) - { - // get the basic info we need - CFDictionaryRef xTransform = (CFDictionaryRef) CFArrayGetValueAtIndex(transforms, n); - - CFStringRef xName = (CFStringRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_NAME); - - CFStringRef xType = (CFStringRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_TYPE); - - // reconstruct the transform - aTransform = TransformFactory::MakeTransformWithType(xType, error); - SecTransformSetAttribute(aTransform, kSecTransformTransformName, xName, NULL); - - // restore the transform state - Transform* tr = (Transform*) CoreFoundationHolder::ObjectFromCFType(aTransform); - tr->RestoreState((CFDictionaryRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_STATE)); - tr->SetCustomExternalData((CFDictionaryRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_CUSTOM_EXPORTS_DICTIONARY)); - - CFIndex cnt = CFDictionaryGetCount(transformHolder); - - // add the transform to the dictionary - CFDictionaryAddValue(transformHolder, xName, aTransform); - - if (CFDictionaryGetCount(transformHolder) <= cnt) - { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, - "Out of memory, or damaged input dictonary (duplicate label %@?)", xName); - } - return NULL; - } - } - - CFIndex numConnections = CFArrayGetCount(connections); - if (numConnections == 0) - { - return aTransform; - } - - SecGroupTransformRef gt = SecTransformCreateGroupTransform(); - - for (n = 0; n < numConnections; ++n) - { - CFDictionaryRef connection = (CFDictionaryRef) CFArrayGetValueAtIndex(connections, n); - CFStringRef fromTransformName = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_FROM_NAME); - CFStringRef fromAttribute = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_FROM_ATTRIBUTE); - CFStringRef toTransformName = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_TO_NAME); - CFStringRef toAttribute = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_TO_ATTRIBUTE); - - SecTransformRef fromTransform = (SecTransformRef) CFDictionaryGetValue(transformHolder, fromTransformName); - if (!fromTransform) { - if (error) { - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "Can't connect %@ to %@ because %@ was not found", fromTransformName, toTransformName, fromTransformName); - } - return NULL; - } - SecTransformRef toTransform = (SecTransformRef) CFDictionaryGetValue(transformHolder, toTransformName); - if (!toTransform) { - if (error) { - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "Can't connect %@ to %@ because %@ was not found", fromTransformName, toTransformName, toTransformName); - } - return NULL; - } - - aTransform = SecTransformConnectTransforms(fromTransform, fromAttribute, toTransform, toAttribute, gt, error); - } - - return gt; -} - - - -SecTransformRef SecTransformFindByName(SecTransformRef transform, CFStringRef name) -{ - Transform *t = (Transform*)CoreFoundationHolder::ObjectFromCFType(transform); - GroupTransform *g = t->GetRootGroup(); - - if (g) { - return g->FindByName(name); - } else { - // There is no group, so if transform isn't our guy nobody is. - return (CFStringCompare(name, t->GetName(), 0) == kCFCompareEqualTo) ? transform : NULL; - } -} - - - -CFTypeID SecGroupTransformGetTypeID() -{ - return GroupTransform::GetCFTypeID(); -} - -CFTypeID SecTransformGetTypeID() -{ - // Obviously this is wrong (returns same CFTypeID as SecTransformGetTypeID) Needs to be fixed - return GroupTransform::GetCFTypeID(); -}