added .gitignore files to NM applet
[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 identification_t *keyid;
159
160 keyid = this->key->get_id(this->key, id->get_type(id));
161 if (!keyid || !keyid->equals(keyid, id))
162 {
163 return NULL;
164 }
165 }
166 this->lock->read_lock(this->lock);
167 return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
168 (void*)this->lock->unlock, this->lock);
169 }
170
171 /**
172 * shared key enumerator implementation
173 */
174 typedef struct {
175 enumerator_t public;
176 private_nm_creds_t *this;
177 shared_key_t *key;
178 bool done;
179 } shared_enumerator_t;
180
181 /**
182 * enumerate function for shared enumerator
183 */
184 static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
185 id_match_t *me, id_match_t *other)
186 {
187 if (this->done)
188 {
189 return FALSE;
190 }
191 *key = this->key;
192 *me = ID_MATCH_PERFECT;
193 *other = ID_MATCH_ANY;
194 this->done = TRUE;
195 return TRUE;
196 }
197
198 /**
199 * Destroy function for shared enumerator
200 */
201 static void shared_destroy(shared_enumerator_t *this)
202 {
203 this->key->destroy(this->key);
204 this->this->lock->unlock(this->this->lock);
205 free(this);
206 }
207 /**
208 * Implements credential_set_t.create_cert_enumerator
209 */
210 static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
211 shared_key_type_t type, identification_t *me,
212 identification_t *other)
213 {
214 shared_enumerator_t *enumerator;
215
216 if (!this->pass || !this->user)
217 {
218 return NULL;
219 }
220 if (type != SHARED_EAP && type != SHARED_IKE)
221 {
222 return NULL;
223 }
224 if (me && !me->equals(me, this->user))
225 {
226 return NULL;
227 }
228
229 enumerator = malloc_thing(shared_enumerator_t);
230 enumerator->public.enumerate = (void*)shared_enumerate;
231 enumerator->public.destroy = (void*)shared_destroy;
232 enumerator->this = this;
233 enumerator->done = FALSE;
234 this->lock->read_lock(this->lock);
235 enumerator->key = shared_key_create(type,
236 chunk_clone(chunk_create(this->pass,
237 strlen(this->pass))));
238 return &enumerator->public;
239 }
240
241 /**
242 * Implementation of nm_creds_t.set_certificate
243 */
244 static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
245 {
246 this->lock->write_lock(this->lock);
247 DESTROY_IF(this->cert);
248 this->cert = cert;
249 this->lock->unlock(this->lock);
250 }
251
252 /**
253 * Implementation of nm_creds_t.set_password
254 */
255 static void set_username_password(private_nm_creds_t *this, identification_t *id,
256 char *password)
257 {
258 this->lock->write_lock(this->lock);
259 DESTROY_IF(this->user);
260 this->user = id->clone(id);
261 free(this->pass);
262 this->pass = password ? strdup(password) : NULL;
263 this->lock->unlock(this->lock);
264 }
265
266 /**
267 * Implementation of nm_creds_t.set_cert_and_key
268 */
269 static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
270 private_key_t *key)
271 {
272 this->lock->write_lock(this->lock);
273 DESTROY_IF(this->key);
274 DESTROY_IF(this->usercert);
275 this->key = key;
276 this->usercert = cert;
277 this->lock->unlock(this->lock);
278 }
279
280 /**
281 * Implementation of nm_creds_t.clear
282 */
283 static void clear(private_nm_creds_t *this)
284 {
285 DESTROY_IF(this->cert);
286 DESTROY_IF(this->user);
287 free(this->pass);
288 DESTROY_IF(this->usercert);
289 DESTROY_IF(this->key);
290 this->key = NULL;
291 this->usercert = NULL;
292 this->pass = NULL;
293 this->cert = NULL;
294 this->user = NULL;
295 }
296
297 /**
298 * Implementation of nm_creds_t.destroy
299 */
300 static void destroy(private_nm_creds_t *this)
301 {
302 clear(this);
303 this->lock->destroy(this->lock);
304 free(this);
305 }
306
307 /*
308 * see header file
309 */
310 nm_creds_t *nm_creds_create()
311 {
312 private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
313
314 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
315 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
316 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
317 this->public.set.create_cdp_enumerator = (void*)return_null;
318 this->public.set.cache_cert = (void*)nop;
319 this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
320 this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password;
321 this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key;
322 this->public.clear = (void(*)(nm_creds_t*))clear;
323 this->public.destroy = (void(*)(nm_creds_t*))destroy;
324
325 this->lock = rwlock_create(RWLOCK_DEFAULT);
326
327 this->cert = NULL;
328 this->user = NULL;
329 this->pass = NULL;
330 this->usercert = NULL;
331 this->key = NULL;
332
333 return &this->public;
334 }
335