fixed compile warnings when using -Wall
[strongswan.git] / src / charon / sa / states / ike_sa_established.c
1 /**
2 * @file ike_sa_established.c
3 *
4 * @brief Implementation of ike_sa_established_t.
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 <string.h>
24
25 #include "ike_sa_established.h"
26
27 #include <daemon.h>
28 #include <encoding/payloads/delete_payload.h>
29 #include <encoding/payloads/sa_payload.h>
30 #include <encoding/payloads/ts_payload.h>
31 #include <encoding/payloads/nonce_payload.h>
32 #include <sa/child_sa.h>
33 #include <sa/states/delete_ike_sa_requested.h>
34
35
36 typedef struct private_ike_sa_established_t private_ike_sa_established_t;
37
38 /**
39 * Private data of a ike_sa_established_t object.
40 */
41 struct private_ike_sa_established_t {
42 /**
43 * methods of the state_t interface
44 */
45 ike_sa_established_t public;
46
47 /**
48 * Assigned IKE_SA.
49 */
50 protected_ike_sa_t *ike_sa;
51
52 /**
53 * Nonce for a new child SA, chosen by initiator
54 */
55 chunk_t nonce_i;
56
57 /**
58 * Nonce for a new child SA, chosen by responder
59 */
60 chunk_t nonce_r;
61
62 /**
63 * Traffic selectors for a new child SA, responder side
64 */
65 linked_list_t *my_ts;
66
67 /**
68 * Traffic selectors for a new child SA, initiator side
69 */
70 linked_list_t *other_ts;
71
72 /**
73 * Newly set up child sa
74 */
75 child_sa_t *child_sa;
76
77 /**
78 * Assigned logger. Use logger of IKE_SA.
79 */
80 logger_t *logger;
81 };
82
83 /**
84 * Implementation of private_ike_sa_established_t.build_sa_payload.
85 */
86 static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_t *request, message_t *response)
87 {
88 proposal_t *proposal, *proposal_tmp;
89 linked_list_t *proposal_list;
90 sa_payload_t *sa_response;
91 chunk_t seed;
92 prf_plus_t *prf_plus;
93 status_t status;
94 connection_t *connection;
95 policy_t *policy;
96
97 /* prepare reply */
98 sa_response = sa_payload_create();
99
100 /* get proposals from request, and select one with ours */
101 policy = this->ike_sa->get_policy(this->ike_sa);
102 proposal_list = request->get_proposals(request);
103 this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:");
104 proposal = policy->select_proposal(policy, proposal_list);
105 /* list is not needed anymore */
106 while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS)
107 {
108 proposal_tmp->destroy(proposal_tmp);
109 }
110 proposal_list->destroy(proposal_list);
111 /* do we have a proposal? */
112 if (proposal == NULL)
113 {
114 notify_payload_t *notify;
115 this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA request did not contain any proposals we accept. "
116 "Adding NO_PROPOSAL_CHOSEN notify");
117 /* add NO_PROPOSAL_CHOSEN and an empty SA payload */
118 notify = notify_payload_create_from_protocol_and_type(PROTO_IKE, NO_PROPOSAL_CHOSEN);
119 response->add_payload(response, (payload_t*)notify);
120 }
121 else
122 {
123 /* set up child sa */
124 seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
125 memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
126 memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
127 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
128 this->logger->log_chunk(this->logger, CONTROL, "Seed", seed);
129 chunk_free(&seed);
130
131 policy = this->ike_sa->get_policy(this->ike_sa);
132 connection = this->ike_sa->get_connection(this->ike_sa);
133 this->child_sa = child_sa_create(connection->get_my_host(connection),
134 connection->get_other_host(connection),
135 policy->get_soft_lifetime(policy),
136 policy->get_hard_lifetime(policy));
137
138 status = this->child_sa->add(this->child_sa, proposal, prf_plus);
139 prf_plus->destroy(prf_plus);
140 if (status != SUCCESS)
141 {
142 this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA!");
143 sa_response->destroy(sa_response);
144 proposal->destroy(proposal);
145 return DESTROY_ME;
146 }
147
148 /* add proposal to sa payload */
149 sa_response->add_proposal(sa_response, proposal);
150 proposal->destroy(proposal);
151 }
152 response->add_payload(response, (payload_t*)sa_response);
153 return SUCCESS;
154 }
155
156 /**
157 * Implementation of private_ike_sa_established_t.build_ts_payload.
158 */
159 static status_t build_ts_payload(private_ike_sa_established_t *this, bool ts_initiator, ts_payload_t *request, message_t* response)
160 {
161 linked_list_t *ts_received, *ts_selected;
162 traffic_selector_t *ts;
163 status_t status = SUCCESS;
164 ts_payload_t *ts_response;
165 policy_t *policy;
166
167 policy = this->ike_sa->get_policy(this->ike_sa);
168
169 /* build a reply payload with selected traffic selectors */
170 ts_received = request->get_traffic_selectors(request);
171 /* select ts depending on payload type */
172 if (ts_initiator)
173 {
174 ts_selected = policy->select_other_traffic_selectors(policy, ts_received);
175 this->other_ts = ts_selected;
176 }
177 else
178 {
179 ts_selected = policy->select_my_traffic_selectors(policy, ts_received);
180 this->my_ts = ts_selected;
181 }
182
183 ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected);
184 response->add_payload(response, (payload_t*)ts_response);
185
186 /* add notify if traffic selectors do not match */
187 if (!ts_initiator &&
188 (ts_selected->get_count(ts_selected) == 0 || this->other_ts->get_count(this->other_ts) == 0))
189 {
190 notify_payload_t *notify;
191
192 this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any traffic selectors we accept. "
193 "Adding TS_UNACCEPTABLE notify");
194
195 notify = notify_payload_create_from_protocol_and_type(0, TS_UNACCEPTABLE);
196 response->add_payload(response, (payload_t*)notify);
197 }
198
199 /* cleanup */
200 while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS)
201 {
202 ts->destroy(ts);
203 }
204 ts_received->destroy(ts_received);
205
206 return status;
207 }
208
209 /**
210 * Implementation of private_ike_sa_established_t.build_nonce_payload.
211 */
212 static status_t build_nonce_payload(private_ike_sa_established_t *this, nonce_payload_t *nonce_request, message_t *response)
213 {
214 nonce_payload_t *nonce_payload;
215 randomizer_t *randomizer;
216 status_t status;
217
218 this->nonce_i = nonce_request->get_nonce(nonce_request);
219
220 randomizer = this->ike_sa->get_randomizer(this->ike_sa);
221 status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &this->nonce_r);
222 if (status != SUCCESS)
223 {
224 return status;
225 }
226
227 nonce_payload = nonce_payload_create();
228 nonce_payload->set_nonce(nonce_payload, this->nonce_r);
229
230 response->add_payload(response,(payload_t *) nonce_payload);
231
232 return SUCCESS;
233 }
234
235 /**
236 * Process a CREATE_CHILD_SA request
237 */
238 static status_t process_create_child_sa(private_ike_sa_established_t *this, message_t *request, message_t *response)
239 {
240 ts_payload_t *tsi_request = NULL, *tsr_request = NULL;
241 sa_payload_t *sa_request = NULL;
242 nonce_payload_t *nonce_request = NULL;
243 iterator_t *payloads;
244 status_t status;
245
246 /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
247 payloads = request->get_payload_iterator(request);
248 while (payloads->has_next(payloads))
249 {
250 payload_t *payload;
251 payloads->current(payloads, (void**)&payload);
252
253 switch (payload->get_type(payload))
254 {
255 case SECURITY_ASSOCIATION:
256 {
257 sa_request = (sa_payload_t*)payload;
258 break;
259 }
260 case TRAFFIC_SELECTOR_INITIATOR:
261 {
262 tsi_request = (ts_payload_t*)payload;
263 break;
264 }
265 case TRAFFIC_SELECTOR_RESPONDER:
266 {
267 tsr_request = (ts_payload_t*)payload;
268 break;
269 }
270 case NONCE:
271 {
272 nonce_request = (nonce_payload_t*)payload;
273 break;
274 }
275 case NOTIFY:
276 {
277 /* TODO: handle notifys */
278 break;
279 }
280 default:
281 {
282 this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)",
283 mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
284 break;
285 }
286 }
287 }
288 /* iterator can be destroyed */
289 payloads->destroy(payloads);
290
291 /* check if we have all payloads */
292 if (!(sa_request && nonce_request && tsi_request && tsr_request))
293 {
294 this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA request did not contain all required payloads. Ignored");
295 return FAILED;
296 }
297
298 /* build response */
299 this->ike_sa->build_message(this->ike_sa, CREATE_CHILD_SA, FALSE, &response);
300
301 /* add payloads to it */
302 status = build_nonce_payload(this, nonce_request, response);
303 if (status != SUCCESS)
304 {
305 response->destroy(response);
306 return status;
307 }
308 status = build_sa_payload(this, sa_request, response);
309 if (status != SUCCESS)
310 {
311 response->destroy(response);
312 return status;
313 }
314 status = build_ts_payload(this, TRUE, tsi_request, response);
315 if (status != SUCCESS)
316 {
317 response->destroy(response);
318 return status;
319 }
320 status = build_ts_payload(this, FALSE, tsr_request, response);
321 if (status != SUCCESS)
322 {
323 response->destroy(response);
324 return status;
325 }
326
327 status = this->ike_sa->send_response(this->ike_sa, response);
328 /* message can now be sent (must not be destroyed) */
329 if (status != SUCCESS)
330 {
331 this->logger->log(this->logger, AUDIT, "Unable to send CREATE_CHILD_SA reply. Ignored");
332 response->destroy(response);
333 return FAILED;
334 }
335
336 /* install child SA policies */
337 if (!this->child_sa)
338 {
339 this->logger->log(this->logger, ERROR, "Proposal negotiation failed, no CHILD_SA built");
340 }
341 else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0)
342 {
343 this->logger->log(this->logger, ERROR, "Traffic selector negotiation failed, no CHILD_SA built");
344 this->child_sa->destroy(this->child_sa);
345 this->child_sa = NULL;
346 }
347 else
348 {
349 status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts);
350 if (status != SUCCESS)
351 {
352 this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy!");
353 }
354 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
355 }
356
357 return SUCCESS;
358 }
359
360
361 /**
362 * Process an informational request
363 */
364 static status_t process_informational(private_ike_sa_established_t *this, message_t *request, message_t *response)
365 {
366 delete_payload_t *delete_request = NULL;
367 iterator_t *payloads = request->get_payload_iterator(request);
368
369 while (payloads->has_next(payloads))
370 {
371 payload_t *payload;
372 payloads->current(payloads, (void**)&payload);
373
374 switch (payload->get_type(payload))
375 {
376 case DELETE:
377 {
378 delete_request = (delete_payload_t *) payload;
379 break;
380 }
381 default:
382 {
383 this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)",
384 mapping_find(payload_type_m, payload->get_type(payload)),
385 payload->get_type(payload));
386 break;
387 }
388 }
389 }
390 /* iterator can be destroyed */
391 payloads->destroy(payloads);
392
393 if (delete_request)
394 {
395 if (delete_request->get_protocol_id(delete_request) == PROTO_IKE)
396 {
397 this->logger->log(this->logger, CONTROL, "DELETE request for IKE_SA received");
398 /* switch to delete_ike_sa_requested. This is not absolutly correct, but we
399 * allow the clean destruction of an SA only in this state. */
400 this->ike_sa->set_new_state(this->ike_sa, (state_t*)delete_ike_sa_requested_create(this->ike_sa));
401 this->public.state_interface.destroy(&(this->public.state_interface));
402 return DESTROY_ME;
403 }
404 else
405 {
406 this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA received. Ignored");
407 return SUCCESS;
408 }
409 }
410
411 if (this->ike_sa->send_response(this->ike_sa, response) != SUCCESS)
412 {
413 /* something is seriously wrong, kill connection */
414 this->logger->log(this->logger, AUDIT, "Unable to send reply. Deleting IKE_SA");
415 response->destroy(response);
416 return DESTROY_ME;
417 }
418 return SUCCESS;
419 }
420
421 /**
422 * Implements state_t.process_message
423 */
424 static status_t process_message(private_ike_sa_established_t *this, message_t *message)
425 {
426 ike_sa_id_t *ike_sa_id;
427 message_t *response;
428 crypter_t *crypter;
429 signer_t *signer;
430 status_t status;
431
432 /* only requests are allowed, responses are handled in other state */
433 if (!message->get_request(message))
434 {
435 this->logger->log(this->logger, ERROR|LEVEL1,
436 "Response not handled in state ike_sa_established");
437 return FAILED;
438 }
439
440 /* get signer for verification and crypter for decryption */
441 ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
442 if (!ike_sa_id->is_initiator(ike_sa_id))
443 {
444 crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
445 signer = this->ike_sa->get_signer_initiator(this->ike_sa);
446 }
447 else
448 {
449 crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
450 signer = this->ike_sa->get_signer_responder(this->ike_sa);
451 }
452
453 /* parse incoming message */
454 status = message->parse_body(message, crypter, signer);
455 if (status != SUCCESS)
456 {
457 this->logger->log(this->logger, AUDIT, "%s request decryption failed. Ignoring message",
458 mapping_find(exchange_type_m, message->get_exchange_type(message)));
459 return status;
460 }
461
462 /* prepare a reply of the same type */
463 this->ike_sa->build_message(this->ike_sa, message->get_exchange_type(message), FALSE, &response);
464
465 /* handle the different message types in their functions */
466 switch (message->get_exchange_type(message))
467 {
468 case INFORMATIONAL:
469 status = process_informational(this, message, response);
470 break;
471 case CREATE_CHILD_SA:
472 status = process_create_child_sa(this, message, response);
473 break;
474 default:
475 this->logger->log(this->logger, ERROR | LEVEL1,
476 "Message of type %s not supported in state ike_sa_established",
477 mapping_find(exchange_type_m, message->get_exchange_type(message)));
478 status = NOT_SUPPORTED;
479 }
480 /* clean up private members */
481 chunk_free(&this->nonce_i);
482 chunk_free(&this->nonce_r);
483 return status;
484 }
485
486 /**
487 * Implementation of state_t.get_state.
488 */
489 static ike_sa_state_t get_state(private_ike_sa_established_t *this)
490 {
491 return IKE_SA_ESTABLISHED;
492 }
493
494 /**
495 * Implementation of state_t.get_state
496 */
497 static void destroy(private_ike_sa_established_t *this)
498 {
499 free(this);
500 }
501
502 /*
503 * Described in header.
504 */
505 ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa)
506 {
507 private_ike_sa_established_t *this = malloc_thing(private_ike_sa_established_t);
508
509 /* interface functions */
510 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
511 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
512 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
513
514 /* private data */
515 this->ike_sa = ike_sa;
516 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
517 this->nonce_i = CHUNK_INITIALIZER;
518 this->nonce_r = CHUNK_INITIALIZER;
519
520 return &(this->public);
521 }