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 / smartcard pin
59 * private key ID of smartcard key
66 certificate_t
*usercert
;
80 * Enumerator for user certificate
82 static enumerator_t
*create_usercert_enumerator(private_nm_creds_t
*this,
83 certificate_type_t cert
, key_type_t key
)
87 if (cert
!= CERT_ANY
&& cert
!= this->usercert
->get_type(this->usercert
))
93 public = this->usercert
->get_public_key(this->usercert
);
98 if (public->get_type(public) != key
)
100 public->destroy(public);
103 public->destroy(public);
105 this->lock
->read_lock(this->lock
);
106 return enumerator_create_cleaner(
107 enumerator_create_single(this->usercert
, NULL
),
108 (void*)this->lock
->unlock
, this->lock
);
112 * CA certificate enumerator data
115 /** ref to credential credential store */
116 private_nm_creds_t
*this;
117 /** type of key we are looking for */
119 /** CA certificate ID */
120 identification_t
*id
;
124 * Destroy CA certificate enumerator data
126 static void cert_data_destroy(cert_data_t
*data
)
128 data
->this->lock
->unlock(data
->this->lock
);
133 * Filter function for certificates enumerator
135 static bool cert_filter(cert_data_t
*data
, certificate_t
**in
,
138 certificate_t
*cert
= *in
;
139 public_key_t
*public;
141 public = cert
->get_public_key(cert
);
146 if (data
->key
!= KEY_ANY
&& public->get_type(public) != data
->key
)
148 public->destroy(public);
151 if (data
->id
&& data
->id
->get_type(data
->id
) == ID_KEY_ID
&&
152 public->has_fingerprint(public, data
->id
->get_encoding(data
->id
)))
154 public->destroy(public);
158 public->destroy(public);
159 if (data
->id
&& !cert
->has_subject(cert
, data
->id
))
168 * Create enumerator for trusted certificates
170 static enumerator_t
*create_trusted_cert_enumerator(private_nm_creds_t
*this,
171 key_type_t key
, identification_t
*id
)
181 this->lock
->read_lock(this->lock
);
182 return enumerator_create_filter(
183 this->certs
->create_enumerator(this->certs
),
184 (void*)cert_filter
, data
, (void*)cert_data_destroy
);
187 METHOD(credential_set_t
, create_cert_enumerator
, enumerator_t
*,
188 private_nm_creds_t
*this, certificate_type_t cert
, key_type_t key
,
189 identification_t
*id
, bool trusted
)
191 if (id
&& this->usercert
&&
192 id
->equals(id
, this->usercert
->get_subject(this->usercert
)))
194 return create_usercert_enumerator(this, cert
, key
);
196 if (cert
== CERT_X509
|| cert
== CERT_ANY
)
198 return create_trusted_cert_enumerator(this, key
, id
);
203 METHOD(credential_set_t
, create_private_enumerator
, enumerator_t
*,
204 private_nm_creds_t
*this, key_type_t type
, identification_t
*id
)
206 if (this->key
== NULL
)
210 if (type
!= KEY_ANY
&& type
!= this->key
->get_type(this->key
))
214 if (id
&& id
->get_type(id
) != ID_ANY
)
216 if (id
->get_type(id
) != ID_KEY_ID
||
217 !this->key
->has_fingerprint(this->key
, id
->get_encoding(id
)))
222 this->lock
->read_lock(this->lock
);
223 return enumerator_create_cleaner(enumerator_create_single(this->key
, NULL
),
224 (void*)this->lock
->unlock
, this->lock
);
228 * shared key enumerator implementation
232 private_nm_creds_t
*this;
235 } shared_enumerator_t
;
237 METHOD(enumerator_t
, shared_enumerate
, bool,
238 shared_enumerator_t
*this, shared_key_t
**key
, id_match_t
*me
,
248 *me
= ID_MATCH_PERFECT
;
252 *other
= ID_MATCH_ANY
;
258 METHOD(enumerator_t
, shared_destroy
, void,
259 shared_enumerator_t
*this)
261 this->key
->destroy(this->key
);
262 this->this->lock
->unlock(this->this->lock
);
266 METHOD(credential_set_t
, create_shared_enumerator
, enumerator_t
*,
267 private_nm_creds_t
*this, shared_key_type_t type
, identification_t
*me
,
268 identification_t
*other
)
270 shared_enumerator_t
*enumerator
;
273 this->lock
->read_lock(this->lock
);
279 if (!this->pass
|| !this->user
)
283 if (me
&& !me
->equals(me
, this->user
))
287 key
= chunk_create(this->pass
, strlen(this->pass
));
289 case SHARED_PRIVATE_KEY_PASS
:
294 key
= chunk_create(this->keypass
, strlen(this->keypass
));
297 if (!this->keypass
|| !me
||
298 !chunk_equals(me
->get_encoding(me
), this->keyid
))
302 key
= chunk_create(this->keypass
, strlen(this->keypass
));
310 .enumerate
= (void*)_shared_enumerate
,
311 .destroy
= _shared_destroy
,
315 enumerator
->key
= shared_key_create(type
, chunk_clone(key
));
316 return &enumerator
->public;
319 this->lock
->unlock(this->lock
);
323 METHOD(nm_creds_t
, add_certificate
, void,
324 private_nm_creds_t
*this, certificate_t
*cert
)
326 this->lock
->write_lock(this->lock
);
327 this->certs
->insert_last(this->certs
, cert
);
328 this->lock
->unlock(this->lock
);
332 * Load a certificate file
334 static void load_ca_file(private_nm_creds_t
*this, char *file
)
338 /* We add the CA constraint, as many CAs miss it */
339 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
340 BUILD_FROM_FILE
, file
, BUILD_END
);
343 DBG1(DBG_CFG
, "loading CA certificate '%s' failed", file
);
347 DBG2(DBG_CFG
, "loaded CA certificate '%Y'", cert
->get_subject(cert
));
348 x509_t
*x509
= (x509_t
*)cert
;
349 if (!(x509
->get_flags(x509
) & X509_SELF_SIGNED
))
351 DBG1(DBG_CFG
, "%Y is not self signed", cert
->get_subject(cert
));
353 this->certs
->insert_last(this->certs
, cert
);
357 METHOD(nm_creds_t
, load_ca_dir
, void,
358 private_nm_creds_t
*this, char *dir
)
360 enumerator_t
*enumerator
;
364 enumerator
= enumerator_create_directory(dir
);
367 while (enumerator
->enumerate(enumerator
, &rel
, &abs
, &st
))
369 /* skip '.', '..' and hidden files */
372 if (S_ISDIR(st
.st_mode
))
374 load_ca_dir(this, abs
);
376 else if (S_ISREG(st
.st_mode
))
378 load_ca_file(this, abs
);
382 enumerator
->destroy(enumerator
);
386 METHOD(nm_creds_t
, set_username_password
, void,
387 private_nm_creds_t
*this, identification_t
*id
, char *password
)
389 this->lock
->write_lock(this->lock
);
390 DESTROY_IF(this->user
);
391 this->user
= id
->clone(id
);
393 this->pass
= strdupnull(password
);
394 this->lock
->unlock(this->lock
);
397 METHOD(nm_creds_t
, set_key_password
, void,
398 private_nm_creds_t
*this, char *password
)
400 this->lock
->write_lock(this->lock
);
402 this->keypass
= strdupnull(password
);
403 this->lock
->unlock(this->lock
);
406 METHOD(nm_creds_t
, set_pin
, void,
407 private_nm_creds_t
*this, chunk_t keyid
, char *pin
)
409 this->lock
->write_lock(this->lock
);
411 free(this->keyid
.ptr
);
412 this->keypass
= strdupnull(pin
);
413 this->keyid
= chunk_clone(keyid
);
414 this->lock
->unlock(this->lock
);
417 METHOD(nm_creds_t
, set_cert_and_key
, void,
418 private_nm_creds_t
*this, certificate_t
*cert
, private_key_t
*key
)
420 this->lock
->write_lock(this->lock
);
421 DESTROY_IF(this->key
);
422 DESTROY_IF(this->usercert
);
424 this->usercert
= cert
;
425 this->lock
->unlock(this->lock
);
428 METHOD(nm_creds_t
, clear
, void,
429 private_nm_creds_t
*this)
433 while (this->certs
->remove_last(this->certs
, (void**)&cert
) == SUCCESS
)
437 DESTROY_IF(this->user
);
440 free(this->keyid
.ptr
);
441 DESTROY_IF(this->usercert
);
442 DESTROY_IF(this->key
);
444 this->usercert
= NULL
;
447 this->keypass
= NULL
;
448 this->keyid
= chunk_empty
;
451 METHOD(nm_creds_t
, destroy
, void,
452 private_nm_creds_t
*this)
455 this->certs
->destroy(this->certs
);
456 this->lock
->destroy(this->lock
);
463 nm_creds_t
*nm_creds_create()
465 private_nm_creds_t
*this;
470 .create_private_enumerator
= _create_private_enumerator
,
471 .create_cert_enumerator
= _create_cert_enumerator
,
472 .create_shared_enumerator
= _create_shared_enumerator
,
473 .create_cdp_enumerator
= (void*)return_null
,
474 .cache_cert
= (void*)nop
,
476 .add_certificate
= _add_certificate
,
477 .load_ca_dir
= _load_ca_dir
,
478 .set_username_password
= _set_username_password
,
479 .set_key_password
= _set_key_password
,
481 .set_cert_and_key
= _set_cert_and_key
,
485 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
486 .certs
= linked_list_create(),
488 return &this->public;