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