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