2 * Copyright (C) 2012 Tobias Brunner
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
16 #include "android_creds.h"
17 #include "../charonservice.h"
21 #include <credentials/sets/mem_cred.h>
22 #include <threading/rwlock.h>
24 typedef struct private_android_creds_t private_android_creds_t
;
27 * Private data of an android_creds_t object
29 struct private_android_creds_t
{
34 android_creds_t
public;
37 * Credential set storing trusted certificates and user credentials
42 * read/write lock to make sure certificates are only loaded once
47 * TRUE if certificates have been loaded via JNI
53 * Free allocated DER encoding
55 static void free_encoding(chunk_t
*chunk
)
62 * Load trusted certificates via charonservice (JNI).
64 static void load_trusted_certificates(private_android_creds_t
*this)
70 certs
= charonservice
->get_trusted_certificates(charonservice
);
73 while (certs
->remove_first(certs
, (void**)¤t
) == SUCCESS
)
75 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
76 BUILD_BLOB_ASN1_DER
, *current
, BUILD_END
);
79 DBG2(DBG_CFG
, "loaded CA certificate '%Y'",
80 cert
->get_subject(cert
));
81 this->creds
->add_cert(this->creds
, TRUE
, cert
);
83 free_encoding(current
);
85 certs
->destroy(certs
);
89 METHOD(credential_set_t
, create_cert_enumerator
, enumerator_t
*,
90 private_android_creds_t
*this, certificate_type_t cert
, key_type_t key
,
91 identification_t
*id
, bool trusted
)
93 enumerator_t
*enumerator
;
95 if (cert
!= CERT_ANY
&& cert
!= CERT_X509
)
99 this->lock
->read_lock(this->lock
);
102 this->lock
->unlock(this->lock
);
103 this->lock
->write_lock(this->lock
);
104 /* check again after acquiring the write lock */
107 load_trusted_certificates(this);
110 this->lock
->unlock(this->lock
);
111 this->lock
->read_lock(this->lock
);
113 enumerator
= this->creds
->set
.create_cert_enumerator(&this->creds
->set
,
114 cert
, key
, id
, trusted
);
115 return enumerator_create_cleaner(enumerator
, (void*)this->lock
->unlock
,
119 METHOD(android_creds_t
, add_username_password
, void,
120 private_android_creds_t
*this, char *username
, char *password
)
122 shared_key_t
*shared_key
;
123 identification_t
*id
;
126 secret
= chunk_create(password
, strlen(password
));
127 shared_key
= shared_key_create(SHARED_EAP
, chunk_clone(secret
));
128 id
= identification_create_from_string(username
);
130 this->creds
->add_shared(this->creds
, shared_key
, id
, NULL
);
133 METHOD(credential_set_t
, create_shared_enumerator
, enumerator_t
*,
134 private_android_creds_t
*this, shared_key_type_t type
,
135 identification_t
*me
, identification_t
*other
)
137 return this->creds
->set
.create_shared_enumerator(&this->creds
->set
,
141 METHOD(android_creds_t
, load_user_certificate
, certificate_t
*,
142 private_android_creds_t
*this)
144 linked_list_t
*encodings
;
145 certificate_t
*cert
= NULL
, *ca_cert
;
148 encodings
= charonservice
->get_user_certificate(charonservice
);
154 while (encodings
->remove_first(encodings
, (void**)¤t
) == SUCCESS
)
157 { /* the first element is the user certificate */
158 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
159 BUILD_BLOB_ASN1_DER
, *current
, BUILD_END
);
162 DBG1(DBG_CFG
, "failed to load user certificate");
163 free_encoding(current
);
166 DBG1(DBG_CFG
, "loaded user certificate '%Y' and private key",
167 cert
->get_subject(cert
));
168 cert
= this->creds
->add_cert_ref(this->creds
, TRUE
, cert
);
169 free_encoding(current
);
172 /* the rest are CA certificates, we ignore failures */
173 ca_cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
174 BUILD_BLOB_ASN1_DER
, *current
, BUILD_END
);
177 DBG1(DBG_CFG
, "loaded CA certificate '%Y'",
178 ca_cert
->get_subject(ca_cert
));
179 this->creds
->add_cert(this->creds
, TRUE
, ca_cert
);
181 free_encoding(current
);
183 encodings
->destroy_function(encodings
, (void*)free_encoding
);
189 key
= charonservice
->get_user_key(charonservice
,
190 cert
->get_public_key(cert
));
193 this->creds
->add_key(this->creds
, key
);
197 DBG1(DBG_CFG
, "failed to load private key");
205 METHOD(credential_set_t
, create_private_enumerator
, enumerator_t
*,
206 private_android_creds_t
*this, key_type_t type
, identification_t
*id
)
208 return this->creds
->set
.create_private_enumerator(&this->creds
->set
,
212 METHOD(android_creds_t
, clear
, void,
213 private_android_creds_t
*this)
215 this->lock
->write_lock(this->lock
);
216 this->creds
->clear(this->creds
);
217 this->loaded
= FALSE
;
218 this->lock
->unlock(this->lock
);
221 METHOD(android_creds_t
, destroy
, void,
222 private_android_creds_t
*this)
225 this->creds
->destroy(this->creds
);
226 this->lock
->destroy(this->lock
);
231 * Described in header.
233 android_creds_t
*android_creds_create()
235 private_android_creds_t
*this;
240 .create_cert_enumerator
= _create_cert_enumerator
,
241 .create_shared_enumerator
= _create_shared_enumerator
,
242 .create_private_enumerator
= _create_private_enumerator
,
243 .create_cdp_enumerator
= (void*)return_null
,
244 .cache_cert
= (void*)nop
,
246 .add_username_password
= _add_username_password
,
247 .load_user_certificate
= _load_user_certificate
,
251 .creds
= mem_cred_create(),
252 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
255 return &this->public;