0e2bc7017c078b928c1a826cce97632cbaf3d691
[strongswan.git] / Source / charon / states / responder_init.c
1 /**
2 * @file responder_init.c
3 *
4 * @brief Start state of a IKE_SA as responder
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 "responder_init.h"
24
25 #include "../globals.h"
26 #include "../utils/allocator.h"
27 #include "../payloads/sa_payload.h"
28 #include "../payloads/ke_payload.h"
29 #include "../payloads/nonce_payload.h"
30 #include "../transforms/diffie_hellman.h"
31
32 /**
33 * Private data of a responder_init_t object.
34 *
35 */
36 typedef struct private_responder_init_s private_responder_init_t;
37 struct private_responder_init_s {
38 /**
39 * Methods of the state_t interface.
40 */
41 responder_init_t public;
42
43 /**
44 * Assigned IKE_SA.
45 */
46 protected_ike_sa_t *ike_sa;
47
48 /**
49 * Diffie Hellman object used to compute shared secret.
50 *
51 * After processing of incoming IKE_SA_INIT-Request the shared key is
52 * passed to the next state of type ike_sa_init_responded_t.
53 */
54 diffie_hellman_t *diffie_hellman;
55
56 /**
57 * Diffie Hellman group number.
58 */
59 u_int16_t dh_group_number;
60
61 /**
62 * Priority used to get matching dh_group number.
63 */
64 u_int16_t dh_group_priority;
65
66 /**
67 * Sent nonce value.
68 *
69 * This value is passed to the next state of type ike_sa_init_responded_t.
70 */
71 chunk_t sent_nonce;
72
73 /**
74 * Received nonce value
75 */
76 chunk_t received_nonce;
77
78 /**
79 * Logger used to log data
80 *
81 * Is logger of ike_sa!
82 */
83 logger_t *logger;
84
85 /**
86 * Proposals used to initiate connection
87 */
88 linked_list_t *proposals;
89
90 /**
91 * Builds the SA payload for this state.
92 *
93 * @param this calling object
94 * @param payload The generated SA payload object of type ke_payload_t is
95 * stored at this location.
96 * @return
97 * - SUCCESS
98 * - OUT_OF_RES
99 */
100 status_t (*build_sa_payload) (private_responder_init_t *this, payload_t **payload);
101
102 /**
103 * Builds the KE payload for this state.
104 *
105 * @param this calling object
106 * @param payload The generated KE payload object of type ke_payload_t is
107 * stored at this location.
108 * @return
109 * - SUCCESS
110 * - OUT_OF_RES
111 */
112 status_t (*build_ke_payload) (private_responder_init_t *this, payload_t **payload);
113 /**
114 * Builds the NONCE payload for this state.
115 *
116 * @param this calling object
117 * @param payload The generated NONCE payload object of type ke_payload_t is
118 * stored at this location.
119 * @return
120 * - SUCCESS
121 * - OUT_OF_RES
122 */
123 status_t (*build_nonce_payload) (private_responder_init_t *this, payload_t **payload);
124 };
125
126 /**
127 * Implements state_t.get_state
128 */
129 static status_t process_message(private_responder_init_t *this, message_t *message, state_t **new_state)
130 {
131 linked_list_iterator_t *payloads;
132 host_t *source, *destination;
133 status_t status;
134 message_t *response;
135 payload_t *payload;
136 packet_t *packet;
137
138 /* this is the first message we process, so copy host infos */
139 message->get_source(message, &source);
140 message->get_destination(message, &destination);
141
142 /* we need to clone them, since we destroy the message later */
143 destination->clone(destination, &(this->ike_sa->me.host));
144 source->clone(source, &(this->ike_sa->other.host));
145
146 /* parse incoming message */
147 status = message->parse_body(message);
148 if (status != SUCCESS)
149 {
150 this->logger->log(this->logger, ERROR | MORE, "Could not parse body of request message");
151 return status;
152 }
153
154 /* iterate over incoming payloads. We can be sure, the message contains only accepted payloads! */
155 status = message->get_payload_iterator(message, &payloads);
156 if (status != SUCCESS)
157 {
158 this->logger->log(this->logger, ERROR, "Fatal error: Could not get payload interator");
159 return status;
160 }
161
162 while (payloads->has_next(payloads))
163 {
164 payload_t *payload;
165
166 /* get current payload */
167 payloads->current(payloads, (void**)&payload);
168
169 this->logger->log(this->logger, CONTROL|MORE, "Processing payload of type %s", mapping_find(payload_type_m, payload->get_type(payload)));
170 switch (payload->get_type(payload))
171 {
172 case SECURITY_ASSOCIATION:
173 {
174 sa_payload_t *sa_payload = (sa_payload_t*)payload;
175 linked_list_iterator_t *suggested_proposals, *accepted_proposals;
176
177 status = this->proposals->create_iterator(this->proposals, &accepted_proposals, FALSE);
178 if (status != SUCCESS)
179 {
180 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on list for proposals");
181 payloads->destroy(payloads);
182 return status;
183 }
184
185 /* get the list of suggested proposals */
186 status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
187 if (status != SUCCESS)
188 {
189 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on suggested proposals");
190 accepted_proposals->destroy(accepted_proposals);
191 payloads->destroy(payloads);
192 return status;
193 }
194
195 /* now let the configuration-manager select a subset of the proposals */
196 status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
197 this->ike_sa->other.host, suggested_proposals, accepted_proposals);
198 if (status != SUCCESS)
199 {
200 this->logger->log(this->logger, CONTROL | MORE, "No proposal of suggested proposals selected");
201 suggested_proposals->destroy(suggested_proposals);
202 accepted_proposals->destroy(accepted_proposals);
203 payloads->destroy(payloads);
204 return status;
205 }
206
207 /* iterators are not needed anymore */
208 suggested_proposals->destroy(suggested_proposals);
209 accepted_proposals->destroy(accepted_proposals);
210
211 this->logger->log(this->logger, CONTROL | MORE, "SA Payload processed");
212 /* ok, we have what we need for sa_payload (proposals are stored in this->proposals)*/
213 break;
214 }
215 case KEY_EXCHANGE:
216 {
217 ke_payload_t *ke_payload = (ke_payload_t*)payload;
218 diffie_hellman_group_t group;
219 diffie_hellman_t *dh;
220 bool allowed_group;
221
222 group = ke_payload->get_dh_group_number(ke_payload);
223
224 status = global_configuration_manager->is_dh_group_allowed_for_host(global_configuration_manager,
225 this->ike_sa->other.host, group, &allowed_group);
226
227 if (status != SUCCESS)
228 {
229 this->logger->log(this->logger, ERROR | MORE, "Could not get informations about DH group");
230 payloads->destroy(payloads);
231 return status;
232 }
233 if (!allowed_group)
234 {
235 /** @todo Send info reply */
236 }
237
238 /* create diffie hellman object to handle DH exchange */
239 dh = diffie_hellman_create(group);
240 if (dh == NULL)
241 {
242 this->logger->log(this->logger, ERROR, "Could not generate DH object");
243 payloads->destroy(payloads);
244 return OUT_OF_RES;
245 }
246
247 this->logger->log(this->logger, CONTROL | MORE, "Set other DH public value");
248
249 status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
250 if (status != SUCCESS)
251 {
252 this->logger->log(this->logger, ERROR, "Could not set other DH public value");
253 dh->destroy(dh);
254 payloads->destroy(payloads);
255 return OUT_OF_RES;
256 }
257
258 this->diffie_hellman = dh;
259
260 this->logger->log(this->logger, CONTROL | MORE, "KE Payload processed");
261 break;
262 }
263 case NONCE:
264 {
265 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
266 chunk_t nonce;
267
268 this->logger->log(this->logger, CONTROL | MORE, "Get nonce value and store it");
269 nonce_payload->get_nonce(nonce_payload, &nonce);
270 /** @todo free if there is already one */
271 this->received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
272 this->received_nonce.len = nonce.len;
273 if (this->received_nonce.ptr == NULL)
274 {
275 payloads->destroy(payloads);
276 return OUT_OF_RES;
277 }
278
279 this->logger->log(this->logger, CONTROL | MORE, "Nonce Payload processed");
280 break;
281 }
282 default:
283 {
284 this->logger->log(this->logger, ERROR | MORE, "Payload type not supported!");
285 payloads->destroy(payloads);
286 return OUT_OF_RES;
287 }
288
289 }
290
291 }
292 /* iterator can be destroyed */
293 payloads->destroy(payloads);
294
295 /********************/
296 diffie_hellman_t *dh = this->diffie_hellman;
297 chunk_t shared_secret;
298
299 status = dh->get_shared_secret(dh, &shared_secret);
300 this->logger->log_chunk(this->logger, RAW, "Shared secret", &shared_secret);
301
302 allocator_free_chunk(shared_secret);
303 /********************/
304
305
306 this->logger->log(this->logger, CONTROL | MORE, "Request successfully handled. Going to create reply.");
307
308 this->logger->log(this->logger, CONTROL | MOST, "Going to create nonce.");
309 if (this->ike_sa->randomizer->allocate_pseudo_random_bytes(this->ike_sa->randomizer, NONCE_SIZE, &(this->sent_nonce)) != SUCCESS)
310 {
311 this->logger->log(this->logger, ERROR, "Could not create nonce!");
312 return OUT_OF_RES;
313 }
314
315
316 /* set up the reply */
317 status = this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response);
318 if (status != SUCCESS)
319 {
320 this->logger->log(this->logger, ERROR, "Could not create empty message");
321 return status;
322 }
323
324 /* build SA payload */
325 status = this->build_sa_payload(this, &payload);
326 if (status != SUCCESS)
327 {
328 this->logger->log(this->logger, ERROR, "Could not build SA payload");
329 return status;
330 }
331
332 this ->logger->log(this->logger, CONTROL|MOST, "add SA payload to message");
333 status = response->add_payload(response, payload);
334 if (status != SUCCESS)
335 {
336 this->logger->log(this->logger, ERROR, "Could not add SA payload to message");
337 return status;
338 }
339
340 /* build KE payload */
341 status = this->build_ke_payload(this,&payload);
342 if (status != SUCCESS)
343 {
344 this->logger->log(this->logger, ERROR, "Could not build KE payload");
345 return status;
346 }
347
348 this ->logger->log(this->logger, CONTROL|MOST, "add KE payload to message");
349 status = response->add_payload(response, payload);
350 if (status != SUCCESS)
351 {
352 this->logger->log(this->logger, ERROR, "Could not add KE payload to message");
353 return status;
354 }
355
356 /* build Nonce payload */
357 status = this->build_nonce_payload(this, &payload);
358 if (status != SUCCESS)
359 {
360 this->logger->log(this->logger, ERROR, "Could not build NONCE payload");
361 return status;
362 }
363
364 this ->logger->log(this->logger, CONTROL|MOST, "add nonce payload to message");
365 status = response->add_payload(response, payload);
366 if (status != SUCCESS)
367 {
368 this->logger->log(this->logger, ERROR, "Could not add nonce payload to message");
369 return status;
370 }
371
372 /* generate packet */
373 this ->logger->log(this->logger, CONTROL|MOST, "generate packet from message");
374 status = response->generate(response, &packet);
375 if (status != SUCCESS)
376 {
377 this->logger->log(this->logger, ERROR, "Fatal error: could not generate packet from message");
378 return status;
379 }
380
381 this ->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
382 status = global_send_queue->add(global_send_queue, packet);
383 if (status != SUCCESS)
384 {
385 this->logger->log(this->logger, ERROR, "Could not add packet to send queue");
386 return status;
387 }
388
389 if ( this->ike_sa->last_responded_message != NULL)
390 {
391 /* destroy message */
392 this ->logger->log(this->logger, CONTROL|MOST, "Destroy stored last responded message");
393 this->ike_sa->last_responded_message->destroy(this->ike_sa->last_responded_message);
394 }
395
396 this->ike_sa->last_responded_message = response;
397
398 /* state has NOW changed :-) */
399 // this ->logger->log(this->logger, CONTROL|MORE, "Change state of IKE_SA from %s to %s",mapping_find(ike_sa_state_m,this->state),mapping_find(ike_sa_state_m,IKE_SA_INIT_REQUESTED) );
400
401 *new_state = &(this->public.state_interface);
402
403 return SUCCESS;
404 }
405
406 /**
407 * implements private_initiator_init_t.build_sa_payload
408 */
409 static status_t build_sa_payload(private_responder_init_t *this, payload_t **payload)
410 {
411 sa_payload_t* sa_payload;
412 linked_list_iterator_t *proposal_iterator;
413 status_t status;
414
415
416 /* SA payload takes proposals from this->ike_sa_init_data.proposals and writes them to the created sa_payload */
417
418 this->logger->log(this->logger, CONTROL|MORE, "building sa payload");
419
420 status = this->proposals->create_iterator(this->proposals, &proposal_iterator, FALSE);
421 if (status != SUCCESS)
422 {
423 this->logger->log(this->logger, ERROR, "Fatal error: Could not create iterator on list for proposals");
424 return status;
425 }
426
427 sa_payload = sa_payload_create();
428 if (sa_payload == NULL)
429 {
430 this->logger->log(this->logger, ERROR, "Fatal error: Could not create SA payload object");
431 return OUT_OF_RES;
432 }
433
434 while (proposal_iterator->has_next(proposal_iterator))
435 {
436 proposal_substructure_t *current_proposal;
437 proposal_substructure_t *current_proposal_clone;
438 status = proposal_iterator->current(proposal_iterator,(void **) &current_proposal);
439 if (status != SUCCESS)
440 {
441 this->logger->log(this->logger, ERROR, "Could not get current proposal needed to copy");
442 proposal_iterator->destroy(proposal_iterator);
443 sa_payload->destroy(sa_payload);
444 return status;
445 }
446 status = current_proposal->clone(current_proposal,&current_proposal_clone);
447 if (status != SUCCESS)
448 {
449 this->logger->log(this->logger, ERROR, "Could not clone current proposal");
450 proposal_iterator->destroy(proposal_iterator);
451 sa_payload->destroy(sa_payload);
452 return status;
453 }
454
455 status = sa_payload->add_proposal_substructure(sa_payload,current_proposal_clone);
456 if (status != SUCCESS)
457 {
458 this->logger->log(this->logger, ERROR, "Could not add cloned proposal to SA payload");
459 proposal_iterator->destroy(proposal_iterator);
460 sa_payload->destroy(sa_payload);
461 return status;
462 }
463
464 }
465
466 proposal_iterator->destroy(proposal_iterator);
467
468 this->logger->log(this->logger, CONTROL|MORE, "sa payload builded");
469
470 *payload = (payload_t *) sa_payload;
471
472 return SUCCESS;
473 }
474
475 /**
476 * implements private_initiator_init_t.build_ke_payload
477 */
478 static status_t build_ke_payload(private_responder_init_t *this, payload_t **payload)
479 {
480 ke_payload_t *ke_payload;
481 chunk_t key_data;
482 status_t status;
483
484 this->logger->log(this->logger, CONTROL|MORE, "building ke payload");
485
486
487 this ->logger->log(this->logger, CONTROL|MORE, "get public dh value to send in ke payload");
488 status = this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data);
489 if (status != SUCCESS)
490 {
491 this->logger->log(this->logger, ERROR, "Could not get my DH public value");
492 return status;
493 }
494
495 ke_payload = ke_payload_create();
496 if (ke_payload == NULL)
497 {
498 this->logger->log(this->logger, ERROR, "Could not create KE payload");
499 allocator_free_chunk(key_data);
500 return OUT_OF_RES;
501 }
502 ke_payload->set_dh_group_number(ke_payload, MODP_1024_BIT);
503 if (ke_payload->set_key_exchange_data(ke_payload, key_data) != SUCCESS)
504 {
505 this->logger->log(this->logger, ERROR, "Could not set key exchange data of KE payload");
506 ke_payload->destroy(ke_payload);
507 allocator_free_chunk(key_data);
508 return OUT_OF_RES;
509 }
510 allocator_free_chunk(key_data);
511
512 *payload = (payload_t *) ke_payload;
513 return SUCCESS;
514 }
515
516 /**
517 * implements private_initiator_init_t.build_nonce_payload
518 */
519 static status_t build_nonce_payload(private_responder_init_t *this, payload_t **payload)
520 {
521 nonce_payload_t *nonce_payload;
522 status_t status;
523
524 this->logger->log(this->logger, CONTROL|MORE, "building nonce payload");
525
526 nonce_payload = nonce_payload_create();
527 if (nonce_payload == NULL)
528 {
529 this->logger->log(this->logger, ERROR, "Fatal error: could not create nonce payload object");
530 return OUT_OF_RES;
531 }
532
533 status = nonce_payload->set_nonce(nonce_payload, this->sent_nonce);
534
535 if (status != SUCCESS)
536 {
537 this->logger->log(this->logger, ERROR, "Fatal error: could not set nonce data of payload");
538 nonce_payload->destroy(nonce_payload);
539 return status;
540 }
541
542 *payload = (payload_t *) nonce_payload;
543
544 return SUCCESS;
545 }
546
547
548 /**
549 * Implements state_t.get_state
550 */
551 static ike_sa_state_t get_state(private_responder_init_t *this)
552 {
553 return RESPONDER_INIT;
554 }
555
556 /**
557 * Implements state_t.get_state
558 */
559 static status_t destroy(private_responder_init_t *this)
560 {
561 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy responder init state object");
562
563 /* destroy stored proposal */
564 this->logger->log(this->logger, CONTROL | MOST, "Destroy stored proposals");
565 while (this->proposals->get_count(this->proposals) > 0)
566 {
567 proposal_substructure_t *current_proposal;
568 this->proposals->remove_first(this->proposals,(void **)&current_proposal);
569 current_proposal->destroy(current_proposal);
570 }
571 this->proposals->destroy(this->proposals);
572
573 if (this->sent_nonce.ptr != NULL)
574 {
575 this->logger->log(this->logger, CONTROL | MOST, "Destroy sent nonce");
576 allocator_free(this->sent_nonce.ptr);
577 }
578
579 if (this->received_nonce.ptr != NULL)
580 {
581 this->logger->log(this->logger, CONTROL | MOST, "Destroy received nonce");
582 allocator_free(this->received_nonce.ptr);
583 }
584
585 /* destroy diffie hellman object */
586 if (this->diffie_hellman != NULL)
587 {
588 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie_hellman_t object");
589 this->diffie_hellman->destroy(this->diffie_hellman);
590 }
591
592 allocator_free(this);
593
594 return SUCCESS;
595
596 }
597
598 /*
599 * Described in header.
600 */
601 responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
602 {
603 private_responder_init_t *this = allocator_alloc_thing(private_responder_init_t);
604
605 if (this == NULL)
606 {
607 return NULL;
608 }
609
610 /* interface functions */
611 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *,state_t **)) process_message;
612 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
613 this->public.state_interface.destroy = (status_t (*) (state_t *)) destroy;
614
615 /* private functions */
616 this->build_sa_payload = build_sa_payload;
617 this->build_ke_payload = build_ke_payload;
618 this->build_nonce_payload = build_nonce_payload;
619
620 /* private data */
621 this->ike_sa = ike_sa;
622 this->logger = this->ike_sa->logger;
623 this->sent_nonce.ptr = NULL;
624 this->sent_nonce.len = 0;
625 this->received_nonce.ptr = NULL;
626 this->received_nonce.len = 0;
627 this->proposals = linked_list_create();
628 if (this->proposals == NULL)
629 {
630 allocator_free(this);
631 return NULL;
632 }
633
634 return &(this->public);
635 }