2 * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "SecCustomTransform.h"
26 #include "SecTransformValidator.h"
28 #include "TransformFactory.h"
29 #include <CoreFoundation/CoreFoundation.h>
32 #include "Utilities.h"
35 static const CFStringRef kSecCustom
= CFSTR("CustomTransform");
36 const CFStringRef kSecTransformPreviousErrorKey
= CFSTR("PreviousError");
37 const CFStringRef kSecTransformAbortOriginatorKey
= CFSTR("Originating Transform");
38 const CFStringRef kSecTransformActionCanExecute
= CFSTR("CanExecute");
39 const CFStringRef kSecTransformActionStartingExecution
= CFSTR("ExecuteStarting");
40 const CFStringRef kSecTransformActionProcessData
= CFSTR("TransformProcessData");
41 const CFStringRef kSecTransformActionAttributeNotification
= CFSTR("GenericAttributeSetNotification");
42 const CFStringRef kSecTransformActionFinalize
= CFSTR("Finalize");
43 const CFStringRef kSecTransformActionExternalizeExtraData
= CFSTR("ExternalizeExtraData");
44 const CFStringRef kSecTransformActionInternalizeExtraData
= CFSTR("InternalizeExtraData");
45 const CFStringRef kSecTransformActionAttributeValidation
= CFSTR("AttributeValidation");
48 @function SecTransformOverrideTransformAction
50 @abstract Used to override the default behavior of a custom transform.
52 @param action This should be either kSecTransformActionCanExecute,
53 kSecTransformActionStartingExecution, or
54 kSecTransformActionFinalize which signifies the behavior
55 that is being overridden.
58 A SecTransformAttributeActionBlock block that implements the
59 override behavior. Please see the
60 SecTransformActionBlock discussion for more
63 @result A CFErrorRef if an error occurred, NULL otherwise.
65 @discussion An action may be overridden more then once, the most
66 recent override will be used.Please see the example in
67 the documentation for the SecTransformActionBlock
71 typedef CFTypeRef (^SecTransformOverrideTransformAction
)(CFStringRef action
,
72 SecTransformActionBlock newAction
);
75 @function SecTransformOverrideDataAction
77 @abstract Changes the default attribute handling for a
80 @param action This should be either kSecTransformActionProcessData,
81 kSecTransformActionExternalizeExtraData which signifies
82 what behavior is being overridden.
85 A SecTransformDataBlock block that implements the
86 override behavior. Please see the
87 SecTransformDataBlock discussion for more
90 @result A CFErrorRef if an error occurred. NULL otherwise.
92 @discussion An action may be overridden more then once, the most
93 recent override will be used. Please see the example
94 in the documentation for the SecTransformAttributeActionBlock
98 typedef CFTypeRef (^SecTransformOverrideDataAction
)(CFStringRef action
,
99 SecTransformDataBlock newAction
);
102 @function SecTransformOverrideAttributeAction
104 @abstract Changes the default attribute handling for a
107 @param action This should be either SecTransformSetAttributeAction,
108 kSecTransformActionAttributeValidation which signifies
109 what behavior is being overridden.
112 The attribute whose attribute default attribute handling is
113 being overridden. Passing NULL will override all attributes
114 that have not been specifically overridden.
117 A SecTransformAttributeActionBlock block
118 that implements the override behavior.
120 If the action parameter is SecTransformSetAttributeAction
121 then this block is called whenever a set is called on the
122 attribute that this block was registered for or in the case
123 of a NULL attribute name any attribute that has not been specifically
124 overridden. The block may transmogrify the data as needed. It may
125 also send the data to any other attribue by calling
126 SecTransformCustomSetAttribute. The value returned from the block
127 will be the new value for the attribute.
129 If the action parameter is kSecTransformActionAttributeValidation then
130 this block is called to validate the new value for the
131 attribute that this block was registered for or in the case
132 of a NULL attribute name any attribute that has not been specifically
133 overridden. The block should test if the new value is acceptable
134 and return NULL if it is valid a CFErrorRef otherwise.
136 @result A CFErrorRef if an error occurred. NULL otherwise.
138 @discussion An action may be overridden more then once, the most
139 recent override will be used. Please see the example
140 in the documentation for the
141 SecTransformAttributeActionBlock block.
144 typedef CFTypeRef (^SecTransformOverrideAttributeAction
)(
146 SecTransformStringOrAttributeRef attribute
,
147 SecTransformAttributeActionBlock newAction
);
151 @function SecTransformGetAttributeBlock
153 @abstract Retrieves the value of the attribute metadata of the
157 The attribute from which to retrieve the metadata from.
159 @param type The type of the metadata to be fetched.
161 @result The value of the metadata that was retrieved or a CFErrorRef
164 @result The value of the metadata that was retrieved.
168 typedef CFTypeRef (^SecTransformGetAttributeBlock
)(
169 SecTransformStringOrAttributeRef attribute
,
170 SecTransformMetaAttributeType type
);
173 @function SecTransformSetAttributeBlock
175 @abstract This sets the value of the metadata of an attribute.
178 The attribute whose value is sent
180 @param type The metadata type that specifies what metadata value
183 @param value The value of the metadata to be sent.
185 @result A CFErrorRef is an error occurred, NULL otherwise.
187 @discussion The attribute parameter specifies which attribute will
188 have its data set. The type parameter specifies which of
189 the metadata items is set. The value parameter is the
193 typedef CFErrorRef (^SecTransformSetAttributeBlock
)(
194 SecTransformStringOrAttributeRef attribute
,
195 SecTransformMetaAttributeType type
,
200 @function SecTransformPushBackAttributeBlock
202 @abstract Allows for putting a single value back for a
203 specific attribute. This will stop the flow of
204 data into the specified attribute until an
205 attribute is changed.
208 The attribute that has its data pushed back.
210 @param value The value being pushed back.
213 @result A CFErrorRef is an error occurred, NULL otherwise.
214 Note: pushing back a second value will abort the
215 transform, not return an error from this call.
217 @discussion A particular custom transform may need multple
218 values to be set before it can do the processing
219 that the custom transform is designed to do. For
220 example, it may need a key and a salt value. The
221 salt value maybe supplied by another transform while
222 the key transform may have been set explicitly. When
223 data is presented to this custom transform the salt
224 value may not have been sent from the upstream transform.
225 The custom transform can then push back the input data
226 which causes the transform to stall. When any
227 attribute on the custom transform is changed, such as
228 the upstream transform delivers the salt value, then
229 the data that was pushed back is re-delivered
232 typedef CFErrorRef (^SecTransformPushBackAttributeBlock
)(
233 SecTransformStringOrAttributeRef attribute
,
237 @const kSecTransformCreateBlockParametersVersion
238 The current version number of the SecTransformCreateBlockParameters
244 kSecTransformCreateBlockParametersVersion
= 1
248 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
252 @struct OpaqueSecTransformImplementation
255 The version number of this structure
257 @field overrideTransform
258 A SecTransformOverrideTransformAction block. See
259 the headerdoc for this block for additional information.
261 @field overrideAttribute
262 A SecTransformOverrideAttributeAction block. See
263 the headerdoc for this block for additional information.
266 A SecTransformGetAttributeBlock block. See
267 the headerdoc for this block for additional information.
270 A SecTransformSetAttributeBlock block. See
271 the headerdoc for this block for additional information.
274 A SecTransformPushBackAttributeBlock block. See
275 the headerdoc for this block for additional information.
277 struct OpaqueSecTransformImplementation
279 CFIndex version
; // Set to kSecTransformCreateBlockParametersVersion
281 // The following two blocks allow for overriding 'standard'
282 // transform behavior
283 SecTransformOverrideTransformAction overrideTransform
;
284 SecTransformOverrideDataAction overrideData
;
285 SecTransformOverrideAttributeAction overrideAttribute
;
287 // The following methods allow for dealing with the transform mechanism
288 // They are called synchronously
289 SecTransformGetAttributeBlock get
;
290 SecTransformSetAttributeBlock send
;
291 SecTransformPushBackAttributeBlock pushback
;
295 class CustomTransformFactory
: public TransformFactory
298 SecTransformCreateFP createFuncPtr
;
300 CustomTransformFactory(CFStringRef name
, SecTransformCreateFP createFP
, CFErrorRef
*error
);
301 virtual ~CustomTransformFactory() {};
302 virtual CFTypeRef
Make();
306 static SecTransformActionBlock default_can_run
= ^{ return (CFTypeRef
)NULL
; };
307 static SecTransformActionBlock default_execute_starting
= default_can_run
;
308 static SecTransformActionBlock default_finalize
= default_execute_starting
;
309 static SecTransformActionBlock default_externalize_data
= default_finalize
;
311 static SecTransformDataBlock default_process_data
= ^(CFTypeRef value
) { return value
; };
312 //static SecTransformDataBlock default_validate = ^(CFTypeRef value) { return (CFTypeRef)NULL; };
313 static SecTransformAttributeActionBlock default_generic_attribute_set_notification
=
314 ^(SecTransformAttributeRef ah
, CFTypeRef value
) { return value
; };
316 static SecTransformAttributeActionBlock default_generic_attribute_validation
=
317 ^(SecTransformAttributeRef ah
, CFTypeRef value
)
319 return (CFTypeRef
)NULL
;
322 static SecTransformDataBlock default_internalize_data
=
325 return (CFTypeRef
)NULL
;
328 class CustomTransform
: public Transform
331 SecTransformCreateFP createFuncPtr
;
332 SecTransformInstanceBlock instanceBlock
;
334 SecTransformActionBlock can_run
;
335 SecTransformActionBlock execute_starting
;
336 SecTransformActionBlock finalize
;
337 SecTransformAttributeActionBlock generic_attribute_set_notification
;
338 SecTransformAttributeActionBlock generic_attribute_validation
;
339 SecTransformDataBlock process_data
;
340 SecTransformActionBlock externalize_data
;
341 SecTransformDataBlock internalize_data
;
345 SecTransformAttributeRef input_ah
;
346 SecTransformAttributeRef output_ah
;
348 OpaqueSecTransformImplementation parameters
;
350 void SetCanExecute(SecTransformActionBlock CanExecuteBlock
)
352 Block_release(can_run
);
355 can_run
= Block_copy(CanExecuteBlock
);
360 can_run
= Block_copy(default_can_run
);
364 void SetExecuteStarting(SecTransformActionBlock executeStartingBlock
)
366 Block_release(execute_starting
);
367 if (executeStartingBlock
)
369 execute_starting
= Block_copy(executeStartingBlock
);
374 execute_starting
= Block_copy(default_execute_starting
);
378 void SetFinalize(SecTransformActionBlock finalizeBlock
)
380 Block_release(finalize
);
383 finalize
= Block_copy(finalizeBlock
);
388 finalize
= Block_copy(default_finalize
);
392 void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock
)
394 Block_release(externalizeBlock
);
395 if (externalizeBlock
)
397 externalize_data
= Block_copy(externalizeBlock
);
402 externalize_data
= Block_copy(default_externalize_data
);
406 void SetProcessData(SecTransformDataBlock processDataBlock
)
408 Block_release(process_data
);
409 if (processDataBlock
)
411 process_data
= Block_copy(processDataBlock
);
416 process_data
= Block_copy(default_process_data
);
420 void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock
)
422 Block_release(internalize_data
);
423 if (InternalizeExtraDataBlock
)
425 internalize_data
= Block_copy(InternalizeExtraDataBlock
);
430 internalize_data
= Block_copy(default_internalize_data
);
436 void SetNotficationBlock(SecTransformStringOrAttributeRef attribute
,
437 SecTransformAttributeActionBlock notificationBlock
)
439 SecTransformAttributeActionBlock blockToSet
=
440 Block_copy((notificationBlock
) ? notificationBlock
:
441 default_generic_attribute_set_notification
);
445 transform_attribute
*ta
= getTA(attribute
, true);
447 if (ta
->attribute_changed_block
)
449 Block_release(ta
->attribute_changed_block
);
452 ta
->attribute_changed_block
= blockToSet
;
457 if (generic_attribute_set_notification
)
459 Block_release(generic_attribute_set_notification
);
462 generic_attribute_set_notification
= blockToSet
;
466 void SetVerifyBlock(SecTransformStringOrAttributeRef attribute
,
467 SecTransformAttributeActionBlock verifyBlock
)
469 SecTransformAttributeActionBlock blockToSet
=
470 Block_copy((verifyBlock
) ? verifyBlock
:
471 generic_attribute_validation
);
475 transform_attribute
*ta
= getTA(attribute
, true);
477 if (ta
->attribute_validate_block
)
479 Block_release(ta
->attribute_validate_block
);
482 ta
->attribute_validate_block
= blockToSet
;
486 if (generic_attribute_validation
)
488 Block_release(generic_attribute_validation
);
491 generic_attribute_validation
= blockToSet
;
498 CustomTransform(CFStringRef name
, SecTransformCreateFP createFP
);
499 virtual ~CustomTransform();
503 CFTypeRef
rebind_data_action(CFStringRef action
,
504 SecTransformDataBlock new_action
);
506 CFTypeRef
rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
);
508 CFTypeRef
rebind_attribute_action(CFStringRef action
,
509 SecTransformStringOrAttributeRef attribute
,
510 SecTransformAttributeActionBlock new_action
);
512 SecTransformRef
get_ref() { return tr
; }
514 virtual void AttributeChanged(CFStringRef name
, CFTypeRef value
);
515 virtual void AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
);
516 virtual CFErrorRef
TransformStartingExecution();
517 virtual CFDictionaryRef
GetCustomExternalData();
518 virtual void SetCustomExternalData(CFDictionaryRef customData
);
520 friend Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
525 #pragma mark CustomTransformFactory
527 CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
* error
) :
528 TransformFactory(uniqueName
, false, kSecCustom
),
529 createFuncPtr(createFP
)
531 TransformFactory
*existing
= FindTransformFactoryByType(uniqueName
);
536 *error
= CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered
,
537 "Custom transform type %s already exists.", uniqueName
);
543 if (CFStringGetCharacterAtIndex(uniqueName
, 0) == '_')
547 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
548 "Invalid transform type name %s -- type names must not start with an _", uniqueName
);
553 static CFCharacterSetRef invalidTypeCharactors
= NULL
;
554 static dispatch_once_t setupInvalidTypeCharactors
;
555 dispatch_once(&setupInvalidTypeCharactors
, ^{
556 invalidTypeCharactors
= CFCharacterSetCreateWithCharactersInString(NULL
, CFSTR("/:"));
559 if (CFStringFindCharacterFromSet(uniqueName
, invalidTypeCharactors
, CFRangeMake(0, CFStringGetLength(uniqueName
)), 0, &has_bad
)) {
562 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
563 "Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName
, has_bad
.location
), uniqueName
);
567 RegisterTransform(this, kSecCustom
);
570 CFTypeRef
CustomTransformFactory::Make()
572 CustomTransform
*ct
= new CustomTransform(this->GetTypename(), createFuncPtr
);
574 return ct
->get_ref();
580 SecTransformAttributeActionBlock
SecTransformCreateValidatorForCFtype(CFTypeID expected_type
, Boolean null_allowed
) {
581 SecTransformAttributeActionBlock validate
= NULL
;
582 CFErrorRef (^make_error_message
)(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) =
583 ^(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) {
584 CFStringRef expected_type_name
= CFCopyTypeIDDescription(expected_type
);
585 CFErrorRef error
= NULL
;
587 CFStringRef value_type_name
= CFCopyTypeIDDescription(CFGetTypeID(value
));
588 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received value of type %@ (%@), expected%@ a %@%@",
589 attr
, value_type_name
, value
,
590 null_allowed
? CFSTR(" either") : CFSTR(""),
592 null_allowed
? CFSTR(" or a NULL") : CFSTR(""));
593 CFRelease(value_type_name
);
595 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received NULL value, expected a %@",
596 attr
, expected_type_name
);
598 CFRelease(expected_type_name
);
605 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
606 if (value
== NULL
|| CFGetTypeID(value
) == expected_type
) {
607 return (CFTypeRef
)NULL
;
609 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
612 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
613 if (value
!= NULL
&& CFGetTypeID(value
) == expected_type
) {
614 return (CFTypeRef
)NULL
;
616 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
620 return Block_copy(validate
);
624 Boolean
SecTransformRegister(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
*caller_error
)
626 CFErrorRef error
= NULL
;
628 CustomTransformFactory
*tf
= new CustomTransformFactory(uniqueName
, createFP
, &error
);
634 *caller_error
= error
;
644 SecTransformRef
SecTransformCreate(CFStringRef name
, CFErrorRef
*error
)
646 SecTransformRef tr
= TransformFactory::MakeTransformWithType(name
, error
);
651 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
)
653 CustomTransform
*ct
= (CustomTransform
*)CoreFoundationHolder::ObjectFromCFType(xst
);
654 extern CFStringRef external_source_name
;
655 if (CFEqual(ct
->mTypeName
, external_source_name
)) {
656 ct
->SetAttribute(ct
->input_ah
, value
);
660 *error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct
->GetName(), ct
->mTypeName
);
667 /* ==========================================================================
669 description: A Special CFType that signifies that no data is being
671 ==========================================================================*/
672 #pragma mark NoDataClass
674 class NoDataClass
: public CoreFoundationObject
680 virtual ~NoDataClass();
681 std::string
FormattingDescription(CFDictionaryRef options
);
682 std::string
DebugDescription();
683 static CFTypeRef
Make();
686 CFTypeRef
NoDataClass::Make() {
687 NoDataClass
* obj
= new NoDataClass();
688 return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName
, obj
);
692 NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName
) {
695 NoDataClass::~NoDataClass()
699 std::string
NoDataClass::DebugDescription()
701 return CoreFoundationObject::DebugDescription() + " | SecTransformNoData";
704 std::string
NoDataClass::FormattingDescription(CFDictionaryRef options
)
706 return CoreFoundationObject::FormattingDescription(options
) + " | SecTransformNoData";
709 CFTypeRef
SecTransformNoData()
711 static dispatch_once_t inited
;
712 static CFTypeRef no_data
;
714 dispatch_once(&inited
,
716 no_data
= NoDataClass::Make();
722 /* ==========================================================================
723 class Implementation CustomTransform
724 ==========================================================================*/
726 #pragma mark CustomTransform
728 void CustomTransform::AttributeChanged(CFStringRef name
, CFTypeRef value
) {
730 // 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
733 // We really shouldn't get here, but this is a production build and recovery is easy to code (but costly to execute)
734 AttributeChanged(getAH(name
, false), value
);
738 void CustomTransform::AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
)
740 transform_attribute
*ta
= ah2ta(ah
);
741 SecTransformAttributeActionBlock attribute_set_notification
= NULL
;
743 SecTransformAttributeActionBlock attribute_validate
= NULL
;
745 attribute_validate
= (SecTransformAttributeActionBlock
)ta
->attribute_validate_block
;
746 if (!attribute_validate
) {
747 attribute_validate
= generic_attribute_validation
;
749 CFTypeRef vr
= attribute_validate(ah
, value
);
751 if (CFGetTypeID(vr
) == CFErrorGetTypeID()) {
752 SendAttribute(AbortAH
, vr
);
755 CFErrorRef e
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr
)), vr
);
756 SendAttribute(AbortAH
, e
);
758 // XXX: this causes a core dump -- I think AbortAH doesn't take it's own reference!! CFRelease(e);
763 attribute_set_notification
= (SecTransformAttributeActionBlock
)ta
->attribute_changed_block
;
765 if ((!attribute_set_notification
) && ah
== input_ah
)
767 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
768 if (vtype
== CFDataGetTypeID())
770 CFTypeRef output
= process_data(value
);
771 if (output
== NULL
|| output
!= SecTransformNoData())
773 SendAttribute(output_ah
, output
);
775 // if output == value, we are being asked to just
776 // forward the existing value. No need to release.
777 // If they are different, we are being asked to
778 // send a new value which must be released.
780 if (output
!= value
&& output
!= NULL
)
786 else if (vtype
== CFErrorGetTypeID() && !ah2ta(ah
)->direct_error_handling
)
788 SendAttribute(output_ah
, value
);
791 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
792 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
793 if (new_value
!= value
)
795 SendAttribute(ah
, new_value
);
801 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
802 if (vtype
!= CFErrorGetTypeID() || ah2ta(ah
)->direct_error_handling
)
804 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
805 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
806 if (new_value
!= value
)
808 SendAttribute(ah
, new_value
);
813 SendAttribute(output_ah
, value
);
818 CFTypeRef
CustomTransform::rebind_data_action(CFStringRef action
,
819 SecTransformDataBlock new_action
)
821 CFTypeRef result
= NULL
;
822 if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionProcessData
, action
, 0))
824 SetProcessData(new_action
);
826 else if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionInternalizeExtraData
, action
, 0))
828 SetInternalizeExtraData(new_action
);
832 result
= (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
834 // XXX: can we get a stackdump here too?
835 CFStringRef msg
= CFStringCreateWithFormat(NULL
, NULL
,
836 CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"),
837 action
, (void*)new_action
, DebugDescription().c_str());
838 char *utf8_message
= utf8(msg
);
839 syslog(LOG_ERR
, "%s", utf8_message
);
846 CFTypeRef
CustomTransform::rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
)
848 CFErrorRef result
= NULL
;
850 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionCanExecute
, 0))
852 SetCanExecute(new_action
);
854 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionStartingExecution
, 0))
856 SetExecuteStarting(new_action
);
858 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionFinalize
, 0))
860 SetFinalize(new_action
);
862 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionExternalizeExtraData
, 0))
864 SetExternalizeExtraData(new_action
);
868 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
870 char *action_utf8
= utf8(action
);
871 syslog(LOG_ERR
, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
878 CFTypeRef
CustomTransform::rebind_attribute_action(
880 SecTransformStringOrAttributeRef attribute
,
881 SecTransformAttributeActionBlock new_action
)
883 CFErrorRef result
= NULL
;
885 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeNotification
, 0))
887 SetNotficationBlock(attribute
, new_action
);
889 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeValidation
, 0))
891 SetVerifyBlock(attribute
, new_action
);
895 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
896 char *action_utf8
= utf8(action
);
897 syslog(LOG_ERR
, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
904 CustomTransform::CustomTransform(CFStringRef cfname
, SecTransformCreateFP createFP
) :
906 createFuncPtr(createFP
),
908 can_run(Block_copy(default_can_run
)),
909 execute_starting(Block_copy(default_execute_starting
)),
910 finalize(Block_copy(default_finalize
)),
911 generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification
)),
912 generic_attribute_validation(Block_copy(default_generic_attribute_validation
)),
913 process_data(Block_copy(default_process_data
)),
914 externalize_data(Block_copy(default_externalize_data
)),
915 internalize_data(Block_copy(default_internalize_data
))
917 mAlwaysSelfNotify
= true;
919 input_ah
= getAH(kSecTransformInputAttributeName
, true);
920 output_ah
= getAH(kSecTransformOutputAttributeName
, true);
922 parameters
.version
= kSecTransformCreateBlockParametersVersion
;
923 parameters
.send
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
, CFTypeRef value
)
925 return SendMetaAttribute(attribute
, type
, value
);
928 parameters
.pushback
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, CFTypeRef value
)
930 return Pushback(getAH(attribute
), value
);
933 parameters
.get
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
)
935 return GetMetaAttribute(attribute
, type
);
938 parameters
.overrideTransform
= Block_copy(^(CFStringRef action
, SecTransformActionBlock new_action
)
940 return rebind_transform_action(action
, new_action
);
943 parameters
.overrideData
= Block_copy(^(CFStringRef action
,
944 SecTransformDataBlock new_action
)
946 return rebind_data_action(action
, new_action
);
950 CFTypeRef (^SecTransformOverrideAttributeAction)(
952 SecTransformStringOrAttributeRef attribute,
953 SecTransformAttributeActionBlock newAction);
955 parameters
.overrideAttribute
=
956 Block_copy(^(CFStringRef action
, SecTransformStringOrAttributeRef attribute
, SecTransformAttributeActionBlock new_action
)
958 return rebind_attribute_action(action
, attribute
, new_action
);
961 char *tname
= const_cast<char*>(CFStringGetCStringPtr(cfname
, kCFStringEncodingUTF8
));
963 CFIndex sz
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname
), kCFStringEncodingUTF8
);
964 tname
= static_cast<typeof(tname
)>(alloca(sz
));
965 CFStringGetCString(cfname
, tname
, sz
, kCFStringEncodingUTF8
);
967 tr
= CoreFoundationHolder::MakeHolder(kSecCustom
, (CoreFoundationObject
*)this);
969 instanceBlock
= (*createFuncPtr
)(cfname
, tr
, ¶meters
);
972 void CustomTransform::Create()
974 (void)instanceBlock();
978 CustomTransform::~CustomTransform() {
983 Block_release(instanceBlock
);
986 Block_release(can_run
);
987 Block_release(execute_starting
);
988 Block_release(finalize
);
989 Block_release(generic_attribute_set_notification
);
990 Block_release(process_data
);
991 Block_release(externalize_data
);
992 Block_release(internalize_data
);
994 Block_release(parameters
.send
);
995 Block_release(parameters
.pushback
);
996 Block_release(parameters
.get
);
997 Block_release(parameters
.overrideTransform
);
998 Block_release(parameters
.overrideData
);
999 Block_release(parameters
.overrideAttribute
);
1001 // strictly speaking this isn't needed, but it can help track down some "use after free" bugs
1003 createFuncPtr
= NULL
;
1004 process_data
= NULL
;
1007 CFErrorRef
CustomTransform::TransformStartingExecution()
1009 CFTypeRef result
= execute_starting();
1010 return (CFErrorRef
)result
;
1014 CFDictionaryRef
CustomTransform::GetCustomExternalData()
1016 CFTypeRef result
= externalize_data();
1022 if (CFGetTypeID(result
) == CFErrorGetTypeID())
1024 // Ouch! we should deal with this
1029 if (CFGetTypeID(result
) == CFDictionaryGetTypeID())
1031 return (CFDictionaryRef
)result
;
1036 return (CFDictionaryRef
)result
;
1040 void CustomTransform::SetCustomExternalData(CFDictionaryRef customData
)
1042 if (NULL
!= customData
)
1044 internalize_data(customData
);
1049 CFErrorRef
SecTransformSetAttributeAction(SecTransformImplementationRef ref
,
1051 SecTransformStringOrAttributeRef attribute
,
1052 SecTransformAttributeActionBlock newAction
)
1056 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1057 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1062 return (CFErrorRef
)ref
->overrideAttribute(action
, attribute
, newAction
);
1065 CFErrorRef
SecTransformSetDataAction(SecTransformImplementationRef ref
,
1067 SecTransformDataBlock newAction
)
1071 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1072 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1077 return (CFErrorRef
)ref
->overrideData(action
, newAction
);
1080 CFErrorRef
SecTransformSetTransformAction(SecTransformImplementationRef ref
,
1082 SecTransformActionBlock newAction
)
1086 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1087 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1092 return (CFErrorRef
)ref
->overrideTransform(action
, newAction
);
1095 CFTypeRef
SecTranformCustomGetAttribute(SecTransformImplementationRef ref
,
1096 SecTransformStringOrAttributeRef attribute
,
1097 SecTransformMetaAttributeType type
)
1101 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1102 "SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref");
1107 return (CFErrorRef
)ref
->get(attribute
, type
);
1110 CFTypeRef
SecTransformCustomSetAttribute(SecTransformImplementationRef ref
,
1111 SecTransformStringOrAttributeRef attribute
,
1112 SecTransformMetaAttributeType type
,
1117 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1118 "SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref");
1123 return (CFErrorRef
)ref
->send(attribute
, type
, value
);
1127 CFTypeRef
SecTransformPushbackAttribute(SecTransformImplementationRef ref
,
1128 SecTransformStringOrAttributeRef attribute
,
1133 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1134 "SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref");
1136 return (CFTypeRef
)result
;
1139 return ref
->pushback(attribute
, value
);