- key derivation for child_sa works
[strongswan.git] / Source / charon / sa / states / ike_auth_requested.c
1 /**
2 * @file ike_auth_requested.c
3 *
4 * @brief Implementation of ike_auth_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_auth_requested.h"
24
25 #include <daemon.h>
26 #include <utils/allocator.h>
27 #include <encoding/payloads/ts_payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/auth_payload.h>
31 #include <encoding/payloads/notify_payload.h>
32 #include <transforms/signers/signer.h>
33 #include <transforms/crypters/crypter.h>
34 #include <sa/states/ike_sa_established.h>
35 #include <sa/authenticator.h>
36 #include <sa/child_sa.h>
37
38 typedef struct private_ike_auth_requested_t private_ike_auth_requested_t;
39
40 /**
41 * Private data of a ike_auth_requested_t object.
42 *
43 */
44 struct private_ike_auth_requested_t {
45 /**
46 * Public interface of ike_auth_requested_t.
47 */
48 ike_auth_requested_t public;
49
50 /**
51 * Assigned IKE_SA.
52 */
53 protected_ike_sa_t *ike_sa;
54
55 /**
56 * SA config, just a copy of the one stored in the ike_sa.
57 */
58 sa_config_t *sa_config;
59
60 /**
61 * Received nonce from responder.
62 */
63 chunk_t received_nonce;
64
65 /**
66 * Sent nonce in IKE_SA_INIT request.
67 */
68 chunk_t sent_nonce;
69
70 /**
71 * IKE_SA_INIT-Request in binary form.
72 */
73 chunk_t ike_sa_init_reply_data;
74
75 /**
76 * Assigned Logger.
77 *
78 * Is logger of ike_sa!
79 */
80 logger_t *logger;
81
82 /**
83 * Process the IDr payload (check if other id is valid)
84 *
85 * @param this calling object
86 * @param idr_payload ID payload of responder
87 * @return
88 * - SUCCESS
89 * - DELETE_ME
90 */
91 status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload);
92
93 /**
94 * Process the SA payload (check if selected proposals are valid, setup child sa)
95 *
96 * @param this calling object
97 * @param sa_payload SA payload of responder
98 *
99 * - SUCCESS
100 * - DELETE_ME
101 */
102 status_t (*process_sa_payload) (private_ike_auth_requested_t *this, sa_payload_t *sa_payload);
103
104 /**
105 * Process the AUTH payload (check authenticity of message)
106 *
107 * @param this calling object
108 * @param auth_payload AUTH payload of responder
109 * @param other_id_payload ID payload of responder
110 *
111 * - SUCCESS
112 * - DELETE_ME
113 */
114 status_t (*process_auth_payload) (private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload);
115
116 /**
117 * Process the TS payload (check if selected traffic selectors are valid)
118 *
119 * @param this calling object
120 * @param ts_initiator TRUE if TS payload is TSi, FALSE for TSr
121 * @param ts_payload TS payload of responder
122 *
123 * - SUCCESS
124 * - DELETE_ME
125 */
126 status_t (*process_ts_payload) (private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload);
127
128 /**
129 * Process a notify payload
130 *
131 * @param this calling object
132 * @param notify_payload notify payload
133 *
134 * - SUCCESS
135 * - FAILED
136 * - DELETE_ME
137 */
138 status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload);
139 };
140
141
142 /**
143 * Implements state_t.process_message
144 */
145 static status_t process_message(private_ike_auth_requested_t *this, message_t *ike_auth_reply)
146 {
147 ts_payload_t *tsi_payload = NULL, *tsr_payload = NULL;
148 id_payload_t *idr_payload = NULL;
149 auth_payload_t *auth_payload = NULL;
150 sa_payload_t *sa_payload = NULL;
151 iterator_t *payloads = NULL;
152 crypter_t *crypter = NULL;
153 signer_t *signer = NULL;
154 status_t status;
155 host_t *my_host, *other_host;
156
157 if (ike_auth_reply->get_exchange_type(ike_auth_reply) != IKE_AUTH)
158 {
159 this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_auth_requested",
160 mapping_find(exchange_type_m,ike_auth_reply->get_exchange_type(ike_auth_reply)));
161 return FAILED;
162 }
163
164 if (ike_auth_reply->get_request(ike_auth_reply))
165 {
166 this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH requests not allowed state ike_sa_init_responded");
167 return FAILED;
168 }
169
170 /* get signer for verification and crypter for decryption */
171 signer = this->ike_sa->get_signer_responder(this->ike_sa);
172 crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
173
174 /* parse incoming message */
175 status = ike_auth_reply->parse_body(ike_auth_reply, crypter, signer);
176 if (status != SUCCESS)
177 {
178 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption failed. Ignoring message");
179 return status;
180 }
181
182 this->sa_config = this->ike_sa->get_sa_config(this->ike_sa);
183
184 /* we collect all payloads, which are processed later. Notify's are processed
185 * in place, since we don't know how may are there.
186 */
187 payloads = ike_auth_reply->get_payload_iterator(ike_auth_reply);
188 while (payloads->has_next(payloads))
189 {
190 payload_t *payload;
191 payloads->current(payloads, (void**)&payload);
192
193 switch (payload->get_type(payload))
194 {
195 case AUTHENTICATION:
196 {
197 auth_payload = (auth_payload_t*)payload;
198 break;
199 }
200 case ID_RESPONDER:
201 {
202 idr_payload = (id_payload_t*)payload;
203 break;
204 }
205 case SECURITY_ASSOCIATION:
206 {
207 sa_payload = (sa_payload_t*)payload;
208 break;
209 }
210 case TRAFFIC_SELECTOR_INITIATOR:
211 {
212 tsi_payload = (ts_payload_t*)payload;
213 break;
214 }
215 case TRAFFIC_SELECTOR_RESPONDER:
216 {
217 tsr_payload = (ts_payload_t*)payload;
218 break;
219 }
220 case NOTIFY:
221 {
222 notify_payload_t *notify_payload = (notify_payload_t *) payload;
223 /* handle the notify directly, abort if no further processing required */
224 status = this->process_notify_payload(this, notify_payload);
225 if (status != SUCCESS)
226 {
227 payloads->destroy(payloads);
228 return status;
229 }
230 }
231 case CERTIFICATE:
232 {
233 /* TODO handle cert payloads */
234 }
235 default:
236 {
237 this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)",
238 mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
239 break;
240 }
241 }
242 }
243 /* iterator can be destroyed */
244 payloads->destroy(payloads);
245
246 /* check if we have all payloads */
247 if (!(idr_payload && sa_payload && auth_payload && tsi_payload && tsr_payload))
248 {
249 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
250 return DELETE_ME;
251 }
252
253 /* process all payloads */
254 status = this->process_idr_payload(this, idr_payload);
255 if (status != SUCCESS)
256 {
257 return status;
258 }
259 status = this->process_sa_payload(this, sa_payload);
260 if (status != SUCCESS)
261 {
262 return status;
263 }
264 status = this->process_auth_payload(this, auth_payload,idr_payload);
265 if (status != SUCCESS)
266 {
267 return status;
268 }
269 status = this->process_ts_payload(this, TRUE, tsi_payload);
270 if (status != SUCCESS)
271 {
272 return status;
273 }
274 status = this->process_ts_payload(this, FALSE, tsr_payload);
275 if (status != SUCCESS)
276 {
277 return status;
278 }
279
280 this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_auth_reply->get_message_id(ike_auth_reply));
281 /* create new state */
282
283 my_host = this->ike_sa->get_my_host(this->ike_sa);
284 other_host = this->ike_sa->get_other_host(this->ike_sa);
285 this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s, authenticated peer with %s",
286 my_host->get_address(my_host), other_host->get_address(other_host),
287 mapping_find(auth_method_m, auth_payload->get_auth_method(auth_payload)));
288
289 this->ike_sa->create_delete_established_ike_sa_job(this->ike_sa,this->sa_config->get_ike_sa_lifetime(this->sa_config));
290 this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
291 this->public.state_interface.destroy(&(this->public.state_interface));
292 return SUCCESS;
293 }
294
295 /**
296 * Implements private_ike_auth_requested_t.process_idr_payload
297 */
298 static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload)
299 {
300 identification_t *other_id, *configured_other_id;
301
302 other_id = idr_payload->get_identification(idr_payload);
303
304 configured_other_id = this->sa_config->get_other_id(this->sa_config);
305 if (configured_other_id)
306 {
307 this->logger->log(this->logger, CONTROL|LEVEL1, "configured ID: %s, ID of responder: %s",
308 configured_other_id->get_string(configured_other_id),
309 other_id->get_string(other_id));
310
311 if (!other_id->equals(other_id, configured_other_id))
312 {
313 other_id->destroy(other_id);
314 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not requested ID. Deleting IKE_SA");
315 return DELETE_ME;
316 }
317 }
318
319 other_id->destroy(other_id);
320 /* TODO do we have to store other_id somewhere ? */
321 return SUCCESS;
322 }
323
324 /**
325 * Implements private_ike_auth_requested_t.process_sa_payload
326 */
327 static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload)
328 {
329 child_proposal_t *proposal, *proposal_tmp;
330 linked_list_t *proposal_list;
331 child_sa_t *child_sa;
332 chunk_t seed;
333 prf_plus_t *prf_plus;
334
335 /* get his selected proposal */
336 proposal_list = sa_payload->get_child_proposals(sa_payload);
337 /* check count of proposals */
338 if (proposal_list->get_count(proposal_list) == 0)
339 {
340 /* no proposal? we accept this, but no child sa is built */
341 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD didn't contain any proposals. No CHILD_SA created",
342 proposal_list->get_count(proposal_list));
343 proposal_list->destroy(proposal_list);
344 return SUCCESS;
345 }
346 if (proposal_list->get_count(proposal_list) > 1)
347 {
348 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD contained %d proposal. Deleting IKE_SA",
349 proposal_list->get_count(proposal_list));
350 while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
351 {
352 proposal->destroy(proposal);
353 }
354 proposal_list->destroy(proposal_list);
355 return DELETE_ME;
356 }
357
358 /* we have to re-check here if other's selection is valid */
359 proposal = this->sa_config->select_proposal(this->sa_config, proposal_list);
360 /* list not needed anymore */
361 while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS)
362 {
363 proposal_tmp->destroy(proposal_tmp);
364 }
365 proposal_list->destroy(proposal_list);
366 /* got a match? */
367 if (proposal == NULL)
368 {
369 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not offered proposal. Deleting IKE_SA");
370 return DELETE_ME;
371 }
372
373 /* install child SAs for AH and esp */
374 seed = allocator_alloc_as_chunk(this->sent_nonce.len + this->received_nonce.len);
375 memcpy(seed.ptr, this->sent_nonce.ptr, this->sent_nonce.len);
376 memcpy(seed.ptr + this->sent_nonce.len, this->received_nonce.ptr, this->received_nonce.len);
377 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
378 allocator_free_chunk(&seed);
379
380 child_sa = child_sa_create(proposal, prf_plus);
381 prf_plus->destroy(prf_plus);
382 child_sa->destroy(child_sa);
383
384 proposal->destroy(proposal);
385
386 return SUCCESS;
387 }
388
389 /**
390 * Implements private_ike_auth_requested_t.process_auth_payload
391 */
392 static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload)
393 {
394 authenticator_t *authenticator;
395 status_t status;
396
397 authenticator = authenticator_create(this->ike_sa);
398 status = authenticator->verify_auth_data(authenticator,auth_payload,this->ike_sa_init_reply_data,this->sent_nonce,other_id_payload,FALSE);
399 authenticator->destroy(authenticator);
400 if (status != SUCCESS)
401 {
402 this->logger->log(this->logger, AUDIT, "Verification of IKE_AUTH reply failed. Deleting IKE_SA");
403 return DELETE_ME;
404 }
405
406 this->logger->log(this->logger, CONTROL|LEVEL1, "AUTH data verified successfully");
407 return SUCCESS;
408 }
409
410 /**
411 * Implements private_ike_auth_requested_t.process_ts_payload
412 */
413 static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload)
414 {
415 traffic_selector_t **ts_received, **ts_selected;
416 size_t ts_received_count, ts_selected_count;
417 status_t status = SUCCESS;
418
419 /* get ts form payload */
420 ts_received_count = ts_payload->get_traffic_selectors(ts_payload, &ts_received);
421 /* select ts depending on payload type */
422 if (ts_initiator)
423 {
424 ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected);
425 }
426 else
427 {
428 ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected);
429 }
430 /* check if the responder selected valid proposals */
431 if (ts_selected_count != ts_received_count)
432 {
433 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained not offered traffic selectors.");
434 }
435
436 /* cleanup */
437 while(ts_received_count--)
438 {
439 traffic_selector_t *ts = *ts_received + ts_received_count;
440 ts->destroy(ts);
441 }
442 allocator_free(ts_received);
443 while(ts_selected_count--)
444 {
445 traffic_selector_t *ts = *ts_selected + ts_selected_count;
446 ts->destroy(ts);
447 }
448 allocator_free(ts_selected);
449 return status;
450 }
451
452 /**
453 * Implements private_ike_auth_requested_t.process_notify_payload
454 */
455 static status_t process_notify_payload(private_ike_auth_requested_t *this, notify_payload_t *notify_payload)
456 {
457 notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload);
458
459 this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s",
460 mapping_find(notify_message_type_m, notify_message_type),
461 mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload)));
462
463 if (notify_payload->get_protocol_id(notify_payload) != IKE)
464 {
465 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a notify for an invalid protocol. Deleting IKE_SA");
466 return DELETE_ME;
467 }
468
469 switch (notify_message_type)
470 {
471 case INVALID_SYNTAX:
472 {
473 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA");
474 return DELETE_ME;
475
476 }
477 case AUTHENTICATION_FAILED:
478 {
479 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA");
480 return DELETE_ME;
481
482 }
483 case SINGLE_PAIR_REQUIRED:
484 {
485 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA");
486 return DELETE_ME;
487 }
488 default:
489 {
490 /*
491 * - In case of unknown error: IKE_SA gets destroyed.
492 * - In case of unknown status: logging
493 */
494
495 if (notify_message_type < 16383)
496 {
497 this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an unknown notify error (%d). Deleting IKE_SA",
498 notify_message_type);
499 return DELETE_ME;
500
501 }
502 else
503 {
504 this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained an unknown notify (%d), ignored.",
505 notify_message_type);
506 return SUCCESS;
507 }
508 }
509 }
510 }
511
512 /**
513 * Implements state_t.get_state
514 */
515 static ike_sa_state_t get_state(private_ike_auth_requested_t *this)
516 {
517 return IKE_AUTH_REQUESTED;
518 }
519
520 /**
521 * Implements state_t.get_state
522 */
523 static void destroy(private_ike_auth_requested_t *this)
524 {
525 allocator_free_chunk(&(this->received_nonce));
526 allocator_free_chunk(&(this->sent_nonce));
527 allocator_free_chunk(&(this->ike_sa_init_reply_data));
528 allocator_free(this);
529 }
530
531 /*
532 * Described in header.
533 */
534 ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk_t sent_nonce,chunk_t received_nonce,chunk_t ike_sa_init_reply_data)
535 {
536 private_ike_auth_requested_t *this = allocator_alloc_thing(private_ike_auth_requested_t);
537
538 /* interface functions */
539 this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
540 this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
541 this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
542
543 /* private functions */
544
545 this->process_idr_payload = process_idr_payload;
546 this->process_sa_payload = process_sa_payload;
547 this->process_auth_payload = process_auth_payload;
548 this->process_ts_payload = process_ts_payload;
549 this->process_notify_payload = process_notify_payload;
550
551 /* private data */
552 this->ike_sa = ike_sa;
553 this->received_nonce = received_nonce;
554 this->sent_nonce = sent_nonce;
555 this->ike_sa_init_reply_data = ike_sa_init_reply_data;
556 this->logger = this->ike_sa->get_logger(this->ike_sa);
557
558 return &(this->public);
559 }