Annotation of embedaddon/strongswan/src/libsimaka/simaka_manager.c, revision 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>