applied new changes from NATT team
[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
392 /* build Notify(NAT-D) payloads */
393 this->build_natd_payloads(this, response);
394
395 /* derive all the keys used in the IKE_SA */
396 status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->received_nonce, this->sent_nonce);
397 if (status != SUCCESS)
398 {
399 this->logger->log(this->logger, AUDIT, "transform objects could not be created from selected proposal, deleting IKE_SA");
400 return DESTROY_ME;
401 }
402
403 /* message can now be sent (must not be destroyed) */
404 status = this->ike_sa->send_response(this->ike_sa, response);
405 if (status != SUCCESS)
406 {
407 this->logger->log(this->logger, AUDIT, "unable to send IKE_SA_INIT response, deleting IKE_SA");
408 response->destroy(response);
409 return DESTROY_ME;
410 }
411
412 /* state can now be changed */
413 this->logger->log(this->logger, CONTROL|LEVEL2, "create next state object of type IKE_SA_INIT_RESPONDED");
414
415 response = this->ike_sa->get_last_responded_message(this->ike_sa);
416 ike_sa_init_response_data = response->get_packet_data(response);
417 ike_sa_init_request_data = message->get_packet_data(message);
418
419 next_state = ike_sa_init_responded_create(this->ike_sa, this->received_nonce, this->sent_nonce,ike_sa_init_request_data,
420 ike_sa_init_response_data);
421
422 /* state can now be changed */
423 this->ike_sa->set_new_state(this->ike_sa, (state_t *) next_state);
424 this->destroy_after_state_change(this);
425
426 return SUCCESS;
427 }
428
429 /**
430 * Implementation of private_initiator_init_t.build_sa_payload.
431 */
432 static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response)
433 {
434 proposal_t *proposal;
435 linked_list_t *proposal_list;
436 connection_t *connection;
437 sa_payload_t* sa_payload;
438 algorithm_t *algo;
439
440 connection = this->ike_sa->get_connection(this->ike_sa);
441
442 this->logger->log(this->logger, CONTROL | LEVEL2, "process received SA payload");
443
444 /* get the list of suggested proposals */
445 proposal_list = sa_request->get_proposals (sa_request);
446
447 /* select proposal */
448 this->proposal = connection->select_proposal(connection, proposal_list);
449 while(proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
450 {
451 proposal->destroy(proposal);
452 }
453 proposal_list->destroy(proposal_list);
454 if (this->proposal == NULL)
455 {
456 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any acceptable proposals, deleting IKE_SA");
457 this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER);
458 return DESTROY_ME;
459 }
460 /* get selected DH group to force policy, this is very restrictive!? */
461 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo))
462 {
463 this->dh_group_number = algo->algorithm;
464 }
465
466 this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed");
467
468 this->logger->log(this->logger, CONTROL|LEVEL2, "building SA payload");
469 sa_payload = sa_payload_create_from_proposal(this->proposal);
470 this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message");
471 response->add_payload(response,(payload_t *) sa_payload);
472
473 return SUCCESS;
474 }
475
476 /**
477 * Implementation of private_initiator_init_t.build_ke_payload.
478 */
479 static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *response)
480 {
481 diffie_hellman_group_t group;
482 ke_payload_t *ke_payload;
483 diffie_hellman_t *dh;
484 chunk_t key_data;
485
486 this->logger->log(this->logger, CONTROL | LEVEL2, "process received KE payload");
487 group = ke_request->get_dh_group_number(ke_request);
488
489 if (group == MODP_NONE)
490 {
491 this->logger->log(this->logger, AUDIT, "no Diffie-Hellman group to select, deleting IKE_SA");
492 return DESTROY_ME;
493 }
494
495 if (this->dh_group_number != group)
496 {
497 u_int16_t accepted_group;
498 chunk_t accepted_group_chunk;
499 /* group not same as selected one
500 * Maybe key exchange payload is before SA payload */
501 this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain an acceptable Diffie-Hellman group, deleting IKE_SA");
502
503 accepted_group = htons(this->dh_group_number);
504 accepted_group_chunk.ptr = (u_int8_t*) &(accepted_group);
505 accepted_group_chunk.len = 2;
506 this->ike_sa->send_notify(this->ike_sa,IKE_SA_INIT,INVALID_KE_PAYLOAD,accepted_group_chunk);
507 return DESTROY_ME;
508 }
509
510 /* create diffie hellman object to handle DH exchange */
511 dh = diffie_hellman_create(group);
512 if (dh == NULL)
513 {
514 this->logger->log(this->logger, AUDIT, "could not generate DH object with group %d, deleting IKE_SA",
515 mapping_find(diffie_hellman_group_m,group) );
516 return DESTROY_ME;
517 }
518 this->logger->log(this->logger, CONTROL | LEVEL2, "set other DH public value");
519
520 dh->set_other_public_value(dh, ke_request->get_key_exchange_data(ke_request));
521
522 this->diffie_hellman = dh;
523
524 this->logger->log(this->logger, CONTROL | LEVEL2, "KE payload processed.");
525
526 this->logger->log(this->logger, CONTROL|LEVEL2, "building KE payload");
527 this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data);
528
529 ke_payload = ke_payload_create();
530 ke_payload->set_key_exchange_data(ke_payload,key_data);
531 ke_payload->set_dh_group_number(ke_payload, this->dh_group_number);
532 chunk_free(&key_data);
533
534 this->logger->log(this->logger, CONTROL|LEVEL2, "add KE payload to message");
535 response->add_payload(response,(payload_t *) ke_payload);
536
537 return SUCCESS;
538 }
539
540 /**
541 * Implementation of private_responder_init_t.build_nonce_payload.
542 */
543 static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response)
544 {
545 nonce_payload_t *nonce_payload;
546 randomizer_t *randomizer;
547 status_t status;
548
549 this->logger->log(this->logger, CONTROL | LEVEL2, "process received NONCE payload");
550 free(this->received_nonce.ptr);
551 this->received_nonce = CHUNK_INITIALIZER;
552
553 this->logger->log(this->logger, CONTROL | LEVEL2, "get NONCE value and store it");
554 this->received_nonce = nonce_request->get_nonce(nonce_request);
555
556 this->logger->log(this->logger, CONTROL | LEVEL2, "create new NONCE value.");
557
558 randomizer = this->ike_sa->get_randomizer(this->ike_sa);
559 status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce));
560 if (status != SUCCESS)
561 {
562 return status;
563 }
564
565 this->logger->log(this->logger, CONTROL|LEVEL2, "building NONCE payload");
566 nonce_payload = nonce_payload_create();
567 nonce_payload->set_nonce(nonce_payload, this->sent_nonce);
568
569 this->logger->log(this->logger, CONTROL|LEVEL2, "add NONCE payload to message");
570 response->add_payload(response,(payload_t *) nonce_payload);
571
572 return SUCCESS;
573 }
574
575 /**
576 * Implementation of private_initiator_init_t.build_natd_payload.
577 */
578 static void build_natd_payload(private_responder_init_t *this, message_t *request, notify_message_type_t type, host_t *host)
579 {
580 chunk_t hash;
581 this->logger->log(this->logger, CONTROL|LEVEL1, "Building Notify(NAT-D) payload");
582 notify_payload_t *notify_payload;
583 notify_payload = notify_payload_create();
584 /*notify_payload->set_protocol_id(notify_payload, NULL);*/
585 /*notify_payload->set_spi(notify_payload, NULL);*/
586 notify_payload->set_notify_message_type(notify_payload, type);
587 hash = this->ike_sa->generate_natd_hash(this->ike_sa,
588 request->get_initiator_spi(request),
589 request->get_responder_spi(request),
590 host);
591 notify_payload->set_notification_data(notify_payload, hash);
592 chunk_free(&hash);
593 this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify(NAT-D) payload to message");
594 request->add_payload(request, (payload_t *) notify_payload);
595 }
596
597 /**
598 * Implementation of private_initiator_init_t.build_natd_payloads.
599 */
600 static void build_natd_payloads(private_responder_init_t *this, message_t *request)
601 {
602 connection_t *connection;
603 connection = this->ike_sa->get_connection(this->ike_sa);
604 this->build_natd_payload(this, request, NAT_DETECTION_SOURCE_IP,
605 connection->get_my_host(connection));
606 this->build_natd_payload(this, request, NAT_DETECTION_DESTINATION_IP,
607 connection->get_other_host(connection));
608 }
609
610 /**
611 * Implementation of private_responder_init_t.process_notify_payload.
612 */
613 static status_t process_notify_payload(private_responder_init_t *this, notify_payload_t *notify_payload)
614 {
615 chunk_t notification_data;
616 notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload);
617
618 this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
619 mapping_find(notify_message_type_m, notify_message_type));
620
621 switch (notify_message_type)
622 {
623 case NAT_DETECTION_DESTINATION_IP:
624 {
625 this->natd_seen_r++;
626 if (this->natd_hash_r_matched)
627 return SUCCESS;
628
629 notification_data = notify_payload->get_notification_data(notify_payload);
630 if (chunk_equals(notification_data, this->natd_hash_r))
631 {
632 this->natd_hash_r_matched = TRUE;
633 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash match");
634 }
635 else
636 {
637 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash mismatch");
638 }
639
640 return SUCCESS;
641 }
642 case NAT_DETECTION_SOURCE_IP:
643 {
644 this->natd_seen_i++;
645 if (this->natd_hash_i_matched)
646 return SUCCESS;
647
648 notification_data = notify_payload->get_notification_data(notify_payload);
649 if (chunk_equals(notification_data, this->natd_hash_i))
650 {
651 this->natd_hash_i_matched = TRUE;
652 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash match");
653 }
654 else
655 {
656 this->logger->log(this->logger, CONTROL|LEVEL3, "NAT-D hash mismatch");
657 }
658
659 return SUCCESS;
660 }
661 default:
662 {
663 this->logger->log(this->logger, CONTROL, "IKE_SA_INIT request contained a notify (%d), ignored.",
664 notify_message_type);
665 return SUCCESS;
666 }
667 }
668 }
669
670 /**
671 * Implementation of state_t.get_state.
672 */
673 static ike_sa_state_t get_state(private_responder_init_t *this)
674 {
675 return RESPONDER_INIT;
676 }
677
678 /**
679 * Implementation of state_t.destroy.
680 */
681 static void destroy(private_responder_init_t *this)
682 {
683 this->logger->log(this->logger, CONTROL | LEVEL1, "going to destroy responder init state object");
684
685 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy nonces");
686 chunk_free(&(this->sent_nonce));
687 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy received nonce");
688 chunk_free(&(this->received_nonce));
689
690 chunk_free(&(this->natd_hash_i));
691 chunk_free(&(this->natd_hash_r));
692
693 if (this->diffie_hellman != NULL)
694 {
695 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy diffie_hellman_t hellman object");
696 this->diffie_hellman->destroy(this->diffie_hellman);
697 }
698 if (this->proposal)
699 {
700 this->proposal->destroy(this->proposal);
701 }
702 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy object");
703 free(this);
704 }
705
706 /**
707 * Implementation of private_responder_init_t.destroy_after_state_change
708 */
709 static void destroy_after_state_change (private_responder_init_t *this)
710 {
711 this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder_init_t state object");
712
713 chunk_free(&(this->natd_hash_i));
714 chunk_free(&(this->natd_hash_r));
715
716 /* destroy diffie hellman object */
717 if (this->diffie_hellman != NULL)
718 {
719 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy diffie_hellman_t object");
720 this->diffie_hellman->destroy(this->diffie_hellman);
721 }
722 if (this->proposal)
723 {
724 this->proposal->destroy(this->proposal);
725 }
726
727 this->logger->log(this->logger, CONTROL | LEVEL2, "destroy object");
728 free(this);
729 }
730
731 /*
732 * Described in header.
733 */
734 responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
735 {
736 private_responder_init_t *this = malloc_thing(private_responder_init_t);
737
738 /* interface functions */
739 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
740 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
741 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
742
743 /* private functions */
744 this->build_sa_payload = build_sa_payload;
745 this->build_ke_payload = build_ke_payload;
746 this->build_nonce_payload = build_nonce_payload;
747 this->destroy_after_state_change = destroy_after_state_change;
748 this->process_notify_payload = process_notify_payload;
749 this->build_natd_payload = build_natd_payload;
750 this->build_natd_payloads = build_natd_payloads;
751
752 /* private data */
753 this->ike_sa = ike_sa;
754 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
755 this->sent_nonce = CHUNK_INITIALIZER;
756 this->received_nonce = CHUNK_INITIALIZER;
757 this->dh_group_number = MODP_NONE;
758 this->diffie_hellman = NULL;
759 this->proposal = NULL;
760 this->natd_hash_i = CHUNK_INITIALIZER;
761 this->natd_hash_i_matched = FALSE;
762 this->natd_seen_i = 0;
763 this->natd_hash_r = CHUNK_INITIALIZER;
764 this->natd_hash_r_matched = FALSE;
765 this->natd_seen_r = 0;
766
767 return &(this->public);
768 }