File: | programs/pluto/timer.c |
Warning: | line 549, column 16 Access to field 'st_logger' results in a dereference of a null pointer (loaded from variable 'st') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* timer event handling | |||
2 | * | |||
3 | * Copyright (C) 1997 Angelos D. Keromytis. | |||
4 | * Copyright (C) 1998-2001 D. Hugh Redelmeier. | |||
5 | * Copyright (C) 2005-2008 Michael Richardson <mcr@xelerance.com> | |||
6 | * Copyright (C) 2008-2010 Paul Wouters <paul@xelerance.com> | |||
7 | * Copyright (C) 2009 David McCullough <david_mccullough@securecomputing.com> | |||
8 | * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com> | |||
9 | * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com> | |||
10 | * Copyright (C) 2013 Matt Rogers <mrogers@redhat.com> | |||
11 | * Copyright (C) 2017 Antony Antony <antony@phenome.org> | |||
12 | * Copyright (C) 2017-2020 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 | #include <stdio.h> | |||
26 | #include <stdlib.h> | |||
27 | #include <sys/types.h> | |||
28 | #include <time.h> | |||
29 | #include <unistd.h> | |||
30 | #include <netinet/in.h> | |||
31 | #include <arpa/inet.h> | |||
32 | ||||
33 | #include <event2/event.h> | |||
34 | #include <event2/event_struct.h> | |||
35 | ||||
36 | #include "sysdep.h" | |||
37 | #include "constants.h" | |||
38 | #include "defs.h" | |||
39 | #include "id.h" | |||
40 | #include "x509.h" | |||
41 | #include "certs.h" | |||
42 | #include "connections.h" /* needs id.h */ | |||
43 | #include "state.h" | |||
44 | #include "packet.h" | |||
45 | #include "demux.h" /* needs packet.h */ | |||
46 | #include "ipsec_doi.h" /* needs demux.h and state.h */ | |||
47 | #include "kernel.h" /* needs connections.h */ | |||
48 | #include "server.h" | |||
49 | #include "log.h" | |||
50 | #include "rnd.h" | |||
51 | #include "timer.h" | |||
52 | #include "whack.h" | |||
53 | #include "ikev1_dpd.h" | |||
54 | #include "ikev2.h" | |||
55 | #include "ikev2_redirect.h" | |||
56 | #include "pending.h" /* for flush_pending_by_connection */ | |||
57 | #include "ikev1_xauth.h" | |||
58 | #ifdef USE_PAM_AUTH1 | |||
59 | #include "pam_auth.h" | |||
60 | #endif | |||
61 | #include "kernel.h" /* for kernel_ops */ | |||
62 | #include "nat_traversal.h" | |||
63 | #include "pluto_sd.h" | |||
64 | #include "ikev1_retry.h" | |||
65 | #include "ikev2_retry.h" | |||
66 | #include "fetch.h" /* for check_crls() */ | |||
67 | #include "pluto_stats.h" | |||
68 | #include "iface.h" | |||
69 | #include "ikev2_liveness.h" | |||
70 | #include "ikev2_mobike.h" | |||
71 | #include "ikev2_delete.h" /* for submit_v2_delete_exchange() */ | |||
72 | ||||
73 | struct state_event **state_event(struct state *st, enum event_type type) | |||
74 | { | |||
75 | /* | |||
76 | * Return a pointer to the event in the state object. | |||
77 | * | |||
78 | * XXX: why not just have an array and index it by KIND? | |||
79 | */ | |||
80 | switch (type) { | |||
81 | ||||
82 | case EVENT_v1_SEND_XAUTH: | |||
83 | return &st->st_v1_send_xauth_event; | |||
84 | ||||
85 | case EVENT_v2_LIVENESS: | |||
86 | return &st->st_v2_liveness_event; | |||
87 | ||||
88 | case EVENT_v2_ADDR_CHANGE: | |||
89 | return &st->st_v2_addr_change_event; | |||
90 | break; | |||
91 | ||||
92 | case EVENT_v2_REKEY: | |||
93 | return &st->st_v2_rekey_event; | |||
94 | break; | |||
95 | ||||
96 | case EVENT_v2_REAUTH: | |||
97 | return &st->st_v2_reauth_event; | |||
98 | break; | |||
99 | ||||
100 | case EVENT_DPD: | |||
101 | case EVENT_DPD_TIMEOUT: | |||
102 | return &st->st_dpd_event; | |||
103 | ||||
104 | case EVENT_RETRANSMIT: | |||
105 | return &st->st_retransmit_event; | |||
106 | ||||
107 | case EVENT_SA_DISCARD: | |||
108 | case EVENT_SA_REPLACE: | |||
109 | case EVENT_SA_EXPIRE: | |||
110 | case EVENT_v1_REPLACE_IF_USED: | |||
111 | case EVENT_CRYPTO_TIMEOUT: | |||
112 | case EVENT_PAM_TIMEOUT: | |||
113 | case EVENT_v2_REDIRECT: | |||
114 | /* | |||
115 | * Many of these don't make sense - however that's | |||
116 | * what happens when (the replaced) default: is used. | |||
117 | */ | |||
118 | return &st->st_event; | |||
119 | ||||
120 | case EVENT_RETAIN: | |||
121 | case EVENT_NULL: | |||
122 | return NULL((void*)0); | |||
123 | } | |||
124 | bad_case(type)libreswan_bad_case("type", (type), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 124, }; &here; })); | |||
125 | } | |||
126 | ||||
127 | /* | |||
128 | * This file has the event handling routines. Events are | |||
129 | * kept as a linked list of event structures. These structures | |||
130 | * have information like event type, expiration time and a pointer | |||
131 | * to event specific data (for example, to a state structure). | |||
132 | */ | |||
133 | ||||
134 | static void dispatch_event(struct state *st, enum event_type event_type, | |||
135 | deltatime_t event_delay); | |||
136 | static event_callback_routine timer_event_cb; | |||
137 | ||||
138 | static void timer_event_cb(evutil_socket_tint unused_fd UNUSED__attribute__ ((unused)), | |||
139 | const short unused_event UNUSED__attribute__ ((unused)), | |||
140 | void *arg) | |||
141 | { | |||
142 | /* | |||
143 | * Start billing before state is found. | |||
144 | */ | |||
145 | threadtime_t inception = threadtime_start(); | |||
146 | ||||
147 | /* | |||
148 | * Get rid of the old timer event before calling the timer | |||
149 | * event processor. | |||
150 | */ | |||
151 | struct state *st; | |||
152 | enum event_type event_type; | |||
153 | const char *event_name; | |||
154 | deltatime_t event_delay; | |||
155 | ||||
156 | { | |||
157 | struct state_event *ev = arg; | |||
158 | passert(ev != NULL)({ _Bool assertion__ = ev != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/timer.c", .line = 158, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "ev != ((void*)0)"); } (void) 1; }); | |||
159 | event_type = ev->ev_type; | |||
160 | event_name = enum_name_short(&event_type_names, event_type); | |||
161 | event_delay = ev->ev_delay; | |||
162 | st = ev->ev_state; /* note: *st might be changed; XXX: why? */ | |||
163 | passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/timer.c", .line = 163, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "st != ((void*)0)"); } (void) 1; }); | |||
164 | passert(event_name != NULL)({ _Bool assertion__ = event_name != ((void*)0); if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 164, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "event_name != ((void*)0)" ); } (void) 1; }); | |||
165 | ||||
166 | dbg("%s: processing %s-event@%p for %s SA #%lu in state %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s" , __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE" : "CHILD", st->st_serialno, st->st_state->short_name ); } } | |||
167 | __func__, event_name, ev,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s" , __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE" : "CHILD", st->st_serialno, st->st_state->short_name ); } } | |||
168 | IS_IKE_SA(st) ? "IKE" : "CHILD",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s" , __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE" : "CHILD", st->st_serialno, st->st_state->short_name ); } } | |||
169 | st->st_serialno, st->st_state->short_name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s" , __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE" : "CHILD", st->st_serialno, st->st_state->short_name ); } }; | |||
170 | ||||
171 | struct state_event **evp = state_event(st, event_type); | |||
172 | if (evp == NULL((void*)0)) { | |||
173 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 173, }; &here; }), | |||
174 | "#%lu has no .st_event field for %s", | |||
175 | st->st_serialno, event_name); | |||
176 | return; | |||
177 | } | |||
178 | ||||
179 | if (*evp != ev) { | |||
180 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 180, }; &here; }), | |||
181 | "#%lu .st_event is %p but should be %s-pe@%p", | |||
182 | st->st_serialno, *evp, event_name, ev); | |||
183 | return; | |||
184 | } | |||
185 | ||||
186 | /* everything useful has been extracted */ | |||
187 | delete_pluto_event(evp); | |||
188 | arg = ev = *evp = NULL((void*)0); /* all gone */ | |||
189 | } | |||
190 | ||||
191 | statetime_t start = statetime_backdate(st, &inception); | |||
192 | dispatch_event(st, event_type, event_delay); | |||
193 | statetime_stop(&start, "%s() %s", __func__, event_name); | |||
194 | } | |||
195 | ||||
196 | static void dispatch_event(struct state *st, enum event_type event_type, | |||
197 | deltatime_t event_delay) | |||
198 | { | |||
199 | /* | |||
200 | * Check that st is as expected for the event type. | |||
201 | * | |||
202 | * For an event type associated with a state, remove the | |||
203 | * backpointer from the appropriate slot of the state object. | |||
204 | * | |||
205 | * We'll eventually either schedule a new event, or delete the | |||
206 | * state. | |||
207 | */ | |||
208 | switch (event_type) { | |||
209 | ||||
210 | case EVENT_v2_ADDR_CHANGE: | |||
211 | dbg("#%lu IKEv2 local address change", st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu IKEv2 local address change", st->st_serialno ); } }; | |||
212 | ikev2_addr_change(st); | |||
213 | break; | |||
214 | ||||
215 | case EVENT_RETRANSMIT: | |||
216 | dbg("IKEv%d retransmit event", st->st_ike_version){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("IKEv%d retransmit event", st->st_connection ->ike_version); } }; | |||
217 | switch (st->st_ike_versionst_connection->ike_version) { | |||
218 | case IKEv2: | |||
219 | retransmit_v2_msg(st); | |||
220 | break; | |||
221 | #ifdef USE_IKEv11 | |||
222 | case IKEv1: | |||
223 | retransmit_v1_msg(st); | |||
224 | break; | |||
225 | #endif | |||
226 | default: | |||
227 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection ->ike_version), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 227, } ; &here; })); | |||
228 | } | |||
229 | break; | |||
230 | ||||
231 | #ifdef USE_IKEv11 | |||
232 | case EVENT_v1_SEND_XAUTH: | |||
233 | dbg("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s", st ->st_serialno, st->st_state->name); } } | |||
234 | st->st_serialno, st->st_state->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s", st ->st_serialno, st->st_state->name); } }; | |||
235 | xauth_send_request(st); | |||
236 | break; | |||
237 | #endif | |||
238 | ||||
239 | case EVENT_v2_LIVENESS: | |||
240 | liveness_check(st); | |||
241 | break; | |||
242 | ||||
243 | case EVENT_v2_REKEY: | |||
244 | pexpect(st->st_ike_version == IKEv2)({ _Bool assertion__ = st->st_connection->ike_version == IKEv2; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c" , .line = 244, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "st->st_connection->ike_version == IKEv2" ); } assertion__; }); | |||
245 | v2_event_sa_rekey(st); | |||
246 | break; | |||
247 | ||||
248 | case EVENT_v2_REAUTH: | |||
249 | pexpect(st->st_ike_version == IKEv2)({ _Bool assertion__ = st->st_connection->ike_version == IKEv2; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c" , .line = 249, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "st->st_connection->ike_version == IKEv2" ); } assertion__; }); | |||
250 | v2_event_sa_reauth(st); | |||
251 | break; | |||
252 | ||||
253 | case EVENT_SA_REPLACE: | |||
254 | case EVENT_v1_REPLACE_IF_USED: | |||
255 | switch (st->st_ike_versionst_connection->ike_version) { | |||
256 | case IKEv2: | |||
257 | pexpect(event_type == EVENT_SA_REPLACE)({ _Bool assertion__ = event_type == EVENT_SA_REPLACE; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 257, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "event_type == EVENT_SA_REPLACE" ); } assertion__; }); | |||
258 | v2_event_sa_replace(st); | |||
259 | break; | |||
260 | case IKEv1: | |||
261 | pexpect(event_type == EVENT_SA_REPLACE ||({ _Bool assertion__ = event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 262, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect( logger_, here_, "%s", "event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED" ); } assertion__; }) | |||
262 | event_type == EVENT_v1_REPLACE_IF_USED)({ _Bool assertion__ = event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 262, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect( logger_, here_, "%s", "event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED" ); } assertion__; }); | |||
263 | struct connection *c = st->st_connection; | |||
264 | const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD"; | |||
265 | ||||
266 | so_serial_t newer_sa = get_newer_sa_from_connection(st); | |||
267 | if (newer_sa != SOS_NOBODY0) { | |||
268 | /* not very interesting: no need to replace */ | |||
269 | dbg("not replacing stale %s SA %lu; #%lu will do",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("not replacing stale %s SA %lu; #%lu will do", satype, st->st_serialno, newer_sa); } } | |||
270 | satype, st->st_serialno, newer_sa){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("not replacing stale %s SA %lu; #%lu will do", satype, st->st_serialno, newer_sa); } }; | |||
271 | } else if (event_type == EVENT_v1_REPLACE_IF_USED && | |||
272 | !monobefore(mononow(), monotime_add(st->st_outbound_time, c->sa_rekey_margin))) { | |||
273 | /* | |||
274 | * we observed no recent use: no need to replace | |||
275 | * | |||
276 | * The sampling effects mean that st_outbound_time | |||
277 | * could be up to SHUNT_SCAN_INTERVAL more recent | |||
278 | * than actual traffic because the sampler looks at | |||
279 | * change over that interval. | |||
280 | * st_outbound_time could also not yet reflect traffic | |||
281 | * in the last SHUNT_SCAN_INTERVAL. | |||
282 | * We expect that SHUNT_SCAN_INTERVAL is smaller than | |||
283 | * c->sa_rekey_margin so that the effects of this will | |||
284 | * be unimportant. | |||
285 | * This is just an optimization: correctness is not | |||
286 | * at stake. | |||
287 | */ | |||
288 | dbg("not replacing stale %s SA: inactive for %jds",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("not replacing stale %s SA: inactive for %jds" , satype, deltasecs(monotimediff(mononow(), st->st_outbound_time ))); } } | |||
289 | satype, deltasecs(monotimediff(mononow(), st->st_outbound_time))){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("not replacing stale %s SA: inactive for %jds" , satype, deltasecs(monotimediff(mononow(), st->st_outbound_time ))); } }; | |||
290 | } else { | |||
291 | dbg("replacing stale %s SA",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("replacing stale %s SA", ((st)->st_clonedfrom == 0) ? "ISAKMP" : "IPsec"); } } | |||
292 | IS_IKE_SA(st) ? "ISAKMP" : "IPsec"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("replacing stale %s SA", ((st)->st_clonedfrom == 0) ? "ISAKMP" : "IPsec"); } }; | |||
293 | /* | |||
294 | * XXX: this call gets double billed - | |||
295 | * both to the state being deleted and | |||
296 | * to the new state being created. | |||
297 | */ | |||
298 | ipsecdoi_replace(st, 1); | |||
299 | } | |||
300 | ||||
301 | event_delete(EVENT_v2_LIVENESS, st); | |||
302 | event_delete(EVENT_DPD, st); | |||
303 | event_schedule(EVENT_SA_EXPIRE, st->st_replace_margin, st); | |||
304 | break; | |||
305 | default: | |||
306 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection ->ike_version), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 306, } ; &here; })); | |||
307 | } | |||
308 | break; | |||
309 | ||||
310 | case EVENT_SA_EXPIRE: | |||
311 | { | |||
312 | struct connection *c = st->st_connection; | |||
313 | const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD"; | |||
314 | so_serial_t newer_sa = get_newer_sa_from_connection(st); | |||
315 | ||||
316 | if (newer_sa != SOS_NOBODY0) { | |||
317 | /* not very interesting: already superseded */ | |||
318 | dbg("%s SA expired (superseded by #%lu)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s SA expired (superseded by #%lu)", satype, newer_sa ); } } | |||
319 | satype, newer_sa){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s SA expired (superseded by #%lu)", satype, newer_sa ); } }; | |||
320 | } else if (!IS_IKE_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) && | |||
321 | !IS_V1_ISAKMP_SA_ESTABLISHED(st)((((lset_t)1 << ((st)->st_state->kind)) & ((( lset_t)1 << (STATE_MAIN_R3)) | ((lset_t)1 << (STATE_MAIN_I4 )) | ((lset_t)1 << (STATE_AGGR_I2)) | ((lset_t)1 << (STATE_AGGR_R2)) | ((lset_t)1 << (STATE_XAUTH_R0)) | ( (lset_t)1 << (STATE_XAUTH_R1)) | ((lset_t)1 << (STATE_MODE_CFG_R0 )) | ((lset_t)1 << (STATE_MODE_CFG_R1)) | ((lset_t)1 << (STATE_MODE_CFG_R2)) | ((lset_t)1 << (STATE_MODE_CFG_I1 )) | ((lset_t)1 << (STATE_XAUTH_I0)) | ((lset_t)1 << (STATE_XAUTH_I1)))) != ((lset_t)0))) { | |||
322 | /* not very interesting: failed IKE attempt */ | |||
323 | dbg("un-established partial Child SA timeout (SA expired)"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("un-established partial Child SA timeout (SA expired)" ); } }; | |||
324 | pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT); | |||
325 | } else { | |||
326 | log_state(RC_LOG, st, "%s SA expired (%s)", satype, | |||
327 | (c->policy & POLICY_DONT_REKEY((lset_t)1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!"); | |||
328 | } | |||
329 | ||||
330 | /* Delete this state object. It must be in the hash table. */ | |||
331 | switch (st->st_ike_versionst_connection->ike_version) { | |||
332 | case IKEv2: | |||
333 | { | |||
334 | struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 334, }; &here; })); | |||
335 | if (ike == NULL((void*)0)) { | |||
336 | /* | |||
337 | * XXX: SNAFU with IKE SA replacing | |||
338 | * itself (but not deleting its | |||
339 | * children?) simultaneous to a CHILD | |||
340 | * SA failing to establish and | |||
341 | * attempting to delete / replace | |||
342 | * itself? | |||
343 | * | |||
344 | * Because these things are | |||
345 | * not serialized it is hard | |||
346 | * to say. | |||
347 | */ | |||
348 | log_state(RC_LOG_SERIOUS, st, "Child SA lost its IKE SA #%lu", | |||
349 | st->st_clonedfrom); | |||
350 | delete_state(st); | |||
351 | st = NULL((void*)0); | |||
352 | } else if (IS_IKE_SA(st)((st)->st_clonedfrom == 0)) { | |||
353 | /* IKEv2 parent, delete children too */ | |||
354 | dbg("IKEv2 SA expired, delete whole family"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("IKEv2 SA expired, delete whole family"); } }; | |||
355 | passert(&ike->sa == st)({ _Bool assertion__ = &ike->sa == st; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 355, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "&ike->sa == st"); } (void) 1; }); | |||
356 | delete_ike_family(ike, PROBABLY_SEND_DELETE); | |||
357 | /* note: no md->st to clear */ | |||
358 | st = NULL((void*)0); | |||
359 | } else if (IS_IKE_SA_ESTABLISHED(&ike->sa)((&ike->sa)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA )) { | |||
360 | /* note: no md->st to clear */ | |||
361 | submit_v2_delete_exchange(ike, pexpect_child_sa(st)); | |||
362 | st = NULL((void*)0); | |||
363 | } else { | |||
364 | delete_state(st); | |||
365 | st = NULL((void*)0); | |||
366 | } | |||
367 | break; | |||
368 | } | |||
369 | case IKEv1: | |||
370 | delete_state(st); | |||
371 | /* note: no md->st to clear */ | |||
372 | /* st = NULL; */ | |||
373 | break; | |||
374 | default: | |||
375 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection ->ike_version), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 375, } ; &here; })); | |||
376 | } | |||
377 | break; | |||
378 | } | |||
379 | ||||
380 | case EVENT_SA_DISCARD: | |||
381 | /* | |||
382 | * The state failed to complete within a reasonable | |||
383 | * time, or the state failed but was left to live for | |||
384 | * a while so re-transmits could work, or the state is | |||
385 | * being garbage collected. Either way, time to | |||
386 | * delete it. | |||
387 | */ | |||
388 | if (deltatime_cmp(event_delay, >, deltatime_zero)(deltatime_sub_sign(event_delay, deltatime_zero) > 0)) { | |||
389 | /* Don't bother logging 0 delay */ | |||
390 | deltatime_buf dtb; | |||
391 | log_state(RC_LOG, st, "deleting incomplete state after %s seconds", | |||
392 | str_deltatime(event_delay, &dtb)); | |||
393 | } | |||
394 | /* | |||
395 | * If no other reason has been given then this is a | |||
396 | * timeout. | |||
397 | */ | |||
398 | pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT); | |||
399 | /* | |||
400 | * XXX: this is scary overkill - delete_state() likes | |||
401 | * to resurect things and/or send messages. What's | |||
402 | * needed is a lower-level discard_state() that just | |||
403 | * does its job. | |||
404 | * | |||
405 | * XXX: for IKEv2, it looks like delete_state() will | |||
406 | * stop spontaneously sending messages (and hopefully | |||
407 | * spontaneously deleting IKE families). | |||
408 | */ | |||
409 | delete_state(st); | |||
410 | break; | |||
411 | ||||
412 | case EVENT_v2_REDIRECT: | |||
413 | initiate_redirect(st); | |||
414 | break; | |||
415 | ||||
416 | #ifdef USE_IKEv11 | |||
417 | case EVENT_DPD: | |||
418 | dpd_event(st); | |||
419 | break; | |||
420 | ||||
421 | case EVENT_DPD_TIMEOUT: | |||
422 | dpd_timeout(st); | |||
423 | break; | |||
424 | ||||
425 | #ifdef USE_PAM_AUTH1 | |||
426 | case EVENT_PAM_TIMEOUT: | |||
427 | dbg("PAM thread timeout on state #%lu", st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("PAM thread timeout on state #%lu", st->st_serialno ); } }; | |||
428 | pam_auth_abort(st, "timeout"); | |||
429 | /* | |||
430 | * Things get cleaned up when the PAM process exits. | |||
431 | * | |||
432 | * Should this schedule an event for the case when the | |||
433 | * child process (which is SIGKILLed) doesn't exit!?! | |||
434 | */ | |||
435 | break; | |||
436 | #endif | |||
437 | #endif | |||
438 | case EVENT_CRYPTO_TIMEOUT: | |||
439 | dbg("event crypto_failed on state #%lu, aborting",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("event crypto_failed on state #%lu, aborting", st->st_serialno); } } | |||
440 | st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("event crypto_failed on state #%lu, aborting", st->st_serialno); } }; | |||
441 | pstat_sa_failed(st, REASON_CRYPTO_TIMEOUT); | |||
442 | delete_state(st); | |||
443 | /* note: no md->st to clear */ | |||
444 | break; | |||
445 | ||||
446 | ||||
447 | default: | |||
448 | bad_case(event_type)libreswan_bad_case("event_type", (event_type), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c" , .line = 448, }; &here; })); | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | /* | |||
453 | * Delete all of the lifetime events (if any). | |||
454 | * | |||
455 | * Most lifetime events (things that kill the state) try to share a | |||
456 | * single .st_event. However, there has been and likely will be | |||
457 | * exceptions (for instance the retransmit timer), and the code below | |||
458 | * is written to deal with it. | |||
459 | * | |||
460 | * XXX: | |||
461 | * | |||
462 | * The decision to have all the loosely lifetime related timers | |||
463 | * (retransmit, rekey, replace, ...) share a single .st_event field is | |||
464 | * ... unfortunate. The code has to constantly juggle the field | |||
465 | * deciding which event is next. Far easier to set and forget each | |||
466 | * independently. This is why the retransmit timer has been split | |||
467 | * off. | |||
468 | */ | |||
469 | void delete_event(struct state *st) | |||
470 | { | |||
471 | struct liveness { | |||
472 | const char *name; | |||
473 | struct state_event **event; | |||
474 | } events[] = { | |||
475 | { "st_event", &st->st_event, }, | |||
476 | }; | |||
477 | for (unsigned e = 0; e < elemsof(events)(sizeof(events) / sizeof(*(events))); e++) { | |||
478 | struct liveness *l = &events[e]; | |||
479 | if (*(l->event) == NULL((void*)0)) { | |||
480 | dbg("state #%lu has no .%s to delete", st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu has no .%s to delete", st->st_serialno , l->name); } } | |||
481 | l->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu has no .%s to delete", st->st_serialno , l->name); } }; | |||
482 | } else { | |||
483 | esb_buf b; | |||
484 | dbg("state #%lu deleting .%s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno , l->name, enum_show(&event_type_names, (*l->event) ->ev_type, &b)); } } | |||
485 | st->st_serialno, l->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno , l->name, enum_show(&event_type_names, (*l->event) ->ev_type, &b)); } } | |||
486 | enum_show(&event_type_names, (*l->event)->ev_type, &b)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno , l->name, enum_show(&event_type_names, (*l->event) ->ev_type, &b)); } }; | |||
487 | delete_pluto_event(l->event); | |||
488 | } | |||
489 | } | |||
490 | } | |||
491 | ||||
492 | /* | |||
493 | * This routine schedules a state event. | |||
494 | */ | |||
495 | void event_schedule(enum event_type type, deltatime_t delay, struct state *st) | |||
496 | { | |||
497 | passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/timer.c", .line = 497, }; &here ; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "st != ((void*)0)"); } (void) 1; }); | |||
498 | /* | |||
499 | * Scheduling a month into the future is most likely a bug. | |||
500 | * pexpect() causes us to flag this in our test cases | |||
501 | */ | |||
502 | pexpect(deltasecs(delay) < secs_per_day * 31)({ _Bool assertion__ = deltasecs(delay) < secs_per_day * 31 ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 502, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "deltasecs(delay) < secs_per_day * 31" ); } assertion__; }); | |||
503 | ||||
504 | const char *en = enum_name(&event_type_names, type); | |||
505 | ||||
506 | struct state_event **evp = state_event(st, type); | |||
507 | if (evp == NULL((void*)0)) { | |||
508 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 508, }; &here; }), | |||
509 | "#%lu has no .st_*event field for %s", | |||
510 | st->st_serialno, | |||
511 | enum_name(&event_type_names, type)); | |||
512 | return; | |||
513 | } | |||
514 | ||||
515 | if (*evp != NULL((void*)0)) { | |||
516 | /* help debugging by stumbling on */ | |||
517 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 517, }; &here; }), | |||
518 | "#%lu already has a scheduled %s; forcing replacement", | |||
519 | st->st_serialno, | |||
520 | enum_name(&event_type_names, type)); | |||
521 | delete_pluto_event(evp); | |||
522 | } | |||
523 | ||||
524 | struct state_event *ev = alloc_thing(struct state_event, en)((struct state_event*) alloc_bytes(sizeof(struct state_event) , (en))); | |||
525 | dbg("%s: newref %s-pe@%p", __func__, en, ev){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: newref %s-pe@%p", __func__, en, ev); } }; | |||
526 | ev->ev_type = type; | |||
527 | ev->ev_name = en; | |||
528 | ev->ev_state = st; | |||
529 | ev->ev_epoch = mononow(); | |||
530 | ev->ev_delay = delay; | |||
531 | ev->ev_time = monotime_add(ev->ev_epoch, delay); | |||
532 | *evp = ev; | |||
533 | ||||
534 | deltatime_buf buf; | |||
535 | dbg("inserting event %s, timeout in %s seconds for #%lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu" , en, str_deltatime(delay, &buf), ev->ev_state->st_serialno ); } } | |||
536 | en, str_deltatime(delay, &buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu" , en, str_deltatime(delay, &buf), ev->ev_state->st_serialno ); } } | |||
537 | ev->ev_state->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu" , en, str_deltatime(delay, &buf), ev->ev_state->st_serialno ); } }; | |||
538 | ||||
539 | fire_timer_photon_torpedo(&ev->ev, timer_event_cb, ev, delay); | |||
540 | } | |||
541 | ||||
542 | /* | |||
543 | * Delete a state backlinked event (if any); leave *evp == NULL. | |||
544 | */ | |||
545 | void event_delete(enum event_type type, struct state *st) | |||
546 | { | |||
547 | struct state_event **evp = state_event(st, type); | |||
548 | if (evp == NULL((void*)0)) { | |||
549 | pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 549, }; &here; }), | |||
| ||||
550 | "#%lu has no .st_event field for %s", | |||
551 | st->st_serialno, enum_name(&event_type_names, type)); | |||
552 | return; | |||
553 | } | |||
554 | if (*evp != NULL((void*)0)) { | |||
555 | dbg("#%lu requesting %s-pe@%p be deleted",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu requesting %s-pe@%p be deleted", st-> st_serialno, enum_name(&event_type_names, (*evp)->ev_type ), *evp); } } | |||
556 | st->st_serialno, enum_name(&event_type_names, (*evp)->ev_type), *evp){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu requesting %s-pe@%p be deleted", st-> st_serialno, enum_name(&event_type_names, (*evp)->ev_type ), *evp); } }; | |||
557 | pexpect(st == (*evp)->ev_state)({ _Bool assertion__ = st == (*evp)->ev_state; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 557, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "st == (*evp)->ev_state" ); } assertion__; }); | |||
558 | delete_pluto_event(evp); | |||
559 | pexpect((*evp) == NULL)({ _Bool assertion__ = (*evp) == ((void*)0); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/timer.c", .line = 559, } ; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "(*evp) == ((void*)0)"); } assertion__; }); | |||
560 | }; | |||
561 | } | |||
562 | ||||
563 | void event_force(enum event_type type, struct state *st) | |||
564 | { | |||
565 | event_delete(type, st); | |||
| ||||
566 | deltatime_t delay = deltatime(0); | |||
567 | event_schedule(type, delay, st); | |||
568 | } | |||
569 | ||||
570 | void call_state_event_handler(struct logger *logger, struct state *st, | |||
571 | enum event_type event_type) | |||
572 | { | |||
573 | const char *event_name = enum_name_short(&event_type_names, event_type); | |||
574 | if (event_name == NULL((void*)0)) { | |||
575 | llog(RC_COMMENT, logger, "%d is not a valid event", event_type); | |||
576 | return; | |||
577 | } | |||
578 | ||||
579 | /* sanity checks */ | |||
580 | struct state_event **evp = state_event(st, event_type); | |||
581 | if (evp == NULL((void*)0)) { | |||
582 | llog(RC_COMMENT, logger, "%s is not a valid event", event_name); | |||
583 | return; | |||
584 | } | |||
585 | ||||
586 | /* | |||
587 | * Like timer_event_cb(), delete the old event before calling | |||
588 | * the event handler. | |||
589 | */ | |||
590 | deltatime_t event_delay = deltatime(1); | |||
591 | if (*evp == NULL((void*)0)) { | |||
592 | llog(RC_COMMENT, logger, | |||
593 | "no existing %s event to delete", event_name); | |||
594 | } else if ((*evp)->ev_type != event_type) { | |||
595 | llog(RC_COMMENT, logger, | |||
596 | "deleting existing %s event occupying the slot shared with %s", | |||
597 | enum_name(&event_type_names, (*evp)->ev_type), | |||
598 | event_name); | |||
599 | delete_pluto_event(evp); | |||
600 | } else { | |||
601 | llog(RC_COMMENT, logger, | |||
602 | "deleting existing %s event", | |||
603 | event_name); | |||
604 | event_delay = (*evp)->ev_delay; | |||
605 | delete_pluto_event(evp); | |||
606 | } | |||
607 | ||||
608 | llog(RC_COMMENT, logger, "calling %s event handler", event_name); | |||
609 | dispatch_event(st, event_type, event_delay); | |||
610 | } |