Annotation of embedaddon/strongswan/src/libtls/tls_cache.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011 Martin Willi
        !             3:  * Copyright (C) 2011 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "tls_cache.h"
        !            17: 
        !            18: #include <utils/debug.h>
        !            19: #include <collections/linked_list.h>
        !            20: #include <collections/hashtable.h>
        !            21: #include <threading/rwlock.h>
        !            22: 
        !            23: typedef struct private_tls_cache_t private_tls_cache_t;
        !            24: 
        !            25: /**
        !            26:  * Private data of an tls_cache_t object.
        !            27:  */
        !            28: struct private_tls_cache_t {
        !            29: 
        !            30:        /**
        !            31:         * Public tls_cache_t interface.
        !            32:         */
        !            33:        tls_cache_t public;
        !            34: 
        !            35:        /**
        !            36:         * Mapping session => entry_t, fast lookup by session
        !            37:         */
        !            38:        hashtable_t *table;
        !            39: 
        !            40:        /**
        !            41:         * List containing all entries
        !            42:         */
        !            43:        linked_list_t *list;
        !            44: 
        !            45:        /**
        !            46:         * Lock to list and table
        !            47:         */
        !            48:        rwlock_t *lock;
        !            49: 
        !            50:        /**
        !            51:         * Session limit
        !            52:         */
        !            53:        u_int max_sessions;
        !            54: 
        !            55:        /**
        !            56:         * maximum age of a session, in seconds
        !            57:         */
        !            58:        u_int max_age;
        !            59: };
        !            60: 
        !            61: /**
        !            62:  * Hashtable entry
        !            63:  */
        !            64: typedef struct {
        !            65:        /** session identifier */
        !            66:        chunk_t session;
        !            67:        /** master secret */
        !            68:        chunk_t master;
        !            69:        /** TLS cipher suite */
        !            70:        tls_cipher_suite_t suite;
        !            71:        /** optional identity this entry is bound to */
        !            72:        identification_t *id;
        !            73:        /** time of add */
        !            74:        time_t t;
        !            75: } entry_t;
        !            76: 
        !            77: /**
        !            78:  * Destroy an entry
        !            79:  */
        !            80: static void entry_destroy(entry_t *entry)
        !            81: {
        !            82:        chunk_clear(&entry->session);
        !            83:        chunk_clear(&entry->master);
        !            84:        DESTROY_IF(entry->id);
        !            85:        free(entry);
        !            86: }
        !            87: 
        !            88: /**
        !            89:  * Hashtable hash function
        !            90:  */
        !            91: static u_int hash(chunk_t *key)
        !            92: {
        !            93:        return chunk_hash(*key);
        !            94: }
        !            95: 
        !            96: /**
        !            97:  * Hashtable equals function
        !            98:  */
        !            99: static bool equals(chunk_t *a, chunk_t *b)
        !           100: {
        !           101:        return chunk_equals(*a, *b);
        !           102: }
        !           103: 
        !           104: METHOD(tls_cache_t, create_, void,
        !           105:        private_tls_cache_t *this, chunk_t session, identification_t *id,
        !           106:        chunk_t master, tls_cipher_suite_t suite)
        !           107: {
        !           108:        entry_t *entry;
        !           109: 
        !           110:        INIT(entry,
        !           111:                .session = chunk_clone(session),
        !           112:                .master = chunk_clone(master),
        !           113:                .suite = suite,
        !           114:                .id = id ? id->clone(id) : NULL,
        !           115:                .t = time_monotonic(NULL),
        !           116:        );
        !           117: 
        !           118:        this->lock->write_lock(this->lock);
        !           119:        this->list->insert_first(this->list, entry);
        !           120:        this->table->put(this->table, &entry->session, entry);
        !           121:        if (this->list->get_count(this->list) > this->max_sessions &&
        !           122:                this->list->remove_last(this->list, (void**)&entry) == SUCCESS)
        !           123:        {
        !           124:                DBG2(DBG_TLS, "session limit of %u reached, deleting %#B",
        !           125:                         this->max_sessions, &entry->session);
        !           126:                this->table->remove(this->table, &entry->session);
        !           127:                entry_destroy(entry);
        !           128:        }
        !           129:        this->lock->unlock(this->lock);
        !           130: 
        !           131:        DBG2(DBG_TLS, "created TLS session %#B, %d sessions",
        !           132:                 &session, this->list->get_count(this->list));
        !           133: }
        !           134: 
        !           135: METHOD(tls_cache_t, lookup, tls_cipher_suite_t,
        !           136:        private_tls_cache_t *this, chunk_t session, identification_t *id,
        !           137:        chunk_t* master)
        !           138: {
        !           139:        tls_cipher_suite_t suite = 0;
        !           140:        entry_t *entry;
        !           141:        time_t now;
        !           142:        u_int age;
        !           143: 
        !           144:        now = time_monotonic(NULL);
        !           145: 
        !           146:        this->lock->write_lock(this->lock);
        !           147:        entry = this->table->get(this->table, &session);
        !           148:        if (entry)
        !           149:        {
        !           150:                age = now - entry->t;
        !           151:                if (age <= this->max_age)
        !           152:                {
        !           153:                        if (!id || !entry->id || id->equals(id, entry->id))
        !           154:                        {
        !           155:                                *master = chunk_clone(entry->master);
        !           156:                                suite = entry->suite;
        !           157:                        }
        !           158:                }
        !           159:                else
        !           160:                {
        !           161:                        DBG2(DBG_TLS, "TLS session %#B expired: %u seconds", &session, age);
        !           162:                }
        !           163:        }
        !           164:        this->lock->unlock(this->lock);
        !           165: 
        !           166:        if (suite)
        !           167:        {
        !           168:                DBG2(DBG_TLS, "resuming TLS session %#B, age %u seconds", &session, age);
        !           169:        }
        !           170:        return suite;
        !           171: }
        !           172: 
        !           173: METHOD(tls_cache_t, check, chunk_t,
        !           174:        private_tls_cache_t *this, identification_t *id)
        !           175: {
        !           176:        chunk_t session = chunk_empty;
        !           177:        enumerator_t *enumerator;
        !           178:        entry_t *entry;
        !           179:        time_t now;
        !           180: 
        !           181:        now = time_monotonic(NULL);
        !           182:        this->lock->read_lock(this->lock);
        !           183:        enumerator = this->list->create_enumerator(this->list);
        !           184:        while (enumerator->enumerate(enumerator, &entry))
        !           185:        {
        !           186:                if (entry->t + this->max_age >= now &&
        !           187:                        entry->id && id->equals(id, entry->id))
        !           188:                {
        !           189:                        session = chunk_clone(entry->session);
        !           190:                        break;
        !           191:                }
        !           192:        }
        !           193:        enumerator->destroy(enumerator);
        !           194:        this->lock->unlock(this->lock);
        !           195: 
        !           196:        return session;
        !           197: }
        !           198: 
        !           199: METHOD(tls_cache_t, destroy, void,
        !           200:        private_tls_cache_t *this)
        !           201: {
        !           202:        entry_t *entry;
        !           203: 
        !           204:        while (this->list->remove_last(this->list, (void**)&entry) == SUCCESS)
        !           205:        {
        !           206:                entry_destroy(entry);
        !           207:        }
        !           208:        this->list->destroy(this->list);
        !           209:        this->table->destroy(this->table);
        !           210:        this->lock->destroy(this->lock);
        !           211:        free(this);
        !           212: }
        !           213: 
        !           214: /**
        !           215:  * See header
        !           216:  */
        !           217: tls_cache_t *tls_cache_create(u_int max_sessions, u_int max_age)
        !           218: {
        !           219:        private_tls_cache_t *this;
        !           220: 
        !           221:        INIT(this,
        !           222:                .public = {
        !           223:                        .create = _create_,
        !           224:                        .lookup = _lookup,
        !           225:                        .check = _check,
        !           226:                        .destroy = _destroy,
        !           227:                },
        !           228:                .table = hashtable_create((hashtable_hash_t)hash,
        !           229:                                                                  (hashtable_equals_t)equals, 8),
        !           230:                .list = linked_list_create(),
        !           231:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        !           232:                .max_sessions = max_sessions,
        !           233:                .max_age = max_age,
        !           234:        );
        !           235: 
        !           236:        return &this->public;
        !           237: }

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