Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_init.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2019 Tobias Brunner
3: * Copyright (C) 2005-2008 Martin Willi
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
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
15: * for more details.
16: */
17:
18: #include "ike_init.h"
19:
20: #include <string.h>
21:
22: #include <daemon.h>
23: #include <bio/bio_reader.h>
24: #include <bio/bio_writer.h>
25: #include <sa/ikev2/keymat_v2.h>
26: #include <crypto/diffie_hellman.h>
27: #include <crypto/hashers/hash_algorithm_set.h>
28: #include <encoding/payloads/sa_payload.h>
29: #include <encoding/payloads/ke_payload.h>
30: #include <encoding/payloads/nonce_payload.h>
31:
32: /** maximum retries to do with cookies/other dh groups */
33: #define MAX_RETRIES 5
34:
35: typedef struct private_ike_init_t private_ike_init_t;
36:
37: /**
38: * Private members of a ike_init_t task.
39: */
40: struct private_ike_init_t {
41:
42: /**
43: * Public methods and task_t interface.
44: */
45: ike_init_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: * diffie hellman group to use
59: */
60: diffie_hellman_group_t dh_group;
61:
62: /**
63: * diffie hellman key exchange
64: */
65: diffie_hellman_t *dh;
66:
67: /**
68: * Applying DH public value failed?
69: */
70: bool dh_failed;
71:
72: /**
73: * Keymat derivation (from IKE_SA)
74: */
75: keymat_v2_t *keymat;
76:
77: /**
78: * nonce chosen by us
79: */
80: chunk_t my_nonce;
81:
82: /**
83: * nonce chosen by peer
84: */
85: chunk_t other_nonce;
86:
87: /**
88: * nonce generator
89: */
90: nonce_gen_t *nonceg;
91:
92: /**
93: * Negotiated proposal used for IKE_SA
94: */
95: proposal_t *proposal;
96:
97: /**
98: * Old IKE_SA which gets rekeyed
99: */
100: ike_sa_t *old_sa;
101:
102: /**
103: * cookie received from responder
104: */
105: chunk_t cookie;
106:
107: /**
108: * retries done so far after failure (cookie or bad dh group)
109: */
110: u_int retry;
111:
112: /**
113: * Whether to use Signature Authentication as per RFC 7427
114: */
115: bool signature_authentication;
116:
117: /**
118: * Whether to follow IKEv2 redirects as per RFC 5685
119: */
120: bool follow_redirects;
121: };
122:
123: /**
124: * Allocate our own nonce value
125: */
126: static bool generate_nonce(private_ike_init_t *this)
127: {
128: if (!this->nonceg)
129: {
130: DBG1(DBG_IKE, "no nonce generator found to create nonce");
131: return FALSE;
132: }
133: if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
134: &this->my_nonce))
135: {
136: DBG1(DBG_IKE, "nonce allocation failed");
137: return FALSE;
138: }
139: return TRUE;
140: }
141:
142: /**
143: * Notify the peer about the hash algorithms we support or expect,
144: * as per RFC 7427
145: */
146: static void send_supported_hash_algorithms(private_ike_init_t *this,
147: message_t *message)
148: {
149: hash_algorithm_set_t *algos;
150: enumerator_t *enumerator, *rounds;
151: bio_writer_t *writer;
152: hash_algorithm_t hash;
153: peer_cfg_t *peer;
154: auth_cfg_t *auth;
155: auth_rule_t rule;
156: signature_params_t *config;
157: int written;
158: size_t len = BUF_LEN;
159: char buf[len];
160: char *pos = buf;
161: char *plugin_name;
162:
163: algos = hash_algorithm_set_create();
164: peer = this->ike_sa->get_peer_cfg(this->ike_sa);
165: if (peer)
166: {
167: rounds = peer->create_auth_cfg_enumerator(peer, FALSE);
168: while (rounds->enumerate(rounds, &auth))
169: {
170: enumerator = auth->create_enumerator(auth);
171: while (enumerator->enumerate(enumerator, &rule, &config))
172: {
173: if (rule == AUTH_RULE_IKE_SIGNATURE_SCHEME)
174: {
175: hash = hasher_from_signature_scheme(config->scheme,
176: config->params);
177: if (hasher_algorithm_for_ikev2(hash))
178: {
179: algos->add(algos, hash);
180: }
181: }
182: }
183: enumerator->destroy(enumerator);
184: }
185: rounds->destroy(rounds);
186: }
187:
188: if (!algos->count(algos))
189: {
190: enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
191: while (enumerator->enumerate(enumerator, &hash, &plugin_name))
192: {
193: if (hasher_algorithm_for_ikev2(hash))
194: {
195: algos->add(algos, hash);
196: }
197: }
198: enumerator->destroy(enumerator);
199: }
200:
201: if (algos->count(algos))
202: {
203: writer = bio_writer_create(0);
204: enumerator = algos->create_enumerator(algos);
205: while (enumerator->enumerate(enumerator, &hash))
206: {
207: writer->write_uint16(writer, hash);
208:
209: /* generate debug output */
210: written = snprintf(pos, len, " %N", hash_algorithm_short_names,
211: hash);
212: if (written > 0 && written < len)
213: {
214: pos += written;
215: len -= written;
216: }
217: }
218: enumerator->destroy(enumerator);
219: message->add_notify(message, FALSE, SIGNATURE_HASH_ALGORITHMS,
220: writer->get_buf(writer));
221: writer->destroy(writer);
222:
223: *pos = '\0';
224: DBG2(DBG_CFG, "sending supported signature hash algorithms:%s", buf);
225: }
226: algos->destroy(algos);
227: }
228:
229: /**
230: * Store algorithms supported by other peer
231: */
232: static void handle_supported_hash_algorithms(private_ike_init_t *this,
233: notify_payload_t *notify)
234: {
235: bio_reader_t *reader;
236: uint16_t algo;
237: int written;
238: size_t len = BUF_LEN;
239: char buf[len];
240: char *pos = buf;
241: bool added = FALSE;
242:
243: reader = bio_reader_create(notify->get_notification_data(notify));
244: while (reader->remaining(reader) >= 2 && reader->read_uint16(reader, &algo))
245: {
246: if (hasher_algorithm_for_ikev2(algo))
247: {
248: this->keymat->add_hash_algorithm(this->keymat, algo);
249: added = TRUE;
250:
251: /* generate debug output */
252: written = snprintf(pos, len, " %N", hash_algorithm_short_names,
253: algo);
254: if (written > 0 && written < len)
255: {
256: pos += written;
257: len -= written;
258: }
259: }
260: }
261: reader->destroy(reader);
262:
263: *pos = '\0';
264: DBG2(DBG_CFG, "received supported signature hash algorithms:%s", buf);
265:
266: if (added)
267: {
268: this->ike_sa->enable_extension(this->ike_sa, EXT_SIGNATURE_AUTH);
269: }
270: }
271:
272: /**
273: * Check whether to send a USE_PPK notify
274: */
275: static bool send_use_ppk(private_ike_init_t *this)
276: {
277: peer_cfg_t *peer;
278: enumerator_t *keys;
279: shared_key_t *key;
280: bool use_ppk = FALSE;
281:
282: if (this->initiator)
283: {
284: peer = this->ike_sa->get_peer_cfg(this->ike_sa);
285: if (peer->get_ppk_id(peer))
286: {
287: use_ppk = TRUE;
288: }
289: }
290: else if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
291: {
292: /* check if we have at least one PPK available */
293: keys = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PPK,
294: NULL, NULL);
295: if (keys->enumerate(keys, &key, NULL, NULL))
296: {
297: use_ppk = TRUE;
298: }
299: keys->destroy(keys);
300: }
301: return use_ppk;
302: }
303:
304: /**
305: * build the payloads for the message
306: */
307: static bool build_payloads(private_ike_init_t *this, message_t *message)
308: {
309: sa_payload_t *sa_payload;
310: ke_payload_t *ke_payload;
311: nonce_payload_t *nonce_payload;
312: linked_list_t *proposal_list, *other_dh_groups;
313: ike_sa_id_t *id;
314: proposal_t *proposal;
315: enumerator_t *enumerator;
316: ike_cfg_t *ike_cfg;
317:
318: id = this->ike_sa->get_id(this->ike_sa);
319:
320: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
321:
322: if (this->initiator)
323: {
324: proposal_list = ike_cfg->get_proposals(ike_cfg);
325: other_dh_groups = linked_list_create();
326: enumerator = proposal_list->create_enumerator(proposal_list);
327: while (enumerator->enumerate(enumerator, (void**)&proposal))
328: {
329: /* include SPI of new IKE_SA when we are rekeying */
330: if (this->old_sa)
331: {
332: proposal->set_spi(proposal, id->get_initiator_spi(id));
333: }
334: /* move the selected DH group to the front of the proposal */
335: if (!proposal->promote_dh_group(proposal, this->dh_group))
336: { /* the proposal does not include the group, move to the back */
337: proposal_list->remove_at(proposal_list, enumerator);
338: other_dh_groups->insert_last(other_dh_groups, proposal);
339: }
340: }
341: enumerator->destroy(enumerator);
342: /* add proposals that don't contain the selected group */
343: enumerator = other_dh_groups->create_enumerator(other_dh_groups);
344: while (enumerator->enumerate(enumerator, (void**)&proposal))
345: { /* no need to remove from the list as we destroy it anyway*/
346: proposal_list->insert_last(proposal_list, proposal);
347: }
348: enumerator->destroy(enumerator);
349: other_dh_groups->destroy(other_dh_groups);
350:
351: sa_payload = sa_payload_create_from_proposals_v2(proposal_list);
352: proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
353: }
354: else
355: {
356: if (this->old_sa)
357: {
358: /* include SPI of new IKE_SA when we are rekeying */
359: this->proposal->set_spi(this->proposal, id->get_responder_spi(id));
360: }
361: sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
362: }
363: message->add_payload(message, (payload_t*)sa_payload);
364:
365: ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
366: this->dh);
367: if (!ke_payload)
368: {
369: DBG1(DBG_IKE, "creating KE payload failed");
370: return FALSE;
371: }
372: nonce_payload = nonce_payload_create(PLV2_NONCE);
373: nonce_payload->set_nonce(nonce_payload, this->my_nonce);
374:
375: if (this->old_sa)
376: { /* payload order differs if we are rekeying */
377: message->add_payload(message, (payload_t*)nonce_payload);
378: message->add_payload(message, (payload_t*)ke_payload);
379: }
380: else
381: {
382: message->add_payload(message, (payload_t*)ke_payload);
383: message->add_payload(message, (payload_t*)nonce_payload);
384: }
385:
386: /* negotiate fragmentation if we are not rekeying */
387: if (!this->old_sa &&
388: ike_cfg->fragmentation(ike_cfg) != FRAGMENTATION_NO)
389: {
390: if (this->initiator ||
391: this->ike_sa->supports_extension(this->ike_sa,
392: EXT_IKE_FRAGMENTATION))
393: {
394: message->add_notify(message, FALSE, FRAGMENTATION_SUPPORTED,
395: chunk_empty);
396: }
397: }
398: /* submit supported hash algorithms for signature authentication */
399: if (!this->old_sa && this->signature_authentication)
400: {
401: if (this->initiator ||
402: this->ike_sa->supports_extension(this->ike_sa,
403: EXT_SIGNATURE_AUTH))
404: {
405: send_supported_hash_algorithms(this, message);
406: }
407: }
408: /* notify other peer if we support redirection */
409: if (!this->old_sa && this->initiator && this->follow_redirects)
410: {
411: identification_t *gateway;
412: host_t *from;
413: chunk_t data;
414:
415: from = this->ike_sa->get_redirected_from(this->ike_sa);
416: if (from)
417: {
418: gateway = identification_create_from_sockaddr(
419: from->get_sockaddr(from));
420: data = redirect_data_create(gateway, chunk_empty);
421: message->add_notify(message, FALSE, REDIRECTED_FROM, data);
422: chunk_free(&data);
423: gateway->destroy(gateway);
424: }
425: else
426: {
427: message->add_notify(message, FALSE, REDIRECT_SUPPORTED,
428: chunk_empty);
429: }
430: }
431: /* notify the peer if we want to use/support PPK */
432: if (!this->old_sa && send_use_ppk(this))
433: {
434: message->add_notify(message, FALSE, USE_PPK, chunk_empty);
435: }
436: /* notify the peer if we accept childless IKE_SAs */
437: if (!this->old_sa && !this->initiator &&
438: ike_cfg->childless(ike_cfg) != CHILDLESS_NEVER)
439: {
440: message->add_notify(message, FALSE, CHILDLESS_IKEV2_SUPPORTED,
441: chunk_empty);
442: }
443: return TRUE;
444: }
445:
446: /**
447: * Process the SA payload and select a proposal
448: */
449: static void process_sa_payload(private_ike_init_t *this, message_t *message,
450: sa_payload_t *sa_payload)
451: {
452: ike_cfg_t *ike_cfg, *cfg, *alt_cfg = NULL;
453: enumerator_t *enumerator;
454: linked_list_t *proposal_list;
455: host_t *me, *other;
456: proposal_selection_flag_t flags = 0;
457:
458: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
459:
460: proposal_list = sa_payload->get_proposals(sa_payload);
461: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
462: !lib->settings->get_bool(lib->settings, "%s.accept_private_algs",
463: FALSE, lib->ns))
464: {
465: flags |= PROPOSAL_SKIP_PRIVATE;
466: }
467: if (!lib->settings->get_bool(lib->settings,
468: "%s.prefer_configured_proposals", TRUE, lib->ns))
469: {
470: flags |= PROPOSAL_PREFER_SUPPLIED;
471: }
472: this->proposal = ike_cfg->select_proposal(ike_cfg, proposal_list, flags);
473: if (!this->proposal)
474: {
475: if (!this->initiator && !this->old_sa)
476: {
477: me = message->get_destination(message);
478: other = message->get_source(message);
479: enumerator = charon->backends->create_ike_cfg_enumerator(
480: charon->backends, me, other, IKEV2);
481: while (enumerator->enumerate(enumerator, &cfg))
482: {
483: if (ike_cfg == cfg)
484: { /* already tried and failed */
485: continue;
486: }
487: DBG1(DBG_IKE, "no matching proposal found, trying alternative "
488: "config");
489: this->proposal = cfg->select_proposal(cfg, proposal_list,
490: flags);
491: if (this->proposal)
492: {
493: alt_cfg = cfg->get_ref(cfg);
494: break;
495: }
496: }
497: enumerator->destroy(enumerator);
498: }
499: if (alt_cfg)
500: {
501: this->ike_sa->set_ike_cfg(this->ike_sa, alt_cfg);
502: alt_cfg->destroy(alt_cfg);
503: }
504: else
505: {
506: charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE,
507: proposal_list);
508: }
509: }
510: proposal_list->destroy_offset(proposal_list,
511: offsetof(proposal_t, destroy));
512: }
513:
514: /**
515: * Read payloads from message
516: */
517: static void process_payloads(private_ike_init_t *this, message_t *message)
518: {
519: enumerator_t *enumerator;
520: payload_t *payload;
521: ke_payload_t *ke_payload = NULL;
522:
523: enumerator = message->create_payload_enumerator(message);
524: while (enumerator->enumerate(enumerator, &payload))
525: {
526: switch (payload->get_type(payload))
527: {
528: case PLV2_SECURITY_ASSOCIATION:
529: {
530: process_sa_payload(this, message, (sa_payload_t*)payload);
531: break;
532: }
533: case PLV2_KEY_EXCHANGE:
534: {
535: ke_payload = (ke_payload_t*)payload;
536:
537: this->dh_group = ke_payload->get_dh_group_number(ke_payload);
538: break;
539: }
540: case PLV2_NONCE:
541: {
542: nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
543:
544: this->other_nonce = nonce_payload->get_nonce(nonce_payload);
545: break;
546: }
547: case PLV2_NOTIFY:
548: {
549: notify_payload_t *notify = (notify_payload_t*)payload;
550:
551: switch (notify->get_notify_type(notify))
552: {
553: case FRAGMENTATION_SUPPORTED:
554: this->ike_sa->enable_extension(this->ike_sa,
555: EXT_IKE_FRAGMENTATION);
556: break;
557: case SIGNATURE_HASH_ALGORITHMS:
558: if (this->signature_authentication)
559: {
560: handle_supported_hash_algorithms(this, notify);
561: }
562: break;
563: case USE_PPK:
564: if (!this->old_sa)
565: {
566: this->ike_sa->enable_extension(this->ike_sa,
567: EXT_PPK);
568: }
569: break;
570: case REDIRECTED_FROM:
571: {
572: identification_t *gateway;
573: chunk_t data;
574:
575: data = notify->get_notification_data(notify);
576: gateway = redirect_data_parse(data, NULL);
577: if (!gateway)
578: {
579: DBG1(DBG_IKE, "received invalid REDIRECTED_FROM "
580: "notify, ignored");
581: break;
582: }
583: DBG1(DBG_IKE, "client got redirected from %Y", gateway);
584: gateway->destroy(gateway);
585: /* fall-through */
586: }
587: case REDIRECT_SUPPORTED:
588: if (!this->old_sa)
589: {
590: this->ike_sa->enable_extension(this->ike_sa,
591: EXT_IKE_REDIRECTION);
592: }
593: break;
594: case CHILDLESS_IKEV2_SUPPORTED:
595: if (this->initiator && !this->old_sa)
596: {
597: this->ike_sa->enable_extension(this->ike_sa,
598: EXT_IKE_CHILDLESS);
599: }
600: break;
601: default:
602: /* other notifies are handled elsewhere */
603: break;
604: }
605:
606: }
607: default:
608: break;
609: }
610: }
611: enumerator->destroy(enumerator);
612:
613: if (this->proposal)
614: {
615: this->ike_sa->set_proposal(this->ike_sa, this->proposal);
616: }
617:
618: if (ke_payload && this->proposal &&
619: this->proposal->has_dh_group(this->proposal, this->dh_group))
620: {
621: if (!this->initiator)
622: {
623: this->dh = this->keymat->keymat.create_dh(
624: &this->keymat->keymat, this->dh_group);
625: }
626: else if (this->dh)
627: {
628: this->dh_failed = this->dh->get_dh_group(this->dh) != this->dh_group;
629: }
630: if (this->dh && !this->dh_failed)
631: {
632: this->dh_failed = !this->dh->set_other_public_value(this->dh,
633: ke_payload->get_key_exchange_data(ke_payload));
634: }
635: }
636: }
637:
638: METHOD(task_t, build_i, status_t,
639: private_ike_init_t *this, message_t *message)
640: {
641: ike_cfg_t *ike_cfg;
642:
643: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
644:
645: DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
646: this->ike_sa->get_name(this->ike_sa),
647: this->ike_sa->get_unique_id(this->ike_sa),
648: this->ike_sa->get_other_host(this->ike_sa));
649: this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
650:
651: if (this->retry >= MAX_RETRIES)
652: {
653: DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES);
654: return FAILED;
655: }
656:
657: /* if we are retrying after an INVALID_KE_PAYLOAD we already have one */
658: if (!this->dh)
659: {
660: if (this->old_sa && lib->settings->get_bool(lib->settings,
661: "%s.prefer_previous_dh_group", TRUE, lib->ns))
662: { /* reuse the DH group we used for the old IKE_SA when rekeying */
663: proposal_t *proposal;
664: uint16_t dh_group;
665:
666: proposal = this->old_sa->get_proposal(this->old_sa);
667: if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
668: &dh_group, NULL))
669: {
670: this->dh_group = dh_group;
671: }
672: else
673: { /* this shouldn't happen, but let's be safe */
674: this->dh_group = ike_cfg->get_dh_group(ike_cfg);
675: }
676: }
677: else
678: {
679: this->dh_group = ike_cfg->get_dh_group(ike_cfg);
680: }
681: this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
682: this->dh_group);
683: if (!this->dh)
684: {
685: DBG1(DBG_IKE, "configured DH group %N not supported",
686: diffie_hellman_group_names, this->dh_group);
687: return FAILED;
688: }
689: }
690: else if (this->dh->get_dh_group(this->dh) != this->dh_group)
691: { /* reset DH instance if group changed (INVALID_KE_PAYLOAD) */
692: this->dh->destroy(this->dh);
693: this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
694: this->dh_group);
695: if (!this->dh)
696: {
697: DBG1(DBG_IKE, "requested DH group %N not supported",
698: diffie_hellman_group_names, this->dh_group);
699: return FAILED;
700: }
701: }
702:
703: /* generate nonce only when we are trying the first time */
704: if (this->my_nonce.ptr == NULL)
705: {
706: if (!generate_nonce(this))
707: {
708: return FAILED;
709: }
710: }
711:
712: if (this->cookie.ptr)
713: {
714: message->add_notify(message, FALSE, COOKIE, this->cookie);
715: }
716:
717: if (!build_payloads(this, message))
718: {
719: return FAILED;
720: }
721:
722: #ifdef ME
723: {
724: chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
725: if (connect_id.ptr)
726: {
727: message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
728: }
729: }
730: #endif /* ME */
731:
732: return NEED_MORE;
733: }
734:
735: METHOD(task_t, process_r, status_t,
736: private_ike_init_t *this, message_t *message)
737: {
738: DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
739: this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
740:
741: if (!generate_nonce(this))
742: {
743: return FAILED;
744: }
745:
746: #ifdef ME
747: {
748: notify_payload_t *notify = message->get_notify(message, ME_CONNECTID);
749: if (notify)
750: {
751: chunk_t connect_id = notify->get_notification_data(notify);
752: DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
753: charon->connect_manager->stop_checks(charon->connect_manager,
754: connect_id);
755: }
756: }
757: #endif /* ME */
758:
759: process_payloads(this, message);
760:
761: return NEED_MORE;
762: }
763:
764: /**
765: * Derive the keymat for the IKE_SA
766: */
767: static bool derive_keys(private_ike_init_t *this,
768: chunk_t nonce_i, chunk_t nonce_r)
769: {
770: keymat_v2_t *old_keymat;
771: pseudo_random_function_t prf_alg = PRF_UNDEFINED;
772: chunk_t skd = chunk_empty;
773: ike_sa_id_t *id;
774:
775: id = this->ike_sa->get_id(this->ike_sa);
776: if (this->old_sa)
777: {
778: /* rekeying: Include old SKd, use old PRF, apply SPI */
779: old_keymat = (keymat_v2_t*)this->old_sa->get_keymat(this->old_sa);
780: prf_alg = old_keymat->get_skd(old_keymat, &skd);
781: if (this->initiator)
782: {
783: id->set_responder_spi(id, this->proposal->get_spi(this->proposal));
784: }
785: else
786: {
787: id->set_initiator_spi(id, this->proposal->get_spi(this->proposal));
788: }
789: }
790: if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
791: nonce_i, nonce_r, id, prf_alg, skd))
792: {
793: return FALSE;
794: }
795: charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, chunk_empty,
796: nonce_i, nonce_r, this->old_sa, NULL, AUTH_NONE);
797: return TRUE;
798: }
799:
800: METHOD(task_t, build_r, status_t,
801: private_ike_init_t *this, message_t *message)
802: {
803: identification_t *gateway;
804:
805: /* check if we have everything we need */
806: if (this->proposal == NULL ||
807: this->other_nonce.len == 0 || this->my_nonce.len == 0)
808: {
809: DBG1(DBG_IKE, "received proposals unacceptable");
810: message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
811: return FAILED;
812: }
813:
814: /* check if we'd have to redirect the client */
815: if (!this->old_sa &&
816: this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
817: charon->redirect->redirect_on_init(charon->redirect, this->ike_sa,
818: &gateway))
819: {
820: chunk_t data;
821:
822: DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
823: data = redirect_data_create(gateway, this->other_nonce);
824: message->add_notify(message, TRUE, REDIRECT, data);
825: gateway->destroy(gateway);
826: chunk_free(&data);
827: return FAILED;
828: }
829:
830: if (this->dh == NULL ||
831: !this->proposal->has_dh_group(this->proposal, this->dh_group))
832: {
833: uint16_t group;
834:
835: if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
836: &group, NULL))
837: {
838: DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
839: diffie_hellman_group_names, this->dh_group,
840: diffie_hellman_group_names, group);
841: this->dh_group = group;
842: group = htons(group);
843: message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
844: chunk_from_thing(group));
845: }
846: else
847: {
848: DBG1(DBG_IKE, "no acceptable proposal found");
849: message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
850: }
851: return FAILED;
852: }
853:
854: if (this->dh_failed)
855: {
856: DBG1(DBG_IKE, "applying DH public value failed");
857: message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
858: return FAILED;
859: }
860:
861: if (!derive_keys(this, this->other_nonce, this->my_nonce))
862: {
863: DBG1(DBG_IKE, "key derivation failed");
864: message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
865: return FAILED;
866: }
867: if (!build_payloads(this, message))
868: {
869: message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
870: return FAILED;
871: }
872: return SUCCESS;
873: }
874:
875: /**
876: * Raise alerts for received notify errors
877: */
878: static void raise_alerts(private_ike_init_t *this, notify_type_t type)
879: {
880: ike_cfg_t *ike_cfg;
881: linked_list_t *list;
882:
883: switch (type)
884: {
885: case NO_PROPOSAL_CHOSEN:
886: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
887: list = ike_cfg->get_proposals(ike_cfg);
888: charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE, list);
889: list->destroy_offset(list, offsetof(proposal_t, destroy));
890: break;
891: default:
892: break;
893: }
894: }
895:
896: METHOD(task_t, pre_process_i, status_t,
897: private_ike_init_t *this, message_t *message)
898: {
899: enumerator_t *enumerator;
900: payload_t *payload;
901:
902: /* check for erroneous notifies */
903: enumerator = message->create_payload_enumerator(message);
904: while (enumerator->enumerate(enumerator, &payload))
905: {
906: if (payload->get_type(payload) == PLV2_NOTIFY)
907: {
908: notify_payload_t *notify = (notify_payload_t*)payload;
909: notify_type_t type = notify->get_notify_type(notify);
910:
911: switch (type)
912: {
913: case COOKIE:
914: {
915: chunk_t cookie;
916:
917: cookie = notify->get_notification_data(notify);
918: if (chunk_equals(cookie, this->cookie))
919: {
920: DBG1(DBG_IKE, "ignore response with duplicate COOKIE "
921: "notify");
922: enumerator->destroy(enumerator);
923: return FAILED;
924: }
925: break;
926: }
927: case REDIRECT:
928: {
929: identification_t *gateway;
930: chunk_t data, nonce = chunk_empty;
931: status_t status = SUCCESS;
932:
933: if (this->old_sa)
934: {
935: break;
936: }
937: data = notify->get_notification_data(notify);
938: gateway = redirect_data_parse(data, &nonce);
939: if (!gateway || !chunk_equals(nonce, this->my_nonce))
940: {
941: DBG1(DBG_IKE, "received invalid REDIRECT notify");
942: status = FAILED;
943: }
944: DESTROY_IF(gateway);
945: chunk_free(&nonce);
946: enumerator->destroy(enumerator);
947: return status;
948: }
949: default:
950: break;
951: }
952: }
953: }
954: enumerator->destroy(enumerator);
955: return SUCCESS;
956: }
957:
958: METHOD(task_t, process_i, status_t,
959: private_ike_init_t *this, message_t *message)
960: {
961: enumerator_t *enumerator;
962: payload_t *payload;
963:
964: /* check for erroneous notifies */
965: enumerator = message->create_payload_enumerator(message);
966: while (enumerator->enumerate(enumerator, &payload))
967: {
968: if (payload->get_type(payload) == PLV2_NOTIFY)
969: {
970: notify_payload_t *notify = (notify_payload_t*)payload;
971: notify_type_t type = notify->get_notify_type(notify);
972:
973: switch (type)
974: {
975: case INVALID_KE_PAYLOAD:
976: {
977: chunk_t data;
978: diffie_hellman_group_t bad_group;
979:
980: bad_group = this->dh_group;
981: data = notify->get_notification_data(notify);
982: this->dh_group = ntohs(*((uint16_t*)data.ptr));
983: DBG1(DBG_IKE, "peer didn't accept DH group %N, "
984: "it requested %N", diffie_hellman_group_names,
985: bad_group, diffie_hellman_group_names, this->dh_group);
986:
987: if (this->old_sa == NULL)
988: { /* reset the IKE_SA if we are not rekeying */
989: this->ike_sa->reset(this->ike_sa, FALSE);
990: }
991:
992: enumerator->destroy(enumerator);
993: this->retry++;
994: return NEED_MORE;
995: }
996: case NAT_DETECTION_SOURCE_IP:
997: case NAT_DETECTION_DESTINATION_IP:
998: /* skip, handled in ike_natd_t */
999: break;
1000: case MULTIPLE_AUTH_SUPPORTED:
1001: /* handled in ike_auth_t */
1002: break;
1003: case COOKIE:
1004: {
1005: chunk_free(&this->cookie);
1006: this->cookie = chunk_clone(notify->get_notification_data(notify));
1007: this->ike_sa->reset(this->ike_sa, FALSE);
1008: enumerator->destroy(enumerator);
1009: DBG2(DBG_IKE, "received %N notify", notify_type_names, type);
1010: this->retry++;
1011: return NEED_MORE;
1012: }
1013: case REDIRECT:
1014: {
1015: identification_t *gateway;
1016: chunk_t data, nonce = chunk_empty;
1017: status_t status = FAILED;
1018:
1019: if (this->old_sa)
1020: {
1021: DBG1(DBG_IKE, "received REDIRECT notify during rekeying"
1022: ", ignored");
1023: break;
1024: }
1025: data = notify->get_notification_data(notify);
1026: gateway = redirect_data_parse(data, &nonce);
1027: if (this->ike_sa->handle_redirect(this->ike_sa, gateway))
1028: {
1029: status = NEED_MORE;
1030: }
1031: DESTROY_IF(gateway);
1032: chunk_free(&nonce);
1033: enumerator->destroy(enumerator);
1034: return status;
1035: }
1036: default:
1037: {
1038: if (type <= 16383)
1039: {
1040: DBG1(DBG_IKE, "received %N notify error",
1041: notify_type_names, type);
1042: enumerator->destroy(enumerator);
1043: raise_alerts(this, type);
1044: return FAILED;
1045: }
1046: DBG2(DBG_IKE, "received %N notify",
1047: notify_type_names, type);
1048: break;
1049: }
1050: }
1051: }
1052: }
1053: enumerator->destroy(enumerator);
1054:
1055: process_payloads(this, message);
1056:
1057: /* check if we have everything */
1058: if (this->proposal == NULL ||
1059: this->other_nonce.len == 0 || this->my_nonce.len == 0)
1060: {
1061: DBG1(DBG_IKE, "peers proposal selection invalid");
1062: return FAILED;
1063: }
1064:
1065: if (this->dh == NULL ||
1066: !this->proposal->has_dh_group(this->proposal, this->dh_group))
1067: {
1068: DBG1(DBG_IKE, "peer DH group selection invalid");
1069: return FAILED;
1070: }
1071:
1072: if (this->dh_failed)
1073: {
1074: DBG1(DBG_IKE, "applying DH public value failed");
1075: return FAILED;
1076: }
1077:
1078: if (!derive_keys(this, this->my_nonce, this->other_nonce))
1079: {
1080: DBG1(DBG_IKE, "key derivation failed");
1081: return FAILED;
1082: }
1083: return SUCCESS;
1084: }
1085:
1086: METHOD(task_t, get_type, task_type_t,
1087: private_ike_init_t *this)
1088: {
1089: return TASK_IKE_INIT;
1090: }
1091:
1092: METHOD(task_t, migrate, void,
1093: private_ike_init_t *this, ike_sa_t *ike_sa)
1094: {
1095: DESTROY_IF(this->proposal);
1096: chunk_free(&this->other_nonce);
1097:
1098: this->ike_sa = ike_sa;
1099: this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
1100: this->proposal = NULL;
1101: this->dh_failed = FALSE;
1102: }
1103:
1104: METHOD(task_t, destroy, void,
1105: private_ike_init_t *this)
1106: {
1107: DESTROY_IF(this->dh);
1108: DESTROY_IF(this->proposal);
1109: DESTROY_IF(this->nonceg);
1110: chunk_free(&this->my_nonce);
1111: chunk_free(&this->other_nonce);
1112: chunk_free(&this->cookie);
1113: free(this);
1114: }
1115:
1116: METHOD(ike_init_t, get_lower_nonce, chunk_t,
1117: private_ike_init_t *this)
1118: {
1119: if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1120: min(this->my_nonce.len, this->other_nonce.len)) < 0)
1121: {
1122: return this->my_nonce;
1123: }
1124: else
1125: {
1126: return this->other_nonce;
1127: }
1128: }
1129:
1130: /*
1131: * Described in header.
1132: */
1133: ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
1134: {
1135: private_ike_init_t *this;
1136:
1137: INIT(this,
1138: .public = {
1139: .task = {
1140: .get_type = _get_type,
1141: .migrate = _migrate,
1142: .destroy = _destroy,
1143: },
1144: .get_lower_nonce = _get_lower_nonce,
1145: },
1146: .ike_sa = ike_sa,
1147: .initiator = initiator,
1148: .dh_group = MODP_NONE,
1149: .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
1150: .old_sa = old_sa,
1151: .signature_authentication = lib->settings->get_bool(lib->settings,
1152: "%s.signature_authentication", TRUE, lib->ns),
1153: .follow_redirects = lib->settings->get_bool(lib->settings,
1154: "%s.follow_redirects", TRUE, lib->ns),
1155: );
1156: this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
1157:
1158: if (initiator)
1159: {
1160: this->public.task.build = _build_i;
1161: this->public.task.process = _process_i;
1162: this->public.task.pre_process = _pre_process_i;
1163: }
1164: else
1165: {
1166: this->public.task.build = _build_r;
1167: this->public.task.process = _process_r;
1168: }
1169: return &this->public;
1170: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>