Coverage Report

Created: 2026-03-31 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libcharon/sa/child_sa.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2006-2025 Tobias Brunner
3
 * Copyright (C) 2016 Andreas Steffen
4
 * Copyright (C) 2005-2008 Martin Willi
5
 * Copyright (C) 2006 Daniel Roethlisberger
6
 * Copyright (C) 2005 Jan Hutter
7
 *
8
 * Copyright (C) secunet Security Networks AG
9
 *
10
 * This program is free software; you can redistribute it and/or modify it
11
 * under the terms of the GNU General Public License as published by the
12
 * Free Software Foundation; either version 2 of the License, or (at your
13
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
14
 *
15
 * This program is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
 * for more details.
19
 */
20
21
#define _GNU_SOURCE
22
#include "child_sa.h"
23
24
#include <stdio.h>
25
#include <string.h>
26
#include <time.h>
27
28
#include <daemon.h>
29
#include <collections/array.h>
30
31
ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
32
  "CREATED",
33
  "ROUTED",
34
  "INSTALLING",
35
  "INSTALLED",
36
  "UPDATING",
37
  "REKEYING",
38
  "REKEYED",
39
  "RETRYING",
40
  "DELETING",
41
  "DELETED",
42
  "DESTROYING",
43
);
44
45
ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
46
  "NONE",
47
  "REGISTERED",
48
  "SA",
49
  "POLICIES",
50
);
51
52
typedef struct private_child_sa_t private_child_sa_t;
53
54
/**
55
 * Private data of a child_sa_t object.
56
 */
57
struct private_child_sa_t {
58
  /**
59
   * Public interface of child_sa_t.
60
   */
61
  child_sa_t public;
62
63
  /**
64
   * address of us
65
   */
66
  host_t *my_addr;
67
68
  /**
69
   * address of remote
70
   */
71
  host_t *other_addr;
72
73
  /**
74
   * our actually used SPI, 0 if unused
75
   */
76
  uint32_t my_spi;
77
78
  /**
79
   * others used SPI, 0 if unused
80
   */
81
  uint32_t other_spi;
82
83
  /**
84
   * our Compression Parameter Index (CPI) used, 0 if unused
85
   */
86
  uint16_t my_cpi;
87
88
  /**
89
   * others Compression Parameter Index (CPI) used, 0 if unused
90
   */
91
  uint16_t other_cpi;
92
93
  /**
94
   * Array for local traffic selectors
95
   */
96
  array_t *my_ts;
97
98
  /**
99
   * Array for remote traffic selectors
100
   */
101
  array_t *other_ts;
102
103
  /**
104
   * Outbound encryption key cached during a rekeying
105
   */
106
  chunk_t encr_r;
107
108
  /**
109
   * Outbound integrity key cached during a rekeying
110
   */
111
  chunk_t integ_r;
112
113
  /**
114
   * Whether the registered outbound SA was created as initiator
115
   */
116
  bool initiator;
117
118
  /**
119
   * Whether the outbound SA has only been registered yet during a rekeying
120
   */
121
  child_sa_outbound_state_t outbound_state;
122
123
  /**
124
   * Whether the inbound SA has been installed
125
   */
126
  bool inbound_installed;
127
128
  /**
129
   * Whether the peer supports TFCv3
130
   */
131
  bool tfcv3;
132
133
  /**
134
   * The "other" CHILD_SA involved in a passive rekeying (either replacing
135
   * this one, or being replaced by it)
136
   */
137
  child_sa_t *rekey_sa;
138
139
  /**
140
   * Protocol used to protect this SA, ESP|AH
141
   */
142
  protocol_id_t protocol;
143
144
  /**
145
   * reqid used for this child_sa
146
   */
147
  uint32_t reqid;
148
149
  /**
150
   * Did we allocate/confirm and must release the reqid?
151
   */
152
  bool reqid_allocated;
153
154
  /**
155
   * Is the reqid statically configured
156
   */
157
  bool static_reqid;
158
159
  /**
160
   * Unique CHILD_SA identifier
161
   */
162
  uint32_t unique_id;
163
164
  /**
165
   * Optional sequence number associated with triggering acquire
166
   */
167
  uint32_t seq;
168
169
  /**
170
   * Whether FWD policies in the outbound direction should be installed
171
   */
172
  bool policies_fwd_out;
173
174
  /**
175
   * Inbound interface ID
176
   */
177
  uint32_t if_id_in;
178
179
  /**
180
   * Outbound interface ID
181
   */
182
  uint32_t if_id_out;
183
184
  /**
185
   * CPU ID to use for the outbound SA
186
   */
187
  uint32_t cpu;
188
189
  /**
190
   * Whether to enable per-CPU feature for this SA
191
   */
192
  bool per_cpu;
193
194
  /**
195
   * inbound mark used for this child_sa
196
   */
197
  mark_t mark_in;
198
199
  /**
200
   * outbound mark used for this child_sa
201
   */
202
  mark_t mark_out;
203
204
  /**
205
   * Security label
206
   */
207
  sec_label_t *label;
208
209
  /**
210
   * absolute time when rekeying is scheduled
211
   */
212
  time_t rekey_time;
213
214
  /**
215
   * absolute time when the SA expires
216
   */
217
  time_t expire_time;
218
219
  /**
220
   * absolute time when SA has been installed
221
   */
222
  time_t install_time;
223
224
  /**
225
   * state of the CHILD_SA
226
   */
227
  child_sa_state_t state;
228
229
  /**
230
   * TRUE if this CHILD_SA is used to install trap policies
231
   */
232
  bool trap;
233
234
  /**
235
   * Specifies if UDP encapsulation is enabled (NAT traversal)
236
   */
237
  bool encap;
238
239
  /**
240
   * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
241
   */
242
  ipcomp_transform_t ipcomp;
243
244
  /**
245
   * mode this SA uses, tunnel/transport
246
   */
247
  ipsec_mode_t mode;
248
249
  /**
250
   * Disable fragmenting packets across IP-TFS packets
251
   */
252
  bool iptfs_dont_frag;
253
254
  /**
255
   * Action to enforce if peer closes the CHILD_SA
256
   */
257
  action_t close_action;
258
259
  /**
260
   * Action to enforce if peer is considered dead
261
   */
262
  action_t dpd_action;
263
264
  /**
265
   * selected proposal
266
   */
267
  proposal_t *proposal;
268
269
  /**
270
   * config used to create this child
271
   */
272
  child_cfg_t *config;
273
274
  /**
275
   * time of last use in seconds (inbound)
276
   */
277
  time_t my_usetime;
278
279
  /**
280
   * time of last use in seconds (outbound)
281
   */
282
  time_t other_usetime;
283
284
  /**
285
   * last number of inbound bytes
286
   */
287
  uint64_t my_usebytes;
288
289
  /**
290
   * last number of outbound bytes
291
   */
292
  uint64_t other_usebytes;
293
294
  /**
295
   * last number of inbound packets
296
   */
297
  uint64_t my_usepackets;
298
299
  /**
300
   * last number of outbound packets
301
   */
302
  uint64_t other_usepackets;
303
};
304
305
/**
306
 * Convert an IKEv2 specific protocol identifier to the IP protocol identifier
307
 */
308
static inline uint8_t proto_ike2ip(protocol_id_t protocol)
309
0
{
310
0
  switch (protocol)
311
0
  {
312
0
    case PROTO_ESP:
313
0
      return IPPROTO_ESP;
314
0
    case PROTO_AH:
315
0
      return IPPROTO_AH;
316
0
    default:
317
0
      return protocol;
318
0
  }
319
0
}
320
321
/**
322
 * Returns the mark to use on the inbound SA
323
 */
324
static inline mark_t mark_in_sa(private_child_sa_t *this)
325
0
{
326
0
  if (this->config->has_option(this->config, OPT_MARK_IN_SA))
327
0
  {
328
0
    return this->mark_in;
329
0
  }
330
0
  return (mark_t){};
331
0
}
332
333
/**
334
 * Possible uses for security labels
335
 */
336
typedef enum {
337
  LABEL_USE_REQID,
338
  LABEL_USE_POLICY,
339
  LABEL_USE_SA,
340
} label_use_t;
341
342
/**
343
 * Returns the security label for either policies, SAs or reqids.
344
 */
345
static inline sec_label_t *label_for(private_child_sa_t *this, label_use_t use)
346
0
{
347
  /* For SELinux we use the configured label for policies and reqid but the
348
   * negotiated one for the SAs. That's because the label on the policies is
349
   * usually a generic one that matches specific labels on flows, which will
350
   * trigger an acquire if no matching SA with that label exists yet.
351
   * When that SA is later installed, we want to avoid having to install
352
   * policies in the kernel that will never get used, so we use the configured
353
   * label again.
354
   * Note that while the labels don't have to be equal, they are both either
355
   * NULL or defined.
356
   */
357
0
  if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
358
0
  {
359
0
    switch (use)
360
0
    {
361
0
      case LABEL_USE_REQID:
362
0
      case LABEL_USE_POLICY:
363
0
        return this->config->get_label(this->config);
364
0
      case LABEL_USE_SA:
365
0
        return this->label;
366
0
    }
367
0
  }
368
  /* for the simple label mode we don't pass labels to the kernel, so we don't
369
   * use it to acquire unique reqids either */
370
0
  return NULL;
371
0
}
372
373
METHOD(child_sa_t, get_name, char*,
374
     private_child_sa_t *this)
375
0
{
376
0
  return this->config->get_name(this->config);
377
0
}
378
379
METHOD(child_sa_t, get_reqid, uint32_t,
380
     private_child_sa_t *this)
381
0
{
382
0
  return this->reqid;
383
0
}
384
385
METHOD(child_sa_t, get_reqid_ref, uint32_t,
386
     private_child_sa_t *this)
387
0
{
388
0
  if ((this->reqid_allocated || (!this->static_reqid && this->reqid)) &&
389
0
    charon->kernel->ref_reqid(charon->kernel, this->reqid) == SUCCESS)
390
0
  {
391
0
    return this->reqid;
392
0
  }
393
0
  return 0;
394
0
}
395
396
METHOD(child_sa_t, get_unique_id, uint32_t,
397
  private_child_sa_t *this)
398
0
{
399
0
  return this->unique_id;
400
0
}
401
402
METHOD(child_sa_t, get_config, child_cfg_t*,
403
     private_child_sa_t *this)
404
0
{
405
0
  return this->config;
406
0
}
407
408
METHOD(child_sa_t, set_state, void,
409
     private_child_sa_t *this, child_sa_state_t state)
410
0
{
411
0
  if (this->state != state)
412
0
  {
413
0
    DBG2(DBG_CHD, "CHILD_SA %s{%d} state change: %N => %N",
414
0
       get_name(this), this->unique_id,
415
0
       child_sa_state_names, this->state,
416
0
       child_sa_state_names, state);
417
0
    charon->bus->child_state_change(charon->bus, &this->public, state);
418
0
    this->state = state;
419
0
  }
420
0
}
421
422
METHOD(child_sa_t, get_state, child_sa_state_t,
423
     private_child_sa_t *this)
424
0
{
425
0
  return this->state;
426
0
}
427
428
METHOD(child_sa_t, get_outbound_state, child_sa_outbound_state_t,
429
     private_child_sa_t *this)
430
0
{
431
0
  return this->outbound_state;
432
0
}
433
434
METHOD(child_sa_t, get_spi, uint32_t,
435
     private_child_sa_t *this, bool inbound)
436
0
{
437
0
  return inbound ? this->my_spi : this->other_spi;
438
0
}
439
440
METHOD(child_sa_t, get_cpi, uint16_t,
441
     private_child_sa_t *this, bool inbound)
442
0
{
443
0
  return inbound ? this->my_cpi : this->other_cpi;
444
0
}
445
446
METHOD(child_sa_t, get_protocol, protocol_id_t,
447
     private_child_sa_t *this)
448
0
{
449
0
  return this->protocol;
450
0
}
451
452
METHOD(child_sa_t, set_protocol, void,
453
     private_child_sa_t *this, protocol_id_t protocol)
454
0
{
455
0
  this->protocol = protocol;
456
0
}
457
458
METHOD(child_sa_t, get_mode, ipsec_mode_t,
459
     private_child_sa_t *this)
460
0
{
461
0
  return this->mode;
462
0
}
463
464
METHOD(child_sa_t, set_mode, void,
465
     private_child_sa_t *this, ipsec_mode_t mode)
466
0
{
467
0
  this->mode = mode;
468
0
}
469
470
METHOD(child_sa_t, set_iptfs_dont_fragment, void,
471
  private_child_sa_t *this)
472
0
{
473
0
  this->iptfs_dont_frag = TRUE;
474
0
}
475
476
METHOD(child_sa_t, has_encap, bool,
477
     private_child_sa_t *this)
478
0
{
479
0
  return this->encap;
480
0
}
481
482
METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
483
     private_child_sa_t *this)
484
0
{
485
0
  return this->ipcomp;
486
0
}
487
488
METHOD(child_sa_t, set_ipcomp, void,
489
     private_child_sa_t *this, ipcomp_transform_t ipcomp)
490
0
{
491
0
  this->ipcomp = ipcomp;
492
0
}
493
494
METHOD(child_sa_t, set_close_action, void,
495
     private_child_sa_t *this, action_t action)
496
0
{
497
0
  this->close_action = action;
498
0
}
499
500
METHOD(child_sa_t, get_close_action, action_t,
501
     private_child_sa_t *this)
502
0
{
503
0
  return this->close_action;
504
0
}
505
506
METHOD(child_sa_t, set_dpd_action, void,
507
     private_child_sa_t *this, action_t action)
508
0
{
509
0
  this->dpd_action = action;
510
0
}
511
512
METHOD(child_sa_t, get_dpd_action, action_t,
513
     private_child_sa_t *this)
514
0
{
515
0
  return this->dpd_action;
516
0
}
517
518
METHOD(child_sa_t, get_proposal, proposal_t*,
519
     private_child_sa_t *this)
520
0
{
521
0
  return this->proposal;
522
0
}
523
524
METHOD(child_sa_t, set_proposal, void,
525
     private_child_sa_t *this, proposal_t *proposal)
526
0
{
527
0
  this->proposal = proposal->clone(proposal, 0);
528
0
}
529
530
METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
531
  private_child_sa_t *this, bool local)
532
0
{
533
0
  if (local)
534
0
  {
535
0
    return array_create_enumerator(this->my_ts);
536
0
  }
537
0
  return array_create_enumerator(this->other_ts);
538
0
}
539
540
typedef struct policy_enumerator_t policy_enumerator_t;
541
542
/**
543
 * Private policy enumerator
544
 */
545
struct policy_enumerator_t {
546
  /** implements enumerator_t */
547
  enumerator_t public;
548
  /** enumerator over own TS */
549
  enumerator_t *mine;
550
  /** enumerator over others TS */
551
  enumerator_t *other;
552
  /** array of others TS, to recreate enumerator */
553
  array_t *array;
554
  /** currently enumerating TS for "me" side */
555
  traffic_selector_t *ts;
556
};
557
558
METHOD(enumerator_t, policy_enumerate, bool,
559
     policy_enumerator_t *this, va_list args)
560
0
{
561
0
  traffic_selector_t *other_ts, **my_out, **other_out;
562
563
0
  VA_ARGS_VGET(args, my_out, other_out);
564
565
0
  while (this->ts || this->mine->enumerate(this->mine, &this->ts))
566
0
  {
567
0
    if (!this->other->enumerate(this->other, &other_ts))
568
0
    { /* end of others list, restart with new of mine */
569
0
      this->other->destroy(this->other);
570
0
      this->other = array_create_enumerator(this->array);
571
0
      this->ts = NULL;
572
0
      continue;
573
0
    }
574
0
    if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
575
0
    { /* family mismatch */
576
0
      continue;
577
0
    }
578
0
    if (this->ts->get_protocol(this->ts) &&
579
0
      other_ts->get_protocol(other_ts) &&
580
0
      this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
581
0
    { /* protocol mismatch */
582
0
      continue;
583
0
    }
584
0
    if (my_out)
585
0
    {
586
0
      *my_out = this->ts;
587
0
    }
588
0
    if (other_out)
589
0
    {
590
0
      *other_out = other_ts;
591
0
    }
592
0
    return TRUE;
593
0
  }
594
0
  return FALSE;
595
0
}
596
597
METHOD(enumerator_t, policy_destroy, void,
598
     policy_enumerator_t *this)
599
0
{
600
0
  this->mine->destroy(this->mine);
601
0
  this->other->destroy(this->other);
602
0
  free(this);
603
0
}
604
605
/**
606
 * Create an enumerator over two lists of traffic selectors, returning all the
607
 * pairs of traffic selectors from the first and second list.
608
 */
609
static enumerator_t *create_policy_enumerator_internal(array_t *my_ts,
610
                             array_t *other_ts)
611
0
{
612
0
  policy_enumerator_t *e;
613
614
0
  INIT(e,
615
0
    .public = {
616
0
      .enumerate = enumerator_enumerate_default,
617
0
      .venumerate = _policy_enumerate,
618
0
      .destroy = _policy_destroy,
619
0
    },
620
0
    .mine = array_create_enumerator(my_ts),
621
0
    .other = array_create_enumerator(other_ts),
622
0
    .array = other_ts,
623
0
    .ts = NULL,
624
0
  );
625
626
0
  return &e->public;
627
0
}
628
629
METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
630
     private_child_sa_t *this)
631
0
{
632
0
  return create_policy_enumerator_internal(this->my_ts, this->other_ts);
633
0
}
634
635
/**
636
 * update the cached usebytes
637
 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
638
 * are available, and NOT_SUPPORTED if the kernel interface does not support
639
 * querying the usebytes.
640
 */
641
static status_t update_usebytes(private_child_sa_t *this, bool inbound)
642
0
{
643
0
  status_t status = FAILED;
644
0
  uint64_t bytes, packets;
645
0
  time_t time;
646
647
0
  if (inbound)
648
0
  {
649
0
    if (this->inbound_installed)
650
0
    {
651
0
      kernel_ipsec_sa_id_t id = {
652
0
        .src = this->other_addr,
653
0
        .dst = this->my_addr,
654
0
        .spi = this->my_spi,
655
0
        .proto = proto_ike2ip(this->protocol),
656
0
        .mark = mark_in_sa(this),
657
0
        .if_id = this->if_id_in,
658
0
      };
659
0
      kernel_ipsec_query_sa_t query = {};
660
661
0
      status = charon->kernel->query_sa(charon->kernel, &id, &query,
662
0
                        &bytes, &packets, &time);
663
0
      if (status == SUCCESS)
664
0
      {
665
0
        if (bytes > this->my_usebytes)
666
0
        {
667
0
          this->my_usebytes = bytes;
668
0
          this->my_usepackets = packets;
669
0
          if (time)
670
0
          {
671
0
            this->my_usetime = time;
672
0
          }
673
0
        }
674
0
        else
675
0
        {
676
0
          status = FAILED;
677
0
        }
678
0
      }
679
0
    }
680
0
  }
681
0
  else
682
0
  {
683
0
    if (this->outbound_state & CHILD_OUTBOUND_SA)
684
0
    {
685
0
      kernel_ipsec_sa_id_t id = {
686
0
        .src = this->my_addr,
687
0
        .dst = this->other_addr,
688
0
        .spi = this->other_spi,
689
0
        .proto = proto_ike2ip(this->protocol),
690
0
        .mark = this->mark_out,
691
0
        .if_id = this->if_id_out,
692
0
      };
693
0
      kernel_ipsec_query_sa_t query = {};
694
695
0
      status = charon->kernel->query_sa(charon->kernel, &id, &query,
696
0
                        &bytes, &packets, &time);
697
0
      if (status == SUCCESS)
698
0
      {
699
0
        if (bytes > this->other_usebytes)
700
0
        {
701
0
          this->other_usebytes = bytes;
702
0
          this->other_usepackets = packets;
703
0
          if (time)
704
0
          {
705
0
            this->other_usetime = time;
706
0
          }
707
0
        }
708
0
        else
709
0
        {
710
0
          status = FAILED;
711
0
        }
712
0
      }
713
0
    }
714
0
  }
715
0
  return status;
716
0
}
717
718
/**
719
 * updates the cached usetime
720
 */
721
static bool update_usetime(private_child_sa_t *this, bool inbound)
722
0
{
723
0
  enumerator_t *enumerator;
724
0
  traffic_selector_t *my_ts, *other_ts;
725
0
  time_t last_use = 0;
726
727
0
  enumerator = create_policy_enumerator(this);
728
0
  while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
729
0
  {
730
0
    time_t in, out, fwd;
731
732
0
    if (inbound)
733
0
    {
734
0
      kernel_ipsec_policy_id_t id = {
735
0
        .dir = POLICY_IN,
736
0
        .src_ts = other_ts,
737
0
        .dst_ts = my_ts,
738
0
        .mark = this->mark_in,
739
0
        .if_id = this->if_id_in,
740
0
        .label = label_for(this, LABEL_USE_POLICY),
741
0
      };
742
0
      kernel_ipsec_query_policy_t query = {};
743
744
0
      if (charon->kernel->query_policy(charon->kernel, &id, &query,
745
0
                       &in) == SUCCESS)
746
0
      {
747
0
        last_use = max(last_use, in);
748
0
      }
749
0
      if (this->mode != MODE_TRANSPORT)
750
0
      {
751
0
        id.dir = POLICY_FWD;
752
0
        if (charon->kernel->query_policy(charon->kernel, &id, &query,
753
0
                         &fwd) == SUCCESS)
754
0
        {
755
0
          last_use = max(last_use, fwd);
756
0
        }
757
0
      }
758
0
    }
759
0
    else
760
0
    {
761
0
      kernel_ipsec_policy_id_t id = {
762
0
        .dir = POLICY_OUT,
763
0
        .src_ts = my_ts,
764
0
        .dst_ts = other_ts,
765
0
        .mark = this->mark_out,
766
0
        .if_id = this->if_id_out,
767
0
        .interface = this->config->get_interface(this->config),
768
0
        .label = label_for(this, LABEL_USE_POLICY),
769
0
      };
770
0
      kernel_ipsec_query_policy_t query = {};
771
772
0
      if (charon->kernel->query_policy(charon->kernel, &id, &query,
773
0
                       &out) == SUCCESS)
774
0
      {
775
0
        last_use = max(last_use, out);
776
0
      }
777
0
    }
778
0
  }
779
0
  enumerator->destroy(enumerator);
780
781
0
  if (last_use == 0)
782
0
  {
783
0
    return FALSE;
784
0
  }
785
0
  if (inbound)
786
0
  {
787
0
    this->my_usetime = last_use;
788
0
  }
789
0
  else
790
0
  {
791
0
    this->other_usetime = last_use;
792
0
  }
793
0
  return TRUE;
794
0
}
795
796
METHOD(child_sa_t, get_usestats, void,
797
  private_child_sa_t *this, bool inbound,
798
  time_t *time, uint64_t *bytes, uint64_t *packets)
799
0
{
800
0
  status_t status = NOT_SUPPORTED;
801
0
  bool sa_use_time;
802
803
0
  sa_use_time = charon->kernel->get_features(charon->kernel) & KERNEL_SA_USE_TIME;
804
805
0
  if (bytes || packets || sa_use_time)
806
0
  {
807
0
    status = update_usebytes(this, inbound);
808
0
  }
809
0
  if (time && !sa_use_time && status != FAILED)
810
0
  { /* query policies only if last use time is not available from SAs and
811
     * there was either traffic or querying the SA wasn't supported */
812
0
    update_usetime(this, inbound);
813
0
  }
814
0
  if (time)
815
0
  {
816
0
    *time = inbound ? this->my_usetime : this->other_usetime;
817
0
  }
818
0
  if (bytes)
819
0
  {
820
0
    *bytes = inbound ? this->my_usebytes : this->other_usebytes;
821
0
  }
822
0
  if (packets)
823
0
  {
824
0
    *packets = inbound ? this->my_usepackets : this->other_usepackets;
825
0
  }
826
0
}
827
828
METHOD(child_sa_t, get_mark, mark_t,
829
  private_child_sa_t *this, bool inbound)
830
0
{
831
0
  return inbound ? this->mark_in : this->mark_out;
832
0
}
833
834
METHOD(child_sa_t, get_if_id, uint32_t,
835
  private_child_sa_t *this, bool inbound)
836
0
{
837
0
  return inbound ? this->if_id_in : this->if_id_out;
838
0
}
839
840
METHOD(child_sa_t, get_label, sec_label_t*,
841
  private_child_sa_t *this)
842
0
{
843
0
  return this->label ?: this->config->get_label(this->config);
844
0
}
845
846
METHOD(child_sa_t, get_acquire_seq, uint32_t,
847
  private_child_sa_t *this)
848
0
{
849
0
  return this->seq;
850
0
}
851
852
METHOD(child_sa_t, set_acquire_seq, void,
853
  private_child_sa_t *this, uint32_t seq)
854
0
{
855
0
  this->seq = seq;
856
0
}
857
858
METHOD(child_sa_t, get_cpu, uint32_t,
859
  private_child_sa_t *this)
860
0
{
861
0
  return this->cpu;
862
0
}
863
864
METHOD(child_sa_t, use_per_cpu, bool,
865
  private_child_sa_t *this)
866
0
{
867
0
  return this->per_cpu;
868
0
}
869
870
METHOD(child_sa_t, set_per_cpu, void,
871
  private_child_sa_t *this, bool per_cpu)
872
0
{
873
0
  if (!per_cpu)
874
0
  {
875
0
    this->cpu = CPU_ID_MAX;
876
0
  }
877
0
  this->per_cpu = per_cpu;
878
0
}
879
880
METHOD(child_sa_t, get_lifetime, time_t,
881
     private_child_sa_t *this, bool hard)
882
0
{
883
0
  return hard ? this->expire_time : this->rekey_time;
884
0
}
885
886
METHOD(child_sa_t, get_installtime, time_t,
887
  private_child_sa_t *this)
888
0
{
889
0
  return this->install_time;
890
0
}
891
892
METHOD(child_sa_t, alloc_spi, uint32_t,
893
     private_child_sa_t *this, protocol_id_t protocol)
894
0
{
895
0
  if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
896
0
              proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
897
0
  {
898
    /* if we allocate a SPI, but then are unable to establish the SA, we
899
     * need to know the protocol family to delete the partial SA */
900
0
    this->protocol = protocol;
901
0
    return this->my_spi;
902
0
  }
903
0
  return 0;
904
0
}
905
906
METHOD(child_sa_t, alloc_cpi, uint16_t,
907
     private_child_sa_t *this)
908
0
{
909
0
  if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
910
0
                &this->my_cpi) == SUCCESS)
911
0
  {
912
0
    return this->my_cpi;
913
0
  }
914
0
  return 0;
915
0
}
916
917
/**
918
 * Allocate a reqid for the given local and remote traffic selector lists.
919
 * On success, release the previously allocated reqid.
920
 */
921
static status_t alloc_reqid_lists(private_child_sa_t *this,
922
                  linked_list_t *my_ts, linked_list_t *other_ts,
923
                  uint32_t *reqid)
924
0
{
925
0
  uint32_t existing_reqid = *reqid;
926
0
  status_t status;
927
928
0
  status = charon->kernel->alloc_reqid(
929
0
              charon->kernel, my_ts, other_ts,
930
0
              this->mark_in, this->mark_out, this->if_id_in,
931
0
              this->if_id_out, label_for(this, LABEL_USE_REQID),
932
0
              reqid);
933
934
0
  if (status == SUCCESS && existing_reqid)
935
0
  {
936
0
    if (charon->kernel->release_reqid(charon->kernel,
937
0
                      existing_reqid) != SUCCESS)
938
0
    {
939
0
      DBG1(DBG_CHD, "releasing previous reqid %u failed", existing_reqid);
940
0
    }
941
0
  }
942
0
  return status;
943
0
}
944
945
/**
946
 * Allocate a reqid for the given local and remote traffic selectors.
947
 */
948
static status_t alloc_reqid(private_child_sa_t *this, array_t *my_ts,
949
              array_t *other_ts, uint32_t *reqid)
950
0
{
951
0
  linked_list_t *my_ts_list, *other_ts_list;
952
0
  status_t status;
953
954
0
  my_ts_list = linked_list_create_from_enumerator(array_create_enumerator(my_ts));
955
0
  other_ts_list = linked_list_create_from_enumerator(array_create_enumerator(other_ts));
956
0
  status = alloc_reqid_lists(this, my_ts_list, other_ts_list, reqid);
957
0
  my_ts_list->destroy(my_ts_list);
958
0
  other_ts_list->destroy(other_ts_list);
959
0
  return status;
960
0
}
961
962
/**
963
 * Install the given SA in the kernel
964
 */
965
static status_t install_internal(private_child_sa_t *this, chunk_t encr,
966
  chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
967
  bool tfcv3)
968
0
{
969
0
  uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
970
0
  uint16_t esn = NO_EXT_SEQ_NUMBERS;
971
0
  linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
972
0
  time_t now;
973
0
  kernel_ipsec_sa_id_t id;
974
0
  kernel_ipsec_add_sa_t sa;
975
0
  lifetime_cfg_t *lifetime;
976
0
  uint32_t tfc = 0;
977
0
  host_t *src, *dst;
978
0
  status_t status;
979
0
  bool update = FALSE;
980
981
  /* BEET requires the bound address from the traffic selectors */
982
0
  my_ts = linked_list_create_from_enumerator(
983
0
                  array_create_enumerator(this->my_ts));
984
0
  other_ts = linked_list_create_from_enumerator(
985
0
                  array_create_enumerator(this->other_ts));
986
987
  /* now we have to decide which spi to use. Use self allocated, if "in",
988
   * or the one in the proposal, if not "in" (others). Additionally,
989
   * source and dest host switch depending on the role */
990
0
  if (inbound)
991
0
  {
992
0
    dst = this->my_addr;
993
0
    src = this->other_addr;
994
0
    if (this->my_spi == spi)
995
0
    { /* alloc_spi has been called, do an SA update */
996
0
      update = TRUE;
997
0
    }
998
0
    this->my_spi = spi;
999
0
    this->my_cpi = cpi;
1000
0
    dst_ts = my_ts;
1001
0
    src_ts = other_ts;
1002
1003
0
    if (this->per_cpu && this->encap)
1004
0
    {
1005
0
      src = src->clone(src);
1006
      /* accept inbound traffic from any port as we don't know if the
1007
       * peer uses random ports or not */
1008
0
      src->set_port(src, 0);
1009
0
    }
1010
0
  }
1011
0
  else
1012
0
  {
1013
0
    src = this->my_addr;
1014
0
    dst = this->other_addr;
1015
0
    this->other_spi = spi;
1016
0
    this->other_cpi = cpi;
1017
0
    src_ts = my_ts;
1018
0
    dst_ts = other_ts;
1019
1020
0
    if (tfcv3)
1021
0
    {
1022
0
      tfc = this->config->get_tfc(this->config);
1023
0
    }
1024
0
    if (this->per_cpu && this->encap &&
1025
0
      this->config->has_option(this->config, OPT_PER_CPU_SAS_ENCAP))
1026
0
    {
1027
0
      src = src->clone(src);
1028
      /* use a random source port between 49152 and 65535. doesn't matter
1029
       * if it's free or not as we don't receive traffic on it */
1030
0
      src->set_port(src, 0xc000 | (random() & 0xffff));
1031
0
    }
1032
0
  }
1033
1034
0
  DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
1035
0
     protocol_id_names, this->protocol);
1036
1037
  /* send SA down to the kernel */
1038
0
  DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
1039
1040
0
  this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
1041
0
                  &enc_alg, &size);
1042
0
  this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
1043
0
                  &int_alg, &size);
1044
0
  this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
1045
0
                  &esn, NULL);
1046
1047
0
  if (int_alg == AUTH_HMAC_SHA2_256_128 &&
1048
0
    this->config->has_option(this->config, OPT_SHA256_96))
1049
0
  {
1050
0
    DBG2(DBG_CHD, "  using %N with 96-bit truncation",
1051
0
       integrity_algorithm_names, int_alg);
1052
0
    int_alg = AUTH_HMAC_SHA2_256_96;
1053
0
  }
1054
1055
0
  if (!this->reqid_allocated && !this->static_reqid)
1056
0
  {
1057
0
    status = alloc_reqid_lists(this, my_ts, other_ts, &this->reqid);
1058
0
    if (status != SUCCESS)
1059
0
    {
1060
0
      my_ts->destroy(my_ts);
1061
0
      other_ts->destroy(other_ts);
1062
0
      return status;
1063
0
    }
1064
0
    this->reqid_allocated = TRUE;
1065
0
  }
1066
1067
0
  lifetime = this->config->get_lifetime(this->config, TRUE);
1068
1069
0
  now = time_monotonic(NULL);
1070
0
  if (lifetime->time.rekey)
1071
0
  {
1072
0
    if (this->rekey_time)
1073
0
    {
1074
0
      this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
1075
0
    }
1076
0
    else
1077
0
    {
1078
0
      this->rekey_time = now + lifetime->time.rekey;
1079
0
    }
1080
0
  }
1081
0
  if (lifetime->time.life)
1082
0
  {
1083
0
    this->expire_time = now + lifetime->time.life;
1084
0
  }
1085
1086
0
  if (!lifetime->time.jitter && !inbound)
1087
0
  { /* avoid triggering multiple rekey events */
1088
0
    lifetime->time.rekey = 0;
1089
0
  }
1090
1091
0
  id = (kernel_ipsec_sa_id_t){
1092
0
    .src = src,
1093
0
    .dst = dst,
1094
0
    .spi = spi,
1095
0
    .proto = proto_ike2ip(this->protocol),
1096
0
    .mark = inbound ? mark_in_sa(this) : this->mark_out,
1097
0
    .if_id = inbound ? this->if_id_in : this->if_id_out,
1098
0
  };
1099
0
  sa = (kernel_ipsec_add_sa_t){
1100
0
    .reqid = this->reqid,
1101
0
    .seq = this->seq,
1102
0
    .mode = this->mode,
1103
0
    .src_ts = src_ts,
1104
0
    .dst_ts = dst_ts,
1105
0
    .interface = inbound ? NULL : this->config->get_interface(this->config),
1106
0
    .lifetime = lifetime,
1107
0
    .enc_alg = enc_alg,
1108
0
    .enc_key = encr,
1109
0
    .int_alg = int_alg,
1110
0
    .int_key = integ,
1111
0
    .replay_window = this->config->get_replay_window(this->config),
1112
0
    .tfc = tfc,
1113
0
    .ipcomp = this->ipcomp,
1114
0
    .cpi = cpi,
1115
0
    .encap = this->encap,
1116
0
    .cpu = this->per_cpu ? this->cpu : CPU_ID_MAX,
1117
0
    .hw_offload = this->config->get_hw_offload(this->config),
1118
0
    .mark = this->config->get_set_mark(this->config, inbound),
1119
0
    .esn = esn,
1120
0
    .copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
1121
0
    .copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
1122
0
    .copy_dscp = this->config->get_copy_dscp(this->config),
1123
0
    .iptfs_dont_frag = this->iptfs_dont_frag,
1124
0
    .forward_icmp = this->config->has_option(this->config, OPT_FORWARD_ICMP),
1125
0
    .label = label_for(this, LABEL_USE_SA),
1126
0
    .initiator = initiator,
1127
0
    .inbound = inbound,
1128
0
    .update = update,
1129
0
  };
1130
1131
0
  if (sa.mark.value == MARK_SAME)
1132
0
  {
1133
0
    sa.mark.value = inbound ? this->mark_in.value : this->mark_out.value;
1134
0
  }
1135
1136
0
  status = charon->kernel->add_sa(charon->kernel, &id, &sa);
1137
1138
0
  if (src != this->my_addr && src != this->other_addr)
1139
0
  {
1140
0
    src->destroy(src);
1141
0
  }
1142
0
  my_ts->destroy(my_ts);
1143
0
  other_ts->destroy(other_ts);
1144
0
  free(lifetime);
1145
1146
0
  if (status == SUCCESS)
1147
0
  {
1148
0
    if (inbound)
1149
0
    {
1150
0
      this->inbound_installed = TRUE;
1151
0
    }
1152
0
    else
1153
0
    {
1154
0
      this->outbound_state |= CHILD_OUTBOUND_SA;
1155
0
    }
1156
0
  }
1157
0
  return status;
1158
0
}
1159
1160
METHOD(child_sa_t, install, status_t,
1161
  private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
1162
  uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
1163
0
{
1164
0
  return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
1165
0
              tfcv3);
1166
0
}
1167
1168
/**
1169
 * Check whether to install policies for this CHILD_SA
1170
 */
1171
static bool require_policies(private_child_sa_t *this)
1172
0
{
1173
0
  return !this->config->has_option(this->config, OPT_NO_POLICIES);
1174
0
}
1175
1176
/**
1177
 * Check if policy updates are required
1178
 */
1179
static bool require_policy_update(private_child_sa_t *this)
1180
0
{
1181
0
  kernel_feature_t f;
1182
1183
0
  if (!require_policies(this))
1184
0
  {
1185
0
    return FALSE;
1186
0
  }
1187
1188
0
  f = charon->kernel->get_features(charon->kernel);
1189
0
  return !(f & KERNEL_NO_POLICY_UPDATES);
1190
0
}
1191
1192
/**
1193
 * Prepare SA config to install/delete policies
1194
 */
1195
static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
1196
               ipsec_sa_cfg_t *other_sa)
1197
0
{
1198
0
  enumerator_t *enumerator;
1199
1200
0
  *my_sa = (ipsec_sa_cfg_t){
1201
0
    .mode = this->mode,
1202
0
    .reqid = this->reqid,
1203
0
    .ipcomp = {
1204
0
      .transform = this->ipcomp,
1205
0
    },
1206
0
  };
1207
0
  *other_sa = *my_sa;
1208
1209
0
  my_sa->ipcomp.cpi = this->my_cpi;
1210
0
  other_sa->ipcomp.cpi = this->other_cpi;
1211
1212
0
  if (this->protocol == PROTO_ESP)
1213
0
  {
1214
0
    my_sa->esp.use = TRUE;
1215
0
    my_sa->esp.spi = this->my_spi;
1216
0
    other_sa->esp.use = TRUE;
1217
0
    other_sa->esp.spi = this->other_spi;
1218
0
  }
1219
0
  else
1220
0
  {
1221
0
    my_sa->ah.use = TRUE;
1222
0
    my_sa->ah.spi = this->my_spi;
1223
0
    other_sa->ah.use = TRUE;
1224
0
    other_sa->ah.spi = this->other_spi;
1225
0
  }
1226
1227
0
  enumerator = create_policy_enumerator(this);
1228
0
  while (enumerator->enumerate(enumerator, NULL, NULL))
1229
0
  {
1230
0
    my_sa->policy_count++;
1231
0
    other_sa->policy_count++;
1232
0
  }
1233
0
  enumerator->destroy(enumerator);
1234
0
}
1235
1236
/**
1237
 * Install inbound policies: in, fwd
1238
 */
1239
static status_t install_policies_inbound(private_child_sa_t *this,
1240
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1241
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1242
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1243
  policy_priority_t priority, uint32_t manual_prio)
1244
0
{
1245
0
  kernel_ipsec_policy_id_t in_id = {
1246
0
    .dir = POLICY_IN,
1247
0
    .src_ts = other_ts,
1248
0
    .dst_ts = my_ts,
1249
0
    .mark = this->mark_in,
1250
0
    .if_id = this->if_id_in,
1251
0
    .label = label_for(this, LABEL_USE_POLICY),
1252
0
  };
1253
0
  kernel_ipsec_manage_policy_t in_policy = {
1254
0
    .type = type,
1255
0
    .prio = priority,
1256
0
    .manual_prio = manual_prio,
1257
0
    .hw_offload = this->config->get_hw_offload(this->config),
1258
0
    .src = other_addr,
1259
0
    .dst = my_addr,
1260
0
    .sa = my_sa,
1261
0
  };
1262
0
  status_t status = SUCCESS;
1263
1264
0
  status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
1265
0
  if (this->mode != MODE_TRANSPORT)
1266
0
  {
1267
0
    in_id.dir = POLICY_FWD;
1268
0
    status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
1269
0
  }
1270
0
  return status;
1271
0
}
1272
1273
/**
1274
 * Install outbound policies: out, [fwd]
1275
 */
1276
static status_t install_policies_outbound(private_child_sa_t *this,
1277
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1278
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1279
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1280
  policy_priority_t priority, uint32_t manual_prio)
1281
0
{
1282
0
  kernel_ipsec_policy_id_t out_id = {
1283
0
    .dir = POLICY_OUT,
1284
0
    .src_ts = my_ts,
1285
0
    .dst_ts = other_ts,
1286
0
    .mark = this->mark_out,
1287
0
    .if_id = this->if_id_out,
1288
0
    .interface = this->config->get_interface(this->config),
1289
0
    .label = label_for(this, LABEL_USE_POLICY),
1290
0
  };
1291
0
  kernel_ipsec_manage_policy_t out_policy = {
1292
0
    .type = type,
1293
0
    .prio = priority,
1294
0
    .manual_prio = manual_prio,
1295
0
    .hw_offload = this->config->get_hw_offload(this->config),
1296
0
    .src = my_addr,
1297
0
    .dst = other_addr,
1298
0
    .pcpu_acquires = this->per_cpu,
1299
0
    .forward_icmp = this->config->has_option(this->config, OPT_FORWARD_ICMP),
1300
0
    .sa = other_sa,
1301
0
  };
1302
0
  uint32_t reqid = other_sa->reqid;
1303
0
  status_t status = SUCCESS;
1304
1305
0
  status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
1306
1307
0
  if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1308
0
  {
1309
    /* install an "outbound" FWD policy in case there is a drop policy
1310
     * matching outbound forwarded traffic, to allow another tunnel to use
1311
     * the reversed subnets and do the same we don't set a reqid (this also
1312
     * allows the kernel backend to distinguish between the two types of
1313
     * FWD policies). To avoid problems with symmetrically overlapping
1314
     * policies of two SAs we install them with reduced priority.  As they
1315
     * basically act as bypass policies for drop policies we use a higher
1316
     * priority than is used for them. */
1317
0
    out_id.dir = POLICY_FWD;
1318
0
    other_sa->reqid = 0;
1319
0
    if (priority == POLICY_PRIORITY_DEFAULT)
1320
0
    {
1321
0
      out_policy.prio = POLICY_PRIORITY_ROUTED;
1322
0
    }
1323
0
    status |= charon->kernel->add_policy(charon->kernel, &out_id,
1324
0
                       &out_policy);
1325
    /* reset the reqid for any other further policies */
1326
0
    other_sa->reqid = reqid;
1327
0
  }
1328
0
  return status;
1329
0
}
1330
1331
/**
1332
 * Install all policies
1333
 */
1334
static status_t install_policies_internal(private_child_sa_t *this,
1335
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1336
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1337
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1338
  policy_priority_t priority, uint32_t manual_prio, bool outbound)
1339
0
{
1340
0
  status_t status = SUCCESS;
1341
1342
0
  status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
1343
0
            other_ts, my_sa, other_sa, type, priority, manual_prio);
1344
0
  if (outbound)
1345
0
  {
1346
0
    status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
1347
0
            other_ts, my_sa, other_sa, type, priority, manual_prio);
1348
0
  }
1349
0
  return status;
1350
0
}
1351
1352
/**
1353
 * Delete inbound policies: in, fwd
1354
 */
1355
static void del_policies_inbound(private_child_sa_t *this,
1356
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1357
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1358
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1359
  policy_priority_t priority, uint32_t manual_prio)
1360
0
{
1361
0
  kernel_ipsec_policy_id_t in_id = {
1362
0
    .dir = POLICY_IN,
1363
0
    .src_ts = other_ts,
1364
0
    .dst_ts = my_ts,
1365
0
    .mark = this->mark_in,
1366
0
    .if_id = this->if_id_in,
1367
0
    .label = label_for(this, LABEL_USE_POLICY),
1368
0
  };
1369
0
  kernel_ipsec_manage_policy_t in_policy = {
1370
0
    .type = type,
1371
0
    .prio = priority,
1372
0
    .manual_prio = manual_prio,
1373
0
    .hw_offload = this->config->get_hw_offload(this->config),
1374
0
    .src = other_addr,
1375
0
    .dst = my_addr,
1376
0
    .sa = my_sa,
1377
0
  };
1378
1379
0
  charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1380
1381
0
  if (this->mode != MODE_TRANSPORT)
1382
0
  {
1383
0
    in_id.dir = POLICY_FWD;
1384
0
    charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1385
0
  }
1386
0
}
1387
1388
/**
1389
 * Delete outbound policies: out, [fwd]
1390
 */
1391
static void del_policies_outbound(private_child_sa_t *this,
1392
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1393
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1394
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1395
  policy_priority_t priority, uint32_t manual_prio)
1396
0
{
1397
0
  kernel_ipsec_policy_id_t out_id = {
1398
0
    .dir = POLICY_OUT,
1399
0
    .src_ts = my_ts,
1400
0
    .dst_ts = other_ts,
1401
0
    .mark = this->mark_out,
1402
0
    .if_id = this->if_id_out,
1403
0
    .interface = this->config->get_interface(this->config),
1404
0
    .label = label_for(this, LABEL_USE_POLICY),
1405
0
  };
1406
0
  kernel_ipsec_manage_policy_t out_policy = {
1407
0
    .type = type,
1408
0
    .prio = priority,
1409
0
    .manual_prio = manual_prio,
1410
0
    .hw_offload = this->config->get_hw_offload(this->config),
1411
0
    .src = my_addr,
1412
0
    .dst = other_addr,
1413
0
    .pcpu_acquires = this->per_cpu,
1414
0
    .forward_icmp = this->config->has_option(this->config, OPT_FORWARD_ICMP),
1415
0
    .sa = other_sa,
1416
0
  };
1417
0
  uint32_t reqid = other_sa->reqid;
1418
1419
0
  charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1420
1421
0
  if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1422
0
  {
1423
0
    out_id.dir = POLICY_FWD;
1424
0
    other_sa->reqid = 0;
1425
0
    if (priority == POLICY_PRIORITY_DEFAULT)
1426
0
    {
1427
0
      out_policy.prio = POLICY_PRIORITY_ROUTED;
1428
0
    }
1429
0
    charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1430
0
    other_sa->reqid = reqid;
1431
0
  }
1432
0
}
1433
1434
/**
1435
 * Delete in- and outbound policies
1436
 */
1437
static void del_policies_internal(private_child_sa_t *this,
1438
  host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1439
  traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1440
  ipsec_sa_cfg_t *other_sa, policy_type_t type,
1441
  policy_priority_t priority, uint32_t manual_prio, bool outbound)
1442
0
{
1443
0
  if (outbound)
1444
0
  {
1445
0
    del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1446
0
            other_sa, type, priority, manual_prio);
1447
0
  }
1448
0
  del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1449
0
            other_sa, type, priority, manual_prio);
1450
0
}
1451
1452
METHOD(child_sa_t, set_policies, void,
1453
     private_child_sa_t *this, linked_list_t *my_ts_list,
1454
     linked_list_t *other_ts_list)
1455
0
{
1456
0
  enumerator_t *enumerator;
1457
0
  traffic_selector_t *my_ts, *other_ts;
1458
1459
0
  if (array_count(this->my_ts))
1460
0
  {
1461
0
    array_destroy_offset(this->my_ts,
1462
0
               offsetof(traffic_selector_t, destroy));
1463
0
    this->my_ts = array_create(0, 0);
1464
0
  }
1465
0
  enumerator = my_ts_list->create_enumerator(my_ts_list);
1466
0
  while (enumerator->enumerate(enumerator, &my_ts))
1467
0
  {
1468
0
    array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts));
1469
0
  }
1470
0
  enumerator->destroy(enumerator);
1471
0
  array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
1472
1473
0
  if (array_count(this->other_ts))
1474
0
  {
1475
0
    array_destroy_offset(this->other_ts,
1476
0
               offsetof(traffic_selector_t, destroy));
1477
0
    this->other_ts = array_create(0, 0);
1478
0
  }
1479
0
  enumerator = other_ts_list->create_enumerator(other_ts_list);
1480
0
  while (enumerator->enumerate(enumerator, &other_ts))
1481
0
  {
1482
0
    array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts));
1483
0
  }
1484
0
  enumerator->destroy(enumerator);
1485
0
  array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
1486
0
}
1487
1488
METHOD(child_sa_t, install_policies, status_t,
1489
     private_child_sa_t *this)
1490
0
{
1491
0
  enumerator_t *enumerator;
1492
0
  traffic_selector_t *my_ts, *other_ts;
1493
0
  status_t status = SUCCESS;
1494
0
  bool install_outbound = FALSE;
1495
1496
0
  if (!this->reqid_allocated && !this->static_reqid)
1497
0
  {
1498
0
    status = alloc_reqid(this, this->my_ts, this->other_ts, &this->reqid);
1499
0
    if (status != SUCCESS)
1500
0
    {
1501
0
      return status;
1502
0
    }
1503
0
    this->reqid_allocated = TRUE;
1504
0
  }
1505
1506
0
  if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
1507
0
  {
1508
0
    install_outbound = TRUE;
1509
0
    this->outbound_state |= CHILD_OUTBOUND_POLICIES;
1510
0
  }
1511
1512
0
  if (require_policies(this))
1513
0
  {
1514
0
    policy_priority_t priority;
1515
0
    ipsec_sa_cfg_t my_sa, other_sa;
1516
0
    uint32_t manual_prio;
1517
1518
0
    prepare_sa_cfg(this, &my_sa, &other_sa);
1519
0
    manual_prio = this->config->get_manual_prio(this->config);
1520
1521
    /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
1522
     * entry) we install a trap policy */
1523
0
    this->trap = this->state == CHILD_CREATED;
1524
0
    priority = this->trap ? POLICY_PRIORITY_ROUTED
1525
0
                : POLICY_PRIORITY_DEFAULT;
1526
1527
    /* enumerate pairs of traffic selectors */
1528
0
    enumerator = create_policy_enumerator(this);
1529
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1530
0
    {
1531
0
      status |= install_policies_internal(this, this->my_addr,
1532
0
                  this->other_addr, my_ts, other_ts,
1533
0
                  &my_sa, &other_sa, POLICY_IPSEC, priority,
1534
0
                  manual_prio, install_outbound);
1535
0
      if (status != SUCCESS)
1536
0
      {
1537
0
        break;
1538
0
      }
1539
0
    }
1540
0
    enumerator->destroy(enumerator);
1541
0
  }
1542
1543
0
  if (status == SUCCESS && this->trap)
1544
0
  {
1545
0
    set_state(this, CHILD_ROUTED);
1546
0
  }
1547
0
  return status;
1548
0
}
1549
1550
/**
1551
 * Check if we can install the outbound SA immediately.
1552
 *
1553
 * If the kernel supports installing SPIs with policies, we can do so as it
1554
 * will only be used once we update the policies.
1555
 *
1556
 * However, if we use labels with SELinux, we can't as we don't set SPIs
1557
 * on the policy in order to match SAs with other labels that match the generic
1558
 * label that's used on the policies. The same is the case for per-CPU SAs.
1559
 */
1560
static bool install_outbound_immediately(private_child_sa_t *this)
1561
0
{
1562
0
  if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI &&
1563
0
    !this->per_cpu)
1564
0
  {
1565
0
    if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
1566
0
    {
1567
0
      return !this->label;
1568
0
    }
1569
0
    return TRUE;
1570
0
  }
1571
0
  return FALSE;
1572
0
}
1573
1574
METHOD(child_sa_t, register_outbound, status_t,
1575
  private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
1576
  uint16_t cpi, bool initiator, bool tfcv3)
1577
0
{
1578
0
  status_t status;
1579
1580
0
  if (install_outbound_immediately(this))
1581
0
  {
1582
0
    status = install_internal(this, encr, integ, spi, cpi, initiator, FALSE,
1583
0
                  tfcv3);
1584
0
  }
1585
0
  else
1586
0
  {
1587
0
    DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
1588
0
       this->protocol);
1589
0
    DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
1590
0
       this->other_addr);
1591
1592
0
    this->other_spi = spi;
1593
0
    this->other_cpi = cpi;
1594
0
    this->encr_r = chunk_clone(encr);
1595
0
    this->integ_r = chunk_clone(integ);
1596
0
    this->initiator = initiator;
1597
0
    this->tfcv3 = tfcv3;
1598
0
    status = SUCCESS;
1599
0
  }
1600
0
  this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
1601
0
  return status;
1602
0
}
1603
1604
METHOD(child_sa_t, install_outbound, status_t,
1605
  private_child_sa_t *this)
1606
0
{
1607
0
  enumerator_t *enumerator;
1608
0
  traffic_selector_t *my_ts, *other_ts;
1609
0
  status_t status = SUCCESS;
1610
1611
0
  if (!(this->outbound_state & CHILD_OUTBOUND_SA))
1612
0
  {
1613
0
    status = install_internal(this, this->encr_r, this->integ_r,
1614
0
                  this->other_spi, this->other_cpi,
1615
0
                  this->initiator, FALSE, this->tfcv3);
1616
0
    chunk_clear(&this->encr_r);
1617
0
    chunk_clear(&this->integ_r);
1618
0
  }
1619
0
  this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
1620
0
  if (status != SUCCESS)
1621
0
  {
1622
0
    return status;
1623
0
  }
1624
0
  if (require_policies(this) &&
1625
0
    !(this->outbound_state & CHILD_OUTBOUND_POLICIES))
1626
0
  {
1627
0
    ipsec_sa_cfg_t my_sa, other_sa;
1628
0
    uint32_t manual_prio;
1629
1630
0
    prepare_sa_cfg(this, &my_sa, &other_sa);
1631
0
    manual_prio = this->config->get_manual_prio(this->config);
1632
1633
0
    enumerator = create_policy_enumerator(this);
1634
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1635
0
    {
1636
0
      status |= install_policies_outbound(this, this->my_addr,
1637
0
                  this->other_addr, my_ts, other_ts,
1638
0
                  &my_sa, &other_sa, POLICY_IPSEC,
1639
0
                  POLICY_PRIORITY_DEFAULT, manual_prio);
1640
0
      if (status != SUCCESS)
1641
0
      {
1642
0
        break;
1643
0
      }
1644
0
    }
1645
0
    enumerator->destroy(enumerator);
1646
0
  }
1647
0
  this->outbound_state |= CHILD_OUTBOUND_POLICIES;
1648
0
  return status;
1649
0
}
1650
1651
METHOD(child_sa_t, remove_outbound, void,
1652
  private_child_sa_t *this)
1653
0
{
1654
0
  enumerator_t *enumerator;
1655
0
  traffic_selector_t *my_ts, *other_ts;
1656
1657
0
  if (!(this->outbound_state & CHILD_OUTBOUND_SA))
1658
0
  {
1659
0
    if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
1660
0
    {
1661
0
      chunk_clear(&this->encr_r);
1662
0
      chunk_clear(&this->integ_r);
1663
0
      this->outbound_state = CHILD_OUTBOUND_NONE;
1664
0
    }
1665
0
    return;
1666
0
  }
1667
1668
0
  if (require_policies(this) &&
1669
0
    (this->outbound_state & CHILD_OUTBOUND_POLICIES))
1670
0
  {
1671
0
    ipsec_sa_cfg_t my_sa, other_sa;
1672
0
    uint32_t manual_prio;
1673
1674
0
    prepare_sa_cfg(this, &my_sa, &other_sa);
1675
0
    manual_prio = this->config->get_manual_prio(this->config);
1676
1677
0
    enumerator = create_policy_enumerator(this);
1678
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1679
0
    {
1680
0
      del_policies_outbound(this, this->my_addr, this->other_addr,
1681
0
                  my_ts, other_ts, &my_sa, &other_sa,
1682
0
                  POLICY_IPSEC, POLICY_PRIORITY_DEFAULT,
1683
0
                  manual_prio);
1684
0
    }
1685
0
    enumerator->destroy(enumerator);
1686
0
  }
1687
1688
0
  kernel_ipsec_sa_id_t id = {
1689
0
    .src = this->my_addr,
1690
0
    .dst = this->other_addr,
1691
0
    .spi = this->other_spi,
1692
0
    .proto = proto_ike2ip(this->protocol),
1693
0
    .mark = this->mark_out,
1694
0
    .if_id = this->if_id_out,
1695
0
  };
1696
0
  kernel_ipsec_del_sa_t sa = {
1697
0
    .cpi = this->other_cpi,
1698
0
  };
1699
0
  charon->kernel->del_sa(charon->kernel, &id, &sa);
1700
0
  this->outbound_state = CHILD_OUTBOUND_NONE;
1701
0
}
1702
1703
METHOD(child_sa_t, set_rekey_sa, void,
1704
  private_child_sa_t *this, child_sa_t *sa)
1705
0
{
1706
0
  this->rekey_sa = sa;
1707
0
}
1708
1709
METHOD(child_sa_t, get_rekey_sa, child_sa_t*,
1710
  private_child_sa_t *this)
1711
0
{
1712
0
  return this->rekey_sa;
1713
0
}
1714
1715
CALLBACK(reinstall_vip, void,
1716
  host_t *vip, va_list args)
1717
0
{
1718
0
  host_t *me;
1719
0
  char *iface;
1720
1721
0
  VA_ARGS_VGET(args, me);
1722
0
  if (charon->kernel->get_interface(charon->kernel, me, &iface))
1723
0
  {
1724
0
    charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
1725
0
    charon->kernel->add_ip(charon->kernel, vip, -1, iface);
1726
0
    free(iface);
1727
0
  }
1728
0
}
1729
1730
/**
1731
 * Update addresses and encap state of IPsec SAs in the kernel
1732
 */
1733
static status_t update_sas(private_child_sa_t *this, host_t *me, host_t *other,
1734
               bool encap, uint32_t reqid)
1735
0
{
1736
  /* update our (initiator) SA */
1737
0
  if (this->inbound_installed)
1738
0
  {
1739
0
    kernel_ipsec_sa_id_t id = {
1740
0
      .src = this->other_addr,
1741
0
      .dst = this->my_addr,
1742
0
      .spi = this->my_spi,
1743
0
      .proto = proto_ike2ip(this->protocol),
1744
0
      .mark = mark_in_sa(this),
1745
0
      .if_id = this->if_id_in,
1746
0
    };
1747
0
    kernel_ipsec_update_sa_t sa = {
1748
0
      .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
1749
0
      .new_src = other,
1750
0
      .new_dst = me,
1751
0
      .encap = this->encap,
1752
0
      .new_encap = encap,
1753
0
      .new_reqid = reqid,
1754
0
    };
1755
0
    if (charon->kernel->update_sa(charon->kernel, &id,
1756
0
                    &sa) == NOT_SUPPORTED)
1757
0
    {
1758
0
      return NOT_SUPPORTED;
1759
0
    }
1760
0
  }
1761
1762
  /* update his (responder) SA */
1763
0
  if (this->outbound_state & CHILD_OUTBOUND_SA)
1764
0
  {
1765
0
    kernel_ipsec_sa_id_t id = {
1766
0
      .src = this->my_addr,
1767
0
      .dst = this->other_addr,
1768
0
      .spi = this->other_spi,
1769
0
      .proto = proto_ike2ip(this->protocol),
1770
0
      .mark = this->mark_out,
1771
0
      .if_id = this->if_id_out,
1772
0
    };
1773
0
    kernel_ipsec_update_sa_t sa = {
1774
0
      .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
1775
0
      .new_src = me,
1776
0
      .new_dst = other,
1777
0
      .encap = this->encap,
1778
0
      .new_encap = encap,
1779
0
      .new_reqid = reqid,
1780
0
    };
1781
0
    if (charon->kernel->update_sa(charon->kernel, &id,
1782
0
                    &sa) == NOT_SUPPORTED)
1783
0
    {
1784
0
      return NOT_SUPPORTED;
1785
0
    }
1786
0
  }
1787
  /* we currently ignore the actual return values above */
1788
0
  return SUCCESS;
1789
0
}
1790
1791
/**
1792
 * Fill the second list with copies of the given traffic selectors updating
1793
 * dynamic traffic selectors based on the given addresses.
1794
 */
1795
static void update_ts(host_t *old_host, host_t *new_host, array_t *old_list,
1796
            array_t *new_list)
1797
0
{
1798
0
  enumerator_t *enumerator;
1799
0
  traffic_selector_t *old_ts, *new_ts;
1800
1801
0
  enumerator = array_create_enumerator(old_list);
1802
0
  while (enumerator->enumerate(enumerator, &old_ts))
1803
0
  {
1804
0
    new_ts = old_ts->clone(old_ts);
1805
0
    if (new_ts->is_host(new_ts, old_host))
1806
0
    {
1807
0
      new_ts->set_address(new_ts, new_host);
1808
0
    }
1809
0
    array_insert(new_list, ARRAY_TAIL, new_ts);
1810
0
  }
1811
0
  enumerator->destroy(enumerator);
1812
0
  array_sort(new_list, (void*)traffic_selector_cmp, NULL);
1813
0
}
1814
1815
METHOD(child_sa_t, update, status_t,
1816
  private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
1817
  bool encap)
1818
0
{
1819
0
  child_sa_state_t old;
1820
0
  bool transport_proxy_mode;
1821
1822
  /* anything changed at all? */
1823
0
  if (me->equals(me, this->my_addr) &&
1824
0
    other->equals(other, this->other_addr) && this->encap == encap)
1825
0
  {
1826
0
    return SUCCESS;
1827
0
  }
1828
1829
0
  old = this->state;
1830
0
  set_state(this, CHILD_UPDATING);
1831
0
  transport_proxy_mode = this->mode == MODE_TRANSPORT &&
1832
0
               this->config->has_option(this->config,
1833
0
                          OPT_PROXY_MODE);
1834
1835
0
  if (require_policy_update(this) && array_count(this->my_ts) &&
1836
0
    array_count(this->other_ts))
1837
0
  {
1838
0
    ipsec_sa_cfg_t my_sa, other_sa;
1839
0
    enumerator_t *enumerator;
1840
0
    traffic_selector_t *my_ts, *other_ts;
1841
0
    array_t *new_my_ts = NULL, *new_other_ts = NULL;
1842
0
    policy_priority_t priority;
1843
0
    uint32_t manual_prio, new_reqid = 0;
1844
0
    status_t state;
1845
0
    bool outbound;
1846
1847
0
    prepare_sa_cfg(this, &my_sa, &other_sa);
1848
0
    manual_prio = this->config->get_manual_prio(this->config);
1849
0
    priority = this->trap ? POLICY_PRIORITY_ROUTED
1850
0
                : POLICY_PRIORITY_DEFAULT;
1851
0
    outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) || this->trap;
1852
1853
0
    enumerator = create_policy_enumerator(this);
1854
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1855
0
    {
1856
0
      if (!new_my_ts && !me->ip_equals(me, this->my_addr) &&
1857
0
        my_ts->is_host(my_ts, this->my_addr))
1858
0
      {
1859
0
        new_my_ts = array_create(0, 0);
1860
0
      }
1861
0
      if (!new_other_ts && !other->ip_equals(other, this->other_addr) &&
1862
0
        other_ts->is_host(other_ts, this->other_addr))
1863
0
      {
1864
0
        new_other_ts = array_create(0, 0);
1865
0
      }
1866
      /* install drop policy to avoid traffic leaks, acquires etc. */
1867
0
      if (outbound)
1868
0
      {
1869
0
        install_policies_outbound(this, this->my_addr, this->other_addr,
1870
0
              my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
1871
0
              POLICY_PRIORITY_DEFAULT, manual_prio);
1872
0
      }
1873
      /* remove old policies */
1874
0
      del_policies_internal(this, this->my_addr, this->other_addr,
1875
0
            my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
1876
0
            priority, manual_prio, outbound);
1877
0
    }
1878
0
    enumerator->destroy(enumerator);
1879
1880
0
    if (new_my_ts)
1881
0
    {
1882
0
      update_ts(this->my_addr, me, this->my_ts, new_my_ts);
1883
0
    }
1884
0
    if (new_other_ts)
1885
0
    {
1886
0
      update_ts(this->other_addr, other, this->other_ts, new_other_ts);
1887
0
    }
1888
0
    if (this->reqid_allocated && (new_my_ts || new_other_ts))
1889
0
    {
1890
      /* if we allocated a reqid with the previous TS, we have to get a
1891
       * new one that matches the updated TS */
1892
0
      if (alloc_reqid(this, new_my_ts ?: this->my_ts,
1893
0
              new_other_ts ?: this->other_ts, &new_reqid) != SUCCESS)
1894
0
      {
1895
0
        DBG1(DBG_CHD, "allocating new reqid for updated SA failed");
1896
0
      }
1897
0
    }
1898
1899
    /* update the IPsec SAs */
1900
0
    state = update_sas(this, me, other, encap, new_reqid);
1901
1902
    /* install new/updated policies only if we were able to update the
1903
     * SAs, otherwise we reinstall the old policies further below */
1904
0
    if (state != NOT_SUPPORTED)
1905
0
    {
1906
      /* we reinstall the virtual IP to handle interface roaming
1907
       * correctly */
1908
0
      if (vips)
1909
0
      {
1910
0
        vips->invoke_function(vips, reinstall_vip, me);
1911
0
      }
1912
0
      if (new_reqid)
1913
0
      {
1914
0
        my_sa.reqid = other_sa.reqid = new_reqid;
1915
0
      }
1916
0
      enumerator = create_policy_enumerator_internal(
1917
0
                        new_my_ts ?: this->my_ts,
1918
0
                        new_other_ts ?: this->other_ts);
1919
0
      while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1920
0
      {
1921
0
        install_policies_internal(this, me, other, my_ts, other_ts,
1922
0
                      &my_sa, &other_sa, POLICY_IPSEC,
1923
0
                      priority, manual_prio, outbound);
1924
0
      }
1925
0
      enumerator->destroy(enumerator);
1926
0
      if (new_reqid)
1927
0
      {
1928
0
        my_sa.reqid = other_sa.reqid = this->reqid;
1929
0
      }
1930
0
    }
1931
1932
0
    enumerator = create_policy_enumerator(this);
1933
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1934
0
    {
1935
      /* reinstall the previous policies if we can't update the SAs */
1936
0
      if (state == NOT_SUPPORTED)
1937
0
      {
1938
0
        install_policies_internal(this, this->my_addr, this->other_addr,
1939
0
            my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
1940
0
            priority, manual_prio, outbound);
1941
0
      }
1942
      /* remove the drop policy */
1943
0
      if (outbound)
1944
0
      {
1945
0
        del_policies_outbound(this, this->my_addr, this->other_addr,
1946
0
            my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
1947
0
            POLICY_PRIORITY_DEFAULT, manual_prio);
1948
0
      }
1949
0
    }
1950
0
    enumerator->destroy(enumerator);
1951
1952
0
    if (state == NOT_SUPPORTED)
1953
0
    {
1954
0
      if (new_reqid &&
1955
0
        charon->kernel->release_reqid(charon->kernel,
1956
0
                        new_reqid) != SUCCESS)
1957
0
      {
1958
0
        DBG1(DBG_CHD, "releasing reqid %u failed", new_reqid);
1959
0
      }
1960
0
      array_destroy_offset(new_my_ts,
1961
0
                 offsetof(traffic_selector_t, destroy));
1962
0
      array_destroy_offset(new_other_ts,
1963
0
                 offsetof(traffic_selector_t, destroy));
1964
0
      set_state(this, old);
1965
0
      return NOT_SUPPORTED;
1966
0
    }
1967
1968
0
    if (new_reqid)
1969
0
    {
1970
0
      if (charon->kernel->release_reqid(charon->kernel,
1971
0
                        this->reqid) != SUCCESS)
1972
0
      {
1973
0
        DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
1974
0
      }
1975
0
      DBG1(DBG_CHD, "replaced reqid %u with reqid %u for updated "
1976
0
         "CHILD_SA %s{%d}", this->reqid, new_reqid, get_name(this),
1977
0
         this->unique_id);
1978
0
      this->reqid = new_reqid;
1979
0
    }
1980
0
    if (new_my_ts)
1981
0
    {
1982
0
      array_destroy_offset(this->my_ts,
1983
0
                 offsetof(traffic_selector_t, destroy));
1984
0
      this->my_ts = new_my_ts;
1985
0
    }
1986
0
    if (new_other_ts)
1987
0
    {
1988
0
      array_destroy_offset(this->other_ts,
1989
0
                 offsetof(traffic_selector_t, destroy));
1990
0
      this->other_ts = new_other_ts;
1991
0
    }
1992
0
  }
1993
0
  else if (!transport_proxy_mode)
1994
0
  {
1995
0
    if (update_sas(this, me, other, encap, 0) == NOT_SUPPORTED)
1996
0
    {
1997
0
      set_state(this, old);
1998
0
      return NOT_SUPPORTED;
1999
0
    }
2000
0
  }
2001
2002
0
  if (!transport_proxy_mode)
2003
0
  {
2004
    /* apply hosts */
2005
0
    if (!me->equals(me, this->my_addr))
2006
0
    {
2007
0
      this->my_addr->destroy(this->my_addr);
2008
0
      this->my_addr = me->clone(me);
2009
0
    }
2010
0
    if (!other->equals(other, this->other_addr))
2011
0
    {
2012
0
      this->other_addr->destroy(this->other_addr);
2013
0
      this->other_addr = other->clone(other);
2014
0
    }
2015
0
  }
2016
2017
0
  this->encap = encap;
2018
0
  set_state(this, old);
2019
2020
0
  return SUCCESS;
2021
0
}
2022
2023
METHOD(child_sa_t, destroy, void,
2024
     private_child_sa_t *this)
2025
0
{
2026
0
  enumerator_t *enumerator;
2027
0
  traffic_selector_t *my_ts, *other_ts;
2028
0
  policy_priority_t priority;
2029
2030
0
  priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
2031
2032
0
  set_state(this, CHILD_DESTROYING);
2033
2034
0
  if (require_policies(this))
2035
0
  {
2036
0
    ipsec_sa_cfg_t my_sa, other_sa;
2037
0
    uint32_t manual_prio;
2038
0
    bool del_outbound;
2039
2040
0
    prepare_sa_cfg(this, &my_sa, &other_sa);
2041
0
    manual_prio = this->config->get_manual_prio(this->config);
2042
0
    del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
2043
0
            this->trap;
2044
2045
    /* delete all policies in the kernel */
2046
0
    enumerator = create_policy_enumerator(this);
2047
0
    while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
2048
0
    {
2049
0
      del_policies_internal(this, this->my_addr,
2050
0
            this->other_addr, my_ts, other_ts, &my_sa, &other_sa,
2051
0
            POLICY_IPSEC, priority, manual_prio, del_outbound);
2052
0
    }
2053
0
    enumerator->destroy(enumerator);
2054
0
  }
2055
2056
  /* delete SAs in the kernel, if they are set up, inbound is always deleted
2057
   * to remove allocated SPIs */
2058
0
  if (this->my_spi)
2059
0
  {
2060
0
    kernel_ipsec_sa_id_t id = {
2061
0
      .src = this->other_addr,
2062
0
      .dst = this->my_addr,
2063
0
      .spi = this->my_spi,
2064
0
      .proto = proto_ike2ip(this->protocol),
2065
0
      .mark = mark_in_sa(this),
2066
0
      .if_id = this->if_id_in,
2067
0
    };
2068
0
    kernel_ipsec_del_sa_t sa = {
2069
0
      .cpi = this->my_cpi,
2070
0
    };
2071
0
    charon->kernel->del_sa(charon->kernel, &id, &sa);
2072
0
  }
2073
0
  if (this->outbound_state & CHILD_OUTBOUND_SA)
2074
0
  {
2075
0
    kernel_ipsec_sa_id_t id = {
2076
0
      .src = this->my_addr,
2077
0
      .dst = this->other_addr,
2078
0
      .spi = this->other_spi,
2079
0
      .proto = proto_ike2ip(this->protocol),
2080
0
      .mark = this->mark_out,
2081
0
      .if_id = this->if_id_out,
2082
0
    };
2083
0
    kernel_ipsec_del_sa_t sa = {
2084
0
      .cpi = this->other_cpi,
2085
0
    };
2086
0
    charon->kernel->del_sa(charon->kernel, &id, &sa);
2087
0
  }
2088
2089
0
  if (this->reqid_allocated || (!this->static_reqid && this->reqid))
2090
0
  {
2091
0
    if (charon->kernel->release_reqid(charon->kernel,
2092
0
                      this->reqid) != SUCCESS)
2093
0
    {
2094
0
      DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
2095
0
    }
2096
0
  }
2097
2098
0
  array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
2099
0
  array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
2100
0
  this->my_addr->destroy(this->my_addr);
2101
0
  this->other_addr->destroy(this->other_addr);
2102
0
  DESTROY_IF(this->proposal);
2103
0
  DESTROY_IF(this->label);
2104
0
  this->config->destroy(this->config);
2105
0
  chunk_clear(&this->encr_r);
2106
0
  chunk_clear(&this->integ_r);
2107
0
  free(this);
2108
0
}
2109
2110
/**
2111
 * Get proxy address for one side, if any
2112
 */
2113
static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
2114
0
{
2115
0
  host_t *host = NULL;
2116
0
  uint8_t mask;
2117
0
  enumerator_t *enumerator;
2118
0
  linked_list_t *ts_list, *list;
2119
0
  traffic_selector_t *ts;
2120
2121
0
  list = linked_list_create_with_items(ike, NULL);
2122
0
  ts_list = config->get_traffic_selectors(config, local, list);
2123
0
  list->destroy(list);
2124
2125
0
  enumerator = ts_list->create_enumerator(ts_list);
2126
0
  while (enumerator->enumerate(enumerator, &ts))
2127
0
  {
2128
0
    if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask))
2129
0
    {
2130
0
      DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H",
2131
0
         local ? "my" : "other", ike, host);
2132
0
      break;
2133
0
    }
2134
0
  }
2135
0
  enumerator->destroy(enumerator);
2136
0
  ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
2137
2138
0
  if (!host)
2139
0
  {
2140
0
    host = ike->clone(ike);
2141
0
  }
2142
0
  return host;
2143
0
}
2144
2145
/*
2146
 * Described in header
2147
 */
2148
child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
2149
              child_sa_create_t *data)
2150
0
{
2151
0
  private_child_sa_t *this;
2152
0
  static refcount_t unique_id = 0;
2153
2154
0
  INIT(this,
2155
0
    .public = {
2156
0
      .get_name = _get_name,
2157
0
      .get_reqid = _get_reqid,
2158
0
      .get_reqid_ref = _get_reqid_ref,
2159
0
      .get_unique_id = _get_unique_id,
2160
0
      .get_config = _get_config,
2161
0
      .get_state = _get_state,
2162
0
      .set_state = _set_state,
2163
0
      .get_outbound_state = _get_outbound_state,
2164
0
      .get_spi = _get_spi,
2165
0
      .get_cpi = _get_cpi,
2166
0
      .get_protocol = _get_protocol,
2167
0
      .set_protocol = _set_protocol,
2168
0
      .get_mode = _get_mode,
2169
0
      .set_mode = _set_mode,
2170
0
      .get_proposal = _get_proposal,
2171
0
      .set_proposal = _set_proposal,
2172
0
      .get_lifetime = _get_lifetime,
2173
0
      .get_installtime = _get_installtime,
2174
0
      .get_usestats = _get_usestats,
2175
0
      .get_mark = _get_mark,
2176
0
      .get_if_id = _get_if_id,
2177
0
      .get_label = _get_label,
2178
0
      .get_cpu = _get_cpu,
2179
0
      .set_per_cpu = _set_per_cpu,
2180
0
      .use_per_cpu = _use_per_cpu,
2181
0
      .get_acquire_seq = _get_acquire_seq,
2182
0
      .set_acquire_seq = _set_acquire_seq,
2183
0
      .has_encap = _has_encap,
2184
0
      .get_ipcomp = _get_ipcomp,
2185
0
      .set_ipcomp = _set_ipcomp,
2186
0
      .set_iptfs_dont_fragment = _set_iptfs_dont_fragment,
2187
0
      .get_close_action = _get_close_action,
2188
0
      .set_close_action = _set_close_action,
2189
0
      .get_dpd_action = _get_dpd_action,
2190
0
      .set_dpd_action = _set_dpd_action,
2191
0
      .alloc_spi = _alloc_spi,
2192
0
      .alloc_cpi = _alloc_cpi,
2193
0
      .install = _install,
2194
0
      .register_outbound = _register_outbound,
2195
0
      .install_outbound = _install_outbound,
2196
0
      .remove_outbound = _remove_outbound,
2197
0
      .set_rekey_sa = _set_rekey_sa,
2198
0
      .get_rekey_sa = _get_rekey_sa,
2199
0
      .update = _update,
2200
0
      .set_policies = _set_policies,
2201
0
      .install_policies = _install_policies,
2202
0
      .create_ts_enumerator = _create_ts_enumerator,
2203
0
      .create_policy_enumerator = _create_policy_enumerator,
2204
0
      .destroy = _destroy,
2205
0
    },
2206
0
    .encap = data->encap,
2207
0
    .ipcomp = IPCOMP_NONE,
2208
0
    .state = CHILD_CREATED,
2209
0
    .my_ts = array_create(0, 0),
2210
0
    .other_ts = array_create(0, 0),
2211
0
    .protocol = PROTO_NONE,
2212
0
    .mode = MODE_TUNNEL,
2213
0
    .close_action = config->get_close_action(config),
2214
0
    .dpd_action = config->get_dpd_action(config),
2215
0
    .reqid = config->get_reqid(config),
2216
0
    .unique_id = ref_get_nonzero(&unique_id),
2217
0
    .mark_in = config->get_mark(config, TRUE),
2218
0
    .mark_out = config->get_mark(config, FALSE),
2219
0
    .if_id_in = config->get_if_id(config, TRUE) ?: data->if_id_in_def,
2220
0
    .if_id_out = config->get_if_id(config, FALSE) ?: data->if_id_out_def,
2221
0
    .label = data->label ? data->label->clone(data->label) : NULL,
2222
0
    .cpu = data->cpu,
2223
0
    .per_cpu = data->per_cpu,
2224
0
    .seq = data->seq,
2225
0
    .install_time = time_monotonic(NULL),
2226
0
    .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
2227
0
  );
2228
2229
0
  this->config = config;
2230
0
  config->get_ref(config);
2231
2232
0
  if (data->mark_in)
2233
0
  {
2234
0
    this->mark_in.value = data->mark_in;
2235
0
  }
2236
0
  if (data->mark_out)
2237
0
  {
2238
0
    this->mark_out.value = data->mark_out;
2239
0
  }
2240
0
  if (data->if_id_in)
2241
0
  {
2242
0
    this->if_id_in = data->if_id_in;
2243
0
  }
2244
0
  if (data->if_id_out)
2245
0
  {
2246
0
    this->if_id_out = data->if_id_out;
2247
0
  }
2248
2249
0
  allocate_unique_if_ids(&this->if_id_in, &this->if_id_out);
2250
0
  allocate_unique_marks(&this->mark_in.value, &this->mark_out.value);
2251
2252
0
  if (!this->reqid)
2253
0
  {
2254
    /* reuse old reqid if we are rekeying an existing CHILD_SA and when
2255
     * initiating a trap policy. the reqid cache will generally find the
2256
     * same reqid for our selectors. but this does not work in a special
2257
     * case: if the IPsec stack does not use sequence numbers for acquires,
2258
     * an SA is triggered by a trap policy and the negotiated TS get
2259
     * narrowed, we still must reuse the same reqid to successfully replace
2260
     * the temporary SA on the kernel level. however, if sequence numbers
2261
     * are supported, the reqid will later get updated in case of narrowing
2262
     * when alloc_reqid() is called */
2263
0
    if (data->reqid &&
2264
0
      charon->kernel->ref_reqid(charon->kernel, data->reqid) == SUCCESS)
2265
0
    {
2266
0
      this->reqid = data->reqid;
2267
0
    }
2268
0
  }
2269
0
  else
2270
0
  {
2271
0
    this->static_reqid = TRUE;
2272
0
  }
2273
2274
  /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
2275
0
  if (config->get_mode(config) == MODE_TRANSPORT &&
2276
0
    config->has_option(config, OPT_PROXY_MODE))
2277
0
  {
2278
0
    this->mode = MODE_TRANSPORT;
2279
2280
0
    this->my_addr = get_proxy_addr(config, me, TRUE);
2281
0
    this->other_addr = get_proxy_addr(config, other, FALSE);
2282
0
  }
2283
0
  else
2284
0
  {
2285
0
    this->my_addr = me->clone(me);
2286
0
    this->other_addr = other->clone(other);
2287
0
  }
2288
0
  return &this->public;
2289
0
}
2290
2291
/**
2292
 * Check if the given traffic selector is contained in any of the traffic
2293
 * selectors in the given list.
2294
 */
2295
static bool is_ts_match(traffic_selector_t *to_check, array_t *list)
2296
0
{
2297
0
  traffic_selector_t *ts;
2298
0
  int i;
2299
2300
0
  for (i = 0; i < array_count(list); i++)
2301
0
  {
2302
0
    array_get(list, i, &ts);
2303
0
    if (to_check->is_contained_in(to_check, ts))
2304
0
    {
2305
0
      return TRUE;
2306
0
    }
2307
0
  }
2308
0
  return FALSE;
2309
0
}
2310
2311
/**
2312
 * Check if all given traffic selectors are contained in any of the traffic
2313
 * selectors in the given list.
2314
 */
2315
static bool is_ts_list_match(traffic_selector_list_t *to_check, array_t *list)
2316
0
{
2317
0
  enumerator_t *enumerator;
2318
0
  traffic_selector_t *ts;
2319
0
  bool matched = TRUE;
2320
2321
0
  enumerator = to_check->create_enumerator(to_check);
2322
0
  while (enumerator->enumerate(enumerator, &ts))
2323
0
  {
2324
0
    if (!is_ts_match(ts, list))
2325
0
    {
2326
0
      matched = FALSE;
2327
0
      break;
2328
0
    }
2329
0
  }
2330
0
  enumerator->destroy(enumerator);
2331
0
  return matched;
2332
0
}
2333
2334
/*
2335
 * Described in header
2336
 */
2337
bool child_sa_ts_match(child_sa_t *child, traffic_selector_t *src,
2338
             traffic_selector_t *dst)
2339
0
{
2340
0
  private_child_sa_t *this = (private_child_sa_t*)child;
2341
2342
0
  return src && dst &&
2343
0
       is_ts_match(src, this->my_ts) &&
2344
0
       is_ts_match(dst, this->other_ts);
2345
0
}
2346
2347
/*
2348
 * Described in header
2349
 */
2350
bool child_sa_ts_lists_match(child_sa_t *child, traffic_selector_list_t *src,
2351
               traffic_selector_list_t *dst)
2352
0
{
2353
0
  private_child_sa_t *this = (private_child_sa_t*)child;
2354
2355
0
  return src && dst &&
2356
0
       is_ts_list_match(src, this->my_ts) &&
2357
0
       is_ts_list_match(dst, this->other_ts);
2358
0
}