2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
18 #include "stroke_ca.h"
19 #include "stroke_cred.h"
21 #include <utils/mutex.h>
22 #include <utils/linked_list.h>
26 typedef struct private_stroke_ca_t private_stroke_ca_t
;
29 * private data of stroke_ca
31 struct private_stroke_ca_t
{
39 * mutex to lock access to list
44 * list of starters CA sections and its certificates (ca_section_t)
46 linked_list_t
*sections
;
49 * stroke credentials, stores our CA certificates
54 typedef struct ca_section_t ca_section_t
;
57 * loaded ipsec.conf CA sections
62 * name of the CA section
67 * reference to cert in trusted_credential_t
83 * create a new CA section
85 static ca_section_t
*ca_section_create(char *name
, certificate_t
*cert
)
87 ca_section_t
*ca
= malloc_thing(ca_section_t
);
89 ca
->name
= strdup(name
);
90 ca
->crl
= linked_list_create();
91 ca
->ocsp
= linked_list_create();
97 * destroy a ca section entry
99 static void ca_section_destroy(ca_section_t
*this)
101 this->crl
->destroy_function(this->crl
, free
);
102 this->ocsp
->destroy_function(this->ocsp
, free
);
108 * data to pass to create_inner_cdp
111 private_stroke_ca_t
*this;
112 certificate_type_t type
;
113 identification_t
*id
;
117 * destroy cdp enumerator data and unlock list
119 static void cdp_data_destroy(cdp_data_t
*data
)
121 data
->this->mutex
->unlock(data
->this->mutex
);
126 * inner enumerator constructor for CDP URIs
128 static enumerator_t
*create_inner_cdp(ca_section_t
*section
, cdp_data_t
*data
)
130 public_key_t
*public;
131 identification_t
*keyid
;
132 enumerator_t
*enumerator
= NULL
;
135 if (data
->type
== CERT_X509_OCSP_RESPONSE
)
137 list
= section
->ocsp
;
144 public = section
->cert
->get_public_key(section
->cert
);
149 enumerator
= list
->create_enumerator(list
);
153 keyid
= public->get_id(public, data
->id
->get_type(data
->id
));
154 if (keyid
&& keyid
->matches(keyid
, data
->id
))
156 enumerator
= list
->create_enumerator(list
);
159 public->destroy(public);
165 * Implementation of credential_set_t.create_cdp_enumerator.
167 static enumerator_t
*create_cdp_enumerator(private_stroke_ca_t
*this,
168 certificate_type_t type
, identification_t
*id
)
173 { /* we serve CRLs and OCSP responders */
175 case CERT_X509_OCSP_RESPONSE
:
181 data
= malloc_thing(cdp_data_t
);
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
);
192 * Implementation of stroke_ca_t.add.
194 static void add(private_stroke_ca_t
*this, stroke_msg_t
*msg
)
199 if (msg
->add_ca
.cacert
== NULL
)
201 DBG1(DBG_CFG
, "missing cacert parameter");
204 cert
= this->cred
->load_ca(this->cred
, msg
->add_ca
.cacert
);
207 ca
= ca_section_create(msg
->add_ca
.name
, cert
);
208 if (msg
->add_ca
.crluri
)
210 ca
->crl
->insert_last(ca
->crl
, strdup(msg
->add_ca
.crluri
));
212 if (msg
->add_ca
.crluri2
)
214 ca
->crl
->insert_last(ca
->crl
, strdup(msg
->add_ca
.crluri2
));
216 if (msg
->add_ca
.ocspuri
)
218 ca
->ocsp
->insert_last(ca
->ocsp
, strdup(msg
->add_ca
.ocspuri
));
220 if (msg
->add_ca
.ocspuri2
)
222 ca
->ocsp
->insert_last(ca
->ocsp
, strdup(msg
->add_ca
.ocspuri2
));
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
);
232 * Implementation of stroke_ca_t.del.
234 static void del(private_stroke_ca_t
*this, stroke_msg_t
*msg
)
236 enumerator_t
*enumerator
;
237 ca_section_t
*ca
= NULL
;
239 this->mutex
->lock(this->mutex
);
240 enumerator
= this->sections
->create_enumerator(this->sections
);
241 while (enumerator
->enumerate(enumerator
, &ca
))
243 if (streq(ca
->name
, msg
->del_ca
.name
))
245 this->sections
->remove_at(this->sections
, enumerator
);
250 enumerator
->destroy(enumerator
);
251 this->mutex
->unlock(this->mutex
);
254 DBG1(DBG_CFG
, "no ca named '%s' found\n", msg
->del_ca
.name
);
257 ca_section_destroy(ca
);
258 /* TODO: flush cached certs */
262 * list crl or ocsp URIs
264 static void list_uris(linked_list_t
*list
, char *label
, FILE *out
)
268 enumerator_t
*enumerator
;
270 enumerator
= list
->create_enumerator(list
);
271 while (enumerator
->enumerate(enumerator
, (void**)&uri
))
282 fprintf(out
, "'%s'\n", uri
);
284 enumerator
->destroy(enumerator
);
288 * Implementation of stroke_ca_t.list.
290 static void list(private_stroke_ca_t
*this, stroke_msg_t
*msg
, FILE *out
)
293 ca_section_t
*section
;
294 enumerator_t
*enumerator
;
296 this->mutex
->lock(this->mutex
);
297 enumerator
= this->sections
->create_enumerator(this->sections
);
298 while (enumerator
->enumerate(enumerator
, (void**)§ion
))
300 certificate_t
*cert
= section
->cert
;
301 public_key_t
*public = cert
->get_public_key(cert
);
306 fprintf(out
, "List of CA Information Sections:\n");
310 fprintf(out
, " authname: %D\n", cert
->get_subject(cert
));
312 /* list authkey and keyid */
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);
321 list_uris(section
->crl
, " crluris: ", out
);
322 list_uris(section
->ocsp
, " ocspuris: ", out
);
324 enumerator
->destroy(enumerator
);
325 this->mutex
->unlock(this->mutex
);
329 * Implementation of stroke_ca_t.destroy
331 static void destroy(private_stroke_ca_t
*this)
333 this->sections
->destroy_function(this->sections
, (void*)ca_section_destroy
);
334 this->mutex
->destroy(this->mutex
);
341 stroke_ca_t
*stroke_ca_create(stroke_cred_t
*cred
)
343 private_stroke_ca_t
*this = malloc_thing(private_stroke_ca_t
);
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.add
= (void(*)(stroke_ca_t
*, stroke_msg_t
*msg
))add
;
350 this->public.del
= (void(*)(stroke_ca_t
*, stroke_msg_t
*msg
))del
;
351 this->public.list
= (void(*)(stroke_ca_t
*, stroke_msg_t
*msg
, FILE *out
))list
;
352 this->public.destroy
= (void(*)(stroke_ca_t
*))destroy
;
354 this->sections
= linked_list_create();
355 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
358 return &this->public;