756b6b9aa4ad0b48b000b0d54dd934267dbb6ed4
[strongswan.git] / Source / charon / sa / states / ike_sa_init_requested.c
1 /**
2 * @file ike_sa_init_requested.c
3 *
4 * @brief Implementation of ike_sa_init_requested_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 "ike_sa_init_requested.h"
24
25 #include <daemon.h>
26 #include <utils/allocator.h>
27 #include <encoding/payloads/sa_payload.h>
28 #include <encoding/payloads/ke_payload.h>
29 #include <encoding/payloads/nonce_payload.h>
30 #include <encoding/payloads/id_payload.h>
31 #include <encoding/payloads/auth_payload.h>
32 #include <encoding/payloads/ts_payload.h>
33 #include <transforms/diffie_hellman.h>
34 #include <sa/states/ike_auth_requested.h>
35
36
37 typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t;
38
39 /**
40 * Private data of a ike_sa_init_requested_t object.
41 *
42 */
43 struct private_ike_sa_init_requested_t {
44 /**
45 * methods of the state_t interface
46 */
47 ike_sa_init_requested_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 * Shared secret of successful exchange
61 */
62 chunk_t shared_secret;
63
64 /**
65 * Sent nonce value
66 */
67 chunk_t sent_nonce;
68
69 /**
70 * Received nonce
71 */
72 chunk_t received_nonce;
73
74 /**
75 * DH group priority used to get dh_group_number from configuration manager.
76 *
77 * Currently unused but usable if informational messages of unsupported dh group number are processed.
78 */
79 u_int16_t dh_group_priority;
80
81 /**
82 * Logger used to log data
83 *
84 * Is logger of ike_sa!
85 */
86 logger_t *logger;
87
88 /**
89 * Builds the IKE_SA_AUTH request message.
90 *
91 * @param this calling object
92 * @param message the created message will be stored at this location
93 */
94 void (*build_ike_auth_request) (private_ike_sa_init_requested_t *this, message_t **message);
95
96 /**
97 * Builds the id payload for this state.
98 *
99 * @param this calling object
100 * @param payload The generated payload object of type id_payload_t is
101 * stored at this location.
102 */
103 void (*build_id_payload) (private_ike_sa_init_requested_t *this, payload_t **payload);
104
105 /**
106 * Builds the id payload for this state.
107 *
108 * @param this calling object
109 * @param payload The generated payload object of type auth_payload_t is
110 * stored at this location.
111 */
112 void (*build_auth_payload) (private_ike_sa_init_requested_t *this, payload_t **payload);
113
114 /**
115 * Builds the SA payload for this state.
116 *
117 * @param this calling object
118 * @param payload The generated payload object of type sa_payload_t is
119 * stored at this location.
120 */
121 void (*build_sa_payload) (private_ike_sa_init_requested_t *this, payload_t **payload);
122
123 /**
124 * Builds the TSi payload for this state.
125 *
126 * @param this calling object
127 * @param payload The generated payload object of type ts_payload_t is
128 * stored at this location.
129 */
130 void (*build_tsi_payload) (private_ike_sa_init_requested_t *this, payload_t **payload);
131
132 /**
133 * Builds the TSr payload for this state.
134 *
135 * @param this calling object
136 * @param payload The generated payload object of type ts_payload_t is
137 * stored at this location.
138 */
139 void (*build_tsr_payload) (private_ike_sa_init_requested_t *this, payload_t **payload);
140
141 /**
142 * Destroy function called internally of this class after state change succeeded.
143 *
144 * This destroy function does not destroy objects which were passed to the new state.
145 *
146 * @param this calling object
147 */
148 void (*destroy_after_state_change) (private_ike_sa_init_requested_t *this);
149 };
150
151 /**
152 * Implements state_t.get_state
153 */
154 static status_t process_message(private_ike_sa_init_requested_t *this, message_t *ike_sa_init_reply)
155 {
156 ike_auth_requested_t *next_state;
157 exchange_type_t exchange_type;
158 init_config_t *init_config;
159 u_int64_t responder_spi;
160 ike_sa_id_t *ike_sa_id;
161 iterator_t *payloads;
162 message_t *request;
163 packet_t *packet;
164 status_t status;
165
166 /*
167 * In this state a reply message of type IKE_SA_INIT is expected:
168 *
169 * <-- HDR, SAr1, KEr, Nr, [CERTREQ]
170 * or
171 * <-- HDR, N
172 */
173 exchange_type = ike_sa_init_reply->get_exchange_type(ike_sa_init_reply);
174 if (exchange_type != IKE_SA_INIT)
175 {
176 this->logger->log(this->logger, ERROR | MORE, "Message of type %s not supported in state ike_sa_init_requested",mapping_find(exchange_type_m,exchange_type));
177 return FAILED;
178 }
179
180 if (ike_sa_init_reply->get_request(ike_sa_init_reply))
181 {
182 this->logger->log(this->logger, ERROR | MORE, "Only responses of type IKE_SA_INIT supported in state ike_sa_init_requested");
183 return FAILED;
184 }
185
186 /* parse incoming message */
187 status = ike_sa_init_reply->parse_body(ike_sa_init_reply, NULL, NULL);
188 if (status != SUCCESS)
189 {
190 this->logger->log(this->logger, ERROR | MORE, "Parsing of body returned error: %s",mapping_find(status_m,status));
191 return status;
192 }
193
194 /* get configuration */
195 init_config = this->ike_sa->get_init_config(this->ike_sa);
196
197
198 if (responder_spi == 0)
199 {
200 this->logger->log(this->logger, ERROR | MORE, "Responder SPI still zero");
201 return FAILED;
202 }
203 /* because I am original initiator i have to update the responder SPI to the new one */
204 responder_spi = ike_sa_init_reply->get_responder_spi(ike_sa_init_reply);
205 ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
206 ike_sa_id->set_responder_spi(ike_sa_id,responder_spi);
207
208 /* Iterate over all payloads.
209 *
210 * The message is allready checked for the right payload types.
211 */
212 payloads = ike_sa_init_reply->get_payload_iterator(ike_sa_init_reply);
213 while (payloads->has_next(payloads))
214 {
215 payload_t *payload;
216 payloads->current(payloads, (void**)&payload);
217
218 this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
219 switch (payload->get_type(payload))
220 {
221 /**
222 * TODO check for notify of type
223 *
224 * and change to state INITIATOR_INIT;
225 *
226 * call destroy after state change not destroy_after_state_change!!!
227 */
228
229 case SECURITY_ASSOCIATION:
230 {
231 sa_payload_t *sa_payload = (sa_payload_t*)payload;
232 ike_proposal_t *ike_proposals;
233 ike_proposal_t selected_proposal;
234 size_t proposal_count;
235
236
237 /* get the list of selected proposals */
238 status = sa_payload->get_ike_proposals (sa_payload, &ike_proposals,&proposal_count);
239 if (status != SUCCESS)
240 {
241 this->logger->log(this->logger, ERROR | MORE, "SA payload does not contain IKE proposals");
242 payloads->destroy(payloads);
243 return status;
244 }
245 /* the peer has to select only one proposal */
246 if (proposal_count != 1)
247 {
248 this->logger->log(this->logger, ERROR | MORE, "More then 1 proposal (%d) selected!",proposal_count);
249 allocator_free(ike_proposals);
250 payloads->destroy(payloads);
251 return status;
252 }
253
254 /* now let the configuration-manager check the selected proposals*/
255 this->logger->log(this->logger, CONTROL | MOST, "Check selected proposal");
256 status = init_config->select_proposal (init_config,ike_proposals,1,&selected_proposal);
257 allocator_free(ike_proposals);
258 if (status != SUCCESS)
259 {
260 this->logger->log(this->logger, ERROR | MORE, "Selected proposal not a suggested one! Peer is trying to trick me!");
261 payloads->destroy(payloads);
262 return status;
263 }
264
265 status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,&selected_proposal);
266 if (status != SUCCESS)
267 {
268 this->logger->log(this->logger, ERROR | MORE, "Transform objects could not be created from selected proposal");
269 payloads->destroy(payloads);
270 return status;
271 }
272 /* ok, we have what we need for sa_payload */
273 break;
274 }
275 case KEY_EXCHANGE:
276 {
277 ke_payload_t *ke_payload = (ke_payload_t*)payload;
278 this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload));
279 /* shared secret is computed AFTER processing of all payloads... */
280 break;
281 }
282 case NONCE:
283 {
284 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
285
286 allocator_free(this->received_nonce.ptr);
287
288 this->received_nonce = CHUNK_INITIALIZER;
289
290 nonce_payload->get_nonce(nonce_payload, &(this->received_nonce));
291 break;
292 }
293 default:
294 {
295 this->logger->log(this->logger, ERROR, "Payload type %s not supported in state ike_sa_init_requested!", mapping_find(payload_type_m, payload->get_type(payload)));
296 payloads->destroy(payloads);
297 return FAILED;
298 }
299
300 }
301
302 }
303 payloads->destroy(payloads);
304
305 allocator_free(this->shared_secret.ptr);
306 this->shared_secret = CHUNK_INITIALIZER;
307
308 /* store shared secret
309 * status of dh objectt does not have to get checked cause other key is set
310 */
311 this->logger->log(this->logger, CONTROL | MOST, "Retrieve shared secret and store it");
312 status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &(this->shared_secret));
313 this->logger->log_chunk(this->logger, PRIVATE, "Shared secret", &this->shared_secret);
314
315 this->logger->log(this->logger, CONTROL | MOST, "Going to derive all secrets from shared secret");
316 this->ike_sa->compute_secrets(this->ike_sa,this->shared_secret,this->sent_nonce, this->received_nonce);
317
318 /* build the complete IKE_AUTH request */
319 this->build_ike_auth_request (this,&request);
320
321 /* generate packet */
322 this->logger->log(this->logger, CONTROL|MOST, "Generate packet from message");
323
324 status = request->generate(request, this->ike_sa->get_crypter_initiator(this->ike_sa), this->ike_sa->get_signer_initiator(this->ike_sa), &packet);
325 if (status != SUCCESS)
326 {
327 this->logger->log(this->logger, ERROR, "Could not generate packet from message");
328 request->destroy(request);
329 return DELETE_ME;
330 }
331
332 this->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
333 charon->send_queue->add(charon->send_queue, packet);
334
335 /* state can now be changed */
336 this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
337 next_state = ike_auth_requested_create(this->ike_sa,this->sent_nonce,this->received_nonce);
338
339 /* last messages can now be set */
340 status = this->ike_sa->set_last_requested_message(this->ike_sa, request);
341
342 if (status != SUCCESS)
343 {
344 this->logger->log(this->logger, ERROR, "Could not set last requested message");
345 (next_state->state_interface).destroy(&(next_state->state_interface));
346 request->destroy(request);
347 return DELETE_ME;
348 }
349
350 /* state can now be changed */
351 this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state);
352
353 /* state has NOW changed :-) */
354 this->logger->log(this->logger, CONTROL|MORE, "Changed state of IKE_SA from %s to %s", mapping_find(ike_sa_state_m,IKE_SA_INIT_REQUESTED),mapping_find(ike_sa_state_m,IKE_AUTH_REQUESTED) );
355
356 this->logger->log(this->logger, CONTROL|MOST, "Destroy old sate object");
357 this->destroy_after_state_change(this);
358 return SUCCESS;
359 }
360
361 /**
362 * implements private_ike_sa_init_requested_t.build_ike_auth_request
363 */
364 static void build_ike_auth_request (private_ike_sa_init_requested_t *this, message_t **request)
365 {
366 payload_t *payload;
367 message_t *message;
368
369 /* going to build message */
370 this->logger->log(this->logger, CONTROL|MOST, "Going to build empty message");
371 this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &message);
372
373 /* build id payload */
374 this->build_id_payload(this, &payload);
375 this->logger->log(this->logger, CONTROL|MOST, "add ID payload to message");
376 message->add_payload(message, payload);
377
378 /* build auth payload */
379 this->build_auth_payload(this, &payload);
380 this->logger->log(this->logger, CONTROL|MOST, "add AUTH payload to message");
381 message->add_payload(message, payload);
382
383 /* build sa payload */
384 this->build_sa_payload(this, &payload);
385 this->logger->log(this->logger, CONTROL|MOST, "add SA payload to message");
386 message->add_payload(message, payload);
387
388 /* build tsi payload */
389 this->build_tsi_payload(this, &payload);
390 this->logger->log(this->logger, CONTROL|MOST, "add TSi payload to message");
391 message->add_payload(message, payload);
392
393 /* build tsr payload */
394 this->build_tsr_payload(this, &payload);
395 this->logger->log(this->logger, CONTROL|MOST, "add TSr payload to message");
396 message->add_payload(message, payload);
397
398 *request = message;
399 }
400
401 /**
402 * Implementation of private_ike_sa_init_requested_t.build_id_payload.
403 */
404 static void build_id_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
405 {
406 sa_config_t *sa_config;
407 id_payload_t *id_payload;
408 identification_t *identification;
409
410 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
411 /* identification_t object gets NOT cloned here */
412 identification = sa_config->get_my_id(sa_config);
413 id_payload = id_payload_create_from_identification(TRUE,identification);
414
415 *payload = (payload_t *) id_payload;
416 }
417
418 /**
419 * Implementation of private_ike_sa_init_requested_t.build_auth_payload.
420 */
421 static void build_auth_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
422 {
423 auth_payload_t *auth_payload;
424 sa_config_t *sa_config;
425
426 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
427 auth_payload = auth_payload_create();
428 auth_payload->set_auth_method(auth_payload,sa_config->get_auth_method(sa_config));
429 /*
430 * TODO generate AUTH DATA
431 */
432
433 *payload = (payload_t *) auth_payload;
434 }
435
436 /**
437 * Implementation of private_ike_sa_init_requested_t.build_sa_payload.
438 */
439 static void build_sa_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
440 {
441 child_proposal_t *proposals;
442 sa_payload_t *sa_payload;
443 sa_config_t *sa_config;
444 size_t proposal_count;
445 /*
446 * TODO: get SPIs from kernel
447 */
448 u_int8_t esp_spi[4] = {0x01,0x01,0x01,0x01};
449 u_int8_t ah_spi[4] = {0x01,0x01,0x01,0x01};
450
451 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
452 proposal_count = sa_config->get_proposals(sa_config,ah_spi,esp_spi,&proposals);
453 sa_payload = sa_payload_create_from_child_proposals(proposals, proposal_count);
454 allocator_free(proposals);
455
456 *payload = (payload_t *) sa_payload;
457 }
458
459 /**
460 * Implementation of private_ike_sa_init_requested_t.build_tsi_payload.
461 */
462 static void build_tsi_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
463 {
464 traffic_selector_t **traffic_selectors;
465 size_t traffic_selectors_count;
466 ts_payload_t *ts_payload;
467 sa_config_t *sa_config;
468
469 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
470 traffic_selectors_count = sa_config->get_traffic_selectors_initiator(sa_config,&traffic_selectors);
471 ts_payload = ts_payload_create_from_traffic_selectors(TRUE,traffic_selectors, traffic_selectors_count);
472 allocator_free(traffic_selectors);
473
474 *payload = (payload_t *) ts_payload;
475 }
476
477 /**
478 * Implementation of private_ike_sa_init_requested_t.build_tsr_payload.
479 */
480 static void build_tsr_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
481 {
482 traffic_selector_t **traffic_selectors;
483 size_t traffic_selectors_count;
484 ts_payload_t *ts_payload;
485 sa_config_t *sa_config;
486
487 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
488 traffic_selectors_count = sa_config->get_traffic_selectors_responder(sa_config,&traffic_selectors);
489 ts_payload = ts_payload_create_from_traffic_selectors(FALSE,traffic_selectors, traffic_selectors_count);
490 allocator_free(traffic_selectors);
491
492 *payload = (payload_t *) ts_payload;
493 }
494
495
496 /**
497 * Implements state_t.get_state
498 */
499 static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this)
500 {
501 return IKE_SA_INIT_REQUESTED;
502 }
503
504 /**
505 * Implements private_ike_sa_init_requested_t.destroy_after_state_change
506 */
507 static void destroy_after_state_change (private_ike_sa_init_requested_t *this)
508 {
509 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t after state change.");
510
511 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
512 this->diffie_hellman->destroy(this->diffie_hellman);
513 this->logger->log(this->logger, CONTROL | MOST, "Destroy shared secret (secrets allready derived)");
514 allocator_free(this->shared_secret.ptr);
515 this->logger->log(this->logger, CONTROL | MOST, "Destroy object itself");
516 allocator_free(this);
517 }
518
519 /**
520 * Implements state_t.get_state
521 */
522 static void destroy(private_ike_sa_init_requested_t *this)
523 {
524 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t");
525
526 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
527 this->diffie_hellman->destroy(this->diffie_hellman);
528 this->logger->log(this->logger, CONTROL | MOST, "Destroy sent nonce");
529 allocator_free(this->sent_nonce.ptr);
530 this->logger->log(this->logger, CONTROL | MOST, "Destroy received nonce");
531 allocator_free(this->received_nonce.ptr);
532 this->logger->log(this->logger, CONTROL | MOST, "Destroy shared secret (secrets allready derived)");
533 allocator_free(this->shared_secret.ptr);
534 this->logger->log(this->logger, CONTROL | MOST, "Destroy object itself");
535 allocator_free(this);
536 }
537
538 /*
539 * Described in header.
540 */
541 ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, u_int16_t dh_group_priority, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce)
542 {
543 private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t);
544
545 /* interface functions */
546 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
547 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
548 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
549
550 /* private functions */
551 this->build_ike_auth_request = build_ike_auth_request;
552 this->build_id_payload = build_id_payload;
553 this->build_auth_payload = build_auth_payload;
554 this->build_sa_payload = build_sa_payload;
555 this->build_tsi_payload = build_tsi_payload;
556 this->build_tsr_payload = build_tsr_payload;
557 this->destroy_after_state_change = destroy_after_state_change;
558
559 /* private data */
560 this->ike_sa = ike_sa;
561 this->received_nonce = CHUNK_INITIALIZER;
562 this->shared_secret = CHUNK_INITIALIZER;
563 this->logger = this->ike_sa->get_logger(this->ike_sa);
564 this->diffie_hellman = diffie_hellman;
565 this->sent_nonce = sent_nonce;
566 this->dh_group_priority = dh_group_priority;
567
568 return &(this->public);
569 }