Create authenticators right when they are used during Main Mode.
[strongswan.git] / src / libcharon / sa / tasks / main_mode.c
1 /*
2 * Copyright (C) 2011 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "main_mode.h"
20
21 #include <string.h>
22
23 #include <daemon.h>
24 #include <sa/keymat_v1.h>
25 #include <crypto/diffie_hellman.h>
26 #include <encoding/payloads/sa_payload.h>
27 #include <encoding/payloads/ke_payload.h>
28 #include <encoding/payloads/nonce_payload.h>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/hash_payload.h>
31 #include <sa/tasks/xauth.h>
32 #include <sa/tasks/mode_config.h>
33 #include <sa/tasks/informational.h>
34
35 typedef struct private_main_mode_t private_main_mode_t;
36
37 /**
38 * Private members of a main_mode_t task.
39 */
40 struct private_main_mode_t {
41
42 /**
43 * Public methods and task_t interface.
44 */
45 main_mode_t public;
46
47 /**
48 * Assigned IKE_SA.
49 */
50 ike_sa_t *ike_sa;
51
52 /**
53 * Are we the initiator?
54 */
55 bool initiator;
56
57 /**
58 * IKE config to establish
59 */
60 ike_cfg_t *ike_cfg;
61
62 /**
63 * Peer config to use
64 */
65 peer_cfg_t *peer_cfg;
66
67 /**
68 * Local authentication configuration
69 */
70 auth_cfg_t *my_auth;
71
72 /**
73 * Remote authentication configuration
74 */
75 auth_cfg_t *other_auth;
76
77 /**
78 * selected IKE proposal
79 */
80 proposal_t *proposal;
81
82 /**
83 * DH exchange
84 */
85 diffie_hellman_t *dh;
86
87 /**
88 * Keymat derivation (from SA)
89 */
90 keymat_v1_t *keymat;
91
92 /**
93 * Received public DH value from peer
94 */
95 chunk_t dh_value;
96
97 /**
98 * Initiators nonce
99 */
100 chunk_t nonce_i;
101
102 /**
103 * Responder nonce
104 */
105 chunk_t nonce_r;
106
107 /**
108 * Encoded SA initiator payload used for authentication
109 */
110 chunk_t sa_payload;
111
112 /**
113 * Negotiated SA lifetime
114 */
115 u_int32_t lifetime;
116
117 /**
118 * Negotiated authentication method
119 */
120 auth_method_t auth_method;
121
122 /** states of main mode */
123 enum {
124 MM_INIT,
125 MM_SA,
126 MM_KE,
127 MM_AUTH,
128 } state;
129 };
130
131 /**
132 * Get the first authentcation config from peer config
133 */
134 static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
135 {
136 enumerator_t *enumerator;
137 auth_cfg_t *cfg = NULL;
138
139 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
140 enumerator->enumerate(enumerator, &cfg);
141 enumerator->destroy(enumerator);
142 return cfg;
143 }
144
145 /**
146 * Create an authenticator, if supported
147 */
148 static authenticator_t *create_authenticator(private_main_mode_t *this)
149 {
150 authenticator_t *authenticator;
151 authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
152 this->auth_method, this->dh,
153 this->dh_value, this->sa_payload);
154 if (!authenticator)
155 {
156 DBG1(DBG_IKE, "negotiated authentication method %N not supported",
157 auth_method_names, this->auth_method);
158 }
159 return authenticator;
160 }
161
162 /**
163 * Save the encoded SA payload of a message
164 */
165 static bool save_sa_payload(private_main_mode_t *this, message_t *message)
166 {
167 enumerator_t *enumerator;
168 payload_t *payload, *sa = NULL;
169 chunk_t data;
170 size_t offset = IKE_HEADER_LENGTH;
171
172 enumerator = message->create_payload_enumerator(message);
173 while (enumerator->enumerate(enumerator, &payload))
174 {
175 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
176 {
177 sa = payload;
178 break;
179 }
180 else
181 {
182 offset += payload->get_length(payload);
183 }
184 }
185 enumerator->destroy(enumerator);
186
187 data = message->get_packet_data(message);
188 if (sa && data.len >= offset + sa->get_length(sa))
189 {
190 /* Get SA payload without 4 byte fixed header */
191 data = chunk_skip(data, offset);
192 data.len = sa->get_length(sa);
193 data = chunk_skip(data, 4);
194 this->sa_payload = chunk_clone(data);
195 return TRUE;
196 }
197 return FALSE;
198 }
199
200 /**
201 * Generate and add NONCE, KE payload
202 */
203 static bool add_nonce_ke(private_main_mode_t *this, chunk_t *nonce,
204 message_t *message)
205 {
206 nonce_payload_t *nonce_payload;
207 ke_payload_t *ke_payload;
208 rng_t *rng;
209
210 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1,
211 this->dh);
212 message->add_payload(message, &ke_payload->payload_interface);
213
214 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
215 if (!rng)
216 {
217 DBG1(DBG_IKE, "no RNG found to create nonce");
218 return FALSE;
219 }
220 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
221 rng->destroy(rng);
222
223 nonce_payload = nonce_payload_create(NONCE_V1);
224 nonce_payload->set_nonce(nonce_payload, *nonce);
225 message->add_payload(message, &nonce_payload->payload_interface);
226
227 return TRUE;
228 }
229
230 /**
231 * Extract nonce from NONCE payload, process KE payload
232 */
233 static bool get_nonce_ke(private_main_mode_t *this, chunk_t *nonce,
234 message_t *message)
235 {
236 nonce_payload_t *nonce_payload;
237 ke_payload_t *ke_payload;
238
239 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
240 if (!ke_payload)
241 {
242 DBG1(DBG_IKE, "KE payload missing in message");
243 return FALSE;
244 }
245 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
246 this->dh->set_other_public_value(this->dh, this->dh_value);
247
248 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
249 if (!nonce_payload)
250 {
251 DBG1(DBG_IKE, "NONCE payload missing in message");
252 return FALSE;
253 }
254 *nonce = nonce_payload->get_nonce(nonce_payload);
255
256 return TRUE;
257 }
258
259 /**
260 * Get the two auth classes from local or remote config
261 */
262 static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
263 auth_class_t *c1, auth_class_t *c2)
264 {
265 enumerator_t *enumerator;
266 auth_cfg_t *auth;
267
268 *c1 = *c2 = AUTH_CLASS_ANY;
269
270 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
271 while (enumerator->enumerate(enumerator, &auth))
272 {
273 if (*c1 == AUTH_CLASS_ANY)
274 {
275 *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
276 }
277 else
278 {
279 *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
280 break;
281 }
282 }
283 enumerator->destroy(enumerator);
284 }
285
286 /**
287 * Get auth method to use from a peer config
288 */
289 static auth_method_t get_auth_method(private_main_mode_t *this,
290 peer_cfg_t *peer_cfg)
291 {
292 auth_class_t i1, i2, r1, r2;
293
294 get_auth_class(peer_cfg, this->initiator, &i1, &i2);
295 get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
296
297 if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
298 {
299 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
300 {
301 /* TODO-IKEv1: ECDSA? */
302 return AUTH_RSA;
303 }
304 if (i2 == AUTH_CLASS_XAUTH)
305 {
306 return AUTH_XAUTH_INIT_RSA;
307 }
308 if (r2 == AUTH_CLASS_XAUTH)
309 {
310 return AUTH_XAUTH_RESP_RSA;
311 }
312 }
313 if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
314 {
315 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
316 {
317 return AUTH_PSK;
318 }
319 if (i2 == AUTH_CLASS_XAUTH)
320 {
321 return AUTH_XAUTH_INIT_PSK;
322 }
323 if (r2 == AUTH_CLASS_XAUTH)
324 {
325 return AUTH_XAUTH_RESP_PSK;
326 }
327 }
328 /* TODO-IKEv1: Hybrid methods? */
329 return AUTH_NONE;;
330 }
331
332 /**
333 * Select the best configuration as responder
334 */
335 static peer_cfg_t *select_config(private_main_mode_t *this, identification_t *id)
336 {
337 enumerator_t *enumerator;
338 peer_cfg_t *current, *found = NULL;
339 host_t *me, *other;
340
341 me = this->ike_sa->get_my_host(this->ike_sa);
342 other = this->ike_sa->get_other_host(this->ike_sa);
343 DBG1(DBG_CFG, "looking for peer configs matching %H...%H[%Y]", me, other, id);
344 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
345 me, other, NULL, id);
346 while (enumerator->enumerate(enumerator, &current))
347 {
348 if (get_auth_method(this, current) == this->auth_method)
349 {
350 found = current->get_ref(current);
351 break;
352 }
353 }
354 enumerator->destroy(enumerator);
355
356 if (found)
357 {
358 DBG2(DBG_CFG, "selected peer config \"%s\"", found->get_name(found));
359 }
360 return found;
361 }
362
363 /**
364 * Check for notify errors, return TRUE if error found
365 */
366 static bool has_notify_errors(private_main_mode_t *this, message_t *message)
367 {
368 enumerator_t *enumerator;
369 payload_t *payload;
370 bool err = FALSE;
371
372 enumerator = message->create_payload_enumerator(message);
373 while (enumerator->enumerate(enumerator, &payload))
374 {
375 if (payload->get_type(payload) == NOTIFY_V1)
376 {
377 notify_payload_t *notify;
378 notify_type_t type;
379
380 notify = (notify_payload_t*)payload;
381 type = notify->get_notify_type(notify);
382 if (type < 16384)
383 {
384 DBG1(DBG_IKE, "received %N error notify",
385 notify_type_names, type);
386 err = TRUE;
387 }
388 else if (type == INITIAL_CONTACT_IKEV1)
389 {
390 if (!this->initiator && this->state == MM_AUTH)
391 {
392 /* If authenticated and received INITIAL_CONTACT,
393 * delete any existing IKE_SAs with that peer.
394 * The delete takes place when the SA is checked in due
395 * to other id not known until the 3rd message.*/
396 this->ike_sa->set_condition(this->ike_sa,
397 COND_INIT_CONTACT_SEEN, TRUE);
398 }
399 }
400 else
401 {
402 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
403 }
404 }
405 }
406 enumerator->destroy(enumerator);
407
408 return err;
409 }
410
411 /**
412 * Queue a task sending a notify in an INFORMATIONAL exchange
413 */
414 static status_t send_notify(private_main_mode_t *this,
415 notify_type_t type, chunk_t data)
416 {
417 notify_payload_t *notify;
418 ike_sa_id_t *ike_sa_id;
419 u_int64_t spi_i, spi_r;
420 chunk_t spi;
421
422 notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
423 PROTO_IKE, type);
424 notify->set_notification_data(notify, data);
425 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
426 spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
427 spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
428 spi = chunk_cata("cc", chunk_from_thing(spi_i), chunk_from_thing(spi_r));
429 notify->set_spi_data(notify, spi);
430
431 this->ike_sa->queue_task(this->ike_sa,
432 (task_t*)informational_create(this->ike_sa, notify));
433 /* cancel all active/passive tasks in favour of informational */
434 return ALREADY_DONE;
435 }
436
437 METHOD(task_t, build_i, status_t,
438 private_main_mode_t *this, message_t *message)
439 {
440 switch (this->state)
441 {
442 case MM_INIT:
443 {
444 sa_payload_t *sa_payload;
445 linked_list_t *proposals;
446 packet_t *packet;
447
448 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
449 DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
450 this->ike_sa->get_name(this->ike_sa),
451 this->ike_sa->get_unique_id(this->ike_sa),
452 this->ike_sa->get_other_host(this->ike_sa));
453 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
454
455 this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
456 this->peer_cfg->get_ref(this->peer_cfg);
457
458 this->my_auth = get_auth_cfg(this->peer_cfg, TRUE);
459 this->other_auth = get_auth_cfg(this->peer_cfg, FALSE);
460 if (!this->my_auth || !this->other_auth)
461 {
462 DBG1(DBG_CFG, "no auth config found");
463 return FAILED;
464 }
465 this->auth_method = get_auth_method(this, this->peer_cfg);
466 if (this->auth_method == AUTH_NONE)
467 {
468 DBG1(DBG_CFG, "configuration uses unsupported authentication");
469 return FAILED;
470 }
471 this->lifetime = this->peer_cfg->get_reauth_time(this->peer_cfg,
472 FALSE);
473 if (!this->lifetime)
474 { /* fall back to rekey time of no rekey time configured */
475 this->lifetime = this->peer_cfg->get_rekey_time(this->peer_cfg,
476 FALSE);
477 }
478 proposals = this->ike_cfg->get_proposals(this->ike_cfg);
479 sa_payload = sa_payload_create_from_proposals_v1(proposals,
480 this->lifetime, 0, this->auth_method, MODE_NONE, FALSE);
481 proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
482
483 message->add_payload(message, &sa_payload->payload_interface);
484
485 /* pregenerate message to store SA payload */
486 if (this->ike_sa->generate_message(this->ike_sa, message,
487 &packet) != SUCCESS)
488 {
489 DBG1(DBG_IKE, "pregenerating SA payload failed");
490 return FAILED;
491 }
492 packet->destroy(packet);
493 if (!save_sa_payload(this, message))
494 {
495 DBG1(DBG_IKE, "SA payload invalid");
496 return FAILED;
497 }
498
499 this->state = MM_SA;
500 return NEED_MORE;
501 }
502 case MM_SA:
503 {
504 u_int16_t group;
505
506 if (!this->keymat->create_hasher(this->keymat, this->proposal))
507 {
508 return FAILED;
509 }
510 if (!this->proposal->get_algorithm(this->proposal,
511 DIFFIE_HELLMAN_GROUP, &group, NULL))
512 {
513 DBG1(DBG_IKE, "DH group selection failed");
514 return FAILED;
515 }
516 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
517 group);
518 if (!this->dh)
519 {
520 DBG1(DBG_IKE, "negotiated DH group not supported");
521 return FAILED;
522 }
523 if (!add_nonce_ke(this, &this->nonce_i, message))
524 {
525 return FAILED;
526 }
527 this->state = MM_KE;
528 return NEED_MORE;
529 }
530 case MM_KE:
531 {
532 authenticator_t *authenticator;
533 id_payload_t *id_payload;
534 identification_t *id;
535
536 id = this->my_auth->get(this->my_auth, AUTH_RULE_IDENTITY);
537 if (!id)
538 {
539 DBG1(DBG_CFG, "own identity not known");
540 return FAILED;
541 }
542
543 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
544
545 id_payload = id_payload_create_from_identification(ID_V1, id);
546 message->add_payload(message, &id_payload->payload_interface);
547
548 authenticator = create_authenticator(this);
549 if (!authenticator || authenticator->build(authenticator,
550 message) != SUCCESS)
551 {
552 DESTROY_IF(authenticator);
553 return FAILED;
554 }
555 authenticator->destroy(authenticator);
556
557 this->state = MM_AUTH;
558 return NEED_MORE;
559 }
560 default:
561 return FAILED;
562 }
563 }
564
565 METHOD(task_t, process_r, status_t,
566 private_main_mode_t *this, message_t *message)
567 {
568 switch (this->state)
569 {
570 case MM_INIT:
571 {
572 linked_list_t *list;
573 sa_payload_t *sa_payload;
574
575 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
576 DBG0(DBG_IKE, "%H is initiating a Main Mode",
577 message->get_source(message));
578 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
579
580 this->ike_sa->update_hosts(this->ike_sa,
581 message->get_destination(message),
582 message->get_source(message), TRUE);
583
584 sa_payload = (sa_payload_t*)message->get_payload(message,
585 SECURITY_ASSOCIATION_V1);
586 if (!sa_payload || !save_sa_payload(this, message))
587 {
588 DBG1(DBG_IKE, "SA payload missing or invalid");
589 return FAILED;
590 }
591
592 list = sa_payload->get_proposals(sa_payload);
593 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
594 list, FALSE);
595 list->destroy_offset(list, offsetof(proposal_t, destroy));
596 if (!this->proposal)
597 {
598 DBG1(DBG_IKE, "no proposal found");
599 return send_notify(this, NO_PROPOSAL_CHOSEN, chunk_empty);
600 }
601
602 this->auth_method = sa_payload->get_auth_method(sa_payload);
603 this->lifetime = sa_payload->get_lifetime(sa_payload);
604
605 this->state = MM_SA;
606 return NEED_MORE;
607 }
608 case MM_SA:
609 {
610 u_int16_t group;
611
612 if (!this->keymat->create_hasher(this->keymat, this->proposal))
613 {
614 return FAILED;
615 }
616 if (!this->proposal->get_algorithm(this->proposal,
617 DIFFIE_HELLMAN_GROUP, &group, NULL))
618 {
619 DBG1(DBG_IKE, "DH group selection failed");
620 return FAILED;
621 }
622 this->dh = lib->crypto->create_dh(lib->crypto, group);
623 if (!this->dh)
624 {
625 DBG1(DBG_IKE, "negotiated DH group not supported");
626 return FAILED;
627 }
628 if (!get_nonce_ke(this, &this->nonce_i, message))
629 {
630 return FAILED;
631 }
632 this->state = MM_KE;
633 return NEED_MORE;
634 }
635 case MM_KE:
636 {
637 authenticator_t *authenticator;
638 id_payload_t *id_payload;
639 identification_t *id;
640
641 id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
642 if (!id_payload)
643 {
644 DBG1(DBG_IKE, "IDii payload missing");
645 return FAILED;
646 }
647
648 id = id_payload->get_identification(id_payload);
649 this->ike_sa->set_other_id(this->ike_sa, id);
650 this->peer_cfg = select_config(this, id);
651 if (!this->peer_cfg)
652 {
653 DBG1(DBG_IKE, "no peer config found");
654 return send_notify(this, AUTHENTICATION_FAILED, chunk_empty);
655 }
656 this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
657
658 this->my_auth = get_auth_cfg(this->peer_cfg, TRUE);
659 this->other_auth = get_auth_cfg(this->peer_cfg, FALSE);
660 if (!this->my_auth || !this->other_auth)
661 {
662 DBG1(DBG_IKE, "auth config missing");
663 return send_notify(this, AUTHENTICATION_FAILED, chunk_empty);
664 }
665
666 authenticator = create_authenticator(this);
667 if (!authenticator || authenticator->process(authenticator,
668 message) != SUCCESS)
669 {
670 DESTROY_IF(authenticator);
671 return send_notify(this, AUTHENTICATION_FAILED, chunk_empty);
672 }
673 authenticator->destroy(authenticator);
674
675 this->state = MM_AUTH;
676 if (has_notify_errors(this, message))
677 {
678 return FAILED;
679 }
680 return NEED_MORE;
681 }
682 default:
683 return FAILED;
684 }
685 }
686
687 /**
688 * Lookup a shared secret for this IKE_SA
689 */
690 static shared_key_t *lookup_shared_key(private_main_mode_t *this)
691 {
692 host_t *me, *other;
693 identification_t *my_id, *other_id;
694 shared_key_t *shared_key = NULL;
695
696 /* try to get a PSK for IP addresses */
697 me = this->ike_sa->get_my_host(this->ike_sa);
698 other = this->ike_sa->get_other_host(this->ike_sa);
699 my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
700 other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
701 if (my_id && other_id)
702 {
703 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
704 my_id, other_id);
705 }
706 DESTROY_IF(my_id);
707 DESTROY_IF(other_id);
708 if (shared_key)
709 {
710 return shared_key;
711 }
712
713 if (this->my_auth && this->other_auth)
714 { /* as initiator, use identities from configuraiton */
715 my_id = this->my_auth->get(this->my_auth, AUTH_RULE_IDENTITY);
716 other_id = this->other_auth->get(this->other_auth, AUTH_RULE_IDENTITY);
717 if (my_id && other_id)
718 {
719 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
720 my_id, other_id);
721 }
722 else
723 {
724 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
725 my_id, me, other_id, other);
726 }
727 }
728 else
729 { /* as responder, we try to find a config by IP */
730 enumerator_t *enumerator;
731 auth_cfg_t *my_auth, *other_auth;
732 peer_cfg_t *peer_cfg = NULL;
733
734 enumerator = charon->backends->create_peer_cfg_enumerator(
735 charon->backends, me, other, NULL, NULL);
736 while (enumerator->enumerate(enumerator, &peer_cfg))
737 {
738 my_auth = get_auth_cfg(peer_cfg, TRUE);
739 other_auth = get_auth_cfg(peer_cfg, FALSE);
740 if (my_auth && other_auth)
741 {
742 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
743 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
744 if (my_id && other_id)
745 {
746 shared_key = lib->credmgr->get_shared(lib->credmgr,
747 SHARED_IKE, my_id, other_id);
748 if (shared_key)
749 {
750 break;
751 }
752 else
753 {
754 DBG1(DBG_IKE, "no shared key found for "
755 "'%Y'[%H] - '%Y'[%H]", my_id, me, other_id, other);
756 }
757 }
758 }
759 }
760 enumerator->destroy(enumerator);
761 if (!peer_cfg)
762 {
763 DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
764 }
765 }
766 return shared_key;
767 }
768
769 /**
770 * Derive key material for this IKE_SA
771 */
772 static bool derive_keys(private_main_mode_t *this, chunk_t nonce_i,
773 chunk_t nonce_r)
774 {
775 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
776 shared_key_t *shared_key = NULL;
777
778 switch (this->auth_method)
779 {
780 case AUTH_PSK:
781 case AUTH_XAUTH_INIT_PSK:
782 case AUTH_XAUTH_RESP_PSK:
783 shared_key = lookup_shared_key(this);
784 break;
785 default:
786 break;
787 }
788 if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
789 this->dh_value, nonce_i, nonce_r, id, this->auth_method, shared_key))
790 {
791 DESTROY_IF(shared_key);
792 DBG1(DBG_IKE, "key derivation for %N failed",
793 auth_method_names, this->auth_method);
794 return FALSE;
795 }
796 DESTROY_IF(shared_key);
797 charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, nonce_i, nonce_r,
798 NULL);
799
800 return TRUE;
801 }
802
803 /**
804 * Set IKE_SA to established state
805 */
806 static void establish(private_main_mode_t *this)
807 {
808 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
809 this->ike_sa->get_name(this->ike_sa),
810 this->ike_sa->get_unique_id(this->ike_sa),
811 this->ike_sa->get_my_host(this->ike_sa),
812 this->ike_sa->get_my_id(this->ike_sa),
813 this->ike_sa->get_other_host(this->ike_sa),
814 this->ike_sa->get_other_id(this->ike_sa));
815
816 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
817 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
818 }
819
820 METHOD(task_t, build_r, status_t,
821 private_main_mode_t *this, message_t *message)
822 {
823 switch (this->state)
824 {
825 case MM_SA:
826 {
827 sa_payload_t *sa_payload;
828
829 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
830 this->lifetime, 0, this->auth_method, MODE_NONE, FALSE);
831 message->add_payload(message, &sa_payload->payload_interface);
832
833 return NEED_MORE;
834 }
835 case MM_KE:
836 {
837 if (!add_nonce_ke(this, &this->nonce_r, message))
838 {
839 return FAILED;
840 }
841 if (!derive_keys(this, this->nonce_i, this->nonce_r))
842 {
843 return FAILED;
844 }
845 return NEED_MORE;
846 }
847 case MM_AUTH:
848 {
849 authenticator_t *authenticator;
850 id_payload_t *id_payload;
851 identification_t *id;
852
853 id = this->my_auth->get(this->my_auth, AUTH_RULE_IDENTITY);
854 if (!id)
855 {
856 DBG1(DBG_CFG, "own identity not known");
857 return FAILED;
858 }
859
860 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
861
862 id_payload = id_payload_create_from_identification(ID_V1, id);
863 message->add_payload(message, &id_payload->payload_interface);
864
865 authenticator = create_authenticator(this);
866 if (!authenticator || authenticator->build(authenticator,
867 message) != SUCCESS)
868 {
869 DESTROY_IF(authenticator);
870 return FAILED;
871 }
872 authenticator->destroy(authenticator);
873
874 if (this->peer_cfg->get_virtual_ip(this->peer_cfg))
875 {
876 this->ike_sa->queue_task(this->ike_sa,
877 (task_t*)mode_config_create(this->ike_sa, TRUE));
878 }
879
880 switch (this->auth_method)
881 {
882 case AUTH_XAUTH_INIT_PSK:
883 case AUTH_XAUTH_INIT_RSA:
884 this->ike_sa->queue_task(this->ike_sa,
885 (task_t*)xauth_create(this->ike_sa, TRUE));
886 return SUCCESS;
887 case AUTH_XAUTH_RESP_PSK:
888 case AUTH_XAUTH_RESP_RSA:
889 /* TODO-IKEv1: not yet supported */
890 return FAILED;
891 default:
892 establish(this);
893 return SUCCESS;
894 }
895 }
896 default:
897 return FAILED;
898 }
899 }
900
901 METHOD(task_t, process_i, status_t,
902 private_main_mode_t *this, message_t *message)
903 {
904 switch (this->state)
905 {
906 case MM_SA:
907 {
908 linked_list_t *list;
909 sa_payload_t *sa_payload;
910 auth_method_t auth_method;
911 u_int32_t lifetime;
912
913 sa_payload = (sa_payload_t*)message->get_payload(message,
914 SECURITY_ASSOCIATION_V1);
915 if (!sa_payload)
916 {
917 DBG1(DBG_IKE, "SA payload missing");
918 return FAILED;
919 }
920 list = sa_payload->get_proposals(sa_payload);
921 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
922 list, FALSE);
923 list->destroy_offset(list, offsetof(proposal_t, destroy));
924 if (!this->proposal)
925 {
926 DBG1(DBG_IKE, "no proposal found");
927 return FAILED;
928 }
929
930 lifetime = sa_payload->get_lifetime(sa_payload);
931 if (lifetime != this->lifetime)
932 {
933 DBG1(DBG_IKE, "received lifetime %us does not match configured "
934 "%us, using lower value", lifetime, this->lifetime);
935 }
936 this->lifetime = min(this->lifetime, lifetime);
937 auth_method = sa_payload->get_auth_method(sa_payload);
938 if (auth_method != this->auth_method)
939 {
940 DBG1(DBG_IKE, "received %N authentication, but configured %N, "
941 "continue with configured", auth_method_names, auth_method,
942 auth_method_names, this->auth_method);
943 }
944 return NEED_MORE;
945 }
946 case MM_KE:
947 {
948 if (!get_nonce_ke(this, &this->nonce_r, message))
949 {
950 return FAILED;
951 }
952 if (!derive_keys(this, this->nonce_i, this->nonce_r))
953 {
954 return FAILED;
955 }
956 return NEED_MORE;
957 }
958 case MM_AUTH:
959 {
960 authenticator_t *authenticator;
961 id_payload_t *id_payload;
962 identification_t *id;
963
964 id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
965 if (!id_payload)
966 {
967 DBG1(DBG_IKE, "IDir payload missing");
968 return FAILED;
969 }
970 id = id_payload->get_identification(id_payload);
971 if (!id->matches(id, this->other_auth->get(this->other_auth,
972 AUTH_RULE_IDENTITY)))
973 {
974 DBG1(DBG_IKE, "IDir does not match");
975 id->destroy(id);
976 return FAILED;
977 }
978 this->ike_sa->set_other_id(this->ike_sa, id);
979
980 authenticator = create_authenticator(this);
981 if (!authenticator || authenticator->process(authenticator,
982 message) != SUCCESS)
983 {
984 DESTROY_IF(authenticator);
985 return FAILED;
986 }
987 authenticator->destroy(authenticator);
988
989 switch (this->auth_method)
990 {
991 case AUTH_XAUTH_INIT_PSK:
992 case AUTH_XAUTH_INIT_RSA:
993 /* wait for XAUTH request */
994 return SUCCESS;
995 case AUTH_XAUTH_RESP_PSK:
996 case AUTH_XAUTH_RESP_RSA:
997 /* TODO-IKEv1: not yet */
998 return FAILED;
999 default:
1000 establish(this);
1001 return SUCCESS;
1002 }
1003 }
1004 default:
1005 return FAILED;
1006 }
1007 }
1008
1009 METHOD(task_t, get_type, task_type_t,
1010 private_main_mode_t *this)
1011 {
1012 return TASK_MAIN_MODE;
1013 }
1014
1015 METHOD(task_t, migrate, void,
1016 private_main_mode_t *this, ike_sa_t *ike_sa)
1017 {
1018 this->ike_sa = ike_sa;
1019 }
1020
1021 METHOD(task_t, destroy, void,
1022 private_main_mode_t *this)
1023 {
1024 DESTROY_IF(this->peer_cfg);
1025 DESTROY_IF(this->proposal);
1026 DESTROY_IF(this->dh);
1027 free(this->dh_value.ptr);
1028 free(this->nonce_i.ptr);
1029 free(this->nonce_r.ptr);
1030 free(this->sa_payload.ptr);
1031 free(this);
1032 }
1033
1034 /*
1035 * Described in header.
1036 */
1037 main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator)
1038 {
1039 private_main_mode_t *this;
1040
1041 INIT(this,
1042 .public = {
1043 .task = {
1044 .get_type = _get_type,
1045 .migrate = _migrate,
1046 .destroy = _destroy,
1047 },
1048 },
1049 .ike_sa = ike_sa,
1050 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1051 .initiator = initiator,
1052 .state = MM_INIT,
1053 );
1054
1055 if (initiator)
1056 {
1057 this->public.task.build = _build_i;
1058 this->public.task.process = _process_i;
1059 }
1060 else
1061 {
1062 this->public.task.build = _build_r;
1063 this->public.task.process = _process_r;
1064 }
1065
1066 return &this->public;
1067 }