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 "isakmp_cert_post.h"
19 #include <sa/ike_sa.h>
20 #include <encoding/payloads/cert_payload.h>
21 #include <encoding/payloads/certreq_payload.h>
22 #include <encoding/payloads/auth_payload.h>
23 #include <encoding/payloads/sa_payload.h>
24 #include <credentials/certificates/x509.h>
27 typedef struct private_isakmp_cert_post_t private_isakmp_cert_post_t
;
30 * Private members of a isakmp_cert_post_t task.
32 struct private_isakmp_cert_post_t
{
35 * Public methods and task_t interface.
37 isakmp_cert_post_t
public;
45 * Are we the initiator?
50 * States of ike cert pre
60 * Check if we actually use certificates for authentication
62 static bool use_certs(private_isakmp_cert_post_t
*this, message_t
*message
)
64 enumerator_t
*enumerator
;
68 enumerator
= message
->create_payload_enumerator(message
);
69 while (enumerator
->enumerate(enumerator
, &payload
))
71 if (payload
->get_type(payload
) == PLV1_SECURITY_ASSOCIATION
)
73 sa_payload_t
*sa_payload
= (sa_payload_t
*)payload
;
75 switch (sa_payload
->get_auth_method(sa_payload
))
81 case AUTH_XAUTH_INIT_RSA
:
82 case AUTH_XAUTH_RESP_RSA
:
83 case AUTH_HYBRID_INIT_RSA
:
84 case AUTH_HYBRID_RESP_RSA
:
93 enumerator
->destroy(enumerator
);
99 * Add certificates to message
101 static void build_certs(private_isakmp_cert_post_t
*this, message_t
*message
)
103 peer_cfg_t
*peer_cfg
;
105 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
111 switch (peer_cfg
->get_cert_policy(peer_cfg
))
113 case CERT_NEVER_SEND
:
115 case CERT_SEND_IF_ASKED
:
116 if (!this->ike_sa
->has_condition(this->ike_sa
, COND_CERTREQ_SEEN
))
121 case CERT_ALWAYS_SEND
:
123 cert_payload_t
*payload
;
124 enumerator_t
*enumerator
;
129 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
130 cert
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
135 payload
= cert_payload_create_from_cert(PLV1_CERTIFICATE
, cert
);
140 DBG1(DBG_IKE
, "sending end entity cert \"%Y\"",
141 cert
->get_subject(cert
));
142 message
->add_payload(message
, (payload_t
*)payload
);
144 enumerator
= auth
->create_enumerator(auth
);
145 while (enumerator
->enumerate(enumerator
, &type
, &cert
))
147 if (type
== AUTH_RULE_IM_CERT
)
149 payload
= cert_payload_create_from_cert(PLV1_CERTIFICATE
, cert
);
152 DBG1(DBG_IKE
, "sending issuer cert \"%Y\"",
153 cert
->get_subject(cert
));
154 message
->add_payload(message
, (payload_t
*)payload
);
158 enumerator
->destroy(enumerator
);
163 METHOD(task_t
, build_i
, status_t
,
164 private_isakmp_cert_post_t
*this, message_t
*message
)
166 switch (message
->get_exchange_type(message
))
169 if (this->state
== CR_AUTH
)
171 build_certs(this, message
);
176 if (this->state
== CR_AUTH
)
178 build_certs(this, message
);
187 METHOD(task_t
, process_r
, status_t
,
188 private_isakmp_cert_post_t
*this, message_t
*message
)
190 switch (message
->get_exchange_type(message
))
197 if (!use_certs(this, message
))
215 if (!use_certs(this, message
))
231 METHOD(task_t
, build_r
, status_t
,
232 private_isakmp_cert_post_t
*this, message_t
*message
)
234 switch (message
->get_exchange_type(message
))
243 this->state
= CR_AUTH
;
246 build_certs(this, message
);
253 build_certs(this, message
);
254 this->state
= CR_AUTH
;
266 METHOD(task_t
, process_i
, status_t
,
267 private_isakmp_cert_post_t
*this, message_t
*message
)
269 switch (message
->get_exchange_type(message
))
276 if (!use_certs(this, message
))
283 this->state
= CR_AUTH
;
293 if (this->state
== CR_SA
)
295 if (!use_certs(this, message
))
299 this->state
= CR_AUTH
;
309 METHOD(task_t
, get_type
, task_type_t
,
310 private_isakmp_cert_post_t
*this)
312 return TASK_ISAKMP_CERT_POST
;
315 METHOD(task_t
, migrate
, void,
316 private_isakmp_cert_post_t
*this, ike_sa_t
*ike_sa
)
318 this->ike_sa
= ike_sa
;
322 METHOD(task_t
, destroy
, void,
323 private_isakmp_cert_post_t
*this)
329 * Described in header.
331 isakmp_cert_post_t
*isakmp_cert_post_create(ike_sa_t
*ike_sa
, bool initiator
)
333 private_isakmp_cert_post_t
*this;
338 .get_type
= _get_type
,
344 .initiator
= initiator
,
349 this->public.task
.process
= _process_i
;
350 this->public.task
.build
= _build_i
;
354 this->public.task
.process
= _process_r
;
355 this->public.task
.build
= _build_r
;
357 return &this->public;