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