2 * @file local_credential_store.c
4 * @brief Implementation of local_credential_store_t.
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
26 #include "local_credential_store.h"
28 #include <utils/linked_list.h>
29 #include <utils/logger_manager.h>
30 #include <crypto/x509.h>
33 typedef struct key_entry_t key_entry_t
;
36 * Private key with an associated ID to find it
46 * Associated rsa private key
48 rsa_private_key_t
*key
;
52 typedef struct private_local_credential_store_t private_local_credential_store_t
;
55 * Private data of an local_credential_store_t object
57 struct private_local_credential_store_t
{
62 local_credential_store_t
public;
65 * list of key_entry_t's with private keys
67 linked_list_t
*private_keys
;
70 * list of x509 certificates with public keys
72 linked_list_t
*certificates
;
82 * Implementation of credential_store_t.get_shared_secret.
84 static status_t
get_shared_secret(private_local_credential_store_t
*this, identification_t
*identification
, chunk_t
*preshared_secret
)
90 * Implementation of credential_store_t.get_rsa_public_key.
92 static rsa_public_key_t
* get_rsa_public_key(private_local_credential_store_t
*this, identification_t
*identification
)
95 rsa_public_key_t
*found
= NULL
;
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
))
103 iterator
->current(iterator
, (void**)¤t
);
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
))
109 found
= current
->get_public_key(current
);
113 iterator
->destroy(iterator
);
118 * Implementation of credential_store_t.get_rsa_private_key.
120 static rsa_private_key_t
*get_rsa_private_key(private_local_credential_store_t
*this, identification_t
*identification
)
122 rsa_private_key_t
*found
= NULL
;
123 key_entry_t
*current
;
124 iterator_t
*iterator
;
126 iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
127 while (iterator
->has_next(iterator
))
129 iterator
->current(iterator
, (void**)¤t
);
130 if (identification
->equals(identification
, current
->id
))
132 found
= current
->key
->clone(current
->key
);
136 iterator
->destroy(iterator
);
141 * Implements local_credential_store_t.load_private_keys
143 static void load_certificates(private_local_credential_store_t
*this, char *path
)
145 struct dirent
* entry
;
152 this->logger
->log(this->logger
, ERROR
, "error opening certificate directory \"%s\"", path
);
155 while ((entry
= readdir(dir
)) != NULL
)
158 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
160 if (stat(file
, &stb
) == -1)
164 /* try to parse all regular files */
165 if (stb
.st_mode
& S_IFREG
)
167 cert
= x509_create_from_file(file
);
170 this->certificates
->insert_last(this->certificates
, (void*)cert
);
171 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "loaded certificate \"%s\"", file
);
175 this->logger
->log(this->logger
, ERROR
, "certificate \"%s\" invalid, skipped", file
);
183 * Query the ID for a private key, by doing a lookup in the certificates
185 static identification_t
*get_id_for_private_key(private_local_credential_store_t
*this, rsa_private_key_t
*private_key
)
187 iterator_t
*iterator
;
189 identification_t
*found
= NULL
;
190 rsa_public_key_t
*public_key
;
192 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Getting ID for a private key...");
194 iterator
= this->certificates
->create_iterator(this->certificates
, TRUE
);
195 while (!found
&& iterator
->has_next(iterator
))
197 iterator
->current(iterator
, (void**)&cert
);
198 public_key
= cert
->get_public_key(cert
);
201 if (private_key
->belongs_to(private_key
, public_key
))
203 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "found a match");
204 found
= cert
->get_subject(cert
);
205 found
= found
->clone(found
);
209 this->logger
->log(this->logger
, CONTROL
|LEVEL3
, "this one did not match");
211 public_key
->destroy(public_key
);
214 iterator
->destroy(iterator
);
219 * Implements local_credential_store_t.load_private_keys
221 static void load_private_keys(private_local_credential_store_t
*this, char *path
)
223 struct dirent
* entry
;
226 rsa_private_key_t
*key
;
230 this->logger
->log(this->logger
, ERROR
, "error opening private key directory \"%s\"", path
);
233 while ((entry
= readdir(dir
)) != NULL
)
236 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
238 if (stat(file
, &stb
) == -1)
242 /* try to parse all regular files */
243 if (stb
.st_mode
& S_IFREG
)
245 key
= rsa_private_key_create_from_file(file
, NULL
);
249 identification_t
*id
= get_id_for_private_key(this, key
);
252 this->logger
->log(this->logger
, ERROR
,
253 "no certificate found for private key \"%s\", skipped", file
);
257 entry
= malloc_thing(key_entry_t
);
260 this->private_keys
->insert_last(this->private_keys
, (void*)entry
);
261 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "loaded private key \"%s\"", file
);
265 this->logger
->log(this->logger
, ERROR
, "private key \"%s\" invalid, skipped", file
);
273 * Implementation of credential_store_t.destroy.
275 static void destroy(private_local_credential_store_t
*this)
278 key_entry_t
*key_entry
;
280 while (this->certificates
->remove_last(this->certificates
, (void**)&certificate
) == SUCCESS
)
282 certificate
->destroy(certificate
);
284 this->certificates
->destroy(this->certificates
);
285 while (this->private_keys
->remove_last(this->private_keys
, (void**)&key_entry
) == SUCCESS
)
287 key_entry
->id
->destroy(key_entry
->id
);
288 key_entry
->key
->destroy(key_entry
->key
);
291 this->private_keys
->destroy(this->private_keys
);
296 * Described in header.
298 local_credential_store_t
* local_credential_store_create()
300 private_local_credential_store_t
*this = malloc_thing(private_local_credential_store_t
);
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
;
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
);
314 return (&this->public);