Annotation of embedaddon/strongswan/src/libstrongswan/credentials/sets/mem_cred.c, revision 1.1.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**)&current))
                    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, &current))
                    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, &current))
                    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, &current))
                    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, &current))
                    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, &current))
                    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>