5b200f6079c5a777754d5c48d78a195ee0c3728c
[strongswan.git] / src / charon / sa / transactions / ike_sa_init.c
1 /**
2 * @file ike_sa_init.c
3 *
4 * @brief Implementation of ike_sa_init_t transaction.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include "ike_sa_init.h"
26
27 #include <string.h>
28
29 #include <daemon.h>
30 #include <crypto/diffie_hellman.h>
31 #include <crypto/hashers/hasher.h>
32 #include <encoding/payloads/sa_payload.h>
33 #include <encoding/payloads/ke_payload.h>
34 #include <encoding/payloads/nonce_payload.h>
35 #include <sa/transactions/ike_auth.h>
36 #include <queues/jobs/delete_half_open_ike_sa_job.h>
37 #include <queues/jobs/delete_established_ike_sa_job.h>
38 #include <queues/jobs/rekey_ike_sa_job.h>
39
40
41 typedef struct private_ike_sa_init_t private_ike_sa_init_t;
42
43 /**
44 * Private members of a ike_sa_init_t object..
45 */
46 struct private_ike_sa_init_t {
47
48 /**
49 * Public methods and transaction_t interface.
50 */
51 ike_sa_init_t public;
52
53 /**
54 * Assigned IKE_SA.
55 */
56 ike_sa_t *ike_sa;
57
58 /**
59 * Message sent by our peer, if already generated
60 */
61 message_t *message;
62
63 /**
64 * Message ID this transaction uses
65 */
66 u_int32_t message_id;
67
68 /**
69 * Times we did send the request
70 */
71 u_int32_t requested;
72
73 /**
74 * Next transaction followed to this one. May be IKE_AUTH,
75 * or a IKE_SA_INIT retry
76 */
77 transaction_t **next;
78
79 /**
80 * Diffie hellman object used to generate public DH value.
81 */
82 diffie_hellman_t *diffie_hellman;
83
84 /**
85 * initiator chosen nonce
86 */
87 chunk_t nonce_i;
88
89 /**
90 * responder chosen nonce
91 */
92 chunk_t nonce_r;
93
94 /**
95 * connection definition used for initiation
96 */
97 connection_t *connection;
98
99 /**
100 * policy definition forwarded to ike_auth transaction
101 */
102 policy_t *policy;
103
104 /**
105 * Negotiated proposal used for IKE_SA
106 */
107 proposal_t *proposal;
108
109 /**
110 * Randomizer to generate nonces
111 */
112 randomizer_t *randomizer;
113
114 /**
115 * Hasher used to build NAT detection hashes
116 */
117 hasher_t *nat_hasher;
118
119 /**
120 * Precomputed NAT hash for source address
121 */
122 chunk_t natd_src_hash;
123
124 /**
125 * Precomputed NAT hash for destination address
126 */
127 chunk_t natd_dst_hash;
128
129 /**
130 * Did we process any NAT detection notifys for a source address?
131 */
132 bool natd_src_seen;
133
134 /**
135 * Did we process any NAT detection notifys for a destination address?
136 */
137 bool natd_dst_seen;
138
139 /**
140 * Have we found a matching source address NAT hash?
141 */
142 bool natd_src_matched;
143
144 /**
145 * Have we found a matching destination address NAT hash?
146 */
147 bool natd_dst_matched;
148
149 /**
150 * Assigned logger.
151 */
152 logger_t *logger;
153 };
154
155 /**
156 * Implementation of ike_sa_init_t.use_dh_group.
157 */
158 static bool use_dh_group(private_ike_sa_init_t *this, diffie_hellman_group_t dh_group)
159 {
160 if (this->connection->check_dh_group(this->connection, dh_group))
161 {
162 this->diffie_hellman = diffie_hellman_create(dh_group);
163 if (this->diffie_hellman)
164 {
165 return TRUE;
166 }
167 }
168 return FALSE;
169 }
170
171 /**
172 * Implementation of ike_sa_init_t.set_config.
173 */
174 static void set_config(private_ike_sa_init_t *this,
175 connection_t *connection, policy_t *policy)
176 {
177 this->connection = connection;
178 this->policy = policy;
179 }
180
181 /**
182 * Implementation of transaction_t.get_message_id.
183 */
184 static u_int32_t get_message_id(private_ike_sa_init_t *this)
185 {
186 return this->message_id;
187 }
188
189 /**
190 * Implementation of transaction_t.requested.
191 */
192 static u_int32_t requested(private_ike_sa_init_t *this)
193 {
194 return this->requested++;
195 }
196
197 /**
198 * Build NAT detection hash for a host
199 */
200 static chunk_t generate_natd_hash(private_ike_sa_init_t *this,
201 ike_sa_id_t * ike_sa_id, host_t *host)
202 {
203 chunk_t natd_chunk, spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk;
204 chunk_t natd_hash;
205 u_int64_t spi_i, spi_r;
206 u_int16_t port;
207
208 /* prepare all requred chunks */
209 spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
210 spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
211 spi_i_chunk.ptr = (void*)&spi_i;
212 spi_i_chunk.len = sizeof(spi_i);
213 spi_r_chunk.ptr = (void*)&spi_r;
214 spi_r_chunk.len = sizeof(spi_r);
215 port = host->get_port(host);
216 port_chunk.ptr = (void*)&port;
217 port_chunk.len = sizeof(port);
218 addr_chunk = host->get_address(host);
219
220 /* natd_hash = SHA1( spi_i | spi_r | address | port ) */
221 natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk);
222 this->nat_hasher->allocate_hash(this->nat_hasher, natd_chunk, &natd_hash);
223 this->logger->log_chunk(this->logger, RAW, "natd_chunk", natd_chunk);
224 this->logger->log_chunk(this->logger, RAW, "natd_hash", natd_hash);
225
226 chunk_free(&natd_chunk);
227 return natd_hash;
228 }
229
230 /**
231 * Build a NAT detection notify payload.
232 */
233 static notify_payload_t *build_natd_payload(private_ike_sa_init_t *this,
234 notify_type_t type, host_t *host)
235 {
236 chunk_t hash;
237 notify_payload_t *notify;
238 ike_sa_id_t *ike_sa_id;
239
240 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
241 notify = notify_payload_create();
242 notify->set_notify_type(notify, type);
243 hash = generate_natd_hash(this, ike_sa_id, host);
244 notify->set_notification_data(notify, hash);
245 chunk_free(&hash);
246
247 return notify;
248 }
249
250 /**
251 * destroy a list of proposals
252 */
253 static void destroy_proposal_list(linked_list_t *list)
254 {
255 proposal_t *proposal;
256
257 while (list->remove_last(list, (void**)&proposal) == SUCCESS)
258 {
259 proposal->destroy(proposal);
260 }
261 list->destroy(list);
262 }
263
264 /**
265 * Implementation of transaction_t.get_request.
266 */
267 static status_t get_request(private_ike_sa_init_t *this, message_t **result)
268 {
269 message_t *request;
270 host_t *me, *other;
271 identification_t *my_id, *other_id;
272
273 /* check if we already have built a message (retransmission) */
274 if (this->message)
275 {
276 *result = this->message;
277 return SUCCESS;
278 }
279
280 me = this->connection->get_my_host(this->connection);
281 other = this->connection->get_other_host(this->connection);
282
283 /* we already set up the IDs. Mine is already fully qualified, other
284 * will be updated in the ike_auth transaction */
285 my_id = this->policy->get_my_id(this->policy);
286 other_id = this->policy->get_other_id(this->policy);
287 this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
288 this->ike_sa->set_other_id(this->ike_sa, other_id->clone(other_id));
289
290 /* build the request */
291 request = message_create();
292 request->set_source(request, me->clone(me));
293 request->set_destination(request, other->clone(other));
294 request->set_exchange_type(request, IKE_SA_INIT);
295 request->set_request(request, TRUE);
296 request->set_message_id(request, this->message_id);
297 request->set_ike_sa_id(request, this->ike_sa->get_id(this->ike_sa));
298 /* apply for caller */
299 *result = request;
300 /* store for retransmission */
301 this->message = request;
302
303 /* if the DH group is set via use_dh_group(), we already have a DH object */
304 if (!this->diffie_hellman)
305 {
306 diffie_hellman_group_t dh_group;
307
308 dh_group = this->connection->get_dh_group(this->connection);
309 this->diffie_hellman = diffie_hellman_create(dh_group);
310 if (this->diffie_hellman == NULL)
311 {
312 this->logger->log(this->logger, AUDIT,
313 "DH group %s (%d) not supported, aborting",
314 mapping_find(diffie_hellman_group_m, dh_group), dh_group);
315 return DESTROY_ME;
316 }
317 }
318
319 { /* build the SA payload from proposals */
320 sa_payload_t *sa_payload;
321 linked_list_t *proposal_list;
322
323 proposal_list = this->connection->get_proposals(this->connection);
324 sa_payload = sa_payload_create_from_proposal_list(proposal_list);
325 destroy_proposal_list(proposal_list);
326
327 request->add_payload(request, (payload_t*)sa_payload);
328 }
329
330 { /* build the KE payload from the DH object */
331 ke_payload_t *ke_payload;
332
333 ke_payload = ke_payload_create_from_diffie_hellman(this->diffie_hellman);
334
335 request->add_payload(request, (payload_t*)ke_payload);
336 }
337
338 { /* build the NONCE payload for us (initiator) */
339 nonce_payload_t *nonce_payload;
340
341 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
342 NONCE_SIZE, &this->nonce_i) != SUCCESS)
343 {
344 return DESTROY_ME;
345 }
346 nonce_payload = nonce_payload_create();
347 nonce_payload->set_nonce(nonce_payload, this->nonce_i);
348
349 request->add_payload(request, (payload_t*)nonce_payload);
350 }
351
352 { /* build NAT_DETECTION notifys */
353 notify_payload_t *notify;
354 linked_list_t *list;
355 host_t *host;
356
357 /* N(NAT_DETECTION_SOURCE_IP)+ */
358 list = charon->socket->create_local_address_list(charon->socket);
359 while (list->remove_first(list, (void**)&host) == SUCCESS)
360 {
361 /* TODO: should we only include NAT payloads for addresses
362 * of used address family? */
363 notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
364 host->destroy(host);
365 request->add_payload(request, (payload_t*)notify);
366 }
367 list->destroy(list);
368
369 /* N(NAT_DETECTION_DESTINATION_IP) */
370 notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other);
371 request->add_payload(request, (payload_t*)notify);
372 }
373
374 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
375 return SUCCESS;
376 }
377
378 /**
379 * Handle all kind of notifys
380 */
381 static status_t process_notifys(private_ike_sa_init_t *this, notify_payload_t *notify_payload)
382 {
383 chunk_t notification_data;
384 notify_type_t notify_type = notify_payload->get_notify_type(notify_payload);
385
386 this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
387 mapping_find(notify_type_m, notify_type));
388
389 switch (notify_type)
390 {
391 case NO_PROPOSAL_CHOSEN:
392 {
393 this->logger->log(this->logger, AUDIT,
394 "received a NO_PROPOSAL_CHOSEN notify, deleting IKE_SA");
395 return DESTROY_ME;
396 }
397 case INVALID_MAJOR_VERSION:
398 {
399 this->logger->log(this->logger, AUDIT,
400 "received a INVALID_MAJOR_VERSION notify, deleting IKE_SA");
401 return DESTROY_ME;
402 }
403 case INVALID_KE_PAYLOAD:
404 {
405 chunk_t notify_data;
406 diffie_hellman_group_t dh_group, old_dh_group;
407 ike_sa_init_t *retry;
408
409 old_dh_group = this->connection->get_dh_group(this->connection);
410 notify_data = notify_payload->get_notification_data(notify_payload);
411 dh_group = ntohs(*((u_int16_t*)notify_data.ptr));
412
413 this->logger->log(this->logger, AUDIT,
414 "peer didn't accept DH group %s, it requested %s",
415 mapping_find(diffie_hellman_group_m, old_dh_group),
416 mapping_find(diffie_hellman_group_m, dh_group));
417 if (!this->connection->check_dh_group(this->connection, dh_group))
418 {
419 this->logger->log(this->logger, AUDIT,
420 "requested DH group not acceptable, aborting");
421 return DESTROY_ME;
422 }
423 retry = ike_sa_init_create(this->ike_sa);
424 retry->set_config(retry, this->connection, this->policy);
425 this->connection = NULL;
426 this->policy = NULL;
427 retry->use_dh_group(retry, dh_group);
428 *this->next = (transaction_t*)retry;
429 return FAILED;
430 }
431 case NAT_DETECTION_DESTINATION_IP:
432 {
433 this->natd_dst_seen = TRUE;
434 if (this->natd_dst_matched)
435 {
436 return SUCCESS;
437 }
438 notification_data = notify_payload->get_notification_data(notify_payload);
439 if (chunk_equals(notification_data, this->natd_dst_hash))
440 {
441 this->natd_dst_matched = TRUE;
442 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D dst hash match");
443 }
444 else
445 {
446 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D dst hash mismatch");
447 }
448 return SUCCESS;
449 }
450 case NAT_DETECTION_SOURCE_IP:
451 {
452 this->natd_src_seen = TRUE;;
453 if (this->natd_src_matched)
454 {
455 return SUCCESS;
456 }
457 notification_data = notify_payload->get_notification_data(notify_payload);
458 if (chunk_equals(notification_data, this->natd_src_hash))
459 {
460 this->natd_src_matched = TRUE;
461 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D src hash match");
462 }
463 else
464 {
465 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D src hash mismatch");
466 }
467 return SUCCESS;
468 }
469 default:
470 {
471 if (notify_type < 16383)
472 {
473 this->logger->log(this->logger, AUDIT,
474 "received %s notify error (%d), deleting IKE_SA",
475 mapping_find(notify_type_m, notify_type),
476 notify_type);
477 return DESTROY_ME;
478 }
479 else
480 {
481 this->logger->log(this->logger, CONTROL,
482 "received %s notify (%d), ignored",
483 mapping_find(notify_type_m, notify_type),
484 notify_type);
485 return SUCCESS;
486 }
487 }
488 }
489 }
490
491 /**
492 * Implementation of transaction_t.get_response.
493 */
494 static status_t get_response(private_ike_sa_init_t *this,
495 message_t *request, message_t **result,
496 transaction_t **next)
497 {
498 host_t *me, *other;
499 message_t *response;
500 status_t status;
501 iterator_t *payloads;
502 sa_payload_t *sa_request = NULL;
503 ke_payload_t *ke_request = NULL;
504 nonce_payload_t *nonce_request = NULL;
505 ike_sa_id_t *ike_sa_id;
506 u_int32_t timeout;
507
508 /* check if we already have built a response (retransmission) */
509 if (this->message)
510 {
511 *result = this->message;
512 return SUCCESS;
513 }
514
515 me = request->get_destination(request);
516 other = request->get_source(request);
517 this->message_id = request->get_message_id(request);
518
519 /* set up response */
520 response = message_create();
521 response->set_source(response, me->clone(me));
522 response->set_destination(response, other->clone(other));
523 response->set_exchange_type(response, IKE_SA_INIT);
524 response->set_request(response, FALSE);
525 response->set_message_id(response, this->message_id);
526 response->set_ike_sa_id(response, this->ike_sa->get_id(this->ike_sa));
527 this->message = response;
528 *result = response;
529
530 /* check message type */
531 if (request->get_exchange_type(request) != IKE_SA_INIT)
532 {
533 this->logger->log(this->logger, ERROR,
534 "IKE_SA_INIT request of invalid type, deleting IKE_SA");
535 return DESTROY_ME;
536 }
537
538 /* this is the first message to process, find a connection for IKE_SA */
539 this->connection = charon->connections->get_connection_by_hosts(
540 charon->connections, me, other);
541 if (this->connection == NULL)
542 {
543 notify_payload_t *notify = notify_payload_create();
544 notify->set_notify_type(notify, NO_PROPOSAL_CHOSEN);
545 response->add_payload(response, (payload_t*)notify);
546
547 this->logger->log(this->logger, AUDIT,
548 "no connection for hosts %s...%s found, deleting IKE_SA",
549 me->get_string(me), other->get_string(other));
550 return DESTROY_ME;
551 }
552 this->ike_sa->set_name(this->ike_sa,
553 this->connection->get_name(this->connection));
554
555 /* Precompute NAT-D hashes for incoming NAT notify comparison */
556 ike_sa_id = request->get_ike_sa_id(request);
557 this->natd_dst_hash = generate_natd_hash(this, ike_sa_id, me);
558 this->natd_src_hash = generate_natd_hash(this, ike_sa_id, other);
559
560 /* Iterate over all payloads. */
561 payloads = request->get_payload_iterator(request);
562 while (payloads->has_next(payloads))
563 {
564 payload_t *payload;
565 payloads->current(payloads, (void**)&payload);
566 switch (payload->get_type(payload))
567 {
568 case SECURITY_ASSOCIATION:
569 sa_request = (sa_payload_t*)payload;
570 break;
571 case KEY_EXCHANGE:
572 ke_request = (ke_payload_t*)payload;
573 break;
574 case NONCE:
575 nonce_request = (nonce_payload_t*)payload;
576 break;
577 case NOTIFY:
578 {
579 status = process_notifys(this, (notify_payload_t*)payload);
580 if (status == FAILED)
581 {
582 payloads->destroy(payloads);
583 /* we return SUCCESS, returned FAILED means do next transaction */
584 return SUCCESS;
585 }
586 if (status == DESTROY_ME)
587 {
588 payloads->destroy(payloads);
589 return DESTROY_ME;
590 }
591 break;
592 }
593 default:
594 {
595 this->logger->log(this->logger, ERROR|LEVEL1,
596 "ignoring %s payload (%d)",
597 mapping_find(payload_type_m, payload->get_type(payload)),
598 payload->get_type(payload));
599 break;
600 }
601 }
602 }
603 payloads->destroy(payloads);
604
605 /* check if we have all payloads */
606 if (!(sa_request && ke_request && nonce_request))
607 {
608 notify_payload_t *notify = notify_payload_create();
609 notify->set_notify_type(notify, INVALID_SYNTAX);
610 response->add_payload(response, (payload_t*)notify);
611 this->logger->log(this->logger, AUDIT,
612 "request message incomplete, deleting IKE_SA");
613 return DESTROY_ME;
614 }
615
616 { /* process SA payload:
617 * -------------------
618 * - extract proposals
619 * - select our most preferred proposal found in extracted
620 * - if no matches, return NO_PROPOSAL_CHOSEN
621 * - add sa payload with selected proposal
622 */
623 sa_payload_t* sa_response;
624 linked_list_t *proposal_list;
625
626 proposal_list = sa_request->get_proposals(sa_request);
627 this->proposal = this->connection->select_proposal(this->connection, proposal_list);
628 destroy_proposal_list(proposal_list);
629 if (this->proposal == NULL)
630 {
631 notify_payload_t *notify = notify_payload_create();
632 notify->set_notify_type(notify, NO_PROPOSAL_CHOSEN);
633 response->add_payload(response, (payload_t*)notify);
634 this->logger->log(this->logger, AUDIT,
635 "request did not contain any acceptable proposals, deleting IKE_SA");
636 return DESTROY_ME;
637 }
638 sa_response = sa_payload_create_from_proposal(this->proposal);
639 response->add_payload(response, (payload_t *)sa_response);
640 }
641
642 { /* process KE payload:
643 * --------------------
644 * - check if used group match the selected proposal
645 * - if not, stop with INVALID_KE_PAYLOAD
646 * - apply others public value to complete diffie hellman exchange
647 * - add our public value to response
648 */
649 diffie_hellman_group_t used_group;
650 ke_payload_t *ke_response;
651
652 used_group = ke_request->get_dh_group_number(ke_request);
653
654 if (!this->connection->check_dh_group(this->connection, used_group) ||
655 (this->diffie_hellman = diffie_hellman_create(used_group)) == NULL)
656 {
657 u_int16_t notify_group;
658 chunk_t notify_chunk;
659 notify_payload_t *notify;
660 iterator_t *iterator;
661 payload_t *payload;
662
663 notify_group = this->connection->get_dh_group(this->connection);
664 this->logger->log(this->logger, AUDIT,
665 "request used inacceptable DH group %s, sending INVALID_KE_PAYLOAD with %s, deleting IKE_SA",
666 mapping_find(diffie_hellman_group_m, used_group),
667 mapping_find(diffie_hellman_group_m, notify_group));
668
669 /* remove already added payloads */
670 iterator = response->get_payload_iterator(response);
671 while (iterator->has_next(iterator))
672 {
673 iterator->current(iterator, (void**)&payload);
674 iterator->remove(iterator);
675 payload->destroy(payload);
676 }
677 iterator->destroy(iterator);
678
679 notify_group = htons(notify_group);
680 notify_chunk.ptr = (u_int8_t*)&notify_group;
681 notify_chunk.len = sizeof(notify_group);
682 notify = notify_payload_create();
683 notify->set_notify_type(notify, INVALID_KE_PAYLOAD);
684 notify->set_notification_data(notify, notify_chunk);
685 response->add_payload(response, (payload_t*)notify);
686 return DESTROY_ME;
687 }
688 this->diffie_hellman->set_other_public_value(this->diffie_hellman,
689 ke_request->get_key_exchange_data(ke_request));
690
691 /* build response */
692 ke_response = ke_payload_create_from_diffie_hellman(this->diffie_hellman);
693 response->add_payload(response, (payload_t*)ke_response);
694 }
695
696 { /* process nonce payload:
697 * ----------------------
698 * - get nonce from payload
699 * - generate own nonce and add to reply
700 */
701 nonce_payload_t *nonce_response;
702
703 this->nonce_i = nonce_request->get_nonce(nonce_request);
704
705 /* build response nonce */
706 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
707 NONCE_SIZE, &this->nonce_r) != SUCCESS)
708 {
709 notify_payload_t *notify = notify_payload_create();
710 notify->set_notify_type(notify, NO_PROPOSAL_CHOSEN);
711 response->add_payload(response, (payload_t*)notify);
712 this->logger->log(this->logger, AUDIT,
713 "could not get random bytes for nonce, deleting IKE_SA");
714 return DESTROY_ME;
715 }
716 nonce_response = nonce_payload_create();
717 nonce_response->set_nonce(nonce_response, this->nonce_r);
718 response->add_payload(response, (payload_t *)nonce_response);
719 }
720
721 { /* processs NATT stuff:
722 * --------------------
723 * - check if we or other is behind NAT
724 * - enable NATT if so
725 * - build NAT detection notifys for reply
726 */
727 notify_payload_t *notify;
728
729 if ((!this->natd_src_seen && this->natd_dst_seen) ||
730 (this->natd_src_seen && !this->natd_dst_seen))
731 {
732 notify = notify_payload_create();
733 notify->set_notify_type(notify, INVALID_SYNTAX);
734 response->add_payload(response, (payload_t*)notify);
735 this->logger->log(this->logger, AUDIT,
736 "request contained wrong number of NAT-D payloads, deleting IKE_SA");
737 return DESTROY_ME;
738 }
739 if (this->natd_dst_seen && !this->natd_dst_matched)
740 {
741 this->ike_sa->enable_natt(this->ike_sa, TRUE);
742 }
743 if (this->natd_src_seen && !this->natd_src_matched)
744 {
745 this->ike_sa->enable_natt(this->ike_sa, FALSE);
746 }
747 /* build response NAT DETECTION notifys, if remote supports it */
748 if (this->natd_src_seen || this->natd_dst_seen)
749 {
750 /* N(NAT_DETECTION_SOURCE_IP) */
751 notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me);
752 response->add_payload(response, (payload_t*)notify);
753
754 /* N(NAT_DETECTION_DESTINATION_IP) */
755 notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other);
756 response->add_payload(response, (payload_t*)notify);
757 }
758 }
759
760 /* derive all the keys used in the IKE_SA */
761 if (this->ike_sa->derive_keys(this->ike_sa, this->proposal,
762 this->diffie_hellman,
763 this->nonce_i, this->nonce_r,
764 FALSE, NULL, NULL) != SUCCESS)
765 {
766 notify_payload_t *notify = notify_payload_create();
767 notify->set_notify_type(notify, NO_PROPOSAL_CHOSEN);
768 response->add_payload(response, (payload_t*)notify);
769 this->logger->log(this->logger, AUDIT,
770 "transform objects could not be created from selected proposal, deleting IKE_SA");
771 return DESTROY_ME;
772 }
773
774 this->ike_sa->set_lifetimes(this->ike_sa,
775 this->connection->get_soft_lifetime(this->connection),
776 this->connection->get_hard_lifetime(this->connection));
777
778 { /* create ike_auth transaction, which will store informations for us */
779 packet_t *response_packet;
780 chunk_t request_chunk, response_chunk;
781 ike_auth_t *ike_auth;
782
783 /* we normally do not generate the message. But we need the generated message
784 * for authentication in the next state, so we do it here. This is not problematic,
785 * as we don't use a crypter/signer in ike_sa_init... */
786 if (response->generate(response, NULL, NULL, &response_packet) != SUCCESS)
787 {
788 this->logger->log(this->logger, AUDIT,
789 "error in response generation, deleting IKE_SA");
790 return DESTROY_ME;
791 }
792 response_packet->destroy(response_packet);
793 request_chunk = request->get_packet_data(request);
794 response_chunk = response->get_packet_data(response);
795
796 /* create next transaction, for which we except a message */
797 ike_auth = ike_auth_create(this->ike_sa);
798 ike_auth->set_config(ike_auth, this->connection, this->policy);
799 this->connection = NULL;
800 this->policy = NULL;
801 ike_auth->set_nonces(ike_auth,
802 chunk_clone(this->nonce_i),
803 chunk_clone(this->nonce_r));
804 ike_auth->set_init_messages(ike_auth, request_chunk, response_chunk);
805 *next = (transaction_t*)ike_auth;
806 }
807
808 /* everything went fine. Now we set a timeout to destroy half initiated IKE_SAs */
809 timeout = charon->configuration->get_half_open_ike_sa_timeout(charon->configuration);
810 if (timeout)
811 {
812 job_t *job = (job_t*)delete_half_open_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa));
813 charon->event_queue->add_relative(charon->event_queue, job, timeout);
814 }
815 /* set new state */
816 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
817
818 return SUCCESS;
819 }
820
821
822 /**
823 * Implementation of transaction_t.conclude
824 */
825 static status_t conclude(private_ike_sa_init_t *this, message_t *response,
826 transaction_t **next)
827 {
828 u_int64_t responder_spi;
829 ike_sa_id_t *ike_sa_id;
830 iterator_t *payloads;
831 host_t *me, *other;
832 sa_payload_t *sa_payload = NULL;
833 ke_payload_t *ke_payload = NULL;
834 nonce_payload_t *nonce_payload = NULL;
835 status_t status;
836
837 /* check message type */
838 if (response->get_exchange_type(response) != IKE_SA_INIT)
839 {
840 this->logger->log(this->logger, ERROR,
841 "IKE_SA_INIT response of invalid type, deleting IKE_SA");
842 return DESTROY_ME;
843 }
844
845 /* allow setting of next transaction in other functions */
846 this->next = next;
847
848 me = this->connection->get_my_host(this->connection);
849 other = this->connection->get_other_host(this->connection);
850
851 /* check if SPI has been updated, but apply only if all goes ok later */
852 responder_spi = response->get_responder_spi(response);
853 if (responder_spi == 0)
854 {
855 this->logger->log(this->logger, ERROR,
856 "response contained a SPI of zero, deleting IKE_SA");
857 return DESTROY_ME;
858 }
859
860 /* Precompute NAT-D hashes for later comparison */
861 ike_sa_id = response->get_ike_sa_id(response);
862 this->natd_src_hash = generate_natd_hash(this, ike_sa_id, other);
863 this->natd_dst_hash = generate_natd_hash(this, ike_sa_id, me);
864
865 /* Iterate over all payloads to collect them */
866 payloads = response->get_payload_iterator(response);
867 while (payloads->has_next(payloads))
868 {
869 payload_t *payload;
870 payloads->current(payloads, (void**)&payload);
871
872 switch (payload->get_type(payload))
873 {
874 case SECURITY_ASSOCIATION:
875 {
876 sa_payload = (sa_payload_t*)payload;
877 break;
878 }
879 case KEY_EXCHANGE:
880 {
881 ke_payload = (ke_payload_t*)payload;
882 break;
883 }
884 case NONCE:
885 {
886 nonce_payload = (nonce_payload_t*)payload;
887 break;
888 }
889 case NOTIFY:
890 {
891 status = process_notifys(this, (notify_payload_t*)payload);
892 if (status == FAILED)
893 {
894 payloads->destroy(payloads);
895 /* we return SUCCESS, returned FAILED means do next transaction */
896 return SUCCESS;
897 }
898 if (status == DESTROY_ME)
899 {
900 payloads->destroy(payloads);
901 return status;
902 }
903 break;
904 }
905 default:
906 {
907 this->logger->log(this->logger, ERROR, "ignoring payload %s (%d)",
908 mapping_find(payload_type_m, payload->get_type(payload)),
909 payload->get_type(payload));
910 break;
911 }
912 }
913 }
914 payloads->destroy(payloads);
915
916 if (!(nonce_payload && sa_payload && ke_payload))
917 {
918 this->logger->log(this->logger, AUDIT, "response message incomplete, deleting IKE_SA");
919 return DESTROY_ME;
920 }
921
922 { /* process SA payload:
923 * -------------------
924 * - get proposals from it
925 * - check if peer selected a proposal
926 * - verify it's selection againts our set
927 */
928 proposal_t *proposal;
929 linked_list_t *proposal_list;
930
931 /* get the list of selected proposals, the peer has to select only one proposal */
932 proposal_list = sa_payload->get_proposals (sa_payload);
933 if (proposal_list->get_count(proposal_list) != 1)
934 {
935 this->logger->log(this->logger, AUDIT,
936 "response did not contain a single proposal, deleting IKE_SA");
937 while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
938 {
939 proposal->destroy(proposal);
940 }
941 proposal_list->destroy(proposal_list);
942 return DESTROY_ME;
943 }
944
945 /* we have to re-check if the others selection is valid */
946 this->proposal = this->connection->select_proposal(this->connection, proposal_list);
947 destroy_proposal_list(proposal_list);
948
949 if (this->proposal == NULL)
950 {
951 this->logger->log(this->logger, AUDIT,
952 "peer selected a proposal we did not offer, deleting IKE_SA");
953 return DESTROY_ME;
954 }
955 }
956
957 { /* process KE payload:
958 * -------------------
959 * - extract others public value
960 * - complete diffie-hellman exchange
961 */
962 this->diffie_hellman->set_other_public_value(this->diffie_hellman,
963 ke_payload->get_key_exchange_data(ke_payload));
964 }
965
966 { /* process NONCE payload:
967 * ----------------------
968 * - extract nonce used for key derivation */
969 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
970 }
971
972 { /* process NATT stuff:
973 * -------------------
974 * - check if we or other is NATted
975 * - switch to port 4500 if so
976 */
977 if ((!this->natd_dst_seen && this->natd_src_seen) ||
978 (this->natd_dst_seen && !this->natd_src_seen))
979 {
980 this->logger->log(this->logger, AUDIT,
981 "request contained wrong number of NAT-D payloads, deleting IKE_SA");
982 return DESTROY_ME;
983 }
984 if (this->natd_src_seen && !this->natd_src_matched)
985 {
986 this->ike_sa->enable_natt(this->ike_sa, FALSE);
987 }
988 if (this->natd_dst_seen && !this->natd_dst_matched)
989 {
990 this->ike_sa->enable_natt(this->ike_sa, TRUE);
991 }
992 if (this->ike_sa->is_natt_enabled(this->ike_sa))
993 {
994 me = this->ike_sa->get_my_host(this->ike_sa);
995 me->set_port(me, IKEV2_NATT_PORT);
996 other = this->ike_sa->get_other_host(this->ike_sa);
997 other->set_port(other, IKEV2_NATT_PORT);
998
999 this->logger->log(this->logger, CONTROL|LEVEL1, "switching to port %d", IKEV2_NATT_PORT);
1000 }
1001 }
1002
1003 /* because we are original initiator we have to update the responder SPI to the new one */
1004 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
1005 ike_sa_id->set_responder_spi(ike_sa_id, responder_spi);
1006
1007 /* derive all the keys used in the IKE_SA */
1008 if (this->ike_sa->derive_keys(this->ike_sa, this->proposal,
1009 this->diffie_hellman,
1010 this->nonce_i, this->nonce_r,
1011 TRUE, NULL, NULL) != SUCCESS)
1012 {
1013 this->logger->log(this->logger, AUDIT,
1014 "transform objects could not be created from selected proposal, deleting IKE_SA");
1015 return DESTROY_ME;
1016 }
1017
1018 this->ike_sa->set_lifetimes(this->ike_sa,
1019 this->connection->get_soft_lifetime(this->connection),
1020 this->connection->get_hard_lifetime(this->connection));
1021
1022 { /* create ike_auth transaction, which will continue IKE_SA setup */
1023 chunk_t request_chunk, response_chunk;
1024 ike_auth_t *ike_auth;
1025
1026 request_chunk = this->message->get_packet_data(this->message);
1027 response_chunk = response->get_packet_data(response);
1028
1029 /* create next transaction, for which we except a message */
1030 ike_auth = ike_auth_create(this->ike_sa);
1031 ike_auth->set_config(ike_auth, this->connection, this->policy);
1032 this->connection = NULL;
1033 this->policy = NULL;
1034 ike_auth->set_nonces(ike_auth,
1035 chunk_clone(this->nonce_i),
1036 chunk_clone(this->nonce_r));
1037 ike_auth->set_init_messages(ike_auth, request_chunk, response_chunk);
1038 *next = (transaction_t*)ike_auth;
1039 }
1040
1041 return SUCCESS;
1042 }
1043
1044 static void destroy(private_ike_sa_init_t *this)
1045 {
1046 DESTROY_IF(this->message);
1047 DESTROY_IF(this->diffie_hellman);
1048 DESTROY_IF(this->proposal);
1049 DESTROY_IF(this->connection);
1050 DESTROY_IF(this->policy);
1051 chunk_free(&this->nonce_i);
1052 chunk_free(&this->nonce_r);
1053 this->randomizer->destroy(this->randomizer);
1054 this->nat_hasher->destroy(this->nat_hasher);
1055 chunk_free(&this->natd_src_hash);
1056 chunk_free(&this->natd_dst_hash);
1057 free(this);
1058 }
1059
1060 /*
1061 * Described in header.
1062 */
1063 ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
1064 {
1065 private_ike_sa_init_t *this = malloc_thing(private_ike_sa_init_t);
1066
1067 /* transaction interface functions */
1068 this->public.transaction.get_request = (status_t(*)(transaction_t*,message_t**))get_request;
1069 this->public.transaction.get_response = (status_t(*)(transaction_t*,message_t*,message_t**,transaction_t**))get_response;
1070 this->public.transaction.conclude = (status_t(*)(transaction_t*,message_t*,transaction_t**))conclude;
1071 this->public.transaction.get_message_id = (u_int32_t(*)(transaction_t*))get_message_id;
1072 this->public.transaction.requested = (u_int32_t(*)(transaction_t*))requested;
1073 this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
1074
1075 /* public functions */
1076 this->public.set_config = (void(*)(ike_sa_init_t*,connection_t*,policy_t*))set_config;
1077 this->public.use_dh_group = (bool(*)(ike_sa_init_t*,diffie_hellman_group_t))use_dh_group;
1078
1079 /* private data */
1080 this->ike_sa = ike_sa;
1081 this->message_id = 0;
1082 this->message = NULL;
1083 this->requested = 0;
1084 this->diffie_hellman = NULL;
1085 this->nonce_i = CHUNK_INITIALIZER;
1086 this->nonce_r = CHUNK_INITIALIZER;
1087 this->connection = NULL;
1088 this->policy = NULL;
1089 this->proposal = NULL;
1090 this->randomizer = randomizer_create();
1091 this->nat_hasher = hasher_create(HASH_SHA1);
1092 this->natd_src_hash = CHUNK_INITIALIZER;
1093 this->natd_dst_hash = CHUNK_INITIALIZER;
1094 this->natd_src_seen = FALSE;
1095 this->natd_dst_seen = FALSE;
1096 this->natd_src_matched = FALSE;
1097 this->natd_dst_matched = FALSE;
1098 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
1099
1100 return &this->public;
1101 }