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