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>