Use authenticators in IKEv1 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 <processing/jobs/initiate_xauth_job.h>
32
33 typedef struct private_main_mode_t private_main_mode_t;
34
35 /**
36 * Private members of a main_mode_t task.
37 */
38 struct private_main_mode_t {
39
40 /**
41 * Public methods and task_t interface.
42 */
43 main_mode_t public;
44
45 /**
46 * Assigned IKE_SA.
47 */
48 ike_sa_t *ike_sa;
49
50 /**
51 * Are we the initiator?
52 */
53 bool initiator;
54
55 /**
56 * IKE config to establish
57 */
58 ike_cfg_t *ike_cfg;
59
60 /**
61 * Peer config to use
62 */
63 peer_cfg_t *peer_cfg;
64
65 /**
66 * Local authentication configuration
67 */
68 auth_cfg_t *my_auth;
69
70 /**
71 * Remote authentication configuration
72 */
73 auth_cfg_t *other_auth;
74
75 /**
76 * selected IKE proposal
77 */
78 proposal_t *proposal;
79
80 /**
81 * DH exchange
82 */
83 diffie_hellman_t *dh;
84
85 /**
86 * Keymat derivation (from SA)
87 */
88 keymat_v1_t *keymat;
89
90 /**
91 * Received public DH value from peer
92 */
93 chunk_t dh_value;
94
95 /**
96 * Initiators nonce
97 */
98 chunk_t nonce_i;
99
100 /**
101 * Responder nonce
102 */
103 chunk_t nonce_r;
104
105 /**
106 * Encoded SA initiator payload used for authentication
107 */
108 chunk_t sa_payload;
109
110 /**
111 * Negotiated SA lifetime
112 */
113 u_int32_t lifetime;
114
115 /**
116 * Negotiated authentication method
117 */
118 auth_method_t auth_method;
119
120 /**
121 * Authenticator to use
122 */
123 authenticator_t *authenticator;
124
125 /** states of main mode */
126 enum {
127 MM_INIT,
128 MM_SA,
129 MM_KE,
130 MM_AUTH,
131 } state;
132 };
133
134 /**
135 * Get the first authentcation config from peer config
136 */
137 static auth_cfg_t *get_auth_cfg(private_main_mode_t *this, bool local)
138 {
139 enumerator_t *enumerator;
140 auth_cfg_t *cfg = NULL;
141
142 enumerator = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg,
143 local);
144 enumerator->enumerate(enumerator, &cfg);
145 enumerator->destroy(enumerator);
146 return cfg;
147 }
148
149 /**
150 * Save the encoded SA payload of a message
151 */
152 static bool save_sa_payload(private_main_mode_t *this, message_t *message)
153 {
154 enumerator_t *enumerator;
155 payload_t *payload, *sa = NULL;
156 chunk_t data;
157 size_t offset = IKE_HEADER_LENGTH;
158
159 enumerator = message->create_payload_enumerator(message);
160 while (enumerator->enumerate(enumerator, &payload))
161 {
162 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
163 {
164 sa = payload;
165 break;
166 }
167 else
168 {
169 offset += payload->get_length(payload);
170 }
171 }
172 enumerator->destroy(enumerator);
173
174 data = message->get_packet_data(message);
175 if (sa && data.len >= offset + sa->get_length(sa))
176 {
177 /* Get SA payload without 4 byte fixed header */
178 data = chunk_skip(data, offset);
179 data.len = sa->get_length(sa);
180 data = chunk_skip(data, 4);
181 this->sa_payload = chunk_clone(data);
182 return TRUE;
183 }
184 return FALSE;
185 }
186
187 /**
188 * Generate and add NONCE, KE payload
189 */
190 static bool add_nonce_ke(private_main_mode_t *this, chunk_t *nonce,
191 message_t *message)
192 {
193 nonce_payload_t *nonce_payload;
194 ke_payload_t *ke_payload;
195 rng_t *rng;
196
197 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1,
198 this->dh);
199 message->add_payload(message, &ke_payload->payload_interface);
200
201 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
202 if (!rng)
203 {
204 DBG1(DBG_IKE, "no RNG found to create nonce");
205 return FALSE;
206 }
207 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
208 rng->destroy(rng);
209
210 nonce_payload = nonce_payload_create(NONCE_V1);
211 nonce_payload->set_nonce(nonce_payload, *nonce);
212 message->add_payload(message, &nonce_payload->payload_interface);
213
214 return TRUE;
215 }
216
217 /**
218 * Extract nonce from NONCE payload, process KE payload
219 */
220 static bool get_nonce_ke(private_main_mode_t *this, chunk_t *nonce,
221 message_t *message)
222 {
223 nonce_payload_t *nonce_payload;
224 ke_payload_t *ke_payload;
225
226 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
227 if (!ke_payload)
228 {
229 DBG1(DBG_IKE, "KE payload missing in message");
230 return FALSE;
231 }
232 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
233 this->dh->set_other_public_value(this->dh, this->dh_value);
234
235 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
236 if (!nonce_payload)
237 {
238 DBG1(DBG_IKE, "NONCE payload missing in message");
239 return FALSE;
240 }
241 *nonce = nonce_payload->get_nonce(nonce_payload);
242
243 return TRUE;
244 }
245
246 /**
247 * Get auth method to use
248 */
249 static auth_method_t get_auth_method(private_main_mode_t *this)
250 {
251 switch ((uintptr_t)this->my_auth->get(this->my_auth, AUTH_RULE_AUTH_CLASS))
252 {
253 case AUTH_CLASS_PSK:
254 return AUTH_PSK;
255 case AUTH_CLASS_XAUTH_PSK:
256 return AUTH_XAUTH_INIT_PSK;
257 case AUTH_CLASS_XAUTH_PUBKEY:
258 return AUTH_XAUTH_INIT_RSA;
259 case AUTH_CLASS_PUBKEY:
260 /* TODO-IKEv1: look for a key, return RSA or ECDSA */
261 default:
262 /* TODO-IKEv1: XAUTH methods */
263 return AUTH_RSA;
264 }
265 }
266
267 METHOD(task_t, build_i, status_t,
268 private_main_mode_t *this, message_t *message)
269 {
270 switch (this->state)
271 {
272 case MM_INIT:
273 {
274 sa_payload_t *sa_payload;
275 linked_list_t *proposals;
276 packet_t *packet;
277
278 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
279 DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
280 this->ike_sa->get_name(this->ike_sa),
281 this->ike_sa->get_unique_id(this->ike_sa),
282 this->ike_sa->get_other_host(this->ike_sa));
283 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
284
285 this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
286 this->peer_cfg->get_ref(this->peer_cfg);
287
288 this->my_auth = get_auth_cfg(this, TRUE);
289 this->other_auth = get_auth_cfg(this, FALSE);
290 if (!this->my_auth || !this->other_auth)
291 {
292 DBG1(DBG_CFG, "no auth config found");
293 return FAILED;
294 }
295
296 proposals = this->ike_cfg->get_proposals(this->ike_cfg);
297 this->auth_method = get_auth_method(this);
298 this->lifetime = this->peer_cfg->get_reauth_time(this->peer_cfg,
299 FALSE);
300 if (!this->lifetime)
301 { /* fall back to rekey time of no rekey time configured */
302 this->lifetime = this->peer_cfg->get_rekey_time(this->peer_cfg,
303 FALSE);
304 }
305 sa_payload = sa_payload_create_from_proposals_v1(proposals,
306 this->lifetime, 0, this->auth_method, MODE_NONE, FALSE);
307 proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
308
309 message->add_payload(message, &sa_payload->payload_interface);
310
311 /* pregenerate message to store SA payload */
312 if (this->ike_sa->generate_message(this->ike_sa, message,
313 &packet) != SUCCESS)
314 {
315 DBG1(DBG_IKE, "pregenerating SA payload failed");
316 return FAILED;
317 }
318 packet->destroy(packet);
319 if (!save_sa_payload(this, message))
320 {
321 DBG1(DBG_IKE, "SA payload invalid");
322 return FAILED;
323 }
324
325 this->state = MM_SA;
326 return NEED_MORE;
327 }
328 case MM_SA:
329 {
330 u_int16_t group;
331
332 if (!this->keymat->create_hasher(this->keymat, this->proposal))
333 {
334 return FAILED;
335 }
336 if (!this->proposal->get_algorithm(this->proposal,
337 DIFFIE_HELLMAN_GROUP, &group, NULL))
338 {
339 DBG1(DBG_IKE, "DH group selection failed");
340 return FAILED;
341 }
342 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
343 group);
344 if (!this->dh)
345 {
346 DBG1(DBG_IKE, "negotiated DH group not supported");
347 return FAILED;
348 }
349 if (!add_nonce_ke(this, &this->nonce_i, message))
350 {
351 return FAILED;
352 }
353 this->state = MM_KE;
354 return NEED_MORE;
355 }
356 case MM_KE:
357 {
358 id_payload_t *id_payload;
359 identification_t *id;
360
361 id = this->my_auth->get(this->my_auth, AUTH_RULE_IDENTITY);
362 if (!id)
363 {
364 DBG1(DBG_CFG, "own identity not known");
365 return FAILED;
366 }
367
368 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
369
370 id_payload = id_payload_create_from_identification(ID_V1, id);
371 message->add_payload(message, &id_payload->payload_interface);
372
373 if (this->authenticator->build(this->authenticator,
374 message) != SUCCESS)
375 {
376 return FAILED;
377 }
378 this->state = MM_AUTH;
379 return NEED_MORE;
380 }
381 default:
382 return FAILED;
383 }
384 }
385
386 METHOD(task_t, process_r, status_t,
387 private_main_mode_t *this, message_t *message)
388 {
389 switch (this->state)
390 {
391 case MM_INIT:
392 {
393 linked_list_t *list;
394 sa_payload_t *sa_payload;
395
396 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
397 DBG0(DBG_IKE, "%H is initiating a Main Mode",
398 message->get_source(message));
399 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
400
401 this->ike_sa->update_hosts(this->ike_sa,
402 message->get_destination(message),
403 message->get_source(message), TRUE);
404
405 sa_payload = (sa_payload_t*)message->get_payload(message,
406 SECURITY_ASSOCIATION_V1);
407 if (!sa_payload || !save_sa_payload(this, message))
408 {
409 DBG1(DBG_IKE, "SA payload missing or invalid");
410 return FAILED;
411 }
412
413 list = sa_payload->get_proposals(sa_payload);
414 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
415 list, FALSE);
416 list->destroy_offset(list, offsetof(proposal_t, destroy));
417 if (!this->proposal)
418 {
419 DBG1(DBG_IKE, "no proposal found");
420 return FAILED;
421 }
422
423 this->auth_method = sa_payload->get_auth_method(sa_payload);
424 this->lifetime = sa_payload->get_lifetime(sa_payload);
425
426 this->state = MM_SA;
427 return NEED_MORE;
428 }
429 case MM_SA:
430 {
431 u_int16_t group;
432
433 if (!this->keymat->create_hasher(this->keymat, this->proposal))
434 {
435 return FAILED;
436 }
437 if (!this->proposal->get_algorithm(this->proposal,
438 DIFFIE_HELLMAN_GROUP, &group, NULL))
439 {
440 DBG1(DBG_IKE, "DH group selection failed");
441 return FAILED;
442 }
443 this->dh = lib->crypto->create_dh(lib->crypto, group);
444 if (!this->dh)
445 {
446 DBG1(DBG_IKE, "negotiated DH group not supported");
447 return FAILED;
448 }
449 if (!get_nonce_ke(this, &this->nonce_i, message))
450 {
451 return FAILED;
452 }
453 this->state = MM_KE;
454 return NEED_MORE;
455 }
456 case MM_KE:
457 {
458 enumerator_t *enumerator;
459 id_payload_t *id_payload;
460 identification_t *id, *any;
461
462 id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
463 if (!id_payload)
464 {
465 DBG1(DBG_IKE, "IDii payload missing");
466 return FAILED;
467 }
468
469 id = id_payload->get_identification(id_payload);
470 any = identification_create_from_encoding(ID_ANY, chunk_empty);
471 enumerator = charon->backends->create_peer_cfg_enumerator(
472 charon->backends,
473 this->ike_sa->get_my_host(this->ike_sa),
474 this->ike_sa->get_other_host(this->ike_sa),
475 any, id);
476 if (!enumerator->enumerate(enumerator, &this->peer_cfg))
477 {
478 DBG1(DBG_IKE, "no peer config found");
479 id->destroy(id);
480 any->destroy(any);
481 enumerator->destroy(enumerator);
482 return FAILED;
483 }
484 this->peer_cfg->get_ref(this->peer_cfg);
485 enumerator->destroy(enumerator);
486 any->destroy(any);
487
488 this->ike_sa->set_other_id(this->ike_sa, id);
489
490 this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
491
492 this->my_auth = get_auth_cfg(this, TRUE);
493 this->other_auth = get_auth_cfg(this, FALSE);
494 if (!this->my_auth || !this->other_auth)
495 {
496 DBG1(DBG_IKE, "auth config missing");
497 return FAILED;
498 }
499
500 if (this->authenticator->process(this->authenticator,
501 message) != SUCCESS)
502 {
503 return FAILED;
504 }
505 this->state = MM_AUTH;
506 return NEED_MORE;
507 }
508 default:
509 return FAILED;
510 }
511 }
512
513 /**
514 * Lookup a shared secret for this IKE_SA
515 */
516 static shared_key_t *lookup_shared_key(private_main_mode_t *this)
517 {
518 host_t *me, *other;
519 identification_t *my_id, *other_id;
520 shared_key_t *shared_key;
521
522 me = this->ike_sa->get_my_host(this->ike_sa);
523 other = this->ike_sa->get_other_host(this->ike_sa);
524 my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
525 other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
526 if (!my_id || !other_id)
527 {
528 DESTROY_IF(my_id);
529 DESTROY_IF(other_id);
530 return NULL;
531 }
532 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id,
533 other_id);
534 if (!shared_key)
535 {
536 DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
537 }
538 my_id->destroy(my_id);
539 other_id->destroy(other_id);
540 return shared_key;
541 }
542
543 /**
544 * Derive key material for this IKE_SA
545 */
546 static bool derive_keys(private_main_mode_t *this, chunk_t nonce_i,
547 chunk_t nonce_r)
548 {
549 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
550 shared_key_t *shared_key = NULL;
551
552 switch (this->auth_method)
553 {
554 case AUTH_PSK:
555 case AUTH_XAUTH_INIT_PSK:
556 case AUTH_XAUTH_RESP_PSK:
557 shared_key = lookup_shared_key(this);
558 break;
559 default:
560 break;
561 }
562 if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
563 this->dh_value, nonce_i, nonce_r, id, this->auth_method, shared_key))
564 {
565 DESTROY_IF(shared_key);
566 DBG1(DBG_IKE, "key derivation for %N failed",
567 auth_method_names, this->auth_method);
568 return FALSE;
569 }
570 DESTROY_IF(shared_key);
571 charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, nonce_i, nonce_r,
572 NULL);
573
574 this->authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
575 this->auth_method, this->dh,
576 this->dh_value, this->sa_payload);
577 if (!this->authenticator)
578 {
579 DBG1(DBG_IKE, "negotiated authentication method %N not supported",
580 auth_method_names, this->auth_method);
581 return FALSE;
582 }
583 return TRUE;
584 }
585
586 METHOD(task_t, build_r, status_t,
587 private_main_mode_t *this, message_t *message)
588 {
589 switch (this->state)
590 {
591 case MM_SA:
592 {
593 sa_payload_t *sa_payload;
594
595 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
596 this->lifetime, 0, this->auth_method, MODE_NONE, FALSE);
597 message->add_payload(message, &sa_payload->payload_interface);
598
599 return NEED_MORE;
600 }
601 case MM_KE:
602 {
603 if (!add_nonce_ke(this, &this->nonce_r, message))
604 {
605 return FAILED;
606 }
607 if (!derive_keys(this, this->nonce_i, this->nonce_r))
608 {
609 return FAILED;
610 }
611 return NEED_MORE;
612 }
613 case MM_AUTH:
614 {
615 id_payload_t *id_payload;
616 identification_t *id;
617
618 id = this->my_auth->get(this->my_auth, AUTH_RULE_IDENTITY);
619 if (!id)
620 {
621 DBG1(DBG_CFG, "own identity not known");
622 return FAILED;
623 }
624
625 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
626
627 id_payload = id_payload_create_from_identification(ID_V1, id);
628 message->add_payload(message, &id_payload->payload_interface);
629
630 if (this->authenticator->build(this->authenticator,
631 message) != SUCCESS)
632 {
633 return FAILED;
634 }
635
636 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
637 this->ike_sa->get_name(this->ike_sa),
638 this->ike_sa->get_unique_id(this->ike_sa),
639 this->ike_sa->get_my_host(this->ike_sa),
640 this->ike_sa->get_my_id(this->ike_sa),
641 this->ike_sa->get_other_host(this->ike_sa),
642 this->ike_sa->get_other_id(this->ike_sa));
643
644 switch (this->auth_method)
645 {
646 case AUTH_XAUTH_INIT_PSK:
647 case AUTH_XAUTH_INIT_RSA: /* There should be more INIT cases here once added */
648 {
649 job_t *job = (job_t *) initiate_xauth_job_create(this->ike_sa->get_id(this->ike_sa));
650 lib->processor->queue_job(lib->processor, job);
651 break;
652 }
653 case AUTH_XAUTH_RESP_PSK:
654 case AUTH_XAUTH_RESP_RSA: /* There should be more RESP cases here once added */
655 {
656 break;
657 }
658 default:
659 {
660 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
661 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
662 break;
663 }
664 }
665 return SUCCESS;
666 }
667 default:
668 return FAILED;
669 }
670 }
671
672 METHOD(task_t, process_i, status_t,
673 private_main_mode_t *this, message_t *message)
674 {
675 switch (this->state)
676 {
677 case MM_SA:
678 {
679 linked_list_t *list;
680 sa_payload_t *sa_payload;
681 auth_method_t auth_method;
682 u_int32_t lifetime;
683
684 sa_payload = (sa_payload_t*)message->get_payload(message,
685 SECURITY_ASSOCIATION_V1);
686 if (!sa_payload)
687 {
688 DBG1(DBG_IKE, "SA payload missing");
689 return FAILED;
690 }
691 list = sa_payload->get_proposals(sa_payload);
692 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
693 list, FALSE);
694 list->destroy_offset(list, offsetof(proposal_t, destroy));
695 if (!this->proposal)
696 {
697 DBG1(DBG_IKE, "no proposal found");
698 return FAILED;
699 }
700
701 lifetime = sa_payload->get_lifetime(sa_payload);
702 if (lifetime != this->lifetime)
703 {
704 DBG1(DBG_IKE, "received lifetime %us does not match configured "
705 "%us, using lower value", lifetime, this->lifetime);
706 }
707 this->lifetime = min(this->lifetime, lifetime);
708 auth_method = sa_payload->get_auth_method(sa_payload);
709 if (auth_method != this->auth_method)
710 {
711 DBG1(DBG_IKE, "received %N authentication, but configured %N, "
712 "continue with configured", auth_method_names, auth_method,
713 auth_method_names, this->auth_method);
714 }
715 return NEED_MORE;
716 }
717 case MM_KE:
718 {
719 if (!get_nonce_ke(this, &this->nonce_r, message))
720 {
721 return FAILED;
722 }
723 if (!derive_keys(this, this->nonce_i, this->nonce_r))
724 {
725 return FAILED;
726 }
727 return NEED_MORE;
728 }
729 case MM_AUTH:
730 {
731 id_payload_t *id_payload;
732 identification_t *id;
733
734 id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
735 if (!id_payload)
736 {
737 DBG1(DBG_IKE, "IDir payload missing");
738 return FAILED;
739 }
740 id = id_payload->get_identification(id_payload);
741 if (!id->matches(id, this->other_auth->get(this->other_auth,
742 AUTH_RULE_IDENTITY)))
743 {
744 DBG1(DBG_IKE, "IDir does not match");
745 id->destroy(id);
746 return FAILED;
747 }
748 this->ike_sa->set_other_id(this->ike_sa, id);
749
750 if (this->authenticator->process(this->authenticator,
751 message) != SUCCESS)
752 {
753 return FAILED;
754 }
755
756 /* TODO-IKEv1: check for XAUTH rounds, queue them */
757 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
758 this->ike_sa->get_name(this->ike_sa),
759 this->ike_sa->get_unique_id(this->ike_sa),
760 this->ike_sa->get_my_host(this->ike_sa),
761 this->ike_sa->get_my_id(this->ike_sa),
762 this->ike_sa->get_other_host(this->ike_sa),
763 this->ike_sa->get_other_id(this->ike_sa));
764
765 switch (this->auth_method)
766 {
767 case AUTH_XAUTH_RESP_PSK:
768 case AUTH_XAUTH_RESP_RSA: /* There should be more RESP cases here once added */
769 {
770 this->ike_sa->initiate_xauth(this->ike_sa, FALSE);
771 break;
772 }
773 case AUTH_XAUTH_INIT_PSK:
774 case AUTH_XAUTH_INIT_RSA: /* There should be more INIT cases here once added */
775 {
776 break;
777 }
778 default:
779 {
780 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
781 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
782 break;
783 }
784 }
785
786 return SUCCESS;
787 }
788 default:
789 return FAILED;
790 }
791 }
792
793 METHOD(task_t, get_type, task_type_t,
794 private_main_mode_t *this)
795 {
796 return TASK_MAIN_MODE;
797 }
798
799 METHOD(task_t, migrate, void,
800 private_main_mode_t *this, ike_sa_t *ike_sa)
801 {
802 this->ike_sa = ike_sa;
803 }
804
805 METHOD(task_t, destroy, void,
806 private_main_mode_t *this)
807 {
808 DESTROY_IF(this->peer_cfg);
809 DESTROY_IF(this->proposal);
810 DESTROY_IF(this->dh);
811 DESTROY_IF(this->authenticator);
812 free(this->dh_value.ptr);
813 free(this->nonce_i.ptr);
814 free(this->nonce_r.ptr);
815 free(this->sa_payload.ptr);
816 free(this);
817 }
818
819 /*
820 * Described in header.
821 */
822 main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator)
823 {
824 private_main_mode_t *this;
825
826 INIT(this,
827 .public = {
828 .task = {
829 .get_type = _get_type,
830 .migrate = _migrate,
831 .destroy = _destroy,
832 },
833 },
834 .ike_sa = ike_sa,
835 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
836 .initiator = initiator,
837 .state = MM_INIT,
838 );
839
840 if (initiator)
841 {
842 this->public.task.build = _build_i;
843 this->public.task.process = _process_i;
844 }
845 else
846 {
847 this->public.task.build = _build_r;
848 this->public.task.process = _process_r;
849 }
850
851 return &this->public;
852 }