- state ike_sa_init_responded implemented (has some memleaks)
[strongswan.git] / Source / charon / sa / states / ike_sa_init_responded.c
1 /**
2 * @file ike_sa_init_responded.c
3 *
4 * @brief State of a IKE_SA after responding to an IKE_SA_INIT request
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 "ike_sa_init_responded.h"
24
25 #include <daemon.h>
26 #include <utils/allocator.h>
27 #include <encoding/payloads/ts_payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/auth_payload.h>
31 #include <transforms/signers/signer.h>
32 #include <transforms/crypters/crypter.h>
33 #include <sa/states/ike_sa_established.h>
34
35
36 typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t;
37
38 /**
39 * Private data of a ike_sa_init_responded_t object.
40 *
41 */
42 struct private_ike_sa_init_responded_t {
43 /**
44 * methods of the state_t interface
45 */
46 ike_sa_init_responded_t public;
47
48 /**
49 * Assigned IKE_SA
50 */
51 protected_ike_sa_t *ike_sa;
52
53 /**
54 * sa config to use
55 */
56 sa_config_t *sa_config;
57
58 /**
59 * Logger used to log data
60 *
61 * Is logger of ike_sa!
62 */
63 logger_t *logger;
64
65 status_t (*build_idr_payload) (private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response);
66 status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response);
67 status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request, message_t *response);
68 status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *response);
69 };
70
71 /**
72 * Implements state_t.get_state
73 */
74 static status_t process_message(private_ike_sa_init_responded_t *this, message_t *request)
75 {
76 status_t status;
77 signer_t *signer;
78 crypter_t *crypter;
79 iterator_t *payloads;
80 exchange_type_t exchange_type;
81 id_payload_t *idi_request, *idr_request = NULL;
82 auth_payload_t *auth_request;
83 sa_payload_t *sa_request;
84 ts_payload_t *tsi_request, *tsr_request;
85 message_t *response;
86 packet_t *response_packet;
87
88 exchange_type = request->get_exchange_type(request);
89 if (exchange_type != IKE_AUTH)
90 {
91 this->logger->log(this->logger, ERROR | MORE, "Message of type %s not supported in state ike_sa_init_responded",
92 mapping_find(exchange_type_m,exchange_type));
93 return FAILED;
94 }
95
96 if (!request->get_request(request))
97 {
98 this->logger->log(this->logger, ERROR | MORE, "Only requests of type IKE_AUTH supported in state ike_sa_init_responded");
99 return FAILED;
100 }
101
102 /* get signer for verification and crypter for decryption */
103 signer = this->ike_sa->get_signer_initiator(this->ike_sa);
104 crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
105
106 /* parse incoming message */
107
108 status = request->parse_body(request, crypter, signer);
109 if (status != SUCCESS)
110 {
111 this->logger->log(this->logger, ERROR | MORE, "Could not parse body of request message");
112 return status;
113 }
114
115 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
116 payloads = request->get_payload_iterator(request);
117 while (payloads->has_next(payloads))
118 {
119 payload_t *payload;
120 payloads->current(payloads, (void**)&payload);
121
122 switch (payload->get_type(payload))
123 {
124 case ID_INITIATOR:
125 {
126 idi_request = (id_payload_t*)payload;
127 break;
128 }
129 case AUTHENTICATION:
130 {
131 auth_request = (auth_payload_t*)payload;
132 break;
133 }
134 case ID_RESPONDER:
135 {
136 idr_request = (id_payload_t*)payload;
137 break;
138 }
139 case SECURITY_ASSOCIATION:
140 {
141 sa_request = (sa_payload_t*)payload;
142 break;
143 }
144 case CERTIFICATE:
145 {
146 /* TODO handle cert payloads */
147 break;
148 }
149 case CERTIFICATE_REQUEST:
150 {
151 /* TODO handle certrequest payloads */
152 break;
153 }
154 case TRAFFIC_SELECTOR_INITIATOR:
155 {
156 tsi_request = (ts_payload_t*)payload;
157 break;
158 }
159 case TRAFFIC_SELECTOR_RESPONDER:
160 {
161 tsr_request = (ts_payload_t*)payload;
162 break;
163 }
164 default:
165 {
166 /* can't happen, since message is verified, notify's? */
167 break;
168 }
169 }
170 }
171 /* iterator can be destroyed */
172 payloads->destroy(payloads);
173
174 /* build response */
175 this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response);
176
177 /* add payloads to it */
178
179 status = this->build_idr_payload(this, idi_request, idr_request, response);
180 if (status != SUCCESS)
181 {
182 this->logger->log(this->logger, ERROR, "Building idr payload failed");
183 response->destroy(response);
184 return status;
185 }
186 status = this->build_sa_payload(this, sa_request, response);
187 if (status != SUCCESS)
188 {
189 this->logger->log(this->logger, ERROR, "Building sa payload failed");
190 response->destroy(response);
191 return status;
192 }
193 status = this->build_auth_payload(this, auth_request, response);
194 if (status != SUCCESS)
195 {
196 this->logger->log(this->logger, ERROR, "Building auth payload failed");
197 response->destroy(response);
198 return status;
199 }
200 status = this->build_ts_payload(this, TRUE, tsi_request, response);
201 if (status != SUCCESS)
202 {
203 this->logger->log(this->logger, ERROR, "Building tsi payload failed");
204 response->destroy(response);
205 return status;
206 }
207 status = this->build_ts_payload(this, FALSE, tsr_request, response);
208 if (status != SUCCESS)
209 {
210 this->logger->log(this->logger, ERROR, "Building tsr payload failed");
211 response->destroy(response);
212 return status;
213 }
214
215 /* generate response, get transfroms first */
216 signer = this->ike_sa->get_signer_responder(this->ike_sa);
217 crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
218 status = response->generate(response, crypter, signer, &response_packet);
219 if (status != SUCCESS)
220 {
221 this->logger->log(this->logger, ERROR, "Error in message generation");
222 response->destroy(response);
223 return status;
224 }
225
226
227 /* send it out */
228 this->logger->log(this->logger, CONTROL | MORE, "IKE_AUTH request successfully handled. Sending reply.");
229 charon->send_queue->add(charon->send_queue, response_packet);
230 /* store for timeout reply */
231 this->ike_sa->set_last_responded_message(this->ike_sa, response);
232
233 /* create new state */
234 this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
235
236 return SUCCESS;
237 }
238
239 /**
240 * Implements private_ike_sa_init_responded_t.build_idr_payload
241 */
242 static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response)
243 {
244 identification_t *other_id, *my_id = NULL;
245 init_config_t *init_config;
246 status_t status;
247 id_payload_t *idr_response;
248
249 other_id = request_idi->get_identification(request_idi);
250 if (request_idr)
251 {
252 my_id = request_idr->get_identification(request_idr);
253 }
254
255 /* build new sa config */
256 init_config = this->ike_sa->get_init_config(this->ike_sa);
257 status = charon->configuration_manager->get_sa_config_for_init_config_and_id(charon->configuration_manager,init_config, other_id,my_id, &(this->sa_config));
258 if (status != SUCCESS)
259 {
260 this->logger->log(this->logger, ERROR, "Could not find config for %s", other_id->get_string(other_id));
261 return NOT_FOUND;
262 }
263
264 /* set sa_config in ike_sa for other states */
265 this->ike_sa->set_sa_config(this->ike_sa, this->sa_config);
266
267 /* build response */
268 idr_response = id_payload_create_from_identification(FALSE, other_id);
269 response->add_payload(response, (payload_t*)idr_response);
270
271 if (my_id)
272 {
273 my_id->destroy(my_id);
274 }
275 other_id->destroy(other_id);
276
277 return SUCCESS;
278 }
279
280 /**
281 * Implements private_ike_sa_init_responded_t.build_sa_payload
282 */
283 static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response)
284 {
285 child_proposal_t *proposals, *proposal_chosen;
286 size_t proposal_count;
287 status_t status;
288 sa_payload_t *sa_response;
289
290 /* dummy spis, until we have a child sa to request them */
291 u_int8_t ah_spi[4] = {0x01, 0x02, 0x03, 0x04};
292 u_int8_t esp_spi[4] = {0x05, 0x06, 0x07, 0x08};
293
294 status = request->get_child_proposals(request, &proposals, &proposal_count);
295 if (status == SUCCESS)
296 {
297 proposal_chosen = this->sa_config->select_proposal(this->sa_config, ah_spi, esp_spi, proposals, proposal_count);
298 if (proposal_chosen != NULL)
299 {
300 sa_response = sa_payload_create_from_child_proposals(proposal_chosen, 1);
301 response->add_payload(response, (payload_t*)sa_response);
302 }
303 else
304 {
305 this->logger->log(this->logger, ERROR, "no matching proposal found");
306 status = NOT_FOUND;
307 }
308 }
309 else
310 {
311 this->logger->log(this->logger, ERROR, "requestor's sa payload contained no proposals");
312 status = NOT_FOUND;
313 }
314
315
316 allocator_free(proposal_chosen);
317 allocator_free(proposals);
318
319
320 return status;
321 }
322
323 /**
324 * Implements private_ike_sa_init_responded_t.build_auth_payload
325 */
326 static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *request, message_t *response)
327 {
328 auth_payload_t *dummy;
329 u_int8_t data[] = {0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03,0x01,0x03};
330 chunk_t auth_data;
331 auth_data.ptr = data;
332 auth_data.len = sizeof(data);
333
334 /* TODO VERIFY auth here */
335
336 dummy = auth_payload_create();
337 dummy->set_data(dummy, auth_data);
338 dummy->set_auth_method(dummy, RSA_DIGITAL_SIGNATURE);
339
340 /* TODO replace dummy */
341
342 response->add_payload(response, (payload_t *)dummy);
343 return SUCCESS;
344 }
345
346 /**
347 * Implements private_ike_sa_init_responded_t.build_ts_payload
348 */
349 static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response)
350 {
351 traffic_selector_t **ts_received, **ts_selected;
352 size_t ts_received_count, ts_selected_count;
353 status_t status = SUCCESS;
354 ts_payload_t *ts_response;
355
356 /* build a reply payload with selected traffic selectors */
357 ts_received_count = request->get_traffic_selectors(request, &ts_received);
358 /* select ts depending on payload type */
359 if (ts_initiator)
360 {
361 ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected);
362 }
363 else
364 {
365 ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected);
366 }
367 if(ts_selected_count == 0)
368 {
369 status = NOT_FOUND;
370 }
371 else
372 {
373 ts_response = ts_payload_create_from_traffic_selectors(FALSE, ts_selected, ts_selected_count);
374 response->add_payload(response, (payload_t*)ts_response);
375 }
376
377 /* cleanup */
378 while(ts_received_count--)
379 {
380 traffic_selector_t *ts = *ts_received + ts_received_count;
381 ts->destroy(ts);
382 }
383 allocator_free(ts_received);
384 while(ts_selected_count--)
385 {
386 traffic_selector_t *ts = *ts_selected + ts_selected_count;
387 ts->destroy(ts);
388 }
389 allocator_free(ts_selected);
390 return status;
391 }
392
393 /**
394 * Implements state_t.get_state
395 */
396 static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this)
397 {
398 return IKE_SA_INIT_RESPONDED;
399 }
400
401 /**
402 * Implements state_t.get_state
403 */
404 static void destroy(private_ike_sa_init_responded_t *this)
405 {
406 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy ike_sa_init_responded_t state object");
407
408 charon->logger_manager->destroy_logger(charon->logger_manager, this->logger);
409
410 allocator_free(this);
411 }
412
413 /*
414 * Described in header.
415 */
416 ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa)
417 {
418 private_ike_sa_init_responded_t *this = allocator_alloc_thing(private_ike_sa_init_responded_t);
419
420 /* interface functions */
421 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
422 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
423 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
424
425 /* private functions */
426 this->build_idr_payload = build_idr_payload;
427 this->build_sa_payload = build_sa_payload;
428 this->build_auth_payload = build_auth_payload;
429 this->build_ts_payload = build_ts_payload;
430
431 /* private data */
432 this->ike_sa = ike_sa;
433 this->logger = this->ike_sa->get_logger(this->ike_sa);
434
435 return &(this->public);
436 }