Bug Summary

File:programs/pluto/ikev2_ts.c
Warning:line 1036, column 10
Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib64/clang/8.0.0 -D TimeZoneOffset=timezone -D linux -D PIE -D NSS_IPSEC_PROFILE -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 USE_SYSTEMD_WATCHDOG -D HAVE_NM -D XAUTH_HAVE_PAM -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 DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/etc/ipsec.d" -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/libreswan/programs/pluto/linux-copy -D HERE_BASENAME="ikev2_ts.c" -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/8.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-missing-field-initializers -std=gnu99 -fdebug-compilation-dir /home/build/libreswan/programs/pluto -ferror-limit 19 -fmessage-length 0 -stack-protector 3 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /tmp/scan-build-2020-09-09-193337-25440-1 -x c /home/build/libreswan/programs/pluto/ikev2_ts.c -faddrsig
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 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 */
25
26#include "defs.h"
27
28#include "log.h"
29#include "ikev2_ts.h"
30#include "connections.h" /* for struct end */
31#include "demux.h"
32#include "virtual.h"
33#include "hostpair.h"
34#include "ip_info.h"
35#include "ip_selector.h"
36
37/*
38 * While the RFC seems to suggest that the traffic selectors come in
39 * pairs, strongswan, at least, doesn't.
40 */
41struct traffic_selectors {
42 unsigned nr;
43 /* ??? is 16 an undocumented limit - IKEv2 has no limit */
44 struct traffic_selector ts[16];
45};
46
47struct ends {
48 const struct end *i;
49 const struct end *r;
50};
51
52enum fit {
53 END_EQUALS_TS = 1,
54 END_NARROWER_THAN_TS,
55 END_WIDER_THAN_TS,
56};
57
58
59static bool_Bool ts_in_tslist(struct traffic_selectors *haystack,
60 struct traffic_selector *needle)
61{
62 for (unsigned int i = 0; i < haystack->nr; i++) {
63 struct traffic_selector hay = haystack->ts[i];
64
65 if (needle->ts_type == hay.ts_type &&
66 needle->ipprotoid == hay.ipprotoid &&
67 needle->startport == hay.startport &&
68 needle->endport == hay.endport &&
69 sameaddr(&needle->net.start, &hay.net.start) &&
70 sameaddr(&needle->net.end, &hay.net.end))
71 {
72 return TRUE1;
73 }
74 }
75 return FALSE0;
76}
77
78static const char *fit_string(enum fit fit)
79{
80 switch (fit) {
81 case END_EQUALS_TS: return "==";
82 case END_NARROWER_THAN_TS: return "<=";
83 case END_WIDER_THAN_TS: return ">=";
84 default: bad_case(fit)libreswan_bad_case("fit", (fit), (where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 84})
;
85 }
86}
87
88void ikev2_print_ts(const struct traffic_selector *ts)
89{
90 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
91 DBG_log("printing contents struct traffic_selector");
92 DBG_log(" ts_type: %s", enum_name(&ikev2_ts_type_names, ts->ts_type));
93 DBG_log(" ipprotoid: %d", ts->ipprotoid);
94 DBG_log(" port range: %d-%d", ts->startport, ts->endport);
95 range_buf b;
96 DBG_log(" ip range: %s", str_range(&ts->net, &b));
97 }
98}
99
100/* rewrite me with address_as_{chunk,shunk}()? */
101struct traffic_selector ikev2_end_to_ts(const struct end *e)
102{
103 struct traffic_selector ts;
104
105 zero(&ts)memset((&ts), '\0', sizeof(*(&ts))); /* OK: no pointer fields */
106
107 switch (subnet_type(&e->client)->af) {
108 case AF_INET2:
109 ts.ts_type = IKEv2_TS_IPV4_ADDR_RANGE;
110 break;
111 case AF_INET610:
112 ts.ts_type = IKEv2_TS_IPV6_ADDR_RANGE;
113 break;
114 }
115
116 /* subnet => range */
117 ts.net = range_from_subnet(&e->client);
118 /* Setting ts_type IKEv2_TS_FC_ADDR_RANGE (RFC-4595) not yet supported */
119
120 ts.ipprotoid = e->protocol;
121
122 /*
123 * if port is %any or 0 we mean all ports (or all iccmp/icmpv6)
124 * See RFC-5996 Section 3.13.1 handling for ICMP(1) and ICMPv6(58)
125 * we only support providing Type, not Code, eg protoport=1/1
126 */
127 if (e->port == 0 || e->has_port_wildcard) {
128 ts.startport = 0;
129 ts.endport = 65535;
130 } else {
131 ts.startport = e->port;
132 ts.endport = e->port;
133 }
134
135 return ts;
136}
137
138static stf_status ikev2_emit_ts(pb_stream *outpbs,
139 const struct_desc *ts_desc,
140 const struct traffic_selector *ts)
141{
142 pb_stream ts_pbs;
143
144 {
145 struct ikev2_ts its = {
146 .isat_critical = ISAKMP_PAYLOAD_NONCRITICAL0x00,
147 .isat_num = 1,
148 };
149
150 if (!out_struct(&its, ts_desc, outpbs, &ts_pbs))
151 return STF_INTERNAL_ERROR;
152 }
153
154 pb_stream ts_pbs2;
155
156 {
157 struct ikev2_ts1 its1 = {
158 .isat1_ipprotoid = ts->ipprotoid, /* protocol as per local policy */
159 .isat1_startport = ts->startport, /* ports as per local policy */
160 .isat1_endport = ts->endport,
161 };
162 switch (ts->ts_type) {
163 case IKEv2_TS_IPV4_ADDR_RANGE:
164 its1.isat1_type = IKEv2_TS_IPV4_ADDR_RANGE;
165 break;
166 case IKEv2_TS_IPV6_ADDR_RANGE:
167 its1.isat1_type = IKEv2_TS_IPV6_ADDR_RANGE;
168 break;
169 case IKEv2_TS_FC_ADDR_RANGE:
170 DBG_log("IKEv2 Traffic Selector IKEv2_TS_FC_ADDR_RANGE not yet supported");
171 return STF_INTERNAL_ERROR;
172
173 default:
174 DBG_log("IKEv2 Traffic Selector type '%d' not supported",
175 ts->ts_type);
176 return STF_INTERNAL_ERROR; /* ??? should be bad_case()? */
177 }
178
179 if (!out_struct(&its1, &ikev2_ts1_desc, &ts_pbs, &ts_pbs2))
180 return STF_INTERNAL_ERROR;
181 }
182
183 /* now do IP addresses */
184 switch (ts->ts_type) {
185 case IKEv2_TS_IPV4_ADDR_RANGE:
186 case IKEv2_TS_IPV6_ADDR_RANGE:
187 {
188 diag_t d;
189 d = pbs_out_address(&ts_pbs2, &ts->net.start, "IP start");
190 if (d != NULL((void*)0)) {
191 log_diag(RC_LOG_SERIOUS, outpbs->out_logger, &d, "%s", "");
192 return STF_INTERNAL_ERROR;
193 }
194 d = pbs_out_address(&ts_pbs2, &ts->net.end, "IP end");
195 if (d != NULL((void*)0)) {
196 log_diag(RC_LOG_SERIOUS, outpbs->out_logger, &d, "%s", "");
197 return STF_INTERNAL_ERROR;
198 }
199 break;
200 }
201 case IKEv2_TS_FC_ADDR_RANGE:
202 DBG_log("Traffic Selector IKEv2_TS_FC_ADDR_RANGE not supported");
203 return STF_FAIL;
204
205 default:
206 DBG_log("Failed to create unknown IKEv2 Traffic Selector payload '%d'",
207 ts->ts_type);
208 return STF_FAIL;
209 }
210
211 close_output_pbs(&ts_pbs2);
212 close_output_pbs(&ts_pbs);
213
214 return STF_OK;
215}
216
217static struct traffic_selector impair_ts_to_subnet(const struct traffic_selector *ts)
218{
219 struct traffic_selector ts_ret = *ts;
220
221 ts_ret.net.end = ts_ret.net.start;
222 ts_ret.net.is_subnet = true1;
223
224 return ts_ret;
225}
226
227
228static struct traffic_selector impair_ts_to_supernet(const struct traffic_selector *ts)
229{
230 struct traffic_selector ts_ret = *ts;
231
232 if (ts_ret.ts_type == IKEv2_TS_IPV4_ADDR_RANGE)
233 ts_ret.net = range_from_subnet(&ipv4_info.all_addresses);
234 else if (ts_ret.ts_type == IKEv2_TS_IPV6_ADDR_RANGE)
235 ts_ret.net = range_from_subnet(&ipv6_info.all_addresses);
236
237 ts_ret.net.is_subnet = true1;
238
239 return ts_ret;
240}
241
242stf_status v2_emit_ts_payloads(const struct child_sa *child,
243 pb_stream *outpbs,
244 const struct connection *c0)
245{
246 const struct traffic_selector *ts_i, *ts_r;
247 struct traffic_selector ts_i_impaired, ts_r_impaired;
248
249
250 switch (child->sa.st_sa_role) {
251 case SA_INITIATOR:
252 ts_i = &child->sa.st_ts_this;
253 ts_r = &child->sa.st_ts_that;
254 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I0 &&
255 impair.rekey_initiate_supernet) {
256 ts_i_impaired = impair_ts_to_supernet(ts_i);
257 ts_i = ts_r = &ts_i_impaired; /* supernet TSi = TSr = 0/0 */
258 range_buf tsi_buf;
259 range_buf tsr_buf;
260 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)); } }
261 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)); } }
262 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)); } }
;
263
264 } else if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I0 &&
265 impair.rekey_initiate_subnet) {
266 ts_i_impaired = impair_ts_to_subnet(ts_i);
267 ts_r_impaired = impair_ts_to_subnet(ts_r);
268 ts_i = &ts_i_impaired;
269 ts_r = &ts_r_impaired;
270 range_buf tsi_buf;
271 range_buf tsr_buf;
272 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)); } }
273 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)); } }
274 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)); } }
;
275
276 }
277
278 break;
279 case SA_RESPONDER:
280 ts_i = &child->sa.st_ts_that;
281 ts_r = &child->sa.st_ts_this;
282 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 &&
283 impair.rekey_respond_subnet) {
284 ts_i_impaired = impair_ts_to_subnet(ts_i);
285 ts_r_impaired = impair_ts_to_subnet(ts_r);
286
287 ts_i = &ts_i_impaired;
288 ts_r = &ts_r_impaired;
289 range_buf tsi_buf;
290 range_buf tsr_buf;
291 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)); } }
292 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)); } }
293 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)); } }
;
294 }
295 if (child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 &&
296 impair.rekey_respond_supernet) {
297 ts_i_impaired = impair_ts_to_supernet(ts_i);
298 ts_i = ts_r = &ts_i_impaired; /* supernet TSi = TSr = 0/0 */
299 range_buf tsi_buf;
300 range_buf tsr_buf;
301 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)); } }
302 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)); } }
303 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)); } }
;
304 }
305 break;
306 default:
307 bad_case(child->sa.st_sa_role)libreswan_bad_case("child->sa.st_sa_role", (child->sa.st_sa_role
), (where_t) { .func = __func__, .basename = "ikev2_ts.c" , .
line = 307})
;
308 }
309
310 /*
311 * XXX: this looks wrong
312 *
313 * - instead of emitting two traffic selector payloads (TSi
314 * TSr) each containing all the corresponding traffic
315 * selectors, it is emitting a sequence of traffic selector
316 * payloads each containing just one traffic selector
317 *
318 * - should multiple initiator (responder) traffic selector
319 * payloads be emitted then they will all contain the same
320 * value - the loop control variable SR is never referenced
321 *
322 * - should multiple traffic selector payload be emitted then
323 * the next payload type for all but the last v2TSr payload
324 * will be wrong - it is always set to the type of the
325 * payload after these
326 */
327
328 for (const struct spd_route *sr = &c0->spd; sr != NULL((void*)0);
329 sr = sr->spd_next) {
330 stf_status ret = ikev2_emit_ts(outpbs, &ikev2_ts_i_desc, ts_i);
331
332 if (ret != STF_OK)
333 return ret;
334 ret = ikev2_emit_ts(outpbs, &ikev2_ts_r_desc, ts_r);
335 if (ret != STF_OK)
336 return ret;
337 }
338
339 return STF_OK;
340}
341
342/* return success */
343static bool_Bool v2_parse_ts(struct payload_digest *const ts_pd,
344 struct traffic_selectors *tss,
345 const char *which)
346{
347 dbg("%s: parsing %u traffic selectors",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsing %u traffic selectors", which, ts_pd
->payload.v2ts.isat_num); } }
348 which, ts_pd->payload.v2ts.isat_num){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsing %u traffic selectors", which, ts_pd
->payload.v2ts.isat_num); } }
;
349
350 if (ts_pd->payload.v2ts.isat_num == 0) {
351 libreswan_log("%s payload contains no entries when at least one is expected",loglog(RC_LOG, "%s payload contains no entries when at least one is expected"
, which)
352 which)loglog(RC_LOG, "%s payload contains no entries when at least one is expected"
, which)
;
353 return false0;
354 }
355
356 if (ts_pd->payload.v2ts.isat_num >= elemsof(tss->ts)(sizeof(tss->ts) / sizeof(*(tss->ts)))) {
357 libreswan_log("%s contains %d entries which exceeds hardwired max of %zu",loglog(RC_LOG, "%s contains %d entries which exceeds hardwired max of %zu"
, which, ts_pd->payload.v2ts.isat_num, (sizeof(tss->ts)
/ sizeof(*(tss->ts))))
358 which, ts_pd->payload.v2ts.isat_num, elemsof(tss->ts))loglog(RC_LOG, "%s contains %d entries which exceeds hardwired max of %zu"
, which, ts_pd->payload.v2ts.isat_num, (sizeof(tss->ts)
/ sizeof(*(tss->ts))))
;
359 return false0; /* won't fit in array */
360 }
361
362 for (tss->nr = 0; tss->nr < ts_pd->payload.v2ts.isat_num; tss->nr++) {
363 struct traffic_selector *ts = &tss->ts[tss->nr];
364
365 pb_stream addr;
366 struct ikev2_ts1 ts1;
367 if (!in_struct(&ts1, &ikev2_ts1_desc, &ts_pd->pbs, &addr))
368 return false0;
369
370 const struct ip_info *ipv;
371 switch (ts1.isat1_type) {
372 case IKEv2_TS_IPV4_ADDR_RANGE:
373 ts->ts_type = IKEv2_TS_IPV4_ADDR_RANGE;
374 ipv = &ipv4_info;
375 break;
376 case IKEv2_TS_IPV6_ADDR_RANGE:
377 ts->ts_type = IKEv2_TS_IPV6_ADDR_RANGE;
378 ipv = &ipv6_info;
379 break;
380 default:
381 return false0;
382 }
383
384 if (!pbs_in_address(&ts->net.start, ipv, &addr, "TS low")) {
385 return false0;
386 }
387 if (!pbs_in_address(&ts->net.end, ipv, &addr, "TS high")) {
388 return false0;
389 }
390 /* XXX: does this matter? */
391 if (pbs_left(&addr)((size_t)((&addr)->roof - (&addr)->cur)) != 0)
392 return false0;
393
394 ts->ipprotoid = ts1.isat1_ipprotoid;
395
396 ts->startport = ts1.isat1_startport;
397 ts->endport = ts1.isat1_endport;
398 if (ts->startport > ts->endport) {
399 libreswan_log("%s traffic selector %d has an invalid port range",loglog(RC_LOG, "%s traffic selector %d has an invalid port range"
, which, tss->nr)
400 which, tss->nr)loglog(RC_LOG, "%s traffic selector %d has an invalid port range"
, which, tss->nr)
;
401 return false0;
402 }
403 }
404
405 dbg("%s: parsed %d traffic selectors", which, tss->nr){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: parsed %d traffic selectors", which, tss->
nr); } }
;
406 return true1;
407}
408
409static bool_Bool v2_parse_tss(const struct msg_digest *md,
410 struct traffic_selectors *tsi,
411 struct traffic_selectors *tsr)
412{
413 if (!v2_parse_ts(md->chain[ISAKMP_NEXT_v2TSi], tsi, "TSi")) {
414 return false0;
415 }
416
417 if (!v2_parse_ts(md->chain[ISAKMP_NEXT_v2TSr], tsr, "TSr")) {
418 return false0;
419 }
420
421 return true1;
422}
423
424#define MATCH_PREFIX" " " "
425
426/*
427 * Check if our policy's protocol (proto) matches the Traffic Selector
428 * protocol (ts_proto).
429 */
430
431static int narrow_protocol(const struct end *end,
432 const struct traffic_selectors *tss,
433 enum fit fit,
434 const char *which, unsigned index)
435{
436 const struct traffic_selector *ts = &tss->ts[index];
437 int protocol = -1;
438
439 switch (fit) {
440 case END_EQUALS_TS:
441 if (end->protocol == ts->ipprotoid) {
442 protocol = end->protocol;
443 }
444 break;
445 case END_NARROWER_THAN_TS:
446 if (ts->ipprotoid == 0 /* wild-card */ ||
447 ts->ipprotoid == end->protocol) {
448 protocol = end->protocol;
449 }
450 break;
451 case END_WIDER_THAN_TS:
452 if (end->protocol == 0 /* wild-card */ ||
453 end->protocol == ts->ipprotoid) {
454 protocol = ts->ipprotoid;
455 }
456 break;
457 default:
458 bad_case(fit)libreswan_bad_case("fit", (fit), (where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 458})
;
459 }
460 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), which, index, ts->ipprotoid == 0 ? "*" : "", ts->
ipprotoid, protocol); } }
461 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), which, index, ts->ipprotoid == 0 ? "*" : "", ts->
ipprotoid, protocol); } }
462 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), which, index, ts->ipprotoid == 0 ? "*" : "", ts->
ipprotoid, protocol); } }
463 which, 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), which, index, ts->ipprotoid == 0 ? "*" : "", ts->
ipprotoid, protocol); } }
464 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), which, index, ts->ipprotoid == 0 ? "*" : "", ts->
ipprotoid, protocol); } }
;
465 return protocol;
466}
467
468static int score_narrow_protocol(const struct end *end,
469 const struct traffic_selectors *tss,
470 enum fit fit,
471 const char *which, unsigned index)
472{
473 int f; /* strength of match */
474
475 int protocol = narrow_protocol(end, tss, fit, which, index);
476 if (protocol == 0) {
477 f = 255; /* ??? odd value */
478 } else if (protocol > 0) {
479 f = 1;
480 } else {
481 f = 0;
482 }
483 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_debug_stream
(buf), buf = ((void*)0))
{
484 const struct traffic_selector *ts = &tss->ts[index];
485 jam(buf, MATCH_PREFIX" " "match end->protocol=%s%d %s %s[%u].ipprotoid=%s%d: ",
486 end->protocol == 0 ? "*" : "", end->protocol,
487 fit_string(fit),
488 which, index, ts->ipprotoid == 0 ? "*" : "", ts->ipprotoid);
489 if (f > 0) {
490 jam(buf, "YES fitness %d", f);
491 } else {
492 jam(buf, "NO");
493 }
494 }
495 return f;
496}
497
498/*
499 * Narrow the END/TS ports according to FIT.
500 *
501 * Returns 0 (all ports), a specific port number, or -1 (no luck).
502 *
503 * Since 'struct end' only describes all-ports or a single port; only
504 * narrow to that.
505 */
506
507static int narrow_port(const struct end *end,
508 const struct traffic_selectors *tss,
509 enum fit fit,
510 const char *which, unsigned index)
511{
512 passert(index < tss->nr){ _Bool assertion__ = index < tss->nr; if (!assertion__
) { lsw_passert_fail((where_t) { .func = __func__, .basename =
"ikev2_ts.c" , .line = 512}, "%s", "index < tss->nr");
} }
;
513 const struct traffic_selector *ts = &tss->ts[index];
514
515 int end_low = end->port;
516 int end_high = end->port == 0 ? 65535 : end->port;
517 int port = -1;
518
519 switch (fit) {
520 case END_EQUALS_TS:
521 if (end_low == ts->startport && ts->endport == end_high) {
522 /* end=ts=0-65535 || end=ts=N-N */
523 port = end_low;
524 }
525 break;
526 case END_NARROWER_THAN_TS:
527 if (ts->startport <= end_low && end_high <= ts->endport) {
528 /* end=ts=0-65535 || ts=N<=end<=M */
529 port = end_low;
530 }
531 break;
532 case END_WIDER_THAN_TS:
533 if (end_low < ts->startport && ts->endport < end_high &&
534 ts->startport == ts->endport) {
535 /*ts=0<N-N<65535*/
536 port = ts->startport;
537 } else if (end_low == ts->startport && ts->endport == end_high) {
538 /* end=ts=0-65535 || end=ts=N-N */
539 port = ts->startport;
540 }
541 break;
542 default:
543 bad_case(fit)libreswan_bad_case("fit", (fit), (where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 543})
;
544 }
545 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), which, index, ts->startport
, ts->endport, port); } }
546 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), which, index, ts->startport
, ts->endport, port); } }
547 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), which, index, ts->startport
, ts->endport, port); } }
548 which, 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), which, index, ts->startport
, ts->endport, port); } }
549 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), which, index, ts->startport
, ts->endport, port); } }
;
550 return port;
551}
552
553/*
554 * Assign a score to the narrowed port, rationale for score lost in
555 * time?
556 */
557
558static int score_narrow_port(const struct end *end,
559 const struct traffic_selectors *tss,
560 enum fit fit,
561 const char *which, unsigned index)
562{
563 int f; /* strength of match */
564
565 int port = narrow_port(end, tss, fit, which, index);
566 if (port > 0) {
567 f = 1;
568 } else if (port == 0) {
569 f = 65536; /* from 1 + 65535-0 */
570 } else {
571 f = 0;
572 }
573 if (f > 0) {
574 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"
, which, index, f); } }
575 which, index, f){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: YES fitness %d"
, which, index, f); } }
;
576 } else {
577 dbg(MATCH_PREFIX " %s[%u] port match: NO",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: NO", which, index
); } }
578 which, index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" " " %s[%u] port match: NO", which, index
); } }
;
579 }
580 return f;
581}
582
583/*
584 * Does TS fit inside of END?
585 *
586 * Given other code flips the comparison depending initiator or
587 * responder, is this right?
588 *
589 * NOTE: Our parser/config only allows 1 CIDR, however IKEv2 ranges
590 * can be non-CIDR for now we really support/limit ourselves to
591 * a single CIDR
592 *
593 * XXX: what exactly is CIDR?
594 */
595
596static int score_address_range(const struct end *end,
597 const struct traffic_selectors *tss,
598 enum fit fit,
599 const char *which, unsigned index)
600{
601 const struct traffic_selector *ts = &tss->ts[index];
602 /*
603 * Pre-compute possible fit --- sum of bits gives how good a
604 * fit this is.
605 */
606 int ts_range = iprange_bits(ts->net.start, ts->net.end);
607 int maskbits = end->client.maskbits;
608 int fitbits = maskbits + ts_range;
609
610 int f = 0;
611
612 /*
613 * NOTE: Our parser/config only allows 1 CIDR, however IKEv2
614 * ranges can be non-CIDR for now we really
615 * support/limit ourselves to a single CIDR
616 *
617 * XXX: so what is CIDR?
618 */
619 ip_range range = range_from_subnet(&end->client);
620 passert(addrcmp(&range.start, &range.end) <= 0){ _Bool assertion__ = addrcmp(&range.start, &range.end
) <= 0; if (!assertion__) { lsw_passert_fail((where_t) { .
func = __func__, .basename = "ikev2_ts.c" , .line = 620}, "%s"
, "addrcmp(&range.start, &range.end) <= 0"); } }
;
621 passert(addrcmp(&ts->net.start, &ts->net.end) <= 0){ _Bool assertion__ = addrcmp(&ts->net.start, &ts->
net.end) <= 0; if (!assertion__) { lsw_passert_fail((where_t
) { .func = __func__, .basename = "ikev2_ts.c" , .line = 621}
, "%s", "addrcmp(&ts->net.start, &ts->net.end) <= 0"
); } }
;
622 switch (fit) {
623 case END_EQUALS_TS:
624 if (addrcmp(&range.start, &ts->net.start) == 0 &&
625 addrcmp(&range.end, &ts->net.end) == 0) {
626 f = fitbits;
627 }
628 break;
629 case END_NARROWER_THAN_TS:
630 if (addrcmp(&range.start, &ts->net.start) >= 0 &&
631 addrcmp(&range.end, &ts->net.end) <= 0) {
632 f = fitbits;
633 }
634 break;
635 case END_WIDER_THAN_TS:
636 if (addrcmp(&range.start, &ts->net.start) <= 0 &&
637 addrcmp(&range.end, &ts->net.end) >= 0) {
638 f = fitbits;
639 }
640 break;
641 default:
642 bad_case(fit)libreswan_bad_case("fit", (fit), (where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 642})
;
643 }
644
645 /*
646 * comparing for ports for finding better local policy
647 *
648 * XXX: why do this?
649 */
650 /* ??? arbitrary modification to objective function */
651 if (end->port != 0 &&
652 ts->startport == end->port &&
653 ts->endport == end->port)
654 f = f << 1;
655
656 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_debug_stream
(buf), buf = ((void*)0))
{
657 jam(buf, MATCH_PREFIX" " "match address end->client=");
658 jam_subnet(buf, &end->client);
659 jam(buf, " %s %s[%u]net=", fit_string(fit), which, index);
660 jam_range(buf, &ts->net);
661 jam(buf, ": ");
662 if (f > 0) {
663 jam(buf, "YES fitness %d", f);
664 } else {
665 jam(buf, "NO");
666 }
667 }
668 return f;
669}
670
671struct score {
672 bool_Bool ok;
673 int address;
674 int port;
675 int protocol;
676};
677
678static struct score score_end(const struct end *end,
679 const struct traffic_selectors *tss,
680 enum fit fit,
681 const char *what, unsigned index)
682{
683 const struct traffic_selector *ts = &tss->ts[index];
684 range_buf ts_net;
685 dbg(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
686 what, index,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
687 str_range(&ts->net, &ts_net),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
688 ts->ipprotoid,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
689 ts->startport,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
690 ts->endport){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" %s[%u] .net=%s .iporotoid=%d .{start,end}port=%d..%d"
, what, index, str_range(&ts->net, &ts_net), ts->
ipprotoid, ts->startport, ts->endport); } }
;
691
692 struct score score = { .ok = false0, };
693 score.address = score_address_range(end, tss, fit, what, index);
694 if (score.address <= 0) {
695 return score;
696 }
697 score.port = score_narrow_port(end, tss, fit, what, index);
698 if (score.port <= 0) {
699 return score;
700 }
701 score.protocol = score_narrow_protocol(end, tss, fit, what, index);
702 if (score.protocol <= 0) {
703 return score;
704 }
705 score.ok = true1;
706 return score;
707}
708
709struct best_score {
710 bool_Bool ok;
711 int address;
712 int port;
713 int protocol;
714 const struct traffic_selector *tsi;
715 const struct traffic_selector *tsr;
716};
717#define NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, } { .ok = false0, .address = -1, .port = -1, .protocol = -1, }
718
719static bool_Bool score_gt(const struct best_score *score, const struct best_score *best)
720{
721 return (score->address > best->address ||
722 (score->address == best->address &&
723 score->port > best->port) ||
724 (score->address == best->address &&
725 score->port == best->port &&
726 score->protocol > best->protocol));
727}
728
729static struct best_score score_ends(enum fit fit,
730 const struct connection *d,
731 const struct ends *ends,
732 const struct traffic_selectors *tsi,
733 const struct traffic_selectors *tsr)
734{
735 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
736 selector_buf ei3;
737 selector_buf er3;
738 connection_buf cib;
739 DBG_log("evaluating our conn="PRI_CONNECTION"\"%s\"%s"" I=%s:%d/%d R=%s:%d/%d%s to their:",
740 pri_connection(d, &cib)(d)->name, str_connection_instance(d, &cib),
741 str_selector(&ends->i->client, &ei3), ends->i->protocol, ends->i->port,
742 str_selector(&ends->r->client, &er3), ends->r->protocol, ends->r->port,
743 is_virtual_connection(d) ? " (virt)" : "");
744 }
745
746 struct best_score best_score = NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, };
747
748 /* compare tsi/r array to this/that, evaluating how well it fits */
749 for (unsigned tsi_n = 0; tsi_n < tsi->nr; tsi_n++) {
750 const struct traffic_selector *tni = &tsi->ts[tsi_n];
751
752 /* choice hardwired! */
753 struct score score_i = score_end(ends->i, tsi, fit, "TSi", tsi_n);
754 if (!score_i.ok) {
755 continue;
756 }
757
758 for (unsigned tsr_n = 0; tsr_n < tsr->nr; tsr_n++) {
759 const struct traffic_selector *tnr = &tsr->ts[tsr_n];
760
761 struct score score_r = score_end(ends->r, tsr, fit, "TSr", tsr_n);
762 if (!score_r.ok) {
763 continue;
764 }
765
766 struct best_score score = {
767 .ok = true1,
768 /* ??? this objective function is odd and arbitrary */
769 .address = (score_i.address << 8) + score_r.address,
770 /* ??? arbitrary objective function */
771 .port = score_i.port + score_r.port,
772 /* ??? arbitrary objective function */
773 .protocol = score_i.protocol + score_r.protocol,
774 /* which one */
775 .tsi = tni, .tsr = tnr,
776 };
777
778 /* score >= best_score? */
779 if (score_gt(&score, &best_score)) {
780 best_score = score;
781 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
); } }
782 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
); } }
;
783 }
784 }
785 }
786
787 return best_score;
788}
789
790/*
791 * find the best connection and, if it is AUTH exchange, create the
792 * child state
793 *
794 * XXX: creating child as a side effect is pretty messed up.
795 */
796bool_Bool v2_process_ts_request(struct child_sa *child,
797 const struct msg_digest *md)
798{
799 passert(v2_msg_role(md) == MESSAGE_REQUEST){ _Bool assertion__ = v2_msg_role(md) == MESSAGE_REQUEST; if (
!assertion__) { lsw_passert_fail((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 799}, "%s", "v2_msg_role(md) == MESSAGE_REQUEST"
); } }
;
1
Assuming the condition is true
2
Taking false branch
800 passert(child->sa.st_sa_role == SA_RESPONDER){ _Bool assertion__ = child->sa.st_sa_role == SA_RESPONDER
; if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 800}, "%s", "child->sa.st_sa_role == SA_RESPONDER"
); } }
;
3
Assuming the condition is true
4
Taking false branch
801
802 /*
803 * XXX: md->st here is parent???? Lets find out.
804 */
805 if (md->st == &child->sa) {
5
Taking false branch
806 dbg("Child SA TS Request has child->sa == md->st; so using child connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Child SA TS Request has child->sa == md->st; so using child connection"
); } }
;
807 } else if (md->st == &ike_sa(&child->sa, HERE(where_t) { .func = __func__, .basename = "ikev2_ts.c" , .line
= 807}
)->sa) {
6
Taking false branch
808 dbg("Child SA TS Request has ike->sa == md->st; so using parent connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Child SA TS Request has ike->sa == md->st; so using parent connection"
); } }
;
809 } else {
810 dbg("Child SA TS Request has an unknown md->st; so using unknown connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Child SA TS Request has an unknown md->st; so using unknown connection"
); } }
;
7
Assuming the condition is false
8
Taking false branch
811 }
812 struct connection *c = md->st->st_connection;
813
814 struct traffic_selectors tsi = { .nr = 0, };
815 struct traffic_selectors tsr = { .nr = 0, };
816 if (!v2_parse_tss(md, &tsi, &tsr)) {
9
Taking false branch
817 return false0;
818 }
819
820 /* best so far; start with state's connection */
821 struct best_score best_score = NO_SCORE{ .ok = 0, .address = -1, .port = -1, .protocol = -1, };
822 const struct spd_route *best_spd_route = NULL((void*)0);
823 struct connection *best_connection = c;
824
825 /* find best spd in c */
826
827 dbg("looking for best SPD in current connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("looking for best SPD in current connection");
} }
;
10
Assuming the condition is false
11
Taking false branch
828 for (const struct spd_route *sra = &c->spd; sra != NULL((void*)0); sra = sra->spd_next) {
12
Assuming 'sra' is not equal to NULL
13
Loop condition is true. Entering loop body
18
Assuming 'sra' is equal to NULL
19
Loop condition is false. Execution continues on line 865
829
830 /* responder */
831 const struct ends ends = {
832 .i = &sra->that,
833 .r = &sra->this,
834 };
835 enum fit responder_fit =
836 (c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
14
Assuming the condition is false
15
'?' condition is false
837 ? END_NARROWER_THAN_TS
838 : END_EQUALS_TS;
839
840 struct best_score score = score_ends(responder_fit, c, &ends, &tsi, &tsr);
841 if (!score.ok) {
16
Taking true branch
842 continue;
17
Execution continues on line 828
843 }
844 if (score_gt(&score, &best_score)) {
845 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 - tsi.ts, score.tsr - tsr.ts); } }
846 score.tsi - tsi.ts, score.tsr - tsr.ts){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" found better spd route for TSi[%td],TSr[%td]"
, score.tsi - tsi.ts, score.tsr - tsr.ts); } }
;
847 best_score = score;
848 best_spd_route = sra;
849 passert(best_connection == c){ _Bool assertion__ = best_connection == c; if (!assertion__)
{ lsw_passert_fail((where_t) { .func = __func__, .basename =
"ikev2_ts.c" , .line = 849}, "%s", "best_connection == c"); }
}
;
850 }
851 }
852
853 /*
854 * ??? the use of hp looks nonsensical.
855 * Either the first non-empty host_pair should be used
856 * (like the current code) and the following should
857 * be broken into two loops: first find the non-empty
858 * host_pair list, second look through the host_pair list.
859 * OR
860 * what's really meant is look at the host_pair for
861 * each sra, something that matches the current
862 * nested loop structure but not what it actually does.
863 */
864
865 dbg("looking for better host pair"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("looking for better host pair"); } }
;
20
Taking false branch
866 const struct host_pair *hp = NULL((void*)0);
867 for (const struct spd_route *sra = &c->spd;
21
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 949
868 hp == NULL((void*)0) && sra != NULL((void*)0); sra = sra->spd_next) {
869 hp = find_host_pair(&sra->this.host_addr,
870 &sra->that.host_addr);
871
872 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
22
Assuming the condition is true
23
Taking true branch
873 selector_buf s2;
874 selector_buf d2;
875 DBG_log(" checking hostpair %s -> %s is %s",
876 str_selector(&sra->this.client, &s2),
877 str_selector(&sra->that.client, &d2),
878 hp == NULL((void*)0) ? "not found" : "found");
24
Assuming 'hp' is equal to NULL
25
'?' condition is true
879 }
880
881 if (hp == NULL((void*)0))
26
Taking true branch
882 continue;
27
Execution continues on line 868
883
884 for (struct connection *d = hp->connections;
885 d != NULL((void*)0); d = d->hp_next) {
886 /* groups are templates instantiated as GROUPINSTANCE */
887 if (d->policy & POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX))) {
888 continue;
889 }
890 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); } }
;
891
892 /*
893 * ??? same_id && match_id seems redundant.
894 * if d->spd.this.id.kind == ID_NONE, both TRUE
895 * else if c->spd.this.id.kind == ID_NONE,
896 * same_id treats it as a wildcard and match_id
897 * does not. Odd.
898 * else if kinds differ, match_id FALSE
899 * else if kind ID_DER_ASN1_DN, wildcards are forbidden by same_id
900 * else match_id just calls same_id.
901 * So: if wildcards are desired, just use match_id.
902 * If they are not, just use same_id
903 */
904 int wildcards; /* value ignored */
905 int pathlen; /* value ignored */
906 if (!(same_id(&c->spd.this.id,
907 &d->spd.this.id) &&
908 match_id(&c->spd.that.id,
909 &d->spd.that.id, &wildcards) &&
910 trusted_ca_nss(c->spd.that.ca,
911 d->spd.that.ca, &pathlen))) {
912 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); } }
913 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); } }
;
914 continue;
915 }
916
917 const struct spd_route *sr;
918
919 for (sr = &d->spd; sr != NULL((void*)0); sr = sr->spd_next) {
920
921 /* responder */
922 const struct ends ends = {
923 .i = &sr->that,
924 .r = &sr->this,
925 };
926 /* responder -- note D! */
927 enum fit responder_fit =
928 (d->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
929 ? END_NARROWER_THAN_TS
930 : END_EQUALS_TS;
931
932 struct best_score score = score_ends(responder_fit, d/*note D*/,
933 &ends, &tsi, &tsr);
934 if (!score.ok) {
935 continue;
936 }
937 if (score_gt(&score, &best_score)) {
938 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 - tsi.ts, score.tsr - tsr.ts); } }
939 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 - tsi.ts, score.tsr - tsr.ts); } }
940 score.tsi - tsi.ts, score.tsr - tsr.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 - tsi.ts, score.tsr - tsr.ts); } }
;
941 best_connection = d;
942 best_score = score;
943 best_spd_route = sr;
944 }
945 }
946 }
947 }
948
949 if (best_connection == c) {
29
Taking true branch
950 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"
); } }
;
30
Assuming the condition is true
31
Taking true branch
951 }
952
953#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)) | \
954 POLICY_DONT_REKEY((lset_t)1 << (POLICY_DONT_REKEY_IX)) | \
955 POLICY_REAUTH((lset_t)1 << (POLICY_REAUTH_IX)) | \
956 POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)) | \
957 POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX)) | \
958 POLICY_GROUTED((lset_t)1 << (POLICY_GROUTED_IX)) | \
959 POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | \
960 POLICY_UP((lset_t)1 << (POLICY_UP_IX)) | \
961 POLICY_XAUTH((lset_t)1 << (POLICY_XAUTH_IX)) | \
962 POLICY_MODECFG_PULL((lset_t)1 << (POLICY_MODECFG_PULL_IX)) | \
963 POLICY_AGGRESSIVE((lset_t)1 << (POLICY_AGGRESSIVE_IX)) | \
964 POLICY_OVERLAPIP((lset_t)1 << (POLICY_OVERLAPIP_IX)) | \
965 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
966
967 /*
968 * Try instantiating something better.
969 */
970 if (best_spd_route == NULL((void*)0) && c->kind != CK_INSTANCE) {
32
Assuming the condition is false
33
Taking false branch
971 /*
972 * Don't try to look for something else to
973 * 'instantiate' when the current connection is
974 * permanent.
975 *
976 * XXX: Is this missing an opportunity? Could there
977 * be a better connection to instantiate when the
978 * current one is permanent?
979 *
980 * XXX: 'instantiate', not really? The code below
981 * blats the current instance with new values -
982 * something that should not be done to a permanent
983 * connection.
984 */
985 pexpect(c->kind == CK_PERMANENT)({ _Bool assertion__ = c->kind == CK_PERMANENT; if (!assertion__
) { log_pexpect((where_t) { .func = __func__, .basename = "ikev2_ts.c"
, .line = 985}, "%s", "c->kind == CK_PERMANENT"); } assertion__
; })
;
986 dbg("no best spd route; but the current %s connection \"%s\" is not a CK_INSTANCE",{ 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"
, enum_name(&connection_kind_names, c->kind), c->name
); } }
987 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"
, enum_name(&connection_kind_names, c->kind), c->name
); } }
;
988 } else if (best_spd_route == NULL((void*)0) &&
989 ((c->policy & POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX))) ||
34
Assuming the condition is true
990 c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))) {
991 /*
992 * Is there something better than the current
993 * connection?
994 *
995 * Rather than overwrite the current INSTANCE; would
996 * it be better to instantiate a new instance, and
997 * then replace it? Would also address the above.
998 */
999 pexpect(c->kind == CK_INSTANCE)({ _Bool assertion__ = c->kind == CK_INSTANCE; if (!assertion__
) { log_pexpect((where_t) { .func = __func__, .basename = "ikev2_ts.c"
, .line = 999}, "%s", "c->kind == CK_INSTANCE"); } assertion__
; })
;
35
Taking false branch
1000 /* since an SPD_ROUTE wasn't found */
1001 passert(best_connection == c){ _Bool assertion__ = best_connection == c; if (!assertion__)
{ lsw_passert_fail((where_t) { .func = __func__, .basename =
"ikev2_ts.c" , .line = 1001}, "%s", "best_connection == c");
} }
;
36
Taking false branch
1002 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"
); } }
;
37
Assuming the condition is true
38
Taking true branch
1003
1004 dbg("FOR_EACH_CONNECTION_... in %s", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_CONNECTION_... in %s", __func__); } }
;
39
Assuming the condition is true
40
Taking true branch
1005 for (struct connection *t = connections; t != NULL((void*)0); t = t->ac_next) {
41
Assuming 't' is not equal to NULL
42
Loop condition is true. Entering loop body
1006 /* require a template */
1007 if (t->kind != CK_TEMPLATE) {
43
Assuming the condition is false
44
Taking false branch
1008 continue;
1009 }
1010 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_debug_stream
(buf), buf = ((void*)0))
{
45
Loop condition is true. Entering loop body
46
Loop condition is true. Entering loop body
47
Loop condition is true. Entering loop body
48
Loop condition is true. Entering loop body
51
Loop condition is false. Execution continues on line 1010
52
Loop condition is false. Execution continues on line 1010
53
Loop condition is false. Execution continues on line 1010
54
Loop condition is false. Execution continues on line 1026
1011 jam(buf, " investigating template \"%s\";",
1012 t->name);
1013 if (t->foodgroup != NULL((void*)0)) {
49
Assuming pointer value is null
50
Taking false branch
1014 jam(buf, " food-group=\"%s\"", t->foodgroup);
1015 }
1016 jam(buf, " policy=%s", prettypolicy(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)))
));
1017 }
1018
1019 /*
1020 * Is it worth looking at the template.
1021 *
1022 * XXX: treat the combination the same as
1023 * group instance, like the old code did; is
1024 * this valid?
1025 */
1026 switch (c->policy & (POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) |
55
Control jumps to 'case 17246978048:' at line 1029
1027 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))) {
1028 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)):
1029 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)): /* XXX: true */
1030 /* XXX: why does this matter; does it imply t->foodgroup != NULL? */
1031 if (!LIN(POLICY_GROUPINSTANCE, t->policy)(((((lset_t)1 << (POLICY_GROUPINSTANCE_IX))) & (t->
policy)) == (((lset_t)1 << (POLICY_GROUPINSTANCE_IX))))
) {
56
Assuming the condition is true
57
Taking false branch
1032 dbg(" skipping; not a group instance"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; not a group instance"); } }
;
1033 continue;
1034 }
1035 /* when OE, don't change food groups? */
1036 if (!streq(c->foodgroup, t->foodgroup)(strcmp((c->foodgroup), (t->foodgroup)) == 0)) {
58
Null pointer passed as an argument to a 'nonnull' parameter
1037 dbg(" skipping; wrong foodgroup name"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; wrong foodgroup name"); } }
;
1038 continue;
1039 }
1040 /* ??? why require current connection->name and t->name to be different */
1041 /* XXX: don't re-instantiate the same connection template???? */
1042 if (streq(c->name, t->name)(strcmp((c->name), (t->name)) == 0)) {
1043 dbg(" skipping; name same as current connection"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; name same as current connection"
); } }
;
1044 continue;
1045 }
1046 break;
1047 case POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)):
1048 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
))))
) {
1049 dbg(" skipping; cannot narrow"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; cannot narrow"); } }
;
1050 continue;
1051 }
1052 break;
1053 default:
1054 bad_case(c->policy)libreswan_bad_case("c->policy", (c->policy), (where_t) {
.func = __func__, .basename = "ikev2_ts.c" , .line = 1054})
; /* not quite true */
1055 }
1056
1057 /* require initiator's subnet <= T; why? */
1058 if (!subnetinsubnet(&c->spd.that.client, &t->spd.that.client)) {
1059 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"
); } }
;
1060 continue;
1061 }
1062 /* require responder address match; why? */
1063 if (!sameaddr(&c->spd.this.client.addr, &t->spd.this.client.addr)) {
1064 dbg(" skipping; responder addresses don't match"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; responder addresses don't match"
); } }
;
1065 continue;
1066 }
1067
1068 /* require a valid narrowed port? */
1069 enum fit fit;
1070 switch (c->policy & (POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) |
1071 POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))) {
1072 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)):
1073 case POLICY_GROUPINSTANCE((lset_t)1 << (POLICY_GROUPINSTANCE_IX)) | POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)): /* XXX: true */
1074 /* exact match; XXX: 'cos that is what old code did */
1075 fit = END_EQUALS_TS;
1076 break;
1077 case POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)):
1078 /* narrow END's port to TS port */
1079 fit = END_WIDER_THAN_TS;
1080 break;
1081 default:
1082 bad_case(c->policy)libreswan_bad_case("c->policy", (c->policy), (where_t) {
.func = __func__, .basename = "ikev2_ts.c" , .line = 1082})
;
1083 }
1084
1085 passert(tsi.nr >= 1){ _Bool assertion__ = tsi.nr >= 1; if (!assertion__) { lsw_passert_fail
((where_t) { .func = __func__, .basename = "ikev2_ts.c" , .line
= 1085}, "%s", "tsi.nr >= 1"); } }
;
1086 int tsi_port = narrow_port(&t->spd.that, &tsi,
1087 fit, "TSi", 0);
1088 if (tsi_port < 0) {
1089 dbg(" skipping; TSi port too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSi port too wide"); } }
;
1090 continue;
1091 }
1092 int tsi_protocol = narrow_protocol(&t->spd.that, &tsi,
1093 fit, "TSi", 0);
1094 if (tsi_protocol < 0) {
1095 dbg(" skipping; TSi protocol too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSi protocol too wide"); } }
;
1096 continue;
1097 }
1098
1099 passert(tsr.nr >= 1){ _Bool assertion__ = tsr.nr >= 1; if (!assertion__) { lsw_passert_fail
((where_t) { .func = __func__, .basename = "ikev2_ts.c" , .line
= 1099}, "%s", "tsr.nr >= 1"); } }
;
1100 int tsr_port = narrow_port(&t->spd.this, &tsr,
1101 fit, "TRi", 0);
1102 if (tsr_port < 0) {
1103 dbg(" skipping; TSr port too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSr port too wide"); } }
;
1104 continue;
1105 }
1106 int tsr_protocol = narrow_protocol(&t->spd.this, &tsr,
1107 fit, "TSr", 0);
1108 if (tsr_protocol < 0) {
1109 dbg(" skipping; TSr protocol too wide"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" skipping; TSr protocol too wide"); } }
;
1110 continue;
1111 }
1112
1113 passert(best_connection == c){ _Bool assertion__ = best_connection == c; if (!assertion__)
{ lsw_passert_fail((where_t) { .func = __func__, .basename =
"ikev2_ts.c" , .line = 1113}, "%s", "best_connection == c");
} }
; /* aka st->st_connection, no leak */
1114
1115 bool_Bool shared = v2_child_connection_probably_shared(child);
1116 if (shared) {
1117 /* instantiate it, filling in peer's ID */
1118 best_connection = instantiate(t, &c->spd.that.host_addr,
1119 NULL((void*)0));
1120 }
1121
1122 /* "this" == responder; see function name */
1123 best_connection->spd.this.port = tsr_port;
1124 best_connection->spd.that.port = tsi_port;
1125 best_connection->spd.this.protocol = tsr_protocol;
1126 best_connection->spd.that.protocol = tsi_protocol;
1127 best_spd_route = &best_connection->spd;
1128
1129 if (shared) {
1130 char old[CONN_INST_BUF(2 + 10 + 1 + sizeof(subnet_buf) + 7 + sizeof(address_reversed_buf
) + 3 + sizeof(subnet_buf) + 1 + 1)
];
1131 char new[CONN_INST_BUF(2 + 10 + 1 + sizeof(subnet_buf) + 7 + sizeof(address_reversed_buf
) + 3 + sizeof(subnet_buf) + 1 + 1)
];
1132 dbg("switching from \"%s\"%s to \"%s\"%s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("switching from \"%s\"%s to \"%s\"%s", c->name
, fmt_conn_instance(c, old), best_connection->name, fmt_conn_instance
(best_connection, new)); } }
1133 c->name, fmt_conn_instance(c, old),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("switching from \"%s\"%s to \"%s\"%s", c->name
, fmt_conn_instance(c, old), best_connection->name, fmt_conn_instance
(best_connection, new)); } }
1134 best_connection->name, fmt_conn_instance(best_connection, new)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("switching from \"%s\"%s to \"%s\"%s", c->name
, fmt_conn_instance(c, old), best_connection->name, fmt_conn_instance
(best_connection, new)); } }
;
1135 } else {
1136 char cib[CONN_INST_BUF(2 + 10 + 1 + sizeof(subnet_buf) + 7 + sizeof(address_reversed_buf
) + 3 + sizeof(subnet_buf) + 1 + 1)
];
1137 dbg(" overwrote connection with instance %s%s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" overwrote connection with instance %s%s", best_connection
->name, fmt_conn_instance(best_connection, cib)); } }
1138 best_connection->name, fmt_conn_instance(best_connection, cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log(" overwrote connection with instance %s%s", best_connection
->name, fmt_conn_instance(best_connection, cib)); } }
;
1139 }
1140 break;
1141 }
1142 }
1143
1144 if (best_spd_route == NULL((void*)0)) {
1145 dbg("giving up"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("giving up"); } }
;
1146 return false0;
1147 }
1148
1149 /*
1150 * this both replaces the child's connection, and flips any
1151 * underlying current-connection
1152 *
1153 * XXX: but this is responder code, there probably isn't a
1154 * current-connection - it would have gone straight to current
1155 * state.
1156 *
1157 * XXX: ah, but the state code does: set-state; set-connection
1158 * (yes order is wrong). Why does it bother?
1159 *
1160 * update_state_connection(), if the connection changes,
1161 * de-references the old connection; which is what really
1162 * matters
1163 */
1164 update_state_connection(&child->sa, best_connection);
1165
1166 child->sa.st_ts_this = ikev2_end_to_ts(&best_spd_route->this);
1167 child->sa.st_ts_that = ikev2_end_to_ts(&best_spd_route->that);
1168
1169 ikev2_print_ts(&child->sa.st_ts_this);
1170 ikev2_print_ts(&child->sa.st_ts_that);
1171
1172 return true1;
1173}
1174
1175/* check TS payloads, response */
1176bool_Bool v2_process_ts_response(struct child_sa *child,
1177 struct msg_digest *md)
1178{
1179 passert(child->sa.st_sa_role == SA_INITIATOR){ _Bool assertion__ = child->sa.st_sa_role == SA_INITIATOR
; if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 1179}, "%s", "child->sa.st_sa_role == SA_INITIATOR"
); } }
;
1180 passert(v2_msg_role(md) == MESSAGE_RESPONSE){ _Bool assertion__ = v2_msg_role(md) == MESSAGE_RESPONSE; if
(!assertion__) { lsw_passert_fail((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 1180}, "%s", "v2_msg_role(md) == MESSAGE_RESPONSE"
); } }
;
1181
1182 struct connection *c = child->sa.st_connection;
1183
1184 struct traffic_selectors tsi = { .nr = 0, };
1185 struct traffic_selectors tsr = { .nr = 0, };
1186 if (!v2_parse_tss(md, &tsi, &tsr)) {
1187 return false0;
1188 }
1189
1190 /* initiator */
1191 const struct spd_route *sra = &c->spd;
1192 const struct ends e = {
1193 .i = &sra->this,
1194 .r = &sra->that,
1195 };
1196 enum fit initiator_widening =
1197 (c->policy & POLICY_IKEV2_ALLOW_NARROWING((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX)))
1198 ? END_WIDER_THAN_TS
1199 : END_EQUALS_TS;
1200
1201 struct best_score best = score_ends(initiator_widening, c, &e, &tsi, &tsr);
1202
1203 if (!best.ok) {
1204 dbg("reject responder TSi/TSr Traffic Selector"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("reject responder TSi/TSr Traffic Selector"); }
}
;
1205 /* prevents parent from going to I3 */
1206 return false0;
1207 }
1208
1209 dbg("found an acceptable TSi/TSr Traffic Selector"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("found an acceptable TSi/TSr Traffic Selector"
); } }
;
1210 struct state *st = &child->sa;
1211 memcpy(&st->st_ts_this, best.tsi,
1212 sizeof(struct traffic_selector));
1213 memcpy(&st->st_ts_that, best.tsr,
1214 sizeof(struct traffic_selector));
1215 ikev2_print_ts(&st->st_ts_this);
1216 ikev2_print_ts(&st->st_ts_that);
1217
1218 ip_subnet tmp_subnet_i;
1219 ip_subnet tmp_subnet_r;
1220 rangetosubnet(&st->st_ts_this.net.start,
1221 &st->st_ts_this.net.end, &tmp_subnet_i);
1222 rangetosubnet(&st->st_ts_that.net.start,
1223 &st->st_ts_that.net.end, &tmp_subnet_r);
1224
1225 c->spd.this.client = tmp_subnet_i;
1226 c->spd.this.port = st->st_ts_this.startport;
1227 c->spd.this.protocol = st->st_ts_this.ipprotoid;
1228 setportof(htons(c->spd.this.port),{ *(&c->spd.this.client.addr) = set_endpoint_hport((&
c->spd.this.client.addr), ntohs(htons(c->spd.this.port)
)); }
1229 &c->spd.this.client.addr){ *(&c->spd.this.client.addr) = set_endpoint_hport((&
c->spd.this.client.addr), ntohs(htons(c->spd.this.port)
)); }
;
1230
1231 c->spd.this.has_client =
1232 !(subnetishost(&c->spd.this.client) &&
1233 addrinsubnet(&c->spd.this.host_addr,
1234 &c->spd.this.client));
1235
1236 c->spd.that.client = tmp_subnet_r;
1237 c->spd.that.port = st->st_ts_that.startport;
1238 c->spd.that.protocol = st->st_ts_that.ipprotoid;
1239 setportof(htons(c->spd.that.port),{ *(&c->spd.that.client.addr) = set_endpoint_hport((&
c->spd.that.client.addr), ntohs(htons(c->spd.that.port)
)); }
1240 &c->spd.that.client.addr){ *(&c->spd.that.client.addr) = set_endpoint_hport((&
c->spd.that.client.addr), ntohs(htons(c->spd.that.port)
)); }
;
1241
1242 c->spd.that.has_client =
1243 !(subnetishost(&c->spd.that.client) &&
1244 addrinsubnet(&c->spd.that.host_addr,
1245 &c->spd.that.client));
1246
1247 return true1;
1248}
1249
1250/*
1251 * RFC 7296 https://tools.ietf.org/html/rfc7296#section-2.8
1252 * "when rekeying, the new Child SA SHOULD NOT have different Traffic
1253 * Selectors and algorithms than the old one."
1254 *
1255 * We already matched the right connection by the SPI of v2N_REKEY_SA
1256 */
1257bool_Bool child_rekey_ts_verify(struct child_sa *child, struct msg_digest *md)
1258{
1259 if (!pexpect(child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 ||({ _Bool assertion__ = child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0
|| child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I1
; if (!assertion__) { log_pexpect((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 1260}, "%s", "child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 || child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I1"
); } assertion__; })
1260 child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I1)({ _Bool assertion__ = child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0
|| child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I1
; if (!assertion__) { log_pexpect((where_t) { .func = __func__
, .basename = "ikev2_ts.c" , .line = 1260}, "%s", "child->sa.st_state->kind == STATE_V2_REKEY_CHILD_R0 || child->sa.st_state->kind == STATE_V2_REKEY_CHILD_I1"
); } assertion__; })
) {
1261 return false0;
1262 }
1263
1264 struct traffic_selectors their_tsis = { .nr = 0, };
1265 struct traffic_selectors their_tsrs = { .nr = 0, };
1266 enum message_role md_role = v2_msg_role(md);
1267
1268 if (!v2_parse_tss(md, &their_tsis, &their_tsrs)) {
1269 log_state(RC_LOG_SERIOUS, &child->sa, "received malformed TSi/TSr payload(s)");
1270 return false0;
1271 }
1272
1273 struct traffic_selector ts_this = ikev2_end_to_ts(&child->sa.st_connection->spd.this);
1274 struct traffic_selector ts_that = ikev2_end_to_ts(&child->sa.st_connection->spd.that);
1275
1276 if (!ts_in_tslist(&their_tsis, (md_role == MESSAGE_REQUEST) ? &ts_that : &ts_this)) {
1277 log_state(RC_LOG_SERIOUS, &child->sa,
1278 "received TSi payload does not contain existing IPsec SA traffic Selectors");
1279 return false0;
1280 }
1281
1282 if (!ts_in_tslist(&their_tsrs, (md_role == MESSAGE_REQUEST) ? &ts_this : &ts_that)) {
1283 log_state(RC_LOG_SERIOUS, &child->sa, "received TSr payload(s) does not contain existing IPsec SA Traffic Selectors");
1284 return false0;
1285 }
1286 return true1;
1287}