2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 <sys/types.h>
23 #include <threading/rwlock.h>
24 #include <credentials/certificates/x509.h>
26 typedef struct private_nm_creds_t private_nm_creds_t
;
29 * private data of nm_creds
31 struct private_nm_creds_t
{
39 * List of trusted certificates, certificate_t*
46 identification_t
*user
;
54 * Private key decryption password
61 certificate_t
*usercert
;
75 * Enumerator for user certificate
77 static enumerator_t
*create_usercert_enumerator(private_nm_creds_t
*this,
78 certificate_type_t cert
, key_type_t key
)
82 if (cert
!= CERT_ANY
&& cert
!= this->usercert
->get_type(this->usercert
))
88 public = this->usercert
->get_public_key(this->usercert
);
93 if (public->get_type(public) != key
)
95 public->destroy(public);
98 public->destroy(public);
100 this->lock
->read_lock(this->lock
);
101 return enumerator_create_cleaner(
102 enumerator_create_single(this->usercert
, NULL
),
103 (void*)this->lock
->unlock
, this->lock
);
107 * CA certificate enumerator data
110 /** ref to credential credential store */
111 private_nm_creds_t
*this;
112 /** type of key we are looking for */
114 /** CA certificate ID */
115 identification_t
*id
;
119 * Destroy CA certificate enumerator data
121 static void cert_data_destroy(cert_data_t
*data
)
123 data
->this->lock
->unlock(data
->this->lock
);
128 * Filter function for certificates enumerator
130 static bool cert_filter(cert_data_t
*data
, certificate_t
**in
,
133 certificate_t
*cert
= *in
;
134 public_key_t
*public;
136 public = cert
->get_public_key(cert
);
141 if (data
->key
!= KEY_ANY
&& public->get_type(public) != data
->key
)
143 public->destroy(public);
146 if (data
->id
&& data
->id
->get_type(data
->id
) == ID_KEY_ID
&&
147 public->has_fingerprint(public, data
->id
->get_encoding(data
->id
)))
149 public->destroy(public);
153 public->destroy(public);
154 if (data
->id
&& !cert
->has_subject(cert
, data
->id
))
163 * Create enumerator for trusted certificates
165 static enumerator_t
*create_trusted_cert_enumerator(private_nm_creds_t
*this,
166 key_type_t key
, identification_t
*id
)
168 cert_data_t
*data
= malloc_thing(cert_data_t
);
174 this->lock
->read_lock(this->lock
);
175 return enumerator_create_filter(
176 this->certs
->create_enumerator(this->certs
),
177 (void*)cert_filter
, data
, (void*)cert_data_destroy
);
181 * Implements credential_set_t.create_cert_enumerator
183 static enumerator_t
* create_cert_enumerator(private_nm_creds_t
*this,
184 certificate_type_t cert
, key_type_t key
,
185 identification_t
*id
, bool trusted
)
187 if (id
&& this->usercert
&&
188 id
->equals(id
, this->usercert
->get_subject(this->usercert
)))
190 return create_usercert_enumerator(this, cert
, key
);
192 if (cert
== CERT_X509
|| cert
== CERT_ANY
)
194 return create_trusted_cert_enumerator(this, key
, id
);
200 * Implements credential_set_t.create_cert_enumerator
202 static enumerator_t
* create_private_enumerator(private_nm_creds_t
*this,
203 key_type_t type
, identification_t
*id
)
205 if (this->key
== NULL
)
209 if (type
!= KEY_ANY
&& type
!= this->key
->get_type(this->key
))
213 if (id
&& id
->get_type(id
) != ID_ANY
)
215 if (id
->get_type(id
) != ID_KEY_ID
||
216 !this->key
->has_fingerprint(this->key
, id
->get_encoding(id
)))
221 this->lock
->read_lock(this->lock
);
222 return enumerator_create_cleaner(enumerator_create_single(this->key
, NULL
),
223 (void*)this->lock
->unlock
, this->lock
);
227 * shared key enumerator implementation
231 private_nm_creds_t
*this;
234 } shared_enumerator_t
;
237 * enumerate function for shared enumerator
239 static bool shared_enumerate(shared_enumerator_t
*this, shared_key_t
**key
,
240 id_match_t
*me
, id_match_t
*other
)
249 *me
= ID_MATCH_PERFECT
;
253 *other
= ID_MATCH_ANY
;
260 * Destroy function for shared enumerator
262 static void shared_destroy(shared_enumerator_t
*this)
264 this->key
->destroy(this->key
);
265 this->this->lock
->unlock(this->this->lock
);
269 * Implements credential_set_t.create_cert_enumerator
271 static enumerator_t
* create_shared_enumerator(private_nm_creds_t
*this,
272 shared_key_type_t type
, identification_t
*me
,
273 identification_t
*other
)
275 shared_enumerator_t
*enumerator
;
282 if (!this->pass
|| !this->user
)
286 if (me
&& !me
->equals(me
, this->user
))
290 key
= chunk_create(this->pass
, strlen(this->pass
));
292 case SHARED_PRIVATE_KEY_PASS
:
297 key
= chunk_create(this->keypass
, strlen(this->keypass
));
303 enumerator
= malloc_thing(shared_enumerator_t
);
304 enumerator
->public.enumerate
= (void*)shared_enumerate
;
305 enumerator
->public.destroy
= (void*)shared_destroy
;
306 enumerator
->this = this;
307 enumerator
->done
= FALSE
;
308 this->lock
->read_lock(this->lock
);
309 enumerator
->key
= shared_key_create(type
, chunk_clone(key
));
310 return &enumerator
->public;
314 * Implementation of nm_creds_t.add_certificate
316 static void add_certificate(private_nm_creds_t
*this, certificate_t
*cert
)
318 this->lock
->write_lock(this->lock
);
319 this->certs
->insert_last(this->certs
, cert
);
320 this->lock
->unlock(this->lock
);
324 * Load a certificate file
326 static void load_ca_file(private_nm_creds_t
*this, char *file
)
330 /* We add the CA constraint, as many CAs miss it */
331 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
332 BUILD_FROM_FILE
, file
, BUILD_END
);
335 DBG1(DBG_CFG
, "loading CA certificate '%s' failed", file
);
339 DBG2(DBG_CFG
, "loaded CA certificate '%Y'", cert
->get_subject(cert
));
340 x509_t
*x509
= (x509_t
*)cert
;
341 if (!(x509
->get_flags(x509
) & X509_SELF_SIGNED
))
343 DBG1(DBG_CFG
, "%Y is not self signed", cert
->get_subject(cert
));
345 this->certs
->insert_last(this->certs
, cert
);
350 * Implementation of nm_creds_t.load_ca_dir
352 static void load_ca_dir(private_nm_creds_t
*this, char *dir
)
354 enumerator_t
*enumerator
;
358 enumerator
= enumerator_create_directory(dir
);
361 while (enumerator
->enumerate(enumerator
, &rel
, &abs
, &st
))
363 /* skip '.', '..' and hidden files */
366 if (S_ISDIR(st
.st_mode
))
368 load_ca_dir(this, abs
);
370 else if (S_ISREG(st
.st_mode
))
372 load_ca_file(this, abs
);
376 enumerator
->destroy(enumerator
);
381 * Implementation of nm_creds_t.set_password
383 static void set_username_password(private_nm_creds_t
*this, identification_t
*id
,
386 this->lock
->write_lock(this->lock
);
387 DESTROY_IF(this->user
);
388 this->user
= id
->clone(id
);
390 this->pass
= password ?
strdup(password
) : NULL
;
391 this->lock
->unlock(this->lock
);
395 * Implementation of nm_creds_t.set_key_password
397 static void set_key_password(private_nm_creds_t
*this, char *password
)
399 this->lock
->write_lock(this->lock
);
401 this->keypass
= password ?
strdup(password
) : NULL
;
402 this->lock
->unlock(this->lock
);
406 * Implementation of nm_creds_t.set_cert_and_key
408 static void set_cert_and_key(private_nm_creds_t
*this, certificate_t
*cert
,
411 this->lock
->write_lock(this->lock
);
412 DESTROY_IF(this->key
);
413 DESTROY_IF(this->usercert
);
415 this->usercert
= cert
;
416 this->lock
->unlock(this->lock
);
420 * Implementation of nm_creds_t.clear
422 static void clear(private_nm_creds_t
*this)
426 while (this->certs
->remove_last(this->certs
, (void**)&cert
) == SUCCESS
)
430 DESTROY_IF(this->user
);
432 DESTROY_IF(this->usercert
);
433 DESTROY_IF(this->key
);
435 this->usercert
= NULL
;
441 * Implementation of nm_creds_t.destroy
443 static void destroy(private_nm_creds_t
*this)
446 this->certs
->destroy(this->certs
);
447 this->lock
->destroy(this->lock
);
454 nm_creds_t
*nm_creds_create()
456 private_nm_creds_t
*this = malloc_thing(private_nm_creds_t
);
458 this->public.set
.create_private_enumerator
= (void*)create_private_enumerator
;
459 this->public.set
.create_cert_enumerator
= (void*)create_cert_enumerator
;
460 this->public.set
.create_shared_enumerator
= (void*)create_shared_enumerator
;
461 this->public.set
.create_cdp_enumerator
= (void*)return_null
;
462 this->public.set
.cache_cert
= (void*)nop
;
463 this->public.add_certificate
= (void(*)(nm_creds_t
*, certificate_t
*cert
))add_certificate
;
464 this->public.load_ca_dir
= (void(*)(nm_creds_t
*, char *dir
))load_ca_dir
;
465 this->public.set_username_password
= (void(*)(nm_creds_t
*, identification_t
*id
, char *password
))set_username_password
;
466 this->public.set_key_password
= (void(*)(nm_creds_t
*, char *password
))set_key_password
;
467 this->public.set_cert_and_key
= (void(*)(nm_creds_t
*, certificate_t
*cert
, private_key_t
*key
))set_cert_and_key
;
468 this->public.clear
= (void(*)(nm_creds_t
*))clear
;
469 this->public.destroy
= (void(*)(nm_creds_t
*))destroy
;
471 this->lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
473 this->certs
= linked_list_create();
476 this->usercert
= NULL
;
479 return &this->public;