Bug Summary

File:programs/pluto/ikev2_ts.c
Warning:line 1405, column 10
Null pointer passed to 2nd parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ikev2_ts.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D HAVE_NM -D USE_PAM_AUTH -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/ikev2_ts.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/ikev2_ts.c
1/* IKEv2 Traffic Selectors, for libreswan
2 *
3 * Copyright (C) 2007-2008 Michael Richardson <mcr@xelerance.com>
4 * Copyright (C) 2009-2010 Paul Wouters <paul@xelerance.com>
5 * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi>
6 * Copyright (C) 2011-2012 Avesh Agarwal <avagarwa@redhat.com>
7 * Copyright (C) 2012-2018 Paul Wouters <pwouters@redhat.com>
8 * Copyright (C) 2012,2016-2017 Antony Antony <appu@phenome.org>
9 * Copyright (C) 2013 D. Hugh Redelmeier <hugh@mimosa.com>
10 * Copyright (C) 2014-2015, 2018 Andrew cagney <cagney@gnu.org>
11 * Copyright (C) 2017 Antony Antony <antony@phenome.org>
12 * Copyright (C) 2019 Andrew Cagney <cagney@gnu.org>
13 * Copyright (C) 2021 Paul Wouters <paul.wouters@aiven.io>
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
24 *
25 */
26
27#include "defs.h"
28
29#include "log.h"
30#include "ikev2_ts.h"
31#include "connections.h" /* for struct end */
32#include "demux.h"
33#include "virtual_ip.h"
34#include "host_pair.h"
35#include "ip_info.h"
36#include "ip_selector.h"
37#include "labeled_ipsec.h"
38#include "ip_range.h"
39#include "iface.h"
40#include "pending.h" /* for connection_is_pending() */
41#include "state_db.h" /* for FOR_EACH_STATE_NEW2OLD() */
42
43/*
44 * While the RFC seems to suggest that the traffic selectors come in
45 * pairs, strongswan, at least, doesn't.
46 */
47
48struct traffic_selectors {
49 const char *name;
50 bool_Bool contains_sec_label;
51 unsigned nr;
52 /* ??? is 16 an undocumented limit - IKEv2 has no limit */
53 struct traffic_selector ts[16];
54};
55
56struct traffic_selector_payloads {
57 struct traffic_selectors i;
58 struct traffic_selectors r;
59};
60
61static const struct traffic_selector_payloads empty_traffic_selectors = {
62 .i = {
63 .name = "TSi",
64 },
65 .r = {
66 .name = "TSr",
67 },
68};
69
70struct ends {
71 const struct end *i;
72 const struct end *r;
73};
74
75enum fit {
76 END_EQUALS_TS = 1,
77 END_NARROWER_THAN_TS,
78 END_WIDER_THAN_TS,
79};
80
81
82static const char *fit_string(enum fit fit)
83{
84 switch (fit) {
85 case END_EQUALS_TS: return "==";
86 case END_NARROWER_THAN_TS: return "<=";
87 case END_WIDER_THAN_TS: return ">=";
88 default: bad_case(fit)libreswan_bad_case("fit", (fit), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 88, }; &here; }))
;
89 }
90}
91
92void dbg_v2_ts(const struct traffic_selector *ts, const char *prefix, ...)
93{
94 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
95 va_list ap;
96 va_start(ap, prefix)__builtin_va_start(ap, prefix);
97 DBG_va_list(prefix, ap);
98 va_end(ap)__builtin_va_end(ap);
99 DBG_log(" ts_type: %s", enum_name(&ikev2_ts_type_names, ts->ts_type));
100 DBG_log(" ipprotoid: %d", ts->ipprotoid);
101 DBG_log(" port range: %d-%d", ts->startport, ts->endport);
102 range_buf b;
103 DBG_log(" ip range: %s", str_range(&ts->net, &b));
104 DBG_log(" sec_label: "PRI_SHUNK"%.*s", pri_shunk(ts->sec_label)((int) (ts->sec_label).len), (const char *) ((ts->sec_label
).ptr)
);
105 }
106}
107
108static void traffic_selector_to_end(const struct traffic_selector *ts, struct end *end,
109 const char *story)
110{
111 dbg_v2_ts(ts, "%s() %s", __func__, story);
112 ip_subnet subnet;
113 happy(range_to_subnet(ts->net, &subnet)){ err_t ugh = range_to_subnet(ts->net, &subnet); if (ugh
!= ((void*)0)) { llog_passert(&failsafe_logger, ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 113, }; &here; }), "%s", ugh); } }
;
114 const ip_protocol *protocol = protocol_by_ipproto(ts->ipprotoid);
115 /* XXX: check port range valid */
116 ip_port port = ip_hport(ts->startport);
117 end->client = selector_from_subnet_protocol_port(subnet, protocol, port);
118 /* redundant */
119 end->port = ts->startport;
120 end->protocol = ts->ipprotoid;
121 end->has_client = !selector_eq_address(end->client, end->host_addr);
122}
123
124/* rewrite me with address_as_{chunk,shunk}()? */
125/* For now, note the struct traffic_selector can contain
126 * two selectors - an IPvX range and a sec_label
127 */
128struct traffic_selector traffic_selector_from_end(const struct end *e, const char *what)
129{
130 struct traffic_selector ts = {
131 /*
132 * Setting ts_type IKEv2_TS_FC_ADDR_RANGE (RFC-4595)
133 * not yet supported.
134 */
135 .ts_type = selector_type(&e->client)->ikev2_ts_addr_range_type,
136 /* subnet => range */
137 .net = selector_range(e->client),
138 .ipprotoid = e->protocol,
139 /*
140 * Use the 'instance/narrowed' label from the ACQUIRE
141 * and stored in the connection instance's sends, if
142 * present.
143 */
144 .sec_label = HUNK_AS_SHUNK(e->sec_label)({ typeof(e->sec_label) h_ = (e->sec_label); shunk2(h_.
ptr, h_.len); })
,
145 };
146
147 /*
148 * if port is %any or 0 we mean all ports (or all
149 * iccmp/icmpv6).
150 *
151 * See RFC-5996 Section 3.13.1 handling for ICMP(1) and
152 * ICMPv6(58) we only support providing Type, not Code, eg
153 * protoport=1/1
154 */
155 if (e->port == 0 || e->has_port_wildcard) {
156 ts.startport = 0;
157 ts.endport = 65535;
158 } else {
159 ts.startport = e->port;
160 ts.endport = e->port;
161 }
162
163 dbg_v2_ts(&ts, "%s TS", what);
164 return ts;
165}
166
167/*
168 * A struct end is converted to a struct traffic_selector.
169 *
170 * This (currently) can contain both an IP range AND a SEC_LABEL,
171 * which will get output here as two Traffic Selectors. The label is
172 * optional, the IP range is mandatory.
173 */
174static stf_status emit_v2TS(struct pbs_outpacket_byte_stream *outpbs,
175 const struct_desc *ts_desc,
176 const struct traffic_selector *ts)
177{
178 struct pbs_outpacket_byte_stream ts_pbs;
179 bool_Bool with_label = (ts->sec_label.len > 0);
180
181 if (ts->ts_type != IKEv2_TS_IPV4_ADDR_RANGE &&
182 ts->ts_type != IKEv2_TS_IPV6_ADDR_RANGE) {
183 return STF_INTERNAL_ERROR;
184 }
185
186 {
187 struct ikev2_ts its = {
188 .isat_critical = ISAKMP_PAYLOAD_NONCRITICAL0x00,
189 /*
190 * If there is a security label in the Traffic
191 * Selector, then we must send a TS_SECLABEL
192 * substructure as part of the Traffic
193 * Selector (TS) Payload.
194 *
195 * That means the TS Payload contains two TS
196 * substructures:
197 * - One for the address/port range
198 * - One for the TS_SECLABEL
199 */
200 .isat_num = with_label ? 2 : 1,
201 };
202
203 if (!out_struct(&its, ts_desc, outpbs, &ts_pbs))
204 return STF_INTERNAL_ERROR;
205 }
206
207 {
208 pb_stream ts_range_pbs;
209 struct ikev2_ts_header ts_header = {
210 .isath_ipprotoid = ts->ipprotoid
211 };
212
213 switch (ts->ts_type) {
214 case IKEv2_TS_IPV4_ADDR_RANGE:
215 ts_header.isath_type = IKEv2_TS_IPV4_ADDR_RANGE;
216 break;
217 case IKEv2_TS_IPV6_ADDR_RANGE:
218 ts_header.isath_type = IKEv2_TS_IPV6_ADDR_RANGE;
219 break;
220 }
221
222 if (!out_struct(&ts_header, &ikev2_ts_header_desc, &ts_pbs, &ts_range_pbs))
223 return STF_INTERNAL_ERROR;
224
225
226 struct ikev2_ts_portrange ts_ports = {
227 .isatpr_startport = ts->startport,
228 .isatpr_endport = ts->endport
229 };
230
231 if (!out_struct(&ts_ports, &ikev2_ts_portrange_desc, &ts_range_pbs, NULL((void*)0)))
232 return STF_INTERNAL_ERROR;
233
234 diag_t d;
235 d = pbs_out_address(&ts_range_pbs, range_start(ts->net), "IP start");
236 if (d != NULL((void*)0)) {
237 llog_diag(RC_LOG_SERIOUS, outpbs->outs_logger, &d, "%s", "");
238 return STF_INTERNAL_ERROR;
239 }
240 d = pbs_out_address(&ts_range_pbs, range_end(ts->net), "IP end");
241 if (d != NULL((void*)0)) {
242 llog_diag(RC_LOG_SERIOUS, outpbs->outs_logger, &d, "%s", "");
243 return STF_INTERNAL_ERROR;
244 }
245 close_output_pbs(&ts_range_pbs);
246 }
247
248 /*
249 * Emit the security label, if known.
250 */
251 if (with_label) {
252
253 struct ikev2_ts_header ts_header = {
254 .isath_type = IKEv2_TS_SECLABEL,
255 .isath_ipprotoid = 0 /* really RESERVED, not iprotoid */
256 };
257 /* Output the header of the TS_SECLABEL substructure payload. */
258 struct pbs_outpacket_byte_stream ts_label_pbs;
259 if (!out_struct(&ts_header, &ikev2_ts_header_desc, &ts_pbs, &ts_label_pbs)) {
260 return STF_INTERNAL_ERROR;
261 }
262
263 /*
264 * Output the security label value of the TS_SECLABEL
265 * substructure payload.
266 *
267 * If we got ACQUIRE, or received a subset TS_LABEL,
268 * use that one - it is subset of connection policy
269 * one
270 */
271
272 dbg("emitting sec_label="PRI_SHUNK, pri_shunk(ts->sec_label)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("emitting sec_label=""%.*s", ((int) (ts->sec_label
).len), (const char *) ((ts->sec_label).ptr)); } }
;
273
274 diag_t d = pbs_out_hunk(&ts_label_pbs, ts->sec_label, "output Security label")({ typeof(ts->sec_label) hunk_ = ts->sec_label; struct packet_byte_stream
*outs_ = &ts_label_pbs; pbs_out_raw(outs_, hunk_.ptr, hunk_
.len, ("output Security label")); })
;
275 if (d != NULL((void*)0)) {
276 llog_diag(RC_LOG_SERIOUS, outpbs->outs_logger, &d, "%s", "");
277 return STF_INTERNAL_ERROR;
278 }
279
280 close_output_pbs(&ts_label_pbs);
281 }
282
283 close_output_pbs(&ts_pbs);
284 return STF_OK;
285}
286
287static struct traffic_selector impair_ts_to_subnet(const struct traffic_selector ts)
288{
289 struct traffic_selector ts_ret = ts;
290
291 ts_ret.net.end = ts_ret.net.start;
292 ts_ret.net.is_subnet = true1;
293
294 return ts_ret;
295}
296
297
298static struct traffic_selector impair_ts_to_supernet(const struct traffic_selector ts)
299{
300 struct traffic_selector ts_ret = ts;
301
302 if (ts_ret.ts_type == IKEv2_TS_IPV4_ADDR_RANGE)
303 ts_ret.net = range_from_subnet(ipv4_info.subnet.all);
304 else if (ts_ret.ts_type == IKEv2_TS_IPV6_ADDR_RANGE)
305 ts_ret.net = range_from_subnet(ipv6_info.subnet.all);
306
307 ts_ret.net.is_subnet = true1;
308
309 ts_ret.sec_label = ts.sec_label;
310
311 return ts_ret;
312}
313
314stf_status emit_v2TS_payloads(struct pbs_outpacket_byte_stream *outpbs, const struct child_sa *child)
315{
316 stf_status ret;
317 struct traffic_selector ts_i, ts_r;
318
319 switch (child->sa.st_sa_role) {
320 case SA_INITIATOR:
321 ts_i = traffic_selector_from_end(&child->sa.st_connection->spd.this, "this TSi");
322 ts_r = traffic_selector_from_end(&child->sa.st_connection->spd.that, "that TSr");
323 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I0 &&
324 impair.rekey_initiate_supernet) {
325 ts_i = ts_r = impair_ts_to_supernet(ts_i);
326 range_buf tsi_buf;
327 range_buf tsr_buf;
328 dbg("rekey-initiate-supernet TSi and TSr set to %s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
329 str_range(&ts_i.net, &tsi_buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
330 str_range(&ts_r.net, &tsr_buf)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
;
331
332 } else if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I0 &&
333 impair.rekey_initiate_subnet) {
334 ts_i = impair_ts_to_subnet(ts_i);
335 ts_r = impair_ts_to_subnet(ts_r);
336 range_buf tsi_buf;
337 range_buf tsr_buf;
338 dbg("rekey-initiate-subnet TSi and TSr set to %s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
339 str_range(&ts_i.net, &tsi_buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
340 str_range(&ts_r.net, &tsr_buf)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-initiate-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
;
341
342 }
343
344 break;
345 case SA_RESPONDER:
346 ts_i = traffic_selector_from_end(&child->sa.st_connection->spd.that, "that TSi");
347 ts_r = traffic_selector_from_end(&child->sa.st_connection->spd.this, "this TSr");
348 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 &&
349 impair.rekey_respond_subnet) {
350 ts_i = impair_ts_to_subnet(ts_i);
351 ts_r = impair_ts_to_subnet(ts_r);
352 range_buf tsi_buf;
353 range_buf tsr_buf;
354 dbg("rekey-respond-subnet TSi and TSr set to %s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
355 str_range(&ts_i.net, &tsi_buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
356 str_range(&ts_r.net, &tsr_buf)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-subnet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
;
357 }
358 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 &&
359 impair.rekey_respond_supernet) {
360 ts_i = ts_r = impair_ts_to_supernet(ts_i);
361 range_buf tsi_buf;
362 range_buf tsr_buf;
363 dbg("rekey-respond-supernet TSi and TSr set to %s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
364 str_range(&ts_i.net, &tsi_buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
365 str_range(&ts_r.net, &tsr_buf)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("rekey-respond-supernet TSi and TSr set to %s %s"
, str_range(&ts_i.net, &tsi_buf), str_range(&ts_r
.net, &tsr_buf)); } }
;
366 }
367 break;
368 default:
369 bad_case(child->sa.st_sa_role)libreswan_bad_case("child->sa.st_sa_role", (child->sa.st_sa_role
), ({ static const struct where here = { .func = __func__, .file
= "programs/pluto/ikev2_ts.c", .line = 369, }; &here; })
)
;
370 }
371
372 ret = emit_v2TS(outpbs, &ikev2_ts_i_desc, &ts_i);
373 if (ret != STF_OK)
374 return ret;
375
376 ret = emit_v2TS(outpbs, &ikev2_ts_r_desc, &ts_r);
377 if (ret != STF_OK)
378 return ret;
379
380 return STF_OK;
381}
382
383/* return success */
384static bool_Bool v2_parse_tss(struct payload_digest *const ts_pd,
385 struct traffic_selectors *tss,
386 struct logger *logger)
387{
388 dbg("%s: parsing %u traffic selectors",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsing %u traffic selectors", tss->name
, ts_pd->payload.v2ts.isat_num); } }
389 tss->name, ts_pd->payload.v2ts.isat_num){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsing %u traffic selectors", tss->name
, ts_pd->payload.v2ts.isat_num); } }
;
390
391 if (ts_pd->payload.v2ts.isat_num == 0) {
392 llog(RC_LOG, logger,
393 "%s payload contains no entries when at least one is expected",
394 tss->name);
395 return false0;
396 }
397
398 if (ts_pd->payload.v2ts.isat_num >= elemsof(tss->ts)(sizeof(tss->ts) / sizeof(*(tss->ts)))) {
399 llog(RC_LOG, logger,
400 "%s contains %d entries which exceeds hardwired max of %zu",
401 tss->name, ts_pd->payload.v2ts.isat_num, elemsof(tss->ts)(sizeof(tss->ts) / sizeof(*(tss->ts))));
402 return false0; /* won't fit in array */
403 }
404
405 for (tss->nr = 0; tss->nr < ts_pd->payload.v2ts.isat_num; ) {
406 diag_t d;
407 struct traffic_selector *ts = &tss->ts[tss->nr];
408
409 *ts = (struct traffic_selector){0};
410
411 struct ikev2_ts_header ts_h;
412 struct pbs_inpacket_byte_stream ts_body_pbs;
413
414 d = pbs_in_struct(&ts_pd->pbs, &ikev2_ts_header_desc,
415 &ts_h, sizeof(ts_h), &ts_body_pbs);
416
417 switch (ts_h.isath_type) {
418 case IKEv2_TS_IPV4_ADDR_RANGE:
419 case IKEv2_TS_IPV6_ADDR_RANGE:
420 {
421 ts->ipprotoid = ts_h.isath_ipprotoid;
422
423 /* read and fill in port range */
424 struct ikev2_ts_portrange pr;
425
426 d = pbs_in_struct(&ts_body_pbs, &ikev2_ts_portrange_desc,
427 &pr, sizeof(pr), NULL((void*)0));
428 if (d != NULL((void*)0)) {
429 llog_diag(RC_LOG, logger, &d, "%s", "");
430 return false0;
431 }
432
433 ts->startport = pr.isatpr_startport;
434 ts->endport = pr.isatpr_endport;
435
436 if (ts->startport > ts->endport) {
437 llog(RC_LOG, logger,
438 "%s traffic selector %d has an invalid port range - ignored",
439 tss->name, tss->nr);
440 continue;
441 }
442
443 /* read and fill in IP address range */
444 const struct ip_info *ipv;
445 switch (ts_h.isath_type) {
446 case IKEv2_TS_IPV4_ADDR_RANGE:
447 ipv = &ipv4_info;
448 break;
449 case IKEv2_TS_IPV6_ADDR_RANGE:
450 ipv = &ipv6_info;
451 break;
452 default:
453 bad_case(ts_h.isath_type)libreswan_bad_case("ts_h.isath_type", (ts_h.isath_type), ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 453, }; &here; }))
; /* make compiler happy */
454 }
455
456 ip_address start;
457 d = pbs_in_address(&ts_body_pbs, &start, ipv, "TS IP start");
458 if (d != NULL((void*)0)) {
459 llog_diag(RC_LOG, logger, &d, "%s", "");
460 return false0;
461 }
462
463 ip_address end;
464 d = pbs_in_address(&ts_body_pbs, &end, ipv, "TS IP end");
465 if (d != NULL((void*)0)) {
466 llog_diag(RC_LOG, logger, &d, "%s", "");
467 return false0;
468 }
469
470 /* XXX: does this matter? */
471 if (pbs_left(&ts_body_pbs)((size_t)((&ts_body_pbs)->roof - (&ts_body_pbs)->
cur))
!= 0)
472 return false0;
473
474 err_t err = addresses_to_nonzero_range(start, end, &ts->net);
475
476 /* pluto doesn't yet do full ranges; check for subnet */
477 ip_subnet ignore;
478 err = err == NULL((void*)0) ? range_to_subnet(ts->net, &ignore) : err;
479
480 if (err != NULL((void*)0)) {
481 address_buf sb, eb;
482 llog(RC_LOG, logger, "Traffic Selector range %s-%s invalid: %s",
483 str_address_sensitive(&start, &sb),
484 str_address_sensitive(&end, &eb),
485 err);
486 return false0;
487 }
488
489 ts->ts_type = ts_h.isath_type;
490 break;
491 }
492
493 case IKEv2_TS_SECLABEL:
494 {
495 if (ts_h.isath_ipprotoid != 0) {
496 llog(RC_LOG, logger, "Traffic Selector of type Security Label should not have non-zero IP protocol '%u' - ignored",
497 ts_h.isath_ipprotoid);
498 }
499
500 shunk_t sec_label = pbs_in_left_as_shunk(&ts_body_pbs);
501 err_t ugh = vet_seclabel(sec_label);
502 if (ugh != NULL((void*)0)) {
503 llog(RC_LOG, logger, "Traffic Selector %s", ugh);
504 /* ??? should we just ignore? If so, use continue */
505 return false0;
506 }
507
508 ts->sec_label = sec_label;
509 ts->ts_type = ts_h.isath_type;
510 tss->contains_sec_label = true1;
511 break;
512 }
513
514 case IKEv2_TS_FC_ADDR_RANGE:
515 llog(RC_LOG, logger, "Encountered Traffic Selector Type FC_ADDR_RANGE not supported");
516 return false0;
517
518 default:
519 llog(RC_LOG, logger, "Encountered Traffic Selector of unknown Type");
520 return false0;
521 }
522 tss->nr++;
523 }
524
525 dbg("%s: parsed %d traffic selectors", tss->name, tss->nr){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsed %d traffic selectors", tss->name
, tss->nr); } }
;
526 return true1;
527}
528
529static bool_Bool v2_parse_tsp(const struct msg_digest *md,
530 struct traffic_selector_payloads *tsp,
531 struct logger *logger)
532{
533 if (!v2_parse_tss(md->chain[ISAKMP_NEXT_v2TSi], &tsp->i, logger)) {
6
Assuming the condition is false
7
Taking false branch
534 return false0;
535 }
536
537 if (!v2_parse_tss(md->chain[ISAKMP_NEXT_v2TSr], &tsp->r, logger)) {
8
Assuming the condition is false
9
Taking false branch
538 return false0;
539 }
540
541 return true1;
10
Returning the value 1, which participates in a condition later
542}
543
544#define MATCH_PREFIX" " " "
545
546/*
547 * Check if our policy's protocol (proto) matches the Traffic Selector
548 * protocol (ts_proto).
549 */
550
551static int narrow_protocol(const struct end *end,
552 const struct traffic_selectors *tss,
553 enum fit fit, unsigned index)
554{
555 const struct traffic_selector *ts = &tss->ts[index];
556 int protocol = -1;
557
558 switch (fit) {
559 case END_EQUALS_TS:
560 if (end->protocol == ts->ipprotoid) {
561 protocol = end->protocol;
562 }
563 break;
564 case END_NARROWER_THAN_TS:
565 if (ts->ipprotoid == 0 /* wild-card */ ||
566 ts->ipprotoid == end->protocol) {
567 protocol = end->protocol;
568 }
569 break;
570 case END_WIDER_THAN_TS:
571 if (end->protocol == 0 /* wild-card */ ||
572 end->protocol == ts->ipprotoid) {
573 protocol = ts->ipprotoid;
574 }
575 break;
576 default:
577 bad_case(fit)libreswan_bad_case("fit", (fit), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 577, }; &here; }))
;
578 }
579 dbg(MATCH_PREFIX "narrow protocol end=%s%d %s %s[%u]=%s%d: %d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow protocol end=%s%d %s %s[%u]=%s%d: %d"
, end->protocol == 0 ? "*" : "", end->protocol, fit_string
(fit), tss->name, index, ts->ipprotoid == 0 ? "*" : "",
ts->ipprotoid, protocol); } }
580 end->protocol == 0 ? "*" : "", end->protocol,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow protocol end=%s%d %s %s[%u]=%s%d: %d"
, end->protocol == 0 ? "*" : "", end->protocol, fit_string
(fit), tss->name, index, ts->ipprotoid == 0 ? "*" : "",
ts->ipprotoid, protocol); } }
581 fit_string(fit),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow protocol end=%s%d %s %s[%u]=%s%d: %d"
, end->protocol == 0 ? "*" : "", end->protocol, fit_string
(fit), tss->name, index, ts->ipprotoid == 0 ? "*" : "",
ts->ipprotoid, protocol); } }
582 tss->name, index, ts->ipprotoid == 0 ? "*" : "", ts->ipprotoid,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow protocol end=%s%d %s %s[%u]=%s%d: %d"
, end->protocol == 0 ? "*" : "", end->protocol, fit_string
(fit), tss->name, index, ts->ipprotoid == 0 ? "*" : "",
ts->ipprotoid, protocol); } }
583 protocol){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow protocol end=%s%d %s %s[%u]=%s%d: %d"
, end->protocol == 0 ? "*" : "", end->protocol, fit_string
(fit), tss->name, index, ts->ipprotoid == 0 ? "*" : "",
ts->ipprotoid, protocol); } }
;
584 return protocol;
585}
586
587static int score_narrow_protocol(const struct end *end,
588 const struct traffic_selectors *tss,
589 enum fit fit, unsigned index)
590{
591 int f; /* strength of match */
592
593 int protocol = narrow_protocol(end, tss, fit, index);
594 if (protocol == 0) {
595 f = 255; /* ??? odd value */
596 } else if (protocol > 0) {
597 f = 1;
598 } else {
599 f = 0;
600 }
601 LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 <<
(DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[(
(size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_
= ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf
), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf
= ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf
, &failsafe_logger, DEBUG_STREAM), buf = ((void*)0))
{
602 const struct traffic_selector *ts = &tss->ts[index];
603 jam(buf, MATCH_PREFIX" " "match end->protocol=%s%d %s %s[%u].ipprotoid=%s%d: ",
604 end->protocol == 0 ? "*" : "", end->protocol,
605 fit_string(fit),
606 tss->name, index, ts->ipprotoid == 0 ? "*" : "", ts->ipprotoid);
607 if (f > 0) {
608 jam(buf, "YES fitness %d", f);
609 } else {
610 jam(buf, "NO");
611 }
612 }
613 return f;
614}
615
616/*
617 * Narrow the END/TS ports according to FIT.
618 *
619 * Returns 0 (all ports), a specific port number, or -1 (no luck).
620 *
621 * Since 'struct end' only describes all-ports or a single port; only
622 * narrow to that.
623 */
624
625static int narrow_port(const struct end *end,
626 const struct traffic_selectors *tss,
627 enum fit fit, unsigned index)
628{
629 passert(index < tss->nr)({ _Bool assertion__ = index < tss->nr; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 629
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "index < tss->nr");
} (void) 1; })
;
630 const struct traffic_selector *ts = &tss->ts[index];
631
632 int end_low = end->port;
633 int end_high = end->port == 0 ? 65535 : end->port;
634 int port = -1;
635
636 switch (fit) {
637 case END_EQUALS_TS:
638 if (end_low == ts->startport && ts->endport == end_high) {
639 /* end=ts=0-65535 || end=ts=N-N */
640 port = end_low;
641 }
642 break;
643 case END_NARROWER_THAN_TS:
644 if (ts->startport <= end_low && end_high <= ts->endport) {
645 /* end=ts=0-65535 || ts=N<=end<=M */
646 port = end_low;
647 }
648 break;
649 case END_WIDER_THAN_TS:
650 if (end_low < ts->startport && ts->endport < end_high &&
651 ts->startport == ts->endport) {
652 /*ts=0<N-N<65535*/
653 port = ts->startport;
654 } else if (end_low == ts->startport && ts->endport == end_high) {
655 /* end=ts=0-65535 || end=ts=N-N */
656 port = ts->startport;
657 }
658 break;
659 default:
660 bad_case(fit)libreswan_bad_case("fit", (fit), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 660, }; &here; }))
;
661 }
662 dbg(MATCH_PREFIX "narrow port end=%u..%u %s %s[%u]=%u..%u: %d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow port end=%u..%u %s %s[%u]=%u..%u: %d"
, end_low, end_high, fit_string(fit), tss->name, index, ts
->startport, ts->endport, port); } }
663 end_low, end_high,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow port end=%u..%u %s %s[%u]=%u..%u: %d"
, end_low, end_high, fit_string(fit), tss->name, index, ts
->startport, ts->endport, port); } }
664 fit_string(fit),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow port end=%u..%u %s %s[%u]=%u..%u: %d"
, end_low, end_high, fit_string(fit), tss->name, index, ts
->startport, ts->endport, port); } }
665 tss->name, index, ts->startport, ts->endport,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow port end=%u..%u %s %s[%u]=%u..%u: %d"
, end_low, end_high, fit_string(fit), tss->name, index, ts
->startport, ts->endport, port); } }
666 port){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " "narrow port end=%u..%u %s %s[%u]=%u..%u: %d"
, end_low, end_high, fit_string(fit), tss->name, index, ts
->startport, ts->endport, port); } }
;
667 return port;
668}
669
670/*
671 * Assign a score to the narrowed port, rationale for score lost in
672 * time?
673 */
674
675static int score_narrow_port(const struct end *end,
676 const struct traffic_selectors *tss,
677 enum fit fit, unsigned index)
678{
679 int f; /* strength of match */
680
681 int port = narrow_port(end, tss, fit, index);
682 if (port > 0) {
683 f = 1;
684 } else if (port == 0) {
685 f = 65536; /* from 1 + 65535-0 */
686 } else {
687 f = 0;
688 }
689 if (f > 0) {
690 dbg(MATCH_PREFIX " %s[%u] port match: YES fitness %d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: YES fitness %d"
, tss->name, index, f); } }
691 tss->name, index, f){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: YES fitness %d"
, tss->name, index, f); } }
;
692 } else {
693 dbg(MATCH_PREFIX " %s[%u] port match: NO",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: NO", tss->
name, index); } }
694 tss->name, index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: NO", tss->
name, index); } }
;
695 }
696 return f;
697}
698
699
700/*
701 * Does TS fit inside of END?
702 *
703 * Given other code flips the comparison depending initiator or
704 * responder, is this right?
705 *
706 * NOTE: Our parser/config only allows 1 CIDR, however IKEv2 ranges
707 * can be non-CIDR for now we really support/limit ourselves to
708 * a single CIDR
709 */
710
711static int score_address_range(const struct end *end,
712 const struct traffic_selectors *tss,
713 enum fit fit, unsigned index)
714{
715 const struct traffic_selector *ts = &tss->ts[index];
716 /*
717 * Pre-compute possible fit --- sum of bits gives how good a
718 * fit this is.
719 */
720 int ts_range = range_host_bits(ts->net);
721 int maskbits = end->client.maskbits;
722 int fitbits = maskbits + ts_range;
723
724 int f = 0;
725
726 /*
727 * NOTE: Our parser/config only allows 1 CIDR, however IKEv2
728 * ranges can be non-CIDR for now we really
729 * support/limit ourselves to a single CIDR
730 *
731 * XXX: so what is CIDR?
732 */
733 ip_range range = selector_range(end->client);
734 switch (fit) {
735 case END_EQUALS_TS:
736 if (range_eq_range(range, ts->net)) {
737 f = fitbits;
738 }
739 break;
740 case END_NARROWER_THAN_TS:
741 if (range_in_range(range, ts->net)) {
742 f = fitbits;
743 }
744 break;
745 case END_WIDER_THAN_TS:
746 if (range_in_range(ts->net, range)) {
747 f = fitbits;
748 }
749 break;
750 default:
751 bad_case(fit)libreswan_bad_case("fit", (fit), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 751, }; &here; }))
;
752 }
753
754 /*
755 * comparing for ports for finding better local policy
756 *
757 * XXX: why do this?
758 */
759 /* ??? arbitrary modification to objective function */
760 if (end->port != 0 &&
761 ts->startport == end->port &&
762 ts->endport == end->port)
763 f = f << 1;
764
765 LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 <<
(DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[(
(size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_
= ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf
), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf
= ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf
, &failsafe_logger, DEBUG_STREAM), buf = ((void*)0))
{
766 jam(buf, MATCH_PREFIX" " "match address end->client=");
767 jam_selector(buf, &end->client);
768 jam(buf, " %s %s[%u]net=", fit_string(fit), tss->name, index);
769 jam_range(buf, &ts->net);
770 jam(buf, ": ");
771 if (f > 0) {
772 jam(buf, "YES fitness %d", f);
773 } else {
774 jam(buf, "NO");
775 }
776 }
777 return f;
778}
779
780struct score {
781 bool_Bool ok;
782 int address;
783 int port;
784 int protocol;
785};
786
787static struct score score_end(const struct end *end,
788 const struct traffic_selectors *tss,
789 enum fit fit, unsigned index)
790{
791 const struct traffic_selector *ts = &tss->ts[index];
792
793 LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 <<
(DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[(
(size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_
= ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf
), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf
= ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf
, &failsafe_logger, DEBUG_STREAM), buf = ((void*)0))
{
794 jam(buf, " %s[%u]", tss->name, index);
795 if (ts->sec_label.len > 0) {
796 jam(buf, " sec_label=");
797 jam_sanitized_hunk(buf, ts->sec_label)({ typeof(ts->sec_label) hunk_ = (ts->sec_label); jam_sanitized_bytes
(buf, hunk_.ptr, hunk_.len); })
;
798 } else {
799 range_buf ts_net;
800 jam(buf, " net=%s iporotoid=%d {start,end}port=%d..%d",
801 str_range(&ts->net, &ts_net),
802 ts->ipprotoid,
803 ts->startport,
804 ts->endport);
805 }
806 }
807
808 struct score score = {
809 .ok = false0,
810 };
811
812 switch(ts->ts_type) {
813 case IKEv2_TS_IPV4_ADDR_RANGE:
814 case IKEv2_TS_IPV6_ADDR_RANGE:
815 score.address = score_address_range(end, tss, fit, index);
816 if (score.address <= 0) {
817 return score;
818 }
819 score.port = score_narrow_port(end, tss, fit, index);
820 if (score.port <= 0) {
821 return score;
822 }
823 score.protocol = score_narrow_protocol(end, tss, fit, index);
824 if (score.protocol <= 0) {
825 return score;
826 }
827 score.ok = true1;
828 return score;
829 case IKEv2_TS_SECLABEL:
830 default:
831 return score;
832 }
833}
834
835struct best_score {
836 bool_Bool ok;
837 int address;
838 int port;
839 int protocol;
840 const struct traffic_selector *tsi;
841 const struct traffic_selector *tsr;
842};
843#define NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, } { .ok = false0, .address = -1, .port = -1, .protocol = -1, }
844
845static bool_Bool score_gt(const struct best_score *score, const struct best_score *best)
846{
847 return (score->address > best->address ||
848 (score->address == best->address &&
849 score->port > best->port) ||
850 (score->address == best->address &&
851 score->port == best->port &&
852 score->protocol > best->protocol));
853}
854
855/*
856 * Return true for sec_label expected and good XOR not expected and
857 * not present.
858 *
859 * Return false when required sec_label is missing or bad; or
860 * sec_label encountered when it wasn't expected.
861 *
862 * The code calls sec_label_within_range() to check that the "source
863 * context has the access permission for the specified class on the
864 * "target context" (see selinux_check_access()):
865 *
866 * - for the initiator searching for a matching template connection to
867 * instantiate, the "source context" is the sec_label from acquire,
868 * and the "target context" is the sec_label in the template
869 * connection.
870 *
871 * - for the responder searching for a template connection to match
872 * the on-wire TS, the "source context" is the sec_label included in
873 * the traffic selector, and the "target context" is (again) the
874 * sec_label in the template connection.
875 *
876 * However, when the initiator gets back the responder's accepted TS
877 * containing a sec_label, the initiator only checks it is identical
878 * to what was sent out in the initiator's TS:
879 *
880 * - the RFC makes vague references to narrowing; but what that means
881 * for sec_labels isn't clear
882 *
883 * - one interpretation, that the responder's "source context" has
884 * "access permission" for the initiator's "source context" seems to
885 * always fail when enforcing is enabled (suspect
886 * selinux_check_access() requires a "ptarget context").
887 */
888
889static bool_Bool check_tss_sec_label(const struct traffic_selectors *tss,
890 chunk_t config_sec_label,
891 shunk_t *selected_sec_label,
892 struct logger *logger)
893{
894 passert(tss->contains_sec_label)({ _Bool assertion__ = tss->contains_sec_label; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 894
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "tss->contains_sec_label"
); } (void) 1; })
;
895
896 *selected_sec_label = null_shunk;
897 for (unsigned i = 0; i < tss->nr; i++) {
898 const struct traffic_selector *ts = &tss->ts[i];
899 if (ts->ts_type != IKEv2_TS_SECLABEL) {
900 continue;
901 }
902
903 passert(vet_seclabel(ts->sec_label) == NULL)({ _Bool assertion__ = vet_seclabel(ts->sec_label) == ((void
*)0); if (!assertion__) { where_t here = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 903, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "vet_seclabel(ts->sec_label) == ((void*)0)"
); } (void) 1; })
;
904
905 if (!sec_label_within_range(ts->sec_label, config_sec_label, logger)) {
906 dbg("ikev2ts: %s sec_label="PRI_SHUNK" is not within range connection sec_label="PRI_SHUNK,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ikev2ts: %s sec_label=""%.*s"" is not within range connection sec_label="
"%.*s", tss->name, ((int) (ts->sec_label).len), (const char
*) ((ts->sec_label).ptr), ((int) (config_sec_label).len),
(const char *) ((config_sec_label).ptr)); } }
907 tss->name, pri_shunk(ts->sec_label), pri_shunk(config_sec_label)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ikev2ts: %s sec_label=""%.*s"" is not within range connection sec_label="
"%.*s", tss->name, ((int) (ts->sec_label).len), (const char
*) ((ts->sec_label).ptr), ((int) (config_sec_label).len),
(const char *) ((config_sec_label).ptr)); } }
;
908 continue;
909 }
910
911 dbg("ikev2ts: received %s label within range of our security label",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ikev2ts: received %s label within range of our security label"
, tss->name); } }
912 tss->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ikev2ts: received %s label within range of our security label"
, tss->name); } }
;
913
914 /* XXX we return the first match. Should we return the best? */
915 *selected_sec_label = ts->sec_label; /* first match */
916 return true1;
917 }
918
919 return false0;
920}
921
922static bool_Bool score_tsp_sec_label(const struct traffic_selector_payloads *tsp,
923 chunk_t config_sec_label,
924 shunk_t *selected_sec_label,
925 struct logger *logger)
926{
927 if (config_sec_label.len == 0) {
928 /* This endpoint is not configured to use labeled IPsec. */
929 if (tsp->i.contains_sec_label || tsp->r.contains_sec_label) {
930 dbg("error: received sec_label but this end is *not* configured to use sec_label"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("error: received sec_label but this end is *not* configured to use sec_label"
); } }
;
931 return false0;
932 }
933 /* No sec_label was found and none was expected */
934 return true1; /* success: no label, as expected */
935 }
936
937 /* This endpoint is configured to use labeled IPsec. */
938 passert(vet_seclabel(HUNK_AS_SHUNK(config_sec_label)) == NULL)({ _Bool assertion__ = vet_seclabel(({ typeof(config_sec_label
) h_ = (config_sec_label); shunk2(h_.ptr, h_.len); })) == ((void
*)0); if (!assertion__) { where_t here = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 938, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "vet_seclabel(({ typeof(config_sec_label) h_ = (config_sec_label); shunk2(h_.ptr, h_.len); })) == ((void*)0)"
); } (void) 1; })
;
939
940 if (!tsp->i.contains_sec_label || !tsp->r.contains_sec_label) {
941 dbg("error: connection requires sec_label but not received TSi/TSr with sec_label"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("error: connection requires sec_label but not received TSi/TSr with sec_label"
); } }
;
942 return false0;
943 }
944
945 if (!check_tss_sec_label(&tsp->i, config_sec_label, selected_sec_label, logger) ||
946 !check_tss_sec_label(&tsp->r, config_sec_label, selected_sec_label, logger)) {
947 return false0;
948 }
949
950 /* security label required and matched */
951 return true1;
952}
953
954static struct best_score score_ends_iprange(enum fit fit,
955 const struct connection *d,
956 const struct ends *ends,
957 const struct traffic_selector_payloads *tsp)
958{
959 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
960 selector_buf ei3;
961 selector_buf er3;
962 connection_buf cib;
963 DBG_log("evaluating our conn="PRI_CONNECTION"\"%s\"%s"" I=%s:%d/%d R=%s:%d/%d%s to their:",
964 pri_connection(d, &cib)(d)->name, str_connection_instance(d, &cib),
965 str_selector(&ends->i->client, &ei3), ends->i->protocol, ends->i->port,
966 str_selector(&ends->r->client, &er3), ends->r->protocol, ends->r->port,
967 is_virtual_connection(d) ? " (virt)" : "");
968 }
969
970 struct best_score best_score = NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, };
971
972 /* compare tsi/r array to this/that, evaluating how well it fits */
973 for (unsigned tsi_n = 0; tsi_n < tsp->i.nr; tsi_n++) {
974 const struct traffic_selector *tni = &tsp->i.ts[tsi_n];
975
976 /* choice hardwired for IPrange and sec_label */
977 struct score score_i = score_end(ends->i, &tsp->i, fit, tsi_n);
978 if (!score_i.ok) {
979 continue;
980 }
981
982 for (unsigned tsr_n = 0; tsr_n < tsp->r.nr; tsr_n++) {
983 const struct traffic_selector *tnr = &tsp->r.ts[tsr_n];
984
985 struct score score_r = score_end(ends->r, &tsp->r, fit, tsr_n);
986 if (!score_r.ok) {
987 continue;
988 }
989 struct best_score score = {
990 .ok = true1,
991 /* ??? this objective function is odd and arbitrary */
992 .address = (score_i.address << 8) + score_r.address,
993 /* ??? arbitrary objective function */
994 .port = score_i.port + score_r.port,
995 /* ??? arbitrary objective function */
996 .protocol = score_i.protocol + score_r.protocol,
997 /* which one */
998 .tsi = tni, .tsr = tnr,
999 };
1000
1001 /* score >= best_score? */
1002 if (score_gt(&score, &best_score)) {
1003 best_score = score;
1004 dbg("best fit so far: TSi[%d] TSr[%d]",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("best fit so far: TSi[%d] TSr[%d]", tsi_n, tsr_n
); } }
1005 tsi_n, tsr_n){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("best fit so far: TSi[%d] TSr[%d]", tsi_n, tsr_n
); } }
;
1006 }
1007 }
1008 }
1009
1010 return best_score;
1011}
1012
1013static bool_Bool v2_child_connection_probably_shared(struct child_sa *child)
1014{
1015 struct connection *c = child->sa.st_connection;
1016
1017 if (connection_is_pending(c)) {
1018 dbg("#%lu connection is also pending; but what about pending for this state???",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu connection is also pending; but what about pending for this state???"
, child->sa.st_serialno); } }
1019 child->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu connection is also pending; but what about pending for this state???"
, child->sa.st_serialno); } }
;
1020 return true1;
1021 }
1022
1023 dbg("FOR_EACH_STATE_... in %s", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_STATE_... in %s", __func__); } }
;
1024 struct ike_sa *ike = ike_sa(&child->sa, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/ikev2_ts.c", .line = 1024, }; &here; }
)
);
1025 struct state *st = NULL((void*)0);
1026 FOR_EACH_STATE_NEW2OLD(st)for (struct list_entry *entry_ = (&state_serialno_list_head
)->head.older; entry_ != ((void*)0); entry_ = ((void*)0)) for
(st = (typeof(st))entry_->data, entry_ = entry_->older
; st != ((void*)0); st = (typeof(st))entry_->data, entry_ =
entry_->older)
{
1027 if (st->st_connection != c) {
1028 continue;
1029 }
1030 if (st == &child->sa) {
1031 dbg("ignoring ourselves #%lu sharing connection %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ignoring ourselves #%lu sharing connection %s"
, st->st_serialno, c->name); } }
1032 st->st_serialno, c->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ignoring ourselves #%lu sharing connection %s"
, st->st_serialno, c->name); } }
;
1033 continue;
1034 }
1035 if (st == &ike->sa) {
1036 dbg("ignoring IKE SA #%lu sharing connection %s with #%lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ignoring IKE SA #%lu sharing connection %s with #%lu"
, st->st_serialno, c->name, child->sa.st_serialno); }
}
1037 st->st_serialno, c->name, child->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ignoring IKE SA #%lu sharing connection %s with #%lu"
, st->st_serialno, c->name, child->sa.st_serialno); }
}
;
1038 continue;
1039 }
1040 dbg("#%lu and #%lu share connection %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu and #%lu share connection %s", child->
sa.st_serialno, st->st_serialno, c->name); } }
1041 child->sa.st_serialno, st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu and #%lu share connection %s", child->
sa.st_serialno, st->st_serialno, c->name); } }
1042 c->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu and #%lu share connection %s", child->
sa.st_serialno, st->st_serialno, c->name); } }
;
1043 return true1;
1044 }
1045
1046 return false0;
1047}
1048
1049struct narrowed_ts {
1050 bool_Bool ok;
1051 int tsi_port;
1052 int tsi_protocol;
1053 int tsr_port;
1054 int tsr_protocol;
1055};
1056
1057static struct narrowed_ts narrow_request_ts(struct connection *c,
1058 const struct traffic_selector_payloads *tsp,
1059 enum fit fit)
1060{
1061 struct narrowed_ts n = {
1062 .ok = false0, /* until proven */
1063 };
1064
1065 passert(tsp->i.nr >= 1)({ _Bool assertion__ = tsp->i.nr >= 1; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1065
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "tsp->i.nr >= 1"); }
(void) 1; })
;
1066 n.tsi_port = narrow_port(&c->spd.that, &tsp->i, fit, 0);
1067 if (n.tsi_port < 0) {
1068 dbg(" skipping; TSi port too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSi port too wide"); } }
;
1069 return n;
1070 }
1071
1072 n.tsi_protocol = narrow_protocol(&c->spd.that, &tsp->r, fit, 0);
1073 if (n.tsi_protocol < 0) {
1074 dbg(" skipping; TSi protocol too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSi protocol too wide"); } }
;
1075 return n;
1076 }
1077
1078 passert(tsp->r.nr >= 1)({ _Bool assertion__ = tsp->r.nr >= 1; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1078
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "tsp->r.nr >= 1"); }
(void) 1; })
;
1079 n.tsr_port = narrow_port(&c->spd.this, &tsp->r, fit, 0);
1080 if (n.tsr_port < 0) {
1081 dbg(" skipping; TSr port too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSr port too wide"); } }
;
1082 return n;
1083 }
1084
1085 n.tsr_protocol = narrow_protocol(&c->spd.this, &tsp->r, fit, 0);
1086 if (n.tsr_protocol < 0) {
1087 dbg(" skipping; TSr protocol too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSr protocol too wide"); } }
;
1088 return n;
1089 }
1090
1091 n.ok = true1;
1092 return n;
1093}
1094
1095static void scribble_request_ts_on_connection(struct child_sa *child,
1096 struct connection *c,
1097 struct narrowed_ts n)
1098{
1099 if (c != child->sa.st_connection) {
1100 connection_buf from, to;
1101 dbg(" switching #%lu from "PRI_CONNECTION" to just-instantiated "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" switching #%lu from ""\"%s\"%s"" to just-instantiated "
"\"%s\"%s", child->sa.st_serialno, (child->sa.st_connection
)->name, str_connection_instance(child->sa.st_connection
, &from), (c)->name, str_connection_instance(c, &to
)); } }
1102 child->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" switching #%lu from ""\"%s\"%s"" to just-instantiated "
"\"%s\"%s", child->sa.st_serialno, (child->sa.st_connection
)->name, str_connection_instance(child->sa.st_connection
, &from), (c)->name, str_connection_instance(c, &to
)); } }
1103 pri_connection(child->sa.st_connection, &from),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" switching #%lu from ""\"%s\"%s"" to just-instantiated "
"\"%s\"%s", child->sa.st_serialno, (child->sa.st_connection
)->name, str_connection_instance(child->sa.st_connection
, &from), (c)->name, str_connection_instance(c, &to
)); } }
1104 pri_connection(c, &to)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" switching #%lu from ""\"%s\"%s"" to just-instantiated "
"\"%s\"%s", child->sa.st_serialno, (child->sa.st_connection
)->name, str_connection_instance(child->sa.st_connection
, &from), (c)->name, str_connection_instance(c, &to
)); } }
;
1105 } else {
1106 connection_buf cib;
1107 dbg(" overwrote #%lu connection "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" overwrote #%lu connection ""\"%s\"%s", child
->sa.st_serialno, (c)->name, str_connection_instance(c,
&cib)); } }
1108 child->sa.st_serialno, pri_connection(c, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" overwrote #%lu connection ""\"%s\"%s", child
->sa.st_serialno, (c)->name, str_connection_instance(c,
&cib)); } }
;
1109 }
1110
1111 /* "this" == responder; see function name */
1112 c->spd.this.port = n.tsr_port;
1113 c->spd.that.port = n.tsi_port;
1114 c->spd.this.protocol = n.tsr_protocol;
1115 c->spd.that.protocol = n.tsi_protocol;
1116 /* hack */
1117 dbg("XXX: updating best connection's ports/protocols"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XXX: updating best connection's ports/protocols"
); } }
;
1118 update_selector_hport(&c->spd.this.client, n.tsr_port){ (&c->spd.this.client)->hport = (n.tsr_port); };
1119 update_selector_hport(&c->spd.that.client, n.tsi_port){ (&c->spd.that.client)->hport = (n.tsi_port); };
1120 update_selector_ipproto(&c->spd.this.client, n.tsr_protocol){ (&c->spd.this.client)->ipproto = (n.tsr_protocol)
; }
;
1121 update_selector_ipproto(&c->spd.that.client, n.tsi_protocol){ (&c->spd.that.client)->ipproto = (n.tsi_protocol)
; }
;
1122}
1123
1124/*
1125 * Find the best connection, possibly updating child.
1126 */
1127bool_Bool v2_process_request_ts_payloads(struct child_sa *child,
1128 const struct msg_digest *md)
1129{
1130 passert(v2_msg_role(md) == MESSAGE_REQUEST)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST; if
(!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1130, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "v2_msg_role(md) == MESSAGE_REQUEST"
); } (void) 1; })
;
1
Assuming the condition is true
2
Taking false branch
1131 passert(child->sa.st_sa_role == SA_RESPONDER)({ _Bool assertion__ = child->sa.st_sa_role == SA_RESPONDER
; if (!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1131, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "child->sa.st_sa_role == SA_RESPONDER"
); } (void) 1; })
;
3
Assuming field 'st_sa_role' is equal to SA_RESPONDER
4
Taking false branch
1132
1133 struct traffic_selector_payloads tsp = empty_traffic_selectors;
1134 if (!v2_parse_tsp(md, &tsp, child->sa.st_logger)) {
5
Calling 'v2_parse_tsp'
11
Returning from 'v2_parse_tsp'
12
Taking false branch
1135 return false0;
1136 }
1137
1138 /* best so far; start with state's connection */
1139 struct best_score best_score = NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, };
1140 const struct spd_route *best_spd_route = NULL((void*)0);
1141 struct connection *const c = child->sa.st_connection;
1142 struct connection *best_connection = c;
1143 shunk_t best_sec_label = null_shunk;
1144
1145 /* find best spd in c */
1146
1147 connection_buf ccb;
1148 dbg("responder looking for best SPD in current connection "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("responder looking for best SPD in current connection "
"\"%s\"%s", (c)->name, str_connection_instance(c, &ccb
)); } }
13
Assuming the condition is false
14
Taking false branch
1149 pri_connection(c, &ccb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("responder looking for best SPD in current connection "
"\"%s\"%s", (c)->name, str_connection_instance(c, &ccb
)); } }
;
1150 for (const struct spd_route *sra = &c->spd; sra != NULL((void*)0); sra = sra->spd_next) {
15
Assuming 'sra' is not equal to NULL
16
Loop condition is true. Entering loop body
20
Assuming 'sra' is equal to NULL
21
Loop condition is false. Execution continues on line 1203
1151
1152 /* responder */
1153 const struct ends ends = {
1154 .i = &sra->that,
1155 .r = &sra->this,
1156 };
1157
1158 shunk_t selected_sec_label = null_shunk;
1159 if (!score_tsp_sec_label(&tsp, c->config->sec_label,
17
Assuming the condition is true
18
Taking true branch
1160 &selected_sec_label,
1161 child->sa.st_logger)) {
1162 /*
1163 * Either:
1164 * - Security label required, but not found.
1165 * OR
1166 * - Security label *not* required, but found.
1167 */
1168 continue;
19
Execution continues on line 1150
1169 }
1170
1171 enum fit responder_fit =
1172 (c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
1173 ? END_NARROWER_THAN_TS
1174 : END_EQUALS_TS;
1175 struct best_score score = score_ends_iprange(responder_fit, c, &ends, &tsp);
1176 if (!score.ok) {
1177 continue;
1178 }
1179
1180 if (score_gt(&score, &best_score)) {
1181 dbg(" found better spd route for TSi[%td],TSr[%td]",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" found better spd route for TSi[%td],TSr[%td]"
, score.tsi - tsp.i.ts, score.tsr - tsp.r.ts); } }
1182 score.tsi - tsp.i.ts, score.tsr - tsp.r.ts){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" found better spd route for TSi[%td],TSr[%td]"
, score.tsi - tsp.i.ts, score.tsr - tsp.r.ts); } }
;
1183 best_score = score;
1184 best_spd_route = sra;
1185 best_sec_label = selected_sec_label;
1186 /* better SPD still within current connection */
1187 passert(best_connection == c)({ _Bool assertion__ = best_connection == c; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1187
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "best_connection == c"); }
(void) 1; })
;
1188 }
1189 }
1190
1191 /*
1192 * ??? the use of hp looks nonsensical.
1193 * Either the first non-empty host_pair should be used
1194 * (like the current code) and the following should
1195 * be broken into two loops: first find the non-empty
1196 * host_pair list, second look through the host_pair list.
1197 * OR
1198 * what's really meant is look at the host_pair for
1199 * each sra, something that matches the current
1200 * nested loop structure but not what it actually does.
1201 */
1202
1203 dbg("looking for better host pair"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("looking for better host pair"); } }
;
22
Assuming the condition is false
23
Taking false branch
1204
1205 const ip_address local = md->iface->ip_dev->id_address;
1206 FOR_EACH_THING(remote, endpoint_address(md->sender), unset_address)for (typeof(endpoint_address(md->sender)) things_[] = { endpoint_address
(md->sender), unset_address }, *thingp_ = things_, remote;
thingp_ < things_ + (sizeof(things_) / sizeof(*(things_))
) ? (remote = *thingp_, 1) : 0; thingp_++)
{
24
'?' condition is true
25
Loop condition is true. Entering loop body
28
'?' condition is true
29
Loop condition is true. Entering loop body
32
'?' condition is false
33
Loop condition is false. Execution continues on line 1306
1207
1208 FOR_EACH_HOST_PAIR_CONNECTION(local, remote, d)for (struct connection *next_ = ((void*)0), *d = next_host_pair_connection
(local, remote, &next_, 1, ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/ikev2_ts.c", .
line = 1208, }; &here; })); d != ((void*)0); d = next_host_pair_connection
(local, remote, &next_, 0, ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/ikev2_ts.c", .
line = 1208, }; &here; })))
{
26
Assuming 'd' is equal to null
27
Loop condition is false. Execution continues on line 1206
30
Assuming 'd' is equal to null
31
Loop condition is false. Execution continues on line 1206
1209
1210 /* groups are templates instantiated as GROUPINSTANCE */
1211 if (d->policy & POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX))) {
1212 continue;
1213 }
1214
1215 /*
1216 * For labeled IPsec, always start with the
1217 * template. Who are we to argue if the
1218 * kernel asks for a new SA with, seemingly, a
1219 * security label that matches an existing
1220 * connection instance.
1221 */
1222 if (c->ike_version == IKEv2 &&
1223 c->config->sec_label.len > 0 &&
1224 c->kind != CK_TEMPLATE) {
1225 connection_buf cb;
1226 dbg("skipping non-template IKEv2 "PRI_CONNECTION" with a security label",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("skipping non-template IKEv2 ""\"%s\"%s"" with a security label"
, (c)->name, str_connection_instance(c, &cb)); } }
1227 pri_connection(c, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("skipping non-template IKEv2 ""\"%s\"%s"" with a security label"
, (c)->name, str_connection_instance(c, &cb)); } }
;
1228 continue;
1229 }
1230
1231 dbg(" investigating connection \"%s\" as a better match", d->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" investigating connection \"%s\" as a better match"
, d->name); } }
;
1232
1233 /*
1234 * ??? same_id && match_id seems redundant.
1235 * if d->spd.this.id.kind == ID_NONE, both TRUE
1236 * else if c->spd.this.id.kind == ID_NONE,
1237 * same_id treats it as a wildcard and match_id
1238 * does not. Odd.
1239 * else if kinds differ, match_id FALSE
1240 * else if kind ID_DER_ASN1_DN, wildcards are forbidden by same_id
1241 * else match_id just calls same_id.
1242 * So: if wildcards are desired, just use match_id.
1243 * If they are not, just use same_id
1244 */
1245 int wildcards; /* value ignored */
1246 int pathlen; /* value ignored */
1247
1248 /* conns created as aliases from the same source have identical ID/CA */
1249 if (!(c->connalias != NULL((void*)0) && d->connalias != NULL((void*)0) && streq(c->connalias, d->connalias)(strcmp((c->connalias), (d->connalias)) == 0))) {
1250 if (!(same_id(&c->spd.this.id, &d->spd.this.id) &&
1251 match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) &&
1252 trusted_ca_nss(c->spd.that.ca, d->spd.that.ca, &pathlen)))
1253 {
1254 dbg(" connection \"%s\" does not match IDs or CA of current connection \"%s\"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" connection \"%s\" does not match IDs or CA of current connection \"%s\""
, d->name, c->name); } }
1255 d->name, c->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" connection \"%s\" does not match IDs or CA of current connection \"%s\""
, d->name, c->name); } }
;
1256 continue;
1257 }
1258 }
1259
1260 const struct spd_route *sr;
1261
1262 for (sr = &d->spd; sr != NULL((void*)0); sr = sr->spd_next) {
1263
1264 /* responder */
1265 const struct ends ends = {
1266 .i = &sr->that,
1267 .r = &sr->this,
1268 };
1269 /* responder -- note D! */
1270 enum fit responder_fit =
1271 (d->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
1272 ? END_NARROWER_THAN_TS
1273 : END_EQUALS_TS;
1274
1275 /* Returns NULL(ok), &null_shunk(skip), memory(ok). */
1276 shunk_t selected_sec_label = null_shunk;
1277 if (!score_tsp_sec_label(&tsp, d->config->sec_label,
1278 &selected_sec_label, child->sa.st_logger)) {
1279 /*
1280 * Either:
1281 * - Security label required, but not found.
1282 * OR
1283 * - Security label *not* required, but found.
1284 */
1285 continue;
1286 }
1287
1288 struct best_score score = score_ends_iprange(responder_fit, d/*note D*/,
1289 &ends, &tsp);
1290 if (!score.ok) {
1291 continue;
1292 }
1293 if (score_gt(&score, &best_score)) {
1294 dbg(" protocol fitness found better match d %s, TSi[%td],TSr[%td]",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" protocol fitness found better match d %s, TSi[%td],TSr[%td]"
, d->name, score.tsi - tsp.i.ts, score.tsr - tsp.r.ts); } }
1295 d->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" protocol fitness found better match d %s, TSi[%td],TSr[%td]"
, d->name, score.tsi - tsp.i.ts, score.tsr - tsp.r.ts); } }
1296 score.tsi - tsp.i.ts, score.tsr - tsp.r.ts){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" protocol fitness found better match d %s, TSi[%td],TSr[%td]"
, d->name, score.tsi - tsp.i.ts, score.tsr - tsp.r.ts); } }
;
1297 best_connection = d;
1298 best_score = score;
1299 best_spd_route = sr;
1300 best_sec_label = selected_sec_label;
1301 }
1302 }
1303 }
1304 }
1305
1306 if (best_connection
33.1
'best_connection' is equal to 'c'
== c) {
34
Taking true branch
1307 dbg(" did not find a better connection using host pair"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" did not find a better connection using host pair"
); } }
;
35
Assuming the condition is false
36
Taking false branch
1308 }
1309
1310#define CONNECTION_POLICIES(((lset_t)1 << (POLICY_NEGO_PASS_IX)) | ((lset_t)1 <<
(POLICY_DONT_REKEY_IX)) | ((lset_t)1 << (POLICY_REAUTH_IX
)) | ((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)) | ((lset_t
)1 << (POLICY_GROUP_IX)) | ((lset_t)1 << (POLICY_GROUTED_IX
)) | ((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | ((lset_t
)1 << (POLICY_UP_IX)) | ((lset_t)1 << (POLICY_XAUTH_IX
)) | ((lset_t)1 << (POLICY_MODECFG_PULL_IX)) | ((lset_t
)1 << (POLICY_AGGRESSIVE_IX)) | ((lset_t)1 << (POLICY_OVERLAPIP_IX
)) | ((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
(POLICY_NEGO_PASS((lset_t)1 << (POLICY_NEGO_PASS_IX)) | \
1311 POLICY_DONT_REKEY((lset_t)1 << (POLICY_DONT_REKEY_IX)) | \
1312 POLICY_REAUTH((lset_t)1 << (POLICY_REAUTH_IX)) | \
1313 POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)) | \
1314 POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX)) | \
1315 POLICY_GROUTED((lset_t)1 << (POLICY_GROUTED_IX)) | \
1316 POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | \
1317 POLICY_UP((lset_t)1 << (POLICY_UP_IX)) | \
1318 POLICY_XAUTH((lset_t)1 << (POLICY_XAUTH_IX)) | \
1319 POLICY_MODECFG_PULL((lset_t)1 << (POLICY_MODECFG_PULL_IX)) | \
1320 POLICY_AGGRESSIVE((lset_t)1 << (POLICY_AGGRESSIVE_IX)) | \
1321 POLICY_OVERLAPIP((lset_t)1 << (POLICY_OVERLAPIP_IX)) | \
1322 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
1323
1324 /*
1325 * Try instantiating something better.
1326 */
1327 if (best_spd_route
36.1
'best_spd_route' is equal to NULL
== NULL((void*)0) && c->kind != CK_INSTANCE) {
37
Assuming field 'kind' is equal to CK_INSTANCE
38
Taking false branch
1328 /*
1329 * Don't try to look for something else to
1330 * 'instantiate' when the current connection is
1331 * permanent.
1332 *
1333 * XXX: but c->kind could be CK_TEMPLATE?
1334 *
1335 * XXX: Is this missing an opportunity? Could there
1336 * be a better connection to instantiate when the
1337 * current one is permanent?
1338 *
1339 * XXX: 'instantiate', not really? The code below
1340 * sometimes blats the current instance with new
1341 * values - something that should not be done to a
1342 * permanent connection.
1343 */
1344 pexpect((c->kind == CK_PERMANENT) ||({ _Bool assertion__ = (c->kind == CK_PERMANENT) || (c->
kind == CK_TEMPLATE && c->config->sec_label.len
> 0); if (!assertion__) { where_t here_ = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1345, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "(c->kind == CK_PERMANENT) || (c->kind == CK_TEMPLATE && c->config->sec_label.len > 0)"
); } assertion__; })
1345 (c->kind == CK_TEMPLATE && c->config->sec_label.len > 0))({ _Bool assertion__ = (c->kind == CK_PERMANENT) || (c->
kind == CK_TEMPLATE && c->config->sec_label.len
> 0); if (!assertion__) { where_t here_ = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1345, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "(c->kind == CK_PERMANENT) || (c->kind == CK_TEMPLATE && c->config->sec_label.len > 0)"
); } assertion__; })
;
1346 dbg("no best spd route; but the current %s connection \"%s\" is not a CK_INSTANCE; giving up",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("no best spd route; but the current %s connection \"%s\" is not a CK_INSTANCE; giving up"
, enum_name(&connection_kind_names, c->kind), c->name
); } }
1347 enum_name(&connection_kind_names, c->kind), c->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("no best spd route; but the current %s connection \"%s\" is not a CK_INSTANCE; giving up"
, enum_name(&connection_kind_names, c->kind), c->name
); } }
;
1348 llog_sa(RC_LOG_SERIOUS, child, "No IKEv2 connection found with compatible Traffic Selectors")llog(RC_LOG_SERIOUS, (child)->sa.st_logger, "No IKEv2 connection found with compatible Traffic Selectors"
)
;
1349 return false0;
1350 }
1351
1352 if (best_spd_route
38.1
'best_spd_route' is equal to NULL
== NULL((void*)0) && ((c->policy & POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX))) ||
39
Assuming the condition is true
1353 (c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX))))) {
1354 /*
1355 * Is there something better than the current
1356 * connection?
1357 *
1358 * Rather than overwrite the current INSTANCE; would
1359 * it be better to instantiate a new instance, and
1360 * then replace it?
1361 *
1362 * Would also address the above.
1363 *
1364 * If the connection seems to be shared, this happens.
1365 */
1366 pexpect(c->kind == CK_INSTANCE)({ _Bool assertion__ = c->kind == CK_INSTANCE; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1366
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->kind == CK_INSTANCE"
); } assertion__; })
;
40
Taking false branch
1367 /* since an SPD_ROUTE wasn't found */
1368 passert(best_connection == c)({ _Bool assertion__ = best_connection == c; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1368
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "best_connection == c"); }
(void) 1; })
;
41
Taking false branch
1369 dbg("no best spd route; looking for a better template connection to instantiate"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("no best spd route; looking for a better template connection to instantiate"
); } }
;
42
Taking false branch
1370
1371 struct connection_query cq = { .where = HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/ikev2_ts.c", .line = 1371, }; &here; }
)
, .c = NULL((void*)0), };
1372 while (new2old_connection(&cq)) {
43
Loop condition is true. Entering loop body
1373 struct connection *t = cq.c;
1374 /* require a template */
1375 if (t->kind != CK_TEMPLATE) {
44
Assuming field 'kind' is equal to CK_TEMPLATE
45
Taking false branch
1376 continue;
1377 }
1378 LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 <<
(DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[(
(size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_
= ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf
), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf
= ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf
, &failsafe_logger, DEBUG_STREAM), buf = ((void*)0))
{
46
Loop condition is true. Entering loop body
47
Loop condition is true. Entering loop body
48
Loop condition is true. Entering loop body
49
Loop condition is true. Entering loop body
52
Loop condition is false. Execution continues on line 1378
53
Loop condition is false. Execution continues on line 1378
54
Loop condition is false. Execution continues on line 1378
55
Loop condition is false. Execution continues on line 1395
1379 jam(buf, " investigating template \"%s\";",
1380 t->name);
1381 if (t->foodgroup != NULL((void*)0)) {
50
Assuming field 'foodgroup' is equal to NULL
51
Taking false branch
1382 jam(buf, " food-group=\"%s\"", t->foodgroup);
1383 }
1384 jam(buf, " policy=");
1385 jam_policy(buf, t->policy & CONNECTION_POLICIES(((lset_t)1 << (POLICY_NEGO_PASS_IX)) | ((lset_t)1 <<
(POLICY_DONT_REKEY_IX)) | ((lset_t)1 << (POLICY_REAUTH_IX
)) | ((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)) | ((lset_t
)1 << (POLICY_GROUP_IX)) | ((lset_t)1 << (POLICY_GROUTED_IX
)) | ((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | ((lset_t
)1 << (POLICY_UP_IX)) | ((lset_t)1 << (POLICY_XAUTH_IX
)) | ((lset_t)1 << (POLICY_MODECFG_PULL_IX)) | ((lset_t
)1 << (POLICY_AGGRESSIVE_IX)) | ((lset_t)1 << (POLICY_OVERLAPIP_IX
)) | ((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
);
1386 }
1387
1388 /*
1389 * Is it worth looking at the template.
1390 *
1391 * XXX: treat the combination the same as
1392 * group instance, like the old code did; is
1393 * this valid?
1394 */
1395 switch (c->policy & (POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) |
56
Control jumps to 'case 4362076160:' at line 1398
1396 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))) {
1397 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)):
1398 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)): /* XXX: true */
1399 /* XXX: why does this matter; does it imply t->foodgroup != NULL? */
1400 if (!LIN(POLICY_GROUPINSTANCE, t->policy)(((((lset_t)1 << (POLICY_GROUPINSTANCE_IX))) & (t->
policy)) == (((lset_t)1 << (POLICY_GROUPINSTANCE_IX))))
) {
57
Assuming the condition is true
58
Taking false branch
1401 dbg(" skipping; not a group instance"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; not a group instance"); } }
;
1402 continue;
1403 }
1404 /* when OE, don't change food groups? */
1405 if (!streq(c->foodgroup, t->foodgroup)(strcmp((c->foodgroup), (t->foodgroup)) == 0)) {
59
Null pointer passed to 2nd parameter expecting 'nonnull'
1406 dbg(" skipping; wrong foodgroup name"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; wrong foodgroup name"); } }
;
1407 continue;
1408 }
1409 /* ??? why require current connection->name and t->name to be different */
1410 /* XXX: don't re-instantiate the same connection template???? */
1411 if (streq(c->name, t->name)(strcmp((c->name), (t->name)) == 0)) {
1412 dbg(" skipping; name same as current connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; name same as current connection"
); } }
;
1413 continue;
1414 }
1415 break;
1416 case POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)):
1417 if (!LIN(POLICY_IKEV2_ALLOW_NARROWING, t->policy)(((((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX))) &
(t->policy)) == (((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX
))))
) {
1418 dbg(" skipping; cannot narrow"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; cannot narrow"); } }
;
1419 continue;
1420 }
1421 break;
1422 default:
1423 bad_case(c->policy)libreswan_bad_case("c->policy", (c->policy), ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1423, }; &here; }))
; /* not quite true */
1424 }
1425
1426 /* require initiator's subnet <= T; why? */
1427 if (!selector_in_selector(c->spd.that.client, t->spd.that.client)) {
1428 dbg(" skipping; current connection's initiator subnet is not <= template"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; current connection's initiator subnet is not <= template"
); } }
;
1429 continue;
1430 }
1431 /* require responder address match; why? */
1432 ip_address c_this_client_address = selector_prefix(c->spd.this.client);
1433 ip_address t_this_client_address = selector_prefix(t->spd.this.client);
1434 if (!address_eq_address(c_this_client_address, t_this_client_address)) {
1435 dbg(" skipping; responder addresses don't match"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; responder addresses don't match"
); } }
;
1436 continue;
1437 }
1438
1439 /* require a valid narrowed port? */
1440 enum fit fit;
1441 switch (c->policy & (POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) |
1442 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))) {
1443 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)):
1444 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)): /* XXX: true */
1445 /* exact match; XXX: 'cos that is what old code did */
1446 fit = END_EQUALS_TS;
1447 break;
1448 case POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)):
1449 /* narrow END's port to TS port */
1450 fit = END_WIDER_THAN_TS;
1451 break;
1452 default:
1453 bad_case(c->policy)libreswan_bad_case("c->policy", (c->policy), ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1453, }; &here; }))
;
1454 }
1455
1456 passert(best_connection == c)({ _Bool assertion__ = best_connection == c; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/ikev2_ts.c", .line = 1456
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "best_connection == c"); }
(void) 1; })
; /* aka st->st_connection, no leak */
1457 pexpect(best_connection == child->sa.st_connection)({ _Bool assertion__ = best_connection == child->sa.st_connection
; if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1457, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "best_connection == child->sa.st_connection"
); } assertion__; })
;
1458 struct narrowed_ts n = narrow_request_ts(t, &tsp, fit);
1459 if (!n.ok) {
1460 continue;
1461 }
1462
1463 struct connection *s;
1464 if (v2_child_connection_probably_shared(child)) {
1465 /* instantiate it, filling in peer's ID */
1466 /* XXX: is best_sec_label ever non-NULL? */
1467 s = instantiate(t, &child->sa.st_connection->spd.that.host_addr,
1468 NULL((void*)0), best_sec_label);
1469 } else {
1470 s = child->sa.st_connection;
1471 }
1472 scribble_request_ts_on_connection(child, s, n);
1473
1474 /* switch */
1475 best_connection = s;
1476 best_spd_route = &best_connection->spd;
1477 break;
1478 }
1479 } else if (best_connection == c &&
1480 c->kind == CK_TEMPLATE &&
1481 c->config->sec_label.len > 0) {
1482 dbg(" instantiating template security label connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" instantiating template security label connection"
); } }
;
1483 /* sure looks like a sec-label template */
1484 struct narrowed_ts n = narrow_request_ts(c, &tsp, END_WIDER_THAN_TS);
1485 if (!n.ok) {
1486 return false0;
1487 }
1488
1489 struct connection *s = instantiate(c, &child->sa.st_connection->spd.that.host_addr,
1490 NULL((void*)0), best_sec_label);
1491 scribble_request_ts_on_connection(child, s, n);
1492
1493 /* switch */
1494 best_connection = s;
1495 best_spd_route = &best_connection->spd;
1496 }
1497
1498 if (best_spd_route == NULL((void*)0)) {
1499 dbg("giving up"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("giving up"); } }
;
1500 return false0;
1501 }
1502
1503 /*
1504 * this both replaces the child's connection, and flips any
1505 * underlying current-connection
1506 *
1507 * XXX: but this is responder code, there probably isn't a
1508 * current-connection - it would have gone straight to current
1509 * state.
1510 *
1511 * XXX: ah, but the state code does: set-state; set-connection
1512 * (yes order is wrong). Why does it bother?
1513 *
1514 * update_state_connection(), if the connection changes,
1515 * de-references the old connection; which is what really
1516 * matters
1517 */
1518 update_state_connection(&child->sa, best_connection);
1519
1520 return true1;
1521}
1522
1523/* check TS payloads, response */
1524bool_Bool v2_process_ts_response(struct child_sa *child,
1525 struct msg_digest *md)
1526{
1527 passert(child->sa.st_sa_role == SA_INITIATOR)({ _Bool assertion__ = child->sa.st_sa_role == SA_INITIATOR
; if (!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1527, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "child->sa.st_sa_role == SA_INITIATOR"
); } (void) 1; })
;
1528 passert(v2_msg_role(md) == MESSAGE_RESPONSE)({ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE; if
(!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1528, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE"
); } (void) 1; })
;
1529
1530 struct connection *c = child->sa.st_connection;
1531
1532 struct traffic_selector_payloads tsp = empty_traffic_selectors;
1533 if (!v2_parse_tsp(md, &tsp, child->sa.st_logger)) {
1534 return false0;
1535 }
1536
1537 /* initiator */
1538 const struct spd_route *sra = &c->spd;
1539 const struct ends e = {
1540 .i = &sra->this,
1541 .r = &sra->that,
1542 };
1543 enum fit initiator_widening =
1544 (c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
1545 ? END_WIDER_THAN_TS
1546 : END_EQUALS_TS;
1547
1548 /* Returns NULL(ok), &null_shunk(skip), memory(ok). */
1549 shunk_t selected_sec_label = null_shunk;
1550 if (!score_tsp_sec_label(&tsp, c->config->sec_label,
1551 &selected_sec_label, child->sa.st_logger)) {
1552 /*
1553 * Either:
1554 * - Security label required, but not found.
1555 * OR
1556 * - Security label *not* required, but found.
1557 */
1558 return false0;
1559 }
1560
1561 struct best_score best = score_ends_iprange(initiator_widening, c, &e, &tsp);
1562
1563 if (!best.ok) {
1564 dbg("reject responder TSi/TSr Traffic Selector"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("reject responder TSi/TSr Traffic Selector"); }
}
;
1565 /* prevents parent from going to I3 */
1566 return false0;
1567 }
1568
1569 traffic_selector_to_end(best.tsi, &c->spd.this,
1570 "scribble accepted TSi response on initiator's this");
1571 traffic_selector_to_end(best.tsr, &c->spd.that,
1572 "scribble accepted TSr response on initiator's that");
1573
1574 return true1;
1575}
1576
1577/*
1578 * RFC 7296 https://tools.ietf.org/html/rfc7296#section-2.8
1579 * "when rekeying, the new Child SA SHOULD NOT have different Traffic
1580 * Selectors and algorithms than the old one."
1581 *
1582 * However, when narrowed down, the original TSi/TSr is wider than the
1583 * returned narrowed TSi/TSr. Windows 10 is known to use the original
1584 * and not the narrowed TSi/TSr.
1585 *
1586 * RFC 7296 #1.3.3 "The Traffic Selectors for traffic to be sent
1587 * on that SA are specified in the TS payloads in the response,
1588 * which may be a subset of what the initiator of the Child SA proposed."
1589 *
1590 * However, the rekey initiator, when it is the original initiator of
1591 * the Child SA, may request a super set. And responder should
1592 * respond with same set as initially negotiated, ie RFC 7296 #2.8
1593 *
1594 * See RFC 7296 Section 1.7. for the above change.
1595 * Significant Differences between RFC 4306 and RFC 5996
1596 *
1597 * We already matched the right connection by the SPI of v2N_REKEY_SA
1598 */
1599bool_Bool child_rekey_responder_ts_verify(struct child_sa *child, struct msg_digest *md)
1600{
1601 if (!pexpect(child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0)({ _Bool assertion__ = child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0
; if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/ikev2_ts.c"
, .line = 1601, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0"
); } assertion__; })
)
1602 return false0;
1603
1604 const struct connection *c = child->sa.st_connection;
1605 struct traffic_selector_payloads their_tsp = empty_traffic_selectors;
1606
1607 if (!v2_parse_tsp(md, &their_tsp, child->sa.st_logger)) {
1608 log_state(RC_LOG_SERIOUS, &child->sa,
1609 "received malformed TSi/TSr payload(s)");
1610 return false0;
1611 }
1612
1613 const struct ends ends = {
1614 .i = &c->spd.that,
1615 .r = &c->spd.this,
1616 };
1617
1618 enum fit fitness = END_NARROWER_THAN_TS;
1619
1620 /* Returns NULL(ok), &null_shunk(skip), memory(ok). */
1621 shunk_t selected_sec_label = null_shunk;
1622 if (!score_tsp_sec_label(&their_tsp, c->config->sec_label,
1623 &selected_sec_label,
1624 child->sa.st_logger)) {
1625 /*
1626 * Either:
1627 * - Security label required, but not found.
1628 * OR
1629 * - Security label *not* required, but found.
1630 */
1631 log_state(RC_LOG_SERIOUS, &child->sa,
1632 "rekey: received Traffic Selectors mismatch configured selectors for Security Label");
1633 return false0;
1634 }
1635
1636 struct best_score score = score_ends_iprange(fitness, c, &ends, &their_tsp);
1637
1638 if (!score.ok) {
1639 log_state(RC_LOG_SERIOUS, &child->sa,
1640 "rekey: received Traffic Selectors does not contain existing IPsec SA Traffic Selectors");
1641 return false0;
1642 }
1643
1644 return true1;
1645}