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