/ OSX / libsecurity_transform / lib / TransformFactory.cpp
TransformFactory.cpp
  1  #include <libkern/OSAtomic.h>
  2  
  3  #include "TransformFactory.h"
  4  #include "NullTransform.h"
  5  #include "Digest.h"
  6  #include "EncryptTransform.h"
  7  #include "GroupTransform.h"
  8  #include "Utilities.h"
  9  
 10  
 11  void TransformFactory::RegisterTransforms()
 12  {
 13  	RegisterTransform_prelocked(NullTransform::MakeTransformFactory(), NULL);
 14  	RegisterTransform_prelocked(DigestTransform::MakeTransformFactory(), NULL);
 15  	RegisterTransform_prelocked(EncryptTransform::MakeTransformFactory(), NULL);
 16  	RegisterTransform_prelocked(DecryptTransform::MakeTransformFactory(), NULL);
 17  	RegisterTransform_prelocked(GroupTransform::MakeTransformFactory(), NULL);
 18  }
 19  
 20  CFMutableDictionaryRef TransformFactory::gRegistered;
 21  dispatch_once_t TransformFactory::gSetup;
 22  dispatch_queue_t TransformFactory::gRegisteredQueue;
 23  
 24  bool TransformFactory::RegisterTransform_prelocked(TransformFactory* tf, CFStringRef cfname)
 25  {
 26      if (!CFDictionaryContainsKey(gRegistered, tf->mCFType)) {
 27          CFDictionaryAddValue(gRegistered, tf->mCFType, tf);
 28          if (!cfname) {
 29              CoreFoundationObject::RegisterObject(tf->mCFType, false);
 30          } else {
 31              if (!CoreFoundationObject::FindObjectType(cfname)) {
 32                  CoreFoundationObject::RegisterObject(cfname, false);
 33              }
 34          }
 35      }
 36      
 37      return true;
 38  }
 39  
 40  
 41  void TransformFactory::RegisterTransform(TransformFactory* tf, CFStringRef cfname)
 42  {
 43      dispatch_once_f(&gSetup, NULL, Setup);
 44      dispatch_barrier_sync(gRegisteredQueue, ^{
 45          RegisterTransform_prelocked(tf, cfname);
 46      });
 47  }
 48  
 49  void TransformFactory::Setup(void *)
 50  {
 51      gRegisteredQueue = dispatch_queue_create("com.apple.security.TransformFactory.Registered", DISPATCH_QUEUE_CONCURRENT);
 52      gRegistered = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
 53      RegisterTransforms();
 54  }
 55  
 56  void TransformFactory::Setup()
 57  {
 58      dispatch_once_f(&gSetup, NULL, Setup);
 59  }
 60  
 61  TransformFactory* TransformFactory::FindTransformFactoryByType(CFStringRef name)
 62  {
 63      dispatch_once_f(&gSetup, NULL, Setup);
 64      __block TransformFactory *ret;
 65      dispatch_barrier_sync(gRegisteredQueue, ^{
 66          ret = (TransformFactory*)CFDictionaryGetValue(gRegistered, name);
 67      });
 68      return ret;
 69  }
 70  
 71  
 72  
 73  SecTransformRef TransformFactory::MakeTransformWithType(CFStringRef type, CFErrorRef* baseError) CF_RETURNS_RETAINED
 74  {
 75  	TransformFactory* tf = FindTransformFactoryByType(type);
 76  	if (!tf)
 77  	{
 78  		if (baseError != NULL)
 79  		{
 80  #if 0
 81              // This version lists out all regestered transform types.
 82              // It is useful more for debugging then for anything else,
 83              // so it is great to keep around, but normally not so good
 84              // to run.
 85  			dispatch_barrier_sync(gRegisteredQueue, ^(void) {
 86                  CFMutableStringRef transformNames = CFStringCreateMutable(NULL, 0);
 87                  CFIndex numberRegistered = CFDictionaryGetCount(gRegistered);
 88                  CFStringRef *names = (CFStringRef*)malloc(numberRegistered * sizeof(CFStringRef));
 89                  if (names == NULL) {
 90                      *baseError = CreateSecTransformErrorRef(errSecMemoryError,
 91                                                              "The %s transform names can't be allocated.", type);
 92                      return NULL;
 93                  }
 94  
 95                  CFDictionaryGetKeysAndValues(gRegistered, (const void**)names, NULL);
 96                  for(int i = 0; i < numberRegistered; i++) {
 97                      if (i != 0) {
 98                          CFStringAppend(transformNames, CFSTR(", "));
 99                      }
100                      CFStringAppend(transformNames, names[i]);
101                  }
102                  
103                  free(names);
104  
105                  *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, 
106                                                          "The %s transform is not registered, choose from: %@", type,transformNames);
107  
108              });
109  #else
110              *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, 
111                                                      "The %s transform is not registered", type);
112  #endif
113  		}
114  		
115  		return NULL;
116  	}
117  	else
118  	{
119  		return tf->Make();
120  	}
121  }
122  
123  
124  
125  TransformFactory::TransformFactory(CFStringRef type, bool registerGlobally, CFStringRef cftype) : mCFType(type)
126  {
127  	if (registerGlobally)
128  	{
129  		CoreFoundationObject::RegisterObject(cftype ? cftype : type, false);
130  	}
131  }