added PSK support
[strongswan.git] / src / charon / config / policies / local_policy_store.c
1 /**
2 * @file local_policy_store.c
3 *
4 * @brief Implementation of local_policy_store_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <string.h>
24
25 #include "local_policy_store.h"
26
27 #include <utils/linked_list.h>
28 #include <utils/logger_manager.h>
29
30
31 typedef struct private_local_policy_store_t private_local_policy_store_t;
32
33 /**
34 * Private data of an local_policy_store_t object
35 */
36 struct private_local_policy_store_t {
37
38 /**
39 * Public part
40 */
41 local_policy_store_t public;
42
43 /**
44 * list of policy_t's
45 */
46 linked_list_t *policies;
47
48 /**
49 * Mutex to exclusivly access list
50 */
51 pthread_mutex_t mutex;
52
53 /**
54 * Assigned logger
55 */
56 logger_t *logger;
57 };
58
59 /**
60 * Implementation of policy_store_t.add_policy.
61 */
62 static void add_policy(private_local_policy_store_t *this, policy_t *policy)
63 {
64 pthread_mutex_lock(&(this->mutex));
65 this->policies->insert_last(this->policies, (void*)policy);
66 pthread_mutex_unlock(&(this->mutex));
67 }
68
69 /**
70 * Check if a policy contains traffic selectors
71 */
72 static bool contains_traffic_selectors(policy_t *policy, bool mine,
73 linked_list_t *ts, host_t *host)
74 {
75 linked_list_t *selected;
76 bool contains = FALSE;
77 traffic_selector_t *to;
78
79 if (mine)
80 {
81 selected = policy->select_my_traffic_selectors(policy, ts, host);
82 }
83 else
84 {
85 selected = policy->select_other_traffic_selectors(policy, ts, host);
86 }
87 if (selected->get_count(selected))
88 {
89 contains = TRUE;
90 }
91 while (selected->remove_last(selected, (void**)&to) == SUCCESS)
92 {
93 to->destroy(to);
94 }
95 selected->destroy(selected);
96 return contains;
97 }
98
99 /**
100 * Implementation of policy_store_t.get_policy.
101 */
102 static policy_t *get_policy(private_local_policy_store_t *this,
103 identification_t *my_id, identification_t *other_id,
104 linked_list_t *my_ts, linked_list_t *other_ts,
105 host_t *my_host, host_t *other_host)
106 {
107 typedef enum {
108 PRIO_UNDEFINED = 0x00,
109 PRIO_ID_ANY = 0x01,
110 PRIO_ID_MATCH = PRIO_ID_ANY + MAX_WILDCARDS,
111 } prio_t;
112
113 prio_t best_prio = PRIO_UNDEFINED;
114
115 iterator_t *iterator;
116 policy_t *candidate;
117 policy_t *found = NULL;
118
119 this->logger->log(this->logger, CONTROL|LEVEL1, "searching policy for ID pair %s...%s",
120 my_id->get_string(my_id), other_id->get_string(other_id));
121
122 pthread_mutex_lock(&(this->mutex));
123 iterator = this->policies->create_iterator(this->policies, TRUE);
124
125 /* determine closest matching policy */
126 while (iterator->has_next(iterator))
127 {
128 identification_t *candidate_my_id;
129 identification_t *candidate_other_id;
130 int wildcards;
131
132 iterator->current(iterator, (void**)&candidate);
133
134 candidate_my_id = candidate->get_my_id(candidate);
135 candidate_other_id = candidate->get_other_id(candidate);
136
137 /* my_id is either %any or if set must match exactly */
138 if (candidate_my_id->matches(candidate_my_id, my_id, &wildcards))
139 {
140 prio_t prio = PRIO_UNDEFINED;
141
142 /* wildcard match for other_id */
143 if (other_id->matches(other_id, candidate_other_id, &wildcards))
144 {
145 prio = PRIO_ID_MATCH - wildcards;
146 }
147
148 /* only accept if traffic selectors match */
149 if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) ||
150 !contains_traffic_selectors(candidate, FALSE, other_ts, other_host))
151 {
152 this->logger->log(this->logger, CONTROL|LEVEL2,
153 "candidate '%s' inacceptable due traffic selector mismatch",
154 candidate->get_name(candidate),
155 candidate_my_id->get_string(candidate_my_id),
156 candidate_other_id->get_string(candidate_other_id),
157 prio);
158 continue;
159 }
160
161 this->logger->log(this->logger, CONTROL|LEVEL2,
162 "candidate policy '%s': %s...%s (prio=%d)",
163 candidate->get_name(candidate),
164 candidate_my_id->get_string(candidate_my_id),
165 candidate_other_id->get_string(candidate_other_id),
166 prio);
167
168 if (prio > best_prio)
169 {
170 found = candidate;
171 best_prio = prio;
172 }
173 }
174 }
175 iterator->destroy(iterator);
176
177 if (found)
178 {
179 identification_t *found_my_id = found->get_my_id(found);
180 identification_t *found_other_id = found->get_other_id(found);
181
182 this->logger->log(this->logger, CONTROL|LEVEL1,
183 "found matching policy '%s': %s...%s (prio=%d)",
184 found->get_name(found),
185 found_my_id->get_string(found_my_id),
186 found_other_id->get_string(found_other_id),
187 best_prio);
188 /* give out a new reference to it */
189 found->get_ref(found);
190 }
191 pthread_mutex_unlock(&(this->mutex));
192 return found;
193 }
194
195 /**
196 * Implementation of policy_store_t.get_policy_by_name.
197 */
198 static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name)
199 {
200 iterator_t *iterator;
201 policy_t *current, *found = NULL;
202
203 this->logger->log(this->logger, CONTROL|LEVEL1, "looking for policy \"%s\"", name);
204
205 pthread_mutex_lock(&(this->mutex));
206 iterator = this->policies->create_iterator(this->policies, TRUE);
207 while (iterator->has_next(iterator))
208 {
209 iterator->current(iterator, (void **)&current);
210 if (strcmp(current->get_name(current), name) == 0)
211 {
212 found = current;
213 }
214 }
215 iterator->destroy(iterator);
216 pthread_mutex_unlock(&(this->mutex));
217
218 /* give out a new reference */
219 found->get_ref(found);
220 return found;
221 }
222
223 /**
224 * Implementation of policy_store_t.delete_policy.
225 */
226 static status_t delete_policy(private_local_policy_store_t *this, char *name)
227 {
228 iterator_t *iterator;
229 policy_t *current;
230 bool found = FALSE;
231
232 pthread_mutex_lock(&(this->mutex));
233 iterator = this->policies->create_iterator(this->policies, TRUE);
234 while (iterator->has_next(iterator))
235 {
236 iterator->current(iterator, (void **)&current);
237 if (strcmp(current->get_name(current), name) == 0)
238 {
239 /* remove policy from list, and destroy it */
240 iterator->remove(iterator);
241 current->destroy(current);
242 found = TRUE;
243 /* we do not break here, as there may be multipe policies */
244 }
245 }
246 iterator->destroy(iterator);
247 pthread_mutex_unlock(&(this->mutex));
248 if (found)
249 {
250 return SUCCESS;
251 }
252 return NOT_FOUND;
253 }
254
255 /**
256 * Implementation of policy_store_t.destroy.
257 */
258 static void destroy(private_local_policy_store_t *this)
259 {
260 policy_t *policy;
261
262 pthread_mutex_lock(&(this->mutex));
263 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
264 {
265 policy->destroy(policy);
266 }
267 this->policies->destroy(this->policies);
268 pthread_mutex_unlock(&(this->mutex));
269 free(this);
270 }
271
272 /**
273 * Described in header.
274 */
275 local_policy_store_t *local_policy_store_create(void)
276 {
277 private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
278
279 this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy;
280 this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*,linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy;
281 this->public.policy_store.get_policy_by_name = (policy_t*(*)(policy_store_t*,char*))get_policy_by_name;
282 this->public.policy_store.delete_policy = (status_t(*)(policy_store_t*,char*))delete_policy;
283 this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy;
284
285 /* private variables */
286 this->policies = linked_list_create();
287 this->logger = logger_manager->get_logger(logger_manager, CONFIG);
288 pthread_mutex_init(&(this->mutex), NULL);
289
290 return (&this->public);
291 }