]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libpts/pts/pts_file_meas.c
Moved debug.[ch] to utils folder
[thirdparty/strongswan.git] / src / libpts / pts / pts_file_meas.c
CommitLineData
d2f49c3d
AS
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 "pts_file_meas.h"
17
12642a68 18#include <collections/linked_list.h>
f05b4272 19#include <utils/debug.h>
d2f49c3d 20
0f236aac
AS
21#include <sys/stat.h>
22#include <libgen.h>
23#include <errno.h>
24
d2f49c3d
AS
25typedef struct private_pts_file_meas_t private_pts_file_meas_t;
26
27/**
28 * Private data of a pts_file_meas_t object.
29 *
30 */
31struct private_pts_file_meas_t {
32
33 /**
34 * Public pts_file_meas_t interface.
35 */
36 pts_file_meas_t public;
37
38 /**
39 * ID of PTS File Measurement Request
40 */
41 u_int16_t request_id;
42
43 /**
44 * List of File Measurements
45 */
46 linked_list_t *list;
47};
48
49typedef struct entry_t entry_t;
50
51/**
52 * PTS File Measurement entry
53 */
54struct entry_t {
05a1b347 55 char *filename;
d2f49c3d
AS
56 chunk_t measurement;
57};
58
59/**
60 * Free an entry_t object
61 */
62static void free_entry(entry_t *entry)
63{
64 if (entry)
65 {
66 free(entry->filename);
67 free(entry->measurement.ptr);
68 free(entry);
69 }
70}
71
72METHOD(pts_file_meas_t, get_request_id, u_int16_t,
73 private_pts_file_meas_t *this)
74{
75 return this->request_id;
76}
77
78METHOD(pts_file_meas_t, get_file_count, int,
79 private_pts_file_meas_t *this)
80{
81 return this->list->get_count(this->list);
82}
83
84METHOD(pts_file_meas_t, add, void,
85 private_pts_file_meas_t *this, char *filename, chunk_t measurement)
86{
87 entry_t *entry;
88
89 entry = malloc_thing(entry_t);
90 entry->filename = strdup(filename);
91 entry->measurement = chunk_clone(measurement);
92
93 this->list->insert_last(this->list, entry);
94}
95
96/**
97 * Enumerate file measurement entries
98 */
99static bool entry_filter(void *null, entry_t **entry, char **filename,
100 void *i2, chunk_t *measurement)
101{
102 *filename = (*entry)->filename;
103 *measurement = (*entry)->measurement;
104 return TRUE;
105}
106
107METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
108 private_pts_file_meas_t *this)
109{
110 return enumerator_create_filter(this->list->create_enumerator(this->list),
111 (void*)entry_filter, NULL, NULL);
112}
113
964de0ab
AS
114METHOD(pts_file_meas_t, check, bool,
115 private_pts_file_meas_t *this, pts_database_t *pts_db, char *product,
116 pts_meas_algorithms_t algo)
12ef9fb1
AS
117{
118 enumerator_t *enumerator;
119 entry_t *entry;
964de0ab
AS
120 int count_ok = 0, count_not_found = 0, count_differ = 0;
121 status_t status;
12ef9fb1
AS
122
123 enumerator = this->list->create_enumerator(this->list);
124 while (enumerator->enumerate(enumerator, &entry))
125 {
964de0ab
AS
126 status = pts_db->check_file_measurement(pts_db, product, algo,
127 entry->measurement, entry->filename);
128 switch (status)
129 {
130 case SUCCESS:
ab957aac
AS
131 DBG3(DBG_PTS, " %#B for '%s' is ok", &entry->measurement,
132 entry->filename);
964de0ab
AS
133 count_ok++;
134 break;
135 case NOT_FOUND:
ab957aac
AS
136 DBG2(DBG_PTS, " %#B for '%s' not found", &entry->measurement,
137 entry->filename);
964de0ab
AS
138 count_not_found++;
139 break;
140 case VERIFY_ERROR:
ab957aac
AS
141 DBG1(DBG_PTS, " %#B for '%s' differs", &entry->measurement,
142 entry->filename);
964de0ab
AS
143 count_differ++;
144 break;
145 case FAILED:
146 default:
ab957aac
AS
147 DBG1(DBG_PTS, " %#B for '%s' failed", &entry->measurement,
148 entry->filename);
964de0ab 149 }
12ef9fb1
AS
150 }
151 enumerator->destroy(enumerator);
152
964de0ab
AS
153 DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
154 this->list->get_count(this->list),
155 count_ok, count_not_found, count_differ);
12ef9fb1
AS
156 return TRUE;
157}
158
582bda55
AS
159METHOD(pts_file_meas_t, verify, bool,
160 private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
161{
162 char *filename;
163 chunk_t measurement;
164 entry_t *entry;
165 enumerator_t *enumerator;
166 bool found, success = TRUE;
167
168 while (e_hash->enumerate(e_hash, &filename, &measurement))
169 {
170 found = FALSE;
171
172 enumerator = this->list->create_enumerator(this->list);
173 while (enumerator->enumerate(enumerator, &entry))
174 {
175 if (!is_dir || streq(filename, entry->filename))
176 {
177 found = TRUE;
178 break;
179 }
180 }
181 enumerator->destroy(enumerator);
12642a68 182
582bda55
AS
183 if (!found)
184 {
b9d61f78 185 DBG1(DBG_PTS, " no measurement found for '%s'", filename);
582bda55 186 success = FALSE;
18072005 187 continue;
582bda55
AS
188 }
189 if (chunk_equals(measurement, entry->measurement))
190 {
b9d61f78 191 DBG2(DBG_PTS, " %#B for '%s' is ok", &measurement, filename);
582bda55
AS
192 }
193 else
194 {
b9d61f78 195 DBG1(DBG_PTS, " %#B for '%s' is incorrect", &measurement, filename);
582bda55
AS
196 success = FALSE;
197 }
198 if (!is_dir)
199 {
200 break;
201 }
202 }
12642a68 203 return success;
582bda55
AS
204}
205
d2f49c3d
AS
206METHOD(pts_file_meas_t, destroy, void,
207 private_pts_file_meas_t *this)
208{
209 this->list->destroy_function(this->list, (void *)free_entry);
210 free(this);
211}
212
213/**
214 * See header
215 */
216pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
217{
218 private_pts_file_meas_t *this;
219
220 INIT(this,
221 .public = {
222 .get_request_id = _get_request_id,
223 .get_file_count = _get_file_count,
224 .add = _add,
225 .create_enumerator = _create_enumerator,
964de0ab 226 .check = _check,
582bda55 227 .verify = _verify,
d2f49c3d
AS
228 .destroy = _destroy,
229 },
230 .request_id = request_id,
231 .list = linked_list_create(),
232 );
233
234 return &this->public;
235}
236
0f236aac
AS
237/**
238 * Hash a file with a given absolute pathname
239 */
240static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
241{
242 u_char buffer[4096];
243 size_t bytes_read;
915bceb4 244 bool success = TRUE;
0f236aac
AS
245 FILE *file;
246
247 file = fopen(pathname, "rb");
248 if (!file)
249 {
250 DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
251 strerror(errno));
252 return FALSE;
253 }
254 while (TRUE)
255 {
256 bytes_read = fread(buffer, 1, sizeof(buffer), file);
257 if (bytes_read > 0)
258 {
915bceb4
AS
259 if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
260 {
261 DBG1(DBG_PTS, " hasher increment error");
262 success = FALSE;
263 break;
264 }
0f236aac
AS
265 }
266 else
267 {
915bceb4
AS
268 if (!hasher->get_hash(hasher, chunk_empty, hash))
269 {
270 DBG1(DBG_PTS, " hasher finalize error");
271 success = FALSE;
272 }
0f236aac
AS
273 break;
274 }
275 }
276 fclose(file);
277
915bceb4 278 return success;
0f236aac
AS
279}
280
281/**
282 * See header
283 */
284pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
285 char *pathname, bool is_dir, bool use_rel_name,
286 pts_meas_algorithms_t alg)
287{
288 private_pts_file_meas_t *this;
289 hash_algorithm_t hash_alg;
290 hasher_t *hasher;
291 u_char hash[HASH_SIZE_SHA384];
292 chunk_t measurement;
293 char* filename;
294 bool success = TRUE;
295
296 /* Create a hasher and a hash measurement buffer */
297 hash_alg = pts_meas_algo_to_hash(alg);
298 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
299 if (!hasher)
300 {
301 DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
302 return NULL;
303 }
304 measurement = chunk_create(hash, hasher->get_hash_size(hasher));
305
306 INIT(this,
307 .public = {
308 .get_request_id = _get_request_id,
309 .get_file_count = _get_file_count,
310 .add = _add,
311 .create_enumerator = _create_enumerator,
964de0ab 312 .check = _check,
0f236aac
AS
313 .verify = _verify,
314 .destroy = _destroy,
315 },
316 .request_id = request_id,
317 .list = linked_list_create(),
318 );
319
320 if (is_dir)
321 {
322 enumerator_t *enumerator;
323 char *rel_name, *abs_name;
324 struct stat st;
325
326 enumerator = enumerator_create_directory(pathname);
327 if (!enumerator)
328 {
329 DBG1(DBG_PTS, " directory '%s' can not be opened, %s", pathname,
330 strerror(errno));
331 success = FALSE;
332 goto end;
333 }
334 while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
335 {
336 /* measure regular files only */
337 if (S_ISREG(st.st_mode) && *rel_name != '.')
338 {
339 if (!hash_file(hasher, abs_name, hash))
340 {
341 success = FALSE;
342 break;
343 }
344 filename = use_rel_name ? rel_name : abs_name;
345 DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
346 add(this, filename, measurement);
347 }
348 }
349 enumerator->destroy(enumerator);
350 }
351 else
352 {
353 if (!hash_file(hasher, pathname, hash))
354 {
355 success = FALSE;
356 goto end;
357 }
358 filename = use_rel_name ? basename(pathname) : pathname;
359 DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
360 add(this, filename, measurement);
361 }
362
363end:
364 hasher->destroy(hasher);
365 if (success)
366 {
367 return &this->public;
368 }
369 else
370 {
371 destroy(this);
372 return NULL;
373 }
374}