(no commit message)
[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 case SECURITY_ASSOCIATION:
222 {
223 sa_payload_t *sa_payload = (sa_payload_t*)payload;
224 ike_proposal_t *ike_proposals;
225 ike_proposal_t selected_proposal;
226 size_t proposal_count;
227
228
229 /* get the list of selected proposals */
230 status = sa_payload->get_ike_proposals (sa_payload, &ike_proposals,&proposal_count);
231 if (status != SUCCESS)
232 {
233 this->logger->log(this->logger, ERROR | MORE, "SA payload does not contain IKE proposals");
234 payloads->destroy(payloads);
235 return status;
236 }
237 /* the peer has to select only one proposal */
238 if (proposal_count != 1)
239 {
240 this->logger->log(this->logger, ERROR | MORE, "More then 1 proposal (%d) selected!",proposal_count);
241 allocator_free(ike_proposals);
242 payloads->destroy(payloads);
243 return status;
244 }
245
246 /* now let the configuration-manager check the selected proposals*/
247 this->logger->log(this->logger, CONTROL | MOST, "Check selected proposal");
248 status = init_config->select_proposal (init_config,ike_proposals,1,&selected_proposal);
249 allocator_free(ike_proposals);
250 if (status != SUCCESS)
251 {
252 this->logger->log(this->logger, ERROR | MORE, "Selected proposal not a suggested one! Peer is trying to trick me!");
253 payloads->destroy(payloads);
254 return status;
255 }
256
257 status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,&selected_proposal);
258 if (status != SUCCESS)
259 {
260 this->logger->log(this->logger, ERROR | MORE, "Transform objects could not be created from selected proposal");
261 payloads->destroy(payloads);
262 return status;
263 }
264 /* ok, we have what we need for sa_payload */
265 break;
266 }
267 case KEY_EXCHANGE:
268 {
269 ke_payload_t *ke_payload = (ke_payload_t*)payload;
270 this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload));
271 /* shared secret is computed AFTER processing of all payloads... */
272 break;
273 }
274 case NONCE:
275 {
276 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
277
278 allocator_free(this->received_nonce.ptr);
279
280 this->received_nonce = CHUNK_INITIALIZER;
281
282 nonce_payload->get_nonce(nonce_payload, &(this->received_nonce));
283 break;
284 }
285 default:
286 {
287 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)));
288 payloads->destroy(payloads);
289 return FAILED;
290 }
291
292 }
293
294 }
295 payloads->destroy(payloads);
296
297 allocator_free(this->shared_secret.ptr);
298 this->shared_secret = CHUNK_INITIALIZER;
299
300 /* store shared secret
301 * status of dh objectt does not have to get checked cause other key is set
302 */
303 this->logger->log(this->logger, CONTROL | MOST, "Retrieve shared secret and store it");
304 status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &(this->shared_secret));
305 this->logger->log_chunk(this->logger, PRIVATE, "Shared secret", &this->shared_secret);
306
307 this->logger->log(this->logger, CONTROL | MOST, "Going to derive all secrets from shared secret");
308 this->ike_sa->compute_secrets(this->ike_sa,this->shared_secret,this->sent_nonce, this->received_nonce);
309
310 /* build the complete IKE_AUTH request */
311 this->build_ike_auth_request (this,&request);
312
313 /* generate packet */
314 this->logger->log(this->logger, CONTROL|MOST, "Generate packet from message");
315
316 status = request->generate(request, this->ike_sa->get_crypter_initiator(this->ike_sa), this->ike_sa->get_signer_initiator(this->ike_sa), &packet);
317 if (status != SUCCESS)
318 {
319 this->logger->log(this->logger, ERROR, "Could not generate packet from message");
320 request->destroy(request);
321 return DELETE_ME;
322 }
323
324 this->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
325 charon->send_queue->add(charon->send_queue, packet);
326
327 /* state can now be changed */
328 this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
329 next_state = ike_auth_requested_create(this->ike_sa,this->sent_nonce,this->received_nonce);
330
331 /* last messages can now be set */
332 status = this->ike_sa->set_last_requested_message(this->ike_sa, request);
333
334 if (status != SUCCESS)
335 {
336 this->logger->log(this->logger, ERROR, "Could not set last requested message");
337 (next_state->state_interface).destroy(&(next_state->state_interface));
338 request->destroy(request);
339 return DELETE_ME;
340 }
341
342 /* state can now be changed */
343 this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state);
344
345 /* state has NOW changed :-) */
346 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) );
347
348 this->logger->log(this->logger, CONTROL|MOST, "Destroy old sate object");
349 this->destroy_after_state_change(this);
350 return SUCCESS;
351 }
352
353 /**
354 * implements private_ike_sa_init_requested_t.build_ike_auth_request
355 */
356 static void build_ike_auth_request (private_ike_sa_init_requested_t *this, message_t **request)
357 {
358 payload_t *payload;
359 message_t *message;
360
361 /* going to build message */
362 this->logger->log(this->logger, CONTROL|MOST, "Going to build empty message");
363 this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &message);
364
365 /* build id payload */
366 this->build_id_payload(this, &payload);
367 this->logger->log(this->logger, CONTROL|MOST, "add ID payload to message");
368 message->add_payload(message, payload);
369
370 /* build auth payload */
371 this->build_auth_payload(this, &payload);
372 this->logger->log(this->logger, CONTROL|MOST, "add AUTH payload to message");
373 message->add_payload(message, payload);
374
375 /* build sa payload */
376 this->build_sa_payload(this, &payload);
377 this->logger->log(this->logger, CONTROL|MOST, "add SA payload to message");
378 message->add_payload(message, payload);
379
380 /* build tsi payload */
381 this->build_tsi_payload(this, &payload);
382 this->logger->log(this->logger, CONTROL|MOST, "add TSi payload to message");
383 message->add_payload(message, payload);
384
385 /* build tsr payload */
386 this->build_tsr_payload(this, &payload);
387 this->logger->log(this->logger, CONTROL|MOST, "add TSr payload to message");
388 message->add_payload(message, payload);
389
390 *request = message;
391 }
392
393 /**
394 * Implementation of private_ike_sa_init_requested_t.build_id_payload.
395 */
396 static void build_id_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
397 {
398 sa_config_t *sa_config;
399 id_payload_t *id_payload;
400 identification_t *identification;
401
402 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
403 /* identification_t object gets NOT cloned here */
404 identification = sa_config->get_my_id(sa_config);
405 id_payload = id_payload_create_from_identification(TRUE,identification);
406
407 *payload = (payload_t *) id_payload;
408 }
409
410 /**
411 * Implementation of private_ike_sa_init_requested_t.build_auth_payload.
412 */
413 static void build_auth_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
414 {
415 auth_payload_t *auth_payload;
416 sa_config_t *sa_config;
417
418 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
419 auth_payload = auth_payload_create();
420 auth_payload->set_auth_method(auth_payload,sa_config->get_auth_method(sa_config));
421 /*
422 * TODO generate AUTH DATA
423 */
424
425 *payload = (payload_t *) auth_payload;
426 }
427
428 /**
429 * Implementation of private_ike_sa_init_requested_t.build_sa_payload.
430 */
431 static void build_sa_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
432 {
433 child_proposal_t *proposals;
434 sa_payload_t *sa_payload;
435 sa_config_t *sa_config;
436 size_t proposal_count;
437 /*
438 * TODO: get SPIs from kernel
439 */
440 u_int8_t esp_spi[4] = {0x01,0x01,0x01,0x01};
441 u_int8_t ah_spi[4] = {0x01,0x01,0x01,0x01};
442
443 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
444 proposal_count = sa_config->get_proposals(sa_config,ah_spi,esp_spi,&proposals);
445 sa_payload = sa_payload_create_from_child_proposals(proposals, proposal_count);
446 allocator_free(proposals);
447
448 *payload = (payload_t *) sa_payload;
449 }
450
451 /**
452 * Implementation of private_ike_sa_init_requested_t.build_tsi_payload.
453 */
454 static void build_tsi_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
455 {
456 traffic_selector_t **traffic_selectors;
457 size_t traffic_selectors_count;
458 ts_payload_t *ts_payload;
459 sa_config_t *sa_config;
460
461 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
462 traffic_selectors_count = sa_config->get_traffic_selectors_initiator(sa_config,&traffic_selectors);
463 ts_payload = ts_payload_create_from_traffic_selectors(TRUE,traffic_selectors, traffic_selectors_count);
464 allocator_free(traffic_selectors);
465
466 *payload = (payload_t *) ts_payload;
467 }
468
469 /**
470 * Implementation of private_ike_sa_init_requested_t.build_tsr_payload.
471 */
472 static void build_tsr_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
473 {
474 traffic_selector_t **traffic_selectors;
475 size_t traffic_selectors_count;
476 ts_payload_t *ts_payload;
477 sa_config_t *sa_config;
478
479 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
480 traffic_selectors_count = sa_config->get_traffic_selectors_responder(sa_config,&traffic_selectors);
481 ts_payload = ts_payload_create_from_traffic_selectors(FALSE,traffic_selectors, traffic_selectors_count);
482 allocator_free(traffic_selectors);
483
484 *payload = (payload_t *) ts_payload;
485 }
486
487
488 /**
489 * Implements state_t.get_state
490 */
491 static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this)
492 {
493 return IKE_SA_INIT_REQUESTED;
494 }
495
496 /**
497 * Implements private_ike_sa_init_requested_t.destroy_after_state_change
498 */
499 static void destroy_after_state_change (private_ike_sa_init_requested_t *this)
500 {
501 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t after state change.");
502
503 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
504 this->diffie_hellman->destroy(this->diffie_hellman);
505 this->logger->log(this->logger, CONTROL | MOST, "Destroy shared secret (secrets allready derived)");
506 allocator_free(this->shared_secret.ptr);
507 this->logger->log(this->logger, CONTROL | MOST, "Destroy object itself");
508 allocator_free(this);
509 }
510
511 /**
512 * Implements state_t.get_state
513 */
514 static void destroy(private_ike_sa_init_requested_t *this)
515 {
516 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t");
517
518 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
519 this->diffie_hellman->destroy(this->diffie_hellman);
520 this->logger->log(this->logger, CONTROL | MOST, "Destroy sent nonce");
521 allocator_free(this->sent_nonce.ptr);
522 this->logger->log(this->logger, CONTROL | MOST, "Destroy received nonce");
523 allocator_free(this->received_nonce.ptr);
524 this->logger->log(this->logger, CONTROL | MOST, "Destroy shared secret (secrets allready derived)");
525 allocator_free(this->shared_secret.ptr);
526 this->logger->log(this->logger, CONTROL | MOST, "Destroy object itself");
527 allocator_free(this);
528 }
529
530 /*
531 * Described in header.
532 */
533 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)
534 {
535 private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t);
536
537 /* interface functions */
538 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
539 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
540 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
541
542 /* private functions */
543 this->build_ike_auth_request = build_ike_auth_request;
544 this->build_id_payload = build_id_payload;
545 this->build_auth_payload = build_auth_payload;
546 this->build_sa_payload = build_sa_payload;
547 this->build_tsi_payload = build_tsi_payload;
548 this->build_tsr_payload = build_tsr_payload;
549 this->destroy_after_state_change = destroy_after_state_change;
550
551 /* private data */
552 this->ike_sa = ike_sa;
553 this->received_nonce = CHUNK_INITIALIZER;
554 this->shared_secret = CHUNK_INITIALIZER;
555 this->logger = this->ike_sa->get_logger(this->ike_sa);
556 this->diffie_hellman = diffie_hellman;
557 this->sent_nonce = sent_nonce;
558 this->dh_group_priority = dh_group_priority;
559
560 return &(this->public);
561 }