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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2010-2016 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2010 Martin Willi
        !             6:  * Copyright (C) 2010 revosec AG
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include "mem_cred.h"
        !            20: 
        !            21: #include <threading/rwlock.h>
        !            22: #include <collections/linked_list.h>
        !            23: 
        !            24: typedef struct private_mem_cred_t private_mem_cred_t;
        !            25: 
        !            26: /**
        !            27:  * Private data of an mem_cred_t object.
        !            28:  */
        !            29: struct private_mem_cred_t {
        !            30: 
        !            31:        /**
        !            32:         * Public mem_cred_t interface.
        !            33:         */
        !            34:        mem_cred_t public;
        !            35: 
        !            36:        /**
        !            37:         * Lock for this set
        !            38:         */
        !            39:        rwlock_t *lock;
        !            40: 
        !            41:        /**
        !            42:         * List of trusted certificates, certificate_t
        !            43:         */
        !            44:        linked_list_t *trusted;
        !            45: 
        !            46:        /**
        !            47:         * List of trusted and untrusted certificates, certificate_t
        !            48:         */
        !            49:        linked_list_t *untrusted;
        !            50: 
        !            51:        /**
        !            52:         * List of private keys, private_key_t
        !            53:         */
        !            54:        linked_list_t *keys;
        !            55: 
        !            56:        /**
        !            57:         * List of shared keys, as shared_entry_t
        !            58:         */
        !            59:        linked_list_t *shared;
        !            60: 
        !            61:        /**
        !            62:         * List of CDPs, as cdp_t
        !            63:         */
        !            64:        linked_list_t *cdps;
        !            65: };
        !            66: 
        !            67: /**
        !            68:  * Data for the certificate enumerator
        !            69:  */
        !            70: typedef struct {
        !            71:        rwlock_t *lock;
        !            72:        certificate_type_t cert;
        !            73:        key_type_t key;
        !            74:        identification_t *id;
        !            75: } cert_data_t;
        !            76: 
        !            77: CALLBACK(cert_data_destroy, void,
        !            78:        cert_data_t *data)
        !            79: {
        !            80:        data->lock->unlock(data->lock);
        !            81:        free(data);
        !            82: }
        !            83: 
        !            84: CALLBACK(certs_filter, bool,
        !            85:        cert_data_t *data, enumerator_t *orig, va_list args)
        !            86: {
        !            87:        public_key_t *public;
        !            88:        certificate_t *cert, **out;
        !            89: 
        !            90:        VA_ARGS_VGET(args, out);
        !            91: 
        !            92:        while (orig->enumerate(orig, &cert))
        !            93:        {
        !            94:                if (data->cert != CERT_ANY && data->cert != cert->get_type(cert))
        !            95:                {
        !            96:                        continue;
        !            97:                }
        !            98:                public = cert->get_public_key(cert);
        !            99:                if (public)
        !           100:                {
        !           101:                        if (data->key == KEY_ANY || data->key == public->get_type(public))
        !           102:                        {
        !           103:                                if (data->id && public->has_fingerprint(public,
        !           104:                                                                                        data->id->get_encoding(data->id)))
        !           105:                                {
        !           106:                                        public->destroy(public);
        !           107:                                        *out = cert;
        !           108:                                        return TRUE;
        !           109:                                }
        !           110:                        }
        !           111:                        else
        !           112:                        {
        !           113:                                public->destroy(public);
        !           114:                                continue;
        !           115:                        }
        !           116:                        public->destroy(public);
        !           117:                }
        !           118:                else if (data->key != KEY_ANY)
        !           119:                {
        !           120:                        continue;
        !           121:                }
        !           122:                if (!data->id || cert->has_subject(cert, data->id))
        !           123:                {
        !           124:                        *out = cert;
        !           125:                        return TRUE;
        !           126:                }
        !           127:        }
        !           128:        return FALSE;
        !           129: }
        !           130: 
        !           131: METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
        !           132:        private_mem_cred_t *this, certificate_type_t cert, key_type_t key,
        !           133:        identification_t *id, bool trusted)
        !           134: {
        !           135:        cert_data_t *data;
        !           136:        enumerator_t *enumerator;
        !           137: 
        !           138:        INIT(data,
        !           139:                .lock = this->lock,
        !           140:                .cert = cert,
        !           141:                .key = key,
        !           142:                .id = id,
        !           143:        );
        !           144:        this->lock->read_lock(this->lock);
        !           145:        if (trusted)
        !           146:        {
        !           147:                enumerator = this->trusted->create_enumerator(this->trusted);
        !           148:        }
        !           149:        else
        !           150:        {
        !           151:                enumerator = this->untrusted->create_enumerator(this->untrusted);
        !           152:        }
        !           153:        return enumerator_create_filter(enumerator, certs_filter, data,
        !           154:                                                                        cert_data_destroy);
        !           155: }
        !           156: 
        !           157: CALLBACK(certificate_equals, bool,
        !           158:        certificate_t *item, va_list args)
        !           159: {
        !           160:        certificate_t *cert;
        !           161: 
        !           162:        VA_ARGS_VGET(args, cert);
        !           163:        return item->equals(item, cert);
        !           164: }
        !           165: 
        !           166: /**
        !           167:  * Add a certificate the the cache. Returns a reference to "cert" or a
        !           168:  * previously cached certificate that equals "cert".
        !           169:  */
        !           170: static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
        !           171:                                                                                certificate_t *cert)
        !           172: {
        !           173:        certificate_t *cached;
        !           174:        this->lock->write_lock(this->lock);
        !           175:        if (this->untrusted->find_first(this->untrusted, certificate_equals,
        !           176:                                                                        (void**)&cached, cert))
        !           177:        {
        !           178:                cert->destroy(cert);
        !           179:                cert = cached->get_ref(cached);
        !           180:        }
        !           181:        else
        !           182:        {
        !           183:                if (trusted)
        !           184:                {
        !           185:                        this->trusted->insert_first(this->trusted, cert->get_ref(cert));
        !           186:                }
        !           187:                this->untrusted->insert_first(this->untrusted, cert->get_ref(cert));
        !           188:        }
        !           189:        this->lock->unlock(this->lock);
        !           190:        return cert;
        !           191: }
        !           192: 
        !           193: METHOD(mem_cred_t, add_cert, void,
        !           194:        private_mem_cred_t *this, bool trusted, certificate_t *cert)
        !           195: {
        !           196:        certificate_t *cached = add_cert_internal(this, trusted, cert);
        !           197:        cached->destroy(cached);
        !           198: }
        !           199: 
        !           200: METHOD(mem_cred_t, add_cert_ref, certificate_t*,
        !           201:        private_mem_cred_t *this, bool trusted, certificate_t *cert)
        !           202: {
        !           203:        return add_cert_internal(this, trusted, cert);
        !           204: }
        !           205: 
        !           206: METHOD(mem_cred_t, get_cert_ref, certificate_t*,
        !           207:        private_mem_cred_t *this, certificate_t *cert)
        !           208: {
        !           209:        certificate_t *cached;
        !           210: 
        !           211:        this->lock->read_lock(this->lock);
        !           212:        if (this->untrusted->find_first(this->untrusted, certificate_equals,
        !           213:                                                                        (void**)&cached, cert))
        !           214:        {
        !           215:                cert->destroy(cert);
        !           216:                cert = cached->get_ref(cached);
        !           217:        }
        !           218:        this->lock->unlock(this->lock);
        !           219: 
        !           220:        return cert;
        !           221: }
        !           222: 
        !           223: METHOD(mem_cred_t, add_crl, bool,
        !           224:        private_mem_cred_t *this, crl_t *crl)
        !           225: {
        !           226:        certificate_t *current, *cert = &crl->certificate;
        !           227:        enumerator_t *enumerator;
        !           228:        bool new = TRUE;
        !           229: 
        !           230:        this->lock->write_lock(this->lock);
        !           231:        enumerator = this->untrusted->create_enumerator(this->untrusted);
        !           232:        while (enumerator->enumerate(enumerator, (void**)&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>