Set device creation date if it hasn't been set yet
[strongswan.git] / src / libimcv / imv / imv_policy_manager.c
1 /*
2 * Copyright (C) 2013 Andreas Steffen
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 "imv_policy_manager_usage.h"
17 #include "imv_workitem.h"
18
19 #include <library.h>
20 #include <utils/debug.h>
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <time.h>
25
26 /**
27 * global debug output variables
28 */
29 static int debug_level = 1;
30 static bool stderr_quiet = FALSE;
31
32 /**
33 * attest dbg function
34 */
35 static void stderr_dbg(debug_t group, level_t level, char *fmt, ...)
36 {
37 va_list args;
38
39 if (level <= debug_level)
40 {
41 if (!stderr_quiet)
42 {
43 va_start(args, fmt);
44 vfprintf(stderr, fmt, args);
45 fprintf(stderr, "\n");
46 va_end(args);
47 }
48 }
49 }
50
51 bool policy_start(database_t *db, int session_id)
52 {
53 enumerator_t *e;
54 int id, gid, device_id, product_id, group_id = 0, parent;
55 int type, file, dir, arg_int, rec_fail, rec_noresult;
56 u_int created;
57 char *argument;
58
59 /* get session data */
60 e = db->query(db,
61 "SELECT s.device, s.product, d.created FROM sessions AS s "
62 "LEFT JOIN devices AS d ON s.device = d.id WHERE s.id = ?",
63 DB_INT, session_id, DB_INT, DB_INT, DB_UINT);
64 if (!e || !e->enumerate(e, &device_id, &product_id, &created))
65 {
66 DESTROY_IF(e);
67 fprintf(stderr, "session %d not found\n", session_id);
68 return FALSE;
69 }
70 e->destroy(e);
71
72 /* if a device ID exists, check if device belongs to a group */
73 if (device_id)
74 {
75 e = db->query(db,
76 "SELECT group_id FROM groups_members WHERE device_id = ?",
77 DB_INT, device_id, DB_INT);
78 if (e)
79 {
80 if (e->enumerate(e, &gid))
81 {
82 group_id = gid;
83 }
84 e->destroy(e);
85 }
86
87 /* set the creation date if hasn't been set yet */
88 if (!created)
89 {
90 if (db->execute(db, NULL,
91 "UPDATE devices SET created = ? WHERE id = ?",
92 DB_UINT, time(NULL), DB_INT, device_id) != 1)
93 {
94 fprintf(stderr, "creation date of device could not be set\n");
95 return FALSE;
96 }
97 }
98 }
99
100 /* if no group membership found, try default product group */
101 if (!group_id)
102 {
103 e = db->query(db,
104 "SELECT group_id FROM groups_product_defaults "
105 "WHERE product_id = ?", DB_INT, product_id, DB_INT);
106 if (e)
107 {
108 if (e->enumerate(e, &gid))
109 {
110 group_id = gid;
111 }
112 e->destroy(e);
113 }
114 }
115
116 /* get iteratively enforcements for given group */
117 while (group_id)
118 {
119 e = db->query(db,
120 "SELECT e.id, "
121 "p.type, p.argument, p.file, p.dir, p.rec_fail, p.rec_noresult "
122 "FROM enforcements AS e JOIN policies as p ON e.policy = p.id "
123 "WHERE e.group_id = ?", DB_INT, group_id,
124 DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT);
125 if (!e)
126 {
127 return FALSE;
128 }
129 while (e->enumerate(e, &id, &type, &argument, &file, &dir,
130 &rec_fail, &rec_noresult))
131 {
132 /* determine arg_int */
133 switch ((imv_workitem_type_t)type)
134 {
135 case IMV_WORKITEM_FILE_REF_MEAS:
136 case IMV_WORKITEM_FILE_MEAS:
137 case IMV_WORKITEM_FILE_META:
138 arg_int = file;
139 break;
140 case IMV_WORKITEM_DIR_REF_MEAS:
141 case IMV_WORKITEM_DIR_MEAS:
142 case IMV_WORKITEM_DIR_META:
143 arg_int = dir;
144 break;
145 default:
146 arg_int = 0;
147 }
148
149 /* insert a workitem */
150 if (db->execute(db, NULL,
151 "INSERT INTO workitems (session, enforcement, type, arg_str, "
152 "arg_int, rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?, ?)",
153 DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
154 DB_INT, arg_int, DB_INT, rec_fail, DB_INT, rec_noresult) != 1)
155 {
156 e->destroy(e);
157 fprintf(stderr, "could not insert workitem\n");
158 return FALSE;
159 }
160 }
161 e->destroy(e);
162
163 e = db->query(db,
164 "SELECT parent FROM groups WHERE id = ?",
165 DB_INT, group_id, DB_INT);
166 if (!e)
167 {
168 return FALSE;
169 }
170 if (e->enumerate(e, &parent))
171 {
172 group_id = parent;
173 }
174 else
175 {
176 fprintf(stderr, "group information not found\n");
177 group_id = 0;
178 }
179 e->destroy(e);
180 }
181
182 return TRUE;
183 }
184
185 bool policy_stop(database_t *db, int session_id)
186 {
187 enumerator_t *e;
188 int rec, policy;
189 char *result;
190
191 e = db->query(db,
192 "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
193 "JOIN enforcements AS e ON w.enforcement = e.id "
194 "WHERE w.session = ? AND w.result IS NOT NULL",
195 DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
196 if (e)
197 {
198 while (e->enumerate(e, &rec, &result, &policy))
199 {
200 db->execute(db, NULL,
201 "INSERT INTO results (session, policy, rec, result) "
202 "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
203 DB_INT, rec, DB_TEXT, result);
204 }
205 e->destroy(e);
206 }
207 return db->execute(db, NULL,
208 "DELETE FROM workitems WHERE session = ?",
209 DB_UINT, session_id) >= 0;
210 }
211
212 int main(int argc, char *argv[])
213 {
214 database_t *db;
215 char *uri, *tnc_session_id;
216 int session_id;
217 bool start, success;
218
219 /* enable attest debugging hook */
220 dbg = stderr_dbg;
221
222 atexit(library_deinit);
223
224 /* initialize library */
225 if (!library_init(NULL))
226 {
227 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
228 }
229 if (!lib->plugins->load(lib->plugins, NULL,
230 lib->settings->get_str(lib->settings, "imv_policy_manager.load",
231 "sqlite")))
232 {
233 exit(SS_RC_INITIALIZATION_FAILED);
234 }
235
236 if (argc < 2)
237 {
238 usage();
239 exit(SS_RC_INITIALIZATION_FAILED);
240 }
241 if (streq(argv[1], "start"))
242 {
243 start = TRUE;
244 }
245 else if (streq(argv[1], "stop"))
246 {
247 start = FALSE;
248 }
249 else
250 {
251 usage();
252 exit(SS_RC_INITIALIZATION_FAILED);
253 }
254
255 /* get session ID */
256 tnc_session_id = getenv("TNC_SESSION_ID");
257 if (!tnc_session_id)
258 {
259 fprintf(stderr, "environment variable TNC_SESSION_ID is not defined\n");
260 exit(SS_RC_INITIALIZATION_FAILED);
261 }
262 session_id = atoi(tnc_session_id);
263
264 /* attach IMV database */
265 uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
266 if (!uri)
267 {
268 fprintf(stderr, "database uri not defined.\n");
269 exit(SS_RC_INITIALIZATION_FAILED);
270 }
271
272 db = lib->db->create(lib->db, uri);
273 if (!db)
274 {
275 fprintf(stderr, "opening database failed.\n");
276 exit(SS_RC_INITIALIZATION_FAILED);
277 }
278
279 if (start)
280 {
281 success = policy_start(db, session_id);
282 }
283 else
284 {
285 success = policy_stop(db, session_id);
286 }
287 db->destroy(db);
288
289 fprintf(stderr, "imv_policy_manager %s %s\n", start ? "start" : "stop",
290 success ? "successful" : "failed");
291
292 exit(EXIT_SUCCESS);
293 }
294