Implemented pre-authentication certificate handling for IKEv1
[strongswan.git] / src / libcharon / sa / tasks / ike_cert_pre_v1.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "ike_cert_pre_v1.h"
17
18 #include <daemon.h>
19 #include <sa/ike_sa.h>
20 #include <encoding/payloads/cert_payload.h>
21 #include <encoding/payloads/sa_payload.h>
22 #include <encoding/payloads/certreq_payload.h>
23 #include <credentials/certificates/x509.h>
24
25
26 typedef struct private_ike_cert_pre_v1_t private_ike_cert_pre_v1_t;
27
28 /**
29 * Private members of a ike_cert_pre_v1_t task.
30 */
31 struct private_ike_cert_pre_v1_t {
32
33 /**
34 * Public methods and task_t interface.
35 */
36 ike_cert_pre_v1_t public;
37
38 /**
39 * Assigned IKE_SA.
40 */
41 ike_sa_t *ike_sa;
42
43 /**
44 * Are we the initiator?
45 */
46 bool initiator;
47
48 /** next message we expect */
49 enum {
50 CR_SA,
51 CR_KE,
52 CR_AUTH,
53 } state;
54 };
55
56 /**
57 * Find the CA certificate for a given certreq payload
58 */
59 static certificate_t* find_certificate(private_ike_cert_pre_v1_t *this,
60 certreq_payload_t *certreq)
61 {
62 identification_t *id;
63 certificate_t *cert;
64
65 if (certreq->get_cert_type(certreq) != CERT_X509)
66 {
67 DBG1(DBG_IKE, "%N CERTREQ not supported - ignored",
68 certificate_type_names, certreq->get_cert_type(certreq));
69 return NULL;
70 }
71 id = certreq->get_dn(certreq);
72 if (!id)
73 {
74 DBG1(DBG_IKE, "ignoring certificate request without data",
75 certificate_type_names, certreq->get_cert_type(certreq));
76 return NULL;
77 }
78 cert = lib->credmgr->get_cert(lib->credmgr, CERT_X509, KEY_ANY, id, TRUE);
79 if (cert)
80 {
81 DBG1(DBG_IKE, "received cert request for '%Y'",
82 cert->get_subject(cert));
83 }
84 else
85 {
86 DBG1(DBG_IKE, "received cert request for unknown ca '%Y'", id);
87 }
88 id->destroy(id);
89
90 return cert;
91 }
92
93 /**
94 * read certificate requests
95 */
96 static void process_certreqs(private_ike_cert_pre_v1_t *this, message_t *message)
97 {
98 enumerator_t *enumerator;
99 payload_t *payload;
100 auth_cfg_t *auth;
101
102 auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
103
104 enumerator = message->create_payload_enumerator(message);
105 while (enumerator->enumerate(enumerator, &payload))
106 {
107 switch (payload->get_type(payload))
108 {
109 case CERTIFICATE_REQUEST_V1:
110 {
111 certificate_t *cert;
112
113 this->ike_sa->set_condition(this->ike_sa,
114 COND_CERTREQ_SEEN, TRUE);
115 cert = find_certificate(this, (certreq_payload_t*)payload);
116 if (cert)
117 {
118 auth->add(auth, AUTH_RULE_CA_CERT, cert);
119 }
120 break;
121 }
122 default:
123 break;
124 }
125 }
126 enumerator->destroy(enumerator);
127 }
128
129 /**
130 * Import receuved certificates
131 */
132 static void process_certs(private_ike_cert_pre_v1_t *this, message_t *message)
133 {
134 enumerator_t *enumerator;
135 payload_t *payload;
136 auth_cfg_t *auth;
137 bool first = TRUE;
138
139 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
140
141 enumerator = message->create_payload_enumerator(message);
142 while (enumerator->enumerate(enumerator, &payload))
143 {
144 if (payload->get_type(payload) == CERTIFICATE_V1)
145 {
146 cert_payload_t *cert_payload;
147 cert_encoding_t encoding;
148 certificate_t *cert;
149
150 cert_payload = (cert_payload_t*)payload;
151 encoding = cert_payload->get_cert_encoding(cert_payload);
152
153 switch (encoding)
154 {
155 case ENC_X509_SIGNATURE:
156 {
157 cert = cert_payload->get_cert(cert_payload);
158 if (cert)
159 {
160 if (first)
161 { /* the first is an end entity certificate */
162 DBG1(DBG_IKE, "received end entity cert \"%Y\"",
163 cert->get_subject(cert));
164 auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
165 first = FALSE;
166 }
167 else
168 {
169 DBG1(DBG_IKE, "received issuer cert \"%Y\"",
170 cert->get_subject(cert));
171 auth->add(auth, AUTH_HELPER_IM_CERT, cert);
172 }
173 }
174 break;
175 }
176 case ENC_CRL:
177 cert = cert_payload->get_cert(cert_payload);
178 if (cert)
179 {
180 DBG1(DBG_IKE, "received CRL \"%Y\"",
181 cert->get_subject(cert));
182 auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
183 }
184 break;
185 case ENC_PKCS7_WRAPPED_X509:
186 case ENC_PGP:
187 case ENC_DNS_SIGNED_KEY:
188 case ENC_KERBEROS_TOKEN:
189 case ENC_ARL:
190 case ENC_SPKI:
191 case ENC_X509_ATTRIBUTE:
192 case ENC_RAW_RSA_KEY:
193 case ENC_X509_HASH_AND_URL_BUNDLE:
194 case ENC_OCSP_CONTENT:
195 default:
196 DBG1(DBG_ENC, "certificate encoding %N not supported",
197 cert_encoding_names, encoding);
198 }
199 }
200 }
201 enumerator->destroy(enumerator);
202 }
203
204 /**
205 * Add the subject of a CA certificate a message
206 */
207 static void add_certreq(private_ike_cert_pre_v1_t *this, message_t *message,
208 certificate_t *cert)
209 {
210 if (cert->get_type(cert) == CERT_X509)
211 {
212 x509_t *x509 = (x509_t*)cert;
213
214 if (x509->get_flags(x509) & X509_CA)
215 {
216 DBG1(DBG_IKE, "sending cert request for \"%Y\"",
217 cert->get_subject(cert));
218 message->add_payload(message, (payload_t*)
219 certreq_payload_create_dn(cert->get_subject(cert)));
220 }
221 }
222 }
223
224 /**
225 * Add auth_cfg's CA certificates to the certificate request
226 */
227 static void add_certreqs(private_ike_cert_pre_v1_t *this,
228 auth_cfg_t *auth, message_t *message)
229 {
230 enumerator_t *enumerator;
231 auth_rule_t type;
232 void *value;
233
234 enumerator = auth->create_enumerator(auth);
235 while (enumerator->enumerate(enumerator, &type, &value))
236 {
237 switch (type)
238 {
239 case AUTH_RULE_CA_CERT:
240 add_certreq(this, message, (certificate_t*)value);
241 break;
242 default:
243 break;
244 }
245 }
246 enumerator->destroy(enumerator);
247 }
248
249 /**
250 * Build certificate requests
251 */
252 static void build_certreqs(private_ike_cert_pre_v1_t *this, message_t *message)
253 {
254 enumerator_t *enumerator;
255 ike_cfg_t *ike_cfg;
256 peer_cfg_t *peer_cfg;
257 certificate_t *cert;
258 auth_cfg_t *auth;
259
260 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
261 if (!ike_cfg->send_certreq(ike_cfg))
262 {
263 return;
264 }
265 /* check if we require a specific CA for that peer */
266 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
267 if (peer_cfg)
268 {
269 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
270 if (enumerator->enumerate(enumerator, &auth))
271 {
272 add_certreqs(this, auth, message);
273 }
274 enumerator->destroy(enumerator);
275 }
276 if (!message->get_payload(message, CERTIFICATE_REQUEST_V1))
277 {
278 /* otherwise add all trusted CA certificates */
279 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
280 CERT_ANY, KEY_ANY, NULL, TRUE);
281 while (enumerator->enumerate(enumerator, &cert))
282 {
283 add_certreq(this, message, cert);
284 }
285 enumerator->destroy(enumerator);
286 }
287 }
288
289 /**
290 * Check if we actually use certificates for authentication
291 */
292 static bool use_certs(private_ike_cert_pre_v1_t *this, message_t *message)
293 {
294 enumerator_t *enumerator;
295 payload_t *payload;
296 bool use = FALSE;
297
298 enumerator = message->create_payload_enumerator(message);
299 while (enumerator->enumerate(enumerator, &payload))
300 {
301 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
302 {
303 sa_payload_t *sa_payload = (sa_payload_t*)payload;
304
305 switch (sa_payload->get_auth_method(sa_payload))
306 {
307 case AUTH_RSA:
308 case AUTH_XAUTH_INIT_RSA:
309 case AUTH_XAUTH_RESP_RSA:
310 use = TRUE;
311 break;
312 default:
313 break;
314 }
315 break;
316 }
317 }
318 enumerator->destroy(enumerator);
319
320 return use;
321 }
322
323 METHOD(task_t, build_i, status_t,
324 private_ike_cert_pre_v1_t *this, message_t *message)
325 {
326 switch (message->get_exchange_type(message))
327 {
328 case ID_PROT:
329 if (this->state == CR_AUTH)
330 {
331 build_certreqs(this, message);
332 }
333 return NEED_MORE;
334 case AGGRESSIVE:
335 if (this->state == CR_SA)
336 {
337 build_certreqs(this, message);
338 }
339 return NEED_MORE;
340 default:
341 return FAILED;
342 }
343 }
344
345 METHOD(task_t, process_r, status_t,
346 private_ike_cert_pre_v1_t *this, message_t *message)
347 {
348 switch (message->get_exchange_type(message))
349 {
350 case ID_PROT:
351 {
352 switch (this->state)
353 {
354 case CR_SA:
355 if (!use_certs(this, message))
356 {
357 return SUCCESS;
358 }
359 return NEED_MORE;
360 case CR_KE:
361 process_certreqs(this, message);
362 return NEED_MORE;
363 case CR_AUTH:
364 process_certreqs(this, message);
365 process_certs(this, message);
366 return SUCCESS;
367 }
368 }
369 case AGGRESSIVE:
370 {
371 switch (this->state)
372 {
373 case CR_SA:
374 if (!use_certs(this, message))
375 {
376 return SUCCESS;
377 }
378 process_certreqs(this, message);
379 return NEED_MORE;
380 case CR_AUTH:
381 process_certs(this, message);
382 return SUCCESS;
383 default:
384 return FAILED;
385 }
386 }
387 default:
388 return FAILED;
389 }
390 }
391
392 METHOD(task_t, build_r, status_t,
393 private_ike_cert_pre_v1_t *this, message_t *message)
394 {
395 switch (message->get_exchange_type(message))
396 {
397 case ID_PROT:
398 switch (this->state)
399 {
400 case CR_SA:
401 this->state = CR_KE;
402 return NEED_MORE;
403 case CR_KE:
404 build_certreqs(this, message);
405 this->state = CR_AUTH;
406 return NEED_MORE;
407 case CR_AUTH:
408 return NEED_MORE;
409 }
410 case AGGRESSIVE:
411 switch (this->state)
412 {
413 case CR_SA:
414 this->state = CR_AUTH;
415 return NEED_MORE;
416 case CR_AUTH:
417 return SUCCESS;
418 default:
419 return FAILED;
420 }
421 default:
422 return FAILED;
423 }
424 }
425
426 METHOD(task_t, process_i, status_t,
427 private_ike_cert_pre_v1_t *this, message_t *message)
428 {
429 switch (message->get_exchange_type(message))
430 {
431 case ID_PROT:
432 {
433 switch (this->state)
434 {
435 case CR_SA:
436 if (!use_certs(this, message))
437 {
438 return SUCCESS;
439 }
440 this->state = CR_KE;
441 return NEED_MORE;
442 case CR_KE:
443 process_certreqs(this, message);
444 this->state = CR_AUTH;
445 return NEED_MORE;
446 case CR_AUTH:
447 process_certs(this, message);
448 return SUCCESS;
449 default:
450 return FAILED;
451 }
452 break;
453 }
454 case AGGRESSIVE:
455 {
456 if (!use_certs(this, message))
457 {
458 return SUCCESS;
459 }
460 process_certreqs(this, message);
461 process_certs(this, message);
462 return SUCCESS;
463 }
464 default:
465 return FAILED;
466 }
467 }
468
469 METHOD(task_t, get_type, task_type_t,
470 private_ike_cert_pre_v1_t *this)
471 {
472 return TASK_IKE_CERT_PRE_V1;
473 }
474
475 METHOD(task_t, migrate, void,
476 private_ike_cert_pre_v1_t *this, ike_sa_t *ike_sa)
477 {
478 this->ike_sa = ike_sa;
479 }
480
481 METHOD(task_t, destroy, void,
482 private_ike_cert_pre_v1_t *this)
483 {
484 free(this);
485 }
486
487 /*
488 * Described in header.
489 */
490 ike_cert_pre_v1_t *ike_cert_pre_v1_create(ike_sa_t *ike_sa, bool initiator)
491 {
492 private_ike_cert_pre_v1_t *this;
493
494 INIT(this,
495 .public = {
496 .task = {
497 .get_type = _get_type,
498 .migrate = _migrate,
499 .destroy = _destroy,
500 },
501 },
502 .ike_sa = ike_sa,
503 .initiator = initiator,
504 .state = CR_SA,
505 );
506 if (initiator)
507 {
508 this->public.task.build = _build_i;
509 this->public.task.process = _process_i;
510 }
511 else
512 {
513 this->public.task.build = _build_r;
514 this->public.task.process = _process_r;
515 }
516 return &this->public;
517 }