30a270ee115e6ecd46bcfd63c97ab6ccccc67510
[strongswan.git] / src / charon / plugins / stroke / stroke_ca.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 "stroke_ca.h"
19 #include "stroke_cred.h"
20
21 #include <utils/mutex.h>
22 #include <utils/linked_list.h>
23
24 #include <daemon.h>
25
26 typedef struct private_stroke_ca_t private_stroke_ca_t;
27
28 /**
29 * private data of stroke_ca
30 */
31 struct private_stroke_ca_t {
32
33 /**
34 * public functions
35 */
36 stroke_ca_t public;
37
38 /**
39 * mutex to lock access to list
40 */
41 mutex_t *mutex;
42
43 /**
44 * list of starters CA sections and its certificates (ca_section_t)
45 */
46 linked_list_t *sections;
47
48 /**
49 * stroke credentials, stores our CA certificates
50 */
51 stroke_cred_t *cred;
52 };
53
54 typedef struct ca_section_t ca_section_t;
55
56 /**
57 * loaded ipsec.conf CA sections
58 */
59 struct ca_section_t {
60
61 /**
62 * name of the CA section
63 */
64 char *name;
65
66 /**
67 * reference to cert in trusted_credential_t
68 */
69 certificate_t *cert;
70
71 /**
72 * CRL URIs
73 */
74 linked_list_t *crl;
75
76 /**
77 * OCSP URIs
78 */
79 linked_list_t *ocsp;
80 };
81
82 /**
83 * create a new CA section
84 */
85 static ca_section_t *ca_section_create(char *name, certificate_t *cert)
86 {
87 ca_section_t *ca = malloc_thing(ca_section_t);
88
89 ca->name = strdup(name);
90 ca->crl = linked_list_create();
91 ca->ocsp = linked_list_create();
92 ca->cert = cert;
93 return ca;
94 }
95
96 /**
97 * destroy a ca section entry
98 */
99 static void ca_section_destroy(ca_section_t *this)
100 {
101 this->crl->destroy_function(this->crl, free);
102 this->ocsp->destroy_function(this->ocsp, free);
103 free(this->name);
104 free(this);
105 }
106
107 /**
108 * data to pass to create_inner_cdp
109 */
110 typedef struct {
111 private_stroke_ca_t *this;
112 certificate_type_t type;
113 identification_t *id;
114 } cdp_data_t;
115
116 /**
117 * destroy cdp enumerator data and unlock list
118 */
119 static void cdp_data_destroy(cdp_data_t *data)
120 {
121 data->this->mutex->unlock(data->this->mutex);
122 free(data);
123 }
124
125 /**
126 * inner enumerator constructor for CDP URIs
127 */
128 static enumerator_t *create_inner_cdp(ca_section_t *section, cdp_data_t *data)
129 {
130 public_key_t *public;
131 identification_t *keyid;
132 enumerator_t *enumerator = NULL;
133 linked_list_t *list;
134
135 if (data->type == CERT_X509_OCSP_RESPONSE)
136 {
137 list = section->ocsp;
138 }
139 else
140 {
141 list = section->crl;
142 }
143
144 public = section->cert->get_public_key(section->cert);
145 if (public)
146 {
147 if (!data->id)
148 {
149 enumerator = list->create_enumerator(list);
150 }
151 else
152 {
153 keyid = public->get_id(public, data->id->get_type(data->id));
154 if (keyid && keyid->matches(keyid, data->id))
155 {
156 enumerator = list->create_enumerator(list);
157 }
158 }
159 public->destroy(public);
160 }
161 return enumerator;
162 }
163
164 /**
165 * Implementation of credential_set_t.create_cdp_enumerator.
166 */
167 static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this,
168 certificate_type_t type, identification_t *id)
169 {
170 cdp_data_t *data;
171
172 switch (type)
173 { /* we serve CRLs and OCSP responders */
174 case CERT_X509_CRL:
175 case CERT_X509_OCSP_RESPONSE:
176 case CERT_ANY:
177 break;
178 default:
179 return NULL;
180 }
181 data = malloc_thing(cdp_data_t);
182 data->this = this;
183 data->type = type;
184 data->id = id;
185
186 this->mutex->lock(this->mutex);
187 return enumerator_create_nested(this->sections->create_enumerator(this->sections),
188 (void*)create_inner_cdp, data,
189 (void*)cdp_data_destroy);
190 }
191 /**
192 * Implementation of stroke_ca_t.add.
193 */
194 static void add(private_stroke_ca_t *this, stroke_msg_t *msg)
195 {
196 certificate_t *cert;
197 ca_section_t *ca;
198
199 if (msg->add_ca.cacert == NULL)
200 {
201 DBG1(DBG_CFG, "missing cacert parameter");
202 return;
203 }
204 cert = this->cred->load_ca(this->cred, msg->add_ca.cacert);
205 if (cert)
206 {
207 ca = ca_section_create(msg->add_ca.name, cert);
208 if (msg->add_ca.crluri)
209 {
210 ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri));
211 }
212 if (msg->add_ca.crluri2)
213 {
214 ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri2));
215 }
216 if (msg->add_ca.ocspuri)
217 {
218 ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri));
219 }
220 if (msg->add_ca.ocspuri2)
221 {
222 ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri2));
223 }
224 this->mutex->lock(this->mutex);
225 this->sections->insert_last(this->sections, ca);
226 this->mutex->unlock(this->mutex);
227 DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
228 }
229 }
230
231 /**
232 * Implementation of stroke_ca_t.del.
233 */
234 static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
235 {
236 enumerator_t *enumerator;
237 ca_section_t *ca = NULL;
238
239 this->mutex->lock(this->mutex);
240 enumerator = this->sections->create_enumerator(this->sections);
241 while (enumerator->enumerate(enumerator, &ca))
242 {
243 if (streq(ca->name, msg->del_ca.name))
244 {
245 this->sections->remove_at(this->sections, enumerator);
246 break;
247 }
248 ca = NULL;
249 }
250 enumerator->destroy(enumerator);
251 this->mutex->unlock(this->mutex);
252 if (ca == NULL)
253 {
254 DBG1(DBG_CFG, "no ca named '%s' found\n", msg->del_ca.name);
255 return;
256 }
257 ca_section_destroy(ca);
258 /* TODO: flush cached certs */
259 }
260
261 /**
262 * list crl or ocsp URIs
263 */
264 static void list_uris(linked_list_t *list, char *label, FILE *out)
265 {
266 bool first = TRUE;
267 char *uri;
268 enumerator_t *enumerator;
269
270 enumerator = list->create_enumerator(list);
271 while (enumerator->enumerate(enumerator, (void**)&uri))
272 {
273 if (first)
274 {
275 fprintf(out, label);
276 first = FALSE;
277 }
278 else
279 {
280 fprintf(out, " ");
281 }
282 fprintf(out, "'%s'\n", uri);
283 }
284 enumerator->destroy(enumerator);
285 }
286
287 /**
288 * Implementation of stroke_ca_t.list.
289 */
290 static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
291 {
292 bool first = TRUE;
293 ca_section_t *section;
294 enumerator_t *enumerator;
295
296 this->mutex->lock(this->mutex);
297 enumerator = this->sections->create_enumerator(this->sections);
298 while (enumerator->enumerate(enumerator, (void**)&section))
299 {
300 certificate_t *cert = section->cert;
301 public_key_t *public = cert->get_public_key(cert);
302
303 if (first)
304 {
305 fprintf(out, "\n");
306 fprintf(out, "List of CA Information Sections:\n");
307 first = FALSE;
308 }
309 fprintf(out, "\n");
310 fprintf(out, " authname: \"%D\"\n", cert->get_subject(cert));
311
312 /* list authkey and keyid */
313 if (public)
314 {
315 fprintf(out, " authkey: %D\n",
316 public->get_id(public, ID_PUBKEY_SHA1));
317 fprintf(out, " keyid: %D\n",
318 public->get_id(public, ID_PUBKEY_INFO_SHA1));
319 public->destroy(public);
320 }
321 list_uris(section->crl, " crluris: ", out);
322 list_uris(section->ocsp, " ocspuris: ", out);
323 }
324 enumerator->destroy(enumerator);
325 this->mutex->unlock(this->mutex);
326 }
327
328 /**
329 * Implementation of stroke_ca_t.destroy
330 */
331 static void destroy(private_stroke_ca_t *this)
332 {
333 this->sections->destroy_function(this->sections, (void*)ca_section_destroy);
334 this->mutex->destroy(this->mutex);
335 free(this);
336 }
337
338 /*
339 * see header file
340 */
341 stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
342 {
343 private_stroke_ca_t *this = malloc_thing(private_stroke_ca_t);
344
345 this->public.set.create_private_enumerator = (void*)return_null;
346 this->public.set.create_cert_enumerator = (void*)return_null;
347 this->public.set.create_shared_enumerator = (void*)return_null;
348 this->public.set.create_cdp_enumerator = (void*)create_cdp_enumerator;
349 this->public.set.cache_cert = (void*)nop;
350 this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add;
351 this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del;
352 this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list;
353 this->public.destroy = (void(*)(stroke_ca_t*))destroy;
354
355 this->sections = linked_list_create();
356 this->mutex = mutex_create(MUTEX_RECURSIVE);
357 this->cred = cred;
358
359 return &this->public;
360 }
361