credential_factory.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2008 Martin Willi
  3. * HSR Hochschule fuer Technik Rapperswil
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * for more details.
  14. */
  15. #include <stdint.h>
  16. #include "credential_factory.h"
  17. #include <utils/debug.h>
  18. #include <collections/linked_list.h>
  19. #include <threading/thread_value.h>
  20. #include <threading/rwlock.h>
  21. #include <credentials/certificates/x509.h>
  22. #include <credentials/containers/container.h>
  23. ENUM(credential_type_names, CRED_PRIVATE_KEY, CRED_CONTAINER,
  24. "CRED_PRIVATE_KEY",
  25. "CRED_PUBLIC_KEY",
  26. "CRED_CERTIFICATE",
  27. "CRED_CONTAINER",
  28. );
  29. typedef struct private_credential_factory_t private_credential_factory_t;
  30. /**
  31. * private data of credential_factory
  32. */
  33. struct private_credential_factory_t {
  34. /**
  35. * public functions
  36. */
  37. credential_factory_t public;
  38. /**
  39. * list with entry_t
  40. */
  41. linked_list_t *constructors;
  42. /**
  43. * Thread specific recursiveness counter
  44. */
  45. thread_value_t *recursive;
  46. /**
  47. * lock access to builders
  48. */
  49. rwlock_t *lock;
  50. };
  51. typedef struct entry_t entry_t;
  52. struct entry_t {
  53. /** kind of credential builder */
  54. credential_type_t type;
  55. /** subtype of credential, e.g. certificate_type_t */
  56. int subtype;
  57. /** registered with final flag? */
  58. bool final;
  59. /** builder function */
  60. builder_function_t constructor;
  61. };
  62. METHOD(credential_factory_t, add_builder, void,
  63. private_credential_factory_t *this, credential_type_t type, int subtype,
  64. bool final, builder_function_t constructor)
  65. {
  66. entry_t *entry = malloc_thing(entry_t);
  67. entry->type = type;
  68. entry->subtype = subtype;
  69. entry->final = final;
  70. entry->constructor = constructor;
  71. this->lock->write_lock(this->lock);
  72. this->constructors->insert_last(this->constructors, entry);
  73. this->lock->unlock(this->lock);
  74. }
  75. METHOD(credential_factory_t, remove_builder, void,
  76. private_credential_factory_t *this, builder_function_t constructor)
  77. {
  78. enumerator_t *enumerator;
  79. entry_t *entry;
  80. this->lock->write_lock(this->lock);
  81. enumerator = this->constructors->create_enumerator(this->constructors);
  82. while (enumerator->enumerate(enumerator, &entry))
  83. {
  84. if (entry->constructor == constructor)
  85. {
  86. this->constructors->remove_at(this->constructors, enumerator);
  87. free(entry);
  88. }
  89. }
  90. enumerator->destroy(enumerator);
  91. this->lock->unlock(this->lock);
  92. }
  93. METHOD(credential_factory_t, create, void*,
  94. private_credential_factory_t *this, credential_type_t type, int subtype, ...)
  95. {
  96. enumerator_t *enumerator;
  97. entry_t *entry;
  98. va_list args;
  99. void *construct = NULL;
  100. int failures = 0;
  101. uintptr_t level;
  102. level = (uintptr_t)this->recursive->get(this->recursive);
  103. this->recursive->set(this->recursive, (void*)level + 1);
  104. this->lock->read_lock(this->lock);
  105. enumerator = this->constructors->create_enumerator(this->constructors);
  106. while (enumerator->enumerate(enumerator, &entry))
  107. {
  108. if (entry->type == type && entry->subtype == subtype)
  109. {
  110. va_start(args, subtype);
  111. construct = entry->constructor(subtype, args);
  112. va_end(args);
  113. if (construct)
  114. {
  115. break;
  116. }
  117. failures++;
  118. }
  119. }
  120. enumerator->destroy(enumerator);
  121. this->lock->unlock(this->lock);
  122. if (!construct && !level)
  123. {
  124. enum_name_t *names;
  125. switch (type)
  126. {
  127. case CRED_CERTIFICATE:
  128. names = certificate_type_names;
  129. break;
  130. case CRED_CONTAINER:
  131. names = container_type_names;
  132. break;
  133. case CRED_PRIVATE_KEY:
  134. case CRED_PUBLIC_KEY:
  135. default:
  136. names = key_type_names;
  137. break;
  138. }
  139. DBG1(DBG_LIB, "building %N - %N failed, tried %d builders",
  140. credential_type_names, type, names, subtype, failures);
  141. }
  142. this->recursive->set(this->recursive, (void*)level);
  143. return construct;
  144. }
  145. CALLBACK(builder_filter, bool,
  146. void *null, enumerator_t *orig, va_list args)
  147. {
  148. entry_t *entry;
  149. credential_type_t *type;
  150. int *subtype;
  151. VA_ARGS_VGET(args, type, subtype);
  152. while (orig->enumerate(orig, &entry))
  153. {
  154. if (entry->final)
  155. {
  156. *type = entry->type;
  157. *subtype = entry->subtype;
  158. return TRUE;
  159. }
  160. }
  161. return FALSE;
  162. }
  163. METHOD(credential_factory_t, create_builder_enumerator, enumerator_t*,
  164. private_credential_factory_t *this)
  165. {
  166. this->lock->read_lock(this->lock);
  167. return enumerator_create_filter(
  168. this->constructors->create_enumerator(this->constructors),
  169. builder_filter, this->lock, (void*)this->lock->unlock);
  170. }
  171. METHOD(credential_factory_t, destroy, void,
  172. private_credential_factory_t *this)
  173. {
  174. this->constructors->destroy_function(this->constructors, free);
  175. this->recursive->destroy(this->recursive);
  176. this->lock->destroy(this->lock);
  177. free(this);
  178. }
  179. /*
  180. * see header file
  181. */
  182. credential_factory_t *credential_factory_create()
  183. {
  184. private_credential_factory_t *this;
  185. INIT(this,
  186. .public = {
  187. .create = _create,
  188. .create_builder_enumerator = _create_builder_enumerator,
  189. .add_builder = _add_builder,
  190. .remove_builder = _remove_builder,
  191. .destroy = _destroy,
  192. },
  193. .constructors = linked_list_create(),
  194. .recursive = thread_value_create(NULL),
  195. .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
  196. );
  197. return &this->public;
  198. }