]> git.ipfire.org Git - people/ms/strongswan.git/blob - programs/charon/charon/config/credentials/local_credential_store.c
- import of strongswan-2.7.0
[people/ms/strongswan.git] / programs / charon / charon / config / credentials / local_credential_store.c
1 /**
2 * @file local_credential_store.c
3 *
4 * @brief Implementation of local_credential_store_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
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 <dirent.h>
25
26 #include "local_credential_store.h"
27
28 #include <utils/linked_list.h>
29 #include <utils/logger_manager.h>
30 #include <crypto/x509.h>
31
32
33 typedef struct key_entry_t key_entry_t;
34
35 /**
36 * Private key with an associated ID to find it
37 */
38 struct key_entry_t {
39
40 /**
41 * ID, as added
42 */
43 identification_t *id;
44
45 /**
46 * Associated rsa private key
47 */
48 rsa_private_key_t *key;
49 };
50
51
52 typedef struct private_local_credential_store_t private_local_credential_store_t;
53
54 /**
55 * Private data of an local_credential_store_t object
56 */
57 struct private_local_credential_store_t {
58
59 /**
60 * Public part
61 */
62 local_credential_store_t public;
63
64 /**
65 * list of key_entry_t's with private keys
66 */
67 linked_list_t *private_keys;
68
69 /**
70 * list of x509 certificates with public keys
71 */
72 linked_list_t *certificates;
73
74 /**
75 * Assigned logger
76 */
77 logger_t *logger;
78 };
79
80
81 /**
82 * Implementation of credential_store_t.get_shared_secret.
83 */
84 static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *identification, chunk_t *preshared_secret)
85 {
86 return FAILED;
87 }
88
89 /**
90 * Implementation of credential_store_t.get_rsa_public_key.
91 */
92 static rsa_public_key_t * get_rsa_public_key(private_local_credential_store_t *this, identification_t *identification)
93 {
94 x509_t *current;
95 rsa_public_key_t *found = NULL;
96 iterator_t *iterator;
97
98 this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s",
99 identification->get_string(identification));
100 iterator = this->certificates->create_iterator(this->certificates, TRUE);
101 while (iterator->has_next(iterator))
102 {
103 iterator->current(iterator, (void**)&current);
104 identification_t *stored = current->get_subject(current);
105 this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s",
106 stored->get_string(stored));
107 if (identification->equals(identification, stored))
108 {
109 found = current->get_public_key(current);
110 break;
111 }
112 }
113 iterator->destroy(iterator);
114 return found;
115 }
116
117 /**
118 * Implementation of credential_store_t.get_rsa_private_key.
119 */
120 static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, identification_t *identification)
121 {
122 rsa_private_key_t *found = NULL;
123 key_entry_t *current;
124 iterator_t *iterator;
125
126 iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
127 while (iterator->has_next(iterator))
128 {
129 iterator->current(iterator, (void**)&current);
130 if (identification->equals(identification, current->id))
131 {
132 found = current->key->clone(current->key);
133 break;
134 }
135 }
136 iterator->destroy(iterator);
137 return found;
138 }
139
140 /**
141 * Implements local_credential_store_t.load_private_keys
142 */
143 static void load_certificates(private_local_credential_store_t *this, char *path)
144 {
145 struct dirent* entry;
146 struct stat stb;
147 DIR* dir;
148 x509_t *cert;
149
150 dir = opendir(path);
151 if (dir == NULL) {
152 this->logger->log(this->logger, ERROR, "error opening certificate directory \"%s\"", path);
153 return;
154 }
155 while ((entry = readdir(dir)) != NULL)
156 {
157 char file[256];
158 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
159
160 if (stat(file, &stb) == -1)
161 {
162 continue;
163 }
164 /* try to parse all regular files */
165 if (stb.st_mode & S_IFREG)
166 {
167 cert = x509_create_from_file(file);
168 if (cert)
169 {
170 this->certificates->insert_last(this->certificates, (void*)cert);
171 this->logger->log(this->logger, CONTROL|LEVEL1, "loaded certificate \"%s\"", file);
172 }
173 else
174 {
175 this->logger->log(this->logger, ERROR, "certificate \"%s\" invalid, skipped", file);
176 }
177 }
178 }
179 closedir(dir);
180 }
181
182 /**
183 * Query the ID for a private key, by doing a lookup in the certificates
184 */
185 static identification_t *get_id_for_private_key(private_local_credential_store_t *this, rsa_private_key_t *private_key)
186 {
187 iterator_t *iterator;
188 x509_t *cert;
189 identification_t *found = NULL;
190 rsa_public_key_t *public_key;
191
192 this->logger->log(this->logger, CONTROL|LEVEL2, "Getting ID for a private key...");
193
194 iterator = this->certificates->create_iterator(this->certificates, TRUE);
195 while (!found && iterator->has_next(iterator))
196 {
197 iterator->current(iterator, (void**)&cert);
198 public_key = cert->get_public_key(cert);
199 if (public_key)
200 {
201 if (private_key->belongs_to(private_key, public_key))
202 {
203 this->logger->log(this->logger, CONTROL|LEVEL2, "found a match");
204 found = cert->get_subject(cert);
205 found = found->clone(found);
206 }
207 else
208 {
209 this->logger->log(this->logger, CONTROL|LEVEL3, "this one did not match");
210 }
211 public_key->destroy(public_key);
212 }
213 }
214 iterator->destroy(iterator);
215 return found;
216 }
217
218 /**
219 * Implements local_credential_store_t.load_private_keys
220 */
221 static void load_private_keys(private_local_credential_store_t *this, char *path)
222 {
223 struct dirent* entry;
224 struct stat stb;
225 DIR* dir;
226 rsa_private_key_t *key;
227
228 dir = opendir(path);
229 if (dir == NULL) {
230 this->logger->log(this->logger, ERROR, "error opening private key directory \"%s\"", path);
231 return;
232 }
233 while ((entry = readdir(dir)) != NULL)
234 {
235 char file[256];
236 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
237
238 if (stat(file, &stb) == -1)
239 {
240 continue;
241 }
242 /* try to parse all regular files */
243 if (stb.st_mode & S_IFREG)
244 {
245 key = rsa_private_key_create_from_file(file, NULL);
246 if (key)
247 {
248 key_entry_t *entry;
249 identification_t *id = get_id_for_private_key(this, key);
250 if (!id)
251 {
252 this->logger->log(this->logger, ERROR,
253 "no certificate found for private key \"%s\", skipped", file);
254 key->destroy(key);
255 continue;
256 }
257 entry = malloc_thing(key_entry_t);
258 entry->key = key;
259 entry->id = id;
260 this->private_keys->insert_last(this->private_keys, (void*)entry);
261 this->logger->log(this->logger, CONTROL|LEVEL1, "loaded private key \"%s\"", file);
262 }
263 else
264 {
265 this->logger->log(this->logger, ERROR, "private key \"%s\" invalid, skipped", file);
266 }
267 }
268 }
269 closedir(dir);
270 }
271
272 /**
273 * Implementation of credential_store_t.destroy.
274 */
275 static void destroy(private_local_credential_store_t *this)
276 {
277 x509_t *certificate;
278 key_entry_t *key_entry;
279
280 while (this->certificates->remove_last(this->certificates, (void**)&certificate) == SUCCESS)
281 {
282 certificate->destroy(certificate);
283 }
284 this->certificates->destroy(this->certificates);
285 while (this->private_keys->remove_last(this->private_keys, (void**)&key_entry) == SUCCESS)
286 {
287 key_entry->id->destroy(key_entry->id);
288 key_entry->key->destroy(key_entry->key);
289 free(key_entry);
290 }
291 this->private_keys->destroy(this->private_keys);
292 free(this);
293 }
294
295 /**
296 * Described in header.
297 */
298 local_credential_store_t * local_credential_store_create()
299 {
300 private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
301
302 this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret;
303 this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,identification_t*))get_rsa_private_key;
304 this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
305 this->public.load_certificates = (void(*)(local_credential_store_t*,char*))load_certificates;
306 this->public.load_private_keys = (void(*)(local_credential_store_t*,char*))load_private_keys;
307 this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy;
308
309 /* private variables */
310 this->private_keys = linked_list_create();
311 this->certificates = linked_list_create();
312 this->logger = logger_manager->get_logger(logger_manager, CONFIG);
313
314 return (&this->public);
315 }