do not process workitems with NULL result
[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 = 2;
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;
54 int type, 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 group_members WHERE device = ?",
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 default_product_groups WHERE product = ?",
90 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 /* if still no group membership found, leave */
102 if (!group_id)
103 {
104 fprintf(stderr, "no group membership found\n");
105 return TRUE;
106 }
107
108 /* get enforcements for given group */
109 e = db->query(db,
110 "SELECT e.id, p.type, p.argument, p.rec_fail, p.rec_noresult "
111 "FROM enforcements AS e JOIN policies as p ON e.policy = p.id "
112 "WHERE e.group_id = ?",
113 DB_INT, group_id, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
114 if (!e)
115 {
116 return FALSE;
117 }
118 while (e->enumerate(e, &id, &type, &argument, &rec_fail, &rec_noresult))
119 {
120 /* insert a workitem */
121 if (db->execute(db, NULL,
122 "INSERT INTO workitems (session, enforcement, type, argument, "
123 "rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?)",
124 DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
125 DB_INT, rec_fail, DB_INT, rec_noresult) != 1)
126 {
127 e->destroy(e);
128 fprintf(stderr, "could not insert workitem\n");
129 return FALSE;
130 }
131 }
132 e->destroy(e);
133
134 return TRUE;
135 }
136
137 bool policy_stop(database_t *db, int session_id)
138 {
139 enumerator_t *e;
140 int rec, policy;
141 char *result;
142 bool no_worklists = TRUE;
143
144 e = db->query(db,
145 "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
146 "JOIN enforcements AS e ON w.enforcement = e.id "
147 "WHERE w.session = ? AND w.result IS NOT NULL",
148 DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
149 if (e)
150 {
151 while (e->enumerate(e, &rec, &result, &policy))
152 {
153 no_worklists = FALSE;
154
155 /* insert result */
156 db->execute(db, NULL,
157 "INSERT INTO results (session, policy, rec, result) "
158 "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
159 DB_INT, rec, DB_TEXT, result);
160 }
161 e->destroy(e);
162
163 if (no_worklists)
164 {
165 return TRUE;
166 }
167 }
168 return db->execute(db, NULL,
169 "DELETE FROM workitems WHERE session = ?",
170 DB_UINT, session_id) > 0;
171 }
172
173 int main(int argc, char *argv[])
174 {
175 database_t *db;
176 char *uri, *tnc_session_id;
177 int session_id;
178 bool start, success;
179
180 /* enable attest debugging hook */
181 dbg = stderr_dbg;
182
183 atexit(library_deinit);
184
185 /* initialize library */
186 if (!library_init(NULL))
187 {
188 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
189 }
190 if (!lib->plugins->load(lib->plugins, NULL,
191 lib->settings->get_str(lib->settings, "imv_policy_manager.load",
192 "sqlite")))
193 {
194 exit(SS_RC_INITIALIZATION_FAILED);
195 }
196
197 if (argc < 2)
198 {
199 usage();
200 exit(SS_RC_INITIALIZATION_FAILED);
201 }
202 if (streq(argv[1], "start"))
203 {
204 start = TRUE;
205 }
206 else if (streq(argv[1], "stop"))
207 {
208 start = FALSE;
209 }
210 else
211 {
212 usage();
213 exit(SS_RC_INITIALIZATION_FAILED);
214 }
215
216 /* get session ID */
217 tnc_session_id = getenv("TNC_SESSION_ID");
218 if (!tnc_session_id)
219 {
220 fprintf(stderr, "environment variable TNC_SESSION_ID is not defined\n");
221 exit(SS_RC_INITIALIZATION_FAILED);
222 }
223 session_id = atoi(tnc_session_id);
224
225 /* attach IMV database */
226 uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
227 db = lib->db->create(lib->db, uri);
228 if (!db)
229 {
230 fprintf(stderr, "opening database failed.\n");
231 exit(SS_RC_INITIALIZATION_FAILED);
232 }
233
234 if (start)
235 {
236 success = policy_start(db, session_id);
237 }
238 else
239 {
240 success = policy_stop(db, session_id);
241 }
242 db->destroy(db);
243
244 fprintf(stderr, "imv_policy_manager %s %s\n", start ? "start" : "stop",
245 success ? "successful" : "failed");
246
247 exit(EXIT_SUCCESS);
248 }
249