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