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 <utils/mutex.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
;
56 certificate_t
*usercert
;
70 * Enumerator for user certificate
72 static enumerator_t
*create_usercert_enumerator(private_nm_creds_t
*this,
73 certificate_type_t cert
, key_type_t key
)
77 if (cert
!= CERT_ANY
&& cert
!= this->usercert
->get_type(this->usercert
))
83 public = this->usercert
->get_public_key(this->usercert
);
88 if (public->get_type(public) != key
)
90 public->destroy(public);
93 public->destroy(public);
95 this->lock
->read_lock(this->lock
);
96 return enumerator_create_cleaner(
97 enumerator_create_single(this->usercert
, NULL
),
98 (void*)this->lock
->unlock
, this->lock
);
102 * CA certificate enumerator data
105 /** ref to credential credential store */
106 private_nm_creds_t
*this;
107 /** type of key we are looking for */
109 /** CA certificate ID */
110 identification_t
*id
;
114 * Destroy CA certificate enumerator data
116 static void cert_data_destroy(cert_data_t
*data
)
118 data
->this->lock
->unlock(data
->this->lock
);
123 * Filter function for certificates enumerator
125 static bool cert_filter(cert_data_t
*data
, certificate_t
**in
,
128 certificate_t
*cert
= *in
;
129 public_key_t
*public;
132 public = cert
->get_public_key(cert
);
137 if (data
->key
!= KEY_ANY
&& public->get_type(public) != data
->key
)
139 public->destroy(public);
142 if (data
->id
&& data
->id
->get_type(data
->id
) == ID_KEY_ID
&&
143 public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1
, &keyid
) &&
144 chunk_equals(keyid
, data
->id
->get_encoding(data
->id
)))
146 public->destroy(public);
150 public->destroy(public);
151 if (data
->id
&& !cert
->has_subject(cert
, data
->id
))
160 * Create enumerator for trusted certificates
162 static enumerator_t
*create_trusted_cert_enumerator(private_nm_creds_t
*this,
163 key_type_t key
, identification_t
*id
)
165 cert_data_t
*data
= malloc_thing(cert_data_t
);
171 this->lock
->read_lock(this->lock
);
172 return enumerator_create_filter(
173 this->certs
->create_enumerator(this->certs
),
174 (void*)cert_filter
, data
, (void*)cert_data_destroy
);
178 * Implements credential_set_t.create_cert_enumerator
180 static enumerator_t
* create_cert_enumerator(private_nm_creds_t
*this,
181 certificate_type_t cert
, key_type_t key
,
182 identification_t
*id
, bool trusted
)
184 if (id
&& this->usercert
&&
185 id
->equals(id
, this->usercert
->get_subject(this->usercert
)))
187 return create_usercert_enumerator(this, cert
, key
);
189 if (cert
== CERT_X509
|| cert
== CERT_ANY
)
191 return create_trusted_cert_enumerator(this, key
, id
);
197 * Implements credential_set_t.create_cert_enumerator
199 static enumerator_t
* create_private_enumerator(private_nm_creds_t
*this,
200 key_type_t type
, identification_t
*id
)
202 if (this->key
== NULL
)
206 if (type
!= KEY_ANY
&& type
!= this->key
->get_type(this->key
))
210 if (id
&& id
->get_type(id
) != ID_ANY
)
214 if (id
->get_type(id
) != ID_KEY_ID
||
215 !this->key
->get_fingerprint(this->key
, KEY_ID_PUBKEY_SHA1
, &keyid
) ||
216 !chunk_equals(keyid
, 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
)
247 *me
= ID_MATCH_PERFECT
;
248 *other
= ID_MATCH_ANY
;
254 * Destroy function for shared enumerator
256 static void shared_destroy(shared_enumerator_t
*this)
258 this->key
->destroy(this->key
);
259 this->this->lock
->unlock(this->this->lock
);
263 * Implements credential_set_t.create_cert_enumerator
265 static enumerator_t
* create_shared_enumerator(private_nm_creds_t
*this,
266 shared_key_type_t type
, identification_t
*me
,
267 identification_t
*other
)
269 shared_enumerator_t
*enumerator
;
271 if (!this->pass
|| !this->user
)
275 if (type
!= SHARED_EAP
&& type
!= SHARED_IKE
)
279 if (me
&& !me
->equals(me
, this->user
))
284 enumerator
= malloc_thing(shared_enumerator_t
);
285 enumerator
->public.enumerate
= (void*)shared_enumerate
;
286 enumerator
->public.destroy
= (void*)shared_destroy
;
287 enumerator
->this = this;
288 enumerator
->done
= FALSE
;
289 this->lock
->read_lock(this->lock
);
290 enumerator
->key
= shared_key_create(type
,
291 chunk_clone(chunk_create(this->pass
,
292 strlen(this->pass
))));
293 return &enumerator
->public;
297 * Implementation of nm_creds_t.add_certificate
299 static void add_certificate(private_nm_creds_t
*this, certificate_t
*cert
)
301 this->lock
->write_lock(this->lock
);
302 this->certs
->insert_last(this->certs
, cert
);
303 this->lock
->unlock(this->lock
);
307 * Load a certificate file
309 static void load_ca_file(private_nm_creds_t
*this, char *file
)
313 /* We add the CA constraint, as many CAs miss it */
314 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
315 BUILD_FROM_FILE
, file
, BUILD_END
);
318 DBG1(DBG_CFG
, "loading CA certificate '%s' failed", file
);
322 DBG2(DBG_CFG
, "loaded CA certificate '%Y'", cert
->get_subject(cert
));
323 x509_t
*x509
= (x509_t
*)cert
;
324 if (!(x509
->get_flags(x509
) & X509_SELF_SIGNED
))
326 DBG1(DBG_CFG
, "%Y is not self signed", cert
->get_subject(cert
));
328 this->certs
->insert_last(this->certs
, cert
);
333 * Implementation of nm_creds_t.load_ca_dir
335 static void load_ca_dir(private_nm_creds_t
*this, char *dir
)
337 enumerator_t
*enumerator
;
341 enumerator
= enumerator_create_directory(dir
);
344 while (enumerator
->enumerate(enumerator
, &rel
, &abs
, &st
))
346 /* skip '.', '..' and hidden files */
349 if (S_ISDIR(st
.st_mode
))
351 load_ca_dir(this, abs
);
353 else if (S_ISREG(st
.st_mode
))
355 load_ca_file(this, abs
);
359 enumerator
->destroy(enumerator
);
364 * Implementation of nm_creds_t.set_password
366 static void set_username_password(private_nm_creds_t
*this, identification_t
*id
,
369 this->lock
->write_lock(this->lock
);
370 DESTROY_IF(this->user
);
371 this->user
= id
->clone(id
);
373 this->pass
= password
? strdup(password
) : NULL
;
374 this->lock
->unlock(this->lock
);
378 * Implementation of nm_creds_t.set_cert_and_key
380 static void set_cert_and_key(private_nm_creds_t
*this, certificate_t
*cert
,
383 this->lock
->write_lock(this->lock
);
384 DESTROY_IF(this->key
);
385 DESTROY_IF(this->usercert
);
387 this->usercert
= cert
;
388 this->lock
->unlock(this->lock
);
392 * Implementation of nm_creds_t.clear
394 static void clear(private_nm_creds_t
*this)
398 while (this->certs
->remove_last(this->certs
, (void**)&cert
) == SUCCESS
)
402 DESTROY_IF(this->user
);
404 DESTROY_IF(this->usercert
);
405 DESTROY_IF(this->key
);
407 this->usercert
= NULL
;
413 * Implementation of nm_creds_t.destroy
415 static void destroy(private_nm_creds_t
*this)
418 this->certs
->destroy(this->certs
);
419 this->lock
->destroy(this->lock
);
426 nm_creds_t
*nm_creds_create()
428 private_nm_creds_t
*this = malloc_thing(private_nm_creds_t
);
430 this->public.set
.create_private_enumerator
= (void*)create_private_enumerator
;
431 this->public.set
.create_cert_enumerator
= (void*)create_cert_enumerator
;
432 this->public.set
.create_shared_enumerator
= (void*)create_shared_enumerator
;
433 this->public.set
.create_cdp_enumerator
= (void*)return_null
;
434 this->public.set
.cache_cert
= (void*)nop
;
435 this->public.add_certificate
= (void(*)(nm_creds_t
*, certificate_t
*cert
))add_certificate
;
436 this->public.load_ca_dir
= (void(*)(nm_creds_t
*, char *dir
))load_ca_dir
;
437 this->public.set_username_password
= (void(*)(nm_creds_t
*, identification_t
*id
, char *password
))set_username_password
;
438 this->public.set_cert_and_key
= (void(*)(nm_creds_t
*, certificate_t
*cert
, private_key_t
*key
))set_cert_and_key
;
439 this->public.clear
= (void(*)(nm_creds_t
*))clear
;
440 this->public.destroy
= (void(*)(nm_creds_t
*))destroy
;
442 this->lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
444 this->certs
= linked_list_create();
447 this->usercert
= NULL
;
450 return &this->public;