cb06c74996cf7f75a345a9cdb3b495e0517d06cf
[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 * $Id$
16 */
17
18 #define _GNU_SOURCE
19 #include <pthread.h>
20
21 #include "nm_creds.h"
22
23 #include <daemon.h>
24
25 typedef struct private_nm_creds_t private_nm_creds_t;
26
27 /**
28 * private data of nm_creds
29 */
30 struct private_nm_creds_t {
31
32 /**
33 * public functions
34 */
35 nm_creds_t public;
36
37 /**
38 * gateway certificate
39 */
40 certificate_t *cert;
41
42 /**
43 * User name
44 */
45 identification_t *user;
46
47 /**
48 * User password
49 */
50 char *pass;
51
52 /**
53 * read/write lock
54 */
55 pthread_rwlock_t lock;
56 };
57
58 /**
59 * Implements credential_set_t.create_cert_enumerator
60 */
61 static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
62 certificate_type_t cert, key_type_t key,
63 identification_t *id, bool trusted)
64 {
65 if (!this->cert)
66 {
67 return NULL;
68 }
69 if (cert != CERT_ANY && cert != this->cert->get_type(this->cert))
70 {
71 return NULL;
72 }
73 if (id && !this->cert->has_subject(this->cert, id))
74 {
75 return NULL;
76 }
77 if (key != KEY_ANY)
78 {
79 public_key_t *public;
80
81 public = this->cert->get_public_key(this->cert);
82 if (!public)
83 {
84 return NULL;
85 }
86 if (public->get_type(public) != key)
87 {
88 public->destroy(public);
89 return NULL;
90 }
91 public->destroy(public);
92 }
93 pthread_rwlock_rdlock(&this->lock);
94 return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL),
95 (void*)pthread_rwlock_unlock, &this->lock);
96 }
97
98 /**
99 * shared key enumerator implementation
100 */
101 typedef struct {
102 enumerator_t public;
103 private_nm_creds_t *this;
104 shared_key_t *key;
105 bool done;
106 } shared_enumerator_t;
107
108 /**
109 * enumerate function for shared enumerator
110 */
111 static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
112 id_match_t *me, id_match_t *other)
113 {
114 if (this->done)
115 {
116 return FALSE;
117 }
118 *key = this->key;
119 *me = ID_MATCH_PERFECT;
120 *other = ID_MATCH_ANY;
121 this->done = TRUE;
122 return TRUE;
123 }
124
125 /**
126 * Destroy function for shared enumerator
127 */
128 static void shared_destroy(shared_enumerator_t *this)
129 {
130 this->key->destroy(this->key);
131 pthread_rwlock_unlock(&this->this->lock);
132 free(this);
133 }
134 /**
135 * Implements credential_set_t.create_cert_enumerator
136 */
137 static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
138 shared_key_type_t type, identification_t *me,
139 identification_t *other)
140 {
141 shared_enumerator_t *enumerator;
142
143 if (!this->pass || !this->user)
144 {
145 return NULL;
146 }
147 if (type != SHARED_EAP && type != SHARED_IKE)
148 {
149 return NULL;
150 }
151 if (me && !me->equals(me, this->user))
152 {
153 return NULL;
154 }
155
156 enumerator = malloc_thing(shared_enumerator_t);
157 enumerator->public.enumerate = (void*)shared_enumerate;
158 enumerator->public.destroy = (void*)shared_destroy;
159 enumerator->this = this;
160 enumerator->done = FALSE;
161 pthread_rwlock_rdlock(&this->lock);
162 enumerator->key = shared_key_create(type,
163 chunk_clone(chunk_create(this->pass,
164 strlen(this->pass))));
165 return &enumerator->public;
166 }
167
168 /**
169 * Implementation of nm_creds_t.set_certificate
170 */
171 static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
172 {
173 pthread_rwlock_wrlock(&this->lock);
174 DESTROY_IF(this->cert);
175 this->cert = cert;
176 pthread_rwlock_unlock(&this->lock);
177 }
178
179 /**
180 * Implementation of nm_creds_t.set_password
181 */
182 static void set_password(private_nm_creds_t *this, identification_t *id,
183 char *password)
184 {
185 pthread_rwlock_wrlock(&this->lock);
186 DESTROY_IF(this->user);
187 this->user = id->clone(id);
188 free(this->pass);
189 this->pass = strdup(password);
190 pthread_rwlock_unlock(&this->lock);
191 }
192
193 /**
194 * Implementation of nm_creds_t.destroy
195 */
196 static void destroy(private_nm_creds_t *this)
197 {
198 DESTROY_IF(this->cert);
199 DESTROY_IF(this->user);
200 free(this->pass);
201 pthread_rwlock_destroy(&this->lock);
202 free(this);
203 }
204
205 /*
206 * see header file
207 */
208 nm_creds_t *nm_creds_create()
209 {
210 private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
211
212 this->public.set.create_private_enumerator = (void*)return_null;
213 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
214 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
215 this->public.set.create_cdp_enumerator = (void*)return_null;
216 this->public.set.cache_cert = (void*)nop;
217 this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
218 this->public.set_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_password;
219 this->public.destroy = (void(*)(nm_creds_t*))destroy;
220
221 pthread_rwlock_init(&this->lock, NULL);
222
223 this->cert = NULL;
224 this->user = NULL;
225 this->pass = NULL;
226
227 return &this->public;
228 }
229