]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/config/ike_cfg.c
Merge branch 'eap-client-select'
[thirdparty/strongswan.git] / src / libcharon / 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 * Allow override of local address
53 */
54 bool my_allow_any;
55
56 /**
57 * Allow override of remote address
58 */
59 bool other_allow_any;
60
61 /**
62 * our source port
63 */
64 u_int16_t my_port;
65
66 /**
67 * destination port
68 */
69 u_int16_t other_port;
70
71 /**
72 * should we send a certificate request?
73 */
74 bool certreq;
75
76 /**
77 * enforce UDP encapsulation
78 */
79 bool force_encap;
80
81 /**
82 * List of proposals to use
83 */
84 linked_list_t *proposals;
85 };
86
87 METHOD(ike_cfg_t, send_certreq, bool,
88 private_ike_cfg_t *this)
89 {
90 return this->certreq;
91 }
92
93 METHOD(ike_cfg_t, force_encap_, bool,
94 private_ike_cfg_t *this)
95 {
96 return this->force_encap;
97 }
98
99 METHOD(ike_cfg_t, get_my_addr, char*,
100 private_ike_cfg_t *this, bool *allow_any)
101 {
102 if (allow_any)
103 {
104 *allow_any = this->my_allow_any;
105 }
106 return this->me;
107 }
108
109 METHOD(ike_cfg_t, get_other_addr, char*,
110 private_ike_cfg_t *this, bool *allow_any)
111 {
112 if (allow_any)
113 {
114 *allow_any = this->other_allow_any;
115 }
116 return this->other;
117 }
118
119 METHOD(ike_cfg_t, get_my_port, u_int16_t,
120 private_ike_cfg_t *this)
121 {
122 return this->my_port;
123 }
124
125 METHOD(ike_cfg_t, get_other_port, u_int16_t,
126 private_ike_cfg_t *this)
127 {
128 return this->other_port;
129 }
130
131 METHOD(ike_cfg_t, add_proposal, void,
132 private_ike_cfg_t *this, proposal_t *proposal)
133 {
134 this->proposals->insert_last(this->proposals, proposal);
135 }
136
137 METHOD(ike_cfg_t, get_proposals, linked_list_t*,
138 private_ike_cfg_t *this)
139 {
140 enumerator_t *enumerator;
141 proposal_t *current;
142 linked_list_t *proposals;
143
144 proposals = linked_list_create();
145 enumerator = this->proposals->create_enumerator(this->proposals);
146 while (enumerator->enumerate(enumerator, &current))
147 {
148 current = current->clone(current);
149 proposals->insert_last(proposals, current);
150 }
151 enumerator->destroy(enumerator);
152
153 DBG2(DBG_CFG, "configured proposals: %#P", proposals);
154
155 return proposals;
156 }
157
158 METHOD(ike_cfg_t, select_proposal, proposal_t*,
159 private_ike_cfg_t *this, linked_list_t *proposals, bool private)
160 {
161 enumerator_t *stored_enum, *supplied_enum;
162 proposal_t *stored, *supplied, *selected;
163
164 stored_enum = this->proposals->create_enumerator(this->proposals);
165 supplied_enum = proposals->create_enumerator(proposals);
166
167
168 /* compare all stored proposals with all supplied. Stored ones are preferred.*/
169 while (stored_enum->enumerate(stored_enum, (void**)&stored))
170 {
171 proposals->reset_enumerator(proposals, supplied_enum);
172
173 while (supplied_enum->enumerate(supplied_enum, (void**)&supplied))
174 {
175 selected = stored->select(stored, supplied, private);
176 if (selected)
177 {
178 /* they match, return */
179 stored_enum->destroy(stored_enum);
180 supplied_enum->destroy(supplied_enum);
181 DBG2(DBG_CFG, "received proposals: %#P", proposals);
182 DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
183 DBG2(DBG_CFG, "selected proposal: %P", selected);
184 return selected;
185 }
186 }
187 }
188 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
189 stored_enum->destroy(stored_enum);
190 supplied_enum->destroy(supplied_enum);
191 DBG1(DBG_CFG, "received proposals: %#P", proposals);
192 DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
193
194 return NULL;
195 }
196
197 METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
198 private_ike_cfg_t *this)
199 {
200 enumerator_t *enumerator;
201 proposal_t *proposal;
202 u_int16_t dh_group = MODP_NONE;
203
204 enumerator = this->proposals->create_enumerator(this->proposals);
205 while (enumerator->enumerate(enumerator, &proposal))
206 {
207 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
208 {
209 break;
210 }
211 }
212 enumerator->destroy(enumerator);
213 return dh_group;
214 }
215
216 METHOD(ike_cfg_t, equals, bool,
217 private_ike_cfg_t *this, ike_cfg_t *other_public)
218 {
219 private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
220 enumerator_t *e1, *e2;
221 proposal_t *p1, *p2;
222 bool eq = TRUE;
223
224 if (this == other)
225 {
226 return TRUE;
227 }
228 if (this->public.equals != other->public.equals)
229 {
230 return FALSE;
231 }
232 if (this->proposals->get_count(this->proposals) !=
233 other->proposals->get_count(other->proposals))
234 {
235 return FALSE;
236 }
237 e1 = this->proposals->create_enumerator(this->proposals);
238 e2 = this->proposals->create_enumerator(this->proposals);
239 while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
240 {
241 if (!p1->equals(p1, p2))
242 {
243 eq = FALSE;
244 break;
245 }
246 }
247 e1->destroy(e1);
248 e2->destroy(e2);
249
250 return (eq &&
251 this->certreq == other->certreq &&
252 this->force_encap == other->force_encap &&
253 streq(this->me, other->me) &&
254 streq(this->other, other->other) &&
255 this->my_port == other->my_port &&
256 this->other_port == other->other_port);
257 }
258
259 METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
260 private_ike_cfg_t *this)
261 {
262 ref_get(&this->refcount);
263 return &this->public;
264 }
265
266 METHOD(ike_cfg_t, destroy, void,
267 private_ike_cfg_t *this)
268 {
269 if (ref_put(&this->refcount))
270 {
271 this->proposals->destroy_offset(this->proposals,
272 offsetof(proposal_t, destroy));
273 free(this->me);
274 free(this->other);
275 free(this);
276 }
277 }
278
279 /**
280 * Described in header.
281 */
282 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
283 char *me, bool my_allow_any, u_int16_t my_port,
284 char *other, bool other_allow_any, u_int16_t other_port)
285 {
286 private_ike_cfg_t *this;
287
288 INIT(this,
289 .public = {
290 .send_certreq = _send_certreq,
291 .force_encap = _force_encap_,
292 .get_my_addr = _get_my_addr,
293 .get_other_addr = _get_other_addr,
294 .get_my_port = _get_my_port,
295 .get_other_port = _get_other_port,
296 .add_proposal = _add_proposal,
297 .get_proposals = _get_proposals,
298 .select_proposal = _select_proposal,
299 .get_dh_group = _get_dh_group,
300 .equals = _equals,
301 .get_ref = _get_ref,
302 .destroy = _destroy,
303 },
304 .refcount = 1,
305 .certreq = certreq,
306 .force_encap = force_encap,
307 .me = strdup(me),
308 .other = strdup(other),
309 .my_allow_any = my_allow_any,
310 .other_allow_any = other_allow_any,
311 .my_port = my_port,
312 .other_port = other_port,
313 .proposals = linked_list_create(),
314 );
315
316 return &this->public;
317 }