X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_transform/lib/SecCustomTransform.cpp?ds=sidebyside diff --git a/Security/libsecurity_transform/lib/SecCustomTransform.cpp b/Security/libsecurity_transform/lib/SecCustomTransform.cpp deleted file mode 100644 index e8a243e8..00000000 --- a/Security/libsecurity_transform/lib/SecCustomTransform.cpp +++ /dev/null @@ -1,1142 +0,0 @@ -/* - * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include "SecCustomTransform.h" -#include "SecTransformValidator.h" - -#include "TransformFactory.h" -#include -#include -#include -#include "Utilities.h" -#include "misc.h" - -static const CFStringRef kSecCustom = CFSTR("CustomTransform"); -const CFStringRef kSecTransformPreviousErrorKey = CFSTR("PreviousError"); -const CFStringRef kSecTransformAbortOriginatorKey = CFSTR("Originating Transform"); -const CFStringRef kSecTransformActionCanExecute = CFSTR("CanExecute"); -const CFStringRef kSecCustomTransformWhatIsRequired = CFSTR("WhatIsRequired"); -const CFStringRef kSecCustomTransformAttributesToExternalize = CFSTR("AttributesToExternalize"); -const CFStringRef kSecTransformActionStartingExecution = CFSTR("ExecuteStarting"); -const CFStringRef kSecTransformActionProcessData = CFSTR("TransformProcessData"); -const CFStringRef kSecTransformActionAttributeNotification = CFSTR("GenericAttributeSetNotification"); -const CFStringRef kSecTransformActionFinalize = CFSTR("Finalize"); -const CFStringRef kSecTransformActionExternalizeExtraData = CFSTR("ExternalizeExtraData"); -const CFStringRef kSecTransformActionInternalizeExtraData = CFSTR("InternalizeExtraData"); -const CFStringRef kSecTransformActionAttributeValidation = CFSTR("AttributeValidation"); - -/*! - @function SecTransformOverrideTransformAction - - @abstract Used to override the default behavior of a custom transform. - - @param action This should be either kSecTransformActionCanExecute, - kSecTransformActionStartingExecution, or - kSecTransformActionFinalize which signifies the behavior - that is being overridden. - - @param newAction - A SecTransformAttributeActionBlock block that implements the - override behavior. Please see the - SecTransformActionBlock discussion for more - information. - - @result A CFErrorRef if an error occurred, NULL otherwise. - - @discussion An action may be overridden more then once, the most - recent override will be used.Please see the example in - the documentation for the SecTransformActionBlock - block. - -*/ -typedef CFTypeRef (^SecTransformOverrideTransformAction)(CFStringRef action, - SecTransformActionBlock newAction); - -/*! - @function SecTransformOverrideDataAction - - @abstract Changes the default attribute handling for a - specified attribute. - - @param action This should be either kSecTransformActionProcessData, - kSecTransformActionExternalizeExtraData which signifies - what behavior is being overridden. - - @param newAction - A SecTransformDataBlock block that implements the - override behavior. Please see the - SecTransformDataBlock discussion for more - information. - - @result A CFErrorRef if an error occurred. NULL otherwise. - - @discussion An action may be overridden more then once, the most - recent override will be used. Please see the example - in the documentation for the SecTransformAttributeActionBlock - block. - -*/ -typedef CFTypeRef (^SecTransformOverrideDataAction)(CFStringRef action, - SecTransformDataBlock newAction); - -/*! - @function SecTransformOverrideAttributeAction - - @abstract Changes the default attribute handling for a - specified attribute. - - @param action This should be either SecTransformSetAttributeAction, - kSecTransformActionAttributeValidation which signifies - what behavior is being overridden. - - @param attribute - The attribute whose attribute default attribute handling is - being overridden. Passing NULL will override all attributes - that have not been specifically overridden. - - @param newAction - A SecTransformAttributeActionBlock block - that implements the override behavior. - - If the action parameter is SecTransformSetAttributeAction - then this block is called whenever a set is called on the - attribute that this block was registered for or in the case - of a NULL attribute name any attribute that has not been specifically - overridden. The block may transmogrify the data as needed. It may - also send the data to any other attribue by calling - SecTransformCustomSetAttribute. The value returned from the block - will be the new value for the attribute. - - If the action parameter is kSecTransformActionAttributeValidation then - this block is called to validate the new value for the - attribute that this block was registered for or in the case - of a NULL attribute name any attribute that has not been specifically - overridden. The block should test if the new value is acceptable - and return NULL if it is valid a CFErrorRef otherwise. - - @result A CFErrorRef if an error occurred. NULL otherwise. - - @discussion An action may be overridden more then once, the most - recent override will be used. Please see the example - in the documentation for the - SecTransformAttributeActionBlock block. - -*/ -typedef CFTypeRef (^SecTransformOverrideAttributeAction)( - CFStringRef action, - SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock newAction); - - -/*! - @function SecTransformGetAttributeBlock - - @abstract Retrieves the value of the attribute metadata of the - type specified. - - @param attribute - The attribute from which to retrieve the metadata from. - - @param type The type of the metadata to be fetched. - - @result The value of the metadata that was retrieved or a CFErrorRef - if an error occurred - - @result The value of the metadata that was retrieved. - - -*/ -typedef CFTypeRef (^SecTransformGetAttributeBlock)( - SecTransformStringOrAttributeRef attribute, - SecTransformMetaAttributeType type); - -/*! - @function SecTransformSetAttributeBlock - - @abstract This sets the value of the metadata of an attribute. - - @param attribute - The attribute whose value is sent - - @param type The metadata type that specifies what metadata value - is set. - - @param value The value of the metadata to be sent. - - @result A CFErrorRef is an error occurred, NULL otherwise. - - @discussion The attribute parameter specifies which attribute will - have its data set. The type parameter specifies which of - the metadata items is set. The value parameter is the - new metadata value. - -*/ -typedef CFErrorRef (^SecTransformSetAttributeBlock)( - SecTransformStringOrAttributeRef attribute, - SecTransformMetaAttributeType type, - CFTypeRef value); - - -/*! - @function SecTransformPushBackAttributeBlock - - @abstract Allows for putting a single value back for a - specific attribute. This will stop the flow of - data into the specified attribute until an - attribute is changed. - - @param attribute - The attribute that has its data pushed back. - - @param value The value being pushed back. - - - @result A CFErrorRef is an error occurred, NULL otherwise. - Note: pushing back a second value will abort the - transform, not return an error from this call. - - @discussion A particular custom transform may need multple - values to be set before it can do the processing - that the custom transform is designed to do. For - example, it may need a key and a salt value. The - salt value maybe supplied by another transform while - the key transform may have been set explicitly. When - data is presented to this custom transform the salt - value may not have been sent from the upstream transform. - The custom transform can then push back the input data - which causes the transform to stall. When any - attribute on the custom transform is changed, such as - the upstream transform delivers the salt value, then - the data that was pushed back is re-delivered - -*/ -typedef CFErrorRef (^SecTransformPushBackAttributeBlock)( - SecTransformStringOrAttributeRef attribute, - CFTypeRef value); - -/*! - @const kSecTransformCreateBlockParametersVersion - The current version number of the SecTransformCreateBlockParameters - struct - -*/ -enum -{ - kSecTransformCreateBlockParametersVersion = 1 -}; - -extern "C" { - Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error); -} - -/*! - @struct OpaqueSecTransformImplementation - - @field version - The version number of this structure - - @field overrideTransform - A SecTransformOverrideTransformAction block. See - the headerdoc for this block for additional information. - - @field overrideAttribute - A SecTransformOverrideAttributeAction block. See - the headerdoc for this block for additional information. - - @field get - A SecTransformGetAttributeBlock block. See - the headerdoc for this block for additional information. - - @field send - A SecTransformSetAttributeBlock block. See - the headerdoc for this block for additional information. - - @field pushback - A SecTransformPushBackAttributeBlock block. See - the headerdoc for this block for additional information. -*/ -struct OpaqueSecTransformImplementation -{ - CFIndex version; // Set to kSecTransformCreateBlockParametersVersion - - // The following two blocks allow for overriding 'standard' - // transform behavior - SecTransformOverrideTransformAction overrideTransform; - SecTransformOverrideDataAction overrideData; - SecTransformOverrideAttributeAction overrideAttribute; - - // The following methods allow for dealing with the transform mechanism - // They are called synchronously - SecTransformGetAttributeBlock get; - SecTransformSetAttributeBlock send; - SecTransformPushBackAttributeBlock pushback; -}; - - -class CustomTransformFactory : public TransformFactory -{ -protected: - SecTransformCreateFP createFuncPtr; -public: - CustomTransformFactory(CFStringRef name, SecTransformCreateFP createFP, CFErrorRef *error); - virtual ~CustomTransformFactory() {}; - virtual CFTypeRef Make(); -}; - - -static SecTransformActionBlock default_can_run = ^{ return (CFTypeRef)NULL; }; -static SecTransformActionBlock default_execute_starting = default_can_run; -static SecTransformActionBlock default_finalize = default_execute_starting; -static SecTransformActionBlock default_externalize_data = default_finalize; - -static SecTransformDataBlock default_process_data = ^(CFTypeRef value) { return value; }; -//static SecTransformDataBlock default_validate = ^(CFTypeRef value) { return (CFTypeRef)NULL; }; -static SecTransformAttributeActionBlock default_generic_attribute_set_notification = - ^(SecTransformAttributeRef ah, CFTypeRef value) { return value; }; - -static SecTransformAttributeActionBlock default_generic_attribute_validation = -^(SecTransformAttributeRef ah, CFTypeRef value) -{ - return (CFTypeRef)NULL; -}; - -static SecTransformDataBlock default_internalize_data = - ^(CFTypeRef value) -{ - return (CFTypeRef)NULL; -}; - -class CustomTransform : public Transform -{ -protected: - SecTransformCreateFP createFuncPtr; - SecTransformInstanceBlock instanceBlock; - - SecTransformActionBlock can_run; - SecTransformActionBlock execute_starting; - SecTransformActionBlock finalize; - SecTransformAttributeActionBlock generic_attribute_set_notification; - SecTransformAttributeActionBlock generic_attribute_validation; - SecTransformDataBlock process_data; - SecTransformActionBlock externalize_data; - SecTransformDataBlock internalize_data; - - SecTransformRef tr; - - SecTransformAttributeRef input_ah; - SecTransformAttributeRef output_ah; - - OpaqueSecTransformImplementation parameters; - - void SetCanExecute(SecTransformActionBlock CanExecuteBlock) - { - Block_release(can_run); - if (CanExecuteBlock) - { - can_run = Block_copy(CanExecuteBlock); - - } - else - { - can_run = Block_copy(default_can_run); - } - } - - void SetExecuteStarting(SecTransformActionBlock executeStartingBlock) - { - Block_release(execute_starting); - if (executeStartingBlock) - { - execute_starting = Block_copy(executeStartingBlock); - - } - else - { - execute_starting = Block_copy(default_execute_starting); - } - } - - void SetFinalize(SecTransformActionBlock finalizeBlock) - { - Block_release(finalize); - if (finalizeBlock) - { - finalize = Block_copy(finalizeBlock); - - } - else - { - finalize = Block_copy(default_finalize); - } - } - - void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock) - { - Block_release(externalizeBlock); - if (externalizeBlock) - { - externalize_data = Block_copy(externalizeBlock); - - } - else - { - externalize_data = Block_copy(default_externalize_data); - } - } - - void SetProcessData(SecTransformDataBlock processDataBlock) - { - Block_release(process_data); - if (processDataBlock) - { - process_data = Block_copy(processDataBlock); - - } - else - { - process_data = Block_copy(default_process_data); - } - } - - void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock) - { - Block_release(internalize_data); - if (InternalizeExtraDataBlock) - { - internalize_data = Block_copy(InternalizeExtraDataBlock); - - } - else - { - internalize_data = Block_copy(default_internalize_data); - } - } - - - - void SetNotficationBlock(SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock notificationBlock) - { - SecTransformAttributeActionBlock blockToSet = - Block_copy((notificationBlock) ? notificationBlock : - default_generic_attribute_set_notification); - - if (attribute) - { - transform_attribute *ta = getTA(attribute, true); - - if (ta->attribute_changed_block) - { - Block_release(ta->attribute_changed_block); - } - - ta->attribute_changed_block = blockToSet; - } - else - { - - if (generic_attribute_set_notification) - { - Block_release(generic_attribute_set_notification); - } - - generic_attribute_set_notification = blockToSet; - } - } - - void SetVerifyBlock(SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock verifyBlock) - { - SecTransformAttributeActionBlock blockToSet = - Block_copy((verifyBlock) ? verifyBlock : - generic_attribute_validation); - - if (attribute) - { - transform_attribute *ta = getTA(attribute, true); - - if (ta->attribute_validate_block) - { - Block_release(ta->attribute_validate_block); - } - - ta->attribute_validate_block = blockToSet; - } - else - { - if (generic_attribute_validation) - { - Block_release(generic_attribute_validation); - } - - generic_attribute_validation = blockToSet; - } - } - - - -public: - CustomTransform(CFStringRef name, SecTransformCreateFP createFP); - virtual ~CustomTransform(); - - void Create(); - - CFTypeRef rebind_data_action(CFStringRef action, - SecTransformDataBlock new_action); - - CFTypeRef rebind_transform_action(CFStringRef action, SecTransformActionBlock new_action); - - CFTypeRef rebind_attribute_action(CFStringRef action, - SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock new_action); - - SecTransformRef get_ref() { return tr; } - - virtual void AttributeChanged(CFStringRef name, CFTypeRef value); - virtual void AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value); - virtual CFErrorRef TransformStartingExecution(); - virtual CFDictionaryRef GetCustomExternalData(); - virtual void SetCustomExternalData(CFDictionaryRef customData); - - friend Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error); -}; - - - -#pragma mark CustomTransformFactory - -CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName, SecTransformCreateFP createFP, CFErrorRef* error) : - TransformFactory(uniqueName, false, kSecCustom), - createFuncPtr(createFP) -{ - TransformFactory *existing = FindTransformFactoryByType(uniqueName); - if (existing) - { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered, - "Custom transform type %s already exists.", uniqueName); - } - return; - } - - - if (CFStringGetCharacterAtIndex(uniqueName, 0) == '_') - { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformInvalidArgument, - "Invalid transform type name %s -- type names must not start with an _", uniqueName); - } - return; - } - - static CFCharacterSetRef invalidTypeCharactors = NULL; - static dispatch_once_t setupInvalidTypeCharactors; - dispatch_once(&setupInvalidTypeCharactors, ^{ - invalidTypeCharactors = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR("/:")); - }); - CFRange has_bad; - if (CFStringFindCharacterFromSet(uniqueName, invalidTypeCharactors, CFRangeMake(0, CFStringGetLength(uniqueName)), 0, &has_bad)) { - if (error) - { - *error = CreateSecTransformErrorRef(kSecTransformInvalidArgument, - "Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName, has_bad.location), uniqueName); - } - return; - } - RegisterTransform(this, kSecCustom); -} - -CFTypeRef CustomTransformFactory::Make() -{ - CustomTransform *ct = new CustomTransform(this->GetTypename(), createFuncPtr); - ct->Create(); - return ct->get_ref(); -} - -#pragma mark MISC - -extern "C" { - SecTransformAttributeActionBlock SecTransformCreateValidatorForCFtype(CFTypeID expected_type, Boolean null_allowed) { - SecTransformAttributeActionBlock validate = NULL; - CFErrorRef (^make_error_message)(SecTransformAttributeRef attr, CFTypeRef value, CFTypeID expected_type, Boolean null_allowed) = - ^(SecTransformAttributeRef attr, CFTypeRef value, CFTypeID expected_type, Boolean null_allowed) { - CFStringRef expected_type_name = CFCopyTypeIDDescription(expected_type); - CFErrorRef error = NULL; - if (value) { - CFStringRef value_type_name = CFCopyTypeIDDescription(CFGetTypeID(value)); - error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "%@ received value of type %@ (%@), expected%@ a %@%@", - attr, value_type_name, value, - null_allowed ? CFSTR(" either") : CFSTR(""), - expected_type_name, - null_allowed ? CFSTR(" or a NULL") : CFSTR("")); - CFRelease(value_type_name); - } else { - error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "%@ received NULL value, expected a %@", - attr, expected_type_name); - } - CFRelease(expected_type_name); - - return error; - }; - - - if (null_allowed) { - validate = ^(SecTransformAttributeRef attr, CFTypeRef value) { - if (value == NULL || CFGetTypeID(value) == expected_type) { - return (CFTypeRef)NULL; - } - return (CFTypeRef)make_error_message(attr, value, expected_type, null_allowed); - }; - } else { - validate = ^(SecTransformAttributeRef attr, CFTypeRef value) { - if (value != NULL && CFGetTypeID(value) == expected_type) { - return (CFTypeRef)NULL; - } - return (CFTypeRef)make_error_message(attr, value, expected_type, null_allowed); - }; - } - - return Block_copy(validate); - } -} - -Boolean SecTransformRegister(CFStringRef uniqueName, SecTransformCreateFP createFP, CFErrorRef *caller_error) -{ - CFErrorRef error = NULL; - - CustomTransformFactory *tf = new CustomTransformFactory(uniqueName, createFP, &error); - if (error) - { - delete tf; - if (caller_error) - { - *caller_error = error; - } - return FALSE; - } - else - { - return TRUE; - } -} - -SecTransformRef SecTransformCreate(CFStringRef name, CFErrorRef *error) -{ - SecTransformRef tr = TransformFactory::MakeTransformWithType(name, error); - return tr; -} - -extern "C" { - Boolean SecExternalSourceSetValue(SecTransformRef xst, CFTypeRef value, CFErrorRef *error) - { - CustomTransform *ct = (CustomTransform *)CoreFoundationHolder::ObjectFromCFType(xst); - extern CFStringRef external_source_name; - if (CFEqual(ct->mTypeName, external_source_name)) { - ct->SetAttribute(ct->input_ah, value); - return true; - } else { - if (error) { - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct->GetName(), ct->mTypeName); - } - return false; - } - } -} - -/* ========================================================================== - class: NoDataClass - description: A Special CFType that signifies that no data is being - returned - ==========================================================================*/ -#pragma mark NoDataClass - -class NoDataClass : public CoreFoundationObject -{ -protected: - NoDataClass(); - -public: - virtual ~NoDataClass(); - std::string FormattingDescription(CFDictionaryRef options); - std::string DebugDescription(); - static CFTypeRef Make(); -}; - -CFTypeRef NoDataClass::Make() { - NoDataClass* obj = new NoDataClass(); - return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName, obj); -} - - -NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName) { -} - -NoDataClass::~NoDataClass() -{ -} - -std::string NoDataClass::DebugDescription() -{ - return CoreFoundationObject::DebugDescription() + " | SecTransformNoData"; -} - -std::string NoDataClass::FormattingDescription(CFDictionaryRef options) -{ - return CoreFoundationObject::FormattingDescription(options) + " | SecTransformNoData"; -} - -CFTypeRef SecTransformNoData() -{ - static dispatch_once_t inited; - static CFTypeRef no_data; - - dispatch_once(&inited, - ^{ - no_data = NoDataClass::Make(); - }); - - return no_data; -} - -/* ========================================================================== - class Implementation CustomTransform - ==========================================================================*/ - -#pragma mark CustomTransform - -void CustomTransform::AttributeChanged(CFStringRef name, CFTypeRef value) { -#ifndef NDEBUG - // We really shouldn't get here, and this is the debug build so we can blow up on the spot so it is easy to look at the stack trace - abort(); -#else - // We really shouldn't get here, but this is a production build and recovery is easy to code (but costly to execute) - AttributeChanged(getAH(name, false), value); -#endif -} - -void CustomTransform::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value) -{ - transform_attribute *ta = ah2ta(ah); - SecTransformAttributeActionBlock attribute_set_notification = NULL; - - SecTransformAttributeActionBlock attribute_validate = NULL; - - attribute_validate = (SecTransformAttributeActionBlock)ta->attribute_validate_block; - if (!attribute_validate) { - attribute_validate = generic_attribute_validation; - } - CFTypeRef vr = attribute_validate(ah, value); - if (vr) { - if (CFGetTypeID(vr) == CFErrorGetTypeID()) { - SendAttribute(AbortAH, vr); - CFRelease(vr); - } else { - CFErrorRef e = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr)), vr); - SendAttribute(AbortAH, e); - CFRelease(vr); - // XXX: this causes a core dump -- I think AbortAH doesn't take it's own reference!! CFRelease(e); - } - return; - } - - attribute_set_notification = (SecTransformAttributeActionBlock)ta->attribute_changed_block; - - if ((!attribute_set_notification) && ah == input_ah) - { - CFTypeID vtype = value ? CFGetTypeID(value) : CFDataGetTypeID(); - if (vtype == CFDataGetTypeID()) - { - CFTypeRef output = process_data(value); - if (output == NULL || output != SecTransformNoData()) - { - SendAttribute(output_ah, output); - - // if output == value, we are being asked to just - // forward the existing value. No need to release. - // If they are different, we are being asked to - // send a new value which must be released. - - if (output != value && output != NULL) - { - CFRelease(output); - } - } - } - else if (vtype == CFErrorGetTypeID() && !ah2ta(ah)->direct_error_handling) - { - SendAttribute(output_ah, value); - } else - { - attribute_set_notification = attribute_set_notification ? attribute_set_notification : generic_attribute_set_notification; - CFTypeRef new_value = attribute_set_notification(ah, value); - if (new_value != value) - { - SendAttribute(ah, new_value); - } - } - } - else - { - CFTypeID vtype = value ? CFGetTypeID(value) : CFDataGetTypeID(); - if (vtype != CFErrorGetTypeID() || ah2ta(ah)->direct_error_handling) - { - attribute_set_notification = attribute_set_notification ? attribute_set_notification : generic_attribute_set_notification; - CFTypeRef new_value = attribute_set_notification(ah, value); - if (new_value != value) - { - SendAttribute(ah, new_value); - } - } - else - { - SendAttribute(output_ah, value); - } - } -} - -CFTypeRef CustomTransform::rebind_data_action(CFStringRef action, - SecTransformDataBlock new_action) -{ - CFTypeRef result = NULL; - if (kCFCompareEqualTo == CFStringCompare(kSecTransformActionProcessData, action, 0)) - { - SetProcessData(new_action); - } - else if (kCFCompareEqualTo == CFStringCompare(kSecTransformActionInternalizeExtraData, action, 0)) - { - SetInternalizeExtraData(new_action); - } - else - { - result = (CFTypeRef)CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type"); - - // XXX: can we get a stackdump here too? - CFStringRef msg = CFStringCreateWithFormat(NULL, NULL, - CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"), - action, (void*)new_action, DebugDescription().c_str()); - char *utf8_message = utf8(msg); - syslog(LOG_ERR, "%s", utf8_message); - free(utf8_message); - CFRelease(msg); - } - return result; -} - -CFTypeRef CustomTransform::rebind_transform_action(CFStringRef action, SecTransformActionBlock new_action) -{ - CFErrorRef result = NULL; - - if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionCanExecute, 0)) - { - SetCanExecute(new_action); - } - else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionStartingExecution, 0)) - { - SetExecuteStarting(new_action); - } - else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionFinalize, 0)) - { - SetFinalize(new_action); - } - else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionExternalizeExtraData, 0)) - { - SetExternalizeExtraData(new_action); - } - else - { - result = CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type"); - - char *action_utf8 = utf8(action); - syslog(LOG_ERR, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8, (void*)new_action, DebugDescription().c_str()); - free(action_utf8); - } - - return result; -} - -CFTypeRef CustomTransform::rebind_attribute_action( - CFStringRef action, - SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock new_action) -{ - CFErrorRef result = NULL; - - if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionAttributeNotification, 0)) - { - SetNotficationBlock(attribute, new_action); - } - else if (kCFCompareEqualTo == CFStringCompare(action, kSecTransformActionAttributeValidation, 0)) - { - SetVerifyBlock(attribute, new_action); - } - else - { - result = CreateSecTransformErrorRef(kSecTransformInvalidOverride, "Unkown override type"); - char *action_utf8 = utf8(action); - syslog(LOG_ERR, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8, (void*)new_action, DebugDescription().c_str()); - free(action_utf8); - } - - return result; -} - -CustomTransform::CustomTransform(CFStringRef cfname, SecTransformCreateFP createFP) : - Transform(cfname), - createFuncPtr(createFP), - instanceBlock(NULL), - can_run(Block_copy(default_can_run)), - execute_starting(Block_copy(default_execute_starting)), - finalize(Block_copy(default_finalize)), - generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification)), - generic_attribute_validation(Block_copy(default_generic_attribute_validation)), - process_data(Block_copy(default_process_data)), - externalize_data(Block_copy(default_externalize_data)), - internalize_data(Block_copy(default_internalize_data)) -{ - mAlwaysSelfNotify = true; - - input_ah = getAH(kSecTransformInputAttributeName, true); - output_ah = getAH(kSecTransformOutputAttributeName, true); - - parameters.version = kSecTransformCreateBlockParametersVersion; - parameters.send = Block_copy(^(SecTransformStringOrAttributeRef attribute, SecTransformMetaAttributeType type, CFTypeRef value) - { - return SendMetaAttribute(attribute, type, value); - }); - - parameters.pushback = Block_copy(^(SecTransformStringOrAttributeRef attribute, CFTypeRef value) - { - return Pushback(getAH(attribute), value); - }); - - parameters.get = Block_copy(^(SecTransformStringOrAttributeRef attribute, SecTransformMetaAttributeType type) - { - return GetMetaAttribute(attribute, type); - }); - - parameters.overrideTransform = Block_copy(^(CFStringRef action, SecTransformActionBlock new_action) - { - return rebind_transform_action(action, new_action); - }); - - parameters.overrideData = Block_copy(^(CFStringRef action, - SecTransformDataBlock new_action) - { - return rebind_data_action(action, new_action); - }); - - /* - CFTypeRef (^SecTransformOverrideAttributeAction)( - CFStringRef action, - SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock newAction); - */ - parameters.overrideAttribute = - Block_copy(^(CFStringRef action, SecTransformStringOrAttributeRef attribute, SecTransformAttributeActionBlock new_action) - { - return rebind_attribute_action(action, attribute, new_action); - }); - - char *tname = const_cast(CFStringGetCStringPtr(cfname, kCFStringEncodingUTF8)); - if (!tname) { - CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname), kCFStringEncodingUTF8); - tname = static_cast(alloca(sz)); - CFStringGetCString(cfname, tname, sz, kCFStringEncodingUTF8); - } - tr = CoreFoundationHolder::MakeHolder(kSecCustom, (CoreFoundationObject*)this); - - instanceBlock = (*createFuncPtr)(cfname, tr, ¶meters); -} - -void CustomTransform::Create() -{ - (void)instanceBlock(); -} - - -CustomTransform::~CustomTransform() { - finalize(); - - if (instanceBlock) - { - Block_release(instanceBlock); - } - - Block_release(can_run); - Block_release(execute_starting); - Block_release(finalize); - Block_release(generic_attribute_set_notification); - Block_release(process_data); - Block_release(externalize_data); - Block_release(internalize_data); - - Block_release(parameters.send); - Block_release(parameters.pushback); - Block_release(parameters.get); - Block_release(parameters.overrideTransform); - Block_release(parameters.overrideData); - Block_release(parameters.overrideAttribute); - - // strictly speaking this isn't needed, but it can help track down some "use after free" bugs - tr = NULL; - createFuncPtr = NULL; - process_data = NULL; -} - -CFErrorRef CustomTransform::TransformStartingExecution() -{ - CFTypeRef result = execute_starting(); - return (CFErrorRef)result; -} - - -CFDictionaryRef CustomTransform::GetCustomExternalData() -{ - CFTypeRef result = externalize_data(); - if (NULL == result) - { - return NULL; - } - - if (CFGetTypeID(result) == CFErrorGetTypeID()) - { - // Ouch! we should deal with this - CFRelease(result); - return NULL; - } - - if (CFGetTypeID(result) == CFDictionaryGetTypeID()) - { - return (CFDictionaryRef)result; - } - - CFRelease(result); - result = NULL; - return (CFDictionaryRef)result; -} - - -void CustomTransform::SetCustomExternalData(CFDictionaryRef customData) -{ - if (NULL != customData) - { - internalize_data(customData); - } - return; -} - -CFErrorRef SecTransformSetAttributeAction(SecTransformImplementationRef ref, - CFStringRef action, - SecTransformStringOrAttributeRef attribute, - SecTransformAttributeActionBlock newAction) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref"); - - return result; - } - - return (CFErrorRef)ref->overrideAttribute(action, attribute, newAction); -} - -CFErrorRef SecTransformSetDataAction(SecTransformImplementationRef ref, - CFStringRef action, - SecTransformDataBlock newAction) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref"); - - return result; - } - - return (CFErrorRef)ref->overrideData(action, newAction); -} - -CFErrorRef SecTransformSetTransformAction(SecTransformImplementationRef ref, - CFStringRef action, - SecTransformActionBlock newAction) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref"); - - return result; - } - - return (CFErrorRef)ref->overrideTransform(action, newAction); -} - -CFTypeRef SecTranformCustomGetAttribute(SecTransformImplementationRef ref, - SecTransformStringOrAttributeRef attribute, - SecTransformMetaAttributeType type) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref"); - - return result; - } - - return (CFErrorRef)ref->get(attribute, type); -} - -CFTypeRef SecTransformCustomSetAttribute(SecTransformImplementationRef ref, - SecTransformStringOrAttributeRef attribute, - SecTransformMetaAttributeType type, - CFTypeRef value) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref"); - - return result; - } - - return (CFErrorRef)ref->send(attribute, type, value); - -} - -CFTypeRef SecTransformPushbackAttribute(SecTransformImplementationRef ref, - SecTransformStringOrAttributeRef attribute, - CFTypeRef value) -{ - if (NULL == ref) - { - CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, - "SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref"); - - return (CFTypeRef)result; - } - - return ref->pushback(attribute, value); -}