a64f43173746471a53f96233cfbaebfb89b0b079
[strongswan.git] / src / libstrongswan / credentials / sets / mem_cred.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 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 "mem_cred.h"
17
18 #include <threading/rwlock.h>
19 #include <utils/linked_list.h>
20
21 typedef struct private_mem_cred_t private_mem_cred_t;
22
23 /**
24 * Private data of an mem_cred_t object.
25 */
26 struct private_mem_cred_t {
27
28 /**
29 * Public mem_cred_t interface.
30 */
31 mem_cred_t public;
32
33 /**
34 * Lock for this set
35 */
36 rwlock_t *lock;
37
38 /**
39 * List of shared keys, as shared_entry_t
40 */
41 linked_list_t *shared;
42 };
43
44 /**
45 * Shared key entry
46 */
47 typedef struct {
48 /* shared key */
49 shared_key_t *shared;
50 /* list of owners, identification_t */
51 linked_list_t *owners;
52 } shared_entry_t;
53
54 /**
55 * Clean up a shared entry
56 */
57 static void shared_entry_destroy(shared_entry_t *entry)
58 {
59 entry->owners->destroy_offset(entry->owners,
60 offsetof(identification_t, destroy));
61 entry->shared->destroy(entry->shared);
62 free(entry);
63 }
64
65 /**
66 * Data for the shared_key enumerator
67 */
68 typedef struct {
69 rwlock_t *lock;
70 identification_t *me;
71 identification_t *other;
72 shared_key_type_t type;
73 } shared_data_t;
74
75 /**
76 * free shared key enumerator data and unlock list
77 */
78 static void shared_data_destroy(shared_data_t *data)
79 {
80 data->lock->unlock(data->lock);
81 free(data);
82 }
83
84 /**
85 * Get the best match of an owner in an entry.
86 */
87 static id_match_t has_owner(shared_entry_t *entry, identification_t *owner)
88 {
89 enumerator_t *enumerator;
90 id_match_t match, best = ID_MATCH_NONE;
91 identification_t *current;
92
93 enumerator = entry->owners->create_enumerator(entry->owners);
94 while (enumerator->enumerate(enumerator, &current))
95 {
96 match = owner->matches(owner, current);
97 if (match > best)
98 {
99 best = match;
100 }
101 }
102 enumerator->destroy(enumerator);
103 return best;
104 }
105
106 /**
107 * enumerator filter function for shared entries
108 */
109 static bool shared_filter(shared_data_t *data,
110 shared_entry_t **in, shared_key_t **out,
111 void **unused1, id_match_t *me,
112 void **unused2, id_match_t *other)
113 {
114 id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
115 shared_entry_t *entry = *in;
116
117 if (data->type != SHARED_ANY &&
118 entry->shared->get_type(entry->shared) != data->type)
119 {
120 return FALSE;
121 }
122 if (data->me)
123 {
124 my_match = has_owner(entry, data->me);
125 }
126 if (data->other)
127 {
128 other_match = has_owner(entry, data->other);
129 }
130 if ((data->me || data->other) && (!my_match && !other_match))
131 {
132 return FALSE;
133 }
134 *out = entry->shared;
135 if (me)
136 {
137 *me = my_match;
138 }
139 if (other)
140 {
141 *other = other_match;
142 }
143 return TRUE;
144 }
145
146 METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
147 private_mem_cred_t *this, shared_key_type_t type,
148 identification_t *me, identification_t *other)
149 {
150 shared_data_t *data;
151
152 INIT(data,
153 .lock = this->lock,
154 .me = me,
155 .other = other,
156 .type = type,
157 );
158 data->lock->read_lock(data->lock);
159 return enumerator_create_filter(
160 this->shared->create_enumerator(this->shared),
161 (void*)shared_filter, data, (void*)shared_data_destroy);
162 }
163
164 METHOD(mem_cred_t, add_shared, void,
165 private_mem_cred_t *this, shared_key_t *shared, ...)
166 {
167 shared_entry_t *entry;
168 identification_t *id;
169 va_list args;
170
171 INIT(entry,
172 .shared = shared,
173 .owners = linked_list_create(),
174 );
175
176 va_start(args, shared);
177 do
178 {
179 id = va_arg(args, identification_t*);
180 if (id)
181 {
182 entry->owners->insert_last(entry->owners, id);
183 }
184 }
185 while (id);
186 va_end(args);
187
188 this->lock->write_lock(this->lock);
189 this->shared->insert_last(this->shared, entry);
190 this->lock->unlock(this->lock);
191 }
192
193
194 METHOD(mem_cred_t, destroy, void,
195 private_mem_cred_t *this)
196 {
197 this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
198 this->lock->destroy(this->lock);
199 free(this);
200 }
201
202 /**
203 * See header
204 */
205 mem_cred_t *mem_cred_create()
206 {
207 private_mem_cred_t *this;
208
209 INIT(this,
210 .public = {
211 .set = {
212 .create_shared_enumerator = _create_shared_enumerator,
213 .create_private_enumerator = (void*)return_null,
214 .create_cert_enumerator = (void*)return_null,
215 .create_cdp_enumerator = (void*)return_null,
216 .cache_cert = (void*)nop,
217 },
218 .add_shared = _add_shared,
219 .destroy = _destroy,
220 },
221 .shared = linked_list_create(),
222 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
223 );
224
225 return &this->public;
226 }