2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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>.
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
16 #include "ike_cert_pre_v1.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>
26 typedef struct private_ike_cert_pre_v1_t private_ike_cert_pre_v1_t
;
29 * Private members of a ike_cert_pre_v1_t task.
31 struct private_ike_cert_pre_v1_t
{
34 * Public methods and task_t interface.
36 ike_cert_pre_v1_t
public;
44 * Are we the initiator?
49 * Send certificate requests?
53 /** next message we expect */
62 * Find the CA certificate for a given certreq payload
64 static certificate_t
* find_certificate(private_ike_cert_pre_v1_t
*this,
65 certreq_payload_t
*certreq
)
70 if (certreq
->get_cert_type(certreq
) != CERT_X509
)
72 DBG1(DBG_IKE
, "%N CERTREQ not supported - ignored",
73 certificate_type_names
, certreq
->get_cert_type(certreq
));
76 id
= certreq
->get_dn(certreq
);
79 DBG1(DBG_IKE
, "ignoring certificate request without data",
80 certificate_type_names
, certreq
->get_cert_type(certreq
));
83 cert
= lib
->credmgr
->get_cert(lib
->credmgr
, CERT_X509
, KEY_ANY
, id
, TRUE
);
86 DBG1(DBG_IKE
, "received cert request for '%Y'",
87 cert
->get_subject(cert
));
91 DBG1(DBG_IKE
, "received cert request for unknown ca '%Y'", id
);
99 * read certificate requests
101 static void process_certreqs(private_ike_cert_pre_v1_t
*this, message_t
*message
)
103 enumerator_t
*enumerator
;
107 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
109 enumerator
= message
->create_payload_enumerator(message
);
110 while (enumerator
->enumerate(enumerator
, &payload
))
112 switch (payload
->get_type(payload
))
114 case CERTIFICATE_REQUEST_V1
:
118 this->ike_sa
->set_condition(this->ike_sa
,
119 COND_CERTREQ_SEEN
, TRUE
);
120 cert
= find_certificate(this, (certreq_payload_t
*)payload
);
123 auth
->add(auth
, AUTH_RULE_CA_CERT
, cert
);
131 enumerator
->destroy(enumerator
);
135 * Import receuved certificates
137 static void process_certs(private_ike_cert_pre_v1_t
*this, message_t
*message
)
139 enumerator_t
*enumerator
;
144 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, FALSE
);
146 enumerator
= message
->create_payload_enumerator(message
);
147 while (enumerator
->enumerate(enumerator
, &payload
))
149 if (payload
->get_type(payload
) == CERTIFICATE_V1
)
151 cert_payload_t
*cert_payload
;
152 cert_encoding_t encoding
;
155 cert_payload
= (cert_payload_t
*)payload
;
156 encoding
= cert_payload
->get_cert_encoding(cert_payload
);
160 case ENC_X509_SIGNATURE
:
162 cert
= cert_payload
->get_cert(cert_payload
);
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
);
174 DBG1(DBG_IKE
, "received issuer cert \"%Y\"",
175 cert
->get_subject(cert
));
176 auth
->add(auth
, AUTH_HELPER_IM_CERT
, cert
);
182 cert
= cert_payload
->get_cert(cert_payload
);
185 DBG1(DBG_IKE
, "received CRL \"%Y\"",
186 cert
->get_subject(cert
));
187 auth
->add(auth
, AUTH_HELPER_REVOCATION_CERT
, cert
);
190 case ENC_PKCS7_WRAPPED_X509
:
192 case ENC_DNS_SIGNED_KEY
:
193 case ENC_KERBEROS_TOKEN
:
196 case ENC_X509_ATTRIBUTE
:
197 case ENC_RAW_RSA_KEY
:
198 case ENC_X509_HASH_AND_URL_BUNDLE
:
199 case ENC_OCSP_CONTENT
:
201 DBG1(DBG_ENC
, "certificate encoding %N not supported",
202 cert_encoding_names
, encoding
);
206 enumerator
->destroy(enumerator
);
210 * Add the subject of a CA certificate a message
212 static void add_certreq(private_ike_cert_pre_v1_t
*this, message_t
*message
,
215 if (cert
->get_type(cert
) == CERT_X509
)
217 x509_t
*x509
= (x509_t
*)cert
;
219 if (x509
->get_flags(x509
) & X509_CA
)
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
)));
230 * Add auth_cfg's CA certificates to the certificate request
232 static void add_certreqs(private_ike_cert_pre_v1_t
*this,
233 auth_cfg_t
*auth
, message_t
*message
)
235 enumerator_t
*enumerator
;
239 enumerator
= auth
->create_enumerator(auth
);
240 while (enumerator
->enumerate(enumerator
, &type
, &value
))
244 case AUTH_RULE_CA_CERT
:
245 add_certreq(this, message
, (certificate_t
*)value
);
251 enumerator
->destroy(enumerator
);
255 * Build certificate requests
257 static void build_certreqs(private_ike_cert_pre_v1_t
*this, message_t
*message
)
259 enumerator_t
*enumerator
;
261 peer_cfg_t
*peer_cfg
;
265 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
266 if (!ike_cfg
->send_certreq(ike_cfg
))
270 /* check if we require a specific CA for that peer */
271 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
274 enumerator
= peer_cfg
->create_auth_cfg_enumerator(peer_cfg
, FALSE
);
275 if (enumerator
->enumerate(enumerator
, &auth
))
277 add_certreqs(this, auth
, message
);
279 enumerator
->destroy(enumerator
);
281 if (!message
->get_payload(message
, CERTIFICATE_REQUEST_V1
))
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
))
288 add_certreq(this, message
, cert
);
290 enumerator
->destroy(enumerator
);
295 * Check if we actually use certificates for authentication
297 static bool use_certs(private_ike_cert_pre_v1_t
*this, message_t
*message
)
299 enumerator_t
*enumerator
;
303 enumerator
= message
->create_payload_enumerator(message
);
304 while (enumerator
->enumerate(enumerator
, &payload
))
306 if (payload
->get_type(payload
) == SECURITY_ASSOCIATION_V1
)
308 sa_payload_t
*sa_payload
= (sa_payload_t
*)payload
;
310 switch (sa_payload
->get_auth_method(sa_payload
))
312 case AUTH_HYBRID_INIT_RSA
:
313 case AUTH_HYBRID_RESP_RSA
:
314 if (!this->initiator
)
316 this->send_req
= FALSE
;
320 case AUTH_XAUTH_INIT_RSA
:
321 case AUTH_XAUTH_RESP_RSA
:
330 enumerator
->destroy(enumerator
);
335 METHOD(task_t
, build_i
, status_t
,
336 private_ike_cert_pre_v1_t
*this, message_t
*message
)
338 switch (message
->get_exchange_type(message
))
341 if (this->state
== CR_AUTH
)
343 build_certreqs(this, message
);
347 if (this->state
== CR_SA
)
349 build_certreqs(this, message
);
357 METHOD(task_t
, process_r
, status_t
,
358 private_ike_cert_pre_v1_t
*this, message_t
*message
)
360 switch (message
->get_exchange_type(message
))
367 if (!use_certs(this, message
))
373 process_certreqs(this, message
);
376 process_certreqs(this, message
);
377 process_certs(this, message
);
386 if (!use_certs(this, message
))
390 process_certreqs(this, message
);
393 process_certs(this, message
);
404 METHOD(task_t
, build_r
, status_t
,
405 private_ike_cert_pre_v1_t
*this, message_t
*message
)
407 switch (message
->get_exchange_type(message
))
418 build_certreqs(this, message
);
420 this->state
= CR_AUTH
;
429 this->state
= CR_AUTH
;
441 METHOD(task_t
, process_i
, status_t
,
442 private_ike_cert_pre_v1_t
*this, message_t
*message
)
444 switch (message
->get_exchange_type(message
))
451 if (!use_certs(this, message
))
458 process_certreqs(this, message
);
459 this->state
= CR_AUTH
;
462 process_certs(this, message
);
471 if (!use_certs(this, message
))
475 process_certreqs(this, message
);
476 process_certs(this, message
);
484 METHOD(task_t
, get_type
, task_type_t
,
485 private_ike_cert_pre_v1_t
*this)
487 return TASK_IKE_CERT_PRE_V1
;
490 METHOD(task_t
, migrate
, void,
491 private_ike_cert_pre_v1_t
*this, ike_sa_t
*ike_sa
)
493 this->ike_sa
= ike_sa
;
496 METHOD(task_t
, destroy
, void,
497 private_ike_cert_pre_v1_t
*this)
503 * Described in header.
505 ike_cert_pre_v1_t
*ike_cert_pre_v1_create(ike_sa_t
*ike_sa
, bool initiator
)
507 private_ike_cert_pre_v1_t
*this;
512 .get_type
= _get_type
,
518 .initiator
= initiator
,
524 this->public.task
.build
= _build_i
;
525 this->public.task
.process
= _process_i
;
529 this->public.task
.build
= _build_r
;
530 this->public.task
.process
= _process_r
;
532 return &this->public;