Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_cert_post.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2019 Tobias Brunner
3: * Copyright (C) 2006-2009 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
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>.
10: *
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
14: * for more details.
15: */
16:
17: #include "ike_cert_post.h"
18:
19: #include <daemon.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>
26:
27:
28: typedef struct private_ike_cert_post_t private_ike_cert_post_t;
29:
30: /**
31: * Private members of a ike_cert_post_t task.
32: */
33: struct private_ike_cert_post_t {
34:
35: /**
36: * Public methods and task_t interface.
37: */
38: ike_cert_post_t public;
39:
40: /**
41: * Assigned IKE_SA.
42: */
43: ike_sa_t *ike_sa;
44:
45: /**
46: * Are we the initiator?
47: */
48: bool initiator;
49: };
50:
51: /**
52: * Generate the payload for a hash-and-URL encoded certificate
53: */
54: static bool build_hash_url_payload(char *base, certificate_t *cert,
55: cert_payload_t **payload)
56: {
57: hasher_t *hasher;
58: chunk_t hash, encoded;
59: char *url, *hex_hash;
60:
61: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
62: if (!hasher)
63: {
64: DBG1(DBG_IKE, "unable to use hash-and-url: SHA-1 not supported");
65: return FALSE;
66: }
67:
68: if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
69: {
70: hasher->destroy(hasher);
71: return FALSE;
72: }
73: if (!hasher->allocate_hash(hasher, encoded, &hash))
74: {
75: hasher->destroy(hasher);
76: chunk_free(&encoded);
77: return FALSE;
78: }
79: chunk_free(&encoded);
80: hasher->destroy(hasher);
81:
82: url = malloc(strlen(base) + 40 + 1);
83: strcpy(url, base);
84: hex_hash = chunk_to_hex(hash, NULL, FALSE).ptr;
85: strncat(url, hex_hash, 40);
86: free(hex_hash);
87:
88: DBG1(DBG_IKE, "sending hash-and-url \"%s\"", url);
89: *payload = cert_payload_create_from_hash_and_url(hash, url);
90: chunk_free(&hash);
91: free(url);
92: return TRUE;
93: }
94:
95: /**
96: * Generates the cert payload, if possible with "Hash and URL"
97: */
98: static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
99: certificate_t *cert)
100: {
101: enumerator_t *enumerator;
102: char *base;
103: cert_payload_t *payload = NULL;
104:
105: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
106: {
107: return cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
108: }
109:
110: enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509,
111: cert->get_issuer(cert));
112: if (!enumerator->enumerate(enumerator, &base) ||
113: !build_hash_url_payload(base, cert, &payload))
114: {
115: payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
116: }
117: enumerator->destroy(enumerator);
118: return payload;
119: }
120:
121: /**
122: * Add subject certificate to message
123: */
124: static bool add_subject_cert(private_ike_cert_post_t *this, auth_cfg_t *auth,
125: message_t *message)
126: {
127: cert_payload_t *payload;
128: certificate_t *cert;
129:
130: cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
131: if (!cert)
132: {
133: return FALSE;
134: }
135: payload = build_cert_payload(this, cert);
136: if (!payload)
137: {
138: return FALSE;
139: }
140: DBG1(DBG_IKE, "sending end entity cert \"%Y\"", cert->get_subject(cert));
141: message->add_payload(message, (payload_t*)payload);
142: return TRUE;
143: }
144:
145: /**
146: * Add intermediate CA certificates to message
147: */
148: static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth,
149: message_t *message)
150: {
151: cert_payload_t *payload;
152: enumerator_t *enumerator;
153: certificate_t *cert;
154: auth_rule_t type;
155:
156: enumerator = auth->create_enumerator(auth);
157: while (enumerator->enumerate(enumerator, &type, &cert))
158: {
159: if (type == AUTH_RULE_IM_CERT)
160: {
161: payload = build_cert_payload(this, cert);
162: if (payload)
163: {
164: DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
165: cert->get_subject(cert));
166: message->add_payload(message, (payload_t*)payload);
167: }
168: }
169: }
170: enumerator->destroy(enumerator);
171: }
172:
173: /**
174: * Add any valid attribute certificates of subject to message
175: */
176: static void add_attribute_certs(private_ike_cert_post_t *this,
177: auth_cfg_t *auth, message_t *message)
178: {
179: certificate_t *subject, *cert;
180:
181: subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
182: if (subject && subject->get_type(subject) == CERT_X509)
183: {
184: x509_t *x509 = (x509_t*)subject;
185: identification_t *id, *serial;
186: enumerator_t *enumerator;
187: cert_payload_t *payload;
188: ac_t *ac;
189:
190: /* we look for attribute certs having our serial and holder issuer,
191: * which is recommended by RFC 5755 */
192: serial = identification_create_from_encoding(ID_KEY_ID,
193: x509->get_serial(x509));
194: enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
195: CERT_X509_AC, KEY_ANY, serial, FALSE);
196: while (enumerator->enumerate(enumerator, &ac))
197: {
198: cert = &ac->certificate;
199: id = ac->get_holderIssuer(ac);
200: if (id && id->equals(id, subject->get_issuer(subject)) &&
201: cert->get_validity(cert, NULL, NULL, NULL))
202: {
203: payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
204: if (payload)
205: {
206: DBG1(DBG_IKE, "sending attribute certificate "
207: "issued by \"%Y\"", cert->get_issuer(cert));
208: message->add_payload(message, (payload_t*)payload);
209: }
210: }
211: }
212: enumerator->destroy(enumerator);
213: serial->destroy(serial);
214: }
215: }
216:
217: /**
218: * add certificates to message
219: */
220: static void build_certs(private_ike_cert_post_t *this, message_t *message)
221: {
222: peer_cfg_t *peer_cfg;
223: auth_payload_t *payload;
224: auth_cfg_t *auth;
225:
226: payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
227: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
228: if (!peer_cfg || !payload || payload->get_auth_method(payload) == AUTH_PSK)
229: { /* no CERT payload for EAP/PSK */
230: return;
231: }
232:
233: switch (peer_cfg->get_cert_policy(peer_cfg))
234: {
235: case CERT_NEVER_SEND:
236: break;
237: case CERT_SEND_IF_ASKED:
238: if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
239: {
240: break;
241: }
242: /* FALL */
243: case CERT_ALWAYS_SEND:
244: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
245: if (add_subject_cert(this, auth, message))
246: {
247: add_im_certs(this, auth, message);
248: add_attribute_certs(this, auth, message);
249: }
250: break;
251: }
252: }
253:
254: METHOD(task_t, build_i, status_t,
255: private_ike_cert_post_t *this, message_t *message)
256: {
257: build_certs(this, message);
258:
259: return NEED_MORE;
260: }
261:
262: METHOD(task_t, process_r, status_t,
263: private_ike_cert_post_t *this, message_t *message)
264: {
265: return NEED_MORE;
266: }
267:
268: METHOD(task_t, build_r, status_t,
269: private_ike_cert_post_t *this, message_t *message)
270: {
271: build_certs(this, message);
272:
273: if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
274: { /* stay alive, we might have additional rounds with certs */
275: return NEED_MORE;
276: }
277: return SUCCESS;
278: }
279:
280: METHOD(task_t, process_i, status_t,
281: private_ike_cert_post_t *this, message_t *message)
282: {
283: if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
284: { /* stay alive, we might have additional rounds with CERTS */
285: return NEED_MORE;
286: }
287: return SUCCESS;
288: }
289:
290: METHOD(task_t, get_type, task_type_t,
291: private_ike_cert_post_t *this)
292: {
293: return TASK_IKE_CERT_POST;
294: }
295:
296: METHOD(task_t, migrate, void,
297: private_ike_cert_post_t *this, ike_sa_t *ike_sa)
298: {
299: this->ike_sa = ike_sa;
300: }
301:
302: METHOD(task_t, destroy, void,
303: private_ike_cert_post_t *this)
304: {
305: free(this);
306: }
307:
308: /*
309: * Described in header.
310: */
311: ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
312: {
313: private_ike_cert_post_t *this;
314:
315: INIT(this,
316: .public = {
317: .task = {
318: .get_type = _get_type,
319: .migrate = _migrate,
320: .destroy = _destroy,
321: },
322: },
323: .ike_sa = ike_sa,
324: .initiator = initiator,
325: );
326:
327: if (initiator)
328: {
329: this->public.task.build = _build_i;
330: this->public.task.process = _process_i;
331: }
332: else
333: {
334: this->public.task.build = _build_r;
335: this->public.task.process = _process_r;
336: }
337:
338: return &this->public;
339: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>