2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2006-2009 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "ike_cert_post.h"
20 #include <sa/ike_sa.h>
21 #include <encoding/payloads/cert_payload.h>
22 #include <encoding/payloads/certreq_payload.h>
23 #include <encoding/payloads/auth_payload.h>
24 #include <credentials/certificates/x509.h>
25 #include <credentials/certificates/ac.h>
28 typedef struct private_ike_cert_post_t private_ike_cert_post_t
;
31 * Private members of a ike_cert_post_t task.
33 struct private_ike_cert_post_t
{
36 * Public methods and task_t interface.
38 ike_cert_post_t
public;
46 * Are we the initiator?
52 * Generates the cert payload, if possible with "Hash and URL"
54 static cert_payload_t
*build_cert_payload(private_ike_cert_post_t
*this,
59 chunk_t hash
, encoded
;
60 enumerator_t
*enumerator
;
62 cert_payload_t
*payload
= NULL
;
64 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_HASH_AND_URL
))
66 return cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
69 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
72 DBG1(DBG_IKE
, "unable to use hash-and-url: sha1 not supported");
73 return cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
76 if (!cert
->get_encoding(cert
, CERT_ASN1_DER
, &encoded
))
78 DBG1(DBG_IKE
, "encoding certificate for cert payload failed");
79 hasher
->destroy(hasher
);
82 if (!hasher
->allocate_hash(hasher
, encoded
, &hash
))
84 hasher
->destroy(hasher
);
86 return cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
89 hasher
->destroy(hasher
);
90 id
= identification_create_from_encoding(ID_KEY_ID
, hash
);
92 enumerator
= lib
->credmgr
->create_cdp_enumerator(lib
->credmgr
, CERT_X509
, id
);
93 if (enumerator
->enumerate(enumerator
, &url
))
95 payload
= cert_payload_create_from_hash_and_url(hash
, url
);
96 DBG1(DBG_IKE
, "sending hash-and-url \"%s\"", url
);
100 payload
= cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
102 enumerator
->destroy(enumerator
);
109 * Add subject certificate to message
111 static bool add_subject_cert(private_ike_cert_post_t
*this, auth_cfg_t
*auth
,
114 cert_payload_t
*payload
;
117 cert
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
122 payload
= build_cert_payload(this, cert
);
127 DBG1(DBG_IKE
, "sending end entity cert \"%Y\"", cert
->get_subject(cert
));
128 message
->add_payload(message
, (payload_t
*)payload
);
133 * Add intermediate CA certificates to message
135 static void add_im_certs(private_ike_cert_post_t
*this, auth_cfg_t
*auth
,
138 cert_payload_t
*payload
;
139 enumerator_t
*enumerator
;
143 enumerator
= auth
->create_enumerator(auth
);
144 while (enumerator
->enumerate(enumerator
, &type
, &cert
))
146 if (type
== AUTH_RULE_IM_CERT
)
148 payload
= cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
151 DBG1(DBG_IKE
, "sending issuer cert \"%Y\"",
152 cert
->get_subject(cert
));
153 message
->add_payload(message
, (payload_t
*)payload
);
157 enumerator
->destroy(enumerator
);
161 * Add any valid attribute certificates of subject to message
163 static void add_attribute_certs(private_ike_cert_post_t
*this,
164 auth_cfg_t
*auth
, message_t
*message
)
166 certificate_t
*subject
, *cert
;
168 subject
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
169 if (subject
&& subject
->get_type(subject
) == CERT_X509
)
171 x509_t
*x509
= (x509_t
*)subject
;
172 identification_t
*id
, *serial
;
173 enumerator_t
*enumerator
;
174 cert_payload_t
*payload
;
177 /* we look for attribute certs having our serial and holder issuer,
178 * which is recommended by RFC 5755 */
179 serial
= identification_create_from_encoding(ID_KEY_ID
,
180 x509
->get_serial(x509
));
181 enumerator
= lib
->credmgr
->create_cert_enumerator(lib
->credmgr
,
182 CERT_X509_AC
, KEY_ANY
, serial
, FALSE
);
183 while (enumerator
->enumerate(enumerator
, &ac
))
185 cert
= &ac
->certificate
;
186 id
= ac
->get_holderIssuer(ac
);
187 if (id
&& id
->equals(id
, subject
->get_issuer(subject
)) &&
188 cert
->get_validity(cert
, NULL
, NULL
, NULL
))
190 payload
= cert_payload_create_from_cert(PLV2_CERTIFICATE
, cert
);
193 DBG1(DBG_IKE
, "sending attribute certificate "
194 "issued by \"%Y\"", cert
->get_issuer(cert
));
195 message
->add_payload(message
, (payload_t
*)payload
);
199 enumerator
->destroy(enumerator
);
200 serial
->destroy(serial
);
205 * add certificates to message
207 static void build_certs(private_ike_cert_post_t
*this, message_t
*message
)
209 peer_cfg_t
*peer_cfg
;
210 auth_payload_t
*payload
;
213 payload
= (auth_payload_t
*)message
->get_payload(message
, PLV2_AUTH
);
214 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
215 if (!peer_cfg
|| !payload
|| payload
->get_auth_method(payload
) == AUTH_PSK
)
216 { /* no CERT payload for EAP/PSK */
220 switch (peer_cfg
->get_cert_policy(peer_cfg
))
222 case CERT_NEVER_SEND
:
224 case CERT_SEND_IF_ASKED
:
225 if (!this->ike_sa
->has_condition(this->ike_sa
, COND_CERTREQ_SEEN
))
230 case CERT_ALWAYS_SEND
:
231 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
232 if (add_subject_cert(this, auth
, message
))
234 add_im_certs(this, auth
, message
);
235 add_attribute_certs(this, auth
, message
);
241 METHOD(task_t
, build_i
, status_t
,
242 private_ike_cert_post_t
*this, message_t
*message
)
244 build_certs(this, message
);
249 METHOD(task_t
, process_r
, status_t
,
250 private_ike_cert_post_t
*this, message_t
*message
)
255 METHOD(task_t
, build_r
, status_t
,
256 private_ike_cert_post_t
*this, message_t
*message
)
258 build_certs(this, message
);
260 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
261 { /* stay alive, we might have additional rounds with certs */
267 METHOD(task_t
, process_i
, status_t
,
268 private_ike_cert_post_t
*this, message_t
*message
)
270 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
271 { /* stay alive, we might have additional rounds with CERTS */
277 METHOD(task_t
, get_type
, task_type_t
,
278 private_ike_cert_post_t
*this)
280 return TASK_IKE_CERT_POST
;
283 METHOD(task_t
, migrate
, void,
284 private_ike_cert_post_t
*this, ike_sa_t
*ike_sa
)
286 this->ike_sa
= ike_sa
;
289 METHOD(task_t
, destroy
, void,
290 private_ike_cert_post_t
*this)
296 * Described in header.
298 ike_cert_post_t
*ike_cert_post_create(ike_sa_t
*ike_sa
, bool initiator
)
300 private_ike_cert_post_t
*this;
305 .get_type
= _get_type
,
311 .initiator
= initiator
,
316 this->public.task
.build
= _build_i
;
317 this->public.task
.process
= _process_i
;
321 this->public.task
.build
= _build_r
;
322 this->public.task
.process
= _process_r
;
325 return &this->public;