added certinfos linked list
[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 #include "certinfo.h"
30
31 #include <library.h>
32 #include <debug.h>
33 #include <utils/linked_list.h>
34 #include <utils/identification.h>
35
36 typedef struct private_ca_info_t private_ca_info_t;
37
38 /**
39 * Private data of a ca_info_t object.
40 */
41 struct private_ca_info_t {
42 /**
43 * Public interface for this ca info record
44 */
45 ca_info_t public;
46
47 /**
48 * Name of the ca info record
49 */
50 char *name;
51
52 /**
53 * Time when ca info record was installed
54 */
55 time_t installed;
56
57 /**
58 * Distinguished Name of the CA
59 */
60 const x509_t *cacert;
61
62 /**
63 * List of crl URIs
64 */
65 linked_list_t *crluris;
66
67 /**
68 * List of ocsp URIs
69 */
70 linked_list_t *ocspuris;
71
72 /**
73 * List of certificate info records
74 */
75 linked_list_t *certinfos;
76 };
77
78 /**
79 * Implements ca_info_t.equals
80 */
81 static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
82 {
83 return chunk_equals(this->cacert->get_keyid(this->cacert),
84 that->cacert->get_keyid(that->cacert));
85 }
86
87 /**
88 * Implements ca_info_t.equals_name
89 */
90 static bool equals_name(const private_ca_info_t *this, const char *name)
91 {
92 return this->name != NULL && streq(this->name, name);
93 }
94
95 /**
96 * Find an exact copy of an identification in a linked list
97 */
98 static identification_t* find_identification(linked_list_t *list, identification_t *id)
99 {
100 identification_t *found_id = NULL, *current_id;
101
102 iterator_t *iterator = list->create_iterator(list, TRUE);
103
104 while (iterator->iterate(iterator, (void**)&current_id))
105 {
106 if (id->equals(id, current_id))
107 {
108 found_id = current_id;
109 break;
110 }
111 }
112 iterator->destroy(iterator);
113
114 return found_id;
115 }
116
117 /**
118 * Add a unique identification to a linked list
119 */
120 static identification_t *add_identification(linked_list_t *list, identification_t *id)
121 {
122 identification_t *found_id = find_identification(list, id);
123
124 if (found_id)
125 {
126 id->destroy(id);
127 return found_id;
128 }
129 else
130 {
131 list->insert_last(list, (void*)id);
132 return id;
133 }
134 }
135
136 /**
137 * Implements ca_info_t.add_crluri
138 */
139 static void add_crluri(private_ca_info_t *this, chunk_t uri)
140 {
141 if (uri.len < 6 ||
142 (strncasecmp(uri.ptr, "http", 4) != 0 &&
143 strncasecmp(uri.ptr, "ldap", 4) != 0 &&
144 strncasecmp(uri.ptr, "file", 4) != 0 &&
145 strncasecmp(uri.ptr, "ftp", 3) != 0))
146 {
147 DBG1(" invalid crl uri '%#B'", uri);
148 return;
149 }
150 else
151 {
152 identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
153
154 add_identification(this->crluris, crluri);
155 }
156 }
157
158 /**
159 * Implements ca_info_t.add_ocspuri
160 */
161 static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
162 {
163 if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0)
164 {
165 DBG1(" invalid ocsp uri '%.*s'", uri.len, uri.ptr);
166 return;
167 }
168 else
169 {
170 identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
171
172 add_identification(this->ocspuris, ocspuri);
173 }
174 }
175
176 /**
177 * Implements ca_info_t.add_info
178 */
179 void add_info (private_ca_info_t *this, const private_ca_info_t *that)
180 {
181 if (this->name == NULL && that->name != NULL)
182 {
183 this->name = strdup(that->name);
184 }
185 {
186 identification_t *uri;
187
188 iterator_t *iterator = that->crluris->create_iterator(that->crluris, TRUE);
189
190 while (iterator->iterate(iterator, (void**)&uri))
191 {
192 add_crluri(this, uri->get_encoding(uri));
193 }
194 iterator->destroy(iterator);
195 }
196 {
197 identification_t *uri;
198
199 iterator_t *iterator = that->ocspuris->create_iterator(that->ocspuris, TRUE);
200
201 while (iterator->iterate(iterator, (void**)&uri))
202 {
203 add_ocspuri(this, uri->get_encoding(uri));
204 }
205 iterator->destroy(iterator);
206 }
207 }
208
209 /**
210 * Implements ca_info_t.release_info
211 */
212 static void release_info(private_ca_info_t *this)
213 {
214 this->crluris->destroy_offset(this->crluris,
215 offsetof(identification_t, destroy));
216 this->crluris = linked_list_create();
217
218 this->ocspuris->destroy_offset(this->ocspuris,
219 offsetof(identification_t, destroy));
220 this->ocspuris = linked_list_create();
221
222 free(this->name);
223 this->name = NULL;
224 }
225
226 /**
227 * Implements ca_info_t.destroy
228 */
229 static void destroy(private_ca_info_t *this)
230 {
231 this->crluris->destroy_offset(this->crluris,
232 offsetof(identification_t, destroy));
233 this->ocspuris->destroy_offset(this->ocspuris,
234 offsetof(identification_t, destroy));
235 this->certinfos->destroy_offset(this->certinfos,
236 offsetof(certinfo_t, destroy));
237 free(this->name);
238 free(this);
239 }
240
241 /**
242 * output handler in printf()
243 */
244 static int print(FILE *stream, const struct printf_info *info,
245 const void *const *args)
246 {
247 private_ca_info_t *this = *((private_ca_info_t**)(args[0]));
248 bool utc = TRUE;
249 int written = 0;
250 const x509_t *cacert;
251 chunk_t keyid;
252
253 if (info->alt)
254 {
255 utc = *((bool*)args[1]);
256 }
257 if (this == NULL)
258 {
259 return fprintf(stream, "(null)");
260 }
261 written += fprintf(stream, "%#T", &this->installed, utc);
262
263 if (this->name)
264 {
265 written += fprintf(stream, ", \"%s\"\n", this->name);
266 }
267 else
268 {
269 written += fprintf(stream, "\n");
270 }
271
272 cacert = this->cacert;
273 written += fprintf(stream, " authname: '%D'\n", cacert->get_subject(cacert));
274
275 {
276 chunk_t keyid = cacert->get_keyid(cacert);
277
278 written += fprintf(stream, " keyid: %#B\n", &keyid);
279 }
280 {
281 identification_t *crluri;
282 iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE);
283 bool first = TRUE;
284
285 while (iterator->iterate(iterator, (void**)&crluri))
286 {
287 written += fprintf(stream, " %s '%D'\n",
288 first? "crluris:":" ", crluri);
289 first = FALSE;
290 }
291 iterator->destroy(iterator);
292 }
293 {
294 identification_t *ocspuri;
295 iterator_t *iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE);
296 bool first = TRUE;
297
298 while (iterator->iterate(iterator, (void**)&ocspuri))
299 {
300 written += fprintf(stream, " %s '%D'\n",
301 first? "ocspuris:":" ", ocspuri);
302 first = FALSE;
303 }
304 iterator->destroy(iterator);
305 }
306 return written;
307 }
308
309 /**
310 * register printf() handlers
311 */
312 static void __attribute__ ((constructor))print_register()
313 {
314 register_printf_function(PRINTF_CAINFO, print, arginfo_ptr_alt_ptr_int);
315 }
316
317 /*
318 * Described in header.
319 */
320 ca_info_t *ca_info_create(const char *name, const x509_t *cacert)
321 {
322 private_ca_info_t *this = malloc_thing(private_ca_info_t);
323
324 /* initialize */
325 this->installed = time(NULL);
326 this->name = (name == NULL)? NULL:strdup(name);
327 this->cacert = cacert;
328 this->crluris = linked_list_create();
329 this->ocspuris = linked_list_create();
330 this->certinfos = linked_list_create();
331
332 /* public functions */
333 this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals;
334 this->public.equals_name = (bool (*) (const ca_info_t*,const char*))equals_name;
335 this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
336 this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri;
337 this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri;
338 this->public.release_info = (void (*) (ca_info_t*))release_info;
339 this->public.destroy = (void (*) (ca_info_t*))destroy;
340
341 return &this->public;
342 }