1 |
|
|
/* $OpenBSD: exchange.c,v 1.139 2017/09/18 07:42:52 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_BITS 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_BITS 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) *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_SA, /* Initiator -> responder. */ |
92 |
|
|
ISAKMP_PAYLOAD_NONCE, |
93 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
94 |
|
|
ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */ |
95 |
|
|
ISAKMP_PAYLOAD_NONCE, |
96 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
97 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, /* Initiator -> responder. */ |
98 |
|
|
ISAKMP_PAYLOAD_ID, |
99 |
|
|
EXCHANGE_SCRIPT_AUTH, |
100 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
101 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, /* Responder -> initiator. */ |
102 |
|
|
ISAKMP_PAYLOAD_ID, |
103 |
|
|
EXCHANGE_SCRIPT_AUTH, |
104 |
|
|
EXCHANGE_SCRIPT_END |
105 |
|
|
}; |
106 |
|
|
|
107 |
|
|
int16_t script_identity_protection[] = { |
108 |
|
|
ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */ |
109 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
110 |
|
|
ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */ |
111 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
112 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, /* Initiator -> responder. */ |
113 |
|
|
ISAKMP_PAYLOAD_NONCE, |
114 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
115 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, /* Responder -> initiator. */ |
116 |
|
|
ISAKMP_PAYLOAD_NONCE, |
117 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
118 |
|
|
ISAKMP_PAYLOAD_ID, /* Initiator -> responder. */ |
119 |
|
|
EXCHANGE_SCRIPT_AUTH, |
120 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
121 |
|
|
ISAKMP_PAYLOAD_ID, /* Responder -> initiator. */ |
122 |
|
|
EXCHANGE_SCRIPT_AUTH, |
123 |
|
|
EXCHANGE_SCRIPT_END |
124 |
|
|
}; |
125 |
|
|
|
126 |
|
|
int16_t script_authentication_only[] = { |
127 |
|
|
ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */ |
128 |
|
|
ISAKMP_PAYLOAD_NONCE, |
129 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
130 |
|
|
ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */ |
131 |
|
|
ISAKMP_PAYLOAD_NONCE, |
132 |
|
|
ISAKMP_PAYLOAD_ID, |
133 |
|
|
EXCHANGE_SCRIPT_AUTH, |
134 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
135 |
|
|
ISAKMP_PAYLOAD_ID, /* Initiator -> responder. */ |
136 |
|
|
EXCHANGE_SCRIPT_AUTH, |
137 |
|
|
EXCHANGE_SCRIPT_END |
138 |
|
|
}; |
139 |
|
|
|
140 |
|
|
int16_t script_aggressive[] = { |
141 |
|
|
ISAKMP_PAYLOAD_SA, /* Initiator -> responder. */ |
142 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, |
143 |
|
|
ISAKMP_PAYLOAD_NONCE, |
144 |
|
|
ISAKMP_PAYLOAD_ID, |
145 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
146 |
|
|
ISAKMP_PAYLOAD_SA, /* Responder -> initiator. */ |
147 |
|
|
ISAKMP_PAYLOAD_KEY_EXCH, |
148 |
|
|
ISAKMP_PAYLOAD_NONCE, |
149 |
|
|
ISAKMP_PAYLOAD_ID, |
150 |
|
|
EXCHANGE_SCRIPT_AUTH, |
151 |
|
|
EXCHANGE_SCRIPT_SWITCH, |
152 |
|
|
EXCHANGE_SCRIPT_AUTH, /* Initiator -> responder. */ |
153 |
|
|
EXCHANGE_SCRIPT_END |
154 |
|
|
}; |
155 |
|
|
|
156 |
|
|
int16_t script_informational[] = { |
157 |
|
|
EXCHANGE_SCRIPT_INFO, /* Initiator -> responder. */ |
158 |
|
|
EXCHANGE_SCRIPT_END |
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_BASE: |
170 |
|
|
return script_base; |
171 |
|
|
case ISAKMP_EXCH_ID_PROT: |
172 |
|
|
return script_identity_protection; |
173 |
|
|
case ISAKMP_EXCH_AUTH_ONLY: |
174 |
|
|
return script_authentication_only; |
175 |
|
|
case ISAKMP_EXCH_AGGRESSIVE: |
176 |
|
|
return script_aggressive; |
177 |
|
|
case ISAKMP_EXCH_INFO: |
178 |
|
|
return script_informational; |
179 |
|
|
case ISAKMP_EXCH_TRANSACTION: |
180 |
|
|
return script_transaction; |
181 |
|
|
default: |
182 |
|
|
if (exchange->type >= ISAKMP_EXCH_DOI_MIN) |
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 && *pc != EXCHANGE_SCRIPT_SWITCH) { |
200 |
|
|
LOG_DBG((LOG_EXCHANGE, 90, |
201 |
|
|
"exchange_validate: checking for required %s", |
202 |
|
|
*pc >= ISAKMP_PAYLOAD_NONE |
203 |
|
|
? constant_name(isakmp_payload_cst, *pc) |
204 |
|
|
: 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 && |
209 |
|
|
!payload_first(msg, ISAKMP_PAYLOAD_HASH) && |
210 |
|
|
!payload_first(msg, ISAKMP_PAYLOAD_SIG)) || |
211 |
|
|
(*pc == EXCHANGE_SCRIPT_INFO && |
212 |
|
|
((!payload_first(msg, ISAKMP_PAYLOAD_NOTIFY) && |
213 |
|
|
!payload_first(msg, ISAKMP_PAYLOAD_DELETE)) || |
214 |
|
|
(payload_first(msg, ISAKMP_PAYLOAD_DELETE) && |
215 |
|
|
!payload_first(msg, ISAKMP_PAYLOAD_HASH))))) { |
216 |
|
|
/* Missing payload. */ |
217 |
|
|
LOG_DBG((LOG_MESSAGE, 70, |
218 |
|
|
"exchange_validate: msg %p requires missing %s", |
219 |
|
|
msg, *pc >= ISAKMP_PAYLOAD_NONE |
220 |
|
|
? constant_name(isakmp_payload_cst, *pc) |
221 |
|
|
: constant_name(exchange_script_cst, *pc))); |
222 |
|
|
return -1; |
223 |
|
|
} |
224 |
|
|
pc++; |
225 |
|
|
} |
226 |
|
|
if (*pc == EXCHANGE_SCRIPT_END) |
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_SA; i < ISAKMP_PAYLOAD_MAX; i++) { |
243 |
|
|
if (i == ISAKMP_PAYLOAD_PROPOSAL || |
244 |
|
|
i == ISAKMP_PAYLOAD_TRANSFORM) |
245 |
|
|
continue; |
246 |
|
|
TAILQ_FOREACH(p, &msg->payload[i], link) { |
247 |
|
|
if (p->flags & PL_MARK) |
248 |
|
|
continue; |
249 |
|
|
if (!doi->handle_leftover_payload || |
250 |
|
|
doi->handle_leftover_payload(msg, i, p)) |
251 |
|
|
LOG_DBG((LOG_EXCHANGE, 10, |
252 |
|
|
"exchange_handle_leftover_payloads: " |
253 |
|
|
"unexpected payload %s", |
254 |
|
|
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_LAST; |
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_PROT || |
336 |
|
|
exchange->type == ISAKMP_EXCH_AGGRESSIVE) && |
337 |
|
|
exchange->phase == 1 && exchange->step == 1) |
338 |
|
|
msg->flags |= MSG_DONTRETRANSMIT; |
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_ENCRYPT) |
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_MALFORMED, 0, 1, 1); |
399 |
|
|
return; |
400 |
|
|
} |
401 |
|
|
} |
402 |
|
|
|
403 |
|
|
LOG_DBG((LOG_EXCHANGE, 40, |
404 |
|
|
"exchange_run: exchange %p finished step %d, advancing...", |
405 |
|
|
exchange, exchange->step)); |
406 |
|
|
exchange->step++; |
407 |
|
|
while (*exchange->exch_pc != EXCHANGE_SCRIPT_SWITCH && |
408 |
|
|
*exchange->exch_pc != EXCHANGE_SCRIPT_END) |
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_BITS) - 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]); |
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; |
436 |
|
|
exchange = LIST_NEXT(exchange, link)) |
437 |
|
|
if (memcmp(exchange->cookies, cookie, |
438 |
|
|
ISAKMP_HDR_ICOOKIE_LEN) == 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; |
457 |
|
|
exchange = LIST_NEXT(exchange, link)) { |
458 |
|
|
LOG_DBG((LOG_EXCHANGE, 90, |
459 |
|
|
"exchange_lookup_by_name: %s == %s && %d == %d?", |
460 |
|
|
name, exchange->name ? exchange->name : |
461 |
|
|
"<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_LAST) == 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; |
491 |
|
|
exchange = LIST_NEXT(exchange, link)) { |
492 |
|
|
LOG_DBG((LOG_EXCHANGE, 90, |
493 |
|
|
"exchange_lookup_active: %s == %s && %d == %d?", |
494 |
|
|
name, exchange->name ? exchange->name : |
495 |
|
|
"<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, |
503 |
|
|
"exchange_lookup_active: avoided " |
504 |
|
|
"early (pre-step 1) exchange %p", |
505 |
|
|
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; 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_LEN; 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); |
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; i += 2) { |
555 |
|
|
cp = msg + ISAKMP_HDR_COOKIES_OFF + 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_LEN; i += 2) { |
561 |
|
|
cp = msg + ISAKMP_HDR_MESSAGE_ID_OFF + 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]); |
567 |
|
|
exchange && (memcmp(msg + ISAKMP_HDR_COOKIES_OFF, |
568 |
|
|
exchange->cookies, ISAKMP_HDR_COOKIES_LEN) != 0 || |
569 |
|
|
(phase2 && memcmp(msg + ISAKMP_HDR_MESSAGE_ID_OFF, |
570 |
|
|
exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN) != 0) || |
571 |
|
|
(!phase2 && !zero_test(msg + ISAKMP_HDR_MESSAGE_ID_OFF, |
572 |
|
|
ISAKMP_HDR_MESSAGE_ID_LEN))); |
573 |
|
|
exchange = LIST_NEXT(exchange, link)) |
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 timeval 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); |
607 |
|
|
bzero(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); |
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); |
614 |
|
|
TAILQ_INIT(&exchange->aca_list); |
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 |
|
|
gettimeofday(&expiration, 0); |
627 |
|
|
delta = conf_get_num("General", "Exchange-max-time", |
628 |
|
|
EXCHANGE_MAX_TIME); |
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_TRANSACTION, 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; |
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_IPSEC; |
737 |
|
|
else if (strcasecmp(str, "ISAKMP") == 0) |
738 |
|
|
doi = ISAKMP_DOI_ISAKMP; |
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; |
777 |
|
|
|
778 |
|
|
if (name && (flags = conf_get_list(name, "Flags")) != NULL) { |
779 |
|
|
for (flag = TAILQ_FIRST(&flags->fields); flag; |
780 |
|
|
flag = TAILQ_NEXT(flag, link)) |
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_LEN); |
809 |
|
|
exchange_enter(exchange); |
810 |
|
|
exchange_dump("exchange_establish_p1", exchange); |
811 |
|
|
|
812 |
|
|
msg = message_alloc(t, 0, ISAKMP_HDR_SZ); |
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_INFO && |
822 |
|
|
exchange->type != ISAKMP_EXCH_TRANSACTION) { |
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); |
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_STAYALIVE; |
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_ISAKMP; |
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_IPSEC; |
875 |
|
|
else if (strcasecmp(str, "ISAKMP") == 0) |
876 |
|
|
doi = ISAKMP_DOI_ISAKMP; |
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); |
919 |
|
|
arc4random_buf(exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN); |
920 |
|
|
exchange->flags |= EXCHANGE_FLAG_ENCRYPT; |
921 |
|
|
if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) |
922 |
|
|
exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; |
923 |
|
|
if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE) |
924 |
|
|
exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; |
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_INFO && |
933 |
|
|
exchange->type != ISAKMP_EXCH_TRANSACTION) { |
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_SZ); |
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); |
975 |
|
|
if (type != ISAKMP_EXCH_INFO) { |
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, |
994 |
|
|
"exchange_establish: %s exchange already " |
995 |
|
|
"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; |
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_IPSEC; |
1015 |
|
|
str = "IPSEC"; |
1016 |
|
|
} |
1017 |
|
|
else if (strcasecmp(str, "ISAKMP") == 0) |
1018 |
|
|
want_doi = ISAKMP_DOI_ISAKMP; |
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)) { |
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))); |
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) { |
1063 |
|
|
for (flag = TAILQ_FIRST(&flags->fields); flag; |
1064 |
|
|
flag = TAILQ_NEXT(flag, link)) |
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_LEN, ISAKMP_HDR_RCOOKIE_LEN); |
1092 |
|
|
GET_ISAKMP_HDR_ICOOKIE(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)); |
1106 |
|
|
if (!exchange) |
1107 |
|
|
return 0; |
1108 |
|
|
GET_ISAKMP_HDR_ICOOKIE(buf, exchange->cookies); |
1109 |
|
|
GET_ISAKMP_HDR_RCOOKIE(buf, |
1110 |
|
|
exchange->cookies + ISAKMP_HDR_ICOOKIE_LEN); |
1111 |
|
|
GET_ISAKMP_HDR_MESSAGE_ID(buf, exchange->message_id); |
1112 |
|
|
if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE)) |
1113 |
|
|
exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; |
1114 |
|
|
if (msg->isakmp_sa && (msg->isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE)) |
1115 |
|
|
exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; |
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_SIZE]; |
1128 |
|
|
/* Don't risk overflowing the final log buffer. */ |
1129 |
|
|
size_t bufsize_max = LOG_SIZE - strlen(header) - 32; |
1130 |
|
|
|
1131 |
|
|
LOG_DBG((class, level, |
1132 |
|
|
"%s: %p %s %s policy %s phase %d doi %d exchange %d step %d", |
1133 |
|
|
header, exchange, exchange->name ? exchange->name : "<unnamed>", |
1134 |
|
|
exchange->policy ? exchange->policy : "<no policy>", |
1135 |
|
|
exchange->initiator ? "initiator" : "responder", exchange->phase, |
1136 |
|
|
exchange->doi->id, exchange->type, exchange->step)); |
1137 |
|
|
LOG_DBG((class, level, "%s: icookie %08x%08x rcookie %08x%08x", header, |
1138 |
|
|
decode_32(exchange->cookies), decode_32(exchange->cookies + 4), |
1139 |
|
|
decode_32(exchange->cookies + 8), |
1140 |
|
|
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); |
1146 |
|
|
sa && strlen(buf) < bufsize_max; sa = TAILQ_NEXT(sa, 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, |
1155 |
|
|
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; |
1172 |
|
|
exchange = LIST_NEXT(exchange, link)) |
1173 |
|
|
exchange_dump_real("exchange_report", exchange, |
1174 |
|
|
LOG_REPORT, 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", |
1190 |
|
|
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_PUBLIC, |
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); |
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); sa; sa = next_sa) { |
1240 |
|
|
next_sa = TAILQ_NEXT(sa, 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); |
1269 |
|
|
exchange->linked = 0; |
1270 |
|
|
GET_ISAKMP_HDR_RCOOKIE(msg->iov[0].iov_base, exchange->cookies + |
1271 |
|
|
ISAKMP_HDR_ICOOKIE_LEN); |
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_READY) || |
1283 |
|
|
(sa->flags & SA_FLAG_REPLACED)) |
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, |
1298 |
|
|
"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); sa; |
1346 |
|
|
sa = TAILQ_NEXT(sa, 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_COMMITTED) { |
1351 |
|
|
for (proto = TAILQ_FIRST(&sa->protos); proto; |
1352 |
|
|
proto = TAILQ_NEXT(proto, link)) |
1353 |
|
|
for (i = 0; i < 2; i++) |
1354 |
|
|
message_send_notification(exchange->last_received, |
1355 |
|
|
msg->isakmp_sa, |
1356 |
|
|
ISAKMP_NOTIFY_STATUS_CONNECTED, |
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_READY; |
1369 |
|
|
if (exchange->name) { |
1370 |
|
|
attrs = conf_get_list(exchange->name, "Flags"); |
1371 |
|
|
if (attrs) { |
1372 |
|
|
for (attr = TAILQ_FIRST(&attrs->fields); attr; |
1373 |
|
|
attr = TAILQ_NEXT(attr, link)) |
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_STAYALIVE; |
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_STAYALIVE; |
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_ENABLE) |
1443 |
|
|
msg->isakmp_sa->flags |= SA_FLAG_NAT_T_ENABLE; |
1444 |
|
|
if (exchange->flags & EXCHANGE_FLAG_NAT_T_KEEPALIVE) |
1445 |
|
|
msg->isakmp_sa->flags |= SA_FLAG_NAT_T_KEEPALIVE; |
1446 |
|
|
|
1447 |
|
|
LOG_DBG((LOG_EXCHANGE, 10, |
1448 |
|
|
"exchange_finalize: phase 1 done: %s, %s", id_doi, |
1449 |
|
|
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)) { |
1467 |
|
|
sa = TAILQ_FIRST(&exchange->sa_list); |
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); |
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_PEER)) |
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, |
1509 |
|
|
"exchange_nonce: invalid nonce length %lu", |
1510 |
|
|
(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)); |
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_SZ + nonce_sz); |
1539 |
|
|
if (!buf) { |
1540 |
|
|
log_error("exchange_gen_nonce: malloc (%lu) failed", |
1541 |
|
|
ISAKMP_NONCE_SZ + (unsigned long)nonce_sz); |
1542 |
|
|
return -1; |
1543 |
|
|
} |
1544 |
|
|
arc4random_buf(buf + ISAKMP_NONCE_DATA_OFF, nonce_sz); |
1545 |
|
|
if (message_add_payload(msg, ISAKMP_PAYLOAD_NONCE, buf, |
1546 |
|
|
ISAKMP_NONCE_SZ + nonce_sz, 1)) { |
1547 |
|
|
free(buf); |
1548 |
|
|
return -1; |
1549 |
|
|
} |
1550 |
|
|
return exchange_nonce(exchange, 0, nonce_sz, |
1551 |
|
|
buf + ISAKMP_NONCE_DATA_OFF); |
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_NONCE); |
1562 |
|
|
noncep->flags |= PL_MARK; |
1563 |
|
|
return exchange_nonce(exchange, 1, GET_ISAKMP_GEN_LENGTH(noncep->p) - |
1564 |
|
|
ISAKMP_NONCE_DATA_OFF, noncep->p + ISAKMP_NONCE_DATA_OFF); |
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) { |
1576 |
|
|
cp->flags |= PL_MARK; |
1577 |
|
|
aca = certreq_decode(GET_ISAKMP_CERTREQ_TYPE(cp->p), cp->p + |
1578 |
|
|
ISAKMP_CERTREQ_AUTHORITY_OFF, GET_ISAKMP_GEN_LENGTH(cp->p) |
1579 |
|
|
- ISAKMP_CERTREQ_AUTHORITY_OFF); |
1580 |
|
|
if (aca) |
1581 |
|
|
TAILQ_INSERT_TAIL(&exchange->aca_list, aca, link); |
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); aca; |
1594 |
|
|
aca = TAILQ_FIRST(&exchange->aca_list)) { |
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); |
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); aca; |
1623 |
|
|
aca = TAILQ_NEXT(aca, link)) { |
1624 |
|
|
|
1625 |
|
|
/* But only do this if we have at least one CA */ |
1626 |
|
|
if (aca->handler != NULL && aca->handler->ca_count() == 0) { |
1627 |
|
|
LOG_DBG((LOG_EXCHANGE, 10, |
1628 |
|
|
"exchange_add_certreqs: no CA, so not " |
1629 |
|
|
"sending a CERTREQ")); |
1630 |
|
|
continue; |
1631 |
|
|
} |
1632 |
|
|
|
1633 |
|
|
if (aca->raw_ca_len) { |
1634 |
|
|
buf = malloc(ISAKMP_CERTREQ_SZ + aca->raw_ca_len); |
1635 |
|
|
if (buf == NULL) { |
1636 |
|
|
log_error("exchange_add_certreqs: " |
1637 |
|
|
"malloc (%lu) failed", |
1638 |
|
|
ISAKMP_CERTREQ_SZ + |
1639 |
|
|
(unsigned long)aca->raw_ca_len); |
1640 |
|
|
return -1; |
1641 |
|
|
} |
1642 |
|
|
|
1643 |
|
|
buf[ISAKMP_CERTREQ_TYPE_OFF] = aca->id; |
1644 |
|
|
memcpy(buf + ISAKMP_CERTREQ_AUTHORITY_OFF, |
1645 |
|
|
aca->raw_ca, aca->raw_ca_len); |
1646 |
|
|
|
1647 |
|
|
if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT_REQ, |
1648 |
|
|
buf, ISAKMP_CERTREQ_SZ + 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 ? exchange->id_r_len : exchange->id_i_len; |
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); aca; |
1683 |
|
|
aca = TAILQ_NEXT(aca, link)) { |
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_SZ + certlen); |
1693 |
|
|
if (!new_cert) { |
1694 |
|
|
log_error("exchange_add_certs: realloc (%p, %d) " |
1695 |
|
|
"failed", cert, ISAKMP_CERT_SZ + certlen); |
1696 |
|
|
free(cert); |
1697 |
|
|
return -1; |
1698 |
|
|
} |
1699 |
|
|
cert = new_cert; |
1700 |
|
|
memmove(cert + ISAKMP_CERT_DATA_OFF, cert, certlen); |
1701 |
|
|
SET_ISAKMP_CERT_ENCODING(cert, aca->id); |
1702 |
|
|
if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT, cert, |
1703 |
|
|
ISAKMP_CERT_SZ + 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; |
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: " |
1728 |
|
|
"finalizing exchange %p with arg %p (%s) & fail = %d", |
1729 |
|
|
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:" |
1754 |
|
|
" returning in passive mode for exchange %s phase %d", |
1755 |
|
|
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, |
1768 |
|
|
"exchange_establish: %s exchange already exists as %p", |
1769 |
|
|
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; |
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 |
|
|
} |