From: Tobias Brunner Date: Mon, 10 Jan 2022 17:31:34 +0000 (+0100) Subject: peer-cfg: Consider security labels when selecting child configs X-Git-Tag: 5.9.6rc1~3^2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03729958db9ed7e9a68daa1be308740ba7a4c323;p=thirdparty%2Fstrongswan.git peer-cfg: Consider security labels when selecting child configs --- diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index 2350ad5016..1f2c5f1094 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -386,13 +386,28 @@ METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*, /** * Check how good a list of TS matches a given child config */ -static int get_ts_match(child_cfg_t *cfg, bool local, - linked_list_t *sup_list, linked_list_t *hosts) +static u_int get_ts_match(child_cfg_t *cfg, bool local, + linked_list_t *sup_list, linked_list_t *hosts, + linked_list_t *sup_labels) { linked_list_t *cfg_list; enumerator_t *sup_enum, *cfg_enum; traffic_selector_t *sup_ts, *cfg_ts, *subset; - int match = 0, round; + sec_label_t *label; + u_int match = 0, round; + bool exact = FALSE; + + if (cfg->select_label(cfg, sup_labels, TRUE, &label, &exact)) + { + if (label) + { + match += exact ? 500 : 100; + } + } + else + { /* label config doesn't match, no need to check TS */ + return match; + } /* fetch configured TS list, narrowing dynamic TS */ cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts, TRUE); @@ -432,24 +447,29 @@ static int get_ts_match(child_cfg_t *cfg, bool local, METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*, private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts, - linked_list_t *my_hosts, linked_list_t *other_hosts) + linked_list_t *my_hosts, linked_list_t *other_hosts, + linked_list_t *my_labels, linked_list_t *other_labels) { child_cfg_t *current, *found = NULL; enumerator_t *enumerator; - int best = 0; + u_int best = 0; DBG2(DBG_CFG, "looking for a child config for %#R === %#R", my_ts, other_ts); enumerator = create_child_cfg_enumerator(this); while (enumerator->enumerate(enumerator, ¤t)) { - int my_prio, other_prio; - - my_prio = get_ts_match(current, TRUE, my_ts, my_hosts); - other_prio = get_ts_match(current, FALSE, other_ts, other_hosts); + u_int my_prio, other_prio; - if (my_prio && other_prio) + my_prio = get_ts_match(current, TRUE, my_ts, my_hosts, my_labels); + if (!my_prio) + { + continue; + } + other_prio = get_ts_match(current, FALSE, other_ts, other_hosts, + other_labels); + if (other_prio) { - DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d", + DBG2(DBG_CFG, " candidate \"%s\" with prio %u+%u", current->get_name(current), my_prio, other_prio); if (my_prio + other_prio > best) { diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index b80e809c2c..da3d6a0cc5 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -174,17 +174,20 @@ struct peer_cfg_t { enumerator_t* (*create_child_cfg_enumerator) (peer_cfg_t *this); /** - * Select a CHILD config from traffic selectors. + * Select a CHILD config from received traffic selectors. * * @param my_ts TS for local side * @param other_ts TS for remote side * @param my_hosts hosts to narrow down dynamic TS for local side * @param other_hosts hosts to narrow down dynamic TS for remote side - * @return selected CHILD config, or NULL if no match found + * @param my_labels optional local security labels + * @param other_labels optional remove security labels + * @return selected CHILD config, or NULL if no match found */ - child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, + child_cfg_t* (*select_child_cfg)(peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts, - linked_list_t *my_hosts, linked_list_t *other_hosts); + linked_list_t *my_hosts, linked_list_t *other_hosts, + linked_list_t *my_labels, linked_list_t *other_labels); /** * Add an authentication config to the peer configuration. diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 6138efc972..5e4bf8620b 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -1096,7 +1096,7 @@ METHOD(task_t, process_r, status_t, hostsi = get_dynamic_hosts(this->ike_sa, FALSE); hostsr = get_dynamic_hosts(this->ike_sa, TRUE); this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi, - hostsr, hostsi); + hostsr, hostsi, NULL, NULL); hostsi->destroy(hostsi); hostsr->destroy(hostsr); if (this->config) diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 83f3c7328a..092ac72a6a 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -1414,7 +1414,7 @@ static child_cfg_t* select_child_cfg(private_child_create_t *this) listi = get_dynamic_hosts(this->ike_sa, FALSE); child_cfg = peer_cfg->select_child_cfg(peer_cfg, tsr ?: this->tsr, tsi ?: this->tsi, - listr, listi); + listr, listi, NULL, NULL); if ((tsi || tsr) && child_cfg && child_cfg->get_mode(child_cfg) != MODE_TRANSPORT) { @@ -1426,7 +1426,8 @@ static child_cfg_t* select_child_cfg(private_child_create_t *this) { /* no match for the substituted NAT selectors, try it without */ child_cfg = peer_cfg->select_child_cfg(peer_cfg, - this->tsr, this->tsi, listr, listi); + this->tsr, this->tsi, + listr, listi, NULL, NULL); } listr->destroy(listr); listi->destroy(listi);