Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c, revision 1.1.1.1
1.1 misho 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 "isakmp_cert_post.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_isakmp_cert_post_t private_isakmp_cert_post_t;
28:
29: /**
30: * Private members of a isakmp_cert_post_t task.
31: */
32: struct private_isakmp_cert_post_t {
33:
34: /**
35: * Public methods and task_t interface.
36: */
37: isakmp_cert_post_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_isakmp_cert_post_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) == PLV1_SECURITY_ASSOCIATION)
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_ECDSA_256:
79: case AUTH_ECDSA_384:
80: case AUTH_ECDSA_521:
81: case AUTH_XAUTH_INIT_RSA:
82: case AUTH_XAUTH_RESP_RSA:
83: case AUTH_HYBRID_INIT_RSA:
84: case AUTH_HYBRID_RESP_RSA:
85: use = TRUE;
86: break;
87: default:
88: break;
89: }
90: break;
91: }
92: }
93: enumerator->destroy(enumerator);
94:
95: return use;
96: }
97:
98: /**
99: * Add certificates to message
100: */
101: static void build_certs(private_isakmp_cert_post_t *this, message_t *message)
102: {
103: peer_cfg_t *peer_cfg;
104:
105: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
106: if (!peer_cfg)
107: {
108: return;
109: }
110:
111: switch (peer_cfg->get_cert_policy(peer_cfg))
112: {
113: case CERT_NEVER_SEND:
114: break;
115: case CERT_SEND_IF_ASKED:
116: if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
117: {
118: break;
119: }
120: /* FALL */
121: case CERT_ALWAYS_SEND:
122: {
123: cert_payload_t *payload;
124: enumerator_t *enumerator;
125: certificate_t *cert;
126: auth_rule_t type;
127: auth_cfg_t *auth;
128:
129: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
130: cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
131: if (!cert)
132: {
133: break;
134: }
135: payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
136: if (!payload)
137: {
138: break;
139: }
140: DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
141: cert->get_subject(cert));
142: message->add_payload(message, (payload_t*)payload);
143:
144: enumerator = auth->create_enumerator(auth);
145: while (enumerator->enumerate(enumerator, &type, &cert))
146: {
147: if (type == AUTH_RULE_IM_CERT)
148: {
149: payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
150: if (payload)
151: {
152: DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
153: cert->get_subject(cert));
154: message->add_payload(message, (payload_t*)payload);
155: }
156: }
157: }
158: enumerator->destroy(enumerator);
159: }
160: }
161: }
162:
163: METHOD(task_t, build_i, status_t,
164: private_isakmp_cert_post_t *this, message_t *message)
165: {
166: switch (message->get_exchange_type(message))
167: {
168: case ID_PROT:
169: if (this->state == CR_AUTH)
170: {
171: build_certs(this, message);
172: return SUCCESS;
173: }
174: return NEED_MORE;
175: case AGGRESSIVE:
176: if (this->state == CR_AUTH)
177: {
178: build_certs(this, message);
179: return SUCCESS;
180: }
181: return NEED_MORE;
182: default:
183: return FAILED;
184: }
185: }
186:
187: METHOD(task_t, process_r, status_t,
188: private_isakmp_cert_post_t *this, message_t *message)
189: {
190: switch (message->get_exchange_type(message))
191: {
192: case ID_PROT:
193: {
194: switch (this->state)
195: {
196: case CR_SA:
197: if (!use_certs(this, message))
198: {
199: return SUCCESS;
200: }
201: return NEED_MORE;
202: case CR_KE:
203: return NEED_MORE;
204: case CR_AUTH:
205: return NEED_MORE;
206: default:
207: return FAILED;
208: }
209: }
210: case AGGRESSIVE:
211: {
212: switch (this->state)
213: {
214: case CR_SA:
215: if (!use_certs(this, message))
216: {
217: return SUCCESS;
218: }
219: return NEED_MORE;
220: case CR_AUTH:
221: return SUCCESS;
222: default:
223: return FAILED;
224: }
225: }
226: default:
227: return FAILED;
228: }
229: }
230:
231: METHOD(task_t, build_r, status_t,
232: private_isakmp_cert_post_t *this, message_t *message)
233: {
234: switch (message->get_exchange_type(message))
235: {
236: case ID_PROT:
237: switch (this->state)
238: {
239: case CR_SA:
240: this->state = CR_KE;
241: return NEED_MORE;
242: case CR_KE:
243: this->state = CR_AUTH;
244: return NEED_MORE;
245: case CR_AUTH:
246: build_certs(this, message);
247: return SUCCESS;
248: }
249: case AGGRESSIVE:
250: switch (this->state)
251: {
252: case CR_SA:
253: build_certs(this, message);
254: this->state = CR_AUTH;
255: return NEED_MORE;
256: case CR_AUTH:
257: return SUCCESS;
258: default:
259: return FAILED;
260: }
261: default:
262: return FAILED;
263: }
264: }
265:
266: METHOD(task_t, process_i, status_t,
267: private_isakmp_cert_post_t *this, message_t *message)
268: {
269: switch (message->get_exchange_type(message))
270: {
271: case ID_PROT:
272: {
273: switch (this->state)
274: {
275: case CR_SA:
276: if (!use_certs(this, message))
277: {
278: return SUCCESS;
279: }
280: this->state = CR_KE;
281: return NEED_MORE;
282: case CR_KE:
283: this->state = CR_AUTH;
284: return NEED_MORE;
285: case CR_AUTH:
286: return SUCCESS;
287: default:
288: return FAILED;
289: }
290: }
291: case AGGRESSIVE:
292: {
293: if (this->state == CR_SA)
294: {
295: if (!use_certs(this, message))
296: {
297: return SUCCESS;
298: }
299: this->state = CR_AUTH;
300: return NEED_MORE;
301: }
302: return SUCCESS;
303: }
304: default:
305: return FAILED;
306: }
307: }
308:
309: METHOD(task_t, get_type, task_type_t,
310: private_isakmp_cert_post_t *this)
311: {
312: return TASK_ISAKMP_CERT_POST;
313: }
314:
315: METHOD(task_t, migrate, void,
316: private_isakmp_cert_post_t *this, ike_sa_t *ike_sa)
317: {
318: this->ike_sa = ike_sa;
319: this->state = CR_SA;
320: }
321:
322: METHOD(task_t, destroy, void,
323: private_isakmp_cert_post_t *this)
324: {
325: free(this);
326: }
327:
328: /*
329: * Described in header.
330: */
331: isakmp_cert_post_t *isakmp_cert_post_create(ike_sa_t *ike_sa, bool initiator)
332: {
333: private_isakmp_cert_post_t *this;
334:
335: INIT(this,
336: .public = {
337: .task = {
338: .get_type = _get_type,
339: .migrate = _migrate,
340: .destroy = _destroy,
341: },
342: },
343: .ike_sa = ike_sa,
344: .initiator = initiator,
345: .state = CR_SA,
346: );
347: if (initiator)
348: {
349: this->public.task.process = _process_i;
350: this->public.task.build = _build_i;
351: }
352: else
353: {
354: this->public.task.process = _process_r;
355: this->public.task.build = _build_r;
356: }
357: return &this->public;
358: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>