Make IKE and EES sockets configurable
[strongswan.git] / src / charon-tkm / src / tkm / tkm_listener.c
1 /*
2 * Copyrigth (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
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 <daemon.h>
18 #include <encoding/payloads/auth_payload.h>
19 #include <utils/chunk.h>
20 #include <tkm/types.h>
21 #include <tkm/constants.h>
22 #include <tkm/client.h>
23
24 #include "tkm.h"
25 #include "tkm_listener.h"
26 #include "tkm_keymat.h"
27 #include "tkm_utils.h"
28
29 typedef struct private_tkm_listener_t private_tkm_listener_t;
30
31 /**
32 * Private data of a tkm_listener_t object.
33 */
34 struct private_tkm_listener_t {
35
36 /**
37 * Public tkm_listener_t interface.
38 */
39 tkm_listener_t public;
40
41 };
42
43 /**
44 * Return id of remote identity.
45 *
46 * TODO: Replace this with the lookup for the remote identitiy id.
47 *
48 * Currently the reqid of the first child SA in peer config of IKE SA is
49 * returned. Might choose wrong reqid if IKE SA has multiple child configs
50 * with different reqids.
51 *
52 * @param peer_cfg Remote peer config
53 * @return remote identity id if found, 0 otherwise
54 */
55 static ri_id_type get_remote_identity_id(peer_cfg_t *peer)
56 {
57 ri_id_type remote_id = 0;
58 child_cfg_t *child;
59 enumerator_t* children = peer->create_child_cfg_enumerator(peer);
60
61 /* pick the reqid of the first child, no need to enumerate all children. */
62 children->enumerate(children, &child);
63 remote_id = child->get_reqid(child);
64 children->destroy(children);
65
66 return remote_id;
67 }
68
69 /**
70 * Build a TKM certificate chain context with given cc id.
71 *
72 * @param ike_sa IKE SA containing auth config to build certificate chain from
73 * @param cc_id Certificate chain ID
74 * @return TRUE if certificate chain was built successfully,
75 * FALSE otherwise
76 */
77 static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id)
78 {
79 DBG1(DBG_IKE, "building certificate chain context %llu for IKE SA %s",
80 cc_id, ike_sa->get_name((ike_sa_t *)ike_sa));
81
82 auth_cfg_t *auth;
83 certificate_t *cert;
84 enumerator_t *rounds;
85 rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE);
86 while (rounds->enumerate(rounds, &auth))
87 {
88 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
89 if (cert)
90 {
91 /* set user certificate */
92 chunk_t enc_user_cert;
93 if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert))
94 {
95 DBG1(DBG_IKE, "unable to extract encoded user certificate");
96 rounds->destroy(rounds);
97 return FALSE;
98 }
99
100 ri_id_type ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa));
101 certificate_type user_cert;
102 chunk_to_sequence(&enc_user_cert, &user_cert,
103 sizeof(certificate_type));
104 chunk_free(&enc_user_cert);
105 if (ike_cc_set_user_certificate(cc_id, ri_id, 1, user_cert) != TKM_OK)
106 {
107 DBG1(DBG_IKE, "error setting user certificate of cert chain"
108 " (cc_id: %llu)", cc_id);
109 rounds->destroy(rounds);
110 return FALSE;
111 }
112
113 /* process intermediate CA certificates */
114 auth_rule_t rule;
115 enumerator_t *enumerator = auth->create_enumerator(auth);
116 while (enumerator->enumerate(enumerator, &rule, &cert))
117 {
118 if (rule == AUTH_RULE_IM_CERT)
119 {
120 chunk_t enc_im_cert;
121 if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert))
122 {
123 DBG1(DBG_IKE, "unable to extract encoded intermediate CA"
124 " certificate");
125 rounds->destroy(rounds);
126 enumerator->destroy(enumerator);
127 return FALSE;
128 }
129
130 certificate_type im_cert;
131 chunk_to_sequence(&enc_im_cert, &im_cert,
132 sizeof(certificate_type));
133 chunk_free(&enc_im_cert);
134 if (ike_cc_add_certificate(cc_id, 1, im_cert) != TKM_OK)
135 {
136 DBG1(DBG_IKE, "error adding intermediate certificate to"
137 " cert chain (cc_id: %llu)", cc_id);
138 rounds->destroy(rounds);
139 enumerator->destroy(enumerator);
140 return FALSE;
141 }
142 }
143 }
144 enumerator->destroy(enumerator);
145
146 /* finally add CA certificate */
147 cert = auth->get(auth, AUTH_RULE_CA_CERT);
148 if (cert)
149 {
150 chunk_t enc_ca_cert;
151 if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert))
152 {
153 DBG1(DBG_IKE, "unable to extract encoded CA certificate");
154 rounds->destroy(rounds);
155 return FALSE;
156 }
157
158 const ca_id_type ca_id = 1;
159 certificate_type ca_cert;
160 chunk_to_sequence(&enc_ca_cert, &ca_cert,
161 sizeof(certificate_type));
162 chunk_free(&enc_ca_cert);
163 if (ike_cc_add_certificate(cc_id, 1, ca_cert) != TKM_OK)
164 {
165 DBG1(DBG_IKE, "error adding CA certificate to cert chain "
166 "(cc_id: %llu)", cc_id);
167 rounds->destroy(rounds);
168 return FALSE;
169 }
170
171 if (ike_cc_check_ca(cc_id, ca_id) != TKM_OK)
172 {
173 DBG1(DBG_IKE, "certificate chain (cc_id: %llu) not based on"
174 " trusted CA (ca_id: %llu)", cc_id, ca_id);
175 rounds->destroy(rounds);
176 return FALSE;
177 }
178
179 rounds->destroy(rounds);
180 return TRUE;
181 }
182 else
183 {
184 DBG1(DBG_IKE, "no CA certificate");
185 }
186 }
187 else
188 {
189 DBG1(DBG_IKE, "no subject certificate for remote peer");
190 }
191 }
192
193 rounds->destroy(rounds);
194 return FALSE;
195 }
196
197 METHOD(listener_t, authorize, bool,
198 private_tkm_listener_t *this, ike_sa_t *ike_sa,
199 bool final, bool *success)
200 {
201 if (!final)
202 {
203 return TRUE;
204 }
205
206 tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa);
207 const isa_id_type isa_id = keymat->get_isa_id(keymat);
208 DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id);
209
210 const cc_id_type cc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_CC);
211 if (!cc_id)
212 {
213 DBG1(DBG_IKE, "unable to acquire CC context id");
214 *success = FALSE;
215 return TRUE;
216 }
217 const bool cc_success = build_cert_chain(ike_sa, cc_id);
218 if (!cc_success)
219 {
220 DBG1(DBG_IKE, "unable to build certificate chain");
221 *success = FALSE;
222 return TRUE;
223 }
224
225 const chunk_t * const auth = keymat->get_auth_payload(keymat);
226 if (!auth->ptr)
227 {
228 DBG1(DBG_IKE, "no AUTHENTICATION data available");
229 *success = FALSE;
230 }
231
232 const chunk_t * const other_init_msg = keymat->get_peer_init_msg(keymat);
233 if (!other_init_msg->ptr)
234 {
235 DBG1(DBG_IKE, "no peer init message available");
236 *success = FALSE;
237 }
238
239 signature_type signature;
240 chunk_to_sequence(auth, &signature, sizeof(signature_type));
241 init_message_type init_msg;
242 chunk_to_sequence(other_init_msg, &init_msg, sizeof(init_message_type));
243
244 if (ike_isa_auth(isa_id, cc_id, init_msg, signature) != TKM_OK)
245 {
246 DBG1(DBG_IKE, "TKM based authentication failed"
247 " for ISA context %llu", isa_id);
248 *success = FALSE;
249 }
250 else
251 {
252 DBG1(DBG_IKE, "TKM based authentication successful"
253 " for ISA context %llu", isa_id);
254 *success = TRUE;
255 }
256
257 return TRUE;
258 }
259
260 METHOD(listener_t, message, bool,
261 private_tkm_listener_t *this, ike_sa_t *ike_sa,
262 message_t *message, bool incoming, bool plain)
263 {
264 if (!incoming || !plain || message->get_exchange_type(message) != IKE_AUTH)
265 {
266 return TRUE;
267 }
268
269 tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa);
270 const isa_id_type isa_id = keymat->get_isa_id(keymat);
271 DBG1(DBG_IKE, "saving AUTHENTICATION payload for authorize hook"
272 " (ISA context %llu)", isa_id);
273
274 auth_payload_t * const auth_payload =
275 (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
276 if (auth_payload)
277 {
278 const chunk_t auth_data = auth_payload->get_data(auth_payload);
279 keymat->set_auth_payload(keymat, &auth_data);
280 }
281 else
282 {
283 DBG1(DBG_IKE, "unable to extract AUTHENTICATION payload, authorize will"
284 " fail");
285 }
286
287 return TRUE;
288 }
289
290 METHOD(tkm_listener_t, destroy, void,
291 private_tkm_listener_t *this)
292 {
293 free(this);
294 }
295
296 /**
297 * See header
298 */
299 tkm_listener_t *tkm_listener_create()
300 {
301 private_tkm_listener_t *this;
302
303 INIT(this,
304 .public = {
305 .listener = {
306 .authorize = _authorize,
307 .message = _message,
308 },
309 .destroy = _destroy,
310 },
311 );
312
313 return &this->public;
314 }