601c91e7bf3cbe19e923aadeff11aa5817325237
[strongswan.git] / src / libcharon / plugins / android / android_creds.c
1 /*
2 * Copyright (C) 2010 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include <keystore_get.h>
17
18 #include "android_creds.h"
19
20 #include <daemon.h>
21 #include <threading/rwlock.h>
22
23 typedef struct private_android_creds_t private_android_creds_t;
24
25 /**
26 * Private data of an android_creds_t object
27 */
28 struct private_android_creds_t {
29
30 /**
31 * Public interface
32 */
33 android_creds_t public;
34
35 /**
36 * List of trusted certificates, certificate_t*
37 */
38 linked_list_t *certs;
39
40 /**
41 * User name (ID)
42 */
43 identification_t *user;
44
45 /**
46 * User password
47 */
48 char *pass;
49
50 /**
51 * read/write lock
52 */
53 rwlock_t *lock;
54
55 };
56
57 /**
58 * Certificate enumerator data
59 */
60 typedef struct {
61 private_android_creds_t *this;
62 key_type_t key;
63 identification_t *id;
64 } cert_data_t;
65
66 /**
67 * Filter function for certificates enumerator
68 */
69 static bool cert_filter(cert_data_t *data, certificate_t **in,
70 certificate_t **out)
71 {
72 certificate_t *cert = *in;
73 public_key_t *public;
74
75 public = cert->get_public_key(cert);
76 if (!public)
77 {
78 return FALSE;
79 }
80 if (data->key != KEY_ANY && public->get_type(public) != data->key)
81 {
82 public->destroy(public);
83 return FALSE;
84 }
85 if (data->id && data->id->get_type(data->id) == ID_KEY_ID &&
86 public->has_fingerprint(public, data->id->get_encoding(data->id)))
87 {
88 public->destroy(public);
89 *out = cert;
90 return TRUE;
91 }
92 public->destroy(public);
93 if (data->id && !cert->has_subject(cert, data->id))
94 {
95 return FALSE;
96 }
97 *out = cert;
98 return TRUE;
99 }
100
101 /**
102 * Destroy certificate enumerator data
103 */
104 static void cert_data_destroy(cert_data_t *this)
105 {
106 this->this->lock->unlock(this->this->lock);
107 free(this);
108 }
109
110 METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
111 private_android_creds_t *this, certificate_type_t cert, key_type_t key,
112 identification_t *id, bool trusted)
113 {
114 if (cert == CERT_X509 || cert == CERT_ANY)
115 {
116 cert_data_t *data;
117 this->lock->read_lock(this->lock);
118 INIT(data, .this = this, .id = id, .key = key);
119 return enumerator_create_filter(
120 this->certs->create_enumerator(this->certs),
121 (void*)cert_filter, data, (void*)cert_data_destroy);
122 }
123 return NULL;
124 }
125
126 /**
127 * Shared key enumerator implementation
128 */
129 typedef struct {
130 enumerator_t public;
131 private_android_creds_t *this;
132 shared_key_t *key;
133 bool done;
134 } shared_enumerator_t;
135
136 METHOD(enumerator_t, shared_enumerate, bool,
137 shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
138 id_match_t *other)
139 {
140 if (this->done)
141 {
142 return FALSE;
143 }
144 *key = this->key;
145 *me = ID_MATCH_PERFECT;
146 *other = ID_MATCH_ANY;
147 this->done = TRUE;
148 return TRUE;
149 }
150
151 METHOD(enumerator_t, shared_destroy, void,
152 shared_enumerator_t *this)
153 {
154 this->key->destroy(this->key);
155 this->this->lock->unlock(this->this->lock);
156 free(this);
157 }
158
159 METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
160 private_android_creds_t *this, shared_key_type_t type,
161 identification_t *me, identification_t *other)
162 {
163 shared_enumerator_t *enumerator;
164
165 this->lock->read_lock(this->lock);
166
167 if (!this->user || !this->pass)
168 {
169 this->lock->unlock(this->lock);
170 return NULL;
171 }
172 if (type != SHARED_EAP && type != SHARED_IKE)
173 {
174 this->lock->unlock(this->lock);
175 return NULL;
176 }
177 if (me && !me->equals(me, this->user))
178 {
179 this->lock->unlock(this->lock);
180 return NULL;
181 }
182
183 INIT(enumerator,
184 .public = {
185 .enumerate = (void*)_shared_enumerate,
186 .destroy = _shared_destroy,
187 },
188 .this = this,
189 .done = FALSE,
190 .key = shared_key_create(type, chunk_clone(chunk_create(this->pass,
191 strlen(this->pass)))),
192 );
193 return &enumerator->public;
194 }
195
196 METHOD(android_creds_t, add_certificate, bool,
197 private_android_creds_t *this, char *name)
198 {
199 certificate_t *cert = NULL;
200 bool status = FALSE;
201 chunk_t chunk;
202 #ifdef KEYSTORE_MESSAGE_SIZE
203 /* most current interface, the eclair interface (without key length) is
204 * currently not supported */
205 char value[KEYSTORE_MESSAGE_SIZE];
206 chunk.ptr = value;
207 chunk.len = keystore_get(name, strlen(name), chunk.ptr);
208 if (chunk.len > 0)
209 #else
210 /* 1.6 interface, allocates memory */
211 chunk.ptr = keystore_get(name, &chunk.len);
212 if (chunk.ptr)
213 #endif /* KEYSTORE_MESSAGE_SIZE */
214 {
215 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
216 BUILD_BLOB_PEM, chunk, BUILD_END);
217 if (cert)
218 {
219 this->lock->write_lock(this->lock);
220 this->certs->insert_last(this->certs, cert);
221 this->lock->unlock(this->lock);
222 status = TRUE;
223 }
224 #ifndef KEYSTORE_MESSAGE_SIZE
225 free(chunk.ptr);
226 #endif /* KEYSTORE_MESSAGE_SIZE */
227 }
228 return status;
229 }
230
231 METHOD(android_creds_t, set_username_password, void,
232 private_android_creds_t *this, identification_t *id, char *password)
233 {
234 this->lock->write_lock(this->lock);
235 DESTROY_IF(this->user);
236 this->user = id->clone(id);
237 free(this->pass);
238 this->pass = strdupnull(password);
239 this->lock->unlock(this->lock);
240 }
241
242 METHOD(android_creds_t, clear, void,
243 private_android_creds_t *this)
244 {
245 certificate_t *cert;
246 this->lock->write_lock(this->lock);
247 while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
248 {
249 cert->destroy(cert);
250 }
251 DESTROY_IF(this->user);
252 free(this->pass);
253 this->user = NULL;
254 this->pass = NULL;
255 this->lock->unlock(this->lock);
256 }
257
258 METHOD(android_creds_t, destroy, void,
259 private_android_creds_t *this)
260 {
261 clear(this);
262 this->certs->destroy(this->certs);
263 this->lock->destroy(this->lock);
264 free(this);
265 }
266
267 /**
268 * Described in header.
269 */
270 android_creds_t *android_creds_create()
271 {
272 private_android_creds_t *this;
273
274 INIT(this,
275 .public = {
276 .set = {
277 .create_cert_enumerator = _create_cert_enumerator,
278 .create_shared_enumerator = _create_shared_enumerator,
279 .create_private_enumerator = (void*)return_null,
280 .create_cdp_enumerator = (void*)return_null,
281 .cache_cert = (void*)nop,
282 },
283 .add_certificate = _add_certificate,
284 .set_username_password = _set_username_password,
285 .clear = _clear,
286 .destroy = _destroy,
287 },
288 .certs = linked_list_create(),
289 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
290 );
291
292 return &this->public;
293 }
294