correct interface definition
[strongswan.git] / src / libstrongswan / crypto / ca.c
1 /**
2 * @file ca.c
3 *
4 * @brief Implementation of ca_info_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Andreas Steffen
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #include "ca.h"
29
30 #include <library.h>
31 #include <debug.h>
32 #include <utils/linked_list.h>
33 #include <utils/identification.h>
34
35 typedef struct private_ca_info_t private_ca_info_t;
36
37 /**
38 * Private data of a ca_info_t object.
39 */
40 struct private_ca_info_t {
41 /**
42 * Public interface for this ca info record
43 */
44 ca_info_t public;
45
46 /**
47 * Name of the ca info record
48 */
49 char *name;
50
51 /**
52 * Time when ca info record was installed
53 */
54 time_t installed;
55
56 /**
57 * Distinguished Name of the CA
58 */
59 const x509_t *cacert;
60
61 /**
62 * List of crl URIs
63 */
64 linked_list_t *crlURIs;
65
66 /**
67 * List of ocsp URIs
68 */
69 linked_list_t *ocspURIs;
70 };
71
72 /**
73 * Implements ca_info_t.equals
74 */
75 static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
76 {
77 return chunk_equals(this->cacert->get_keyid(this->cacert),
78 that->cacert->get_keyid(that->cacert));
79 }
80
81 /**
82 * Implements ca_info_t.equals_name
83 */
84 static bool equals_name(const private_ca_info_t *this, const char *name)
85 {
86 return this->name != NULL && streq(this->name, name);
87 }
88
89 /**
90 * Find an exact copy of an identification in a linked list
91 */
92 static identification_t* find_identification(linked_list_t *list, identification_t *id)
93 {
94 identification_t *found_id = NULL, *current_id;
95
96 iterator_t *iterator = list->create_iterator(list, TRUE);
97
98 while (iterator->iterate(iterator, (void**)&current_id))
99 {
100 if (id->equals(id, current_id))
101 {
102 found_id = current_id;
103 break;
104 }
105 }
106 iterator->destroy(iterator);
107
108 return found_id;
109 }
110
111 /**
112 * Add a unique identification to a linked list
113 */
114 static identification_t *add_identification(linked_list_t *list, identification_t *id)
115 {
116 identification_t *found_id = find_identification(list, id);
117
118 if (found_id)
119 {
120 id->destroy(id);
121 return found_id;
122 }
123 else
124 {
125 list->insert_last(list, (void*)id);
126 return id;
127 }
128 }
129
130 /**
131 * Implements ca_info_t.add_crluri
132 */
133 static void add_crluri(private_ca_info_t *this, chunk_t uri)
134 {
135 if (uri.len < 6 ||
136 (strncasecmp(uri.ptr, "http", 4) != 0 &&
137 strncasecmp(uri.ptr, "ldap", 4) != 0 &&
138 strncasecmp(uri.ptr, "file", 4) != 0 &&
139 strncasecmp(uri.ptr, "ftp", 3) != 0))
140 {
141 DBG1(" invalid crl uri '%#B'", uri);
142 return;
143 }
144 else
145 {
146 identification_t *crlURI = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
147
148 add_identification(this->crlURIs, crlURI);
149 }
150 }
151
152 /**
153 * Implements ca_info_t.add_ocspuri
154 */
155 static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
156 {
157 if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0)
158 {
159 DBG1(" invalid ocsp uri '%.*s'", uri.len, uri.ptr);
160 return;
161 }
162 else
163 {
164 identification_t *ocspURI = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
165
166 add_identification(this->ocspURIs, ocspURI);
167 }
168 }
169
170 /**
171 * Implements ca_info_t.add_info
172 */
173 void add_info (private_ca_info_t *this, const private_ca_info_t *that)
174 {
175 if (this->name == NULL && that->name != NULL)
176 {
177 this->name = strdup(that->name);
178 }
179 {
180 identification_t *uri;
181
182 iterator_t *iterator = that->crlURIs->create_iterator(that->crlURIs, TRUE);
183
184 while (iterator->iterate(iterator, (void**)&uri))
185 {
186 add_crluri(this, uri->get_encoding(uri));
187 }
188 iterator->destroy(iterator);
189 }
190 {
191 identification_t *uri;
192
193 iterator_t *iterator = that->ocspURIs->create_iterator(that->ocspURIs, TRUE);
194
195 while (iterator->iterate(iterator, (void**)&uri))
196 {
197 add_ocspuri(this, uri->get_encoding(uri));
198 }
199 iterator->destroy(iterator);
200 }
201 }
202
203 /**
204 * Implements ca_info_t.release_info
205 */
206 static void release_info(private_ca_info_t *this)
207 {
208 this->crlURIs->destroy_offset(this->crlURIs,
209 offsetof(identification_t, destroy));
210 this->crlURIs = linked_list_create();
211
212 this->ocspURIs->destroy_offset(this->ocspURIs,
213 offsetof(identification_t, destroy));
214 this->ocspURIs = linked_list_create();
215
216 free(this->name);
217 this->name = NULL;
218 }
219
220 /**
221 * Implements ca_info_t.destroy
222 */
223 static void destroy(private_ca_info_t *this)
224 {
225 this->crlURIs->destroy_offset(this->crlURIs,
226 offsetof(identification_t, destroy));
227 this->ocspURIs->destroy_offset(this->ocspURIs,
228 offsetof(identification_t, destroy));
229 free(this->name);
230 free(this);
231 }
232
233 /**
234 * output handler in printf()
235 */
236 static int print(FILE *stream, const struct printf_info *info,
237 const void *const *args)
238 {
239 private_ca_info_t *this = *((private_ca_info_t**)(args[0]));
240 bool utc = TRUE;
241 int written = 0;
242 const x509_t *cacert;
243 chunk_t keyid;
244
245 if (info->alt)
246 {
247 utc = *((bool*)args[1]);
248 }
249 if (this == NULL)
250 {
251 return fprintf(stream, "(null)");
252 }
253 written += fprintf(stream, "%#T", &this->installed, utc);
254
255 if (this->name)
256 {
257 written += fprintf(stream, ", \"%s\"\n", this->name);
258 }
259 else
260 {
261 written += fprintf(stream, "\n");
262 }
263
264 cacert = this->cacert;
265 written += fprintf(stream, " authname: '%D'\n", cacert->get_subject(cacert));
266
267 {
268 chunk_t keyid = cacert->get_keyid(cacert);
269
270 written += fprintf(stream, " keyid: %#B\n", &keyid);
271 }
272 {
273 identification_t *crlURI;
274 iterator_t *iterator = this->crlURIs->create_iterator(this->crlURIs, TRUE);
275 bool first = TRUE;
276
277 while (iterator->iterate(iterator, (void**)&crlURI))
278 {
279 written += fprintf(stream, " %s '%D'\n",
280 first? "crluris:":" ", crlURI);
281 first = FALSE;
282 }
283 iterator->destroy(iterator);
284 }
285 {
286 identification_t *ocspURI;
287 iterator_t *iterator = this->ocspURIs->create_iterator(this->ocspURIs, TRUE);
288 bool first = TRUE;
289
290 while (iterator->iterate(iterator, (void**)&ocspURI))
291 {
292 written += fprintf(stream, " %s '%D'\n",
293 first? "ocspuris:":" ", ocspURI);
294 first = FALSE;
295 }
296 iterator->destroy(iterator);
297 }
298 return written;
299 }
300
301 /**
302 * register printf() handlers
303 */
304 static void __attribute__ ((constructor))print_register()
305 {
306 register_printf_function(PRINTF_CAINFO, print, arginfo_ptr_alt_ptr_int);
307 }
308
309 /*
310 * Described in header.
311 */
312 ca_info_t *ca_info_create(const char *name, const x509_t *cacert)
313 {
314 private_ca_info_t *this = malloc_thing(private_ca_info_t);
315
316 /* initialize */
317 this->installed = time(NULL);
318 this->name = (name == NULL)? NULL:strdup(name);
319 this->cacert = cacert;
320 this->crlURIs = linked_list_create();
321 this->ocspURIs = linked_list_create();
322
323 /* public functions */
324 this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals;
325 this->public.equals_name = (bool (*) (const ca_info_t*,const char*))equals_name;
326 this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
327 this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri;
328 this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri;
329 this->public.release_info = (void (*) (ca_info_t*))release_info;
330 this->public.destroy = (void (*) (ca_info_t*))destroy;
331
332 return &this->public;
333 }