IKEv1 support for PKCS#7 wrapped certificates
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / isakmp_cert_pre.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 /*
17 * Copyright (C) 2013 Volker RĂ¼melin
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this software and associated documentation files (the "Software"), to deal
21 * in the Software without restriction, including without limitation the rights
22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 * copies of the Software, and to permit persons to whom the Software is
24 * furnished to do so, subject to the following conditions:
25 *
26 * The above copyright notice and this permission notice shall be included in
27 * all copies or substantial portions of the Software.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 * THE SOFTWARE.
36 */
37
38 #include "isakmp_cert_pre.h"
39
40 #include <daemon.h>
41 #include <sa/ike_sa.h>
42 #include <encoding/payloads/cert_payload.h>
43 #include <encoding/payloads/sa_payload.h>
44 #include <encoding/payloads/certreq_payload.h>
45 #include <credentials/certificates/x509.h>
46 #include <credentials/containers/pkcs7.h>
47
48
49 typedef struct private_isakmp_cert_pre_t private_isakmp_cert_pre_t;
50
51 /**
52 * Private members of a isakmp_cert_pre_t task.
53 */
54 struct private_isakmp_cert_pre_t {
55
56 /**
57 * Public methods and task_t interface.
58 */
59 isakmp_cert_pre_t public;
60
61 /**
62 * Assigned IKE_SA.
63 */
64 ike_sa_t *ike_sa;
65
66 /**
67 * Are we the initiator?
68 */
69 bool initiator;
70
71 /**
72 * Send certificate requests?
73 */
74 bool send_req;
75
76 /** next message we expect */
77 enum {
78 CR_SA,
79 CR_KE,
80 CR_AUTH,
81 } state;
82 };
83
84 /**
85 * Find the CA certificate for a given certreq payload
86 */
87 static certificate_t* find_certificate(private_isakmp_cert_pre_t *this,
88 certreq_payload_t *certreq)
89 {
90 identification_t *id;
91 certificate_t *cert;
92
93 if (certreq->get_cert_type(certreq) != CERT_X509)
94 {
95 DBG1(DBG_IKE, "%N CERTREQ not supported - ignored",
96 certificate_type_names, certreq->get_cert_type(certreq));
97 return NULL;
98 }
99 id = certreq->get_dn(certreq);
100 if (!id)
101 {
102 DBG1(DBG_IKE, "ignoring certificate request without data",
103 certificate_type_names, certreq->get_cert_type(certreq));
104 return NULL;
105 }
106 cert = lib->credmgr->get_cert(lib->credmgr, CERT_X509, KEY_ANY, id, TRUE);
107 if (cert)
108 {
109 DBG1(DBG_IKE, "received cert request for '%Y'",
110 cert->get_subject(cert));
111 }
112 else
113 {
114 DBG1(DBG_IKE, "received cert request for unknown ca '%Y'", id);
115 }
116 id->destroy(id);
117
118 return cert;
119 }
120
121 /**
122 * read certificate requests
123 */
124 static void process_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
125 {
126 enumerator_t *enumerator;
127 payload_t *payload;
128 auth_cfg_t *auth;
129
130 auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
131
132 enumerator = message->create_payload_enumerator(message);
133 while (enumerator->enumerate(enumerator, &payload))
134 {
135 switch (payload->get_type(payload))
136 {
137 case CERTIFICATE_REQUEST_V1:
138 {
139 certificate_t *cert;
140
141 this->ike_sa->set_condition(this->ike_sa,
142 COND_CERTREQ_SEEN, TRUE);
143 cert = find_certificate(this, (certreq_payload_t*)payload);
144 if (cert)
145 {
146 auth->add(auth, AUTH_RULE_CA_CERT, cert);
147 }
148 break;
149 }
150 default:
151 break;
152 }
153 }
154 enumerator->destroy(enumerator);
155 }
156
157 /**
158 * Import received certificates
159 */
160 static void process_certs(private_isakmp_cert_pre_t *this, message_t *message)
161 {
162 enumerator_t *enumerator;
163 payload_t *payload;
164 auth_cfg_t *auth;
165 bool first = TRUE;
166
167 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
168
169 enumerator = message->create_payload_enumerator(message);
170 while (enumerator->enumerate(enumerator, &payload))
171 {
172 if (payload->get_type(payload) == CERTIFICATE_V1)
173 {
174 cert_payload_t *cert_payload;
175 cert_encoding_t encoding;
176 certificate_t *cert;
177
178 cert_payload = (cert_payload_t*)payload;
179 encoding = cert_payload->get_cert_encoding(cert_payload);
180
181 switch (encoding)
182 {
183 case ENC_X509_SIGNATURE:
184 {
185 cert = cert_payload->get_cert(cert_payload);
186 if (cert)
187 {
188 if (first)
189 { /* the first is an end entity certificate */
190 DBG1(DBG_IKE, "received end entity cert \"%Y\"",
191 cert->get_subject(cert));
192 auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
193 first = FALSE;
194 }
195 else
196 {
197 DBG1(DBG_IKE, "received issuer cert \"%Y\"",
198 cert->get_subject(cert));
199 auth->add(auth, AUTH_HELPER_IM_CERT, cert);
200 }
201 }
202 break;
203 }
204 case ENC_CRL:
205 cert = cert_payload->get_cert(cert_payload);
206 if (cert)
207 {
208 DBG1(DBG_IKE, "received CRL \"%Y\"",
209 cert->get_subject(cert));
210 auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
211 }
212 break;
213 case ENC_PKCS7_WRAPPED_X509:
214 {
215 container_t *container;
216
217 container = cert_payload->get_container(cert_payload);
218 if (container)
219 {
220 pkcs7_t *pkcs7;
221 enumerator_t *enumerator;
222
223 pkcs7 = (pkcs7_t *)container;
224 enumerator = pkcs7->create_cert_enumerator(pkcs7);
225 while (enumerator->enumerate(enumerator, &cert))
226 {
227 if (cert->get_type(cert) == CERT_X509)
228 {
229 auth_rule_t rule;
230 x509_t *x509 = (x509_t*)cert;
231
232 if (x509->get_flags(x509) & X509_CA)
233 {
234 DBG1(DBG_IKE,
235 "received intermediate ca cert \"%Y\"",
236 cert->get_subject(cert));
237 rule = AUTH_HELPER_IM_CERT;
238 }
239 else
240 {
241 DBG1(DBG_IKE,
242 "received end entity cert \"%Y\"",
243 cert->get_subject(cert));
244 rule = AUTH_HELPER_SUBJECT_CERT;
245 }
246 auth->add(auth, rule, cert->get_ref(cert));
247 }
248 else
249 {
250 DBG1(DBG_IKE,
251 "received unsupported cert type %N",
252 certificate_type_names,
253 cert->get_type(cert));
254 }
255 }
256 enumerator->destroy(enumerator);
257 container->destroy(container);
258 }
259 break;
260 }
261 case ENC_PGP:
262 case ENC_DNS_SIGNED_KEY:
263 case ENC_KERBEROS_TOKEN:
264 case ENC_ARL:
265 case ENC_SPKI:
266 case ENC_X509_ATTRIBUTE:
267 case ENC_RAW_RSA_KEY:
268 case ENC_X509_HASH_AND_URL_BUNDLE:
269 case ENC_OCSP_CONTENT:
270 default:
271 DBG1(DBG_ENC, "certificate encoding %N not supported",
272 cert_encoding_names, encoding);
273 }
274 }
275 }
276 enumerator->destroy(enumerator);
277 }
278
279 /**
280 * Add the subject of a CA certificate a message
281 */
282 static void add_certreq(private_isakmp_cert_pre_t *this, message_t *message,
283 certificate_t *cert)
284 {
285 if (cert->get_type(cert) == CERT_X509)
286 {
287 x509_t *x509 = (x509_t*)cert;
288
289 if (x509->get_flags(x509) & X509_CA)
290 {
291 DBG1(DBG_IKE, "sending cert request for \"%Y\"",
292 cert->get_subject(cert));
293 message->add_payload(message, (payload_t*)
294 certreq_payload_create_dn(cert->get_subject(cert)));
295 }
296 }
297 }
298
299 /**
300 * Add auth_cfg's CA certificates to the certificate request
301 */
302 static void add_certreqs(private_isakmp_cert_pre_t *this,
303 auth_cfg_t *auth, message_t *message)
304 {
305 enumerator_t *enumerator;
306 auth_rule_t type;
307 void *value;
308
309 enumerator = auth->create_enumerator(auth);
310 while (enumerator->enumerate(enumerator, &type, &value))
311 {
312 switch (type)
313 {
314 case AUTH_RULE_CA_CERT:
315 add_certreq(this, message, (certificate_t*)value);
316 break;
317 default:
318 break;
319 }
320 }
321 enumerator->destroy(enumerator);
322 }
323
324 /**
325 * Build certificate requests
326 */
327 static void build_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
328 {
329 enumerator_t *enumerator;
330 ike_cfg_t *ike_cfg;
331 peer_cfg_t *peer_cfg;
332 certificate_t *cert;
333 auth_cfg_t *auth;
334
335 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
336 if (!ike_cfg->send_certreq(ike_cfg))
337 {
338 return;
339 }
340 /* check if we require a specific CA for that peer */
341 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
342 if (peer_cfg)
343 {
344 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
345 if (enumerator->enumerate(enumerator, &auth))
346 {
347 add_certreqs(this, auth, message);
348 }
349 enumerator->destroy(enumerator);
350 }
351 if (!message->get_payload(message, CERTIFICATE_REQUEST_V1))
352 {
353 /* otherwise add all trusted CA certificates */
354 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
355 CERT_ANY, KEY_ANY, NULL, TRUE);
356 while (enumerator->enumerate(enumerator, &cert))
357 {
358 add_certreq(this, message, cert);
359 }
360 enumerator->destroy(enumerator);
361 }
362 }
363
364 /**
365 * Check if we actually use certificates for authentication
366 */
367 static bool use_certs(private_isakmp_cert_pre_t *this, message_t *message)
368 {
369 enumerator_t *enumerator;
370 payload_t *payload;
371 bool use = FALSE;
372
373 enumerator = message->create_payload_enumerator(message);
374 while (enumerator->enumerate(enumerator, &payload))
375 {
376 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
377 {
378 sa_payload_t *sa_payload = (sa_payload_t*)payload;
379
380 switch (sa_payload->get_auth_method(sa_payload))
381 {
382 case AUTH_HYBRID_INIT_RSA:
383 case AUTH_HYBRID_RESP_RSA:
384 if (!this->initiator)
385 {
386 this->send_req = FALSE;
387 }
388 /* FALL */
389 case AUTH_RSA:
390 case AUTH_ECDSA_256:
391 case AUTH_ECDSA_384:
392 case AUTH_ECDSA_521:
393 case AUTH_XAUTH_INIT_RSA:
394 case AUTH_XAUTH_RESP_RSA:
395 use = TRUE;
396 break;
397 default:
398 break;
399 }
400 break;
401 }
402 }
403 enumerator->destroy(enumerator);
404
405 return use;
406 }
407
408 /**
409 * Check if we should send a certificate request
410 */
411 static bool send_certreq(private_isakmp_cert_pre_t *this)
412 {
413 enumerator_t *enumerator;
414 peer_cfg_t *peer_cfg;
415 auth_cfg_t *auth;
416 bool req = FALSE;
417 auth_class_t class;
418
419 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
420 if (peer_cfg)
421 {
422 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
423 if (enumerator->enumerate(enumerator, &auth))
424 {
425 class = (intptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
426 if (class == AUTH_CLASS_PUBKEY)
427 {
428 req = TRUE;
429 }
430 }
431 enumerator->destroy(enumerator);
432 }
433 return req;
434 }
435
436 METHOD(task_t, build_i, status_t,
437 private_isakmp_cert_pre_t *this, message_t *message)
438 {
439 switch (message->get_exchange_type(message))
440 {
441 case ID_PROT:
442 if (this->state == CR_AUTH)
443 {
444 build_certreqs(this, message);
445 }
446 return NEED_MORE;
447 case AGGRESSIVE:
448 if (this->state == CR_SA)
449 {
450 if (send_certreq(this))
451 {
452 build_certreqs(this, message);
453 }
454 }
455 return NEED_MORE;
456 default:
457 return FAILED;
458 }
459 }
460
461 METHOD(task_t, process_r, status_t,
462 private_isakmp_cert_pre_t *this, message_t *message)
463 {
464 switch (message->get_exchange_type(message))
465 {
466 case ID_PROT:
467 {
468 switch (this->state)
469 {
470 case CR_SA:
471 if (!use_certs(this, message))
472 {
473 return SUCCESS;
474 }
475 return NEED_MORE;
476 case CR_KE:
477 process_certreqs(this, message);
478 return NEED_MORE;
479 case CR_AUTH:
480 process_certreqs(this, message);
481 process_certs(this, message);
482 return SUCCESS;
483 default:
484 return FAILED;
485 }
486 }
487 case AGGRESSIVE:
488 {
489 switch (this->state)
490 {
491 case CR_SA:
492 if (!use_certs(this, message))
493 {
494 return SUCCESS;
495 }
496 process_certreqs(this, message);
497 return NEED_MORE;
498 case CR_AUTH:
499 process_certs(this, message);
500 return SUCCESS;
501 default:
502 return FAILED;
503 }
504 }
505 default:
506 return FAILED;
507 }
508 }
509
510 METHOD(task_t, build_r, status_t,
511 private_isakmp_cert_pre_t *this, message_t *message)
512 {
513 switch (message->get_exchange_type(message))
514 {
515 case ID_PROT:
516 switch (this->state)
517 {
518 case CR_SA:
519 this->state = CR_KE;
520 return NEED_MORE;
521 case CR_KE:
522 if (this->send_req)
523 {
524 build_certreqs(this, message);
525 }
526 this->state = CR_AUTH;
527 return NEED_MORE;
528 case CR_AUTH:
529 return NEED_MORE;
530 default:
531 return FAILED;
532 }
533 case AGGRESSIVE:
534 switch (this->state)
535 {
536 case CR_SA:
537 if (this->send_req)
538 {
539 build_certreqs(this, message);
540 }
541 this->state = CR_AUTH;
542 return NEED_MORE;
543 case CR_AUTH:
544 return SUCCESS;
545 default:
546 return FAILED;
547 }
548 default:
549 return FAILED;
550 }
551 }
552
553 METHOD(task_t, process_i, status_t,
554 private_isakmp_cert_pre_t *this, message_t *message)
555 {
556 switch (message->get_exchange_type(message))
557 {
558 case ID_PROT:
559 {
560 switch (this->state)
561 {
562 case CR_SA:
563 if (!use_certs(this, message))
564 {
565 return SUCCESS;
566 }
567 this->state = CR_KE;
568 return NEED_MORE;
569 case CR_KE:
570 process_certreqs(this, message);
571 this->state = CR_AUTH;
572 return NEED_MORE;
573 case CR_AUTH:
574 process_certs(this, message);
575 return SUCCESS;
576 default:
577 return FAILED;
578 }
579 break;
580 }
581 case AGGRESSIVE:
582 {
583 if (!use_certs(this, message))
584 {
585 return SUCCESS;
586 }
587 process_certreqs(this, message);
588 process_certs(this, message);
589 this->state = CR_AUTH;
590 return SUCCESS;
591 }
592 default:
593 return FAILED;
594 }
595 }
596
597 METHOD(task_t, get_type, task_type_t,
598 private_isakmp_cert_pre_t *this)
599 {
600 return TASK_ISAKMP_CERT_PRE;
601 }
602
603 METHOD(task_t, migrate, void,
604 private_isakmp_cert_pre_t *this, ike_sa_t *ike_sa)
605 {
606 this->ike_sa = ike_sa;
607 this->state = CR_SA;
608 this->send_req = TRUE;
609 }
610
611 METHOD(task_t, destroy, void,
612 private_isakmp_cert_pre_t *this)
613 {
614 free(this);
615 }
616
617 /*
618 * Described in header.
619 */
620 isakmp_cert_pre_t *isakmp_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
621 {
622 private_isakmp_cert_pre_t *this;
623
624 INIT(this,
625 .public = {
626 .task = {
627 .get_type = _get_type,
628 .migrate = _migrate,
629 .destroy = _destroy,
630 },
631 },
632 .ike_sa = ike_sa,
633 .initiator = initiator,
634 .state = CR_SA,
635 .send_req = TRUE,
636 );
637 if (initiator)
638 {
639 this->public.task.build = _build_i;
640 this->public.task.process = _process_i;
641 }
642 else
643 {
644 this->public.task.build = _build_r;
645 this->public.task.process = _process_r;
646 }
647 return &this->public;
648 }