ike-cfg: remove the to be obsoleted allow any parameter in get_my/other_addr
[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 ENUM(ike_version_names, IKE_ANY, IKEV2,
25 "IKEv1/2",
26 "IKEv1",
27 "IKEv2",
28 );
29
30 typedef struct private_ike_cfg_t private_ike_cfg_t;
31
32 /**
33 * Private data of an ike_cfg_t object
34 */
35 struct private_ike_cfg_t {
36
37 /**
38 * Public part
39 */
40 ike_cfg_t public;
41
42 /**
43 * Number of references hold by others to this ike_cfg
44 */
45 refcount_t refcount;
46
47 /**
48 * IKE version to use
49 */
50 ike_version_t version;
51
52 /**
53 * Address of local host
54 */
55 char *me;
56
57 /**
58 * Address of remote host
59 */
60 char *other;
61
62 /**
63 * Allow override of local address
64 */
65 bool my_allow_any;
66
67 /**
68 * Allow override of remote address
69 */
70 bool other_allow_any;
71
72 /**
73 * our source port
74 */
75 u_int16_t my_port;
76
77 /**
78 * destination port
79 */
80 u_int16_t other_port;
81
82 /**
83 * should we send a certificate request?
84 */
85 bool certreq;
86
87 /**
88 * enforce UDP encapsulation
89 */
90 bool force_encap;
91
92 /**
93 * use IKEv1 fragmentation
94 */
95 fragmentation_t fragmentation;
96
97 /**
98 * DSCP value to use on sent IKE packets
99 */
100 u_int8_t dscp;
101
102 /**
103 * List of proposals to use
104 */
105 linked_list_t *proposals;
106 };
107
108 METHOD(ike_cfg_t, get_version, ike_version_t,
109 private_ike_cfg_t *this)
110 {
111 return this->version;
112 }
113
114 METHOD(ike_cfg_t, send_certreq, bool,
115 private_ike_cfg_t *this)
116 {
117 return this->certreq;
118 }
119
120 METHOD(ike_cfg_t, force_encap_, bool,
121 private_ike_cfg_t *this)
122 {
123 return this->force_encap;
124 }
125
126 METHOD(ike_cfg_t, fragmentation, fragmentation_t,
127 private_ike_cfg_t *this)
128 {
129 return this->fragmentation;
130 }
131
132 METHOD(ike_cfg_t, resolve_me, host_t*,
133 private_ike_cfg_t *this, int family)
134 {
135 return host_create_from_dns(this->me, family, this->my_port);
136 }
137
138 METHOD(ike_cfg_t, resolve_other, host_t*,
139 private_ike_cfg_t *this, int family)
140 {
141 return host_create_from_dns(this->other, family, this->other_port);
142 }
143
144 METHOD(ike_cfg_t, match_me, u_int,
145 private_ike_cfg_t *this, host_t *host)
146 {
147 host_t *me;
148 int quality = 0;
149
150 me = resolve_me(this, host->get_family(host));
151 if (me)
152 {
153 if (me->ip_equals(me, host))
154 {
155 quality = 2;
156 }
157 else if (this->my_allow_any)
158 {
159 quality = 1;
160 }
161 me->destroy(me);
162 }
163 return quality;
164 }
165
166 METHOD(ike_cfg_t, match_other, u_int,
167 private_ike_cfg_t *this, host_t *host)
168 {
169 host_t *other;
170 int quality = 0;
171
172 other = resolve_other(this, host->get_family(host));
173 if (other)
174 {
175 if (other->ip_equals(other, host))
176 {
177 quality = 2;
178 }
179 else if (this->other_allow_any)
180 {
181 quality = 1;
182 }
183 other->destroy(other);
184 }
185 return quality;
186 }
187
188 METHOD(ike_cfg_t, get_my_addr, char*,
189 private_ike_cfg_t *this)
190 {
191 return this->me;
192 }
193
194 METHOD(ike_cfg_t, get_other_addr, char*,
195 private_ike_cfg_t *this)
196 {
197 return this->other;
198 }
199
200 METHOD(ike_cfg_t, get_my_port, u_int16_t,
201 private_ike_cfg_t *this)
202 {
203 return this->my_port;
204 }
205
206 METHOD(ike_cfg_t, get_other_port, u_int16_t,
207 private_ike_cfg_t *this)
208 {
209 return this->other_port;
210 }
211
212 METHOD(ike_cfg_t, get_dscp, u_int8_t,
213 private_ike_cfg_t *this)
214 {
215 return this->dscp;
216 }
217
218 METHOD(ike_cfg_t, add_proposal, void,
219 private_ike_cfg_t *this, proposal_t *proposal)
220 {
221 this->proposals->insert_last(this->proposals, proposal);
222 }
223
224 METHOD(ike_cfg_t, get_proposals, linked_list_t*,
225 private_ike_cfg_t *this)
226 {
227 enumerator_t *enumerator;
228 proposal_t *current;
229 linked_list_t *proposals;
230
231 proposals = linked_list_create();
232 enumerator = this->proposals->create_enumerator(this->proposals);
233 while (enumerator->enumerate(enumerator, &current))
234 {
235 current = current->clone(current);
236 proposals->insert_last(proposals, current);
237 }
238 enumerator->destroy(enumerator);
239
240 DBG2(DBG_CFG, "configured proposals: %#P", proposals);
241
242 return proposals;
243 }
244
245 METHOD(ike_cfg_t, select_proposal, proposal_t*,
246 private_ike_cfg_t *this, linked_list_t *proposals, bool private)
247 {
248 enumerator_t *stored_enum, *supplied_enum;
249 proposal_t *stored, *supplied, *selected;
250
251 stored_enum = this->proposals->create_enumerator(this->proposals);
252 supplied_enum = proposals->create_enumerator(proposals);
253
254
255 /* compare all stored proposals with all supplied. Stored ones are preferred.*/
256 while (stored_enum->enumerate(stored_enum, (void**)&stored))
257 {
258 proposals->reset_enumerator(proposals, supplied_enum);
259
260 while (supplied_enum->enumerate(supplied_enum, (void**)&supplied))
261 {
262 selected = stored->select(stored, supplied, private);
263 if (selected)
264 {
265 /* they match, return */
266 stored_enum->destroy(stored_enum);
267 supplied_enum->destroy(supplied_enum);
268 DBG2(DBG_CFG, "received proposals: %#P", proposals);
269 DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
270 DBG2(DBG_CFG, "selected proposal: %P", selected);
271 return selected;
272 }
273 }
274 }
275 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
276 stored_enum->destroy(stored_enum);
277 supplied_enum->destroy(supplied_enum);
278 DBG1(DBG_CFG, "received proposals: %#P", proposals);
279 DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
280
281 return NULL;
282 }
283
284 METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
285 private_ike_cfg_t *this)
286 {
287 enumerator_t *enumerator;
288 proposal_t *proposal;
289 u_int16_t dh_group = MODP_NONE;
290
291 enumerator = this->proposals->create_enumerator(this->proposals);
292 while (enumerator->enumerate(enumerator, &proposal))
293 {
294 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
295 {
296 break;
297 }
298 }
299 enumerator->destroy(enumerator);
300 return dh_group;
301 }
302
303 METHOD(ike_cfg_t, equals, bool,
304 private_ike_cfg_t *this, ike_cfg_t *other_public)
305 {
306 private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
307 enumerator_t *e1, *e2;
308 proposal_t *p1, *p2;
309 bool eq = TRUE;
310
311 if (this == other)
312 {
313 return TRUE;
314 }
315 if (this->public.equals != other->public.equals)
316 {
317 return FALSE;
318 }
319 if (this->proposals->get_count(this->proposals) !=
320 other->proposals->get_count(other->proposals))
321 {
322 return FALSE;
323 }
324 e1 = this->proposals->create_enumerator(this->proposals);
325 e2 = this->proposals->create_enumerator(this->proposals);
326 while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
327 {
328 if (!p1->equals(p1, p2))
329 {
330 eq = FALSE;
331 break;
332 }
333 }
334 e1->destroy(e1);
335 e2->destroy(e2);
336
337 return (eq &&
338 this->version == other->version &&
339 this->certreq == other->certreq &&
340 this->force_encap == other->force_encap &&
341 this->fragmentation == other->fragmentation &&
342 streq(this->me, other->me) &&
343 streq(this->other, other->other) &&
344 this->my_port == other->my_port &&
345 this->other_port == other->other_port);
346 }
347
348 METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
349 private_ike_cfg_t *this)
350 {
351 ref_get(&this->refcount);
352 return &this->public;
353 }
354
355 METHOD(ike_cfg_t, destroy, void,
356 private_ike_cfg_t *this)
357 {
358 if (ref_put(&this->refcount))
359 {
360 this->proposals->destroy_offset(this->proposals,
361 offsetof(proposal_t, destroy));
362 free(this->me);
363 free(this->other);
364 free(this);
365 }
366 }
367
368 /**
369 * Described in header.
370 */
371 ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
372 char *me, bool my_allow_any, u_int16_t my_port,
373 char *other, bool other_allow_any, u_int16_t other_port,
374 fragmentation_t fragmentation, u_int8_t dscp)
375 {
376 private_ike_cfg_t *this;
377
378 INIT(this,
379 .public = {
380 .get_version = _get_version,
381 .send_certreq = _send_certreq,
382 .force_encap = _force_encap_,
383 .fragmentation = _fragmentation,
384 .resolve_me = _resolve_me,
385 .resolve_other = _resolve_other,
386 .match_me = _match_me,
387 .match_other = _match_other,
388 .get_my_addr = _get_my_addr,
389 .get_other_addr = _get_other_addr,
390 .get_my_port = _get_my_port,
391 .get_other_port = _get_other_port,
392 .get_dscp = _get_dscp,
393 .add_proposal = _add_proposal,
394 .get_proposals = _get_proposals,
395 .select_proposal = _select_proposal,
396 .get_dh_group = _get_dh_group,
397 .equals = _equals,
398 .get_ref = _get_ref,
399 .destroy = _destroy,
400 },
401 .refcount = 1,
402 .version = version,
403 .certreq = certreq,
404 .force_encap = force_encap,
405 .fragmentation = fragmentation,
406 .me = strdup(me),
407 .other = strdup(other),
408 .my_allow_any = my_allow_any,
409 .other_allow_any = other_allow_any,
410 .my_port = my_port,
411 .other_port = other_port,
412 .dscp = dscp,
413 .proposals = linked_list_create(),
414 );
415
416 return &this->public;
417 }