3e85ea5faf64eeaccefd47bd3805fac4707ba7b5
[strongswan.git] / src / charon / sa / states / responder_init.c
1 /**
2 * @file responder_init.c
3 *
4 * @brief Implementation of responder_init_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
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 "responder_init.h"
25
26 #include <daemon.h>
27 #include <sa/states/state.h>
28 #include <sa/states/ike_sa_init_responded.h>
29 #include <encoding/payloads/sa_payload.h>
30 #include <encoding/payloads/ke_payload.h>
31 #include <encoding/payloads/nonce_payload.h>
32 #include <encoding/payloads/notify_payload.h>
33 #include <crypto/diffie_hellman.h>
34 #include <queues/jobs/send_keepalive_job.h>
35
36
37 typedef struct private_responder_init_t private_responder_init_t;
38
39 /**
40 * Private data of a responder_init_t object.
41 *
42 */
43 struct private_responder_init_t {
44 /**
45 * Methods of the state_t interface.
46 */
47 responder_init_t public;
48
49 /**
50 * Assigned IKE_SA.
51 */
52 protected_ike_sa_t *ike_sa;
53
54 /**
55 * Diffie Hellman object used to compute shared secret.
56 */
57 diffie_hellman_t *diffie_hellman;
58
59 /**
60 * Diffie Hellman group number from selected IKE proposal.
61 */
62 u_int16_t dh_group_number;
63
64 /**
65 * Priority used to get matching dh_group number.
66 */
67 u_int16_t dh_group_priority;
68
69 /**
70 * Sent nonce value.
71 *
72 * This value is passed to the next state of type IKE_SA_INIT_RESPONDED.
73 */
74 chunk_t sent_nonce;
75
76 /**
77 * Received nonce value
78 *
79 * This value is passed to the next state of type IKE_SA_INIT_RESPONDED.
80 */
81 chunk_t received_nonce;
82
83 /**
84 * Selected proposal
85 */
86 proposal_t *proposal;
87
88 /**
89 * Logger used to log data .
90 *
91 * Is logger of ike_sa!
92 */
93 logger_t *logger;
94
95 /**
96 * Precomputed NAT-D hash for initiator.
97 */
98 chunk_t natd_hash_i;
99
100 /**
101 * Flag indicating that an initiator NAT-D hash matched.
102 */
103 bool natd_hash_i_matched;
104
105 /**
106 * NAT-D payload count for NAT_DETECTION_SOURCE_IP.
107 */
108 int natd_seen_i;
109
110 /**
111 * Precomputed NAT-D hash of responder.
112 */
113 chunk_t natd_hash_r;
114
115 /**
116 * Flag indicating that a responder NAT-D hash matched.
117 */
118 bool natd_hash_r_matched;
119
120 /**
121 * NAT-D payload count for NAT_DETECTION_DESTINATION_IP.
122 */
123 int natd_seen_r;
124
125
126 /**
127 * Handles received SA payload and builds the SA payload for the response.
128 *
129 * @param this calling object
130 * @param sa_request The received SA payload
131 * @param response the SA payload is added to this response message_t object.
132 * @return
133 * - DESTROY_ME
134 * - SUCCESS
135 */
136 status_t (*build_sa_payload) (private_responder_init_t *this,sa_payload_t *sa_request, message_t *response);
137
138 /**
139 * Handles received KE payload and builds the KE payload for the response.
140 *
141 * @param this calling object
142 * @param ke_request The received KE payload
143 * @param response the KE payload is added to this response message_t object.
144 * - DESTROY_ME
145 * - SUCCESS
146 */
147 status_t (*build_ke_payload) (private_responder_init_t *this,ke_payload_t *ke_request, message_t *response);
148
149 /**
150 * Handles received NONCE payload and builds the NONCE payload for the response.
151 *
152 * @param this calling object
153 * @param nonce_request The received NONCE payload
154 * @param response the NONCE payload is added to this response message_t object.
155 * - DESTROY_ME
156 * - SUCCESS
157 */
158 status_t (*build_nonce_payload) (private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response);
159
160 /**
161 * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and
162 * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state.
163 *
164 * @param this calling object
165 * @param request message_t object to add the Notify payloads
166 */
167 void (*build_natd_payload) (private_responder_init_t *this, message_t *request, notify_message_type_t type, host_t *host);
168
169 /**
170 * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and
171 * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state.
172 *
173 * @param this calling object
174 * @param request message_t object to add the Notify payloads
175 */
176 void (*build_natd_payloads) (private_responder_init_t *this, message_t *request);
177
178 /**
179 * Sends a IKE_SA_INIT reply containing a notify payload.
180 *
181 * @param this calling object
182 * @param notify_payload notify_payload to process
183 */
184 status_t (*process_notify_payload) (private_responder_init_t *this, notify_payload_t *notify_payload);
185
186 /**
187 * Destroy function called internally of this class after change
188 * to state IKE_SA_INIT_RESPONDED succeeded.
189 *
190 * This destroy function does not destroy objects which were passed to the new state.
191 *
192 * @param this calling object
193 */
194 void (*destroy_after_state_change) (private_responder_init_t *this);
195
196 };
197
198 /**
199 * Implementation of state_t.process_message.
200 */
201 static status_t process_message(private_responder_init_t *this, message_t *message)
202 {
203 ike_sa_init_responded_t *next_state;
204 chunk_t ike_sa_init_response_data;
205 chunk_t ike_sa_init_request_data;
206 sa_payload_t *sa_request = NULL;
207 ke_payload_t *ke_request = NULL;
208 nonce_payload_t *nonce_request = NULL;
209 host_t *source, *destination;
210 connection_t *connection;
211 iterator_t *payloads;
212 message_t *response;
213 status_t status;
214
215 if (message->get_exchange_type(message) != IKE_SA_INIT)
216 {
217 this->logger->log(this->logger, ERROR | LEVEL1, "message of type %s not supported in state responder_init",
218 mapping_find(exchange_type_m,message->get_exchange_type(message)));
219 return DESTROY_ME;
220 }
221 if (!message->get_request(message))
222 {
223 this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT responses not allowed in state ike_sa_init_responded");
224 return DESTROY_ME;
225 }
226
227 /* this is the first message to process, so get host infos */
228 source = message->get_source(message);
229 destination = message->get_destination(message);
230
231 connection = charon->connections->get_connection_by_hosts(charon->connections, destination, source);
232 if (connection == NULL)
233 {
234 /* no configuration matches given hosts */
235 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request does not match any available connection, deleting IKE_SA");
236 /* TODO: inform requestor */
237 return DESTROY_ME;
238 }
239 this->ike_sa->set_connection(this->ike_sa, connection);
240 status = this->ike_sa->update_connection_hosts(this->ike_sa,
241 destination, source);
242 if (status != SUCCESS)
243 {
244 return status;
245 }
246
247 /* parse incoming message */
248 status = message->parse_body(message, NULL, NULL);
249 if (status != SUCCESS)
250 {
251 if (status == NOT_SUPPORTED)
252 {
253 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request contains unsupported payload with critical flag set, "
254 "deleting IKE_SA");
255 this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER);
256 }
257 else
258 {
259 this->logger->log(this->logger, AUDIT, "unable to parse IKE_SA_INIT request, deleting IKE_SA");
260 }
261 return DESTROY_ME;
262 }
263
264 /*
265 * Precompute NAT-D hashes.
266 * Even though there SHOULD only be a single payload of Notify type
267 * NAT_DETECTION_DESTINATION_IP we precompute both hashes.
268 */
269 this->natd_hash_i = this->ike_sa->generate_natd_hash(this->ike_sa,
270 message->get_initiator_spi(message),
271 message->get_responder_spi(message),
272 message->get_source(message));
273 this->natd_hash_i_matched = FALSE;
274 this->natd_seen_i = 0;
275 this->natd_hash_r = this->ike_sa->generate_natd_hash(this->ike_sa,
276 message->get_initiator_spi(message),
277 message->get_responder_spi(message),
278 message->get_destination(message));
279 this->natd_hash_r_matched = FALSE;
280 this->natd_seen_r = 0;
281 this->ike_sa->set_my_host_behind_nat(this->ike_sa, FALSE);
282 this->ike_sa->set_other_host_behind_nat(this->ike_sa, FALSE);
283
284 /* Iterate over all payloads.
285 *
286 * The message is already checked for the right payload types.
287 */
288 payloads = message->get_payload_iterator(message);
289 while (payloads->has_next(payloads))
290 {
291 payload_t *payload;
292
293 payloads->current(payloads, (void**)&payload);
294
295 switch (payload->get_type(payload))
296 {
297 case SECURITY_ASSOCIATION:
298 {
299 sa_request = (sa_payload_t*)payload;
300 break;
301 }
302 case KEY_EXCHANGE:
303 {
304 ke_request = (ke_payload_t*)payload;
305 break;
306 }
307 case NONCE:
308 {
309 nonce_request = (nonce_payload_t*)payload;
310 break;
311 }
312 case NOTIFY:
313 {
314 notify_payload_t *notify_payload = (notify_payload_t *) payload;
315 status = this->process_notify_payload(this, notify_payload);
316 if (status != SUCCESS)
317 {
318 payloads->destroy(payloads);
319 return status;
320 }
321 break;
322 }
323 default:
324 {
325 this->logger->log(this->logger, ERROR|LEVEL1, "ignoring payload %s (%d)",
326 mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
327 break;
328 }
329 }
330 }
331 payloads->destroy(payloads);
332
333 /* check if we have all payloads */
334 if (!(sa_request && ke_request && nonce_request))
335 {
336 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain all required payloads. Deleting IKE_SA");
337 return DESTROY_ME;
338 }
339
340 /* NAT-D */
341 if ((!this->natd_seen_i && this->natd_seen_r > 0)
342 || (this->natd_seen_i > 0 && !this->natd_seen_r))
343 {
344 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request contained wrong number of NAT-D payloads. Deleting IKE_SA");
345 return DESTROY_ME;
346 }
347 if (this->natd_seen_r > 1)
348 {
349 this->logger->log(this->logger, AUDIT, "Warning: IKE_SA_INIT request contained multiple Notify(NAT_DETECTION_DESTINATION_IP) payloads.");
350 }
351 if (this->natd_seen_i > 0 && !this->natd_hash_i_matched)
352 {
353 this->logger->log(this->logger, AUDIT, "Remote host is behind NAT, using NAT-T.");
354 this->ike_sa->set_other_host_behind_nat(this->ike_sa, TRUE);
355 }
356 if (this->natd_seen_r > 0 && !this->natd_hash_r_matched)
357 {
358 this->logger->log(this->logger, AUDIT, "Local host is behind NAT, using NAT-T.");
359 this->ike_sa->set_my_host_behind_nat(this->ike_sa, TRUE);
360 charon->event_queue->add_relative(charon->event_queue,
361 (job_t*)send_keepalive_job_create(this->ike_sa->public.get_id((ike_sa_t*)this->ike_sa)),
362 charon->configuration->get_keepalive_interval(charon->configuration));
363 }
364 if (!this->ike_sa->public.is_any_host_behind_nat((ike_sa_t*)this->ike_sa))
365 {
366 this->logger->log(this->logger, AUDIT, "No NAT detected, not using NAT-T.");
367 }
368
369 this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response);
370
371 status = this->build_sa_payload(this, sa_request, response);
372 if (status != SUCCESS)
373 {
374 response->destroy(response);
375 return status;
376 }
377
378 status = this->build_ke_payload(this, ke_request, response);
379 if (status != SUCCESS)
380 {
381 response->destroy(response);
382 return status;
383 }
384
385 status = this->build_nonce_payload(this, nonce_request, response);
386 if (status != SUCCESS)
387 {
388 response->destroy(response);
389 return status;
390 }
391 /* build Notify(NAT-D) payloads */
392 this->build_natd_payloads(this, response);
393
394 /* derive all the keys used in the IKE_SA */
395 status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->received_nonce, this->sent_nonce);
396 if (status != SUCCESS)
397 {
398 this->logger->log(this->logger, AUDIT, "transform objects could not be created from selected proposal, deleting IKE_SA");
399 return DESTROY_ME;
400 }
401
402 /* message can now be sent (must not be destroyed) */
403 status = this->ike_sa->send_response(this->ike_sa, response);
404 if (status != SUCCESS)
405 {
406 this->logger->log(this->logger, AUDIT, "unable to send IKE_SA_INIT response, deleting IKE_SA");
407 response->destroy(response);
408 return DESTROY_ME;
409 }
410
411 /* state can now be changed */
412 this->logger->log(this->logger, CONTROL|LEVEL2, "create next state object of type IKE_SA_INIT_RESPONDED");
413
414 response = this->ike_sa->get_last_responded_message(this->ike_sa);
415 ike_sa_init_response_data = response->get_packet_data(response);
416 ike_sa_init_request_data = message->get_packet_data(message);
417
418 next_state = ike_sa_init_responded_create(this->ike_sa, this->received_nonce, this->sent_nonce,ike_sa_init_request_data,
419 ike_sa_init_response_data);
420
421 /* state can now be changed */
422 this->ike_sa->set_new_state(this->ike_sa, (state_t *) next_state);
423 this->destroy_after_state_change(this);
424
425 return SUCCESS;
426 }
427
428 /**
429 * Implementation of private_initiator_init_t.build_sa_payload.
430 */
431 static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response)
432 {
433 proposal_t *proposal;
434 linked_list_t *proposal_list;
435 connection_t *connection;
436 sa_payload_t* sa_payload;
437 algorithm_t *algo;
438
439 connection = this->ike_sa->get_connection(this->ike_sa);
440
441 this->logger->log(this->logger, CONTROL | LEVEL2, "process received SA payload");
442
443 /* get the list of suggested proposals */
444 proposal_list = sa_request->get_proposals (sa_request);
445
446 /* select proposal */
447 this->proposal = connection->select_proposal(connection, proposal_list);
448 while(proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
449 {
450 proposal->destroy(proposal);
451 }
452 proposal_list->destroy(proposal_list);
453 if (this->proposal == NULL)
454 {
455 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any acceptable proposals, deleting IKE_SA");
456 this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER);
457 return DESTROY_ME;
458 }
459 /* get selected DH group to force policy, this is very restrictive!? */
460 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo))
461 {
462 this->dh_group_number = algo->algorithm;
463 }
464
465 this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed");
466
467 this->logger->log(this->logger, CONTROL|LEVEL2, "building SA payload");
468 sa_payload = sa_payload_create_from_proposal(this->proposal);
469 this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message");
470 response->add_payload(response,(payload_t *) sa_payload);
471
472 return SUCCESS;
473 }
474
475 /**
476 * Implementation of private_initiator_init_t.build_ke_payload.
477 */
478 static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *response)
479 {
480 diffie_hellman_group_t group;
481 ke_payload_t *ke_payload;
482 diffie_hellman_t *dh;
483 chunk_t key_data;
484
485 this->logger->log(this->logger, CONTROL | LEVEL2, "process received KE payload");
486 group = ke_request->get_dh_group_number(ke_request);
487
488 if (group == MODP_NONE)
489 {
490 this->logger->log(this->logger, AUDIT, "no Diffie-Hellman group to select, deleting IKE_SA");
491 return DESTROY_ME;
492 }
493
494 if (this->dh_group_number != group)
495 {
496 u_int16_t accepted_group;
497 chunk_t accepted_group_chunk;
498 /* group not same as selected one
499 * Maybe key exchange payload is before SA payload */
500 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain an acceptable Diffie-Hellman group, deleting IKE_SA");
501
502 accepted_group = htons(this->dh_group_number);
503 accepted_group_chunk.ptr = (u_int8_t*) &(accepted_group);
504 accepted_group_chunk.len = 2;
505 this->ike_sa->send_notify(this->ike_sa,IKE_SA_INIT,INVALID_KE_PAYLOAD,accepted_group_chunk);
506 return DESTROY_ME;
507 }
508
509 /* create diffie hellman object to handle DH exchange */
510 dh = diffie_hellman_create(group);
511 if (dh == NULL)
512 {
513 this->logger->log(this->logger, AUDIT, "could not generate DH object with group %d, deleting IKE_SA",
514 mapping_find(diffie_hellman_group_m,group) );
515 return DESTROY_ME;
516 }
517 this->logger->log(this->logger, CONTROL | LEVEL2, "set other DH public value");
518
519 dh->set_other_public_value(dh, ke_request->get_key_exchange_data(ke_request));
520
521 this->diffie_hellman = dh;
522
523 this->logger->log(this->logger, CONTROL | LEVEL2, "KE payload processed.");
524
525 this->logger->log(this->logger, CONTROL|LEVEL2, "building KE payload");
526 this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data);
527
528 ke_payload = ke_payload_create();
529 ke_payload->set_key_exchange_data(ke_payload,key_data);
530 ke_payload->set_dh_group_number(ke_payload, this->dh_group_number);
531 chunk_free(&key_data);
532
533 this->logger->log(this->logger, CONTROL|LEVEL2, "add KE payload to message");
534 response->add_payload(response,(payload_t *) ke_payload);
535
536 return SUCCESS;
537 }
538
539 /**
540 * Implementation of private_responder_init_t.build_nonce_payload.
541 */
542 static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response)
543 {
544 nonce_payload_t *nonce_payload;
545 randomizer_t *randomizer;
546 status_t status;
547
548 this->logger->log(this->logger, CONTROL | LEVEL2, "process received NONCE payload");
549 free(this->received_nonce.ptr);
550 this->received_nonce = CHUNK_INITIALIZER;
551
552 this->logger->log(this->logger, CONTROL | LEVEL2, "get NONCE value and store it");
553 this->received_nonce = nonce_request->get_nonce(nonce_request);
554
555 this->logger->log(this->logger, CONTROL | LEVEL2, "create new NONCE value.");
556
557 randomizer = this->ike_sa->get_randomizer(this->ike_sa);
558 status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce));
559 if (status != SUCCESS)
560 {
561 return status;
562 }
563
564 this->logger->log(this->logger, CONTROL|LEVEL2, "building NONCE payload");
565 nonce_payload = nonce_payload_create();
566 nonce_payload->set_nonce(nonce_payload, this->sent_nonce);
567
568 this->logger->log(this->logger, CONTROL|LEVEL2, "add NONCE payload to message");
569 response->add_payload(response,(payload_t *) nonce_payload);
570
571 return SUCCESS;
572 }
573
574 /**
575 * Implementation of private_initiator_init_t.build_natd_payload.
576 */
577 static void build_natd_payload(private_responder_init_t *this, message_t *request, notify_message_type_t type, host_t *host)
578 {
579 chunk_t hash;
580 this->logger->log(this->logger, CONTROL|LEVEL1, "Building Notify(NAT-D) payload");
581 notify_payload_t *notify_payload;
582 notify_payload = notify_payload_create();
583 /*notify_payload->set_protocol_id(notify_payload, NULL);*/
584 /*notify_payload->set_spi(notify_payload, NULL);*/
585 notify_payload->set_notify_message_type(notify_payload, type);
586 hash = this->ike_sa->generate_natd_hash(this->ike_sa,
587 request->get_initiator_spi(request),
588 request->get_responder_spi(request),
589 host);
590 notify_payload->set_notification_data(notify_payload, hash);
591 chunk_free(&hash);
592 this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify(NAT-D) payload to message");
593 request->add_payload(request, (payload_t *) notify_payload);
594 }
595
596 /**
597 * Implementation of private_initiator_init_t.build_natd_payloads.
598 */
599 static void build_natd_payloads(private_responder_init_t *this, message_t *request)
600 {
601 connection_t *connection;
602 connection = this->ike_sa->get_connection(this->ike_sa);
603 this->build_natd_payload(this, request, NAT_DETECTION_SOURCE_IP,
604 connection->get_my_host(connection));
605 this->build_natd_payload(this, request, NAT_DETECTION_DESTINATION_IP,
606 connection->get_other_host(connection));
607 }
608
609 /**
610 * Implementation of private_responder_init_t.process_notify_payload.
611 */
612 static status_t process_notify_payload(private_responder_init_t *this, notify_payload_t *notify_payload)
613 {
614 chunk_t notification_data;
615 notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload);
616
617 this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
618 mapping_find(notify_message_type_m, notify_message_type));
619 switch (notify_message_type)
620 {
621 case NAT_DETECTION_DESTINATION_IP:
622 {
623 this->natd_seen_r++;
624 if (this->natd_hash_r_matched)
625 return SUCCESS;
626
627 notification_data = notify_payload->get_notification_data(notify_payload);
628 if (chunk_equals(notification_data, this->natd_hash_r))
629 {
630 this->natd_hash_r_matched = TRUE;
631 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash match");
632 }
633 else
634 {
635 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash mismatch");
636 }
637
638 return SUCCESS;
639 }
640 case NAT_DETECTION_SOURCE_IP:
641 {
642 this->natd_seen_i++;
643 if (this->natd_hash_i_matched)
644 return SUCCESS;
645
646 notification_data = notify_payload->get_notification_data(notify_payload);
647 if (chunk_equals(notification_data, this->natd_hash_i))
648 {
649 this->natd_hash_i_matched = TRUE;
650 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash match");
651 }
652 else
653 {
654 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash mismatch");
655 }
656
657 return SUCCESS;
658 }
659 default:
660 {
661 this->logger->log(this->logger, CONTROL, "IKE_SA_INIT request contained a notify (%d), ignored.",
662 notify_message_type);
663 return SUCCESS;
664 }
665 }
666 }
667
668 /**
669 * Implementation of state_t.get_state.
670 */
671 static ike_sa_state_t get_state(private_responder_init_t *this)
672 {
673 return RESPONDER_INIT;
674 }
675
676 /**
677 * Implementation of state_t.destroy.
678 */
679 static void destroy(private_responder_init_t *this)
680 {
681 this->logger->log(this->logger, CONTROL | LEVEL1, "going to destroy responder init state object");
682
683 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy nonces");
684 chunk_free(&(this->sent_nonce));
685 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy received nonce");
686 chunk_free(&(this->received_nonce));
687
688 chunk_free(&(this->natd_hash_i));
689 chunk_free(&(this->natd_hash_r));
690
691 if (this->diffie_hellman != NULL)
692 {
693 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy diffie_hellman_t hellman object");
694 this->diffie_hellman->destroy(this->diffie_hellman);
695 }
696 if (this->proposal)
697 {
698 this->proposal->destroy(this->proposal);
699 }
700 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy object");
701 free(this);
702 }
703
704 /**
705 * Implementation of private_responder_init_t.destroy_after_state_change
706 */
707 static void destroy_after_state_change (private_responder_init_t *this)
708 {
709 this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder_init_t state object");
710
711 chunk_free(&(this->natd_hash_i));
712 chunk_free(&(this->natd_hash_r));
713
714 /* destroy diffie hellman object */
715 if (this->diffie_hellman != NULL)
716 {
717 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy diffie_hellman_t object");
718 this->diffie_hellman->destroy(this->diffie_hellman);
719 }
720 if (this->proposal)
721 {
722 this->proposal->destroy(this->proposal);
723 }
724
725 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy object");
726 free(this);
727 }
728
729 /*
730 * Described in header.
731 */
732 responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
733 {
734 private_responder_init_t *this = malloc_thing(private_responder_init_t);
735
736 /* interface functions */
737 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
738 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
739 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
740
741 /* private functions */
742 this->build_sa_payload = build_sa_payload;
743 this->build_ke_payload = build_ke_payload;
744 this->build_nonce_payload = build_nonce_payload;
745 this->destroy_after_state_change = destroy_after_state_change;
746 this->process_notify_payload = process_notify_payload;
747 this->build_natd_payload = build_natd_payload;
748 this->build_natd_payloads = build_natd_payloads;
749
750 /* private data */
751 this->ike_sa = ike_sa;
752 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
753 this->sent_nonce = CHUNK_INITIALIZER;
754 this->received_nonce = CHUNK_INITIALIZER;
755 this->dh_group_number = MODP_NONE;
756 this->diffie_hellman = NULL;
757 this->proposal = NULL;
758 this->natd_hash_i = CHUNK_INITIALIZER;
759 this->natd_hash_i_matched = FALSE;
760 this->natd_seen_i = 0;
761 this->natd_hash_r = CHUNK_INITIALIZER;
762 this->natd_hash_r_matched = FALSE;
763 this->natd_seen_r = 0;
764
765 return &(this->public);
766 }