Bug Summary

File:programs/pluto/ikev2_ts.c
Warning:line 970, column 32
Access to field 'kind' results in a dereference of a null pointer (loaded from variable 'c')

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 true 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"
); } }
;
6
Assuming the condition is false
7
Taking false branch
807 } else if (md->st == &ike_sa(&child->sa, HERE(where_t) { .func = __func__, .basename = "ikev2_ts.c" , .line
= 807}
)->sa) {
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"
); } }
;
811 }
812 struct connection *c = md->st->st_connection;
8
'c' initialized here
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 equal to NULL
13
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)))
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) {
842 continue;
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"); } }
;
14
Taking false branch
866 const struct host_pair *hp = NULL((void*)0);
867 for (const struct spd_route *sra = &c->spd;
15
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))))) {
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");
879 }
880
881 if (hp == NULL((void*)0))
882 continue;
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) {
16
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"
); } }
;
17
Taking false 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) {
18
Access to field 'kind' results in a dereference of a null pointer (loaded from variable 'c')
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))) ||
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__
; })
;
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");
} }
;
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"
); } }
;
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__); } }
;
1005 for (struct connection *t = connections; t != NULL((void*)0); t = t->ac_next) {
1006 /* require a template */
1007 if (t->kind != CK_TEMPLATE) {
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))
{
1011 jam(buf, " investigating template \"%s\";",
1012 t->name);
1013 if (t->foodgroup != NULL((void*)0)) {
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)) |
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))))
) {
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)) {
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}