2 * Copyright (C) 2013-2015 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imv_policy_manager_usage.h"
17 #include "imv_workitem.h"
20 #include <utils/debug.h>
22 #include <tncif_names.h>
28 /* The default policy group #1 is assumed to always exist */
29 #define DEFAULT_GROUP_ID 1
32 * global debug output variables
34 static int debug_level
= 1;
35 static bool stderr_quiet
= FALSE
;
40 static void stderr_dbg(debug_t group
, level_t level
, char *fmt
, ...)
44 if (level
<= debug_level
)
49 vfprintf(stderr
, fmt
, args
);
50 fprintf(stderr
, "\n");
57 * Collect all enforcements by iterating up through parent groups
59 static bool iterate_enforcements(database_t
*db
, int device_id
, int session_id
,
62 int id
, type
, file
, dir
, arg_int
, parent
, policy
, max_age
;
63 int p_rec_fail
, p_rec_noresult
, e_rec_fail
, e_rec_noresult
, latest_rec
;
67 enumerator_t
*e
, *e1
, *e2
;
74 "SELECT e.id, p.type, p.argument, p.file, p.dir, p.rec_fail, "
75 "p.rec_noresult, e.policy, e.max_age, e.rec_fail, e.rec_noresult "
76 "FROM enforcements AS e JOIN policies as p ON e.policy = p.id "
77 "WHERE e.group_id = ?", DB_INT
, group_id
,
78 DB_INT
, DB_INT
, DB_TEXT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
79 DB_INT
, DB_INT
, DB_INT
, DB_INT
);
84 while (e1
->enumerate(e1
, &id
, &type
, &argument
, &file
, &dir
,
85 &p_rec_fail
, &p_rec_noresult
, &policy
, &max_age
,
86 &e_rec_fail
, &e_rec_noresult
))
88 /* check if the latest measurement of the device was successful */
89 latest_success
= FALSE
;
94 "SELECT r.rec FROM results AS r "
95 "JOIN sessions AS s ON s.id = r.session "
96 "WHERE r.policy = ? AND s.device = ? AND s.time > ? "
97 "ORDER BY s.time DESC",
98 DB_INT
, policy
, DB_INT
, device_id
,
99 DB_UINT
, now
- max_age
, DB_INT
);
105 if (e2
->enumerate(e2
, &latest_rec
) &&
106 latest_rec
== TNC_IMV_ACTION_RECOMMENDATION_ALLOW
)
108 latest_success
= TRUE
;
115 /*skipping enforcement */
116 printf("skipping enforcment %d\n", id
);
120 /* determine arg_int */
121 switch ((imv_workitem_type_t
)type
)
123 case IMV_WORKITEM_FILE_REF_MEAS
:
124 case IMV_WORKITEM_FILE_MEAS
:
125 case IMV_WORKITEM_FILE_META
:
128 case IMV_WORKITEM_DIR_REF_MEAS
:
129 case IMV_WORKITEM_DIR_MEAS
:
130 case IMV_WORKITEM_DIR_META
:
137 /* insert a workitem */
138 if (db
->execute(db
, NULL
,
139 "INSERT INTO workitems (session, enforcement, type, arg_str, "
140 "arg_int, rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?, ?)",
141 DB_INT
, session_id
, DB_INT
, id
, DB_INT
, type
, DB_TEXT
, argument
,
142 DB_INT
, arg_int
, DB_INT
, e_rec_fail
? e_rec_fail
: p_rec_fail
,
143 DB_INT
, e_rec_noresult
? e_rec_noresult
: p_rec_noresult
) != 1)
146 fprintf(stderr
, "could not insert workitem\n");
153 "SELECT parent FROM groups WHERE id = ?",
154 DB_INT
, group_id
, DB_INT
);
159 if (e
->enumerate(e
, &parent
))
165 fprintf(stderr
, "group information not found\n");
173 static bool policy_start(database_t
*db
, int session_id
)
176 int device_id
, product_id
, gid
, group_id
= DEFAULT_GROUP_ID
;
179 /* get session data */
181 "SELECT s.device, s.product, d.created FROM sessions AS s "
182 "LEFT JOIN devices AS d ON s.device = d.id WHERE s.id = ?",
183 DB_INT
, session_id
, DB_INT
, DB_INT
, DB_UINT
);
184 if (!e
|| !e
->enumerate(e
, &device_id
, &product_id
, &created
))
187 fprintf(stderr
, "session %d not found\n", session_id
);
192 /* if a device ID with a creation date exists, get all group memberships */
193 if (device_id
&& created
)
196 "SELECT group_id FROM groups_members WHERE device_id = ?",
197 DB_INT
, device_id
, DB_INT
);
202 while (e
->enumerate(e
, &group_id
))
204 if (!iterate_enforcements(db
, device_id
, session_id
, group_id
))
215 /* determine if a default product group exists */
217 "SELECT group_id FROM groups_product_defaults "
218 "WHERE product_id = ?", DB_INT
, product_id
, DB_INT
);
223 if (e
->enumerate(e
, &gid
))
229 if (device_id
&& !created
)
231 /* assign a newly created device to a default group */
232 if (db
->execute(db
, NULL
,
233 "INSERT INTO groups_members (device_id, group_id) "
234 "VALUES (?, ?)", DB_INT
, device_id
, DB_INT
, group_id
) != 1)
236 fprintf(stderr
, "could not assign device to a default group\n");
240 /* set the creation date if it hasn't been set yet */
241 if (db
->execute(db
, NULL
,
242 "UPDATE devices SET created = ? WHERE id = ?",
243 DB_UINT
, time(NULL
), DB_INT
, device_id
) != 1)
245 fprintf(stderr
, "creation date of device could not be set\n");
250 return iterate_enforcements(db
, device_id
, session_id
, group_id
);
253 static bool policy_stop(database_t
*db
, int session_id
)
256 int rec
, policy
, final_rec
, id_type
;
258 char *result
, *ip_address
= NULL
;
261 /* store all workitem results for this session in the results table */
263 "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
264 "JOIN enforcements AS e ON w.enforcement = e.id "
265 "WHERE w.session = ? AND w.result IS NOT NULL",
266 DB_INT
, session_id
, DB_INT
, DB_TEXT
, DB_INT
);
269 while (e
->enumerate(e
, &rec
, &result
, &policy
))
271 db
->execute(db
, NULL
,
272 "INSERT INTO results (session, policy, rec, result) "
273 "VALUES (?, ?, ?, ?)", DB_INT
, session_id
, DB_INT
, policy
,
274 DB_INT
, rec
, DB_TEXT
, result
);
283 /* delete all workitems for this session from the database */
284 if (db
->execute(db
, NULL
,
285 "DELETE FROM workitems WHERE session = ?",
286 DB_UINT
, session_id
) < 0)
291 final_rec
= TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
;
293 /* retrieve the final recommendation for this session */
295 "SELECT rec FROM sessions WHERE id = ?",
296 DB_INT
, session_id
, DB_INT
);
299 if (!e
->enumerate(e
, &final_rec
))
310 /* retrieve client IP address for this session */
312 "SELECT i.type, i.value FROM identities AS i "
313 "JOIN sessions_identities AS si ON si.identity_id = i.id "
314 "WHERE si.session_id = ? AND (i.type = ? OR i.type = ?)",
315 DB_INT
, session_id
, DB_INT
, TNC_ID_IPV4_ADDR
, DB_INT
,
316 TNC_ID_IPV6_ADDR
, DB_INT
, DB_BLOB
);
319 if (e
->enumerate(e
, &id_type
, &id_value
))
321 ip_address
= strndup(id_value
.ptr
, id_value
.len
);
334 fprintf(stderr
, "recommendation for access requestor %s is %N\n",
335 ip_address
? ip_address
: "0.0.0.0",
336 TNC_IMV_Action_Recommendation_names
, final_rec
);
342 int main(int argc
, char *argv
[])
349 /* enable attest debugging hook */
352 atexit(library_deinit
);
354 /* initialize library */
355 if (!library_init(NULL
, "imv_policy_manager"))
357 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY
);
359 if (!lib
->plugins
->load(lib
->plugins
,
360 lib
->settings
->get_str(lib
->settings
, "imv_policy_manager.load",
363 exit(SS_RC_INITIALIZATION_FAILED
);
369 exit(SS_RC_INITIALIZATION_FAILED
);
371 if (streq(argv
[1], "start"))
375 else if (streq(argv
[1], "stop"))
382 exit(SS_RC_INITIALIZATION_FAILED
);
385 session_id
= atoi(argv
[2]);
387 /* attach IMV database */
388 uri
= lib
->settings
->get_str(lib
->settings
,
389 "imv_policy_manager.database",
390 lib
->settings
->get_str(lib
->settings
,
391 "charon.imcv.database",
392 lib
->settings
->get_str(lib
->settings
,
393 "libimcv.database", NULL
)));
396 fprintf(stderr
, "database uri not defined.\n");
397 exit(SS_RC_INITIALIZATION_FAILED
);
400 db
= lib
->db
->create(lib
->db
, uri
);
403 fprintf(stderr
, "opening database failed.\n");
404 exit(SS_RC_INITIALIZATION_FAILED
);
409 success
= policy_start(db
, session_id
);
413 success
= policy_stop(db
, session_id
);
417 fprintf(stderr
, "imv_policy_manager %s %s\n", start
? "start" : "stop",
418 success
? "successful" : "failed");