proposal: Add selection flags to clone() method
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / aggressive_mode.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2012 Martin Willi
6 * Copyright (C) 2012 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 "aggressive_mode.h"
20
21 #include <string.h>
22
23 #include <daemon.h>
24 #include <sa/ikev1/phase1.h>
25 #include <encoding/payloads/sa_payload.h>
26 #include <encoding/payloads/id_payload.h>
27 #include <encoding/payloads/hash_payload.h>
28 #include <sa/ikev1/tasks/xauth.h>
29 #include <sa/ikev1/tasks/mode_config.h>
30 #include <sa/ikev1/tasks/informational.h>
31 #include <sa/ikev1/tasks/isakmp_delete.h>
32 #include <processing/jobs/adopt_children_job.h>
33 #include <processing/jobs/delete_ike_sa_job.h>
34
35 typedef struct private_aggressive_mode_t private_aggressive_mode_t;
36
37 /**
38 * Private members of a aggressive_mode_t task.
39 */
40 struct private_aggressive_mode_t {
41
42 /**
43 * Public methods and task_t interface.
44 */
45 aggressive_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 * Common phase 1 helper class
59 */
60 phase1_t *ph1;
61
62 /**
63 * IKE config to establish
64 */
65 ike_cfg_t *ike_cfg;
66
67 /**
68 * Peer config to use
69 */
70 peer_cfg_t *peer_cfg;
71
72 /**
73 * selected IKE proposal
74 */
75 proposal_t *proposal;
76
77 /**
78 * Negotiated SA lifetime
79 */
80 uint32_t lifetime;
81
82 /**
83 * Negotiated authentication method
84 */
85 auth_method_t method;
86
87 /**
88 * Encoded ID payload, without fixed header
89 */
90 chunk_t id_data;
91
92 /** states of aggressive mode */
93 enum {
94 AM_INIT,
95 AM_AUTH,
96 } state;
97 };
98
99 /**
100 * Set IKE_SA to established state
101 */
102 static bool establish(private_aggressive_mode_t *this)
103 {
104 if (!charon->bus->authorize(charon->bus, TRUE))
105 {
106 DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
107 return FALSE;
108 }
109
110 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
111 this->ike_sa->get_name(this->ike_sa),
112 this->ike_sa->get_unique_id(this->ike_sa),
113 this->ike_sa->get_my_host(this->ike_sa),
114 this->ike_sa->get_my_id(this->ike_sa),
115 this->ike_sa->get_other_host(this->ike_sa),
116 this->ike_sa->get_other_id(this->ike_sa));
117
118 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
119 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
120
121 return TRUE;
122 }
123
124 /**
125 * Check for notify errors, return TRUE if error found
126 */
127 static bool has_notify_errors(private_aggressive_mode_t *this, message_t *message)
128 {
129 enumerator_t *enumerator;
130 payload_t *payload;
131 bool err = FALSE;
132
133 enumerator = message->create_payload_enumerator(message);
134 while (enumerator->enumerate(enumerator, &payload))
135 {
136 if (payload->get_type(payload) == PLV1_NOTIFY)
137 {
138 notify_payload_t *notify;
139 notify_type_t type;
140
141 notify = (notify_payload_t*)payload;
142 type = notify->get_notify_type(notify);
143 if (type < 16384)
144 {
145 DBG1(DBG_IKE, "received %N error notify",
146 notify_type_names, type);
147 err = TRUE;
148 }
149 else
150 {
151 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
152 }
153 }
154 }
155 enumerator->destroy(enumerator);
156
157 return err;
158 }
159
160 /**
161 * Queue a task sending a notify in an INFORMATIONAL exchange
162 */
163 static status_t send_notify(private_aggressive_mode_t *this, notify_type_t type)
164 {
165 notify_payload_t *notify;
166 ike_sa_id_t *ike_sa_id;
167 uint64_t spi_i, spi_r;
168 chunk_t spi;
169
170 notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
171 PROTO_IKE, type);
172 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
173 spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
174 spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
175 spi = chunk_cata("cc", chunk_from_thing(spi_i), chunk_from_thing(spi_r));
176 notify->set_spi_data(notify, spi);
177
178 this->ike_sa->queue_task(this->ike_sa,
179 (task_t*)informational_create(this->ike_sa, notify));
180 /* cancel all active/passive tasks in favour of informational */
181 this->ike_sa->flush_queue(this->ike_sa,
182 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
183 return ALREADY_DONE;
184 }
185
186 /**
187 * Queue a delete task if authentication failed as initiator
188 */
189 static status_t send_delete(private_aggressive_mode_t *this)
190 {
191 this->ike_sa->queue_task(this->ike_sa,
192 (task_t*)isakmp_delete_create(this->ike_sa, TRUE));
193 /* cancel all active tasks in favour of informational */
194 this->ike_sa->flush_queue(this->ike_sa,
195 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
196 return ALREADY_DONE;
197 }
198
199 /**
200 * Schedule a timeout for the IKE_SA should it not establish
201 */
202 static void schedule_timeout(ike_sa_t *ike_sa)
203 {
204 job_t *job;
205
206 job = (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
207 lib->scheduler->schedule_job(lib->scheduler, job, HALF_OPEN_IKE_SA_TIMEOUT);
208 }
209
210 METHOD(task_t, build_i, status_t,
211 private_aggressive_mode_t *this, message_t *message)
212 {
213 switch (this->state)
214 {
215 case AM_INIT:
216 {
217 sa_payload_t *sa_payload;
218 id_payload_t *id_payload;
219 linked_list_t *proposals;
220 identification_t *id;
221 packet_t *packet;
222 uint16_t group;
223
224 DBG0(DBG_IKE, "initiating Aggressive Mode IKE_SA %s[%d] to %H",
225 this->ike_sa->get_name(this->ike_sa),
226 this->ike_sa->get_unique_id(this->ike_sa),
227 this->ike_sa->get_other_host(this->ike_sa));
228 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
229
230 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
231 this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
232 this->peer_cfg->get_ref(this->peer_cfg);
233
234 this->method = this->ph1->get_auth_method(this->ph1, this->peer_cfg);
235 if (this->method == AUTH_NONE)
236 {
237 DBG1(DBG_CFG, "configuration uses unsupported authentication");
238 return FAILED;
239 }
240 this->lifetime = this->peer_cfg->get_reauth_time(this->peer_cfg,
241 FALSE);
242 if (!this->lifetime)
243 { /* fall back to rekey time of no rekey time configured */
244 this->lifetime = this->peer_cfg->get_rekey_time(this->peer_cfg,
245 FALSE);
246 }
247 this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
248 proposals = this->ike_cfg->get_proposals(this->ike_cfg);
249 sa_payload = sa_payload_create_from_proposals_v1(proposals,
250 this->lifetime, 0, this->method, MODE_NONE,
251 ENCAP_NONE, 0);
252 proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
253
254 message->add_payload(message, &sa_payload->payload_interface);
255
256 group = this->ike_cfg->get_dh_group(this->ike_cfg);
257 if (group == MODP_NONE)
258 {
259 DBG1(DBG_IKE, "DH group selection failed");
260 return FAILED;
261 }
262 if (!this->ph1->create_dh(this->ph1, group))
263 {
264 DBG1(DBG_IKE, "DH group %N not supported",
265 diffie_hellman_group_names, group);
266 return FAILED;
267 }
268 if (!this->ph1->add_nonce_ke(this->ph1, message))
269 {
270 return FAILED;
271 }
272 id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
273 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
274 id_payload = id_payload_create_from_identification(PLV1_ID, id);
275 this->id_data = id_payload->get_encoded(id_payload);
276 message->add_payload(message, &id_payload->payload_interface);
277
278 /* pregenerate message to store SA payload */
279 if (this->ike_sa->generate_message(this->ike_sa, message,
280 &packet) != SUCCESS)
281 {
282 DBG1(DBG_IKE, "pregenerating SA payload failed");
283 return FAILED;
284 }
285 packet->destroy(packet);
286 if (!this->ph1->save_sa_payload(this->ph1, message))
287 {
288 DBG1(DBG_IKE, "SA payload invalid");
289 return FAILED;
290 }
291 this->state = AM_AUTH;
292 return NEED_MORE;
293 }
294 case AM_AUTH:
295 {
296 if (!this->ph1->build_auth(this->ph1, this->method, message,
297 this->id_data))
298 {
299 this->id_data = chunk_empty;
300 charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
301 return send_notify(this, AUTHENTICATION_FAILED);
302 }
303 this->id_data = chunk_empty;
304
305 switch (this->method)
306 {
307 case AUTH_XAUTH_INIT_PSK:
308 case AUTH_XAUTH_INIT_RSA:
309 case AUTH_HYBRID_INIT_RSA:
310 /* wait for XAUTH request */
311 schedule_timeout(this->ike_sa);
312 break;
313 case AUTH_XAUTH_RESP_PSK:
314 case AUTH_XAUTH_RESP_RSA:
315 case AUTH_HYBRID_RESP_RSA:
316 this->ike_sa->queue_task(this->ike_sa,
317 (task_t*)xauth_create(this->ike_sa, TRUE));
318 break;
319 default:
320 if (charon->ike_sa_manager->check_uniqueness(
321 charon->ike_sa_manager, this->ike_sa, FALSE))
322 {
323 DBG1(DBG_IKE, "cancelling Aggressive Mode due to "
324 "uniqueness policy");
325 return send_notify(this, AUTHENTICATION_FAILED);
326 }
327 if (!establish(this))
328 {
329 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
330 return send_notify(this, AUTHENTICATION_FAILED);
331 }
332 break;
333 }
334 /* check for and prepare mode config push/pull */
335 if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
336 {
337 if (this->peer_cfg->use_pull_mode(this->peer_cfg))
338 {
339 this->ike_sa->queue_task(this->ike_sa,
340 (task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
341 }
342 else
343 {
344 schedule_timeout(this->ike_sa);
345 }
346 }
347 else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
348 {
349 if (this->peer_cfg->use_pull_mode(this->peer_cfg))
350 {
351 schedule_timeout(this->ike_sa);
352 }
353 else
354 {
355 this->ike_sa->queue_task(this->ike_sa,
356 (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
357 }
358 }
359 return SUCCESS;
360 }
361 default:
362 return FAILED;
363 }
364 }
365
366 METHOD(task_t, process_r, status_t,
367 private_aggressive_mode_t *this, message_t *message)
368 {
369 switch (this->state)
370 {
371 case AM_INIT:
372 {
373 sa_payload_t *sa_payload;
374 id_payload_t *id_payload;
375 identification_t *id;
376 linked_list_t *list;
377 proposal_selection_flag_t flags = PROPOSAL_SKIP_PRIVATE;
378 uint16_t group;
379
380 this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
381 DBG0(DBG_IKE, "%H is initiating a Aggressive Mode IKE_SA",
382 message->get_source(message));
383 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
384
385 this->ike_sa->update_hosts(this->ike_sa,
386 message->get_destination(message),
387 message->get_source(message), TRUE);
388
389 sa_payload = (sa_payload_t*)message->get_payload(message,
390 PLV1_SECURITY_ASSOCIATION);
391 if (!sa_payload)
392 {
393 DBG1(DBG_IKE, "SA payload missing");
394 return send_notify(this, INVALID_PAYLOAD_TYPE);
395 }
396 if (!this->ph1->save_sa_payload(this->ph1, message))
397 {
398 return send_notify(this, INVALID_PAYLOAD_TYPE);
399 }
400
401 list = sa_payload->get_proposals(sa_payload);
402 if (!lib->settings->get_bool(lib->settings,
403 "%s.prefer_configured_proposals", TRUE, lib->ns))
404 {
405 flags = PROPOSAL_PREFER_SUPPLIED;
406 }
407 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg, list,
408 flags);
409 list->destroy_offset(list, offsetof(proposal_t, destroy));
410 if (!this->proposal)
411 {
412 DBG1(DBG_IKE, "no proposal found");
413 return send_notify(this, NO_PROPOSAL_CHOSEN);
414 }
415 this->ike_sa->set_proposal(this->ike_sa, this->proposal);
416
417 this->method = sa_payload->get_auth_method(sa_payload);
418 this->lifetime = sa_payload->get_lifetime(sa_payload);
419
420 switch (this->method)
421 {
422 case AUTH_XAUTH_INIT_PSK:
423 case AUTH_XAUTH_RESP_PSK:
424 case AUTH_PSK:
425 if (!lib->settings->get_bool(lib->settings, "%s.i_dont_care"
426 "_about_security_and_use_aggressive_mode_psk",
427 FALSE, lib->ns))
428 {
429 DBG1(DBG_IKE, "Aggressive Mode PSK disabled for "
430 "security reasons");
431 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
432 return send_notify(this, AUTHENTICATION_FAILED);
433 }
434 break;
435 default:
436 break;
437 }
438
439 if (!this->proposal->get_algorithm(this->proposal,
440 DIFFIE_HELLMAN_GROUP, &group, NULL))
441 {
442 DBG1(DBG_IKE, "DH group selection failed");
443 return send_notify(this, INVALID_KEY_INFORMATION);
444 }
445 if (!this->ph1->create_dh(this->ph1, group))
446 {
447 DBG1(DBG_IKE, "negotiated DH group not supported");
448 return send_notify(this, INVALID_KEY_INFORMATION);
449 }
450 if (!this->ph1->get_nonce_ke(this->ph1, message))
451 {
452 return send_notify(this, INVALID_PAYLOAD_TYPE);
453 }
454
455 id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
456 if (!id_payload)
457 {
458 DBG1(DBG_IKE, "IDii payload missing");
459 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
460 return send_notify(this, INVALID_PAYLOAD_TYPE);
461 }
462
463 id = id_payload->get_identification(id_payload);
464 this->id_data = id_payload->get_encoded(id_payload);
465 this->ike_sa->set_other_id(this->ike_sa, id);
466 this->peer_cfg = this->ph1->select_config(this->ph1,
467 this->method, TRUE, id);
468 if (!this->peer_cfg)
469 {
470 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
471 return send_notify(this, AUTHENTICATION_FAILED);
472 }
473 this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
474
475 this->state = AM_AUTH;
476 if (has_notify_errors(this, message))
477 {
478 return FAILED;
479 }
480 return NEED_MORE;
481 }
482 case AM_AUTH:
483 {
484 adopt_children_job_t *job = NULL;
485 xauth_t *xauth = NULL;
486
487 while (TRUE)
488 {
489 if (this->ph1->verify_auth(this->ph1, this->method, message,
490 chunk_clone(this->id_data)))
491 {
492 break;
493 }
494 this->peer_cfg->destroy(this->peer_cfg);
495 this->peer_cfg = this->ph1->select_config(this->ph1,
496 this->method, TRUE, NULL);
497 if (!this->peer_cfg)
498 {
499 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
500 return send_delete(this);
501 }
502 this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
503 }
504
505 if (!charon->bus->authorize(charon->bus, FALSE))
506 {
507 DBG1(DBG_IKE, "Aggressive Mode authorization hook forbids "
508 "IKE_SA, cancelling");
509 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
510 return send_delete(this);
511 }
512
513 switch (this->method)
514 {
515 case AUTH_XAUTH_INIT_PSK:
516 case AUTH_XAUTH_INIT_RSA:
517 case AUTH_HYBRID_INIT_RSA:
518 xauth = xauth_create(this->ike_sa, TRUE);
519 this->ike_sa->queue_task(this->ike_sa, (task_t*)xauth);
520 break;
521 case AUTH_XAUTH_RESP_PSK:
522 case AUTH_XAUTH_RESP_RSA:
523 case AUTH_HYBRID_RESP_RSA:
524 /* wait for XAUTH request */
525 break;
526 default:
527 if (charon->ike_sa_manager->check_uniqueness(
528 charon->ike_sa_manager, this->ike_sa, FALSE))
529 {
530 DBG1(DBG_IKE, "cancelling Aggressive Mode due to "
531 "uniqueness policy");
532 return send_delete(this);
533 }
534 if (!establish(this))
535 {
536 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
537 return send_delete(this);
538 }
539 job = adopt_children_job_create(
540 this->ike_sa->get_id(this->ike_sa));
541 break;
542 }
543 /* check for and prepare mode config push/pull */
544 if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
545 {
546 if (this->peer_cfg->use_pull_mode(this->peer_cfg))
547 {
548 this->ike_sa->queue_task(this->ike_sa,
549 (task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
550 }
551 }
552 else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
553 {
554 if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
555 {
556 if (job)
557 {
558 job->queue_task(job, (task_t*)
559 mode_config_create(this->ike_sa, TRUE, FALSE));
560 }
561 else if (xauth)
562 {
563 xauth->queue_mode_config_push(xauth);
564 }
565 else
566 {
567 this->ike_sa->queue_task(this->ike_sa, (task_t*)
568 mode_config_create(this->ike_sa, TRUE, FALSE));
569 }
570 }
571 }
572 if (job)
573 {
574 lib->processor->queue_job(lib->processor, (job_t*)job);
575 }
576 return SUCCESS;
577 }
578 default:
579 return FAILED;
580 }
581 }
582
583 METHOD(task_t, build_r, status_t,
584 private_aggressive_mode_t *this, message_t *message)
585 {
586 if (this->state == AM_AUTH)
587 {
588 sa_payload_t *sa_payload;
589 id_payload_t *id_payload;
590 identification_t *id;
591
592 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
593 this->lifetime, 0, this->method, MODE_NONE,
594 ENCAP_NONE, 0);
595 message->add_payload(message, &sa_payload->payload_interface);
596
597 if (!this->ph1->add_nonce_ke(this->ph1, message))
598 {
599 return send_notify(this, INVALID_KEY_INFORMATION);
600 }
601 if (!this->ph1->create_hasher(this->ph1))
602 {
603 return send_notify(this, NO_PROPOSAL_CHOSEN);
604 }
605 if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
606 {
607 return send_notify(this, INVALID_KEY_INFORMATION);
608 }
609
610 id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
611 this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
612
613 id_payload = id_payload_create_from_identification(PLV1_ID, id);
614 message->add_payload(message, &id_payload->payload_interface);
615
616 if (!this->ph1->build_auth(this->ph1, this->method, message,
617 id_payload->get_encoded(id_payload)))
618 {
619 charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
620 return send_notify(this, AUTHENTICATION_FAILED);
621 }
622 return NEED_MORE;
623 }
624 return FAILED;
625 }
626
627 METHOD(task_t, process_i, status_t,
628 private_aggressive_mode_t *this, message_t *message)
629 {
630 if (this->state == AM_AUTH)
631 {
632 auth_method_t method;
633 sa_payload_t *sa_payload;
634 id_payload_t *id_payload;
635 identification_t *id, *cid;
636 linked_list_t *list;
637 uint32_t lifetime;
638
639 sa_payload = (sa_payload_t*)message->get_payload(message,
640 PLV1_SECURITY_ASSOCIATION);
641 if (!sa_payload)
642 {
643 DBG1(DBG_IKE, "SA payload missing");
644 return send_notify(this, INVALID_PAYLOAD_TYPE);
645 }
646 list = sa_payload->get_proposals(sa_payload);
647 this->proposal = this->ike_cfg->select_proposal(this->ike_cfg, list, 0);
648 list->destroy_offset(list, offsetof(proposal_t, destroy));
649 if (!this->proposal)
650 {
651 DBG1(DBG_IKE, "no proposal found");
652 return send_notify(this, NO_PROPOSAL_CHOSEN);
653 }
654 this->ike_sa->set_proposal(this->ike_sa, this->proposal);
655
656 lifetime = sa_payload->get_lifetime(sa_payload);
657 if (lifetime != this->lifetime)
658 {
659 DBG1(DBG_IKE, "received lifetime %us does not match configured "
660 "lifetime %us", lifetime, this->lifetime);
661 }
662 this->lifetime = lifetime;
663 method = sa_payload->get_auth_method(sa_payload);
664 if (method != this->method)
665 {
666 DBG1(DBG_IKE, "received %N authentication, but configured %N, "
667 "continue with configured", auth_method_names, method,
668 auth_method_names, this->method);
669 }
670 if (!this->ph1->get_nonce_ke(this->ph1, message))
671 {
672 return send_notify(this, INVALID_PAYLOAD_TYPE);
673 }
674 if (!this->ph1->create_hasher(this->ph1))
675 {
676 return send_notify(this, NO_PROPOSAL_CHOSEN);
677 }
678
679 id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
680 if (!id_payload)
681 {
682 DBG1(DBG_IKE, "IDir payload missing");
683 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
684 return send_delete(this);
685 }
686 id = id_payload->get_identification(id_payload);
687 cid = this->ph1->get_id(this->ph1, this->peer_cfg, FALSE);
688 if (cid && !id->matches(id, cid))
689 {
690 DBG1(DBG_IKE, "IDir '%Y' does not match to '%Y'", id, cid);
691 id->destroy(id);
692 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
693 return send_notify(this, INVALID_ID_INFORMATION);
694 }
695 this->ike_sa->set_other_id(this->ike_sa, id);
696
697 if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
698 {
699 return send_notify(this, INVALID_KEY_INFORMATION);
700 }
701 if (!this->ph1->verify_auth(this->ph1, this->method, message,
702 id_payload->get_encoded(id_payload)))
703 {
704 charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
705 return send_notify(this, AUTHENTICATION_FAILED);
706 }
707 if (!charon->bus->authorize(charon->bus, FALSE))
708 {
709 DBG1(DBG_IKE, "Aggressive Mode authorization hook forbids IKE_SA, "
710 "cancelling");
711 return send_notify(this, AUTHENTICATION_FAILED);
712 }
713
714 return NEED_MORE;
715 }
716 return FAILED;
717 }
718
719 METHOD(task_t, get_type, task_type_t,
720 private_aggressive_mode_t *this)
721 {
722 return TASK_AGGRESSIVE_MODE;
723 }
724
725 METHOD(task_t, migrate, void,
726 private_aggressive_mode_t *this, ike_sa_t *ike_sa)
727 {
728 DESTROY_IF(this->peer_cfg);
729 DESTROY_IF(this->proposal);
730 this->ph1->destroy(this->ph1);
731 chunk_free(&this->id_data);
732
733 this->ike_sa = ike_sa;
734 this->state = AM_INIT;
735 this->peer_cfg = NULL;
736 this->proposal = NULL;
737 this->ph1 = phase1_create(ike_sa, this->initiator);
738 }
739
740 METHOD(task_t, destroy, void,
741 private_aggressive_mode_t *this)
742 {
743 DESTROY_IF(this->peer_cfg);
744 DESTROY_IF(this->proposal);
745 this->ph1->destroy(this->ph1);
746 chunk_free(&this->id_data);
747 free(this);
748 }
749
750 /*
751 * Described in header.
752 */
753 aggressive_mode_t *aggressive_mode_create(ike_sa_t *ike_sa, bool initiator)
754 {
755 private_aggressive_mode_t *this;
756
757 INIT(this,
758 .public = {
759 .task = {
760 .get_type = _get_type,
761 .migrate = _migrate,
762 .destroy = _destroy,
763 },
764 },
765 .ike_sa = ike_sa,
766 .ph1 = phase1_create(ike_sa, initiator),
767 .initiator = initiator,
768 .state = AM_INIT,
769 );
770
771 if (initiator)
772 {
773 this->public.task.build = _build_i;
774 this->public.task.process = _process_i;
775 }
776 else
777 {
778 this->public.task.build = _build_r;
779 this->public.task.process = _process_r;
780 }
781
782 return &this->public;
783 }