2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "ha_sync_ike.h"
20 typedef struct private_ha_sync_ike_t private_ha_sync_ike_t
;
23 * Private data of an ha_sync_ike_t object.
25 struct private_ha_sync_ike_t
{
28 * Public ha_sync_ike_t interface.
33 * socket we use for syncing
35 ha_sync_socket_t
*socket
;
39 * Return condition if it is set on ike_sa
41 static ike_condition_t
copy_condition(ike_sa_t
*ike_sa
, ike_condition_t cond
)
43 if (ike_sa
->has_condition(ike_sa
, cond
))
51 * Return extension if it is supported by peers IKE_SA
53 static ike_extension_t
copy_extension(ike_sa_t
*ike_sa
, ike_extension_t ext
)
55 if (ike_sa
->supports_extension(ike_sa
, ext
))
63 * Implementation of listener_t.ike_keys
65 static bool ike_keys(private_ha_sync_ike_t
*this, ike_sa_t
*ike_sa
,
66 diffie_hellman_t
*dh
, chunk_t nonce_i
, chunk_t nonce_r
,
74 if (dh
->get_shared_secret(dh
, &secret
) != SUCCESS
)
79 m
= ha_sync_message_create(HA_SYNC_IKE_ADD
);
80 m
->add_attribute(m
, HA_SYNC_IKE_ID
, ike_sa
->get_id(ike_sa
));
87 keymat
= rekey
->get_keymat(rekey
);
88 m
->add_attribute(m
, HA_SYNC_IKE_REKEY_ID
, rekey
->get_id(rekey
));
89 m
->add_attribute(m
, HA_SYNC_ALG_OLD_PRF
, keymat
->get_skd(keymat
, &skd
));
90 m
->add_attribute(m
, HA_SYNC_OLD_SKD
, skd
);
93 proposal
= ike_sa
->get_proposal(ike_sa
);
94 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &len
))
96 m
->add_attribute(m
, HA_SYNC_ALG_ENCR
, alg
);
99 m
->add_attribute(m
, HA_SYNC_ALG_ENCR_LEN
, len
);
102 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, NULL
))
104 m
->add_attribute(m
, HA_SYNC_ALG_INTEG
, alg
);
106 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, &alg
, NULL
))
108 m
->add_attribute(m
, HA_SYNC_ALG_PRF
, alg
);
110 m
->add_attribute(m
, HA_SYNC_NONCE_I
, nonce_i
);
111 m
->add_attribute(m
, HA_SYNC_NONCE_R
, nonce_r
);
112 m
->add_attribute(m
, HA_SYNC_SECRET
, secret
);
113 chunk_clear(&secret
);
115 this->socket
->push(this->socket
, m
);
122 * Implementation of listener_t.ike_state_change
124 static bool ike_state_change(private_ha_sync_ike_t
*this, ike_sa_t
*ike_sa
,
125 ike_sa_state_t state
)
127 ha_sync_message_t
*m
;
129 if (ike_sa
->get_state(ike_sa
) == IKE_PASSIVE
)
130 { /* only sync active IKE_SAs */
136 case IKE_ESTABLISHED
:
138 iterator_t
*iterator
;
139 peer_cfg_t
*peer_cfg
;
140 u_int32_t extension
, condition
;
142 identification_t
*eap_id
;
145 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
147 condition
= copy_condition(ike_sa
, COND_NAT_ANY
)
148 | copy_condition(ike_sa
, COND_NAT_HERE
)
149 | copy_condition(ike_sa
, COND_NAT_THERE
)
150 | copy_condition(ike_sa
, COND_NAT_FAKE
)
151 | copy_condition(ike_sa
, COND_EAP_AUTHENTICATED
)
152 | copy_condition(ike_sa
, COND_CERTREQ_SEEN
)
153 | copy_condition(ike_sa
, COND_ORIGINAL_INITIATOR
);
155 extension
= copy_extension(ike_sa
, EXT_NATT
)
156 | copy_extension(ike_sa
, EXT_MOBIKE
)
157 | copy_extension(ike_sa
, EXT_HASH_AND_URL
);
159 eap_id
= ike_sa
->get_eap_identity(ike_sa
);
160 id
= ike_sa
->get_id(ike_sa
);
162 m
= ha_sync_message_create(HA_SYNC_IKE_UPDATE
);
163 m
->add_attribute(m
, HA_SYNC_IKE_ID
, id
);
164 m
->add_attribute(m
, HA_SYNC_LOCAL_ID
, ike_sa
->get_my_id(ike_sa
));
165 m
->add_attribute(m
, HA_SYNC_REMOTE_ID
, ike_sa
->get_other_id(ike_sa
));
166 m
->add_attribute(m
, HA_SYNC_LOCAL_ADDR
, ike_sa
->get_my_host(ike_sa
));
167 m
->add_attribute(m
, HA_SYNC_REMOTE_ADDR
, ike_sa
->get_other_host(ike_sa
));
168 m
->add_attribute(m
, HA_SYNC_CONDITIONS
, condition
);
169 m
->add_attribute(m
, HA_SYNC_EXTENSIONS
, extension
);
170 m
->add_attribute(m
, HA_SYNC_CONFIG_NAME
, peer_cfg
->get_name(peer_cfg
));
173 m
->add_attribute(m
, HA_SYNC_EAP_ID
, eap_id
);
175 iterator
= ike_sa
->create_additional_address_iterator(ike_sa
);
176 while (iterator
->iterate(iterator
, (void**)&addr
))
178 m
->add_attribute(m
, HA_SYNC_ADDITIONAL_ADDR
, addr
);
180 iterator
->destroy(iterator
);
185 m
= ha_sync_message_create(HA_SYNC_IKE_DELETE
);
186 m
->add_attribute(m
, HA_SYNC_IKE_ID
, ike_sa
->get_id(ike_sa
));
192 this->socket
->push(this->socket
, m
);
198 * Implementation of listener_t.message
200 static bool message_hook(private_ha_sync_ike_t
*this, ike_sa_t
*ike_sa
,
201 message_t
*message
, bool incoming
)
203 if (message
->get_exchange_type(message
) != IKE_SA_INIT
&&
204 message
->get_request(message
))
205 { /* we sync on requests, but skip it on IKE_SA_INIT */
206 ha_sync_message_t
*m
;
209 m
= ha_sync_message_create(HA_SYNC_IKE_UPDATE
);
210 m
->add_attribute(m
, HA_SYNC_IKE_ID
, ike_sa
->get_id(ike_sa
));
211 mid
= message
->get_message_id(message
) + 1;
214 m
->add_attribute(m
, HA_SYNC_RESPOND_MID
, mid
);
218 m
->add_attribute(m
, HA_SYNC_INITIATE_MID
, mid
);
220 this->socket
->push(this->socket
, m
);
223 if (ike_sa
->get_state(ike_sa
) == IKE_ESTABLISHED
&&
224 message
->get_exchange_type(message
) == IKE_AUTH
&&
225 !message
->get_request(message
))
226 { /* After IKE_SA has been established, sync peers virtual IP.
227 * We cannot sync it in the state_change hook, it is installed later.
228 * TODO: where to sync local VIP? */
229 ha_sync_message_t
*m
;
232 vip
= ike_sa
->get_virtual_ip(ike_sa
, FALSE
);
235 m
= ha_sync_message_create(HA_SYNC_IKE_UPDATE
);
236 m
->add_attribute(m
, HA_SYNC_IKE_ID
, ike_sa
->get_id(ike_sa
));
237 m
->add_attribute(m
, HA_SYNC_REMOTE_VIP
, vip
);
238 this->socket
->push(this->socket
, m
);
246 * Implementation of ha_sync_ike_t.destroy.
248 static void destroy(private_ha_sync_ike_t
*this)
256 ha_sync_ike_t
*ha_sync_ike_create(ha_sync_socket_t
*socket
)
258 private_ha_sync_ike_t
*this = malloc_thing(private_ha_sync_ike_t
);
260 memset(&this->public.listener
, 0, sizeof(listener_t
));
261 this->public.listener
.ike_keys
= (bool(*)(listener_t
*, ike_sa_t
*ike_sa
, diffie_hellman_t
*dh
,chunk_t nonce_i
, chunk_t nonce_r
, ike_sa_t
*rekey
))ike_keys
;
262 this->public.listener
.ike_state_change
= (bool(*)(listener_t
*,ike_sa_t
*ike_sa
, ike_sa_state_t state
))ike_state_change
;
263 this->public.listener
.message
= (bool(*)(listener_t
*, ike_sa_t
*, message_t
*,bool))message_hook
;
264 this->public.destroy
= (void(*)(ha_sync_ike_t
*))destroy
;
266 this->socket
= socket
;
268 return &this->public;