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>