Bug Summary

File:programs/pluto/pending.c
Warning:line 344, column 4
Access to field 'name' results in a dereference of a null pointer (loaded from field 'connection')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pending.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D HAVE_NM -D USE_PAM_AUTH -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/pending.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/pending.c
1/* information about connections between hosts and clients
2 *
3 * Copyright (C) 1998-2002,2013,2015 D. Hugh Redelmeier <hugh@mimosa.com>
4 * Copyright (C) 2003-2007 Michael Richardson <mcr@xelerance.com>
5 * Copyright (C) 2009 Paul Wouters <paul@xelerance.com>
6 * Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
7 * Copyright (C) 2012-2018 Paul Wouters <pwouters@redhat.com>
8 * Copyright (C) 2011 Anthony Tong <atong@TrustedCS.com>
9 * Copyright (C) 2017-2018 Antony Antony <antony@phenome.org>
10 * Copyright (C) 2019 Andrew Cagney <cagney@gnu.org>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23#include <string.h>
24#include <stdio.h>
25#include <stddef.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <netinet/in.h>
29#include <sys/socket.h>
30#include <sys/stat.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
34#include <errno(*__errno_location ()).h>
35
36
37#include "sysdep.h"
38#include "constants.h"
39#include "defs.h"
40#include "id.h"
41#include "x509.h"
42#include "certs.h"
43#include "connections.h" /* needs id.h */
44#include "pending.h"
45#include "log.h"
46#include "state.h"
47#include "packet.h"
48#include "demux.h"
49#include "ikev1_quick.h"
50#include "timer.h"
51#include "ikev2.h"
52#include "ip_address.h"
53#include "host_pair.h"
54#include "ikev2_create_child_sa.h" /* for initiate_v2_CREATE_CHILD_SA_create_child() */
55
56/*
57 * queue an IPsec SA negotiation pending completion of a
58 * suitable phase 1 (IKE SA)
59 */
60
61static void add_pending(struct fd *whack_sock,
62 struct ike_sa *ike,
63 struct connection *c,
64 lset_t policy,
65 unsigned long try,
66 so_serial_t replacing,
67 const shunk_t sec_label,
68 bool_Bool part_of_initiate)
69{
70 /* look for duplicate pending IPsec SA's, skip add operation */
71 struct pending **pp = host_pair_first_pending(c);
72 for (struct pending *p = pp ? *pp : NULL((void*)0); p != NULL((void*)0); p = p->next) {
73 if (p->connection == c) {
74 address_buf b;
75 connection_buf cib;
76 bool_Bool duplicate = (p->ike == ike);
77 dbg("connection "PRI_CONNECTION" is already pending: waiting on IKE SA #%lu connecting to %s; %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s"
, (c)->name, str_connection_instance(c, &cib), p->ike
->sa.st_serialno, str_address(&c->spd.that.host_addr
, &b), duplicate ? "ignoring duplicate" : "this IKE SA is different"
); } }
78 pri_connection(c, &cib),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s"
, (c)->name, str_connection_instance(c, &cib), p->ike
->sa.st_serialno, str_address(&c->spd.that.host_addr
, &b), duplicate ? "ignoring duplicate" : "this IKE SA is different"
); } }
79 p->ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s"
, (c)->name, str_connection_instance(c, &cib), p->ike
->sa.st_serialno, str_address(&c->spd.that.host_addr
, &b), duplicate ? "ignoring duplicate" : "this IKE SA is different"
); } }
80 str_address(&c->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s"
, (c)->name, str_connection_instance(c, &cib), p->ike
->sa.st_serialno, str_address(&c->spd.that.host_addr
, &b), duplicate ? "ignoring duplicate" : "this IKE SA is different"
); } }
81 duplicate ? "ignoring duplicate" : "this IKE SA is different"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s"
, (c)->name, str_connection_instance(c, &cib), p->ike
->sa.st_serialno, str_address(&c->spd.that.host_addr
, &b), duplicate ? "ignoring duplicate" : "this IKE SA is different"
); } }
;
82 if (duplicate) {
83 return;
84 }
85 }
86 }
87
88 struct pending *p = alloc_thing(struct pending, "struct pending")((struct pending*) alloc_bytes(sizeof(struct pending), ("struct pending"
)))
;
89 p->whack_sock = fd_dup(whack_sock, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 89, }; &here; })
); /*on heap*/
90 p->ike = ike;
91 p->connection = c;
92 p->policy = policy;
93 p->try = try;
94 p->replacing = replacing;
95 p->pend_time = mononow();
96 p->part_of_initiate = part_of_initiate; /* useful */
97 p->sec_label = sec_label;
98
99 /*
100 * If this is part of an initiate then there's already enough
101 * going on; no need to log this action.
102 */
103 enum stream only = part_of_initiate ? (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) ? DEBUG_STREAM : NO_STREAM) : ALL_STREAMS;
104 if (only != NO_STREAM) {
105 address_buf b;
106 state_bufconnection_buf sab;
107 log_pending(only | RC_COMMENT, p,
108 "queue %s; waiting on %s "PRI_STATE"\"%s\"%s"" ""#%lu"" negotiating with %s",
109 /* "Child SA" or "IPsec SA" */
110 enum_enum_name(&sa_type_names, p->connection->ike_version, IPSEC_SA),
111 /* "IKE SA" or "ISAKMP SA" */
112 enum_enum_name(&sa_type_names, p->connection->ike_version, IKE_SA),
113 pri_state(&ike->sa, &sab)((&ike->sa)->st_connection)->name, str_connection_instance
((&ike->sa)->st_connection, &sab), ((&ike->
sa)->st_serialno)
,
114 ipstr(&c->spd.that.host_addr, &b));
115 }
116 host_pair_enqueue_pending(c, p);
117}
118
119void add_v1_pending(struct fd *whackfd,
120 struct ike_sa *ike,
121 struct connection *c,
122 lset_t policy,
123 unsigned long try,
124 so_serial_t replacing,
125 const shunk_t sec_label,
126 bool_Bool part_of_initiate)
127{
128 passert(ike->sa.st_ike_version == IKEv1)({ _Bool assertion__ = ike->sa.st_connection->ike_version
== IKEv1; if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 128, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "ike->sa.st_connection->ike_version == IKEv1"
); } (void) 1; })
;
129 add_pending(whackfd, ike, c, policy, try, replacing, sec_label, part_of_initiate);
130}
131
132void add_v2_pending(struct fd *whackfd,
133 struct ike_sa *ike,
134 struct connection *c,
135 lset_t policy,
136 unsigned long try,
137 so_serial_t replacing,
138 const shunk_t sec_label,
139 bool_Bool part_of_initiate)
140{
141 passert(ike->sa.st_ike_version == IKEv2)({ _Bool assertion__ = ike->sa.st_connection->ike_version
== IKEv2; if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 141, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "ike->sa.st_connection->ike_version == IKEv2"
); } (void) 1; })
;
142 if (c->config->sec_label.len > 0 || sec_label.len > 0) {
143 /*
144 * Convert the template connection into a connection
145 * instance that contains the sec_label, and toss that
146 * onto the pending queue.
147 */
148 if (!pexpect(c->kind == CK_TEMPLATE)({ _Bool assertion__ = c->kind == CK_TEMPLATE; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/pending.c", .line = 148,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->kind == CK_TEMPLATE"
); } assertion__; })
||
149 !pexpect(c->config->sec_label.len > 0)({ _Bool assertion__ = c->config->sec_label.len > 0;
if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 149, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "c->config->sec_label.len > 0"
); } assertion__; })
||
150 !pexpect(sec_label.len > 0)({ _Bool assertion__ = sec_label.len > 0; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/pending.c", .line = 150,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "sec_label.len > 0");
} assertion__; })
) {
151 return;
152 }
153 ip_address remote_address = endpoint_address(ike->sa.st_remote_endpoint);
154 struct connection *d = instantiate(c, &remote_address, /*peer_id*/NULL((void*)0), sec_label);
155 connection_buf db;
156 dbg("generating and then tossing child connection "PRI_CONNECTION" with sec_label="PRI_SHUNK" into the pending queue",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("generating and then tossing child connection "
"\"%s\"%s"" with sec_label=""%.*s"" into the pending queue", (
d)->name, str_connection_instance(d, &db), ((int) (sec_label
).len), (const char *) ((sec_label).ptr)); } }
157 pri_connection(d, &db), pri_shunk(sec_label)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("generating and then tossing child connection "
"\"%s\"%s"" with sec_label=""%.*s"" into the pending queue", (
d)->name, str_connection_instance(d, &db), ((int) (sec_label
).len), (const char *) ((sec_label).ptr)); } }
;
158 c = d;
159 }
160 add_pending(whackfd, ike, c, policy, try, replacing, sec_label, part_of_initiate);
161}
162
163/*
164 * Release all the whacks awaiting the completion of this state. This
165 * is accomplished by closing all the whack socket file descriptors.
166 * We go to some trouble to tell each whack, but to not tell it twice.
167 */
168
169void release_pending_whacks(struct state *st, err_t story)
170{
171 /*
172 * Use fstat() to uniquely identify the whack connection -
173 * multiple sockets to the same whack will have similar
174 * 'struct stat' values.
175 *
176 * If the socket is valid, close it.
177 */
178 if (!fd_p(st->st_logger->object_whackfd)) {
179 dbg("%s: state #%lu has no whack fd",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: state #%lu has no whack fd", __func__, st
->st_serialno); } }
180 __func__, st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: state #%lu has no whack fd", __func__, st
->st_serialno); } }
;
181 return;
182 }
183
184 /*
185 * Check for the SA's parent and if that needs to disconnect.
186 *
187 * For instance, when the IKE_SA establishes but the first
188 * CHILD_SA fails with a timeout then this code will be called
189 * with the CHILD_SA.
190 *
191 * XXX: Since this is meant to release pending whacks, should
192 * this check for, and release the whacks for any pending
193 * CHILD_SA attached to this ST's IKE SA?
194 */
195 struct ike_sa *ike_with_same_whack = NULL((void*)0);
196 if (IS_CHILD_SA(st)((st)->st_clonedfrom != 0)) {
197 struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 197, }; &here; })
);
198 if (same_fd(st->st_logger->object_whackfd, ike->sa.st_logger->object_whackfd)) {
199 ike_with_same_whack = ike;
200 release_any_whack(&ike->sa, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 200, }; &here; })
, "release pending whacks state's IKE SA");
201 } else {
202 release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 202, }; &here; })
, "releasing isolated child");
203 return;
204 }
205 } else {
206 ike_with_same_whack = pexpect_ike_sa(st);
207 }
208 pexpect(ike_with_same_whack != NULL)({ _Bool assertion__ = ike_with_same_whack != ((void*)0); if (
!assertion__) { where_t here_ = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/pending.c", .line
= 208, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike_with_same_whack != ((void*)0)"
); } assertion__; })
;
209
210 /*
211 * Now go through pending children and close the whack socket
212 * of any that are going to be assigned this ST as the parent.
213 * XXX: Is this because the parent is dying so anything
214 * waiting on it should be deleted.
215 *
216 * SAME_FD() is used to identify whack sockets that are
217 * different to ST - when found a further release message is
218 * printed.
219 */
220
221 struct pending **pp = host_pair_first_pending(st->st_connection);
222 if (pp == NULL((void*)0))
223 return;
224 for (struct pending *p = *pp; p != NULL((void*)0); p = p->next) {
225 dbg("%s: IKE SA #%lu "PRI_FD" has pending CHILD SA with socket "PRI_FD,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket "
"fd@%p", __func__, p->ike->sa.st_serialno, (p->ike->
sa.st_logger->object_whackfd), (p->whack_sock)); } }
226 __func__, p->ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket "
"fd@%p", __func__, p->ike->sa.st_serialno, (p->ike->
sa.st_logger->object_whackfd), (p->whack_sock)); } }
227 pri_fd(p->ike->sa.st_logger->object_whackfd),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket "
"fd@%p", __func__, p->ike->sa.st_serialno, (p->ike->
sa.st_logger->object_whackfd), (p->whack_sock)); } }
228 pri_fd(p->whack_sock)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket "
"fd@%p", __func__, p->ike->sa.st_serialno, (p->ike->
sa.st_logger->object_whackfd), (p->whack_sock)); } }
;
229 if (p->ike == ike_with_same_whack && fd_p(p->whack_sock)) {
230 if (!same_fd(st->st_logger->object_whackfd, p->whack_sock)) {
231 /* XXX: why not the log file? */
232 log_pending(WHACK_STREAM|RC_COMMENT, p,
233 "%s for IKE SA, but releasing whack for pending %s",
234 story,
235 /* "IPsec SA" or "CHILD SA" */
236 enum_enum_name(&sa_type_names, p->connection->ike_version, IPSEC_SA));
237 }
238 close_any(&p->whack_sock)close_any_fd((&p->whack_sock), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 238, }; &here; }))
;/*on-heap*/
239 }
240 }
241 release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 241, }; &here; })
, "releasing child");
242}
243
244/*
245 * remove a pending from a linked list.
246 *
247 * pp points to the link to the entry.
248 * *pp will be updated to point to the successor to the original *pp.
249 * In effect, we advance *pp.
250 * Note: If you are traversing a linked list and deleting some entries,
251 * you should not advance pp after calling delete_pending.
252 */
253static void delete_pending(struct pending **pp)
254{
255 /* remove from list */
256 struct pending *p = *pp;
257 *pp = p->next;
258
259 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
260 if (p->connection == NULL((void*)0)) {
261 /*
262 * ??? when does this happen?
263 *
264 * Look for p->connection=NULL below. When
265 * unpend()ing, the pending connection's
266 * ownership is transfered to the state.
267 */
268 DBG_log("removing pending policy {%p}; connection ownership transfered", p);
269 } else {
270 connection_buf cib;
271 DBG_log("removing pending policy {%p} with connection "PRI_CONNECTION"\"%s\"%s""",
272 p, pri_connection(p->connection, &cib)(p->connection)->name, str_connection_instance(p->connection
, &cib)
);
273 }
274 }
275
276 if (p->connection != NULL((void*)0)) {
277 /* above unlink means C is no longer pending */
278 pexpect(!connection_is_pending(p->connection))({ _Bool assertion__ = !connection_is_pending(p->connection
); if (!assertion__) { where_t here_ = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 278, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "!connection_is_pending(p->connection)"
); } assertion__; })
;
279 connection_delete_unused_instance(&p->connection,
280 /*old-state*/NULL((void*)0),
281 null_fd((struct fd *) ((void*)0))/*XXX: p->whack_sock?*/);
282 }
283 close_any(&p->whack_sock)close_any_fd((&p->whack_sock), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/pending.c"
, .line = 283, }; &here; }))
; /*on-heap*/
284
285 pfree(p);
286}
287
288/*
289 * Look for phase2s that were waiting for a phase 1.
290 *
291 * XXX instead of doing this work NOW, we should simply create an event
292 * in zero future time to unpend the state.
293 * YYY but, in fact, quick_mode will enqueue a cryptographic operation
294 * anyway, which will get done "later" anyway, so make it is just fine
295 * as it is.
296 * In IKEv2 it called when AUTH is complete, child is established.
297 * Established child get removed not unpend.
298 */
299
300void unpend(struct ike_sa *ike, struct connection *cc)
301{
302 if (cc == NULL((void*)0)) {
1
Assuming 'cc' is equal to NULL
2
Taking true branch
303 dbg("unpending state #%lu", ike->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("unpending state #%lu", ike->sa.st_serialno
); } }
;
3
Assuming the condition is false
4
Taking false branch
304 } else {
305 connection_buf cib;
306 dbg("unpending state #%lu connection "PRI_CONNECTION"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("unpending state #%lu connection ""\"%s\"%s"""
, ike->sa.st_serialno, (cc)->name, str_connection_instance
(cc, &cib)); } }
307 ike->sa.st_serialno, pri_connection(cc, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("unpending state #%lu connection ""\"%s\"%s"""
, ike->sa.st_serialno, (cc)->name, str_connection_instance
(cc, &cib)); } }
;
308 }
309
310 for (struct pending *p, **pp = host_pair_first_pending(ike->sa.st_connection);
6
Loop condition is true. Entering loop body
311 (p = *pp) != NULL((void*)0); ) {
5
Assuming the condition is true
312 if (p->ike == ike) {
7
Assuming 'ike' is equal to field 'ike'
8
Taking true branch
313 p->pend_time = mononow();
314 char *what ="unqueuing";
315 switch (ike->sa.st_ike_versionst_connection->ike_version) {
9
Control jumps to 'case IKEv2:' at line 316
316 case IKEv2:
317 if (cc == p->connection) {
10
Assuming 'cc' is equal to field 'connection'
11
Taking true branch
318 /*
319 * IKEv2 AUTH negotiation
320 * include child. nothing to
321 * upend, like in IKEv1,
322 * delete it
323 */
324 what = "delete from";
325 } else if (!already_has_larval_v2_child(ike, p->connection)) {
326 submit_v2_CREATE_CHILD_SA_new_child(ike, p->connection,
327 p->policy, p->try,
328 p->whack_sock);
329 }
330 break;
12
Execution continues on line 342
331 case IKEv1:
332#ifdef USE_IKEv11
333 quick_outI1(p->whack_sock, &ike->sa, p->connection,
334 p->policy,
335 p->try, p->replacing,
336 null_shunk);
337#endif
338 break;
339 default:
340 bad_case(ike->sa.st_ike_version)libreswan_bad_case("ike->sa.st_ike_version", (ike->sa.st_connection
->ike_version), ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/pending.c", .line = 340,
}; &here; }))
;
341 }
342 address_buf b;
343 connection_buf cib;
344 dbg("%s pending %s with %s "PRI_CONNECTION"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_connection->ike_version == IKEv2) ? "Child SA" :
"Quick Mode", str_address(&p->connection->spd.that
.host_addr, &b), (p->connection)->name, str_connection_instance
(p->connection, &cib)); } }
13
Assuming the condition is true
14
Taking true branch
15
'?' condition is true
16
Access to field 'name' results in a dereference of a null pointer (loaded from field 'connection')
345 what,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_connection->ike_version == IKEv2) ? "Child SA" :
"Quick Mode", str_address(&p->connection->spd.that
.host_addr, &b), (p->connection)->name, str_connection_instance
(p->connection, &cib)); } }
346 (ike->sa.st_ike_version == IKEv2) ? "Child SA" : "Quick Mode",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_connection->ike_version == IKEv2) ? "Child SA" :
"Quick Mode", str_address(&p->connection->spd.that
.host_addr, &b), (p->connection)->name, str_connection_instance
(p->connection, &cib)); } }
347 str_address(&p->connection->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_connection->ike_version == IKEv2) ? "Child SA" :
"Quick Mode", str_address(&p->connection->spd.that
.host_addr, &b), (p->connection)->name, str_connection_instance
(p->connection, &cib)); } }
348 pri_connection(p->connection, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_connection->ike_version == IKEv2) ? "Child SA" :
"Quick Mode", str_address(&p->connection->spd.that
.host_addr, &b), (p->connection)->name, str_connection_instance
(p->connection, &cib)); } }
;
349
350 p->connection = NULL((void*)0); /* ownership transferred */
351 delete_pending(pp); /* in effect, advances pp */
352 } else {
353 pp = &p->next;
354 }
355 }
356}
357
358struct connection *first_pending(const struct ike_sa *ike,
359 lset_t *policy,
360 struct fd **p_whack_sock)
361{
362 struct pending **pp, *p;
363
364 dbg("getting first pending from state #%lu", ike->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("getting first pending from state #%lu", ike->
sa.st_serialno); } }
;
365
366 for (pp = host_pair_first_pending(ike->sa.st_connection);
367 (p = *pp) != NULL((void*)0); pp = &p->next)
368 {
369 if (p->ike == ike) {
370 close_any(p_whack_sock)close_any_fd((p_whack_sock), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/pending.c", .line
= 370, }; &here; }))
; /*on-heap*/
371 *p_whack_sock = fd_dup(p->whack_sock, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/pending.c", .line = 371, }; &here; })
); /*on-heap*/
372 *policy = p->policy;
373 return p->connection;
374 }
375 }
376 return NULL((void*)0);
377}
378
379/*
380 * Look for phase2s that were waiting for a phase 1. If the time that we
381 * have been pending exceeds a DPD timeout that was set, then we call the
382 * dpd_timeout() on this state. We hope this kills the pending state.
383 */
384bool_Bool pending_check_timeout(const struct connection *c)
385{
386 struct pending **pp, *p;
387
388 for (pp = host_pair_first_pending(c); (p = *pp) != NULL((void*)0); ) {
389 deltatime_t waited = monotimediff(mononow(), p->pend_time);
390 connection_buf cib;
391 dbg("checking connection "PRI_CONNECTION" for stuck phase 2s (waited %jd, patience 3*%jd)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)"
, (c)->name, str_connection_instance(c, &cib), deltasecs
(waited), deltasecs(c->dpd_timeout)); } }
392 pri_connection(c, &cib), deltasecs(waited),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)"
, (c)->name, str_connection_instance(c, &cib), deltasecs
(waited), deltasecs(c->dpd_timeout)); } }
393 deltasecs(c->dpd_timeout)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)"
, (c)->name, str_connection_instance(c, &cib), deltasecs
(waited), deltasecs(c->dpd_timeout)); } }
;
394 if (deltasecs(c->dpd_timeout) > 0) {
395 if (!monobefore(mononow(),
396 monotime_add(p->pend_time,
397 deltatimescale(3, 1, c->dpd_timeout)))) {
398 connection_buf cib;
399 dbg("connection "PRI_CONNECTION" stuck, restarting",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" stuck, restarting", (
c)->name, str_connection_instance(c, &cib)); } }
400 pri_connection(c, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection ""\"%s\"%s"" stuck, restarting", (
c)->name, str_connection_instance(c, &cib)); } }
;
401 return true1;
402 }
403 }
404 pp = &p->next;
405 }
406 return false0;
407}
408
409/* a IKE SA negotiation has been replaced; update any pending */
410void update_pending(struct ike_sa *old_ike, struct ike_sa *new_ike)
411{
412 struct pending *p, **pp;
413
414 pexpect(old_ike != NULL)({ _Bool assertion__ = old_ike != ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/pending.c", .line = 414,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "old_ike != ((void*)0)")
; } assertion__; })
;
415 if (old_ike == NULL((void*)0))
416 return;
417
418 pp = host_pair_first_pending(old_ike->sa.st_connection);
419 if (pp == NULL((void*)0))
420 return;
421
422 for (p = *pp; p != NULL((void*)0); p = p->next)
423 if (p->ike == old_ike)
424 p->ike = new_ike;
425}
426
427/* a IKE SA negotiation has failed; discard any pending */
428void flush_pending_by_state(struct ike_sa *ike)
429{
430 struct pending **pp, *p;
431
432 pp = host_pair_first_pending(ike->sa.st_connection);
433 if (pp == NULL((void*)0))
434 return;
435
436 while ((p = *pp) != NULL((void*)0)) {
437 if (p->ike == ike) {
438 /* we don't have to worry about deref to free'ed
439 * *pp, because delete_pending updates pp to
440 * point to the next element before it frees *pp
441 */
442 delete_pending(pp); /* in effect, advances pp */
443 } else {
444 pp = &p->next;
445 }
446 }
447}
448
449/* a connection has been deleted; discard any related pending */
450void flush_pending_by_connection(const struct connection *c)
451{
452 struct pending **pp, *p;
453
454 pp = host_pair_first_pending(c);
455 if (pp == NULL((void*)0))
456 return;
457
458 while ((p = *pp) != NULL((void*)0)) {
459 if (p->connection == c) {
460 p->connection = NULL((void*)0); /* prevent delete_pending from releasing */
461 delete_pending(pp); /* in effect, advances pp */
462 } else {
463 pp = &p->next;
464 }
465 }
466}
467
468void show_pending_child_details(struct show *s,
469 const struct connection *c,
470 const struct ike_sa *ike)
471{
472 struct pending **pp, *p;
473
474 pp = host_pair_first_pending(c);
475 if (pp == NULL((void*)0))
476 return;
477
478 for (p = *pp; p != NULL((void*)0); p = p->next) {
479 if (p->ike == ike) {
480 /* connection-name state-number [replacing state-number] */
481 SHOW_JAMBUF(RC_COMMENT, s, buf)for (struct jambuf *buf = show_jambuf(s); buf != ((void*)0); jambuf_to_show
(buf, s, RC_COMMENT), buf = ((void*)0))
{
482 jam(buf, "#%lu: pending ", p->ike->sa.st_serialno);
483 jam_string(buf, (ike->sa.st_ike_versionst_connection->ike_version == IKEv2) ? "CHILD SA" : "Phase 2");
484 jam(buf, " for ");
485 jam_connection(buf, c);
486 if (p->replacing != SOS_NOBODY0) {
487 jam(buf, " replacing #%lu", p->replacing);
488 }
489 }
490 }
491 }
492}
493
494bool_Bool connection_is_pending(const struct connection *c)
495{
496 /* see if it is being used by a pending */
497 struct pending **pp, *p;
498
499 pp = host_pair_first_pending(c);
500 if (pp == NULL((void*)0))
501 return false0;
502
503 for (p = *pp; p != NULL((void*)0); p = p->next)
504 if (p->connection == c)
505 return true1; /* in use, so we're done */
506
507 return false0;
508}