From: Tobias Brunner Date: Tue, 11 Jan 2022 09:15:53 +0000 (+0100) Subject: child-cfg: Add method to select a security label X-Git-Tag: 5.9.6rc1~3^2~26 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=63d4bd071ff2c9b08f41d2db71d95148f2b8876b;p=thirdparty%2Fstrongswan.git child-cfg: Add method to select a security label --- diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 92a1ed5027..862ec69ea2 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -544,6 +544,85 @@ METHOD(child_cfg_t, get_label_mode, sec_label_mode_t, return this->label_mode; } +METHOD(child_cfg_t, select_label, bool, + private_child_cfg_t *this, linked_list_t *labels, bool log, + sec_label_t **label, bool *exact_out) +{ + enumerator_t *enumerator; + sec_label_t *current, *match = NULL; + bool exact = FALSE; + + if (labels && labels->get_count(labels)) + { + if (!this->label) + { + DBG2(DBG_CFG, "peer proposed a security label, but none expected"); + return FALSE; + } + if (log) + { + DBG2(DBG_CFG, "selecting security label matching '%s':", + this->label->get_string(this->label)); + } + enumerator = labels->create_enumerator(labels); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (this->label->equals(this->label, current)) + { + if (log) + { + DBG2(DBG_CFG, " %s => matches exactly", + current->get_string(current)); + } + match = current; + exact = TRUE; + break; + } + else if (this->label_mode == SEC_LABEL_MODE_SELINUX && + this->label->matches(this->label, current)) + { + if (log) + { + DBG2(DBG_CFG, " %s => matches%s", + current->get_string(current), match ? ", ignored" : ""); + } + /* return the first match if we don't find an exact one */ + if (!match) + { + match = current; + } + } + else if (log) + { + DBG2(DBG_CFG, " %s => no match", current->get_string(current)); + } + } + enumerator->destroy(enumerator); + if (!match) + { + DBG2(DBG_CFG, "none of the proposed security labels match the " + "configured label '%s'", this->label->get_string(this->label)); + return FALSE; + } + } + else if (this->label) + { + DBG2(DBG_CFG, "peer didn't propose any security labels, we expect one " + "matching '%s'", this->label->get_string(this->label)); + return FALSE; + } + + if (label) + { + *label = match; + } + if (exact_out) + { + *exact_out = exact; + } + return TRUE; +} + METHOD(child_cfg_t, get_tfc, uint32_t, private_child_cfg_t *this) { @@ -686,6 +765,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data) .get_set_mark = _get_set_mark, .get_label = _get_label, .get_label_mode = _get_label_mode, + .select_label = _select_label, .get_tfc = _get_tfc, .get_manual_prio = _get_manual_prio, .get_interface = _get_interface, diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 15c52b7bc9..710596d89b 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -261,6 +261,27 @@ struct child_cfg_t { */ sec_label_mode_t (*get_label_mode)(child_cfg_t *this); + /** + * Select a security label from the given list that matches the configured + * label. + * + * This fails under the following conditions: + * - a label is configured but no labels are provided + * - no label is configured but at least one label is provided + * - the configured and provided labels don't match + * + * If no label is configured and none are provided, that's considered a + * success and label will be set to NULL. + * + * @param labels list of labels to match + * @param log FALSE to avoid logging details about the selection + * @param label[out] selected label or NULL if no label necessary + * @param exact[out] TRUE if there was an exact match + * @return FALSE on failure + */ + bool (*select_label)(child_cfg_t *this, linked_list_t *labels, bool log, + sec_label_t **label, bool *exact); + /** * Get the TFC padding value to use for CHILD_SA. *