implemented Linux IMA functional component
[strongswan.git] / src / libpts / pts / pts_database.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 "pts_database.h"
17
18 #include <debug.h>
19 #include <crypto/hashers/hasher.h>
20
21
22 typedef struct private_pts_database_t private_pts_database_t;
23
24 /**
25 * Private data of a pts_database_t object.
26 *
27 */
28 struct private_pts_database_t {
29
30 /**
31 * Public pts_database_t interface.
32 */
33 pts_database_t public;
34
35 /**
36 * database instance
37 */
38 database_t *db;
39
40 };
41
42 METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
43 private_pts_database_t *this, char *product)
44 {
45 enumerator_t *e;
46
47 /* look for all entries belonging to a product in the files table */
48 e = this->db->query(this->db,
49 "SELECT f.id, f.type, f.path FROM files AS f "
50 "JOIN product_file AS pf ON f.id = pf.file "
51 "JOIN products AS p ON p.id = pf.product "
52 "WHERE p.name = ? AND pf.measurement = 1",
53 DB_TEXT, product, DB_INT, DB_INT, DB_TEXT);
54 return e;
55 }
56
57 METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*,
58 private_pts_database_t *this, char *product)
59 {
60 enumerator_t *e;
61
62 /* look for all entries belonging to a product in the files table */
63 e = this->db->query(this->db,
64 "SELECT f.type, f.path FROM files AS f "
65 "JOIN product_file AS pf ON f.id = pf.file "
66 "JOIN products AS p ON p.id = pf.product "
67 "WHERE p.name = ? AND pf.metadata = 1",
68 DB_TEXT, product, DB_INT, DB_TEXT);
69 return e;
70 }
71
72 METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
73 private_pts_database_t *this, char *product)
74 {
75 enumerator_t *e;
76
77 /* look for all entries belonging to a product in the components table */
78 e = this->db->query(this->db,
79 "SELECT c.vendor_id, c.name, c.qualifier, pc.depth "
80 "FROM components AS c "
81 "JOIN product_component AS pc ON c.id = pc.component "
82 "JOIN products AS p ON p.id = pc.product "
83 "WHERE p.name = ? ORDER BY pc.seq_no",
84 DB_TEXT, product, DB_INT, DB_INT, DB_INT, DB_INT);
85 return e;
86 }
87
88
89 METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
90 private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
91 int id, bool is_dir)
92 {
93 enumerator_t *e;
94
95 if (is_dir)
96 {
97 e = this->db->query(this->db,
98 "SELECT f.path, fh.hash FROM file_hashes AS fh "
99 "JOIN files AS f ON fh.file = f.id "
100 "JOIN products AS p ON fh.product = p.id "
101 "WHERE p.name = ? AND fh.directory = ? AND fh.algo = ? "
102 "ORDER BY f.path",
103 DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
104 }
105 else
106 {
107 e = this->db->query(this->db,
108 "SELECT f.path, fh.hash FROM file_hashes AS fh "
109 "JOIN files AS f ON fh.file = f.id "
110 "JOIN products AS p ON fh.product = p.id "
111 "WHERE p.name = ? AND fh.file = ? AND fh.algo = ?",
112 DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
113 }
114 return e;
115 }
116
117 METHOD(pts_database_t, check_comp_measurement, status_t,
118 private_pts_database_t *this, chunk_t measurement,
119 pts_comp_func_name_t *comp_name, char *product,
120 int seq_no, int pcr, pts_meas_algorithms_t algo)
121 {
122 enumerator_t *e;
123 chunk_t hash;
124 status_t status = NOT_FOUND;
125
126 e = this->db->query(this->db,
127 "SELECT ch.hash FROM component_hashes AS ch "
128 "JOIN products AS p ON ch.product = p.id "
129 "JOIN components AS c ON ch.component = c.id "
130 "WHERE c.vendor_id = ? AND c.name = ? AND c.qualifier = ? "
131 "AND p.name = ? AND ch.seq_no = ? AND ch.pcr = ? AND ch.algo = ? ",
132 DB_INT, comp_name->get_vendor_id(comp_name),
133 DB_INT, comp_name->get_name(comp_name),
134 DB_INT, comp_name->get_qualifier(comp_name),
135 DB_TEXT, product, DB_INT, seq_no, DB_INT, pcr, DB_INT, algo,
136 DB_BLOB);
137 if (!e)
138 {
139 DBG1(DBG_PTS, "no database query enumerator returned");
140 return FAILED;
141 }
142
143 while (e->enumerate(e, &hash))
144 {
145 if (chunk_equals(hash, measurement))
146 {
147 DBG2(DBG_PTS, "PCR %2d matching component measurement #%d "
148 "found in database", pcr, seq_no);
149 status = SUCCESS;
150 break;
151 }
152 else
153 {
154 DBG1(DBG_PTS, "PCR %2d no matching component measurement #%d "
155 "found in database", pcr, seq_no);
156 DBG1(DBG_PTS, " expected: %#B", &hash);
157 DBG1(DBG_PTS, " received: %#B", &measurement);
158 status = FAILED;
159 break;
160 }
161 }
162 e->destroy(e);
163
164 if (status == NOT_FOUND)
165 {
166 DBG1(DBG_PTS, "PCR %2d no measurement #%d "
167 "found in database", pcr, seq_no);
168 }
169
170 return status;
171 }
172
173 METHOD(pts_database_t, destroy, void,
174 private_pts_database_t *this)
175 {
176 this->db->destroy(this->db);
177 free(this);
178 }
179
180 /**
181 * See header
182 */
183 pts_database_t *pts_database_create(char *uri)
184 {
185 private_pts_database_t *this;
186
187 INIT(this,
188 .public = {
189 .create_file_meas_enumerator = _create_file_meas_enumerator,
190 .create_file_meta_enumerator = _create_file_meta_enumerator,
191 .create_comp_evid_enumerator = _create_comp_evid_enumerator,
192 .create_file_hash_enumerator = _create_file_hash_enumerator,
193 .check_comp_measurement = _check_comp_measurement,
194 .destroy = _destroy,
195 },
196 .db = lib->db->create(lib->db, uri),
197 );
198
199 if (!this->db)
200 {
201 DBG1(DBG_PTS,
202 "failed to connect to PTS file measurement database '%s'", uri);
203 free(this);
204 return NULL;
205 }
206
207 return &this->public;
208 }
209