f9b852d272190b5e7e11b3de83252711f81dfdfe
[strongswan.git] / src / charon / plugins / nm / nm_creds.c
1 /*
2 * Copyright (C) 2008 Martin Willi
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 "nm_creds.h"
17
18 #include <daemon.h>
19 #include <utils/mutex.h>
20
21 typedef struct private_nm_creds_t private_nm_creds_t;
22
23 /**
24 * private data of nm_creds
25 */
26 struct private_nm_creds_t {
27
28 /**
29 * public functions
30 */
31 nm_creds_t public;
32
33 /**
34 * gateway certificate
35 */
36 certificate_t *cert;
37
38 /**
39 * User name
40 */
41 identification_t *user;
42
43 /**
44 * User password
45 */
46 char *pass;
47
48 /**
49 * users certificate
50 */
51 certificate_t *usercert;
52
53 /**
54 * users private key
55 */
56 private_key_t *key;
57
58 /**
59 * read/write lock
60 */
61 rwlock_t *lock;
62 };
63
64 /**
65 * Enumerator for user certificate
66 */
67 static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
68 certificate_type_t cert, key_type_t key)
69 {
70 public_key_t *public;
71
72 if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert))
73 {
74 return NULL;
75 }
76 if (key != KEY_ANY)
77 {
78 public = this->usercert->get_public_key(this->usercert);
79 if (!public)
80 {
81 return NULL;
82 }
83 if (public->get_type(public) != key)
84 {
85 public->destroy(public);
86 return NULL;
87 }
88 public->destroy(public);
89 }
90 this->lock->read_lock(this->lock);
91 return enumerator_create_cleaner(
92 enumerator_create_single(this->usercert, NULL),
93 (void*)this->lock->unlock, this->lock);
94 }
95
96 /**
97 * Implements credential_set_t.create_cert_enumerator
98 */
99 static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
100 certificate_type_t cert, key_type_t key,
101 identification_t *id, bool trusted)
102 {
103 if (id && this->usercert &&
104 id->equals(id, this->usercert->get_subject(this->usercert)))
105 {
106 return create_usercert_enumerator(this, cert, key);
107 }
108
109 if (!this->cert)
110 {
111 return NULL;
112 }
113 if (cert != CERT_ANY && cert != this->cert->get_type(this->cert))
114 {
115 return NULL;
116 }
117 if (id && !this->cert->has_subject(this->cert, id))
118 {
119 return NULL;
120 }
121 if (key != KEY_ANY)
122 {
123 public_key_t *public;
124
125 public = this->cert->get_public_key(this->cert);
126 if (!public)
127 {
128 return NULL;
129 }
130 if (public->get_type(public) != key)
131 {
132 public->destroy(public);
133 return NULL;
134 }
135 public->destroy(public);
136 }
137 this->lock->read_lock(this->lock);
138 return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL),
139 (void*)this->lock->unlock, this->lock);
140 }
141
142 /**
143 * Implements credential_set_t.create_cert_enumerator
144 */
145 static enumerator_t* create_private_enumerator(private_nm_creds_t *this,
146 key_type_t type, identification_t *id)
147 {
148 if (this->key == NULL)
149 {
150 return NULL;
151 }
152 if (type != KEY_ANY && type != this->key->get_type(this->key))
153 {
154 return NULL;
155 }
156 if (id && id->get_type(id) != ID_ANY)
157 {
158 chunk_t keyid;
159
160 if (id->get_type(id) != ID_KEY_ID ||
161 !this->key->get_fingerprint(this->key, KEY_ID_PUBKEY_SHA1, &keyid) ||
162 !chunk_equals(keyid, id->get_encoding(id)))
163 {
164 return NULL;
165 }
166 }
167 this->lock->read_lock(this->lock);
168 return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
169 (void*)this->lock->unlock, this->lock);
170 }
171
172 /**
173 * shared key enumerator implementation
174 */
175 typedef struct {
176 enumerator_t public;
177 private_nm_creds_t *this;
178 shared_key_t *key;
179 bool done;
180 } shared_enumerator_t;
181
182 /**
183 * enumerate function for shared enumerator
184 */
185 static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
186 id_match_t *me, id_match_t *other)
187 {
188 if (this->done)
189 {
190 return FALSE;
191 }
192 *key = this->key;
193 *me = ID_MATCH_PERFECT;
194 *other = ID_MATCH_ANY;
195 this->done = TRUE;
196 return TRUE;
197 }
198
199 /**
200 * Destroy function for shared enumerator
201 */
202 static void shared_destroy(shared_enumerator_t *this)
203 {
204 this->key->destroy(this->key);
205 this->this->lock->unlock(this->this->lock);
206 free(this);
207 }
208 /**
209 * Implements credential_set_t.create_cert_enumerator
210 */
211 static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
212 shared_key_type_t type, identification_t *me,
213 identification_t *other)
214 {
215 shared_enumerator_t *enumerator;
216
217 if (!this->pass || !this->user)
218 {
219 return NULL;
220 }
221 if (type != SHARED_EAP && type != SHARED_IKE)
222 {
223 return NULL;
224 }
225 if (me && !me->equals(me, this->user))
226 {
227 return NULL;
228 }
229
230 enumerator = malloc_thing(shared_enumerator_t);
231 enumerator->public.enumerate = (void*)shared_enumerate;
232 enumerator->public.destroy = (void*)shared_destroy;
233 enumerator->this = this;
234 enumerator->done = FALSE;
235 this->lock->read_lock(this->lock);
236 enumerator->key = shared_key_create(type,
237 chunk_clone(chunk_create(this->pass,
238 strlen(this->pass))));
239 return &enumerator->public;
240 }
241
242 /**
243 * Implementation of nm_creds_t.set_certificate
244 */
245 static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
246 {
247 this->lock->write_lock(this->lock);
248 DESTROY_IF(this->cert);
249 this->cert = cert;
250 this->lock->unlock(this->lock);
251 }
252
253 /**
254 * Implementation of nm_creds_t.set_password
255 */
256 static void set_username_password(private_nm_creds_t *this, identification_t *id,
257 char *password)
258 {
259 this->lock->write_lock(this->lock);
260 DESTROY_IF(this->user);
261 this->user = id->clone(id);
262 free(this->pass);
263 this->pass = password ? strdup(password) : NULL;
264 this->lock->unlock(this->lock);
265 }
266
267 /**
268 * Implementation of nm_creds_t.set_cert_and_key
269 */
270 static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
271 private_key_t *key)
272 {
273 this->lock->write_lock(this->lock);
274 DESTROY_IF(this->key);
275 DESTROY_IF(this->usercert);
276 this->key = key;
277 this->usercert = cert;
278 this->lock->unlock(this->lock);
279 }
280
281 /**
282 * Implementation of nm_creds_t.clear
283 */
284 static void clear(private_nm_creds_t *this)
285 {
286 DESTROY_IF(this->cert);
287 DESTROY_IF(this->user);
288 free(this->pass);
289 DESTROY_IF(this->usercert);
290 DESTROY_IF(this->key);
291 this->key = NULL;
292 this->usercert = NULL;
293 this->pass = NULL;
294 this->cert = NULL;
295 this->user = NULL;
296 }
297
298 /**
299 * Implementation of nm_creds_t.destroy
300 */
301 static void destroy(private_nm_creds_t *this)
302 {
303 clear(this);
304 this->lock->destroy(this->lock);
305 free(this);
306 }
307
308 /*
309 * see header file
310 */
311 nm_creds_t *nm_creds_create()
312 {
313 private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
314
315 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
316 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
317 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
318 this->public.set.create_cdp_enumerator = (void*)return_null;
319 this->public.set.cache_cert = (void*)nop;
320 this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
321 this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password;
322 this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key;
323 this->public.clear = (void(*)(nm_creds_t*))clear;
324 this->public.destroy = (void(*)(nm_creds_t*))destroy;
325
326 this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
327
328 this->cert = NULL;
329 this->user = NULL;
330 this->pass = NULL;
331 this->usercert = NULL;
332 this->key = NULL;
333
334 return &this->public;
335 }
336