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 kSecCustomTransformWhatIsRequired
= CFSTR("WhatIsRequired");
40 const CFStringRef kSecCustomTransformAttributesToExternalize
= CFSTR("AttributesToExternalize");
41 const CFStringRef kSecTransformActionStartingExecution
= CFSTR("ExecuteStarting");
42 const CFStringRef kSecTransformActionProcessData
= CFSTR("TransformProcessData");
43 const CFStringRef kSecTransformActionAttributeNotification
= CFSTR("GenericAttributeSetNotification");
44 const CFStringRef kSecTransformActionFinalize
= CFSTR("Finalize");
45 const CFStringRef kSecTransformActionExternalizeExtraData
= CFSTR("ExternalizeExtraData");
46 const CFStringRef kSecTransformActionInternalizeExtraData
= CFSTR("InternalizeExtraData");
47 const CFStringRef kSecTransformActionAttributeValidation
= CFSTR("AttributeValidation");
50 @function SecTransformOverrideTransformAction
52 @abstract Used to override the default behavior of a custom transform.
54 @param action This should be either kSecTransformActionCanExecute,
55 kSecTransformActionStartingExecution, or
56 kSecTransformActionFinalize which signifies the behavior
57 that is being overridden.
60 A SecTransformAttributeActionBlock block that implements the
61 override behavior. Please see the
62 SecTransformActionBlock discussion for more
65 @result A CFErrorRef if an error occurred, NULL otherwise.
67 @discussion An action may be overridden more then once, the most
68 recent override will be used.Please see the example in
69 the documentation for the SecTransformActionBlock
73 typedef CFTypeRef (^SecTransformOverrideTransformAction
)(CFStringRef action
,
74 SecTransformActionBlock newAction
);
77 @function SecTransformOverrideDataAction
79 @abstract Changes the default attribute handling for a
82 @param action This should be either kSecTransformActionProcessData,
83 kSecTransformActionExternalizeExtraData which signifies
84 what behavior is being overridden.
87 A SecTransformDataBlock block that implements the
88 override behavior. Please see the
89 SecTransformDataBlock discussion for more
92 @result A CFErrorRef if an error occurred. NULL otherwise.
94 @discussion An action may be overridden more then once, the most
95 recent override will be used. Please see the example
96 in the documentation for the SecTransformAttributeActionBlock
100 typedef CFTypeRef (^SecTransformOverrideDataAction
)(CFStringRef action
,
101 SecTransformDataBlock newAction
);
104 @function SecTransformOverrideAttributeAction
106 @abstract Changes the default attribute handling for a
109 @param action This should be either SecTransformSetAttributeAction,
110 kSecTransformActionAttributeValidation which signifies
111 what behavior is being overridden.
114 The attribute whose attribute default attribute handling is
115 being overridden. Passing NULL will override all attributes
116 that have not been specifically overridden.
119 A SecTransformAttributeActionBlock block
120 that implements the override behavior.
122 If the action parameter is SecTransformSetAttributeAction
123 then this block is called whenever a set is called on the
124 attribute that this block was registered for or in the case
125 of a NULL attribute name any attribute that has not been specifically
126 overridden. The block may transmogrify the data as needed. It may
127 also send the data to any other attribue by calling
128 SecTransformCustomSetAttribute. The value returned from the block
129 will be the new value for the attribute.
131 If the action parameter is kSecTransformActionAttributeValidation then
132 this block is called to validate the new value for the
133 attribute that this block was registered for or in the case
134 of a NULL attribute name any attribute that has not been specifically
135 overridden. The block should test if the new value is acceptable
136 and return NULL if it is valid a CFErrorRef otherwise.
138 @result A CFErrorRef if an error occurred. NULL otherwise.
140 @discussion An action may be overridden more then once, the most
141 recent override will be used. Please see the example
142 in the documentation for the
143 SecTransformAttributeActionBlock block.
146 typedef CFTypeRef (^SecTransformOverrideAttributeAction
)(
148 SecTransformStringOrAttributeRef attribute
,
149 SecTransformAttributeActionBlock newAction
);
153 @function SecTransformGetAttributeBlock
155 @abstract Retrieves the value of the attribute metadata of the
159 The attribute from which to retrieve the metadata from.
161 @param type The type of the metadata to be fetched.
163 @result The value of the metadata that was retrieved or a CFErrorRef
166 @result The value of the metadata that was retrieved.
170 typedef CFTypeRef (^SecTransformGetAttributeBlock
)(
171 SecTransformStringOrAttributeRef attribute
,
172 SecTransformMetaAttributeType type
);
175 @function SecTransformSetAttributeBlock
177 @abstract This sets the value of the metadata of an attribute.
180 The attribute whose value is sent
182 @param type The metadata type that specifies what metadata value
185 @param value The value of the metadata to be sent.
187 @result A CFErrorRef is an error occurred, NULL otherwise.
189 @discussion The attribute parameter specifies which attribute will
190 have its data set. The type parameter specifies which of
191 the metadata items is set. The value parameter is the
195 typedef CFErrorRef (^SecTransformSetAttributeBlock
)(
196 SecTransformStringOrAttributeRef attribute
,
197 SecTransformMetaAttributeType type
,
202 @function SecTransformPushBackAttributeBlock
204 @abstract Allows for putting a single value back for a
205 specific attribute. This will stop the flow of
206 data into the specified attribute until an
207 attribute is changed.
210 The attribute that has its data pushed back.
212 @param value The value being pushed back.
215 @result A CFErrorRef is an error occurred, NULL otherwise.
216 Note: pushing back a second value will abort the
217 transform, not return an error from this call.
219 @discussion A particular custom transform may need multple
220 values to be set before it can do the processing
221 that the custom transform is designed to do. For
222 example, it may need a key and a salt value. The
223 salt value maybe supplied by another transform while
224 the key transform may have been set explicitly. When
225 data is presented to this custom transform the salt
226 value may not have been sent from the upstream transform.
227 The custom transform can then push back the input data
228 which causes the transform to stall. When any
229 attribute on the custom transform is changed, such as
230 the upstream transform delivers the salt value, then
231 the data that was pushed back is re-delivered
234 typedef CFErrorRef (^SecTransformPushBackAttributeBlock
)(
235 SecTransformStringOrAttributeRef attribute
,
239 @const kSecTransformCreateBlockParametersVersion
240 The current version number of the SecTransformCreateBlockParameters
246 kSecTransformCreateBlockParametersVersion
= 1
250 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
254 @struct OpaqueSecTransformImplementation
257 The version number of this structure
259 @field overrideTransform
260 A SecTransformOverrideTransformAction block. See
261 the headerdoc for this block for additional information.
263 @field overrideAttribute
264 A SecTransformOverrideAttributeAction block. See
265 the headerdoc for this block for additional information.
268 A SecTransformGetAttributeBlock block. See
269 the headerdoc for this block for additional information.
272 A SecTransformSetAttributeBlock block. See
273 the headerdoc for this block for additional information.
276 A SecTransformPushBackAttributeBlock block. See
277 the headerdoc for this block for additional information.
279 struct OpaqueSecTransformImplementation
281 CFIndex version
; // Set to kSecTransformCreateBlockParametersVersion
283 // The following two blocks allow for overriding 'standard'
284 // transform behavior
285 SecTransformOverrideTransformAction overrideTransform
;
286 SecTransformOverrideDataAction overrideData
;
287 SecTransformOverrideAttributeAction overrideAttribute
;
289 // The following methods allow for dealing with the transform mechanism
290 // They are called synchronously
291 SecTransformGetAttributeBlock get
;
292 SecTransformSetAttributeBlock send
;
293 SecTransformPushBackAttributeBlock pushback
;
297 class CustomTransformFactory
: public TransformFactory
300 SecTransformCreateFP createFuncPtr
;
302 CustomTransformFactory(CFStringRef name
, SecTransformCreateFP createFP
, CFErrorRef
*error
);
303 virtual ~CustomTransformFactory() {};
304 virtual CFTypeRef
Make();
308 static SecTransformActionBlock default_can_run
= ^{ return (CFTypeRef
)NULL
; };
309 static SecTransformActionBlock default_execute_starting
= default_can_run
;
310 static SecTransformActionBlock default_finalize
= default_execute_starting
;
311 static SecTransformActionBlock default_externalize_data
= default_finalize
;
313 static SecTransformDataBlock default_process_data
= ^(CFTypeRef value
) { return value
; };
314 //static SecTransformDataBlock default_validate = ^(CFTypeRef value) { return (CFTypeRef)NULL; };
315 static SecTransformAttributeActionBlock default_generic_attribute_set_notification
=
316 ^(SecTransformAttributeRef ah
, CFTypeRef value
) { return value
; };
318 static SecTransformAttributeActionBlock default_generic_attribute_validation
=
319 ^(SecTransformAttributeRef ah
, CFTypeRef value
)
321 return (CFTypeRef
)NULL
;
324 static SecTransformDataBlock default_internalize_data
=
327 return (CFTypeRef
)NULL
;
330 class CustomTransform
: public Transform
333 SecTransformCreateFP createFuncPtr
;
334 SecTransformInstanceBlock instanceBlock
;
336 SecTransformActionBlock can_run
;
337 SecTransformActionBlock execute_starting
;
338 SecTransformActionBlock finalize
;
339 SecTransformAttributeActionBlock generic_attribute_set_notification
;
340 SecTransformAttributeActionBlock generic_attribute_validation
;
341 SecTransformDataBlock process_data
;
342 SecTransformActionBlock externalize_data
;
343 SecTransformDataBlock internalize_data
;
347 SecTransformAttributeRef input_ah
;
348 SecTransformAttributeRef output_ah
;
350 OpaqueSecTransformImplementation parameters
;
352 void SetCanExecute(SecTransformActionBlock CanExecuteBlock
)
354 Block_release(can_run
);
357 can_run
= Block_copy(CanExecuteBlock
);
362 can_run
= Block_copy(default_can_run
);
366 void SetExecuteStarting(SecTransformActionBlock executeStartingBlock
)
368 Block_release(execute_starting
);
369 if (executeStartingBlock
)
371 execute_starting
= Block_copy(executeStartingBlock
);
376 execute_starting
= Block_copy(default_execute_starting
);
380 void SetFinalize(SecTransformActionBlock finalizeBlock
)
382 Block_release(finalize
);
385 finalize
= Block_copy(finalizeBlock
);
390 finalize
= Block_copy(default_finalize
);
394 void SetExternalizeExtraData(SecTransformActionBlock externalizeBlock
)
396 Block_release(externalizeBlock
);
397 if (externalizeBlock
)
399 externalize_data
= Block_copy(externalizeBlock
);
404 externalize_data
= Block_copy(default_externalize_data
);
408 void SetProcessData(SecTransformDataBlock processDataBlock
)
410 Block_release(process_data
);
411 if (processDataBlock
)
413 process_data
= Block_copy(processDataBlock
);
418 process_data
= Block_copy(default_process_data
);
422 void SetInternalizeExtraData(SecTransformDataBlock InternalizeExtraDataBlock
)
424 Block_release(internalize_data
);
425 if (InternalizeExtraDataBlock
)
427 internalize_data
= Block_copy(InternalizeExtraDataBlock
);
432 internalize_data
= Block_copy(default_internalize_data
);
438 void SetNotficationBlock(SecTransformStringOrAttributeRef attribute
,
439 SecTransformAttributeActionBlock notificationBlock
)
441 SecTransformAttributeActionBlock blockToSet
=
442 Block_copy((notificationBlock
) ? notificationBlock
:
443 default_generic_attribute_set_notification
);
447 transform_attribute
*ta
= getTA(attribute
, true);
449 if (ta
->attribute_changed_block
)
451 Block_release(ta
->attribute_changed_block
);
454 ta
->attribute_changed_block
= blockToSet
;
459 if (generic_attribute_set_notification
)
461 Block_release(generic_attribute_set_notification
);
464 generic_attribute_set_notification
= blockToSet
;
468 void SetVerifyBlock(SecTransformStringOrAttributeRef attribute
,
469 SecTransformAttributeActionBlock verifyBlock
)
471 SecTransformAttributeActionBlock blockToSet
=
472 Block_copy((verifyBlock
) ? verifyBlock
:
473 generic_attribute_validation
);
477 transform_attribute
*ta
= getTA(attribute
, true);
479 if (ta
->attribute_validate_block
)
481 Block_release(ta
->attribute_validate_block
);
484 ta
->attribute_validate_block
= blockToSet
;
488 if (generic_attribute_validation
)
490 Block_release(generic_attribute_validation
);
493 generic_attribute_validation
= blockToSet
;
500 CustomTransform(CFStringRef name
, SecTransformCreateFP createFP
);
501 virtual ~CustomTransform();
505 CFTypeRef
rebind_data_action(CFStringRef action
,
506 SecTransformDataBlock new_action
);
508 CFTypeRef
rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
);
510 CFTypeRef
rebind_attribute_action(CFStringRef action
,
511 SecTransformStringOrAttributeRef attribute
,
512 SecTransformAttributeActionBlock new_action
);
514 SecTransformRef
get_ref() { return tr
; }
516 virtual void AttributeChanged(CFStringRef name
, CFTypeRef value
);
517 virtual void AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
);
518 virtual CFErrorRef
TransformStartingExecution();
519 virtual CFDictionaryRef
GetCustomExternalData();
520 virtual void SetCustomExternalData(CFDictionaryRef customData
);
522 friend Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
);
527 #pragma mark CustomTransformFactory
529 CustomTransformFactory::CustomTransformFactory(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
* error
) :
530 TransformFactory(uniqueName
, false, kSecCustom
),
531 createFuncPtr(createFP
)
533 TransformFactory
*existing
= FindTransformFactoryByType(uniqueName
);
538 *error
= CreateSecTransformErrorRef(kSecTransformErrorNameAlreadyRegistered
,
539 "Custom transform type %s already exists.", uniqueName
);
545 if (CFStringGetCharacterAtIndex(uniqueName
, 0) == '_')
549 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
550 "Invalid transform type name %s -- type names must not start with an _", uniqueName
);
555 static CFCharacterSetRef invalidTypeCharactors
= NULL
;
556 static dispatch_once_t setupInvalidTypeCharactors
;
557 dispatch_once(&setupInvalidTypeCharactors
, ^{
558 invalidTypeCharactors
= CFCharacterSetCreateWithCharactersInString(NULL
, CFSTR("/:"));
561 if (CFStringFindCharacterFromSet(uniqueName
, invalidTypeCharactors
, CFRangeMake(0, CFStringGetLength(uniqueName
)), 0, &has_bad
)) {
564 *error
= CreateSecTransformErrorRef(kSecTransformInvalidArgument
,
565 "Invalid character '%c' in transform type name %s", CFStringGetCharacterAtIndex(uniqueName
, has_bad
.location
), uniqueName
);
569 RegisterTransform(this, kSecCustom
);
572 CFTypeRef
CustomTransformFactory::Make()
574 CustomTransform
*ct
= new CustomTransform(this->GetTypename(), createFuncPtr
);
576 return ct
->get_ref();
582 SecTransformAttributeActionBlock
SecTransformCreateValidatorForCFtype(CFTypeID expected_type
, Boolean null_allowed
) {
583 SecTransformAttributeActionBlock validate
= NULL
;
584 CFErrorRef (^make_error_message
)(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) =
585 ^(SecTransformAttributeRef attr
, CFTypeRef value
, CFTypeID expected_type
, Boolean null_allowed
) {
586 CFStringRef expected_type_name
= CFCopyTypeIDDescription(expected_type
);
587 CFErrorRef error
= NULL
;
589 CFStringRef value_type_name
= CFCopyTypeIDDescription(CFGetTypeID(value
));
590 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received value of type %@ (%@), expected%@ a %@%@",
591 attr
, value_type_name
, value
,
592 null_allowed
? CFSTR(" either") : CFSTR(""),
594 null_allowed
? CFSTR(" or a NULL") : CFSTR(""));
595 CFRelease(value_type_name
);
597 error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "%@ received NULL value, expected a %@",
598 attr
, expected_type_name
);
600 CFRelease(expected_type_name
);
607 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
608 if (value
== NULL
|| CFGetTypeID(value
) == expected_type
) {
609 return (CFTypeRef
)NULL
;
611 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
614 validate
= ^(SecTransformAttributeRef attr
, CFTypeRef value
) {
615 if (value
!= NULL
&& CFGetTypeID(value
) == expected_type
) {
616 return (CFTypeRef
)NULL
;
618 return (CFTypeRef
)make_error_message(attr
, value
, expected_type
, null_allowed
);
622 return Block_copy(validate
);
626 Boolean
SecTransformRegister(CFStringRef uniqueName
, SecTransformCreateFP createFP
, CFErrorRef
*caller_error
)
628 CFErrorRef error
= NULL
;
630 CustomTransformFactory
*tf
= new CustomTransformFactory(uniqueName
, createFP
, &error
);
636 *caller_error
= error
;
646 SecTransformRef
SecTransformCreate(CFStringRef name
, CFErrorRef
*error
)
648 SecTransformRef tr
= TransformFactory::MakeTransformWithType(name
, error
);
653 Boolean
SecExternalSourceSetValue(SecTransformRef xst
, CFTypeRef value
, CFErrorRef
*error
)
655 CustomTransform
*ct
= (CustomTransform
*)CoreFoundationHolder::ObjectFromCFType(xst
);
656 extern CFStringRef external_source_name
;
657 if (CFEqual(ct
->mTypeName
, external_source_name
)) {
658 ct
->SetAttribute(ct
->input_ah
, value
);
662 *error
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "SecExternalSourceSetValue called for %@, you need to pass in an ExternalSource transform not a %@", ct
->GetName(), ct
->mTypeName
);
669 /* ==========================================================================
671 description: A Special CFType that signifies that no data is being
673 ==========================================================================*/
674 #pragma mark NoDataClass
676 class NoDataClass
: public CoreFoundationObject
682 virtual ~NoDataClass();
683 std::string
FormattingDescription(CFDictionaryRef options
);
684 std::string
DebugDescription();
685 static CFTypeRef
Make();
688 CFTypeRef
NoDataClass::Make() {
689 NoDataClass
* obj
= new NoDataClass();
690 return CoreFoundationHolder::MakeHolder(gInternalProtectedCFObjectName
, obj
);
694 NoDataClass::NoDataClass() : CoreFoundationObject(gInternalProtectedCFObjectName
) {
697 NoDataClass::~NoDataClass()
701 std::string
NoDataClass::DebugDescription()
703 return CoreFoundationObject::DebugDescription() + " | SecTransformNoData";
706 std::string
NoDataClass::FormattingDescription(CFDictionaryRef options
)
708 return CoreFoundationObject::FormattingDescription(options
) + " | SecTransformNoData";
711 CFTypeRef
SecTransformNoData()
713 static dispatch_once_t inited
;
714 static CFTypeRef no_data
;
716 dispatch_once(&inited
,
718 no_data
= NoDataClass::Make();
724 /* ==========================================================================
725 class Implementation CustomTransform
726 ==========================================================================*/
728 #pragma mark CustomTransform
730 void CustomTransform::AttributeChanged(CFStringRef name
, CFTypeRef value
) {
732 // 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
735 // We really shouldn't get here, but this is a production build and recovery is easy to code (but costly to execute)
736 AttributeChanged(getAH(name
, false), value
);
740 void CustomTransform::AttributeChanged(SecTransformAttributeRef ah
, CFTypeRef value
)
742 transform_attribute
*ta
= ah2ta(ah
);
743 SecTransformAttributeActionBlock attribute_set_notification
= NULL
;
745 SecTransformAttributeActionBlock attribute_validate
= NULL
;
747 attribute_validate
= (SecTransformAttributeActionBlock
)ta
->attribute_validate_block
;
748 if (!attribute_validate
) {
749 attribute_validate
= generic_attribute_validation
;
751 CFTypeRef vr
= attribute_validate(ah
, value
);
753 if (CFGetTypeID(vr
) == CFErrorGetTypeID()) {
754 SendAttribute(AbortAH
, vr
);
757 CFErrorRef e
= CreateSecTransformErrorRef(kSecTransformErrorInvalidType
, "Invalid return type from a validate action, expected a CFErrorRef got a %@ (%@)", CFCopyTypeIDDescription(CFGetTypeID(vr
)), vr
);
758 SendAttribute(AbortAH
, e
);
760 // XXX: this causes a core dump -- I think AbortAH doesn't take it's own reference!! CFRelease(e);
765 attribute_set_notification
= (SecTransformAttributeActionBlock
)ta
->attribute_changed_block
;
767 if ((!attribute_set_notification
) && ah
== input_ah
)
769 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
770 if (vtype
== CFDataGetTypeID())
772 CFTypeRef output
= process_data(value
);
773 if (output
== NULL
|| output
!= SecTransformNoData())
775 SendAttribute(output_ah
, output
);
777 // if output == value, we are being asked to just
778 // forward the existing value. No need to release.
779 // If they are different, we are being asked to
780 // send a new value which must be released.
782 if (output
!= value
&& output
!= NULL
)
788 else if (vtype
== CFErrorGetTypeID() && !ah2ta(ah
)->direct_error_handling
)
790 SendAttribute(output_ah
, value
);
793 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
794 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
795 if (new_value
!= value
)
797 SendAttribute(ah
, new_value
);
803 CFTypeID vtype
= value
? CFGetTypeID(value
) : CFDataGetTypeID();
804 if (vtype
!= CFErrorGetTypeID() || ah2ta(ah
)->direct_error_handling
)
806 attribute_set_notification
= attribute_set_notification
? attribute_set_notification
: generic_attribute_set_notification
;
807 CFTypeRef new_value
= attribute_set_notification(ah
, value
);
808 if (new_value
!= value
)
810 SendAttribute(ah
, new_value
);
815 SendAttribute(output_ah
, value
);
820 CFTypeRef
CustomTransform::rebind_data_action(CFStringRef action
,
821 SecTransformDataBlock new_action
)
823 CFTypeRef result
= NULL
;
824 if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionProcessData
, action
, 0))
826 SetProcessData(new_action
);
828 else if (kCFCompareEqualTo
== CFStringCompare(kSecTransformActionInternalizeExtraData
, action
, 0))
830 SetInternalizeExtraData(new_action
);
834 result
= (CFTypeRef
)CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
836 // XXX: can we get a stackdump here too?
837 CFStringRef msg
= CFStringCreateWithFormat(NULL
, NULL
,
838 CFSTR("rebind_data_action (action %@, new_action %p, transform %s)"),
839 action
, (void*)new_action
, DebugDescription().c_str());
840 char *utf8_message
= utf8(msg
);
841 syslog(LOG_ERR
, "%s", utf8_message
);
848 CFTypeRef
CustomTransform::rebind_transform_action(CFStringRef action
, SecTransformActionBlock new_action
)
850 CFErrorRef result
= NULL
;
852 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionCanExecute
, 0))
854 SetCanExecute(new_action
);
856 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionStartingExecution
, 0))
858 SetExecuteStarting(new_action
);
860 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionFinalize
, 0))
862 SetFinalize(new_action
);
864 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionExternalizeExtraData
, 0))
866 SetExternalizeExtraData(new_action
);
870 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
872 char *action_utf8
= utf8(action
);
873 syslog(LOG_ERR
, "rebind_transform_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
880 CFTypeRef
CustomTransform::rebind_attribute_action(
882 SecTransformStringOrAttributeRef attribute
,
883 SecTransformAttributeActionBlock new_action
)
885 CFErrorRef result
= NULL
;
887 if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeNotification
, 0))
889 SetNotficationBlock(attribute
, new_action
);
891 else if (kCFCompareEqualTo
== CFStringCompare(action
, kSecTransformActionAttributeValidation
, 0))
893 SetVerifyBlock(attribute
, new_action
);
897 result
= CreateSecTransformErrorRef(kSecTransformInvalidOverride
, "Unkown override type");
898 char *action_utf8
= utf8(action
);
899 syslog(LOG_ERR
, "rebind_attribute_action (action %s, all-attributes, block %p, transform %s)\n", action_utf8
, (void*)new_action
, DebugDescription().c_str());
906 CustomTransform::CustomTransform(CFStringRef cfname
, SecTransformCreateFP createFP
) :
908 createFuncPtr(createFP
),
910 can_run(Block_copy(default_can_run
)),
911 execute_starting(Block_copy(default_execute_starting
)),
912 finalize(Block_copy(default_finalize
)),
913 generic_attribute_set_notification(Block_copy(default_generic_attribute_set_notification
)),
914 generic_attribute_validation(Block_copy(default_generic_attribute_validation
)),
915 process_data(Block_copy(default_process_data
)),
916 externalize_data(Block_copy(default_externalize_data
)),
917 internalize_data(Block_copy(default_internalize_data
))
919 mAlwaysSelfNotify
= true;
921 input_ah
= getAH(kSecTransformInputAttributeName
, true);
922 output_ah
= getAH(kSecTransformOutputAttributeName
, true);
924 parameters
.version
= kSecTransformCreateBlockParametersVersion
;
925 parameters
.send
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
, CFTypeRef value
)
927 return SendMetaAttribute(attribute
, type
, value
);
930 parameters
.pushback
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, CFTypeRef value
)
932 return Pushback(getAH(attribute
), value
);
935 parameters
.get
= Block_copy(^(SecTransformStringOrAttributeRef attribute
, SecTransformMetaAttributeType type
)
937 return GetMetaAttribute(attribute
, type
);
940 parameters
.overrideTransform
= Block_copy(^(CFStringRef action
, SecTransformActionBlock new_action
)
942 return rebind_transform_action(action
, new_action
);
945 parameters
.overrideData
= Block_copy(^(CFStringRef action
,
946 SecTransformDataBlock new_action
)
948 return rebind_data_action(action
, new_action
);
952 CFTypeRef (^SecTransformOverrideAttributeAction)(
954 SecTransformStringOrAttributeRef attribute,
955 SecTransformAttributeActionBlock newAction);
957 parameters
.overrideAttribute
=
958 Block_copy(^(CFStringRef action
, SecTransformStringOrAttributeRef attribute
, SecTransformAttributeActionBlock new_action
)
960 return rebind_attribute_action(action
, attribute
, new_action
);
963 char *tname
= const_cast<char*>(CFStringGetCStringPtr(cfname
, kCFStringEncodingUTF8
));
965 CFIndex sz
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfname
), kCFStringEncodingUTF8
);
966 tname
= static_cast<typeof(tname
)>(alloca(sz
));
967 CFStringGetCString(cfname
, tname
, sz
, kCFStringEncodingUTF8
);
969 tr
= CoreFoundationHolder::MakeHolder(kSecCustom
, (CoreFoundationObject
*)this);
971 instanceBlock
= (*createFuncPtr
)(cfname
, tr
, ¶meters
);
974 void CustomTransform::Create()
976 (void)instanceBlock();
980 CustomTransform::~CustomTransform() {
985 Block_release(instanceBlock
);
988 Block_release(can_run
);
989 Block_release(execute_starting
);
990 Block_release(finalize
);
991 Block_release(generic_attribute_set_notification
);
992 Block_release(process_data
);
993 Block_release(externalize_data
);
994 Block_release(internalize_data
);
996 Block_release(parameters
.send
);
997 Block_release(parameters
.pushback
);
998 Block_release(parameters
.get
);
999 Block_release(parameters
.overrideTransform
);
1000 Block_release(parameters
.overrideData
);
1001 Block_release(parameters
.overrideAttribute
);
1003 // strictly speaking this isn't needed, but it can help track down some "use after free" bugs
1005 createFuncPtr
= NULL
;
1006 process_data
= NULL
;
1009 CFErrorRef
CustomTransform::TransformStartingExecution()
1011 CFTypeRef result
= execute_starting();
1012 return (CFErrorRef
)result
;
1016 CFDictionaryRef
CustomTransform::GetCustomExternalData()
1018 CFTypeRef result
= externalize_data();
1024 if (CFGetTypeID(result
) == CFErrorGetTypeID())
1026 // Ouch! we should deal with this
1031 if (CFGetTypeID(result
) == CFDictionaryGetTypeID())
1033 return (CFDictionaryRef
)result
;
1038 return (CFDictionaryRef
)result
;
1042 void CustomTransform::SetCustomExternalData(CFDictionaryRef customData
)
1044 if (NULL
!= customData
)
1046 internalize_data(customData
);
1051 CFErrorRef
SecTransformSetAttributeAction(SecTransformImplementationRef ref
,
1053 SecTransformStringOrAttributeRef attribute
,
1054 SecTransformAttributeActionBlock newAction
)
1058 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1059 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1064 return (CFErrorRef
)ref
->overrideAttribute(action
, attribute
, newAction
);
1067 CFErrorRef
SecTransformSetDataAction(SecTransformImplementationRef ref
,
1069 SecTransformDataBlock newAction
)
1073 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1074 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1079 return (CFErrorRef
)ref
->overrideData(action
, newAction
);
1082 CFErrorRef
SecTransformSetTransformAction(SecTransformImplementationRef ref
,
1084 SecTransformActionBlock newAction
)
1088 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1089 "SecTransformSetAttributeNotificationAction called with a NULL SecTransformImplementationRef ref");
1094 return (CFErrorRef
)ref
->overrideTransform(action
, newAction
);
1097 CFTypeRef
SecTranformCustomGetAttribute(SecTransformImplementationRef ref
,
1098 SecTransformStringOrAttributeRef attribute
,
1099 SecTransformMetaAttributeType type
)
1103 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1104 "SecTransformCustomGetAttribute called with a NULL SecTransformImplementationRef ref");
1109 return (CFErrorRef
)ref
->get(attribute
, type
);
1112 CFTypeRef
SecTransformCustomSetAttribute(SecTransformImplementationRef ref
,
1113 SecTransformStringOrAttributeRef attribute
,
1114 SecTransformMetaAttributeType type
,
1119 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1120 "SecTransformCustomSetAttribute called with a NULL SecTransformImplementationRef ref");
1125 return (CFErrorRef
)ref
->send(attribute
, type
, value
);
1129 CFTypeRef
SecTransformPushbackAttribute(SecTransformImplementationRef ref
,
1130 SecTransformStringOrAttributeRef attribute
,
1135 CFErrorRef result
= CreateSecTransformErrorRef(kSecTransformErrorInvalidInput
,
1136 "SecTransformPushbackAttribute called with a NULL SecTransformImplementationRef ref");
1138 return (CFTypeRef
)result
;
1141 return ref
->pushback(attribute
, value
);