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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2009 Martin Willi
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             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 "cred_encoding.h"
        !            17: 
        !            18: #include <stdint.h>
        !            19: 
        !            20: #include <collections/linked_list.h>
        !            21: #include <collections/hashtable.h>
        !            22: #include <threading/rwlock.h>
        !            23: 
        !            24: typedef struct private_cred_encoding_t private_cred_encoding_t;
        !            25: 
        !            26: /**
        !            27:  * Private data of an cred_encoding_t object.
        !            28:  */
        !            29: struct private_cred_encoding_t {
        !            30: 
        !            31:        /**
        !            32:         * Public cred_encoding_t interface.
        !            33:         */
        !            34:        cred_encoding_t public;
        !            35: 
        !            36:        /**
        !            37:         * cached encodings, a table for each encoding_type_t, containing chunk_t*
        !            38:         */
        !            39:        hashtable_t *cache[CRED_ENCODING_MAX];
        !            40: 
        !            41:        /**
        !            42:         * Registered encoding functions, cred_encoder_t
        !            43:         */
        !            44:        linked_list_t *encoders;
        !            45: 
        !            46:        /**
        !            47:         * lock to access cache/encoders
        !            48:         */
        !            49:        rwlock_t *lock;
        !            50: };
        !            51: 
        !            52: /**
        !            53:  * See header.
        !            54:  */
        !            55: bool cred_encoding_args(va_list args, ...)
        !            56: {
        !            57:        va_list parts, copy;
        !            58:        bool failed = FALSE;
        !            59: 
        !            60:        va_start(parts, args);
        !            61: 
        !            62:        while (!failed)
        !            63:        {
        !            64:                cred_encoding_part_t current, target;
        !            65:                chunk_t *out, data;
        !            66: 
        !            67:                /* get the part we are looking for */
        !            68:                target = va_arg(parts, cred_encoding_part_t);
        !            69:                if (target == CRED_PART_END)
        !            70:                {
        !            71:                        break;
        !            72:                }
        !            73:                out = va_arg(parts, chunk_t*);
        !            74: 
        !            75:                va_copy(copy, args);
        !            76:                while (!failed)
        !            77:                {
        !            78:                        current = va_arg(copy, cred_encoding_part_t);
        !            79:                        if (current == CRED_PART_END)
        !            80:                        {
        !            81:                                failed = TRUE;
        !            82:                                break;
        !            83:                        }
        !            84:                        data = va_arg(copy, chunk_t);
        !            85:                        if (current == target)
        !            86:                        {
        !            87:                                *out = data;
        !            88:                                break;
        !            89:                        }
        !            90:                }
        !            91:                va_end(copy);
        !            92:        }
        !            93:        va_end(parts);
        !            94:        return !failed;
        !            95: }
        !            96: 
        !            97: METHOD(cred_encoding_t, get_cache, bool,
        !            98:        private_cred_encoding_t *this, cred_encoding_type_t type, void *cache,
        !            99:        chunk_t *encoding)
        !           100: {
        !           101:        chunk_t *chunk;
        !           102: 
        !           103:        if (type >= CRED_ENCODING_MAX || (int)type < 0)
        !           104:        {
        !           105:                return FALSE;
        !           106:        }
        !           107:        this->lock->read_lock(this->lock);
        !           108:        chunk = this->cache[type]->get(this->cache[type], cache);
        !           109:        if (chunk)
        !           110:        {
        !           111:                *encoding = *chunk;
        !           112:        }
        !           113:        this->lock->unlock(this->lock);
        !           114:        return !!chunk;
        !           115: }
        !           116: 
        !           117: /**
        !           118:  * Implementation of cred_encoding_t.encode
        !           119:  */
        !           120: static bool encode(private_cred_encoding_t *this, cred_encoding_type_t type,
        !           121:                                   void *cache, chunk_t *encoding, ...)
        !           122: {
        !           123:        enumerator_t *enumerator;
        !           124:        va_list args, copy;
        !           125:        cred_encoder_t encode;
        !           126:        bool success = FALSE;
        !           127:        chunk_t *chunk;
        !           128: 
        !           129:        if (type >= CRED_ENCODING_MAX || (int)type < 0)
        !           130:        {
        !           131:                return FALSE;
        !           132:        }
        !           133:        this->lock->read_lock(this->lock);
        !           134:        if (cache)
        !           135:        {
        !           136:                chunk = this->cache[type]->get(this->cache[type], cache);
        !           137:                if (chunk)
        !           138:                {
        !           139:                        *encoding = *chunk;
        !           140:                        this->lock->unlock(this->lock);
        !           141:                        return TRUE;
        !           142:                }
        !           143:        }
        !           144:        va_start(args, encoding);
        !           145:        enumerator = this->encoders->create_enumerator(this->encoders);
        !           146:        while (enumerator->enumerate(enumerator, &encode))
        !           147:        {
        !           148:                va_copy(copy, args);
        !           149:                success = encode(type, encoding, copy);
        !           150:                va_end(copy);
        !           151:                if (success)
        !           152:                {
        !           153:                        break;
        !           154:                }
        !           155:        }
        !           156:        enumerator->destroy(enumerator);
        !           157:        this->lock->unlock(this->lock);
        !           158:        va_end(args);
        !           159: 
        !           160:        if (success && cache)
        !           161:        {
        !           162:                chunk = malloc_thing(chunk_t);
        !           163:                *chunk = *encoding;
        !           164:                this->lock->write_lock(this->lock);
        !           165:                chunk = this->cache[type]->put(this->cache[type], cache, chunk);
        !           166:                this->lock->unlock(this->lock);
        !           167:                if (chunk)
        !           168:                {
        !           169:                        free(chunk->ptr);
        !           170:                        free(chunk);
        !           171:                }
        !           172:        }
        !           173:        return success;
        !           174: }
        !           175: 
        !           176: METHOD(cred_encoding_t, cache, void,
        !           177:        private_cred_encoding_t *this, cred_encoding_type_t type, void *cache,
        !           178:        chunk_t encoding)
        !           179: {
        !           180:        chunk_t *chunk;
        !           181: 
        !           182:        if (type >= CRED_ENCODING_MAX || (int)type < 0)
        !           183:        {
        !           184:                return free(encoding.ptr);
        !           185:        }
        !           186:        chunk = malloc_thing(chunk_t);
        !           187:        *chunk = encoding;
        !           188:        this->lock->write_lock(this->lock);
        !           189:        chunk = this->cache[type]->put(this->cache[type], cache, chunk);
        !           190:        this->lock->unlock(this->lock);
        !           191:        /* free an encoding already associated to the cache */
        !           192:        if (chunk)
        !           193:        {
        !           194:                free(chunk->ptr);
        !           195:                free(chunk);
        !           196:        }
        !           197: }
        !           198: 
        !           199: METHOD(cred_encoding_t, clear_cache, void,
        !           200:        private_cred_encoding_t *this, void *cache)
        !           201: {
        !           202:        cred_encoding_type_t type;
        !           203:        chunk_t *chunk;
        !           204: 
        !           205:        this->lock->write_lock(this->lock);
        !           206:        for (type = 0; type < CRED_ENCODING_MAX; type++)
        !           207:        {
        !           208:                chunk = this->cache[type]->remove(this->cache[type], cache);
        !           209:                if (chunk)
        !           210:                {
        !           211:                        chunk_free(chunk);
        !           212:                        free(chunk);
        !           213:                }
        !           214:        }
        !           215:        this->lock->unlock(this->lock);
        !           216: }
        !           217: 
        !           218: METHOD(cred_encoding_t, add_encoder, void,
        !           219:        private_cred_encoding_t *this, cred_encoder_t encoder)
        !           220: {
        !           221:        this->lock->write_lock(this->lock);
        !           222:        this->encoders->insert_last(this->encoders, encoder);
        !           223:        this->lock->unlock(this->lock);
        !           224: }
        !           225: 
        !           226: METHOD(cred_encoding_t, remove_encoder, void,
        !           227:        private_cred_encoding_t *this, cred_encoder_t encoder)
        !           228: {
        !           229:        this->lock->write_lock(this->lock);
        !           230:        this->encoders->remove(this->encoders, encoder, NULL);
        !           231:        this->lock->unlock(this->lock);
        !           232: }
        !           233: 
        !           234: METHOD(cred_encoding_t, destroy, void,
        !           235:        private_cred_encoding_t *this)
        !           236: {
        !           237:        cred_encoding_type_t type;
        !           238: 
        !           239:        for (type = 0; type < CRED_ENCODING_MAX; type++)
        !           240:        {
        !           241:                /* We explicitly do not free remaining encodings. All creds should
        !           242:                 * have gone now, and they are responsible for cleaning out their
        !           243:                 * cache entries. Not flushing here allows the leak detective to
        !           244:                 * complain if a credential did not flush cached encodings. */
        !           245:                this->cache[type]->destroy(this->cache[type]);
        !           246:        }
        !           247:        this->encoders->destroy(this->encoders);
        !           248:        this->lock->destroy(this->lock);
        !           249:        free(this);
        !           250: }
        !           251: 
        !           252: /**
        !           253:  * See header
        !           254:  */
        !           255: cred_encoding_t *cred_encoding_create()
        !           256: {
        !           257:        private_cred_encoding_t *this;
        !           258:        cred_encoding_type_t type;
        !           259: 
        !           260:        INIT(this,
        !           261:                .public = {
        !           262:                        .encode = (bool(*)(cred_encoding_t*, cred_encoding_type_t type, void *cache, chunk_t *encoding, ...))encode,
        !           263:                        .get_cache = _get_cache,
        !           264:                        .cache = _cache,
        !           265:                        .clear_cache = _clear_cache,
        !           266:                        .add_encoder = _add_encoder,
        !           267:                        .remove_encoder = _remove_encoder,
        !           268:                        .destroy = _destroy,
        !           269:                },
        !           270:                .encoders = linked_list_create(),
        !           271:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        !           272:        );
        !           273: 
        !           274:        for (type = 0; type < CRED_ENCODING_MAX; type++)
        !           275:        {
        !           276:                this->cache[type] = hashtable_create(hashtable_hash_ptr,
        !           277:                                                                                         hashtable_equals_ptr, 8);
        !           278:        }
        !           279: 
        !           280:        return &this->public;
        !           281: }
        !           282: 

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