Annotation of embedaddon/strongswan/src/libsimaka/simaka_manager.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Martin Willi
3: * HSR 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:
16: #include "simaka_manager.h"
17:
18: #include <utils/debug.h>
19: #include <collections/linked_list.h>
20: #include <threading/rwlock.h>
21:
22: typedef struct private_simaka_manager_t private_simaka_manager_t;
23:
24: /**
25: * Private data of an simaka_manager_t object.
26: */
27: struct private_simaka_manager_t {
28:
29: /**
30: * Public simaka_manager_t interface.
31: */
32: simaka_manager_t public;
33:
34: /**
35: * list of added cards
36: */
37: linked_list_t *cards;
38:
39: /**
40: * list of added provider
41: */
42: linked_list_t *providers;
43:
44: /**
45: * list of added hooks
46: */
47: linked_list_t *hooks;
48:
49: /**
50: * lock for lists above
51: */
52: rwlock_t *lock;
53: };
54:
55: /**
56: * Described in header.
57: */
58: void libsimaka_init(void)
59: {
60: /* empty */
61: }
62:
63: METHOD(simaka_manager_t, add_card, void,
64: private_simaka_manager_t *this, simaka_card_t *card)
65: {
66: this->lock->write_lock(this->lock);
67: this->cards->insert_last(this->cards, card);
68: this->lock->unlock(this->lock);
69: }
70:
71: METHOD(simaka_manager_t, remove_card, void,
72: private_simaka_manager_t *this, simaka_card_t *card)
73: {
74: this->lock->write_lock(this->lock);
75: this->cards->remove(this->cards, card, NULL);
76: this->lock->unlock(this->lock);
77: }
78:
79: METHOD(simaka_manager_t, card_get_triplet, bool,
80: private_simaka_manager_t *this, identification_t *id,
81: char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
82: {
83: enumerator_t *enumerator;
84: simaka_card_t *card;
85: int tried = 0;
86:
87: this->lock->read_lock(this->lock);
88: enumerator = this->cards->create_enumerator(this->cards);
89: while (enumerator->enumerate(enumerator, &card))
90: {
91: if (card->get_triplet(card, id, rand, sres, kc))
92: {
93: enumerator->destroy(enumerator);
94: this->lock->unlock(this->lock);
95: return TRUE;
96: }
97: tried++;
98: }
99: enumerator->destroy(enumerator);
100: this->lock->unlock(this->lock);
101: DBG1(DBG_LIB, "tried %d SIM cards, but none has triplets for '%Y'",
102: tried, id);
103: return FALSE;
104: }
105:
106: METHOD(simaka_manager_t, card_get_quintuplet, status_t,
107: private_simaka_manager_t *this, identification_t *id, char rand[AKA_RAND_LEN],
108: char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
109: char res[AKA_RES_MAX], int *res_len)
110: {
111: enumerator_t *enumerator;
112: simaka_card_t *card;
113: status_t status = NOT_FOUND;
114: int tried = 0;
115:
116: this->lock->read_lock(this->lock);
117: enumerator = this->cards->create_enumerator(this->cards);
118: while (enumerator->enumerate(enumerator, &card))
119: {
120: status = card->get_quintuplet(card, id, rand, autn, ck, ik, res, res_len);
121: switch (status)
122: { /* try next on error, but not on INVALID_STATE */
123: case SUCCESS:
124: case INVALID_STATE:
125: enumerator->destroy(enumerator);
126: this->lock->unlock(this->lock);
127: return status;
128: case NOT_SUPPORTED:
129: case FAILED:
130: default:
131: tried++;
132: continue;
133: }
134: }
135: enumerator->destroy(enumerator);
136: this->lock->unlock(this->lock);
137: DBG1(DBG_LIB, "tried %d SIM cards, but none has quintuplets for '%Y'",
138: tried, id);
139: return status;
140: }
141:
142: METHOD(simaka_manager_t, card_resync, bool,
143: private_simaka_manager_t *this, identification_t *id,
144: char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
145: {
146: enumerator_t *enumerator;
147: simaka_card_t *card;
148:
149: this->lock->read_lock(this->lock);
150: enumerator = this->cards->create_enumerator(this->cards);
151: while (enumerator->enumerate(enumerator, &card))
152: {
153: if (card->resync(card, id, rand, auts))
154: {
155: enumerator->destroy(enumerator);
156: this->lock->unlock(this->lock);
157: return TRUE;
158: }
159: }
160: enumerator->destroy(enumerator);
161: this->lock->unlock(this->lock);
162: return FALSE;
163: }
164:
165: METHOD(simaka_manager_t, card_set_pseudonym, void,
166: private_simaka_manager_t *this, identification_t *id,
167: identification_t *pseudonym)
168: {
169: enumerator_t *enumerator;
170: simaka_card_t *card;
171:
172: DBG1(DBG_LIB, "storing pseudonym '%Y' for '%Y'", pseudonym, id);
173:
174: this->lock->read_lock(this->lock);
175: enumerator = this->cards->create_enumerator(this->cards);
176: while (enumerator->enumerate(enumerator, &card))
177: {
178: card->set_pseudonym(card, id, pseudonym);
179: }
180: enumerator->destroy(enumerator);
181: this->lock->unlock(this->lock);
182: }
183:
184: METHOD(simaka_manager_t, card_get_pseudonym, identification_t*,
185: private_simaka_manager_t *this, identification_t *id)
186: {
187: enumerator_t *enumerator;
188: simaka_card_t *card;
189: identification_t *pseudonym = NULL;
190:
191: this->lock->read_lock(this->lock);
192: enumerator = this->cards->create_enumerator(this->cards);
193: while (enumerator->enumerate(enumerator, &card))
194: {
195: pseudonym = card->get_pseudonym(card, id);
196: if (pseudonym)
197: {
198: DBG1(DBG_LIB, "using stored pseudonym identity '%Y' "
199: "instead of '%Y'", pseudonym, id);
200: break;
201: }
202: }
203: enumerator->destroy(enumerator);
204: this->lock->unlock(this->lock);
205: return pseudonym;
206: }
207:
208: METHOD(simaka_manager_t, card_set_reauth, void,
209: private_simaka_manager_t *this, identification_t *id, identification_t *next,
210: char mk[HASH_SIZE_SHA1], uint16_t counter)
211: {
212: enumerator_t *enumerator;
213: simaka_card_t *card;
214:
215: DBG1(DBG_LIB, "storing next reauthentication identity '%Y' for '%Y'",
216: next, id);
217:
218: this->lock->read_lock(this->lock);
219: enumerator = this->cards->create_enumerator(this->cards);
220: while (enumerator->enumerate(enumerator, &card))
221: {
222: card->set_reauth(card, id, next, mk, counter);
223: }
224: enumerator->destroy(enumerator);
225: this->lock->unlock(this->lock);
226: }
227:
228: METHOD(simaka_manager_t, card_get_reauth, identification_t*,
229: private_simaka_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1],
230: uint16_t *counter)
231: {
232: enumerator_t *enumerator;
233: simaka_card_t *card;
234: identification_t *reauth = NULL;
235:
236: this->lock->read_lock(this->lock);
237: enumerator = this->cards->create_enumerator(this->cards);
238: while (enumerator->enumerate(enumerator, &card))
239: {
240: reauth = card->get_reauth(card, id, mk, counter);
241: if (reauth)
242: {
243: DBG1(DBG_LIB, "using stored reauthentication identity '%Y' "
244: "instead of '%Y'", reauth, id);
245: break;
246: }
247: }
248: enumerator->destroy(enumerator);
249: this->lock->unlock(this->lock);
250: return reauth;
251: }
252:
253: METHOD(simaka_manager_t, add_provider, void,
254: private_simaka_manager_t *this, simaka_provider_t *provider)
255: {
256: this->lock->write_lock(this->lock);
257: this->providers->insert_last(this->providers, provider);
258: this->lock->unlock(this->lock);
259: }
260:
261: METHOD(simaka_manager_t, remove_provider, void,
262: private_simaka_manager_t *this, simaka_provider_t *provider)
263: {
264: this->lock->write_lock(this->lock);
265: this->providers->remove(this->providers, provider, NULL);
266: this->lock->unlock(this->lock);
267: }
268:
269: METHOD(simaka_manager_t, provider_get_triplet, bool,
270: private_simaka_manager_t *this, identification_t *id,
271: char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
272: {
273: enumerator_t *enumerator;
274: simaka_provider_t *provider;
275: int tried = 0;
276:
277: this->lock->read_lock(this->lock);
278: enumerator = this->providers->create_enumerator(this->providers);
279: while (enumerator->enumerate(enumerator, &provider))
280: {
281: if (provider->get_triplet(provider, id, rand, sres, kc))
282: {
283: enumerator->destroy(enumerator);
284: this->lock->unlock(this->lock);
285: return TRUE;
286: }
287: tried++;
288: }
289: enumerator->destroy(enumerator);
290: this->lock->unlock(this->lock);
291: DBG1(DBG_LIB, "tried %d SIM providers, but none had a triplet for '%Y'",
292: tried, id);
293: return FALSE;
294: }
295:
296: METHOD(simaka_manager_t, provider_get_quintuplet, bool,
297: private_simaka_manager_t *this, identification_t *id,
298: char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len,
299: char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
300: {
301: enumerator_t *enumerator;
302: simaka_provider_t *provider;
303: int tried = 0;
304:
305: this->lock->read_lock(this->lock);
306: enumerator = this->providers->create_enumerator(this->providers);
307: while (enumerator->enumerate(enumerator, &provider))
308: {
309: if (provider->get_quintuplet(provider, id, rand, xres, xres_len,
310: ck, ik, autn))
311: {
312: enumerator->destroy(enumerator);
313: this->lock->unlock(this->lock);
314: return TRUE;
315: }
316: }
317: enumerator->destroy(enumerator);
318: this->lock->unlock(this->lock);
319: DBG1(DBG_LIB, "tried %d SIM providers, but none had a quintuplet for '%Y'",
320: tried, id);
321: return FALSE;
322: }
323:
324: METHOD(simaka_manager_t, provider_resync, bool,
325: private_simaka_manager_t *this, identification_t *id,
326: char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
327: {
328: enumerator_t *enumerator;
329: simaka_provider_t *provider;
330:
331: this->lock->read_lock(this->lock);
332: enumerator = this->providers->create_enumerator(this->providers);
333: while (enumerator->enumerate(enumerator, &provider))
334: {
335: if (provider->resync(provider, id, rand, auts))
336: {
337: enumerator->destroy(enumerator);
338: this->lock->unlock(this->lock);
339: return TRUE;
340: }
341: }
342: enumerator->destroy(enumerator);
343: this->lock->unlock(this->lock);
344: return FALSE;
345: }
346:
347: METHOD(simaka_manager_t, provider_is_pseudonym, identification_t*,
348: private_simaka_manager_t *this, identification_t *id)
349: {
350: enumerator_t *enumerator;
351: simaka_provider_t *provider;
352: identification_t *permanent = NULL;
353:
354: this->lock->read_lock(this->lock);
355: enumerator = this->providers->create_enumerator(this->providers);
356: while (enumerator->enumerate(enumerator, &provider))
357: {
358: permanent = provider->is_pseudonym(provider, id);
359: if (permanent)
360: {
361: DBG1(DBG_LIB, "received pseudonym identity '%Y' "
362: "mapping to '%Y'", id, permanent);
363: break;
364: }
365: }
366: enumerator->destroy(enumerator);
367: this->lock->unlock(this->lock);
368: return permanent;
369: }
370:
371: METHOD(simaka_manager_t, provider_gen_pseudonym, identification_t*,
372: private_simaka_manager_t *this, identification_t *id)
373: {
374: enumerator_t *enumerator;
375: simaka_provider_t *provider;
376: identification_t *pseudonym = NULL;
377:
378: this->lock->read_lock(this->lock);
379: enumerator = this->providers->create_enumerator(this->providers);
380: while (enumerator->enumerate(enumerator, &provider))
381: {
382: pseudonym = provider->gen_pseudonym(provider, id);
383: if (pseudonym)
384: {
385: DBG1(DBG_LIB, "proposing new pseudonym '%Y'", pseudonym);
386: break;
387: }
388: }
389: enumerator->destroy(enumerator);
390: this->lock->unlock(this->lock);
391: return pseudonym;
392: }
393:
394: METHOD(simaka_manager_t, provider_is_reauth, identification_t*,
395: private_simaka_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1],
396: uint16_t *counter)
397: {
398: enumerator_t *enumerator;
399: simaka_provider_t *provider;
400: identification_t *permanent = NULL;
401:
402: this->lock->read_lock(this->lock);
403: enumerator = this->providers->create_enumerator(this->providers);
404: while (enumerator->enumerate(enumerator, &provider))
405: {
406: permanent = provider->is_reauth(provider, id, mk, counter);
407: if (permanent)
408: {
409: DBG1(DBG_LIB, "received reauthentication identity '%Y' "
410: "mapping to '%Y'", id, permanent);
411: break;
412: }
413: }
414: enumerator->destroy(enumerator);
415: this->lock->unlock(this->lock);
416: return permanent;
417: }
418:
419: METHOD(simaka_manager_t, provider_gen_reauth, identification_t*,
420: private_simaka_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1])
421: {
422: enumerator_t *enumerator;
423: simaka_provider_t *provider;
424: identification_t *reauth = NULL;
425:
426: this->lock->read_lock(this->lock);
427: enumerator = this->providers->create_enumerator(this->providers);
428: while (enumerator->enumerate(enumerator, &provider))
429: {
430: reauth = provider->gen_reauth(provider, id, mk);
431: if (reauth)
432: {
433: DBG1(DBG_LIB, "proposing new reauthentication identity '%Y'", reauth);
434: break;
435: }
436: }
437: enumerator->destroy(enumerator);
438: this->lock->unlock(this->lock);
439: return reauth;
440: }
441:
442: METHOD(simaka_manager_t, add_hooks, void,
443: private_simaka_manager_t *this, simaka_hooks_t *hooks)
444: {
445: this->lock->write_lock(this->lock);
446: this->hooks->insert_last(this->hooks, hooks);
447: this->lock->unlock(this->lock);
448: }
449:
450: METHOD(simaka_manager_t, remove_hooks, void,
451: private_simaka_manager_t *this, simaka_hooks_t *hooks)
452: {
453: this->lock->write_lock(this->lock);
454: this->hooks->remove(this->hooks, hooks, NULL);
455: this->lock->unlock(this->lock);
456: }
457:
458: METHOD(simaka_manager_t, message_hook, void,
459: private_simaka_manager_t *this, simaka_message_t *message,
460: bool inbound, bool decrypted)
461: {
462: enumerator_t *enumerator;
463: simaka_hooks_t *hooks;
464:
465: this->lock->read_lock(this->lock);
466: enumerator = this->hooks->create_enumerator(this->hooks);
467: while (enumerator->enumerate(enumerator, &hooks))
468: {
469: hooks->message(hooks, message, inbound, decrypted);
470: }
471: enumerator->destroy(enumerator);
472: this->lock->unlock(this->lock);
473: }
474:
475: METHOD(simaka_manager_t, key_hook, void,
476: private_simaka_manager_t *this, chunk_t k_encr, chunk_t k_auth)
477: {
478: enumerator_t *enumerator;
479: simaka_hooks_t *hooks;
480:
481: this->lock->read_lock(this->lock);
482: enumerator = this->hooks->create_enumerator(this->hooks);
483: while (enumerator->enumerate(enumerator, &hooks))
484: {
485: hooks->keys(hooks, k_encr, k_auth);
486: }
487: enumerator->destroy(enumerator);
488: this->lock->unlock(this->lock);
489: }
490:
491: METHOD(simaka_manager_t, destroy, void,
492: private_simaka_manager_t *this)
493: {
494: this->cards->destroy(this->cards);
495: this->providers->destroy(this->providers);
496: this->hooks->destroy(this->hooks);
497: this->lock->destroy(this->lock);
498: free(this);
499: }
500:
501: /**
502: * See header
503: */
504: simaka_manager_t *simaka_manager_create()
505: {
506: private_simaka_manager_t *this;
507:
508: INIT(this,
509: .public = {
510: .add_card = _add_card,
511: .remove_card = _remove_card,
512: .card_get_triplet = _card_get_triplet,
513: .card_get_quintuplet = _card_get_quintuplet,
514: .card_resync = _card_resync,
515: .card_set_pseudonym = _card_set_pseudonym,
516: .card_get_pseudonym = _card_get_pseudonym,
517: .card_set_reauth = _card_set_reauth,
518: .card_get_reauth = _card_get_reauth,
519: .add_provider = _add_provider,
520: .remove_provider = _remove_provider,
521: .provider_get_triplet = _provider_get_triplet,
522: .provider_get_quintuplet = _provider_get_quintuplet,
523: .provider_resync = _provider_resync,
524: .provider_is_pseudonym = _provider_is_pseudonym,
525: .provider_gen_pseudonym = _provider_gen_pseudonym,
526: .provider_is_reauth = _provider_is_reauth,
527: .provider_gen_reauth = _provider_gen_reauth,
528: .add_hooks = _add_hooks,
529: .remove_hooks = _remove_hooks,
530: .message_hook = _message_hook,
531: .key_hook = _key_hook,
532: .destroy = _destroy,
533: },
534: .cards = linked_list_create(),
535: .providers = linked_list_create(),
536: .hooks = linked_list_create(),
537: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
538: );
539:
540: return &this->public;
541: }
542:
543: /**
544: * (Un-)register a provider to a simaka manager
545: */
546: static bool register_card(char *mgr_name, bool reg, simaka_card_t *card)
547: {
548: simaka_manager_t *mgr;
549:
550: if (!card)
551: {
552: return FALSE;
553: }
554: mgr = lib->get(lib, mgr_name);
555: if (mgr)
556: {
557: if (reg)
558: {
559: mgr->add_card(mgr, card);
560: }
561: else
562: {
563: mgr->remove_card(mgr, card);
564: }
565: return TRUE;
566: }
567: return FALSE;
568: }
569:
570: /**
571: * (Un-)register a provider to a simaka manager
572: */
573: static bool register_provider(char *mgr_name, bool reg,
574: simaka_provider_t *provider)
575: {
576: simaka_manager_t *mgr;
577:
578: if (!provider)
579: {
580: return FALSE;
581: }
582: mgr = lib->get(lib, mgr_name);
583: if (mgr)
584: {
585: if (reg)
586: {
587: mgr->add_provider(mgr, provider);
588: }
589: else
590: {
591: mgr->remove_provider(mgr, provider);
592: }
593: return TRUE;
594: }
595: return FALSE;
596: }
597:
598: /**
599: * See header
600: */
601: bool simaka_manager_register(plugin_t *plugin, plugin_feature_t *feature,
602: bool reg, void *data)
603: {
604: simaka_manager_register_cb_t get = (simaka_manager_register_cb_t)data;
605:
606: if (feature->type == FEATURE_CUSTOM)
607: {
608: if (streq(feature->arg.custom, "aka-card"))
609: {
610: return register_card("aka-manager", reg, get(plugin));
611: }
612: else if (streq(feature->arg.custom, "aka-provider"))
613: {
614: return register_provider("aka-manager", reg, get(plugin));
615: }
616: else if (streq(feature->arg.custom, "sim-card"))
617: {
618: return register_card("sim-manager", reg, get(plugin));
619: }
620: else if (streq(feature->arg.custom, "sim-provider"))
621: {
622: return register_provider("sim-manager", reg, get(plugin));
623: }
624: }
625: return FALSE;
626: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>