certificate handling for XAuth responder.
[strongswan.git] / src / libcharon / sa / tasks / ike_cert_post.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2006-2009 Martin Willi
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 "ike_cert_post.h"
18
19 #include <daemon.h>
20 #include <sa/ike_sa.h>
21 #include <encoding/payloads/cert_payload.h>
22 #include <encoding/payloads/certreq_payload.h>
23 #include <encoding/payloads/auth_payload.h>
24 #include <encoding/payloads/sa_payload.h>
25 #include <credentials/certificates/x509.h>
26
27
28 typedef struct private_ike_cert_post_t private_ike_cert_post_t;
29
30 /**
31 * Private members of a ike_cert_post_t task.
32 */
33 struct private_ike_cert_post_t {
34
35 /**
36 * Public methods and task_t interface.
37 */
38 ike_cert_post_t public;
39
40 /**
41 * Assigned IKE_SA.
42 */
43 ike_sa_t *ike_sa;
44
45 /**
46 * Are we the initiator?
47 */
48 bool initiator;
49
50 /**
51 * Certificate payload type that we are handling
52 */
53 payload_type_t payload_type;
54
55 /**
56 * States of ike cert pre
57 */
58 enum {
59 CP_INIT,
60 CP_SA,
61 CP_SA_POST,
62 } state;
63 };
64
65 /**
66 * Generates the cert payload, if possible with "Hash and URL"
67 */
68 static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
69 certificate_t *cert)
70 {
71 hasher_t *hasher;
72 identification_t *id;
73 chunk_t hash, encoded ;
74 enumerator_t *enumerator;
75 char *url;
76 cert_payload_t *payload = NULL;
77
78 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
79 {
80 return cert_payload_create_from_cert(cert, this->payload_type);
81 }
82
83 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
84 if (!hasher)
85 {
86 DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported");
87 return cert_payload_create_from_cert(cert, this->payload_type);
88 }
89
90 if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
91 {
92 DBG1(DBG_IKE, "encoding certificate for cert payload failed");
93 hasher->destroy(hasher);
94 return NULL;
95 }
96 hasher->allocate_hash(hasher, encoded, &hash);
97 chunk_free(&encoded);
98 hasher->destroy(hasher);
99 id = identification_create_from_encoding(ID_KEY_ID, hash);
100
101 enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509, id);
102 if (enumerator->enumerate(enumerator, &url))
103 {
104 payload = cert_payload_create_from_hash_and_url(hash, url, this->payload_type);
105 DBG1(DBG_IKE, "sending hash-and-url \"%s\"", url);
106 }
107 else
108 {
109 payload = cert_payload_create_from_cert(cert, this->payload_type);
110 }
111 enumerator->destroy(enumerator);
112 chunk_free(&hash);
113 id->destroy(id);
114 return payload;
115 }
116
117 /**
118 * Checks for the auth_method to see if this task should handle certificates.
119 * (IKEv1 only)
120 */
121 static status_t check_auth_method(private_ike_cert_post_t *this,
122 message_t *message)
123 {
124 enumerator_t *enumerator;
125 payload_t *payload;
126 status_t status = SUCCESS;
127
128 enumerator = message->create_payload_enumerator(message);
129 while (enumerator->enumerate(enumerator, &payload))
130 {
131 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
132 {
133 sa_payload_t *sa_payload = (sa_payload_t*)payload;
134
135 switch (sa_payload->get_auth_method(sa_payload))
136 {
137 case AUTH_RSA:
138 case AUTH_XAUTH_INIT_RSA:
139 case AUTH_XAUTH_RESP_RSA:
140 DBG3(DBG_IKE, "handling certs method (%d)",
141 sa_payload->get_auth_method(sa_payload));
142 status = NEED_MORE;
143 break;
144 default:
145 DBG3(DBG_IKE, "not handling certs method (%d)",
146 sa_payload->get_auth_method(sa_payload));
147 status = SUCCESS;
148 break;
149 }
150
151 this->state = CP_SA;
152 break;
153 }
154 }
155 enumerator->destroy(enumerator);
156
157 return status;
158 }
159
160 /**
161 * add certificates to message
162 */
163 static void build_certs(private_ike_cert_post_t *this, message_t *message)
164 {
165 peer_cfg_t *peer_cfg;
166
167 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
168
169 if (!peer_cfg)
170 {
171 return;
172 }
173
174 if (this->payload_type == CERTIFICATE)
175 {
176 auth_payload_t *payload;
177 payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
178
179 if (!payload || payload->get_auth_method(payload) == AUTH_PSK)
180 { /* no CERT payload for EAP/PSK */
181 return;
182 }
183 }
184
185 switch (peer_cfg->get_cert_policy(peer_cfg))
186 {
187 case CERT_NEVER_SEND:
188 break;
189 case CERT_SEND_IF_ASKED:
190 if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
191 {
192 break;
193 }
194 /* FALL */
195 case CERT_ALWAYS_SEND:
196 {
197 cert_payload_t *payload;
198 enumerator_t *enumerator;
199 certificate_t *cert;
200 auth_rule_t type;
201 auth_cfg_t *auth;
202
203 auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
204
205 /* get subject cert first, then issuing certificates */
206 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
207 if (!cert)
208 {
209 break;
210 }
211 payload = build_cert_payload(this, cert);
212 if (!payload)
213 {
214 break;
215 }
216 DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
217 cert->get_subject(cert));
218 message->add_payload(message, (payload_t*)payload);
219
220 enumerator = auth->create_enumerator(auth);
221 while (enumerator->enumerate(enumerator, &type, &cert))
222 {
223 if (type == AUTH_RULE_IM_CERT)
224 {
225 payload = cert_payload_create_from_cert(cert, this->payload_type);
226 if (payload)
227 {
228 DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
229 cert->get_subject(cert));
230 message->add_payload(message, (payload_t*)payload);
231 }
232 }
233 }
234 enumerator->destroy(enumerator);
235 }
236 }
237
238 return;
239 }
240
241 METHOD(task_t, build_i, status_t,
242 private_ike_cert_post_t *this, message_t *message)
243 {
244 build_certs(this, message);
245
246 return NEED_MORE;
247 }
248
249 METHOD(task_t, build_i_v1, status_t,
250 private_ike_cert_post_t *this, message_t *message)
251 {
252 /* TODO:*/
253
254 return FAILED;
255 }
256
257 METHOD(task_t, process_r, status_t,
258 private_ike_cert_post_t *this, message_t *message)
259 {
260 return NEED_MORE;
261 }
262
263 METHOD(task_t, build_r, status_t,
264 private_ike_cert_post_t *this, message_t *message)
265 {
266 build_certs(this, message);
267
268 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
269 { /* stay alive, we might have additional rounds with certs */
270 return NEED_MORE;
271 }
272 return SUCCESS;
273 }
274
275 METHOD(task_t, build_r_v1, status_t,
276 private_ike_cert_post_t *this, message_t *message)
277 {
278 switch (message->get_exchange_type(message))
279 {
280 case ID_PROT:
281 {
282 switch (this->state)
283 {
284 case CP_INIT:
285 this->state = CP_SA;
286 return check_auth_method(this, message);
287 break;
288
289 case CP_SA:
290 this->state = CP_SA_POST;
291 build_certs(this, message);
292 break;
293
294 case CP_SA_POST:
295 build_certs(this, message);
296 return SUCCESS;
297 }
298 break;
299 }
300 case AGGRESSIVE:
301 {
302 if (check_auth_method(this, message) == NEED_MORE)
303 {
304 build_certs(this, message);
305 }
306 return SUCCESS;
307 break;
308 }
309 default:
310 break;
311 }
312
313 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
314 {
315 return NEED_MORE;
316 }
317
318 return SUCCESS;
319 }
320
321 METHOD(task_t, process_i, status_t,
322 private_ike_cert_post_t *this, message_t *message)
323 {
324 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
325 { /* stay alive, we might have additional rounds with CERTS */
326 return NEED_MORE;
327 }
328 return SUCCESS;
329 }
330
331 METHOD(task_t, get_type, task_type_t,
332 private_ike_cert_post_t *this)
333 {
334 return TASK_IKE_CERT_POST;
335 }
336
337 METHOD(task_t, migrate, void,
338 private_ike_cert_post_t *this, ike_sa_t *ike_sa)
339 {
340 this->ike_sa = ike_sa;
341 }
342
343 METHOD(task_t, destroy, void,
344 private_ike_cert_post_t *this)
345 {
346 free(this);
347 }
348
349 /*
350 * Described in header.
351 */
352 ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
353 {
354 private_ike_cert_post_t *this;
355
356 INIT(this,
357 .public = {
358 .task = {
359 .get_type = _get_type,
360 .migrate = _migrate,
361 .destroy = _destroy,
362 },
363 },
364 .ike_sa = ike_sa,
365 .initiator = initiator,
366 );
367
368
369 if (initiator)
370 {
371 this->public.task.process = _process_i;
372 }
373 else
374 {
375 this->public.task.process = _process_r;
376 }
377
378 if (ike_sa->get_version(ike_sa) == IKEV2)
379 {
380 this->payload_type = CERTIFICATE;
381
382 if (initiator)
383 {
384 this->public.task.build = _build_i;
385 }
386 else
387 {
388 this->public.task.build = _build_r;
389 }
390 }
391 else
392 {
393 this->payload_type = CERTIFICATE_V1;
394
395 if (initiator)
396 {
397 this->public.task.build = _build_i_v1;
398 }
399 else
400 {
401 this->public.task.build = _build_r_v1;
402 }
403 }
404
405 return &this->public;
406 }
407