optimized handling of UNIX file metadata
[strongswan.git] / src / libpts / tcg / tcg_pts_attr_unix_file_meta.c
1 /*
2 * Copyright (C) 2011 Sansar Choinyambuu
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_unix_file_meta.h"
17
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <utils/linked_list.h>
22 #include <debug.h>
23
24 typedef struct private_tcg_pts_attr_file_meta_t private_tcg_pts_attr_file_meta_t;
25
26 /**
27 * Unix-Style File Metadata
28 * see section 3.17.3 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 * | File metadata Length | Type | Reserved |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | File Size |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | File Size |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | File Create Time |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | File Create Time |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Last Modify Time |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * | Last Modify Time |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | Last Access Time |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * | Last Access Time |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * | File Owner ID |
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * | File Owner ID |
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 * | File Group ID |
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | File Group ID |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * ~ Filename (Variable Length) ~
64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 * ...........................
66 */
67
68 #define PTS_FILE_META_SIZE 8
69 #define PTS_FILE_MEAS_RESERVED 0x00
70 #define PTS_FILE_METADATA_SIZE 52
71
72 /**
73 * Private data of an tcg_pts_attr_file_meta_t object.
74 */
75 struct private_tcg_pts_attr_file_meta_t {
76
77 /**
78 * Public members of tcg_pts_attr_file_meta_t
79 */
80 tcg_pts_attr_file_meta_t public;
81
82 /**
83 * Attribute vendor ID
84 */
85 pen_t vendor_id;
86
87 /**
88 * Attribute type
89 */
90 u_int32_t type;
91
92 /**
93 * Attribute value
94 */
95 chunk_t value;
96
97 /**
98 * Noskip flag
99 */
100 bool noskip_flag;
101
102 /**
103 * PTS File Metadata
104 */
105 pts_file_meta_t *metadata;
106
107 };
108
109 METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
110 private_tcg_pts_attr_file_meta_t *this)
111 {
112 return this->vendor_id;
113 }
114
115 METHOD(pa_tnc_attr_t, get_type, u_int32_t,
116 private_tcg_pts_attr_file_meta_t *this)
117 {
118 return this->type;
119 }
120
121 METHOD(pa_tnc_attr_t, get_value, chunk_t,
122 private_tcg_pts_attr_file_meta_t *this)
123 {
124 return this->value;
125 }
126
127 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
128 private_tcg_pts_attr_file_meta_t *this)
129 {
130 return this->noskip_flag;
131 }
132
133 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
134 private_tcg_pts_attr_file_meta_t *this, bool noskip)
135 {
136 this->noskip_flag = noskip;
137 }
138
139 METHOD(pa_tnc_attr_t, build, void,
140 private_tcg_pts_attr_file_meta_t *this)
141 {
142 bio_writer_t *writer;
143 enumerator_t *enumerator;
144 pts_file_metadata_t *entry;
145 u_int64_t number_of_files;
146
147 number_of_files = this->metadata->get_file_count(this->metadata);
148 writer = bio_writer_create(PTS_FILE_META_SIZE);
149
150 writer->write_uint64(writer, number_of_files);
151
152 enumerator = this->metadata->create_enumerator(this->metadata);
153 while (enumerator->enumerate(enumerator, &entry))
154 {
155 writer->write_uint16(writer, PTS_FILE_METADATA_SIZE +
156 strlen(entry->filename));
157 writer->write_uint8 (writer, entry->type);
158 writer->write_uint8 (writer, PTS_FILE_MEAS_RESERVED);
159 writer->write_uint64(writer, entry->filesize);
160 writer->write_uint64(writer, entry->created);
161 writer->write_uint64(writer, entry->modified);
162 writer->write_uint64(writer, entry->accessed);
163 writer->write_uint64(writer, entry->owner);
164 writer->write_uint64(writer, entry->group);
165 writer->write_data (writer, chunk_create(entry->filename,
166 strlen(entry->filename)));
167 }
168 enumerator->destroy(enumerator);
169
170 this->value = chunk_clone(writer->get_buf(writer));
171 writer->destroy(writer);
172 }
173
174 METHOD(pa_tnc_attr_t, process, status_t,
175 private_tcg_pts_attr_file_meta_t *this, u_int32_t *offset)
176 {
177 bio_reader_t *reader;
178 pts_file_metadata_t *entry;
179 u_int8_t type, reserved;
180 u_int16_t len;
181 u_int64_t number_of_files, filesize, created, modified, accessed;
182 u_int64_t owner, group;
183 chunk_t filename;
184 status_t status = FAILED;
185
186 if (this->value.len < PTS_FILE_META_SIZE)
187 {
188 DBG1(DBG_TNC, "insufficient data for PTS Unix-Style file metadata header");
189 *offset = 0;
190 return FAILED;
191 }
192 reader = bio_reader_create(this->value);
193 reader->read_uint64(reader, &number_of_files);
194
195 this->metadata = pts_file_meta_create();
196
197 while (number_of_files--)
198 {
199 if (!reader->read_uint16(reader, &len))
200 {
201 DBG1(DBG_TNC, "insufficient data for PTS file metadata length");
202 goto end;
203 }
204 if (!reader->read_uint8(reader, &type))
205 {
206 DBG1(DBG_TNC, "insufficient data for file type");
207 goto end;
208 }
209 if (!reader->read_uint8(reader, &reserved))
210 {
211 DBG1(DBG_TNC, "insufficient data for reserved field");
212 goto end;
213 }
214 if (!reader->read_uint64(reader, &filesize))
215 {
216 DBG1(DBG_TNC, "insufficient data for file size");
217 goto end;
218 }
219 if (!reader->read_uint64(reader, &created))
220 {
221 DBG1(DBG_TNC, "insufficient data for file create time");
222 goto end;
223 }
224 if (!reader->read_uint64(reader, &modified))
225 {
226 DBG1(DBG_TNC, "insufficient data for last modify time");
227 goto end;
228 }
229 if (!reader->read_uint64(reader, &accessed))
230 {
231 DBG1(DBG_TNC, "insufficient data for last access time");
232 goto end;
233 }
234 if (!reader->read_uint64(reader, &owner))
235 {
236 DBG1(DBG_TNC, "insufficient data for owner id");
237 goto end;
238 }
239 if (!reader->read_uint64(reader, &group))
240 {
241 DBG1(DBG_TNC, "insufficient data for group id");
242 goto end;
243 }
244 if (!reader->read_data(reader, len - PTS_FILE_METADATA_SIZE, &filename))
245 {
246 DBG1(DBG_TNC, "insufficient data for filename");
247 goto end;
248 }
249
250 entry = malloc_thing(pts_file_metadata_t);
251 entry->type = type;
252 entry->filesize = filesize;
253 entry->created = created;
254 entry->modified = modified;
255 entry->accessed = accessed;
256 entry->owner = owner;
257 entry->group = group;
258 entry->filename = malloc(filename.len + 1);
259 entry->filename[filename.len] = '\0';
260 memcpy(entry->filename, filename.ptr, filename.len);
261
262 this->metadata->add(this->metadata, entry);
263 }
264 status = SUCCESS;
265
266 end:
267 reader->destroy(reader);
268 return status;
269 }
270
271 METHOD(pa_tnc_attr_t, destroy, void,
272 private_tcg_pts_attr_file_meta_t *this)
273 {
274 this->metadata->destroy(this->metadata);
275 free(this->value.ptr);
276 free(this);
277 }
278
279 METHOD(tcg_pts_attr_file_meta_t, get_metadata, pts_file_meta_t*,
280 private_tcg_pts_attr_file_meta_t *this)
281 {
282 return this->metadata;
283 }
284
285 /**
286 * Described in header.
287 */
288 pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata)
289 {
290 private_tcg_pts_attr_file_meta_t *this;
291
292 INIT(this,
293 .public = {
294 .pa_tnc_attribute = {
295 .get_vendor_id = _get_vendor_id,
296 .get_type = _get_type,
297 .get_value = _get_value,
298 .get_noskip_flag = _get_noskip_flag,
299 .set_noskip_flag = _set_noskip_flag,
300 .build = _build,
301 .process = _process,
302 .destroy = _destroy,
303 },
304 .get_metadata = _get_metadata,
305 },
306 .vendor_id = PEN_TCG,
307 .type = TCG_PTS_UNIX_FILE_META,
308 .metadata = metadata,
309 );
310
311 return &this->public.pa_tnc_attribute;
312 }
313
314
315 /**
316 * Described in header.
317 */
318 pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create_from_data(chunk_t data)
319 {
320 private_tcg_pts_attr_file_meta_t *this;
321
322 INIT(this,
323 .public = {
324 .pa_tnc_attribute = {
325 .get_vendor_id = _get_vendor_id,
326 .get_type = _get_type,
327 .get_value = _get_value,
328 .get_noskip_flag = _get_noskip_flag,
329 .set_noskip_flag = _set_noskip_flag,
330 .build = _build,
331 .process = _process,
332 .destroy = _destroy,
333 },
334 .get_metadata = _get_metadata,
335 },
336 .vendor_id = PEN_TCG,
337 .type = TCG_PTS_UNIX_FILE_META,
338 .value = chunk_clone(data),
339 );
340
341 return &this->public.pa_tnc_attribute;
342 }