(no commit message)
[strongswan.git] / Source / charon / sa / states / responder_init.c
1 /**
2 * @file responder_init.c
3 *
4 * @brief Start state of a IKE_SA as responder
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "responder_init.h"
24
25 #include <globals.h>
26 #include <sa/states/state.h>
27 #include <sa/states/ike_sa_init_responded.h>
28 #include <utils/allocator.h>
29 #include <encoding/payloads/sa_payload.h>
30 #include <encoding/payloads/ke_payload.h>
31 #include <encoding/payloads/nonce_payload.h>
32 #include <transforms/diffie_hellman.h>
33
34 /**
35 * Private data of a responder_init_t object.
36 *
37 */
38 typedef struct private_responder_init_s private_responder_init_t;
39 struct private_responder_init_s {
40 /**
41 * Methods of the state_t interface.
42 */
43 responder_init_t public;
44
45 /**
46 * Assigned IKE_SA.
47 */
48 protected_ike_sa_t *ike_sa;
49
50 /**
51 * Diffie Hellman object used to compute shared secret.
52 *
53 * After processing of incoming IKE_SA_INIT-Request the shared key is
54 * passed to the next state of type ike_sa_init_responded_t.
55 */
56 diffie_hellman_t *diffie_hellman;
57
58 /**
59 * Diffie Hellman group number.
60 */
61 u_int16_t dh_group_number;
62
63 /**
64 * Priority used to get matching dh_group number.
65 */
66 u_int16_t dh_group_priority;
67
68 /**
69 * Sent nonce value.
70 *
71 * This value is passed to the next state of type ike_sa_init_responded_t.
72 */
73 chunk_t sent_nonce;
74
75 /**
76 * Received nonce value
77 *
78 * This value is passed to the next state of type ike_sa_init_responded_t.
79 */
80 chunk_t received_nonce;
81
82 /**
83 * Logger used to log data
84 *
85 * Is logger of ike_sa!
86 */
87 logger_t *logger;
88
89 /**
90 * Proposals used to initiate connection
91 */
92 linked_list_t *proposals;
93
94 /**
95 * Builds the SA payload for this state.
96 *
97 * @param this calling object
98 * @param payload The generated SA payload object of type ke_payload_t is
99 * stored at this location.
100 * @return
101 * - SUCCESS
102 * - OUT_OF_RES
103 */
104 status_t (*build_sa_payload) (private_responder_init_t *this, payload_t **payload);
105
106 /**
107 * Builds the KE payload for this state.
108 *
109 * @param this calling object
110 * @param payload The generated KE payload object of type ke_payload_t is
111 * stored at this location.
112 * @return
113 * - SUCCESS
114 * - OUT_OF_RES
115 */
116 status_t (*build_ke_payload) (private_responder_init_t *this, payload_t **payload);
117 /**
118 * Builds the NONCE payload for this state.
119 *
120 * @param this calling object
121 * @param payload The generated NONCE payload object of type ke_payload_t is
122 * stored at this location.
123 * @return
124 * - SUCCESS
125 * - OUT_OF_RES
126 */
127 status_t (*build_nonce_payload) (private_responder_init_t *this, payload_t **payload);
128
129 /**
130 * Destroy function called internally of this class after state change succeeded.
131 *
132 * This destroy function does not destroy objects which were passed to the new state.
133 *
134 * @param this calling object
135 * @return SUCCESS in any case
136 */
137 status_t (*destroy_after_state_change) (private_responder_init_t *this);
138 };
139
140 /**
141 * Implements state_t.get_state
142 */
143 static status_t process_message(private_responder_init_t *this, message_t *message, state_t **new_state)
144 {
145 linked_list_iterator_t *payloads;
146 host_t *source, *destination;
147 status_t status;
148 message_t *response;
149 payload_t *payload;
150 packet_t *packet;
151 chunk_t shared_secret;
152 exchange_type_t exchange_type;
153 ike_sa_init_responded_t *next_state;
154
155 exchange_type = message->get_exchange_type(message);
156 if (exchange_type != IKE_SA_INIT)
157 {
158 this->logger->log(this->logger, ERROR | MORE, "Message of type %s not supported in state responder_init",mapping_find(exchange_type_m,exchange_type));
159 return FAILED;
160 }
161
162 if (!message->get_request(message))
163 {
164 this->logger->log(this->logger, ERROR | MORE, "Only requests of type IKE_SA_INIT supported in state responder_init");
165 return FAILED;
166 }
167
168 /* this is the first message we process, so copy host infos */
169 message->get_source(message, &source);
170 message->get_destination(message, &destination);
171
172 /* we need to clone them, since we destroy the message later */
173 destination->clone(destination, &(this->ike_sa->me.host));
174 source->clone(source, &(this->ike_sa->other.host));
175
176 /* parse incoming message */
177 status = message->parse_body(message);
178 if (status != SUCCESS)
179 {
180 this->logger->log(this->logger, ERROR | MORE, "Could not parse body of request message");
181 return status;
182 }
183
184 /* iterate over incoming payloads. We can be sure, the message contains only accepted payloads! */
185 status = message->get_payload_iterator(message, &payloads);
186 if (status != SUCCESS)
187 {
188 this->logger->log(this->logger, ERROR, "Fatal error: Could not get payload interator");
189 return status;
190 }
191
192 while (payloads->has_next(payloads))
193 {
194 payload_t *payload;
195
196 /* get current payload */
197 payloads->current(payloads, (void**)&payload);
198
199 this->logger->log(this->logger, CONTROL|MORE, "Processing payload of type %s", mapping_find(payload_type_m, payload->get_type(payload)));
200 switch (payload->get_type(payload))
201 {
202 case SECURITY_ASSOCIATION:
203 {
204 sa_payload_t *sa_payload = (sa_payload_t*)payload;
205 linked_list_iterator_t *suggested_proposals, *accepted_proposals;
206 encryption_algorithm_t encryption_algorithm = ENCR_UNDEFINED;
207 pseudo_random_function_t pseudo_random_function = PRF_UNDEFINED;
208 integrity_algorithm_t integrity_algorithm = AUTH_UNDEFINED;
209
210 status = this->proposals->create_iterator(this->proposals, &accepted_proposals, FALSE);
211 if (status != SUCCESS)
212 {
213 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on list for proposals");
214 payloads->destroy(payloads);
215 return status;
216 }
217
218 /* get the list of suggested proposals */
219 status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
220 if (status != SUCCESS)
221 {
222 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on suggested proposals");
223 accepted_proposals->destroy(accepted_proposals);
224 payloads->destroy(payloads);
225 return status;
226 }
227
228 /* now let the configuration-manager select a subset of the proposals */
229 status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
230 this->ike_sa->other.host, suggested_proposals, accepted_proposals);
231 if (status != SUCCESS)
232 {
233 this->logger->log(this->logger, CONTROL | MORE, "No proposal of suggested proposals selected");
234 suggested_proposals->destroy(suggested_proposals);
235 accepted_proposals->destroy(accepted_proposals);
236 payloads->destroy(payloads);
237 return status;
238 }
239
240 /* iterators are not needed anymore */
241 suggested_proposals->destroy(suggested_proposals);
242
243
244 /* now let the configuration-manager return the transforms for the given proposal*/
245 this->logger->log(this->logger, CONTROL | MOST, "Get transforms for accepted proposal");
246 status = global_configuration_manager->get_transforms_for_host_and_proposals(global_configuration_manager,
247 this->ike_sa->other.host, accepted_proposals, &encryption_algorithm,&pseudo_random_function,&integrity_algorithm);
248 if (status != SUCCESS)
249 {
250 this->logger->log(this->logger, ERROR | MORE, "Accepted proposals not supported?!");
251 accepted_proposals->destroy(accepted_proposals);
252 payloads->destroy(payloads);
253 return status;
254 }
255 accepted_proposals->destroy(accepted_proposals);
256
257 this->ike_sa->prf = prf_create(pseudo_random_function);
258 if (this->ike_sa->prf == NULL)
259 {
260 this->logger->log(this->logger, ERROR | MORE, "PRF type not supported");
261 payloads->destroy(payloads);
262 return FAILED;
263 }
264
265 this->logger->log(this->logger, CONTROL | MORE, "SA Payload processed");
266 /* ok, we have what we need for sa_payload (proposals are stored in this->proposals)*/
267 break;
268 }
269 case KEY_EXCHANGE:
270 {
271 ke_payload_t *ke_payload = (ke_payload_t*)payload;
272 diffie_hellman_group_t group;
273 diffie_hellman_t *dh;
274 bool allowed_group;
275
276 group = ke_payload->get_dh_group_number(ke_payload);
277
278 status = global_configuration_manager->is_dh_group_allowed_for_host(global_configuration_manager,
279 this->ike_sa->other.host, group, &allowed_group);
280
281 if (status != SUCCESS)
282 {
283 this->logger->log(this->logger, ERROR | MORE, "Could not get informations about DH group");
284 payloads->destroy(payloads);
285 return status;
286 }
287 if (!allowed_group)
288 {
289 /** @todo Send info reply */
290 }
291
292 /* create diffie hellman object to handle DH exchange */
293 dh = diffie_hellman_create(group);
294 if (dh == NULL)
295 {
296 this->logger->log(this->logger, ERROR, "Could not generate DH object");
297 payloads->destroy(payloads);
298 return OUT_OF_RES;
299 }
300
301 this->logger->log(this->logger, CONTROL | MORE, "Set other DH public value");
302
303 status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
304 if (status != SUCCESS)
305 {
306 this->logger->log(this->logger, ERROR, "Could not set other DH public value");
307 dh->destroy(dh);
308 payloads->destroy(payloads);
309 return OUT_OF_RES;
310 }
311
312 this->diffie_hellman = dh;
313
314 this->logger->log(this->logger, CONTROL | MORE, "KE Payload processed");
315 break;
316 }
317 case NONCE:
318 {
319 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
320
321 if (this->received_nonce.ptr != NULL)
322 {
323 this->logger->log(this->logger, CONTROL | MOST, "Destroy stored received nonce");
324 allocator_free(this->received_nonce.ptr);
325 this->received_nonce.ptr = NULL;
326 this->received_nonce.len = 0;
327 }
328
329 this->logger->log(this->logger, CONTROL | MORE, "Get nonce value and store it");
330 status = nonce_payload->get_nonce(nonce_payload, &(this->received_nonce));
331 if (status != SUCCESS)
332 {
333 this->logger->log(this->logger, ERROR, "Fatal error: Could not get nonce");
334 payloads->destroy(payloads);
335 return OUT_OF_RES;
336 }
337
338 this->logger->log(this->logger, CONTROL | MORE, "Nonce Payload processed");
339 break;
340 }
341 default:
342 {
343 this->logger->log(this->logger, ERROR | MORE, "Payload type not supported!");
344 payloads->destroy(payloads);
345 return OUT_OF_RES;
346 }
347
348 }
349
350 }
351 /* iterator can be destroyed */
352 payloads->destroy(payloads);
353
354 this->logger->log(this->logger, CONTROL | MORE, "Request successfully handled. Going to create reply.");
355
356 this->logger->log(this->logger, CONTROL | MOST, "Going to create nonce.");
357 if (this->ike_sa->randomizer->allocate_pseudo_random_bytes(this->ike_sa->randomizer, NONCE_SIZE, &(this->sent_nonce)) != SUCCESS)
358 {
359 this->logger->log(this->logger, ERROR, "Could not create nonce!");
360 return OUT_OF_RES;
361 }
362
363 /* store shared secret */
364 this->logger->log(this->logger, CONTROL | MOST, "Retrieve shared secret and store it");
365 status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &shared_secret);
366 this->logger->log_chunk(this->logger, PRIVATE, "Shared secret", &shared_secret);
367
368 status = this->ike_sa->compute_secrets(this->ike_sa,shared_secret,this->received_nonce, this->sent_nonce);
369 if (status != SUCCESS)
370 {
371 /* secrets could not be computed */
372 this->logger->log(this->logger, ERROR | MORE, "Secrets could not be computed!");
373 return status;
374 }
375
376
377
378 /* set up the reply */
379 status = this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response);
380 if (status != SUCCESS)
381 {
382 this->logger->log(this->logger, ERROR, "Could not create empty message");
383 return status;
384 }
385
386 /* build SA payload */
387 status = this->build_sa_payload(this, &payload);
388 if (status != SUCCESS)
389 {
390 this->logger->log(this->logger, ERROR, "Could not build SA payload");
391 return status;
392 }
393
394 this ->logger->log(this->logger, CONTROL|MOST, "add SA payload to message");
395 status = response->add_payload(response, payload);
396 if (status != SUCCESS)
397 {
398 this->logger->log(this->logger, ERROR, "Could not add SA payload to message");
399 return status;
400 }
401
402 /* build KE payload */
403 status = this->build_ke_payload(this,&payload);
404 if (status != SUCCESS)
405 {
406 this->logger->log(this->logger, ERROR, "Could not build KE payload");
407 return status;
408 }
409
410 this ->logger->log(this->logger, CONTROL|MOST, "add KE payload to message");
411 status = response->add_payload(response, payload);
412 if (status != SUCCESS)
413 {
414 this->logger->log(this->logger, ERROR, "Could not add KE payload to message");
415 return status;
416 }
417
418 /* build Nonce payload */
419 status = this->build_nonce_payload(this, &payload);
420 if (status != SUCCESS)
421 {
422 this->logger->log(this->logger, ERROR, "Could not build NONCE payload");
423 return status;
424 }
425
426 this ->logger->log(this->logger, CONTROL|MOST, "add nonce payload to message");
427 status = response->add_payload(response, payload);
428 if (status != SUCCESS)
429 {
430 this->logger->log(this->logger, ERROR, "Could not add nonce payload to message");
431 return status;
432 }
433
434 /* generate packet */
435 this ->logger->log(this->logger, CONTROL|MOST, "generate packet from message");
436 status = response->generate(response, &packet);
437 if (status != SUCCESS)
438 {
439 this->logger->log(this->logger, ERROR, "Fatal error: could not generate packet from message");
440 return status;
441 }
442
443 this ->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
444 status = global_send_queue->add(global_send_queue, packet);
445 if (status != SUCCESS)
446 {
447 this->logger->log(this->logger, ERROR, "Could not add packet to send queue");
448 return status;
449 }
450
451 /* state can now be changed */
452 this ->logger->log(this->logger, CONTROL|MOST, "Create next state object");
453
454 next_state = ike_sa_init_responded_create(this->ike_sa, shared_secret, this->received_nonce, this->sent_nonce);
455
456 if (next_state == NULL)
457 {
458 this ->logger->log(this->logger, ERROR, "Fatal error: could not create next state object of type ike_sa_init_responded_t");
459 allocator_free_chunk(shared_secret);
460 return FAILED;
461 }
462
463 if ( this->ike_sa->last_responded_message != NULL)
464 {
465 /* destroy message */
466 this ->logger->log(this->logger, CONTROL|MOST, "Destroy stored last responded message");
467 this->ike_sa->last_responded_message->destroy(this->ike_sa->last_responded_message);
468 }
469 this->ike_sa->last_responded_message = response;
470
471 /* message counter can now be increased */
472 this ->logger->log(this->logger, CONTROL|MOST, "Increate message counter for incoming messages");
473 this->ike_sa->message_id_in++;
474
475 *new_state = (state_t *) next_state;
476 /* state has NOW changed :-) */
477 this ->logger->log(this->logger, CONTROL|MORE, "Changed state of IKE_SA from %s to %s",mapping_find(ike_sa_state_m,RESPONDER_INIT),mapping_find(ike_sa_state_m,IKE_SA_INIT_RESPONDED) );
478
479 this ->logger->log(this->logger, CONTROL|MOST, "Destroy old sate object");
480 this->destroy_after_state_change(this);
481
482 return SUCCESS;
483 }
484
485 /**
486 * implements private_initiator_init_t.build_sa_payload
487 */
488 static status_t build_sa_payload(private_responder_init_t *this, payload_t **payload)
489 {
490 sa_payload_t* sa_payload;
491 linked_list_iterator_t *proposal_iterator;
492 status_t status;
493
494
495 /* SA payload takes proposals from this->ike_sa_init_data.proposals and writes them to the created sa_payload */
496
497 this->logger->log(this->logger, CONTROL|MORE, "building sa payload");
498
499 status = this->proposals->create_iterator(this->proposals, &proposal_iterator, FALSE);
500 if (status != SUCCESS)
501 {
502 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on list for proposals");
503 return status;
504 }
505
506 sa_payload = sa_payload_create();
507 if (sa_payload == NULL)
508 {
509 this->logger->log(this->logger, ERROR, "Fatal error: Could not create SA payload object");
510 return OUT_OF_RES;
511 }
512
513 while (proposal_iterator->has_next(proposal_iterator))
514 {
515 proposal_substructure_t *current_proposal;
516 proposal_substructure_t *current_proposal_clone;
517 status = proposal_iterator->current(proposal_iterator,(void **) &current_proposal);
518 if (status != SUCCESS)
519 {
520 this->logger->log(this->logger, ERROR, "Could not get current proposal needed to copy");
521 proposal_iterator->destroy(proposal_iterator);
522 sa_payload->destroy(sa_payload);
523 return status;
524 }
525 status = current_proposal->clone(current_proposal,&current_proposal_clone);
526 if (status != SUCCESS)
527 {
528 this->logger->log(this->logger, ERROR, "Could not clone current proposal");
529 proposal_iterator->destroy(proposal_iterator);
530 sa_payload->destroy(sa_payload);
531 return status;
532 }
533
534 status = sa_payload->add_proposal_substructure(sa_payload,current_proposal_clone);
535 if (status != SUCCESS)
536 {
537 this->logger->log(this->logger, ERROR, "Could not add cloned proposal to SA payload");
538 proposal_iterator->destroy(proposal_iterator);
539 sa_payload->destroy(sa_payload);
540 return status;
541 }
542
543 }
544
545 proposal_iterator->destroy(proposal_iterator);
546
547 this->logger->log(this->logger, CONTROL|MORE, "sa payload builded");
548
549 *payload = (payload_t *) sa_payload;
550
551 return SUCCESS;
552 }
553
554 /**
555 * implements private_initiator_init_t.build_ke_payload
556 */
557 static status_t build_ke_payload(private_responder_init_t *this, payload_t **payload)
558 {
559 ke_payload_t *ke_payload;
560 chunk_t key_data;
561 status_t status;
562
563 this->logger->log(this->logger, CONTROL|MORE, "building ke payload");
564
565
566 this ->logger->log(this->logger, CONTROL|MORE, "get public dh value to send in ke payload");
567 status = this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data);
568 if (status != SUCCESS)
569 {
570 this->logger->log(this->logger, ERROR, "Could not get my DH public value");
571 return status;
572 }
573
574 ke_payload = ke_payload_create();
575 if (ke_payload == NULL)
576 {
577 this->logger->log(this->logger, ERROR, "Could not create KE payload");
578 allocator_free_chunk(key_data);
579 return OUT_OF_RES;
580 }
581 ke_payload->set_dh_group_number(ke_payload, MODP_1024_BIT);
582 if (ke_payload->set_key_exchange_data(ke_payload, key_data) != SUCCESS)
583 {
584 this->logger->log(this->logger, ERROR, "Could not set key exchange data of KE payload");
585 ke_payload->destroy(ke_payload);
586 allocator_free_chunk(key_data);
587 return OUT_OF_RES;
588 }
589 allocator_free_chunk(key_data);
590
591 *payload = (payload_t *) ke_payload;
592 return SUCCESS;
593 }
594
595 /**
596 * implements private_initiator_init_t.build_nonce_payload
597 */
598 static status_t build_nonce_payload(private_responder_init_t *this, payload_t **payload)
599 {
600 nonce_payload_t *nonce_payload;
601 status_t status;
602
603 this->logger->log(this->logger, CONTROL|MORE, "building nonce payload");
604
605 nonce_payload = nonce_payload_create();
606 if (nonce_payload == NULL)
607 {
608 this->logger->log(this->logger, ERROR, "Fatal error: could not create nonce payload object");
609 return OUT_OF_RES;
610 }
611
612 status = nonce_payload->set_nonce(nonce_payload, this->sent_nonce);
613
614 if (status != SUCCESS)
615 {
616 this->logger->log(this->logger, ERROR, "Fatal error: could not set nonce data of payload");
617 nonce_payload->destroy(nonce_payload);
618 return status;
619 }
620
621 *payload = (payload_t *) nonce_payload;
622
623 return SUCCESS;
624 }
625
626
627 /**
628 * Implements state_t.get_state
629 */
630 static ike_sa_state_t get_state(private_responder_init_t *this)
631 {
632 return RESPONDER_INIT;
633 }
634
635 /**
636 * Implements state_t.get_state
637 */
638 static status_t destroy(private_responder_init_t *this)
639 {
640 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy responder init state object");
641
642 /* destroy stored proposal */
643 this->logger->log(this->logger, CONTROL | MOST, "Destroy stored proposals");
644 while (this->proposals->get_count(this->proposals) > 0)
645 {
646 proposal_substructure_t *current_proposal;
647 this->proposals->remove_first(this->proposals,(void **)&current_proposal);
648 current_proposal->destroy(current_proposal);
649 }
650 this->proposals->destroy(this->proposals);
651
652 if (this->sent_nonce.ptr != NULL)
653 {
654 this->logger->log(this->logger, CONTROL | MOST, "Destroy sent nonce");
655 allocator_free(this->sent_nonce.ptr);
656 }
657
658 if (this->received_nonce.ptr != NULL)
659 {
660 this->logger->log(this->logger, CONTROL | MOST, "Destroy received nonce");
661 allocator_free(this->received_nonce.ptr);
662 }
663
664 /* destroy diffie hellman object */
665 if (this->diffie_hellman != NULL)
666 {
667 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie_hellman_t object");
668 this->diffie_hellman->destroy(this->diffie_hellman);
669 }
670
671 allocator_free(this);
672
673 return SUCCESS;
674
675 }
676
677 /**
678 * Implements private_responder_init_t.destroy_after_state_change
679 */
680 static status_t destroy_after_state_change (private_responder_init_t *this)
681 {
682 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy responder_init_t state object");
683
684 /* destroy stored proposal */
685 this->logger->log(this->logger, CONTROL | MOST, "Destroy stored proposals");
686 while (this->proposals->get_count(this->proposals) > 0)
687 {
688 proposal_substructure_t *current_proposal;
689 this->proposals->remove_first(this->proposals,(void **)&current_proposal);
690 current_proposal->destroy(current_proposal);
691 }
692 this->proposals->destroy(this->proposals);
693
694 /* destroy diffie hellman object */
695 if (this->diffie_hellman != NULL)
696 {
697 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie_hellman_t object");
698 this->diffie_hellman->destroy(this->diffie_hellman);
699 }
700
701 allocator_free(this);
702 return SUCCESS;
703 }
704
705 /*
706 * Described in header.
707 */
708 responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
709 {
710 private_responder_init_t *this = allocator_alloc_thing(private_responder_init_t);
711
712 if (this == NULL)
713 {
714 return NULL;
715 }
716
717 /* interface functions */
718 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *,state_t **)) process_message;
719 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
720 this->public.state_interface.destroy = (status_t (*) (state_t *)) destroy;
721
722 /* private functions */
723 this->build_sa_payload = build_sa_payload;
724 this->build_ke_payload = build_ke_payload;
725 this->build_nonce_payload = build_nonce_payload;
726 this->destroy_after_state_change = destroy_after_state_change;
727
728 /* private data */
729 this->ike_sa = ike_sa;
730 this->logger = this->ike_sa->logger;
731 this->sent_nonce.ptr = NULL;
732 this->sent_nonce.len = 0;
733 this->received_nonce.ptr = NULL;
734 this->received_nonce.len = 0;
735 this->proposals = linked_list_create();
736 if (this->proposals == NULL)
737 {
738 allocator_free(this);
739 return NULL;
740 }
741
742 return &(this->public);
743 }