better normalized tables for SQL plugin (IDs)
[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
98 e = malloc_thing(private_enumerator_t);
99 e->current = NULL;
100 e->public.enumerate = (void*)private_enumerator_enumerate;
101 e->public.destroy = (void*)private_enumerator_destroy;
102 if (id && id->get_type(id) != ID_ANY)
103 {
104 e->inner = this->db->query(this->db,
105 "SELECT p.type, p.data FROM private_keys AS p "
106 "JOIN private_key_identity AS pi ON p.id = pi.private_key "
107 "JOIN identities AS i ON pi.identity = i.id "
108 "WHERE i.type = ? AND i.data = ? AND (? OR p.type = ?)",
109 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
110 DB_INT, type == KEY_ANY, DB_INT, type,
111 DB_INT, DB_BLOB);
112 }
113 else
114 {
115 e->inner = this->db->query(this->db,
116 "SELECT type, data FROM private_keys WHERE (? OR type = ?)",
117 DB_INT, type == KEY_ANY, DB_INT, type,
118 DB_INT, DB_BLOB);
119 }
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
184 e = malloc_thing(cert_enumerator_t);
185 e->current = NULL;
186 e->public.enumerate = (void*)cert_enumerator_enumerate;
187 e->public.destroy = (void*)cert_enumerator_destroy;
188 if (id && id->get_type(id) != ID_ANY)
189 {
190 e->inner = this->db->query(this->db,
191 "SELECT c.type, c.data FROM certificates AS c "
192 "JOIN certificate_identity AS ci ON c.id = ci.certificate "
193 "JOIN identities AS i ON ci.identity = i.id "
194 "WHERE i.type = ? AND i.data = ? AND "
195 "(? OR c.type = ?) AND (? OR c.keytype = ?)",
196 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
197 DB_INT, cert == CERT_ANY, DB_INT, cert,
198 DB_INT, key == KEY_ANY, DB_INT, key,
199 DB_INT, DB_BLOB);
200 }
201 else
202 {
203 e->inner = this->db->query(this->db,
204 "SELECT type, data FROM certificates WHERE "
205 "(? OR type = ?) AND (? OR keytype = ?)",
206 DB_INT, cert == CERT_ANY, DB_INT, cert,
207 DB_INT, key == KEY_ANY, DB_INT, key,
208 DB_INT, DB_BLOB);
209 }
210 if (!e->inner)
211 {
212 free(e);
213 return NULL;
214 }
215 return &e->public;
216 }
217
218 /**
219 * enumerator over shared keys
220 */
221 typedef struct {
222 /** implements enumerator */
223 enumerator_t public;
224 /** inner SQL enumerator */
225 enumerator_t *inner;
226 /** own identity */
227 identification_t *me;
228 /** remote identity */
229 identification_t *other;
230 /** currently enumerated private key */
231 shared_key_t *current;
232 } shared_enumerator_t;
233
234 /**
235 * Implementation of shared_enumerator_t.public.enumerate
236 */
237 static bool shared_enumerator_enumerate(shared_enumerator_t *this,
238 shared_key_t **shared,
239 id_match_t *me, id_match_t *other)
240 {
241 chunk_t blob;
242 int type;
243
244 DESTROY_IF(this->current);
245 while (this->inner->enumerate(this->inner, &type, &blob))
246 {
247 this->current = shared_key_create(type, chunk_clone(blob));
248 if (this->current)
249 {
250 *shared = this->current;
251 if (me)
252 {
253 *me = this->me ? ID_MATCH_PERFECT : ID_MATCH_ANY;
254 }
255 if (other)
256 {
257 *other = this->other ? ID_MATCH_PERFECT : ID_MATCH_ANY;
258 }
259 return TRUE;
260 }
261 }
262 this->current = NULL;
263 return FALSE;
264 }
265
266 /**
267 * Implementation of shared_enumerator_t.public.destroy
268 */
269 static void shared_enumerator_destroy(shared_enumerator_t *this)
270 {
271 DESTROY_IF(this->current);
272 this->inner->destroy(this->inner);
273 free(this);
274 }
275
276 /**
277 * Implementation of credential_set_t.create_shared_enumerator.
278 */
279 static enumerator_t* create_shared_enumerator(private_sql_cred_t *this,
280 shared_key_type_t type,
281 identification_t *me, identification_t *other)
282 {
283 shared_enumerator_t *e;
284
285 e = malloc_thing(shared_enumerator_t);
286 e->me = me;
287 e->other = other;
288 e->current = NULL;
289 e->public.enumerate = (void*)shared_enumerator_enumerate;
290 e->public.destroy = (void*)shared_enumerator_destroy;
291 if (!me && !other)
292 {
293 e->inner = this->db->query(this->db,
294 "SELECT type, data FROM shared_secrets WHERE (? OR type = ?)",
295 DB_INT, type == SHARED_ANY, DB_INT, type,
296 DB_INT, DB_BLOB);
297 }
298 else if (me && other)
299 {
300 e->inner = this->db->query(this->db,
301 "SELECT s.type, s.data FROM shared_secrets AS s "
302 "JOIN shared_secret_identity AS sm ON s.id = sm.shared_secret "
303 "JOIN identities AS m ON sm.identity = m.id "
304 "JOIN shared_secret_identity AS so ON s.id = so.shared_secret "
305 "JOIN identities AS o ON so.identity = o.id "
306 "WHERE m.type = ? AND m.data = ? AND o.type = ? AND o.data = ? "
307 "AND (? OR s.type = ?)",
308 DB_INT, me->get_type(me), DB_BLOB, me->get_encoding(me),
309 DB_INT, other->get_type(other), DB_BLOB, other->get_encoding(other),
310 DB_INT, type == SHARED_ANY, DB_INT, type,
311 DB_INT, DB_BLOB);
312 }
313 else
314 {
315 identification_t *id = me ? me : other;
316
317 e->inner = this->db->query(this->db,
318 "SELECT s.type, s.data FROM shared_secrets AS s "
319 "JOIN shared_secret_identity AS si ON s.id = si.shared_secret "
320 "JOIN identities AS i ON si.identity = i.id "
321 "WHERE i.type = ? AND i.data = ? AND (? OR s.type = ?)",
322 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
323 DB_INT, type == SHARED_ANY, DB_INT, type,
324 DB_INT, DB_BLOB);
325 }
326 if (!e->inner)
327 {
328 free(e);
329 return NULL;
330 }
331 return &e->public;
332 }
333
334 /**
335 * return null
336 */
337 static void *return_null()
338 {
339 return NULL;
340 }
341
342 /**
343 * Implementation of sql_cred_t.destroy.
344 */
345 static void destroy(private_sql_cred_t *this)
346 {
347 free(this);
348 }
349
350 /**
351 * Described in header.
352 */
353 sql_cred_t *sql_cred_create(database_t *db)
354 {
355 private_sql_cred_t *this = malloc_thing(private_sql_cred_t);
356
357 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
358 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
359 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
360 this->public.set.create_cdp_enumerator = (void*)return_null;
361 this->public.destroy = (void(*)(sql_cred_t*))destroy;
362
363 this->db = db;
364
365 return &this->public;
366 }
367