File: ikev1_replace.c

package info (click to toggle)
libreswan 5.2-2.3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 81,644 kB
  • sloc: ansic: 129,988; sh: 32,018; xml: 20,646; python: 10,303; makefile: 3,022; javascript: 1,506; sed: 574; yacc: 511; perl: 264; awk: 52
file content (139 lines) | stat: -rw-r--r-- 4,933 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* timer event handling
 *
 * Copyright (C) 1997 Angelos D. Keromytis.
 * Copyright (C) 1998-2002,2010-2017 D. Hugh Redelmeier <hugh@mimosa.com>
 * Copyright (C) 2003-2008  Michael Richardson <mcr@xelerance.com>
 * Copyright (C) 2003-2018 Paul Wouters <paul@xelerance.com>
 * Copyright (C) 2010-2011 Tuomo Soini <tis@foobar.fi>
 * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com>
 * Copyright (C) 2013 David McCullough <ucdevel@gmail.com>
 * Copyright (C) 2013 Matt Rogers <mrogers@redhat.com>
 * Copyright (C) 2014-2021 Andrew Cagney <cagney@gnu.org>
 * Copyright (C) 2017-2018 Antony Antony <antony@phenome.org>
 * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com>
 * Copyright (C) 2009 David McCullough <david_mccullough@securecomputing.com>
 * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <https://www.gnu.org/licenses/gpl2.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#include "defs.h"
#include "state.h"
#include "connections.h"
#include "ikev1_replace.h"
#include "log.h"
#include "ipsec_doi.h"
#include "timer.h"		/* for event_*() */
#include "ikev1.h"
#include "initiate.h"

/* Replace SA with a fresh one that is similar
 *
 * Shares some logic with ipsecdoi_initiate, but not the same!
 * - we must not reuse the ISAKMP SA if we are trying to replace it!
 * - if trying to replace IPSEC SA, use ipsecdoi_initiate to build
 *   ISAKMP SA if needed.
 * - duplicate whack fd, if live.
 * Does not delete the old state -- someone else will do that.
 */

void ikev1_replace(struct state *st)
{
	/*
	 * start billing the new state.  The old state also gets
	 * billed for this function call, oops.
	 */
	threadtime_t inception = threadtime_start();

	if (IS_IKE_SA(st)) {
		/*
		 * Should this call capture_child_rekey_policy(st) or
		 * child_sa_policy(c) to capture the Child SA's
		 * policy?
		 *
		 * Probably not.
		 *
		 * When the IKE (ISAKMP) SA initiator code sees
		 * policy=LEMPTY it skips scheduling the connection as
		 * a Child SA to be initiated once the IKE SA
		 * establishes.  Instead the revival code will
		 * schedule the connection as a child.
		 */
		const struct child_policy policy = {0};
		struct connection *c = st->st_connection;
		struct ike_sa *predecessor = pexpect_ike_sa(st);
		if (c->config->aggressive) {
			aggr_outI1(c, predecessor, &policy, &inception, /*background?*/false);
		} else {
			main_outI1(c, predecessor, &policy, &inception, /*background?*/false);
		}

	} else {

		/*
		 * Start from policy in (ipsec) state, not connection.
		 * This ensures that rekeying doesn't downgrade
		 * security.  I admit that this doesn't capture
		 * everything.
		 */
		const struct child_policy policy = capture_child_rekey_policy(st);
		passert(has_child_policy(&policy));
		initiate(st->st_connection, &policy, st->st_serialno, &inception,
			 null_shunk, /*background?*/false, st->logger,
			 INITIATED_BY_REPLACE, HERE);
	}
}

void event_v1_replace(struct state *st, monotime_t now)
{
	const char *satype = IS_IKE_SA(st) ? "ISAKMP" : "IPsec";
	struct connection *c = st->st_connection;

	so_serial_t newer_sa = get_newer_sa_from_connection(st);
	if (newer_sa != SOS_NOBODY) {
		/* not very interesting: no need to replace */
		ldbg(st->logger,
		     "not replacing stale %s SA %lu; #%lu will do",
		     satype, st->st_serialno, newer_sa);
	} else if (!c->config->rekey &&
		   monotime_cmp(now, >=, monotime_add(st->st_outbound_time,
						      c->config->sa_rekey_margin))) {
		/*
		 * we observed no recent use: no need to replace
		 *
		 * The sampling effects mean that st_outbound_time
		 * could be up to SHUNT_SCAN_INTERVAL more recent
		 * than actual traffic because the sampler looks at
		 * change over that interval.
		 * st_outbound_time could also not yet reflect traffic
		 * in the last SHUNT_SCAN_INTERVAL.
		 * We expect that SHUNT_SCAN_INTERVAL is smaller than
		 * c->sa_rekey_margin so that the effects of this will
		 * be unimportant.
		 * This is just an optimization: correctness is not
		 * at stake.
		 */
		ldbg(st->logger,
		     "not replacing stale %s SA: inactive for %jds",
		     satype, deltasecs(monotime_diff(now, st->st_outbound_time)));
	} else {
		ldbg(st->logger, "replacing stale %s SA", satype);
		/*
		 * XXX: this call gets double billed -
		 * both to the state being deleted and
		 * to the new state being created.
		 */
		ikev1_replace(st);
	}

	event_delete(EVENT_v1_DPD, st);
	event_schedule(EVENT_v1_EXPIRE, st->st_replace_margin, st);
}