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