generate workitems based on group policy
[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 WHERE w.id = ?",
147 DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
148 if (e)
149 {
150 while (e->enumerate(e, &rec, &result, &policy))
151 {
152 no_worklists = FALSE;
153
154 /* insert result */
155 db->execute(db, NULL,
156 "INSERT INTO results (session, policy, rec, result) "
157 "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
158 DB_INT, rec, DB_TEXT, result);
159 }
160 e->destroy(e);
161
162 if (no_worklists)
163 {
164 return TRUE;
165 }
166 }
167 return db->execute(db, NULL,
168 "DELETE FROM workitems WHERE session = ?",
169 DB_UINT, session_id) > 0;
170 }
171
172 int main(int argc, char *argv[])
173 {
174 database_t *db;
175 char *uri, *tnc_session_id;
176 int session_id;
177 bool start, success;
178
179 /* enable attest debugging hook */
180 dbg = stderr_dbg;
181
182 atexit(library_deinit);
183
184 /* initialize library */
185 if (!library_init(NULL))
186 {
187 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
188 }
189 if (!lib->plugins->load(lib->plugins, NULL,
190 lib->settings->get_str(lib->settings, "imv_policy_manager.load",
191 "sqlite")))
192 {
193 exit(SS_RC_INITIALIZATION_FAILED);
194 }
195
196 if (argc < 2)
197 {
198 usage();
199 exit(SS_RC_INITIALIZATION_FAILED);
200 }
201 if (streq(argv[1], "start"))
202 {
203 start = TRUE;
204 }
205 else if (streq(argv[1], "stop"))
206 {
207 start = FALSE;
208 }
209 else
210 {
211 usage();
212 exit(SS_RC_INITIALIZATION_FAILED);
213 }
214
215 /* get session ID */
216 tnc_session_id = getenv("TNC_SESSION_ID");
217 if (!tnc_session_id)
218 {
219 fprintf(stderr, "environment variable TNC_SESSION_ID is not defined\n");
220 exit(SS_RC_INITIALIZATION_FAILED);
221 }
222 session_id = atoi(tnc_session_id);
223
224 /* attach IMV database */
225 uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
226 db = lib->db->create(lib->db, uri);
227 if (!db)
228 {
229 fprintf(stderr, "opening database failed.\n");
230 exit(SS_RC_INITIALIZATION_FAILED);
231 }
232
233 if (start)
234 {
235 success = policy_start(db, session_id);
236 }
237 else
238 {
239 success = policy_stop(db, session_id);
240 }
241 db->destroy(db);
242
243 fprintf(stderr, "imv_policy_manager %s %s\n", start ? "start" : "stop",
244 success ? "successful" : "failed");
245
246 exit(EXIT_SUCCESS);
247 }
248