6358293860d628c4e09fe5cfafcdeb466bb98c70
[strongswan.git] / src / libstrongswan / credentials / credential_factory.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * 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 * $Id$
16 */
17
18 #include "credential_factory.h"
19
20 #include <debug.h>
21 #include <utils/linked_list.h>
22 #include <utils/mutex.h>
23 #include <credentials/certificates/x509.h>
24
25 typedef struct private_credential_factory_t private_credential_factory_t;
26
27 /**
28 * private data of credential_factory
29 */
30 struct private_credential_factory_t {
31
32 /**
33 * public functions
34 */
35 credential_factory_t public;
36
37 /**
38 * list with entry_t
39 */
40 linked_list_t *constructors;
41
42 /**
43 * mutex to lock access to modules
44 */
45 mutex_t *mutex;
46 };
47
48 typedef struct entry_t entry_t;
49 struct entry_t {
50 /** kind of credential builder */
51 credential_type_t type;
52 /** subtype of credential, e.g. certificate_type_t */
53 int subtype;
54 /** builder construction function */
55 builder_constructor_t constructor;
56 };
57
58 /**
59 * Implementation of credential_factory_t.create_builder.
60 */
61 static builder_t* create_builder(private_credential_factory_t *this,
62 credential_type_t type, int subtype)
63 {
64 enumerator_t *enumerator;
65 entry_t *entry;
66 builder_t *builder = NULL;
67
68 this->mutex->lock(this->mutex);
69 enumerator = this->constructors->create_enumerator(this->constructors);
70 while (enumerator->enumerate(enumerator, &entry))
71 {
72 if (entry->type == type && entry->subtype == subtype)
73 {
74 builder = entry->constructor(subtype);
75 if (builder)
76 {
77 break;
78 }
79 }
80 }
81 enumerator->destroy(enumerator);
82 this->mutex->unlock(this->mutex);
83 return builder;
84 }
85
86 /**
87 * Implementation of credential_factory_t.add_builder_constructor.
88 */
89 static void add_builder(private_credential_factory_t *this,
90 credential_type_t type, int subtype,
91 builder_constructor_t constructor)
92 {
93 entry_t *entry = malloc_thing(entry_t);
94
95 entry->type = type;
96 entry->subtype = subtype;
97 entry->constructor = constructor;
98 this->mutex->lock(this->mutex);
99 this->constructors->insert_last(this->constructors, entry);
100 this->mutex->unlock(this->mutex);
101 }
102
103 /**
104 * Implementation of credential_factory_t.remove_builder.
105 */
106 static void remove_builder(private_credential_factory_t *this,
107 builder_constructor_t constructor)
108 {
109 enumerator_t *enumerator;
110 entry_t *entry;
111
112 this->mutex->lock(this->mutex);
113 enumerator = this->constructors->create_enumerator(this->constructors);
114 while (enumerator->enumerate(enumerator, &entry))
115 {
116 if (entry->constructor == constructor)
117 {
118 this->constructors->remove_at(this->constructors, enumerator);
119 free(entry);
120 }
121 }
122 enumerator->destroy(enumerator);
123 this->mutex->unlock(this->mutex);
124 }
125
126 /**
127 * Implementation of credential_factory_t.create.
128 */
129 static void* create(private_credential_factory_t *this, credential_type_t type,
130 int subtype, ...)
131 {
132 builder_t *builder;
133 builder_part_t part;
134 va_list args;
135
136 builder = create_builder(this, type, subtype);
137 if (builder)
138 {
139 va_start(args, subtype);
140 while (TRUE)
141 {
142 part = va_arg(args, builder_part_t);
143
144 switch (part)
145 {
146 case BUILD_END:
147 break;
148 case BUILD_BLOB_ASN1_DER:
149 builder->add(builder, part, va_arg(args, chunk_t));
150 continue;
151 case BUILD_X509_FLAG:
152 builder->add(builder, part, va_arg(args, x509_flag_t));
153 continue;
154 case BUILD_KEY_SIZE:
155 builder->add(builder, part, va_arg(args, u_int));
156 continue;
157 case BUILD_SIGNING_KEY:
158 case BUILD_PUBLIC_KEY:
159 case BUILD_SUBJECT:
160 case BUILD_SUBJECT_ALTNAME:
161 case BUILD_ISSUER:
162 case BUILD_ISSUER_ALTNAME:
163 case BUILD_SIGNING_CERT:
164 case BUILD_CA_CERT:
165 case BUILD_CERT:
166 builder->add(builder, part, va_arg(args, void*));
167 continue;
168 default:
169 DBG1("builder part %N not supported by factory",
170 builder_part_names, part);
171 break;
172 }
173 break;
174 }
175 va_end(args);
176
177 return builder->build(builder);
178 }
179
180 /** shredder all data on failure */
181 va_start(args, subtype);
182 while (TRUE)
183 {
184 part = va_arg(args, builder_part_t);
185
186 switch (part)
187 {
188 case BUILD_END:
189 break;
190 case BUILD_BLOB_ASN1_DER:
191 {
192 chunk_t chunk = va_arg(args, chunk_t);
193 free(chunk.ptr);
194 continue;
195 }
196 case BUILD_SIGNING_KEY:
197 {
198 private_key_t *private = va_arg(args, private_key_t*);
199 private->destroy(private);
200 continue;
201 }
202 case BUILD_PUBLIC_KEY:
203 {
204 public_key_t *public = va_arg(args, public_key_t*);
205 public->destroy(public);
206 continue;
207 }
208 case BUILD_SUBJECT:
209 case BUILD_SUBJECT_ALTNAME:
210 case BUILD_ISSUER:
211 case BUILD_ISSUER_ALTNAME:
212 {
213 identification_t *id = va_arg(args, identification_t*);
214 id->destroy(id);
215 continue;
216 }
217 case BUILD_SIGNING_CERT:
218 case BUILD_CA_CERT:
219 case BUILD_CERT:
220 {
221 certificate_t *cert = va_arg(args, certificate_t*);
222 cert->destroy(cert);
223 continue;
224 }
225 case BUILD_KEY_SIZE:
226 case BUILD_X509_FLAG:
227 continue;
228 default:
229 DBG1("builder part %N not supported by factory",
230 builder_part_names, part);
231 continue;
232 }
233 break;
234 }
235 va_end(args);
236 return NULL;
237 }
238
239 /**
240 * Implementation of credential_factory_t.destroy
241 */
242 static void destroy(private_credential_factory_t *this)
243 {
244 this->constructors->destroy_function(this->constructors, free);
245 this->mutex->destroy(this->mutex);
246 free(this);
247 }
248
249 /*
250 * see header file
251 */
252 credential_factory_t *credential_factory_create()
253 {
254 private_credential_factory_t *this = malloc_thing(private_credential_factory_t);
255
256 this->public.create = (void*(*)(credential_factory_t*, credential_type_t type, int subtype, ...))create;
257 this->public.create_builder = (builder_t*(*)(credential_factory_t*, credential_type_t type, int subtype))create_builder;
258 this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_constructor_t constructor))add_builder;
259 this->public.remove_builder = (void(*)(credential_factory_t*,builder_constructor_t constructor))remove_builder;
260 this->public.destroy = (void(*)(credential_factory_t*))destroy;
261
262 this->constructors = linked_list_create();
263
264 this->mutex = mutex_create(MUTEX_RECURSIVE);
265
266 return &this->public;
267 }
268