Annotation of embedaddon/strongswan/src/libstrongswan/credentials/sets/mem_cred.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2010-2016 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * Copyright (C) 2010 Martin Willi
! 6: * Copyright (C) 2010 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: #include "mem_cred.h"
! 20:
! 21: #include <threading/rwlock.h>
! 22: #include <collections/linked_list.h>
! 23:
! 24: typedef struct private_mem_cred_t private_mem_cred_t;
! 25:
! 26: /**
! 27: * Private data of an mem_cred_t object.
! 28: */
! 29: struct private_mem_cred_t {
! 30:
! 31: /**
! 32: * Public mem_cred_t interface.
! 33: */
! 34: mem_cred_t public;
! 35:
! 36: /**
! 37: * Lock for this set
! 38: */
! 39: rwlock_t *lock;
! 40:
! 41: /**
! 42: * List of trusted certificates, certificate_t
! 43: */
! 44: linked_list_t *trusted;
! 45:
! 46: /**
! 47: * List of trusted and untrusted certificates, certificate_t
! 48: */
! 49: linked_list_t *untrusted;
! 50:
! 51: /**
! 52: * List of private keys, private_key_t
! 53: */
! 54: linked_list_t *keys;
! 55:
! 56: /**
! 57: * List of shared keys, as shared_entry_t
! 58: */
! 59: linked_list_t *shared;
! 60:
! 61: /**
! 62: * List of CDPs, as cdp_t
! 63: */
! 64: linked_list_t *cdps;
! 65: };
! 66:
! 67: /**
! 68: * Data for the certificate enumerator
! 69: */
! 70: typedef struct {
! 71: rwlock_t *lock;
! 72: certificate_type_t cert;
! 73: key_type_t key;
! 74: identification_t *id;
! 75: } cert_data_t;
! 76:
! 77: CALLBACK(cert_data_destroy, void,
! 78: cert_data_t *data)
! 79: {
! 80: data->lock->unlock(data->lock);
! 81: free(data);
! 82: }
! 83:
! 84: CALLBACK(certs_filter, bool,
! 85: cert_data_t *data, enumerator_t *orig, va_list args)
! 86: {
! 87: public_key_t *public;
! 88: certificate_t *cert, **out;
! 89:
! 90: VA_ARGS_VGET(args, out);
! 91:
! 92: while (orig->enumerate(orig, &cert))
! 93: {
! 94: if (data->cert != CERT_ANY && data->cert != cert->get_type(cert))
! 95: {
! 96: continue;
! 97: }
! 98: public = cert->get_public_key(cert);
! 99: if (public)
! 100: {
! 101: if (data->key == KEY_ANY || data->key == public->get_type(public))
! 102: {
! 103: if (data->id && public->has_fingerprint(public,
! 104: data->id->get_encoding(data->id)))
! 105: {
! 106: public->destroy(public);
! 107: *out = cert;
! 108: return TRUE;
! 109: }
! 110: }
! 111: else
! 112: {
! 113: public->destroy(public);
! 114: continue;
! 115: }
! 116: public->destroy(public);
! 117: }
! 118: else if (data->key != KEY_ANY)
! 119: {
! 120: continue;
! 121: }
! 122: if (!data->id || cert->has_subject(cert, data->id))
! 123: {
! 124: *out = cert;
! 125: return TRUE;
! 126: }
! 127: }
! 128: return FALSE;
! 129: }
! 130:
! 131: METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
! 132: private_mem_cred_t *this, certificate_type_t cert, key_type_t key,
! 133: identification_t *id, bool trusted)
! 134: {
! 135: cert_data_t *data;
! 136: enumerator_t *enumerator;
! 137:
! 138: INIT(data,
! 139: .lock = this->lock,
! 140: .cert = cert,
! 141: .key = key,
! 142: .id = id,
! 143: );
! 144: this->lock->read_lock(this->lock);
! 145: if (trusted)
! 146: {
! 147: enumerator = this->trusted->create_enumerator(this->trusted);
! 148: }
! 149: else
! 150: {
! 151: enumerator = this->untrusted->create_enumerator(this->untrusted);
! 152: }
! 153: return enumerator_create_filter(enumerator, certs_filter, data,
! 154: cert_data_destroy);
! 155: }
! 156:
! 157: CALLBACK(certificate_equals, bool,
! 158: certificate_t *item, va_list args)
! 159: {
! 160: certificate_t *cert;
! 161:
! 162: VA_ARGS_VGET(args, cert);
! 163: return item->equals(item, cert);
! 164: }
! 165:
! 166: /**
! 167: * Add a certificate the the cache. Returns a reference to "cert" or a
! 168: * previously cached certificate that equals "cert".
! 169: */
! 170: static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
! 171: certificate_t *cert)
! 172: {
! 173: certificate_t *cached;
! 174: this->lock->write_lock(this->lock);
! 175: if (this->untrusted->find_first(this->untrusted, certificate_equals,
! 176: (void**)&cached, cert))
! 177: {
! 178: cert->destroy(cert);
! 179: cert = cached->get_ref(cached);
! 180: }
! 181: else
! 182: {
! 183: if (trusted)
! 184: {
! 185: this->trusted->insert_first(this->trusted, cert->get_ref(cert));
! 186: }
! 187: this->untrusted->insert_first(this->untrusted, cert->get_ref(cert));
! 188: }
! 189: this->lock->unlock(this->lock);
! 190: return cert;
! 191: }
! 192:
! 193: METHOD(mem_cred_t, add_cert, void,
! 194: private_mem_cred_t *this, bool trusted, certificate_t *cert)
! 195: {
! 196: certificate_t *cached = add_cert_internal(this, trusted, cert);
! 197: cached->destroy(cached);
! 198: }
! 199:
! 200: METHOD(mem_cred_t, add_cert_ref, certificate_t*,
! 201: private_mem_cred_t *this, bool trusted, certificate_t *cert)
! 202: {
! 203: return add_cert_internal(this, trusted, cert);
! 204: }
! 205:
! 206: METHOD(mem_cred_t, get_cert_ref, certificate_t*,
! 207: private_mem_cred_t *this, certificate_t *cert)
! 208: {
! 209: certificate_t *cached;
! 210:
! 211: this->lock->read_lock(this->lock);
! 212: if (this->untrusted->find_first(this->untrusted, certificate_equals,
! 213: (void**)&cached, cert))
! 214: {
! 215: cert->destroy(cert);
! 216: cert = cached->get_ref(cached);
! 217: }
! 218: this->lock->unlock(this->lock);
! 219:
! 220: return cert;
! 221: }
! 222:
! 223: METHOD(mem_cred_t, add_crl, bool,
! 224: private_mem_cred_t *this, crl_t *crl)
! 225: {
! 226: certificate_t *current, *cert = &crl->certificate;
! 227: enumerator_t *enumerator;
! 228: bool new = TRUE;
! 229:
! 230: this->lock->write_lock(this->lock);
! 231: enumerator = this->untrusted->create_enumerator(this->untrusted);
! 232: while (enumerator->enumerate(enumerator, (void**)¤t))
! 233: {
! 234: if (current->get_type(current) == CERT_X509_CRL)
! 235: {
! 236: chunk_t base;
! 237: bool found = FALSE;
! 238: crl_t *crl_c = (crl_t*)current;
! 239: chunk_t authkey = crl->get_authKeyIdentifier(crl);
! 240: chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c);
! 241:
! 242: /* compare authorityKeyIdentifiers if available */
! 243: if (chunk_equals(authkey, authkey_c))
! 244: {
! 245: found = TRUE;
! 246: }
! 247: else
! 248: {
! 249: identification_t *issuer = cert->get_issuer(cert);
! 250: identification_t *issuer_c = current->get_issuer(current);
! 251:
! 252: /* otherwise compare issuer distinguished names */
! 253: if (issuer->equals(issuer, issuer_c))
! 254: {
! 255: found = TRUE;
! 256: }
! 257: }
! 258: if (found)
! 259: {
! 260: /* we keep at most one delta CRL for each base CRL */
! 261: if (crl->is_delta_crl(crl, &base))
! 262: {
! 263: if (!crl_c->is_delta_crl(crl_c, NULL))
! 264: {
! 265: if (chunk_equals(base, crl_c->get_serial(crl_c)))
! 266: { /* keep the added delta and the existing base CRL
! 267: * but check if this is the newest delta CRL for
! 268: * the same base */
! 269: continue;
! 270: }
! 271: }
! 272: }
! 273: else if (crl_c->is_delta_crl(crl_c, &base))
! 274: {
! 275: if (chunk_equals(base, crl->get_serial(crl)))
! 276: { /* keep the existing delta and the added base CRL,
! 277: * but check if we don't store it already */
! 278: continue;
! 279: }
! 280: }
! 281: new = crl_is_newer(crl, crl_c);
! 282: if (!new)
! 283: {
! 284: cert->destroy(cert);
! 285: break;
! 286: }
! 287: /* we remove the existing older CRL but there might be other
! 288: * delta or base CRLs we can replace */
! 289: this->untrusted->remove_at(this->untrusted, enumerator);
! 290: current->destroy(current);
! 291: }
! 292: }
! 293: }
! 294: enumerator->destroy(enumerator);
! 295:
! 296: if (new)
! 297: {
! 298: this->untrusted->insert_first(this->untrusted, cert);
! 299: }
! 300: this->lock->unlock(this->lock);
! 301: return new;
! 302: }
! 303:
! 304: /**
! 305: * Data for key enumerator
! 306: */
! 307: typedef struct {
! 308: rwlock_t *lock;
! 309: key_type_t type;
! 310: identification_t *id;
! 311: } key_data_t;
! 312:
! 313: CALLBACK(key_data_destroy, void,
! 314: key_data_t *data)
! 315: {
! 316: data->lock->unlock(data->lock);
! 317: free(data);
! 318: }
! 319:
! 320: CALLBACK(key_filter, bool,
! 321: key_data_t *data, enumerator_t *orig, va_list args)
! 322: {
! 323: private_key_t *key, **out;
! 324:
! 325: VA_ARGS_VGET(args, out);
! 326:
! 327: while (orig->enumerate(orig, &key))
! 328: {
! 329: if (data->type == KEY_ANY || data->type == key->get_type(key))
! 330: {
! 331: if (data->id == NULL ||
! 332: key->has_fingerprint(key, data->id->get_encoding(data->id)))
! 333: {
! 334: *out = key;
! 335: return TRUE;
! 336: }
! 337: }
! 338: }
! 339: return FALSE;
! 340: }
! 341:
! 342: METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
! 343: private_mem_cred_t *this, key_type_t type, identification_t *id)
! 344: {
! 345: key_data_t *data;
! 346:
! 347: INIT(data,
! 348: .lock = this->lock,
! 349: .type = type,
! 350: .id = id,
! 351: );
! 352: this->lock->read_lock(this->lock);
! 353: return enumerator_create_filter(this->keys->create_enumerator(this->keys),
! 354: key_filter, data, key_data_destroy);
! 355: }
! 356:
! 357: METHOD(mem_cred_t, add_key, void,
! 358: private_mem_cred_t *this, private_key_t *key)
! 359: {
! 360: enumerator_t *enumerator;
! 361: private_key_t *current;
! 362:
! 363: this->lock->write_lock(this->lock);
! 364:
! 365: enumerator = this->keys->create_enumerator(this->keys);
! 366: while (enumerator->enumerate(enumerator, ¤t))
! 367: {
! 368: if (current->equals(current, key))
! 369: {
! 370: this->keys->remove_at(this->keys, enumerator);
! 371: current->destroy(current);
! 372: break;
! 373: }
! 374: }
! 375: enumerator->destroy(enumerator);
! 376:
! 377: this->keys->insert_first(this->keys, key);
! 378:
! 379: this->lock->unlock(this->lock);
! 380: }
! 381:
! 382: METHOD(mem_cred_t, remove_key, bool,
! 383: private_mem_cred_t *this, chunk_t fp)
! 384: {
! 385: enumerator_t *enumerator;
! 386: private_key_t *current;
! 387: bool found = FALSE;
! 388:
! 389: this->lock->write_lock(this->lock);
! 390:
! 391: enumerator = this->keys->create_enumerator(this->keys);
! 392: while (enumerator->enumerate(enumerator, ¤t))
! 393: {
! 394: if (current->has_fingerprint(current, fp))
! 395: {
! 396: this->keys->remove_at(this->keys, enumerator);
! 397: current->destroy(current);
! 398: found = TRUE;
! 399: break;
! 400: }
! 401: }
! 402: enumerator->destroy(enumerator);
! 403:
! 404: this->lock->unlock(this->lock);
! 405: return found;
! 406: }
! 407:
! 408: /**
! 409: * Shared key entry
! 410: */
! 411: typedef struct {
! 412: /** shared key */
! 413: shared_key_t *shared;
! 414: /** list of owners, identification_t */
! 415: linked_list_t *owners;
! 416: /** optional unique identifier */
! 417: char *id;
! 418: } shared_entry_t;
! 419:
! 420: /**
! 421: * Clean up a shared entry
! 422: */
! 423: static void shared_entry_destroy(shared_entry_t *entry)
! 424: {
! 425: entry->owners->destroy_offset(entry->owners,
! 426: offsetof(identification_t, destroy));
! 427: entry->shared->destroy(entry->shared);
! 428: free(entry->id);
! 429: free(entry);
! 430: }
! 431:
! 432: /**
! 433: * Check if two shared key entries are equal (ignoring the unique identifier)
! 434: */
! 435: static bool shared_entry_equals(shared_entry_t *a, shared_entry_t *b)
! 436: {
! 437: enumerator_t *e1, *e2;
! 438: identification_t *id1, *id2;
! 439: bool equals = TRUE;
! 440:
! 441: if (a->shared->get_type(a->shared) != b->shared->get_type(b->shared))
! 442: {
! 443: return FALSE;
! 444: }
! 445: if (!chunk_equals(a->shared->get_key(a->shared),
! 446: b->shared->get_key(b->shared)))
! 447: {
! 448: return FALSE;
! 449: }
! 450: if (a->owners->get_count(a->owners) != b->owners->get_count(b->owners))
! 451: {
! 452: return FALSE;
! 453: }
! 454: e1 = a->owners->create_enumerator(a->owners);
! 455: e2 = b->owners->create_enumerator(b->owners);
! 456: while (e1->enumerate(e1, &id1) && e2->enumerate(e2, &id2))
! 457: {
! 458: if (!id1->equals(id1, id2))
! 459: {
! 460: equals = FALSE;
! 461: break;
! 462: }
! 463: }
! 464: e1->destroy(e1);
! 465: e2->destroy(e2);
! 466:
! 467: return equals;
! 468: }
! 469:
! 470: /**
! 471: * Data for the shared_key enumerator
! 472: */
! 473: typedef struct {
! 474: rwlock_t *lock;
! 475: identification_t *me;
! 476: identification_t *other;
! 477: shared_key_type_t type;
! 478: } shared_data_t;
! 479:
! 480: CALLBACK(shared_data_destroy, void,
! 481: shared_data_t *data)
! 482: {
! 483: data->lock->unlock(data->lock);
! 484: free(data);
! 485: }
! 486:
! 487: /**
! 488: * Get the best match of an owner in an entry.
! 489: */
! 490: static id_match_t has_owner(shared_entry_t *entry, identification_t *owner)
! 491: {
! 492: enumerator_t *enumerator;
! 493: id_match_t match, best = ID_MATCH_NONE;
! 494: identification_t *current;
! 495:
! 496: enumerator = entry->owners->create_enumerator(entry->owners);
! 497: while (enumerator->enumerate(enumerator, ¤t))
! 498: {
! 499: match = owner->matches(owner, current);
! 500: if (match > best)
! 501: {
! 502: best = match;
! 503: }
! 504: }
! 505: enumerator->destroy(enumerator);
! 506: return best;
! 507: }
! 508:
! 509: CALLBACK(shared_filter, bool,
! 510: shared_data_t *data, enumerator_t *orig, va_list args)
! 511: {
! 512: id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
! 513: shared_entry_t *entry;
! 514: shared_key_t **out;
! 515: id_match_t *me, *other;
! 516:
! 517: VA_ARGS_VGET(args, out, me, other);
! 518:
! 519: while (orig->enumerate(orig, &entry))
! 520: {
! 521: if (data->type != SHARED_ANY &&
! 522: entry->shared->get_type(entry->shared) != data->type)
! 523: {
! 524: continue;
! 525: }
! 526: if (data->me)
! 527: {
! 528: my_match = has_owner(entry, data->me);
! 529: }
! 530: if (data->other)
! 531: {
! 532: other_match = has_owner(entry, data->other);
! 533: }
! 534: if ((data->me || data->other) && (!my_match && !other_match))
! 535: {
! 536: continue;
! 537: }
! 538: *out = entry->shared;
! 539: if (me)
! 540: {
! 541: *me = my_match;
! 542: }
! 543: if (other)
! 544: {
! 545: *other = other_match;
! 546: }
! 547: return TRUE;
! 548: }
! 549: return FALSE;
! 550: }
! 551:
! 552: METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
! 553: private_mem_cred_t *this, shared_key_type_t type,
! 554: identification_t *me, identification_t *other)
! 555: {
! 556: shared_data_t *data;
! 557:
! 558: INIT(data,
! 559: .lock = this->lock,
! 560: .me = me,
! 561: .other = other,
! 562: .type = type,
! 563: );
! 564: data->lock->read_lock(data->lock);
! 565: return enumerator_create_filter(
! 566: this->shared->create_enumerator(this->shared),
! 567: shared_filter, data, shared_data_destroy);
! 568: }
! 569:
! 570: METHOD(mem_cred_t, add_shared_unique, void,
! 571: private_mem_cred_t *this, char *id, shared_key_t *shared,
! 572: linked_list_t* owners)
! 573: {
! 574: shared_entry_t *current, *new;
! 575: enumerator_t *enumerator;
! 576:
! 577: INIT(new,
! 578: .shared = shared,
! 579: .owners = owners,
! 580: .id = strdupnull(id),
! 581: );
! 582:
! 583: this->lock->write_lock(this->lock);
! 584:
! 585: enumerator = this->shared->create_enumerator(this->shared);
! 586: while (enumerator->enumerate(enumerator, ¤t))
! 587: {
! 588: /* always replace keys with the same unique identifier, only compare
! 589: * them if both have no unique id assigned */
! 590: if ((id && streq(id, current->id)) ||
! 591: (!id && !current->id && shared_entry_equals(current, new)))
! 592: {
! 593: this->shared->remove_at(this->shared, enumerator);
! 594: shared_entry_destroy(current);
! 595: break;
! 596: }
! 597: }
! 598: enumerator->destroy(enumerator);
! 599:
! 600: this->shared->insert_first(this->shared, new);
! 601:
! 602: this->lock->unlock(this->lock);
! 603: }
! 604:
! 605: METHOD(mem_cred_t, add_shared_list, void,
! 606: private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners)
! 607: {
! 608: add_shared_unique(this, NULL, shared, owners);
! 609: }
! 610:
! 611: METHOD(mem_cred_t, add_shared, void,
! 612: private_mem_cred_t *this, shared_key_t *shared, ...)
! 613: {
! 614: identification_t *id;
! 615: linked_list_t *owners = linked_list_create();
! 616: va_list args;
! 617:
! 618: va_start(args, shared);
! 619: do
! 620: {
! 621: id = va_arg(args, identification_t*);
! 622: if (id)
! 623: {
! 624: owners->insert_first(owners, id);
! 625: }
! 626: }
! 627: while (id);
! 628: va_end(args);
! 629:
! 630: add_shared_list(this, shared, owners);
! 631: }
! 632:
! 633: METHOD(mem_cred_t, remove_shared_unique, void,
! 634: private_mem_cred_t *this, char *id)
! 635: {
! 636: enumerator_t *enumerator;
! 637: shared_entry_t *current;
! 638:
! 639: if (!id)
! 640: {
! 641: return;
! 642: }
! 643:
! 644: this->lock->write_lock(this->lock);
! 645:
! 646: enumerator = this->shared->create_enumerator(this->shared);
! 647: while (enumerator->enumerate(enumerator, ¤t))
! 648: {
! 649: if (streq(id, current->id))
! 650: {
! 651: this->shared->remove_at(this->shared, enumerator);
! 652: shared_entry_destroy(current);
! 653: break;
! 654: }
! 655: }
! 656: enumerator->destroy(enumerator);
! 657:
! 658: this->lock->unlock(this->lock);
! 659: }
! 660:
! 661: CALLBACK(unique_filter, bool,
! 662: void *unused, enumerator_t *orig, va_list args)
! 663: {
! 664: shared_entry_t *entry;
! 665: char **id;
! 666:
! 667: VA_ARGS_VGET(args, id);
! 668:
! 669: while (orig->enumerate(orig, &entry))
! 670: {
! 671: if (!entry->id)
! 672: {
! 673: continue;
! 674: }
! 675: if (id)
! 676: {
! 677: *id = entry->id;
! 678: }
! 679: return TRUE;
! 680: }
! 681: return FALSE;
! 682: }
! 683:
! 684: METHOD(mem_cred_t, create_unique_shared_enumerator, enumerator_t*,
! 685: private_mem_cred_t *this)
! 686: {
! 687: this->lock->read_lock(this->lock);
! 688: return enumerator_create_filter(
! 689: this->shared->create_enumerator(this->shared),
! 690: unique_filter, this->lock,
! 691: (void*)this->lock->unlock);
! 692: }
! 693:
! 694: /**
! 695: * Certificate distribution point
! 696: */
! 697: typedef struct {
! 698: certificate_type_t type;
! 699: identification_t *id;
! 700: char *uri;
! 701: } cdp_t;
! 702:
! 703: /**
! 704: * Destroy a CDP entry
! 705: */
! 706: static void cdp_destroy(cdp_t *this)
! 707: {
! 708: this->id->destroy(this->id);
! 709: free(this->uri);
! 710: free(this);
! 711: }
! 712:
! 713: METHOD(mem_cred_t, add_cdp, void,
! 714: private_mem_cred_t *this, certificate_type_t type,
! 715: identification_t *id, char *uri)
! 716: {
! 717: cdp_t *cdp;
! 718:
! 719: INIT(cdp,
! 720: .type = type,
! 721: .id = id->clone(id),
! 722: .uri = strdup(uri),
! 723: );
! 724: this->lock->write_lock(this->lock);
! 725: this->cdps->insert_last(this->cdps, cdp);
! 726: this->lock->unlock(this->lock);
! 727: }
! 728:
! 729: /**
! 730: * CDP enumerator data
! 731: */
! 732: typedef struct {
! 733: certificate_type_t type;
! 734: identification_t *id;
! 735: rwlock_t *lock;
! 736: } cdp_data_t;
! 737:
! 738: CALLBACK(cdp_data_destroy, void,
! 739: cdp_data_t *data)
! 740: {
! 741: data->lock->unlock(data->lock);
! 742: free(data);
! 743: }
! 744:
! 745: CALLBACK(cdp_filter, bool,
! 746: cdp_data_t *data, enumerator_t *orig, va_list args)
! 747: {
! 748: cdp_t *cdp;
! 749: char **uri;
! 750:
! 751: VA_ARGS_VGET(args, uri);
! 752:
! 753: while (orig->enumerate(orig, &cdp))
! 754: {
! 755: if (data->type != CERT_ANY && data->type != cdp->type)
! 756: {
! 757: continue;
! 758: }
! 759: if (data->id && !cdp->id->matches(cdp->id, data->id))
! 760: {
! 761: continue;
! 762: }
! 763: *uri = cdp->uri;
! 764: return TRUE;
! 765: }
! 766: return FALSE;
! 767: }
! 768:
! 769: METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
! 770: private_mem_cred_t *this, certificate_type_t type, identification_t *id)
! 771: {
! 772: cdp_data_t *data;
! 773:
! 774: INIT(data,
! 775: .type = type,
! 776: .id = id,
! 777: .lock = this->lock,
! 778: );
! 779: this->lock->read_lock(this->lock);
! 780: return enumerator_create_filter(this->cdps->create_enumerator(this->cdps),
! 781: cdp_filter, data, cdp_data_destroy);
! 782:
! 783: }
! 784:
! 785: static void reset_certs(private_mem_cred_t *this)
! 786: {
! 787: this->trusted->destroy_offset(this->trusted,
! 788: offsetof(certificate_t, destroy));
! 789: this->untrusted->destroy_offset(this->untrusted,
! 790: offsetof(certificate_t, destroy));
! 791: this->trusted = linked_list_create();
! 792: this->untrusted = linked_list_create();
! 793: }
! 794:
! 795: static void copy_certs(linked_list_t *dst, linked_list_t *src, bool clone)
! 796: {
! 797: enumerator_t *enumerator;
! 798: certificate_t *cert;
! 799:
! 800: enumerator = src->create_enumerator(src);
! 801: while (enumerator->enumerate(enumerator, &cert))
! 802: {
! 803: if (clone)
! 804: {
! 805: cert = cert->get_ref(cert);
! 806: }
! 807: else
! 808: {
! 809: src->remove_at(src, enumerator);
! 810: }
! 811: dst->insert_last(dst, cert);
! 812: }
! 813: enumerator->destroy(enumerator);
! 814: }
! 815:
! 816: METHOD(mem_cred_t, replace_certs, void,
! 817: private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
! 818: {
! 819: private_mem_cred_t *other = (private_mem_cred_t*)other_set;
! 820:
! 821: this->lock->write_lock(this->lock);
! 822: reset_certs(this);
! 823: copy_certs(this->untrusted, other->untrusted, clone);
! 824: copy_certs(this->trusted, other->trusted, clone);
! 825: this->lock->unlock(this->lock);
! 826: }
! 827:
! 828: static void reset_secrets(private_mem_cred_t *this)
! 829: {
! 830: this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
! 831: this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
! 832: this->keys = linked_list_create();
! 833: this->shared = linked_list_create();
! 834: }
! 835:
! 836: METHOD(mem_cred_t, replace_secrets, void,
! 837: private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
! 838: {
! 839: private_mem_cred_t *other = (private_mem_cred_t*)other_set;
! 840: enumerator_t *enumerator;
! 841: shared_entry_t *entry, *new_entry;
! 842: private_key_t *key;
! 843:
! 844: this->lock->write_lock(this->lock);
! 845:
! 846: reset_secrets(this);
! 847:
! 848: if (clone)
! 849: {
! 850: enumerator = other->keys->create_enumerator(other->keys);
! 851: while (enumerator->enumerate(enumerator, &key))
! 852: {
! 853: this->keys->insert_last(this->keys, key->get_ref(key));
! 854: }
! 855: enumerator->destroy(enumerator);
! 856: enumerator = other->shared->create_enumerator(other->shared);
! 857: while (enumerator->enumerate(enumerator, &entry))
! 858: {
! 859: INIT(new_entry,
! 860: .shared = entry->shared->get_ref(entry->shared),
! 861: .owners = entry->owners->clone_offset(entry->owners,
! 862: offsetof(identification_t, clone)),
! 863: );
! 864: this->shared->insert_last(this->shared, new_entry);
! 865: }
! 866: enumerator->destroy(enumerator);
! 867: }
! 868: else
! 869: {
! 870: while (other->keys->remove_first(other->keys, (void**)&key) == SUCCESS)
! 871: {
! 872: this->keys->insert_last(this->keys, key);
! 873: }
! 874: while (other->shared->remove_first(other->shared,
! 875: (void**)&entry) == SUCCESS)
! 876: {
! 877: this->shared->insert_last(this->shared, entry);
! 878: }
! 879: }
! 880: this->lock->unlock(this->lock);
! 881: }
! 882:
! 883: METHOD(mem_cred_t, clear_secrets, void,
! 884: private_mem_cred_t *this)
! 885: {
! 886: this->lock->write_lock(this->lock);
! 887: reset_secrets(this);
! 888: this->lock->unlock(this->lock);
! 889: }
! 890:
! 891: METHOD(mem_cred_t, clear_, void,
! 892: private_mem_cred_t *this)
! 893: {
! 894: this->lock->write_lock(this->lock);
! 895: this->cdps->destroy_function(this->cdps, (void*)cdp_destroy);
! 896: this->cdps = linked_list_create();
! 897: reset_certs(this);
! 898: reset_secrets(this);
! 899: this->lock->unlock(this->lock);
! 900: }
! 901:
! 902: METHOD(mem_cred_t, destroy, void,
! 903: private_mem_cred_t *this)
! 904: {
! 905: clear_(this);
! 906: this->trusted->destroy(this->trusted);
! 907: this->untrusted->destroy(this->untrusted);
! 908: this->keys->destroy(this->keys);
! 909: this->shared->destroy(this->shared);
! 910: this->cdps->destroy(this->cdps);
! 911: this->lock->destroy(this->lock);
! 912: free(this);
! 913: }
! 914:
! 915: /**
! 916: * See header
! 917: */
! 918: mem_cred_t *mem_cred_create()
! 919: {
! 920: private_mem_cred_t *this;
! 921:
! 922: INIT(this,
! 923: .public = {
! 924: .set = {
! 925: .create_shared_enumerator = _create_shared_enumerator,
! 926: .create_private_enumerator = _create_private_enumerator,
! 927: .create_cert_enumerator = _create_cert_enumerator,
! 928: .create_cdp_enumerator = _create_cdp_enumerator,
! 929: .cache_cert = (void*)nop,
! 930: },
! 931: .add_cert = _add_cert,
! 932: .add_cert_ref = _add_cert_ref,
! 933: .get_cert_ref = _get_cert_ref,
! 934: .add_crl = _add_crl,
! 935: .add_key = _add_key,
! 936: .remove_key = _remove_key,
! 937: .add_shared = _add_shared,
! 938: .add_shared_list = _add_shared_list,
! 939: .add_shared_unique = _add_shared_unique,
! 940: .remove_shared_unique = _remove_shared_unique,
! 941: .create_unique_shared_enumerator = _create_unique_shared_enumerator,
! 942: .add_cdp = _add_cdp,
! 943: .replace_certs = _replace_certs,
! 944: .replace_secrets = _replace_secrets,
! 945: .clear = _clear_,
! 946: .clear_secrets = _clear_secrets,
! 947: .destroy = _destroy,
! 948: },
! 949: .trusted = linked_list_create(),
! 950: .untrusted = linked_list_create(),
! 951: .keys = linked_list_create(),
! 952: .shared = linked_list_create(),
! 953: .cdps = linked_list_create(),
! 954: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
! 955: );
! 956:
! 957: return &this->public;
! 958: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>