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