diff -Naur libreswan-4.3-orig/programs/pluto/connections.c libreswan-4.3/programs/pluto/connections.c --- libreswan-4.3-orig/programs/pluto/connections.c 2021-02-21 12:03:03.000000000 -0500 +++ libreswan-4.3/programs/pluto/connections.c 2021-02-24 16:28:05.608119041 -0500 @@ -2475,9 +2475,8 @@ endpoint_in_selector(local_client, &sr->this.client) && endpoint_in_selector(remote_client, &sr->that.client) #ifdef HAVE_LABELED_IPSEC - && ((sec_label.ptr == NULL && - sr->this.sec_label.ptr == NULL) || - /* don't call with NULL, it confuses it */ + && ((sec_label.ptr == NULL && sr->this.sec_label.ptr == NULL) || + hunk_eq(sec_label, sr->this.sec_label) || within_range((const char *)sec_label.ptr, (const char *)sr->this.sec_label.ptr, logger)) #endif diff -Naur libreswan-4.3-orig/programs/pluto/ikev1_spdb_struct.c libreswan-4.3/programs/pluto/ikev1_spdb_struct.c --- libreswan-4.3-orig/programs/pluto/ikev1_spdb_struct.c 2021-02-21 12:03:03.000000000 -0500 +++ libreswan-4.3/programs/pluto/ikev1_spdb_struct.c 2021-02-24 16:28:59.819791102 -0500 @@ -113,7 +113,9 @@ return false; } - if (!within_range(sec_label.ptr, /* we ensured NUL termination above */ + + if (!hunk_eq(sec_label, c->spd.this.sec_label) && + !within_range(sec_label.ptr, /* we ensured NUL termination above */ (const char *)c->spd.this.sec_label.ptr, /* we ensured NUL termination earlier? */ st->st_logger)) { LLOG_JAMBUF(RC_LOG_SERIOUS, st->st_logger, buf) { diff -Naur libreswan-4.3-orig/programs/pluto/ikev2_ts.c libreswan-4.3/programs/pluto/ikev2_ts.c --- libreswan-4.3-orig/programs/pluto/ikev2_ts.c 2021-02-21 12:03:03.000000000 -0500 +++ libreswan-4.3/programs/pluto/ikev2_ts.c 2021-02-24 16:30:19.639780631 -0500 @@ -862,7 +862,8 @@ } #ifdef HAVE_LABELED_IPSEC -static bool score_ends_seclabel(const struct ends *ends, +static bool score_ends_seclabel(const chunk_t **selected_sec_label, + const struct ends *ends, const struct connection *d, const struct traffic_selectors *tsi, const struct traffic_selectors *tsr, @@ -875,6 +876,10 @@ bool match_i = false; bool match_r = false; + if (selected_sec_label != NULL) { + *selected_sec_label = NULL; + } + for (unsigned tsi_n = 0; tsi_n < tsi->nr; tsi_n++) { const struct traffic_selector *cur = &tsi->ts[tsi_n]; if (cur->ts_type == IKEv2_TS_SECLABEL) { @@ -883,7 +888,8 @@ // complain loudly continue; } else { - if (within_range((const char *)cur->sec_label.ptr, (const char *)d->spd.this.sec_label.ptr, logger)) { + if (hunk_eq(cur->sec_label, d->spd.this.sec_label) || + within_range((const char *)cur->sec_label.ptr, (const char *)d->spd.this.sec_label.ptr, logger)) { match_i = true; dbg("ikev2ts #1: received label within range of our security label"); } else { @@ -902,9 +908,13 @@ dbg("IKEv2_TS_SECLABEL but zero length cur->sec_label"); continue; } else { - if (within_range((const char *)ends->r->sec_label.ptr, (const char *)d->spd.this.sec_label.ptr, logger)) { + if (hunk_eq(ends->r->sec_label, d->spd.this.sec_label) || + within_range((const char *)ends->r->sec_label.ptr, (const char *)d->spd.this.sec_label.ptr, logger)) { dbg("ikev2ts #2: received label within range of our security label"); match_r = true; + if (selected_sec_label != NULL) { + *selected_sec_label = &cur->sec_label; + } } else { dbg("ikev2ts #2: received label not within range of our security label"); DBG_dump_hunk("ends->r->sec_label", ends->r->sec_label); @@ -926,7 +936,8 @@ return require_label == recv_label_i && match_i && match_r; } #else -static bool score_ends_seclabel(const struct ends *ends UNUSED, +static bool score_ends_seclabel(const chunk_t **selected_sec_label, + const struct ends *ends UNUSED, const struct connection *d UNUSED, const struct traffic_selectors *tsi UNUSED, const struct traffic_selectors *tsr UNUSED, @@ -1030,6 +1041,7 @@ struct best_score best_score = NO_SCORE; const struct spd_route *best_spd_route = NULL; struct connection *best_connection = c; + const chunk_t *best_sec_label = NULL; /* find best spd in c */ @@ -1042,7 +1054,8 @@ .r = &sra->this, }; - if (!score_ends_seclabel(&ends, c, &tsi, &tsr, child->sa.st_logger)) { + const chunk_t* selected_sec_label = NULL; + if (!score_ends_seclabel(&selected_sec_label, &ends, c, &tsi, &tsr, child->sa.st_logger)) { continue; } @@ -1060,6 +1073,7 @@ score.tsi - tsi.ts, score.tsr - tsr.ts); best_score = score; best_spd_route = sra; + best_sec_label = selected_sec_label; passert(best_connection == c); } } @@ -1143,7 +1157,8 @@ ? END_NARROWER_THAN_TS : END_EQUALS_TS; - if (!score_ends_seclabel(&ends, d, &tsi, &tsr, + const chunk_t* selected_sec_label = NULL; + if (!score_ends_seclabel(&selected_sec_label, &ends, d, &tsi, &tsr, child->sa.st_logger)) continue; @@ -1159,6 +1174,7 @@ best_connection = d; best_score = score; best_spd_route = sr; + best_sec_label = selected_sec_label; } } } @@ -1389,6 +1405,13 @@ */ update_state_connection(&child->sa, best_connection); + if (best_sec_label != NULL) { + if (child->sa.st_seen_sec_label.len != 0) { + free_chunk_content(&child->sa.st_seen_sec_label); + } + child->sa.st_seen_sec_label = clone_hunk(*best_sec_label, "st_seen_sec_label"); + } + child->sa.st_ts_this = ikev2_end_to_ts(&best_spd_route->this, child->sa.st_acquired_sec_label); child->sa.st_ts_that = ikev2_end_to_ts(&best_spd_route->that, child->sa.st_seen_sec_label); @@ -1424,7 +1447,8 @@ ? END_WIDER_THAN_TS : END_EQUALS_TS; - if (!score_ends_seclabel(&e, c, &tsi, &tsr, child->sa.st_logger)) + const chunk_t *selected_sec_label = NULL; + if (!score_ends_seclabel(&selected_sec_label, &e, c, &tsi, &tsr, child->sa.st_logger)) return false; struct best_score best = score_ends_iprange(initiator_widening, c, &e, &tsi, &tsr); @@ -1435,6 +1459,13 @@ return false; } + if (selected_sec_label != NULL) { + if (child->sa.st_seen_sec_label.len != 0) { + free_chunk_content(&child->sa.st_seen_sec_label); + } + child->sa.st_seen_sec_label = clone_hunk(*selected_sec_label, "st_seen_sec_label"); + } + /* XXX: check conversions */ dbg("initiator saving acceptable TSi response in this"); ts_to_end(best.tsi, &c->spd.this, &child->sa.st_ts_this); @@ -1489,7 +1520,7 @@ enum fit fitness = END_NARROWER_THAN_TS; - if (!score_ends_seclabel(&ends, c, &their_tsis, &their_tsrs, + if (!score_ends_seclabel(NULL, &ends, c, &their_tsis, &their_tsrs, child->sa.st_logger)) { log_state(RC_LOG_SERIOUS, &child->sa, "rekey: received Traffic Selectors mismatch configured selectors for Security Label"); diff -Naur libreswan-4.3-orig/programs/pluto/ikev2_parent.c libreswan-4.3/programs/pluto/ikev2_parent.c --- libreswan-4.3-orig/programs/pluto/ikev2_parent.c 2021-02-21 12:03:03.000000000 -0500 +++ libreswan-4.3/programs/pluto/ikev2_parent.c 2021-03-01 10:31:49.667207958 -0500 @@ -5943,8 +5943,6 @@ * from a policy we gave the kernel, so it _should_ be within our range? */ child->sa.st_acquired_sec_label = clone_hunk(p->sec_label, "st_acquired_sec_label"); - c->spd.this.sec_label = clone_hunk(p->sec_label, "updated conn label"); - c->spd.that.sec_label = clone_hunk(p->sec_label, "updated conn label"); } } else {