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