- baschtel
[strongswan.git] / Source / charon / ike_sa.c
1 /**
2 * @file ike_sa.c
3 *
4 * @brief Class ike_sa_t. An object of this type is managed by an
5 * ike_sa_manager_t object and represents an IKE_SA
6 *
7 */
8
9 /*
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "ike_sa.h"
25
26 #include "types.h"
27 #include "globals.h"
28 #include "definitions.h"
29 #include "utils/allocator.h"
30 #include "utils/linked_list.h"
31 #include "utils/logger_manager.h"
32 #include "utils/randomizer.h"
33 #include "transforms/diffie_hellman.h"
34 #include "payloads/sa_payload.h"
35 #include "payloads/nonce_payload.h"
36 #include "payloads/ke_payload.h"
37 #include "payloads/transform_substructure.h"
38 #include "payloads/transform_attribute.h"
39
40
41 /**
42 *
43 * This implementation supports only window size 1
44 */
45 #define WINDOW_SIZE 1
46
47 /**
48 * States in which a IKE_SA can actually be
49 */
50 typedef enum ike_sa_state_e ike_sa_state_t;
51
52 enum ike_sa_state_e {
53
54 /**
55 * IKE_SA is is not in a state
56 */
57 NO_STATE = 1,
58
59 /**
60 * A IKE_SA_INIT-message was sent: role initiator
61 */
62 IKE_SA_INIT_REQUESTED = 2,
63
64 /**
65 * A IKE_SA_INIT-message was replied: role responder
66 */
67 IKE_SA_INIT_RESPONDED = 3,
68
69 /**
70 * An IKE_AUTH-message was sent after a successful
71 * IKE_SA_INIT-exchange: role initiator
72 */
73 IKE_AUTH_REQUESTED = 4,
74
75 /**
76 * An IKE_AUTH-message was replied: role responder.
77 * In this state, all the informations for an IKE_SA
78 * and one CHILD_SA are known.
79 */
80 IKE_SA_INITIALIZED = 5
81 };
82
83 /**
84 * string mappings for ike_sa_state
85 */
86 mapping_t ike_sa_state_m[] = {
87 {NO_STATE, "NO_STATE"},
88 {IKE_SA_INIT_REQUESTED, "IKE_SA_INIT_REQUESTED"},
89 {IKE_SA_INIT_RESPONDED, "IKE_SA_INIT_RESPONDED"},
90 {IKE_AUTH_REQUESTED, "IKE_AUTH_REQUESTED"},
91 {IKE_SA_INITIALIZED, "IKE_SA_INITIALIZED"},
92 {MAPPING_END, NULL}
93 };
94
95
96 /**
97 * Private data of an message_t object
98 */
99 typedef struct private_ike_sa_s private_ike_sa_t;
100
101 struct private_ike_sa_s {
102
103 /**
104 * Public part of a ike_sa_t object
105 */
106 ike_sa_t public;
107
108 status_t (*build_sa_payload) (private_ike_sa_t *this, sa_payload_t **payload);
109 status_t (*build_ke_payload) (private_ike_sa_t *this, ke_payload_t **payload);
110 status_t (*build_nonce_payload) (private_ike_sa_t *this, nonce_payload_t **payload);
111
112 status_t (*build_message) (private_ike_sa_t *this, exchange_type_t type, bool request, message_t **message);
113
114
115 status_t (*transto_ike_sa_init_requested) (private_ike_sa_t *this, char *name);
116 status_t (*transto_ike_sa_init_responded) (private_ike_sa_t *this, message_t *message);
117 status_t (*transto_ike_auth_requested) (private_ike_sa_t *this, message_t *message);
118
119 /* Private values */
120 /**
121 * Identifier for the current IKE_SA
122 */
123 ike_sa_id_t *ike_sa_id;
124
125 /**
126 * Linked List containing the child sa's of the current IKE_SA
127 */
128 linked_list_t *child_sas;
129
130 /**
131 * Current state of the IKE_SA
132 */
133 ike_sa_state_t state;
134
135 /**
136 * this SA's source for random data
137 */
138 randomizer_t *randomizer;
139
140 /**
141 * contains the last X responded messages
142 *
143 * X is windows size (here 1)
144 */
145 linked_list_t *responded_messages;
146
147 /**
148 * contains the last X requested messages
149 *
150 * X is windows size (here 1)
151 */
152 linked_list_t *requested_messages;
153
154 struct {
155 host_t *host;
156 } me;
157
158 struct {
159 host_t *host;
160 } other;
161
162
163 struct {
164 /**
165 * Diffie Hellman object used to compute shared secret
166 */
167 diffie_hellman_t *diffie_hellman;
168 /**
169 * Diffie Hellman group number
170 */
171 u_int16_t dh_group_number;
172
173 /**
174 * Priority used get matching dh_group number
175 */
176 u_int16_t dh_group_priority;
177
178 /**
179 * selected proposals
180 */
181 linked_list_t *proposals;
182 /**
183 *
184 */
185 chunk_t sent_nonce;
186 /**
187 *
188 */
189 chunk_t received_nonce;
190 } ike_sa_init_data;
191
192
193 /**
194 * next message id to receive
195 */
196 u_int32_t message_id_in;
197
198 /**
199 * next message id to send
200 */
201 u_int32_t message_id_out;
202
203 /**
204 * a logger for this IKE_SA
205 */
206 logger_t *logger;
207 };
208
209 /**
210 * @brief implements function process_message of private_ike_sa_t
211 */
212 static status_t process_message (private_ike_sa_t *this, message_t *message)
213 {
214 u_int32_t message_id;
215 bool is_request;
216 is_request = message->get_request(message);
217 this->logger->log(this->logger, CONTROL|MORE, "Process %s message of exchange type %s",(is_request) ? "REQUEST" : "RESPONSE",
218 mapping_find(exchange_type_m,message->get_exchange_type(message)));
219
220
221 //message->get_exchange_type(message);
222
223
224 switch (message->get_exchange_type(message))
225 {
226 case IKE_SA_INIT:
227 {
228 if (message->get_request(message)) {
229 if (this->state == NO_STATE)
230 {
231 /* state transission NO_STATE => IKE_SA_INIT_RESPONDED */
232 return this->transto_ike_sa_init_responded(this, message);
233 }
234 }
235 else
236 {
237 if (this->state == IKE_SA_INIT_REQUESTED)
238 {
239 /* state transission IKE_SA_INIT_REQUESTED => IKE_AUTH_REQUESTED*/
240 return this->transto_ike_auth_requested(this, message);
241 }
242 }
243 break;
244 }
245 case IKE_AUTH:
246 {
247 /* break; */
248 }
249 case CREATE_CHILD_SA:
250 {
251 /* break; */
252 }
253 case INFORMATIONAL:
254 {
255 /* break; */
256 }
257 default:
258 {
259 this->logger->log(this->logger, ERROR, "processing %s-message not supported.",
260 mapping_find(exchange_type_m,message->get_exchange_type(message)));
261 return NOT_SUPPORTED;
262 }
263 }
264 this->logger->log(this->logger, ERROR, "received %s-message in state %s, rejected.",
265 mapping_find(exchange_type_m, message->get_exchange_type(message)),
266 mapping_find(ike_sa_state_m, this->state));
267 return INVALID_STATE;
268 }
269
270
271 static status_t build_message(private_ike_sa_t *this, exchange_type_t type, bool request, message_t **message)
272 {
273 status_t status;
274 message_t *new_message;
275 host_t *source, *destination;
276
277 new_message = message_create();
278 if (new_message == NULL)
279 {
280 return OUT_OF_RES;
281 }
282
283 status = this->me.host->clone(this->me.host, &source);
284 status |= this->other.host->clone(this->other.host, &destination);
285 if (status != SUCCESS)
286 {
287 new_message->destroy(new_message);
288 return status;
289 }
290 new_message->set_source(new_message, source);
291 new_message->set_destination(new_message, destination);
292
293 new_message->set_exchange_type(new_message, type);
294 new_message->set_request(new_message, request);
295
296 if (request)
297 {
298 new_message->set_message_id(new_message, this->message_id_out);
299 }else
300 {
301 new_message->set_message_id(new_message, this->message_id_in);
302 }
303
304 new_message->set_ike_sa_id(new_message, this->ike_sa_id);
305
306 *message = new_message;
307
308 return SUCCESS;
309 }
310
311
312 static status_t transto_ike_sa_init_requested(private_ike_sa_t *this, char *name)
313 {
314 message_t *message;
315 payload_t *payload;
316 packet_t *packet;
317 status_t status;
318
319 this->logger->log(this->logger, CONTROL, "initializing connection");
320
321 status = global_configuration_manager->get_local_host(global_configuration_manager, name, &(this->me.host));
322 if (status != SUCCESS)
323 {
324 return INVALID_ARG;
325 }
326
327 status = global_configuration_manager->get_remote_host(global_configuration_manager, name, &(this->other.host));
328 if (status != SUCCESS)
329 {
330 return INVALID_ARG;
331 }
332
333 status = global_configuration_manager->get_dh_group_number(global_configuration_manager, name, &(this->ike_sa_init_data.dh_group_number), this->ike_sa_init_data.dh_group_priority);
334 if (status != SUCCESS)
335 {
336 return INVALID_ARG;
337 }
338
339 this ->logger->log(this->logger, CONTROL|MORE, "create diffie hellman object");
340 if (this->ike_sa_init_data.diffie_hellman != NULL)
341 {
342 this->logger->log(this->logger, ERROR, "Object of type diffie_hellman_t already existing!");
343 return FAILED;
344 }
345 this->ike_sa_init_data.diffie_hellman = diffie_hellman_create(this->ike_sa_init_data.dh_group_number);
346 if (this->ike_sa_init_data.diffie_hellman == NULL)
347 {
348 this->logger->log(this->logger, ERROR, "Object of type diffie_hellman_t could not be created!");
349 return FAILED;
350 }
351
352 if (this->ike_sa_init_data.sent_nonce.ptr != NULL)
353 {
354 this->logger->log(this->logger, ERROR, "Nonce for IKE_SA_INIT phase already existing!");
355 return FAILED;
356 }
357
358 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer, 16, &(this->ike_sa_init_data.sent_nonce)) != SUCCESS)
359 {
360 this->logger->log(this->logger, ERROR, "Could not create nonce!");
361 return OUT_OF_RES;
362 }
363
364
365 /* going to build message */
366
367 status = this->build_message(this, IKE_SA_INIT, TRUE, &message);
368 if (status != SUCCESS)
369 {
370 this->logger->log(this->logger, ERROR, "Could not build message");
371 return status;
372 }
373
374 /* build SA payload */
375 status = this->build_sa_payload(this, (sa_payload_t**)&payload);
376 if (status != SUCCESS)
377 {
378 this->logger->log(this->logger, ERROR, "Could not build SA payload");
379 message->destroy(message);
380 return status;
381 }
382 message->add_payload(message, payload);
383
384 /* build KE payload */
385 status = this->build_ke_payload(this,(ke_payload_t **) &payload);
386 if (status != SUCCESS)
387 {
388 this->logger->log(this->logger, ERROR, "Could not build KE payload");
389 message->destroy(message);
390 return status;
391 }
392 message->add_payload(message, payload);
393
394 /* build Nonce payload */
395 status = this->build_nonce_payload(this, (nonce_payload_t**)&payload);
396 if (status != SUCCESS)
397 {
398 this->logger->log(this->logger, ERROR, "Could not build NONCE payload");
399 message->destroy(message);
400 return status;
401 }
402 message->add_payload(message, payload);
403
404
405 status = message->generate(message, &packet);
406 if (status != SUCCESS)
407 {
408 this->logger->log(this->logger, ERROR, "Could not generate message");
409 message->destroy(message);
410 return status;
411 }
412
413 status = global_send_queue->add(global_send_queue, packet);
414 if (status != SUCCESS)
415 {
416 this->logger->log(this->logger, ERROR, "Could not add packet to send queue");
417 message->destroy(message);
418 return status;
419 }
420
421 if ( this->requested_messages->get_count(this->requested_messages) >= WINDOW_SIZE)
422 {
423 message_t *removed_message;
424 /* destroy message */
425 this->requested_messages->remove_last(this->requested_messages,(void **)&removed_message);
426 removed_message->destroy(removed_message);
427 }
428
429 status = this->requested_messages->insert_first(this->requested_messages,(void *) message);
430 if (status != SUCCESS)
431 {
432 this->logger->log(this->logger, ERROR, "Could not store last received message");
433 message->destroy(message);
434 return status;
435 }
436
437 /* message counter can now be increased */
438 this->message_id_out++;
439
440 /* states has NOW changed :-) */
441 this->state = IKE_SA_INIT_REQUESTED;
442
443 return SUCCESS;
444 }
445
446 static status_t transto_ike_sa_init_responded(private_ike_sa_t *this, message_t *request)
447 {
448 status_t status;
449 linked_list_iterator_t *payloads;
450 message_t *response;
451 host_t *source, *destination;
452
453 /* this is the first message we process, so copy host infos */
454 request->get_source(request, &source);
455 request->get_destination(request, &destination);
456 /* we need to clone them, since we destroy the message later */
457 destination->clone(destination, &(this->me.host));
458 source->clone(source, &(this->other.host));
459
460 /* parse incoming message */
461 status = request->parse_body(request);
462 if (status != SUCCESS)
463 {
464 this->logger->log(this->logger, ERROR, "Could not parse body");
465 return status;
466 }
467 /* iterate over incoming payloads */
468 status = request->get_payload_iterator(request, &payloads);
469 if (status != SUCCESS)
470 {
471 request->destroy(request);
472 return status;
473 }
474 while (payloads->has_next(payloads))
475 {
476 payload_t *payload;
477 payloads->current(payloads, (void**)&payload);
478
479 this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
480 switch (payload->get_type(payload))
481 {
482 case SECURITY_ASSOCIATION:
483 {
484 sa_payload_t *sa_payload = (sa_payload_t*)payload;
485 linked_list_iterator_t *suggested_proposals, *accepted_proposals;
486 /* create a list for accepted proposals */
487 if (this->ike_sa_init_data.proposals == NULL) {
488 this->ike_sa_init_data.proposals = linked_list_create();
489 }
490 else
491 {
492 /** @todo destroy list contents */
493 }
494 if (this->ike_sa_init_data.proposals == NULL)
495 {
496 payloads->destroy(payloads);
497 return OUT_OF_RES;
498 }
499 status = this->ike_sa_init_data.proposals->create_iterator(this->ike_sa_init_data.proposals, &accepted_proposals, FALSE);
500 if (status != SUCCESS)
501 {
502 payloads->destroy(payloads);
503 return status;
504 }
505
506 /* get the list of suggested proposals */
507 status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
508 if (status != SUCCESS)
509 {
510 accepted_proposals->destroy(accepted_proposals);
511 payloads->destroy(payloads);
512 return status;
513 }
514
515 /* now let the configuration-manager select a subset of the proposals */
516 status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
517 this->other.host, suggested_proposals, accepted_proposals);
518 if (status != SUCCESS)
519 {
520 suggested_proposals->destroy(suggested_proposals);
521 accepted_proposals->destroy(accepted_proposals);
522 payloads->destroy(payloads);
523 return status;
524 }
525
526 suggested_proposals->destroy(suggested_proposals);
527 accepted_proposals->destroy(accepted_proposals);
528
529 /* ok, we have what we need for sa_payload */
530 break;
531 }
532 case KEY_EXCHANGE:
533 {
534 ke_payload_t *ke_payload = (ke_payload_t*)payload;
535 diffie_hellman_t *dh;
536 diffie_hellman_group_t group;
537 bool allowed_group;
538
539 group = ke_payload->get_dh_group_number(ke_payload);
540
541 status = global_configuration_manager->is_dh_group_allowed_for_host(global_configuration_manager,
542 this->other.host, group, &allowed_group);
543 if (status != SUCCESS)
544 {
545 payloads->destroy(payloads);
546 return status;
547 }
548 if (!allowed_group)
549 {
550 /** @todo info reply */
551 }
552
553 dh = diffie_hellman_create(group);
554 if (dh == NULL)
555 {
556 payloads->destroy(payloads);
557 return OUT_OF_RES;
558 }
559
560 status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
561 if (status != SUCCESS)
562 {
563 dh->destroy(dh);
564 payloads->destroy(payloads);
565 return OUT_OF_RES;
566 }
567 /** @todo destroy if there is already one */
568 this->ike_sa_init_data.diffie_hellman = dh;
569 break;
570 }
571 case NONCE:
572 {
573 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
574 chunk_t nonce;
575
576 nonce_payload->get_nonce(nonce_payload, &nonce);
577 /** @todo free if there is already one */
578 this->ike_sa_init_data.received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
579 this->ike_sa_init_data.received_nonce.len = nonce.len;
580 if (this->ike_sa_init_data.received_nonce.ptr == NULL)
581 {
582 payloads->destroy(payloads);
583 return OUT_OF_RES;
584 }
585 break;
586 }
587 default:
588 {
589 /** @todo handle */
590 }
591
592 }
593
594 }
595 payloads->destroy(payloads);
596
597 printf("done.\n");
598
599 /* set up the reply */
600 status = this->build_message(this, IKE_SA_INIT, FALSE, &response);
601 if (status != SUCCESS)
602 {
603 return status;
604 }
605
606
607
608
609 /*
610 job_t *delete_job;
611 delete_job = (job_t *) delete_ike_sa_job_create(this->ike_sa_id);
612 if (delete_job == NULL)
613 {
614 this->logger->log(this->logger, ERROR, "Job to delete IKE SA could not be created");
615 }
616
617 status = global_job_queue->add(global_job_queue,delete_job);
618 if (status != SUCCESS)
619 {
620 this->logger->log(this->logger, ERROR, "%s Job to delete IKE SA could not be added to job queue",mapping_find(status_m,status));
621 delete_job->destroy_all(delete_job);
622 }*/
623 return SUCCESS;
624 }
625
626 static status_t transto_ike_auth_requested(private_ike_sa_t *this, message_t *response)
627 {
628 status_t status;
629 linked_list_iterator_t *payloads;
630
631
632 /* parse incoming message */
633 status = response->parse_body(response);
634 if (status != SUCCESS)
635 {
636 this->logger->log(this->logger, ERROR, "Could not parse body");
637 return status;
638 }
639 /* iterate over incoming payloads */
640 status = response->get_payload_iterator(response, &payloads);
641 if (status != SUCCESS)
642 {
643 response->destroy(response);
644 return status;
645 }
646 while (payloads->has_next(payloads))
647 {
648 payload_t *payload;
649 payloads->current(payloads, (void**)&payload);
650
651 this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
652 switch (payload->get_type(payload))
653 {
654 // case SECURITY_ASSOCIATION:
655 // {
656 // sa_payload_t *sa_payload = (sa_payload_t*)payload;
657 // linked_list_iterator_t *suggested_proposals, *accepted_proposals;
658 // /* create a list for accepted proposals */
659 // if (this->ike_sa_init_data.proposals == NULL) {
660 // this->ike_sa_init_data.proposals = linked_list_create();
661 // }
662 // else
663 // {
664 // /** @todo destroy list contents */
665 // }
666 // if (this->ike_sa_init_data.proposals == NULL)
667 // {
668 // payloads->destroy(payloads);
669 // return OUT_OF_RES;
670 // }
671 // status = this->ike_sa_init_data.proposals->create_iterator(this->ike_sa_init_data.proposals, &accepted_proposals, FALSE);
672 // if (status != SUCCESS)
673 // {
674 // payloads->destroy(payloads);
675 // return status;
676 // }
677 //
678 // /* get the list of suggested proposals */
679 // status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
680 // if (status != SUCCESS)
681 // {
682 // accepted_proposals->destroy(accepted_proposals);
683 // payloads->destroy(payloads);
684 // return status;
685 // }
686 //
687 // /* now let the configuration-manager select a subset of the proposals */
688 // status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
689 // this->other.host, suggested_proposals, accepted_proposals);
690 // if (status != SUCCESS)
691 // {
692 // suggested_proposals->destroy(suggested_proposals);
693 // accepted_proposals->destroy(accepted_proposals);
694 // payloads->destroy(payloads);
695 // return status;
696 // }
697 //
698 // suggested_proposals->destroy(suggested_proposals);
699 // accepted_proposals->destroy(accepted_proposals);
700 //
701 // /* ok, we have what we need for sa_payload */
702 // break;
703 // }
704 case KEY_EXCHANGE:
705 {
706 ke_payload_t *ke_payload = (ke_payload_t*)payload;
707 diffie_hellman_t *dh;
708 chunk_t shared_secret;
709
710 dh = this->ike_sa_init_data.diffie_hellman;
711
712
713
714
715 status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
716 if (status != SUCCESS)
717 {
718 dh->destroy(dh);
719 payloads->destroy(payloads);
720 return OUT_OF_RES;
721 }
722
723 status = dh->get_shared_secret(dh, &shared_secret);
724
725 this->logger->log_chunk(this->logger, RAW, "Shared secret", &shared_secret);
726
727 break;
728 }
729 case NONCE:
730 {
731 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
732 chunk_t nonce;
733
734 nonce_payload->get_nonce(nonce_payload, &nonce);
735 /** @todo free if there is already one */
736 this->ike_sa_init_data.received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
737 this->ike_sa_init_data.received_nonce.len = nonce.len;
738 if (this->ike_sa_init_data.received_nonce.ptr == NULL)
739 {
740 payloads->destroy(payloads);
741 return OUT_OF_RES;
742 }
743 break;
744 }
745 default:
746 {
747 /** @todo handle */
748 }
749
750 }
751
752 }
753 payloads->destroy(payloads);
754
755 printf("done.\n");
756
757 /* set up the reply */
758 status = this->build_message(this, IKE_SA_INIT, FALSE, &response);
759 if (status != SUCCESS)
760 {
761 return status;
762 }
763
764
765
766 }
767
768 /**
769 * @brief implements function process_configuration of private_ike_sa_t
770 */
771 static status_t initialize_connection(private_ike_sa_t *this, char *name)
772 {
773 /* work is done in transto_ike_sa_init_requested */
774 return (this->transto_ike_sa_init_requested(this,name));
775 }
776
777 /**
778 * @brief implements function private_ike_sa_t.get_id
779 */
780 static ike_sa_id_t* get_id(private_ike_sa_t *this)
781 {
782 return this->ike_sa_id;
783 }
784
785 /**
786 * implements private_ike_sa_t.build_sa_payload
787 */
788 static status_t build_sa_payload(private_ike_sa_t *this, sa_payload_t **payload)
789 {
790 sa_payload_t* sa_payload;
791 linked_list_iterator_t *iterator;
792 status_t status;
793
794 this->logger->log(this->logger, CONTROL|MORE, "building sa payload");
795
796 sa_payload = sa_payload_create();
797 if (sa_payload == NULL)
798 {
799 return OUT_OF_RES;
800 }
801 status = sa_payload->create_proposal_substructure_iterator(sa_payload, &iterator, FALSE);
802 if (status != SUCCESS)
803 {
804 sa_payload->destroy(sa_payload);
805 return status;
806 }
807 status = global_configuration_manager->get_proposals_for_host(global_configuration_manager, this->other.host, iterator);
808 if (status != SUCCESS)
809 {
810 sa_payload->destroy(sa_payload);
811 return status;
812 }
813
814 *payload = sa_payload;
815
816 return SUCCESS;
817 }
818
819 static status_t build_ke_payload(private_ike_sa_t *this, ke_payload_t **payload)
820 {
821 ke_payload_t *ke_payload;
822 chunk_t key_data;
823 status_t status;
824
825 this->logger->log(this->logger, CONTROL|MORE, "building ke payload");
826
827 if (this->state != NO_STATE)
828 {
829 this->logger->log(this->logger, ERROR, "KE payload in state %s not supported",mapping_find(ike_sa_state_m,this->state));
830 return FALSE;
831 }
832
833 switch(this->ike_sa_id->is_initiator(this->ike_sa_id))
834 {
835 case TRUE:
836 {
837 this ->logger->log(this->logger, CONTROL|MORE, "get public dh value to send in ke payload");
838 status = this->ike_sa_init_data.diffie_hellman->get_my_public_value(this->ike_sa_init_data.diffie_hellman,&key_data);
839 if (status != SUCCESS)
840 {
841 this->logger->log(this->logger, ERROR, "Could not get my DH public value");
842 return status;
843 }
844
845 ke_payload = ke_payload_create();
846 if (ke_payload == NULL)
847 {
848 this->logger->log(this->logger, ERROR, "Could not create KE payload");
849 allocator_free_chunk(key_data);
850 return OUT_OF_RES;
851 }
852 ke_payload->set_dh_group_number(ke_payload, MODP_1024_BIT);
853 if (ke_payload->set_key_exchange_data(ke_payload, key_data) != SUCCESS)
854 {
855 this->logger->log(this->logger, ERROR, "Could not set key exchange data of KE payload");
856 ke_payload->destroy(ke_payload);
857 allocator_free_chunk(key_data);
858 return OUT_OF_RES;
859 }
860 allocator_free_chunk(key_data);
861
862 *payload = ke_payload;
863 return SUCCESS;
864 }
865 default: /* FALSE */
866 {
867 break;
868 }
869 }
870
871 return FAILED;
872 }
873
874 /**
875 * implements private_ike_sa_t.build_nonce_payload
876 */
877 static status_t build_nonce_payload(private_ike_sa_t *this, nonce_payload_t **payload)
878 {
879 nonce_payload_t *nonce_payload;
880
881 this->logger->log(this->logger, CONTROL|MORE, "building nonce payload");
882 nonce_payload = nonce_payload_create();
883 if (nonce_payload == NULL)
884 {
885 return OUT_OF_RES;
886 }
887
888 nonce_payload->set_nonce(nonce_payload, this->ike_sa_init_data.sent_nonce);
889
890 *payload = nonce_payload;
891
892 return SUCCESS;
893 }
894
895 /**
896 * @brief implements function destroy of private_ike_sa_t
897 */
898 static status_t destroy (private_ike_sa_t *this)
899 {
900 /* destroy child sa's */
901 while (this->child_sas->get_count(this->child_sas) > 0)
902 {
903 void *child_sa;
904 if (this->child_sas->remove_first(this->child_sas,&child_sa) != SUCCESS)
905 {
906 break;
907 }
908 /* destroy child sa */
909 }
910 this->child_sas->destroy(this->child_sas);
911
912 /* destroy ike_sa_id */
913 this->ike_sa_id->destroy(this->ike_sa_id);
914
915 /* destroy stored requested messages */
916 while (this->requested_messages->get_count(this->requested_messages) > 0)
917 {
918 message_t *message;
919 if (this->requested_messages->remove_first(this->requested_messages,(void **) &message) != SUCCESS)
920 {
921 break;
922 }
923 message->destroy(message);
924 }
925 this->requested_messages->destroy(this->requested_messages);
926
927 /* destroy stored responded messages */
928 while (this->responded_messages->get_count(this->responded_messages) > 0)
929 {
930 message_t *message;
931 if (this->responded_messages->remove_first(this->responded_messages,(void **) &message) != SUCCESS)
932 {
933 break;
934 }
935 message->destroy(message);
936 }
937 this->responded_messages->destroy(this->responded_messages);
938
939
940 this->randomizer->destroy(this->randomizer);
941 if (this->ike_sa_init_data.diffie_hellman != NULL)
942 {
943 this->ike_sa_init_data.diffie_hellman->destroy(this->ike_sa_init_data.diffie_hellman);
944 }
945 if (this->ike_sa_init_data.sent_nonce.ptr != NULL)
946 {
947 allocator_free_chunk(this->ike_sa_init_data.sent_nonce);
948 }
949 if (this->ike_sa_init_data.received_nonce.ptr != NULL)
950 {
951 allocator_free_chunk(this->ike_sa_init_data.received_nonce);
952 }
953
954 global_logger_manager->destroy_logger(global_logger_manager, this->logger);
955
956 allocator_free(this);
957
958 return SUCCESS;
959 }
960
961 /*
962 * Described in Header
963 */
964 ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
965 {
966 private_ike_sa_t *this = allocator_alloc_thing(private_ike_sa_t);
967 if (this == NULL)
968 {
969 return NULL;
970 }
971
972
973 /* Public functions */
974 this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
975 this->public.initialize_connection = (status_t(*)(ike_sa_t*, char*)) initialize_connection;
976 this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
977 this->public.destroy = (status_t(*)(ike_sa_t*))destroy;
978
979 /* private functions */
980 this->build_sa_payload = build_sa_payload;
981 this->build_nonce_payload = build_nonce_payload;
982 this->build_ke_payload = build_ke_payload;
983 this->build_message = build_message;
984 this->transto_ike_sa_init_requested = transto_ike_sa_init_requested;
985 this->transto_ike_sa_init_responded = transto_ike_sa_init_responded;
986 this->transto_ike_auth_requested = transto_ike_auth_requested;
987
988
989
990 /* initialize private fields */
991 if (ike_sa_id->clone(ike_sa_id,&(this->ike_sa_id)) != SUCCESS)
992 {
993 allocator_free(this);
994 return NULL;
995 }
996 this->child_sas = linked_list_create();
997 if (this->child_sas == NULL)
998 {
999 this->ike_sa_id->destroy(this->ike_sa_id);
1000 allocator_free(this);
1001 return NULL;
1002 }
1003 this->randomizer = randomizer_create();
1004 if (this->randomizer == NULL)
1005 {
1006 this->child_sas->destroy(this->child_sas);
1007 this->ike_sa_id->destroy(this->ike_sa_id);
1008 allocator_free(this);
1009 }
1010 this->responded_messages = linked_list_create();
1011 if (this->responded_messages == NULL)
1012 {
1013 this->randomizer->destroy(this->randomizer);
1014 this->child_sas->destroy(this->child_sas);
1015 this->ike_sa_id->destroy(this->ike_sa_id);
1016 allocator_free(this);
1017 }
1018 this->requested_messages = linked_list_create();
1019 if (this->requested_messages == NULL)
1020 {
1021 this->randomizer->destroy(this->randomizer);
1022 this->child_sas->destroy(this->child_sas);
1023 this->ike_sa_id->destroy(this->ike_sa_id);
1024 this->responded_messages->destroy(this->responded_messages);
1025 allocator_free(this);
1026 }
1027
1028 this->logger = global_logger_manager->create_logger(global_logger_manager, IKE_SA, NULL);
1029 if (this->logger == NULL)
1030 {
1031 this->randomizer->destroy(this->randomizer);
1032 this->child_sas->destroy(this->child_sas);
1033 this->ike_sa_id->destroy(this->ike_sa_id);
1034 this->responded_messages->destroy(this->responded_messages);
1035 this->requested_messages->destroy(this->requested_messages);
1036 allocator_free(this);
1037 }
1038
1039 this->me.host = NULL;
1040 this->other.host = NULL;
1041 this->ike_sa_init_data.diffie_hellman = NULL;
1042 this->ike_sa_init_data.dh_group_number = 0;
1043 /* 1 means highest priority */
1044 this->ike_sa_init_data.dh_group_priority = 1;
1045 this->ike_sa_init_data.sent_nonce.len = 0;
1046 this->ike_sa_init_data.sent_nonce.ptr = NULL;
1047 this->ike_sa_init_data.received_nonce.len = 0;
1048 this->ike_sa_init_data.received_nonce.ptr = NULL;
1049 this->ike_sa_init_data.proposals = NULL;
1050 this->message_id_out = 0;
1051 this->message_id_in = 0;
1052
1053
1054 /* at creation time, IKE_SA isn't in a specific state */
1055 this->state = NO_STATE;
1056
1057 return (&this->public);
1058 }