shortened fieldnames of pts_file_metadata_t struct
[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
71 /**
72 * Private data of an tcg_pts_attr_file_meta_t object.
73 */
74 struct private_tcg_pts_attr_file_meta_t {
75
76 /**
77 * Public members of tcg_pts_attr_file_meta_t
78 */
79 tcg_pts_attr_file_meta_t public;
80
81 /**
82 * Attribute vendor ID
83 */
84 pen_t vendor_id;
85
86 /**
87 * Attribute type
88 */
89 u_int32_t type;
90
91 /**
92 * Attribute value
93 */
94 chunk_t value;
95
96 /**
97 * Noskip flag
98 */
99 bool noskip_flag;
100
101 /**
102 * PTS File Metadata
103 */
104 pts_file_meta_t *metadata;
105
106 };
107
108 METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
109 private_tcg_pts_attr_file_meta_t *this)
110 {
111 return this->vendor_id;
112 }
113
114 METHOD(pa_tnc_attr_t, get_type, u_int32_t,
115 private_tcg_pts_attr_file_meta_t *this)
116 {
117 return this->type;
118 }
119
120 METHOD(pa_tnc_attr_t, get_value, chunk_t,
121 private_tcg_pts_attr_file_meta_t *this)
122 {
123 return this->value;
124 }
125
126 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
127 private_tcg_pts_attr_file_meta_t *this)
128 {
129 return this->noskip_flag;
130 }
131
132 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
133 private_tcg_pts_attr_file_meta_t *this, bool noskip)
134 {
135 this->noskip_flag = noskip;
136 }
137
138 METHOD(pa_tnc_attr_t, build, void,
139 private_tcg_pts_attr_file_meta_t *this)
140 {
141 bio_writer_t *writer;
142 enumerator_t *enumerator;
143 pts_file_metadata_t *entry;
144 u_int64_t number_of_files;
145
146 number_of_files = this->metadata->get_file_count(this->metadata);
147 writer = bio_writer_create(PTS_FILE_META_SIZE);
148
149 /* Write the 64 bit integer field - number of files as two 32 bit parts */
150 writer->write_uint32(writer, number_of_files >> 32);
151 writer->write_uint32(writer, number_of_files & 0xffffffff);
152
153 enumerator = this->metadata->create_enumerator(this->metadata);
154 while (enumerator->enumerate(enumerator, &entry))
155 {
156 writer->write_uint16(writer, PTS_FILE_METADATA_SIZE + strlen(entry->filename));
157 writer->write_uint8 (writer, entry->type);
158 writer->write_uint8 (writer, PTS_FILE_MEAS_RESERVED);
159
160 /* Write the 64 bit integer fields as two 32 bit parts */
161 writer->write_uint32(writer, entry->filesize >> 32);
162 writer->write_uint32(writer, entry->filesize & 0xffffffff);
163 writer->write_uint32(writer, ((u_int64_t)entry->created) >> 32);
164 writer->write_uint32(writer, ((u_int64_t)entry->created) & 0xffffffff);
165 writer->write_uint32(writer, ((u_int64_t)entry->modified) >> 32);
166 writer->write_uint32(writer, ((u_int64_t)entry->modified) & 0xffffffff);
167 writer->write_uint32(writer, ((u_int64_t)entry->accessed) >> 32);
168 writer->write_uint32(writer, ((u_int64_t)entry->accessed) & 0xffffffff);
169 writer->write_uint32(writer, entry->owner >> 32);
170 writer->write_uint32(writer, entry->owner & 0xffffffff);
171 writer->write_uint32(writer, entry->group >> 32);
172 writer->write_uint32(writer, entry->group & 0xffffffff);
173
174 writer->write_data (writer, chunk_create(entry->filename, strlen(entry->filename)));
175 }
176 enumerator->destroy(enumerator);
177
178 this->value = chunk_clone(writer->get_buf(writer));
179 writer->destroy(writer);
180 }
181
182 METHOD(pa_tnc_attr_t, process, status_t,
183 private_tcg_pts_attr_file_meta_t *this, u_int32_t *offset)
184 {
185 bio_reader_t *reader;
186 pts_file_metadata_t *entry;
187
188 int number_of_files;
189 u_int32_t number_of_files32;
190
191 u_int16_t meta_length;
192 pts_file_type_t type;
193 u_int8_t type8;
194 u_int8_t reserved;
195
196 int filesize;
197 u_int32_t filesize32;
198
199 int create_time;
200 u_int32_t create_time32;
201 time_t create_time_t;
202 int modify_time;
203 u_int32_t modify_time32;
204 time_t modify_time_t;
205 int access_time;
206 u_int32_t access_time32;
207 time_t access_time_t;
208
209 int owner_id;
210 u_int32_t owner_id32;
211
212 int group_id;
213 u_int32_t group_id32;
214
215 size_t len;
216 chunk_t filename;
217 char buf[BUF_LEN];
218 status_t status = FAILED;
219
220 if (this->value.len < PTS_FILE_META_SIZE)
221 {
222 DBG1(DBG_TNC, "insufficient data for PTS Unix-Style file metadata header");
223 *offset = 0;
224 return FAILED;
225 }
226 reader = bio_reader_create(this->value);
227
228 reader->read_uint32(reader, &number_of_files32);
229 number_of_files = (sizeof(number_of_files) > 4) ? number_of_files32 << 32 : 0;
230 reader->read_uint32(reader, &number_of_files32);
231 number_of_files += number_of_files32;
232
233 this->metadata = pts_file_meta_create();
234
235 while (number_of_files--)
236 {
237 if (!reader->read_uint16(reader, &meta_length))
238 {
239 DBG1(DBG_TNC, "insufficient data for PTS file metadata length");
240 goto end;
241 }
242 if (!reader->read_uint8 (reader, &type8))
243 {
244 DBG1(DBG_TNC, "insufficient data for file type");
245 goto end;
246 }
247 type = (pts_file_type_t)type8;
248 if (!reader->read_uint8 (reader, &reserved))
249 {
250 DBG1(DBG_TNC, "insufficient data for reserved field");
251 goto end;
252 }
253 if (!reader->read_uint32(reader, &filesize32))
254 {
255 DBG1(DBG_TNC, "insufficient data for file size");
256 goto end;
257 }
258 filesize = (sizeof(filesize) > 4) ? filesize32 << 32 : 0;
259 if (!reader->read_uint32(reader, &filesize32))
260 {
261 DBG1(DBG_TNC, "insufficient data for file size");
262 goto end;
263 }
264 filesize += filesize32;
265
266 if (!reader->read_uint32(reader, &create_time32))
267 {
268 DBG1(DBG_TNC, "insufficient data for file size");
269 goto end;
270 }
271 create_time = (sizeof(create_time) > 4) ? create_time32 << 32 : 0;
272 if (!reader->read_uint32(reader, &create_time32))
273 {
274 DBG1(DBG_TNC, "insufficient data for file size");
275 goto end;
276 }
277 create_time += create_time32;
278 create_time_t = (time_t)create_time;
279
280 if (!reader->read_uint32(reader, &modify_time32))
281 {
282 DBG1(DBG_TNC, "insufficient data for file size");
283 goto end;
284 }
285 modify_time = (sizeof(modify_time) > 4) ? modify_time32 << 32 : 0;
286 if (!reader->read_uint32(reader, &modify_time32))
287 {
288 DBG1(DBG_TNC, "insufficient data for file size");
289 goto end;
290 }
291 modify_time += modify_time32;
292 modify_time_t = (time_t)modify_time;
293
294 if (!reader->read_uint32(reader, &access_time32))
295 {
296 DBG1(DBG_TNC, "insufficient data for file size");
297 goto end;
298 }
299 access_time = (sizeof(access_time) > 4) ? access_time32 << 32 : 0;
300 if (!reader->read_uint32(reader, &access_time32))
301 {
302 DBG1(DBG_TNC, "insufficient data for file size");
303 goto end;
304 }
305 access_time += access_time32;
306 access_time_t = (time_t)access_time;
307
308 if (!reader->read_uint32(reader, &owner_id32))
309 {
310 DBG1(DBG_TNC, "insufficient data for file size");
311 goto end;
312 }
313 owner_id = (sizeof(owner_id) > 4) ? owner_id32 << 32 : 0;
314 if (!reader->read_uint32(reader, &owner_id32))
315 {
316 DBG1(DBG_TNC, "insufficient data for file size");
317 goto end;
318 }
319 owner_id += owner_id32;
320
321 if (!reader->read_uint32(reader, &group_id32))
322 {
323 DBG1(DBG_TNC, "insufficient data for file size");
324 goto end;
325 }
326 group_id = (sizeof(group_id) > 4) ? group_id32 << 32 : 0;
327 if (!reader->read_uint32(reader, &group_id32))
328 {
329 DBG1(DBG_TNC, "insufficient data for file size");
330 goto end;
331 }
332 group_id += group_id32;
333
334 if (!reader->read_data(reader, meta_length - PTS_FILE_METADATA_SIZE, &filename))
335 {
336 DBG1(DBG_TNC, "insufficient data for filename");
337 goto end;
338 }
339
340 len = min(filename.len, BUF_LEN - 1);
341 memcpy(buf, filename.ptr, len);
342 buf[len] = '\0';
343
344 entry = malloc_thing(pts_file_metadata_t);
345 entry->filename = strdup(buf);
346 entry->meta_length = PTS_FILE_METADATA_SIZE + strlen(entry->filename);
347 entry->type = type;
348 entry->filesize = filesize;
349 entry->created = create_time_t;
350 entry->modified = modify_time_t;
351 entry->accessed = access_time_t;
352 entry->owner = owner_id;
353 entry->group = group_id;
354
355 this->metadata->add(this->metadata, entry);
356 }
357 status = SUCCESS;
358
359 end:
360 reader->destroy(reader);
361 return status;
362 }
363
364 METHOD(pa_tnc_attr_t, destroy, void,
365 private_tcg_pts_attr_file_meta_t *this)
366 {
367 this->metadata->destroy(this->metadata);
368 free(this->value.ptr);
369 free(this);
370 }
371
372 METHOD(tcg_pts_attr_file_meta_t, get_metadata, pts_file_meta_t*,
373 private_tcg_pts_attr_file_meta_t *this)
374 {
375 return this->metadata;
376 }
377
378 /**
379 * Described in header.
380 */
381 pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata)
382 {
383 private_tcg_pts_attr_file_meta_t *this;
384
385 INIT(this,
386 .public = {
387 .pa_tnc_attribute = {
388 .get_vendor_id = _get_vendor_id,
389 .get_type = _get_type,
390 .get_value = _get_value,
391 .get_noskip_flag = _get_noskip_flag,
392 .set_noskip_flag = _set_noskip_flag,
393 .build = _build,
394 .process = _process,
395 .destroy = _destroy,
396 },
397 .get_metadata = _get_metadata,
398 },
399 .vendor_id = PEN_TCG,
400 .type = TCG_PTS_UNIX_FILE_META,
401 .metadata = metadata,
402 );
403
404 return &this->public.pa_tnc_attribute;
405 }
406
407
408 /**
409 * Described in header.
410 */
411 pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create_from_data(chunk_t data)
412 {
413 private_tcg_pts_attr_file_meta_t *this;
414
415 INIT(this,
416 .public = {
417 .pa_tnc_attribute = {
418 .get_vendor_id = _get_vendor_id,
419 .get_type = _get_type,
420 .get_value = _get_value,
421 .get_noskip_flag = _get_noskip_flag,
422 .set_noskip_flag = _set_noskip_flag,
423 .build = _build,
424 .process = _process,
425 .destroy = _destroy,
426 },
427 .get_metadata = _get_metadata,
428 },
429 .vendor_id = PEN_TCG,
430 .type = TCG_PTS_UNIX_FILE_META,
431 .value = chunk_clone(data),
432 );
433
434 return &this->public.pa_tnc_attribute;
435 }