]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/config/ike_cfg.c
ike-cfg: Change how OCSP certificate requests are enabled
[thirdparty/strongswan.git] / src / libcharon / config / ike_cfg.c
CommitLineData
e0fe7651 1/*
9486a2e5 2 * Copyright (C) 2012-2019 Tobias Brunner
e0fe7651
MW
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
19ef2aec
TB
5 *
6 * Copyright (C) secunet Security Networks AG
e0fe7651
MW
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
ab13364c 19#define _GNU_SOURCE /* for stdndup() */
e0fe7651
MW
20#include <string.h>
21
ab13364c 22#include "ike_cfg.h"
035930fc 23
ab13364c 24#include <daemon.h>
e0fe7651 25
cf62d073
MW
26ENUM(ike_version_names, IKE_ANY, IKEV2,
27 "IKEv1/2",
28 "IKEv1",
29 "IKEv2",
30);
31
e0fe7651
MW
32typedef struct private_ike_cfg_t private_ike_cfg_t;
33
34/**
35 * Private data of an ike_cfg_t object
36 */
37struct private_ike_cfg_t {
38
39 /**
40 * Public part
41 */
42 ike_cfg_t public;
7daf5226 43
e0fe7651
MW
44 /**
45 * Number of references hold by others to this ike_cfg
46 */
47 refcount_t refcount;
48
9fc7cc6f
MW
49 /**
50 * IKE version to use
51 */
52 ike_version_t version;
53
e0fe7651 54 /**
3070697f 55 * Address list string for local host
e0fe7651 56 */
5a22a021 57 char *me;
e0fe7651
MW
58
59 /**
3070697f 60 * Address list string for remote host
7daf5226 61 */
5a22a021 62 char *other;
7daf5226 63
1d315bdd 64 /**
3070697f 65 * Local single host or DNS names, as allocated char*
1d315bdd 66 */
3070697f 67 linked_list_t *my_hosts;
1d315bdd
AS
68
69 /**
3070697f 70 * Remote single host or DNS names, as allocated char*
1d315bdd 71 */
3070697f
MW
72 linked_list_t *other_hosts;
73
74 /**
75 * Local ranges/subnets this config matches to, as traffic_selector_t*
76 */
77 linked_list_t *my_ranges;
78
79 /**
80 * Remote ranges/subnets this config matches to, as traffic_selector_t*
81 */
82 linked_list_t *other_ranges;
1d315bdd 83
4e18490e
MW
84 /**
85 * our source port
86 */
b12c53ce 87 uint16_t my_port;
4e18490e
MW
88
89 /**
90 * destination port
91 */
b12c53ce 92 uint16_t other_port;
4e18490e 93
e0fe7651
MW
94 /**
95 * should we send a certificate request?
96 */
97 bool certreq;
7daf5226 98
15612b3a
JFH
99 /**
100 * should we send an OCSP status request?
101 */
102 bool ocsp_certreq;
103
f53b74c9
MW
104 /**
105 * enforce UDP encapsulation
106 */
107 bool force_encap;
7daf5226 108
97973f86 109 /**
ddb083c1 110 * use IKE fragmentation
97973f86 111 */
365d9a6f 112 fragmentation_t fragmentation;
97973f86 113
ddb083c1
TB
114 /**
115 * childless IKE_SAs
116 */
117 childless_t childless;
118
306a269e
MW
119 /**
120 * DSCP value to use on sent IKE packets
121 */
b12c53ce 122 uint8_t dscp;
306a269e 123
e0fe7651
MW
124 /**
125 * List of proposals to use
126 */
127 linked_list_t *proposals;
128};
129
9fc7cc6f
MW
130METHOD(ike_cfg_t, get_version, ike_version_t,
131 private_ike_cfg_t *this)
132{
133 return this->version;
134}
135
deac3a0a
MW
136METHOD(ike_cfg_t, send_certreq, bool,
137 private_ike_cfg_t *this)
e0fe7651
MW
138{
139 return this->certreq;
140}
7daf5226 141
15612b3a
JFH
142METHOD(ike_cfg_t, send_ocsp_certreq, bool,
143 private_ike_cfg_t *this)
144{
145 return this->ocsp_certreq;
146}
147
deac3a0a
MW
148METHOD(ike_cfg_t, force_encap_, bool,
149 private_ike_cfg_t *this)
f53b74c9
MW
150{
151 return this->force_encap;
152}
e0fe7651 153
365d9a6f 154METHOD(ike_cfg_t, fragmentation, fragmentation_t,
97973f86
TB
155 private_ike_cfg_t *this)
156{
157 return this->fragmentation;
158}
159
ddb083c1
TB
160METHOD(ike_cfg_t, childless, childless_t,
161 private_ike_cfg_t *this)
162{
163 return this->childless;
164}
165
3070697f
MW
166/**
167 * Common function for resolve_me/other
168 */
b12c53ce 169static host_t* resolve(linked_list_t *hosts, int family, uint16_t port)
3070697f
MW
170{
171 enumerator_t *enumerator;
172 host_t *host = NULL;
173 bool tried = FALSE;
174 char *str;
175
176 enumerator = hosts->create_enumerator(hosts);
177 while (enumerator->enumerate(enumerator, &str))
178 {
179 host = host_create_from_dns(str, family, port);
180 if (host)
181 {
182 break;
183 }
184 tried = TRUE;
185 }
186 enumerator->destroy(enumerator);
187
188 if (!host && !tried)
189 {
190 /* we have no single host configured, return %any */
191 host = host_create_any(family ?: AF_INET);
192 host->set_port(host, port);
193 }
194 return host;
195}
196
e743275c
MW
197METHOD(ike_cfg_t, resolve_me, host_t*,
198 private_ike_cfg_t *this, int family)
199{
3070697f 200 return resolve(this->my_hosts, family, this->my_port);
e743275c
MW
201}
202
203METHOD(ike_cfg_t, resolve_other, host_t*,
204 private_ike_cfg_t *this, int family)
205{
3070697f 206 return resolve(this->other_hosts, family, this->other_port);
e743275c
MW
207}
208
3070697f
MW
209/**
210 * Common function for match_me/other
211 */
212static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
6f666192 213{
3070697f
MW
214 enumerator_t *enumerator;
215 traffic_selector_t *ts;
216 char *str;
217 host_t *host;
b12c53ce 218 uint8_t mask;
3070697f
MW
219 u_int quality = 0;
220
221 /* try single hosts first */
222 enumerator = hosts->create_enumerator(hosts);
223 while (enumerator->enumerate(enumerator, &str))
6f666192 224 {
3070697f
MW
225 host = host_create_from_dns(str, cand->get_family(cand), 0);
226 if (host)
6f666192 227 {
3070697f
MW
228 if (host->ip_equals(host, cand))
229 {
230 quality = max(quality, 128 + 1);
231 }
232 if (host->is_anyaddr(host))
233 {
234 quality = max(quality, 1);
235 }
236 host->destroy(host);
6f666192 237 }
3070697f
MW
238 }
239 enumerator->destroy(enumerator);
240
241 /* then ranges/subnets */
242 enumerator = ranges->create_enumerator(ranges);
243 while (enumerator->enumerate(enumerator, &ts))
244 {
245 if (ts->includes(ts, cand))
6f666192 246 {
3070697f
MW
247 if (ts->to_subnet(ts, &host, &mask))
248 {
249 quality = max(quality, mask + 1);
3070697f
MW
250 }
251 else
252 {
253 quality = max(quality, 1);
254 }
a09e79ed 255 host->destroy(host);
6f666192 256 }
6f666192 257 }
3070697f
MW
258 enumerator->destroy(enumerator);
259
6f666192
MW
260 return quality;
261}
262
3070697f 263METHOD(ike_cfg_t, match_me, u_int,
6f666192
MW
264 private_ike_cfg_t *this, host_t *host)
265{
3070697f
MW
266 return match(this->my_hosts, this->my_ranges, host);
267}
6f666192 268
3070697f
MW
269METHOD(ike_cfg_t, match_other, u_int,
270 private_ike_cfg_t *this, host_t *host)
271{
272 return match(this->other_hosts, this->other_ranges, host);
6f666192
MW
273}
274
deac3a0a 275METHOD(ike_cfg_t, get_my_addr, char*,
beffdc6a 276 private_ike_cfg_t *this)
e0fe7651 277{
5a22a021 278 return this->me;
e0fe7651
MW
279}
280
deac3a0a 281METHOD(ike_cfg_t, get_other_addr, char*,
beffdc6a 282 private_ike_cfg_t *this)
e0fe7651 283{
5a22a021 284 return this->other;
e0fe7651
MW
285}
286
b12c53ce 287METHOD(ike_cfg_t, get_my_port, uint16_t,
4e18490e
MW
288 private_ike_cfg_t *this)
289{
290 return this->my_port;
291}
292
b12c53ce 293METHOD(ike_cfg_t, get_other_port, uint16_t,
4e18490e
MW
294 private_ike_cfg_t *this)
295{
296 return this->other_port;
297}
298
b12c53ce 299METHOD(ike_cfg_t, get_dscp, uint8_t,
306a269e
MW
300 private_ike_cfg_t *this)
301{
302 return this->dscp;
303}
304
deac3a0a
MW
305METHOD(ike_cfg_t, add_proposal, void,
306 private_ike_cfg_t *this, proposal_t *proposal)
e0fe7651 307{
3312c447
MW
308 if (proposal)
309 {
310 this->proposals->insert_last(this->proposals, proposal);
311 }
e0fe7651
MW
312}
313
deac3a0a
MW
314METHOD(ike_cfg_t, get_proposals, linked_list_t*,
315 private_ike_cfg_t *this)
e0fe7651 316{
deac3a0a 317 enumerator_t *enumerator;
e0fe7651 318 proposal_t *current;
deac3a0a 319 linked_list_t *proposals;
7daf5226 320
deac3a0a
MW
321 proposals = linked_list_create();
322 enumerator = this->proposals->create_enumerator(this->proposals);
323 while (enumerator->enumerate(enumerator, &current))
e0fe7651 324 {
a2cb2c9c 325 current = current->clone(current, 0);
deac3a0a 326 proposals->insert_last(proposals, current);
e0fe7651 327 }
deac3a0a 328 enumerator->destroy(enumerator);
a21fac9a
TB
329
330 DBG2(DBG_CFG, "configured proposals: %#P", proposals);
7daf5226 331
e0fe7651
MW
332 return proposals;
333}
7daf5226 334
29e7fe63
TB
335METHOD(ike_cfg_t, has_proposal, bool,
336 private_ike_cfg_t *this, proposal_t *match, bool private)
337{
338 enumerator_t *enumerator;
339 proposal_t *proposal;
340
341 enumerator = this->proposals->create_enumerator(this->proposals);
342 while (enumerator->enumerate(enumerator, &proposal))
343 {
f930b732 344 if (proposal->matches(proposal, match,
a2cb2c9c 345 private ? 0 : PROPOSAL_SKIP_PRIVATE))
29e7fe63
TB
346 {
347 enumerator->destroy(enumerator);
348 return TRUE;
349 }
350 }
351 enumerator->destroy(enumerator);
352 return FALSE;
353}
354
deac3a0a 355METHOD(ike_cfg_t, select_proposal, proposal_t*,
f930b732
TE
356 private_ike_cfg_t *this, linked_list_t *proposals,
357 proposal_selection_flag_t flags)
e0fe7651 358{
c9599d41 359 return proposal_select(this->proposals, proposals, flags);
e0fe7651
MW
360}
361
093fc1ac
TB
362METHOD(ike_cfg_t, get_algorithm, uint16_t,
363 private_ike_cfg_t *this, transform_type_t type)
e0fe7651 364{
3c7e72f5 365 enumerator_t *enumerator;
e0fe7651 366 proposal_t *proposal;
093fc1ac 367 uint16_t alg = 0;
7daf5226 368
3c7e72f5
MW
369 enumerator = this->proposals->create_enumerator(this->proposals);
370 while (enumerator->enumerate(enumerator, &proposal))
e0fe7651 371 {
093fc1ac 372 if (proposal->get_algorithm(proposal, type, &alg, NULL))
e0fe7651 373 {
e0fe7651
MW
374 break;
375 }
376 }
3c7e72f5 377 enumerator->destroy(enumerator);
093fc1ac 378 return alg;
e0fe7651
MW
379}
380
deac3a0a
MW
381METHOD(ike_cfg_t, equals, bool,
382 private_ike_cfg_t *this, ike_cfg_t *other_public)
3c7e72f5 383{
deac3a0a 384 private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
7daf5226 385
3c7e72f5
MW
386 if (this == other)
387 {
388 return TRUE;
389 }
390 if (this->public.equals != other->public.equals)
391 {
392 return FALSE;
393 }
8db4f19a
TB
394 if (!this->proposals->equals_offset(this->proposals, other->proposals,
395 offsetof(proposal_t, equals)))
3c7e72f5
MW
396 {
397 return FALSE;
398 }
8db4f19a 399 return
9fc7cc6f 400 this->version == other->version &&
3c7e72f5 401 this->certreq == other->certreq &&
15612b3a 402 this->ocsp_certreq == other->ocsp_certreq &&
3c7e72f5 403 this->force_encap == other->force_encap &&
97973f86 404 this->fragmentation == other->fragmentation &&
ddb083c1 405 this->childless == other->childless &&
5a22a021 406 streq(this->me, other->me) &&
af2c43fd
MW
407 streq(this->other, other->other) &&
408 this->my_port == other->my_port &&
8db4f19a 409 this->other_port == other->other_port;
3c7e72f5
MW
410}
411
deac3a0a
MW
412METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
413 private_ike_cfg_t *this)
e0fe7651
MW
414{
415 ref_get(&this->refcount);
ff683671 416 return &this->public;
e0fe7651
MW
417}
418
deac3a0a
MW
419METHOD(ike_cfg_t, destroy, void,
420 private_ike_cfg_t *this)
e0fe7651
MW
421{
422 if (ref_put(&this->refcount))
423 {
424 this->proposals->destroy_offset(this->proposals,
425 offsetof(proposal_t, destroy));
5a22a021
MW
426 free(this->me);
427 free(this->other);
3070697f
MW
428 this->my_hosts->destroy_function(this->my_hosts, free);
429 this->other_hosts->destroy_function(this->other_hosts, free);
430 this->my_ranges->destroy_offset(this->my_ranges,
431 offsetof(traffic_selector_t, destroy));
432 this->other_ranges->destroy_offset(this->other_ranges,
433 offsetof(traffic_selector_t, destroy));
e0fe7651
MW
434 free(this);
435 }
436}
437
3070697f
MW
438/**
439 * Try to parse a string as subnet
440 */
441static traffic_selector_t* make_subnet(char *str)
442{
443 char *pos;
444
445 pos = strchr(str, '/');
446 if (!pos)
447 {
448 return NULL;
449 }
450 return traffic_selector_create_from_cidr(str, 0, 0, 0);
451}
452
453/**
454 * Try to parse a string as an IP range
455 */
456static traffic_selector_t* make_range(char *str)
457{
458 traffic_selector_t *ts;
459 ts_type_t type;
3070697f
MW
460 host_t *from, *to;
461
e0cd3bad 462 if (!host_create_from_range(str, &from, &to))
3070697f 463 {
3070697f
MW
464 return NULL;
465 }
466 if (to->get_family(to) == AF_INET)
467 {
468 type = TS_IPV4_ADDR_RANGE;
469 }
470 else
471 {
472 type = TS_IPV6_ADDR_RANGE;
473 }
474 ts = traffic_selector_create_from_bytes(0, type,
475 from->get_address(from), 0,
476 to->get_address(to), 0);
477 from->destroy(from);
478 to->destroy(to);
479 return ts;
480}
481
482/**
483 * Parse address string into lists of single hosts and ranges/subnets
484 */
485static void parse_addresses(char *str, linked_list_t *hosts,
486 linked_list_t *ranges)
487{
488 enumerator_t *enumerator;
489 traffic_selector_t *ts;
490
491 enumerator = enumerator_create_token(str, ",", " ");
492 while (enumerator->enumerate(enumerator, &str))
493 {
494 ts = make_subnet(str);
495 if (ts)
496 {
497 ranges->insert_last(ranges, ts);
498 continue;
499 }
500 ts = make_range(str);
501 if (ts)
502 {
503 ranges->insert_last(ranges, ts);
504 continue;
505 }
506 hosts->insert_last(hosts, strdup(str));
507 }
508 enumerator->destroy(enumerator);
509}
510
6bfa6606
TB
511/**
512 * Described in header.
513 */
514int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
515{
516 private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
517 enumerator_t *enumerator;
518 host_t *host;
519 char *str;
520 int family = AF_UNSPEC;
521
522 if (local)
523 {
524 enumerator = this->my_hosts->create_enumerator(this->my_hosts);
525 }
526 else
527 {
528 enumerator = this->other_hosts->create_enumerator(this->other_hosts);
529 }
530 while (enumerator->enumerate(enumerator, &str))
531 {
532 if (streq(str, "%any"))
533 { /* ignore %any as its family is undetermined */
534 continue;
535 }
536 host = host_create_from_string(str, 0);
537 if (host)
538 {
539 if (family == AF_UNSPEC)
540 {
541 family = host->get_family(host);
542 }
543 else if (family != host->get_family(host))
544 {
545 /* more than one address family defined */
546 family = AF_UNSPEC;
547 host->destroy(host);
548 break;
549 }
550 }
551 DESTROY_IF(host);
552 }
553 enumerator->destroy(enumerator);
554 return family;
555}
556
5a7a17b7
TB
557/**
558 * Described in header.
559 */
560bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
561{
562 private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
563 enumerator_t *enumerator;
564 host_t *host;
565 char *str;
566 bool found = FALSE;
567
568 if (local)
569 {
570 enumerator = this->my_hosts->create_enumerator(this->my_hosts);
571 }
572 else
573 {
574 enumerator = this->other_hosts->create_enumerator(this->other_hosts);
575 }
576 while (enumerator->enumerate(enumerator, &str))
577 {
578 host = host_create_from_string(str, 0);
579 if (host && addr->ip_equals(addr, host))
580 {
66805c7b 581 host->destroy(host);
5a7a17b7
TB
582 found = TRUE;
583 break;
584 }
585 DESTROY_IF(host);
586 }
587 enumerator->destroy(enumerator);
588 return found;
589}
590
9486a2e5
TB
591/*
592 * Described in header
e0fe7651 593 */
9486a2e5 594ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
e0fe7651 595{
deac3a0a
MW
596 private_ike_cfg_t *this;
597
598 INIT(this,
599 .public = {
9fc7cc6f 600 .get_version = _get_version,
deac3a0a 601 .send_certreq = _send_certreq,
15612b3a 602 .send_ocsp_certreq = _send_ocsp_certreq,
deac3a0a 603 .force_encap = _force_encap_,
97973f86 604 .fragmentation = _fragmentation,
ddb083c1 605 .childless = _childless,
e743275c
MW
606 .resolve_me = _resolve_me,
607 .resolve_other = _resolve_other,
6f666192
MW
608 .match_me = _match_me,
609 .match_other = _match_other,
deac3a0a
MW
610 .get_my_addr = _get_my_addr,
611 .get_other_addr = _get_other_addr,
4e18490e
MW
612 .get_my_port = _get_my_port,
613 .get_other_port = _get_other_port,
306a269e 614 .get_dscp = _get_dscp,
deac3a0a
MW
615 .add_proposal = _add_proposal,
616 .get_proposals = _get_proposals,
617 .select_proposal = _select_proposal,
29e7fe63 618 .has_proposal = _has_proposal,
093fc1ac 619 .get_algorithm = _get_algorithm,
deac3a0a
MW
620 .equals = _equals,
621 .get_ref = _get_ref,
622 .destroy = _destroy,
623 },
624 .refcount = 1,
9486a2e5
TB
625 .version = data->version,
626 .certreq = !data->no_certreq,
9acd9057 627 .ocsp_certreq = data->ocsp_certreq,
9486a2e5
TB
628 .force_encap = data->force_encap,
629 .fragmentation = data->fragmentation,
ddb083c1 630 .childless = data->childless,
9486a2e5 631 .me = strdup(data->local),
3070697f
MW
632 .my_ranges = linked_list_create(),
633 .my_hosts = linked_list_create(),
9486a2e5 634 .other = strdup(data->remote),
3070697f
MW
635 .other_ranges = linked_list_create(),
636 .other_hosts = linked_list_create(),
9486a2e5
TB
637 .my_port = data->local_port,
638 .other_port = data->remote_port,
639 .dscp = data->dscp,
deac3a0a
MW
640 .proposals = linked_list_create(),
641 );
7daf5226 642
9486a2e5
TB
643 parse_addresses(data->local, this->my_hosts, this->my_ranges);
644 parse_addresses(data->remote, this->other_hosts, this->other_ranges);
3070697f 645
e0fe7651
MW
646 return &this->public;
647}