Annotation of embedaddon/strongswan/src/libstrongswan/credentials/credential_manager.c, revision 1.1.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>