Annotation of embedaddon/strongswan/src/libstrongswan/credentials/sets/mem_cred.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>