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>
27 typedef struct private_ike_cert_post_t private_ike_cert_post_t
;
30 * Private members of a ike_cert_post_t task.
32 struct private_ike_cert_post_t
{
35 * Public methods and task_t interface.
37 ike_cert_post_t
public;
45 * Are we the initiator?
51 * Generates the cert payload, if possible with "Hash and URL"
53 static cert_payload_t
*build_cert_payload(private_ike_cert_post_t
*this, certificate_t
*cert
)
55 cert_payload_t
*payload
= NULL
;
57 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_HASH_AND_URL
))
59 /* ok, our peer sent us a HTTP_CERT_LOOKUP_SUPPORTED Notify */
60 hasher_t
*hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
63 chunk_t hash
, encoded
= cert
->get_encoding(cert
);
64 enumerator_t
*enumerator
;
67 hasher
->allocate_hash(hasher
, encoded
, &hash
);
68 identification_t
*id
= identification_create_from_encoding(ID_CERT_DER_SHA1
, hash
);
70 enumerator
= charon
->credentials
->create_cdp_enumerator(charon
->credentials
, CERT_X509
, id
);
71 if (enumerator
->enumerate(enumerator
, &url
))
73 /* if we have an URL available we send that to our peer */
74 payload
= cert_payload_create_from_hash_and_url(hash
, url
);
76 enumerator
->destroy(enumerator
);
81 hasher
->destroy(hasher
);
85 DBG1(DBG_IKE
, "unable to use hash-and-url: sha1 not supported");
91 /* our peer does not support "Hash and URL" or we do not have an URL
92 * to send to our peer, just create a normal cert payload */
93 payload
= cert_payload_create_from_cert(cert
);
100 * add certificates to message
102 static void build_certs(private_ike_cert_post_t
*this, message_t
*message
)
104 peer_cfg_t
*peer_cfg
;
105 auth_payload_t
*payload
;
107 payload
= (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
108 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
109 if (!peer_cfg
|| !payload
|| payload
->get_auth_method(payload
) == AUTH_PSK
)
110 { /* no CERT payload for EAP/PSK */
114 switch (peer_cfg
->get_cert_policy(peer_cfg
))
116 case CERT_NEVER_SEND
:
118 case CERT_SEND_IF_ASKED
:
119 if (!this->ike_sa
->has_condition(this->ike_sa
, COND_CERTREQ_SEEN
))
124 case CERT_ALWAYS_SEND
:
126 cert_payload_t
*payload
;
127 enumerator_t
*enumerator
;
132 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
134 /* get subject cert first, then issuing certificates */
135 cert
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
140 payload
= build_cert_payload(this, cert
);
145 DBG1(DBG_IKE
, "sending end entity cert \"%Y\"",
146 cert
->get_subject(cert
));
147 message
->add_payload(message
, (payload_t
*)payload
);
149 enumerator
= auth
->create_enumerator(auth
);
150 while (enumerator
->enumerate(enumerator
, &type
, &cert
))
152 if (type
== AUTH_RULE_IM_CERT
)
154 payload
= cert_payload_create_from_cert(cert
);
157 DBG1(DBG_IKE
, "sending issuer cert \"%Y\"",
158 cert
->get_subject(cert
));
159 message
->add_payload(message
, (payload_t
*)payload
);
163 enumerator
->destroy(enumerator
);
169 * Implementation of task_t.process for initiator
171 static status_t
build_i(private_ike_cert_post_t
*this, message_t
*message
)
173 build_certs(this, message
);
179 * Implementation of task_t.process for responder
181 static status_t
process_r(private_ike_cert_post_t
*this, message_t
*message
)
187 * Implementation of task_t.build for responder
189 static status_t
build_r(private_ike_cert_post_t
*this, message_t
*message
)
191 build_certs(this, message
);
193 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
194 { /* stay alive, we might have additional rounds with certs */
201 * Implementation of task_t.process for initiator
203 static status_t
process_i(private_ike_cert_post_t
*this, message_t
*message
)
205 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
206 { /* stay alive, we might have additional rounds with CERTS */
213 * Implementation of task_t.get_type
215 static task_type_t
get_type(private_ike_cert_post_t
*this)
217 return IKE_CERT_POST
;
221 * Implementation of task_t.migrate
223 static void migrate(private_ike_cert_post_t
*this, ike_sa_t
*ike_sa
)
225 this->ike_sa
= ike_sa
;
229 * Implementation of task_t.destroy
231 static void destroy(private_ike_cert_post_t
*this)
237 * Described in header.
239 ike_cert_post_t
*ike_cert_post_create(ike_sa_t
*ike_sa
, bool initiator
)
241 private_ike_cert_post_t
*this = malloc_thing(private_ike_cert_post_t
);
243 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
244 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
245 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
249 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
250 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
254 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
255 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
258 this->ike_sa
= ike_sa
;
259 this->initiator
= initiator
;
261 return &this->public;