fixed the cleanup code when the credential factory fails to create a builder
[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 ENUM(credential_type_names, CRED_PRIVATE_KEY, CRED_CERTIFICATE,
26 "CRED_PRIVATE_KEY",
27 "CRED_PUBLIC_KEY",
28 "CRED_CERTIFICATE",
29 );
30
31 typedef struct private_credential_factory_t private_credential_factory_t;
32
33 /**
34 * private data of credential_factory
35 */
36 struct private_credential_factory_t {
37
38 /**
39 * public functions
40 */
41 credential_factory_t public;
42
43 /**
44 * list with entry_t
45 */
46 linked_list_t *constructors;
47
48 /**
49 * mutex to lock access to modules
50 */
51 mutex_t *mutex;
52 };
53
54 typedef struct entry_t entry_t;
55 struct entry_t {
56 /** kind of credential builder */
57 credential_type_t type;
58 /** subtype of credential, e.g. certificate_type_t */
59 int subtype;
60 /** builder construction function */
61 builder_constructor_t constructor;
62 };
63
64 /**
65 * Implementation of credential_factory_t.create_builder.
66 */
67 static builder_t* create_builder(private_credential_factory_t *this,
68 credential_type_t type, int subtype)
69 {
70 enumerator_t *enumerator;
71 entry_t *entry;
72 builder_t *builder = NULL;
73
74 this->mutex->lock(this->mutex);
75 enumerator = this->constructors->create_enumerator(this->constructors);
76 while (enumerator->enumerate(enumerator, &entry))
77 {
78 if (entry->type == type && entry->subtype == subtype)
79 {
80 builder = entry->constructor(subtype);
81 if (builder)
82 {
83 break;
84 }
85 }
86 }
87 enumerator->destroy(enumerator);
88 this->mutex->unlock(this->mutex);
89 return builder;
90 }
91
92 /**
93 * Implementation of credential_factory_t.add_builder_constructor.
94 */
95 static void add_builder(private_credential_factory_t *this,
96 credential_type_t type, int subtype,
97 builder_constructor_t constructor)
98 {
99 entry_t *entry = malloc_thing(entry_t);
100
101 entry->type = type;
102 entry->subtype = subtype;
103 entry->constructor = constructor;
104 this->mutex->lock(this->mutex);
105 this->constructors->insert_last(this->constructors, entry);
106 this->mutex->unlock(this->mutex);
107 }
108
109 /**
110 * Implementation of credential_factory_t.remove_builder.
111 */
112 static void remove_builder(private_credential_factory_t *this,
113 builder_constructor_t constructor)
114 {
115 enumerator_t *enumerator;
116 entry_t *entry;
117
118 this->mutex->lock(this->mutex);
119 enumerator = this->constructors->create_enumerator(this->constructors);
120 while (enumerator->enumerate(enumerator, &entry))
121 {
122 if (entry->constructor == constructor)
123 {
124 this->constructors->remove_at(this->constructors, enumerator);
125 free(entry);
126 }
127 }
128 enumerator->destroy(enumerator);
129 this->mutex->unlock(this->mutex);
130 }
131
132 /**
133 * Implementation of credential_factory_t.create.
134 */
135 static void* create(private_credential_factory_t *this, credential_type_t type,
136 int subtype, ...)
137 {
138 builder_t *builder;
139 builder_part_t part;
140 va_list args;
141
142 builder = create_builder(this, type, subtype);
143 if (builder)
144 {
145 va_start(args, subtype);
146 while (TRUE)
147 {
148 part = va_arg(args, builder_part_t);
149
150 switch (part)
151 {
152 case BUILD_END:
153 break;
154 case BUILD_BLOB_ASN1_DER:
155 case BUILD_SERIAL:
156 builder->add(builder, part, va_arg(args, chunk_t));
157 continue;
158 case BUILD_X509_FLAG:
159 builder->add(builder, part, va_arg(args, x509_flag_t));
160 continue;
161 case BUILD_KEY_SIZE:
162 builder->add(builder, part, va_arg(args, u_int));
163 continue;
164 case BUILD_NOT_BEFORE_TIME:
165 case BUILD_NOT_AFTER_TIME:
166 builder->add(builder, part, va_arg(args, time_t));
167 continue;
168 case BUILD_FROM_FILE:
169 case BUILD_SIGNING_KEY:
170 case BUILD_PUBLIC_KEY:
171 case BUILD_SUBJECT:
172 case BUILD_SUBJECT_ALTNAME:
173 case BUILD_ISSUER:
174 case BUILD_ISSUER_ALTNAME:
175 case BUILD_SIGNING_CERT:
176 case BUILD_CA_CERT:
177 case BUILD_CERT:
178 case BUILD_IETF_GROUP_ATTR:
179 builder->add(builder, part, va_arg(args, void*));
180 continue;
181 default:
182 DBG1("builder part %N not supported by factory",
183 builder_part_names, part);
184 break;
185 }
186 break;
187 }
188 va_end(args);
189
190 return builder->build(builder);
191 }
192 else
193 {
194 DBG1("failed to create a builder for credential type %N,"
195 " subtype (%d)", credential_type_names, type, subtype);
196 }
197
198 /** shredder all data on failure */
199 va_start(args, subtype);
200 while (TRUE)
201 {
202 part = va_arg(args, builder_part_t);
203
204 switch (part)
205 {
206 case BUILD_END:
207 break;
208 case BUILD_BLOB_ASN1_DER:
209 {
210 chunk_t chunk = va_arg(args, chunk_t);
211 free(chunk.ptr);
212 continue;
213 }
214 case BUILD_SERIAL:
215 {
216 va_arg(args, chunk_t);
217 continue;
218 }
219 case BUILD_X509_FLAG:
220 {
221 va_arg(args, x509_flag_t);
222 continue;
223 }
224 case BUILD_KEY_SIZE:
225 {
226 va_arg(args, u_int);
227 continue;
228 }
229 case BUILD_NOT_BEFORE_TIME:
230 case BUILD_NOT_AFTER_TIME:
231 {
232 va_arg(args, time_t);
233 continue;
234 }
235 case BUILD_SIGNING_KEY:
236 {
237 private_key_t *private = va_arg(args, private_key_t*);
238 private->destroy(private);
239 continue;
240 }
241 case BUILD_PUBLIC_KEY:
242 {
243 public_key_t *public = va_arg(args, public_key_t*);
244 public->destroy(public);
245 continue;
246 }
247 case BUILD_SUBJECT:
248 case BUILD_SUBJECT_ALTNAME:
249 case BUILD_ISSUER:
250 case BUILD_ISSUER_ALTNAME:
251 {
252 identification_t *id = va_arg(args, identification_t*);
253 id->destroy(id);
254 continue;
255 }
256 case BUILD_SIGNING_CERT:
257 case BUILD_CA_CERT:
258 case BUILD_CERT:
259 {
260 certificate_t *cert = va_arg(args, certificate_t*);
261 cert->destroy(cert);
262 continue;
263 }
264 case BUILD_FROM_FILE:
265 case BUILD_IETF_GROUP_ATTR:
266 {
267 va_arg(args, void*);
268 continue;
269 }
270 default:
271 DBG1("builder part %N not supported by factory",
272 builder_part_names, part);
273 continue;
274 }
275 break;
276 }
277 va_end(args);
278 return NULL;
279 }
280
281 /**
282 * Implementation of credential_factory_t.destroy
283 */
284 static void destroy(private_credential_factory_t *this)
285 {
286 this->constructors->destroy_function(this->constructors, free);
287 this->mutex->destroy(this->mutex);
288 free(this);
289 }
290
291 /*
292 * see header file
293 */
294 credential_factory_t *credential_factory_create()
295 {
296 private_credential_factory_t *this = malloc_thing(private_credential_factory_t);
297
298 this->public.create = (void*(*)(credential_factory_t*, credential_type_t type, int subtype, ...))create;
299 this->public.create_builder = (builder_t*(*)(credential_factory_t*, credential_type_t type, int subtype))create_builder;
300 this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_constructor_t constructor))add_builder;
301 this->public.remove_builder = (void(*)(credential_factory_t*,builder_constructor_t constructor))remove_builder;
302 this->public.destroy = (void(*)(credential_factory_t*))destroy;
303
304 this->constructors = linked_list_create();
305
306 this->mutex = mutex_create(MUTEX_RECURSIVE);
307
308 return &this->public;
309 }
310