removed trailing spaces ([[:space:]]+$)
[strongswan.git] / src / charon / config / ike_cfg.c
1 /*
2 * Copyright (C) 2005-2007 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "ike_cfg.h"
18
19 #include <string.h>
20
21 #include <daemon.h>
22
23
24 typedef struct private_ike_cfg_t private_ike_cfg_t;
25
26 /**
27 * Private data of an ike_cfg_t object
28 */
29 struct private_ike_cfg_t {
30
31 /**
32 * Public part
33 */
34 ike_cfg_t public;
35
36 /**
37 * Number of references hold by others to this ike_cfg
38 */
39 refcount_t refcount;
40
41 /**
42 * Address of local host
43 */
44 char *me;
45
46 /**
47 * Address of remote host
48 */
49 char *other;
50
51 /**
52 * should we send a certificate request?
53 */
54 bool certreq;
55
56 /**
57 * enforce UDP encapsulation
58 */
59 bool force_encap;
60
61 /**
62 * List of proposals to use
63 */
64 linked_list_t *proposals;
65 };
66
67 /**
68 * Implementation of ike_cfg_t.certreq.
69 */
70 static bool send_certreq(private_ike_cfg_t *this)
71 {
72 return this->certreq;
73 }
74
75 /**
76 * Implementation of ike_cfg_t.force_encap.
77 */
78 static bool force_encap_meth(private_ike_cfg_t *this)
79 {
80 return this->force_encap;
81 }
82
83 /**
84 * Implementation of ike_cfg_t.get_my_addr.
85 */
86 static char *get_my_addr(private_ike_cfg_t *this)
87 {
88 return this->me;
89 }
90
91 /**
92 * Implementation of ike_cfg_t.get_other_addr.
93 */
94 static char *get_other_addr(private_ike_cfg_t *this)
95 {
96 return this->other;
97 }
98
99 /**
100 * Implementation of ike_cfg_t.add_proposal.
101 */
102 static void add_proposal(private_ike_cfg_t *this, proposal_t *proposal)
103 {
104 this->proposals->insert_last(this->proposals, proposal);
105 }
106
107 /**
108 * Implementation of ike_cfg_t.get_proposals.
109 */
110 static linked_list_t* get_proposals(private_ike_cfg_t *this)
111 {
112 iterator_t *iterator;
113 proposal_t *current;
114 linked_list_t *proposals = linked_list_create();
115
116 iterator = this->proposals->create_iterator(this->proposals, TRUE);
117 while (iterator->iterate(iterator, (void**)&current))
118 {
119 current = current->clone(current);
120 proposals->insert_last(proposals, (void*)current);
121 }
122 iterator->destroy(iterator);
123
124 return proposals;
125 }
126
127 /**
128 * Implementation of ike_cfg_t.select_proposal.
129 */
130 static proposal_t *select_proposal(private_ike_cfg_t *this,
131 linked_list_t *proposals)
132 {
133 iterator_t *stored_iter, *supplied_iter;
134 proposal_t *stored, *supplied, *selected;
135
136 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
137 supplied_iter = proposals->create_iterator(proposals, TRUE);
138
139
140 /* compare all stored proposals with all supplied. Stored ones are preferred.*/
141 while (stored_iter->iterate(stored_iter, (void**)&stored))
142 {
143 supplied_iter->reset(supplied_iter);
144
145 while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
146 {
147 selected = stored->select(stored, supplied);
148 if (selected)
149 {
150 /* they match, return */
151 stored_iter->destroy(stored_iter);
152 supplied_iter->destroy(supplied_iter);
153 DBG2(DBG_CFG, "received proposals: %#P", proposals);
154 DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
155 DBG2(DBG_CFG, "selected proposal: %P", selected);
156 return selected;
157 }
158 }
159 }
160 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
161 stored_iter->destroy(stored_iter);
162 supplied_iter->destroy(supplied_iter);
163 DBG1(DBG_CFG, "received proposals: %#P", proposals);
164 DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
165
166 return NULL;
167 }
168
169 /**
170 * Implementation of ike_cfg_t.get_dh_group.
171 */
172 static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this)
173 {
174 enumerator_t *enumerator;
175 proposal_t *proposal;
176 u_int16_t dh_group = MODP_NONE;
177
178 enumerator = this->proposals->create_enumerator(this->proposals);
179 while (enumerator->enumerate(enumerator, &proposal))
180 {
181 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
182 {
183 break;
184 }
185 }
186 enumerator->destroy(enumerator);
187 return dh_group;
188 }
189
190 /**
191 * Implementation of ike_cfg_t.equals.
192 */
193 static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other)
194 {
195 enumerator_t *e1, *e2;
196 proposal_t *p1, *p2;
197 bool eq = TRUE;
198
199 if (this == other)
200 {
201 return TRUE;
202 }
203 if (this->public.equals != other->public.equals)
204 {
205 return FALSE;
206 }
207 if (this->proposals->get_count(this->proposals) !=
208 other->proposals->get_count(other->proposals))
209 {
210 return FALSE;
211 }
212 e1 = this->proposals->create_enumerator(this->proposals);
213 e2 = this->proposals->create_enumerator(this->proposals);
214 while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
215 {
216 if (!p1->equals(p1, p2))
217 {
218 eq = FALSE;
219 break;
220 }
221 }
222 e1->destroy(e1);
223 e2->destroy(e2);
224
225 return (eq &&
226 this->certreq == other->certreq &&
227 this->force_encap == other->force_encap &&
228 streq(this->me, other->me) &&
229 streq(this->other, other->other));
230 }
231
232 /**
233 * Implementation of ike_cfg_t.get_ref.
234 */
235 static ike_cfg_t* get_ref(private_ike_cfg_t *this)
236 {
237 ref_get(&this->refcount);
238 return &this->public;
239 }
240
241 /**
242 * Implementation of ike_cfg_t.destroy.
243 */
244 static void destroy(private_ike_cfg_t *this)
245 {
246 if (ref_put(&this->refcount))
247 {
248 this->proposals->destroy_offset(this->proposals,
249 offsetof(proposal_t, destroy));
250 free(this->me);
251 free(this->other);
252 free(this);
253 }
254 }
255
256 /**
257 * Described in header.
258 */
259 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
260 char *me, char *other)
261 {
262 private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t);
263
264 /* public functions */
265 this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq;
266 this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth;
267 this->public.get_my_addr = (char*(*)(ike_cfg_t*))get_my_addr;
268 this->public.get_other_addr = (char*(*)(ike_cfg_t*))get_other_addr;
269 this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal;
270 this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals;
271 this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal;
272 this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group;
273 this->public.equals = (bool(*)(ike_cfg_t*,ike_cfg_t*)) equals;
274 this->public.get_ref = (ike_cfg_t*(*)(ike_cfg_t*))get_ref;
275 this->public.destroy = (void(*)(ike_cfg_t*))destroy;
276
277 /* private variables */
278 this->refcount = 1;
279 this->certreq = certreq;
280 this->force_encap = force_encap;
281 this->me = strdup(me);
282 this->other = strdup(other);
283 this->proposals = linked_list_create();
284
285 return &this->public;
286 }