Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c, revision 1.1.1.1
1.1 misho 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 PLV1_CERTREQ:
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: * Process an X509 certificate payload
159: */
160: static void process_x509(cert_payload_t *payload, auth_cfg_t *auth, bool *first)
161: {
162: certificate_t *cert;
163:
164: cert = payload->get_cert(payload);
165: if (cert)
166: {
167: if (*first)
168: { /* the first is an end entity certificate */
169: DBG1(DBG_IKE, "received end entity cert \"%Y\"",
170: cert->get_subject(cert));
171: auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
172: *first = FALSE;
173: }
174: else
175: {
176: DBG1(DBG_IKE, "received issuer cert \"%Y\"",
177: cert->get_subject(cert));
178: auth->add(auth, AUTH_HELPER_IM_CERT, cert);
179: }
180: }
181: }
182:
183: /**
184: * Process a CRL certificate payload
185: */
186: static void process_crl(cert_payload_t *payload, auth_cfg_t *auth)
187: {
188: certificate_t *cert;
189:
190: cert = payload->get_cert(payload);
191: if (cert)
192: {
193: DBG1(DBG_IKE, "received CRL \"%Y\"", cert->get_subject(cert));
194: auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
195: }
196: }
197:
198: /**
199: * Process a PKCS7 certificate payload
200: */
201: static void process_pkcs7(cert_payload_t *payload, auth_cfg_t *auth)
202: {
203: enumerator_t *enumerator;
204: container_t *container;
205: certificate_t *cert;
206: pkcs7_t *pkcs7;
207:
208: container = payload->get_container(payload);
209: if (!container)
210: {
211: return;
212: }
213: switch (container->get_type(container))
214: {
215: case CONTAINER_PKCS7_DATA:
216: case CONTAINER_PKCS7_SIGNED_DATA:
217: case CONTAINER_PKCS7_ENVELOPED_DATA:
218: break;
219: default:
220: container->destroy(container);
221: return;
222: }
223:
224: pkcs7 = (pkcs7_t *)container;
225: enumerator = pkcs7->create_cert_enumerator(pkcs7);
226: while (enumerator->enumerate(enumerator, &cert))
227: {
228: if (cert->get_type(cert) == CERT_X509)
229: {
230: x509_t *x509 = (x509_t*)cert;
231:
232: if (x509->get_flags(x509) & X509_CA)
233: {
234: DBG1(DBG_IKE, "received issuer cert \"%Y\"",
235: cert->get_subject(cert));
236: auth->add(auth, AUTH_HELPER_IM_CERT, cert->get_ref(cert));
237: }
238: else
239: {
240: DBG1(DBG_IKE, "received end entity cert \"%Y\"",
241: cert->get_subject(cert));
242: auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert->get_ref(cert));
243: }
244: }
245: else
246: {
247: DBG1(DBG_IKE, "received unsupported cert type %N",
248: certificate_type_names, cert->get_type(cert));
249: }
250: }
251: enumerator->destroy(enumerator);
252:
253: container->destroy(container);
254: }
255:
256: /**
257: * Import received certificates
258: */
259: static void process_certs(private_isakmp_cert_pre_t *this, message_t *message)
260: {
261: enumerator_t *enumerator;
262: payload_t *payload;
263: auth_cfg_t *auth;
264: bool first = TRUE;
265:
266: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
267:
268: enumerator = message->create_payload_enumerator(message);
269: while (enumerator->enumerate(enumerator, &payload))
270: {
271: if (payload->get_type(payload) == PLV1_CERTIFICATE)
272: {
273: cert_payload_t *cert_payload;
274: cert_encoding_t encoding;
275:
276: cert_payload = (cert_payload_t*)payload;
277: encoding = cert_payload->get_cert_encoding(cert_payload);
278:
279: switch (encoding)
280: {
281: case ENC_X509_SIGNATURE:
282: process_x509(cert_payload, auth, &first);
283: break;
284: case ENC_CRL:
285: process_crl(cert_payload, auth);
286: break;
287: case ENC_PKCS7_WRAPPED_X509:
288: process_pkcs7(cert_payload, auth);
289: break;
290: case ENC_PGP:
291: case ENC_DNS_SIGNED_KEY:
292: case ENC_KERBEROS_TOKEN:
293: case ENC_ARL:
294: case ENC_SPKI:
295: case ENC_X509_ATTRIBUTE:
296: case ENC_RAW_RSA_KEY:
297: case ENC_X509_HASH_AND_URL_BUNDLE:
298: case ENC_OCSP_CONTENT:
299: default:
300: DBG1(DBG_ENC, "certificate encoding %N not supported",
301: cert_encoding_names, encoding);
302: }
303: }
304: }
305: enumerator->destroy(enumerator);
306: }
307:
308: /**
309: * Add the subject of a CA certificate a message
310: */
311: static void add_certreq(private_isakmp_cert_pre_t *this, message_t *message,
312: certificate_t *cert)
313: {
314: if (cert->get_type(cert) == CERT_X509)
315: {
316: x509_t *x509 = (x509_t*)cert;
317:
318: if (x509->get_flags(x509) & X509_CA)
319: {
320: DBG1(DBG_IKE, "sending cert request for \"%Y\"",
321: cert->get_subject(cert));
322: message->add_payload(message, (payload_t*)
323: certreq_payload_create_dn(cert->get_subject(cert)));
324: }
325: }
326: }
327:
328: /**
329: * Add auth_cfg's CA certificates to the certificate request
330: */
331: static void add_certreqs(private_isakmp_cert_pre_t *this,
332: auth_cfg_t *auth, message_t *message)
333: {
334: enumerator_t *enumerator;
335: auth_rule_t type;
336: void *value;
337:
338: enumerator = auth->create_enumerator(auth);
339: while (enumerator->enumerate(enumerator, &type, &value))
340: {
341: switch (type)
342: {
343: case AUTH_RULE_CA_CERT:
344: add_certreq(this, message, (certificate_t*)value);
345: break;
346: default:
347: break;
348: }
349: }
350: enumerator->destroy(enumerator);
351: }
352:
353: /**
354: * Build certificate requests
355: */
356: static void build_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
357: {
358: enumerator_t *enumerator;
359: ike_cfg_t *ike_cfg;
360: peer_cfg_t *peer_cfg;
361: certificate_t *cert;
362: auth_cfg_t *auth;
363:
364: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
365: if (!ike_cfg->send_certreq(ike_cfg))
366: {
367: return;
368: }
369: /* check if we require a specific CA for that peer */
370: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
371: if (peer_cfg)
372: {
373: enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
374: if (enumerator->enumerate(enumerator, &auth))
375: {
376: add_certreqs(this, auth, message);
377: }
378: enumerator->destroy(enumerator);
379: }
380: if (!message->get_payload(message, PLV1_CERTREQ))
381: {
382: /* otherwise add all trusted CA certificates */
383: enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
384: CERT_ANY, KEY_ANY, NULL, TRUE);
385: while (enumerator->enumerate(enumerator, &cert))
386: {
387: add_certreq(this, message, cert);
388: }
389: enumerator->destroy(enumerator);
390: }
391: }
392:
393: /**
394: * Check if we actually use certificates for authentication
395: */
396: static bool use_certs(private_isakmp_cert_pre_t *this, message_t *message)
397: {
398: enumerator_t *enumerator;
399: payload_t *payload;
400: bool use = FALSE;
401:
402: enumerator = message->create_payload_enumerator(message);
403: while (enumerator->enumerate(enumerator, &payload))
404: {
405: if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
406: {
407: sa_payload_t *sa_payload = (sa_payload_t*)payload;
408:
409: switch (sa_payload->get_auth_method(sa_payload))
410: {
411: case AUTH_HYBRID_INIT_RSA:
412: case AUTH_HYBRID_RESP_RSA:
413: if (!this->initiator)
414: {
415: this->send_req = FALSE;
416: }
417: /* FALL */
418: case AUTH_RSA:
419: case AUTH_ECDSA_256:
420: case AUTH_ECDSA_384:
421: case AUTH_ECDSA_521:
422: case AUTH_XAUTH_INIT_RSA:
423: case AUTH_XAUTH_RESP_RSA:
424: use = TRUE;
425: break;
426: default:
427: break;
428: }
429: break;
430: }
431: }
432: enumerator->destroy(enumerator);
433:
434: return use;
435: }
436:
437: /**
438: * Check if we should send a certificate request
439: */
440: static bool send_certreq(private_isakmp_cert_pre_t *this)
441: {
442: enumerator_t *enumerator;
443: peer_cfg_t *peer_cfg;
444: auth_cfg_t *auth;
445: bool req = FALSE;
446: auth_class_t class;
447:
448: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
449: if (peer_cfg)
450: {
451: enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
452: if (enumerator->enumerate(enumerator, &auth))
453: {
454: class = (intptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
455: if (class == AUTH_CLASS_PUBKEY)
456: {
457: req = TRUE;
458: }
459: }
460: enumerator->destroy(enumerator);
461: }
462: return req;
463: }
464:
465: METHOD(task_t, build_i, status_t,
466: private_isakmp_cert_pre_t *this, message_t *message)
467: {
468: switch (message->get_exchange_type(message))
469: {
470: case ID_PROT:
471: if (this->state == CR_AUTH)
472: {
473: build_certreqs(this, message);
474: }
475: return NEED_MORE;
476: case AGGRESSIVE:
477: if (this->state == CR_SA)
478: {
479: if (send_certreq(this))
480: {
481: build_certreqs(this, message);
482: }
483: }
484: return NEED_MORE;
485: default:
486: return FAILED;
487: }
488: }
489:
490: METHOD(task_t, process_r, status_t,
491: private_isakmp_cert_pre_t *this, message_t *message)
492: {
493: switch (message->get_exchange_type(message))
494: {
495: case ID_PROT:
496: {
497: switch (this->state)
498: {
499: case CR_SA:
500: if (!use_certs(this, message))
501: {
502: return SUCCESS;
503: }
504: return NEED_MORE;
505: case CR_KE:
506: process_certreqs(this, message);
507: return NEED_MORE;
508: case CR_AUTH:
509: process_certreqs(this, message);
510: process_certs(this, message);
511: return SUCCESS;
512: default:
513: return FAILED;
514: }
515: }
516: case AGGRESSIVE:
517: {
518: switch (this->state)
519: {
520: case CR_SA:
521: if (!use_certs(this, message))
522: {
523: return SUCCESS;
524: }
525: process_certreqs(this, message);
526: return NEED_MORE;
527: case CR_AUTH:
528: process_certs(this, message);
529: return SUCCESS;
530: default:
531: return FAILED;
532: }
533: }
534: default:
535: return FAILED;
536: }
537: }
538:
539: METHOD(task_t, build_r, status_t,
540: private_isakmp_cert_pre_t *this, message_t *message)
541: {
542: switch (message->get_exchange_type(message))
543: {
544: case ID_PROT:
545: switch (this->state)
546: {
547: case CR_SA:
548: this->state = CR_KE;
549: return NEED_MORE;
550: case CR_KE:
551: if (this->send_req)
552: {
553: build_certreqs(this, message);
554: }
555: this->state = CR_AUTH;
556: return NEED_MORE;
557: case CR_AUTH:
558: return NEED_MORE;
559: default:
560: return FAILED;
561: }
562: case AGGRESSIVE:
563: switch (this->state)
564: {
565: case CR_SA:
566: if (this->send_req)
567: {
568: build_certreqs(this, message);
569: }
570: this->state = CR_AUTH;
571: return NEED_MORE;
572: case CR_AUTH:
573: return SUCCESS;
574: default:
575: return FAILED;
576: }
577: default:
578: return FAILED;
579: }
580: }
581:
582: METHOD(task_t, process_i, status_t,
583: private_isakmp_cert_pre_t *this, message_t *message)
584: {
585: switch (message->get_exchange_type(message))
586: {
587: case ID_PROT:
588: {
589: switch (this->state)
590: {
591: case CR_SA:
592: if (!use_certs(this, message))
593: {
594: return SUCCESS;
595: }
596: this->state = CR_KE;
597: return NEED_MORE;
598: case CR_KE:
599: process_certreqs(this, message);
600: this->state = CR_AUTH;
601: return NEED_MORE;
602: case CR_AUTH:
603: process_certs(this, message);
604: return SUCCESS;
605: default:
606: return FAILED;
607: }
608: }
609: case AGGRESSIVE:
610: {
611: if (!use_certs(this, message))
612: {
613: return SUCCESS;
614: }
615: process_certreqs(this, message);
616: process_certs(this, message);
617: this->state = CR_AUTH;
618: return SUCCESS;
619: }
620: default:
621: return FAILED;
622: }
623: }
624:
625: METHOD(task_t, get_type, task_type_t,
626: private_isakmp_cert_pre_t *this)
627: {
628: return TASK_ISAKMP_CERT_PRE;
629: }
630:
631: METHOD(task_t, migrate, void,
632: private_isakmp_cert_pre_t *this, ike_sa_t *ike_sa)
633: {
634: this->ike_sa = ike_sa;
635: this->state = CR_SA;
636: this->send_req = TRUE;
637: }
638:
639: METHOD(task_t, destroy, void,
640: private_isakmp_cert_pre_t *this)
641: {
642: free(this);
643: }
644:
645: /*
646: * Described in header.
647: */
648: isakmp_cert_pre_t *isakmp_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
649: {
650: private_isakmp_cert_pre_t *this;
651:
652: INIT(this,
653: .public = {
654: .task = {
655: .get_type = _get_type,
656: .migrate = _migrate,
657: .destroy = _destroy,
658: },
659: },
660: .ike_sa = ike_sa,
661: .initiator = initiator,
662: .state = CR_SA,
663: .send_req = TRUE,
664: );
665: if (initiator)
666: {
667: this->public.task.build = _build_i;
668: this->public.task.process = _process_i;
669: }
670: else
671: {
672: this->public.task.build = _build_r;
673: this->public.task.process = _process_r;
674: }
675: return &this->public;
676: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>