517f8c1bf4fc8a0359f9b000da229c6433e76084
[strongswan.git] / src / libcharon / sa / tasks / ike_cert_post_v1.c
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 #include "ike_cert_post_v1.h"
17
18 #include <daemon.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>
25
26
27 typedef struct private_ike_cert_post_v1_t private_ike_cert_post_v1_t;
28
29 /**
30 * Private members of a ike_cert_post_v1_t task.
31 */
32 struct private_ike_cert_post_v1_t {
33
34 /**
35 * Public methods and task_t interface.
36 */
37 ike_cert_post_v1_t public;
38
39 /**
40 * Assigned IKE_SA.
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Are we the initiator?
46 */
47 bool initiator;
48
49 /**
50 * States of ike cert pre
51 */
52 enum {
53 CR_SA,
54 CR_KE,
55 CR_AUTH,
56 } state;
57 };
58
59 /**
60 * Check if we actually use certificates for authentication
61 */
62 static bool use_certs(private_ike_cert_post_v1_t *this, message_t *message)
63 {
64 enumerator_t *enumerator;
65 payload_t *payload;
66 bool use = FALSE;
67
68 enumerator = message->create_payload_enumerator(message);
69 while (enumerator->enumerate(enumerator, &payload))
70 {
71 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
72 {
73 sa_payload_t *sa_payload = (sa_payload_t*)payload;
74
75 switch (sa_payload->get_auth_method(sa_payload))
76 {
77 case AUTH_RSA:
78 case AUTH_XAUTH_INIT_RSA:
79 case AUTH_XAUTH_RESP_RSA:
80 use = TRUE;
81 break;
82 default:
83 break;
84 }
85 break;
86 }
87 }
88 enumerator->destroy(enumerator);
89
90 return use;
91 }
92
93 /**
94 * Add certificates to message
95 */
96 static void build_certs(private_ike_cert_post_v1_t *this, message_t *message)
97 {
98 peer_cfg_t *peer_cfg;
99
100 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
101 if (!peer_cfg)
102 {
103 return;
104 }
105
106 switch (peer_cfg->get_cert_policy(peer_cfg))
107 {
108 case CERT_NEVER_SEND:
109 break;
110 case CERT_SEND_IF_ASKED:
111 if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
112 {
113 break;
114 }
115 /* FALL */
116 case CERT_ALWAYS_SEND:
117 {
118 cert_payload_t *payload;
119 enumerator_t *enumerator;
120 certificate_t *cert;
121 auth_rule_t type;
122 auth_cfg_t *auth;
123
124 auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
125 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
126 if (!cert)
127 {
128 break;
129 }
130 payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
131 if (!payload)
132 {
133 break;
134 }
135 DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
136 cert->get_subject(cert));
137 message->add_payload(message, (payload_t*)payload);
138
139 enumerator = auth->create_enumerator(auth);
140 while (enumerator->enumerate(enumerator, &type, &cert))
141 {
142 if (type == AUTH_RULE_IM_CERT)
143 {
144 payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
145 if (payload)
146 {
147 DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
148 cert->get_subject(cert));
149 message->add_payload(message, (payload_t*)payload);
150 }
151 }
152 }
153 enumerator->destroy(enumerator);
154 }
155 }
156 }
157
158 METHOD(task_t, build_i, status_t,
159 private_ike_cert_post_v1_t *this, message_t *message)
160 {
161 switch (message->get_exchange_type(message))
162 {
163 case ID_PROT:
164 if (this->state == CR_AUTH)
165 {
166 build_certs(this, message);
167 return SUCCESS;
168 }
169 return NEED_MORE;
170 case AGGRESSIVE:
171 if (this->state == CR_AUTH)
172 {
173 build_certs(this, message);
174 return SUCCESS;
175 }
176 return NEED_MORE;
177 default:
178 return FAILED;
179 }
180 }
181
182 METHOD(task_t, process_r, status_t,
183 private_ike_cert_post_v1_t *this, message_t *message)
184 {
185 switch (message->get_exchange_type(message))
186 {
187 case ID_PROT:
188 {
189 switch (this->state)
190 {
191 case CR_SA:
192 if (!use_certs(this, message))
193 {
194 return SUCCESS;
195 }
196 return NEED_MORE;
197 case CR_KE:
198 return NEED_MORE;
199 case CR_AUTH:
200 return NEED_MORE;
201 }
202 }
203 case AGGRESSIVE:
204 {
205 switch (this->state)
206 {
207 case CR_SA:
208 if (!use_certs(this, message))
209 {
210 return SUCCESS;
211 }
212 return NEED_MORE;
213 case CR_AUTH:
214 return SUCCESS;
215 default:
216 return FAILED;
217 }
218 }
219 default:
220 return FAILED;
221 }
222 }
223
224 METHOD(task_t, build_r, status_t,
225 private_ike_cert_post_v1_t *this, message_t *message)
226 {
227 switch (message->get_exchange_type(message))
228 {
229 case ID_PROT:
230 switch (this->state)
231 {
232 case CR_SA:
233 this->state = CR_KE;
234 return NEED_MORE;
235 case CR_KE:
236 this->state = CR_AUTH;
237 return NEED_MORE;
238 case CR_AUTH:
239 build_certs(this, message);
240 return SUCCESS;
241 }
242 case AGGRESSIVE:
243 switch (this->state)
244 {
245 case CR_SA:
246 build_certs(this, message);
247 this->state = CR_AUTH;
248 return NEED_MORE;
249 case CR_AUTH:
250 return SUCCESS;
251 default:
252 return FAILED;
253 }
254 default:
255 return FAILED;
256 }
257 }
258
259 METHOD(task_t, process_i, status_t,
260 private_ike_cert_post_v1_t *this, message_t *message)
261 {
262 switch (message->get_exchange_type(message))
263 {
264 case ID_PROT:
265 {
266 switch (this->state)
267 {
268 case CR_SA:
269 if (!use_certs(this, message))
270 {
271 return SUCCESS;
272 }
273 this->state = CR_KE;
274 return NEED_MORE;
275 case CR_KE:
276 this->state = CR_AUTH;
277 return NEED_MORE;
278 case CR_AUTH:
279 return SUCCESS;
280 default:
281 return FAILED;
282 }
283 break;
284 }
285 case AGGRESSIVE:
286 {
287 if (!use_certs(this, message))
288 {
289 return SUCCESS;
290 }
291 return SUCCESS;
292 }
293 default:
294 return FAILED;
295 }
296 }
297
298 METHOD(task_t, get_type, task_type_t,
299 private_ike_cert_post_v1_t *this)
300 {
301 return TASK_IKE_CERT_POST_V1;
302 }
303
304 METHOD(task_t, migrate, void,
305 private_ike_cert_post_v1_t *this, ike_sa_t *ike_sa)
306 {
307 this->ike_sa = ike_sa;
308 }
309
310 METHOD(task_t, destroy, void,
311 private_ike_cert_post_v1_t *this)
312 {
313 free(this);
314 }
315
316 /*
317 * Described in header.
318 */
319 ike_cert_post_v1_t *ike_cert_post_v1_create(ike_sa_t *ike_sa, bool initiator)
320 {
321 private_ike_cert_post_v1_t *this;
322
323 INIT(this,
324 .public = {
325 .task = {
326 .get_type = _get_type,
327 .migrate = _migrate,
328 .destroy = _destroy,
329 },
330 },
331 .ike_sa = ike_sa,
332 .initiator = initiator,
333 .state = CR_SA,
334 );
335 if (initiator)
336 {
337 this->public.task.process = _process_i;
338 this->public.task.build = _build_i;
339 }
340 else
341 {
342 this->public.task.process = _process_r;
343 this->public.task.build = _build_r;
344 }
345 return &this->public;
346 }