]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/plugins/ha/ha_child.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / ha / ha_child.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 *
4 * Copyright (C) secunet Security Networks AG
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "ha_child.h"
18
19 typedef struct private_ha_child_t private_ha_child_t;
20
21 /**
22 * Private data of an ha_child_t object.
23 */
24 struct private_ha_child_t {
25
26 /**
27 * Public ha_child_t interface.
28 */
29 ha_child_t public;
30
31 /**
32 * socket we use for syncing
33 */
34 ha_socket_t *socket;
35
36 /**
37 * tunnel securing sync messages
38 */
39 ha_tunnel_t *tunnel;
40
41 /**
42 * Segment handling
43 */
44 ha_segments_t *segments;
45
46 /**
47 * Kernel helper
48 */
49 ha_kernel_t *kernel;
50 };
51
52 METHOD(listener_t, child_keys, bool,
53 private_ha_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
54 bool initiator, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
55 {
56 ha_message_t *m;
57 chunk_t secret;
58 proposal_t *proposal;
59 uint16_t alg, len;
60 linked_list_t *local_ts, *remote_ts;
61 enumerator_t *enumerator;
62 traffic_selector_t *ts;
63 u_int seg_i, seg_o;
64
65 if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
66 { /* do not sync SA between nodes */
67 return TRUE;
68 }
69
70 m = ha_message_create(HA_CHILD_ADD);
71
72 m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
73 m->add_attribute(m, HA_INITIATOR, (uint8_t)initiator);
74 m->add_attribute(m, HA_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE));
75 m->add_attribute(m, HA_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE));
76 m->add_attribute(m, HA_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE));
77 m->add_attribute(m, HA_OUTBOUND_CPI, child_sa->get_cpi(child_sa, FALSE));
78 m->add_attribute(m, HA_IPSEC_MODE, child_sa->get_mode(child_sa));
79 m->add_attribute(m, HA_IPCOMP, child_sa->get_ipcomp(child_sa));
80 m->add_attribute(m, HA_CONFIG_NAME, child_sa->get_name(child_sa));
81
82 proposal = child_sa->get_proposal(child_sa);
83 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
84 {
85 m->add_attribute(m, HA_ALG_ENCR, alg);
86 if (len)
87 {
88 m->add_attribute(m, HA_ALG_ENCR_LEN, len);
89 }
90 }
91 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
92 {
93 m->add_attribute(m, HA_ALG_INTEG, alg);
94 }
95 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
96 {
97 m->add_attribute(m, HA_ALG_DH, alg);
98 }
99 if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, &alg, NULL))
100 {
101 m->add_attribute(m, HA_ESN, alg);
102 }
103 m->add_attribute(m, HA_NONCE_I, nonce_i);
104 m->add_attribute(m, HA_NONCE_R, nonce_r);
105 if (dh && dh->get_shared_secret(dh, &secret))
106 {
107 m->add_attribute(m, HA_SECRET, secret);
108 chunk_clear(&secret);
109 }
110
111 local_ts = linked_list_create();
112 remote_ts = linked_list_create();
113
114 enumerator = child_sa->create_ts_enumerator(child_sa, TRUE);
115 while (enumerator->enumerate(enumerator, &ts))
116 {
117 m->add_attribute(m, HA_LOCAL_TS, ts);
118 local_ts->insert_last(local_ts, ts);
119 }
120 enumerator->destroy(enumerator);
121
122 enumerator = child_sa->create_ts_enumerator(child_sa, FALSE);
123 while (enumerator->enumerate(enumerator, &ts))
124 {
125 m->add_attribute(m, HA_REMOTE_TS, ts);
126 remote_ts->insert_last(remote_ts, ts);
127 }
128 enumerator->destroy(enumerator);
129
130 seg_i = this->kernel->get_segment_spi(this->kernel,
131 ike_sa->get_my_host(ike_sa), child_sa->get_spi(child_sa, TRUE));
132 seg_o = this->kernel->get_segment_spi(this->kernel,
133 ike_sa->get_other_host(ike_sa), child_sa->get_spi(child_sa, FALSE));
134 DBG1(DBG_CFG, "handling HA CHILD_SA %s{%d} %#R === %#R "
135 "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
136 child_sa->get_unique_id(child_sa), local_ts, remote_ts,
137 seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
138 seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
139
140 local_ts->destroy(local_ts);
141 remote_ts->destroy(remote_ts);
142
143 this->socket->push(this->socket, m);
144 m->destroy(m);
145
146 return TRUE;
147 }
148
149 METHOD(listener_t, child_state_change, bool,
150 private_ha_child_t *this, ike_sa_t *ike_sa,
151 child_sa_t *child_sa, child_sa_state_t state)
152 {
153 if (!ike_sa ||
154 ike_sa->get_state(ike_sa) == IKE_PASSIVE ||
155 ike_sa->get_state(ike_sa) == IKE_DESTROYING)
156 { /* only sync active IKE_SAs */
157 return TRUE;
158 }
159 if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
160 { /* do not sync SA between nodes */
161 return TRUE;
162 }
163
164
165 if (state == CHILD_DESTROYING)
166 {
167 ha_message_t *m;
168
169 m = ha_message_create(HA_CHILD_DELETE);
170
171 m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
172 m->add_attribute(m, HA_INBOUND_SPI,
173 child_sa->get_spi(child_sa, TRUE));
174 this->socket->push(this->socket, m);
175 m->destroy(m);
176 }
177 return TRUE;
178 }
179
180 METHOD(ha_child_t, destroy, void,
181 private_ha_child_t *this)
182 {
183 free(this);
184 }
185
186 /**
187 * See header
188 */
189 ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
190 ha_segments_t *segments, ha_kernel_t *kernel)
191 {
192 private_ha_child_t *this;
193
194 INIT(this,
195 .public = {
196 .listener = {
197 .child_keys = _child_keys,
198 .child_state_change = _child_state_change,
199 },
200 .destroy = _destroy,
201 },
202 .socket = socket,
203 .tunnel = tunnel,
204 .segments = segments,
205 .kernel = kernel,
206 );
207
208 return &this->public;
209 }