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