]> git.ipfire.org Git - people/ms/strongswan.git/blame - Source/charon/sa/states/ike_sa_init_requested.c
- get_type changed
[people/ms/strongswan.git] / Source / charon / sa / states / ike_sa_init_requested.c
CommitLineData
c7dd2a7b
MW
1/**
2 * @file ike_sa_init_requested.c
3 *
df3c59d0 4 * @brief Implementation of ike_sa_init_requested_t.
c7dd2a7b
MW
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
0e96f7d8 25#include <daemon.h>
c7dd2a7b
MW
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>
f890d8fe 30#include <encoding/payloads/id_payload.h>
af30c6b9 31#include <encoding/payloads/auth_payload.h>
1b3f92d2 32#include <encoding/payloads/ts_payload.h>
c7dd2a7b 33#include <transforms/diffie_hellman.h>
af30c6b9 34#include <sa/states/ike_auth_requested.h>
c7dd2a7b 35
5796aa16
MW
36
37typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t;
38
c7dd2a7b
MW
39/**
40 * Private data of a ike_sa_init_requested_t object.
41 *
42 */
5796aa16 43struct private_ike_sa_init_requested_t {
c7dd2a7b
MW
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 *
1b3f92d2 77 * Currently unused but usable if informational messages of unsupported dh group number are processed.
c7dd2a7b
MW
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;
f890d8fe
JH
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
af30c6b9
JH
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
1b3f92d2
JH
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
af30c6b9
JH
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);
c7dd2a7b
MW
149};
150
151/**
152 * Implements state_t.get_state
153 */
1b3f92d2 154static status_t process_message(private_ike_sa_init_requested_t *this, message_t *ike_sa_init_reply)
c7dd2a7b 155{
1b3f92d2 156 ike_auth_requested_t *next_state;
aad398a7 157 exchange_type_t exchange_type;
56aeee49 158 init_config_t *init_config;
aad398a7
JH
159 u_int64_t responder_spi;
160 ike_sa_id_t *ike_sa_id;
1b3f92d2
JH
161 iterator_t *payloads;
162 message_t *request;
163 packet_t *packet;
164 status_t status;
aad398a7 165
1b3f92d2
JH
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);
c7dd2a7b
MW
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
1b3f92d2 180 if (ike_sa_init_reply->get_request(ike_sa_init_reply))
c7dd2a7b
MW
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 */
1b3f92d2 187 status = ike_sa_init_reply->parse_body(ike_sa_init_reply, NULL, NULL);
c7dd2a7b
MW
188 if (status != SUCCESS)
189 {
1b3f92d2 190 this->logger->log(this->logger, ERROR | MORE, "Parsing of body returned error: %s",mapping_find(status_m,status));
c7dd2a7b
MW
191 return status;
192 }
193
56aeee49
JH
194 /* get configuration */
195 init_config = this->ike_sa->get_init_config(this->ike_sa);
196
1b3f92d2
JH
197
198 if (responder_spi == 0)
199 {
56aeee49 200 this->logger->log(this->logger, ERROR | MORE, "Responder SPI still zero");
1b3f92d2
JH
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);
aad398a7
JH
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);
c7dd2a7b 207
1b3f92d2
JH
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);
c7dd2a7b 213 while (payloads->has_next(payloads))
56aeee49 214 {
c7dd2a7b
MW
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 {
b9d9f188 223 sa_payload_t *sa_payload = (sa_payload_t*)payload;
a9428251
JH
224 ike_proposal_t *ike_proposals;
225 ike_proposal_t selected_proposal;
226 size_t proposal_count;
56aeee49 227
aad398a7 228
56aeee49 229 /* get the list of selected proposals */
a9428251 230 status = sa_payload->get_ike_proposals (sa_payload, &ike_proposals,&proposal_count);
c7dd2a7b
MW
231 if (status != SUCCESS)
232 {
a9428251 233 this->logger->log(this->logger, ERROR | MORE, "SA payload does not contain IKE proposals");
c7dd2a7b 234 payloads->destroy(payloads);
a9428251 235 return status;
c7dd2a7b 236 }
56aeee49 237 /* the peer has to select only one proposal */
a9428251 238 if (proposal_count != 1)
b9d9f188 239 {
56aeee49 240 this->logger->log(this->logger, ERROR | MORE, "More then 1 proposal (%d) selected!",proposal_count);
a9428251 241 allocator_free(ike_proposals);
b9d9f188 242 payloads->destroy(payloads);
a9428251 243 return status;
b9d9f188 244 }
a9428251
JH
245
246 /* now let the configuration-manager check the selected proposals*/
56aeee49 247 this->logger->log(this->logger, CONTROL | MOST, "Check selected proposal");
a9428251
JH
248 status = init_config->select_proposal (init_config,ike_proposals,1,&selected_proposal);
249 allocator_free(ike_proposals);
b9d9f188 250 if (status != SUCCESS)
c7dd2a7b 251 {
56aeee49 252 this->logger->log(this->logger, ERROR | MORE, "Selected proposal not a suggested one! Peer is trying to trick me!");
c7dd2a7b 253 payloads->destroy(payloads);
b9d9f188
JH
254 return status;
255 }
a9428251
JH
256
257 status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,&selected_proposal);
b9d9f188
JH
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;
c7dd2a7b 263 }
c7dd2a7b
MW
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;
56aeee49 270 this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload));
c7dd2a7b
MW
271 /* shared secret is computed AFTER processing of all payloads... */
272 break;
273 }
274 case NONCE:
275 {
56aeee49 276 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
c7dd2a7b 277
d048df5c 278 allocator_free(this->received_nonce.ptr);
56aeee49 279
d048df5c
MW
280 this->received_nonce = CHUNK_INITIALIZER;
281
282 nonce_payload->get_nonce(nonce_payload, &(this->received_nonce));
c7dd2a7b
MW
283 break;
284 }
285 default:
286 {
56aeee49 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)));
c7dd2a7b
MW
288 payloads->destroy(payloads);
289 return FAILED;
290 }
291
292 }
293
294 }
295 payloads->destroy(payloads);
d048df5c
MW
296
297 allocator_free(this->shared_secret.ptr);
298 this->shared_secret = CHUNK_INITIALIZER;
299
56aeee49
JH
300 /* store shared secret
301 * status of dh objectt does not have to get checked cause other key is set
302 */
c7dd2a7b
MW
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);
56aeee49
JH
306
307 this->logger->log(this->logger, CONTROL | MOST, "Going to derive all secrets from shared secret");
d048df5c 308 this->ike_sa->compute_secrets(this->ike_sa,this->shared_secret,this->sent_nonce, this->received_nonce);
c7dd2a7b 309
d440fe6d 310 /* build the complete IKE_AUTH request */
f890d8fe
JH
311 this->build_ike_auth_request (this,&request);
312
313 /* generate packet */
56aeee49 314 this->logger->log(this->logger, CONTROL|MOST, "Generate packet from message");
f890d8fe
JH
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 {
56aeee49 319 this->logger->log(this->logger, ERROR, "Could not generate packet from message");
1b3f92d2 320 request->destroy(request);
56aeee49 321 return DELETE_ME;
f890d8fe
JH
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
af30c6b9
JH
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);
f890d8fe 330
d440fe6d
JH
331 /* last message 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");
af30c6b9 337 (next_state->state_interface).destroy(&(next_state->state_interface));
d440fe6d 338 request->destroy(request);
56aeee49 339 return DELETE_ME;
d440fe6d
JH
340 }
341
af30c6b9
JH
342 /* state can now be changed */
343 this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state);
f890d8fe 344
af30c6b9
JH
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) );
c7dd2a7b 347
af30c6b9
JH
348 this->logger->log(this->logger, CONTROL|MOST, "Destroy old sate object");
349 this->destroy_after_state_change(this);
c7dd2a7b
MW
350 return SUCCESS;
351}
352
f890d8fe
JH
353/**
354 * implements private_ike_sa_init_requested_t.build_ike_auth_request
355 */
356static 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
f890d8fe
JH
365 /* build id payload */
366 this->build_id_payload(this, &payload);
af30c6b9
JH
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");
f890d8fe
JH
373 message->add_payload(message, payload);
374
1b3f92d2
JH
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
f890d8fe
JH
390 *request = message;
391}
392
af30c6b9
JH
393/**
394 * Implementation of private_ike_sa_init_requested_t.build_id_payload.
395 */
f890d8fe
JH
396static void build_id_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
397{
1b3f92d2 398 sa_config_t *sa_config;
f890d8fe 399 id_payload_t *id_payload;
1b3f92d2
JH
400 identification_t *identification;
401
402 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
403
404 identification = sa_config->get_my_id(sa_config);
f890d8fe
JH
405
406 /* create IDi */
1b3f92d2 407 id_payload = id_payload_create_from_identification(TRUE,identification);
f890d8fe
JH
408
409 *payload = (payload_t *) id_payload;
410}
411
af30c6b9
JH
412/**
413 * Implementation of private_ike_sa_init_requested_t.build_auth_payload.
414 */
415static void build_auth_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
416{
417 auth_payload_t *auth_payload;
1b3f92d2
JH
418 sa_config_t *sa_config;
419
420 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
af30c6b9 421
af30c6b9 422 auth_payload = auth_payload_create();
1b3f92d2 423 auth_payload->set_auth_method(auth_payload,sa_config->get_auth_method(sa_config));
af30c6b9
JH
424 *payload = (payload_t *) auth_payload;
425}
426
1b3f92d2
JH
427/**
428 * Implementation of private_ike_sa_init_requested_t.build_sa_payload.
429 */
430static void build_sa_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
431{
432 sa_config_t *sa_config;
433 sa_payload_t *sa_payload;
434 u_int8_t esp_spi[4] = {0x01,0x01,0x01,0x01};
435 u_int8_t ah_spi[4] = {0x01,0x01,0x01,0x01};
436 size_t proposal_count;
437 child_proposal_t *proposals;
438
439 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
440
441 proposal_count = sa_config->get_proposals(sa_config,ah_spi,esp_spi,&proposals);
442 /* create IDi */
443 sa_payload = sa_payload_create_from_child_proposals(proposals, proposal_count);
444 allocator_free(proposals);
445 *payload = (payload_t *) sa_payload;
446}
447
448/**
449 * Implementation of private_ike_sa_init_requested_t.build_tsi_payload.
450 */
451static void build_tsi_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
452{
453 sa_config_t *sa_config;
454 ts_payload_t *ts_payload;
455 size_t traffic_selectors_count;
456 traffic_selector_t **traffic_selectors;
457
458 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
459
460 traffic_selectors_count = sa_config->get_traffic_selectors_initiator(sa_config,&traffic_selectors);
461
462 /* create IDi */
463 ts_payload = ts_payload_create_from_traffic_selectors(TRUE,traffic_selectors, traffic_selectors_count);
464 allocator_free(traffic_selectors);
465 *payload = (payload_t *) ts_payload;
466}
467
468/**
469 * Implementation of private_ike_sa_init_requested_t.build_tsr_payload.
470 */
471static void build_tsr_payload (private_ike_sa_init_requested_t *this, payload_t **payload)
472{
473 sa_config_t *sa_config;
474 ts_payload_t *ts_payload;
475 size_t traffic_selectors_count;
476 traffic_selector_t **traffic_selectors;
477
478 sa_config = this->ike_sa->get_sa_config(this->ike_sa);
479
480 traffic_selectors_count = sa_config->get_traffic_selectors_responder(sa_config,&traffic_selectors);
481
482 /* create IDi */
483 ts_payload = ts_payload_create_from_traffic_selectors(FALSE,traffic_selectors, traffic_selectors_count);
484 allocator_free(traffic_selectors);
485 *payload = (payload_t *) ts_payload;
486}
487
488
c7dd2a7b
MW
489/**
490 * Implements state_t.get_state
491 */
492static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this)
493{
494 return IKE_SA_INIT_REQUESTED;
495}
496
af30c6b9
JH
497/**
498 * Implements private_ike_sa_init_requested_t.destroy_after_state_change
499 */
500static void destroy_after_state_change (private_ike_sa_init_requested_t *this)
501{
502 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t after state change");
503
504 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
505 this->diffie_hellman->destroy(this->diffie_hellman);
1b3f92d2 506
af30c6b9
JH
507 allocator_free(this->sent_nonce.ptr);
508 allocator_free(this->received_nonce.ptr);
509 allocator_free(this->shared_secret.ptr);
1b3f92d2 510 allocator_free(this);
af30c6b9
JH
511}
512
c7dd2a7b
MW
513/**
514 * Implements state_t.get_state
515 */
d048df5c 516static void destroy(private_ike_sa_init_requested_t *this)
c7dd2a7b
MW
517{
518 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy state of type ike_sa_init_requested_t");
519
520 this->logger->log(this->logger, CONTROL | MOST, "Destroy diffie hellman object");
521 this->diffie_hellman->destroy(this->diffie_hellman);
c7dd2a7b 522
d048df5c
MW
523 allocator_free(this->sent_nonce.ptr);
524 allocator_free(this->received_nonce.ptr);
525 allocator_free(this->shared_secret.ptr);
c7dd2a7b 526 allocator_free(this);
c7dd2a7b
MW
527}
528
529/*
530 * Described in header.
531 */
1b3f92d2 532ike_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)
c7dd2a7b
MW
533{
534 private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t);
535
c7dd2a7b 536 /* interface functions */
aad398a7 537 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
c7dd2a7b 538 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
d048df5c 539 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
c7dd2a7b 540
f890d8fe
JH
541 /* private functions */
542 this->build_ike_auth_request = build_ike_auth_request;
543 this->build_id_payload = build_id_payload;
af30c6b9 544 this->build_auth_payload = build_auth_payload;
1b3f92d2
JH
545 this->build_sa_payload = build_sa_payload;
546 this->build_tsi_payload = build_tsi_payload;
547 this->build_tsr_payload = build_tsr_payload;
af30c6b9 548 this->destroy_after_state_change = destroy_after_state_change;
f890d8fe 549
c7dd2a7b
MW
550 /* private data */
551 this->ike_sa = ike_sa;
d048df5c
MW
552 this->received_nonce = CHUNK_INITIALIZER;
553 this->shared_secret = CHUNK_INITIALIZER;
aad398a7 554 this->logger = this->ike_sa->get_logger(this->ike_sa);
c7dd2a7b
MW
555 this->diffie_hellman = diffie_hellman;
556 this->sent_nonce = sent_nonce;
557 this->dh_group_priority = dh_group_priority;
558
559 return &(this->public);
560}