91185ee98e41dc30d8c073645491ab30973957d9
[strongswan.git] / src / charon / plugins / sql / sql_cred.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: sql_cred.c 3589 2008-03-13 14:14:44Z martin $
16 */
17
18 #include <string.h>
19
20 #include "sql_cred.h"
21
22 #include <daemon.h>
23
24 typedef struct private_sql_cred_t private_sql_cred_t;
25
26 /**
27 * Private data of an sql_cred_t object
28 */
29 struct private_sql_cred_t {
30
31 /**
32 * Public part
33 */
34 sql_cred_t public;
35
36 /**
37 * database connection
38 */
39 database_t *db;
40 };
41
42 /**
43 * enumerator over private keys
44 */
45 typedef struct {
46 /** implements enumerator */
47 enumerator_t public;
48 /** inner SQL enumerator */
49 enumerator_t *inner;
50 /** currently enumerated private key */
51 private_key_t *current;
52 } private_enumerator_t;
53
54 /**
55 * Implementation of private_enumerator_t.public.enumerate
56 */
57 static bool private_enumerator_enumerate(private_enumerator_t *this,
58 private_key_t **key)
59 {
60 chunk_t blob;
61 int type;
62
63 DESTROY_IF(this->current);
64 while (this->inner->enumerate(this->inner, &type, &blob))
65 {
66 this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
67 BUILD_BLOB_ASN1_DER, chunk_clone(blob),
68 BUILD_END);
69 if (this->current)
70 {
71 *key = this->current;
72 return TRUE;
73 }
74 }
75 this->current = NULL;
76 return FALSE;
77 }
78
79 /**
80 * Implementation of private_enumerator_t.public.destroy
81 */
82 static void private_enumerator_destroy(private_enumerator_t *this)
83 {
84 DESTROY_IF(this->current);
85 this->inner->destroy(this->inner);
86 free(this);
87 }
88
89 /**
90 * Implementation of credential_set_t.create_private_enumerator.
91 */
92 static enumerator_t* create_private_enumerator(private_sql_cred_t *this,
93 key_type_t type,
94 identification_t *id)
95 {
96 private_enumerator_t *e;
97 chunk_t keyid = chunk_empty;
98
99 if (id)
100 {
101 if (id->get_type(id) != ID_PUBKEY_INFO_SHA1)
102 {
103 DBG1(DBG_CFG, "looking for %N private key", id_type_names, id->get_type(id));
104 return NULL;
105 }
106 keyid = id->get_encoding(id);
107 DBG1(DBG_CFG, "looking for %#B", &keyid);
108 }
109 DBG1(DBG_CFG, "looking for a private key");
110 e = malloc_thing(private_enumerator_t);
111 e->current = NULL;
112 e->public.enumerate = (void*)private_enumerator_enumerate;
113 e->public.destroy = (void*)private_enumerator_destroy;
114 e->inner = this->db->query(this->db,
115 "SELECT type, data FROM private_keys "
116 "WHERE (? OR keyid = ?) AND (? OR type = ?)",
117 DB_INT, id == NULL, DB_BLOB, keyid,
118 DB_INT, type == KEY_ANY, DB_INT, type,
119 DB_INT, DB_BLOB);
120 if (!e->inner)
121 {
122 free(e);
123 return NULL;
124 }
125 return &e->public;
126 }
127
128 /**
129 * enumerator over certificates
130 */
131 typedef struct {
132 /** implements enumerator */
133 enumerator_t public;
134 /** inner SQL enumerator */
135 enumerator_t *inner;
136 /** currently enumerated cert */
137 certificate_t *current;
138 } cert_enumerator_t;
139
140 /**
141 * Implementation of cert_enumerator_t.public.enumerate
142 */
143 static bool cert_enumerator_enumerate(cert_enumerator_t *this,
144 certificate_t **cert)
145 {
146 chunk_t blob;
147 int type;
148
149 DESTROY_IF(this->current);
150 while (this->inner->enumerate(this->inner, &type, &blob))
151 {
152 this->current = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
153 BUILD_BLOB_ASN1_DER, chunk_clone(blob),
154 BUILD_END);
155 if (this->current)
156 {
157 *cert = this->current;
158 return TRUE;
159 }
160 }
161 this->current = NULL;
162 return FALSE;
163 }
164
165 /**
166 * Implementation of cert_enumerator_t.public.destroy
167 */
168 static void cert_enumerator_destroy(cert_enumerator_t *this)
169 {
170 DESTROY_IF(this->current);
171 this->inner->destroy(this->inner);
172 free(this);
173 }
174
175 /**
176 * Implementation of credential_set_t.create_cert_enumerator.
177 */
178 static enumerator_t* create_cert_enumerator(private_sql_cred_t *this,
179 certificate_type_t cert, key_type_t key,
180 identification_t *id, bool trusted)
181 {
182 cert_enumerator_t *e;
183 chunk_t enc = chunk_empty;
184 id_type_t type = ID_ANY;
185
186 if (id)
187 {
188 type = id->get_type(id);
189 enc = id->get_encoding(id);
190 }
191
192 e = malloc_thing(cert_enumerator_t);
193 e->current = NULL;
194 e->public.enumerate = (void*)cert_enumerator_enumerate;
195 e->public.destroy = (void*)cert_enumerator_destroy;
196 e->inner = this->db->query(this->db,
197 "SELECT type, data FROM certificates "
198 "WHERE (? OR type = ?) AND (? OR keytype = ?) AND "
199 "(? OR (? AND subject = ?) OR (? AND keyid = ?))",
200 DB_INT, cert == CERT_ANY, DB_INT, cert,
201 DB_INT, key == KEY_ANY, DB_INT, key,
202 DB_INT, id == NULL,
203 DB_INT, type == ID_DER_ASN1_DN, DB_BLOB, enc,
204 DB_INT, type == ID_PUBKEY_INFO_SHA1, DB_BLOB, enc,
205 DB_INT, DB_BLOB);
206 if (!e->inner)
207 {
208 free(e);
209 return NULL;
210 }
211 return &e->public;
212 }
213
214 /**
215 * enumerator over shared keys
216 */
217 typedef struct {
218 /** implements enumerator */
219 enumerator_t public;
220 /** inner SQL enumerator */
221 enumerator_t *inner;
222 /** match of me */
223 id_match_t me;
224 /** match of other */
225 id_match_t other;
226 /** currently enumerated private key */
227 shared_key_t *current;
228 } shared_enumerator_t;
229
230 /**
231 * Implementation of shared_enumerator_t.public.enumerate
232 */
233 static bool shared_enumerator_enumerate(shared_enumerator_t *this,
234 shared_key_t **shared,
235 id_match_t *me, id_match_t *other)
236 {
237 chunk_t blob;
238 int type;
239
240 DESTROY_IF(this->current);
241 while (this->inner->enumerate(this->inner, &type, &blob))
242 {
243 this->current = shared_key_create(type, chunk_clone(blob));
244 if (this->current)
245 {
246 *shared = this->current;
247 if (me)
248 {
249 *me = this->me;
250 }
251 if (other)
252 {
253 *other = this->other;
254 }
255 return TRUE;
256 }
257 }
258 this->current = NULL;
259 return FALSE;
260 }
261
262 /**
263 * Implementation of shared_enumerator_t.public.destroy
264 */
265 static void shared_enumerator_destroy(shared_enumerator_t *this)
266 {
267 DESTROY_IF(this->current);
268 this->inner->destroy(this->inner);
269 free(this);
270 }
271
272 /**
273 * Implementation of credential_set_t.create_shared_enumerator.
274 */
275 static enumerator_t* create_shared_enumerator(private_sql_cred_t *this,
276 shared_key_type_t type,
277 identification_t *me, identification_t *other)
278 {
279 shared_enumerator_t *e;
280 chunk_t my_chunk = chunk_empty, other_chunk = chunk_empty;
281
282 e = malloc_thing(shared_enumerator_t);
283 e->me = ID_MATCH_ANY;
284 e->other = ID_MATCH_ANY;
285 if (me)
286 {
287 e->me = ID_MATCH_PERFECT;
288 my_chunk = me->get_encoding(me);
289 }
290 if (other)
291 {
292 e->other = ID_MATCH_PERFECT;
293 other_chunk = other->get_encoding(other);
294 }
295 e->current = NULL;
296 e->public.enumerate = (void*)shared_enumerator_enumerate;
297 e->public.destroy = (void*)shared_enumerator_destroy;
298 e->inner = this->db->query(this->db,
299 "SELECT type, data FROM certificates "
300 "WHERE (? OR local = ?) AND (? OR remote = ?) AND (? OR type = ?)",
301 DB_INT, me == NULL, DB_BLOB, my_chunk,
302 DB_INT, other == NULL, DB_BLOB, other_chunk,
303 DB_INT, type == SHARED_ANY, DB_INT, type,
304 DB_INT, DB_BLOB);
305 if (!e->inner)
306 {
307 free(e);
308 return NULL;
309 }
310 return &e->public;
311 }
312
313 /**
314 * return null
315 */
316 static void *return_null()
317 {
318 return NULL;
319 }
320
321 /**
322 * Implementation of sql_cred_t.destroy.
323 */
324 static void destroy(private_sql_cred_t *this)
325 {
326 free(this);
327 }
328
329 /**
330 * Described in header.
331 */
332 sql_cred_t *sql_cred_create(database_t *db)
333 {
334 private_sql_cred_t *this = malloc_thing(private_sql_cred_t);
335
336 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
337 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
338 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
339 this->public.set.create_cdp_enumerator = (void*)return_null;
340 this->public.destroy = (void(*)(sql_cred_t*))destroy;
341
342 this->db = db;
343
344 return &this->public;
345 }
346