/src/strongswan/src/libstrongswan/credentials/credential_factory.c
Line | Count | Source (jump to first uncovered line) |
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 | 98.4k | { |
81 | 98.4k | entry_t *entry = malloc_thing(entry_t); |
82 | | |
83 | 98.4k | entry->type = type; |
84 | 98.4k | entry->subtype = subtype; |
85 | 98.4k | entry->final = final; |
86 | 98.4k | entry->plugin_name = plugin_name; |
87 | 98.4k | entry->constructor = constructor; |
88 | 98.4k | this->lock->write_lock(this->lock); |
89 | 98.4k | this->constructors->insert_last(this->constructors, entry); |
90 | 98.4k | this->lock->unlock(this->lock); |
91 | 98.4k | } |
92 | | |
93 | | METHOD(credential_factory_t, remove_builder, void, |
94 | | private_credential_factory_t *this, builder_function_t constructor) |
95 | 98.4k | { |
96 | 98.4k | enumerator_t *enumerator; |
97 | 98.4k | entry_t *entry; |
98 | | |
99 | 98.4k | this->lock->write_lock(this->lock); |
100 | 98.4k | enumerator = this->constructors->create_enumerator(this->constructors); |
101 | 1.41M | while (enumerator->enumerate(enumerator, &entry)) |
102 | 1.31M | { |
103 | 1.31M | if (entry->constructor == constructor) |
104 | 98.4k | { |
105 | 98.4k | this->constructors->remove_at(this->constructors, enumerator); |
106 | 98.4k | free(entry); |
107 | 98.4k | } |
108 | 1.31M | } |
109 | 98.4k | enumerator->destroy(enumerator); |
110 | 98.4k | this->lock->unlock(this->lock); |
111 | 98.4k | } |
112 | | |
113 | | METHOD(credential_factory_t, create, void*, |
114 | | private_credential_factory_t *this, credential_type_t type, int subtype, ...) |
115 | 21.5k | { |
116 | 21.5k | enumerator_t *enumerator; |
117 | 21.5k | entry_t *entry; |
118 | 21.5k | va_list args; |
119 | 21.5k | void *construct = NULL; |
120 | 21.5k | int failures = 0; |
121 | 21.5k | uintptr_t level; |
122 | 21.5k | enum_name_t *names DBG_UNUSED; |
123 | | |
124 | 21.5k | switch (type) |
125 | 21.5k | { |
126 | 19.3k | case CRED_CERTIFICATE: |
127 | 19.3k | names = certificate_type_names; |
128 | 19.3k | break; |
129 | 0 | case CRED_CONTAINER: |
130 | 0 | names = container_type_names; |
131 | 0 | break; |
132 | 0 | case CRED_PRIVATE_KEY: |
133 | 2.16k | case CRED_PUBLIC_KEY: |
134 | 2.16k | default: |
135 | 2.16k | names = key_type_names; |
136 | 2.16k | break; |
137 | 21.5k | } |
138 | | |
139 | 21.5k | level = (uintptr_t)this->recursive->get(this->recursive); |
140 | 21.5k | this->recursive->set(this->recursive, (void*)level + 1); |
141 | | |
142 | 21.5k | this->lock->read_lock(this->lock); |
143 | 21.5k | enumerator = this->constructors->create_enumerator(this->constructors); |
144 | 554k | while (enumerator->enumerate(enumerator, &entry)) |
145 | 536k | { |
146 | 536k | if (entry->type == type && entry->subtype == subtype) |
147 | 60.2k | { |
148 | 60.2k | DBG2(DBG_LIB, "builder L%d %N - %N of plugin '%s'", |
149 | 60.2k | (int)level, credential_type_names, type, names, subtype, |
150 | 60.2k | entry->plugin_name); |
151 | 60.2k | va_start(args, subtype); |
152 | 60.2k | construct = entry->constructor(subtype, args); |
153 | 60.2k | va_end(args); |
154 | 60.2k | if (construct) |
155 | 3.20k | { |
156 | 3.20k | break; |
157 | 3.20k | } |
158 | 57.0k | failures++; |
159 | 57.0k | } |
160 | 536k | } |
161 | 21.5k | enumerator->destroy(enumerator); |
162 | 21.5k | this->lock->unlock(this->lock); |
163 | | |
164 | 21.5k | if (!construct && !level) |
165 | 3.18k | { |
166 | 3.18k | DBG1(DBG_LIB, "building %N - %N failed, tried %d builders", |
167 | 3.18k | credential_type_names, type, names, subtype, failures); |
168 | 3.18k | } |
169 | 21.5k | this->recursive->set(this->recursive, (void*)level); |
170 | 21.5k | return construct; |
171 | 21.5k | } |
172 | | |
173 | | CALLBACK(builder_filter, bool, |
174 | | void *null, enumerator_t *orig, va_list args) |
175 | 0 | { |
176 | 0 | entry_t *entry; |
177 | 0 | credential_type_t *type; |
178 | 0 | int *subtype; |
179 | |
|
180 | 0 | VA_ARGS_VGET(args, type, subtype); |
181 | |
|
182 | 0 | while (orig->enumerate(orig, &entry)) |
183 | 0 | { |
184 | 0 | if (entry->final) |
185 | 0 | { |
186 | 0 | *type = entry->type; |
187 | 0 | *subtype = entry->subtype; |
188 | 0 | return TRUE; |
189 | 0 | } |
190 | 0 | } |
191 | 0 | return FALSE; |
192 | 0 | } |
193 | | |
194 | | METHOD(credential_factory_t, create_builder_enumerator, enumerator_t*, |
195 | | private_credential_factory_t *this) |
196 | 0 | { |
197 | 0 | this->lock->read_lock(this->lock); |
198 | 0 | return enumerator_create_filter( |
199 | 0 | this->constructors->create_enumerator(this->constructors), |
200 | 0 | builder_filter, this->lock, (void*)this->lock->unlock); |
201 | 0 | } |
202 | | |
203 | | METHOD(credential_factory_t, destroy, void, |
204 | | private_credential_factory_t *this) |
205 | 3.51k | { |
206 | 3.51k | this->constructors->destroy_function(this->constructors, free); |
207 | 3.51k | this->recursive->destroy(this->recursive); |
208 | 3.51k | this->lock->destroy(this->lock); |
209 | 3.51k | free(this); |
210 | 3.51k | } |
211 | | |
212 | | /* |
213 | | * see header file |
214 | | */ |
215 | | credential_factory_t *credential_factory_create() |
216 | 3.51k | { |
217 | 3.51k | private_credential_factory_t *this; |
218 | | |
219 | 3.51k | INIT(this, |
220 | 3.51k | .public = { |
221 | 3.51k | .create = _create, |
222 | 3.51k | .create_builder_enumerator = _create_builder_enumerator, |
223 | 3.51k | .add_builder = _add_builder, |
224 | 3.51k | .remove_builder = _remove_builder, |
225 | 3.51k | .destroy = _destroy, |
226 | 3.51k | }, |
227 | 3.51k | .constructors = linked_list_create(), |
228 | 3.51k | .recursive = thread_value_create(NULL), |
229 | 3.51k | .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), |
230 | 3.51k | ); |
231 | | |
232 | 3.51k | return &this->public; |
233 | 3.51k | } |
234 | | |