| File: | src/sbin/isakmpd/exchange.c |
| Warning: | line 1595, column 8 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: exchange.c,v 1.142 2018/01/15 09:54:48 mpi Exp $ */ | |||
| 2 | /* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */ | |||
| 3 | ||||
| 4 | /* | |||
| 5 | * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. | |||
| 6 | * Copyright (c) 1999, 2001 Angelos D. Keromytis. All rights reserved. | |||
| 7 | * Copyright (c) 1999, 2000, 2002 Håkan Olsson. All rights reserved. | |||
| 8 | * | |||
| 9 | * Redistribution and use in source and binary forms, with or without | |||
| 10 | * modification, are permitted provided that the following conditions | |||
| 11 | * are met: | |||
| 12 | * 1. Redistributions of source code must retain the above copyright | |||
| 13 | * notice, this list of conditions and the following disclaimer. | |||
| 14 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 15 | * notice, this list of conditions and the following disclaimer in the | |||
| 16 | * documentation and/or other materials provided with the distribution. | |||
| 17 | * | |||
| 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
| 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
| 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
| 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
| 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
| 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
| 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
| 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
| 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| 28 | */ | |||
| 29 | ||||
| 30 | /* | |||
| 31 | * This code was written under funding by Ericsson Radio Systems. | |||
| 32 | */ | |||
| 33 | ||||
| 34 | #include <sys/types.h> | |||
| 35 | #include <sys/socket.h> | |||
| 36 | #include <netinet/in.h> | |||
| 37 | #include <arpa/inet.h> | |||
| 38 | #include <stdlib.h> | |||
| 39 | #include <string.h> | |||
| 40 | #include <regex.h> | |||
| 41 | #include <keynote.h> | |||
| 42 | ||||
| 43 | #include "cert.h" | |||
| 44 | #include "conf.h" | |||
| 45 | #include "connection.h" | |||
| 46 | #include "constants.h" | |||
| 47 | #include "cookie.h" | |||
| 48 | #include "crypto.h" | |||
| 49 | #include "doi.h" | |||
| 50 | #include "exchange.h" | |||
| 51 | #include "ipsec_num.h" | |||
| 52 | #include "isakmp.h" | |||
| 53 | #include "isakmp_cfg.h" | |||
| 54 | #include "libcrypto.h" | |||
| 55 | #include "log.h" | |||
| 56 | #include "message.h" | |||
| 57 | #include "timer.h" | |||
| 58 | #include "transport.h" | |||
| 59 | #include "ipsec.h" | |||
| 60 | #include "sa.h" | |||
| 61 | #include "ui.h" | |||
| 62 | #include "util.h" | |||
| 63 | #include "key.h" | |||
| 64 | #include "dpd.h" | |||
| 65 | ||||
| 66 | /* Initial number of bits from the cookies used as hash. */ | |||
| 67 | #define INITIAL_BUCKET_BITS6 6 | |||
| 68 | ||||
| 69 | /* | |||
| 70 | * Don't try to use more bits than this as a hash. | |||
| 71 | * We only XOR 16 bits so going above that means changing the code below | |||
| 72 | * too. | |||
| 73 | */ | |||
| 74 | #define MAX_BUCKET_BITS16 16 | |||
| 75 | ||||
| 76 | static void exchange_dump(char *, struct exchange *); | |||
| 77 | static void exchange_free_aux(void *); | |||
| 78 | static struct exchange *exchange_lookup_active(char *, int); | |||
| 79 | ||||
| 80 | static | |||
| 81 | LIST_HEAD(exchange_list, exchange)struct exchange_list { struct exchange *lh_first; } *exchange_tab; | |||
| 82 | ||||
| 83 | /* Works both as a maximum index and a mask. */ | |||
| 84 | static int bucket_mask; | |||
| 85 | ||||
| 86 | /* | |||
| 87 | * Validation scripts used to test messages for correct content of | |||
| 88 | * payloads depending on the exchange type. | |||
| 89 | */ | |||
| 90 | int16_t script_base[] = { | |||
| 91 | ISAKMP_PAYLOAD_SA1, /* Initiator -> responder. */ | |||
| 92 | ISAKMP_PAYLOAD_NONCE10, | |||
| 93 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 94 | ISAKMP_PAYLOAD_SA1, /* Responder -> initiator. */ | |||
| 95 | ISAKMP_PAYLOAD_NONCE10, | |||
| 96 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 97 | ISAKMP_PAYLOAD_KEY_EXCH4, /* Initiator -> responder. */ | |||
| 98 | ISAKMP_PAYLOAD_ID5, | |||
| 99 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 100 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 101 | ISAKMP_PAYLOAD_KEY_EXCH4, /* Responder -> initiator. */ | |||
| 102 | ISAKMP_PAYLOAD_ID5, | |||
| 103 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 104 | EXCHANGE_SCRIPT_END-4 | |||
| 105 | }; | |||
| 106 | ||||
| 107 | int16_t script_identity_protection[] = { | |||
| 108 | ISAKMP_PAYLOAD_SA1, /* Initiator -> responder. */ | |||
| 109 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 110 | ISAKMP_PAYLOAD_SA1, /* Responder -> initiator. */ | |||
| 111 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 112 | ISAKMP_PAYLOAD_KEY_EXCH4, /* Initiator -> responder. */ | |||
| 113 | ISAKMP_PAYLOAD_NONCE10, | |||
| 114 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 115 | ISAKMP_PAYLOAD_KEY_EXCH4, /* Responder -> initiator. */ | |||
| 116 | ISAKMP_PAYLOAD_NONCE10, | |||
| 117 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 118 | ISAKMP_PAYLOAD_ID5, /* Initiator -> responder. */ | |||
| 119 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 120 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 121 | ISAKMP_PAYLOAD_ID5, /* Responder -> initiator. */ | |||
| 122 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 123 | EXCHANGE_SCRIPT_END-4 | |||
| 124 | }; | |||
| 125 | ||||
| 126 | int16_t script_authentication_only[] = { | |||
| 127 | ISAKMP_PAYLOAD_SA1, /* Initiator -> responder. */ | |||
| 128 | ISAKMP_PAYLOAD_NONCE10, | |||
| 129 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 130 | ISAKMP_PAYLOAD_SA1, /* Responder -> initiator. */ | |||
| 131 | ISAKMP_PAYLOAD_NONCE10, | |||
| 132 | ISAKMP_PAYLOAD_ID5, | |||
| 133 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 134 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 135 | ISAKMP_PAYLOAD_ID5, /* Initiator -> responder. */ | |||
| 136 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 137 | EXCHANGE_SCRIPT_END-4 | |||
| 138 | }; | |||
| 139 | ||||
| 140 | int16_t script_aggressive[] = { | |||
| 141 | ISAKMP_PAYLOAD_SA1, /* Initiator -> responder. */ | |||
| 142 | ISAKMP_PAYLOAD_KEY_EXCH4, | |||
| 143 | ISAKMP_PAYLOAD_NONCE10, | |||
| 144 | ISAKMP_PAYLOAD_ID5, | |||
| 145 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 146 | ISAKMP_PAYLOAD_SA1, /* Responder -> initiator. */ | |||
| 147 | ISAKMP_PAYLOAD_KEY_EXCH4, | |||
| 148 | ISAKMP_PAYLOAD_NONCE10, | |||
| 149 | ISAKMP_PAYLOAD_ID5, | |||
| 150 | EXCHANGE_SCRIPT_AUTH-1, | |||
| 151 | EXCHANGE_SCRIPT_SWITCH-3, | |||
| 152 | EXCHANGE_SCRIPT_AUTH-1, /* Initiator -> responder. */ | |||
| 153 | EXCHANGE_SCRIPT_END-4 | |||
| 154 | }; | |||
| 155 | ||||
| 156 | int16_t script_informational[] = { | |||
| 157 | EXCHANGE_SCRIPT_INFO-2, /* Initiator -> responder. */ | |||
| 158 | EXCHANGE_SCRIPT_END-4 | |||
| 159 | }; | |||
| 160 | ||||
| 161 | /* | |||
| 162 | * Check what exchange SA is negotiated with and return a suitable validation | |||
| 163 | * script. | |||
| 164 | */ | |||
| 165 | int16_t * | |||
| 166 | exchange_script(struct exchange *exchange) | |||
| 167 | { | |||
| 168 | switch (exchange->type) { | |||
| 169 | case ISAKMP_EXCH_BASE1: | |||
| 170 | return script_base; | |||
| 171 | case ISAKMP_EXCH_ID_PROT2: | |||
| 172 | return script_identity_protection; | |||
| 173 | case ISAKMP_EXCH_AUTH_ONLY3: | |||
| 174 | return script_authentication_only; | |||
| 175 | case ISAKMP_EXCH_AGGRESSIVE4: | |||
| 176 | return script_aggressive; | |||
| 177 | case ISAKMP_EXCH_INFO5: | |||
| 178 | return script_informational; | |||
| 179 | case ISAKMP_EXCH_TRANSACTION6: | |||
| 180 | return script_transaction; | |||
| 181 | default: | |||
| 182 | if (exchange->type >= ISAKMP_EXCH_DOI_MIN32) | |||
| 183 | return exchange->doi->exchange_script(exchange->type); | |||
| 184 | } | |||
| 185 | return 0; | |||
| 186 | } | |||
| 187 | ||||
| 188 | /* | |||
| 189 | * Validate the message MSG's contents wrt what payloads the exchange type | |||
| 190 | * requires at this point in the dialogue. Return -1 if the validation fails, | |||
| 191 | * 0 if it succeeds and the script is not finished and 1 if it's ready. | |||
| 192 | */ | |||
| 193 | static int | |||
| 194 | exchange_validate(struct message *msg) | |||
| 195 | { | |||
| 196 | struct exchange *exchange = msg->exchange; | |||
| 197 | int16_t *pc = exchange->exch_pc; | |||
| 198 | ||||
| 199 | while (*pc != EXCHANGE_SCRIPT_END-4 && *pc != EXCHANGE_SCRIPT_SWITCH-3) { | |||
| 200 | LOG_DBG((LOG_EXCHANGE, 90,log_debug (LOG_EXCHANGE, 90, "exchange_validate: checking for required %s" , *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name (exchange_script_cst, *pc)) | |||
| 201 | "exchange_validate: checking for required %s",log_debug (LOG_EXCHANGE, 90, "exchange_validate: checking for required %s" , *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name (exchange_script_cst, *pc)) | |||
| 202 | *pc >= ISAKMP_PAYLOAD_NONElog_debug (LOG_EXCHANGE, 90, "exchange_validate: checking for required %s" , *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name (exchange_script_cst, *pc)) | |||
| 203 | ? constant_name(isakmp_payload_cst, *pc)log_debug (LOG_EXCHANGE, 90, "exchange_validate: checking for required %s" , *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name (exchange_script_cst, *pc)) | |||
| 204 | : constant_name(exchange_script_cst, *pc)))log_debug (LOG_EXCHANGE, 90, "exchange_validate: checking for required %s" , *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name (exchange_script_cst, *pc)); | |||
| 205 | ||||
| 206 | /* Check for existence of the required payloads. */ | |||
| 207 | if ((*pc > 0 && !payload_first(msg, *pc)) || | |||
| 208 | (*pc == EXCHANGE_SCRIPT_AUTH-1 && | |||
| 209 | !payload_first(msg, ISAKMP_PAYLOAD_HASH8) && | |||
| 210 | !payload_first(msg, ISAKMP_PAYLOAD_SIG9)) || | |||
| 211 | (*pc == EXCHANGE_SCRIPT_INFO-2 && | |||
| 212 | ((!payload_first(msg, ISAKMP_PAYLOAD_NOTIFY11) && | |||
| 213 | !payload_first(msg, ISAKMP_PAYLOAD_DELETE12)) || | |||
| 214 | (payload_first(msg, ISAKMP_PAYLOAD_DELETE12) && | |||
| 215 | !payload_first(msg, ISAKMP_PAYLOAD_HASH8))))) { | |||
| 216 | /* Missing payload. */ | |||
| 217 | LOG_DBG((LOG_MESSAGE, 70,log_debug (LOG_MESSAGE, 70, "exchange_validate: msg %p requires missing %s" , msg, *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name(exchange_script_cst, *pc)) | |||
| 218 | "exchange_validate: msg %p requires missing %s",log_debug (LOG_MESSAGE, 70, "exchange_validate: msg %p requires missing %s" , msg, *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name(exchange_script_cst, *pc)) | |||
| 219 | msg, *pc >= ISAKMP_PAYLOAD_NONElog_debug (LOG_MESSAGE, 70, "exchange_validate: msg %p requires missing %s" , msg, *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name(exchange_script_cst, *pc)) | |||
| 220 | ? constant_name(isakmp_payload_cst, *pc)log_debug (LOG_MESSAGE, 70, "exchange_validate: msg %p requires missing %s" , msg, *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name(exchange_script_cst, *pc)) | |||
| 221 | : constant_name(exchange_script_cst, *pc)))log_debug (LOG_MESSAGE, 70, "exchange_validate: msg %p requires missing %s" , msg, *pc >= 0 ? constant_name(isakmp_payload_cst, *pc) : constant_name(exchange_script_cst, *pc)); | |||
| 222 | return -1; | |||
| 223 | } | |||
| 224 | pc++; | |||
| 225 | } | |||
| 226 | if (*pc == EXCHANGE_SCRIPT_END-4) | |||
| 227 | /* Cleanup. */ | |||
| 228 | return 1; | |||
| 229 | ||||
| 230 | return 0; | |||
| 231 | } | |||
| 232 | ||||
| 233 | /* Feed unhandled payloads to the DOI for handling. Help for exchange_run(). */ | |||
| 234 | static void | |||
| 235 | exchange_handle_leftover_payloads(struct message *msg) | |||
| 236 | { | |||
| 237 | struct exchange *exchange = msg->exchange; | |||
| 238 | struct doi *doi = exchange->doi; | |||
| 239 | struct payload *p; | |||
| 240 | int i; | |||
| 241 | ||||
| 242 | for (i = ISAKMP_PAYLOAD_SA1; i < ISAKMP_PAYLOAD_MAX255; i++) { | |||
| 243 | if (i == ISAKMP_PAYLOAD_PROPOSAL2 || | |||
| 244 | i == ISAKMP_PAYLOAD_TRANSFORM3) | |||
| 245 | continue; | |||
| 246 | TAILQ_FOREACH(p, &msg->payload[i], link)for((p) = ((&msg->payload[i])->tqh_first); (p) != ( (void*)0); (p) = ((p)->link.tqe_next)) { | |||
| 247 | if (p->flags & PL_MARK1) | |||
| 248 | continue; | |||
| 249 | if (!doi->handle_leftover_payload || | |||
| 250 | doi->handle_leftover_payload(msg, i, p)) | |||
| 251 | LOG_DBG((LOG_EXCHANGE, 10,log_debug (LOG_EXCHANGE, 10, "exchange_handle_leftover_payloads: " "unexpected payload %s", constant_name(isakmp_payload_cst, i )) | |||
| 252 | "exchange_handle_leftover_payloads: "log_debug (LOG_EXCHANGE, 10, "exchange_handle_leftover_payloads: " "unexpected payload %s", constant_name(isakmp_payload_cst, i )) | |||
| 253 | "unexpected payload %s",log_debug (LOG_EXCHANGE, 10, "exchange_handle_leftover_payloads: " "unexpected payload %s", constant_name(isakmp_payload_cst, i )) | |||
| 254 | constant_name(isakmp_payload_cst, i)))log_debug (LOG_EXCHANGE, 10, "exchange_handle_leftover_payloads: " "unexpected payload %s", constant_name(isakmp_payload_cst, i )); | |||
| 255 | } | |||
| 256 | } | |||
| 257 | } | |||
| 258 | ||||
| 259 | /* | |||
| 260 | * Run the exchange script from a point given by the "program counter" | |||
| 261 | * upto either the script's end or a transmittal of a message. If we are | |||
| 262 | * at the point of a reception of a message, that message should be handed | |||
| 263 | * in here in the MSG argument. Otherwise we are the initiator and should | |||
| 264 | * expect MSG to be a half-cooked message without payloads. | |||
| 265 | */ | |||
| 266 | void | |||
| 267 | exchange_run(struct message *msg) | |||
| 268 | { | |||
| 269 | struct exchange *exchange = msg->exchange; | |||
| 270 | struct doi *doi = exchange->doi; | |||
| 271 | int (*handler)(struct message *) = exchange->initiator ? | |||
| 272 | doi->initiator : doi->responder; | |||
| 273 | int done = 0; | |||
| 274 | ||||
| 275 | while (!done) { | |||
| 276 | /* | |||
| 277 | * It's our turn if we're either the initiator on an even step, | |||
| 278 | * or the responder on an odd step of the dialogue. | |||
| 279 | */ | |||
| 280 | if (exchange->initiator ^ (exchange->step % 2)) { | |||
| 281 | done = 1; | |||
| 282 | if (exchange->step) | |||
| 283 | msg = message_alloc_reply(msg); | |||
| 284 | message_setup_header(msg, exchange->type, 0, | |||
| 285 | exchange->message_id); | |||
| 286 | if (handler(msg)) { | |||
| 287 | /* | |||
| 288 | * This can happen when transient starvation | |||
| 289 | * of memory occurs. | |||
| 290 | * XXX The peer's retransmit ought to | |||
| 291 | * kick-start this exchange again. If he's | |||
| 292 | * stopped retransmitting he's likely dropped | |||
| 293 | * the SA at his side so we need to do that | |||
| 294 | * too, i.e. implement automatic SA teardown | |||
| 295 | * after a certain amount of inactivity. | |||
| 296 | */ | |||
| 297 | log_print("exchange_run: doi->%s (%p) failed", | |||
| 298 | exchange->initiator ? "initiator" : | |||
| 299 | "responder", msg); | |||
| 300 | message_free(msg); | |||
| 301 | return; | |||
| 302 | } | |||
| 303 | switch (exchange_validate(msg)) { | |||
| 304 | case 1: | |||
| 305 | /* | |||
| 306 | * The last message of a multi-message | |||
| 307 | * exchange should not be retransmitted other | |||
| 308 | * than "on-demand", i.e. if we see | |||
| 309 | * retransmits of the last message of the peer | |||
| 310 | * later. | |||
| 311 | */ | |||
| 312 | msg->flags |= MSG_LAST0x01; | |||
| 313 | if (exchange->step > 0) { | |||
| 314 | if (exchange->last_sent) | |||
| 315 | message_free(exchange->last_sent); | |||
| 316 | exchange->last_sent = msg; | |||
| 317 | } | |||
| 318 | /* | |||
| 319 | * After we physically have sent our last | |||
| 320 | * message we need to do SA-specific | |||
| 321 | * finalization, like telling our application | |||
| 322 | * the SA is ready to be used, or issuing a | |||
| 323 | * CONNECTED notify if we set the COMMIT bit. | |||
| 324 | */ | |||
| 325 | message_register_post_send(msg, | |||
| 326 | exchange_finalize); | |||
| 327 | ||||
| 328 | /* FALLTHROUGH */ | |||
| 329 | ||||
| 330 | case 0: | |||
| 331 | /* | |||
| 332 | * Don't retransmit responses for | |||
| 333 | * unauthenticated messages. | |||
| 334 | */ | |||
| 335 | if ((exchange->type == ISAKMP_EXCH_ID_PROT2 || | |||
| 336 | exchange->type == ISAKMP_EXCH_AGGRESSIVE4) && | |||
| 337 | exchange->phase == 1 && exchange->step == 1) | |||
| 338 | msg->flags |= MSG_DONTRETRANSMIT0x40; | |||
| 339 | ||||
| 340 | /* XXX error handling. */ | |||
| 341 | message_send(msg); | |||
| 342 | break; | |||
| 343 | ||||
| 344 | default: | |||
| 345 | log_print("exchange_run: exchange_validate " | |||
| 346 | "failed, DOI error"); | |||
| 347 | exchange_free(exchange); | |||
| 348 | message_free(msg); | |||
| 349 | return; | |||
| 350 | } | |||
| 351 | } else { | |||
| 352 | done = exchange_validate(msg); | |||
| 353 | switch (done) { | |||
| 354 | case 0: | |||
| 355 | case 1: | |||
| 356 | /* Feed the message to the DOI. */ | |||
| 357 | if (handler(msg)) { | |||
| 358 | /* | |||
| 359 | * Trust the peer to retransmit. | |||
| 360 | * XXX We have to implement SA aging | |||
| 361 | * with automatic teardown. | |||
| 362 | */ | |||
| 363 | message_free(msg); | |||
| 364 | return; | |||
| 365 | } | |||
| 366 | /* | |||
| 367 | * Go over the yet unhandled payloads and feed | |||
| 368 | * them to DOI for handling. | |||
| 369 | */ | |||
| 370 | exchange_handle_leftover_payloads(msg); | |||
| 371 | ||||
| 372 | /* | |||
| 373 | * We have advanced the state. If we have | |||
| 374 | * been processing an incoming message, record | |||
| 375 | * that message as the one to do duplication | |||
| 376 | * tests against. | |||
| 377 | */ | |||
| 378 | if (exchange->last_received) | |||
| 379 | message_free(exchange->last_received); | |||
| 380 | exchange->last_received = msg; | |||
| 381 | if (exchange->flags & EXCHANGE_FLAG_ENCRYPT0x0004) | |||
| 382 | crypto_update_iv(exchange->keystate); | |||
| 383 | ||||
| 384 | if (done) { | |||
| 385 | exchange_finalize(msg); | |||
| 386 | return; | |||
| 387 | } | |||
| 388 | break; | |||
| 389 | ||||
| 390 | case -1: | |||
| 391 | log_print("exchange_run: exchange_validate " | |||
| 392 | "failed"); | |||
| 393 | /* | |||
| 394 | * XXX Is this the best error notification | |||
| 395 | * type? | |||
| 396 | */ | |||
| 397 | message_drop(msg, | |||
| 398 | ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1); | |||
| 399 | return; | |||
| 400 | } | |||
| 401 | } | |||
| 402 | ||||
| 403 | LOG_DBG((LOG_EXCHANGE, 40,log_debug (LOG_EXCHANGE, 40, "exchange_run: exchange %p finished step %d, advancing..." , exchange, exchange->step) | |||
| 404 | "exchange_run: exchange %p finished step %d, advancing...",log_debug (LOG_EXCHANGE, 40, "exchange_run: exchange %p finished step %d, advancing..." , exchange, exchange->step) | |||
| 405 | exchange, exchange->step))log_debug (LOG_EXCHANGE, 40, "exchange_run: exchange %p finished step %d, advancing..." , exchange, exchange->step); | |||
| 406 | exchange->step++; | |||
| 407 | while (*exchange->exch_pc != EXCHANGE_SCRIPT_SWITCH-3 && | |||
| 408 | *exchange->exch_pc != EXCHANGE_SCRIPT_END-4) | |||
| 409 | exchange->exch_pc++; | |||
| 410 | exchange->exch_pc++; | |||
| 411 | } | |||
| 412 | } | |||
| 413 | ||||
| 414 | void | |||
| 415 | exchange_init(void) | |||
| 416 | { | |||
| 417 | int i; | |||
| 418 | ||||
| 419 | bucket_mask = (1 << INITIAL_BUCKET_BITS6) - 1; | |||
| 420 | exchange_tab = calloc(bucket_mask + 1, sizeof(struct exchange_list)); | |||
| 421 | if (!exchange_tab) | |||
| 422 | log_fatal("exchange_init: out of memory"); | |||
| 423 | for (i = 0; i <= bucket_mask; i++) | |||
| 424 | LIST_INIT(&exchange_tab[i])do { ((&exchange_tab[i])->lh_first) = ((void*)0); } while (0); | |||
| 425 | } | |||
| 426 | ||||
| 427 | /* Lookup a phase 1 exchange out of just the initiator cookie. */ | |||
| 428 | struct exchange * | |||
| 429 | exchange_lookup_from_icookie(u_int8_t *cookie) | |||
| 430 | { | |||
| 431 | struct exchange *exchange; | |||
| 432 | int i; | |||
| 433 | ||||
| 434 | for (i = 0; i <= bucket_mask; i++) | |||
| 435 | for (exchange = LIST_FIRST(&exchange_tab[i])((&exchange_tab[i])->lh_first); exchange; | |||
| 436 | exchange = LIST_NEXT(exchange, link)((exchange)->link.le_next)) | |||
| 437 | if (memcmp(exchange->cookies, cookie, | |||
| 438 | ISAKMP_HDR_ICOOKIE_LEN8) == 0 && | |||
| 439 | exchange->phase == 1) | |||
| 440 | return exchange; | |||
| 441 | return 0; | |||
| 442 | } | |||
| 443 | ||||
| 444 | /* Lookup an exchange out of the name and phase. */ | |||
| 445 | struct exchange * | |||
| 446 | exchange_lookup_by_name(char *name, int phase) | |||
| 447 | { | |||
| 448 | struct exchange *exchange; | |||
| 449 | int i; | |||
| 450 | ||||
| 451 | /* If we search for nothing, we will find nothing. */ | |||
| 452 | if (!name) | |||
| 453 | return 0; | |||
| 454 | ||||
| 455 | for (i = 0; i <= bucket_mask; i++) | |||
| 456 | for (exchange = LIST_FIRST(&exchange_tab[i])((&exchange_tab[i])->lh_first); exchange; | |||
| 457 | exchange = LIST_NEXT(exchange, link)((exchange)->link.le_next)) { | |||
| 458 | LOG_DBG((LOG_EXCHANGE, 90,log_debug (LOG_EXCHANGE, 90, "exchange_lookup_by_name: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 459 | "exchange_lookup_by_name: %s == %s && %d == %d?",log_debug (LOG_EXCHANGE, 90, "exchange_lookup_by_name: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 460 | name, exchange->name ? exchange->name :log_debug (LOG_EXCHANGE, 90, "exchange_lookup_by_name: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 461 | "<unnamed>", phase, exchange->phase))log_debug (LOG_EXCHANGE, 90, "exchange_lookup_by_name: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase); | |||
| 462 | ||||
| 463 | /* | |||
| 464 | * Match by name, but don't select finished exchanges, | |||
| 465 | * i.e where MSG_LAST are set in last_sent msg. | |||
| 466 | */ | |||
| 467 | if (exchange->name && | |||
| 468 | strcasecmp(exchange->name, name) == 0 && | |||
| 469 | exchange->phase == phase && | |||
| 470 | (!exchange->last_sent || | |||
| 471 | (exchange->last_sent->flags & MSG_LAST0x01) == 0)) | |||
| 472 | return exchange; | |||
| 473 | } | |||
| 474 | return 0; | |||
| 475 | } | |||
| 476 | ||||
| 477 | /* Lookup an exchange out of the name, phase and step > 1. */ | |||
| 478 | static struct exchange * | |||
| 479 | exchange_lookup_active(char *name, int phase) | |||
| 480 | { | |||
| 481 | struct exchange *exchange; | |||
| 482 | int i; | |||
| 483 | ||||
| 484 | /* XXX Almost identical to exchange_lookup_by_name. */ | |||
| 485 | ||||
| 486 | if (!name) | |||
| 487 | return 0; | |||
| 488 | ||||
| 489 | for (i = 0; i <= bucket_mask; i++) | |||
| 490 | for (exchange = LIST_FIRST(&exchange_tab[i])((&exchange_tab[i])->lh_first); exchange; | |||
| 491 | exchange = LIST_NEXT(exchange, link)((exchange)->link.le_next)) { | |||
| 492 | LOG_DBG((LOG_EXCHANGE, 90,log_debug (LOG_EXCHANGE, 90, "exchange_lookup_active: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 493 | "exchange_lookup_active: %s == %s && %d == %d?",log_debug (LOG_EXCHANGE, 90, "exchange_lookup_active: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 494 | name, exchange->name ? exchange->name :log_debug (LOG_EXCHANGE, 90, "exchange_lookup_active: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase) | |||
| 495 | "<unnamed>", phase, exchange->phase))log_debug (LOG_EXCHANGE, 90, "exchange_lookup_active: %s == %s && %d == %d?" , name, exchange->name ? exchange->name : "<unnamed>" , phase, exchange->phase); | |||
| 496 | if (exchange->name && | |||
| 497 | strcasecmp(exchange->name, name) == 0 && | |||
| 498 | exchange->phase == phase) { | |||
| 499 | if (exchange->step > 1) | |||
| 500 | return exchange; | |||
| 501 | else | |||
| 502 | LOG_DBG((LOG_EXCHANGE, 80,log_debug (LOG_EXCHANGE, 80, "exchange_lookup_active: avoided " "early (pre-step 1) exchange %p", exchange) | |||
| 503 | "exchange_lookup_active: avoided "log_debug (LOG_EXCHANGE, 80, "exchange_lookup_active: avoided " "early (pre-step 1) exchange %p", exchange) | |||
| 504 | "early (pre-step 1) exchange %p",log_debug (LOG_EXCHANGE, 80, "exchange_lookup_active: avoided " "early (pre-step 1) exchange %p", exchange) | |||
| 505 | exchange))log_debug (LOG_EXCHANGE, 80, "exchange_lookup_active: avoided " "early (pre-step 1) exchange %p", exchange); | |||
| 506 | } | |||
| 507 | } | |||
| 508 | return 0; | |||
| 509 | } | |||
| 510 | ||||
| 511 | static void | |||
| 512 | exchange_enter(struct exchange *exchange) | |||
| 513 | { | |||
| 514 | u_int16_t bucket = 0; | |||
| 515 | u_int8_t *cp; | |||
| 516 | int i; | |||
| 517 | ||||
| 518 | /* XXX We might resize if we are crossing a certain threshold */ | |||
| 519 | ||||
| 520 | for (i = 0; i < ISAKMP_HDR_COOKIES_LEN(8 + 8); i += 2) { | |||
| 521 | cp = exchange->cookies + i; | |||
| 522 | /* Doing it this way avoids alignment problems. */ | |||
| 523 | bucket ^= cp[0] | cp[1] << 8; | |||
| 524 | } | |||
| 525 | for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN4; i += 2) { | |||
| 526 | cp = exchange->message_id + i; | |||
| 527 | /* Doing it this way avoids alignment problems. */ | |||
| 528 | bucket ^= cp[0] | cp[1] << 8; | |||
| 529 | } | |||
| 530 | bucket &= bucket_mask; | |||
| 531 | LIST_INSERT_HEAD(&exchange_tab[bucket], exchange, link)do { if (((exchange)->link.le_next = (&exchange_tab[bucket ])->lh_first) != ((void*)0)) (&exchange_tab[bucket])-> lh_first->link.le_prev = &(exchange)->link.le_next; (&exchange_tab[bucket])->lh_first = (exchange); (exchange )->link.le_prev = &(&exchange_tab[bucket])->lh_first ; } while (0); | |||
| 532 | exchange->linked = 1; | |||
| 533 | } | |||
| 534 | ||||
| 535 | /* | |||
| 536 | * Lookup the exchange given by the header fields MSG. PHASE2 is false when | |||
| 537 | * looking for phase 1 exchanges and true otherwise. | |||
| 538 | */ | |||
| 539 | struct exchange * | |||
| 540 | exchange_lookup(u_int8_t *msg, int phase2) | |||
| 541 | { | |||
| 542 | struct exchange *exchange; | |||
| 543 | u_int16_t bucket = 0; | |||
| 544 | u_int8_t *cp; | |||
| 545 | int i; | |||
| 546 | ||||
| 547 | /* | |||
| 548 | * We use the cookies to get bits to use as an index into exchange_tab, | |||
| 549 | * as at least one (our cookie) is a good hash, xoring all the bits, | |||
| 550 | * 16 at a time, and then masking, should do. Doing it this way means | |||
| 551 | * we can validate cookies very fast thus delimiting the effects of | |||
| 552 | * "Denial of service"-attacks using packet flooding. | |||
| 553 | */ | |||
| 554 | for (i = 0; i < ISAKMP_HDR_COOKIES_LEN(8 + 8); i += 2) { | |||
| 555 | cp = msg + ISAKMP_HDR_COOKIES_OFF0 + i; | |||
| 556 | /* Doing it this way avoids alignment problems. */ | |||
| 557 | bucket ^= cp[0] | cp[1] << 8; | |||
| 558 | } | |||
| 559 | if (phase2) | |||
| 560 | for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN4; i += 2) { | |||
| 561 | cp = msg + ISAKMP_HDR_MESSAGE_ID_OFF20 + i; | |||
| 562 | /* Doing it this way avoids alignment problems. */ | |||
| 563 | bucket ^= cp[0] | cp[1] << 8; | |||
| 564 | } | |||
| 565 | bucket &= bucket_mask; | |||
| 566 | for (exchange = LIST_FIRST(&exchange_tab[bucket])((&exchange_tab[bucket])->lh_first); | |||
| 567 | exchange && (memcmp(msg + ISAKMP_HDR_COOKIES_OFF0, | |||
| 568 | exchange->cookies, ISAKMP_HDR_COOKIES_LEN(8 + 8)) != 0 || | |||
| 569 | (phase2 && memcmp(msg + ISAKMP_HDR_MESSAGE_ID_OFF20, | |||
| 570 | exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN4) != 0) || | |||
| 571 | (!phase2 && !zero_test(msg + ISAKMP_HDR_MESSAGE_ID_OFF20, | |||
| 572 | ISAKMP_HDR_MESSAGE_ID_LEN4))); | |||
| 573 | exchange = LIST_NEXT(exchange, link)((exchange)->link.le_next)) | |||
| 574 | ; | |||
| 575 | ||||
| 576 | return exchange; | |||
| 577 | } | |||
| 578 | ||||
| 579 | /* | |||
| 580 | * Create a phase PHASE exchange where INITIATOR denotes our role. DOI | |||
| 581 | * is the domain of interpretation identifier and TYPE tells what exchange | |||
| 582 | * type to use per either the DOI document or the ISAKMP spec proper. | |||
| 583 | * NSA tells how many SAs we should pre-allocate, and should be zero | |||
| 584 | * when we have the responder role. | |||
| 585 | */ | |||
| 586 | static struct exchange * | |||
| 587 | exchange_create(int phase, int initiator, int doi, int type) | |||
| 588 | { | |||
| 589 | struct exchange *exchange; | |||
| 590 | struct timespec expiration; | |||
| 591 | int delta; | |||
| 592 | ||||
| 593 | /* | |||
| 594 | * We want the exchange zeroed for exchange_free to be able to find | |||
| 595 | * out what fields have been filled-in. | |||
| 596 | */ | |||
| 597 | exchange = calloc(1, sizeof *exchange); | |||
| 598 | if (!exchange) { | |||
| 599 | log_error("exchange_create: calloc (1, %lu) failed", | |||
| 600 | (unsigned long)sizeof *exchange); | |||
| 601 | return 0; | |||
| 602 | } | |||
| 603 | exchange->phase = phase; | |||
| 604 | exchange->step = 0; | |||
| 605 | exchange->initiator = initiator; | |||
| 606 | bzero(exchange->cookies, ISAKMP_HDR_COOKIES_LEN(8 + 8)); | |||
| 607 | bzero(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN4); | |||
| 608 | exchange->doi = doi_lookup(doi); | |||
| 609 | exchange->type = type; | |||
| 610 | exchange->policy_id = -1; | |||
| 611 | exchange->exch_pc = exchange_script(exchange); | |||
| 612 | exchange->last_sent = exchange->last_received = 0; | |||
| 613 | TAILQ_INIT(&exchange->sa_list)do { (&exchange->sa_list)->tqh_first = ((void*)0); ( &exchange->sa_list)->tqh_last = &(&exchange ->sa_list)->tqh_first; } while (0); | |||
| 614 | TAILQ_INIT(&exchange->aca_list)do { (&exchange->aca_list)->tqh_first = ((void*)0); (&exchange->aca_list)->tqh_last = &(&exchange ->aca_list)->tqh_first; } while (0); | |||
| 615 | ||||
| 616 | /* Allocate the DOI-specific structure and initialize it to zeroes. */ | |||
| 617 | if (exchange->doi->exchange_size) { | |||
| 618 | exchange->data = calloc(1, exchange->doi->exchange_size); | |||
| 619 | if (!exchange->data) { | |||
| 620 | log_error("exchange_create: calloc (1, %lu) failed", | |||
| 621 | (unsigned long)exchange->doi->exchange_size); | |||
| 622 | exchange_free(exchange); | |||
| 623 | return 0; | |||
| 624 | } | |||
| 625 | } | |||
| 626 | clock_gettime(CLOCK_MONOTONIC3, &expiration); | |||
| 627 | delta = conf_get_num("General", "Exchange-max-time", | |||
| 628 | EXCHANGE_MAX_TIME120); | |||
| 629 | expiration.tv_sec += delta; | |||
| 630 | exchange->death = timer_add_event("exchange_free_aux", | |||
| 631 | exchange_free_aux, exchange, &expiration); | |||
| 632 | if (!exchange->death) { | |||
| 633 | /* If we don't give up we might start leaking... */ | |||
| 634 | exchange_free_aux(exchange); | |||
| 635 | return 0; | |||
| 636 | } | |||
| 637 | return exchange; | |||
| 638 | } | |||
| 639 | ||||
| 640 | struct exchange_finalization_node { | |||
| 641 | void (*first)(struct exchange *, void *, int); | |||
| 642 | void *first_arg; | |||
| 643 | void (*second)(struct exchange *, void *, int); | |||
| 644 | void *second_arg; | |||
| 645 | }; | |||
| 646 | ||||
| 647 | /* Run the finalization functions of ARG. */ | |||
| 648 | static void | |||
| 649 | exchange_run_finalizations(struct exchange *exchange, void *arg, int fail) | |||
| 650 | { | |||
| 651 | struct exchange_finalization_node *node = arg; | |||
| 652 | ||||
| 653 | node->first(exchange, node->first_arg, fail); | |||
| 654 | node->second(exchange, node->second_arg, fail); | |||
| 655 | free(node); | |||
| 656 | } | |||
| 657 | ||||
| 658 | /* | |||
| 659 | * Add a finalization function FINALIZE with argument ARG to the tail | |||
| 660 | * of the finalization function list of EXCHANGE. | |||
| 661 | */ | |||
| 662 | static void | |||
| 663 | exchange_add_finalization(struct exchange *exchange, | |||
| 664 | void (*finalize)(struct exchange *, void *, int), void *arg) | |||
| 665 | { | |||
| 666 | struct exchange_finalization_node *node; | |||
| 667 | ||||
| 668 | if (!finalize) | |||
| 669 | return; | |||
| 670 | ||||
| 671 | if (!exchange->finalize) { | |||
| 672 | exchange->finalize = finalize; | |||
| 673 | exchange->finalize_arg = arg; | |||
| 674 | return; | |||
| 675 | } | |||
| 676 | node = malloc(sizeof *node); | |||
| 677 | if (!node) { | |||
| 678 | log_error("exchange_add_finalization: malloc (%lu) failed", | |||
| 679 | (unsigned long)sizeof *node); | |||
| 680 | free(arg); | |||
| 681 | return; | |||
| 682 | } | |||
| 683 | node->first = exchange->finalize; | |||
| 684 | node->first_arg = exchange->finalize_arg; | |||
| 685 | node->second = finalize; | |||
| 686 | node->second_arg = arg; | |||
| 687 | exchange->finalize = exchange_run_finalizations; | |||
| 688 | exchange->finalize_arg = node; | |||
| 689 | } | |||
| 690 | ||||
| 691 | static void | |||
| 692 | exchange_establish_transaction(struct exchange *exchange, void *arg, int fail) | |||
| 693 | { | |||
| 694 | /* Establish a TRANSACTION exchange. */ | |||
| 695 | struct exchange_finalization_node *node = | |||
| 696 | (struct exchange_finalization_node *)arg; | |||
| 697 | struct sa *isakmp_sa = sa_lookup_by_name((char *) node->second_arg, 1); | |||
| 698 | ||||
| 699 | if (isakmp_sa && !fail) | |||
| 700 | exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_TRANSACTION6, 0, 0, | |||
| 701 | node->first, node->first_arg); | |||
| 702 | ||||
| 703 | free(node); | |||
| 704 | } | |||
| 705 | ||||
| 706 | /* Establish a phase 1 exchange. */ | |||
| 707 | int | |||
| 708 | exchange_establish_p1(struct transport *t, u_int8_t type, u_int32_t doi, | |||
| 709 | char *name, void *args, void (*finalize)(struct exchange *, void *, int), | |||
| 710 | void *arg, int stayalive) | |||
| 711 | { | |||
| 712 | struct exchange *exchange; | |||
| 713 | struct message *msg; | |||
| 714 | struct conf_list *flags; | |||
| 715 | struct conf_list_node *flag; | |||
| 716 | char *tag = 0; | |||
| 717 | char *str; | |||
| 718 | ||||
| 719 | if (name) { | |||
| 720 | /* If no exchange type given, fetch from the configuration. */ | |||
| 721 | if (type == 0) { | |||
| 722 | /* | |||
| 723 | * XXX Similar code can be found in | |||
| 724 | * exchange_setup_p1. Share? | |||
| 725 | */ | |||
| 726 | ||||
| 727 | /* Find out our phase 1 mode. */ | |||
| 728 | tag = conf_get_str(name, "Configuration"); | |||
| 729 | if (!tag) { | |||
| 730 | /* Use default setting. */ | |||
| 731 | tag = CONF_DFLT_TAG_PHASE1_CONFIG"Default-phase-1-configuration"; | |||
| 732 | } | |||
| 733 | /* Figure out the DOI. XXX Factor out? */ | |||
| 734 | str = conf_get_str(tag, "DOI"); | |||
| 735 | if (!str || strcasecmp(str, "IPSEC") == 0) | |||
| 736 | doi = IPSEC_DOI_IPSEC1; | |||
| 737 | else if (strcasecmp(str, "ISAKMP") == 0) | |||
| 738 | doi = ISAKMP_DOI_ISAKMP0; | |||
| 739 | else { | |||
| 740 | log_print("exchange_establish_p1: " | |||
| 741 | "DOI \"%s\" unsupported", str); | |||
| 742 | return -1; | |||
| 743 | } | |||
| 744 | ||||
| 745 | /* What exchange type do we want? */ | |||
| 746 | str = conf_get_str(tag, "EXCHANGE_TYPE"); | |||
| 747 | if (!str) { | |||
| 748 | log_print("exchange_establish_p1: " | |||
| 749 | "no \"EXCHANGE_TYPE\" tag in [%s] section", | |||
| 750 | tag); | |||
| 751 | return -1; | |||
| 752 | } | |||
| 753 | type = constant_value(isakmp_exch_cst, str); | |||
| 754 | if (!type) { | |||
| 755 | log_print("exchange_establish_p1: " | |||
| 756 | "unknown exchange type %s", str); | |||
| 757 | return -1; | |||
| 758 | } | |||
| 759 | } | |||
| 760 | } | |||
| 761 | exchange = exchange_create(1, 1, doi, type); | |||
| 762 | if (!exchange) { | |||
| 763 | return -1; | |||
| 764 | } | |||
| 765 | if (name) { | |||
| 766 | exchange->name = strdup(name); | |||
| 767 | if (!exchange->name) { | |||
| 768 | log_error("exchange_establish_p1: " | |||
| 769 | "strdup (\"%s\") failed", name); | |||
| 770 | exchange_free(exchange); | |||
| 771 | return -1; | |||
| 772 | } | |||
| 773 | } | |||
| 774 | exchange->policy = name ? conf_get_str(name, "Configuration") : 0; | |||
| 775 | if (!exchange->policy && name) | |||
| 776 | exchange->policy = CONF_DFLT_TAG_PHASE1_CONFIG"Default-phase-1-configuration"; | |||
| 777 | ||||
| 778 | if (name && (flags = conf_get_list(name, "Flags")) != NULL((void*)0)) { | |||
| 779 | for (flag = TAILQ_FIRST(&flags->fields)((&flags->fields)->tqh_first); flag; | |||
| 780 | flag = TAILQ_NEXT(flag, link)((flag)->link.tqe_next)) | |||
| 781 | if (strcasecmp(flag->field, "ikecfg") == 0) { | |||
| 782 | struct exchange_finalization_node *node; | |||
| 783 | ||||
| 784 | node = calloc(1, (unsigned long)sizeof *node); | |||
| 785 | if (!node) { | |||
| 786 | log_print("exchange_establish_p1: " | |||
| 787 | "calloc (1, %lu) failed", | |||
| 788 | (unsigned long)sizeof(*node)); | |||
| 789 | exchange_free(exchange); | |||
| 790 | return -1; | |||
| 791 | } | |||
| 792 | /* | |||
| 793 | * Insert this finalization inbetween | |||
| 794 | * the original. | |||
| 795 | */ | |||
| 796 | node->first = finalize; | |||
| 797 | node->first_arg = arg; | |||
| 798 | node->second_arg = name; | |||
| 799 | exchange_add_finalization(exchange, | |||
| 800 | exchange_establish_transaction, | |||
| 801 | node); | |||
| 802 | finalize = 0; | |||
| 803 | } | |||
| 804 | conf_free_list(flags); | |||
| 805 | } | |||
| 806 | ||||
| 807 | exchange_add_finalization(exchange, finalize, arg); | |||
| 808 | cookie_gen(t, exchange, exchange->cookies, ISAKMP_HDR_ICOOKIE_LEN8); | |||
| 809 | exchange_enter(exchange); | |||
| 810 | exchange_dump("exchange_establish_p1", exchange); | |||
| 811 | ||||
| 812 | msg = message_alloc(t, 0, ISAKMP_HDR_SZ28); | |||
| 813 | if (!msg) { | |||
| 814 | log_print("exchange_establish_p1: message_alloc () failed"); | |||
| 815 | exchange_free(exchange); | |||
| 816 | return 0; /* exchange_free() runs finalize */ | |||
| 817 | } | |||
| 818 | msg->exchange = exchange; | |||
| 819 | ||||
| 820 | /* Do not create SA for an information or transaction exchange. */ | |||
| 821 | if (exchange->type != ISAKMP_EXCH_INFO5 && | |||
| 822 | exchange->type != ISAKMP_EXCH_TRANSACTION6) { | |||
| 823 | /* | |||
| 824 | * Don't install a transport into this SA as it will be an | |||
| 825 | * INADDR_ANY address in the local end, which is not good at | |||
| 826 | * all. Let the reply packet install the transport instead. | |||
| 827 | */ | |||
| 828 | sa_create(exchange, 0); | |||
| 829 | msg->isakmp_sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); | |||
| 830 | if (!msg->isakmp_sa) { | |||
| 831 | message_free(msg); | |||
| 832 | exchange_free(exchange); | |||
| 833 | return 0; /* exchange_free() runs finalize */ | |||
| 834 | } | |||
| 835 | sa_reference(msg->isakmp_sa); | |||
| 836 | ||||
| 837 | if (stayalive) | |||
| 838 | msg->isakmp_sa->flags |= SA_FLAG_STAYALIVE0x02; | |||
| 839 | } | |||
| 840 | msg->extra = args; | |||
| 841 | ||||
| 842 | exchange_run(msg); | |||
| 843 | return 0; | |||
| 844 | } | |||
| 845 | ||||
| 846 | /* Establish a phase 2 exchange. XXX With just one SA for now. */ | |||
| 847 | int | |||
| 848 | exchange_establish_p2(struct sa *isakmp_sa, u_int8_t type, char *name, | |||
| 849 | void *args, void (*finalize)(struct exchange *, void *, int), void *arg) | |||
| 850 | { | |||
| 851 | struct exchange *exchange; | |||
| 852 | struct message *msg; | |||
| 853 | u_int32_t doi = ISAKMP_DOI_ISAKMP0; | |||
| 854 | u_int32_t seq = 0; | |||
| 855 | int i; | |||
| 856 | char *tag, *str; | |||
| 857 | ||||
| 858 | if (isakmp_sa) | |||
| 859 | doi = isakmp_sa->doi->id; | |||
| 860 | ||||
| 861 | if (name) { | |||
| 862 | /* Find out our phase 2 modes. */ | |||
| 863 | tag = conf_get_str(name, "Configuration"); | |||
| 864 | if (!tag) { | |||
| 865 | log_print("exchange_establish_p2: " | |||
| 866 | "no configuration for peer \"%s\"", name); | |||
| 867 | return -1; | |||
| 868 | } | |||
| 869 | seq = (u_int32_t)conf_get_num(name, "Acquire-ID", 0); | |||
| 870 | ||||
| 871 | /* Figure out the DOI. */ | |||
| 872 | str = conf_get_str(tag, "DOI"); | |||
| 873 | if (!str || strcasecmp(str, "IPSEC") == 0) | |||
| 874 | doi = IPSEC_DOI_IPSEC1; | |||
| 875 | else if (strcasecmp(str, "ISAKMP") == 0) | |||
| 876 | doi = ISAKMP_DOI_ISAKMP0; | |||
| 877 | else { | |||
| 878 | log_print("exchange_establish_p2: " | |||
| 879 | "DOI \"%s\" unsupported", str); | |||
| 880 | return -1; | |||
| 881 | } | |||
| 882 | ||||
| 883 | /* What exchange type do we want? */ | |||
| 884 | if (!type) { | |||
| 885 | str = conf_get_str(tag, "EXCHANGE_TYPE"); | |||
| 886 | if (!str) { | |||
| 887 | log_print("exchange_establish_p2: " | |||
| 888 | "no \"EXCHANGE_TYPE\" tag in [%s] section", | |||
| 889 | tag); | |||
| 890 | return -1; | |||
| 891 | } | |||
| 892 | /* XXX IKE dependent. */ | |||
| 893 | type = constant_value(ike_exch_cst, str); | |||
| 894 | if (!type) { | |||
| 895 | log_print("exchange_establish_p2: unknown " | |||
| 896 | "exchange type %s", str); | |||
| 897 | return -1; | |||
| 898 | } | |||
| 899 | } | |||
| 900 | } | |||
| 901 | exchange = exchange_create(2, 1, doi, type); | |||
| 902 | if (!exchange) { | |||
| 903 | return -1; | |||
| 904 | } | |||
| 905 | if (name) { | |||
| 906 | exchange->name = strdup(name); | |||
| 907 | if (!exchange->name) { | |||
| 908 | log_error("exchange_establish_p2: " | |||
| 909 | "strdup (\"%s\") failed", name); | |||
| 910 | exchange_free(exchange); | |||
| 911 | return -1; | |||
| 912 | } | |||
| 913 | } | |||
| 914 | exchange->policy = name ? conf_get_str(name, "Configuration") : 0; | |||
| 915 | exchange->finalize = finalize; | |||
| 916 | exchange->finalize_arg = arg; | |||
| 917 | exchange->seq = seq; | |||
| 918 | memcpy(exchange->cookies, isakmp_sa->cookies, ISAKMP_HDR_COOKIES_LEN(8 + 8)); | |||
| 919 | arc4random_buf(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN4); | |||
| 920 | exchange->flags |= EXCHANGE_FLAG_ENCRYPT0x0004; | |||
| 921 | if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE0x100) | |||
| 922 | exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE0x0010; | |||
| 923 | if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE0x200) | |||
| 924 | exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE0x0020; | |||
| 925 | exchange_enter(exchange); | |||
| 926 | exchange_dump("exchange_establish_p2", exchange); | |||
| 927 | ||||
| 928 | /* | |||
| 929 | * Do not create SA's for informational exchanges. | |||
| 930 | * XXX How to handle new group mode? | |||
| 931 | */ | |||
| 932 | if (exchange->type != ISAKMP_EXCH_INFO5 && | |||
| 933 | exchange->type != ISAKMP_EXCH_TRANSACTION6) { | |||
| 934 | /* XXX Number of SAs should come from the args structure. */ | |||
| 935 | for (i = 0; i < 1; i++) | |||
| 936 | if (sa_create(exchange, isakmp_sa->transport)) { | |||
| 937 | exchange_free(exchange); | |||
| 938 | return 0; /* exchange_free() runs finalize */ | |||
| 939 | } | |||
| 940 | } | |||
| 941 | msg = message_alloc(isakmp_sa->transport, 0, ISAKMP_HDR_SZ28); | |||
| 942 | msg->isakmp_sa = isakmp_sa; | |||
| 943 | sa_reference(isakmp_sa); | |||
| 944 | ||||
| 945 | msg->extra = args; | |||
| 946 | ||||
| 947 | /* This needs to be done late or else get_keystate won't work right. */ | |||
| 948 | msg->exchange = exchange; | |||
| 949 | ||||
| 950 | exchange_run(msg); | |||
| 951 | ||||
| 952 | return 0; | |||
| 953 | } | |||
| 954 | ||||
| 955 | /* Out of an incoming phase 1 message, setup an exchange. */ | |||
| 956 | struct exchange * | |||
| 957 | exchange_setup_p1(struct message *msg, u_int32_t doi) | |||
| 958 | { | |||
| 959 | struct transport *t = msg->transport; | |||
| 960 | struct exchange *exchange; | |||
| 961 | struct sockaddr *dst; | |||
| 962 | struct conf_list *flags; | |||
| 963 | struct conf_list_node *flag; | |||
| 964 | char *name = 0, *policy = 0, *str; | |||
| 965 | u_int32_t want_doi; | |||
| 966 | u_int8_t type; | |||
| 967 | ||||
| 968 | /* XXX Similar code can be found in exchange_establish_p1. Share? */ | |||
| 969 | ||||
| 970 | /* | |||
| 971 | * Unless this is an informational exchange, look up our policy for | |||
| 972 | * this peer. | |||
| 973 | */ | |||
| 974 | type = GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base)field_get_num (isakmp_hdr_fld + 4, msg->iov[0].iov_base); | |||
| 975 | if (type != ISAKMP_EXCH_INFO5) { | |||
| 976 | /* | |||
| 977 | * Find out our inbound phase 1 mode. | |||
| 978 | */ | |||
| 979 | t->vtbl->get_dst(t, &dst); | |||
| 980 | if (sockaddr2text(dst, &str, 0) == -1) | |||
| 981 | return 0; | |||
| 982 | name = conf_get_str("Phase 1", str); | |||
| 983 | free(str); | |||
| 984 | if (name) { | |||
| 985 | /* | |||
| 986 | * If another phase 1 exchange is ongoing don't bother | |||
| 987 | * returning the call. However, we will need to | |||
| 988 | * continue responding if our phase 1 exchange is | |||
| 989 | * still waiting for step 1 (i.e still half-open). | |||
| 990 | */ | |||
| 991 | exchange = exchange_lookup_active(name, 1); | |||
| 992 | if (exchange) { | |||
| 993 | LOG_DBG((LOG_EXCHANGE, 40,log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already " "exists as %p", name, exchange) | |||
| 994 | "exchange_establish: %s exchange already "log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already " "exists as %p", name, exchange) | |||
| 995 | "exists as %p", name, exchange))log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already " "exists as %p", name, exchange); | |||
| 996 | return 0; | |||
| 997 | } | |||
| 998 | } else { | |||
| 999 | name = conf_get_str("Phase 1", "Default"); | |||
| 1000 | if (!name) { | |||
| 1001 | log_print("exchange_setup_p1: no \"Default\" " | |||
| 1002 | "tag in [Phase 1] section"); | |||
| 1003 | return 0; | |||
| 1004 | } | |||
| 1005 | } | |||
| 1006 | ||||
| 1007 | policy = conf_get_str(name, "Configuration"); | |||
| 1008 | if (!policy) | |||
| 1009 | policy = CONF_DFLT_TAG_PHASE1_CONFIG"Default-phase-1-configuration"; | |||
| 1010 | ||||
| 1011 | /* Figure out the DOI. */ | |||
| 1012 | str = conf_get_str(policy, "DOI"); | |||
| 1013 | if (!str || strcasecmp(str, "IPSEC") == 0) { | |||
| 1014 | want_doi = IPSEC_DOI_IPSEC1; | |||
| 1015 | str = "IPSEC"; | |||
| 1016 | } | |||
| 1017 | else if (strcasecmp(str, "ISAKMP") == 0) | |||
| 1018 | want_doi = ISAKMP_DOI_ISAKMP0; | |||
| 1019 | else { | |||
| 1020 | log_print("exchange_setup_p1: " | |||
| 1021 | "DOI \"%s\" unsupported", str); | |||
| 1022 | return 0; | |||
| 1023 | } | |||
| 1024 | if (want_doi != doi) { | |||
| 1025 | /* XXX Should I tell what DOI I got? */ | |||
| 1026 | log_print("exchange_setup_p1: expected %s DOI", str); | |||
| 1027 | return 0; | |||
| 1028 | } | |||
| 1029 | /* What exchange type do we want? */ | |||
| 1030 | str = conf_get_str(policy, "EXCHANGE_TYPE"); | |||
| 1031 | if (!str) { | |||
| 1032 | log_print("exchange_setup_p1: no \"EXCHANGE_TYPE\" " | |||
| 1033 | "tag in [%s] section", policy); | |||
| 1034 | return 0; | |||
| 1035 | } | |||
| 1036 | type = constant_value(isakmp_exch_cst, str); | |||
| 1037 | if (!type) { | |||
| 1038 | log_print("exchange_setup_p1: " | |||
| 1039 | "unknown exchange type %s", str); | |||
| 1040 | return 0; | |||
| 1041 | } | |||
| 1042 | if (type != GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base)field_get_num (isakmp_hdr_fld + 4, msg->iov[0].iov_base)) { | |||
| 1043 | log_print("exchange_setup_p1: " | |||
| 1044 | "expected exchange type %s got %s", str, | |||
| 1045 | constant_name(isakmp_exch_cst, | |||
| 1046 | GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base)field_get_num (isakmp_hdr_fld + 4, msg->iov[0].iov_base))); | |||
| 1047 | return 0; | |||
| 1048 | } | |||
| 1049 | } | |||
| 1050 | exchange = exchange_create(1, 0, doi, type); | |||
| 1051 | if (!exchange) | |||
| 1052 | return 0; | |||
| 1053 | ||||
| 1054 | exchange->name = name ? strdup(name) : 0; | |||
| 1055 | if (name && !exchange->name) { | |||
| 1056 | log_error("exchange_setup_p1: strdup (\"%s\") failed", name); | |||
| 1057 | exchange_free(exchange); | |||
| 1058 | return 0; | |||
| 1059 | } | |||
| 1060 | exchange->policy = policy; | |||
| 1061 | ||||
| 1062 | if (name && (flags = conf_get_list(name, "Flags")) != NULL((void*)0)) { | |||
| 1063 | for (flag = TAILQ_FIRST(&flags->fields)((&flags->fields)->tqh_first); flag; | |||
| 1064 | flag = TAILQ_NEXT(flag, link)((flag)->link.tqe_next)) | |||
| 1065 | if (strcasecmp(flag->field, "ikecfg") == 0) { | |||
| 1066 | struct exchange_finalization_node *node; | |||
| 1067 | ||||
| 1068 | node = calloc(1, (unsigned long)sizeof *node); | |||
| 1069 | if (!node) { | |||
| 1070 | log_print("exchange_establish_p1: " | |||
| 1071 | "calloc (1, %lu) failed", | |||
| 1072 | (unsigned long)sizeof(*node)); | |||
| 1073 | exchange_free(exchange); | |||
| 1074 | return 0; | |||
| 1075 | } | |||
| 1076 | /* | |||
| 1077 | * Insert this finalization inbetween | |||
| 1078 | * the original. | |||
| 1079 | */ | |||
| 1080 | node->first = 0; | |||
| 1081 | node->first_arg = 0; | |||
| 1082 | node->second_arg = name; | |||
| 1083 | exchange_add_finalization(exchange, | |||
| 1084 | exchange_establish_transaction, | |||
| 1085 | node); | |||
| 1086 | } | |||
| 1087 | conf_free_list(flags); | |||
| 1088 | } | |||
| 1089 | ||||
| 1090 | cookie_gen(msg->transport, exchange, exchange->cookies + | |||
| 1091 | ISAKMP_HDR_ICOOKIE_LEN8, ISAKMP_HDR_RCOOKIE_LEN8); | |||
| 1092 | GET_ISAKMP_HDR_ICOOKIE(msg->iov[0].iov_base, exchange->cookies)field_get_raw (isakmp_hdr_fld + 0, msg->iov[0].iov_base, exchange ->cookies); | |||
| 1093 | exchange_enter(exchange); | |||
| 1094 | exchange_dump("exchange_setup_p1", exchange); | |||
| 1095 | return exchange; | |||
| 1096 | } | |||
| 1097 | ||||
| 1098 | /* Out of an incoming phase 2 message, setup an exchange. */ | |||
| 1099 | struct exchange * | |||
| 1100 | exchange_setup_p2(struct message *msg, u_int8_t doi) | |||
| 1101 | { | |||
| 1102 | struct exchange *exchange; | |||
| 1103 | u_int8_t *buf = msg->iov[0].iov_base; | |||
| 1104 | ||||
| 1105 | exchange = exchange_create(2, 0, doi, GET_ISAKMP_HDR_EXCH_TYPE(buf)field_get_num (isakmp_hdr_fld + 4, buf)); | |||
| 1106 | if (!exchange) | |||
| 1107 | return 0; | |||
| 1108 | GET_ISAKMP_HDR_ICOOKIE(buf, exchange->cookies)field_get_raw (isakmp_hdr_fld + 0, buf, exchange->cookies); | |||
| 1109 | GET_ISAKMP_HDR_RCOOKIE(buf,field_get_raw (isakmp_hdr_fld + 1, buf, exchange->cookies + 8) | |||
| 1110 | exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN)field_get_raw (isakmp_hdr_fld + 1, buf, exchange->cookies + 8); | |||
| 1111 | GET_ISAKMP_HDR_MESSAGE_ID(buf, exchange->message_id)field_get_raw (isakmp_hdr_fld + 6, buf, exchange->message_id ); | |||
| 1112 | if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE0x100)) | |||
| 1113 | exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE0x0010; | |||
| 1114 | if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE0x200)) | |||
| 1115 | exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE0x0020; | |||
| 1116 | exchange_enter(exchange); | |||
| 1117 | exchange_dump("exchange_setup_p2", exchange); | |||
| 1118 | return exchange; | |||
| 1119 | } | |||
| 1120 | ||||
| 1121 | /* Dump interesting data about an exchange. */ | |||
| 1122 | static void | |||
| 1123 | exchange_dump_real(char *header, struct exchange *exchange, int class, | |||
| 1124 | int level) | |||
| 1125 | { | |||
| 1126 | struct sa *sa; | |||
| 1127 | char buf[LOG_SIZE200]; | |||
| 1128 | /* Don't risk overflowing the final log buffer. */ | |||
| 1129 | size_t bufsize_max = LOG_SIZE200 - strlen(header) - 32; | |||
| 1130 | ||||
| 1131 | LOG_DBG((class, level,log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step) | |||
| 1132 | "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d",log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step) | |||
| 1133 | header, exchange, exchange->name ? exchange->name : "<unnamed>",log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step) | |||
| 1134 | exchange->policy ? exchange->policy : "<no policy>",log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step) | |||
| 1135 | exchange->initiator ? "initiator" : "responder", exchange->phase,log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step) | |||
| 1136 | exchange->doi->id, exchange->type, exchange->step))log_debug (class, level, "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d" , header, exchange, exchange->name ? exchange->name : "<unnamed>" , exchange->policy ? exchange->policy : "<no policy>" , exchange->initiator ? "initiator" : "responder", exchange ->phase, exchange->doi->id, exchange->type, exchange ->step); | |||
| 1137 | LOG_DBG((class, level, "%s: icookie %08x%08x rcookie %08x%08x", header,log_debug (class, level, "%s: icookie %08x%08x rcookie %08x%08x" , header, decode_32(exchange->cookies), decode_32(exchange ->cookies + 4), decode_32(exchange->cookies + 8), decode_32 (exchange->cookies + 12)) | |||
| 1138 | decode_32(exchange->cookies), decode_32(exchange->cookies + 4),log_debug (class, level, "%s: icookie %08x%08x rcookie %08x%08x" , header, decode_32(exchange->cookies), decode_32(exchange ->cookies + 4), decode_32(exchange->cookies + 8), decode_32 (exchange->cookies + 12)) | |||
| 1139 | decode_32(exchange->cookies + 8),log_debug (class, level, "%s: icookie %08x%08x rcookie %08x%08x" , header, decode_32(exchange->cookies), decode_32(exchange ->cookies + 4), decode_32(exchange->cookies + 8), decode_32 (exchange->cookies + 12)) | |||
| 1140 | decode_32(exchange->cookies + 12)))log_debug (class, level, "%s: icookie %08x%08x rcookie %08x%08x" , header, decode_32(exchange->cookies), decode_32(exchange ->cookies + 4), decode_32(exchange->cookies + 8), decode_32 (exchange->cookies + 12)); | |||
| 1141 | ||||
| 1142 | /* Include phase 2 SA list for this exchange */ | |||
| 1143 | if (exchange->phase == 2) { | |||
| 1144 | snprintf(buf, bufsize_max, "sa_list "); | |||
| 1145 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); | |||
| 1146 | sa && strlen(buf) < bufsize_max; sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) | |||
| 1147 | snprintf(buf + strlen(buf), bufsize_max - strlen(buf), | |||
| 1148 | "%p ", sa); | |||
| 1149 | if (sa) | |||
| 1150 | strlcat(buf, "...", bufsize_max); | |||
| 1151 | } else | |||
| 1152 | buf[0] = '\0'; | |||
| 1153 | ||||
| 1154 | LOG_DBG((class, level, "%s: msgid %08x %s", header,log_debug (class, level, "%s: msgid %08x %s", header, decode_32 (exchange->message_id), buf) | |||
| 1155 | decode_32(exchange->message_id), buf))log_debug (class, level, "%s: msgid %08x %s", header, decode_32 (exchange->message_id), buf); | |||
| 1156 | } | |||
| 1157 | ||||
| 1158 | static void | |||
| 1159 | exchange_dump(char *header, struct exchange *exchange) | |||
| 1160 | { | |||
| 1161 | exchange_dump_real(header, exchange, LOG_EXCHANGE, 10); | |||
| 1162 | } | |||
| 1163 | ||||
| 1164 | void | |||
| 1165 | exchange_report(void) | |||
| 1166 | { | |||
| 1167 | struct exchange *exchange; | |||
| 1168 | int i; | |||
| 1169 | ||||
| 1170 | for (i = 0; i <= bucket_mask; i++) | |||
| 1171 | for (exchange = LIST_FIRST(&exchange_tab[i])((&exchange_tab[i])->lh_first); exchange; | |||
| 1172 | exchange = LIST_NEXT(exchange, link)((exchange)->link.le_next)) | |||
| 1173 | exchange_dump_real("exchange_report", exchange, | |||
| 1174 | LOG_REPORT-2, 0); | |||
| 1175 | } | |||
| 1176 | ||||
| 1177 | /* | |||
| 1178 | * Release all resources this exchange is using *except* for the "death" | |||
| 1179 | * event. When removing an exchange from the expiration handler that event | |||
| 1180 | * will be dealt with therein instead. | |||
| 1181 | */ | |||
| 1182 | static void | |||
| 1183 | exchange_free_aux(void *v_exch) | |||
| 1184 | { | |||
| 1185 | struct exchange *exchange = v_exch; | |||
| 1186 | struct sa *sa, *next_sa; | |||
| 1187 | struct cert_handler *handler; | |||
| 1188 | ||||
| 1189 | LOG_DBG((LOG_EXCHANGE, 80, "exchange_free_aux: freeing exchange %p",log_debug (LOG_EXCHANGE, 80, "exchange_free_aux: freeing exchange %p" , exchange) | |||
| 1190 | exchange))log_debug (LOG_EXCHANGE, 80, "exchange_free_aux: freeing exchange %p" , exchange); | |||
| 1191 | ||||
| 1192 | if (exchange->last_received) | |||
| 1193 | message_free(exchange->last_received); | |||
| 1194 | if (exchange->last_sent) | |||
| 1195 | message_free(exchange->last_sent); | |||
| 1196 | if (exchange->in_transit && | |||
| 1197 | exchange->in_transit != exchange->last_sent) | |||
| 1198 | message_free(exchange->in_transit); | |||
| 1199 | free(exchange->nonce_i); | |||
| 1200 | free(exchange->nonce_r); | |||
| 1201 | free(exchange->id_i); | |||
| 1202 | free(exchange->id_r); | |||
| 1203 | free(exchange->keystate); | |||
| 1204 | if (exchange->data) { | |||
| 1205 | if (exchange->doi && exchange->doi->free_exchange_data) | |||
| 1206 | exchange->doi->free_exchange_data(exchange->data); | |||
| 1207 | free(exchange->data); | |||
| 1208 | } | |||
| 1209 | free(exchange->name); | |||
| 1210 | if (exchange->recv_cert) { | |||
| 1211 | handler = cert_get(exchange->recv_certtype); | |||
| 1212 | if (handler) | |||
| 1213 | handler->cert_free(exchange->recv_cert); | |||
| 1214 | } | |||
| 1215 | if (exchange->sent_cert) { | |||
| 1216 | handler = cert_get(exchange->sent_certtype); | |||
| 1217 | if (handler) | |||
| 1218 | handler->cert_free(exchange->sent_cert); | |||
| 1219 | } | |||
| 1220 | if (exchange->recv_key) | |||
| 1221 | key_free(exchange->recv_keytype, ISAKMP_KEYTYPE_PUBLIC0, | |||
| 1222 | exchange->recv_key); | |||
| 1223 | free(exchange->keynote_key); /* This is just a string */ | |||
| 1224 | ||||
| 1225 | if (exchange->policy_id != -1) | |||
| 1226 | kn_close(exchange->policy_id); | |||
| 1227 | ||||
| 1228 | exchange_free_aca_list(exchange); | |||
| 1229 | if (exchange->linked) { | |||
| 1230 | LIST_REMOVE(exchange, link)do { if ((exchange)->link.le_next != ((void*)0)) (exchange )->link.le_next->link.le_prev = (exchange)->link.le_prev ; *(exchange)->link.le_prev = (exchange)->link.le_next; ; ; } while (0); | |||
| 1231 | exchange->linked = 0; | |||
| 1232 | } | |||
| 1233 | ||||
| 1234 | /* Tell potential finalize routine we never got there. */ | |||
| 1235 | if (exchange->finalize) | |||
| 1236 | exchange->finalize(exchange, exchange->finalize_arg, 1); | |||
| 1237 | ||||
| 1238 | /* Remove any SAs that have not been disassociated from us. */ | |||
| 1239 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa; sa = next_sa) { | |||
| 1240 | next_sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next); | |||
| 1241 | /* One for the reference in exchange->sa_list. */ | |||
| 1242 | sa_release(sa); | |||
| 1243 | /* And two more for the expiration and SA linked list. */ | |||
| 1244 | sa_free(sa); | |||
| 1245 | } | |||
| 1246 | ||||
| 1247 | free(exchange); | |||
| 1248 | } | |||
| 1249 | ||||
| 1250 | /* Release all resources this exchange is using. */ | |||
| 1251 | void | |||
| 1252 | exchange_free(struct exchange *exchange) | |||
| 1253 | { | |||
| 1254 | if (exchange->death) | |||
| 1255 | timer_remove_event(exchange->death); | |||
| 1256 | exchange_free_aux(exchange); | |||
| 1257 | } | |||
| 1258 | ||||
| 1259 | /* | |||
| 1260 | * Upgrade the phase 1 exchange and its ISAKMP SA with the rcookie of our | |||
| 1261 | * peer (found in his recently sent message MSG). | |||
| 1262 | */ | |||
| 1263 | void | |||
| 1264 | exchange_upgrade_p1(struct message *msg) | |||
| 1265 | { | |||
| 1266 | struct exchange *exchange = msg->exchange; | |||
| 1267 | ||||
| 1268 | LIST_REMOVE(exchange, link)do { if ((exchange)->link.le_next != ((void*)0)) (exchange )->link.le_next->link.le_prev = (exchange)->link.le_prev ; *(exchange)->link.le_prev = (exchange)->link.le_next; ; ; } while (0); | |||
| 1269 | exchange->linked = 0; | |||
| 1270 | GET_ISAKMP_HDR_RCOOKIE(msg->iov[0].iov_base, exchange->cookies +field_get_raw (isakmp_hdr_fld + 1, msg->iov[0].iov_base, exchange ->cookies + 8) | |||
| 1271 | ISAKMP_HDR_ICOOKIE_LEN)field_get_raw (isakmp_hdr_fld + 1, msg->iov[0].iov_base, exchange ->cookies + 8); | |||
| 1272 | exchange_enter(exchange); | |||
| 1273 | sa_isakmp_upgrade(msg); | |||
| 1274 | } | |||
| 1275 | ||||
| 1276 | static int | |||
| 1277 | exchange_check_old_sa(struct sa *sa, void *v_arg) | |||
| 1278 | { | |||
| 1279 | struct sa *new_sa = v_arg; | |||
| 1280 | char res1[1024]; | |||
| 1281 | ||||
| 1282 | if (sa == new_sa || !sa->name || !(sa->flags & SA_FLAG_READY0x01) || | |||
| 1283 | (sa->flags & SA_FLAG_REPLACED0x08)) | |||
| 1284 | return 0; | |||
| 1285 | ||||
| 1286 | if (sa->phase != new_sa->phase || new_sa->name == 0 || | |||
| 1287 | strcasecmp(sa->name, new_sa->name)) | |||
| 1288 | return 0; | |||
| 1289 | ||||
| 1290 | if (sa->initiator) | |||
| 1291 | strlcpy(res1, ipsec_decode_ids("%s %s", sa->id_i, sa->id_i_len, | |||
| 1292 | sa->id_r, sa->id_r_len, 0), sizeof res1); | |||
| 1293 | else | |||
| 1294 | strlcpy(res1, ipsec_decode_ids("%s %s", sa->id_r, sa->id_r_len, | |||
| 1295 | sa->id_i, sa->id_i_len, 0), sizeof res1); | |||
| 1296 | ||||
| 1297 | LOG_DBG((LOG_EXCHANGE, 30,log_debug (LOG_EXCHANGE, 30, "checking whether new SA replaces existing SA with IDs %s" , res1) | |||
| 1298 | "checking whether new SA replaces existing SA with IDs %s", res1))log_debug (LOG_EXCHANGE, 30, "checking whether new SA replaces existing SA with IDs %s" , res1); | |||
| 1299 | ||||
| 1300 | if (new_sa->initiator) | |||
| 1301 | return strcasecmp(res1, ipsec_decode_ids("%s %s", new_sa->id_i, | |||
| 1302 | new_sa->id_i_len, new_sa->id_r, new_sa->id_r_len, 0)) == 0; | |||
| 1303 | else | |||
| 1304 | return strcasecmp(res1, ipsec_decode_ids("%s %s", new_sa->id_r, | |||
| 1305 | new_sa->id_r_len, new_sa->id_i, new_sa->id_i_len, 0)) == 0; | |||
| 1306 | } | |||
| 1307 | ||||
| 1308 | void | |||
| 1309 | exchange_finalize(struct message *msg) | |||
| 1310 | { | |||
| 1311 | struct exchange *exchange = msg->exchange; | |||
| 1312 | struct sa *sa, *old_sa; | |||
| 1313 | struct proto *proto; | |||
| 1314 | struct conf_list *attrs; | |||
| 1315 | struct conf_list_node *attr; | |||
| 1316 | struct cert_handler *handler; | |||
| 1317 | int i; | |||
| 1318 | char *id_doi, *id_trp; | |||
| 1319 | ||||
| 1320 | exchange_dump("exchange_finalize", exchange); | |||
| 1321 | ||||
| 1322 | /* Copy the ID from phase 1 to exchange or phase 2 SA. */ | |||
| 1323 | if (msg->isakmp_sa) { | |||
| 1324 | if (exchange->id_i && exchange->id_r) { | |||
| 1325 | ipsec_clone_id(&msg->isakmp_sa->id_i, | |||
| 1326 | &msg->isakmp_sa->id_i_len, exchange->id_i, | |||
| 1327 | exchange->id_i_len); | |||
| 1328 | ipsec_clone_id(&msg->isakmp_sa->id_r, | |||
| 1329 | &msg->isakmp_sa->id_r_len, exchange->id_r, | |||
| 1330 | exchange->id_r_len); | |||
| 1331 | } else if (msg->isakmp_sa->id_i && msg->isakmp_sa->id_r) { | |||
| 1332 | ipsec_clone_id(&exchange->id_i, &exchange->id_i_len, | |||
| 1333 | msg->isakmp_sa->id_i, msg->isakmp_sa->id_i_len); | |||
| 1334 | ipsec_clone_id(&exchange->id_r, &exchange->id_r_len, | |||
| 1335 | msg->isakmp_sa->id_r, msg->isakmp_sa->id_r_len); | |||
| 1336 | } | |||
| 1337 | } | |||
| 1338 | /* | |||
| 1339 | * Walk over all the SAs and noting them as ready. If we set the | |||
| 1340 | * COMMIT bit, tell the peer each SA is connected. | |||
| 1341 | * | |||
| 1342 | * XXX The decision should really be based on if a SA was installed | |||
| 1343 | * successfully. | |||
| 1344 | */ | |||
| 1345 | for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa; | |||
| 1346 | sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) { | |||
| 1347 | /* Move over the name to the SA. */ | |||
| 1348 | sa->name = exchange->name ? strdup(exchange->name) : 0; | |||
| 1349 | ||||
| 1350 | if (exchange->flags & EXCHANGE_FLAG_I_COMMITTED0x0001) { | |||
| 1351 | for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto; | |||
| 1352 | proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next)) | |||
| 1353 | for (i = 0; i < 2; i++) | |||
| 1354 | message_send_notification(exchange->last_received, | |||
| 1355 | msg->isakmp_sa, | |||
| 1356 | ISAKMP_NOTIFY_STATUS_CONNECTED16384, | |||
| 1357 | proto, i); | |||
| 1358 | } | |||
| 1359 | /* | |||
| 1360 | * Locate any old SAs and mark them replaced | |||
| 1361 | * (SA_FLAG_REPLACED). | |||
| 1362 | */ | |||
| 1363 | sa->initiator = exchange->initiator; | |||
| 1364 | while ((old_sa = sa_find(exchange_check_old_sa, sa)) != 0) | |||
| 1365 | sa_mark_replaced(old_sa); | |||
| 1366 | ||||
| 1367 | /* Setup the SA flags. */ | |||
| 1368 | sa->flags |= SA_FLAG_READY0x01; | |||
| 1369 | if (exchange->name) { | |||
| 1370 | attrs = conf_get_list(exchange->name, "Flags"); | |||
| 1371 | if (attrs) { | |||
| 1372 | for (attr = TAILQ_FIRST(&attrs->fields)((&attrs->fields)->tqh_first); attr; | |||
| 1373 | attr = TAILQ_NEXT(attr, link)((attr)->link.tqe_next)) | |||
| 1374 | sa->flags |= sa_flag(attr->field); | |||
| 1375 | conf_free_list(attrs); | |||
| 1376 | } | |||
| 1377 | /* 'Connections' should stay alive. */ | |||
| 1378 | if (connection_exist(exchange->name)) { | |||
| 1379 | sa->flags |= SA_FLAG_STAYALIVE0x02; | |||
| 1380 | ||||
| 1381 | /* | |||
| 1382 | * ISAKMP SA of this connection should also | |||
| 1383 | * stay alive. | |||
| 1384 | */ | |||
| 1385 | if (exchange->phase == 2 && msg->isakmp_sa) | |||
| 1386 | msg->isakmp_sa->flags |= | |||
| 1387 | SA_FLAG_STAYALIVE0x02; | |||
| 1388 | } | |||
| 1389 | } | |||
| 1390 | sa->seq = exchange->seq; | |||
| 1391 | sa->exch_type = exchange->type; | |||
| 1392 | } | |||
| 1393 | ||||
| 1394 | /* | |||
| 1395 | * If this was an phase 1 SA negotiation, save the keystate in the | |||
| 1396 | * ISAKMP SA structure for future initialization of phase 2 exchanges' | |||
| 1397 | * keystates. Also save the Phase 1 ID and authentication | |||
| 1398 | * information. | |||
| 1399 | */ | |||
| 1400 | if (exchange->phase == 1 && msg->isakmp_sa) { | |||
| 1401 | msg->isakmp_sa->keystate = exchange->keystate; | |||
| 1402 | exchange->keystate = 0; | |||
| 1403 | ||||
| 1404 | msg->isakmp_sa->recv_certtype = exchange->recv_certtype; | |||
| 1405 | msg->isakmp_sa->sent_certtype = exchange->sent_certtype; | |||
| 1406 | msg->isakmp_sa->recv_keytype = exchange->recv_keytype; | |||
| 1407 | msg->isakmp_sa->recv_key = exchange->recv_key; | |||
| 1408 | msg->isakmp_sa->keynote_key = exchange->keynote_key; | |||
| 1409 | /* Reset. */ | |||
| 1410 | exchange->recv_key = 0; | |||
| 1411 | exchange->keynote_key = 0; | |||
| 1412 | msg->isakmp_sa->policy_id = exchange->policy_id; | |||
| 1413 | exchange->policy_id = -1; | |||
| 1414 | msg->isakmp_sa->initiator = exchange->initiator; | |||
| 1415 | ||||
| 1416 | if (exchange->recv_certtype && exchange->recv_cert) { | |||
| 1417 | handler = cert_get(exchange->recv_certtype); | |||
| 1418 | if (handler) | |||
| 1419 | msg->isakmp_sa->recv_cert = | |||
| 1420 | handler->cert_dup(exchange->recv_cert); | |||
| 1421 | } | |||
| 1422 | if (exchange->sent_certtype) { | |||
| 1423 | handler = cert_get(exchange->sent_certtype); | |||
| 1424 | if (handler) | |||
| 1425 | msg->isakmp_sa->sent_cert = | |||
| 1426 | handler->cert_dup(exchange->sent_cert); | |||
| 1427 | } | |||
| 1428 | if (exchange->doi) | |||
| 1429 | id_doi = exchange->doi->decode_ids( | |||
| 1430 | "initiator id %s, responder id %s", | |||
| 1431 | exchange->id_i, exchange->id_i_len, | |||
| 1432 | exchange->id_r, exchange->id_r_len, 0); | |||
| 1433 | else | |||
| 1434 | id_doi = "<no doi>"; | |||
| 1435 | ||||
| 1436 | if (msg->isakmp_sa->transport) | |||
| 1437 | id_trp = | |||
| 1438 | msg->isakmp_sa->transport->vtbl->decode_ids(msg->isakmp_sa->transport); | |||
| 1439 | else | |||
| 1440 | id_trp = "<no transport>"; | |||
| 1441 | ||||
| 1442 | if (exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE0x0010) | |||
| 1443 | msg->isakmp_sa->flags |= SA_FLAG_NAT_T_ENABLE0x100; | |||
| 1444 | if (exchange->flags & EXCHANGE_FLAG_NAT_T_KEEPALIVE0x0020) | |||
| 1445 | msg->isakmp_sa->flags |= SA_FLAG_NAT_T_KEEPALIVE0x200; | |||
| 1446 | ||||
| 1447 | LOG_DBG((LOG_EXCHANGE, 10,log_debug (LOG_EXCHANGE, 10, "exchange_finalize: phase 1 done: %s, %s" , id_doi, id_trp) | |||
| 1448 | "exchange_finalize: phase 1 done: %s, %s", id_doi,log_debug (LOG_EXCHANGE, 10, "exchange_finalize: phase 1 done: %s, %s" , id_doi, id_trp) | |||
| 1449 | id_trp))log_debug (LOG_EXCHANGE, 10, "exchange_finalize: phase 1 done: %s, %s" , id_doi, id_trp); | |||
| 1450 | ||||
| 1451 | log_verbose("isakmpd: phase 1 done%s: %s, %s", | |||
| 1452 | (exchange->initiator == 0) ? " (as responder)" : "", | |||
| 1453 | id_doi, id_trp); | |||
| 1454 | } | |||
| 1455 | exchange->doi->finalize_exchange(msg); | |||
| 1456 | if (exchange->finalize) | |||
| 1457 | exchange->finalize(exchange, exchange->finalize_arg, 0); | |||
| 1458 | exchange->finalize = 0; | |||
| 1459 | ||||
| 1460 | /* | |||
| 1461 | * There is no reason to keep the SAs connected to us anymore, in fact | |||
| 1462 | * it can hurt us if we have short lifetimes on the SAs and we try | |||
| 1463 | * to call exchange_report, where the SA list will be walked and | |||
| 1464 | * references to freed SAs can occur. | |||
| 1465 | */ | |||
| 1466 | while (TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first)) { | |||
| 1467 | sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); | |||
| 1468 | ||||
| 1469 | if (exchange->id_i && exchange->id_r) { | |||
| 1470 | ipsec_clone_id(&sa->id_i, &sa->id_i_len, | |||
| 1471 | exchange->id_i, exchange->id_i_len); | |||
| 1472 | ipsec_clone_id(&sa->id_r, &sa->id_r_len, | |||
| 1473 | exchange->id_r, exchange->id_r_len); | |||
| 1474 | } | |||
| 1475 | TAILQ_REMOVE(&exchange->sa_list, sa, next)do { if (((sa)->next.tqe_next) != ((void*)0)) (sa)->next .tqe_next->next.tqe_prev = (sa)->next.tqe_prev; else (& exchange->sa_list)->tqh_last = (sa)->next.tqe_prev; * (sa)->next.tqe_prev = (sa)->next.tqe_next; ; ; } while ( 0); | |||
| 1476 | sa_release(sa); | |||
| 1477 | } | |||
| 1478 | /* | |||
| 1479 | * Start sending DPD messages after all SAs have been released. | |||
| 1480 | * Otherwise we have a race between exchange_free_aux() and | |||
| 1481 | * dpd_check_event() where both will call sa_free(). | |||
| 1482 | */ | |||
| 1483 | if (exchange->phase == 1 && msg->isakmp_sa && | |||
| 1484 | (exchange->flags & EXCHANGE_FLAG_DPD_CAP_PEER0x0040)) | |||
| 1485 | dpd_start(msg->isakmp_sa); | |||
| 1486 | ||||
| 1487 | /* If we have nothing to retransmit we can safely remove ourselves. */ | |||
| 1488 | if (!exchange->last_sent) | |||
| 1489 | exchange_free(exchange); | |||
| 1490 | } | |||
| 1491 | ||||
| 1492 | /* Stash a nonce into the exchange data. */ | |||
| 1493 | static int | |||
| 1494 | exchange_nonce(struct exchange *exchange, int peer, size_t nonce_sz, | |||
| 1495 | u_int8_t *buf) | |||
| 1496 | { | |||
| 1497 | u_int8_t **nonce; | |||
| 1498 | size_t *nonce_len; | |||
| 1499 | int initiator = exchange->initiator ^ peer; | |||
| 1500 | char header[32]; | |||
| 1501 | ||||
| 1502 | if (nonce_sz < 8 || nonce_sz > 256) { | |||
| 1503 | /* | |||
| 1504 | * RFC2409, ch 5: The length of nonce payload MUST be | |||
| 1505 | * between 8 and 256 bytes inclusive. | |||
| 1506 | * XXX I'm assuming the generic payload header is not included. | |||
| 1507 | */ | |||
| 1508 | LOG_DBG((LOG_EXCHANGE, 20,log_debug (LOG_EXCHANGE, 20, "exchange_nonce: invalid nonce length %lu" , (unsigned long)nonce_sz) | |||
| 1509 | "exchange_nonce: invalid nonce length %lu",log_debug (LOG_EXCHANGE, 20, "exchange_nonce: invalid nonce length %lu" , (unsigned long)nonce_sz) | |||
| 1510 | (unsigned long)nonce_sz))log_debug (LOG_EXCHANGE, 20, "exchange_nonce: invalid nonce length %lu" , (unsigned long)nonce_sz); | |||
| 1511 | return -1; | |||
| 1512 | } | |||
| 1513 | ||||
| 1514 | nonce = initiator ? &exchange->nonce_i : &exchange->nonce_r; | |||
| 1515 | nonce_len = | |||
| 1516 | initiator ? &exchange->nonce_i_len : &exchange->nonce_r_len; | |||
| 1517 | *nonce_len = nonce_sz; | |||
| 1518 | *nonce = malloc(nonce_sz); | |||
| 1519 | if (!*nonce) { | |||
| 1520 | log_error("exchange_nonce: malloc (%lu) failed", | |||
| 1521 | (unsigned long)nonce_sz); | |||
| 1522 | return -1; | |||
| 1523 | } | |||
| 1524 | memcpy(*nonce, buf, nonce_sz); | |||
| 1525 | snprintf(header, sizeof header, "exchange_nonce: NONCE_%c", | |||
| 1526 | initiator ? 'i' : 'r'); | |||
| 1527 | LOG_DBG_BUF((LOG_EXCHANGE, 80, header, *nonce, nonce_sz))log_debug_buf (LOG_EXCHANGE, 80, header, *nonce, nonce_sz); | |||
| 1528 | return 0; | |||
| 1529 | } | |||
| 1530 | ||||
| 1531 | /* Generate our NONCE. */ | |||
| 1532 | int | |||
| 1533 | exchange_gen_nonce(struct message *msg, size_t nonce_sz) | |||
| 1534 | { | |||
| 1535 | struct exchange *exchange = msg->exchange; | |||
| 1536 | u_int8_t *buf; | |||
| 1537 | ||||
| 1538 | buf = malloc(ISAKMP_NONCE_SZ4 + nonce_sz); | |||
| 1539 | if (!buf) { | |||
| 1540 | log_error("exchange_gen_nonce: malloc (%lu) failed", | |||
| 1541 | ISAKMP_NONCE_SZ4 + (unsigned long)nonce_sz); | |||
| 1542 | return -1; | |||
| 1543 | } | |||
| 1544 | arc4random_buf(buf + ISAKMP_NONCE_DATA_OFF4, nonce_sz); | |||
| 1545 | if (message_add_payload(msg, ISAKMP_PAYLOAD_NONCE10, buf, | |||
| 1546 | ISAKMP_NONCE_SZ4 + nonce_sz, 1)) { | |||
| 1547 | free(buf); | |||
| 1548 | return -1; | |||
| 1549 | } | |||
| 1550 | return exchange_nonce(exchange, 0, nonce_sz, | |||
| 1551 | buf + ISAKMP_NONCE_DATA_OFF4); | |||
| 1552 | } | |||
| 1553 | ||||
| 1554 | /* Save the peer's NONCE. */ | |||
| 1555 | int | |||
| 1556 | exchange_save_nonce(struct message *msg) | |||
| 1557 | { | |||
| 1558 | struct payload *noncep; | |||
| 1559 | struct exchange *exchange = msg->exchange; | |||
| 1560 | ||||
| 1561 | noncep = payload_first(msg, ISAKMP_PAYLOAD_NONCE10); | |||
| 1562 | noncep->flags |= PL_MARK1; | |||
| 1563 | return exchange_nonce(exchange, 1, GET_ISAKMP_GEN_LENGTH(noncep->p)field_get_num (isakmp_gen_fld + 2, noncep->p) - | |||
| 1564 | ISAKMP_NONCE_DATA_OFF4, noncep->p + ISAKMP_NONCE_DATA_OFF4); | |||
| 1565 | } | |||
| 1566 | ||||
| 1567 | /* Save the peer's CERT REQuests. */ | |||
| 1568 | int | |||
| 1569 | exchange_save_certreq(struct message *msg) | |||
| 1570 | { | |||
| 1571 | struct payload *cp; | |||
| 1572 | struct exchange *exchange = msg->exchange; | |||
| 1573 | struct certreq_aca *aca; | |||
| 1574 | ||||
| 1575 | TAILQ_FOREACH(cp, &msg->payload[ISAKMP_PAYLOAD_CERT_REQ], link)for((cp) = ((&msg->payload[7])->tqh_first); (cp) != ((void*)0); (cp) = ((cp)->link.tqe_next)) { | |||
| 1576 | cp->flags |= PL_MARK1; | |||
| 1577 | aca = certreq_decode(GET_ISAKMP_CERTREQ_TYPE(cp->p)field_get_num (isakmp_certreq_fld + 0, cp->p), cp->p + | |||
| 1578 | ISAKMP_CERTREQ_AUTHORITY_OFF5, GET_ISAKMP_GEN_LENGTH(cp->p)field_get_num (isakmp_gen_fld + 2, cp->p) | |||
| 1579 | - ISAKMP_CERTREQ_AUTHORITY_OFF5); | |||
| 1580 | if (aca) | |||
| 1581 | TAILQ_INSERT_TAIL(&exchange->aca_list, aca, link)do { (aca)->link.tqe_next = ((void*)0); (aca)->link.tqe_prev = (&exchange->aca_list)->tqh_last; *(&exchange ->aca_list)->tqh_last = (aca); (&exchange->aca_list )->tqh_last = &(aca)->link.tqe_next; } while (0); | |||
| 1582 | } | |||
| 1583 | ||||
| 1584 | return 0; | |||
| 1585 | } | |||
| 1586 | ||||
| 1587 | /* Free the list of pending CERTREQs. */ | |||
| 1588 | void | |||
| 1589 | exchange_free_aca_list(struct exchange *exchange) | |||
| 1590 | { | |||
| 1591 | struct certreq_aca *aca; | |||
| 1592 | ||||
| 1593 | for (aca = TAILQ_FIRST(&exchange->aca_list)((&exchange->aca_list)->tqh_first); aca; | |||
| 1594 | aca = TAILQ_FIRST(&exchange->aca_list)((&exchange->aca_list)->tqh_first)) { | |||
| 1595 | free(aca->raw_ca); | |||
| ||||
| 1596 | if (aca->data) { | |||
| 1597 | if (aca->handler) | |||
| 1598 | aca->handler->free_aca(aca->data); | |||
| 1599 | free(aca->data); | |||
| 1600 | } | |||
| 1601 | TAILQ_REMOVE(&exchange->aca_list, aca, link)do { if (((aca)->link.tqe_next) != ((void*)0)) (aca)->link .tqe_next->link.tqe_prev = (aca)->link.tqe_prev; else ( &exchange->aca_list)->tqh_last = (aca)->link.tqe_prev ; *(aca)->link.tqe_prev = (aca)->link.tqe_next; ; ; } while (0); | |||
| 1602 | free(aca); | |||
| 1603 | } | |||
| 1604 | } | |||
| 1605 | ||||
| 1606 | /* Add any CERTREQs we should send. */ | |||
| 1607 | int | |||
| 1608 | exchange_add_certreqs(struct message *msg) | |||
| 1609 | { | |||
| 1610 | struct exchange *exchange = msg->exchange; | |||
| 1611 | struct certreq_aca *aca; | |||
| 1612 | u_int8_t *buf; | |||
| 1613 | ||||
| 1614 | /* | |||
| 1615 | * Some peers (e.g. Cisco IOS) won't send their cert unless we | |||
| 1616 | * specifically ask beforehand with CERTREQ. We reflect any | |||
| 1617 | * CERTREQs we receive from the initiator in order to do this. | |||
| 1618 | * This avoids leaking information about which CAs we trust, | |||
| 1619 | * and works in the most common case where both ends trust the | |||
| 1620 | * same CA. | |||
| 1621 | */ | |||
| 1622 | for (aca = TAILQ_FIRST(&exchange->aca_list)((&exchange->aca_list)->tqh_first); aca; | |||
| 1623 | aca = TAILQ_NEXT(aca, link)((aca)->link.tqe_next)) { | |||
| 1624 | ||||
| 1625 | /* But only do this if we have at least one CA */ | |||
| 1626 | if (aca->handler != NULL((void*)0) && aca->handler->ca_count() == 0) { | |||
| 1627 | LOG_DBG((LOG_EXCHANGE, 10,log_debug (LOG_EXCHANGE, 10, "exchange_add_certreqs: no CA, so not " "sending a CERTREQ") | |||
| 1628 | "exchange_add_certreqs: no CA, so not "log_debug (LOG_EXCHANGE, 10, "exchange_add_certreqs: no CA, so not " "sending a CERTREQ") | |||
| 1629 | "sending a CERTREQ"))log_debug (LOG_EXCHANGE, 10, "exchange_add_certreqs: no CA, so not " "sending a CERTREQ"); | |||
| 1630 | continue; | |||
| 1631 | } | |||
| 1632 | ||||
| 1633 | if (aca->raw_ca_len) { | |||
| 1634 | buf = malloc(ISAKMP_CERTREQ_SZ5 + aca->raw_ca_len); | |||
| 1635 | if (buf == NULL((void*)0)) { | |||
| 1636 | log_error("exchange_add_certreqs: " | |||
| 1637 | "malloc (%lu) failed", | |||
| 1638 | ISAKMP_CERTREQ_SZ5 + | |||
| 1639 | (unsigned long)aca->raw_ca_len); | |||
| 1640 | return -1; | |||
| 1641 | } | |||
| 1642 | ||||
| 1643 | buf[ISAKMP_CERTREQ_TYPE_OFF4] = aca->id; | |||
| 1644 | memcpy(buf + ISAKMP_CERTREQ_AUTHORITY_OFF5, | |||
| 1645 | aca->raw_ca, aca->raw_ca_len); | |||
| 1646 | ||||
| 1647 | if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT_REQ7, | |||
| 1648 | buf, ISAKMP_CERTREQ_SZ5 + aca->raw_ca_len, 1)) { | |||
| 1649 | free(buf); | |||
| 1650 | return -1; | |||
| 1651 | } | |||
| 1652 | } | |||
| 1653 | } | |||
| 1654 | ||||
| 1655 | return 0; | |||
| 1656 | } | |||
| 1657 | ||||
| 1658 | /* Obtain certificates from acceptable certification authority. */ | |||
| 1659 | int | |||
| 1660 | exchange_add_certs(struct message *msg) | |||
| 1661 | { | |||
| 1662 | struct exchange *exchange = msg->exchange; | |||
| 1663 | struct certreq_aca *aca; | |||
| 1664 | u_int8_t *cert = 0, *new_cert = 0; | |||
| 1665 | u_int32_t certlen; | |||
| 1666 | u_int8_t *id; | |||
| 1667 | size_t id_len; | |||
| 1668 | ||||
| 1669 | id = exchange->initiator ? exchange->id_r : exchange->id_i; | |||
| ||||
| 1670 | id_len = exchange->initiator
| |||
| 1671 | ||||
| 1672 | /* | |||
| 1673 | * Without IDs we cannot handle this yet. Keep the aca_list around for | |||
| 1674 | * a later step/retry to see if we got the ID by then. | |||
| 1675 | * Note: A 'return -1' breaks X509-auth interop in the responder case | |||
| 1676 | * with some IPsec clients that send CERTREQs early (such as | |||
| 1677 | * the SSH Sentinel). | |||
| 1678 | */ | |||
| 1679 | if (!id) | |||
| 1680 | return 0; | |||
| 1681 | ||||
| 1682 | for (aca = TAILQ_FIRST(&exchange->aca_list)((&exchange->aca_list)->tqh_first); aca; | |||
| 1683 | aca = TAILQ_NEXT(aca, link)((aca)->link.tqe_next)) { | |||
| 1684 | /* XXX? If we can not satisfy a CERTREQ we drop the message. */ | |||
| 1685 | if (!aca->handler->cert_obtain(id, id_len, aca->data, &cert, | |||
| 1686 | &certlen)) { | |||
| 1687 | log_print("exchange_add_certs: could not obtain cert " | |||
| 1688 | "for a type %d cert request", aca->id); | |||
| 1689 | free(cert); | |||
| 1690 | return -1; | |||
| 1691 | } | |||
| 1692 | new_cert = realloc(cert, ISAKMP_CERT_SZ5 + certlen); | |||
| 1693 | if (!new_cert) { | |||
| 1694 | log_error("exchange_add_certs: realloc (%p, %d) " | |||
| 1695 | "failed", cert, ISAKMP_CERT_SZ5 + certlen); | |||
| 1696 | free(cert); | |||
| 1697 | return -1; | |||
| 1698 | } | |||
| 1699 | cert = new_cert; | |||
| 1700 | memmove(cert + ISAKMP_CERT_DATA_OFF5, cert, certlen); | |||
| 1701 | SET_ISAKMP_CERT_ENCODING(cert, aca->id)field_set_num (isakmp_cert_fld + 0, cert, aca->id); | |||
| 1702 | if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT6, cert, | |||
| 1703 | ISAKMP_CERT_SZ5 + certlen, 1)) { | |||
| 1704 | free(cert); | |||
| 1705 | return -1; | |||
| 1706 | } | |||
| 1707 | /* | |||
| 1708 | * We need to reset cert here, as it is now controlled by | |||
| 1709 | * message_add_payload() (i.e. we must not free() it), and | |||
| 1710 | * it is possible for the next iteration of the aca loop | |||
| 1711 | * to fail early in cert_obtain before it writes to &cert. | |||
| 1712 | */ | |||
| 1713 | cert = NULL((void*)0); | |||
| 1714 | } | |||
| 1715 | ||||
| 1716 | /* We dont need the CERT REQs any more, they are answered. */ | |||
| 1717 | exchange_free_aca_list(exchange); | |||
| 1718 | ||||
| 1719 | return 0; | |||
| 1720 | } | |||
| 1721 | ||||
| 1722 | static void | |||
| 1723 | exchange_establish_finalize(struct exchange *exchange, void *arg, int fail) | |||
| 1724 | { | |||
| 1725 | char *name = arg; | |||
| 1726 | ||||
| 1727 | LOG_DBG((LOG_EXCHANGE, 20, "exchange_establish_finalize: "log_debug (LOG_EXCHANGE, 20, "exchange_establish_finalize: " "finalizing exchange %p with arg %p (%s) & fail = %d" , exchange, arg, name ? name : "<unnamed>", fail) | |||
| 1728 | "finalizing exchange %p with arg %p (%s) & fail = %d",log_debug (LOG_EXCHANGE, 20, "exchange_establish_finalize: " "finalizing exchange %p with arg %p (%s) & fail = %d" , exchange, arg, name ? name : "<unnamed>", fail) | |||
| 1729 | exchange, arg, name ? name : "<unnamed>", fail))log_debug (LOG_EXCHANGE, 20, "exchange_establish_finalize: " "finalizing exchange %p with arg %p (%s) & fail = %d" , exchange, arg, name ? name : "<unnamed>", fail); | |||
| 1730 | ||||
| 1731 | if (!fail) | |||
| 1732 | exchange_establish(name, 0, 0, 0); | |||
| 1733 | free(name); | |||
| 1734 | } | |||
| 1735 | ||||
| 1736 | /* | |||
| 1737 | * Establish an exchange named NAME, and record the FINALIZE function | |||
| 1738 | * taking ARG as an argument to be run after the exchange is ready. | |||
| 1739 | */ | |||
| 1740 | void | |||
| 1741 | exchange_establish(char *name, void (*finalize)(struct exchange *, void *, | |||
| 1742 | int), void *arg, int stayalive) | |||
| 1743 | { | |||
| 1744 | struct transport *transport; | |||
| 1745 | struct sa *isakmp_sa; | |||
| 1746 | struct exchange *exchange; | |||
| 1747 | int phase; | |||
| 1748 | char *trpt, *peer; | |||
| 1749 | ||||
| 1750 | phase = conf_get_num(name, "Phase", 0); | |||
| 1751 | ||||
| 1752 | if (ui_daemon_passive) { | |||
| 1753 | LOG_DBG((LOG_EXCHANGE, 40, "exchange_establish:"log_debug (LOG_EXCHANGE, 40, "exchange_establish:" " returning in passive mode for exchange %s phase %d" , name, phase) | |||
| 1754 | " returning in passive mode for exchange %s phase %d",log_debug (LOG_EXCHANGE, 40, "exchange_establish:" " returning in passive mode for exchange %s phase %d" , name, phase) | |||
| 1755 | name, phase))log_debug (LOG_EXCHANGE, 40, "exchange_establish:" " returning in passive mode for exchange %s phase %d" , name, phase); | |||
| 1756 | if (finalize) | |||
| 1757 | finalize(0, arg, 1); | |||
| 1758 | return; | |||
| 1759 | } | |||
| 1760 | ||||
| 1761 | /* | |||
| 1762 | * First of all, never try to establish anything if another exchange | |||
| 1763 | * of the same kind is running. | |||
| 1764 | */ | |||
| 1765 | exchange = exchange_lookup_by_name(name, phase); | |||
| 1766 | if (exchange) { | |||
| 1767 | LOG_DBG((LOG_EXCHANGE, 40,log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already exists as %p" , name, exchange) | |||
| 1768 | "exchange_establish: %s exchange already exists as %p",log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already exists as %p" , name, exchange) | |||
| 1769 | name, exchange))log_debug (LOG_EXCHANGE, 40, "exchange_establish: %s exchange already exists as %p" , name, exchange); | |||
| 1770 | exchange_add_finalization(exchange, finalize, arg); | |||
| 1771 | return; | |||
| 1772 | } | |||
| 1773 | switch (phase) { | |||
| 1774 | case 1: | |||
| 1775 | trpt = conf_get_str(name, "Transport"); | |||
| 1776 | if (!trpt) { | |||
| 1777 | /* Phase 1 transport defaults to "udp". */ | |||
| 1778 | trpt = ISAKMP_DEFAULT_TRANSPORT"udp"; | |||
| 1779 | } | |||
| 1780 | transport = transport_create(trpt, name); | |||
| 1781 | if (!transport) { | |||
| 1782 | log_print("exchange_establish: transport \"%s\" for " | |||
| 1783 | "peer \"%s\" could not be created", trpt, name); | |||
| 1784 | if (finalize) | |||
| 1785 | finalize(0, arg, 1); | |||
| 1786 | return; | |||
| 1787 | } | |||
| 1788 | if (exchange_establish_p1(transport, 0, 0, name, 0, finalize, | |||
| 1789 | arg, stayalive) < 0 && finalize) | |||
| 1790 | finalize(0, arg, 1); | |||
| 1791 | break; | |||
| 1792 | ||||
| 1793 | case 2: | |||
| 1794 | peer = conf_get_str(name, "ISAKMP-peer"); | |||
| 1795 | if (!peer) { | |||
| 1796 | log_print("exchange_establish: No ISAKMP-peer given " | |||
| 1797 | "for \"%s\"", name); | |||
| 1798 | if (finalize) | |||
| 1799 | finalize(0, arg, 1); | |||
| 1800 | return; | |||
| 1801 | } | |||
| 1802 | isakmp_sa = sa_lookup_by_name(peer, 1); | |||
| 1803 | if (!isakmp_sa) { | |||
| 1804 | /* freed by exchange_establish_finalize() */ | |||
| 1805 | name = strdup(name); | |||
| 1806 | if (!name) { | |||
| 1807 | log_error("exchange_establish: " | |||
| 1808 | "strdup (\"%s\") failed", name); | |||
| 1809 | if (finalize) | |||
| 1810 | finalize(0, arg, 1); | |||
| 1811 | return; | |||
| 1812 | } | |||
| 1813 | if (conf_get_num(peer, "Phase", 0) != 1) { | |||
| 1814 | log_print("exchange_establish: " | |||
| 1815 | "[%s]:ISAKMP-peer's (%s) phase is not 1", | |||
| 1816 | name, peer); | |||
| 1817 | if (finalize) | |||
| 1818 | finalize(0, arg, 1); | |||
| 1819 | free(name); | |||
| 1820 | return; | |||
| 1821 | } | |||
| 1822 | /* | |||
| 1823 | * XXX We're losing information here (what the | |||
| 1824 | * original finalize routine was. As a result, if an | |||
| 1825 | * exchange does not manage to get through, there may | |||
| 1826 | * be application-specific information that won't get | |||
| 1827 | * cleaned up, since no error signaling will be done. | |||
| 1828 | * This is the case with dynamic SAs and PFKEY. | |||
| 1829 | */ | |||
| 1830 | exchange_establish(peer, exchange_establish_finalize, | |||
| 1831 | name, 0); | |||
| 1832 | exchange = exchange_lookup_by_name(peer, 1); | |||
| 1833 | /* | |||
| 1834 | * If the exchange was correctly initialized, add the | |||
| 1835 | * original finalization routine; otherwise, call it | |||
| 1836 | * directly. | |||
| 1837 | */ | |||
| 1838 | if (exchange) | |||
| 1839 | exchange_add_finalization(exchange, finalize, | |||
| 1840 | arg); | |||
| 1841 | else { | |||
| 1842 | /* Indicate failure */ | |||
| 1843 | if (finalize) | |||
| 1844 | finalize(0, arg, 1); | |||
| 1845 | } | |||
| 1846 | return; | |||
| 1847 | } else { | |||
| 1848 | if (exchange_establish_p2(isakmp_sa, 0, name, 0, | |||
| 1849 | finalize, arg) < 0 && finalize) | |||
| 1850 | finalize(0, arg, 1); | |||
| 1851 | } | |||
| 1852 | break; | |||
| 1853 | ||||
| 1854 | default: | |||
| 1855 | log_print("exchange_establish: " | |||
| 1856 | "peer \"%s\" does not have a correct phase (%d)", | |||
| 1857 | name, phase); | |||
| 1858 | break; | |||
| 1859 | } | |||
| 1860 | } |