Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/cert_payload.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Tobias Brunner
3: * Copyright (C) 2005-2010 Martin Willi
4: * Copyright (C) 2010 revosec AG
5: * Copyright (C) 2005 Jan Hutter
6: * HSR Hochschule fuer Technik Rapperswil
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public License as published by the
10: * Free Software Foundation; either version 2 of the License, or (at your
11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12: *
13: * This program is distributed in the hope that it will be useful, but
14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16: * for more details.
17: */
18:
19: #include <stddef.h>
20: #include <ctype.h>
21:
22: #include <daemon.h>
23:
24: #include "cert_payload.h"
25:
26: ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT,
27: "ENC_PKCS7_WRAPPED_X509",
28: "ENC_PGP",
29: "ENC_DNS_SIGNED_KEY",
30: "ENC_X509_SIGNATURE",
31: "ENC_X509_KEY_EXCHANGE",
32: "ENC_KERBEROS_TOKENS",
33: "ENC_CRL",
34: "ENC_ARL",
35: "ENC_SPKI",
36: "ENC_X509_ATTRIBUTE",
37: "ENC_RAW_RSA_KEY",
38: "ENC_X509_HASH_AND_URL",
39: "ENC_X509_HASH_AND_URL_BUNDLE",
40: "ENC_OCSP_CONTENT",
41: );
42:
43: typedef struct private_cert_payload_t private_cert_payload_t;
44:
45: /**
46: * Private data of an cert_payload_t object.
47: */
48: struct private_cert_payload_t {
49:
50: /**
51: * Public cert_payload_t interface.
52: */
53: cert_payload_t public;
54:
55: /**
56: * Next payload type.
57: */
58: uint8_t next_payload;
59:
60: /**
61: * Critical flag.
62: */
63: bool critical;
64:
65: /**
66: * reserved bits
67: */
68: bool reserved[7];
69:
70: /**
71: * Length of this payload.
72: */
73: uint16_t payload_length;
74:
75: /**
76: * Encoding of the CERT Data.
77: */
78: uint8_t encoding;
79:
80: /**
81: * The contained cert data value.
82: */
83: chunk_t data;
84:
85: /**
86: * TRUE if the "Hash and URL" data is invalid
87: */
88: bool invalid_hash_and_url;
89:
90: /**
91: * The payload type.
92: */
93: payload_type_t type;
94: };
95:
96: /**
97: * Encoding rules to parse or generate a CERT payload
98: *
99: * The defined offsets are the positions in a object of type
100: * private_cert_payload_t.
101: *
102: */
103: static encoding_rule_t encodings[] = {
104: /* 1 Byte next payload type, stored in the field next_payload */
105: { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
106: /* the critical bit */
107: { FLAG, offsetof(private_cert_payload_t, critical) },
108: /* 7 Bit reserved bits, nowhere stored */
109: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[0]) },
110: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[1]) },
111: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[2]) },
112: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[3]) },
113: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[4]) },
114: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[5]) },
115: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[6]) },
116: /* Length of the whole payload*/
117: { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
118: /* 1 Byte CERT type*/
119: { U_INT_8, offsetof(private_cert_payload_t, encoding) },
120: /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
121: { CHUNK_DATA, offsetof(private_cert_payload_t, data) }
122: };
123:
124: /*
125: 1 2 3
126: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
127: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128: ! Next Payload !C! RESERVED ! Payload Length !
129: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130: ! Cert Encoding ! !
131: +-+-+-+-+-+-+-+-+ !
132: ~ Certificate Data ~
133: ! !
134: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135: */
136:
137: METHOD(payload_t, verify, status_t,
138: private_cert_payload_t *this)
139: {
140: if (this->encoding == ENC_X509_HASH_AND_URL ||
141: this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
142: {
143: int i;
144:
145: /* coarse verification of "Hash and URL" encoded certificates */
146: if (this->data.len <= 20)
147: {
148: DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
149: this->data.len);
150: this->invalid_hash_and_url = TRUE;
151: return SUCCESS;
152: }
153: for (i = 20; i < this->data.len; ++i)
154: {
155: if (this->data.ptr[i] == '\0')
156: {
157: /* null terminated, fine */
158: return SUCCESS;
159: }
160: else if (!isprint(this->data.ptr[i]))
161: {
162: DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
163: " encoded certificate payload, ignore");
164: this->invalid_hash_and_url = TRUE;
165: return SUCCESS;
166: }
167: }
168: /* URL is not null terminated, correct that */
169: this->data = chunk_cat("mc", this->data, chunk_from_chars(0));
170: }
171: return SUCCESS;
172: }
173:
174: METHOD(payload_t, get_encoding_rules, int,
175: private_cert_payload_t *this, encoding_rule_t **rules)
176: {
177: *rules = encodings;
178: return countof(encodings);
179: }
180:
181: METHOD(payload_t, get_header_length, int,
182: private_cert_payload_t *this)
183: {
184: return 5;
185: }
186:
187: METHOD(payload_t, get_type, payload_type_t,
188: private_cert_payload_t *this)
189: {
190: return this->type;
191: }
192:
193: METHOD(payload_t, get_next_type, payload_type_t,
194: private_cert_payload_t *this)
195: {
196: return this->next_payload;
197: }
198:
199: METHOD(payload_t, set_next_type, void,
200: private_cert_payload_t *this, payload_type_t type)
201: {
202: this->next_payload = type;
203: }
204:
205: METHOD(payload_t, get_length, size_t,
206: private_cert_payload_t *this)
207: {
208: return this->payload_length;
209: }
210:
211: METHOD(cert_payload_t, get_cert_encoding, cert_encoding_t,
212: private_cert_payload_t *this)
213: {
214: return this->encoding;
215: }
216:
217: METHOD(cert_payload_t, get_cert, certificate_t*,
218: private_cert_payload_t *this)
219: {
220: int type;
221:
222: switch (this->encoding)
223: {
224: case ENC_X509_SIGNATURE:
225: type = CERT_X509;
226: break;
227: case ENC_X509_ATTRIBUTE:
228: type = CERT_X509_AC;
229: break;
230: case ENC_CRL:
231: type = CERT_X509_CRL;
232: break;
233: default:
234: return NULL;
235: }
236: return lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
237: BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
238: }
239:
240: METHOD(cert_payload_t, get_container, container_t*,
241: private_cert_payload_t *this)
242: {
243: int type;
244:
245: switch (this->encoding)
246: {
247: case ENC_PKCS7_WRAPPED_X509:
248: type = CONTAINER_PKCS7;
249: break;
250: default:
251: return NULL;
252: }
253: return lib->creds->create(lib->creds, CRED_CONTAINER, type,
254: BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
255: }
256:
257: METHOD(cert_payload_t, get_hash, chunk_t,
258: private_cert_payload_t *this)
259: {
260: chunk_t hash = chunk_empty;
261:
262: if ((this->encoding != ENC_X509_HASH_AND_URL &&
263: this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
264: this->invalid_hash_and_url)
265: {
266: return hash;
267: }
268: hash.ptr = this->data.ptr;
269: hash.len = 20;
270: return hash;
271: }
272:
273: METHOD(cert_payload_t, get_url, char*,
274: private_cert_payload_t *this)
275: {
276: if ((this->encoding != ENC_X509_HASH_AND_URL &&
277: this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
278: this->invalid_hash_and_url)
279: {
280: return NULL;
281: }
282: return (char*)this->data.ptr + 20;
283: }
284:
285: METHOD2(payload_t, cert_payload_t, destroy, void,
286: private_cert_payload_t *this)
287: {
288: free(this->data.ptr);
289: free(this);
290: }
291:
292: /*
293: * Described in header
294: */
295: cert_payload_t *cert_payload_create(payload_type_t type)
296: {
297: private_cert_payload_t *this;
298:
299: INIT(this,
300: .public = {
301: .payload_interface = {
302: .verify = _verify,
303: .get_encoding_rules = _get_encoding_rules,
304: .get_header_length = _get_header_length,
305: .get_length = _get_length,
306: .get_next_type = _get_next_type,
307: .set_next_type = _set_next_type,
308: .get_type = _get_type,
309: .destroy = _destroy,
310: },
311: .get_cert = _get_cert,
312: .get_container = _get_container,
313: .get_cert_encoding = _get_cert_encoding,
314: .get_hash = _get_hash,
315: .get_url = _get_url,
316: .destroy = _destroy,
317: },
318: .next_payload = PL_NONE,
319: .payload_length = get_header_length(this),
320: .type = type,
321: );
322: return &this->public;
323: }
324:
325: /*
326: * Described in header
327: */
328: cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
329: certificate_t *cert)
330: {
331: private_cert_payload_t *this;
332:
333: this = (private_cert_payload_t*)cert_payload_create(type);
334: switch (cert->get_type(cert))
335: {
336: case CERT_X509:
337: this->encoding = ENC_X509_SIGNATURE;
338: break;
339: case CERT_X509_AC:
340: this->encoding = ENC_X509_ATTRIBUTE;
341: break;
342: default:
343: DBG1(DBG_ENC, "embedding %N certificate in payload failed",
344: certificate_type_names, cert->get_type(cert));
345: free(this);
346: return NULL;
347: }
348: if (!cert->get_encoding(cert, CERT_ASN1_DER, &this->data))
349: {
350: DBG1(DBG_ENC, "encoding certificate for cert payload failed");
351: free(this);
352: return NULL;
353: }
354: this->payload_length = get_header_length(this) + this->data.len;
355:
356: return &this->public;
357: }
358:
359: /*
360: * Described in header
361: */
362: cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
363: {
364: private_cert_payload_t *this;
365:
366: this = (private_cert_payload_t*)cert_payload_create(PLV2_CERTIFICATE);
367: this->encoding = ENC_X509_HASH_AND_URL;
368: this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
369: this->payload_length = get_header_length(this) + this->data.len;
370:
371: return &this->public;
372: }
373:
374: /*
375: * Described in header
376: */
377: cert_payload_t *cert_payload_create_custom(payload_type_t type,
378: cert_encoding_t encoding, chunk_t data)
379: {
380: private_cert_payload_t *this;
381:
382: this = (private_cert_payload_t*)cert_payload_create(type);
383: this->encoding = encoding;
384: this->data = data;
385: this->payload_length = get_header_length(this) + this->data.len;
386:
387: return &this->public;
388: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>