2 * SecCustomTransform.cpp
3 * libsecurity_transform
5 * Created by JOsborne on 2/18/10.
6 * Copyright 2010 Apple. All rights reserved.
10 #include "SecCustomTransform.h"
11 #include "SecTransformValidator.h"
13 #include "TransformFactory.h"
14 #include <CoreFoundation/CoreFoundation.h>
17 #include "Utilities.h"
20 static const CFStringRef kSecCustom
= CFSTR("CustomTransform");
21 const CFStringRef kSecTransformPreviousErrorKey
= CFSTR("PreviousError");
22 const CFStringRef kSecTransformAbortOriginatorKey
= CFSTR("Originating Transform");
23 const CFStringRef kSecTransformActionCanExecute
= CFSTR("CanExecute");
24 const CFStringRef kSecCustomTransformWhatIsRequired
= CFSTR("WhatIsRequired");
25 const CFStringRef kSecCustomTransformAttributesToExternalize
= CFSTR("AttributesToExternalize");
26 const CFStringRef kSecTransformActionStartingExecution
= CFSTR("ExecuteStarting");
27 const CFStringRef kSecTransformActionProcessData
= CFSTR("TransformProcessData");
28 const CFStringRef kSecTransformActionAttributeNotification
= CFSTR("GenericAttributeSetNotification");
29 const CFStringRef kSecTransformActionFinalize
= CFSTR("Finalize");
30 const CFStringRef kSecTransformActionExternalizeExtraData
= CFSTR("ExternalizeExtraData");
31 const CFStringRef kSecTransformActionInternalizeExtraData
= CFSTR("InternalizeExtraData");
32 const CFStringRef kSecTransformActionAttributeValidation
= CFSTR("AttributeValidation");
35 @function SecTransformOverrideTransformAction
37 @abstract Used to override the default behavior of a custom transform.
39 @param action This should be either kSecTransformActionCanExecute,
40 kSecTransformActionStartingExecution, or
41 kSecTransformActionFinalize which signifies the behavior
42 that is being overridden.
45 A SecTransformAttributeActionBlock block that implements the
46 override behavior. Please see the
47 SecTransformActionBlock discussion for more
50 @result A CFErrorRef if an error occurred, NULL otherwise.
52 @discussion An action may be overridden more then once, the most
53 recent override will be used.Please see the example in
54 the documentation for the SecTransformActionBlock
58 typedef CFTypeRef (^SecTransformOverrideTransformAction
)(CFStringRef action
,
59 SecTransformActionBlock newAction
);
62 @function SecTransformOverrideDataAction
64 @abstract Changes the default attribute handling for a
67 @param action This should be either kSecTransformActionProcessData,
68 kSecTransformActionExternalizeExtraData which signifies
69 what behavior is being overridden.
72 A SecTransformDataBlock block that implements the
73 override behavior. Please see the
74 SecTransformDataBlock discussion for more
77 @result A CFErrorRef if an error occurred. NULL otherwise.
79 @discussion An action may be overridden more then once, the most
80 recent override will be used. Please see the example
81 in the documentation for the SecTransformAttributeActionBlock
85 typedef CFTypeRef (^SecTransformOverrideDataAction
)(CFStringRef action
,
86 SecTransformDataBlock newAction
);
89 @function SecTransformOverrideAttributeAction
91 @abstract Changes the default attribute handling for a
94 @param action This should be either SecTransformSetAttributeAction,
95 kSecTransformActionAttributeValidation which signifies
96 what behavior is being overridden.
99 The attribute whose attribute default attribute handling is
100 being overridden. Passing NULL will override all attributes
101 that have not been specifically overridden.
104 A SecTransformAttributeActionBlock block
105 that implements the override behavior.
107 If the action parameter is SecTransformSetAttributeAction
108 then this block is called whenever a set is called on the
109 attribute that this block was registered for or in the case
110 of a NULL attribute name any attribute that has not been specifically
111 overridden. The block may transmogrify the data as needed. It may
112 also send the data to any other attribue by calling
113 SecTransformCustomSetAttribute. The value returned from the block
114 will be the new value for the attribute.
116 If the action parameter is kSecTransformActionAttributeValidation then
117 this block is called to validate the new value for the
118 attribute that this block was registered for or in the case
119 of a NULL attribute name any attribute that has not been specifically
120 overridden. The block should test if the new value is acceptable
121 and return NULL if it is valid a CFErrorRef otherwise.
123 @result A CFErrorRef if an error occurred. NULL otherwise.
125 @discussion An action may be overridden more then once, the most
126 recent override will be used. Please see the example
127 in the documentation for the
128 SecTransformAttributeActionBlock block.
131 typedef CFTypeRef (^SecTransformOverrideAttributeAction
)(
133 SecTransformStringOrAttributeRef attribute
,
134 SecTransformAttributeActionBlock newAction
);
138 @function SecTransformGetAttributeBlock
140 @abstract Retrieves the value of the attribute metadata of the
144 The attribute from which to retrieve the metadata from.
146 @param type The type of the metadata to be fetched.
148 @result The value of the metadata that was retrieved or a CFErrorRef
151 @result The value of the metadata that was retrieved.
155 typedef CFTypeRef (^SecTransformGetAttributeBlock
)(
156 SecTransformStringOrAttributeRef attribute
,
157 SecTransformMetaAttributeType type
);
160 @function SecTransformSetAttributeBlock
162 @abstract This sets the value of the metadata of an attribute.
165 The attribute whose value is sent
167 @param type The metadata type that specifies what metadata value
170 @param value The value of the metadata to be sent.
172 @result A CFErrorRef is an error occurred, NULL otherwise.
174 @discussion The attribute parameter specifies which attribute will
175 have its data set. The type parameter specifies which of
176 the metadata items is set. The value parameter is the
180 typedef CFErrorRef (^SecTransformSetAttributeBlock
)(
181 SecTransformStringOrAttributeRef attribute
,
182 SecTransformMetaAttributeType type
,
187 @function SecTransformPushBackAttributeBlock
189 @abstract Allows for putting a single value back for a
190 specific attribute. This will stop the flow of
191 data into the specified attribute until an
192 attribute is changed.
195 The attribute that has its data pushed back.
197 @param value The value being pushed back.
200 @result A CFErrorRef is an error occurred, NULL otherwise.
201 Note: pushing back a second value will abort the
202 transform, not return an error from this call.
204 @discussion A particular custom transform may need multple
205 values to be set before it can do the processing
206 that the custom transform is designed to do. For
207 example, it may need a key and a salt value. The
208 salt value maybe supplied by another transform while
209 the key transform may have been set explicitly. When
210 data is presented to this custom transform the salt
211 value may not have been sent from the upstream transform.
212 The custom transform can then push back the input data
213 which causes the transform to stall. When any
214 attribute on the custom transform is changed, such as
215 the upstream transform delivers the salt value, then
216 the data that was pushed back is re-delivered
219 typedef CFErrorRef (^SecTransformPushBackAttributeBlock
)(
220 SecTransformStringOrAttributeRef attribute
,
224 @const kSecTransformCreateBlockParametersVersion
225 The current version number of the SecTransformCreateBlockParameters
231 kSecTransformCreateBlockParametersVersion
= 1
235 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
239 @struct OpaqueSecTransformImplementation
242 The version number of this structure
244 @field overrideTransform
245 A SecTransformOverrideTransformAction block. See
246 the headerdoc for this block for additional information.
248 @field overrideAttribute
249 A SecTransformOverrideAttributeAction block. See
250 the headerdoc for this block for additional information.
253 A SecTransformGetAttributeBlock block. See
254 the headerdoc for this block for additional information.
257 A SecTransformSetAttributeBlock block. See
258 the headerdoc for this block for additional information.
261 A SecTransformPushBackAttributeBlock block. See
262 the headerdoc for this block for additional information.
264 struct OpaqueSecTransformImplementation
266 CFIndex version
; // Set to kSecTransformCreateBlockParametersVersion
268 // The following two blocks allow for overriding 'standard'
269 // transform behavior
270 SecTransformOverrideTransformAction overrideTransform
;
271 SecTransformOverrideDataAction overrideData
;
272 SecTransformOverrideAttributeAction overrideAttribute
;
274 // The following methods allow for dealing with the transform mechanism
275 // They are called synchronously
276 SecTransformGetAttributeBlock get
;
277 SecTransformSetAttributeBlock send
;
278 SecTransformPushBackAttributeBlock pushback
;
282 class CustomTransformFactory
: public TransformFactory
285 SecTransformCreateFP createFuncPtr
;
287 CustomTransformFactory(CFStringRef name
, SecTransformCreateFP createFP
, CFErrorRef
*error
);
288 virtual ~CustomTransformFactory() {};
289 virtual CFTypeRef
Make();
293 static SecTransformActionBlock default_can_run
= ^{ return (CFTypeRef
)NULL
; };
294 static SecTransformActionBlock default_execute_starting
= default_can_run
;
295 static SecTransformActionBlock default_finalize
= default_execute_starting
;
296 static SecTransformActionBlock default_externalize_data
= default_finalize
;
298 static SecTransformDataBlock default_process_data
= ^(CFTypeRef value
) { return value
; };
299 //static SecTransformDataBlock default_validate = ^(CFTypeRef value) { return (CFTypeRef)NULL; };
300 static SecTransformAttributeActionBlock default_generic_attribute_set_notification
=
301 ^(SecTransformAttributeRef ah
, CFTypeRef value
) { return value
; };
303 static SecTransformAttributeActionBlock default_generic_attribute_validation
=
304 ^(SecTransformAttributeRef ah
, CFTypeRef value
)
306 return (CFTypeRef
)NULL
;
309 static SecTransformDataBlock default_internalize_data
=
312 return (CFTypeRef
)NULL
;
315 class CustomTransform
: public Transform
318 SecTransformCreateFP createFuncPtr
;
319 SecTransformInstanceBlock instanceBlock
;
321 SecTransformActionBlock can_run
;
322 SecTransformActionBlock execute_starting
;
323 SecTransformActionBlock finalize
;
324 SecTransformAttributeActionBlock generic_attribute_set_notification
;
325 SecTransformAttributeActionBlock generic_attribute_validation
;
326 SecTransformDataBlock process_data
;
327 SecTransformActionBlock externalize_data
;
328 SecTransformDataBlock internalize_data
;
332 SecTransformAttributeRef input_ah
;
333 SecTransformAttributeRef output_ah
;
335 OpaqueSecTransformImplementation parameters
;
337 void SetCanExecute(SecTransformActionBlock CanExecuteBlock
)
339 Block_release(can_run
);
342 can_run
= Block_copy(CanExecuteBlock
);
347 can_run
= Block_copy(default_can_run
);
351 void SetExecuteStarting(SecTransformActionBlock executeStartingBlock
)
353 Block_release(execute_starting
);
354 if (executeStartingBlock
)
356 execute_starting
= Block_copy(executeStartingBlock
);
361 execute_starting
= Block_copy(default_execute_starting
);
365 void SetFinalize(SecTransformActionBlock finalizeBlock
)
367 Block_release(finalize
);
370 finalize
= Block_copy(finalizeBlock
);
375 finalize
= Block_copy(default_finalize
);
379 void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock
)
381 Block_release(externalizeBlock
);
382 if (externalizeBlock
)
384 externalize_data
= Block_copy(externalizeBlock
);
389 externalize_data
= Block_copy(default_externalize_data
);
393 void SetProcessData(SecTransformDataBlock processDataBlock
)
395 Block_release(process_data
);
396 if (processDataBlock
)
398 process_data
= Block_copy(processDataBlock
);
403 process_data
= Block_copy(default_process_data
);
407 void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock
)
409 Block_release(internalize_data
);
410 if (InternalizeExtraDataBlock
)
412 internalize_data
= Block_copy(InternalizeExtraDataBlock
);
417 internalize_data
= Block_copy(default_internalize_data
);
423 void SetNotficationBlock(SecTransformStringOrAttributeRef attribute
,
424 SecTransformAttributeActionBlock notificationBlock
)
426 SecTransformAttributeActionBlock blockToSet
=
427 Block_copy((notificationBlock
) ? notificationBlock
:
428 default_generic_attribute_set_notification
);
432 transform_attribute
*ta
= getTA(attribute
, true);
434 if (ta
->attribute_changed_block
)
436 Block_release(ta
->attribute_changed_block
);
439 ta
->attribute_changed_block
= blockToSet
;
444 if (generic_attribute_set_notification
)
446 Block_release(generic_attribute_set_notification
);
449 generic_attribute_set_notification
= blockToSet
;
453 void SetVerifyBlock(SecTransformStringOrAttributeRef attribute
,
454 SecTransformAttributeActionBlock verifyBlock
)
456 SecTransformAttributeActionBlock blockToSet
=
457 Block_copy((verifyBlock
) ? verifyBlock
:
458 generic_attribute_validation
);
462 transform_attribute
*ta
= getTA(attribute
, true);
464 if (ta
->attribute_validate_block
)
466 Block_release(ta
->attribute_validate_block
);
469 ta
->attribute_validate_block
= blockToSet
;
473 if (generic_attribute_validation
)
475 Block_release(generic_attribute_validation
);
478 generic_attribute_validation
= blockToSet
;
485 CustomTransform(CFStringRef name
, SecTransformCreateFP createFP
);
486 virtual ~CustomTransform();
490 CFTypeRef
rebind_data_action(CFStringRef action
,
491 SecTransformDataBlock new_action
);
493 CFTypeRef
rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
);
495 CFTypeRef
rebind_attribute_action(CFStringRef action
,
496 SecTransformStringOrAttributeRef attribute
,
497 SecTransformAttributeActionBlock new_action
);
499 SecTransformRef
get_ref() { return tr
; }
501 virtual void AttributeChanged(CFStringRef name
, CFTypeRef value
);
502 virtual void AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
);
503 virtual CFErrorRef
TransformStartingExecution();
504 virtual CFDictionaryRef
GetCustomExternalData();
505 virtual void SetCustomExternalData(CFDictionaryRef customData
);
507 friend Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
512 #pragma mark CustomTransformFactory
514 CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
* error
) :
515 TransformFactory(uniqueName
, false, kSecCustom
),
516 createFuncPtr(createFP
)
518 TransformFactory
*existing
= FindTransformFactoryByType(uniqueName
);
523 *error
= CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered
,
524 "Custom transform type %s already exists.", uniqueName
);
530 if (CFStringGetCharacterAtIndex(uniqueName
, 0) == '_')
534 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
535 "Invalid transform type name %s -- type names must not start with an _", uniqueName
);
540 static CFCharacterSetRef invalidTypeCharactors
= NULL
;
541 static dispatch_once_t setupInvalidTypeCharactors
;
542 dispatch_once(&setupInvalidTypeCharactors
, ^{
543 invalidTypeCharactors
= CFCharacterSetCreateWithCharactersInString(NULL
, CFSTR("/:"));
546 if (CFStringFindCharacterFromSet(uniqueName
, invalidTypeCharactors
, CFRangeMake(0, CFStringGetLength(uniqueName
)), 0, &has_bad
)) {
549 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
550 "Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName
, has_bad
.location
), uniqueName
);
554 RegisterTransform(this, kSecCustom
);
557 CFTypeRef
CustomTransformFactory::Make()
559 CustomTransform
*ct
= new CustomTransform(this->GetTypename(), createFuncPtr
);
561 return ct
->get_ref();
567 SecTransformAttributeActionBlock
SecTransformCreateValidatorForCFtype(CFTypeID expected_type
, Boolean null_allowed
) {
568 SecTransformAttributeActionBlock validate
= NULL
;
569 CFErrorRef (^make_error_message
)(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) =
570 ^(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) {
571 CFStringRef expected_type_name
= CFCopyTypeIDDescription(expected_type
);
572 CFErrorRef error
= NULL
;
574 CFStringRef value_type_name
= CFCopyTypeIDDescription(CFGetTypeID(value
));
575 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received value of type %@ (%@), expected%@ a %@%@",
576 attr
, value_type_name
, value
,
577 null_allowed
? CFSTR(" either") : CFSTR(""),
579 null_allowed
? CFSTR(" or a NULL") : CFSTR(""));
580 CFRelease(value_type_name
);
582 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received NULL value, expected a %@",
583 attr
, expected_type_name
);
585 CFRelease(expected_type_name
);
592 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
593 if (value
== NULL
|| CFGetTypeID(value
) == expected_type
) {
594 return (CFTypeRef
)NULL
;
596 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
599 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
600 if (value
!= NULL
&& CFGetTypeID(value
) == expected_type
) {
601 return (CFTypeRef
)NULL
;
603 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
607 return Block_copy(validate
);
611 Boolean
SecTransformRegister(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
*caller_error
)
613 CFErrorRef error
= NULL
;
615 CustomTransformFactory
*tf
= new CustomTransformFactory(uniqueName
, createFP
, &error
);
621 *caller_error
= error
;
631 SecTransformRef
SecTransformCreate(CFStringRef name
, CFErrorRef
*error
)
633 SecTransformRef tr
= TransformFactory::MakeTransformWithType(name
, error
);
638 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
)
640 CustomTransform
*ct
= (CustomTransform
*)CoreFoundationHolder::ObjectFromCFType(xst
);
641 extern CFStringRef external_source_name
;
642 if (CFEqual(ct
->mTypeName
, external_source_name
)) {
643 ct
->SetAttribute(ct
->input_ah
, value
);
647 *error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct
->GetName(), ct
->mTypeName
);
654 /* ==========================================================================
656 description: A Special CFType that signifies that no data is being
658 ==========================================================================*/
659 #pragma mark NoDataClass
661 class NoDataClass
: public CoreFoundationObject
667 virtual ~NoDataClass();
668 std::string
FormattingDescription(CFDictionaryRef options
);
669 std::string
DebugDescription();
670 static CFTypeRef
Make();
673 CFTypeRef
NoDataClass::Make() {
674 NoDataClass
* obj
= new NoDataClass();
675 return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName
, obj
);
679 NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName
) {
682 NoDataClass::~NoDataClass()
686 std::string
NoDataClass::DebugDescription()
688 return CoreFoundationObject::DebugDescription() + " | SecTransformNoData";
691 std::string
NoDataClass::FormattingDescription(CFDictionaryRef options
)
693 return CoreFoundationObject::FormattingDescription(options
) + " | SecTransformNoData";
696 CFTypeRef
SecTransformNoData()
698 static dispatch_once_t inited
;
699 static CFTypeRef no_data
;
701 dispatch_once(&inited
,
703 no_data
= NoDataClass::Make();
709 /* ==========================================================================
710 class Implementation CustomTransform
711 ==========================================================================*/
713 #pragma mark CustomTransform
715 void CustomTransform::AttributeChanged(CFStringRef name
, CFTypeRef value
) {
717 // 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
720 // We really shouldn't get here, but this is a production build and recovery is easy to code (but costly to execute)
721 AttributeChanged(getAH(name
, false), value
);
725 void CustomTransform::AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
)
727 transform_attribute
*ta
= ah2ta(ah
);
728 SecTransformAttributeActionBlock attribute_set_notification
= NULL
;
730 SecTransformAttributeActionBlock attribute_validate
= NULL
;
732 attribute_validate
= (SecTransformAttributeActionBlock
)ta
->attribute_validate_block
;
733 if (!attribute_validate
) {
734 attribute_validate
= generic_attribute_validation
;
736 CFTypeRef vr
= attribute_validate(ah
, value
);
738 if (CFGetTypeID(vr
) == CFErrorGetTypeID()) {
739 SendAttribute(AbortAH
, vr
);
742 CFErrorRef e
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr
)), vr
);
743 SendAttribute(AbortAH
, e
);
745 // XXX: this causes a core dump -- I think AbortAH doesn't take it's own reference!! CFRelease(e);
750 attribute_set_notification
= (SecTransformAttributeActionBlock
)ta
->attribute_changed_block
;
752 if ((!attribute_set_notification
) && ah
== input_ah
)
754 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
755 if (vtype
== CFDataGetTypeID())
757 CFTypeRef output
= process_data(value
);
758 if (output
== NULL
|| output
!= SecTransformNoData())
760 SendAttribute(output_ah
, output
);
762 // if output == value, we are being asked to just
763 // forward the existing value. No need to release.
764 // If they are different, we are being asked to
765 // send a new value which must be released.
767 if (output
!= value
&& output
!= NULL
)
773 else if (vtype
== CFErrorGetTypeID() && !ah2ta(ah
)->direct_error_handling
)
775 SendAttribute(output_ah
, value
);
778 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
779 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
780 if (new_value
!= value
)
782 SendAttribute(ah
, new_value
);
788 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
789 if (vtype
!= CFErrorGetTypeID() || ah2ta(ah
)->direct_error_handling
)
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
);
800 SendAttribute(output_ah
, value
);
805 CFTypeRef
CustomTransform::rebind_data_action(CFStringRef action
,
806 SecTransformDataBlock new_action
)
808 CFTypeRef result
= NULL
;
809 if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionProcessData
, action
, 0))
811 SetProcessData(new_action
);
813 else if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionInternalizeExtraData
, action
, 0))
815 SetInternalizeExtraData(new_action
);
819 result
= (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
821 // XXX: can we get a stackdump here too?
822 CFStringRef msg
= CFStringCreateWithFormat(NULL
, NULL
,
823 CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"),
824 action
, (void*)new_action
, DebugDescription().c_str());
825 char *utf8_message
= utf8(msg
);
826 syslog(LOG_ERR
, "%s", utf8_message
);
833 CFTypeRef
CustomTransform::rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
)
835 CFErrorRef result
= NULL
;
837 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionCanExecute
, 0))
839 SetCanExecute(new_action
);
841 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionStartingExecution
, 0))
843 SetExecuteStarting(new_action
);
845 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionFinalize
, 0))
847 SetFinalize(new_action
);
849 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionExternalizeExtraData
, 0))
851 SetExternalizeExtraData(new_action
);
855 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
857 char *action_utf8
= utf8(action
);
858 syslog(LOG_ERR
, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
865 CFTypeRef
CustomTransform::rebind_attribute_action(
867 SecTransformStringOrAttributeRef attribute
,
868 SecTransformAttributeActionBlock new_action
)
870 CFErrorRef result
= NULL
;
872 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeNotification
, 0))
874 SetNotficationBlock(attribute
, new_action
);
876 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeValidation
, 0))
878 SetVerifyBlock(attribute
, new_action
);
882 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
883 char *action_utf8
= utf8(action
);
884 syslog(LOG_ERR
, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
891 CustomTransform::CustomTransform(CFStringRef cfname
, SecTransformCreateFP createFP
) :
893 createFuncPtr(createFP
),
895 can_run(Block_copy(default_can_run
)),
896 execute_starting(Block_copy(default_execute_starting
)),
897 finalize(Block_copy(default_finalize
)),
898 generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification
)),
899 generic_attribute_validation(Block_copy(default_generic_attribute_validation
)),
900 process_data(Block_copy(default_process_data
)),
901 externalize_data(Block_copy(default_externalize_data
)),
902 internalize_data(Block_copy(default_internalize_data
))
904 mAlwaysSelfNotify
= true;
906 input_ah
= getAH(kSecTransformInputAttributeName
, true);
907 output_ah
= getAH(kSecTransformOutputAttributeName
, true);
909 parameters
.version
= kSecTransformCreateBlockParametersVersion
;
910 parameters
.send
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
, CFTypeRef value
)
912 return SendMetaAttribute(attribute
, type
, value
);
915 parameters
.pushback
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, CFTypeRef value
)
917 return Pushback(getAH(attribute
), value
);
920 parameters
.get
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
)
922 return GetMetaAttribute(attribute
, type
);
925 parameters
.overrideTransform
= Block_copy(^(CFStringRef action
, SecTransformActionBlock new_action
)
927 return rebind_transform_action(action
, new_action
);
930 parameters
.overrideData
= Block_copy(^(CFStringRef action
,
931 SecTransformDataBlock new_action
)
933 return rebind_data_action(action
, new_action
);
937 CFTypeRef (^SecTransformOverrideAttributeAction)(
939 SecTransformStringOrAttributeRef attribute,
940 SecTransformAttributeActionBlock newAction);
942 parameters
.overrideAttribute
=
943 Block_copy(^(CFStringRef action
, SecTransformStringOrAttributeRef attribute
, SecTransformAttributeActionBlock new_action
)
945 return rebind_attribute_action(action
, attribute
, new_action
);
948 char *tname
= const_cast<char*>(CFStringGetCStringPtr(cfname
, kCFStringEncodingUTF8
));
950 CFIndex sz
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname
), kCFStringEncodingUTF8
);
951 tname
= static_cast<typeof(tname
)>(alloca(sz
));
952 CFStringGetCString(cfname
, tname
, sz
, kCFStringEncodingUTF8
);
954 tr
= CoreFoundationHolder::MakeHolder(kSecCustom
, (CoreFoundationObject
*)this);
956 instanceBlock
= (*createFuncPtr
)(cfname
, tr
, ¶meters
);
959 void CustomTransform::Create()
961 (void)instanceBlock();
965 CustomTransform::~CustomTransform() {
970 Block_release(instanceBlock
);
973 Block_release(can_run
);
974 Block_release(execute_starting
);
975 Block_release(finalize
);
976 Block_release(generic_attribute_set_notification
);
977 Block_release(process_data
);
978 Block_release(externalize_data
);
979 Block_release(internalize_data
);
981 Block_release(parameters
.send
);
982 Block_release(parameters
.pushback
);
983 Block_release(parameters
.get
);
984 Block_release(parameters
.overrideTransform
);
985 Block_release(parameters
.overrideData
);
986 Block_release(parameters
.overrideAttribute
);
988 // strictly speaking this isn't needed, but it can help track down some "use after free" bugs
990 createFuncPtr
= NULL
;
994 CFErrorRef
CustomTransform::TransformStartingExecution()
996 CFTypeRef result
= execute_starting();
997 return (CFErrorRef
)result
;
1001 CFDictionaryRef
CustomTransform::GetCustomExternalData()
1003 CFTypeRef result
= externalize_data();
1009 if (CFGetTypeID(result
) == CFErrorGetTypeID())
1011 // Ouch! we should deal with this
1016 if (CFGetTypeID(result
) == CFDictionaryGetTypeID())
1018 return (CFDictionaryRef
)result
;
1023 return (CFDictionaryRef
)result
;
1027 void CustomTransform::SetCustomExternalData(CFDictionaryRef customData
)
1029 if (NULL
!= customData
)
1031 internalize_data(customData
);
1036 CFErrorRef
SecTransformSetAttributeAction(SecTransformImplementationRef ref
,
1038 SecTransformStringOrAttributeRef attribute
,
1039 SecTransformAttributeActionBlock newAction
)
1043 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1044 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1049 return (CFErrorRef
)ref
->overrideAttribute(action
, attribute
, newAction
);
1052 CFErrorRef
SecTransformSetDataAction(SecTransformImplementationRef ref
,
1054 SecTransformDataBlock newAction
)
1058 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1059 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1064 return (CFErrorRef
)ref
->overrideData(action
, newAction
);
1067 CFErrorRef
SecTransformSetTransformAction(SecTransformImplementationRef ref
,
1069 SecTransformActionBlock newAction
)
1073 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1074 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1079 return (CFErrorRef
)ref
->overrideTransform(action
, newAction
);
1082 CFTypeRef
SecTranformCustomGetAttribute(SecTransformImplementationRef ref
,
1083 SecTransformStringOrAttributeRef attribute
,
1084 SecTransformMetaAttributeType type
)
1088 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1089 "SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref");
1094 return (CFErrorRef
)ref
->get(attribute
, type
);
1097 CFTypeRef
SecTransformCustomSetAttribute(SecTransformImplementationRef ref
,
1098 SecTransformStringOrAttributeRef attribute
,
1099 SecTransformMetaAttributeType type
,
1104 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1105 "SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref");
1110 return (CFErrorRef
)ref
->send(attribute
, type
, value
);
1114 CFTypeRef
SecTransformPushbackAttribute(SecTransformImplementationRef ref
,
1115 SecTransformStringOrAttributeRef attribute
,
1120 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1121 "SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref");
1123 return (CFTypeRef
)result
;
1126 return ref
->pushback(attribute
, value
);