Fix destruction of tcg_pts_attr_file_meas_t when building from encoding
[strongswan.git] / src / libpts / tcg / tcg_pts_attr_file_meas.c
1 /*
2 * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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 "tcg_pts_attr_file_meas.h"
17
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <collections/linked_list.h>
22 #include <utils/debug.h>
23
24 typedef struct private_tcg_pts_attr_file_meas_t private_tcg_pts_attr_file_meas_t;
25
26 /**
27 * File Measurement
28 * see section 3.19.2 of PTS Protocol: Binding to TNC IF-M Specification
29 *
30 * 1 2 3
31 * 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
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Number of Files included |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Number of Files included |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | Request ID | Measurement Length |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Measurement #1 (Variable Length) |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Filename Length | Filename (Variable Length) ~
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * ~ Filename (Variable Length) ~
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Measurement #2 (Variable Length) |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Filename Length | Filename (Variable Length) ~
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * ~ Filename (Variable Length) ~
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * ...........................
52 */
53
54 #define PTS_FILE_MEAS_SIZE 12
55
56 /**
57 * Private data of an tcg_pts_attr_file_meas_t object.
58 */
59 struct private_tcg_pts_attr_file_meas_t {
60
61 /**
62 * Public members of tcg_pts_attr_file_meas_t
63 */
64 tcg_pts_attr_file_meas_t public;
65
66 /**
67 * Vendor-specific attribute type
68 */
69 pen_type_t type;
70
71 /**
72 * Attribute value
73 */
74 chunk_t value;
75
76 /**
77 * Noskip flag
78 */
79 bool noskip_flag;
80
81 /**
82 * PTS File Measurements
83 */
84 pts_file_meas_t *measurements;
85
86 /**
87 * Reference count
88 */
89 refcount_t ref;
90 };
91
92 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
93 private_tcg_pts_attr_file_meas_t *this)
94 {
95 return this->type;
96 }
97
98 METHOD(pa_tnc_attr_t, get_value, chunk_t,
99 private_tcg_pts_attr_file_meas_t *this)
100 {
101 return this->value;
102 }
103
104 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
105 private_tcg_pts_attr_file_meas_t *this)
106 {
107 return this->noskip_flag;
108 }
109
110 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
111 private_tcg_pts_attr_file_meas_t *this, bool noskip)
112 {
113 this->noskip_flag = noskip;
114 }
115
116 METHOD(pa_tnc_attr_t, build, void,
117 private_tcg_pts_attr_file_meas_t *this)
118 {
119 bio_writer_t *writer;
120 enumerator_t *enumerator;
121 u_int64_t number_of_files;
122 u_int16_t request_id;
123 char *filename;
124 chunk_t measurement;
125 bool first = TRUE;
126
127 if (this->value.ptr)
128 {
129 return;
130 }
131 number_of_files = this->measurements->get_file_count(this->measurements);
132 request_id = this->measurements->get_request_id(this->measurements);
133
134 writer = bio_writer_create(PTS_FILE_MEAS_SIZE);
135 writer->write_uint64(writer, number_of_files);
136 writer->write_uint16(writer, request_id);
137
138 enumerator = this->measurements->create_enumerator(this->measurements);
139 while (enumerator->enumerate(enumerator, &filename, &measurement))
140 {
141 if (first)
142 {
143 writer->write_uint16(writer, measurement.len);
144 first = FALSE;
145 }
146 writer->write_data (writer, measurement);
147 writer->write_data16(writer, chunk_create(filename, strlen(filename)));
148 }
149 enumerator->destroy(enumerator);
150
151 if (first)
152 {
153 /* no attached measurements */
154 writer->write_uint16(writer, 0);
155 }
156
157 this->value = chunk_clone(writer->get_buf(writer));
158 writer->destroy(writer);
159 }
160
161 METHOD(pa_tnc_attr_t, process, status_t,
162 private_tcg_pts_attr_file_meas_t *this, u_int32_t *offset)
163 {
164 bio_reader_t *reader;
165 u_int64_t number_of_files;
166 u_int16_t request_id, meas_len;
167 chunk_t measurement, filename;
168 size_t len;
169 char buf[BUF_LEN];
170 status_t status = FAILED;
171
172 if (this->value.len < PTS_FILE_MEAS_SIZE)
173 {
174 DBG1(DBG_TNC, "insufficient data for PTS file measurement header");
175 *offset = 0;
176 return FAILED;
177 }
178
179 reader = bio_reader_create(this->value);
180 reader->read_uint64(reader, &number_of_files);
181 reader->read_uint16(reader, &request_id);
182 reader->read_uint16(reader, &meas_len);
183 *offset = PTS_FILE_MEAS_SIZE;
184
185 this->measurements = pts_file_meas_create(request_id);
186
187 while (number_of_files--)
188 {
189 if (!reader->read_data(reader, meas_len, &measurement))
190 {
191 DBG1(DBG_TNC, "insufficient data for PTS file measurement");
192 goto end;
193 }
194 *offset += meas_len;
195
196 if (!reader->read_data16(reader, &filename))
197 {
198 DBG1(DBG_TNC, "insufficient data for filename");
199 goto end;
200 }
201 *offset += 2 + filename.len;
202
203 len = min(filename.len, BUF_LEN-1);
204 memcpy(buf, filename.ptr, len);
205 buf[len] = '\0';
206 this->measurements->add(this->measurements, buf, measurement);
207 }
208 status = SUCCESS;
209
210 end:
211 reader->destroy(reader);
212 return status;
213 }
214
215 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
216 private_tcg_pts_attr_file_meas_t *this)
217 {
218 ref_get(&this->ref);
219 return &this->public.pa_tnc_attribute;
220 }
221 METHOD(pa_tnc_attr_t, destroy, void,
222 private_tcg_pts_attr_file_meas_t *this)
223 {
224 if (ref_put(&this->ref))
225 {
226 DESTROY_IF(this->measurements);
227 free(this->value.ptr);
228 free(this);
229 }
230 }
231
232 METHOD(tcg_pts_attr_file_meas_t, get_measurements, pts_file_meas_t*,
233 private_tcg_pts_attr_file_meas_t *this)
234 {
235 return this->measurements;
236 }
237
238 /**
239 * Described in header.
240 */
241 pa_tnc_attr_t *tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements)
242 {
243 private_tcg_pts_attr_file_meas_t *this;
244
245 INIT(this,
246 .public = {
247 .pa_tnc_attribute = {
248 .get_type = _get_type,
249 .get_value = _get_value,
250 .get_noskip_flag = _get_noskip_flag,
251 .set_noskip_flag = _set_noskip_flag,
252 .build = _build,
253 .process = _process,
254 .get_ref = _get_ref,
255 .destroy = _destroy,
256 },
257 .get_measurements = _get_measurements,
258 },
259 .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
260 .measurements = measurements,
261 .ref = 1,
262 );
263
264 return &this->public.pa_tnc_attribute;
265 }
266
267
268 /**
269 * Described in header.
270 */
271 pa_tnc_attr_t *tcg_pts_attr_file_meas_create_from_data(chunk_t data)
272 {
273 private_tcg_pts_attr_file_meas_t *this;
274
275 INIT(this,
276 .public = {
277 .pa_tnc_attribute = {
278 .get_type = _get_type,
279 .get_value = _get_value,
280 .get_noskip_flag = _get_noskip_flag,
281 .set_noskip_flag = _set_noskip_flag,
282 .build = _build,
283 .process = _process,
284 .get_ref = _get_ref,
285 .destroy = _destroy,
286 },
287 .get_measurements = _get_measurements,
288 },
289 .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
290 .value = chunk_clone(data),
291 .ref = 1,
292 );
293
294 return &this->public.pa_tnc_attribute;
295 }