]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/charon-nm/nm/nm_creds.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / charon-nm / nm / nm_creds.c
CommitLineData
ec249871
MW
1/*
2 * Copyright (C) 2008 Martin Willi
ec249871
MW
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
ec249871
MW
13 */
14
ec249871
MW
15#include "nm_creds.h"
16
85af7a89
MW
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <unistd.h>
20
ec249871 21#include <daemon.h>
eba64cef 22#include <threading/rwlock.h>
85af7a89 23#include <credentials/certificates/x509.h>
ec249871
MW
24
25typedef struct private_nm_creds_t private_nm_creds_t;
26
27/**
28 * private data of nm_creds
29 */
30struct private_nm_creds_t {
31
32 /**
33 * public functions
34 */
35 nm_creds_t public;
7daf5226 36
ec249871 37 /**
85af7a89 38 * List of trusted certificates, certificate_t*
ec249871 39 */
85af7a89 40 linked_list_t *certs;
7daf5226 41
142eaea4 42 /**
7b3814f7
MW
43 * User name
44 */
45 identification_t *user;
7daf5226 46
ec249871
MW
47 /**
48 * User password
49 */
50 char *pass;
7daf5226 51
15177f57 52 /**
8bec0f51 53 * Private key decryption password / smartcard pin
15177f57
MW
54 */
55 char *keypass;
56
8bec0f51
MW
57 /**
58 * private key ID of smartcard key
59 */
60 chunk_t keyid;
61
aff26a62
MW
62 /**
63 * users certificate
64 */
65 certificate_t *usercert;
7daf5226 66
aff26a62
MW
67 /**
68 * users private key
69 */
70 private_key_t *key;
7daf5226 71
ec249871
MW
72 /**
73 * read/write lock
74 */
27ed987e 75 rwlock_t *lock;
ec249871
MW
76};
77
aff26a62 78/**
8dbf40d1 79 * Enumerator for user certificate (lock has to be locked)
aff26a62
MW
80 */
81static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
82 certificate_type_t cert, key_type_t key)
83{
aff26a62
MW
84 return enumerator_create_cleaner(
85 enumerator_create_single(this->usercert, NULL),
27ed987e 86 (void*)this->lock->unlock, this->lock);
aff26a62
MW
87}
88
85af7a89
MW
89/**
90 * CA certificate enumerator data
91 */
92typedef struct {
93 /** ref to credential credential store */
94 private_nm_creds_t *this;
8dbf40d1
TB
95 /** certificate type we are looking for */
96 certificate_type_t type;
85af7a89
MW
97 /** type of key we are looking for */
98 key_type_t key;
99 /** CA certificate ID */
100 identification_t *id;
101} cert_data_t;
102
525cc46c
TB
103CALLBACK(cert_data_destroy, void,
104 cert_data_t *data)
85af7a89
MW
105{
106 data->this->lock->unlock(data->this->lock);
107 free(data);
108}
109
525cc46c
TB
110CALLBACK(cert_filter, bool,
111 cert_data_t *data, enumerator_t *orig, va_list args)
85af7a89 112{
525cc46c 113 certificate_t *cert, **out;
85af7a89 114
525cc46c
TB
115 VA_ARGS_VGET(args, out);
116
117 while (orig->enumerate(orig, &cert))
85af7a89 118 {
8dbf40d1 119 if (certificate_matches(cert, data->type, data->key, data->id))
525cc46c 120 {
525cc46c
TB
121 *out = cert;
122 return TRUE;
123 }
85af7a89 124 }
525cc46c 125 return FALSE;
85af7a89
MW
126}
127
128/**
8dbf40d1 129 * Create enumerator for trusted certificates (lock has to be locked)
85af7a89
MW
130 */
131static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this,
8dbf40d1
TB
132 certificate_type_t type, key_type_t key,
133 identification_t *id)
85af7a89 134{
65a07156 135 cert_data_t *data;
85af7a89 136
65a07156
TB
137 INIT(data,
138 .this = this,
8dbf40d1 139 .type = type,
65a07156 140 .key = key,
8dbf40d1 141 .id = id,
65a07156 142 );
85af7a89 143
85af7a89
MW
144 return enumerator_create_filter(
145 this->certs->create_enumerator(this->certs),
525cc46c 146 cert_filter, data, cert_data_destroy);
85af7a89
MW
147}
148
65a07156
TB
149METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
150 private_nm_creds_t *this, certificate_type_t cert, key_type_t key,
151 identification_t *id, bool trusted)
ec249871 152{
8dbf40d1
TB
153 this->lock->read_lock(this->lock);
154
aff26a62 155 if (id && this->usercert &&
8dbf40d1 156 certificate_matches(this->usercert, cert, key, id))
aff26a62
MW
157 {
158 return create_usercert_enumerator(this, cert, key);
159 }
8dbf40d1 160 return create_trusted_cert_enumerator(this, cert, key, id);
ec249871
MW
161}
162
65a07156
TB
163METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
164 private_nm_creds_t *this, key_type_t type, identification_t *id)
aff26a62
MW
165{
166 if (this->key == NULL)
167 {
168 return NULL;
169 }
170 if (type != KEY_ANY && type != this->key->get_type(this->key))
171 {
172 return NULL;
173 }
174 if (id && id->get_type(id) != ID_ANY)
175 {
87d20263 176 if (id->get_type(id) != ID_KEY_ID ||
c84b139a 177 !this->key->has_fingerprint(this->key, id->get_encoding(id)))
aff26a62
MW
178 {
179 return NULL;
180 }
181 }
27ed987e 182 this->lock->read_lock(this->lock);
aff26a62 183 return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
27ed987e 184 (void*)this->lock->unlock, this->lock);
aff26a62
MW
185}
186
142eaea4
MW
187/**
188 * shared key enumerator implementation
189 */
190typedef struct {
191 enumerator_t public;
192 private_nm_creds_t *this;
193 shared_key_t *key;
194 bool done;
195} shared_enumerator_t;
196
65a07156 197METHOD(enumerator_t, shared_enumerate, bool,
95a63bf2 198 shared_enumerator_t *this, va_list args)
142eaea4 199{
95a63bf2
TB
200 shared_key_t **key;
201 id_match_t *me, *other;
202
203 VA_ARGS_VGET(args, key, me, other);
204
142eaea4
MW
205 if (this->done)
206 {
207 return FALSE;
208 }
209 *key = this->key;
15177f57
MW
210 if (me)
211 {
212 *me = ID_MATCH_PERFECT;
213 }
214 if (other)
215 {
216 *other = ID_MATCH_ANY;
217 }
142eaea4
MW
218 this->done = TRUE;
219 return TRUE;
220}
221
65a07156
TB
222METHOD(enumerator_t, shared_destroy, void,
223 shared_enumerator_t *this)
142eaea4
MW
224{
225 this->key->destroy(this->key);
27ed987e 226 this->this->lock->unlock(this->this->lock);
142eaea4
MW
227 free(this);
228}
65a07156
TB
229
230METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
231 private_nm_creds_t *this, shared_key_type_t type, identification_t *me,
232 identification_t *other)
ec249871 233{
142eaea4 234 shared_enumerator_t *enumerator;
15177f57 235 chunk_t key;
ec249871 236
8107d9f4
TB
237 this->lock->read_lock(this->lock);
238
15177f57 239 switch (type)
142eaea4 240 {
15177f57
MW
241 case SHARED_EAP:
242 case SHARED_IKE:
243 if (!this->pass || !this->user)
244 {
8107d9f4 245 goto no_secret;
15177f57 246 }
ff8f6b15 247 if (me && !me->matches(me, this->user))
15177f57 248 {
8107d9f4 249 goto no_secret;
15177f57
MW
250 }
251 key = chunk_create(this->pass, strlen(this->pass));
252 break;
253 case SHARED_PRIVATE_KEY_PASS:
254 if (!this->keypass)
255 {
8107d9f4 256 goto no_secret;
15177f57
MW
257 }
258 key = chunk_create(this->keypass, strlen(this->keypass));
259 break;
8bec0f51
MW
260 case SHARED_PIN:
261 if (!this->keypass || !me ||
262 !chunk_equals(me->get_encoding(me), this->keyid))
263 {
8107d9f4 264 goto no_secret;
8bec0f51
MW
265 }
266 key = chunk_create(this->keypass, strlen(this->keypass));
267 break;
15177f57 268 default:
8107d9f4 269 goto no_secret;
142eaea4 270 }
7daf5226 271
65a07156
TB
272 INIT(enumerator,
273 .public = {
95a63bf2
TB
274 .enumerate = enumerator_enumerate_default,
275 .venumerate = _shared_enumerate,
65a07156
TB
276 .destroy = _shared_destroy,
277 },
278 .this = this,
279 );
15177f57 280 enumerator->key = shared_key_create(type, chunk_clone(key));
142eaea4 281 return &enumerator->public;
8107d9f4
TB
282
283no_secret:
284 this->lock->unlock(this->lock);
285 return NULL;
ec249871
MW
286}
287
65a07156
TB
288METHOD(nm_creds_t, add_certificate, void,
289 private_nm_creds_t *this, certificate_t *cert)
ec249871 290{
27ed987e 291 this->lock->write_lock(this->lock);
85af7a89 292 this->certs->insert_last(this->certs, cert);
27ed987e 293 this->lock->unlock(this->lock);
ec249871
MW
294}
295
85af7a89
MW
296/**
297 * Load a certificate file
298 */
299static void load_ca_file(private_nm_creds_t *this, char *file)
300{
301 certificate_t *cert;
302
303 /* We add the CA constraint, as many CAs miss it */
304 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
305 BUILD_FROM_FILE, file, BUILD_END);
306 if (!cert)
307 {
308 DBG1(DBG_CFG, "loading CA certificate '%s' failed", file);
309 }
310 else
311 {
312 DBG2(DBG_CFG, "loaded CA certificate '%Y'", cert->get_subject(cert));
313 x509_t *x509 = (x509_t*)cert;
314 if (!(x509->get_flags(x509) & X509_SELF_SIGNED))
315 {
316 DBG1(DBG_CFG, "%Y is not self signed", cert->get_subject(cert));
317 }
318 this->certs->insert_last(this->certs, cert);
319 }
320}
321
65a07156
TB
322METHOD(nm_creds_t, load_ca_dir, void,
323 private_nm_creds_t *this, char *dir)
85af7a89
MW
324{
325 enumerator_t *enumerator;
326 char *rel, *abs;
327 struct stat st;
328
329 enumerator = enumerator_create_directory(dir);
330 if (enumerator)
331 {
332 while (enumerator->enumerate(enumerator, &rel, &abs, &st))
333 {
334 /* skip '.', '..' and hidden files */
335 if (rel[0] != '.')
336 {
337 if (S_ISDIR(st.st_mode))
338 {
339 load_ca_dir(this, abs);
340 }
341 else if (S_ISREG(st.st_mode))
342 {
343 load_ca_file(this, abs);
344 }
345 }
346 }
347 enumerator->destroy(enumerator);
348 }
349}
350
65a07156
TB
351METHOD(nm_creds_t, set_username_password, void,
352 private_nm_creds_t *this, identification_t *id, char *password)
ec249871 353{
27ed987e 354 this->lock->write_lock(this->lock);
142eaea4 355 DESTROY_IF(this->user);
a44bb934 356 this->user = id->clone(id);
ec249871 357 free(this->pass);
1038d9fe 358 this->pass = strdupnull(password);
27ed987e 359 this->lock->unlock(this->lock);
ec249871
MW
360}
361
65a07156
TB
362METHOD(nm_creds_t, set_key_password, void,
363 private_nm_creds_t *this, char *password)
15177f57
MW
364{
365 this->lock->write_lock(this->lock);
366 free(this->keypass);
1038d9fe 367 this->keypass = strdupnull(password);
15177f57
MW
368 this->lock->unlock(this->lock);
369}
370
65a07156
TB
371METHOD(nm_creds_t, set_pin, void,
372 private_nm_creds_t *this, chunk_t keyid, char *pin)
8bec0f51
MW
373{
374 this->lock->write_lock(this->lock);
375 free(this->keypass);
376 free(this->keyid.ptr);
1038d9fe 377 this->keypass = strdupnull(pin);
8bec0f51
MW
378 this->keyid = chunk_clone(keyid);
379 this->lock->unlock(this->lock);
380}
381
65a07156
TB
382METHOD(nm_creds_t, set_cert_and_key, void,
383 private_nm_creds_t *this, certificate_t *cert, private_key_t *key)
aff26a62 384{
27ed987e 385 this->lock->write_lock(this->lock);
aff26a62
MW
386 DESTROY_IF(this->key);
387 DESTROY_IF(this->usercert);
388 this->key = key;
389 this->usercert = cert;
27ed987e 390 this->lock->unlock(this->lock);
7daf5226 391}
aff26a62 392
65a07156
TB
393METHOD(nm_creds_t, clear, void,
394 private_nm_creds_t *this)
ec249871 395{
85af7a89
MW
396 certificate_t *cert;
397
398 while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
399 {
400 cert->destroy(cert);
401 }
142eaea4 402 DESTROY_IF(this->user);
ec249871 403 free(this->pass);
8bec0f51
MW
404 free(this->keypass);
405 free(this->keyid.ptr);
aff26a62
MW
406 DESTROY_IF(this->usercert);
407 DESTROY_IF(this->key);
408 this->key = NULL;
409 this->usercert = NULL;
410 this->pass = NULL;
aff26a62 411 this->user = NULL;
8bec0f51
MW
412 this->keypass = NULL;
413 this->keyid = chunk_empty;
aff26a62
MW
414}
415
65a07156
TB
416METHOD(nm_creds_t, destroy, void,
417 private_nm_creds_t *this)
aff26a62
MW
418{
419 clear(this);
85af7a89 420 this->certs->destroy(this->certs);
27ed987e 421 this->lock->destroy(this->lock);
ec249871
MW
422 free(this);
423}
424
425/*
426 * see header file
427 */
428nm_creds_t *nm_creds_create()
429{
65a07156 430 private_nm_creds_t *this;
7daf5226 431
65a07156
TB
432 INIT(this,
433 .public = {
434 .set = {
435 .create_private_enumerator = _create_private_enumerator,
436 .create_cert_enumerator = _create_cert_enumerator,
437 .create_shared_enumerator = _create_shared_enumerator,
438 .create_cdp_enumerator = (void*)return_null,
439 .cache_cert = (void*)nop,
440 },
441 .add_certificate = _add_certificate,
442 .load_ca_dir = _load_ca_dir,
443 .set_username_password = _set_username_password,
444 .set_key_password = _set_key_password,
445 .set_pin = _set_pin,
446 .set_cert_and_key = _set_cert_and_key,
447 .clear = _clear,
448 .destroy = _destroy,
449 },
450 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
451 .certs = linked_list_create(),
452 );
ec249871
MW
453 return &this->public;
454}
455