2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 <threading/rwlock.h>
19 #include <utils/linked_list.h>
21 typedef struct private_mem_cred_t private_mem_cred_t
;
24 * Private data of an mem_cred_t object.
26 struct private_mem_cred_t
{
29 * Public mem_cred_t interface.
39 * List of trusted certificates, certificate_t
41 linked_list_t
*trusted
;
44 * List of trusted and untrusted certificates, certificate_t
46 linked_list_t
*untrusted
;
49 * List of private keys, private_key_t
54 * List of shared keys, as shared_entry_t
56 linked_list_t
*shared
;
60 * Data for the certificate enumerator
64 certificate_type_t cert
;
72 static void cert_data_destroy(cert_data_t
*data
)
74 data
->lock
->unlock(data
->lock
);
79 * filter function for certs enumerator
81 static bool certs_filter(cert_data_t
*data
, certificate_t
**in
, certificate_t
**out
)
84 certificate_t
*cert
= *in
;
86 if (data
->cert
== CERT_ANY
|| data
->cert
== cert
->get_type(cert
))
88 public = cert
->get_public_key(cert
);
91 if (data
->key
== KEY_ANY
|| data
->key
== public->get_type(public))
93 if (data
->id
&& public->has_fingerprint(public,
94 data
->id
->get_encoding(data
->id
)))
96 public->destroy(public);
101 public->destroy(public);
103 else if (data
->key
!= KEY_ANY
)
107 if (data
->id
== NULL
|| cert
->has_subject(cert
, data
->id
))
116 METHOD(credential_set_t
, create_cert_enumerator
, enumerator_t
*,
117 private_mem_cred_t
*this, certificate_type_t cert
, key_type_t key
,
118 identification_t
*id
, bool trusted
)
121 enumerator_t
*enumerator
;
129 this->lock
->read_lock(this->lock
);
132 enumerator
= this->trusted
->create_enumerator(this->trusted
);
136 enumerator
= this->untrusted
->create_enumerator(this->untrusted
);
138 return enumerator_create_filter(enumerator
, (void*)certs_filter
, data
,
139 (void*)cert_data_destroy
);
142 static bool certificate_equals(certificate_t
*item
, certificate_t
*cert
)
144 return item
->equals(item
, cert
);
147 METHOD(mem_cred_t
, add_cert
, void,
148 private_mem_cred_t
*this, bool trusted
, certificate_t
*cert
)
150 this->lock
->write_lock(this->lock
);
151 if (this->untrusted
->find_last(this->untrusted
,
152 (linked_list_match_t
)certificate_equals
, NULL
, cert
) != SUCCESS
)
156 this->trusted
->insert_last(this->trusted
, cert
->get_ref(cert
));
158 this->untrusted
->insert_last(this->untrusted
, cert
->get_ref(cert
));
161 this->lock
->unlock(this->lock
);
165 * Data for key enumerator
170 identification_t
*id
;
174 * Destroy key enumerator data
176 static void key_data_destroy(key_data_t
*data
)
178 data
->lock
->unlock(data
->lock
);
183 * filter function for private key enumerator
185 static bool key_filter(key_data_t
*data
, private_key_t
**in
, private_key_t
**out
)
190 if (data
->type
== KEY_ANY
|| data
->type
== key
->get_type(key
))
192 if (data
->id
== NULL
||
193 key
->has_fingerprint(key
, data
->id
->get_encoding(data
->id
)))
202 METHOD(credential_set_t
, create_private_enumerator
, enumerator_t
*,
203 private_mem_cred_t
*this, key_type_t type
, identification_t
*id
)
212 this->lock
->read_lock(this->lock
);
213 return enumerator_create_filter(this->keys
->create_enumerator(this->keys
),
214 (void*)key_filter
, data
, (void*)key_data_destroy
);
217 METHOD(mem_cred_t
, add_key
, void,
218 private_mem_cred_t
*this, private_key_t
*key
)
220 this->lock
->write_lock(this->lock
);
221 this->keys
->insert_last(this->keys
, key
);
222 this->lock
->unlock(this->lock
);
230 shared_key_t
*shared
;
231 /* list of owners, identification_t */
232 linked_list_t
*owners
;
236 * Clean up a shared entry
238 static void shared_entry_destroy(shared_entry_t
*entry
)
240 entry
->owners
->destroy_offset(entry
->owners
,
241 offsetof(identification_t
, destroy
));
242 entry
->shared
->destroy(entry
->shared
);
247 * Data for the shared_key enumerator
251 identification_t
*me
;
252 identification_t
*other
;
253 shared_key_type_t type
;
257 * free shared key enumerator data and unlock list
259 static void shared_data_destroy(shared_data_t
*data
)
261 data
->lock
->unlock(data
->lock
);
266 * Get the best match of an owner in an entry.
268 static id_match_t
has_owner(shared_entry_t
*entry
, identification_t
*owner
)
270 enumerator_t
*enumerator
;
271 id_match_t match
, best
= ID_MATCH_NONE
;
272 identification_t
*current
;
274 enumerator
= entry
->owners
->create_enumerator(entry
->owners
);
275 while (enumerator
->enumerate(enumerator
, ¤t
))
277 match
= owner
->matches(owner
, current
);
283 enumerator
->destroy(enumerator
);
288 * enumerator filter function for shared entries
290 static bool shared_filter(shared_data_t
*data
,
291 shared_entry_t
**in
, shared_key_t
**out
,
292 void **unused1
, id_match_t
*me
,
293 void **unused2
, id_match_t
*other
)
295 id_match_t my_match
= ID_MATCH_NONE
, other_match
= ID_MATCH_NONE
;
296 shared_entry_t
*entry
= *in
;
298 if (data
->type
!= SHARED_ANY
&&
299 entry
->shared
->get_type(entry
->shared
) != data
->type
)
305 my_match
= has_owner(entry
, data
->me
);
309 other_match
= has_owner(entry
, data
->other
);
311 if ((data
->me
|| data
->other
) && (!my_match
&& !other_match
))
315 *out
= entry
->shared
;
322 *other
= other_match
;
327 METHOD(credential_set_t
, create_shared_enumerator
, enumerator_t
*,
328 private_mem_cred_t
*this, shared_key_type_t type
,
329 identification_t
*me
, identification_t
*other
)
339 data
->lock
->read_lock(data
->lock
);
340 return enumerator_create_filter(
341 this->shared
->create_enumerator(this->shared
),
342 (void*)shared_filter
, data
, (void*)shared_data_destroy
);
345 METHOD(mem_cred_t
, add_shared
, void,
346 private_mem_cred_t
*this, shared_key_t
*shared
, ...)
348 shared_entry_t
*entry
;
349 identification_t
*id
;
354 .owners
= linked_list_create(),
357 va_start(args
, shared
);
360 id
= va_arg(args
, identification_t
*);
363 entry
->owners
->insert_last(entry
->owners
, id
);
369 this->lock
->write_lock(this->lock
);
370 this->shared
->insert_last(this->shared
, entry
);
371 this->lock
->unlock(this->lock
);
374 METHOD(mem_cred_t
, clear
, void,
375 private_mem_cred_t
*this)
377 this->lock
->write_lock(this->lock
);
378 this->trusted
->destroy_offset(this->trusted
,
379 offsetof(certificate_t
, destroy
));
380 this->untrusted
->destroy_offset(this->untrusted
,
381 offsetof(certificate_t
, destroy
));
382 this->keys
->destroy_offset(this->keys
, offsetof(private_key_t
, destroy
));
383 this->shared
->destroy_function(this->shared
, (void*)shared_entry_destroy
);
384 this->trusted
= linked_list_create();
385 this->untrusted
= linked_list_create();
386 this->keys
= linked_list_create();
387 this->shared
= linked_list_create();
388 this->lock
->unlock(this->lock
);
391 METHOD(mem_cred_t
, destroy
, void,
392 private_mem_cred_t
*this)
395 this->trusted
->destroy(this->trusted
);
396 this->untrusted
->destroy(this->untrusted
);
397 this->keys
->destroy(this->keys
);
398 this->shared
->destroy(this->shared
);
399 this->lock
->destroy(this->lock
);
406 mem_cred_t
*mem_cred_create()
408 private_mem_cred_t
*this;
413 .create_shared_enumerator
= _create_shared_enumerator
,
414 .create_private_enumerator
= _create_private_enumerator
,
415 .create_cert_enumerator
= _create_cert_enumerator
,
416 .create_cdp_enumerator
= (void*)return_null
,
417 .cache_cert
= (void*)nop
,
419 .add_cert
= _add_cert
,
421 .add_shared
= _add_shared
,
425 .trusted
= linked_list_create(),
426 .untrusted
= linked_list_create(),
427 .keys
= linked_list_create(),
428 .shared
= linked_list_create(),
429 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
432 return &this->public;