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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2015 Tobias Brunner
        !             3:  * Copyright (C) 2007 Martin Willi
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #include "credential_manager.h"
        !            18: 
        !            19: #include <library.h>
        !            20: #include <utils/debug.h>
        !            21: #include <threading/thread_value.h>
        !            22: #include <threading/mutex.h>
        !            23: #include <threading/rwlock.h>
        !            24: #include <collections/linked_list.h>
        !            25: #include <credentials/sets/cert_cache.h>
        !            26: #include <credentials/sets/auth_cfg_wrapper.h>
        !            27: #include <credentials/certificates/x509.h>
        !            28: 
        !            29: /**
        !            30:  * Maximum length of a certificate trust chain
        !            31:  */
        !            32: #define MAX_TRUST_PATH_LEN 7
        !            33: 
        !            34: typedef struct private_credential_manager_t private_credential_manager_t;
        !            35: 
        !            36: /**
        !            37:  * private data of credential_manager
        !            38:  */
        !            39: struct private_credential_manager_t {
        !            40: 
        !            41:        /**
        !            42:         * public functions
        !            43:         */
        !            44:        credential_manager_t public;
        !            45: 
        !            46:        /**
        !            47:         * list of credential sets
        !            48:         */
        !            49:        linked_list_t *sets;
        !            50: 
        !            51:        /**
        !            52:         * thread local set of credentials, linked_list_t with credential_set_t's
        !            53:         */
        !            54:        thread_value_t *local_sets;
        !            55: 
        !            56:        /**
        !            57:         * Exclusive local sets, linked_list_t with credential_set_t
        !            58:         */
        !            59:        thread_value_t *exclusive_local_sets;
        !            60: 
        !            61:        /**
        !            62:         * trust relationship and certificate cache
        !            63:         */
        !            64:        cert_cache_t *cache;
        !            65: 
        !            66:        /**
        !            67:         * certificates queued for persistent caching
        !            68:         */
        !            69:        linked_list_t *cache_queue;
        !            70: 
        !            71:        /**
        !            72:         * list of certificate validators, cert_validator_t
        !            73:         */
        !            74:        linked_list_t *validators;
        !            75: 
        !            76:        /**
        !            77:         * read-write lock to sets list
        !            78:         */
        !            79:        rwlock_t *lock;
        !            80: 
        !            81:        /**
        !            82:         * mutex for cache queue
        !            83:         */
        !            84:        mutex_t *queue_mutex;
        !            85: 
        !            86:        /**
        !            87:         * Registered hook to call on validation errors
        !            88:         */
        !            89:        credential_hook_t hook;
        !            90: 
        !            91:        /**
        !            92:         * Registered data to pass to hook
        !            93:         */
        !            94:        void *hook_data;
        !            95: };
        !            96: 
        !            97: /** data to pass to create_private_enumerator */
        !            98: typedef struct {
        !            99:        private_credential_manager_t *this;
        !           100:        key_type_t type;
        !           101:        identification_t* keyid;
        !           102: } private_data_t;
        !           103: 
        !           104: /** data to pass to create_cert_enumerator */
        !           105: typedef struct {
        !           106:        private_credential_manager_t *this;
        !           107:        certificate_type_t cert;
        !           108:        key_type_t key;
        !           109:        identification_t *id;
        !           110:        bool trusted;
        !           111: } cert_data_t;
        !           112: 
        !           113: /** data to pass to create_cdp_enumerator */
        !           114: typedef struct {
        !           115:        private_credential_manager_t *this;
        !           116:        certificate_type_t type;
        !           117:        identification_t *id;
        !           118: } cdp_data_t;
        !           119: 
        !           120: /** data to pass to create_shared_enumerator */
        !           121: typedef struct {
        !           122:        private_credential_manager_t *this;
        !           123:        shared_key_type_t type;
        !           124:        identification_t *me;
        !           125:        identification_t *other;
        !           126: } shared_data_t;
        !           127: 
        !           128: /** enumerator over local and global sets */
        !           129: typedef struct {
        !           130:        /** implements enumerator_t */
        !           131:        enumerator_t public;
        !           132:        /** enumerator over global sets */
        !           133:        enumerator_t *global;
        !           134:        /** enumerator over local sets */
        !           135:        enumerator_t *local;
        !           136:        /** enumerator over exclusive local sets */
        !           137:        enumerator_t *exclusive;
        !           138: } sets_enumerator_t;
        !           139: 
        !           140: METHOD(credential_manager_t, set_hook, void,
        !           141:        private_credential_manager_t *this, credential_hook_t hook, void *data)
        !           142: {
        !           143:        this->hook = hook;
        !           144:        this->hook_data = data;
        !           145: }
        !           146: 
        !           147: METHOD(credential_manager_t, call_hook, void,
        !           148:        private_credential_manager_t *this, credential_hook_type_t type,
        !           149:        certificate_t *cert)
        !           150: {
        !           151:        if (this->hook)
        !           152:        {
        !           153:                this->hook(this->hook_data, type, cert);
        !           154:        }
        !           155: }
        !           156: 
        !           157: METHOD(enumerator_t, sets_enumerate, bool,
        !           158:        sets_enumerator_t *this, va_list args)
        !           159: {
        !           160:        credential_set_t **set;
        !           161: 
        !           162:        VA_ARGS_VGET(args, set);
        !           163: 
        !           164:        if (this->exclusive)
        !           165:        {
        !           166:                if (this->exclusive->enumerate(this->exclusive, set))
        !           167:                {       /* only enumerate last added */
        !           168:                        this->exclusive->destroy(this->exclusive);
        !           169:                        this->exclusive = NULL;
        !           170:                        return TRUE;
        !           171:                }
        !           172:        }
        !           173:        if (this->local)
        !           174:        {
        !           175:                if (this->local->enumerate(this->local, set))
        !           176:                {
        !           177:                        return TRUE;
        !           178:                }
        !           179:                /* end of local sets, look for global */
        !           180:                this->local->destroy(this->local);
        !           181:                this->local = NULL;
        !           182:        }
        !           183:        if (this->global)
        !           184:        {
        !           185:                return this->global->enumerate(this->global, set);
        !           186:        }
        !           187:        return FALSE;
        !           188: }
        !           189: 
        !           190: METHOD(enumerator_t, sets_destroy, void,
        !           191:        sets_enumerator_t *this)
        !           192: {
        !           193:        DESTROY_IF(this->global);
        !           194:        DESTROY_IF(this->local);
        !           195:        DESTROY_IF(this->exclusive);
        !           196:        free(this);
        !           197: }
        !           198: 
        !           199: /**
        !           200:  * create an enumerator over both, global and local sets
        !           201:  */
        !           202: static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
        !           203: {
        !           204:        sets_enumerator_t *enumerator;
        !           205:        linked_list_t *list;
        !           206: 
        !           207:        INIT(enumerator,
        !           208:                .public = {
        !           209:                        .enumerate = enumerator_enumerate_default,
        !           210:                        .venumerate = _sets_enumerate,
        !           211:                        .destroy = _sets_destroy,
        !           212:                },
        !           213:        );
        !           214: 
        !           215:        list = this->exclusive_local_sets->get(this->exclusive_local_sets);
        !           216:        if (list && list->get_count(list))
        !           217:        {
        !           218:                enumerator->exclusive = list->create_enumerator(list);
        !           219:        }
        !           220:        else
        !           221:        {
        !           222:                enumerator->global = this->sets->create_enumerator(this->sets);
        !           223:                list = this->local_sets->get(this->local_sets);
        !           224:                if (list)
        !           225:                {
        !           226:                        enumerator->local = list->create_enumerator(list);
        !           227:                }
        !           228:        }
        !           229:        return &enumerator->public;
        !           230: }
        !           231: 
        !           232: /**
        !           233:  * cleanup function for cert data
        !           234:  */
        !           235: static void destroy_cert_data(cert_data_t *data)
        !           236: {
        !           237:        data->this->lock->unlock(data->this->lock);
        !           238:        free(data);
        !           239: }
        !           240: 
        !           241: /**
        !           242:  * enumerator constructor for certificates
        !           243:  */
        !           244: static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
        !           245: {
        !           246:        return set->create_cert_enumerator(set, data->cert, data->key,
        !           247:                                                                           data->id, data->trusted);
        !           248: }
        !           249: 
        !           250: METHOD(credential_manager_t, create_cert_enumerator, enumerator_t*,
        !           251:        private_credential_manager_t *this, certificate_type_t certificate,
        !           252:        key_type_t key, identification_t *id, bool trusted)
        !           253: {
        !           254:        cert_data_t *data = malloc_thing(cert_data_t);
        !           255:        data->this = this;
        !           256:        data->cert = certificate;
        !           257:        data->key = key;
        !           258:        data->id = id;
        !           259:        data->trusted = trusted;
        !           260: 
        !           261:        this->lock->read_lock(this->lock);
        !           262:        return enumerator_create_nested(create_sets_enumerator(this),
        !           263:                                                                        (void*)create_cert, data,
        !           264:                                                                        (void*)destroy_cert_data);
        !           265: }
        !           266: 
        !           267: METHOD(credential_manager_t, get_cert, certificate_t*,
        !           268:        private_credential_manager_t *this, certificate_type_t cert, key_type_t key,
        !           269:        identification_t *id, bool trusted)
        !           270: {
        !           271:        certificate_t *current, *found = NULL;
        !           272:        enumerator_t *enumerator;
        !           273: 
        !           274:        enumerator = create_cert_enumerator(this, cert, key, id, trusted);
        !           275:        if (enumerator->enumerate(enumerator, &current))
        !           276:        {
        !           277:                /* TODO: best match? order by keyid, subject, subjectAltName */
        !           278:                found = current->get_ref(current);
        !           279:        }
        !           280:        enumerator->destroy(enumerator);
        !           281:        return found;
        !           282: }
        !           283: 
        !           284: 
        !           285: /**
        !           286:  * cleanup function for cdp data
        !           287:  */
        !           288: static void destroy_cdp_data(cdp_data_t *data)
        !           289: {
        !           290:        data->this->lock->unlock(data->this->lock);
        !           291:        free(data);
        !           292: }
        !           293: 
        !           294: /**
        !           295:  * enumerator constructor for CDPs
        !           296:  */
        !           297: static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
        !           298: {
        !           299:        return set->create_cdp_enumerator(set, data->type, data->id);
        !           300: }
        !           301: 
        !           302: METHOD(credential_manager_t, create_cdp_enumerator, enumerator_t*,
        !           303:        private_credential_manager_t *this, certificate_type_t type,
        !           304:        identification_t *id)
        !           305: {
        !           306:        cdp_data_t *data;
        !           307: 
        !           308:        INIT(data,
        !           309:                .this = this,
        !           310:                .type = type,
        !           311:                .id = id,
        !           312:        );
        !           313:        this->lock->read_lock(this->lock);
        !           314:        return enumerator_create_nested(create_sets_enumerator(this),
        !           315:                                                                        (void*)create_cdp, data,
        !           316:                                                                        (void*)destroy_cdp_data);
        !           317: }
        !           318: 
        !           319: /**
        !           320:  * cleanup function for private data
        !           321:  */
        !           322: static void destroy_private_data(private_data_t *data)
        !           323: {
        !           324:        data->this->lock->unlock(data->this->lock);
        !           325:        free(data);
        !           326: }
        !           327: 
        !           328: /**
        !           329:  * enumerator constructor for private keys
        !           330:  */
        !           331: static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
        !           332: {
        !           333:        return set->create_private_enumerator(set, data->type, data->keyid);
        !           334: }
        !           335: 
        !           336: /**
        !           337:  * Create an enumerator over private keys
        !           338:  */
        !           339: static enumerator_t *create_private_enumerator(
        !           340:        private_credential_manager_t *this, key_type_t key, identification_t *keyid)
        !           341: {
        !           342:        private_data_t *data;
        !           343: 
        !           344:        INIT(data,
        !           345:                .this = this,
        !           346:                .type = key,
        !           347:                .keyid = keyid,
        !           348:        );
        !           349:        this->lock->read_lock(this->lock);
        !           350:        return enumerator_create_nested(create_sets_enumerator(this),
        !           351:                                                                        (void*)create_private, data,
        !           352:                                                                        (void*)destroy_private_data);
        !           353: }
        !           354: 
        !           355: /**
        !           356:  * Look up a private key by its key identifier
        !           357:  */
        !           358: static private_key_t* get_private_by_keyid(private_credential_manager_t *this,
        !           359:                                                                        key_type_t key, identification_t *keyid)
        !           360: {
        !           361:        private_key_t *found = NULL;
        !           362:        enumerator_t *enumerator;
        !           363: 
        !           364:        enumerator = create_private_enumerator(this, key, keyid);
        !           365:        if (enumerator->enumerate(enumerator, &found))
        !           366:        {
        !           367:                found->get_ref(found);
        !           368:        }
        !           369:        enumerator->destroy(enumerator);
        !           370:        return found;
        !           371: }
        !           372: 
        !           373: /**
        !           374:  * cleanup function for shared data
        !           375:  */
        !           376: static void destroy_shared_data(shared_data_t *data)
        !           377: {
        !           378:        data->this->lock->unlock(data->this->lock);
        !           379:        free(data);
        !           380: }
        !           381: 
        !           382: /**
        !           383:  * enumerator constructor for shared keys
        !           384:  */
        !           385: static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
        !           386: {
        !           387:        return set->create_shared_enumerator(set, data->type, data->me, data->other);
        !           388: }
        !           389: 
        !           390: METHOD(credential_manager_t, create_shared_enumerator, enumerator_t*,
        !           391:        private_credential_manager_t *this, shared_key_type_t type,
        !           392:        identification_t *me, identification_t *other)
        !           393: {
        !           394:        shared_data_t *data;
        !           395: 
        !           396:        INIT(data,
        !           397:                .this = this,
        !           398:                .type = type,
        !           399:                .me = me,
        !           400:                .other = other,
        !           401:        );
        !           402:        this->lock->read_lock(this->lock);
        !           403:        return enumerator_create_nested(create_sets_enumerator(this),
        !           404:                                                                        (void*)create_shared, data,
        !           405:                                                                        (void*)destroy_shared_data);
        !           406: }
        !           407: 
        !           408: METHOD(credential_manager_t, get_shared, shared_key_t*,
        !           409:        private_credential_manager_t *this, shared_key_type_t type,
        !           410:        identification_t *me, identification_t *other)
        !           411: {
        !           412:        shared_key_t *current, *found = NULL;
        !           413:        id_match_t best_me = ID_MATCH_NONE, best_other = ID_MATCH_NONE;
        !           414:        id_match_t match_me, match_other;
        !           415:        enumerator_t *enumerator;
        !           416: 
        !           417:        enumerator = create_shared_enumerator(this, type, me, other);
        !           418:        while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
        !           419:        {
        !           420:                if (match_other > best_other ||
        !           421:                        (match_other == best_other && match_me > best_me))
        !           422:                {
        !           423:                        DESTROY_IF(found);
        !           424:                        found = current->get_ref(current);
        !           425:                        best_me = match_me;
        !           426:                        best_other = match_other;
        !           427:                }
        !           428:                if (best_me == ID_MATCH_PERFECT && best_other == ID_MATCH_PERFECT)
        !           429:                {
        !           430:                        break;
        !           431:                }
        !           432:        }
        !           433:        enumerator->destroy(enumerator);
        !           434:        return found;
        !           435: }
        !           436: 
        !           437: METHOD(credential_manager_t, add_local_set, void,
        !           438:        private_credential_manager_t *this, credential_set_t *set, bool exclusive)
        !           439: {
        !           440:        linked_list_t *sets;
        !           441:        thread_value_t *tv;
        !           442: 
        !           443:        if (exclusive)
        !           444:        {
        !           445:                tv = this->exclusive_local_sets;
        !           446:        }
        !           447:        else
        !           448:        {
        !           449:                tv = this->local_sets;
        !           450:        }
        !           451:        sets = tv->get(tv);
        !           452:        if (!sets)
        !           453:        {
        !           454:                sets = linked_list_create();
        !           455:                tv->set(tv, sets);
        !           456:        }
        !           457:        if (exclusive)
        !           458:        {
        !           459:                sets->insert_first(sets, set);
        !           460:        }
        !           461:        else
        !           462:        {
        !           463:                sets->insert_last(sets, set);
        !           464:        }
        !           465: }
        !           466: 
        !           467: METHOD(credential_manager_t, remove_local_set, void,
        !           468:        private_credential_manager_t *this, credential_set_t *set)
        !           469: {
        !           470:        linked_list_t *sets;
        !           471:        thread_value_t *tv;
        !           472: 
        !           473:        tv = this->local_sets;
        !           474:        sets = tv->get(tv);
        !           475:        if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
        !           476:        {
        !           477:                tv->set(tv, NULL);
        !           478:                sets->destroy(sets);
        !           479:        }
        !           480:        tv = this->exclusive_local_sets;
        !           481:        sets = tv->get(tv);
        !           482:        if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
        !           483:        {
        !           484:                tv->set(tv, NULL);
        !           485:                sets->destroy(sets);
        !           486:        }
        !           487: }
        !           488: 
        !           489: METHOD(credential_manager_t, issued_by, bool,
        !           490:        private_credential_manager_t *this, certificate_t *subject,
        !           491:        certificate_t *issuer, signature_params_t **scheme)
        !           492: {
        !           493:        if (this->cache)
        !           494:        {
        !           495:                return this->cache->issued_by(this->cache, subject, issuer, scheme);
        !           496:        }
        !           497:        return subject->issued_by(subject, issuer, scheme);
        !           498: }
        !           499: 
        !           500: METHOD(credential_manager_t, cache_cert, void,
        !           501:        private_credential_manager_t *this, certificate_t *cert)
        !           502: {
        !           503:        credential_set_t *set;
        !           504:        enumerator_t *enumerator;
        !           505: 
        !           506:        if (this->lock->try_write_lock(this->lock))
        !           507:        {
        !           508:                enumerator = this->sets->create_enumerator(this->sets);
        !           509:                while (enumerator->enumerate(enumerator, &set))
        !           510:                {
        !           511:                        set->cache_cert(set, cert);
        !           512:                }
        !           513:                enumerator->destroy(enumerator);
        !           514:                this->lock->unlock(this->lock);
        !           515:        }
        !           516:        else
        !           517:        {       /* we can't cache now as other threads are active, queue for later */
        !           518:                this->queue_mutex->lock(this->queue_mutex);
        !           519:                this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
        !           520:                this->queue_mutex->unlock(this->queue_mutex);
        !           521:        }
        !           522: }
        !           523: 
        !           524: /**
        !           525:  * Try to cache certificates queued for caching
        !           526:  */
        !           527: static void cache_queue(private_credential_manager_t *this)
        !           528: {
        !           529:        credential_set_t *set;
        !           530:        certificate_t *cert;
        !           531:        enumerator_t *enumerator;
        !           532: 
        !           533:        this->queue_mutex->lock(this->queue_mutex);
        !           534:        if (this->cache_queue->get_count(this->cache_queue) > 0 &&
        !           535:                this->lock->try_write_lock(this->lock))
        !           536:        {
        !           537:                while (this->cache_queue->remove_last(this->cache_queue,
        !           538:                                                                                          (void**)&cert) == SUCCESS)
        !           539:                {
        !           540:                        enumerator = this->sets->create_enumerator(this->sets);
        !           541:                        while (enumerator->enumerate(enumerator, &set))
        !           542:                        {
        !           543:                                set->cache_cert(set, cert);
        !           544:                        }
        !           545:                        enumerator->destroy(enumerator);
        !           546:                        cert->destroy(cert);
        !           547:                }
        !           548:                this->lock->unlock(this->lock);
        !           549:        }
        !           550:        this->queue_mutex->unlock(this->queue_mutex);
        !           551: }
        !           552: 
        !           553: /**
        !           554:  * Use validators to check the lifetime of certificates
        !           555:  */
        !           556: static bool check_lifetime(private_credential_manager_t *this,
        !           557:                                                   certificate_t *cert, char *label,
        !           558:                                                   int pathlen, bool trusted, auth_cfg_t *auth)
        !           559: {
        !           560:        time_t not_before, not_after;
        !           561:        cert_validator_t *validator;
        !           562:        enumerator_t *enumerator;
        !           563:        status_t status = NEED_MORE;
        !           564: 
        !           565:        enumerator = this->validators->create_enumerator(this->validators);
        !           566:        while (enumerator->enumerate(enumerator, &validator))
        !           567:        {
        !           568:                if (!validator->check_lifetime)
        !           569:                {
        !           570:                        continue;
        !           571:                }
        !           572:                status = validator->check_lifetime(validator, cert,
        !           573:                                                                                   pathlen, trusted, auth);
        !           574:                if (status != NEED_MORE)
        !           575:                {
        !           576:                        break;
        !           577:                }
        !           578:        }
        !           579:        enumerator->destroy(enumerator);
        !           580: 
        !           581:        switch (status)
        !           582:        {
        !           583:                case NEED_MORE:
        !           584:                        if (!cert->get_validity(cert, NULL, &not_before, &not_after))
        !           585:                        {
        !           586:                                DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)",
        !           587:                                         label, &not_before, FALSE, &not_after, FALSE);
        !           588:                                break;
        !           589:                        }
        !           590:                        return TRUE;
        !           591:                case SUCCESS:
        !           592:                        return TRUE;
        !           593:                case FAILED:
        !           594:                default:
        !           595:                        break;
        !           596:        }
        !           597:        call_hook(this, CRED_HOOK_EXPIRED, cert);
        !           598:        return FALSE;
        !           599: }
        !           600: 
        !           601: /**
        !           602:  * check a certificate for its lifetime
        !           603:  */
        !           604: static bool check_certificate(private_credential_manager_t *this,
        !           605:                                certificate_t *subject, certificate_t *issuer, bool online,
        !           606:                                int pathlen, bool trusted, auth_cfg_t *auth)
        !           607: {
        !           608:        cert_validator_t *validator;
        !           609:        enumerator_t *enumerator;
        !           610: 
        !           611:        if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
        !           612:                !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
        !           613:        {
        !           614:                return FALSE;
        !           615:        }
        !           616: 
        !           617:        enumerator = this->validators->create_enumerator(this->validators);
        !           618:        while (enumerator->enumerate(enumerator, &validator))
        !           619:        {
        !           620:                if (!validator->validate)
        !           621:                {
        !           622:                        continue;
        !           623:                }
        !           624:                if (!validator->validate(validator, subject, issuer,
        !           625:                                                                 online, pathlen, trusted, auth))
        !           626:                {
        !           627:                        enumerator->destroy(enumerator);
        !           628:                        return FALSE;
        !           629:                }
        !           630:        }
        !           631:        enumerator->destroy(enumerator);
        !           632:        return TRUE;
        !           633: }
        !           634: 
        !           635: /**
        !           636:  * Get a trusted certificate from a credential set
        !           637:  */
        !           638: static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
        !           639:                                                                                  key_type_t type, identification_t *id)
        !           640: {
        !           641:        certificate_t *subject;
        !           642:        public_key_t *public;
        !           643: 
        !           644:        subject = get_cert(this, CERT_ANY, type, id, TRUE);
        !           645:        if (!subject)
        !           646:        {
        !           647:                return NULL;
        !           648:        }
        !           649:        public = subject->get_public_key(subject);
        !           650:        if (!public)
        !           651:        {
        !           652:                subject->destroy(subject);
        !           653:                return NULL;
        !           654:        }
        !           655:        public->destroy(public);
        !           656:        return subject;
        !           657: }
        !           658: 
        !           659: /**
        !           660:  * Get the issuing certificate of a subject certificate
        !           661:  */
        !           662: static certificate_t *get_issuer_cert(private_credential_manager_t *this,
        !           663:                                                                          certificate_t *subject, bool trusted,
        !           664:                                                                          signature_params_t **scheme)
        !           665: {
        !           666:        enumerator_t *enumerator;
        !           667:        certificate_t *issuer = NULL, *candidate;
        !           668: 
        !           669:        enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
        !           670:                                                                                subject->get_issuer(subject), trusted);
        !           671:        while (enumerator->enumerate(enumerator, &candidate))
        !           672:        {
        !           673:                if (issued_by(this, subject, candidate, scheme))
        !           674:                {
        !           675:                        issuer = candidate->get_ref(candidate);
        !           676:                        break;
        !           677:                }
        !           678:        }
        !           679:        enumerator->destroy(enumerator);
        !           680:        return issuer;
        !           681: }
        !           682: 
        !           683: /**
        !           684:  * Get the strength of certificate, add it to auth
        !           685:  */
        !           686: static void get_key_strength(certificate_t *cert, auth_cfg_t *auth)
        !           687: {
        !           688:        uintptr_t strength;
        !           689:        public_key_t *key;
        !           690:        key_type_t type;
        !           691: 
        !           692:        key = cert->get_public_key(cert);
        !           693:        if (key)
        !           694:        {
        !           695:                type = key->get_type(key);
        !           696:                strength = key->get_keysize(key);
        !           697:                DBG2(DBG_CFG, "  certificate \"%Y\" key: %d bit %N",
        !           698:                         cert->get_subject(cert), strength, key_type_names, type);
        !           699:                switch (type)
        !           700:                {
        !           701:                        case KEY_RSA:
        !           702:                                auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength);
        !           703:                                break;
        !           704:                        case KEY_ECDSA:
        !           705:                                auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength);
        !           706:                                break;
        !           707:                        case KEY_BLISS:
        !           708:                                auth->add(auth, AUTH_RULE_BLISS_STRENGTH, strength);
        !           709:                                break;
        !           710:                        default:
        !           711:                                break;
        !           712:                }
        !           713:                key->destroy(key);
        !           714:        }
        !           715: }
        !           716: 
        !           717: /**
        !           718:  * try to verify the trust chain of subject, return TRUE if trusted
        !           719:  */
        !           720: static bool verify_trust_chain(private_credential_manager_t *this,
        !           721:                                                           certificate_t *subject, auth_cfg_t *result,
        !           722:                                                           bool trusted, bool online)
        !           723: {
        !           724:        certificate_t *current, *issuer;
        !           725:        auth_cfg_t *auth;
        !           726:        signature_params_t *scheme;
        !           727:        int pathlen;
        !           728: 
        !           729:        auth = auth_cfg_create();
        !           730:        get_key_strength(subject, auth);
        !           731:        current = subject->get_ref(subject);
        !           732:        auth->add(auth, AUTH_RULE_SUBJECT_CERT, current->get_ref(current));
        !           733: 
        !           734:        for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
        !           735:        {
        !           736:                issuer = get_issuer_cert(this, current, TRUE, &scheme);
        !           737:                if (issuer)
        !           738:                {
        !           739:                        /* accept only self-signed CAs as trust anchor */
        !           740:                        if (issued_by(this, issuer, issuer, NULL))
        !           741:                        {
        !           742:                                auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
        !           743:                                DBG1(DBG_CFG, "  using trusted ca certificate \"%Y\"",
        !           744:                                                          issuer->get_subject(issuer));
        !           745:                                trusted = TRUE;
        !           746:                        }
        !           747:                        else
        !           748:                        {
        !           749:                                auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
        !           750:                                DBG1(DBG_CFG, "  using trusted intermediate ca certificate "
        !           751:                                         "\"%Y\"", issuer->get_subject(issuer));
        !           752:                        }
        !           753:                        auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
        !           754:                }
        !           755:                else
        !           756:                {
        !           757:                        issuer = get_issuer_cert(this, current, FALSE, &scheme);
        !           758:                        if (issuer)
        !           759:                        {
        !           760:                                if (current->equals(current, issuer))
        !           761:                                {
        !           762:                                        DBG1(DBG_CFG, "  self-signed certificate \"%Y\" is not "
        !           763:                                                 "trusted", current->get_subject(current));
        !           764:                                        issuer->destroy(issuer);
        !           765:                                        call_hook(this, CRED_HOOK_UNTRUSTED_ROOT, current);
        !           766:                                        break;
        !           767:                                }
        !           768:                                auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
        !           769:                                DBG1(DBG_CFG, "  using untrusted intermediate certificate "
        !           770:                                         "\"%Y\"", issuer->get_subject(issuer));
        !           771:                                auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
        !           772:                        }
        !           773:                        else
        !           774:                        {
        !           775:                                DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
        !           776:                                         current->get_subject(current));
        !           777:                                DBG1(DBG_CFG, "  issuer is \"%Y\"",
        !           778:                                         current->get_issuer(current));
        !           779:                                call_hook(this, CRED_HOOK_NO_ISSUER, current);
        !           780:                                break;
        !           781:                        }
        !           782:                }
        !           783:                if (!check_certificate(this, current, issuer, online,
        !           784:                                                           pathlen, trusted, auth))
        !           785:                {
        !           786:                        trusted = FALSE;
        !           787:                        issuer->destroy(issuer);
        !           788:                        break;
        !           789:                }
        !           790:                if (issuer)
        !           791:                {
        !           792:                        get_key_strength(issuer, auth);
        !           793:                }
        !           794:                current->destroy(current);
        !           795:                current = issuer;
        !           796:                if (trusted)
        !           797:                {
        !           798:                        DBG1(DBG_CFG, "  reached self-signed root ca with a "
        !           799:                                 "path length of %d", pathlen);
        !           800:                        break;
        !           801:                }
        !           802:        }
        !           803:        current->destroy(current);
        !           804:        if (pathlen > MAX_TRUST_PATH_LEN)
        !           805:        {
        !           806:                DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
        !           807:                call_hook(this, CRED_HOOK_EXCEEDED_PATH_LEN, subject);
        !           808:        }
        !           809:        if (trusted)
        !           810:        {
        !           811:                result->merge(result, auth, FALSE);
        !           812:        }
        !           813:        auth->destroy(auth);
        !           814:        return trusted;
        !           815: }
        !           816: 
        !           817: CALLBACK(cert_equals, bool,
        !           818:        certificate_t *a, va_list args)
        !           819: {
        !           820:        certificate_t *b;
        !           821: 
        !           822:        VA_ARGS_VGET(args, b);
        !           823:        return a->equals(a, b);
        !           824: }
        !           825: 
        !           826: /**
        !           827:  * enumerator for trusted certificates
        !           828:  */
        !           829: typedef struct {
        !           830:        /** implements enumerator_t interface */
        !           831:        enumerator_t public;
        !           832:        /** enumerator over candidate peer certificates */
        !           833:        enumerator_t *candidates;
        !           834:        /** reference to the credential_manager */
        !           835:        private_credential_manager_t *this;
        !           836:        /** type of the requested key */
        !           837:        key_type_t type;
        !           838:        /** identity the requested key belongs to */
        !           839:        identification_t *id;
        !           840:        /** TRUE to do CRL/OCSP checking */
        !           841:        bool online;
        !           842:        /** pretrusted certificate we have served at first invocation */
        !           843:        certificate_t *pretrusted;
        !           844:        /** currently enumerating auth config */
        !           845:        auth_cfg_t *auth;
        !           846:        /** list of failed candidates */
        !           847:        linked_list_t *failed;
        !           848: } trusted_enumerator_t;
        !           849: 
        !           850: METHOD(enumerator_t, trusted_enumerate, bool,
        !           851:        trusted_enumerator_t *this, va_list args)
        !           852: {
        !           853:        certificate_t *current, **cert;
        !           854:        auth_cfg_t **auth;
        !           855: 
        !           856:        VA_ARGS_VGET(args, cert, auth);
        !           857: 
        !           858:        DESTROY_IF(this->auth);
        !           859:        this->auth = auth_cfg_create();
        !           860: 
        !           861:        if (!this->candidates)
        !           862:        {
        !           863:                /* first invocation, build enumerator for next one */
        !           864:                this->candidates = create_cert_enumerator(this->this, CERT_ANY,
        !           865:                                                                                                  this->type, this->id, FALSE);
        !           866:                /* check if we have a trusted certificate for that peer */
        !           867:                this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
        !           868:                if (this->pretrusted)
        !           869:                {
        !           870:                        /* if we find a trusted self signed certificate, we just accept it.
        !           871:                         * However, in order to fulfill authorization rules, we try to build
        !           872:                         * the trust chain if it is not self signed */
        !           873:                        if (issued_by(this->this, this->pretrusted, this->pretrusted, NULL) ||
        !           874:                                verify_trust_chain(this->this, this->pretrusted, this->auth,
        !           875:                                                                   TRUE, this->online))
        !           876:                        {
        !           877:                                DBG1(DBG_CFG, "  using trusted certificate \"%Y\"",
        !           878:                                         this->pretrusted->get_subject(this->pretrusted));
        !           879:                                *cert = this->pretrusted;
        !           880:                                if (!this->auth->get(this->auth, AUTH_RULE_SUBJECT_CERT))
        !           881:                                {       /* add cert to auth info, if not returned by trustchain */
        !           882:                                        this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
        !           883:                                                                        this->pretrusted->get_ref(this->pretrusted));
        !           884:                                }
        !           885:                                if (auth)
        !           886:                                {
        !           887:                                        *auth = this->auth;
        !           888:                                }
        !           889:                                return TRUE;
        !           890:                        }
        !           891:                }
        !           892:        }
        !           893:        /* try to verify the trust chain for each certificate found */
        !           894:        while (this->candidates->enumerate(this->candidates, &current))
        !           895:        {
        !           896:                if (this->pretrusted &&
        !           897:                        this->pretrusted->equals(this->pretrusted, current))
        !           898:                {       /* skip pretrusted certificate we already served */
        !           899:                        continue;
        !           900:                }
        !           901: 
        !           902:                if (this->failed->find_first(this->failed, cert_equals, NULL, current))
        !           903:                {       /* check each candidate only once */
        !           904:                        continue;
        !           905:                }
        !           906: 
        !           907:                DBG1(DBG_CFG, "  using certificate \"%Y\"",
        !           908:                         current->get_subject(current));
        !           909:                if (verify_trust_chain(this->this, current, this->auth, FALSE,
        !           910:                                                           this->online))
        !           911:                {
        !           912:                        *cert = current;
        !           913:                        if (auth)
        !           914:                        {
        !           915:                                *auth = this->auth;
        !           916:                        }
        !           917:                        return TRUE;
        !           918:                }
        !           919:                this->failed->insert_last(this->failed, current->get_ref(current));
        !           920:        }
        !           921:        return FALSE;
        !           922: }
        !           923: 
        !           924: METHOD(enumerator_t, trusted_destroy, void,
        !           925:        trusted_enumerator_t *this)
        !           926: {
        !           927:        DESTROY_IF(this->pretrusted);
        !           928:        DESTROY_IF(this->auth);
        !           929:        DESTROY_IF(this->candidates);
        !           930:        this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy));
        !           931:        /* check for delayed certificate cache queue */
        !           932:        cache_queue(this->this);
        !           933:        free(this);
        !           934: }
        !           935: 
        !           936: METHOD(credential_manager_t, create_trusted_enumerator, enumerator_t*,
        !           937:        private_credential_manager_t *this, key_type_t type,
        !           938:        identification_t *id, bool online)
        !           939: {
        !           940:        trusted_enumerator_t *enumerator;
        !           941: 
        !           942:        INIT(enumerator,
        !           943:                .public = {
        !           944:                        .enumerate = enumerator_enumerate_default,
        !           945:                        .venumerate = _trusted_enumerate,
        !           946:                        .destroy = _trusted_destroy,
        !           947:                },
        !           948:                .this = this,
        !           949:                .type = type,
        !           950:                .id = id,
        !           951:                .online = online,
        !           952:                .failed = linked_list_create(),
        !           953:        );
        !           954:        return &enumerator->public;
        !           955: }
        !           956: 
        !           957: /**
        !           958:  * enumerator for public keys
        !           959:  */
        !           960: typedef struct {
        !           961:        /** implements enumerator_t interface */
        !           962:        enumerator_t public;
        !           963:        /** enumerator over candidate peer certificates */
        !           964:        enumerator_t *inner;
        !           965:        /** reference to the credential_manager */
        !           966:        private_credential_manager_t *this;
        !           967:        /** currently enumerating key */
        !           968:        public_key_t *current;
        !           969:        /** credset wrapper around auth config */
        !           970:        auth_cfg_wrapper_t *wrapper;
        !           971: } public_enumerator_t;
        !           972: 
        !           973: METHOD(enumerator_t, public_enumerate, bool,
        !           974:        public_enumerator_t *this, va_list args)
        !           975: {
        !           976:        certificate_t *cert;
        !           977:        public_key_t **key;
        !           978:        auth_cfg_t **auth;
        !           979: 
        !           980:        VA_ARGS_VGET(args, key, auth);
        !           981: 
        !           982:        while (this->inner->enumerate(this->inner, &cert, auth))
        !           983:        {
        !           984:                DESTROY_IF(this->current);
        !           985:                this->current = cert->get_public_key(cert);
        !           986:                if (this->current)
        !           987:                {
        !           988:                        *key = this->current;
        !           989:                        return TRUE;
        !           990:                }
        !           991:        }
        !           992:        return FALSE;
        !           993: }
        !           994: 
        !           995: METHOD(enumerator_t, public_destroy, void,
        !           996:        public_enumerator_t *this)
        !           997: {
        !           998:        DESTROY_IF(this->current);
        !           999:        this->inner->destroy(this->inner);
        !          1000:        if (this->wrapper)
        !          1001:        {
        !          1002:                remove_local_set(this->this, &this->wrapper->set);
        !          1003:                this->wrapper->destroy(this->wrapper);
        !          1004:        }
        !          1005:        this->this->lock->unlock(this->this->lock);
        !          1006:        /* check for delayed certificate cache queue */
        !          1007:        cache_queue(this->this);
        !          1008:        free(this);
        !          1009: }
        !          1010: 
        !          1011: METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
        !          1012:        private_credential_manager_t *this, key_type_t type, identification_t *id,
        !          1013:        auth_cfg_t *auth, bool online)
        !          1014: {
        !          1015:        public_enumerator_t *enumerator;
        !          1016: 
        !          1017:        INIT(enumerator,
        !          1018:                .public = {
        !          1019:                        .enumerate = enumerator_enumerate_default,
        !          1020:                        .venumerate = _public_enumerate,
        !          1021:                        .destroy = _public_destroy,
        !          1022:                },
        !          1023:                .inner = create_trusted_enumerator(this, type, id, online),
        !          1024:                .this = this,
        !          1025:        );
        !          1026:        if (auth)
        !          1027:        {
        !          1028:                enumerator->wrapper = auth_cfg_wrapper_create(auth);
        !          1029:                add_local_set(this, &enumerator->wrapper->set, FALSE);
        !          1030:        }
        !          1031:        this->lock->read_lock(this->lock);
        !          1032:        return &enumerator->public;
        !          1033: }
        !          1034: 
        !          1035: /**
        !          1036:  * Check if a helper contains a certificate as trust anchor
        !          1037:  */
        !          1038: static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
        !          1039: {
        !          1040:        enumerator_t *enumerator;
        !          1041:        identification_t *value;
        !          1042:        auth_rule_t type;
        !          1043:        bool found = FALSE;
        !          1044: 
        !          1045:        enumerator = auth->create_enumerator(auth);
        !          1046:        while (enumerator->enumerate(enumerator, &type, &value))
        !          1047:        {
        !          1048:                if (type == AUTH_RULE_CA_CERT &&
        !          1049:                        cert->equals(cert, (certificate_t*)value))
        !          1050:                {
        !          1051:                        found = TRUE;
        !          1052:                        break;
        !          1053:                }
        !          1054:        }
        !          1055:        enumerator->destroy(enumerator);
        !          1056:        return found;
        !          1057: }
        !          1058: 
        !          1059: /**
        !          1060:  * build a trustchain from subject up to a trust anchor in trusted
        !          1061:  */
        !          1062: static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
        !          1063:                                                                         certificate_t *subject, auth_cfg_t *auth)
        !          1064: {
        !          1065:        certificate_t *issuer, *current;
        !          1066:        auth_cfg_t *trustchain;
        !          1067:        int pathlen = 0;
        !          1068:        bool has_anchor;
        !          1069: 
        !          1070:        trustchain = auth_cfg_create();
        !          1071:        has_anchor = auth->get(auth, AUTH_RULE_CA_CERT) != NULL;
        !          1072:        current = subject->get_ref(subject);
        !          1073:        while (TRUE)
        !          1074:        {
        !          1075:                if (auth_contains_cacert(auth, current))
        !          1076:                {
        !          1077:                        trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
        !          1078:                        return trustchain;
        !          1079:                }
        !          1080:                if (subject == current)
        !          1081:                {
        !          1082:                        trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
        !          1083:                }
        !          1084:                else
        !          1085:                {
        !          1086:                        if (!has_anchor && issued_by(this, current, current, NULL))
        !          1087:                        {       /* If no trust anchor specified, accept any CA */
        !          1088:                                trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
        !          1089:                                return trustchain;
        !          1090:                        }
        !          1091:                        trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
        !          1092:                }
        !          1093:                if (pathlen++ > MAX_TRUST_PATH_LEN)
        !          1094:                {
        !          1095:                        break;
        !          1096:                }
        !          1097:                issuer = get_issuer_cert(this, current, FALSE, NULL);
        !          1098:                if (!issuer)
        !          1099:                {
        !          1100:                        if (!has_anchor)
        !          1101:                        {       /* If no trust anchor specified, accept incomplete chains */
        !          1102:                                return trustchain;
        !          1103:                        }
        !          1104:                        break;
        !          1105:                }
        !          1106:                if (has_anchor && issuer->equals(issuer, current))
        !          1107:                {
        !          1108:                        issuer->destroy(issuer);
        !          1109:                        break;
        !          1110:                }
        !          1111:                current = issuer;
        !          1112:        }
        !          1113:        trustchain->destroy(trustchain);
        !          1114:        return NULL;
        !          1115: }
        !          1116: 
        !          1117: /**
        !          1118:  * find a private key of a given certificate
        !          1119:  */
        !          1120: static private_key_t *get_private_by_cert(private_credential_manager_t *this,
        !          1121:                                                                                  certificate_t *cert, key_type_t type)
        !          1122: {
        !          1123:        private_key_t *private = NULL;
        !          1124:        identification_t *keyid;
        !          1125:        chunk_t chunk;
        !          1126:        public_key_t *public;
        !          1127: 
        !          1128:        public = cert->get_public_key(cert);
        !          1129:        if (public)
        !          1130:        {
        !          1131:                if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
        !          1132:                {
        !          1133:                        keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
        !          1134:                        private = get_private_by_keyid(this, type, keyid);
        !          1135:                        keyid->destroy(keyid);
        !          1136:                }
        !          1137:                public->destroy(public);
        !          1138:        }
        !          1139:        return private;
        !          1140: }
        !          1141: 
        !          1142: /**
        !          1143:  * Move the actually used certificate to front, so it gets returned with get()
        !          1144:  */
        !          1145: static void prefer_cert(auth_cfg_t *auth, certificate_t *cert)
        !          1146: {
        !          1147:        enumerator_t *enumerator;
        !          1148:        auth_rule_t rule;
        !          1149:        certificate_t *current;
        !          1150: 
        !          1151:        enumerator = auth->create_enumerator(auth);
        !          1152:        while (enumerator->enumerate(enumerator, &rule, &current))
        !          1153:        {
        !          1154:                if (rule == AUTH_RULE_SUBJECT_CERT)
        !          1155:                {
        !          1156:                        current->get_ref(current);
        !          1157:                        auth->replace(auth, enumerator, AUTH_RULE_SUBJECT_CERT, cert);
        !          1158:                        cert = current;
        !          1159:                }
        !          1160:        }
        !          1161:        enumerator->destroy(enumerator);
        !          1162:        auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
        !          1163: }
        !          1164: 
        !          1165: METHOD(credential_manager_t, get_private, private_key_t*,
        !          1166:        private_credential_manager_t *this, key_type_t type, identification_t *id,
        !          1167:        auth_cfg_t *auth)
        !          1168: {
        !          1169:        enumerator_t *enumerator;
        !          1170:        certificate_t *cert;
        !          1171:        private_key_t *private = NULL;
        !          1172:        auth_cfg_t *trustchain;
        !          1173:        auth_rule_t rule;
        !          1174: 
        !          1175:        /* check if this is a lookup by key ID, and do it if so */
        !          1176:        if (id && id->get_type(id) == ID_KEY_ID)
        !          1177:        {
        !          1178:                private = get_private_by_keyid(this, type, id);
        !          1179:                if (private)
        !          1180:                {
        !          1181:                        return private;
        !          1182:                }
        !          1183:        }
        !          1184: 
        !          1185:        if (auth)
        !          1186:        {
        !          1187:                /* try to find a trustchain with one of the configured subject certs */
        !          1188:                enumerator = auth->create_enumerator(auth);
        !          1189:                while (enumerator->enumerate(enumerator, &rule, &cert))
        !          1190:                {
        !          1191:                        if (rule == AUTH_RULE_SUBJECT_CERT)
        !          1192:                        {
        !          1193:                                private = get_private_by_cert(this, cert, type);
        !          1194:                                if (private)
        !          1195:                                {
        !          1196:                                        trustchain = build_trustchain(this, cert, auth);
        !          1197:                                        if (trustchain)
        !          1198:                                        {
        !          1199:                                                auth->merge(auth, trustchain, FALSE);
        !          1200:                                                prefer_cert(auth, cert->get_ref(cert));
        !          1201:                                                trustchain->destroy(trustchain);
        !          1202:                                                break;
        !          1203:                                        }
        !          1204:                                        private->destroy(private);
        !          1205:                                        private = NULL;
        !          1206:                                }
        !          1207:                        }
        !          1208:                }
        !          1209:                enumerator->destroy(enumerator);
        !          1210:                if (private)
        !          1211:                {
        !          1212:                        return private;
        !          1213:                }
        !          1214: 
        !          1215:                /* if none yielded a trustchain, enforce the first configured cert */
        !          1216:                cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
        !          1217:                if (cert)
        !          1218:                {
        !          1219:                        private = get_private_by_cert(this, cert, type);
        !          1220:                        if (private)
        !          1221:                        {
        !          1222:                                trustchain = build_trustchain(this, cert, auth);
        !          1223:                                if (trustchain)
        !          1224:                                {
        !          1225:                                        auth->merge(auth, trustchain, FALSE);
        !          1226:                                        trustchain->destroy(trustchain);
        !          1227:                                }
        !          1228:                                return private;
        !          1229:                        }
        !          1230:                }
        !          1231: 
        !          1232:                /* try to build a trust chain for each certificate found */
        !          1233:                enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
        !          1234:                while (enumerator->enumerate(enumerator, &cert))
        !          1235:                {
        !          1236:                        private = get_private_by_cert(this, cert, type);
        !          1237:                        if (private)
        !          1238:                        {
        !          1239:                                trustchain = build_trustchain(this, cert, auth);
        !          1240:                                if (trustchain)
        !          1241:                                {
        !          1242:                                        auth->merge(auth, trustchain, FALSE);
        !          1243:                                        trustchain->destroy(trustchain);
        !          1244:                                        break;
        !          1245:                                }
        !          1246:                                private->destroy(private);
        !          1247:                                private = NULL;
        !          1248:                        }
        !          1249:                }
        !          1250:                enumerator->destroy(enumerator);
        !          1251:        }
        !          1252: 
        !          1253:        /* if no valid trustchain was found, fall back to the first usable cert */
        !          1254:        if (!private)
        !          1255:        {
        !          1256:                enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
        !          1257:                while (enumerator->enumerate(enumerator, &cert))
        !          1258:                {
        !          1259:                        private = get_private_by_cert(this, cert, type);
        !          1260:                        if (private)
        !          1261:                        {
        !          1262:                                if (auth)
        !          1263:                                {
        !          1264:                                        auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
        !          1265:                                }
        !          1266:                                break;
        !          1267:                        }
        !          1268:                }
        !          1269:                enumerator->destroy(enumerator);
        !          1270:        }
        !          1271:        return private;
        !          1272: }
        !          1273: 
        !          1274: METHOD(credential_manager_t, flush_cache, void,
        !          1275:        private_credential_manager_t *this, certificate_type_t type)
        !          1276: {
        !          1277:        if (this->cache)
        !          1278:        {
        !          1279:                this->cache->flush(this->cache, type);
        !          1280:        }
        !          1281: }
        !          1282: 
        !          1283: METHOD(credential_manager_t, add_set, void,
        !          1284:        private_credential_manager_t *this, credential_set_t *set)
        !          1285: {
        !          1286:        this->lock->write_lock(this->lock);
        !          1287:        this->sets->insert_last(this->sets, set);
        !          1288:        this->lock->unlock(this->lock);
        !          1289: }
        !          1290: 
        !          1291: METHOD(credential_manager_t, remove_set, void,
        !          1292:        private_credential_manager_t *this, credential_set_t *set)
        !          1293: {
        !          1294:        this->lock->write_lock(this->lock);
        !          1295:        this->sets->remove(this->sets, set, NULL);
        !          1296:        this->lock->unlock(this->lock);
        !          1297: }
        !          1298: 
        !          1299: METHOD(credential_manager_t, add_validator, void,
        !          1300:        private_credential_manager_t *this, cert_validator_t *vdtr)
        !          1301: {
        !          1302:        this->lock->write_lock(this->lock);
        !          1303:        this->validators->insert_last(this->validators, vdtr);
        !          1304:        this->lock->unlock(this->lock);
        !          1305: }
        !          1306: 
        !          1307: METHOD(credential_manager_t, remove_validator, void,
        !          1308:        private_credential_manager_t *this, cert_validator_t *vdtr)
        !          1309: {
        !          1310:        this->lock->write_lock(this->lock);
        !          1311:        this->validators->remove(this->validators, vdtr, NULL);
        !          1312:        this->lock->unlock(this->lock);
        !          1313: }
        !          1314: 
        !          1315: METHOD(credential_manager_t, destroy, void,
        !          1316:        private_credential_manager_t *this)
        !          1317: {
        !          1318:        cache_queue(this);
        !          1319:        this->cache_queue->destroy(this->cache_queue);
        !          1320:        if (this->cache)
        !          1321:        {
        !          1322:                this->sets->remove(this->sets, this->cache, NULL);
        !          1323:                this->cache->destroy(this->cache);
        !          1324:        }
        !          1325:        this->sets->destroy(this->sets);
        !          1326:        this->local_sets->destroy(this->local_sets);
        !          1327:        this->exclusive_local_sets->destroy(this->exclusive_local_sets);
        !          1328:        this->validators->destroy(this->validators);
        !          1329:        this->lock->destroy(this->lock);
        !          1330:        this->queue_mutex->destroy(this->queue_mutex);
        !          1331:        free(this);
        !          1332: }
        !          1333: 
        !          1334: /*
        !          1335:  * see header file
        !          1336:  */
        !          1337: credential_manager_t *credential_manager_create()
        !          1338: {
        !          1339:        private_credential_manager_t *this;
        !          1340: 
        !          1341:        INIT(this,
        !          1342:                .public = {
        !          1343:                        .create_cert_enumerator = _create_cert_enumerator,
        !          1344:                        .create_shared_enumerator = _create_shared_enumerator,
        !          1345:                        .create_cdp_enumerator = _create_cdp_enumerator,
        !          1346:                        .get_cert = _get_cert,
        !          1347:                        .get_shared = _get_shared,
        !          1348:                        .get_private = _get_private,
        !          1349:                        .create_trusted_enumerator = _create_trusted_enumerator,
        !          1350:                        .create_public_enumerator = _create_public_enumerator,
        !          1351:                        .flush_cache = _flush_cache,
        !          1352:                        .cache_cert = _cache_cert,
        !          1353:                        .issued_by = _issued_by,
        !          1354:                        .add_set = _add_set,
        !          1355:                        .remove_set = _remove_set,
        !          1356:                        .add_local_set = _add_local_set,
        !          1357:                        .remove_local_set = _remove_local_set,
        !          1358:                        .add_validator = _add_validator,
        !          1359:                        .remove_validator = _remove_validator,
        !          1360:                        .set_hook = _set_hook,
        !          1361:                        .call_hook = _call_hook,
        !          1362:                        .destroy = _destroy,
        !          1363:                },
        !          1364:                .sets = linked_list_create(),
        !          1365:                .validators = linked_list_create(),
        !          1366:                .cache_queue = linked_list_create(),
        !          1367:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        !          1368:                .queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
        !          1369:        );
        !          1370: 
        !          1371:        this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
        !          1372:        this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
        !          1373:        if (lib->settings->get_bool(lib->settings, "%s.cert_cache", TRUE, lib->ns))
        !          1374:        {
        !          1375:                this->cache = cert_cache_create();
        !          1376:                this->sets->insert_first(this->sets, this->cache);
        !          1377:        }
        !          1378: 
        !          1379:        return &this->public;
        !          1380: }

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