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"
12 #include "TransformFactory.h"
13 #include <CoreFoundation/CoreFoundation.h>
16 #include "Utilities.h"
19 static const CFStringRef kSecCustom
= CFSTR("CustomTransform");
20 static const char *kSecCustom_cstr
= "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 CFTypeRef
Make();
292 static SecTransformActionBlock default_can_run
= ^{ return (CFTypeRef
)NULL
; };
293 static SecTransformActionBlock default_execute_starting
= default_can_run
;
294 static SecTransformActionBlock default_finalize
= default_execute_starting
;
295 static SecTransformActionBlock default_externalize_data
= default_finalize
;
297 static SecTransformDataBlock default_process_data
= ^(CFTypeRef value
) { return value
; };
298 //static SecTransformDataBlock default_validate = ^(CFTypeRef value) { return (CFTypeRef)NULL; };
299 static SecTransformAttributeActionBlock default_generic_attribute_set_notification
=
300 ^(SecTransformAttributeRef ah
, CFTypeRef value
) { return value
; };
302 static SecTransformAttributeActionBlock default_generic_attribute_validation
=
303 ^(SecTransformAttributeRef ah
, CFTypeRef value
)
305 return (CFTypeRef
)NULL
;
308 static SecTransformDataBlock default_internalize_data
=
311 return (CFTypeRef
)NULL
;
314 class CustomTransform
: public Transform
317 SecTransformCreateFP createFuncPtr
;
318 SecTransformInstanceBlock instanceBlock
;
320 SecTransformActionBlock can_run
;
321 SecTransformActionBlock execute_starting
;
322 SecTransformActionBlock finalize
;
323 SecTransformAttributeActionBlock generic_attribute_set_notification
;
324 SecTransformAttributeActionBlock generic_attribute_validation
;
325 SecTransformDataBlock process_data
;
326 SecTransformActionBlock externalize_data
;
327 SecTransformDataBlock internalize_data
;
331 SecTransformAttributeRef input_ah
;
332 SecTransformAttributeRef output_ah
;
334 OpaqueSecTransformImplementation parameters
;
336 void SetCanExecute(SecTransformActionBlock CanExecuteBlock
)
338 Block_release(can_run
);
341 can_run
= Block_copy(CanExecuteBlock
);
346 can_run
= Block_copy(default_can_run
);
350 void SetExecuteStarting(SecTransformActionBlock executeStartingBlock
)
352 Block_release(execute_starting
);
353 if (executeStartingBlock
)
355 execute_starting
= Block_copy(executeStartingBlock
);
360 execute_starting
= Block_copy(default_execute_starting
);
364 void SetFinalize(SecTransformActionBlock finalizeBlock
)
366 Block_release(finalize
);
369 finalize
= Block_copy(finalizeBlock
);
374 finalize
= Block_copy(default_finalize
);
378 void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock
)
380 Block_release(externalizeBlock
);
381 if (externalizeBlock
)
383 externalize_data
= Block_copy(externalizeBlock
);
388 externalize_data
= Block_copy(default_externalize_data
);
392 void SetProcessData(SecTransformDataBlock processDataBlock
)
394 Block_release(process_data
);
395 if (processDataBlock
)
397 process_data
= Block_copy(processDataBlock
);
402 process_data
= Block_copy(default_process_data
);
406 void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock
)
408 Block_release(internalize_data
);
409 if (InternalizeExtraDataBlock
)
411 internalize_data
= Block_copy(InternalizeExtraDataBlock
);
416 internalize_data
= Block_copy(default_internalize_data
);
422 void SetNotficationBlock(SecTransformStringOrAttributeRef attribute
,
423 SecTransformAttributeActionBlock notificationBlock
)
425 SecTransformAttributeActionBlock blockToSet
=
426 Block_copy((notificationBlock
) ? notificationBlock
:
427 default_generic_attribute_set_notification
);
431 transform_attribute
*ta
= getTA(attribute
, true);
433 if (ta
->attribute_changed_block
)
435 Block_release(ta
->attribute_changed_block
);
438 ta
->attribute_changed_block
= blockToSet
;
443 if (generic_attribute_set_notification
)
445 Block_release(generic_attribute_set_notification
);
448 generic_attribute_set_notification
= blockToSet
;
452 void SetVerifyBlock(SecTransformStringOrAttributeRef attribute
,
453 SecTransformAttributeActionBlock verifyBlock
)
455 SecTransformAttributeActionBlock blockToSet
=
456 Block_copy((verifyBlock
) ? verifyBlock
:
457 generic_attribute_validation
);
461 transform_attribute
*ta
= getTA(attribute
, true);
463 if (ta
->attribute_validate_block
)
465 Block_release(ta
->attribute_validate_block
);
468 ta
->attribute_validate_block
= blockToSet
;
472 if (generic_attribute_validation
)
474 Block_release(generic_attribute_validation
);
477 generic_attribute_validation
= blockToSet
;
484 CustomTransform(CFStringRef name
, SecTransformCreateFP createFP
);
485 virtual ~CustomTransform();
489 CFTypeRef
rebind_data_action(CFStringRef action
,
490 SecTransformDataBlock new_action
);
492 CFTypeRef
rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
);
494 CFTypeRef
rebind_attribute_action(CFStringRef action
,
495 SecTransformStringOrAttributeRef attribute
,
496 SecTransformAttributeActionBlock new_action
);
498 SecTransformRef
get_ref() { return tr
; }
500 virtual void AttributeChanged(CFStringRef name
, CFTypeRef value
);
501 virtual void AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
);
502 virtual CFErrorRef
TransformStartingExecution();
503 virtual CFDictionaryRef
GetCustomExternalData();
504 virtual void SetCustomExternalData(CFDictionaryRef customData
);
506 friend Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
511 #pragma mark CustomTransformFactory
513 CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
* error
) :
514 TransformFactory(uniqueName
, false, kSecCustom
),
515 createFuncPtr(createFP
)
517 TransformFactory
*existing
= FindTransformFactoryByType(uniqueName
);
522 *error
= CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered
,
523 "Custom transform type %s already exists.", uniqueName
);
529 if (CFStringGetCharacterAtIndex(uniqueName
, 0) == '_')
533 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
534 "Invalid transform type name %s -- type names must not start with an _", uniqueName
);
539 static CFCharacterSetRef invalidTypeCharactors
= NULL
;
540 static dispatch_once_t setupInvalidTypeCharactors
;
541 dispatch_once(&setupInvalidTypeCharactors
, ^{
542 invalidTypeCharactors
= CFCharacterSetCreateWithCharactersInString(NULL
, CFSTR("/:"));
545 if (CFStringFindCharacterFromSet(uniqueName
, invalidTypeCharactors
, CFRangeMake(0, CFStringGetLength(uniqueName
)), 0, &has_bad
)) {
548 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
549 "Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName
, has_bad
.location
), uniqueName
);
553 RegisterTransform(this, kSecCustom
);
556 CFTypeRef
CustomTransformFactory::Make()
558 CustomTransform
*ct
= new CustomTransform(this->GetTypename(), createFuncPtr
);
560 return ct
->get_ref();
565 const void *Block_copy_a(CFAllocatorRef allocator
, const void *block
) {
566 return Block_copy(block
);
569 void Block_release_a(CFAllocatorRef allocator
, const void *block
) {
570 Block_release(block
);
574 SecTransformAttributeActionBlock
SecTransformCreateValidatorForCFtype(CFTypeID expected_type
, Boolean null_allowed
) {
575 SecTransformAttributeActionBlock validate
= NULL
;
576 CFErrorRef (^make_error_message
)(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) =
577 ^(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) {
578 CFStringRef expected_type_name
= CFCopyTypeIDDescription(expected_type
);
579 CFErrorRef error
= NULL
;
581 CFStringRef value_type_name
= CFCopyTypeIDDescription(CFGetTypeID(value
));
582 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received value of type %@ (%@), expected%@ a %@%@",
583 attr
, value_type_name
, value
,
584 null_allowed
? CFSTR(" either") : CFSTR(""),
586 null_allowed
? CFSTR(" or a NULL") : CFSTR(""));
587 CFRelease(value_type_name
);
589 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received NULL value, expected a %@",
590 attr
, expected_type_name
);
592 CFRelease(expected_type_name
);
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
);
606 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
607 if (value
!= NULL
&& CFGetTypeID(value
) == expected_type
) {
608 return (CFTypeRef
)NULL
;
610 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
614 return Block_copy(validate
);
618 Boolean
SecTransformRegister(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
*caller_error
)
620 CFErrorRef error
= NULL
;
622 CustomTransformFactory
*tf
= new CustomTransformFactory(uniqueName
, createFP
, &error
);
628 *caller_error
= error
;
638 SecTransformRef
SecTransformCreate(CFStringRef name
, CFErrorRef
*error
)
640 SecTransformRef tr
= TransformFactory::MakeTransformWithType(name
, error
);
645 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
)
647 CustomTransform
*ct
= (CustomTransform
*)CoreFoundationHolder::ObjectFromCFType(xst
);
648 extern CFStringRef external_source_name
;
649 if (CFEqual(ct
->mTypeName
, external_source_name
)) {
650 ct
->SetAttribute(ct
->input_ah
, value
);
654 *error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct
->GetName(), ct
->mTypeName
);
661 /* ==========================================================================
663 description: A Special CFType that signifies that no data is being
665 ==========================================================================*/
666 #pragma mark NoDataClass
668 class NoDataClass
: public CoreFoundationObject
674 virtual ~NoDataClass();
675 std::string
FormattingDescription(CFDictionaryRef options
);
676 std::string
DebugDescription();
677 static CFTypeRef
Make();
680 CFTypeRef
NoDataClass::Make() {
681 NoDataClass
* obj
= new NoDataClass();
682 return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName
, obj
);
686 NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName
) {
689 NoDataClass::~NoDataClass()
693 std::string
NoDataClass::DebugDescription()
695 return CoreFoundationObject::DebugDescription() + " | SecTransformNoData";
698 std::string
NoDataClass::FormattingDescription(CFDictionaryRef options
)
700 return CoreFoundationObject::FormattingDescription(options
) + " | SecTransformNoData";
703 CFTypeRef
SecTransformNoData()
705 static dispatch_once_t inited
;
706 static CFTypeRef no_data
;
708 dispatch_once(&inited
,
710 no_data
= NoDataClass::Make();
716 /* ==========================================================================
717 class Implementation CustomTransform
718 ==========================================================================*/
720 #pragma mark CustomTransform
722 void CustomTransform::AttributeChanged(CFStringRef name
, CFTypeRef value
) {
724 // 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
727 // We really shouldn't get here, but this is a production build and recovery is easy to code (but costly to execute)
728 AttributeChanged(getAH(name
, false), value
);
732 void CustomTransform::AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
)
734 transform_attribute
*ta
= ah2ta(ah
);
735 SecTransformAttributeActionBlock attribute_set_notification
= NULL
;
737 SecTransformAttributeActionBlock attribute_validate
= NULL
;
739 attribute_validate
= (SecTransformAttributeActionBlock
)ta
->attribute_validate_block
;
740 if (!attribute_validate
) {
741 attribute_validate
= generic_attribute_validation
;
743 CFTypeRef vr
= attribute_validate(ah
, value
);
745 if (CFGetTypeID(vr
) == CFErrorGetTypeID()) {
746 SendAttribute(AbortAH
, vr
);
749 CFErrorRef e
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr
)), vr
);
750 SendAttribute(AbortAH
, e
);
752 // XXX: this causes a core dump -- I think AbortAH doesn't take it's own reference!! CFRelease(e);
757 attribute_set_notification
= (SecTransformAttributeActionBlock
)ta
->attribute_changed_block
;
759 if ((!attribute_set_notification
) && ah
== input_ah
)
761 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
762 if (vtype
== CFDataGetTypeID())
764 CFTypeRef output
= process_data(value
);
765 if (output
== NULL
|| output
!= SecTransformNoData())
767 SendAttribute(output_ah
, output
);
769 // if output == value, we are being asked to just
770 // forward the existing value. No need to release.
771 // If they are different, we are being asked to
772 // send a new value which must be released.
774 if (output
!= value
&& output
!= NULL
)
780 else if (vtype
== CFErrorGetTypeID() && !ah2ta(ah
)->direct_error_handling
)
782 SendAttribute(output_ah
, value
);
785 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
786 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
787 if (new_value
!= value
)
789 SendAttribute(ah
, new_value
);
795 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
796 if (vtype
!= CFErrorGetTypeID() || ah2ta(ah
)->direct_error_handling
)
798 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
799 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
800 if (new_value
!= value
)
802 SendAttribute(ah
, new_value
);
807 SendAttribute(output_ah
, value
);
812 CFTypeRef
CustomTransform::rebind_data_action(CFStringRef action
,
813 SecTransformDataBlock new_action
)
815 CFTypeRef result
= NULL
;
816 if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionProcessData
, action
, 0))
818 SetProcessData(new_action
);
820 else if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionInternalizeExtraData
, action
, 0))
822 SetInternalizeExtraData(new_action
);
826 result
= (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
828 // XXX: can we get a stackdump here too?
829 CFStringRef msg
= CFStringCreateWithFormat(NULL
, NULL
,
830 CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"),
831 action
, (void*)new_action
, DebugDescription().c_str());
832 char *utf8_message
= utf8(msg
);
833 syslog(LOG_ERR
, "%s", utf8_message
);
840 CFTypeRef
CustomTransform::rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
)
842 CFErrorRef result
= NULL
;
844 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionCanExecute
, 0))
846 SetCanExecute(new_action
);
848 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionStartingExecution
, 0))
850 SetExecuteStarting(new_action
);
852 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionFinalize
, 0))
854 SetFinalize(new_action
);
856 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionExternalizeExtraData
, 0))
858 SetExternalizeExtraData(new_action
);
862 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
864 char *action_utf8
= utf8(action
);
865 syslog(LOG_ERR
, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
872 CFTypeRef
CustomTransform::rebind_attribute_action(
874 SecTransformStringOrAttributeRef attribute
,
875 SecTransformAttributeActionBlock new_action
)
877 CFErrorRef result
= NULL
;
879 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeNotification
, 0))
881 SetNotficationBlock(attribute
, new_action
);
883 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeValidation
, 0))
885 SetVerifyBlock(attribute
, new_action
);
889 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
890 char *action_utf8
= utf8(action
);
891 syslog(LOG_ERR
, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
898 CustomTransform::CustomTransform(CFStringRef cfname
, SecTransformCreateFP createFP
) :
900 createFuncPtr(createFP
),
902 can_run(Block_copy(default_can_run
)),
903 execute_starting(Block_copy(default_execute_starting
)),
904 finalize(Block_copy(default_finalize
)),
905 generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification
)),
906 generic_attribute_validation(Block_copy(default_generic_attribute_validation
)),
907 process_data(Block_copy(default_process_data
)),
908 externalize_data(Block_copy(default_externalize_data
)),
909 internalize_data(Block_copy(default_internalize_data
))
911 mAlwaysSelfNotify
= true;
913 input_ah
= getAH(kSecTransformInputAttributeName
, true);
914 output_ah
= getAH(kSecTransformOutputAttributeName
, true);
916 parameters
.version
= kSecTransformCreateBlockParametersVersion
;
917 parameters
.send
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
, CFTypeRef value
)
919 return SendMetaAttribute(attribute
, type
, value
);
922 parameters
.pushback
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, CFTypeRef value
)
924 return Pushback(getAH(attribute
), value
);
927 parameters
.get
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
)
929 return GetMetaAttribute(attribute
, type
);
932 parameters
.overrideTransform
= Block_copy(^(CFStringRef action
, SecTransformActionBlock new_action
)
934 return rebind_transform_action(action
, new_action
);
937 parameters
.overrideData
= Block_copy(^(CFStringRef action
,
938 SecTransformDataBlock new_action
)
940 return rebind_data_action(action
, new_action
);
944 CFTypeRef (^SecTransformOverrideAttributeAction)(
946 SecTransformStringOrAttributeRef attribute,
947 SecTransformAttributeActionBlock newAction);
949 parameters
.overrideAttribute
=
950 Block_copy(^(CFStringRef action
, SecTransformStringOrAttributeRef attribute
, SecTransformAttributeActionBlock new_action
)
952 return rebind_attribute_action(action
, attribute
, new_action
);
955 char *tname
= const_cast<char*>(CFStringGetCStringPtr(cfname
, kCFStringEncodingUTF8
));
957 CFIndex sz
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname
), kCFStringEncodingUTF8
);
958 tname
= static_cast<typeof(tname
)>(alloca(sz
));
959 CFStringGetCString(cfname
, tname
, sz
, kCFStringEncodingUTF8
);
961 tr
= CoreFoundationHolder::MakeHolder(kSecCustom
, (CoreFoundationObject
*)this);
963 instanceBlock
= (*createFuncPtr
)(cfname
, tr
, ¶meters
);
966 void CustomTransform::Create()
968 (void)instanceBlock();
972 CustomTransform::~CustomTransform() {
977 Block_release(instanceBlock
);
980 Block_release(can_run
);
981 Block_release(execute_starting
);
982 Block_release(finalize
);
983 Block_release(generic_attribute_set_notification
);
984 Block_release(process_data
);
985 Block_release(externalize_data
);
986 Block_release(internalize_data
);
988 Block_release(parameters
.send
);
989 Block_release(parameters
.pushback
);
990 Block_release(parameters
.get
);
991 Block_release(parameters
.overrideTransform
);
992 Block_release(parameters
.overrideData
);
993 Block_release(parameters
.overrideAttribute
);
995 // strictly speaking this isn't needed, but it can help track down some "use after free" bugs
997 createFuncPtr
= NULL
;
1001 CFErrorRef
CustomTransform::TransformStartingExecution()
1003 CFTypeRef result
= execute_starting();
1004 return (CFErrorRef
)result
;
1008 CFDictionaryRef
CustomTransform::GetCustomExternalData()
1010 CFTypeRef result
= externalize_data();
1016 if (CFGetTypeID(result
) == CFErrorGetTypeID())
1018 // Ouch! we should deal with this
1023 if (CFGetTypeID(result
) == CFDictionaryGetTypeID())
1025 return (CFDictionaryRef
)result
;
1030 return (CFDictionaryRef
)result
;
1034 void CustomTransform::SetCustomExternalData(CFDictionaryRef customData
)
1036 if (NULL
!= customData
)
1038 internalize_data(customData
);
1043 CFErrorRef
SecTransformSetAttributeAction(SecTransformImplementationRef ref
,
1045 SecTransformStringOrAttributeRef attribute
,
1046 SecTransformAttributeActionBlock newAction
)
1050 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1051 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1056 return (CFErrorRef
)ref
->overrideAttribute(action
, attribute
, newAction
);
1059 CFErrorRef
SecTransformSetDataAction(SecTransformImplementationRef ref
,
1061 SecTransformDataBlock newAction
)
1065 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1066 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1071 return (CFErrorRef
)ref
->overrideData(action
, newAction
);
1074 CFErrorRef
SecTransformSetTransformAction(SecTransformImplementationRef ref
,
1076 SecTransformActionBlock newAction
)
1080 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1081 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1086 return (CFErrorRef
)ref
->overrideTransform(action
, newAction
);
1089 CFTypeRef
SecTranformCustomGetAttribute(SecTransformImplementationRef ref
,
1090 SecTransformStringOrAttributeRef attribute
,
1091 SecTransformMetaAttributeType type
)
1095 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1096 "SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref");
1101 return (CFErrorRef
)ref
->get(attribute
, type
);
1104 CFTypeRef
SecTransformCustomSetAttribute(SecTransformImplementationRef ref
,
1105 SecTransformStringOrAttributeRef attribute
,
1106 SecTransformMetaAttributeType type
,
1111 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1112 "SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref");
1117 return (CFErrorRef
)ref
->send(attribute
, type
, value
);
1121 CFTypeRef
SecTransformPushbackAttribute(SecTransformImplementationRef ref
,
1122 SecTransformStringOrAttributeRef attribute
,
1127 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1128 "SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref");
1130 return (CFTypeRef
)result
;
1133 return ref
->pushback(attribute
, value
);