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