]>
Commit | Line | Data |
---|---|---|
c60c7694 | 1 | /* |
a9e60c96 | 2 | * Copyright (C) 2012-2018 Tobias Brunner |
a44bb934 | 3 | * Copyright (C) 2005-2009 Martin Willi |
c60c7694 | 4 | * Copyright (C) 2005 Jan Hutter |
1b671669 | 5 | * HSR Hochschule fuer Technik Rapperswil |
c60c7694 MW |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
01bc9bf4 | 15 | * for more details. |
c60c7694 MW |
16 | */ |
17 | ||
18 | #include "ike_auth.h" | |
19 | ||
20 | #include <string.h> | |
21 | ||
22 | #include <daemon.h> | |
c60c7694 MW |
23 | #include <encoding/payloads/id_payload.h> |
24 | #include <encoding/payloads/auth_payload.h> | |
49e8ac05 | 25 | #include <encoding/payloads/eap_payload.h> |
c60c7694 | 26 | #include <encoding/payloads/nonce_payload.h> |
a9e60c96 | 27 | #include <sa/ikev2/keymat_v2.h> |
15a682f4 | 28 | #include <sa/ikev2/authenticators/eap_authenticator.h> |
19233ef9 | 29 | #include <processing/jobs/delete_ike_sa_job.h> |
49e8ac05 | 30 | |
c60c7694 MW |
31 | typedef struct private_ike_auth_t private_ike_auth_t; |
32 | ||
33 | /** | |
34 | * Private members of a ike_auth_t task. | |
35 | */ | |
36 | struct private_ike_auth_t { | |
7daf5226 | 37 | |
c60c7694 MW |
38 | /** |
39 | * Public methods and task_t interface. | |
40 | */ | |
41 | ike_auth_t public; | |
7daf5226 | 42 | |
c60c7694 MW |
43 | /** |
44 | * Assigned IKE_SA. | |
45 | */ | |
46 | ike_sa_t *ike_sa; | |
7daf5226 | 47 | |
c60c7694 MW |
48 | /** |
49 | * Are we the initiator? | |
50 | */ | |
51 | bool initiator; | |
7daf5226 | 52 | |
c60c7694 MW |
53 | /** |
54 | * Nonce chosen by us in ike_init | |
55 | */ | |
56 | chunk_t my_nonce; | |
7daf5226 | 57 | |
c60c7694 MW |
58 | /** |
59 | * Nonce chosen by peer in ike_init | |
60 | */ | |
61 | chunk_t other_nonce; | |
7daf5226 | 62 | |
a9e60c96 TB |
63 | /** |
64 | * PPK_ID sent or received | |
65 | */ | |
66 | identification_t *ppk_id; | |
67 | ||
68 | /** | |
69 | * Optional PPK to use | |
70 | */ | |
71 | chunk_t ppk; | |
72 | ||
c60c7694 MW |
73 | /** |
74 | * IKE_SA_INIT message sent by us | |
75 | */ | |
76 | packet_t *my_packet; | |
7daf5226 | 77 | |
c60c7694 MW |
78 | /** |
79 | * IKE_SA_INIT message sent by peer | |
80 | */ | |
81 | packet_t *other_packet; | |
7daf5226 | 82 | |
5f15faeb MW |
83 | /** |
84 | * Reserved bytes of ID payload | |
85 | */ | |
86 | char reserved[3]; | |
87 | ||
c60c7694 | 88 | /** |
a44bb934 | 89 | * currently active authenticator, to authenticate us |
c60c7694 | 90 | */ |
a44bb934 | 91 | authenticator_t *my_auth; |
7daf5226 | 92 | |
a44bb934 MW |
93 | /** |
94 | * currently active authenticator, to authenticate peer | |
95 | */ | |
96 | authenticator_t *other_auth; | |
7daf5226 | 97 | |
a44bb934 MW |
98 | /** |
99 | * peer_cfg candidates, ordered by priority | |
100 | */ | |
101 | linked_list_t *candidates; | |
7daf5226 | 102 | |
a44bb934 MW |
103 | /** |
104 | * selected peer config (might change when using multiple authentications) | |
105 | */ | |
106 | peer_cfg_t *peer_cfg; | |
7daf5226 | 107 | |
a44bb934 MW |
108 | /** |
109 | * have we planned an(other) authentication exchange? | |
110 | */ | |
111 | bool do_another_auth; | |
7daf5226 | 112 | |
a44bb934 MW |
113 | /** |
114 | * has the peer announced another authentication exchange? | |
115 | */ | |
116 | bool expect_another_auth; | |
7daf5226 | 117 | |
a44bb934 MW |
118 | /** |
119 | * should we send a AUTHENTICATION_FAILED notify? | |
120 | */ | |
121 | bool authentication_failed; | |
6f5892f5 MW |
122 | |
123 | /** | |
124 | * received an INITIAL_CONTACT? | |
125 | */ | |
126 | bool initial_contact; | |
0020b25a MW |
127 | |
128 | /** | |
129 | * Is EAP acceptable, did we strictly authenticate peer? | |
130 | */ | |
131 | bool eap_acceptable; | |
f5a9025c TB |
132 | |
133 | /** | |
134 | * Gateway ID if redirected | |
135 | */ | |
136 | identification_t *redirect_to; | |
a44bb934 | 137 | }; |
49e8ac05 MW |
138 | |
139 | /** | |
a44bb934 | 140 | * check if multiple authentication extension is enabled, configuration-wise |
49e8ac05 | 141 | */ |
a44bb934 | 142 | static bool multiple_auth_enabled() |
49e8ac05 | 143 | { |
a44bb934 | 144 | return lib->settings->get_bool(lib->settings, |
d223fe80 | 145 | "%s.multiple_authentication", TRUE, lib->ns); |
c60c7694 MW |
146 | } |
147 | ||
148 | /** | |
149 | * collect the needed information in the IKE_SA_INIT exchange from our message | |
150 | */ | |
a44bb934 MW |
151 | static status_t collect_my_init_data(private_ike_auth_t *this, |
152 | message_t *message) | |
c60c7694 MW |
153 | { |
154 | nonce_payload_t *nonce; | |
7daf5226 | 155 | |
c60c7694 | 156 | /* get the nonce that was generated in ike_init */ |
3ecfc83c | 157 | nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE); |
94f9f421 | 158 | if (!nonce) |
c60c7694 MW |
159 | { |
160 | return FAILED; | |
161 | } | |
162 | this->my_nonce = nonce->get_nonce(nonce); | |
7daf5226 | 163 | |
a44bb934 | 164 | /* pre-generate the message, keep a copy */ |
c60c7694 MW |
165 | if (this->ike_sa->generate_message(this->ike_sa, message, |
166 | &this->my_packet) != SUCCESS) | |
167 | { | |
168 | return FAILED; | |
169 | } | |
7daf5226 | 170 | return NEED_MORE; |
c60c7694 MW |
171 | } |
172 | ||
173 | /** | |
174 | * collect the needed information in the IKE_SA_INIT exchange from others message | |
175 | */ | |
a44bb934 MW |
176 | static status_t collect_other_init_data(private_ike_auth_t *this, |
177 | message_t *message) | |
c60c7694 MW |
178 | { |
179 | /* we collect the needed information in the IKE_SA_INIT exchange */ | |
180 | nonce_payload_t *nonce; | |
7daf5226 | 181 | |
c60c7694 | 182 | /* get the nonce that was generated in ike_init */ |
3ecfc83c | 183 | nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE); |
94f9f421 | 184 | if (!nonce) |
c60c7694 MW |
185 | { |
186 | return FAILED; | |
187 | } | |
188 | this->other_nonce = nonce->get_nonce(nonce); | |
7daf5226 | 189 | |
a44bb934 | 190 | /* keep a copy of the received packet */ |
c60c7694 | 191 | this->other_packet = message->get_packet(message); |
7daf5226 | 192 | return NEED_MORE; |
c60c7694 MW |
193 | } |
194 | ||
5f15faeb MW |
195 | /** |
196 | * Get and store reserved bytes of id_payload, required for AUTH payload | |
197 | */ | |
198 | static void get_reserved_id_bytes(private_ike_auth_t *this, id_payload_t *id) | |
199 | { | |
b12c53ce | 200 | uint8_t *byte; |
5f15faeb MW |
201 | int i; |
202 | ||
203 | for (i = 0; i < countof(this->reserved); i++) | |
204 | { | |
205 | byte = payload_get_field(&id->payload_interface, RESERVED_BYTE, i); | |
206 | if (byte) | |
207 | { | |
208 | this->reserved[i] = *byte; | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
49e8ac05 | 213 | /** |
a44bb934 | 214 | * Get the next authentication configuration |
49e8ac05 | 215 | */ |
a44bb934 | 216 | static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local) |
49e8ac05 | 217 | { |
a44bb934 MW |
218 | enumerator_t *e1, *e2; |
219 | auth_cfg_t *c1, *c2, *next = NULL; | |
7daf5226 | 220 | |
a44bb934 MW |
221 | /* find an available config not already done */ |
222 | e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local); | |
223 | while (e1->enumerate(e1, &c1)) | |
95f1735f | 224 | { |
a44bb934 | 225 | bool found = FALSE; |
7daf5226 | 226 | |
44ce7493 | 227 | e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local); |
a44bb934 MW |
228 | while (e2->enumerate(e2, &c2)) |
229 | { | |
230 | if (c2->complies(c2, c1, FALSE)) | |
231 | { | |
232 | found = TRUE; | |
233 | break; | |
234 | } | |
235 | } | |
236 | e2->destroy(e2); | |
237 | if (!found) | |
238 | { | |
239 | next = c1; | |
240 | break; | |
49e8ac05 | 241 | } |
49e8ac05 | 242 | } |
a44bb934 MW |
243 | e1->destroy(e1); |
244 | return next; | |
49e8ac05 MW |
245 | } |
246 | ||
289b9b7b MW |
247 | /** |
248 | * Move the currently active auth config to the auth configs completed | |
249 | */ | |
250 | static void apply_auth_cfg(private_ike_auth_t *this, bool local) | |
251 | { | |
252 | auth_cfg_t *cfg; | |
253 | ||
254 | cfg = auth_cfg_create(); | |
255 | cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, local), local); | |
256 | this->ike_sa->add_auth_cfg(this->ike_sa, local, cfg); | |
257 | } | |
258 | ||
49e8ac05 | 259 | /** |
a44bb934 | 260 | * Check if we have should initiate another authentication round |
49e8ac05 | 261 | */ |
a44bb934 | 262 | static bool do_another_auth(private_ike_auth_t *this) |
49e8ac05 | 263 | { |
a44bb934 MW |
264 | bool do_another = FALSE; |
265 | enumerator_t *done, *todo; | |
266 | auth_cfg_t *done_cfg, *todo_cfg; | |
7daf5226 | 267 | |
a44bb934 | 268 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH)) |
49e8ac05 | 269 | { |
a44bb934 | 270 | return FALSE; |
49e8ac05 | 271 | } |
7daf5226 | 272 | |
44ce7493 | 273 | done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, TRUE); |
a44bb934 MW |
274 | todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE); |
275 | while (todo->enumerate(todo, &todo_cfg)) | |
49e8ac05 | 276 | { |
a44bb934 | 277 | if (!done->enumerate(done, &done_cfg)) |
49e8ac05 | 278 | { |
a44bb934 MW |
279 | done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); |
280 | } | |
281 | if (!done_cfg->complies(done_cfg, todo_cfg, FALSE)) | |
282 | { | |
283 | do_another = TRUE; | |
284 | break; | |
49e8ac05 | 285 | } |
49e8ac05 | 286 | } |
a44bb934 MW |
287 | done->destroy(done); |
288 | todo->destroy(todo); | |
289 | return do_another; | |
49e8ac05 MW |
290 | } |
291 | ||
a9e60c96 TB |
292 | /** |
293 | * Check if this is the first authentication round | |
294 | */ | |
295 | static bool is_first_round(private_ike_auth_t *this, bool local) | |
296 | { | |
297 | enumerator_t *done; | |
298 | auth_cfg_t *cfg; | |
299 | ||
300 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH)) | |
301 | { | |
302 | return TRUE; | |
303 | } | |
304 | ||
305 | done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local); | |
306 | if (done->enumerate(done, &cfg)) | |
307 | { | |
308 | done->destroy(done); | |
309 | return FALSE; | |
310 | } | |
311 | done->destroy(done); | |
312 | return TRUE; | |
313 | } | |
314 | ||
49e8ac05 | 315 | /** |
a44bb934 | 316 | * Get peer configuration candidates from backends |
49e8ac05 | 317 | */ |
a44bb934 | 318 | static bool load_cfg_candidates(private_ike_auth_t *this) |
49e8ac05 | 319 | { |
a44bb934 MW |
320 | enumerator_t *enumerator; |
321 | peer_cfg_t *peer_cfg; | |
da288a07 | 322 | ike_cfg_t *ike_cfg; |
a44bb934 MW |
323 | host_t *me, *other; |
324 | identification_t *my_id, *other_id; | |
da288a07 TB |
325 | proposal_t *ike_proposal; |
326 | bool private; | |
7daf5226 | 327 | |
a44bb934 MW |
328 | me = this->ike_sa->get_my_host(this->ike_sa); |
329 | other = this->ike_sa->get_other_host(this->ike_sa); | |
330 | my_id = this->ike_sa->get_my_id(this->ike_sa); | |
331 | other_id = this->ike_sa->get_other_id(this->ike_sa); | |
da288a07 | 332 | ike_proposal = this->ike_sa->get_proposal(this->ike_sa); |
05e373ae TE |
333 | private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) || |
334 | lib->settings->get_bool(lib->settings, "%s.accept_private_algs", | |
335 | FALSE, lib->ns); | |
7daf5226 | 336 | |
033dfba0 MW |
337 | DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]", |
338 | me, my_id, other, other_id); | |
a44bb934 | 339 | enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends, |
ac009df1 | 340 | me, other, my_id, other_id, IKEV2); |
a44bb934 MW |
341 | while (enumerator->enumerate(enumerator, &peer_cfg)) |
342 | { | |
da288a07 TB |
343 | /* ignore all configs that have no matching IKE proposal */ |
344 | ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); | |
345 | if (!ike_cfg->has_proposal(ike_cfg, ike_proposal, private)) | |
346 | { | |
347 | DBG2(DBG_CFG, "ignore candidate '%s' without matching IKE proposal", | |
348 | peer_cfg->get_name(peer_cfg)); | |
349 | continue; | |
350 | } | |
a44bb934 | 351 | peer_cfg->get_ref(peer_cfg); |
94f9f421 | 352 | if (!this->peer_cfg) |
a44bb934 MW |
353 | { /* best match */ |
354 | this->peer_cfg = peer_cfg; | |
a44bb934 MW |
355 | } |
356 | else | |
357 | { | |
358 | this->candidates->insert_last(this->candidates, peer_cfg); | |
359 | } | |
f5fbad4a | 360 | } |
a44bb934 MW |
361 | enumerator->destroy(enumerator); |
362 | if (this->peer_cfg) | |
49e8ac05 | 363 | { |
da288a07 | 364 | this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); |
a44bb934 MW |
365 | DBG1(DBG_CFG, "selected peer config '%s'", |
366 | this->peer_cfg->get_name(this->peer_cfg)); | |
367 | return TRUE; | |
49e8ac05 | 368 | } |
a44bb934 MW |
369 | DBG1(DBG_CFG, "no matching peer config found"); |
370 | return FALSE; | |
f5fbad4a MW |
371 | } |
372 | ||
373 | /** | |
a44bb934 | 374 | * update the current peer candidate if necessary, using candidates |
f5fbad4a | 375 | */ |
a44bb934 | 376 | static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) |
f5fbad4a | 377 | { |
a44bb934 | 378 | do |
49e8ac05 | 379 | { |
a44bb934 MW |
380 | if (this->peer_cfg) |
381 | { | |
cc787697 | 382 | char *comply_error = NULL; |
a44bb934 MW |
383 | enumerator_t *e1, *e2, *tmp; |
384 | auth_cfg_t *c1, *c2; | |
7daf5226 | 385 | |
44ce7493 | 386 | e1 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE); |
a44bb934 | 387 | e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE); |
7daf5226 | 388 | |
a44bb934 MW |
389 | if (strict) |
390 | { /* swap lists in strict mode: all configured rounds must be | |
391 | * fulfilled. If !strict, we check only the rounds done so far. */ | |
392 | tmp = e1; | |
393 | e1 = e2; | |
394 | e2 = tmp; | |
395 | } | |
396 | while (e1->enumerate(e1, &c1)) | |
397 | { | |
398 | /* check if done authentications comply to configured ones */ | |
cc787697 | 399 | if (!e2->enumerate(e2, &c2)) |
a44bb934 | 400 | { |
cc787697 MW |
401 | comply_error = "insufficient authentication rounds"; |
402 | break; | |
403 | } | |
404 | if (!strict && !c1->complies(c1, c2, TRUE)) | |
405 | { | |
406 | comply_error = "non-matching authentication done"; | |
407 | break; | |
408 | } | |
409 | if (strict && !c2->complies(c2, c1, TRUE)) | |
410 | { | |
411 | comply_error = "constraint checking failed"; | |
a44bb934 MW |
412 | break; |
413 | } | |
414 | } | |
415 | e1->destroy(e1); | |
416 | e2->destroy(e2); | |
cc787697 | 417 | if (!comply_error) |
a44bb934 MW |
418 | { |
419 | break; | |
420 | } | |
2ad1df95 | 421 | DBG1(DBG_CFG, "selected peer config '%s' unacceptable: %s", |
cc787697 | 422 | this->peer_cfg->get_name(this->peer_cfg), comply_error); |
a44bb934 MW |
423 | this->peer_cfg->destroy(this->peer_cfg); |
424 | } | |
425 | if (this->candidates->remove_first(this->candidates, | |
426 | (void**)&this->peer_cfg) != SUCCESS) | |
427 | { | |
428 | DBG1(DBG_CFG, "no alternative config found"); | |
429 | this->peer_cfg = NULL; | |
430 | } | |
431 | else | |
432 | { | |
433 | DBG1(DBG_CFG, "switching to peer config '%s'", | |
434 | this->peer_cfg->get_name(this->peer_cfg)); | |
435 | this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); | |
436 | } | |
49e8ac05 | 437 | } |
a44bb934 | 438 | while (this->peer_cfg); |
7daf5226 | 439 | |
a44bb934 | 440 | return this->peer_cfg != NULL; |
49e8ac05 MW |
441 | } |
442 | ||
a9e60c96 TB |
443 | /** |
444 | * Currently defined PPK_ID types | |
445 | */ | |
446 | #define PPK_ID_OPAQUE 1 | |
447 | #define PPK_ID_FIXED 2 | |
448 | ||
449 | /** | |
450 | * Parse the payload data of the given PPK_IDENTITY notify | |
451 | */ | |
452 | static bool parse_ppk_identity(notify_payload_t *notify, identification_t **id) | |
453 | { | |
454 | chunk_t data; | |
455 | ||
456 | data = notify->get_notification_data(notify); | |
457 | if (data.len < 2) | |
458 | { | |
459 | return FALSE; | |
460 | } | |
461 | switch (data.ptr[0]) | |
462 | { | |
a9e60c96 TB |
463 | case PPK_ID_FIXED: |
464 | data = chunk_skip(data, 1); | |
465 | break; | |
85afe81e TB |
466 | default: |
467 | return FALSE; | |
a9e60c96 TB |
468 | } |
469 | *id = identification_create_from_data(data); | |
470 | return TRUE; | |
471 | } | |
472 | ||
473 | /** | |
474 | * Add a PPK_IDENTITY with the given PPK_ID to the given message | |
475 | */ | |
476 | static void add_ppk_identity(identification_t *id, message_t *msg) | |
477 | { | |
478 | chunk_t data; | |
479 | uint8_t type = PPK_ID_FIXED; | |
480 | ||
481 | /* we currently only support one type */ | |
482 | data = chunk_cata("cc", chunk_from_thing(type), id->get_encoding(id)); | |
483 | msg->add_notify(msg, FALSE, PPK_IDENTITY, data); | |
484 | } | |
485 | ||
486 | /** | |
487 | * Use the given PPK_ID to find a PPK and store it and the ID in the task | |
488 | */ | |
489 | static bool get_ppk(private_ike_auth_t *this, identification_t *ppk_id) | |
490 | { | |
491 | shared_key_t *key; | |
492 | ||
493 | key = lib->credmgr->get_shared(lib->credmgr, SHARED_PPK, ppk_id, NULL); | |
494 | if (!key) | |
495 | { | |
496 | if (this->peer_cfg->ppk_required(this->peer_cfg)) | |
497 | { | |
498 | DBG1(DBG_CFG, "PPK required but no PPK found for '%Y'", ppk_id); | |
499 | return FALSE; | |
500 | } | |
501 | DBG1(DBG_CFG, "no PPK for '%Y' found, ignored because PPK is not " | |
502 | "required", ppk_id); | |
503 | return TRUE; | |
504 | } | |
505 | this->ppk = chunk_clone(key->get_key(key)); | |
506 | this->ppk_id = ppk_id->clone(ppk_id); | |
507 | key->destroy(key); | |
508 | return TRUE; | |
509 | } | |
510 | ||
511 | /** | |
512 | * Check if we have a PPK available and, if not, whether we require one as | |
513 | * initiator | |
514 | */ | |
515 | static bool get_ppk_i(private_ike_auth_t *this) | |
516 | { | |
517 | identification_t *ppk_id; | |
518 | ||
519 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK)) | |
520 | { | |
521 | if (this->peer_cfg->ppk_required(this->peer_cfg)) | |
522 | { | |
523 | DBG1(DBG_CFG, "PPK required but peer does not support PPK"); | |
524 | return FALSE; | |
525 | } | |
526 | return TRUE; | |
527 | } | |
528 | ||
529 | ppk_id = this->peer_cfg->get_ppk_id(this->peer_cfg); | |
530 | if (!ppk_id) | |
531 | { | |
532 | if (this->peer_cfg->ppk_required(this->peer_cfg)) | |
533 | { | |
534 | DBG1(DBG_CFG, "PPK required but no PPK_ID configured"); | |
535 | return FALSE; | |
536 | } | |
537 | return TRUE; | |
538 | } | |
539 | return get_ppk(this, ppk_id); | |
540 | } | |
541 | ||
542 | /** | |
543 | * Check if we have a PPK available and if not whether we require one as | |
544 | * responder | |
545 | */ | |
546 | static bool get_ppk_r(private_ike_auth_t *this, message_t *msg) | |
547 | { | |
548 | notify_payload_t *notify; | |
549 | identification_t *ppk_id, *ppk_id_cfg; | |
550 | bool result; | |
551 | ||
552 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK)) | |
553 | { | |
554 | if (this->peer_cfg->ppk_required(this->peer_cfg)) | |
555 | { | |
556 | DBG1(DBG_CFG, "PPK required but peer does not support PPK"); | |
557 | return FALSE; | |
558 | } | |
559 | return TRUE; | |
560 | } | |
561 | ||
562 | notify = msg->get_notify(msg, PPK_IDENTITY); | |
563 | if (!notify || !parse_ppk_identity(notify, &ppk_id)) | |
564 | { | |
565 | if (this->peer_cfg->ppk_required(this->peer_cfg)) | |
566 | { | |
567 | DBG1(DBG_CFG, "PPK required but no PPK_IDENTITY received"); | |
568 | return FALSE; | |
569 | } | |
570 | return TRUE; | |
571 | } | |
572 | ||
573 | ppk_id_cfg = this->peer_cfg->get_ppk_id(this->peer_cfg); | |
574 | if (ppk_id_cfg && !ppk_id->matches(ppk_id, ppk_id_cfg)) | |
575 | { | |
576 | DBG1(DBG_CFG, "received PPK_ID '%Y', but require '%Y'", ppk_id, | |
577 | ppk_id_cfg); | |
578 | ppk_id->destroy(ppk_id); | |
579 | return FALSE; | |
580 | } | |
581 | result = get_ppk(this, ppk_id); | |
582 | ppk_id->destroy(ppk_id); | |
583 | return result; | |
584 | } | |
585 | ||
2b7686b5 MW |
586 | METHOD(task_t, build_i, status_t, |
587 | private_ike_auth_t *this, message_t *message) | |
c60c7694 | 588 | { |
a44bb934 | 589 | auth_cfg_t *cfg; |
7daf5226 | 590 | |
c60c7694 MW |
591 | if (message->get_exchange_type(message) == IKE_SA_INIT) |
592 | { | |
593 | return collect_my_init_data(this, message); | |
594 | } | |
7daf5226 | 595 | |
94f9f421 | 596 | if (!this->peer_cfg) |
8b8dd69d | 597 | { |
a44bb934 MW |
598 | this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); |
599 | this->peer_cfg->get_ref(this->peer_cfg); | |
8b8dd69d | 600 | } |
7daf5226 | 601 | |
12fca6cc MW |
602 | if (message->get_message_id(message) == 1) |
603 | { /* in the first IKE_AUTH ... */ | |
604 | if (this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH)) | |
605 | { /* indicate support for multiple authentication */ | |
606 | message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED, | |
607 | chunk_empty); | |
608 | } | |
609 | /* indicate support for EAP-only authentication */ | |
610 | message->add_notify(message, FALSE, EAP_ONLY_AUTHENTICATION, | |
611 | chunk_empty); | |
d6ffa85f TB |
612 | /* indicate support for RFC 6311 Message ID synchronization */ |
613 | message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED, | |
614 | chunk_empty); | |
a9e60c96 TB |
615 | /* only use a PPK in the first round */ |
616 | if (!get_ppk_i(this)) | |
617 | { | |
618 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); | |
619 | return FAILED; | |
620 | } | |
49e8ac05 | 621 | } |
7daf5226 | 622 | |
a44bb934 MW |
623 | if (!this->do_another_auth && !this->my_auth) |
624 | { /* we have done our rounds */ | |
625 | return NEED_MORE; | |
626 | } | |
7daf5226 | 627 | |
a44bb934 | 628 | /* check if an authenticator is in progress */ |
94f9f421 | 629 | if (!this->my_auth) |
49e8ac05 | 630 | { |
a4a1e24d | 631 | identification_t *idi, *idr = NULL; |
a44bb934 | 632 | id_payload_t *id_payload; |
7daf5226 | 633 | |
a44bb934 MW |
634 | /* clean up authentication config from a previous round */ |
635 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); | |
636 | cfg->purge(cfg, TRUE); | |
7daf5226 | 637 | |
a44bb934 MW |
638 | /* add (optional) IDr */ |
639 | cfg = get_auth_cfg(this, FALSE); | |
640 | if (cfg) | |
641 | { | |
a4a1e24d | 642 | idr = cfg->get(cfg, AUTH_RULE_IDENTITY); |
3a8852c7 TB |
643 | if (!cfg->get(cfg, AUTH_RULE_IDENTITY_LOOSE) && idr && |
644 | !idr->contains_wildcards(idr)) | |
a44bb934 | 645 | { |
a4a1e24d | 646 | this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr)); |
a44bb934 | 647 | id_payload = id_payload_create_from_identification( |
3ecfc83c | 648 | PLV2_ID_RESPONDER, idr); |
a44bb934 MW |
649 | message->add_payload(message, (payload_t*)id_payload); |
650 | } | |
651 | } | |
652 | /* add IDi */ | |
653 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); | |
654 | cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE); | |
a4a1e24d | 655 | idi = cfg->get(cfg, AUTH_RULE_IDENTITY); |
b241a374 | 656 | if (!idi || idi->get_type(idi) == ID_ANY) |
4b32bde4 | 657 | { /* ID_ANY is invalid as IDi, use local IP address instead */ |
4b32bde4 | 658 | host_t *me; |
4b32bde4 | 659 | |
b241a374 | 660 | DBG1(DBG_CFG, "no IDi configured, fall back on IP address"); |
4b32bde4 TB |
661 | me = this->ike_sa->get_my_host(this->ike_sa); |
662 | idi = identification_create_from_sockaddr(me->get_sockaddr(me)); | |
7e84c427 | 663 | cfg->add(cfg, AUTH_RULE_IDENTITY, idi); |
4b32bde4 | 664 | } |
a4a1e24d | 665 | this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi)); |
3ecfc83c | 666 | id_payload = id_payload_create_from_identification(PLV2_ID_INITIATOR, idi); |
5f15faeb | 667 | get_reserved_id_bytes(this, id_payload); |
a44bb934 | 668 | message->add_payload(message, (payload_t*)id_payload); |
7daf5226 | 669 | |
2f95c552 TB |
670 | if (idr && !idr->contains_wildcards(idr) && |
671 | message->get_message_id(message) == 1 && | |
f4cc7ea1 | 672 | this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER) |
a4a1e24d MW |
673 | { |
674 | host_t *host; | |
675 | ||
676 | host = this->ike_sa->get_other_host(this->ike_sa); | |
677 | if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager, | |
678 | idi, idr, host->get_family(host))) | |
679 | { | |
680 | message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty); | |
681 | } | |
682 | } | |
683 | ||
a44bb934 | 684 | /* build authentication data */ |
25f2d52f MW |
685 | this->my_auth = authenticator_create_builder(this->ike_sa, cfg, |
686 | this->other_nonce, this->my_nonce, | |
687 | this->other_packet->get_data(this->other_packet), | |
5f15faeb MW |
688 | this->my_packet->get_data(this->my_packet), |
689 | this->reserved); | |
a44bb934 | 690 | if (!this->my_auth) |
49e8ac05 | 691 | { |
3f7f5388 | 692 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); |
49e8ac05 MW |
693 | return FAILED; |
694 | } | |
695 | } | |
a9e60c96 TB |
696 | /* for authentication methods that return NEED_MORE, the PPK will be reset |
697 | * in process_i() for messages without PPK_ID notify, so we always set it | |
698 | * during the first round (afterwards the PPK won't be available) */ | |
699 | if (this->ppk.ptr && this->my_auth->use_ppk) | |
700 | { | |
701 | this->my_auth->use_ppk(this->my_auth, this->ppk, | |
702 | !this->peer_cfg->ppk_required(this->peer_cfg)); | |
703 | } | |
a44bb934 MW |
704 | switch (this->my_auth->build(this->my_auth, message)) |
705 | { | |
706 | case SUCCESS: | |
289b9b7b | 707 | apply_auth_cfg(this, TRUE); |
a44bb934 MW |
708 | this->my_auth->destroy(this->my_auth); |
709 | this->my_auth = NULL; | |
710 | break; | |
711 | case NEED_MORE: | |
712 | break; | |
713 | default: | |
3f7f5388 | 714 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); |
a44bb934 MW |
715 | return FAILED; |
716 | } | |
7daf5226 | 717 | |
a9e60c96 TB |
718 | /* add a PPK_IDENTITY notify to the message that contains AUTH */ |
719 | if (this->ppk_id && message->get_payload(message, PLV2_AUTH)) | |
720 | { | |
721 | add_ppk_identity(this->ppk_id, message); | |
722 | } | |
723 | ||
a44bb934 MW |
724 | /* check for additional authentication rounds */ |
725 | if (do_another_auth(this)) | |
726 | { | |
3ecfc83c | 727 | if (message->get_payload(message, PLV2_AUTH)) |
a44bb934 MW |
728 | { |
729 | message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty); | |
730 | } | |
731 | } | |
732 | else | |
733 | { | |
734 | this->do_another_auth = FALSE; | |
735 | } | |
49e8ac05 | 736 | return NEED_MORE; |
c60c7694 MW |
737 | } |
738 | ||
2b7686b5 MW |
739 | METHOD(task_t, process_r, status_t, |
740 | private_ike_auth_t *this, message_t *message) | |
e0fe7651 | 741 | { |
a44bb934 MW |
742 | auth_cfg_t *cfg, *cand; |
743 | id_payload_t *id_payload; | |
744 | identification_t *id; | |
7daf5226 | 745 | |
c60c7694 MW |
746 | if (message->get_exchange_type(message) == IKE_SA_INIT) |
747 | { | |
748 | return collect_other_init_data(this, message); | |
749 | } | |
7daf5226 | 750 | |
94f9f421 | 751 | if (!this->my_auth && this->do_another_auth) |
a44bb934 MW |
752 | { |
753 | /* handle (optional) IDr payload, apply proposed identity */ | |
3ecfc83c | 754 | id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER); |
a44bb934 MW |
755 | if (id_payload) |
756 | { | |
757 | id = id_payload->get_identification(id_payload); | |
758 | } | |
759 | else | |
760 | { | |
761 | id = identification_create_from_encoding(ID_ANY, chunk_empty); | |
762 | } | |
763 | this->ike_sa->set_my_id(this->ike_sa, id); | |
764 | } | |
7daf5226 | 765 | |
a44bb934 | 766 | if (!this->expect_another_auth) |
49e8ac05 MW |
767 | { |
768 | return NEED_MORE; | |
769 | } | |
12fca6cc MW |
770 | |
771 | if (message->get_message_id(message) == 1) | |
772 | { /* check for extensions in the first IKE_AUTH */ | |
773 | if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED)) | |
774 | { | |
775 | this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH); | |
776 | } | |
83628fd6 TB |
777 | if (message->get_notify(message, EAP_ONLY_AUTHENTICATION)) |
778 | { | |
12fca6cc MW |
779 | this->ike_sa->enable_extension(this->ike_sa, |
780 | EXT_EAP_ONLY_AUTHENTICATION); | |
781 | } | |
a6289d93 TB |
782 | if (message->get_notify(message, INITIAL_CONTACT)) |
783 | { | |
784 | this->initial_contact = TRUE; | |
785 | } | |
a44bb934 | 786 | } |
7daf5226 | 787 | |
94f9f421 | 788 | if (!this->other_auth) |
a44bb934 MW |
789 | { |
790 | /* handle IDi payload */ | |
3ecfc83c | 791 | id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_INITIATOR); |
a44bb934 MW |
792 | if (!id_payload) |
793 | { | |
794 | DBG1(DBG_IKE, "IDi payload missing"); | |
795 | return FAILED; | |
796 | } | |
797 | id = id_payload->get_identification(id_payload); | |
5f15faeb | 798 | get_reserved_id_bytes(this, id_payload); |
a44bb934 MW |
799 | this->ike_sa->set_other_id(this->ike_sa, id); |
800 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); | |
801 | cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id)); | |
7daf5226 | 802 | |
94f9f421 | 803 | if (!this->peer_cfg) |
a44bb934 MW |
804 | { |
805 | if (!load_cfg_candidates(this)) | |
806 | { | |
807 | this->authentication_failed = TRUE; | |
808 | return NEED_MORE; | |
809 | } | |
810 | } | |
94f9f421 | 811 | if (!message->get_payload(message, PLV2_AUTH)) |
a44bb934 MW |
812 | { /* before authenticating with EAP, we need a EAP config */ |
813 | cand = get_auth_cfg(this, FALSE); | |
814 | while (!cand || ( | |
815 | (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK && | |
816 | (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0)) | |
817 | { /* peer requested EAP, but current config does not match */ | |
2ad1df95 | 818 | DBG1(DBG_IKE, "peer requested EAP, config unacceptable"); |
a44bb934 MW |
819 | this->peer_cfg->destroy(this->peer_cfg); |
820 | this->peer_cfg = NULL; | |
821 | if (!update_cfg_candidates(this, FALSE)) | |
822 | { | |
823 | this->authentication_failed = TRUE; | |
824 | return NEED_MORE; | |
825 | } | |
826 | cand = get_auth_cfg(this, FALSE); | |
827 | } | |
ec6caa13 MW |
828 | /* copy over the EAP specific rules for authentication */ |
829 | cfg->add(cfg, AUTH_RULE_EAP_TYPE, | |
830 | cand->get(cand, AUTH_RULE_EAP_TYPE)); | |
831 | cfg->add(cfg, AUTH_RULE_EAP_VENDOR, | |
832 | cand->get(cand, AUTH_RULE_EAP_VENDOR)); | |
833 | id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY); | |
834 | if (id) | |
835 | { | |
836 | cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id)); | |
837 | } | |
36eafea2 MW |
838 | id = (identification_t*)cand->get(cand, AUTH_RULE_AAA_IDENTITY); |
839 | if (id) | |
840 | { | |
841 | cfg->add(cfg, AUTH_RULE_AAA_IDENTITY, id->clone(id)); | |
842 | } | |
a44bb934 | 843 | } |
7daf5226 | 844 | |
a44bb934 | 845 | /* verify authentication data */ |
25f2d52f MW |
846 | this->other_auth = authenticator_create_verifier(this->ike_sa, |
847 | message, this->other_nonce, this->my_nonce, | |
848 | this->other_packet->get_data(this->other_packet), | |
5f15faeb MW |
849 | this->my_packet->get_data(this->my_packet), |
850 | this->reserved); | |
a44bb934 MW |
851 | if (!this->other_auth) |
852 | { | |
853 | this->authentication_failed = TRUE; | |
854 | return NEED_MORE; | |
855 | } | |
856 | } | |
a9e60c96 TB |
857 | if (message->get_payload(message, PLV2_AUTH) && |
858 | is_first_round(this, FALSE)) | |
859 | { | |
860 | if (!get_ppk_r(this, message)) | |
861 | { | |
862 | this->authentication_failed = TRUE; | |
863 | return NEED_MORE; | |
864 | } | |
865 | else if (this->ppk.ptr && this->other_auth->use_ppk) | |
866 | { | |
867 | this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE); | |
868 | } | |
869 | } | |
a44bb934 | 870 | switch (this->other_auth->process(this->other_auth, message)) |
49e8ac05 MW |
871 | { |
872 | case SUCCESS: | |
a44bb934 MW |
873 | this->other_auth->destroy(this->other_auth); |
874 | this->other_auth = NULL; | |
49e8ac05 | 875 | break; |
a44bb934 | 876 | case NEED_MORE: |
3ecfc83c | 877 | if (message->get_payload(message, PLV2_AUTH)) |
a44bb934 MW |
878 | { /* AUTH verification successful, but another build() needed */ |
879 | break; | |
880 | } | |
881 | return NEED_MORE; | |
49e8ac05 | 882 | default: |
a44bb934 | 883 | this->authentication_failed = TRUE; |
552cc11b | 884 | return NEED_MORE; |
49e8ac05 | 885 | } |
7daf5226 | 886 | |
a44bb934 | 887 | /* another auth round done, invoke authorize hook */ |
44ce7493 | 888 | if (!charon->bus->authorize(charon->bus, FALSE)) |
a44bb934 | 889 | { |
44ce7493 | 890 | DBG1(DBG_IKE, "authorization hook forbids IKE_SA, cancelling"); |
a44bb934 MW |
891 | this->authentication_failed = TRUE; |
892 | return NEED_MORE; | |
893 | } | |
7daf5226 | 894 | |
289b9b7b | 895 | apply_auth_cfg(this, FALSE); |
b49d047b | 896 | |
a44bb934 | 897 | if (!update_cfg_candidates(this, FALSE)) |
6e04f253 | 898 | { |
a44bb934 MW |
899 | this->authentication_failed = TRUE; |
900 | return NEED_MORE; | |
6e04f253 | 901 | } |
7daf5226 | 902 | |
94f9f421 | 903 | if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS)) |
a44bb934 MW |
904 | { |
905 | this->expect_another_auth = FALSE; | |
906 | if (!update_cfg_candidates(this, TRUE)) | |
907 | { | |
908 | this->authentication_failed = TRUE; | |
909 | return NEED_MORE; | |
910 | } | |
82290106 | 911 | } |
c60c7694 MW |
912 | return NEED_MORE; |
913 | } | |
914 | ||
a9e60c96 TB |
915 | /** |
916 | * Clear the PPK and PPK_ID | |
917 | */ | |
918 | static void clear_ppk(private_ike_auth_t *this) | |
919 | { | |
920 | DESTROY_IF(this->ppk_id); | |
921 | this->ppk_id = NULL; | |
922 | chunk_clear(&this->ppk); | |
923 | } | |
924 | ||
925 | /** | |
926 | * Derive new keys and clear the PPK | |
927 | */ | |
928 | static bool apply_ppk(private_ike_auth_t *this) | |
929 | { | |
930 | keymat_v2_t *keymat; | |
931 | ||
932 | if (this->ppk.ptr) | |
933 | { | |
934 | keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); | |
935 | if (!keymat->derive_ike_keys_ppk(keymat, this->ppk)) | |
936 | { | |
937 | return FALSE; | |
938 | } | |
939 | DBG1(DBG_CFG, "using PPK for PPK_ID '%Y'", this->ppk_id); | |
e4d85011 | 940 | this->ike_sa->set_condition(this->ike_sa, COND_PPK, TRUE); |
a9e60c96 TB |
941 | } |
942 | clear_ppk(this); | |
943 | return TRUE; | |
944 | } | |
945 | ||
2b7686b5 MW |
946 | METHOD(task_t, build_r, status_t, |
947 | private_ike_auth_t *this, message_t *message) | |
c60c7694 | 948 | { |
19233ef9 | 949 | identification_t *gateway; |
a44bb934 | 950 | auth_cfg_t *cfg; |
7daf5226 | 951 | |
c60c7694 MW |
952 | if (message->get_exchange_type(message) == IKE_SA_INIT) |
953 | { | |
a44bb934 MW |
954 | if (multiple_auth_enabled()) |
955 | { | |
956 | message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED, | |
957 | chunk_empty); | |
958 | } | |
c60c7694 MW |
959 | return collect_my_init_data(this, message); |
960 | } | |
7daf5226 | 961 | |
94f9f421 | 962 | if (this->authentication_failed || !this->peer_cfg) |
552cc11b | 963 | { |
ccbe3803 | 964 | goto peer_auth_failed; |
552cc11b | 965 | } |
7daf5226 | 966 | |
94f9f421 | 967 | if (!this->my_auth && this->do_another_auth) |
f007a700 | 968 | { |
a44bb934 MW |
969 | identification_t *id, *id_cfg; |
970 | id_payload_t *id_payload; | |
7daf5226 | 971 | |
a44bb934 MW |
972 | /* add IDr */ |
973 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); | |
974 | cfg->purge(cfg, TRUE); | |
975 | cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE); | |
7daf5226 | 976 | |
a44bb934 MW |
977 | id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY); |
978 | id = this->ike_sa->get_my_id(this->ike_sa); | |
979 | if (id->get_type(id) == ID_ANY) | |
980 | { /* no IDr received, apply configured ID */ | |
981 | if (!id_cfg || id_cfg->contains_wildcards(id_cfg)) | |
7fd6c078 TB |
982 | { /* no ID configured, use local IP address */ |
983 | host_t *me; | |
984 | ||
985 | DBG1(DBG_CFG, "no IDr configured, fall back on IP address"); | |
986 | me = this->ike_sa->get_my_host(this->ike_sa); | |
987 | id_cfg = identification_create_from_sockaddr( | |
988 | me->get_sockaddr(me)); | |
7e84c427 | 989 | cfg->add(cfg, AUTH_RULE_IDENTITY, id_cfg); |
a44bb934 MW |
990 | } |
991 | this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg)); | |
992 | id = id_cfg; | |
993 | } | |
994 | else | |
995 | { /* IDr received, check if it matches configuration */ | |
996 | if (id_cfg && !id->matches(id, id_cfg)) | |
997 | { | |
d24a74c5 | 998 | DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg); |
ccbe3803 | 999 | goto peer_auth_failed; |
a44bb934 MW |
1000 | } |
1001 | } | |
7daf5226 | 1002 | |
3ecfc83c | 1003 | id_payload = id_payload_create_from_identification(PLV2_ID_RESPONDER, id); |
5f15faeb | 1004 | get_reserved_id_bytes(this, id_payload); |
a44bb934 | 1005 | message->add_payload(message, (payload_t*)id_payload); |
7daf5226 | 1006 | |
f34702ff MW |
1007 | if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP) |
1008 | { /* EAP-only authentication */ | |
1009 | if (!this->ike_sa->supports_extension(this->ike_sa, | |
1010 | EXT_EAP_ONLY_AUTHENTICATION)) | |
1011 | { | |
1012 | DBG1(DBG_IKE, "configured EAP-only authentication, but peer " | |
1013 | "does not support it"); | |
ccbe3803 | 1014 | goto peer_auth_failed; |
f34702ff MW |
1015 | } |
1016 | } | |
1017 | else | |
a44bb934 | 1018 | { |
f34702ff MW |
1019 | /* build authentication data */ |
1020 | this->my_auth = authenticator_create_builder(this->ike_sa, cfg, | |
1021 | this->other_nonce, this->my_nonce, | |
1022 | this->other_packet->get_data(this->other_packet), | |
5f15faeb MW |
1023 | this->my_packet->get_data(this->my_packet), |
1024 | this->reserved); | |
f34702ff MW |
1025 | if (!this->my_auth) |
1026 | { | |
3f7f5388 | 1027 | goto local_auth_failed; |
f34702ff | 1028 | } |
a44bb934 | 1029 | } |
f007a700 | 1030 | } |
7daf5226 | 1031 | |
a44bb934 | 1032 | if (this->other_auth) |
49e8ac05 | 1033 | { |
a44bb934 MW |
1034 | switch (this->other_auth->build(this->other_auth, message)) |
1035 | { | |
1036 | case SUCCESS: | |
1037 | this->other_auth->destroy(this->other_auth); | |
1038 | this->other_auth = NULL; | |
1039 | break; | |
1040 | case NEED_MORE: | |
1041 | break; | |
1042 | default: | |
3ecfc83c | 1043 | if (message->get_payload(message, PLV2_EAP)) |
a44bb934 | 1044 | { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */ |
ccbe3803 | 1045 | goto peer_auth_failed_no_notify; |
a44bb934 | 1046 | } |
ccbe3803 | 1047 | goto peer_auth_failed; |
a44bb934 | 1048 | } |
49e8ac05 | 1049 | } |
a44bb934 | 1050 | if (this->my_auth) |
0644ebd3 | 1051 | { |
a9e60c96 TB |
1052 | if (this->ppk.ptr && this->my_auth->use_ppk) |
1053 | { | |
1054 | this->my_auth->use_ppk(this->my_auth, this->ppk, FALSE); | |
1055 | } | |
a44bb934 MW |
1056 | switch (this->my_auth->build(this->my_auth, message)) |
1057 | { | |
1058 | case SUCCESS: | |
289b9b7b | 1059 | apply_auth_cfg(this, TRUE); |
a44bb934 MW |
1060 | this->my_auth->destroy(this->my_auth); |
1061 | this->my_auth = NULL; | |
1062 | break; | |
1063 | case NEED_MORE: | |
1064 | break; | |
1065 | default: | |
3f7f5388 | 1066 | goto local_auth_failed; |
a44bb934 | 1067 | } |
0644ebd3 | 1068 | } |
7daf5226 | 1069 | |
a9e60c96 TB |
1070 | /* add a PPK_IDENTITY notify and derive new keys and clear the PPK */ |
1071 | if (this->ppk.ptr) | |
1072 | { | |
1073 | message->add_notify(message, FALSE, PPK_IDENTITY, chunk_empty); | |
1074 | if (!apply_ppk(this)) | |
1075 | { | |
1076 | goto local_auth_failed; | |
1077 | } | |
1078 | } | |
1079 | ||
a44bb934 MW |
1080 | /* check for additional authentication rounds */ |
1081 | if (do_another_auth(this)) | |
1082 | { | |
1083 | message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty); | |
1084 | } | |
1085 | else | |
1086 | { | |
1087 | this->do_another_auth = FALSE; | |
1088 | } | |
19233ef9 | 1089 | if (this->do_another_auth || this->expect_another_auth) |
c60c7694 | 1090 | { |
19233ef9 | 1091 | return NEED_MORE; |
c60c7694 | 1092 | } |
19233ef9 TB |
1093 | |
1094 | if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager, | |
a6289d93 | 1095 | this->ike_sa, this->initial_contact)) |
19233ef9 TB |
1096 | { |
1097 | DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy"); | |
1098 | charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP); | |
1099 | message->add_notify(message, TRUE, AUTHENTICATION_FAILED, | |
1100 | chunk_empty); | |
1101 | return FAILED; | |
1102 | } | |
1103 | if (!charon->bus->authorize(charon->bus, TRUE)) | |
1104 | { | |
1105 | DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling"); | |
1106 | goto peer_auth_failed; | |
1107 | } | |
1108 | if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) && | |
1109 | charon->redirect->redirect_on_auth(charon->redirect, this->ike_sa, | |
1110 | &gateway)) | |
1111 | { | |
1112 | delete_ike_sa_job_t *job; | |
1113 | chunk_t data; | |
1114 | ||
1115 | DBG1(DBG_IKE, "redirecting peer to %Y", gateway); | |
1116 | data = redirect_data_create(gateway, chunk_empty); | |
1117 | message->add_notify(message, FALSE, REDIRECT, data); | |
1118 | gateway->destroy(gateway); | |
1119 | chunk_free(&data); | |
1120 | /* we use this condition to prevent the CHILD_SA from getting created */ | |
1121 | this->ike_sa->set_condition(this->ike_sa, COND_REDIRECTED, TRUE); | |
1122 | /* if the peer does not delete the SA we do so after a while */ | |
1123 | job = delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE); | |
1124 | lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, | |
1125 | lib->settings->get_int(lib->settings, | |
1126 | "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT, | |
1127 | lib->ns)); | |
1128 | } | |
1129 | DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", | |
1130 | this->ike_sa->get_name(this->ike_sa), | |
1131 | this->ike_sa->get_unique_id(this->ike_sa), | |
1132 | this->ike_sa->get_my_host(this->ike_sa), | |
1133 | this->ike_sa->get_my_id(this->ike_sa), | |
1134 | this->ike_sa->get_other_host(this->ike_sa), | |
1135 | this->ike_sa->get_other_id(this->ike_sa)); | |
1136 | this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); | |
1137 | charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE); | |
1138 | return SUCCESS; | |
ccbe3803 TB |
1139 | |
1140 | peer_auth_failed: | |
3f7f5388 | 1141 | message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); |
ccbe3803 TB |
1142 | peer_auth_failed_no_notify: |
1143 | charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED); | |
1144 | return FAILED; | |
3f7f5388 MW |
1145 | local_auth_failed: |
1146 | message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); | |
1147 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); | |
1148 | return FAILED; | |
c60c7694 MW |
1149 | } |
1150 | ||
eaafcec1 MW |
1151 | /** |
1152 | * Send an INFORMATIONAL message with an AUTH_FAILED before closing IKE_SA | |
1153 | */ | |
1154 | static void send_auth_failed_informational(private_ike_auth_t *this, | |
1155 | message_t *reply) | |
1156 | { | |
1157 | message_t *message; | |
1158 | packet_t *packet; | |
1159 | host_t *host; | |
1160 | ||
1161 | message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION); | |
1162 | message->set_message_id(message, reply->get_message_id(reply) + 1); | |
1163 | host = this->ike_sa->get_my_host(this->ike_sa); | |
1164 | message->set_source(message, host->clone(host)); | |
1165 | host = this->ike_sa->get_other_host(this->ike_sa); | |
1166 | message->set_destination(message, host->clone(host)); | |
1167 | message->set_exchange_type(message, INFORMATIONAL); | |
1168 | message->add_notify(message, FALSE, AUTHENTICATION_FAILED, chunk_empty); | |
1169 | ||
1170 | if (this->ike_sa->generate_message(this->ike_sa, message, | |
1171 | &packet) == SUCCESS) | |
1172 | { | |
1173 | charon->sender->send(charon->sender, packet); | |
1174 | } | |
1175 | message->destroy(message); | |
1176 | } | |
1177 | ||
0020b25a | 1178 | /** |
b3ab7a48 | 1179 | * Check if strict constraint fulfillment required to continue current auth |
0020b25a MW |
1180 | */ |
1181 | static bool require_strict(private_ike_auth_t *this, bool mutual_eap) | |
1182 | { | |
1183 | auth_cfg_t *cfg; | |
1184 | ||
1185 | if (this->eap_acceptable) | |
1186 | { | |
1187 | return FALSE; | |
1188 | } | |
1189 | ||
1190 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); | |
1191 | switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS)) | |
1192 | { | |
1193 | case AUTH_CLASS_EAP: | |
1194 | if (mutual_eap && this->my_auth) | |
1195 | { | |
1196 | this->eap_acceptable = TRUE; | |
1197 | return !this->my_auth->is_mutual(this->my_auth); | |
1198 | } | |
1199 | return TRUE; | |
1200 | case AUTH_CLASS_PSK: | |
1201 | return TRUE; | |
1202 | case AUTH_CLASS_PUBKEY: | |
1203 | case AUTH_CLASS_ANY: | |
1204 | default: | |
1205 | return FALSE; | |
1206 | } | |
1207 | } | |
1208 | ||
2b7686b5 MW |
1209 | METHOD(task_t, process_i, status_t, |
1210 | private_ike_auth_t *this, message_t *message) | |
c60c7694 | 1211 | { |
a44bb934 | 1212 | enumerator_t *enumerator; |
c60c7694 | 1213 | payload_t *payload; |
a44bb934 | 1214 | auth_cfg_t *cfg; |
a9e60c96 | 1215 | bool mutual_eap = FALSE, ppk_id_received = FALSE; |
7daf5226 | 1216 | |
c60c7694 MW |
1217 | if (message->get_exchange_type(message) == IKE_SA_INIT) |
1218 | { | |
a44bb934 MW |
1219 | if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) && |
1220 | multiple_auth_enabled()) | |
1221 | { | |
1222 | this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH); | |
1223 | } | |
c60c7694 MW |
1224 | return collect_other_init_data(this, message); |
1225 | } | |
7daf5226 | 1226 | |
a44bb934 MW |
1227 | enumerator = message->create_payload_enumerator(message); |
1228 | while (enumerator->enumerate(enumerator, &payload)) | |
c60c7694 | 1229 | { |
3ecfc83c | 1230 | if (payload->get_type(payload) == PLV2_NOTIFY) |
c60c7694 MW |
1231 | { |
1232 | notify_payload_t *notify = (notify_payload_t*)payload; | |
1233 | notify_type_t type = notify->get_notify_type(notify); | |
7daf5226 | 1234 | |
c60c7694 MW |
1235 | switch (type) |
1236 | { | |
1237 | case NO_PROPOSAL_CHOSEN: | |
1238 | case SINGLE_PAIR_REQUIRED: | |
1239 | case NO_ADDITIONAL_SAS: | |
1240 | case INTERNAL_ADDRESS_FAILURE: | |
1241 | case FAILED_CP_REQUIRED: | |
1242 | case TS_UNACCEPTABLE: | |
1243 | case INVALID_SELECTORS: | |
1244 | /* these are errors, but are not critical as only the | |
1245 | * CHILD_SA won't get build, but IKE_SA establishes anyway */ | |
17d92e97 MW |
1246 | break; |
1247 | case MOBIKE_SUPPORTED: | |
1248 | case ADDITIONAL_IP4_ADDRESS: | |
1249 | case ADDITIONAL_IP6_ADDRESS: | |
1250 | /* handled in ike_mobike task */ | |
1251 | break; | |
ee614711 | 1252 | case AUTH_LIFETIME: |
7805ad30 | 1253 | /* handled in ike_auth_lifetime task */ |
ee614711 | 1254 | break; |
dc04b7c7 TB |
1255 | case ME_ENDPOINT: |
1256 | /* handled in ike_me task */ | |
3af51375 | 1257 | break; |
f5a9025c TB |
1258 | case REDIRECT: |
1259 | DESTROY_IF(this->redirect_to); | |
1260 | this->redirect_to = redirect_data_parse( | |
1261 | notify->get_notification_data(notify), NULL); | |
1262 | if (!this->redirect_to) | |
1263 | { | |
1264 | DBG1(DBG_IKE, "received invalid REDIRECT notify"); | |
1265 | } | |
1266 | break; | |
d6ffa85f TB |
1267 | case IKEV2_MESSAGE_ID_SYNC_SUPPORTED: |
1268 | this->ike_sa->enable_extension(this->ike_sa, | |
1269 | EXT_IKE_MESSAGE_ID_SYNC); | |
1270 | break; | |
a9e60c96 TB |
1271 | case PPK_IDENTITY: |
1272 | ppk_id_received = TRUE; | |
1273 | break; | |
c60c7694 MW |
1274 | default: |
1275 | { | |
3c354b6d | 1276 | if (type <= 16383) |
c60c7694 | 1277 | { |
a985db3f | 1278 | DBG1(DBG_IKE, "received %N notify error", |
c60c7694 | 1279 | notify_type_names, type); |
a44bb934 | 1280 | enumerator->destroy(enumerator); |
965348cd | 1281 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); |
7daf5226 | 1282 | return FAILED; |
c60c7694 | 1283 | } |
196b28a4 | 1284 | DBG2(DBG_IKE, "received %N notify", |
e5a7f1cd MW |
1285 | notify_type_names, type); |
1286 | break; | |
c60c7694 MW |
1287 | } |
1288 | } | |
1289 | } | |
1290 | } | |
a44bb934 | 1291 | enumerator->destroy(enumerator); |
7daf5226 | 1292 | |
a44bb934 | 1293 | if (this->expect_another_auth) |
49e8ac05 | 1294 | { |
94f9f421 | 1295 | if (!this->other_auth) |
a44bb934 MW |
1296 | { |
1297 | id_payload_t *id_payload; | |
1298 | identification_t *id; | |
7daf5226 | 1299 | |
a44bb934 MW |
1300 | /* handle IDr payload */ |
1301 | id_payload = (id_payload_t*)message->get_payload(message, | |
3ecfc83c | 1302 | PLV2_ID_RESPONDER); |
a44bb934 MW |
1303 | if (!id_payload) |
1304 | { | |
1305 | DBG1(DBG_IKE, "IDr payload missing"); | |
ccbe3803 | 1306 | goto peer_auth_failed; |
a44bb934 MW |
1307 | } |
1308 | id = id_payload->get_identification(id_payload); | |
5f15faeb | 1309 | get_reserved_id_bytes(this, id_payload); |
a44bb934 MW |
1310 | this->ike_sa->set_other_id(this->ike_sa, id); |
1311 | cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); | |
1312 | cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id)); | |
7daf5226 | 1313 | |
3ecfc83c | 1314 | if (message->get_payload(message, PLV2_AUTH)) |
a44bb934 | 1315 | { |
f34702ff MW |
1316 | /* verify authentication data */ |
1317 | this->other_auth = authenticator_create_verifier(this->ike_sa, | |
1318 | message, this->other_nonce, this->my_nonce, | |
1319 | this->other_packet->get_data(this->other_packet), | |
5f15faeb MW |
1320 | this->my_packet->get_data(this->my_packet), |
1321 | this->reserved); | |
f34702ff MW |
1322 | if (!this->other_auth) |
1323 | { | |
ccbe3803 | 1324 | goto peer_auth_failed; |
f34702ff MW |
1325 | } |
1326 | } | |
1327 | else | |
2aa553d7 MW |
1328 | { |
1329 | /* responder omitted AUTH payload, indicating EAP-only */ | |
1330 | mutual_eap = TRUE; | |
a44bb934 MW |
1331 | } |
1332 | } | |
f34702ff | 1333 | if (this->other_auth) |
a44bb934 | 1334 | { |
a9e60c96 TB |
1335 | if (ppk_id_received && is_first_round(this, FALSE) && |
1336 | this->other_auth->use_ppk) | |
1337 | { | |
1338 | this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE); | |
1339 | } | |
f34702ff MW |
1340 | switch (this->other_auth->process(this->other_auth, message)) |
1341 | { | |
1342 | case SUCCESS: | |
1343 | break; | |
1344 | case NEED_MORE: | |
1345 | return NEED_MORE; | |
1346 | default: | |
ccbe3803 | 1347 | goto peer_auth_failed; |
f34702ff MW |
1348 | } |
1349 | this->other_auth->destroy(this->other_auth); | |
1350 | this->other_auth = NULL; | |
a44bb934 | 1351 | } |
a44bb934 | 1352 | /* another auth round done, invoke authorize hook */ |
44ce7493 | 1353 | if (!charon->bus->authorize(charon->bus, FALSE)) |
a44bb934 | 1354 | { |
44ce7493 | 1355 | DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling"); |
ccbe3803 | 1356 | goto peer_auth_failed; |
a44bb934 | 1357 | } |
b49d047b | 1358 | |
d8a94c18 MW |
1359 | if (!mutual_eap) |
1360 | { | |
1361 | apply_auth_cfg(this, FALSE); | |
1362 | } | |
49e8ac05 | 1363 | } |
7daf5226 | 1364 | |
0020b25a MW |
1365 | if (require_strict(this, mutual_eap)) |
1366 | { | |
1367 | if (!update_cfg_candidates(this, TRUE)) | |
1368 | { | |
1369 | goto peer_auth_failed; | |
1370 | } | |
1371 | } | |
1372 | ||
2aa553d7 MW |
1373 | if (this->my_auth) |
1374 | { | |
a9e60c96 TB |
1375 | /* while we already set the PPK in build_i(), we MUST not use it if |
1376 | * the peer did not reply with a PPK_ID notify */ | |
1377 | if (this->ppk.ptr && this->my_auth->use_ppk) | |
1378 | { | |
1379 | this->my_auth->use_ppk(this->my_auth, | |
1380 | ppk_id_received ? this->ppk : chunk_empty, | |
1381 | FALSE); | |
1382 | } | |
2aa553d7 MW |
1383 | switch (this->my_auth->process(this->my_auth, message)) |
1384 | { | |
1385 | case SUCCESS: | |
289b9b7b | 1386 | apply_auth_cfg(this, TRUE); |
d8a94c18 MW |
1387 | if (this->my_auth->is_mutual(this->my_auth)) |
1388 | { | |
1389 | apply_auth_cfg(this, FALSE); | |
1390 | } | |
2aa553d7 MW |
1391 | this->my_auth->destroy(this->my_auth); |
1392 | this->my_auth = NULL; | |
1393 | this->do_another_auth = do_another_auth(this); | |
1394 | break; | |
1395 | case NEED_MORE: | |
1396 | break; | |
1397 | default: | |
a9e60c96 TB |
1398 | goto local_auth_failed; |
1399 | } | |
1400 | } | |
1401 | ||
1402 | /* change keys and clear PPK after we are done with our authentication, so | |
1403 | * we only explicitly use it for the first round, afterwards we just use the | |
1404 | * changed SK_p keys implicitly */ | |
1405 | if (!this->my_auth && this->ppk_id) | |
1406 | { | |
1407 | if (ppk_id_received) | |
1408 | { | |
1409 | if (!apply_ppk(this)) | |
1410 | { | |
1411 | goto local_auth_failed; | |
1412 | } | |
1413 | } | |
1414 | else | |
1415 | { | |
1416 | DBG1(DBG_CFG, "peer didn't use PPK for PPK_ID '%Y'", this->ppk_id); | |
2aa553d7 | 1417 | } |
a9e60c96 | 1418 | clear_ppk(this); |
2aa553d7 | 1419 | } |
a9e60c96 | 1420 | |
2aa553d7 MW |
1421 | if (mutual_eap) |
1422 | { | |
1423 | if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth)) | |
1424 | { | |
1425 | DBG1(DBG_IKE, "do not allow non-mutual EAP-only authentication"); | |
ccbe3803 | 1426 | goto peer_auth_failed; |
2aa553d7 MW |
1427 | } |
1428 | DBG1(DBG_IKE, "allow mutual EAP-only authentication"); | |
1429 | } | |
1430 | ||
94f9f421 | 1431 | if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS)) |
552cc11b | 1432 | { |
a44bb934 | 1433 | this->expect_another_auth = FALSE; |
552cc11b | 1434 | } |
f5a9025c | 1435 | if (this->expect_another_auth || this->do_another_auth || this->my_auth) |
a44bb934 | 1436 | { |
f5a9025c | 1437 | return NEED_MORE; |
a44bb934 | 1438 | } |
f5a9025c TB |
1439 | if (!update_cfg_candidates(this, TRUE)) |
1440 | { | |
1441 | goto peer_auth_failed; | |
1442 | } | |
1443 | if (!charon->bus->authorize(charon->bus, TRUE)) | |
1444 | { | |
1445 | DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, " | |
1446 | "cancelling"); | |
1447 | goto peer_auth_failed; | |
1448 | } | |
1449 | DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", | |
1450 | this->ike_sa->get_name(this->ike_sa), | |
1451 | this->ike_sa->get_unique_id(this->ike_sa), | |
1452 | this->ike_sa->get_my_host(this->ike_sa), | |
1453 | this->ike_sa->get_my_id(this->ike_sa), | |
1454 | this->ike_sa->get_other_host(this->ike_sa), | |
1455 | this->ike_sa->get_other_id(this->ike_sa)); | |
1456 | this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); | |
1457 | charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE); | |
1458 | ||
1459 | if (this->redirect_to) | |
1460 | { | |
1461 | this->ike_sa->handle_redirect(this->ike_sa, this->redirect_to); | |
1462 | } | |
1463 | return SUCCESS; | |
ff4b25f9 | 1464 | |
ccbe3803 TB |
1465 | peer_auth_failed: |
1466 | charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED); | |
eaafcec1 | 1467 | send_auth_failed_informational(this, message); |
ff4b25f9 | 1468 | return FAILED; |
a9e60c96 TB |
1469 | local_auth_failed: |
1470 | charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); | |
1471 | send_auth_failed_informational(this, message); | |
1472 | return FAILED; | |
c60c7694 MW |
1473 | } |
1474 | ||
2b7686b5 MW |
1475 | METHOD(task_t, get_type, task_type_t, |
1476 | private_ike_auth_t *this) | |
c60c7694 | 1477 | { |
a09972df | 1478 | return TASK_IKE_AUTH; |
c60c7694 MW |
1479 | } |
1480 | ||
2b7686b5 MW |
1481 | METHOD(task_t, migrate, void, |
1482 | private_ike_auth_t *this, ike_sa_t *ike_sa) | |
c60c7694 | 1483 | { |
a9e60c96 | 1484 | clear_ppk(this); |
c60c7694 MW |
1485 | chunk_free(&this->my_nonce); |
1486 | chunk_free(&this->other_nonce); | |
1487 | DESTROY_IF(this->my_packet); | |
1488 | DESTROY_IF(this->other_packet); | |
a44bb934 MW |
1489 | DESTROY_IF(this->peer_cfg); |
1490 | DESTROY_IF(this->my_auth); | |
1491 | DESTROY_IF(this->other_auth); | |
f5a9025c | 1492 | DESTROY_IF(this->redirect_to); |
a44bb934 | 1493 | this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy)); |
7daf5226 | 1494 | |
c60c7694 MW |
1495 | this->my_packet = NULL; |
1496 | this->other_packet = NULL; | |
c60c7694 | 1497 | this->ike_sa = ike_sa; |
a44bb934 MW |
1498 | this->peer_cfg = NULL; |
1499 | this->my_auth = NULL; | |
1500 | this->other_auth = NULL; | |
f5a9025c | 1501 | this->redirect_to = NULL; |
a44bb934 MW |
1502 | this->do_another_auth = TRUE; |
1503 | this->expect_another_auth = TRUE; | |
1504 | this->authentication_failed = FALSE; | |
a44bb934 | 1505 | this->candidates = linked_list_create(); |
c60c7694 MW |
1506 | } |
1507 | ||
2b7686b5 MW |
1508 | METHOD(task_t, destroy, void, |
1509 | private_ike_auth_t *this) | |
c60c7694 | 1510 | { |
a9e60c96 | 1511 | clear_ppk(this); |
c60c7694 MW |
1512 | chunk_free(&this->my_nonce); |
1513 | chunk_free(&this->other_nonce); | |
1514 | DESTROY_IF(this->my_packet); | |
1515 | DESTROY_IF(this->other_packet); | |
a44bb934 MW |
1516 | DESTROY_IF(this->my_auth); |
1517 | DESTROY_IF(this->other_auth); | |
1518 | DESTROY_IF(this->peer_cfg); | |
f5a9025c | 1519 | DESTROY_IF(this->redirect_to); |
a44bb934 | 1520 | this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy)); |
c60c7694 MW |
1521 | free(this); |
1522 | } | |
1523 | ||
1524 | /* | |
1525 | * Described in header. | |
1526 | */ | |
1527 | ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator) | |
1528 | { | |
2b7686b5 MW |
1529 | private_ike_auth_t *this; |
1530 | ||
1531 | INIT(this, | |
1532 | .public = { | |
1533 | .task = { | |
1534 | .get_type = _get_type, | |
1535 | .migrate = _migrate, | |
1536 | .build = _build_r, | |
1537 | .process = _process_r, | |
1538 | .destroy = _destroy, | |
1539 | }, | |
1540 | }, | |
1541 | .ike_sa = ike_sa, | |
1542 | .initiator = initiator, | |
1543 | .candidates = linked_list_create(), | |
1544 | .do_another_auth = TRUE, | |
1545 | .expect_another_auth = TRUE, | |
1546 | ); | |
c60c7694 MW |
1547 | if (initiator) |
1548 | { | |
2b7686b5 MW |
1549 | this->public.task.build = _build_i; |
1550 | this->public.task.process = _process_i; | |
c60c7694 | 1551 | } |
c60c7694 MW |
1552 | return &this->public; |
1553 | } |