| 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') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | ||||
| 61 | static 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 | ||||
| 119 | void 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 | ||||
| 132 | void 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 | ||||
| 169 | void 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 | */ | |||
| 253 | static 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 | ||||
| 300 | void unpend(struct ike_sa *ike, struct connection *cc) | |||
| 301 | { | |||
| 302 | if (cc == NULL((void*)0)) { | |||
| ||||
| 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 ); } }; | |||
| 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); | |||
| 311 | (p = *pp) != NULL((void*)0); ) { | |||
| 312 | if (p->ike == ike) { | |||
| 313 | p->pend_time = mononow(); | |||
| 314 | char *what ="unqueuing"; | |||
| 315 | switch (ike->sa.st_ike_versionst_connection->ike_version) { | |||
| 316 | case IKEv2: | |||
| 317 | if (cc == p->connection) { | |||
| 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; | |||
| 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)); } } | |||
| ||||
| 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 | ||||
| 358 | struct 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 | */ | |||
| 384 | bool_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 */ | |||
| 410 | void 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 */ | |||
| 428 | void 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 */ | |||
| 450 | void 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 | ||||
| 468 | void 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 | ||||
| 494 | bool_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 | } |