2 * @file initiator_init.c
4 * @brief Implementation of initiator_init_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "initiator_init.h"
27 #include <sa/states/state.h>
28 #include <sa/states/ike_sa_init_requested.h>
29 #include <queues/jobs/retransmit_request_job.h>
30 #include <crypto/diffie_hellman.h>
31 #include <encoding/payloads/sa_payload.h>
32 #include <encoding/payloads/ke_payload.h>
33 #include <encoding/payloads/nonce_payload.h>
36 typedef struct private_initiator_init_t private_initiator_init_t
;
39 * Private data of a initiator_init_t object..
42 struct private_initiator_init_t
{
44 * Methods of the state_t interface.
46 initiator_init_t
public;
51 protected_ike_sa_t
*ike_sa
;
54 * Diffie hellman object used to generate public DH value.
55 * This objet is passed to the next state of type IKE_SA_INIT_REQUESTED.
57 diffie_hellman_t
*diffie_hellman
;
61 * This nonce is passed to the next state of type IKE_SA_INIT_REQUESTED.
68 * Is logger of ike_sa!
73 * Builds the SA payload for this state.
75 * @param this calling object
76 * @param request message_t object to add the SA payload
78 void (*build_sa_payload
) (private_initiator_init_t
*this, message_t
*request
);
81 * Builds the KE payload for this state.
83 * @param this calling object
84 * @param request message_t object to add the KE payload
86 void (*build_ke_payload
) (private_initiator_init_t
*this, message_t
*request
);
89 * Builds the NONCE payload for this state.
91 * @param this calling object
92 * @param request message_t object to add the NONCE payload
94 status_t (*build_nonce_payload
) (private_initiator_init_t
*this,message_t
*request
);
97 * Destroy function called internally of this class after state change to state
98 * IKE_SA_INIT_REQUESTED succeeded.
100 * This destroy function does not destroy objects which were passed to the new state.
102 * @param this calling object
104 void (*destroy_after_state_change
) (private_initiator_init_t
*this);
108 * Implementation of initiator_init_t.initiate_connection.
110 static status_t
initiate_connection (private_initiator_init_t
*this, connection_t
*connection
)
113 diffie_hellman_group_t dh_group
;
114 host_t
*my_host
, *other_host
;
115 identification_t
*my_id
, *other_id
;
117 my_host
= connection
->get_my_host(connection
);
118 other_host
= connection
->get_other_host(connection
);
119 my_id
= connection
->get_my_id(connection
);
120 other_id
= connection
->get_other_id(connection
);
122 this->logger
->log(this->logger
, CONTROL
, "Initiating connection between %s (%s) - %s (%s)",
123 my_id
->get_string(my_id
), my_host
->get_address(my_host
),
124 other_id
->get_string(other_id
), other_host
->get_address(other_host
));
126 this->ike_sa
->set_connection(this->ike_sa
, connection
);
129 policy
= charon
->policies
->get_policy(charon
->policies
, my_id
, other_id
);
132 this->logger
->log(this->logger
, ERROR
| LEVEL1
, "Could not get a policy for '%s - %s', aborting",
133 my_id
->get_string(my_id
), other_id
->get_string(other_id
));
136 this->ike_sa
->set_policy(this->ike_sa
,policy
);
138 /* we must guess now a DH group. For that we choose our most preferred group */
139 dh_group
= connection
->get_dh_group(connection
);
141 /* next step is done in retry_initiate_connection */
142 return this->public.retry_initiate_connection(&this->public, dh_group
);
146 * Implementation of initiator_init_t.retry_initiate_connection.
148 status_t
retry_initiate_connection (private_initiator_init_t
*this, diffie_hellman_group_t dh_group
)
150 ike_sa_init_requested_t
*next_state
;
151 chunk_t ike_sa_init_request_data
;
152 connection_t
*connection
;
153 ike_sa_id_t
*ike_sa_id
;
157 if (dh_group
== MODP_UNDEFINED
)
159 this->logger
->log(this->logger
, AUDIT
, "No DH group acceptable for initialization, Aborting");
163 connection
= this->ike_sa
->get_connection(this->ike_sa
);
164 this->diffie_hellman
= diffie_hellman_create(dh_group
);
165 ike_sa_id
= this->ike_sa
->public.get_id(&(this->ike_sa
->public));
166 ike_sa_id
->set_responder_spi(ike_sa_id
,0);
168 /* going to build message */
169 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Going to build message");
170 this->ike_sa
->build_message(this->ike_sa
, IKE_SA_INIT
, TRUE
, &message
);
172 /* build SA payload */
173 this->build_sa_payload(this, message
);
175 /* build KE payload */
176 this->build_ke_payload(this, message
);
178 /* build Nonce payload */
179 status
= this->build_nonce_payload(this, message
);
180 if (status
!= SUCCESS
)
182 this->logger
->log(this->logger
, ERROR
, "Building nonce payload failed. Aborting");
183 message
->destroy(message
);
187 /* message can now be sent (must not be destroyed) */
188 status
= this->ike_sa
->send_request(this->ike_sa
, message
);
189 if (status
!= SUCCESS
)
191 this->logger
->log(this->logger
, AUDIT
, "Unable to initiate connection, could not send message. Aborting");
192 message
->destroy(message
);
196 message
= this->ike_sa
->get_last_requested_message(this->ike_sa
);
198 ike_sa_init_request_data
= message
->get_packet_data(message
);
200 /* state can now be changed */
201 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Create next state object");
202 next_state
= ike_sa_init_requested_create(this->ike_sa
, this->diffie_hellman
, this->sent_nonce
,ike_sa_init_request_data
);
203 this->ike_sa
->set_new_state(this->ike_sa
,(state_t
*) next_state
);
205 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Destroy old sate object");
206 this->destroy_after_state_change(this);
211 * Implementation of private_initiator_init_t.build_sa_payload.
213 static void build_sa_payload(private_initiator_init_t
*this, message_t
*request
)
215 sa_payload_t
* sa_payload
;
216 linked_list_t
*proposal_list
;
217 connection_t
*connection
;
219 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Building SA payload");
221 connection
= this->ike_sa
->get_connection(this->ike_sa
);
223 proposal_list
= connection
->get_proposals(connection
);
225 sa_payload
= sa_payload_create_from_proposal_list(proposal_list
);
227 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Add SA payload to message");
228 request
->add_payload(request
, (payload_t
*) sa_payload
);
232 * Implementation of private_initiator_init_t.build_ke_payload.
234 static void build_ke_payload(private_initiator_init_t
*this, message_t
*request
)
236 ke_payload_t
*ke_payload
;
238 diffie_hellman_group_t dh_group
;
240 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Building KE payload");
242 this->diffie_hellman
->get_my_public_value(this->diffie_hellman
,&key_data
);
243 dh_group
= this->diffie_hellman
->get_dh_group(this->diffie_hellman
);
245 ke_payload
= ke_payload_create();
246 ke_payload
->set_dh_group_number(ke_payload
, dh_group
);
247 ke_payload
->set_key_exchange_data(ke_payload
, key_data
);
249 chunk_free(&key_data
);
251 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Add KE payload to message");
252 request
->add_payload(request
, (payload_t
*) ke_payload
);
256 * Implementation of private_initiator_init_t.build_nonce_payload.
258 static status_t
build_nonce_payload(private_initiator_init_t
*this, message_t
*request
)
260 nonce_payload_t
*nonce_payload
;
261 randomizer_t
*randomizer
;
264 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "Building NONCE payload");
266 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Get pseudo random bytes for NONCE");
267 randomizer
= this->ike_sa
->get_randomizer(this->ike_sa
);
269 status
= randomizer
->allocate_pseudo_random_bytes(randomizer
, NONCE_SIZE
, &(this->sent_nonce
));
270 if (status
!= SUCCESS
)
275 this->logger
->log(this->logger
, RAW
|LEVEL2
, "Initiator NONCE",&(this->sent_nonce
));
277 nonce_payload
= nonce_payload_create();
279 nonce_payload
->set_nonce(nonce_payload
, this->sent_nonce
);
281 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Add NONCE payload to message");
282 request
->add_payload(request
, (payload_t
*) nonce_payload
);
287 * Implementation of state_t.process_message.
289 static status_t
process_message(private_initiator_init_t
*this, message_t
*message
)
291 this->logger
->log(this->logger
, ERROR
, "In state INITIATOR_INIT, no message is processed");
296 * Implementation of state_t.get_state.
298 static ike_sa_state_t
get_state(private_initiator_init_t
*this)
300 return INITIATOR_INIT
;
304 * Implementation of state_t.destroy.
306 static void destroy(private_initiator_init_t
*this)
308 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Going to destroy initiator_init_t state object");
310 /* destroy diffie hellman object */
311 if (this->diffie_hellman
!= NULL
)
313 this->diffie_hellman
->destroy(this->diffie_hellman
);
315 if (this->sent_nonce
.ptr
!= NULL
)
317 free(this->sent_nonce
.ptr
);
323 * Implementation of private_initiator_init_t.destroy_after_state_change
325 static void destroy_after_state_change (private_initiator_init_t
*this)
327 this->logger
->log(this->logger
, CONTROL
| LEVEL3
, "Going to destroy initiator_init_t state object");
332 * Described in header.
334 initiator_init_t
*initiator_init_create(protected_ike_sa_t
*ike_sa
)
336 private_initiator_init_t
*this = malloc_thing(private_initiator_init_t
);
338 /* interface functions */
339 this->public.state_interface
.process_message
= (status_t (*) (state_t
*,message_t
*)) process_message
;
340 this->public.state_interface
.get_state
= (ike_sa_state_t (*) (state_t
*)) get_state
;
341 this->public.state_interface
.destroy
= (void (*) (state_t
*)) destroy
;
343 /* public functions */
344 this->public.initiate_connection
= (status_t (*)(initiator_init_t
*, connection_t
*)) initiate_connection
;
345 this->public.retry_initiate_connection
= (status_t (*)(initiator_init_t
*, int )) retry_initiate_connection
;
347 /* private functions */
348 this->destroy_after_state_change
= destroy_after_state_change
;
349 this->build_nonce_payload
= build_nonce_payload
;
350 this->build_sa_payload
= build_sa_payload
;
351 this->build_ke_payload
= build_ke_payload
;
354 this->ike_sa
= ike_sa
;
355 this->logger
= logger_manager
->get_logger(logger_manager
, IKE_SA
);
356 this->sent_nonce
= CHUNK_INITIALIZER
;
357 this->diffie_hellman
= NULL
;
359 return &(this->public);