lookup of private key based on keyid of public key
[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 "local_policy_store.h"
24
25 #include <utils/linked_list.h>
26 #include <utils/logger_manager.h>
27
28
29 typedef struct private_local_policy_store_t private_local_policy_store_t;
30
31 /**
32 * Private data of an local_policy_store_t object
33 */
34 struct private_local_policy_store_t {
35
36 /**
37 * Public part
38 */
39 local_policy_store_t public;
40
41 /**
42 * list of policy_t's
43 */
44 linked_list_t *policies;
45
46 /**
47 * Mutex to exclusivly access list
48 */
49 pthread_mutex_t mutex;
50
51 /**
52 * Assigned logger
53 */
54 logger_t *logger;
55 };
56
57 /**
58 * Implementation of policy_store_t.add_policy.
59 */
60 static void add_policy(private_local_policy_store_t *this, policy_t *policy)
61 {
62 pthread_mutex_lock(&(this->mutex));
63 this->policies->insert_last(this->policies, (void*)policy);
64 pthread_mutex_unlock(&(this->mutex));
65 }
66
67 /**
68 * Implementation of policy_store_t.get_policy_by_ids.
69 */
70 static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id)
71 {
72 typedef enum {
73 PRIO_UNDEFINED = 0x00,
74 PRIO_ID_ANY = 0x01,
75 PRIO_ID_WILDCARD = 0x02,
76 PRIO_ID_MATCH = 0x04,
77 } prio_t;
78
79 prio_t best_prio = PRIO_UNDEFINED;
80
81 iterator_t *iterator;
82 policy_t *candidate;
83 policy_t *found = NULL;
84
85 this->logger->log(this->logger, CONTROL|LEVEL1, "searching policy for ID pair %s...%s",
86 my_id->get_string(my_id), other_id->get_string(other_id));
87
88 pthread_mutex_lock(&(this->mutex));
89 iterator = this->policies->create_iterator(this->policies, TRUE);
90 /* determine closest matching policy */
91 while (iterator->has_next(iterator))
92 {
93 identification_t *candidate_my_id;
94 identification_t *candidate_other_id;
95
96 iterator->current(iterator, (void**)&candidate);
97
98 candidate_my_id = candidate->get_my_id(candidate);
99 candidate_other_id = candidate->get_other_id(candidate);
100
101 /* my_id must match, or may be %any */
102 if (candidate_my_id->belongs_to(candidate_my_id, my_id))
103 {
104 prio_t prio = PRIO_UNDEFINED;
105
106 /* exact match of id? */
107 if (other_id->equals(other_id, candidate_other_id))
108 {
109 prio = PRIO_ID_MATCH;
110 }
111 /* match against any? */
112 else if (candidate_other_id->get_type(candidate_other_id) == ID_ANY)
113 {
114 prio = PRIO_ID_ANY;
115 }
116 /* wildcard match? */
117 else if (other_id->belongs_to(other_id, candidate_other_id))
118 {
119 prio = PRIO_ID_WILDCARD;
120 }
121
122 this->logger->log(this->logger, CONTROL|LEVEL2,
123 "candidate policy \"%s\": %s...%s (prio=%d)",
124 candidate->get_name(candidate),
125 candidate_my_id->get_string(candidate_my_id),
126 candidate_other_id->get_string(candidate_other_id),
127 prio);
128
129 if (prio > best_prio)
130 {
131 found = candidate;
132 best_prio = prio;
133 }
134 if (prio == PRIO_ID_MATCH)
135 {
136 /* won't get better, stop searching */
137 break;
138 }
139 }
140 }
141 iterator->destroy(iterator);
142
143 if (found)
144 {
145 identification_t *found_my_id = found->get_my_id(found);
146 identification_t *found_other_id = found->get_other_id(found);
147
148 this->logger->log(this->logger, CONTROL|LEVEL1,
149 "found matching policy \"%s\": %s...%s (prio=%d)",
150 found->get_name(found),
151 found_my_id->get_string(found_my_id),
152 found_other_id->get_string(found_other_id),
153 best_prio);
154
155 found = found->clone(found);
156 if (best_prio != PRIO_ID_MATCH)
157 {
158 /* replace %any/wildcards by the peer's address */
159 found->update_other_id(found, other_id->clone(other_id));
160 }
161 }
162 pthread_mutex_unlock(&(this->mutex));
163 return found;
164 }
165
166 /**
167 * Implementation of policy_store_t.get_policy_by_name.
168 */
169 static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name)
170 {
171 iterator_t *iterator;
172 policy_t *current, *found = NULL;
173
174 this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy \"%s\"", name);
175
176 pthread_mutex_lock(&(this->mutex));
177 iterator = this->policies->create_iterator(this->policies, TRUE);
178 while (iterator->has_next(iterator))
179 {
180 iterator->current(iterator, (void **)&current);
181 if (strcmp(current->get_name(current), name) == 0)
182 {
183 found = current->clone(current);
184 }
185 }
186 iterator->destroy(iterator);
187 pthread_mutex_unlock(&(this->mutex));
188
189 return found;
190 }
191
192 /**
193 * Implementation of policy_store_t.delete_policy.
194 */
195 static status_t delete_policy(private_local_policy_store_t *this, char *name)
196 {
197 iterator_t *iterator;
198 policy_t *current;
199 bool found = FALSE;
200
201 pthread_mutex_lock(&(this->mutex));
202 iterator = this->policies->create_iterator(this->policies, TRUE);
203 while (iterator->has_next(iterator))
204 {
205 iterator->current(iterator, (void **)&current);
206 if (strcmp(current->get_name(current), name) == 0)
207 {
208 /* remove policy from list, and destroy it */
209 iterator->remove(iterator);
210 current->destroy(current);
211 found = TRUE;
212 /* we do not break here, as there may be multipe policies */
213 }
214 }
215 iterator->destroy(iterator);
216 pthread_mutex_unlock(&(this->mutex));
217 if (found)
218 {
219 return SUCCESS;
220 }
221 return NOT_FOUND;
222 }
223
224 /**
225 * Implementation of policy_store_t.destroy.
226 */
227 static void destroy(private_local_policy_store_t *this)
228 {
229 policy_t *policy;
230
231 pthread_mutex_lock(&(this->mutex));
232 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
233 {
234 policy->destroy(policy);
235 }
236 this->policies->destroy(this->policies);
237 pthread_mutex_unlock(&(this->mutex));
238 free(this);
239 }
240
241 /**
242 * Described in header.
243 */
244 local_policy_store_t *local_policy_store_create(void)
245 {
246 private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
247
248 this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy;
249 this->public.policy_store.get_policy_by_ids = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy_by_ids;
250 this->public.policy_store.get_policy_by_name = (policy_t*(*)(policy_store_t*,char*))get_policy_by_name;
251 this->public.policy_store.delete_policy = (status_t(*)(policy_store_t*,char*))delete_policy;
252 this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy;
253
254 /* private variables */
255 this->policies = linked_list_create();
256 this->logger = logger_manager->get_logger(logger_manager, CONFIG);
257 pthread_mutex_init(&(this->mutex), NULL);
258
259 return (&this->public);
260 }