4c92c412cb14effaba6bad1c9a03f0197a7444dc
[strongswan.git] / src / libstrongswan / plugins / plugin_feature.c
1 /*
2 * Copyright (C) 2012-2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #define _GNU_SOURCE
20 #include <stdio.h>
21
22 #include "plugin_feature.h"
23
24 #include <utils/debug.h>
25
26 ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
27 "NONE",
28 "CRYPTER",
29 "AEAD",
30 "SIGNER",
31 "HASHER",
32 "PRF",
33 "DH",
34 "RNG",
35 "NONCE_GEN",
36 "PRIVKEY",
37 "PRIVKEY_GEN",
38 "PRIVKEY_SIGN",
39 "PRIVKEY_DECRYPT",
40 "PUBKEY",
41 "PUBKEY_VERIFY",
42 "PUBKEY_ENCRYPT",
43 "CERT_DECODE",
44 "CERT_ENCODE",
45 "CONTAINER_DECODE",
46 "CONTAINER_ENCODE",
47 "EAP_SERVER",
48 "EAP_CLIENT",
49 "XAUTH_SERVER",
50 "XAUTH_CLIENT",
51 "DATABASE",
52 "FETCHER",
53 "RESOLVER",
54 "CUSTOM",
55 );
56
57 /**
58 * See header.
59 */
60 uint32_t plugin_feature_hash(plugin_feature_t *feature)
61 {
62 chunk_t data = chunk_empty;
63
64 switch (feature->type)
65 {
66 case FEATURE_NONE:
67 case FEATURE_RNG:
68 case FEATURE_NONCE_GEN:
69 case FEATURE_DATABASE:
70 case FEATURE_FETCHER:
71 case FEATURE_RESOLVER:
72 /* put these special cases in their (type-specific) buckets */
73 data = chunk_empty;
74 break;
75 case FEATURE_CRYPTER:
76 data = chunk_from_thing(feature->arg.crypter);
77 break;
78 case FEATURE_AEAD:
79 data = chunk_from_thing(feature->arg.aead);
80 break;
81 case FEATURE_SIGNER:
82 data = chunk_from_thing(feature->arg.signer);
83 break;
84 case FEATURE_HASHER:
85 data = chunk_from_thing(feature->arg.hasher);
86 break;
87 case FEATURE_PRF:
88 data = chunk_from_thing(feature->arg.prf);
89 break;
90 case FEATURE_DH:
91 data = chunk_from_thing(feature->arg.dh_group);
92 break;
93 case FEATURE_PRIVKEY:
94 data = chunk_from_thing(feature->arg.privkey);
95 break;
96 case FEATURE_PRIVKEY_GEN:
97 data = chunk_from_thing(feature->arg.privkey_gen);
98 break;
99 case FEATURE_PUBKEY:
100 data = chunk_from_thing(feature->arg.pubkey);
101 break;
102 case FEATURE_PRIVKEY_SIGN:
103 data = chunk_from_thing(feature->arg.privkey_sign);
104 break;
105 case FEATURE_PUBKEY_VERIFY:
106 data = chunk_from_thing(feature->arg.pubkey_verify);
107 break;
108 case FEATURE_PRIVKEY_DECRYPT:
109 data = chunk_from_thing(feature->arg.privkey_decrypt);
110 break;
111 case FEATURE_PUBKEY_ENCRYPT:
112 data = chunk_from_thing(feature->arg.pubkey_encrypt);
113 break;
114 case FEATURE_CERT_DECODE:
115 case FEATURE_CERT_ENCODE:
116 data = chunk_from_thing(feature->arg.cert);
117 break;
118 case FEATURE_CONTAINER_DECODE:
119 case FEATURE_CONTAINER_ENCODE:
120 data = chunk_from_thing(feature->arg.container);
121 break;
122 case FEATURE_EAP_SERVER:
123 case FEATURE_EAP_PEER:
124 data = chunk_from_thing(feature->arg.eap);
125 break;
126 case FEATURE_CUSTOM:
127 data = chunk_create(feature->arg.custom,
128 strlen(feature->arg.custom));
129 break;
130 case FEATURE_XAUTH_SERVER:
131 case FEATURE_XAUTH_PEER:
132 data = chunk_create(feature->arg.xauth,
133 strlen(feature->arg.xauth));
134 break;
135 }
136 return chunk_hash_inc(chunk_from_thing(feature->type),
137 chunk_hash(data));
138 }
139
140 /**
141 * See header.
142 */
143 bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
144 {
145 if (a->type == b->type)
146 {
147 switch (a->type)
148 {
149 case FEATURE_NONE:
150 return FALSE;
151 case FEATURE_CRYPTER:
152 return a->arg.crypter.alg == b->arg.crypter.alg &&
153 a->arg.crypter.key_size == b->arg.crypter.key_size;
154 case FEATURE_AEAD:
155 return a->arg.aead.alg == b->arg.aead.alg &&
156 a->arg.aead.key_size == b->arg.aead.key_size;
157 case FEATURE_SIGNER:
158 return a->arg.signer == b->arg.signer;
159 case FEATURE_HASHER:
160 return a->arg.hasher == b->arg.hasher;
161 case FEATURE_PRF:
162 return a->arg.prf == b->arg.prf;
163 case FEATURE_DH:
164 return a->arg.dh_group == b->arg.dh_group;
165 case FEATURE_RNG:
166 return a->arg.rng_quality <= b->arg.rng_quality;
167 case FEATURE_NONCE_GEN:
168 case FEATURE_RESOLVER:
169 return TRUE;
170 case FEATURE_PRIVKEY:
171 case FEATURE_PRIVKEY_GEN:
172 case FEATURE_PUBKEY:
173 return a->arg.privkey == b->arg.privkey;
174 case FEATURE_PRIVKEY_SIGN:
175 case FEATURE_PUBKEY_VERIFY:
176 return a->arg.privkey_sign == b->arg.privkey_sign;
177 case FEATURE_PRIVKEY_DECRYPT:
178 case FEATURE_PUBKEY_ENCRYPT:
179 return a->arg.privkey_decrypt == b->arg.privkey_decrypt;
180 case FEATURE_CERT_DECODE:
181 case FEATURE_CERT_ENCODE:
182 return a->arg.cert == b->arg.cert;
183 case FEATURE_CONTAINER_DECODE:
184 case FEATURE_CONTAINER_ENCODE:
185 return a->arg.container == b->arg.container;
186 case FEATURE_EAP_SERVER:
187 case FEATURE_EAP_PEER:
188 return a->arg.eap.vendor == b->arg.eap.vendor &&
189 a->arg.eap.type == b->arg.eap.type;
190 case FEATURE_DATABASE:
191 return a->arg.database == DB_ANY ||
192 a->arg.database == b->arg.database;
193 case FEATURE_FETCHER:
194 return a->arg.fetcher == NULL ||
195 streq(a->arg.fetcher, b->arg.fetcher);
196 case FEATURE_CUSTOM:
197 return streq(a->arg.custom, b->arg.custom);
198 case FEATURE_XAUTH_SERVER:
199 case FEATURE_XAUTH_PEER:
200 return streq(a->arg.xauth, b->arg.xauth);
201 }
202 }
203 return FALSE;
204 }
205
206 /**
207 * See header.
208 */
209 bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
210 {
211 if (a->type == b->type)
212 {
213 switch (a->type)
214 {
215 case FEATURE_NONE:
216 case FEATURE_CRYPTER:
217 case FEATURE_AEAD:
218 case FEATURE_SIGNER:
219 case FEATURE_HASHER:
220 case FEATURE_PRF:
221 case FEATURE_DH:
222 case FEATURE_NONCE_GEN:
223 case FEATURE_RESOLVER:
224 case FEATURE_PRIVKEY:
225 case FEATURE_PRIVKEY_GEN:
226 case FEATURE_PUBKEY:
227 case FEATURE_PRIVKEY_SIGN:
228 case FEATURE_PUBKEY_VERIFY:
229 case FEATURE_PRIVKEY_DECRYPT:
230 case FEATURE_PUBKEY_ENCRYPT:
231 case FEATURE_CERT_DECODE:
232 case FEATURE_CERT_ENCODE:
233 case FEATURE_CONTAINER_DECODE:
234 case FEATURE_CONTAINER_ENCODE:
235 case FEATURE_EAP_SERVER:
236 case FEATURE_EAP_PEER:
237 case FEATURE_CUSTOM:
238 case FEATURE_XAUTH_SERVER:
239 case FEATURE_XAUTH_PEER:
240 return plugin_feature_matches(a, b);
241 case FEATURE_RNG:
242 return a->arg.rng_quality == b->arg.rng_quality;
243 case FEATURE_DATABASE:
244 return a->arg.database == b->arg.database;
245 case FEATURE_FETCHER:
246 if (a->arg.fetcher && b->arg.fetcher)
247 {
248 return streq(a->arg.fetcher, b->arg.fetcher);
249 }
250 return !a->arg.fetcher && !b->arg.fetcher;
251 }
252 }
253 return FALSE;
254 }
255
256 /**
257 * See header.
258 */
259 char* plugin_feature_get_string(plugin_feature_t *feature)
260 {
261 char *str = NULL;
262
263 if (feature->kind == FEATURE_REGISTER)
264 {
265 return strdup("(register function)");
266 }
267 switch (feature->type)
268 {
269 case FEATURE_NONE:
270 return strdup("NONE");
271 case FEATURE_CRYPTER:
272 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
273 encryption_algorithm_names, feature->arg.crypter.alg,
274 feature->arg.crypter.key_size) > 0)
275 {
276 return str;
277 }
278 break;
279 case FEATURE_AEAD:
280 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
281 encryption_algorithm_names, feature->arg.aead.alg,
282 feature->arg.aead.key_size) > 0)
283 {
284 return str;
285 }
286 break;
287 case FEATURE_SIGNER:
288 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
289 integrity_algorithm_names, feature->arg.signer) > 0)
290 {
291 return str;
292 }
293 break;
294 case FEATURE_HASHER:
295 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
296 hash_algorithm_names, feature->arg.hasher) > 0)
297 {
298 return str;
299 }
300 break;
301 case FEATURE_PRF:
302 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
303 pseudo_random_function_names, feature->arg.prf) > 0)
304 {
305 return str;
306 }
307 break;
308 case FEATURE_DH:
309 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
310 diffie_hellman_group_names, feature->arg.dh_group) > 0)
311 {
312 return str;
313 }
314 break;
315 case FEATURE_RNG:
316 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
317 rng_quality_names, feature->arg.rng_quality) > 0)
318 {
319 return str;
320 }
321 break;
322 case FEATURE_NONCE_GEN:
323 case FEATURE_RESOLVER:
324 if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0)
325 {
326 return str;
327 }
328 break;
329 case FEATURE_PRIVKEY:
330 case FEATURE_PRIVKEY_GEN:
331 case FEATURE_PUBKEY:
332 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
333 key_type_names, feature->arg.privkey) > 0)
334 {
335 return str;
336 }
337 break;
338 case FEATURE_PRIVKEY_SIGN:
339 case FEATURE_PUBKEY_VERIFY:
340 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
341 signature_scheme_names, feature->arg.privkey_sign) > 0)
342 {
343 return str;
344 }
345 break;
346 case FEATURE_PRIVKEY_DECRYPT:
347 case FEATURE_PUBKEY_ENCRYPT:
348 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
349 encryption_scheme_names, feature->arg.privkey_decrypt) > 0)
350 {
351 return str;
352 }
353 break;
354 case FEATURE_CERT_DECODE:
355 case FEATURE_CERT_ENCODE:
356 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
357 certificate_type_names, feature->arg.cert) > 0)
358 {
359 return str;
360 }
361 break;
362 case FEATURE_CONTAINER_DECODE:
363 case FEATURE_CONTAINER_ENCODE:
364 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
365 container_type_names, feature->arg.container) > 0)
366 {
367 return str;
368 }
369 break;
370 case FEATURE_EAP_SERVER:
371 case FEATURE_EAP_PEER:
372 if (feature->arg.eap.vendor &&
373 asprintf(&str, "%N:%d-%d", plugin_feature_names, feature->type,
374 feature->arg.eap.type, feature->arg.eap.vendor) > 0)
375 {
376 return str;
377 }
378 else if (!feature->arg.eap.vendor &&
379 asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
380 eap_type_short_names, feature->arg.eap.type) > 0)
381 {
382 return str;
383 }
384 break;
385 case FEATURE_DATABASE:
386 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
387 db_driver_names, feature->arg.database) > 0)
388 {
389 return str;
390 }
391 break;
392 case FEATURE_FETCHER:
393 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
394 feature->arg.fetcher) > 0)
395 {
396 return str;
397 }
398 break;
399 case FEATURE_CUSTOM:
400 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
401 feature->arg.custom) > 0)
402 {
403 return str;
404 }
405 break;
406 case FEATURE_XAUTH_SERVER:
407 case FEATURE_XAUTH_PEER:
408 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
409 feature->arg.xauth) > 0)
410 {
411 return str;
412 }
413 break;
414 }
415 if (!str)
416 {
417 str = strdup("(invalid)");
418 }
419 return str;
420 }
421
422 /**
423 * See header.
424 */
425 bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
426 plugin_feature_t *reg)
427 {
428 char *name;
429
430 if (!reg)
431 { /* noting to do for this feature */
432 return TRUE;
433 }
434 if (reg->kind == FEATURE_CALLBACK)
435 {
436 if (!reg->arg.cb.f ||
437 reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data))
438 {
439 return TRUE;
440 }
441 return FALSE;
442 }
443 name = plugin->get_name(plugin);
444 switch (feature->type)
445 {
446 case FEATURE_CRYPTER:
447 lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg,
448 feature->arg.crypter.key_size,
449 name, reg->arg.reg.f);
450 break;
451 case FEATURE_AEAD:
452 lib->crypto->add_aead(lib->crypto, feature->arg.aead.alg,
453 feature->arg.aead.key_size,
454 name, reg->arg.reg.f);
455 break;
456 case FEATURE_SIGNER:
457 lib->crypto->add_signer(lib->crypto, feature->arg.signer,
458 name, reg->arg.reg.f);
459 break;
460 case FEATURE_HASHER:
461 lib->crypto->add_hasher(lib->crypto, feature->arg.hasher,
462 name, reg->arg.reg.f);
463 break;
464 case FEATURE_PRF:
465 lib->crypto->add_prf(lib->crypto, feature->arg.prf,
466 name, reg->arg.reg.f);
467 break;
468 case FEATURE_DH:
469 lib->crypto->add_dh(lib->crypto, feature->arg.dh_group,
470 name, reg->arg.reg.f);
471 break;
472 case FEATURE_RNG:
473 lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality,
474 name, reg->arg.reg.f);
475 break;
476 case FEATURE_NONCE_GEN:
477 lib->crypto->add_nonce_gen(lib->crypto,
478 name, reg->arg.reg.f);
479 break;
480 case FEATURE_PRIVKEY:
481 case FEATURE_PRIVKEY_GEN:
482 lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY,
483 feature->arg.privkey, reg->arg.reg.final,
484 reg->arg.reg.f);
485 break;
486 case FEATURE_PUBKEY:
487 lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY,
488 feature->arg.pubkey, reg->arg.reg.final,
489 reg->arg.reg.f);
490 break;
491 case FEATURE_CERT_DECODE:
492 case FEATURE_CERT_ENCODE:
493 lib->creds->add_builder(lib->creds, CRED_CERTIFICATE,
494 feature->arg.cert, reg->arg.reg.final,
495 reg->arg.reg.f);
496 break;
497 case FEATURE_CONTAINER_DECODE:
498 case FEATURE_CONTAINER_ENCODE:
499 lib->creds->add_builder(lib->creds, CRED_CONTAINER,
500 feature->arg.container, reg->arg.reg.final,
501 reg->arg.reg.f);
502 break;
503 case FEATURE_DATABASE:
504 lib->db->add_database(lib->db, reg->arg.reg.f);
505 break;
506 case FEATURE_FETCHER:
507 lib->fetcher->add_fetcher(lib->fetcher, reg->arg.reg.f,
508 feature->arg.fetcher);
509 break;
510 case FEATURE_RESOLVER:
511 lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f);
512 break;
513 default:
514 break;
515 }
516 return TRUE;
517 }
518
519 /**
520 * See header.
521 */
522 bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
523 plugin_feature_t *reg)
524 {
525 if (!reg)
526 { /* noting to do for this feature */
527 return TRUE;
528 }
529 if (reg->kind == FEATURE_CALLBACK)
530 {
531 if (!reg->arg.cb.f ||
532 reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data))
533 {
534 return TRUE;
535 }
536 return FALSE;
537 }
538 switch (feature->type)
539 {
540 case FEATURE_CRYPTER:
541 lib->crypto->remove_crypter(lib->crypto, reg->arg.reg.f);
542 break;
543 case FEATURE_AEAD:
544 lib->crypto->remove_aead(lib->crypto, reg->arg.reg.f);
545 break;
546 case FEATURE_SIGNER:
547 lib->crypto->remove_signer(lib->crypto, reg->arg.reg.f);
548 break;
549 case FEATURE_HASHER:
550 lib->crypto->remove_hasher(lib->crypto, reg->arg.reg.f);
551 break;
552 case FEATURE_PRF:
553 lib->crypto->remove_prf(lib->crypto, reg->arg.reg.f);
554 break;
555 case FEATURE_DH:
556 lib->crypto->remove_dh(lib->crypto, reg->arg.reg.f);
557 break;
558 case FEATURE_RNG:
559 lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f);
560 break;
561 case FEATURE_NONCE_GEN:
562 lib->crypto->remove_nonce_gen(lib->crypto, reg->arg.reg.f);
563 break;
564 case FEATURE_PRIVKEY:
565 case FEATURE_PRIVKEY_GEN:
566 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
567 break;
568 case FEATURE_PUBKEY:
569 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
570 break;
571 case FEATURE_CERT_DECODE:
572 case FEATURE_CERT_ENCODE:
573 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
574 break;
575 case FEATURE_CONTAINER_DECODE:
576 case FEATURE_CONTAINER_ENCODE:
577 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
578 break;
579 case FEATURE_DATABASE:
580 lib->db->remove_database(lib->db, reg->arg.reg.f);
581 break;
582 case FEATURE_FETCHER:
583 lib->fetcher->remove_fetcher(lib->fetcher, reg->arg.reg.f);
584 break;
585 case FEATURE_RESOLVER:
586 lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f);
587 break;
588 default:
589 break;
590 }
591 return TRUE;
592 }