]>
Commit | Line | Data |
---|---|---|
510c3426 JH |
1 | /** |
2 | * @file certreq_payload.c | |
3 | * | |
4 | * @brief Implementation of certreq_payload_t. | |
5 | * | |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
23 | #include "certreq_payload.h" | |
24 | ||
25 | #include <utils/allocator.h> | |
26 | ||
27 | ||
28 | typedef struct private_certreq_payload_t private_certreq_payload_t; | |
29 | ||
30 | /** | |
31 | * Private data of an certreq_payload_t object. | |
32 | * | |
33 | */ | |
34 | struct private_certreq_payload_t { | |
35 | /** | |
36 | * Public certreq_payload_t interface. | |
37 | */ | |
38 | certreq_payload_t public; | |
39 | ||
40 | /** | |
41 | * Next payload type. | |
42 | */ | |
43 | u_int8_t next_payload; | |
44 | ||
45 | /** | |
46 | * Critical flag. | |
47 | */ | |
48 | bool critical; | |
49 | ||
50 | /** | |
51 | * Length of this payload. | |
52 | */ | |
53 | u_int16_t payload_length; | |
54 | ||
55 | /** | |
56 | * Encoding of the CERT Data. | |
57 | */ | |
58 | u_int8_t cert_encoding; | |
59 | ||
60 | /** | |
61 | * The contained certreq data value. | |
62 | */ | |
63 | chunk_t certreq_data; | |
64 | }; | |
65 | ||
66 | /** | |
67 | * Encoding rules to parse or generate a CERTREQ payload | |
68 | * | |
69 | * The defined offsets are the positions in a object of type | |
70 | * private_certreq_payload_t. | |
71 | * | |
72 | */ | |
73 | encoding_rule_t certreq_payload_encodings[] = { | |
74 | /* 1 Byte next payload type, stored in the field next_payload */ | |
75 | { U_INT_8, offsetof(private_certreq_payload_t, next_payload) }, | |
76 | /* the critical bit */ | |
77 | { FLAG, offsetof(private_certreq_payload_t, critical) }, | |
78 | /* 7 Bit reserved bits, nowhere stored */ | |
79 | { RESERVED_BIT, 0 }, | |
80 | { RESERVED_BIT, 0 }, | |
81 | { RESERVED_BIT, 0 }, | |
82 | { RESERVED_BIT, 0 }, | |
83 | { RESERVED_BIT, 0 }, | |
84 | { RESERVED_BIT, 0 }, | |
85 | { RESERVED_BIT, 0 }, | |
86 | /* Length of the whole payload*/ | |
87 | { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)}, | |
88 | /* 1 Byte CERTREQ type*/ | |
89 | { U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)}, | |
90 | /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */ | |
91 | { CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)} | |
92 | }; | |
93 | ||
94 | /* | |
95 | 1 2 3 | |
96 | 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 | |
97 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
98 | ! Next Payload !C! RESERVED ! Payload Length ! | |
99 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
100 | ! Cert Encoding ! ! | |
101 | +-+-+-+-+-+-+-+-+ ! | |
102 | ~ Certification Authority ~ | |
103 | ! ! | |
104 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
105 | */ | |
106 | ||
107 | /** | |
108 | * Implementation of payload_t.verify. | |
109 | */ | |
110 | static status_t verify(private_certreq_payload_t *this) | |
111 | { | |
112 | if (this->critical) | |
113 | { | |
114 | /* critical bit is set! */ | |
115 | return FAILED; | |
116 | } | |
117 | if ((this->cert_encoding == 0) || | |
118 | ((this->cert_encoding >= 14) && (this->cert_encoding <= 200))) | |
119 | { | |
120 | /* reserved IDs */ | |
121 | return FAILED; | |
122 | } | |
123 | return SUCCESS; | |
124 | } | |
125 | ||
126 | /** | |
127 | * Implementation of certreq_payload_t.get_encoding_rules. | |
128 | */ | |
129 | static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count) | |
130 | { | |
131 | *rules = certreq_payload_encodings; | |
132 | *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t); | |
133 | } | |
134 | ||
135 | /** | |
136 | * Implementation of payload_t.get_type. | |
137 | */ | |
138 | static payload_type_t get_payload_type(private_certreq_payload_t *this) | |
139 | { | |
140 | return CERTIFICATE_REQUEST; | |
141 | } | |
142 | ||
143 | /** | |
144 | * Implementation of payload_t.get_next_type. | |
145 | */ | |
146 | static payload_type_t get_next_type(private_certreq_payload_t *this) | |
147 | { | |
148 | return (this->next_payload); | |
149 | } | |
150 | ||
151 | /** | |
152 | * Implementation of payload_t.set_next_type. | |
153 | */ | |
154 | static void set_next_type(private_certreq_payload_t *this,payload_type_t type) | |
155 | { | |
156 | this->next_payload = type; | |
157 | } | |
158 | ||
159 | /** | |
160 | * Implementation of payload_t.get_length. | |
161 | */ | |
162 | static size_t get_length(private_certreq_payload_t *this) | |
163 | { | |
164 | return this->payload_length; | |
165 | } | |
166 | ||
167 | /** | |
168 | * Implementation of certreq_payload_t.set_cert_encoding. | |
169 | */ | |
170 | static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding) | |
171 | { | |
172 | this->cert_encoding = encoding; | |
173 | } | |
174 | ||
175 | /** | |
176 | * Implementation of certreq_payload_t.get_cert_encoding. | |
177 | */ | |
178 | static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this) | |
179 | { | |
180 | return (this->cert_encoding); | |
181 | } | |
182 | ||
183 | /** | |
184 | * Implementation of certreq_payload_t.set_data. | |
185 | */ | |
186 | static void set_data (private_certreq_payload_t *this, chunk_t data) | |
187 | { | |
188 | if (this->certreq_data.ptr != NULL) | |
189 | { | |
190 | allocator_free_chunk(&(this->certreq_data)); | |
191 | } | |
192 | this->certreq_data.ptr = allocator_clone_bytes(data.ptr,data.len); | |
193 | this->certreq_data.len = data.len; | |
194 | this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len; | |
195 | } | |
196 | ||
197 | /** | |
198 | * Implementation of certreq_payload_t.get_data. | |
199 | */ | |
200 | static chunk_t get_data (private_certreq_payload_t *this) | |
201 | { | |
202 | return (this->certreq_data); | |
203 | } | |
204 | ||
205 | /** | |
206 | * Implementation of certreq_payload_t.get_data_clone. | |
207 | */ | |
208 | static chunk_t get_data_clone (private_certreq_payload_t *this) | |
209 | { | |
210 | chunk_t cloned_data; | |
211 | if (this->certreq_data.ptr == NULL) | |
212 | { | |
213 | return (this->certreq_data); | |
214 | } | |
215 | cloned_data.ptr = allocator_clone_bytes(this->certreq_data.ptr,this->certreq_data.len); | |
216 | cloned_data.len = this->certreq_data.len; | |
217 | return cloned_data; | |
218 | } | |
219 | ||
220 | /** | |
221 | * Implementation of payload_t.destroy and certreq_payload_t.destroy. | |
222 | */ | |
223 | static void destroy(private_certreq_payload_t *this) | |
224 | { | |
225 | if (this->certreq_data.ptr != NULL) | |
226 | { | |
227 | allocator_free_chunk(&(this->certreq_data)); | |
228 | } | |
229 | ||
230 | allocator_free(this); | |
231 | } | |
232 | ||
233 | /* | |
234 | * Described in header | |
235 | */ | |
236 | certreq_payload_t *certreq_payload_create() | |
237 | { | |
238 | private_certreq_payload_t *this = allocator_alloc_thing(private_certreq_payload_t); | |
239 | ||
240 | /* interface functions */ | |
241 | this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; | |
242 | this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; | |
243 | this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; | |
244 | this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; | |
245 | this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; | |
246 | this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; | |
247 | this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; | |
248 | ||
249 | /* public functions */ | |
250 | this->public.destroy = (void (*) (certreq_payload_t *)) destroy; | |
251 | this->public.set_cert_encoding = (void (*) (certreq_payload_t *,cert_encoding_t)) set_cert_encoding; | |
252 | this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t *)) get_cert_encoding; | |
253 | this->public.set_data = (void (*) (certreq_payload_t *,chunk_t)) set_data; | |
254 | this->public.get_data_clone = (chunk_t (*) (certreq_payload_t *)) get_data_clone; | |
255 | this->public.get_data = (chunk_t (*) (certreq_payload_t *)) get_data; | |
256 | ||
257 | /* private variables */ | |
258 | this->critical = FALSE; | |
259 | this->next_payload = NO_PAYLOAD; | |
260 | this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH; | |
261 | this->certreq_data = CHUNK_INITIALIZER; | |
262 | ||
263 | return (&(this->public)); | |
264 | } |