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