1*2f1aa25bSmpi /* $OpenBSD: exchange.c,v 1.142 2018/01/15 09:54:48 mpi Exp $ */
272c6dfaeSniklas /* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */
32040585eSniklas
42040585eSniklas /*
542af7185Sniklas * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved.
642af7185Sniklas * Copyright (c) 1999, 2001 Angelos D. Keromytis. All rights reserved.
7d6351a66Sho * Copyright (c) 1999, 2000, 2002 H�kan Olsson. All rights reserved.
82040585eSniklas *
92040585eSniklas * Redistribution and use in source and binary forms, with or without
102040585eSniklas * modification, are permitted provided that the following conditions
112040585eSniklas * are met:
122040585eSniklas * 1. Redistributions of source code must retain the above copyright
132040585eSniklas * notice, this list of conditions and the following disclaimer.
142040585eSniklas * 2. Redistributions in binary form must reproduce the above copyright
152040585eSniklas * notice, this list of conditions and the following disclaimer in the
162040585eSniklas * documentation and/or other materials provided with the distribution.
172040585eSniklas *
182040585eSniklas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
192040585eSniklas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
202040585eSniklas * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
212040585eSniklas * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
222040585eSniklas * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
232040585eSniklas * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242040585eSniklas * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252040585eSniklas * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262040585eSniklas * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
272040585eSniklas * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282040585eSniklas */
292040585eSniklas
302040585eSniklas /*
312040585eSniklas * This code was written under funding by Ericsson Radio Systems.
322040585eSniklas */
332040585eSniklas
342040585eSniklas #include <sys/types.h>
352b81057dSniklas #include <sys/socket.h>
362b81057dSniklas #include <netinet/in.h>
372b81057dSniklas #include <arpa/inet.h>
382040585eSniklas #include <stdlib.h>
392040585eSniklas #include <string.h>
4092d6a220Shshoexer #include <regex.h>
4192d6a220Shshoexer #include <keynote.h>
422040585eSniklas
432040585eSniklas #include "cert.h"
442b81057dSniklas #include "conf.h"
45ec172ef8Sniklas #include "connection.h"
462040585eSniklas #include "constants.h"
472040585eSniklas #include "cookie.h"
482040585eSniklas #include "crypto.h"
492040585eSniklas #include "doi.h"
502040585eSniklas #include "exchange.h"
512b81057dSniklas #include "ipsec_num.h"
522040585eSniklas #include "isakmp.h"
533b43e3b6Sniklas #include "isakmp_cfg.h"
54867bc2a7Sniklas #include "libcrypto.h"
552040585eSniklas #include "log.h"
562040585eSniklas #include "message.h"
572040585eSniklas #include "timer.h"
582b81057dSniklas #include "transport.h"
5980f73593Sniklas #include "ipsec.h"
602040585eSniklas #include "sa.h"
6114f1d06aSmpf #include "ui.h"
622040585eSniklas #include "util.h"
6300b1b4a9Sangelos #include "key.h"
64a31e0ec4Smarkus #include "dpd.h"
652040585eSniklas
662040585eSniklas /* Initial number of bits from the cookies used as hash. */
672040585eSniklas #define INITIAL_BUCKET_BITS 6
682040585eSniklas
692040585eSniklas /*
702040585eSniklas * Don't try to use more bits than this as a hash.
712040585eSniklas * We only XOR 16 bits so going above that means changing the code below
722040585eSniklas * too.
732040585eSniklas */
742040585eSniklas #define MAX_BUCKET_BITS 16
752040585eSniklas
762040585eSniklas static void exchange_dump(char *, struct exchange *);
7722819a49Sniklas static void exchange_free_aux(void *);
78cc6cc03eSho static struct exchange *exchange_lookup_active(char *, int);
792040585eSniklas
80baf9095eShshoexer static
LIST_HEAD(exchange_list,exchange)81baf9095eShshoexer LIST_HEAD(exchange_list, exchange) *exchange_tab;
822040585eSniklas
832040585eSniklas /* Works both as a maximum index and a mask. */
842040585eSniklas static int bucket_mask;
852040585eSniklas
862040585eSniklas /*
872040585eSniklas * Validation scripts used to test messages for correct content of
882040585eSniklas * payloads depending on the exchange type.
892040585eSniklas */
902040585eSniklas int16_t script_base[] = {
912040585eSniklas ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */
922040585eSniklas ISAKMP_PAYLOAD_NONCE,
932040585eSniklas EXCHANGE_SCRIPT_SWITCH,
942040585eSniklas ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */
952040585eSniklas ISAKMP_PAYLOAD_NONCE,
962040585eSniklas EXCHANGE_SCRIPT_SWITCH,
972040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH, /* Initiator -> responder. */
982040585eSniklas ISAKMP_PAYLOAD_ID,
992040585eSniklas EXCHANGE_SCRIPT_AUTH,
1002040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1012040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH, /* Responder -> initiator. */
1022040585eSniklas ISAKMP_PAYLOAD_ID,
1032040585eSniklas EXCHANGE_SCRIPT_AUTH,
1042040585eSniklas EXCHANGE_SCRIPT_END
1052040585eSniklas };
1062040585eSniklas
1072040585eSniklas int16_t script_identity_protection[] = {
1082040585eSniklas ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */
1092040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1102040585eSniklas ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */
1112040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1122040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH, /* Initiator -> responder. */
1132040585eSniklas ISAKMP_PAYLOAD_NONCE,
1142040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1152040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH, /* Responder -> initiator. */
1162040585eSniklas ISAKMP_PAYLOAD_NONCE,
1172040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1182040585eSniklas ISAKMP_PAYLOAD_ID, /* Initiator -> responder. */
1192040585eSniklas EXCHANGE_SCRIPT_AUTH,
1202040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1212040585eSniklas ISAKMP_PAYLOAD_ID, /* Responder -> initiator. */
1222040585eSniklas EXCHANGE_SCRIPT_AUTH,
1232040585eSniklas EXCHANGE_SCRIPT_END
1242040585eSniklas };
1252040585eSniklas
1262040585eSniklas int16_t script_authentication_only[] = {
1272040585eSniklas ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */
1282040585eSniklas ISAKMP_PAYLOAD_NONCE,
1292040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1302040585eSniklas ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */
1312040585eSniklas ISAKMP_PAYLOAD_NONCE,
1322040585eSniklas ISAKMP_PAYLOAD_ID,
1332040585eSniklas EXCHANGE_SCRIPT_AUTH,
1342040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1352040585eSniklas ISAKMP_PAYLOAD_ID, /* Initiator -> responder. */
1362040585eSniklas EXCHANGE_SCRIPT_AUTH,
1372040585eSniklas EXCHANGE_SCRIPT_END
1382040585eSniklas };
1392040585eSniklas
1402040585eSniklas int16_t script_aggressive[] = {
1412040585eSniklas ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */
1422040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH,
1432040585eSniklas ISAKMP_PAYLOAD_NONCE,
1442040585eSniklas ISAKMP_PAYLOAD_ID,
1452040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1462040585eSniklas ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */
1472040585eSniklas ISAKMP_PAYLOAD_KEY_EXCH,
1482040585eSniklas ISAKMP_PAYLOAD_NONCE,
1492040585eSniklas ISAKMP_PAYLOAD_ID,
1502040585eSniklas EXCHANGE_SCRIPT_AUTH,
1512040585eSniklas EXCHANGE_SCRIPT_SWITCH,
1522040585eSniklas EXCHANGE_SCRIPT_AUTH, /* Initiator -> responder. */
1532040585eSniklas EXCHANGE_SCRIPT_END
1542040585eSniklas };
1552040585eSniklas
1562040585eSniklas int16_t script_informational[] = {
1572040585eSniklas EXCHANGE_SCRIPT_INFO, /* Initiator -> responder. */
1582040585eSniklas EXCHANGE_SCRIPT_END
1592040585eSniklas };
1602040585eSniklas
1612040585eSniklas /*
1622040585eSniklas * Check what exchange SA is negotiated with and return a suitable validation
1632040585eSniklas * script.
1642040585eSniklas */
165b26670e8Sho int16_t *
exchange_script(struct exchange * exchange)1662040585eSniklas exchange_script(struct exchange *exchange)
1672040585eSniklas {
168baf9095eShshoexer switch (exchange->type) {
1692040585eSniklas case ISAKMP_EXCH_BASE:
1702040585eSniklas return script_base;
1712040585eSniklas case ISAKMP_EXCH_ID_PROT:
1722040585eSniklas return script_identity_protection;
1732040585eSniklas case ISAKMP_EXCH_AUTH_ONLY:
1742040585eSniklas return script_authentication_only;
1752040585eSniklas case ISAKMP_EXCH_AGGRESSIVE:
1762040585eSniklas return script_aggressive;
1772040585eSniklas case ISAKMP_EXCH_INFO:
1782040585eSniklas return script_informational;
1793b43e3b6Sniklas case ISAKMP_EXCH_TRANSACTION:
1803b43e3b6Sniklas return script_transaction;
1812040585eSniklas default:
1829d6bd3cfSderaadt if (exchange->type >= ISAKMP_EXCH_DOI_MIN)
1832040585eSniklas return exchange->doi->exchange_script(exchange->type);
1842040585eSniklas }
1852040585eSniklas return 0;
1862040585eSniklas }
1872040585eSniklas
1882040585eSniklas /*
1892040585eSniklas * Validate the message MSG's contents wrt what payloads the exchange type
1905678a57aShshoexer * requires at this point in the dialogue. Return -1 if the validation fails,
1912040585eSniklas * 0 if it succeeds and the script is not finished and 1 if it's ready.
1922040585eSniklas */
1932040585eSniklas static int
exchange_validate(struct message * msg)1942040585eSniklas exchange_validate(struct message *msg)
1952040585eSniklas {
1962040585eSniklas struct exchange *exchange = msg->exchange;
1972040585eSniklas int16_t *pc = exchange->exch_pc;
1982040585eSniklas
199baf9095eShshoexer while (*pc != EXCHANGE_SCRIPT_END && *pc != EXCHANGE_SCRIPT_SWITCH) {
20051ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 90,
201172c7fecSniklas "exchange_validate: checking for required %s",
2022040585eSniklas *pc >= ISAKMP_PAYLOAD_NONE
2032040585eSniklas ? constant_name(isakmp_payload_cst, *pc)
20451ca15aeSniklas : constant_name(exchange_script_cst, *pc)));
2052040585eSniklas
2062040585eSniklas /* Check for existence of the required payloads. */
2079d6bd3cfSderaadt if ((*pc > 0 && !payload_first(msg, *pc)) ||
2089d6bd3cfSderaadt (*pc == EXCHANGE_SCRIPT_AUTH &&
2099d6bd3cfSderaadt !payload_first(msg, ISAKMP_PAYLOAD_HASH) &&
2109d6bd3cfSderaadt !payload_first(msg, ISAKMP_PAYLOAD_SIG)) ||
2119d6bd3cfSderaadt (*pc == EXCHANGE_SCRIPT_INFO &&
2129d6bd3cfSderaadt ((!payload_first(msg, ISAKMP_PAYLOAD_NOTIFY) &&
2139d6bd3cfSderaadt !payload_first(msg, ISAKMP_PAYLOAD_DELETE)) ||
2149d6bd3cfSderaadt (payload_first(msg, ISAKMP_PAYLOAD_DELETE) &&
2159d6bd3cfSderaadt !payload_first(msg, ISAKMP_PAYLOAD_HASH))))) {
2162040585eSniklas /* Missing payload. */
21751ca15aeSniklas LOG_DBG((LOG_MESSAGE, 70,
218baf9095eShshoexer "exchange_validate: msg %p requires missing %s",
219baf9095eShshoexer msg, *pc >= ISAKMP_PAYLOAD_NONE
2202040585eSniklas ? constant_name(isakmp_payload_cst, *pc)
22151ca15aeSniklas : constant_name(exchange_script_cst, *pc)));
2222040585eSniklas return -1;
2232040585eSniklas }
2242040585eSniklas pc++;
2252040585eSniklas }
2262040585eSniklas if (*pc == EXCHANGE_SCRIPT_END)
2272040585eSniklas /* Cleanup. */
2282040585eSniklas return 1;
2292040585eSniklas
2302040585eSniklas return 0;
2312040585eSniklas }
2322040585eSniklas
233cc6cc03eSho /* Feed unhandled payloads to the DOI for handling. Help for exchange_run(). */
234cc6cc03eSho static void
exchange_handle_leftover_payloads(struct message * msg)235cc6cc03eSho exchange_handle_leftover_payloads(struct message *msg)
236cc6cc03eSho {
237cc6cc03eSho struct exchange *exchange = msg->exchange;
238cc6cc03eSho struct doi *doi = exchange->doi;
239cc6cc03eSho struct payload *p;
240cc6cc03eSho int i;
241cc6cc03eSho
242cc3c17beShshoexer for (i = ISAKMP_PAYLOAD_SA; i < ISAKMP_PAYLOAD_MAX; i++) {
243cc6cc03eSho if (i == ISAKMP_PAYLOAD_PROPOSAL ||
244cc6cc03eSho i == ISAKMP_PAYLOAD_TRANSFORM)
245cc6cc03eSho continue;
246ed76d6b8Shshoexer TAILQ_FOREACH(p, &msg->payload[i], link) {
247cc6cc03eSho if (p->flags & PL_MARK)
248cc6cc03eSho continue;
249cc6cc03eSho if (!doi->handle_leftover_payload ||
250cc6cc03eSho doi->handle_leftover_payload(msg, i, p))
251cc6cc03eSho LOG_DBG((LOG_EXCHANGE, 10,
2529aa1bed2Shshoexer "exchange_handle_leftover_payloads: "
2539aa1bed2Shshoexer "unexpected payload %s",
254cc6cc03eSho constant_name(isakmp_payload_cst, i)));
255cc6cc03eSho }
256cc6cc03eSho }
257cc6cc03eSho }
258cc6cc03eSho
2592040585eSniklas /*
2602040585eSniklas * Run the exchange script from a point given by the "program counter"
2612040585eSniklas * upto either the script's end or a transmittal of a message. If we are
2622040585eSniklas * at the point of a reception of a message, that message should be handed
2632040585eSniklas * in here in the MSG argument. Otherwise we are the initiator and should
2642040585eSniklas * expect MSG to be a half-cooked message without payloads.
2652040585eSniklas */
2662040585eSniklas void
exchange_run(struct message * msg)2672040585eSniklas exchange_run(struct message *msg)
2682040585eSniklas {
2692040585eSniklas struct exchange *exchange = msg->exchange;
27022819a49Sniklas struct doi *doi = exchange->doi;
271baf9095eShshoexer int (*handler)(struct message *) = exchange->initiator ?
272baf9095eShshoexer doi->initiator : doi->responder;
273cc6cc03eSho int done = 0;
2742040585eSniklas
275baf9095eShshoexer while (!done) {
2762040585eSniklas /*
2772040585eSniklas * It's our turn if we're either the initiator on an even step,
2782040585eSniklas * or the responder on an odd step of the dialogue.
2792040585eSniklas */
280baf9095eShshoexer if (exchange->initiator ^ (exchange->step % 2)) {
2812040585eSniklas done = 1;
2822040585eSniklas if (exchange->step)
2832040585eSniklas msg = message_alloc_reply(msg);
284baf9095eShshoexer message_setup_header(msg, exchange->type, 0,
285baf9095eShshoexer exchange->message_id);
286baf9095eShshoexer if (handler(msg)) {
2872040585eSniklas /*
288baf9095eShshoexer * This can happen when transient starvation
289baf9095eShshoexer * of memory occurs.
290baf9095eShshoexer * XXX The peer's retransmit ought to
291baf9095eShshoexer * kick-start this exchange again. If he's
292baf9095eShshoexer * stopped retransmitting he's likely dropped
293baf9095eShshoexer * the SA at his side so we need to do that
294baf9095eShshoexer * too, i.e. implement automatic SA teardown
295baf9095eShshoexer * after a certain amount of inactivity.
2962040585eSniklas */
29722819a49Sniklas log_print("exchange_run: doi->%s (%p) failed",
298baf9095eShshoexer exchange->initiator ? "initiator" :
299baf9095eShshoexer "responder", msg);
3002040585eSniklas message_free(msg);
3012040585eSniklas return;
3022040585eSniklas }
303baf9095eShshoexer switch (exchange_validate(msg)) {
3042040585eSniklas case 1:
3052040585eSniklas /*
306baf9095eShshoexer * The last message of a multi-message
307baf9095eShshoexer * exchange should not be retransmitted other
308baf9095eShshoexer * than "on-demand", i.e. if we see
309baf9095eShshoexer * retransmits of the last message of the peer
31022819a49Sniklas * later.
3112040585eSniklas */
31222819a49Sniklas msg->flags |= MSG_LAST;
313baf9095eShshoexer if (exchange->step > 0) {
31422819a49Sniklas if (exchange->last_sent)
31522819a49Sniklas message_free(exchange->last_sent);
31622819a49Sniklas exchange->last_sent = msg;
3171d9d87a5Sniklas }
3182040585eSniklas /*
319baf9095eShshoexer * After we physically have sent our last
320baf9095eShshoexer * message we need to do SA-specific
321baf9095eShshoexer * finalization, like telling our application
322baf9095eShshoexer * the SA is ready to be used, or issuing a
323baf9095eShshoexer * CONNECTED notify if we set the COMMIT bit.
3242040585eSniklas */
325cc6cc03eSho message_register_post_send(msg,
326cc6cc03eSho exchange_finalize);
3272040585eSniklas
32836d3c850Shshoexer /* FALLTHROUGH */
3292040585eSniklas
3302040585eSniklas case 0:
33120c653ebSyasuoka /*
33220c653ebSyasuoka * Don't retransmit responses for
33320c653ebSyasuoka * unauthenticated messages.
33420c653ebSyasuoka */
33520c653ebSyasuoka if ((exchange->type == ISAKMP_EXCH_ID_PROT ||
33620c653ebSyasuoka exchange->type == ISAKMP_EXCH_AGGRESSIVE) &&
33720c653ebSyasuoka exchange->phase == 1 && exchange->step == 1)
33820c653ebSyasuoka msg->flags |= MSG_DONTRETRANSMIT;
33920c653ebSyasuoka
3402040585eSniklas /* XXX error handling. */
3412040585eSniklas message_send(msg);
3422040585eSniklas break;
3432040585eSniklas
3442040585eSniklas default:
345cc6cc03eSho log_print("exchange_run: exchange_validate "
346cc6cc03eSho "failed, DOI error");
3472040585eSniklas exchange_free(exchange);
3482040585eSniklas message_free(msg);
3492040585eSniklas return;
3502040585eSniklas }
351baf9095eShshoexer } else {
3522040585eSniklas done = exchange_validate(msg);
353baf9095eShshoexer switch (done) {
3542040585eSniklas case 0:
3552040585eSniklas case 1:
3562040585eSniklas /* Feed the message to the DOI. */
357baf9095eShshoexer if (handler(msg)) {
3582040585eSniklas /*
3592040585eSniklas * Trust the peer to retransmit.
360baf9095eShshoexer * XXX We have to implement SA aging
361baf9095eShshoexer * with automatic teardown.
3622040585eSniklas */
3632040585eSniklas message_free(msg);
3642040585eSniklas return;
3652040585eSniklas }
3662040585eSniklas /*
367baf9095eShshoexer * Go over the yet unhandled payloads and feed
368baf9095eShshoexer * them to DOI for handling.
3692040585eSniklas */
370cc6cc03eSho exchange_handle_leftover_payloads(msg);
3712040585eSniklas
3722040585eSniklas /*
373baf9095eShshoexer * We have advanced the state. If we have
374baf9095eShshoexer * been processing an incoming message, record
375baf9095eShshoexer * that message as the one to do duplication
376baf9095eShshoexer * tests against.
3772040585eSniklas */
3782040585eSniklas if (exchange->last_received)
3792040585eSniklas message_free(exchange->last_received);
3802040585eSniklas exchange->last_received = msg;
3812040585eSniklas if (exchange->flags & EXCHANGE_FLAG_ENCRYPT)
3822040585eSniklas crypto_update_iv(exchange->keystate);
3832040585eSniklas
384baf9095eShshoexer if (done) {
3852040585eSniklas exchange_finalize(msg);
3862040585eSniklas return;
3872040585eSniklas }
3882040585eSniklas break;
3892040585eSniklas
3902040585eSniklas case -1:
391cc6cc03eSho log_print("exchange_run: exchange_validate "
392cc6cc03eSho "failed");
393baf9095eShshoexer /*
394baf9095eShshoexer * XXX Is this the best error notification
395baf9095eShshoexer * type?
396baf9095eShshoexer */
397cc6cc03eSho message_drop(msg,
398cc6cc03eSho ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1);
3992040585eSniklas return;
4002040585eSniklas }
4012040585eSniklas }
4022040585eSniklas
40351ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 40,
404fd37c001Sniklas "exchange_run: exchange %p finished step %d, advancing...",
40551ca15aeSniklas exchange, exchange->step));
4062040585eSniklas exchange->step++;
4079d6bd3cfSderaadt while (*exchange->exch_pc != EXCHANGE_SCRIPT_SWITCH &&
4089d6bd3cfSderaadt *exchange->exch_pc != EXCHANGE_SCRIPT_END)
4092040585eSniklas exchange->exch_pc++;
4102040585eSniklas exchange->exch_pc++;
4112040585eSniklas }
4122040585eSniklas }
4132040585eSniklas
4142040585eSniklas void
exchange_init(void)4151616f820Sderaadt exchange_init(void)
4162040585eSniklas {
4172040585eSniklas int i;
4182040585eSniklas
4192040585eSniklas bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1;
420bfdaf066Sderaadt exchange_tab = calloc(bucket_mask + 1, sizeof(struct exchange_list));
4212040585eSniklas if (!exchange_tab)
4222040585eSniklas log_fatal("exchange_init: out of memory");
423cc6cc03eSho for (i = 0; i <= bucket_mask; i++)
4242040585eSniklas LIST_INIT(&exchange_tab[i]);
4252040585eSniklas }
4262040585eSniklas
4272040585eSniklas /* Lookup a phase 1 exchange out of just the initiator cookie. */
4282040585eSniklas struct exchange *
exchange_lookup_from_icookie(u_int8_t * cookie)4292040585eSniklas exchange_lookup_from_icookie(u_int8_t *cookie)
4302040585eSniklas {
4312040585eSniklas struct exchange *exchange;
432cc6cc03eSho int i;
4332040585eSniklas
434172c7fecSniklas for (i = 0; i <= bucket_mask; i++)
4352040585eSniklas for (exchange = LIST_FIRST(&exchange_tab[i]); exchange;
4362040585eSniklas exchange = LIST_NEXT(exchange, link))
437baf9095eShshoexer if (memcmp(exchange->cookies, cookie,
438cc6cc03eSho ISAKMP_HDR_ICOOKIE_LEN) == 0 &&
439cc6cc03eSho exchange->phase == 1)
4402040585eSniklas return exchange;
4412040585eSniklas return 0;
4422040585eSniklas }
4432040585eSniklas
444f5228d8eSniklas /* Lookup an exchange out of the name and phase. */
445f5228d8eSniklas struct exchange *
exchange_lookup_by_name(char * name,int phase)4462b81057dSniklas exchange_lookup_by_name(char *name, int phase)
4472b81057dSniklas {
4482b81057dSniklas struct exchange *exchange;
449cc6cc03eSho int i;
4502b81057dSniklas
451172c7fecSniklas /* If we search for nothing, we will find nothing. */
452172c7fecSniklas if (!name)
453172c7fecSniklas return 0;
454172c7fecSniklas
455172c7fecSniklas for (i = 0; i <= bucket_mask; i++)
4562b81057dSniklas for (exchange = LIST_FIRST(&exchange_tab[i]); exchange;
457baf9095eShshoexer exchange = LIST_NEXT(exchange, link)) {
45851ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 90,
459baf9095eShshoexer "exchange_lookup_by_name: %s == %s && %d == %d?",
460baf9095eShshoexer name, exchange->name ? exchange->name :
461baf9095eShshoexer "<unnamed>", phase, exchange->phase));
46222819a49Sniklas
46322819a49Sniklas /*
464baf9095eShshoexer * Match by name, but don't select finished exchanges,
465baf9095eShshoexer * i.e where MSG_LAST are set in last_sent msg.
46622819a49Sniklas */
467cc6cc03eSho if (exchange->name &&
468cc6cc03eSho strcasecmp(exchange->name, name) == 0 &&
469cc6cc03eSho exchange->phase == phase &&
470cc6cc03eSho (!exchange->last_sent ||
471cc6cc03eSho (exchange->last_sent->flags & MSG_LAST) == 0))
4722b81057dSniklas return exchange;
473a06203bdSniklas }
4742b81057dSniklas return 0;
4752b81057dSniklas }
4762b81057dSniklas
477172c7fecSniklas /* Lookup an exchange out of the name, phase and step > 1. */
4784c8c122bSho static struct exchange *
exchange_lookup_active(char * name,int phase)479172c7fecSniklas exchange_lookup_active(char *name, int phase)
480172c7fecSniklas {
481172c7fecSniklas struct exchange *exchange;
482cc6cc03eSho int i;
483172c7fecSniklas
48422819a49Sniklas /* XXX Almost identical to exchange_lookup_by_name. */
485172c7fecSniklas
486172c7fecSniklas if (!name)
487172c7fecSniklas return 0;
488172c7fecSniklas
489172c7fecSniklas for (i = 0; i <= bucket_mask; i++)
490172c7fecSniklas for (exchange = LIST_FIRST(&exchange_tab[i]); exchange;
491baf9095eShshoexer exchange = LIST_NEXT(exchange, link)) {
49251ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 90,
493172c7fecSniklas "exchange_lookup_active: %s == %s && %d == %d?",
494baf9095eShshoexer name, exchange->name ? exchange->name :
495baf9095eShshoexer "<unnamed>", phase, exchange->phase));
496cc6cc03eSho if (exchange->name &&
497cc6cc03eSho strcasecmp(exchange->name, name) == 0 &&
498cc6cc03eSho exchange->phase == phase) {
499172c7fecSniklas if (exchange->step > 1)
500172c7fecSniklas return exchange;
501172c7fecSniklas else
50251ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 80,
503cc6cc03eSho "exchange_lookup_active: avoided "
504cc6cc03eSho "early (pre-step 1) exchange %p",
505cc6cc03eSho exchange));
506172c7fecSniklas }
507172c7fecSniklas }
508172c7fecSniklas return 0;
509172c7fecSniklas }
510172c7fecSniklas
511a06203bdSniklas static void
exchange_enter(struct exchange * exchange)5122040585eSniklas exchange_enter(struct exchange *exchange)
5132040585eSniklas {
5142040585eSniklas u_int16_t bucket = 0;
5152040585eSniklas u_int8_t *cp;
516cc6cc03eSho int i;
5172040585eSniklas
5182040585eSniklas /* XXX We might resize if we are crossing a certain threshold */
5192040585eSniklas
520baf9095eShshoexer for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) {
5212040585eSniklas cp = exchange->cookies + i;
5222040585eSniklas /* Doing it this way avoids alignment problems. */
5232040585eSniklas bucket ^= cp[0] | cp[1] << 8;
5242040585eSniklas }
525baf9095eShshoexer for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) {
5262040585eSniklas cp = exchange->message_id + i;
5272040585eSniklas /* Doing it this way avoids alignment problems. */
5282040585eSniklas bucket ^= cp[0] | cp[1] << 8;
5292040585eSniklas }
5302040585eSniklas bucket &= bucket_mask;
5312040585eSniklas LIST_INSERT_HEAD(&exchange_tab[bucket], exchange, link);
53210dd6cf1Smpi exchange->linked = 1;
5332040585eSniklas }
5342040585eSniklas
5352040585eSniklas /*
5362040585eSniklas * Lookup the exchange given by the header fields MSG. PHASE2 is false when
5372040585eSniklas * looking for phase 1 exchanges and true otherwise.
5382040585eSniklas */
5392040585eSniklas struct exchange *
exchange_lookup(u_int8_t * msg,int phase2)5402040585eSniklas exchange_lookup(u_int8_t *msg, int phase2)
5412040585eSniklas {
5422040585eSniklas struct exchange *exchange;
543cc6cc03eSho u_int16_t bucket = 0;
5442040585eSniklas u_int8_t *cp;
545cc6cc03eSho int i;
5462040585eSniklas
5472040585eSniklas /*
548cc6cc03eSho * We use the cookies to get bits to use as an index into exchange_tab,
549cc6cc03eSho * as at least one (our cookie) is a good hash, xoring all the bits,
550cc6cc03eSho * 16 at a time, and then masking, should do. Doing it this way means
551cc6cc03eSho * we can validate cookies very fast thus delimiting the effects of
552cc6cc03eSho * "Denial of service"-attacks using packet flooding.
5532040585eSniklas */
554baf9095eShshoexer for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2) {
5552040585eSniklas cp = msg + ISAKMP_HDR_COOKIES_OFF + i;
5562040585eSniklas /* Doing it this way avoids alignment problems. */
5572040585eSniklas bucket ^= cp[0] | cp[1] << 8;
5582040585eSniklas }
5592040585eSniklas if (phase2)
560baf9095eShshoexer for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2) {
5612040585eSniklas cp = msg + ISAKMP_HDR_MESSAGE_ID_OFF + i;
5622040585eSniklas /* Doing it this way avoids alignment problems. */
5632040585eSniklas bucket ^= cp[0] | cp[1] << 8;
5642040585eSniklas }
5652040585eSniklas bucket &= bucket_mask;
5662040585eSniklas for (exchange = LIST_FIRST(&exchange_tab[bucket]);
567cc6cc03eSho exchange && (memcmp(msg + ISAKMP_HDR_COOKIES_OFF,
568cc6cc03eSho exchange->cookies, ISAKMP_HDR_COOKIES_LEN) != 0 ||
569cc6cc03eSho (phase2 && memcmp(msg + ISAKMP_HDR_MESSAGE_ID_OFF,
570cc6cc03eSho exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN) != 0) ||
571cc6cc03eSho (!phase2 && !zero_test(msg + ISAKMP_HDR_MESSAGE_ID_OFF,
5722b81057dSniklas ISAKMP_HDR_MESSAGE_ID_LEN)));
5732040585eSniklas exchange = LIST_NEXT(exchange, link))
5742040585eSniklas ;
5752040585eSniklas
5762040585eSniklas return exchange;
5772040585eSniklas }
5782040585eSniklas
5792040585eSniklas /*
5802040585eSniklas * Create a phase PHASE exchange where INITIATOR denotes our role. DOI
5812040585eSniklas * is the domain of interpretation identifier and TYPE tells what exchange
5822040585eSniklas * type to use per either the DOI document or the ISAKMP spec proper.
5832040585eSniklas * NSA tells how many SAs we should pre-allocate, and should be zero
5842040585eSniklas * when we have the responder role.
5852040585eSniklas */
5862040585eSniklas static struct exchange *
exchange_create(int phase,int initiator,int doi,int type)5872040585eSniklas exchange_create(int phase, int initiator, int doi, int type)
5882040585eSniklas {
5892040585eSniklas struct exchange *exchange;
5906ee513e5Sjca struct timespec expiration;
5912b81057dSniklas int delta;
5922040585eSniklas
5932040585eSniklas /*
59422819a49Sniklas * We want the exchange zeroed for exchange_free to be able to find
59522819a49Sniklas * out what fields have been filled-in.
5962040585eSniklas */
5972040585eSniklas exchange = calloc(1, sizeof *exchange);
598baf9095eShshoexer if (!exchange) {
5997eb3b581Sderaadt log_error("exchange_create: calloc (1, %lu) failed",
6007eb3b581Sderaadt (unsigned long)sizeof *exchange);
6012040585eSniklas return 0;
60224d2f2e1Sniklas }
6032040585eSniklas exchange->phase = phase;
6042040585eSniklas exchange->step = 0;
6052040585eSniklas exchange->initiator = initiator;
6060dc10397Shshoexer bzero(exchange->cookies, ISAKMP_HDR_COOKIES_LEN);
6070dc10397Shshoexer bzero(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN);
6082040585eSniklas exchange->doi = doi_lookup(doi);
6092040585eSniklas exchange->type = type;
61032f522cdSniklas exchange->policy_id = -1;
6112040585eSniklas exchange->exch_pc = exchange_script(exchange);
6122040585eSniklas exchange->last_sent = exchange->last_received = 0;
6132040585eSniklas TAILQ_INIT(&exchange->sa_list);
6142040585eSniklas TAILQ_INIT(&exchange->aca_list);
6152040585eSniklas
6162040585eSniklas /* Allocate the DOI-specific structure and initialize it to zeroes. */
617baf9095eShshoexer if (exchange->doi->exchange_size) {
6182040585eSniklas exchange->data = calloc(1, exchange->doi->exchange_size);
619baf9095eShshoexer if (!exchange->data) {
6207eb3b581Sderaadt log_error("exchange_create: calloc (1, %lu) failed",
6217eb3b581Sderaadt (unsigned long)exchange->doi->exchange_size);
6222040585eSniklas exchange_free(exchange);
6232040585eSniklas return 0;
6242040585eSniklas }
6259bfbb31eSniklas }
6266ee513e5Sjca clock_gettime(CLOCK_MONOTONIC, &expiration);
627cc6cc03eSho delta = conf_get_num("General", "Exchange-max-time",
628cc6cc03eSho EXCHANGE_MAX_TIME);
6292b81057dSniklas expiration.tv_sec += delta;
630cc6cc03eSho exchange->death = timer_add_event("exchange_free_aux",
631cc6cc03eSho exchange_free_aux, exchange, &expiration);
632baf9095eShshoexer if (!exchange->death) {
6332040585eSniklas /* If we don't give up we might start leaking... */
63422819a49Sniklas exchange_free_aux(exchange);
6352040585eSniklas return 0;
6362040585eSniklas }
6372040585eSniklas return exchange;
6382040585eSniklas }
6392040585eSniklas
640baf9095eShshoexer struct exchange_finalization_node {
641172c7fecSniklas void (*first)(struct exchange *, void *, int);
642a06203bdSniklas void *first_arg;
643172c7fecSniklas void (*second)(struct exchange *, void *, int);
644a06203bdSniklas void *second_arg;
645a06203bdSniklas };
646a06203bdSniklas
647a06203bdSniklas /* Run the finalization functions of ARG. */
648a06203bdSniklas static void
exchange_run_finalizations(struct exchange * exchange,void * arg,int fail)649172c7fecSniklas exchange_run_finalizations(struct exchange *exchange, void *arg, int fail)
650a06203bdSniklas {
651a06203bdSniklas struct exchange_finalization_node *node = arg;
652a06203bdSniklas
653172c7fecSniklas node->first(exchange, node->first_arg, fail);
654172c7fecSniklas node->second(exchange, node->second_arg, fail);
655a06203bdSniklas free(node);
656a06203bdSniklas }
657a06203bdSniklas
658a06203bdSniklas /*
659a06203bdSniklas * Add a finalization function FINALIZE with argument ARG to the tail
660a06203bdSniklas * of the finalization function list of EXCHANGE.
661a06203bdSniklas */
662a06203bdSniklas static void
exchange_add_finalization(struct exchange * exchange,void (* finalize)(struct exchange *,void *,int),void * arg)663a06203bdSniklas exchange_add_finalization(struct exchange *exchange,
664baf9095eShshoexer void (*finalize)(struct exchange *, void *, int), void *arg)
665a06203bdSniklas {
666a06203bdSniklas struct exchange_finalization_node *node;
667a06203bdSniklas
668a06203bdSniklas if (!finalize)
669a06203bdSniklas return;
670a06203bdSniklas
671baf9095eShshoexer if (!exchange->finalize) {
672a06203bdSniklas exchange->finalize = finalize;
673a06203bdSniklas exchange->finalize_arg = arg;
674a06203bdSniklas return;
675a06203bdSniklas }
676a06203bdSniklas node = malloc(sizeof *node);
677baf9095eShshoexer if (!node) {
6787eb3b581Sderaadt log_error("exchange_add_finalization: malloc (%lu) failed",
6797eb3b581Sderaadt (unsigned long)sizeof *node);
680a06203bdSniklas free(arg);
681a06203bdSniklas return;
682a06203bdSniklas }
683a06203bdSniklas node->first = exchange->finalize;
684a06203bdSniklas node->first_arg = exchange->finalize_arg;
685a06203bdSniklas node->second = finalize;
686a06203bdSniklas node->second_arg = arg;
687a06203bdSniklas exchange->finalize = exchange_run_finalizations;
688a06203bdSniklas exchange->finalize_arg = node;
689a06203bdSniklas }
690a06203bdSniklas
691d6351a66Sho static void
exchange_establish_transaction(struct exchange * exchange,void * arg,int fail)692d6351a66Sho exchange_establish_transaction(struct exchange *exchange, void *arg, int fail)
693d6351a66Sho {
694d6351a66Sho /* Establish a TRANSACTION exchange. */
695baf9095eShshoexer struct exchange_finalization_node *node =
696baf9095eShshoexer (struct exchange_finalization_node *)arg;
697d6351a66Sho struct sa *isakmp_sa = sa_lookup_by_name((char *) node->second_arg, 1);
698d6351a66Sho
699d6351a66Sho if (isakmp_sa && !fail)
700d6351a66Sho exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_TRANSACTION, 0, 0,
701d6351a66Sho node->first, node->first_arg);
702d6351a66Sho
703d6351a66Sho free(node);
704d6351a66Sho }
705d6351a66Sho
7062040585eSniklas /* Establish a phase 1 exchange. */
70710dd6cf1Smpi int
exchange_establish_p1(struct transport * t,u_int8_t type,u_int32_t doi,char * name,void * args,void (* finalize)(struct exchange *,void *,int),void * arg,int stayalive)7082040585eSniklas exchange_establish_p1(struct transport *t, u_int8_t type, u_int32_t doi,
709baf9095eShshoexer char *name, void *args, void (*finalize)(struct exchange *, void *, int),
710a28d886cShshoexer void *arg, int stayalive)
7112040585eSniklas {
7122040585eSniklas struct exchange *exchange;
7132040585eSniklas struct message *msg;
714d6351a66Sho struct conf_list *flags;
715d6351a66Sho struct conf_list_node *flag;
7162b81057dSniklas char *tag = 0;
7172b81057dSniklas char *str;
7182b81057dSniklas
719baf9095eShshoexer if (name) {
7202b81057dSniklas /* If no exchange type given, fetch from the configuration. */
721baf9095eShshoexer if (type == 0) {
722baf9095eShshoexer /*
723baf9095eShshoexer * XXX Similar code can be found in
724baf9095eShshoexer * exchange_setup_p1. Share?
725baf9095eShshoexer */
7262b81057dSniklas
7272b81057dSniklas /* Find out our phase 1 mode. */
7282b81057dSniklas tag = conf_get_str(name, "Configuration");
729baf9095eShshoexer if (!tag) {
730419caefeSho /* Use default setting. */
731419caefeSho tag = CONF_DFLT_TAG_PHASE1_CONFIG;
7322b81057dSniklas }
733f5228d8eSniklas /* Figure out the DOI. XXX Factor out? */
7342b81057dSniklas str = conf_get_str(tag, "DOI");
73532f522cdSniklas if (!str || strcasecmp(str, "IPSEC") == 0)
7362b81057dSniklas doi = IPSEC_DOI_IPSEC;
73732f522cdSniklas else if (strcasecmp(str, "ISAKMP") == 0)
73832f522cdSniklas doi = ISAKMP_DOI_ISAKMP;
739baf9095eShshoexer else {
740cc6cc03eSho log_print("exchange_establish_p1: "
741cc6cc03eSho "DOI \"%s\" unsupported", str);
74210dd6cf1Smpi return -1;
7432b81057dSniklas }
7442b81057dSniklas
7452b81057dSniklas /* What exchange type do we want? */
7462b81057dSniklas str = conf_get_str(tag, "EXCHANGE_TYPE");
747baf9095eShshoexer if (!str) {
7482b81057dSniklas log_print("exchange_establish_p1: "
749baf9095eShshoexer "no \"EXCHANGE_TYPE\" tag in [%s] section",
750baf9095eShshoexer tag);
75110dd6cf1Smpi return -1;
7522b81057dSniklas }
7532b81057dSniklas type = constant_value(isakmp_exch_cst, str);
754baf9095eShshoexer if (!type) {
7552c0f0c92Shshoexer log_print("exchange_establish_p1: "
756cc6cc03eSho "unknown exchange type %s", str);
75710dd6cf1Smpi return -1;
7582b81057dSniklas }
7592b81057dSniklas }
7607f056c7bSniklas }
7612040585eSniklas exchange = exchange_create(1, 1, doi, type);
762baf9095eShshoexer if (!exchange) {
76310dd6cf1Smpi return -1;
7642040585eSniklas }
765baf9095eShshoexer if (name) {
7669bfbb31eSniklas exchange->name = strdup(name);
767baf9095eShshoexer if (!exchange->name) {
768cc6cc03eSho log_error("exchange_establish_p1: "
769cc6cc03eSho "strdup (\"%s\") failed", name);
7702b81057dSniklas exchange_free(exchange);
77110dd6cf1Smpi return -1;
7722b81057dSniklas }
7739bfbb31eSniklas }
7742b81057dSniklas exchange->policy = name ? conf_get_str(name, "Configuration") : 0;
7750eb823c5Sniklas if (!exchange->policy && name)
776419caefeSho exchange->policy = CONF_DFLT_TAG_PHASE1_CONFIG;
777c40d7257Sniklas
778cc6cc03eSho if (name && (flags = conf_get_list(name, "Flags")) != NULL) {
779d6351a66Sho for (flag = TAILQ_FIRST(&flags->fields); flag;
780d6351a66Sho flag = TAILQ_NEXT(flag, link))
781baf9095eShshoexer if (strcasecmp(flag->field, "ikecfg") == 0) {
782d6351a66Sho struct exchange_finalization_node *node;
783d6351a66Sho
784d6351a66Sho node = calloc(1, (unsigned long)sizeof *node);
785baf9095eShshoexer if (!node) {
786cc6cc03eSho log_print("exchange_establish_p1: "
787cc6cc03eSho "calloc (1, %lu) failed",
788d6351a66Sho (unsigned long)sizeof(*node));
789d6351a66Sho exchange_free(exchange);
79010dd6cf1Smpi return -1;
791d6351a66Sho }
792baf9095eShshoexer /*
793baf9095eShshoexer * Insert this finalization inbetween
794baf9095eShshoexer * the original.
795baf9095eShshoexer */
796d6351a66Sho node->first = finalize;
797d6351a66Sho node->first_arg = arg;
798d6351a66Sho node->second_arg = name;
799d6351a66Sho exchange_add_finalization(exchange,
800d6351a66Sho exchange_establish_transaction,
801d6351a66Sho node);
802d6351a66Sho finalize = 0;
803d6351a66Sho }
804d6351a66Sho conf_free_list(flags);
805d6351a66Sho }
806fcd76f45Sho
807d6351a66Sho exchange_add_finalization(exchange, finalize, arg);
8082040585eSniklas cookie_gen(t, exchange, exchange->cookies, ISAKMP_HDR_ICOOKIE_LEN);
8092040585eSniklas exchange_enter(exchange);
8102040585eSniklas exchange_dump("exchange_establish_p1", exchange);
8112040585eSniklas
8122040585eSniklas msg = message_alloc(t, 0, ISAKMP_HDR_SZ);
813baf9095eShshoexer if (!msg) {
8145d97d718Sho log_print("exchange_establish_p1: message_alloc () failed");
8155d97d718Sho exchange_free(exchange);
81610dd6cf1Smpi return 0; /* exchange_free() runs finalize */
8175d97d718Sho }
8182040585eSniklas msg->exchange = exchange;
8192040585eSniklas
820e0d722f1Sho /* Do not create SA for an information or transaction exchange. */
8219d6bd3cfSderaadt if (exchange->type != ISAKMP_EXCH_INFO &&
8229d6bd3cfSderaadt exchange->type != ISAKMP_EXCH_TRANSACTION) {
8232040585eSniklas /*
824baf9095eShshoexer * Don't install a transport into this SA as it will be an
825baf9095eShshoexer * INADDR_ANY address in the local end, which is not good at
826baf9095eShshoexer * all. Let the reply packet install the transport instead.
8272040585eSniklas */
8282040585eSniklas sa_create(exchange, 0);
8292040585eSniklas msg->isakmp_sa = TAILQ_FIRST(&exchange->sa_list);
830baf9095eShshoexer if (!msg->isakmp_sa) {
8315d97d718Sho message_free(msg);
8322040585eSniklas exchange_free(exchange);
83310dd6cf1Smpi return 0; /* exchange_free() runs finalize */
8342040585eSniklas }
835b36e8b75Sniklas sa_reference(msg->isakmp_sa);
836a28d886cShshoexer
837a28d886cShshoexer if (stayalive)
838a28d886cShshoexer msg->isakmp_sa->flags |= SA_FLAG_STAYALIVE;
839bd4e5273Sniklas }
8402040585eSniklas msg->extra = args;
8412040585eSniklas
8422040585eSniklas exchange_run(msg);
84310dd6cf1Smpi return 0;
8442040585eSniklas }
8452040585eSniklas
8462040585eSniklas /* Establish a phase 2 exchange. XXX With just one SA for now. */
84710dd6cf1Smpi int
exchange_establish_p2(struct sa * isakmp_sa,u_int8_t type,char * name,void * args,void (* finalize)(struct exchange *,void *,int),void * arg)848a06203bdSniklas exchange_establish_p2(struct sa *isakmp_sa, u_int8_t type, char *name,
849baf9095eShshoexer void *args, void (*finalize)(struct exchange *, void *, int), void *arg)
8502040585eSniklas {
8512040585eSniklas struct exchange *exchange;
8522040585eSniklas struct message *msg;
853a06203bdSniklas u_int32_t doi = ISAKMP_DOI_ISAKMP;
8542bf8caf4Sangelos u_int32_t seq = 0;
855cc6cc03eSho int i;
856cc6cc03eSho char *tag, *str;
857a06203bdSniklas
8587db938adSniklas if (isakmp_sa)
8597db938adSniklas doi = isakmp_sa->doi->id;
8607db938adSniklas
861baf9095eShshoexer if (name) {
8622b81057dSniklas /* Find out our phase 2 modes. */
8632b81057dSniklas tag = conf_get_str(name, "Configuration");
864baf9095eShshoexer if (!tag) {
865cc6cc03eSho log_print("exchange_establish_p2: "
866cc6cc03eSho "no configuration for peer \"%s\"", name);
86710dd6cf1Smpi return -1;
8682b81057dSniklas }
8692bf8caf4Sangelos seq = (u_int32_t)conf_get_num(name, "Acquire-ID", 0);
8702bf8caf4Sangelos
8712b81057dSniklas /* Figure out the DOI. */
8722b81057dSniklas str = conf_get_str(tag, "DOI");
87332f522cdSniklas if (!str || strcasecmp(str, "IPSEC") == 0)
8742b81057dSniklas doi = IPSEC_DOI_IPSEC;
87532f522cdSniklas else if (strcasecmp(str, "ISAKMP") == 0)
87632f522cdSniklas doi = ISAKMP_DOI_ISAKMP;
877baf9095eShshoexer else {
878cc6cc03eSho log_print("exchange_establish_p2: "
879cc6cc03eSho "DOI \"%s\" unsupported", str);
88010dd6cf1Smpi return -1;
8812b81057dSniklas }
8822b81057dSniklas
8832b81057dSniklas /* What exchange type do we want? */
884baf9095eShshoexer if (!type) {
8852b81057dSniklas str = conf_get_str(tag, "EXCHANGE_TYPE");
886baf9095eShshoexer if (!str) {
8872b81057dSniklas log_print("exchange_establish_p2: "
888baf9095eShshoexer "no \"EXCHANGE_TYPE\" tag in [%s] section",
889baf9095eShshoexer tag);
89010dd6cf1Smpi return -1;
8912b81057dSniklas }
8922b81057dSniklas /* XXX IKE dependent. */
8932b81057dSniklas type = constant_value(ike_exch_cst, str);
894baf9095eShshoexer if (!type) {
895baf9095eShshoexer log_print("exchange_establish_p2: unknown "
896baf9095eShshoexer "exchange type %s", str);
89710dd6cf1Smpi return -1;
8982b81057dSniklas }
8992b81057dSniklas }
900a06203bdSniklas }
9012b81057dSniklas exchange = exchange_create(2, 1, doi, type);
902baf9095eShshoexer if (!exchange) {
90310dd6cf1Smpi return -1;
9042040585eSniklas }
905baf9095eShshoexer if (name) {
9069bfbb31eSniklas exchange->name = strdup(name);
907baf9095eShshoexer if (!exchange->name) {
908cc6cc03eSho log_error("exchange_establish_p2: "
909cc6cc03eSho "strdup (\"%s\") failed", name);
9102b81057dSniklas exchange_free(exchange);
91110dd6cf1Smpi return -1;
9122b81057dSniklas }
9139bfbb31eSniklas }
9142b81057dSniklas exchange->policy = name ? conf_get_str(name, "Configuration") : 0;
915a06203bdSniklas exchange->finalize = finalize;
916a06203bdSniklas exchange->finalize_arg = arg;
9172bf8caf4Sangelos exchange->seq = seq;
9182040585eSniklas memcpy(exchange->cookies, isakmp_sa->cookies, ISAKMP_HDR_COOKIES_LEN);
919baf9c2dbSderaadt arc4random_buf(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN);
9202040585eSniklas exchange->flags |= EXCHANGE_FLAG_ENCRYPT;
921aa584aacSho if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE)
922aa584aacSho exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE;
923aa584aacSho if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE)
924aa584aacSho exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE;
9252040585eSniklas exchange_enter(exchange);
9262040585eSniklas exchange_dump("exchange_establish_p2", exchange);
9272040585eSniklas
928bd4e5273Sniklas /*
929bd4e5273Sniklas * Do not create SA's for informational exchanges.
930bd4e5273Sniklas * XXX How to handle new group mode?
931bd4e5273Sniklas */
932c7adf84cSho if (exchange->type != ISAKMP_EXCH_INFO &&
933e0d722f1Sho exchange->type != ISAKMP_EXCH_TRANSACTION) {
9342040585eSniklas /* XXX Number of SAs should come from the args structure. */
9352040585eSniklas for (i = 0; i < 1; i++)
936baf9095eShshoexer if (sa_create(exchange, isakmp_sa->transport)) {
9372040585eSniklas exchange_free(exchange);
93810dd6cf1Smpi return 0; /* exchange_free() runs finalize */
9392040585eSniklas }
940bd4e5273Sniklas }
9412040585eSniklas msg = message_alloc(isakmp_sa->transport, 0, ISAKMP_HDR_SZ);
9422040585eSniklas msg->isakmp_sa = isakmp_sa;
943d19346c1Sniklas sa_reference(isakmp_sa);
944bd4e5273Sniklas
9452040585eSniklas msg->extra = args;
9462040585eSniklas
9472040585eSniklas /* This needs to be done late or else get_keystate won't work right. */
9482040585eSniklas msg->exchange = exchange;
9492040585eSniklas
9502040585eSniklas exchange_run(msg);
95110dd6cf1Smpi
95210dd6cf1Smpi return 0;
9532040585eSniklas }
9542040585eSniklas
9552040585eSniklas /* Out of an incoming phase 1 message, setup an exchange. */
9562040585eSniklas struct exchange *
exchange_setup_p1(struct message * msg,u_int32_t doi)9572040585eSniklas exchange_setup_p1(struct message *msg, u_int32_t doi)
9582040585eSniklas {
9592b81057dSniklas struct transport *t = msg->transport;
9602040585eSniklas struct exchange *exchange;
9612b81057dSniklas struct sockaddr *dst;
9620c6ec862Sho struct conf_list *flags;
9630c6ec862Sho struct conf_list_node *flag;
964107c5904Sho char *name = 0, *policy = 0, *str;
9652b81057dSniklas u_int32_t want_doi;
9662b81057dSniklas u_int8_t type;
9672040585eSniklas
9682b81057dSniklas /* XXX Similar code can be found in exchange_establish_p1. Share? */
9692b81057dSniklas
9704c7a9999Sniklas /*
971baf9095eShshoexer * Unless this is an informational exchange, look up our policy for
972baf9095eShshoexer * this peer.
973172c7fecSniklas */
974172c7fecSniklas type = GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base);
975baf9095eShshoexer if (type != ISAKMP_EXCH_INFO) {
976172c7fecSniklas /*
9774c7a9999Sniklas * Find out our inbound phase 1 mode.
9784c7a9999Sniklas */
9793fd8781bSho t->vtbl->get_dst(t, &dst);
98077d42baeSniklas if (sockaddr2text(dst, &str, 0) == -1)
9813b43e3b6Sniklas return 0;
98277d42baeSniklas name = conf_get_str("Phase 1", str);
98377d42baeSniklas free(str);
984baf9095eShshoexer if (name) {
985172c7fecSniklas /*
986baf9095eShshoexer * If another phase 1 exchange is ongoing don't bother
987baf9095eShshoexer * returning the call. However, we will need to
988baf9095eShshoexer * continue responding if our phase 1 exchange is
989baf9095eShshoexer * still waiting for step 1 (i.e still half-open).
990172c7fecSniklas */
9917788aeeeSmikeb exchange = exchange_lookup_active(name, 1);
9927788aeeeSmikeb if (exchange) {
9937788aeeeSmikeb LOG_DBG((LOG_EXCHANGE, 40,
9947788aeeeSmikeb "exchange_establish: %s exchange already "
9957788aeeeSmikeb "exists as %p", name, exchange));
996172c7fecSniklas return 0;
9977788aeeeSmikeb }
998baf9095eShshoexer } else {
9992b81057dSniklas name = conf_get_str("Phase 1", "Default");
1000baf9095eShshoexer if (!name) {
1001baf9095eShshoexer log_print("exchange_setup_p1: no \"Default\" "
1002baf9095eShshoexer "tag in [Phase 1] section");
10032b81057dSniklas return 0;
10042b81057dSniklas }
10052b81057dSniklas }
10062b81057dSniklas
10072b81057dSniklas policy = conf_get_str(name, "Configuration");
10082b81057dSniklas if (!policy)
1009419caefeSho policy = CONF_DFLT_TAG_PHASE1_CONFIG;
10102b81057dSniklas
10112b81057dSniklas /* Figure out the DOI. */
10122b81057dSniklas str = conf_get_str(policy, "DOI");
101396136e5eScloder if (!str || strcasecmp(str, "IPSEC") == 0) {
10142b81057dSniklas want_doi = IPSEC_DOI_IPSEC;
101596136e5eScloder str = "IPSEC";
101696136e5eScloder }
101732f522cdSniklas else if (strcasecmp(str, "ISAKMP") == 0)
101832f522cdSniklas want_doi = ISAKMP_DOI_ISAKMP;
1019baf9095eShshoexer else {
1020cc6cc03eSho log_print("exchange_setup_p1: "
1021cc6cc03eSho "DOI \"%s\" unsupported", str);
10222b81057dSniklas return 0;
10232b81057dSniklas }
1024baf9095eShshoexer if (want_doi != doi) {
10252b81057dSniklas /* XXX Should I tell what DOI I got? */
10262b81057dSniklas log_print("exchange_setup_p1: expected %s DOI", str);
10272b81057dSniklas return 0;
10282b81057dSniklas }
10292b81057dSniklas /* What exchange type do we want? */
10302b81057dSniklas str = conf_get_str(policy, "EXCHANGE_TYPE");
1031baf9095eShshoexer if (!str) {
1032baf9095eShshoexer log_print("exchange_setup_p1: no \"EXCHANGE_TYPE\" "
1033baf9095eShshoexer "tag in [%s] section", policy);
10342b81057dSniklas return 0;
10352b81057dSniklas }
10362b81057dSniklas type = constant_value(isakmp_exch_cst, str);
1037baf9095eShshoexer if (!type) {
1038cc6cc03eSho log_print("exchange_setup_p1: "
1039cc6cc03eSho "unknown exchange type %s", str);
10402b81057dSniklas return 0;
10412b81057dSniklas }
1042baf9095eShshoexer if (type != GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base)) {
1043cc6cc03eSho log_print("exchange_setup_p1: "
1044cc6cc03eSho "expected exchange type %s got %s", str,
1045cc6cc03eSho constant_name(isakmp_exch_cst,
1046baf9095eShshoexer GET_ISAKMP_HDR_EXCH_TYPE(msg->iov[0].iov_base)));
10472b81057dSniklas return 0;
10482b81057dSniklas }
1049172c7fecSniklas }
10502b81057dSniklas exchange = exchange_create(1, 0, doi, type);
10512040585eSniklas if (!exchange)
10522040585eSniklas return 0;
10532b81057dSniklas
1054172c7fecSniklas exchange->name = name ? strdup(name) : 0;
1055baf9095eShshoexer if (name && !exchange->name) {
10569bfbb31eSniklas log_error("exchange_setup_p1: strdup (\"%s\") failed", name);
10572b81057dSniklas exchange_free(exchange);
10582b81057dSniklas return 0;
10592b81057dSniklas }
10602b81057dSniklas exchange->policy = policy;
10610c6ec862Sho
1062cc6cc03eSho if (name && (flags = conf_get_list(name, "Flags")) != NULL) {
10630c6ec862Sho for (flag = TAILQ_FIRST(&flags->fields); flag;
10640c6ec862Sho flag = TAILQ_NEXT(flag, link))
1065baf9095eShshoexer if (strcasecmp(flag->field, "ikecfg") == 0) {
10660c6ec862Sho struct exchange_finalization_node *node;
10670c6ec862Sho
10680c6ec862Sho node = calloc(1, (unsigned long)sizeof *node);
1069baf9095eShshoexer if (!node) {
1070cc6cc03eSho log_print("exchange_establish_p1: "
1071cc6cc03eSho "calloc (1, %lu) failed",
10720c6ec862Sho (unsigned long)sizeof(*node));
10730c6ec862Sho exchange_free(exchange);
10740c6ec862Sho return 0;
10750c6ec862Sho }
1076baf9095eShshoexer /*
1077baf9095eShshoexer * Insert this finalization inbetween
1078baf9095eShshoexer * the original.
1079baf9095eShshoexer */
10800c6ec862Sho node->first = 0;
10810c6ec862Sho node->first_arg = 0;
10820c6ec862Sho node->second_arg = name;
10830c6ec862Sho exchange_add_finalization(exchange,
10840c6ec862Sho exchange_establish_transaction,
10850c6ec862Sho node);
10860c6ec862Sho }
10870c6ec862Sho conf_free_list(flags);
10880c6ec862Sho }
1089fcd76f45Sho
1090baf9095eShshoexer cookie_gen(msg->transport, exchange, exchange->cookies +
1091baf9095eShshoexer ISAKMP_HDR_ICOOKIE_LEN, ISAKMP_HDR_RCOOKIE_LEN);
10922040585eSniklas GET_ISAKMP_HDR_ICOOKIE(msg->iov[0].iov_base, exchange->cookies);
10932040585eSniklas exchange_enter(exchange);
10942040585eSniklas exchange_dump("exchange_setup_p1", exchange);
10952040585eSniklas return exchange;
10962040585eSniklas }
10972040585eSniklas
10982040585eSniklas /* Out of an incoming phase 2 message, setup an exchange. */
10992040585eSniklas struct exchange *
exchange_setup_p2(struct message * msg,u_int8_t doi)11002040585eSniklas exchange_setup_p2(struct message *msg, u_int8_t doi)
11012040585eSniklas {
11022040585eSniklas struct exchange *exchange;
11032040585eSniklas u_int8_t *buf = msg->iov[0].iov_base;
11042040585eSniklas
11052040585eSniklas exchange = exchange_create(2, 0, doi, GET_ISAKMP_HDR_EXCH_TYPE(buf));
11062040585eSniklas if (!exchange)
11072040585eSniklas return 0;
11082040585eSniklas GET_ISAKMP_HDR_ICOOKIE(buf, exchange->cookies);
1109cc6cc03eSho GET_ISAKMP_HDR_RCOOKIE(buf,
1110cc6cc03eSho exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN);
11112040585eSniklas GET_ISAKMP_HDR_MESSAGE_ID(buf, exchange->message_id);
11124ab75681Shshoexer if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE))
1113aa584aacSho exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE;
11144ab75681Shshoexer if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE))
1115aa584aacSho exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE;
11162040585eSniklas exchange_enter(exchange);
11172040585eSniklas exchange_dump("exchange_setup_p2", exchange);
11182040585eSniklas return exchange;
11192040585eSniklas }
11202040585eSniklas
11212b81057dSniklas /* Dump interesting data about an exchange. */
11222040585eSniklas static void
exchange_dump_real(char * header,struct exchange * exchange,int class,int level)1123172c7fecSniklas exchange_dump_real(char *header, struct exchange *exchange, int class,
1124172c7fecSniklas int level)
11252040585eSniklas {
1126cc6cc03eSho struct sa *sa;
1127172c7fecSniklas char buf[LOG_SIZE];
1128172c7fecSniklas /* Don't risk overflowing the final log buffer. */
1129c7c448f9Sho size_t bufsize_max = LOG_SIZE - strlen(header) - 32;
1130172c7fecSniklas
113151ca15aeSniklas LOG_DBG((class, level,
11322b81057dSniklas "%s: %p %s %s policy %s phase %d doi %d exchange %d step %d",
1133a06203bdSniklas header, exchange, exchange->name ? exchange->name : "<unnamed>",
1134a06203bdSniklas exchange->policy ? exchange->policy : "<no policy>",
11352b81057dSniklas exchange->initiator ? "initiator" : "responder", exchange->phase,
113651ca15aeSniklas exchange->doi->id, exchange->type, exchange->step));
1137baf9095eShshoexer LOG_DBG((class, level, "%s: icookie %08x%08x rcookie %08x%08x", header,
11382040585eSniklas decode_32(exchange->cookies), decode_32(exchange->cookies + 4),
113950eea14cSho decode_32(exchange->cookies + 8),
114050eea14cSho decode_32(exchange->cookies + 12)));
1141172c7fecSniklas
1142172c7fecSniklas /* Include phase 2 SA list for this exchange */
1143baf9095eShshoexer if (exchange->phase == 2) {
1144b8380d91Sho snprintf(buf, bufsize_max, "sa_list ");
1145172c7fecSniklas for (sa = TAILQ_FIRST(&exchange->sa_list);
1146172c7fecSniklas sa && strlen(buf) < bufsize_max; sa = TAILQ_NEXT(sa, next))
1147cc6cc03eSho snprintf(buf + strlen(buf), bufsize_max - strlen(buf),
1148cc6cc03eSho "%p ", sa);
1149172c7fecSniklas if (sa)
1150b8380d91Sho strlcat(buf, "...", bufsize_max);
1151baf9095eShshoexer } else
1152172c7fecSniklas buf[0] = '\0';
1153172c7fecSniklas
115451ca15aeSniklas LOG_DBG((class, level, "%s: msgid %08x %s", header,
115551ca15aeSniklas decode_32(exchange->message_id), buf));
1156172c7fecSniklas }
1157172c7fecSniklas
1158172c7fecSniklas static void
exchange_dump(char * header,struct exchange * exchange)1159172c7fecSniklas exchange_dump(char *header, struct exchange *exchange)
1160172c7fecSniklas {
1161172c7fecSniklas exchange_dump_real(header, exchange, LOG_EXCHANGE, 10);
11622040585eSniklas }
11632040585eSniklas
11642040585eSniklas void
exchange_report(void)11652040585eSniklas exchange_report(void)
11662040585eSniklas {
11672040585eSniklas struct exchange *exchange;
1168cc6cc03eSho int i;
11692040585eSniklas
1170172c7fecSniklas for (i = 0; i <= bucket_mask; i++)
11712040585eSniklas for (exchange = LIST_FIRST(&exchange_tab[i]); exchange;
11722040585eSniklas exchange = LIST_NEXT(exchange, link))
1173cc6cc03eSho exchange_dump_real("exchange_report", exchange,
1174cc6cc03eSho LOG_REPORT, 0);
11752040585eSniklas }
11762040585eSniklas
117722819a49Sniklas /*
117822819a49Sniklas * Release all resources this exchange is using *except* for the "death"
117922819a49Sniklas * event. When removing an exchange from the expiration handler that event
118022819a49Sniklas * will be dealt with therein instead.
118122819a49Sniklas */
118222819a49Sniklas static void
exchange_free_aux(void * v_exch)118322819a49Sniklas exchange_free_aux(void *v_exch)
11842040585eSniklas {
118522819a49Sniklas struct exchange *exchange = v_exch;
11867db938adSniklas struct sa *sa, *next_sa;
1187fb1921ccSniklas struct cert_handler *handler;
11889bfbb31eSniklas
118951ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 80, "exchange_free_aux: freeing exchange %p",
119051ca15aeSniklas exchange));
11919bfbb31eSniklas
119222819a49Sniklas if (exchange->last_received)
119322819a49Sniklas message_free(exchange->last_received);
11941d9d87a5Sniklas if (exchange->last_sent)
11951d9d87a5Sniklas message_free(exchange->last_sent);
1196cc6cc03eSho if (exchange->in_transit &&
1197cc6cc03eSho exchange->in_transit != exchange->last_sent)
11981d9d87a5Sniklas message_free(exchange->in_transit);
11992040585eSniklas free(exchange->nonce_i);
12002040585eSniklas free(exchange->nonce_r);
12012040585eSniklas free(exchange->id_i);
12022040585eSniklas free(exchange->id_r);
12032040585eSniklas free(exchange->keystate);
120410dd6cf1Smpi if (exchange->data) {
12052040585eSniklas if (exchange->doi && exchange->doi->free_exchange_data)
12062040585eSniklas exchange->doi->free_exchange_data(exchange->data);
12072040585eSniklas free(exchange->data);
120810dd6cf1Smpi }
12092b81057dSniklas free(exchange->name);
1210baf9095eShshoexer if (exchange->recv_cert) {
1211fb1921ccSniklas handler = cert_get(exchange->recv_certtype);
1212fb1921ccSniklas if (handler)
1213fb1921ccSniklas handler->cert_free(exchange->recv_cert);
121400b1b4a9Sangelos }
1215baf9095eShshoexer if (exchange->sent_cert) {
121600b1b4a9Sangelos handler = cert_get(exchange->sent_certtype);
121700b1b4a9Sangelos if (handler)
121800b1b4a9Sangelos handler->cert_free(exchange->sent_cert);
1219fb1921ccSniklas }
122032f522cdSniklas if (exchange->recv_key)
122100b1b4a9Sangelos key_free(exchange->recv_keytype, ISAKMP_KEYTYPE_PUBLIC,
122200b1b4a9Sangelos exchange->recv_key);
122300b1b4a9Sangelos free(exchange->keynote_key); /* This is just a string */
122432f522cdSniklas
122532f522cdSniklas if (exchange->policy_id != -1)
1226f61a65acSho kn_close(exchange->policy_id);
122732f522cdSniklas
12282040585eSniklas exchange_free_aca_list(exchange);
122910dd6cf1Smpi if (exchange->linked) {
123022819a49Sniklas LIST_REMOVE(exchange, link);
123110dd6cf1Smpi exchange->linked = 0;
123210dd6cf1Smpi }
123324d2f2e1Sniklas
1234bd4e5273Sniklas /* Tell potential finalize routine we never got there. */
123524d2f2e1Sniklas if (exchange->finalize)
1236172c7fecSniklas exchange->finalize(exchange, exchange->finalize_arg, 1);
1237bd4e5273Sniklas
12389c28b8a1Sangelos /* Remove any SAs that have not been disassociated from us. */
1239baf9095eShshoexer for (sa = TAILQ_FIRST(&exchange->sa_list); sa; sa = next_sa) {
12407db938adSniklas next_sa = TAILQ_NEXT(sa, next);
12419c28b8a1Sangelos /* One for the reference in exchange->sa_list. */
12429c28b8a1Sangelos sa_release(sa);
12439c28b8a1Sangelos /* And two more for the expiration and SA linked list. */
12447db938adSniklas sa_free(sa);
12457db938adSniklas }
124624d2f2e1Sniklas
12472040585eSniklas free(exchange);
12482040585eSniklas }
12492040585eSniklas
12502040585eSniklas /* Release all resources this exchange is using. */
12512040585eSniklas void
exchange_free(struct exchange * exchange)12522040585eSniklas exchange_free(struct exchange *exchange)
12532040585eSniklas {
12542040585eSniklas if (exchange->death)
12552040585eSniklas timer_remove_event(exchange->death);
12562040585eSniklas exchange_free_aux(exchange);
12572040585eSniklas }
12582040585eSniklas
12592040585eSniklas /*
12602040585eSniklas * Upgrade the phase 1 exchange and its ISAKMP SA with the rcookie of our
12612040585eSniklas * peer (found in his recently sent message MSG).
12622040585eSniklas */
12632040585eSniklas void
exchange_upgrade_p1(struct message * msg)12642040585eSniklas exchange_upgrade_p1(struct message *msg)
12652040585eSniklas {
12662040585eSniklas struct exchange *exchange = msg->exchange;
12672040585eSniklas
12682040585eSniklas LIST_REMOVE(exchange, link);
126910dd6cf1Smpi exchange->linked = 0;
1270baf9095eShshoexer GET_ISAKMP_HDR_RCOOKIE(msg->iov[0].iov_base, exchange->cookies +
1271baf9095eShshoexer ISAKMP_HDR_ICOOKIE_LEN);
12722040585eSniklas exchange_enter(exchange);
12732040585eSniklas sa_isakmp_upgrade(msg);
12742040585eSniklas }
12752040585eSniklas
1276172c7fecSniklas static int
exchange_check_old_sa(struct sa * sa,void * v_arg)1277172c7fecSniklas exchange_check_old_sa(struct sa *sa, void *v_arg)
1278172c7fecSniklas {
1279172c7fecSniklas struct sa *new_sa = v_arg;
12802beb4bdbSangelos char res1[1024];
1281172c7fecSniklas
1282baf9095eShshoexer if (sa == new_sa || !sa->name || !(sa->flags & SA_FLAG_READY) ||
1283baf9095eShshoexer (sa->flags & SA_FLAG_REPLACED))
1284172c7fecSniklas return 0;
1285172c7fecSniklas
1286baf9095eShshoexer if (sa->phase != new_sa->phase || new_sa->name == 0 ||
1287baf9095eShshoexer strcasecmp(sa->name, new_sa->name))
12882beb4bdbSangelos return 0;
12892beb4bdbSangelos
12902beb4bdbSangelos if (sa->initiator)
1291baf9095eShshoexer strlcpy(res1, ipsec_decode_ids("%s %s", sa->id_i, sa->id_i_len,
1292baf9095eShshoexer sa->id_r, sa->id_r_len, 0), sizeof res1);
12932beb4bdbSangelos else
1294baf9095eShshoexer strlcpy(res1, ipsec_decode_ids("%s %s", sa->id_r, sa->id_r_len,
1295baf9095eShshoexer sa->id_i, sa->id_i_len, 0), sizeof res1);
12962beb4bdbSangelos
12972beb4bdbSangelos LOG_DBG((LOG_EXCHANGE, 30,
1298a7b8c2e4Sniklas "checking whether new SA replaces existing SA with IDs %s", res1));
12992beb4bdbSangelos
13002beb4bdbSangelos if (new_sa->initiator)
13012beb4bdbSangelos return strcasecmp(res1, ipsec_decode_ids("%s %s", new_sa->id_i,
1302baf9095eShshoexer new_sa->id_i_len, new_sa->id_r, new_sa->id_r_len, 0)) == 0;
13032beb4bdbSangelos else
13042beb4bdbSangelos return strcasecmp(res1, ipsec_decode_ids("%s %s", new_sa->id_r,
1305baf9095eShshoexer new_sa->id_r_len, new_sa->id_i, new_sa->id_i_len, 0)) == 0;
1306172c7fecSniklas }
1307172c7fecSniklas
13082040585eSniklas void
exchange_finalize(struct message * msg)13092040585eSniklas exchange_finalize(struct message *msg)
13102040585eSniklas {
13112040585eSniklas struct exchange *exchange = msg->exchange;
131222819a49Sniklas struct sa *sa, *old_sa;
13132040585eSniklas struct proto *proto;
131419a5b5f4Sniklas struct conf_list *attrs;
131519a5b5f4Sniklas struct conf_list_node *attr;
131600b1b4a9Sangelos struct cert_handler *handler;
13172040585eSniklas int i;
13182cc3a730Shshoexer char *id_doi, *id_trp;
13192040585eSniklas
13202040585eSniklas exchange_dump("exchange_finalize", exchange);
13212040585eSniklas
1322f37486b9Sho /* Copy the ID from phase 1 to exchange or phase 2 SA. */
1323baf9095eShshoexer if (msg->isakmp_sa) {
1324baf9095eShshoexer if (exchange->id_i && exchange->id_r) {
1325cc6cc03eSho ipsec_clone_id(&msg->isakmp_sa->id_i,
1326cc6cc03eSho &msg->isakmp_sa->id_i_len, exchange->id_i,
1327cc6cc03eSho exchange->id_i_len);
1328cc6cc03eSho ipsec_clone_id(&msg->isakmp_sa->id_r,
1329cc6cc03eSho &msg->isakmp_sa->id_r_len, exchange->id_r,
1330cc6cc03eSho exchange->id_r_len);
1331baf9095eShshoexer } else if (msg->isakmp_sa->id_i && msg->isakmp_sa->id_r) {
1332f37486b9Sho ipsec_clone_id(&exchange->id_i, &exchange->id_i_len,
1333f37486b9Sho msg->isakmp_sa->id_i, msg->isakmp_sa->id_i_len);
1334f37486b9Sho ipsec_clone_id(&exchange->id_r, &exchange->id_r_len,
1335f37486b9Sho msg->isakmp_sa->id_r, msg->isakmp_sa->id_r_len);
1336f37486b9Sho }
1337f37486b9Sho }
13382040585eSniklas /*
133922819a49Sniklas * Walk over all the SAs and noting them as ready. If we set the
134022819a49Sniklas * COMMIT bit, tell the peer each SA is connected.
134122819a49Sniklas *
13422040585eSniklas * XXX The decision should really be based on if a SA was installed
13432040585eSniklas * successfully.
13442040585eSniklas */
1345cc6cc03eSho for (sa = TAILQ_FIRST(&exchange->sa_list); sa;
1346cc6cc03eSho sa = TAILQ_NEXT(sa, next)) {
1347a06203bdSniklas /* Move over the name to the SA. */
13489bfbb31eSniklas sa->name = exchange->name ? strdup(exchange->name) : 0;
1349a06203bdSniklas
1350baf9095eShshoexer if (exchange->flags & EXCHANGE_FLAG_I_COMMITTED) {
13512040585eSniklas for (proto = TAILQ_FIRST(&sa->protos); proto;
13522040585eSniklas proto = TAILQ_NEXT(proto, link))
13532040585eSniklas for (i = 0; i < 2; i++)
13542040585eSniklas message_send_notification(exchange->last_received,
13552040585eSniklas msg->isakmp_sa,
1356baf9095eShshoexer ISAKMP_NOTIFY_STATUS_CONNECTED,
1357baf9095eShshoexer proto, i);
13582040585eSniklas }
1359baf9095eShshoexer /*
1360baf9095eShshoexer * Locate any old SAs and mark them replaced
1361baf9095eShshoexer * (SA_FLAG_REPLACED).
1362baf9095eShshoexer */
13635fc21c41Sho sa->initiator = exchange->initiator;
1364172c7fecSniklas while ((old_sa = sa_find(exchange_check_old_sa, sa)) != 0)
1365172c7fecSniklas sa_mark_replaced(old_sa);
1366172c7fecSniklas
136719a5b5f4Sniklas /* Setup the SA flags. */
13682040585eSniklas sa->flags |= SA_FLAG_READY;
1369baf9095eShshoexer if (exchange->name) {
1370a06203bdSniklas attrs = conf_get_list(exchange->name, "Flags");
1371baf9095eShshoexer if (attrs) {
137219a5b5f4Sniklas for (attr = TAILQ_FIRST(&attrs->fields); attr;
137319a5b5f4Sniklas attr = TAILQ_NEXT(attr, link))
137419a5b5f4Sniklas sa->flags |= sa_flag(attr->field);
137524d2f2e1Sniklas conf_free_list(attrs);
137624d2f2e1Sniklas }
1377ec172ef8Sniklas /* 'Connections' should stay alive. */
1378baf9095eShshoexer if (connection_exist(exchange->name)) {
1379ec172ef8Sniklas sa->flags |= SA_FLAG_STAYALIVE;
1380ec172ef8Sniklas
1381baf9095eShshoexer /*
1382baf9095eShshoexer * ISAKMP SA of this connection should also
1383baf9095eShshoexer * stay alive.
1384baf9095eShshoexer */
1385ec172ef8Sniklas if (exchange->phase == 2 && msg->isakmp_sa)
1386cc6cc03eSho msg->isakmp_sa->flags |=
1387cc6cc03eSho SA_FLAG_STAYALIVE;
1388ec172ef8Sniklas }
13894c7a9999Sniklas }
139045055671Sangelos sa->seq = exchange->seq;
13912040585eSniklas sa->exch_type = exchange->type;
13922040585eSniklas }
13932040585eSniklas
13942040585eSniklas /*
1395baf9095eShshoexer * If this was an phase 1 SA negotiation, save the keystate in the
1396baf9095eShshoexer * ISAKMP SA structure for future initialization of phase 2 exchanges'
1397baf9095eShshoexer * keystates. Also save the Phase 1 ID and authentication
1398baf9095eShshoexer * information.
13992040585eSniklas */
1400baf9095eShshoexer if (exchange->phase == 1 && msg->isakmp_sa) {
14012040585eSniklas msg->isakmp_sa->keystate = exchange->keystate;
14022040585eSniklas exchange->keystate = 0;
14037409b616Sniklas
14047409b616Sniklas msg->isakmp_sa->recv_certtype = exchange->recv_certtype;
140500b1b4a9Sangelos msg->isakmp_sa->sent_certtype = exchange->sent_certtype;
140600b1b4a9Sangelos msg->isakmp_sa->recv_keytype = exchange->recv_keytype;
140732f522cdSniklas msg->isakmp_sa->recv_key = exchange->recv_key;
140800b1b4a9Sangelos msg->isakmp_sa->keynote_key = exchange->keynote_key;
14090eb823c5Sniklas /* Reset. */
14100eb823c5Sniklas exchange->recv_key = 0;
14110eb823c5Sniklas exchange->keynote_key = 0;
141232f522cdSniklas msg->isakmp_sa->policy_id = exchange->policy_id;
14130e8582adSangelos exchange->policy_id = -1;
14147409b616Sniklas msg->isakmp_sa->initiator = exchange->initiator;
14157409b616Sniklas
1416baf9095eShshoexer if (exchange->recv_certtype && exchange->recv_cert) {
141700b1b4a9Sangelos handler = cert_get(exchange->recv_certtype);
141800b1b4a9Sangelos if (handler)
1419baf9095eShshoexer msg->isakmp_sa->recv_cert =
1420baf9095eShshoexer handler->cert_dup(exchange->recv_cert);
142154a25d2eSniklas }
1422baf9095eShshoexer if (exchange->sent_certtype) {
142300b1b4a9Sangelos handler = cert_get(exchange->sent_certtype);
142400b1b4a9Sangelos if (handler)
1425baf9095eShshoexer msg->isakmp_sa->sent_cert =
1426baf9095eShshoexer handler->cert_dup(exchange->sent_cert);
14272040585eSniklas }
14282cc3a730Shshoexer if (exchange->doi)
1429baf9095eShshoexer id_doi = exchange->doi->decode_ids(
1430baf9095eShshoexer "initiator id %s, responder id %s",
143180f73593Sniklas exchange->id_i, exchange->id_i_len,
1432baf9095eShshoexer exchange->id_r, exchange->id_r_len, 0);
14332cc3a730Shshoexer else
14342cc3a730Shshoexer id_doi = "<no doi>";
14352cc3a730Shshoexer
1436aa584aacSho if (msg->isakmp_sa->transport)
1437cc6cc03eSho id_trp =
1438cc6cc03eSho msg->isakmp_sa->transport->vtbl->decode_ids(msg->isakmp_sa->transport);
14392cc3a730Shshoexer else
14402cc3a730Shshoexer id_trp = "<no transport>";
14412cc3a730Shshoexer
1442aa584aacSho if (exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE)
1443aa584aacSho msg->isakmp_sa->flags |= SA_FLAG_NAT_T_ENABLE;
1444aa584aacSho if (exchange->flags & EXCHANGE_FLAG_NAT_T_KEEPALIVE)
1445aa584aacSho msg->isakmp_sa->flags |= SA_FLAG_NAT_T_KEEPALIVE;
1446aa584aacSho
1447baf9095eShshoexer LOG_DBG((LOG_EXCHANGE, 10,
1448cc6cc03eSho "exchange_finalize: phase 1 done: %s, %s", id_doi,
1449cc6cc03eSho id_trp));
14502cc3a730Shshoexer
1451e76eb8e7Slum log_verbose("isakmpd: phase 1 done%s: %s, %s",
1452e76eb8e7Slum (exchange->initiator == 0) ? " (as responder)" : "",
1453e76eb8e7Slum id_doi, id_trp);
14547409b616Sniklas }
1455d6351a66Sho exchange->doi->finalize_exchange(msg);
1456d6351a66Sho if (exchange->finalize)
1457d6351a66Sho exchange->finalize(exchange, exchange->finalize_arg, 0);
1458d6351a66Sho exchange->finalize = 0;
1459d6351a66Sho
1460bd4e5273Sniklas /*
1461bd4e5273Sniklas * There is no reason to keep the SAs connected to us anymore, in fact
1462bd4e5273Sniklas * it can hurt us if we have short lifetimes on the SAs and we try
1463bd4e5273Sniklas * to call exchange_report, where the SA list will be walked and
1464bd4e5273Sniklas * references to freed SAs can occur.
1465bd4e5273Sniklas */
1466baf9095eShshoexer while (TAILQ_FIRST(&exchange->sa_list)) {
1467605cc57cSho sa = TAILQ_FIRST(&exchange->sa_list);
146880f73593Sniklas
1469baf9095eShshoexer if (exchange->id_i && exchange->id_r) {
1470cc6cc03eSho ipsec_clone_id(&sa->id_i, &sa->id_i_len,
1471cc6cc03eSho exchange->id_i, exchange->id_i_len);
1472cc6cc03eSho ipsec_clone_id(&sa->id_r, &sa->id_r_len,
1473cc6cc03eSho exchange->id_r, exchange->id_r_len);
147472c6dfaeSniklas }
147580f73593Sniklas TAILQ_REMOVE(&exchange->sa_list, sa, next);
14761d312cf3Sniklas sa_release(sa);
147780f73593Sniklas }
1478a31e0ec4Smarkus /*
1479a31e0ec4Smarkus * Start sending DPD messages after all SAs have been released.
1480a31e0ec4Smarkus * Otherwise we have a race between exchange_free_aux() and
1481a31e0ec4Smarkus * dpd_check_event() where both will call sa_free().
1482a31e0ec4Smarkus */
1483a31e0ec4Smarkus if (exchange->phase == 1 && msg->isakmp_sa &&
1484a31e0ec4Smarkus (exchange->flags & EXCHANGE_FLAG_DPD_CAP_PEER))
1485a31e0ec4Smarkus dpd_start(msg->isakmp_sa);
1486bd4e5273Sniklas
148722819a49Sniklas /* If we have nothing to retransmit we can safely remove ourselves. */
148822819a49Sniklas if (!exchange->last_sent)
14892040585eSniklas exchange_free(exchange);
14902040585eSniklas }
14912040585eSniklas
14922040585eSniklas /* Stash a nonce into the exchange data. */
14932040585eSniklas static int
exchange_nonce(struct exchange * exchange,int peer,size_t nonce_sz,u_int8_t * buf)14942040585eSniklas exchange_nonce(struct exchange *exchange, int peer, size_t nonce_sz,
14952040585eSniklas u_int8_t *buf)
14962040585eSniklas {
14972040585eSniklas u_int8_t **nonce;
14982040585eSniklas size_t *nonce_len;
1499cc6cc03eSho int initiator = exchange->initiator ^ peer;
15002040585eSniklas char header[32];
15012040585eSniklas
1502120ded69Sho if (nonce_sz < 8 || nonce_sz > 256) {
1503120ded69Sho /*
1504120ded69Sho * RFC2409, ch 5: The length of nonce payload MUST be
1505120ded69Sho * between 8 and 256 bytes inclusive.
1506120ded69Sho * XXX I'm assuming the generic payload header is not included.
1507120ded69Sho */
1508120ded69Sho LOG_DBG((LOG_EXCHANGE, 20,
1509120ded69Sho "exchange_nonce: invalid nonce length %lu",
1510120ded69Sho (unsigned long)nonce_sz));
1511120ded69Sho return -1;
1512120ded69Sho }
1513120ded69Sho
15142040585eSniklas nonce = initiator ? &exchange->nonce_i : &exchange->nonce_r;
1515cc6cc03eSho nonce_len =
1516cc6cc03eSho initiator ? &exchange->nonce_i_len : &exchange->nonce_r_len;
15172040585eSniklas *nonce_len = nonce_sz;
15182040585eSniklas *nonce = malloc(nonce_sz);
1519baf9095eShshoexer if (!*nonce) {
1520baf9095eShshoexer log_error("exchange_nonce: malloc (%lu) failed",
1521baf9095eShshoexer (unsigned long)nonce_sz);
15222040585eSniklas return -1;
152324d2f2e1Sniklas }
15242040585eSniklas memcpy(*nonce, buf, nonce_sz);
1525f799be47Sho snprintf(header, sizeof header, "exchange_nonce: NONCE_%c",
1526f799be47Sho initiator ? 'i' : 'r');
152751ca15aeSniklas LOG_DBG_BUF((LOG_EXCHANGE, 80, header, *nonce, nonce_sz));
15282040585eSniklas return 0;
15292040585eSniklas }
15302040585eSniklas
15312040585eSniklas /* Generate our NONCE. */
15322040585eSniklas int
exchange_gen_nonce(struct message * msg,size_t nonce_sz)15332040585eSniklas exchange_gen_nonce(struct message *msg, size_t nonce_sz)
15342040585eSniklas {
15352040585eSniklas struct exchange *exchange = msg->exchange;
15362040585eSniklas u_int8_t *buf;
15372040585eSniklas
15382040585eSniklas buf = malloc(ISAKMP_NONCE_SZ + nonce_sz);
1539baf9095eShshoexer if (!buf) {
15407eb3b581Sderaadt log_error("exchange_gen_nonce: malloc (%lu) failed",
15417eb3b581Sderaadt ISAKMP_NONCE_SZ + (unsigned long)nonce_sz);
15422040585eSniklas return -1;
154324d2f2e1Sniklas }
1544baf9c2dbSderaadt arc4random_buf(buf + ISAKMP_NONCE_DATA_OFF, nonce_sz);
15452040585eSniklas if (message_add_payload(msg, ISAKMP_PAYLOAD_NONCE, buf,
1546baf9095eShshoexer ISAKMP_NONCE_SZ + nonce_sz, 1)) {
15472040585eSniklas free(buf);
15482040585eSniklas return -1;
15492040585eSniklas }
1550cc6cc03eSho return exchange_nonce(exchange, 0, nonce_sz,
1551cc6cc03eSho buf + ISAKMP_NONCE_DATA_OFF);
15522040585eSniklas }
15532040585eSniklas
15542040585eSniklas /* Save the peer's NONCE. */
15552040585eSniklas int
exchange_save_nonce(struct message * msg)15562040585eSniklas exchange_save_nonce(struct message *msg)
15572040585eSniklas {
15582040585eSniklas struct payload *noncep;
15592040585eSniklas struct exchange *exchange = msg->exchange;
15602040585eSniklas
156177fa3de5Sho noncep = payload_first(msg, ISAKMP_PAYLOAD_NONCE);
15622040585eSniklas noncep->flags |= PL_MARK;
1563baf9095eShshoexer return exchange_nonce(exchange, 1, GET_ISAKMP_GEN_LENGTH(noncep->p) -
1564baf9095eShshoexer ISAKMP_NONCE_DATA_OFF, noncep->p + ISAKMP_NONCE_DATA_OFF);
15652040585eSniklas }
15662040585eSniklas
15672040585eSniklas /* Save the peer's CERT REQuests. */
15682040585eSniklas int
exchange_save_certreq(struct message * msg)15692040585eSniklas exchange_save_certreq(struct message *msg)
15702040585eSniklas {
1571ed76d6b8Shshoexer struct payload *cp;
15722040585eSniklas struct exchange *exchange = msg->exchange;
1573a7b8c2e4Sniklas struct certreq_aca *aca;
15742040585eSniklas
1575ed76d6b8Shshoexer TAILQ_FOREACH(cp, &msg->payload[ISAKMP_PAYLOAD_CERT_REQ], link) {
15762040585eSniklas cp->flags |= PL_MARK;
1577baf9095eShshoexer aca = certreq_decode(GET_ISAKMP_CERTREQ_TYPE(cp->p), cp->p +
1578baf9095eShshoexer ISAKMP_CERTREQ_AUTHORITY_OFF, GET_ISAKMP_GEN_LENGTH(cp->p)
1579baf9095eShshoexer - ISAKMP_CERTREQ_AUTHORITY_OFF);
1580a7b8c2e4Sniklas if (aca)
1581a7b8c2e4Sniklas TAILQ_INSERT_TAIL(&exchange->aca_list, aca, link);
15822040585eSniklas }
15832040585eSniklas
15842040585eSniklas return 0;
15852040585eSniklas }
15862040585eSniklas
15873b43e3b6Sniklas /* Free the list of pending CERTREQs. */
15882040585eSniklas void
exchange_free_aca_list(struct exchange * exchange)15892040585eSniklas exchange_free_aca_list(struct exchange *exchange)
15902040585eSniklas {
15912040585eSniklas struct certreq_aca *aca;
15922040585eSniklas
15932040585eSniklas for (aca = TAILQ_FIRST(&exchange->aca_list); aca;
1594baf9095eShshoexer aca = TAILQ_FIRST(&exchange->aca_list)) {
159505442ddfStom free(aca->raw_ca);
1596baf9095eShshoexer if (aca->data) {
1597172c7fecSniklas if (aca->handler)
15982040585eSniklas aca->handler->free_aca(aca->data);
15992040585eSniklas free(aca->data);
16002040585eSniklas }
16012040585eSniklas TAILQ_REMOVE(&exchange->aca_list, aca, link);
16022040585eSniklas free(aca);
16032040585eSniklas }
16042040585eSniklas }
16052040585eSniklas
160605442ddfStom /* Add any CERTREQs we should send. */
160705442ddfStom int
exchange_add_certreqs(struct message * msg)160805442ddfStom exchange_add_certreqs(struct message *msg)
160905442ddfStom {
161005442ddfStom struct exchange *exchange = msg->exchange;
161105442ddfStom struct certreq_aca *aca;
161205442ddfStom u_int8_t *buf;
161305442ddfStom
161405442ddfStom /*
161505442ddfStom * Some peers (e.g. Cisco IOS) won't send their cert unless we
161605442ddfStom * specifically ask beforehand with CERTREQ. We reflect any
161705442ddfStom * CERTREQs we receive from the initiator in order to do this.
161805442ddfStom * This avoids leaking information about which CAs we trust,
161905442ddfStom * and works in the most common case where both ends trust the
162005442ddfStom * same CA.
162105442ddfStom */
162205442ddfStom for (aca = TAILQ_FIRST(&exchange->aca_list); aca;
162305442ddfStom aca = TAILQ_NEXT(aca, link)) {
162405442ddfStom
162505442ddfStom /* But only do this if we have at least one CA */
162605442ddfStom if (aca->handler != NULL && aca->handler->ca_count() == 0) {
162705442ddfStom LOG_DBG((LOG_EXCHANGE, 10,
162805442ddfStom "exchange_add_certreqs: no CA, so not "
162905442ddfStom "sending a CERTREQ"));
163005442ddfStom continue;
163105442ddfStom }
163205442ddfStom
163305442ddfStom if (aca->raw_ca_len) {
163405442ddfStom buf = malloc(ISAKMP_CERTREQ_SZ + aca->raw_ca_len);
163505442ddfStom if (buf == NULL) {
163605442ddfStom log_error("exchange_add_certreqs: "
163705442ddfStom "malloc (%lu) failed",
163805442ddfStom ISAKMP_CERTREQ_SZ +
163905442ddfStom (unsigned long)aca->raw_ca_len);
164005442ddfStom return -1;
164105442ddfStom }
164205442ddfStom
164305442ddfStom buf[ISAKMP_CERTREQ_TYPE_OFF] = aca->id;
164405442ddfStom memcpy(buf + ISAKMP_CERTREQ_AUTHORITY_OFF,
164505442ddfStom aca->raw_ca, aca->raw_ca_len);
164605442ddfStom
164705442ddfStom if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT_REQ,
164805442ddfStom buf, ISAKMP_CERTREQ_SZ + aca->raw_ca_len, 1)) {
164905442ddfStom free(buf);
165005442ddfStom return -1;
165105442ddfStom }
165205442ddfStom }
165305442ddfStom }
165405442ddfStom
165505442ddfStom return 0;
165605442ddfStom }
165705442ddfStom
165824d2f2e1Sniklas /* Obtain certificates from acceptable certification authority. */
16592040585eSniklas int
exchange_add_certs(struct message * msg)16602040585eSniklas exchange_add_certs(struct message *msg)
16612040585eSniklas {
16622040585eSniklas struct exchange *exchange = msg->exchange;
16632040585eSniklas struct certreq_aca *aca;
1664e7e18aa3Scloder u_int8_t *cert = 0, *new_cert = 0;
16652040585eSniklas u_int32_t certlen;
1666fb1921ccSniklas u_int8_t *id;
1667fb1921ccSniklas size_t id_len;
1668fb1921ccSniklas
1669fb1921ccSniklas id = exchange->initiator ? exchange->id_r : exchange->id_i;
1670fb1921ccSniklas id_len = exchange->initiator ? exchange->id_r_len : exchange->id_i_len;
16712040585eSniklas
167282bf5ee8Sho /*
167382bf5ee8Sho * Without IDs we cannot handle this yet. Keep the aca_list around for
167482bf5ee8Sho * a later step/retry to see if we got the ID by then.
167582bf5ee8Sho * Note: A 'return -1' breaks X509-auth interop in the responder case
1676cc6cc03eSho * with some IPsec clients that send CERTREQs early (such as
1677cc6cc03eSho * the SSH Sentinel).
167882bf5ee8Sho */
167982bf5ee8Sho if (!id)
168082bf5ee8Sho return 0;
168182bf5ee8Sho
16822040585eSniklas for (aca = TAILQ_FIRST(&exchange->aca_list); aca;
1683baf9095eShshoexer aca = TAILQ_NEXT(aca, link)) {
1684a7b8c2e4Sniklas /* XXX? If we can not satisfy a CERTREQ we drop the message. */
1685cc6cc03eSho if (!aca->handler->cert_obtain(id, id_len, aca->data, &cert,
1686cc6cc03eSho &certlen)) {
1687baf9095eShshoexer log_print("exchange_add_certs: could not obtain cert "
1688baf9095eShshoexer "for a type %d cert request", aca->id);
1689e7e18aa3Scloder free(cert);
16902040585eSniklas return -1;
16912040585eSniklas }
1692e7e18aa3Scloder new_cert = realloc(cert, ISAKMP_CERT_SZ + certlen);
1693baf9095eShshoexer if (!new_cert) {
1694cc6cc03eSho log_error("exchange_add_certs: realloc (%p, %d) "
1695cc6cc03eSho "failed", cert, ISAKMP_CERT_SZ + certlen);
1696e7e18aa3Scloder free(cert);
16972040585eSniklas return -1;
169824d2f2e1Sniklas }
1699e7e18aa3Scloder cert = new_cert;
17002040585eSniklas memmove(cert + ISAKMP_CERT_DATA_OFF, cert, certlen);
17012040585eSniklas SET_ISAKMP_CERT_ENCODING(cert, aca->id);
17022040585eSniklas if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT, cert,
1703baf9095eShshoexer ISAKMP_CERT_SZ + certlen, 1)) {
17042040585eSniklas free(cert);
17052040585eSniklas return -1;
17062040585eSniklas }
170711d4dffdStom /*
170811d4dffdStom * We need to reset cert here, as it is now controlled by
170911d4dffdStom * message_add_payload() (i.e. we must not free() it), and
171011d4dffdStom * it is possible for the next iteration of the aca loop
171111d4dffdStom * to fail early in cert_obtain before it writes to &cert.
171211d4dffdStom */
171311d4dffdStom cert = NULL;
17142040585eSniklas }
17152040585eSniklas
1716a7b8c2e4Sniklas /* We dont need the CERT REQs any more, they are answered. */
17172040585eSniklas exchange_free_aca_list(exchange);
17182040585eSniklas
17192040585eSniklas return 0;
17202040585eSniklas }
17212b81057dSniklas
17222b81057dSniklas static void
exchange_establish_finalize(struct exchange * exchange,void * arg,int fail)1723172c7fecSniklas exchange_establish_finalize(struct exchange *exchange, void *arg, int fail)
17242b81057dSniklas {
17252b81057dSniklas char *name = arg;
1726172c7fecSniklas
1727baf9095eShshoexer LOG_DBG((LOG_EXCHANGE, 20, "exchange_establish_finalize: "
1728172c7fecSniklas "finalizing exchange %p with arg %p (%s) & fail = %d",
172951ca15aeSniklas exchange, arg, name ? name : "<unnamed>", fail));
17302b81057dSniklas
173124d2f2e1Sniklas if (!fail)
1732a28d886cShshoexer exchange_establish(name, 0, 0, 0);
17339bfbb31eSniklas free(name);
17342b81057dSniklas }
17352b81057dSniklas
1736a06203bdSniklas /*
1737a06203bdSniklas * Establish an exchange named NAME, and record the FINALIZE function
1738a06203bdSniklas * taking ARG as an argument to be run after the exchange is ready.
1739a06203bdSniklas */
17402b81057dSniklas void
exchange_establish(char * name,void (* finalize)(struct exchange *,void *,int),void * arg,int stayalive)1741baf9095eShshoexer exchange_establish(char *name, void (*finalize)(struct exchange *, void *,
1742a28d886cShshoexer int), void *arg, int stayalive)
17432b81057dSniklas {
17442b81057dSniklas struct transport *transport;
17452b81057dSniklas struct sa *isakmp_sa;
1746172c7fecSniklas struct exchange *exchange;
1747cc6cc03eSho int phase;
1748cc6cc03eSho char *trpt, *peer;
1749cc6cc03eSho
1750f5228d8eSniklas phase = conf_get_num(name, "Phase", 0);
1751172c7fecSniklas
175214f1d06aSmpf if (ui_daemon_passive) {
175314f1d06aSmpf LOG_DBG((LOG_EXCHANGE, 40, "exchange_establish:"
175414f1d06aSmpf " returning in passive mode for exchange %s phase %d",
175514f1d06aSmpf name, phase));
175610dd6cf1Smpi if (finalize)
175710dd6cf1Smpi finalize(0, arg, 1);
175814f1d06aSmpf return;
175914f1d06aSmpf }
176014f1d06aSmpf
1761172c7fecSniklas /*
1762baf9095eShshoexer * First of all, never try to establish anything if another exchange
1763baf9095eShshoexer * of the same kind is running.
1764172c7fecSniklas */
1765172c7fecSniklas exchange = exchange_lookup_by_name(name, phase);
1766baf9095eShshoexer if (exchange) {
176751ca15aeSniklas LOG_DBG((LOG_EXCHANGE, 40,
1768cc6cc03eSho "exchange_establish: %s exchange already exists as %p",
1769cc6cc03eSho name, exchange));
1770172c7fecSniklas exchange_add_finalization(exchange, finalize, arg);
1771172c7fecSniklas return;
1772172c7fecSniklas }
1773baf9095eShshoexer switch (phase) {
17742b81057dSniklas case 1:
17752b81057dSniklas trpt = conf_get_str(name, "Transport");
1776baf9095eShshoexer if (!trpt) {
177780f73593Sniklas /* Phase 1 transport defaults to "udp". */
177880f73593Sniklas trpt = ISAKMP_DEFAULT_TRANSPORT;
17792b81057dSniklas }
17802b81057dSniklas transport = transport_create(trpt, name);
1781baf9095eShshoexer if (!transport) {
1782cc6cc03eSho log_print("exchange_establish: transport \"%s\" for "
1783cc6cc03eSho "peer \"%s\" could not be created", trpt, name);
178410dd6cf1Smpi if (finalize)
178510dd6cf1Smpi finalize(0, arg, 1);
17862b81057dSniklas return;
17872b81057dSniklas }
178810dd6cf1Smpi if (exchange_establish_p1(transport, 0, 0, name, 0, finalize,
178910dd6cf1Smpi arg, stayalive) < 0 && finalize)
179010dd6cf1Smpi finalize(0, arg, 1);
17912b81057dSniklas break;
17922b81057dSniklas
17932b81057dSniklas case 2:
17942b81057dSniklas peer = conf_get_str(name, "ISAKMP-peer");
1795baf9095eShshoexer if (!peer) {
1796cc6cc03eSho log_print("exchange_establish: No ISAKMP-peer given "
1797cc6cc03eSho "for \"%s\"", name);
179810dd6cf1Smpi if (finalize)
179910dd6cf1Smpi finalize(0, arg, 1);
18002b81057dSniklas return;
18012b81057dSniklas }
18022b81057dSniklas isakmp_sa = sa_lookup_by_name(peer, 1);
1803baf9095eShshoexer if (!isakmp_sa) {
180410dd6cf1Smpi /* freed by exchange_establish_finalize() */
18052b81057dSniklas name = strdup(name);
1806baf9095eShshoexer if (!name) {
1807cc6cc03eSho log_error("exchange_establish: "
1808cc6cc03eSho "strdup (\"%s\") failed", name);
180910dd6cf1Smpi if (finalize)
181010dd6cf1Smpi finalize(0, arg, 1);
18112b81057dSniklas return;
18122b81057dSniklas }
1813baf9095eShshoexer if (conf_get_num(peer, "Phase", 0) != 1) {
1814afcc621fSho log_print("exchange_establish: "
1815baf9095eShshoexer "[%s]:ISAKMP-peer's (%s) phase is not 1",
1816baf9095eShshoexer name, peer);
181710dd6cf1Smpi if (finalize)
181810dd6cf1Smpi finalize(0, arg, 1);
1819b05ee9e0Smarkus free(name);
18207409b616Sniklas return;
18217409b616Sniklas }
18228ce6c35cSangelos /*
1823baf9095eShshoexer * XXX We're losing information here (what the
1824baf9095eShshoexer * original finalize routine was. As a result, if an
1825baf9095eShshoexer * exchange does not manage to get through, there may
1826baf9095eShshoexer * be application-specific information that won't get
18275678a57aShshoexer * cleaned up, since no error signaling will be done.
1828baf9095eShshoexer * This is the case with dynamic SAs and PFKEY.
18298ce6c35cSangelos */
1830cc6cc03eSho exchange_establish(peer, exchange_establish_finalize,
1831a28d886cShshoexer name, 0);
1832ea9e0bc0Sangelos exchange = exchange_lookup_by_name(peer, 1);
1833ea9e0bc0Sangelos /*
1834baf9095eShshoexer * If the exchange was correctly initialized, add the
1835baf9095eShshoexer * original finalization routine; otherwise, call it
1836baf9095eShshoexer * directly.
1837ea9e0bc0Sangelos */
1838ea9e0bc0Sangelos if (exchange)
1839cc6cc03eSho exchange_add_finalization(exchange, finalize,
1840cc6cc03eSho arg);
1841b05ee9e0Smarkus else {
18423dbbcfa7Scloder /* Indicate failure */
18433dbbcfa7Scloder if (finalize)
18443dbbcfa7Scloder finalize(0, arg, 1);
1845b05ee9e0Smarkus }
1846ea9e0bc0Sangelos return;
184710dd6cf1Smpi } else {
184810dd6cf1Smpi if (exchange_establish_p2(isakmp_sa, 0, name, 0,
184910dd6cf1Smpi finalize, arg) < 0 && finalize)
185010dd6cf1Smpi finalize(0, arg, 1);
185110dd6cf1Smpi }
18522b81057dSniklas break;
18532b81057dSniklas
18542b81057dSniklas default:
18552b81057dSniklas log_print("exchange_establish: "
18562b81057dSniklas "peer \"%s\" does not have a correct phase (%d)",
18572b81057dSniklas name, phase);
18582b81057dSniklas break;
18592b81057dSniklas }
18602b81057dSniklas }
1861