Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/quick_mode.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-2019 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2011 Martin Willi
6: * Copyright (C) 2011 revosec AG
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public License as published by the
10: * Free Software Foundation; either version 2 of the License, or (at your
11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12: *
13: * This program is distributed in the hope that it will be useful, but
14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16: * for more details.
17: */
18:
19: /*
20: * Copyright (C) 2012 Volker RĂ¼melin
21: *
22: * Permission is hereby granted, free of charge, to any person obtaining a copy
23: * of this software and associated documentation files (the "Software"), to deal
24: * in the Software without restriction, including without limitation the rights
25: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26: * copies of the Software, and to permit persons to whom the Software is
27: * furnished to do so, subject to the following conditions:
28: *
29: * The above copyright notice and this permission notice shall be included in
30: * all copies or substantial portions of the Software.
31: *
32: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38: * THE SOFTWARE.
39: */
40:
41: #include "quick_mode.h"
42:
43: #include <string.h>
44:
45: #include <daemon.h>
46: #include <sa/ikev1/keymat_v1.h>
47: #include <encoding/payloads/sa_payload.h>
48: #include <encoding/payloads/nonce_payload.h>
49: #include <encoding/payloads/ke_payload.h>
50: #include <encoding/payloads/id_payload.h>
51: #include <encoding/payloads/payload.h>
52: #include <sa/ikev1/tasks/informational.h>
53: #include <sa/ikev1/tasks/quick_delete.h>
54: #include <processing/jobs/inactivity_job.h>
55:
56: typedef struct private_quick_mode_t private_quick_mode_t;
57:
58: /**
59: * Private members of a quick_mode_t task.
60: */
61: struct private_quick_mode_t {
62:
63: /**
64: * Public methods and task_t interface.
65: */
66: quick_mode_t public;
67:
68: /**
69: * Assigned IKE_SA.
70: */
71: ike_sa_t *ike_sa;
72:
73: /**
74: * TRUE if we are initiating quick mode
75: */
76: bool initiator;
77:
78: /**
79: * Traffic selector of initiator
80: */
81: traffic_selector_t *tsi;
82:
83: /**
84: * Traffic selector of responder
85: */
86: traffic_selector_t *tsr;
87:
88: /**
89: * Initiators nonce
90: */
91: chunk_t nonce_i;
92:
93: /**
94: * Responder nonce
95: */
96: chunk_t nonce_r;
97:
98: /**
99: * Initiators ESP SPI
100: */
101: uint32_t spi_i;
102:
103: /**
104: * Responder ESP SPI
105: */
106: uint32_t spi_r;
107:
108: /**
109: * Initiators IPComp CPI
110: */
111: uint16_t cpi_i;
112:
113: /**
114: * Responders IPComp CPI
115: */
116: uint16_t cpi_r;
117:
118: /**
119: * selected CHILD_SA proposal
120: */
121: proposal_t *proposal;
122:
123: /**
124: * Config of CHILD_SA to establish
125: */
126: child_cfg_t *config;
127:
128: /**
129: * CHILD_SA we are about to establish
130: */
131: child_sa_t *child_sa;
132:
133: /**
134: * IKEv1 keymat
135: */
136: keymat_v1_t *keymat;
137:
138: /**
139: * DH exchange, when PFS is in use
140: */
141: diffie_hellman_t *dh;
142:
143: /**
144: * Negotiated lifetime of new SA
145: */
146: uint32_t lifetime;
147:
148: /**
149: * Negotiated lifebytes of new SA
150: */
151: uint64_t lifebytes;
152:
153: /**
154: * Data collected to create the CHILD_SA
155: */
156: child_sa_create_t child;
157:
158: /**
159: * SPI of SA we rekey
160: */
161: uint32_t rekey;
162:
163: /**
164: * Delete old child after successful rekey
165: */
166: bool delete;
167:
168: /**
169: * Negotiated mode, tunnel or transport
170: */
171: ipsec_mode_t mode;
172:
173: /*
174: * SA protocol (ESP|AH) negotiated
175: */
176: protocol_id_t proto;
177:
178: /**
179: * Message ID of handled quick mode exchange
180: */
181: uint32_t mid;
182:
183: /** states of quick mode */
184: enum {
185: QM_INIT,
186: QM_NEGOTIATED,
187: } state;
188: };
189:
190: /**
191: * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
192: */
193: static void schedule_inactivity_timeout(private_quick_mode_t *this)
194: {
195: uint32_t timeout;
196: bool close_ike;
197:
198: timeout = this->config->get_inactivity(this->config);
199: if (timeout)
200: {
201: close_ike = lib->settings->get_bool(lib->settings,
202: "%s.inactivity_close_ike", FALSE, lib->ns);
203: lib->scheduler->schedule_job(lib->scheduler, (job_t*)
204: inactivity_job_create(this->child_sa->get_unique_id(this->child_sa),
205: timeout, close_ike), timeout);
206: }
207: }
208:
209: /**
210: * Check if we have a an address pool configured
211: */
212: static bool have_pool(ike_sa_t *ike_sa)
213: {
214: enumerator_t *enumerator;
215: peer_cfg_t *peer_cfg;
216: char *pool;
217: bool found = FALSE;
218:
219: peer_cfg = ike_sa->get_peer_cfg(ike_sa);
220: if (peer_cfg)
221: {
222: enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
223: if (enumerator->enumerate(enumerator, &pool))
224: {
225: found = TRUE;
226: }
227: enumerator->destroy(enumerator);
228: }
229: return found;
230: }
231:
232: /**
233: * Get hosts to use for dynamic traffic selectors
234: */
235: static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
236: {
237: enumerator_t *enumerator;
238: linked_list_t *list;
239: host_t *host;
240:
241: list = linked_list_create();
242: enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
243: while (enumerator->enumerate(enumerator, &host))
244: {
245: list->insert_last(list, host);
246: }
247: enumerator->destroy(enumerator);
248:
249: if (list->get_count(list) == 0)
250: { /* no virtual IPs assigned */
251: if (local)
252: {
253: host = ike_sa->get_my_host(ike_sa);
254: list->insert_last(list, host);
255: }
256: else if (!have_pool(ike_sa))
257: { /* use host only if we don't have a pool configured */
258: host = ike_sa->get_other_host(ike_sa);
259: list->insert_last(list, host);
260: }
261: }
262: return list;
263: }
264:
265: /**
266: * Install negotiated CHILD_SA
267: */
268: static bool install(private_quick_mode_t *this)
269: {
270: status_t status, status_i, status_o;
271: chunk_t encr_i, encr_r, integ_i, integ_r;
272: linked_list_t *tsi, *tsr, *my_ts, *other_ts;
273: child_sa_t *old = NULL;
274:
275: this->child_sa->set_proposal(this->child_sa, this->proposal);
276: this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
277: this->child_sa->set_mode(this->child_sa, this->mode);
278:
279: if (this->cpi_i && this->cpi_r)
280: { /* DEFLATE is the only transform we currently support */
281: this->child_sa->set_ipcomp(this->child_sa, IPCOMP_DEFLATE);
282: }
283: else
284: {
285: this->cpi_i = this->cpi_r = 0;
286: }
287:
288: this->child_sa->set_protocol(this->child_sa,
289: this->proposal->get_protocol(this->proposal));
290:
291: status_i = status_o = FAILED;
292: encr_i = encr_r = integ_i = integ_r = chunk_empty;
293: tsi = linked_list_create_with_items(this->tsi->clone(this->tsi), NULL);
294: tsr = linked_list_create_with_items(this->tsr->clone(this->tsr), NULL);
295: if (this->initiator)
296: {
297: charon->bus->narrow(charon->bus, this->child_sa,
298: NARROW_INITIATOR_POST_AUTH, tsi, tsr);
299: }
300: else
301: {
302: charon->bus->narrow(charon->bus, this->child_sa,
303: NARROW_RESPONDER_POST, tsr, tsi);
304: }
305: if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0)
306: {
307: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
308: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
309: DBG1(DBG_IKE, "no acceptable traffic selectors found");
310: return FALSE;
311: }
312:
313: if (this->initiator)
314: {
315: this->child_sa->set_policies(this->child_sa, tsi, tsr);
316: }
317: else
318: {
319: this->child_sa->set_policies(this->child_sa, tsr, tsi);
320: }
321: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
322: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
323:
324: if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
325: this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
326: &encr_i, &integ_i, &encr_r, &integ_r))
327: {
328: if (this->initiator)
329: {
330: status_i = this->child_sa->install(this->child_sa,
331: encr_r, integ_r, this->spi_i, this->cpi_i,
332: this->initiator, TRUE, FALSE);
333: status_o = this->child_sa->install(this->child_sa,
334: encr_i, integ_i, this->spi_r, this->cpi_r,
335: this->initiator, FALSE, FALSE);
336: }
337: else
338: {
339: status_i = this->child_sa->install(this->child_sa,
340: encr_i, integ_i, this->spi_r, this->cpi_r,
341: this->initiator, TRUE, FALSE);
342: status_o = this->child_sa->install(this->child_sa,
343: encr_r, integ_r, this->spi_i, this->cpi_i,
344: this->initiator, FALSE, FALSE);
345: }
346: }
347:
348: if (status_i != SUCCESS || status_o != SUCCESS)
349: {
350: DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
351: (status_i != SUCCESS) ? "inbound " : "",
352: (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
353: (status_o != SUCCESS) ? "outbound " : "");
354: status = FAILED;
355: }
356: else
357: {
358: status = this->child_sa->install_policies(this->child_sa);
359:
360: if (status != SUCCESS)
361: {
362: DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
363: }
364: else
365: {
366: charon->bus->child_derived_keys(charon->bus, this->child_sa,
367: this->initiator, encr_i, encr_r,
368: integ_i, integ_r);
369: }
370: }
371: chunk_clear(&integ_i);
372: chunk_clear(&integ_r);
373: chunk_clear(&encr_i);
374: chunk_clear(&encr_r);
375:
376: if (status != SUCCESS)
377: {
378: return FALSE;
379: }
380:
381: charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
382: this->dh, this->nonce_i, this->nonce_r);
383:
384: my_ts = linked_list_create_from_enumerator(
385: this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
386: other_ts = linked_list_create_from_enumerator(
387: this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
388:
389: DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
390: "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
391: this->child_sa->get_name(this->child_sa),
392: this->child_sa->get_unique_id(this->child_sa),
393: ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
394: ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts);
395:
396: my_ts->destroy(my_ts);
397: other_ts->destroy(other_ts);
398:
399: this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
400: this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
401:
402: if (this->rekey)
403: {
404: old = this->ike_sa->get_child_sa(this->ike_sa,
405: this->proposal->get_protocol(this->proposal),
406: this->rekey, TRUE);
407: }
408: if (old)
409: {
410: charon->bus->child_rekey(charon->bus, old, this->child_sa);
411: /* rekeyed CHILD_SAs stay installed until they expire or are deleted
412: * by the other peer */
413: old->set_state(old, CHILD_REKEYED);
414: /* as initiator we delete the CHILD_SA if configured to do so */
415: if (this->initiator && this->delete)
416: {
417: this->ike_sa->queue_task(this->ike_sa,
418: (task_t*)quick_delete_create(this->ike_sa,
419: this->proposal->get_protocol(this->proposal),
420: this->rekey, TRUE, FALSE));
421: }
422: }
423: else
424: {
425: charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
426: }
427: schedule_inactivity_timeout(this);
428: this->child_sa = NULL;
429: return TRUE;
430: }
431:
432: /**
433: * Generate and add NONCE
434: */
435: static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
436: message_t *message)
437: {
438: nonce_payload_t *nonce_payload;
439: nonce_gen_t *nonceg;
440:
441: nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
442: if (!nonceg)
443: {
444: DBG1(DBG_IKE, "no nonce generator found to create nonce");
445: return FALSE;
446: }
447: if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce))
448: {
449: DBG1(DBG_IKE, "nonce allocation failed");
450: nonceg->destroy(nonceg);
451: return FALSE;
452: }
453: nonceg->destroy(nonceg);
454:
455: nonce_payload = nonce_payload_create(PLV1_NONCE);
456: nonce_payload->set_nonce(nonce_payload, *nonce);
457: message->add_payload(message, &nonce_payload->payload_interface);
458:
459: return TRUE;
460: }
461:
462: /**
463: * Extract nonce from NONCE payload
464: */
465: static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
466: message_t *message)
467: {
468: nonce_payload_t *nonce_payload;
469:
470: nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
471: if (!nonce_payload)
472: {
473: DBG1(DBG_IKE, "NONCE payload missing in message");
474: return FALSE;
475: }
476: *nonce = nonce_payload->get_nonce(nonce_payload);
477:
478: return TRUE;
479: }
480:
481: /**
482: * Add KE payload to message
483: */
484: static bool add_ke(private_quick_mode_t *this, message_t *message)
485: {
486: ke_payload_t *ke_payload;
487:
488: ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
489: this->dh);
490: if (!ke_payload)
491: {
492: DBG1(DBG_IKE, "creating KE payload failed");
493: return FALSE;
494: }
495: message->add_payload(message, &ke_payload->payload_interface);
496: return TRUE;
497: }
498:
499: /**
500: * Get DH value from a KE payload
501: */
502: static bool get_ke(private_quick_mode_t *this, message_t *message)
503: {
504: ke_payload_t *ke_payload;
505:
506: ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
507: if (!ke_payload)
508: {
509: DBG1(DBG_IKE, "KE payload missing");
510: return FALSE;
511: }
512: if (!this->dh->set_other_public_value(this->dh,
513: ke_payload->get_key_exchange_data(ke_payload)))
514: {
515: DBG1(DBG_IKE, "unable to apply received KE value");
516: return FALSE;
517: }
518: return TRUE;
519: }
520:
521: /**
522: * Select a traffic selector from configuration
523: */
524: static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
525: linked_list_t *supplied)
526: {
527: traffic_selector_t *ts;
528: linked_list_t *list, *hosts;
529:
530: hosts = get_dynamic_hosts(this->ike_sa, local);
531: list = this->config->get_traffic_selectors(this->config,
532: local, supplied, hosts, TRUE);
533: hosts->destroy(hosts);
534: if (list->get_first(list, (void**)&ts) == SUCCESS)
535: {
536: ts = ts->clone(ts);
537: }
538: else
539: {
540: DBG1(DBG_IKE, "%s traffic selector missing in configuration",
541: local ? "local" : "remote");
542: ts = NULL;
543: }
544: list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
545: return ts;
546: }
547:
548: /**
549: * Add selected traffic selectors to message
550: */
551: static void add_ts(private_quick_mode_t *this, message_t *message)
552: {
553: id_payload_t *id_payload;
554:
555: id_payload = id_payload_create_from_ts(this->tsi);
556: message->add_payload(message, &id_payload->payload_interface);
557: id_payload = id_payload_create_from_ts(this->tsr);
558: message->add_payload(message, &id_payload->payload_interface);
559: }
560:
561: /**
562: * Get traffic selectors from received message
563: */
564: static bool get_ts(private_quick_mode_t *this, message_t *message)
565: {
566: traffic_selector_t *tsi = NULL, *tsr = NULL;
567: enumerator_t *enumerator;
568: id_payload_t *id_payload;
569: payload_t *payload;
570: host_t *hsi, *hsr;
571: bool first = TRUE;
572:
573: enumerator = message->create_payload_enumerator(message);
574: while (enumerator->enumerate(enumerator, &payload))
575: {
576: if (payload->get_type(payload) == PLV1_ID)
577: {
578: id_payload = (id_payload_t*)payload;
579:
580: if (first)
581: {
582: tsi = id_payload->get_ts(id_payload);
583: first = FALSE;
584: }
585: else
586: {
587: tsr = id_payload->get_ts(id_payload);
588: break;
589: }
590: }
591: }
592: enumerator->destroy(enumerator);
593:
594: /* create host2host selectors if ID payloads missing */
595: if (this->initiator)
596: {
597: hsi = this->ike_sa->get_my_host(this->ike_sa);
598: hsr = this->ike_sa->get_other_host(this->ike_sa);
599: }
600: else
601: {
602: hsr = this->ike_sa->get_my_host(this->ike_sa);
603: hsi = this->ike_sa->get_other_host(this->ike_sa);
604: }
605: if (!tsi)
606: {
607: tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
608: hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535);
609: }
610: if (!tsr)
611: {
612: tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
613: hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535);
614: }
615: if (this->mode == MODE_TRANSPORT && this->child.encap &&
616: (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
617: { /* change TS in case of a NAT in transport mode */
618: DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
619: tsi, tsr);
620: tsi->set_address(tsi, hsi);
621: tsr->set_address(tsr, hsr);
622: }
623:
624: if (this->initiator)
625: {
626: traffic_selector_t *tsisub, *tsrsub;
627:
628: /* check if peer selection is valid */
629: tsisub = this->tsi->get_subset(this->tsi, tsi);
630: tsrsub = this->tsr->get_subset(this->tsr, tsr);
631: if (!tsisub || !tsrsub)
632: {
633: DBG1(DBG_IKE, "peer selected invalid traffic selectors: "
634: "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
635: DESTROY_IF(tsisub);
636: DESTROY_IF(tsrsub);
637: tsi->destroy(tsi);
638: tsr->destroy(tsr);
639: return FALSE;
640: }
641: tsi->destroy(tsi);
642: tsr->destroy(tsr);
643: this->tsi->destroy(this->tsi);
644: this->tsr->destroy(this->tsr);
645: this->tsi = tsisub;
646: this->tsr = tsrsub;
647: }
648: else
649: {
650: this->tsi = tsi;
651: this->tsr = tsr;
652: }
653: return TRUE;
654: }
655:
656: /**
657: * Get encap
658: */
659: static encap_t get_encap(ike_sa_t* ike_sa, bool udp)
660: {
661: if (!udp)
662: {
663: return ENCAP_NONE;
664: }
665: if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
666: {
667: return ENCAP_UDP_DRAFT_00_03;
668: }
669: return ENCAP_UDP;
670: }
671:
672: /**
673: * Get NAT-OA payload type (RFC 3947 or RFC 3947 drafts).
674: */
675: static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
676: {
677: if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
678: {
679: return PLV1_NAT_OA_DRAFT_00_03;
680: }
681: return PLV1_NAT_OA;
682: }
683:
684: /**
685: * Add NAT-OA payloads
686: */
687: static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
688: {
689: identification_t *id;
690: id_payload_t *nat_oa;
691: host_t *init, *resp;
692: payload_type_t nat_oa_payload_type;
693:
694: if (this->initiator)
695: {
696: init = message->get_source(message);
697: resp = message->get_destination(message);
698: }
699: else
700: {
701: init = message->get_destination(message);
702: resp = message->get_source(message);
703: }
704:
705: nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
706:
707: /* first NAT-OA is the initiator's address */
708: id = identification_create_from_sockaddr(init->get_sockaddr(init));
709: nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
710: message->add_payload(message, (payload_t*)nat_oa);
711: id->destroy(id);
712:
713: /* second NAT-OA is that of the responder */
714: id = identification_create_from_sockaddr(resp->get_sockaddr(resp));
715: nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
716: message->add_payload(message, (payload_t*)nat_oa);
717: id->destroy(id);
718: }
719:
720: /**
721: * Look up lifetimes
722: */
723: static void get_lifetimes(private_quick_mode_t *this)
724: {
725: lifetime_cfg_t *lft;
726:
727: lft = this->config->get_lifetime(this->config, TRUE);
728: if (lft->time.life)
729: {
730: this->lifetime = lft->time.life;
731: }
732: if (lft->bytes.life)
733: {
734: this->lifebytes = lft->bytes.life;
735: }
736: free(lft);
737: }
738:
739: /**
740: * Check and apply lifetimes
741: */
742: static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
743: {
744: uint32_t lifetime;
745: uint64_t lifebytes;
746:
747: lifetime = sa_payload->get_lifetime(sa_payload, this->proposal);
748: lifebytes = sa_payload->get_lifebytes(sa_payload, this->proposal);
749: if (this->lifetime != lifetime)
750: {
751: DBG1(DBG_IKE, "received %us lifetime, configured %us",
752: lifetime, this->lifetime);
753: this->lifetime = lifetime;
754: }
755: if (this->lifebytes != lifebytes)
756: {
757: DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
758: lifebytes, this->lifebytes);
759: this->lifebytes = lifebytes;
760: }
761: }
762:
763: /**
764: * Set the task ready to build notify error message
765: */
766: static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
767: {
768: notify_payload_t *notify;
769:
770: notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
771: this->proto, type);
772: notify->set_spi(notify, this->spi_i);
773:
774: this->ike_sa->queue_task(this->ike_sa,
775: (task_t*)informational_create(this->ike_sa, notify));
776: /* cancel all active/passive tasks in favour of informational */
777: this->ike_sa->flush_queue(this->ike_sa,
778: this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
779: return ALREADY_DONE;
780: }
781:
782: /**
783: * Prepare a list of proposals from child_config containing only the specified
784: * DH group, unless it is set to MODP_NONE.
785: */
786: static linked_list_t *get_proposals(private_quick_mode_t *this,
787: diffie_hellman_group_t group)
788: {
789: linked_list_t *list;
790: proposal_t *proposal;
791: enumerator_t *enumerator;
792:
793: list = this->config->get_proposals(this->config, FALSE);
794: enumerator = list->create_enumerator(list);
795: while (enumerator->enumerate(enumerator, &proposal))
796: {
797: if (group != MODP_NONE)
798: {
799: if (!proposal->has_dh_group(proposal, group))
800: {
801: list->remove_at(list, enumerator);
802: proposal->destroy(proposal);
803: continue;
804: }
805: proposal->promote_dh_group(proposal, group);
806: }
807: proposal->set_spi(proposal, this->spi_i);
808: }
809: enumerator->destroy(enumerator);
810:
811: return list;
812: }
813:
814: METHOD(task_t, build_i, status_t,
815: private_quick_mode_t *this, message_t *message)
816: {
817: switch (this->state)
818: {
819: case QM_INIT:
820: {
821: sa_payload_t *sa_payload;
822: linked_list_t *list, *tsi, *tsr;
823: proposal_t *proposal;
824: diffie_hellman_group_t group;
825: encap_t encap;
826:
827: this->mode = this->config->get_mode(this->config);
828: this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa,
829: TRUE);
830: this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa,
831: FALSE);
832: this->child.encap = this->ike_sa->has_condition(this->ike_sa,
833: COND_NAT_ANY);
834: this->child_sa = child_sa_create(
835: this->ike_sa->get_my_host(this->ike_sa),
836: this->ike_sa->get_other_host(this->ike_sa),
837: this->config, &this->child);
838:
839: if (this->child.encap && this->mode == MODE_TRANSPORT)
840: {
841: /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
842: add_nat_oa_payloads(this, message);
843: }
844:
845: if (this->config->has_option(this->config, OPT_IPCOMP))
846: {
847: this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
848: if (!this->cpi_i)
849: {
850: DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
851: "IPComp disabled");
852: }
853: }
854:
855: list = this->config->get_proposals(this->config, FALSE);
856: if (list->get_first(list, (void**)&proposal) == SUCCESS)
857: {
858: this->proto = proposal->get_protocol(proposal);
859: }
860: list->destroy_offset(list, offsetof(proposal_t, destroy));
861: this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto);
862: if (!this->spi_i)
863: {
864: DBG1(DBG_IKE, "allocating SPI from kernel failed");
865: return FAILED;
866: }
867:
868: group = this->config->get_dh_group(this->config);
869: if (group != MODP_NONE)
870: {
871: proposal_t *proposal;
872: uint16_t preferred_group;
873:
874: proposal = this->ike_sa->get_proposal(this->ike_sa);
875: proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
876: &preferred_group, NULL);
877: /* try the negotiated DH group from IKE_SA */
878: list = get_proposals(this, preferred_group);
879: if (list->get_count(list))
880: {
881: group = preferred_group;
882: }
883: else
884: {
885: /* fall back to the first configured DH group */
886: list->destroy(list);
887: list = get_proposals(this, group);
888: }
889:
890: this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
891: group);
892: if (!this->dh)
893: {
894: DBG1(DBG_IKE, "configured DH group %N not supported",
895: diffie_hellman_group_names, group);
896: list->destroy_offset(list, offsetof(proposal_t, destroy));
897: return FAILED;
898: }
899: }
900: else
901: {
902: list = get_proposals(this, MODP_NONE);
903: }
904:
905: get_lifetimes(this);
906: encap = get_encap(this->ike_sa, this->child.encap);
907: sa_payload = sa_payload_create_from_proposals_v1(list,
908: this->lifetime, this->lifebytes, AUTH_NONE,
909: this->mode, encap, this->cpi_i);
910: list->destroy_offset(list, offsetof(proposal_t, destroy));
911: message->add_payload(message, &sa_payload->payload_interface);
912:
913: if (!add_nonce(this, &this->nonce_i, message))
914: {
915: return FAILED;
916: }
917: if (group != MODP_NONE)
918: {
919: if (!add_ke(this, message))
920: {
921: return FAILED;
922: }
923: }
924: if (!this->tsi)
925: {
926: this->tsi = select_ts(this, TRUE, NULL);
927: }
928: if (!this->tsr)
929: {
930: this->tsr = select_ts(this, FALSE, NULL);
931: }
932: tsi = linked_list_create_with_items(this->tsi, NULL);
933: tsr = linked_list_create_with_items(this->tsr, NULL);
934: this->tsi = this->tsr = NULL;
935: charon->bus->narrow(charon->bus, this->child_sa,
936: NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
937: tsi->remove_first(tsi, (void**)&this->tsi);
938: tsr->remove_first(tsr, (void**)&this->tsr);
939: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
940: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
941: if (!this->tsi || !this->tsr)
942: {
943: return FAILED;
944: }
945: add_ts(this, message);
946: return NEED_MORE;
947: }
948: case QM_NEGOTIATED:
949: {
950: return SUCCESS;
951: }
952: default:
953: return FAILED;
954: }
955: }
956:
957: /**
958: * Check for notify errors, return TRUE if error found
959: */
960: static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
961: {
962: enumerator_t *enumerator;
963: payload_t *payload;
964: bool err = FALSE;
965:
966: enumerator = message->create_payload_enumerator(message);
967: while (enumerator->enumerate(enumerator, &payload))
968: {
969: if (payload->get_type(payload) == PLV1_NOTIFY)
970: {
971: notify_payload_t *notify;
972: notify_type_t type;
973:
974: notify = (notify_payload_t*)payload;
975: type = notify->get_notify_type(notify);
976: if (type < 16384)
977: {
978:
979: DBG1(DBG_IKE, "received %N error notify",
980: notify_type_names, type);
981: err = TRUE;
982: }
983: else
984: {
985: DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
986: }
987: }
988: }
989: enumerator->destroy(enumerator);
990:
991: return err;
992: }
993:
994: /**
995: * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
996: */
997: static void check_for_rekeyed_child(private_quick_mode_t *this, bool responder)
998: {
999: enumerator_t *enumerator, *policies;
1000: traffic_selector_t *local, *remote, *my_ts, *other_ts;
1001: child_sa_t *child_sa;
1002: proposal_t *proposal;
1003: char *name;
1004:
1005: if (responder)
1006: {
1007: my_ts = this->tsr;
1008: other_ts = this->tsi;
1009: }
1010: else
1011: {
1012: my_ts = this->tsi;
1013: other_ts = this->tsr;
1014: }
1015:
1016: name = this->config->get_name(this->config);
1017: enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
1018: while (!this->child.reqid && enumerator->enumerate(enumerator, &child_sa))
1019: {
1020: if (streq(child_sa->get_name(child_sa), name))
1021: {
1022: proposal = child_sa->get_proposal(child_sa);
1023: switch (child_sa->get_state(child_sa))
1024: {
1025: case CHILD_INSTALLED:
1026: case CHILD_REKEYING:
1027: policies = child_sa->create_policy_enumerator(child_sa);
1028: if (policies->enumerate(policies, &local, &remote) &&
1029: local->equals(local, my_ts) &&
1030: remote->equals(remote, other_ts) &&
1031: this->proposal->equals(this->proposal, proposal))
1032: {
1033: this->rekey = child_sa->get_spi(child_sa, TRUE);
1034: this->child.reqid = child_sa->get_reqid(child_sa);
1035: this->child.mark_in = child_sa->get_mark(child_sa,
1036: TRUE).value;
1037: this->child.mark_out = child_sa->get_mark(child_sa,
1038: FALSE).value;
1039: this->child.if_id_in = child_sa->get_if_id(child_sa,
1040: TRUE);
1041: this->child.if_id_out = child_sa->get_if_id(child_sa,
1042: FALSE);
1043: child_sa->set_state(child_sa, CHILD_REKEYING);
1044: DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
1045: child_sa->get_name(child_sa),
1046: child_sa->get_unique_id(child_sa));
1047: }
1048: policies->destroy(policies);
1049: break;
1050: case CHILD_REKEYED:
1051: default:
1052: break;
1053: }
1054: }
1055: }
1056: enumerator->destroy(enumerator);
1057: }
1058:
1059: METHOD(task_t, process_r, status_t,
1060: private_quick_mode_t *this, message_t *message)
1061: {
1062: if (this->mid && this->mid != message->get_message_id(message))
1063: { /* not responsible for this quick mode exchange */
1064: return INVALID_ARG;
1065: }
1066:
1067: switch (this->state)
1068: {
1069: case QM_INIT:
1070: {
1071: sa_payload_t *sa_payload;
1072: linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
1073: peer_cfg_t *peer_cfg;
1074: uint16_t group;
1075: proposal_selection_flag_t flags = 0;
1076:
1077: sa_payload = (sa_payload_t*)message->get_payload(message,
1078: PLV1_SECURITY_ASSOCIATION);
1079: if (!sa_payload)
1080: {
1081: DBG1(DBG_IKE, "sa payload missing");
1082: return send_notify(this, INVALID_PAYLOAD_TYPE);
1083: }
1084:
1085: this->mode = sa_payload->get_encap_mode(sa_payload,
1086: &this->child.encap);
1087:
1088: if (!get_ts(this, message))
1089: {
1090: return FAILED;
1091: }
1092: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1093: tsi = linked_list_create_with_items(this->tsi, NULL);
1094: tsr = linked_list_create_with_items(this->tsr, NULL);
1095: this->tsi = this->tsr = NULL;
1096: hostsi = get_dynamic_hosts(this->ike_sa, FALSE);
1097: hostsr = get_dynamic_hosts(this->ike_sa, TRUE);
1098: this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
1099: hostsr, hostsi);
1100: hostsi->destroy(hostsi);
1101: hostsr->destroy(hostsr);
1102: if (this->config)
1103: {
1104: this->tsi = select_ts(this, FALSE, tsi);
1105: this->tsr = select_ts(this, TRUE, tsr);
1106: }
1107: if (!this->config || !this->tsi || !this->tsr ||
1108: this->mode != this->config->get_mode(this->config))
1109: {
1110: DBG1(DBG_IKE, "no matching CHILD_SA config found for "
1111: "%#R === %#R", tsi, tsr);
1112: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1113: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1114: return send_notify(this, INVALID_ID_INFORMATION);
1115: }
1116: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1117: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1118:
1119: if (this->config->has_option(this->config, OPT_IPCOMP))
1120: {
1121: list = sa_payload->get_ipcomp_proposals(sa_payload,
1122: &this->cpi_i);
1123: if (!list->get_count(list))
1124: {
1125: DBG1(DBG_IKE, "expected IPComp proposal but peer did "
1126: "not send one, IPComp disabled");
1127: this->cpi_i = 0;
1128: }
1129: }
1130: if (!list || !list->get_count(list))
1131: {
1132: DESTROY_IF(list);
1133: list = sa_payload->get_proposals(sa_payload);
1134: }
1135: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN)
1136: && !lib->settings->get_bool(lib->settings,
1137: "%s.accept_private_algs", FALSE, lib->ns))
1138: {
1139: flags |= PROPOSAL_SKIP_PRIVATE;
1140: }
1141: if (!lib->settings->get_bool(lib->settings,
1142: "%s.prefer_configured_proposals", TRUE, lib->ns))
1143: {
1144: flags |= PROPOSAL_PREFER_SUPPLIED;
1145: }
1146: this->proposal = this->config->select_proposal(this->config, list,
1147: flags);
1148: list->destroy_offset(list, offsetof(proposal_t, destroy));
1149:
1150: if (!this->proposal)
1151: {
1152: DBG1(DBG_IKE, "no matching proposal found, sending %N",
1153: notify_type_names, NO_PROPOSAL_CHOSEN);
1154: return send_notify(this, NO_PROPOSAL_CHOSEN);
1155: }
1156: this->spi_i = this->proposal->get_spi(this->proposal);
1157:
1158: get_lifetimes(this);
1159: apply_lifetimes(this, sa_payload);
1160:
1161: if (!get_nonce(this, &this->nonce_i, message))
1162: {
1163: return send_notify(this, INVALID_PAYLOAD_TYPE);
1164: }
1165:
1166: if (this->proposal->get_algorithm(this->proposal,
1167: DIFFIE_HELLMAN_GROUP, &group, NULL))
1168: {
1169: this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
1170: group);
1171: if (!this->dh)
1172: {
1173: DBG1(DBG_IKE, "negotiated DH group %N not supported",
1174: diffie_hellman_group_names, group);
1175: return send_notify(this, INVALID_KEY_INFORMATION);
1176: }
1177: if (!get_ke(this, message))
1178: {
1179: return send_notify(this, INVALID_PAYLOAD_TYPE);
1180: }
1181: }
1182:
1183: check_for_rekeyed_child(this, TRUE);
1184: this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa,
1185: TRUE);
1186: this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa,
1187: FALSE);
1188: this->child_sa = child_sa_create(
1189: this->ike_sa->get_my_host(this->ike_sa),
1190: this->ike_sa->get_other_host(this->ike_sa),
1191: this->config, &this->child);
1192:
1193: tsi = linked_list_create_with_items(this->tsi, NULL);
1194: tsr = linked_list_create_with_items(this->tsr, NULL);
1195: this->tsi = this->tsr = NULL;
1196: charon->bus->narrow(charon->bus, this->child_sa,
1197: NARROW_RESPONDER, tsr, tsi);
1198: if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS ||
1199: tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS)
1200: {
1201: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1202: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1203: return send_notify(this, INVALID_ID_INFORMATION);
1204: }
1205: tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1206: tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1207:
1208: return NEED_MORE;
1209: }
1210: case QM_NEGOTIATED:
1211: {
1212: if (has_notify_errors(this, message))
1213: {
1214: return SUCCESS;
1215: }
1216: if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1217: {
1218: if (message->get_payload(message, PLV1_DELETE))
1219: {
1220: /* If the DELETE for a Quick Mode follows immediately
1221: * after rekeying, we might receive it before the
1222: * third completing Quick Mode message. Ignore it, as
1223: * it gets handled by a separately queued delete task. */
1224: return NEED_MORE;
1225: }
1226: return SUCCESS;
1227: }
1228: if (!this->rekey)
1229: {
1230: /* do another check in case SAs were created since we handled
1231: * the QM request, this is consistent with the rekey check
1232: * before installation on the initiator */
1233: check_for_rekeyed_child(this, TRUE);
1234: if (this->rekey)
1235: {
1236: this->child_sa->destroy(this->child_sa);
1237: this->child_sa = child_sa_create(
1238: this->ike_sa->get_my_host(this->ike_sa),
1239: this->ike_sa->get_other_host(this->ike_sa),
1240: this->config, &this->child);
1241: }
1242: }
1243: if (!install(this))
1244: {
1245: ike_sa_t *ike_sa = this->ike_sa;
1246: task_t *task;
1247:
1248: task = (task_t*)quick_delete_create(this->ike_sa,
1249: this->proposal->get_protocol(this->proposal),
1250: this->spi_i, TRUE, TRUE);
1251: /* flush_queue() destroys the current task */
1252: ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE);
1253: ike_sa->queue_task(ike_sa, task);
1254: return ALREADY_DONE;
1255: }
1256: return SUCCESS;
1257: }
1258: default:
1259: return FAILED;
1260: }
1261: }
1262:
1263: METHOD(task_t, build_r, status_t,
1264: private_quick_mode_t *this, message_t *message)
1265: {
1266: if (this->mid && this->mid != message->get_message_id(message))
1267: { /* not responsible for this quick mode exchange */
1268: return INVALID_ARG;
1269: }
1270:
1271: switch (this->state)
1272: {
1273: case QM_INIT:
1274: {
1275: sa_payload_t *sa_payload;
1276: encap_t encap;
1277:
1278: this->proto = this->proposal->get_protocol(this->proposal);
1279: this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto);
1280: if (!this->spi_r)
1281: {
1282: DBG1(DBG_IKE, "allocating SPI from kernel failed");
1283: return send_notify(this, NO_PROPOSAL_CHOSEN);
1284: }
1285: this->proposal->set_spi(this->proposal, this->spi_r);
1286:
1287: if (this->cpi_i)
1288: {
1289: this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
1290: if (!this->cpi_r)
1291: {
1292: DBG1(DBG_IKE, "unable to allocate a CPI from "
1293: "kernel, IPComp disabled");
1294: return send_notify(this, NO_PROPOSAL_CHOSEN);
1295: }
1296: }
1297:
1298: if (this->child.encap && this->mode == MODE_TRANSPORT)
1299: {
1300: /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
1301: add_nat_oa_payloads(this, message);
1302: }
1303:
1304: encap = get_encap(this->ike_sa, this->child.encap);
1305: sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
1306: this->lifetime, this->lifebytes, AUTH_NONE,
1307: this->mode, encap, this->cpi_r);
1308: message->add_payload(message, &sa_payload->payload_interface);
1309:
1310: if (!add_nonce(this, &this->nonce_r, message))
1311: {
1312: return FAILED;
1313: }
1314: if (this->dh)
1315: {
1316: if (!add_ke(this, message))
1317: {
1318: return FAILED;
1319: }
1320: }
1321:
1322: add_ts(this, message);
1323:
1324: this->state = QM_NEGOTIATED;
1325: this->mid = message->get_message_id(message);
1326: return NEED_MORE;
1327: }
1328: case QM_NEGOTIATED:
1329: if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1330: {
1331: /* skip INFORMATIONAL response if we received a INFORMATIONAL
1332: * delete, see process_r() */
1333: return ALREADY_DONE;
1334: }
1335: /* fall */
1336: default:
1337: return FAILED;
1338: }
1339: }
1340:
1341: METHOD(task_t, process_i, status_t,
1342: private_quick_mode_t *this, message_t *message)
1343: {
1344: switch (this->state)
1345: {
1346: case QM_INIT:
1347: {
1348: sa_payload_t *sa_payload;
1349: linked_list_t *list = NULL;
1350: proposal_selection_flag_t flags = 0;
1351:
1352: sa_payload = (sa_payload_t*)message->get_payload(message,
1353: PLV1_SECURITY_ASSOCIATION);
1354: if (!sa_payload)
1355: {
1356: DBG1(DBG_IKE, "sa payload missing");
1357: return send_notify(this, NO_PROPOSAL_CHOSEN);
1358: }
1359: if (this->cpi_i)
1360: {
1361: list = sa_payload->get_ipcomp_proposals(sa_payload,
1362: &this->cpi_r);
1363: if (!list->get_count(list))
1364: {
1365: DBG1(DBG_IKE, "peer did not accept our IPComp proposal, "
1366: "IPComp disabled");
1367: this->cpi_i = 0;
1368: }
1369: }
1370: if (!list || !list->get_count(list))
1371: {
1372: DESTROY_IF(list);
1373: list = sa_payload->get_proposals(sa_payload);
1374: }
1375: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN)
1376: && !lib->settings->get_bool(lib->settings,
1377: "%s.accept_private_algs", FALSE, lib->ns))
1378: {
1379: flags |= PROPOSAL_SKIP_PRIVATE;
1380: }
1381: this->proposal = this->config->select_proposal(this->config, list,
1382: flags);
1383: list->destroy_offset(list, offsetof(proposal_t, destroy));
1384: if (!this->proposal)
1385: {
1386: DBG1(DBG_IKE, "no matching proposal found");
1387: return send_notify(this, NO_PROPOSAL_CHOSEN);
1388: }
1389: this->spi_r = this->proposal->get_spi(this->proposal);
1390:
1391: apply_lifetimes(this, sa_payload);
1392:
1393: if (!get_nonce(this, &this->nonce_r, message))
1394: {
1395: return send_notify(this, INVALID_PAYLOAD_TYPE);
1396: }
1397: if (this->dh && !get_ke(this, message))
1398: {
1399: return send_notify(this, INVALID_KEY_INFORMATION);
1400: }
1401: if (!get_ts(this, message))
1402: {
1403: return send_notify(this, INVALID_PAYLOAD_TYPE);
1404: }
1405: check_for_rekeyed_child(this, FALSE);
1406: if (!install(this))
1407: {
1408: return send_notify(this, NO_PROPOSAL_CHOSEN);
1409: }
1410: this->state = QM_NEGOTIATED;
1411: return NEED_MORE;
1412: }
1413: default:
1414: return FAILED;
1415: }
1416: }
1417:
1418: METHOD(task_t, get_type, task_type_t,
1419: private_quick_mode_t *this)
1420: {
1421: return TASK_QUICK_MODE;
1422: }
1423:
1424: METHOD(quick_mode_t, get_mid, uint32_t,
1425: private_quick_mode_t *this)
1426: {
1427: return this->mid;
1428: }
1429:
1430: METHOD(quick_mode_t, use_reqid, void,
1431: private_quick_mode_t *this, uint32_t reqid)
1432: {
1433: this->child.reqid = reqid;
1434: }
1435:
1436: METHOD(quick_mode_t, use_marks, void,
1437: private_quick_mode_t *this, uint32_t in, uint32_t out)
1438: {
1439: this->child.mark_in = in;
1440: this->child.mark_out = out;
1441: }
1442:
1443: METHOD(quick_mode_t, use_if_ids, void,
1444: private_quick_mode_t *this, uint32_t in, uint32_t out)
1445: {
1446: this->child.if_id_in = in;
1447: this->child.if_id_out = out;
1448: }
1449:
1450: METHOD(quick_mode_t, rekey, void,
1451: private_quick_mode_t *this, uint32_t spi)
1452: {
1453: this->rekey = spi;
1454: }
1455:
1456: METHOD(task_t, migrate, void,
1457: private_quick_mode_t *this, ike_sa_t *ike_sa)
1458: {
1459: chunk_free(&this->nonce_i);
1460: chunk_free(&this->nonce_r);
1461: DESTROY_IF(this->tsi);
1462: DESTROY_IF(this->tsr);
1463: DESTROY_IF(this->proposal);
1464: DESTROY_IF(this->child_sa);
1465: DESTROY_IF(this->dh);
1466:
1467: this->ike_sa = ike_sa;
1468: this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1469: this->state = QM_INIT;
1470: this->mid = 0;
1471: this->tsi = NULL;
1472: this->tsr = NULL;
1473: this->proposal = NULL;
1474: this->child_sa = NULL;
1475: this->dh = NULL;
1476: this->spi_i = 0;
1477: this->spi_r = 0;
1478: this->child = (child_sa_create_t){};
1479:
1480: if (!this->initiator)
1481: {
1482: DESTROY_IF(this->config);
1483: this->config = NULL;
1484: }
1485: }
1486:
1487: METHOD(task_t, destroy, void,
1488: private_quick_mode_t *this)
1489: {
1490: chunk_free(&this->nonce_i);
1491: chunk_free(&this->nonce_r);
1492: DESTROY_IF(this->tsi);
1493: DESTROY_IF(this->tsr);
1494: DESTROY_IF(this->proposal);
1495: DESTROY_IF(this->child_sa);
1496: DESTROY_IF(this->config);
1497: DESTROY_IF(this->dh);
1498: free(this);
1499: }
1500:
1501: /*
1502: * Described in header.
1503: */
1504: quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1505: traffic_selector_t *tsi, traffic_selector_t *tsr)
1506: {
1507: private_quick_mode_t *this;
1508:
1509: INIT(this,
1510: .public = {
1511: .task = {
1512: .get_type = _get_type,
1513: .migrate = _migrate,
1514: .destroy = _destroy,
1515: },
1516: .get_mid = _get_mid,
1517: .use_reqid = _use_reqid,
1518: .use_marks = _use_marks,
1519: .use_if_ids = _use_if_ids,
1520: .rekey = _rekey,
1521: },
1522: .ike_sa = ike_sa,
1523: .initiator = config != NULL,
1524: .config = config,
1525: .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1526: .state = QM_INIT,
1527: .tsi = tsi ? tsi->clone(tsi) : NULL,
1528: .tsr = tsr ? tsr->clone(tsr) : NULL,
1529: .proto = PROTO_ESP,
1530: .delete = lib->settings->get_bool(lib->settings,
1531: "%s.delete_rekeyed", FALSE, lib->ns),
1532: );
1533:
1534: if (config)
1535: {
1536: this->public.task.build = _build_i;
1537: this->public.task.process = _process_i;
1538: }
1539: else
1540: {
1541: this->public.task.build = _build_r;
1542: this->public.task.process = _process_r;
1543: }
1544:
1545: return &this->public;
1546: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>