File: | programs/pluto/timer.c |
Warning: | line 538, 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 "pluto_crypt.h" /* for pluto_crypto_req & pluto_crypto_req_cont */ | |||
54 | #include "ikev1_dpd.h" | |||
55 | #include "ikev2.h" | |||
56 | #include "ikev2_redirect.h" | |||
57 | #include "pending.h" /* for flush_pending_by_connection */ | |||
58 | #include "ikev1_xauth.h" | |||
59 | #include "xauth.h" | |||
60 | #include "kernel.h" /* for kernel_ops */ | |||
61 | #include "nat_traversal.h" | |||
62 | #include "pluto_sd.h" | |||
63 | #include "retry.h" | |||
64 | #include "fetch.h" /* for check_crls() */ | |||
65 | #include "pluto_stats.h" | |||
66 | #include "iface.h" | |||
67 | #include "ikev2_liveness.h" | |||
68 | ||||
69 | struct pluto_event **state_event(struct state *st, enum event_type type) | |||
70 | { | |||
71 | /* | |||
72 | * Return a pointer to the event in the state object. | |||
73 | * | |||
74 | * XXX: why not just have an array and index it by KIND? | |||
75 | */ | |||
76 | switch (type) { | |||
77 | case EVENT_v2_ADDR_CHANGE: | |||
78 | return &st->st_addr_change_event; | |||
79 | break; | |||
80 | ||||
81 | case EVENT_DPD: | |||
82 | case EVENT_DPD_TIMEOUT: | |||
83 | return &st->st_dpd_event; | |||
84 | ||||
85 | case EVENT_v2_LIVENESS: | |||
86 | return &st->st_liveness_event; | |||
87 | ||||
88 | case EVENT_v2_RELEASE_WHACK: | |||
89 | return &st->st_rel_whack_event; | |||
90 | ||||
91 | case EVENT_v1_SEND_XAUTH: | |||
92 | return &st->st_send_xauth_event; | |||
93 | ||||
94 | case EVENT_RETRANSMIT: | |||
95 | return &st->st_retransmit_event; | |||
96 | ||||
97 | case EVENT_SO_DISCARD: | |||
98 | case EVENT_SA_REKEY: | |||
99 | case EVENT_SA_REPLACE: | |||
100 | case EVENT_SA_EXPIRE: | |||
101 | case EVENT_v1_SA_REPLACE_IF_USED: | |||
102 | case EVENT_CRYPTO_TIMEOUT: | |||
103 | case EVENT_PAM_TIMEOUT: | |||
104 | case EVENT_v2_INITIATE_CHILD: | |||
105 | case EVENT_v2_REDIRECT: | |||
106 | /* | |||
107 | * Many of these don't make sense - however that's | |||
108 | * what happens when (the replaced) default: is used. | |||
109 | */ | |||
110 | return &st->st_event; | |||
111 | ||||
112 | case EVENT_RETAIN: | |||
113 | case EVENT_NULL: | |||
114 | return NULL((void*)0); | |||
115 | } | |||
116 | bad_case(type)libreswan_bad_case("type", (type), (where_t) { .func = __func__ , .basename = "timer.c" , .line = 116}); | |||
117 | } | |||
118 | ||||
119 | /* | |||
120 | * This file has the event handling routines. Events are | |||
121 | * kept as a linked list of event structures. These structures | |||
122 | * have information like event type, expiration time and a pointer | |||
123 | * to event specific data (for example, to a state structure). | |||
124 | */ | |||
125 | ||||
126 | static event_callback_routine timer_event_cb; | |||
127 | static void timer_event_cb(evutil_socket_tint unused_fd UNUSED__attribute__ ((unused)), | |||
128 | const short unused_event UNUSED__attribute__ ((unused)), | |||
129 | void *arg) | |||
130 | { | |||
131 | threadtime_t inception = threadtime_start(); | |||
132 | ||||
133 | /* | |||
134 | * Get rid of the old timer event before calling the timer | |||
135 | * event processor (was deleting the old timer after calling | |||
136 | * the processor giving the impression that the processor's | |||
137 | * just created event was being deleted). | |||
138 | */ | |||
139 | struct state *st; | |||
140 | enum event_type type; | |||
141 | const char *event_name; | |||
142 | { | |||
143 | struct pluto_event *ev = arg; | |||
144 | dbg("%s: processing event@%p", __func__, ev){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: processing event@%p", __func__, ev); } }; | |||
145 | passert(ev != NULL){ _Bool assertion__ = ev != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "timer.c" , .line = 145}, "%s", "ev != NULL"); } }; | |||
146 | type = ev->ev_type; | |||
147 | event_name = enum_short_name(&timer_event_names, type); | |||
148 | st = ev->ev_state; /* note: *st might be changed; XXX: why? */ | |||
149 | passert(st != NULL){ _Bool assertion__ = st != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "timer.c" , .line = 149}, "%s", "st != NULL"); } }; | |||
150 | ||||
151 | dbg("handling event %s for %s state #%lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("handling event %s for %s state #%lu", enum_show (&timer_event_names, type), (st->st_clonedfrom == 0) ? "parent" : "child", st->st_serialno); } } | |||
152 | enum_show(&timer_event_names, type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("handling event %s for %s state #%lu", enum_show (&timer_event_names, type), (st->st_clonedfrom == 0) ? "parent" : "child", st->st_serialno); } } | |||
153 | (st->st_clonedfrom == SOS_NOBODY) ? "parent" : "child",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("handling event %s for %s state #%lu", enum_show (&timer_event_names, type), (st->st_clonedfrom == 0) ? "parent" : "child", st->st_serialno); } } | |||
154 | st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("handling event %s for %s state #%lu", enum_show (&timer_event_names, type), (st->st_clonedfrom == 0) ? "parent" : "child", st->st_serialno); } }; | |||
155 | ||||
156 | #if 0 | |||
157 | /* | |||
158 | * XXX: this line, which is a merger of the above two | |||
159 | * lines, leaks into the expected test output causing | |||
160 | * failures. | |||
161 | */ | |||
162 | 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 ); } } | |||
163 | __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 ); } } | |||
164 | 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 ); } } | |||
165 | 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 ); } }; | |||
166 | #endif | |||
167 | ||||
168 | struct pluto_event **evp = state_event(st, type); | |||
169 | if (evp == NULL((void*)0)) { | |||
170 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 170}, | |||
171 | "#%lu has no .st_event field for %s", | |||
172 | st->st_serialno, enum_name(&timer_event_names, type)); | |||
173 | return; | |||
174 | } | |||
175 | if (*evp != ev) { | |||
176 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 176}, | |||
177 | "#%lu .st_event is %p but should be %s-pe@%p", | |||
178 | st->st_serialno, *evp, | |||
179 | enum_name(&timer_event_names, (*evp)->ev_type), | |||
180 | ev); | |||
181 | return; | |||
182 | } | |||
183 | delete_pluto_event(evp); | |||
184 | arg = ev = *evp = NULL((void*)0); /* all gone */ | |||
185 | } | |||
186 | ||||
187 | pexpect_reset_globals()log_pexpect_reset_globals((where_t) { .func = __func__, .basename = "timer.c" , .line = 187}); | |||
188 | so_serial_t old_state = push_cur_state(st)log_push_state(st, (where_t) { .func = __func__, .basename = "timer.c" , .line = 188}); | |||
189 | pexpect(old_state == SOS_NOBODY)({ _Bool assertion__ = old_state == 0; if (!assertion__) { log_pexpect ((where_t) { .func = __func__, .basename = "timer.c" , .line = 189}, "%s", "old_state == SOS_NOBODY"); } assertion__; }); /* since globals are reset */ | |||
190 | statetime_t start = statetime_backdate(st, &inception); | |||
191 | ||||
192 | /* | |||
193 | * Check that st is as expected for the event type. | |||
194 | * | |||
195 | * For an event type associated with a state, remove the | |||
196 | * backpointer from the appropriate slot of the state object. | |||
197 | * | |||
198 | * We'll eventually either schedule a new event, or delete the | |||
199 | * state. | |||
200 | */ | |||
201 | switch (type) { | |||
202 | ||||
203 | case EVENT_v2_ADDR_CHANGE: | |||
204 | 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 ); } }; | |||
205 | ikev2_addr_change(st); | |||
206 | break; | |||
207 | ||||
208 | case EVENT_v2_RELEASE_WHACK: | |||
209 | dbg("%s releasing whack for #%lu %s (sock="PRI_FD")",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s releasing whack for #%lu %s (sock=""fd-fd@%p" ")", enum_show(&timer_event_names, type), st->st_serialno , st->st_state->name, (st->st_logger->object_whackfd )); } } | |||
210 | enum_show(&timer_event_names, type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s releasing whack for #%lu %s (sock=""fd-fd@%p" ")", enum_show(&timer_event_names, type), st->st_serialno , st->st_state->name, (st->st_logger->object_whackfd )); } } | |||
211 | st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s releasing whack for #%lu %s (sock=""fd-fd@%p" ")", enum_show(&timer_event_names, type), st->st_serialno , st->st_state->name, (st->st_logger->object_whackfd )); } } | |||
212 | st->st_state->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s releasing whack for #%lu %s (sock=""fd-fd@%p" ")", enum_show(&timer_event_names, type), st->st_serialno , st->st_state->name, (st->st_logger->object_whackfd )); } } | |||
213 | pri_fd(st->st_whack_sock)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s releasing whack for #%lu %s (sock=""fd-fd@%p" ")", enum_show(&timer_event_names, type), st->st_serialno , st->st_state->name, (st->st_logger->object_whackfd )); } }; | |||
214 | release_pending_whacks(st, "release whack"); | |||
215 | break; | |||
216 | ||||
217 | case EVENT_RETRANSMIT: | |||
218 | 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_ike_version ); } }; | |||
219 | switch (st->st_ike_version) { | |||
220 | case IKEv2: | |||
221 | retransmit_v2_msg(st); | |||
222 | break; | |||
223 | case IKEv1: | |||
224 | retransmit_v1_msg(st); | |||
225 | break; | |||
226 | default: | |||
227 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_ike_version ), (where_t) { .func = __func__, .basename = "timer.c" , .line = 227}); | |||
228 | } | |||
229 | break; | |||
230 | ||||
231 | case EVENT_v1_SEND_XAUTH: | |||
232 | 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); } } | |||
233 | 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); } }; | |||
234 | xauth_send_request(st); | |||
235 | break; | |||
236 | ||||
237 | case EVENT_v2_INITIATE_CHILD: | |||
238 | ikev2_child_outI(st); | |||
239 | break; | |||
240 | ||||
241 | case EVENT_v2_LIVENESS: | |||
242 | liveness_check(st); | |||
243 | break; | |||
244 | ||||
245 | case EVENT_SA_REKEY: | |||
246 | pexpect(st->st_ike_version == IKEv2)({ _Bool assertion__ = st->st_ike_version == IKEv2; if (!assertion__ ) { log_pexpect((where_t) { .func = __func__, .basename = "timer.c" , .line = 246}, "%s", "st->st_ike_version == IKEv2"); } assertion__ ; }); | |||
247 | v2_event_sa_rekey(st); | |||
248 | break; | |||
249 | ||||
250 | case EVENT_SA_REPLACE: | |||
251 | case EVENT_v1_SA_REPLACE_IF_USED: | |||
252 | switch (st->st_ike_version) { | |||
253 | case IKEv2: | |||
254 | pexpect(type == EVENT_SA_REPLACE)({ _Bool assertion__ = type == EVENT_SA_REPLACE; if (!assertion__ ) { log_pexpect((where_t) { .func = __func__, .basename = "timer.c" , .line = 254}, "%s", "type == EVENT_SA_REPLACE"); } assertion__ ; }); | |||
255 | v2_event_sa_replace(st); | |||
256 | break; | |||
257 | case IKEv1: | |||
258 | pexpect(type == EVENT_SA_REPLACE ||({ _Bool assertion__ = type == EVENT_SA_REPLACE || type == EVENT_v1_SA_REPLACE_IF_USED ; if (!assertion__) { log_pexpect((where_t) { .func = __func__ , .basename = "timer.c" , .line = 259}, "%s", "type == EVENT_SA_REPLACE || type == EVENT_v1_SA_REPLACE_IF_USED" ); } assertion__; }) | |||
259 | type == EVENT_v1_SA_REPLACE_IF_USED)({ _Bool assertion__ = type == EVENT_SA_REPLACE || type == EVENT_v1_SA_REPLACE_IF_USED ; if (!assertion__) { log_pexpect((where_t) { .func = __func__ , .basename = "timer.c" , .line = 259}, "%s", "type == EVENT_SA_REPLACE || type == EVENT_v1_SA_REPLACE_IF_USED" ); } assertion__; }); | |||
260 | struct connection *c = st->st_connection; | |||
261 | const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD"; | |||
262 | ||||
263 | so_serial_t newer_sa = get_newer_sa_from_connection(st); | |||
264 | if (newer_sa != SOS_NOBODY0) { | |||
265 | /* not very interesting: no need to replace */ | |||
266 | 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); } } | |||
267 | 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); } }; | |||
268 | } else if (type == EVENT_v1_SA_REPLACE_IF_USED && | |||
269 | !monobefore(mononow(), monotime_add(st->st_outbound_time, c->sa_rekey_margin))) { | |||
270 | /* | |||
271 | * we observed no recent use: no need to replace | |||
272 | * | |||
273 | * The sampling effects mean that st_outbound_time | |||
274 | * could be up to SHUNT_SCAN_INTERVAL more recent | |||
275 | * than actual traffic because the sampler looks at | |||
276 | * change over that interval. | |||
277 | * st_outbound_time could also not yet reflect traffic | |||
278 | * in the last SHUNT_SCAN_INTERVAL. | |||
279 | * We expect that SHUNT_SCAN_INTERVAL is smaller than | |||
280 | * c->sa_rekey_margin so that the effects of this will | |||
281 | * be unimportant. | |||
282 | * This is just an optimization: correctness is not | |||
283 | * at stake. | |||
284 | */ | |||
285 | 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 ))); } } | |||
286 | 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 ))); } }; | |||
287 | } else { | |||
288 | 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"); } } | |||
289 | 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"); } }; | |||
290 | /* | |||
291 | * XXX: this call gets double billed - | |||
292 | * both to the state being deleted and | |||
293 | * to the new state being created. | |||
294 | */ | |||
295 | ipsecdoi_replace(st, 1); | |||
296 | } | |||
297 | ||||
298 | event_delete(EVENT_v2_LIVENESS, st); | |||
299 | event_delete(EVENT_DPD, st); | |||
300 | event_schedule(EVENT_SA_EXPIRE, st->st_replace_margin, st); | |||
301 | break; | |||
302 | default: | |||
303 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_ike_version ), (where_t) { .func = __func__, .basename = "timer.c" , .line = 303}); | |||
304 | } | |||
305 | break; | |||
306 | ||||
307 | case EVENT_SA_EXPIRE: | |||
308 | { | |||
309 | struct connection *c = st->st_connection; | |||
310 | const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD"; | |||
311 | so_serial_t newer_sa = get_newer_sa_from_connection(st); | |||
312 | ||||
313 | if (newer_sa != SOS_NOBODY0) { | |||
314 | /* not very interesting: already superseded */ | |||
315 | 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 ); } } | |||
316 | satype, newer_sa){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s SA expired (superseded by #%lu)", satype, newer_sa ); } }; | |||
317 | } else if (!IS_IKE_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)1 << (STATE_V2_ESTABLISHED_IKE_SA )))) != ((lset_t)0)) || ((((st)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA ) && !((st)->st_clonedfrom != 0)) && ((st) ->st_clonedfrom == 0)))) { | |||
318 | /* not very interesting: failed IKE attempt */ | |||
319 | dbg("un-established partial CHILD SA timeout (%s)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("un-established partial CHILD SA timeout (%s)" , type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout" ); } } | |||
320 | type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("un-established partial CHILD SA timeout (%s)" , type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout" ); } }; | |||
321 | pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT); | |||
322 | } else { | |||
323 | libreswan_log("%s %s (%s)", satype,loglog(RC_LOG, "%s %s (%s)", satype, type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout", (c->policy & ((lset_t )1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!" ) | |||
324 | type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout",loglog(RC_LOG, "%s %s (%s)", satype, type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout", (c->policy & ((lset_t )1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!" ) | |||
325 | (c->policy & POLICY_DONT_REKEY) ?loglog(RC_LOG, "%s %s (%s)", satype, type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout", (c->policy & ((lset_t )1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!" ) | |||
326 | "--dontrekey" : "LATEST!")loglog(RC_LOG, "%s %s (%s)", satype, type == EVENT_SA_EXPIRE ? "SA expired" : "Responder timeout", (c->policy & ((lset_t )1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!" ); | |||
327 | } | |||
328 | ||||
329 | /* Delete this state object. It must be in the hash table. */ | |||
330 | switch (st->st_ike_version) { | |||
331 | case IKEv2: | |||
332 | if (IS_IKE_SA(st)((st)->st_clonedfrom == 0)) { | |||
333 | /* IKEv2 parent, delete children too */ | |||
334 | delete_ike_family(pexpect_ike_sa(st), | |||
335 | PROBABLY_SEND_DELETE); | |||
336 | /* note: no md->st to clear */ | |||
337 | } else { | |||
338 | struct ike_sa *ike = ike_sa(st, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 338}); | |||
339 | if (ike == NULL((void*)0)) { | |||
340 | /* | |||
341 | * XXX: SNAFU with IKE SA | |||
342 | * replacing itself (but not | |||
343 | * deleting its children?) | |||
344 | * simultaneous to a CHILD SA | |||
345 | * failing to establish and | |||
346 | * attempting to delete / | |||
347 | * replace itself? | |||
348 | * | |||
349 | * Because these things are | |||
350 | * not serialized it is hard | |||
351 | * to say. | |||
352 | */ | |||
353 | loglog(RC_LOG_SERIOUS, "CHILD SA #%lu lost its IKE SA", | |||
354 | st->st_serialno); | |||
355 | delete_state(st); | |||
356 | st = NULL((void*)0); | |||
357 | } else { | |||
358 | /* note: no md->st to clear */ | |||
359 | passert(st != &ike->sa){ _Bool assertion__ = st != &ike->sa; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "timer.c" , .line = 359}, "%s", "st != &ike->sa"); } }; | |||
360 | schedule_next_child_delete(st, ike); | |||
361 | st = NULL((void*)0); | |||
362 | } | |||
363 | } | |||
364 | break; | |||
365 | case IKEv1: | |||
366 | delete_state(st); | |||
367 | /* note: no md->st to clear */ | |||
368 | /* st = NULL; */ | |||
369 | break; | |||
370 | default: | |||
371 | bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_ike_version ), (where_t) { .func = __func__, .basename = "timer.c" , .line = 371}); | |||
372 | } | |||
373 | break; | |||
374 | } | |||
375 | ||||
376 | case EVENT_SO_DISCARD: | |||
377 | /* | |||
378 | * The state failed to complete within a reasonable | |||
379 | * time, or the state failed but was left to live for | |||
380 | * a while so re-transmits could work. Either way, | |||
381 | * time to delete it. | |||
382 | */ | |||
383 | passert(st != NULL){ _Bool assertion__ = st != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "timer.c" , .line = 383}, "%s", "st != NULL"); } }; | |||
384 | deltatime_t timeout = (st->st_ike_version == IKEv2 ? MAXIMUM_RESPONDER_WAIT_DELAYdeltatime(200) : | |||
385 | st->st_connection->r_timeout); | |||
386 | deltatime_buf dtb; | |||
387 | libreswan_log("deleting incomplete state after %s seconds",loglog(RC_LOG, "deleting incomplete state after %s seconds", str_deltatime (timeout, &dtb)) | |||
388 | str_deltatime(timeout, &dtb))loglog(RC_LOG, "deleting incomplete state after %s seconds", str_deltatime (timeout, &dtb)); | |||
389 | /* | |||
390 | * If no other reason has been given then this is a | |||
391 | * timeout. | |||
392 | */ | |||
393 | pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT); | |||
394 | /* | |||
395 | * XXX: this is scary overkill - delete_state() likes | |||
396 | * to resurect things and/or send messages. What's | |||
397 | * needed is a lower-level discard_state() that just | |||
398 | * does its job. | |||
399 | */ | |||
400 | delete_state(st); | |||
401 | break; | |||
402 | ||||
403 | case EVENT_v2_REDIRECT: | |||
404 | initiate_redirect(st); | |||
405 | break; | |||
406 | ||||
407 | case EVENT_DPD: | |||
408 | dpd_event(st); | |||
409 | break; | |||
410 | ||||
411 | case EVENT_DPD_TIMEOUT: | |||
412 | dpd_timeout(st); | |||
413 | break; | |||
414 | ||||
415 | case EVENT_CRYPTO_TIMEOUT: | |||
416 | 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); } } | |||
417 | st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("event crypto_failed on state #%lu, aborting", st->st_serialno); } }; | |||
418 | pstat_sa_failed(st, REASON_CRYPTO_TIMEOUT); | |||
419 | delete_state(st); | |||
420 | /* note: no md->st to clear */ | |||
421 | break; | |||
422 | ||||
423 | #ifdef XAUTH_HAVE_PAM1 | |||
424 | case EVENT_PAM_TIMEOUT: | |||
425 | 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 ); } }; | |||
426 | xauth_pam_abort(st); | |||
427 | /* | |||
428 | * Things get cleaned up when the PAM process exits. | |||
429 | * | |||
430 | * Should this schedule an event for the case when the | |||
431 | * child process (which is SIGKILLed) doesn't exit!?! | |||
432 | */ | |||
433 | break; | |||
434 | #endif | |||
435 | ||||
436 | default: | |||
437 | bad_case(type)libreswan_bad_case("type", (type), (where_t) { .func = __func__ , .basename = "timer.c" , .line = 437}); | |||
438 | } | |||
439 | ||||
440 | statetime_stop(&start, "%s() %s", __func__, event_name); | |||
441 | pop_cur_state(old_state)log_pop_state(old_state, (where_t) { .func = __func__, .basename = "timer.c" , .line = 441}); | |||
442 | } | |||
443 | ||||
444 | /* | |||
445 | * Delete all of the lifetime events (if any). | |||
446 | * | |||
447 | * Most lifetime events (things that kill the state) try to share a | |||
448 | * single .st_event. However, there has been and likely will be | |||
449 | * exceptions (for instance the retransmit timer), and the code below | |||
450 | * is written to deal with it. | |||
451 | * | |||
452 | * XXX: | |||
453 | * | |||
454 | * The decision to have all the loosely lifetime related timers | |||
455 | * (retransmit, rekey, replace, ...) share a single .st_event field is | |||
456 | * ... unfortunate. The code has to constantly juggle the field | |||
457 | * deciding which event is next. Far easier to set and forget each | |||
458 | * independently. This is why the retransmit timer has been split | |||
459 | * off. | |||
460 | */ | |||
461 | void delete_event(struct state *st) | |||
462 | { | |||
463 | struct liveness { | |||
464 | const char *name; | |||
465 | struct pluto_event **event; | |||
466 | } events[] = { | |||
467 | { "st_event", &st->st_event, }, | |||
468 | }; | |||
469 | for (unsigned e = 0; e < elemsof(events)(sizeof(events) / sizeof(*(events))); e++) { | |||
470 | struct liveness *l = &events[e]; | |||
471 | if (*(l->event) == NULL((void*)0)) { | |||
472 | 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); } } | |||
473 | 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); } }; | |||
474 | } else { | |||
475 | 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(&timer_event_names, (*l->event )->ev_type)); } } | |||
476 | 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(&timer_event_names, (*l->event )->ev_type)); } } | |||
477 | enum_show(&timer_event_names,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno , l->name, enum_show(&timer_event_names, (*l->event )->ev_type)); } } | |||
478 | (*l->event)->ev_type)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno , l->name, enum_show(&timer_event_names, (*l->event )->ev_type)); } }; | |||
479 | delete_pluto_event(l->event); | |||
480 | } | |||
481 | } | |||
482 | } | |||
483 | ||||
484 | /* | |||
485 | * This routine schedules a state event. | |||
486 | */ | |||
487 | void event_schedule(enum event_type type, deltatime_t delay, struct state *st) | |||
488 | { | |||
489 | passert(st != NULL){ _Bool assertion__ = st != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "timer.c" , .line = 489}, "%s", "st != NULL"); } }; | |||
490 | /* | |||
491 | * Scheduling a month into the future is most likely a bug. | |||
492 | * pexpect() causes us to flag this in our test cases | |||
493 | */ | |||
494 | pexpect(deltasecs(delay) < secs_per_day * 31)({ _Bool assertion__ = deltasecs(delay) < secs_per_day * 31 ; if (!assertion__) { log_pexpect((where_t) { .func = __func__ , .basename = "timer.c" , .line = 494}, "%s", "deltasecs(delay) < secs_per_day * 31" ); } assertion__; }); | |||
495 | ||||
496 | const char *en = enum_name(&timer_event_names, type); | |||
497 | ||||
498 | struct pluto_event **evp = state_event(st, type); | |||
499 | if (evp == NULL((void*)0)) { | |||
500 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 500}, | |||
501 | "#%lu has no .st_*event field for %s", | |||
502 | st->st_serialno, | |||
503 | enum_name(&timer_event_names, type)); | |||
504 | return; | |||
505 | } | |||
506 | if (*evp != NULL((void*)0)) { | |||
507 | /* help debugging by stumbling on */ | |||
508 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 508}, | |||
509 | "#%lu already has a scheduled %s; forcing replacement", | |||
510 | st->st_serialno, | |||
511 | enum_name(&timer_event_names, type)); | |||
512 | delete_pluto_event(evp); | |||
513 | } | |||
514 | ||||
515 | struct pluto_event *ev = alloc_thing(struct pluto_event, en)((struct pluto_event*) alloc_bytes(sizeof(struct pluto_event) , (en))); | |||
516 | 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); } }; | |||
517 | ev->ev_type = type; | |||
518 | ev->ev_name = en; | |||
519 | ev->ev_state = st; | |||
520 | ev->ev_time = monotime_add(mononow(), delay); | |||
521 | *evp = ev; | |||
522 | ||||
523 | deltatime_buf buf; | |||
524 | 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 ); } } | |||
525 | 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 ); } } | |||
526 | 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 ); } }; | |||
527 | ||||
528 | fire_timer_photon_torpedo(&ev->ev, timer_event_cb, ev, delay); | |||
529 | } | |||
530 | ||||
531 | /* | |||
532 | * Delete a state backlinked event (if any); leave *evp == NULL. | |||
533 | */ | |||
534 | void event_delete(enum event_type type, struct state *st) | |||
535 | { | |||
536 | struct pluto_event **evp = state_event(st, type); | |||
537 | if (evp == NULL((void*)0)) { | |||
538 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "timer.c" , .line = 538}, | |||
| ||||
539 | "#%lu has no .st_event field for %s", | |||
540 | st->st_serialno, enum_name(&timer_event_names, type)); | |||
541 | return; | |||
542 | } | |||
543 | if (*evp != NULL((void*)0)) { | |||
544 | 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(&timer_event_names, (*evp)->ev_type ), *evp); } } | |||
545 | st->st_serialno, enum_name(&timer_event_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(&timer_event_names, (*evp)->ev_type ), *evp); } }; | |||
546 | pexpect(st == (*evp)->ev_state)({ _Bool assertion__ = st == (*evp)->ev_state; if (!assertion__ ) { log_pexpect((where_t) { .func = __func__, .basename = "timer.c" , .line = 546}, "%s", "st == (*evp)->ev_state"); } assertion__ ; }); | |||
547 | delete_pluto_event(evp); | |||
548 | pexpect((*evp) == NULL)({ _Bool assertion__ = (*evp) == ((void*)0); if (!assertion__ ) { log_pexpect((where_t) { .func = __func__, .basename = "timer.c" , .line = 548}, "%s", "(*evp) == NULL"); } assertion__; }); | |||
549 | }; | |||
550 | } | |||
551 | ||||
552 | void event_force(enum event_type type, struct state *st) | |||
553 | { | |||
554 | event_delete(type, st); | |||
| ||||
555 | deltatime_t delay = deltatime(0); | |||
556 | event_schedule(type, delay, st); | |||
557 | } | |||
558 | ||||
559 | void call_state_event_inline(struct logger *logger, struct state *st, | |||
560 | enum event_type event) | |||
561 | { | |||
562 | /* sanity checks */ | |||
563 | struct pluto_event **evp = state_event(st, event); | |||
564 | if (evp == NULL((void*)0)) { | |||
565 | log_message(RC_COMMENT, logger, "%s is not a valid event", | |||
566 | enum_name(&timer_event_names, event)); | |||
567 | return; | |||
568 | } | |||
569 | if (*evp == NULL((void*)0)) { | |||
570 | log_message(RC_COMMENT, logger, "no handler for %s", | |||
571 | enum_name(&timer_event_names, event)); | |||
572 | return; | |||
573 | } | |||
574 | if ((*evp)->ev_type != event) { | |||
575 | log_message(RC_COMMENT, logger, "handler for %s is actually %s", | |||
576 | enum_name(&timer_event_names, event), | |||
577 | enum_name(&timer_event_names, (*evp)->ev_type)); | |||
578 | return; | |||
579 | } | |||
580 | /* | |||
581 | * XXX: can this kill off the old event when it is still | |||
582 | * pending? | |||
583 | */ | |||
584 | log_message(RC_COMMENT, logger, "calling %s", | |||
585 | enum_name(&timer_event_names, event)); | |||
586 | timer_event_cb(0/*sock*/, 0/*event*/, *evp); | |||
587 | } |