Introduced workitems to Attestation IMV

This commit is contained in:
Andreas Steffen
2013-06-21 23:25:23 +02:00
parent 7e9bdd20aa
commit b1da8368d0
20 changed files with 777 additions and 471 deletions
+59 -4
View File
@@ -262,6 +262,12 @@ INSERT INTO files ( /* 5 */
'openssl', 8 'openssl', 8
); );
INSERT INTO files ( /* 6 */
name, dir
) VALUES (
'tnc_config', 2
);
/* Algorithms */ /* Algorithms */
INSERT INTO algorithms ( INSERT INTO algorithms (
@@ -639,15 +645,40 @@ INSERT INTO policies ( /* 7 */
INSERT INTO policies ( /* 8 */ INSERT INTO policies ( /* 8 */
type, name, rec_fail, rec_noresult type, name, rec_fail, rec_noresult
) VALUES ( ) VALUES (
9, 'No Open TCP Ports', 1, 1 11, 'No Open TCP Ports', 1, 1
); );
INSERT INTO policies ( /* 9 */ INSERT INTO policies ( /* 9 */
type, name, rec_fail, rec_noresult type, name, rec_fail, rec_noresult
) VALUES ( ) VALUES (
10, 'No Open UDP Ports', 1, 1 12, 'No Open UDP Ports', 1, 1
); );
INSERT INTO policies ( /* 10 */
type, name, file, rec_fail, rec_noresult
) VALUES (
7, 'Metadata of /etc/tnc_config', 6, 0, 0
);
INSERT INTO policies ( /* 11 */
type, name, dir, rec_fail, rec_noresult
) VALUES (
8, 'Measure as reference /bin', 1, 0, 0
);
INSERT INTO policies ( /* 12 */
type, name, file, rec_fail, rec_noresult
) VALUES (
6, 'Measure /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', 2, 2, 2
);
INSERT INTO policies ( /* 13 */
type, name, file, rec_fail, rec_noresult
) VALUES (
6, 'Measure /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0', 4, 2, 2
);
/* Enforcements */ /* Enforcements */
INSERT INTO enforcements ( INSERT INTO enforcements (
@@ -713,13 +744,13 @@ INSERT INTO enforcements (
INSERT INTO enforcements ( INSERT INTO enforcements (
policy, group_id, max_age policy, group_id, max_age
) VALUES ( ) VALUES (
5, 2, 86400 5, 4, 86400
); );
INSERT INTO enforcements ( INSERT INTO enforcements (
policy, group_id, max_age policy, group_id, max_age
) VALUES ( ) VALUES (
6, 2, 86400 6, 4, 86400
); );
INSERT INTO enforcements ( INSERT INTO enforcements (
@@ -788,3 +819,27 @@ INSERT INTO enforcements (
9, 5, 60 9, 5, 60
); );
INSERT INTO enforcements (
policy, group_id, max_age
) VALUES (
10, 2, 60
);
INSERT INTO enforcements (
policy, group_id, max_age
) VALUES (
11, 2, 86400
);
INSERT INTO enforcements (
policy, group_id, max_age
) VALUES (
12, 2, 86400
);
INSERT INTO enforcements (
policy, group_id, max_age
) VALUES (
13, 2, 86400
);
+7 -1
View File
@@ -285,6 +285,7 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
imv_state_t *state; imv_state_t *state;
imv_session_t *session;
bool found = FALSE; bool found = FALSE;
this->connection_lock->write_lock(this->connection_lock); this->connection_lock->write_lock(this->connection_lock);
@@ -294,6 +295,11 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id)
if (id == state->get_connection_id(state)) if (id == state->get_connection_id(state))
{ {
found = TRUE; found = TRUE;
session = state->get_session(state);
if (session)
{
imcv_db->remove_session(imcv_db, session);
}
state->destroy(state); state->destroy(state);
this->connections->remove_at(this->connections, enumerator); this->connections->remove_at(this->connections, enumerator);
break; break;
@@ -480,7 +486,7 @@ METHOD(imv_agent_t, create_state, TNC_Result,
if (imcv_db) if (imcv_db)
{ {
session = imcv_db->get_session(imcv_db, conn_id, ar_id_type, ar_id_value); session = imcv_db->add_session(imcv_db, conn_id, ar_id_type, ar_id_value);
if (session) if (session)
{ {
DBG2(DBG_IMV, " assigned session ID %d", DBG2(DBG_IMV, " assigned session ID %d",
+32 -25
View File
@@ -59,7 +59,7 @@ struct private_imv_database_t {
}; };
METHOD(imv_database_t, get_session, imv_session_t*, METHOD(imv_database_t, add_session, imv_session_t*,
private_imv_database_t *this, TNC_ConnectionID conn_id, private_imv_database_t *this, TNC_ConnectionID conn_id,
u_int32_t ar_id_type, chunk_t ar_id_value) u_int32_t ar_id_type, chunk_t ar_id_value)
{ {
@@ -123,6 +123,26 @@ METHOD(imv_database_t, get_session, imv_session_t*,
return session; return session;
} }
METHOD(imv_database_t, remove_session, void,
private_imv_database_t *this, imv_session_t *session)
{
enumerator_t *enumerator;
imv_session_t *current;
this->mutex->lock(this->mutex);
enumerator = this->sessions->create_enumerator(this->sessions);
while (enumerator->enumerate(enumerator, &current))
{
if (current == session)
{
this->sessions->remove_at(this->sessions, enumerator);
break;
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
METHOD(imv_database_t, add_product, int, METHOD(imv_database_t, add_product, int,
private_imv_database_t *this, imv_session_t *session, char *product) private_imv_database_t *this, imv_session_t *session, char *product)
{ {
@@ -204,10 +224,9 @@ METHOD(imv_database_t, policy_script, bool,
{ {
imv_workitem_t *workitem; imv_workitem_t *workitem;
imv_workitem_type_t type; imv_workitem_type_t type;
imv_session_t *current; int id, session_id, arg_int, rec_fail, rec_noresult;
int id, session_id, rec_fail, rec_noresult; enumerator_t *e;
enumerator_t *enumerator, *e; char command[512], resp[128], *last, *arg_str;
char command[512], resp[128], *last, *argument;
FILE *shell; FILE *shell;
session_id = session->get_session_id(session); session_id = session->get_session_id(session);
@@ -250,17 +269,18 @@ METHOD(imv_database_t, policy_script, bool,
{ {
/* get workitem list generated by policy manager */ /* get workitem list generated by policy manager */
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT id, type, argument, rec_fail, rec_noresult " "SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult "
"FROM workitems WHERE session = ?", "FROM workitems WHERE session = ?", DB_INT, session_id,
DB_INT, session_id, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT); DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT);
if (!e) if (!e)
{ {
DBG1(DBG_IMV, "no workitem enumerator returned"); DBG1(DBG_IMV, "no workitem enumerator returned");
return FALSE; return FALSE;
} }
while (e->enumerate(e, &id, &type, &argument, &rec_fail, &rec_noresult)) while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail,
&rec_noresult))
{ {
workitem = imv_workitem_create(id, type, argument, rec_fail, workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail,
rec_noresult); rec_noresult);
session->insert_workitem(session, workitem); session->insert_workitem(session, workitem);
} }
@@ -270,20 +290,6 @@ METHOD(imv_database_t, policy_script, bool,
} }
else if (!start && session->get_policy_started(session)) else if (!start && session->get_policy_started(session))
{ {
/* remove session */
this->mutex->lock(this->mutex);
enumerator = this->sessions->create_enumerator(this->sessions);
while (enumerator->enumerate(enumerator, &current))
{
if (current == session)
{
this->sessions->remove_at(this->sessions, enumerator);
break;
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
session->set_policy_started(session, FALSE); session->set_policy_started(session, FALSE);
} }
@@ -329,7 +335,8 @@ imv_database_t *imv_database_create(char *uri, char *script)
INIT(this, INIT(this,
.public = { .public = {
.get_session = _get_session, .add_session = _add_session,
.remove_session = _remove_session,
.add_product = _add_product, .add_product = _add_product,
.add_device = _add_device, .add_device = _add_device,
.add_recommendation = _add_recommendation, .add_recommendation = _add_recommendation,
+8 -1
View File
@@ -44,10 +44,17 @@ struct imv_database_t {
* @param ar_id_value Access Requestor identity value * @param ar_id_value Access Requestor identity value
* @return Session associated with TNCCS Connection * @return Session associated with TNCCS Connection
*/ */
imv_session_t* (*get_session)(imv_database_t *this, imv_session_t* (*add_session)(imv_database_t *this,
TNC_ConnectionID conn_id, TNC_ConnectionID conn_id,
u_int32_t ar_id_type, chunk_t ar_id_value); u_int32_t ar_id_type, chunk_t ar_id_value);
/**
* Remove and delete a session
*
* @param session Session
*/
void (*remove_session)(imv_database_t *this, imv_session_t *session);
/** /**
* Add product information string to a session database entry * Add product information string to a session database entry
* *
+35 -19
View File
@@ -25,7 +25,7 @@
/** /**
* global debug output variables * global debug output variables
*/ */
static int debug_level = 2; static int debug_level = 1;
static bool stderr_quiet = FALSE; static bool stderr_quiet = FALSE;
/** /**
@@ -51,7 +51,7 @@ bool policy_start(database_t *db, int session_id)
{ {
enumerator_t *e; enumerator_t *e;
int id, gid, device_id, product_id, group_id = 0; int id, gid, device_id, product_id, group_id = 0;
int type, rec_fail, rec_noresult; int type, file, dir, arg_int, rec_fail, rec_noresult;
char *argument; char *argument;
/* get session data */ /* get session data */
@@ -107,22 +107,41 @@ bool policy_start(database_t *db, int session_id)
/* get enforcements for given group */ /* get enforcements for given group */
e = db->query(db, e = db->query(db,
"SELECT e.id, p.type, p.argument, p.rec_fail, p.rec_noresult " "SELECT e.id, "
"p.type, p.argument, p.file, p.dir, p.rec_fail, p.rec_noresult "
"FROM enforcements AS e JOIN policies as p ON e.policy = p.id " "FROM enforcements AS e JOIN policies as p ON e.policy = p.id "
"WHERE e.group_id = ?", "WHERE e.group_id = ?", DB_INT, group_id,
DB_INT, group_id, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT); DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT);
if (!e) if (!e)
{ {
return FALSE; return FALSE;
} }
while (e->enumerate(e, &id, &type, &argument, &rec_fail, &rec_noresult)) while (e->enumerate(e, &id, &type, &argument, &file, &dir, &rec_fail,
&rec_noresult))
{ {
/* determine arg_int */
switch ((imv_workitem_type_t)type)
{
case IMV_WORKITEM_FILE_REF_MEAS:
case IMV_WORKITEM_FILE_MEAS:
case IMV_WORKITEM_FILE_META:
arg_int = file;
break;
case IMV_WORKITEM_DIR_REF_MEAS:
case IMV_WORKITEM_DIR_MEAS:
case IMV_WORKITEM_DIR_META:
arg_int = dir;
break;
default:
arg_int = 0;
}
/* insert a workitem */ /* insert a workitem */
if (db->execute(db, NULL, if (db->execute(db, NULL,
"INSERT INTO workitems (session, enforcement, type, argument, " "INSERT INTO workitems (session, enforcement, type, arg_str, "
"rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?)", "arg_int, rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?, ?)",
DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument, DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
DB_INT, rec_fail, DB_INT, rec_noresult) != 1) DB_INT, arg_int, DB_INT, rec_fail, DB_INT, rec_noresult) != 1)
{ {
e->destroy(e); e->destroy(e);
fprintf(stderr, "could not insert workitem\n"); fprintf(stderr, "could not insert workitem\n");
@@ -139,7 +158,6 @@ bool policy_stop(database_t *db, int session_id)
enumerator_t *e; enumerator_t *e;
int rec, policy; int rec, policy;
char *result; char *result;
bool no_worklists = TRUE;
e = db->query(db, e = db->query(db,
"SELECT w.rec_final, w.result, e.policy FROM workitems AS w " "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
@@ -150,24 +168,16 @@ bool policy_stop(database_t *db, int session_id)
{ {
while (e->enumerate(e, &rec, &result, &policy)) while (e->enumerate(e, &rec, &result, &policy))
{ {
no_worklists = FALSE;
/* insert result */
db->execute(db, NULL, db->execute(db, NULL,
"INSERT INTO results (session, policy, rec, result) " "INSERT INTO results (session, policy, rec, result) "
"VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy, "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
DB_INT, rec, DB_TEXT, result); DB_INT, rec, DB_TEXT, result);
} }
e->destroy(e); e->destroy(e);
if (no_worklists)
{
return TRUE;
}
} }
return db->execute(db, NULL, return db->execute(db, NULL,
"DELETE FROM workitems WHERE session = ?", "DELETE FROM workitems WHERE session = ?",
DB_UINT, session_id) > 0; DB_UINT, session_id) >= 0;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -224,6 +234,12 @@ int main(int argc, char *argv[])
/* attach IMV database */ /* attach IMV database */
uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL); uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
if (!uri)
{
fprintf(stderr, "database uri not defined.\n");
exit(SS_RC_INITIALIZATION_FAILED);
}
db = lib->db->create(lib->db, uri); db = lib->db->create(lib->db, uri);
if (!db) if (!db)
{ {
+14
View File
@@ -79,6 +79,20 @@ struct imv_state_t {
*/ */
u_int32_t (*get_max_msg_len)(imv_state_t *this); u_int32_t (*get_max_msg_len)(imv_state_t *this);
/**
* Set flags for completed actions
*
* @param flags Flags to be set
*/
void (*set_action_flags)(imv_state_t *this, u_int32_t flags);
/**
* Get flags set for completed actions
*
* @return Flags set for completed actions
*/
u_int32_t (*get_action_flags)(imv_state_t *this);
/** /**
* Set Access Requestor ID * Set Access Requestor ID
* *
+26 -10
View File
@@ -27,8 +27,10 @@ ENUM(imv_workitem_type_names, IMV_WORKITEM_PACKAGES, IMV_WORKITEM_UDP_SCAN,
"PWDEN", "PWDEN",
"FREFM", "FREFM",
"FMEAS", "FMEAS",
"FMETA",
"DREFM", "DREFM",
"DMEAS", "DMEAS",
"DMETA",
"TCPSC", "TCPSC",
"UDPSC" "UDPSC"
); );
@@ -62,7 +64,12 @@ struct private_imv_workitem_t {
/** /**
* Argument string * Argument string
*/ */
char *argument; char *arg_str;
/**
* Argument integer
*/
int arg_int;
/** /**
* Result string * Result string
@@ -110,10 +117,16 @@ METHOD(imv_workitem_t, get_type, imv_workitem_type_t,
return this->type; return this->type;
} }
METHOD(imv_workitem_t, get_argument, char*, METHOD(imv_workitem_t, get_arg_str, char*,
private_imv_workitem_t *this) private_imv_workitem_t *this)
{ {
return this->argument; return this->arg_str;
}
METHOD(imv_workitem_t, get_arg_int, int,
private_imv_workitem_t *this)
{
return this->arg_int;
} }
METHOD(imv_workitem_t, set_result, TNC_IMV_Action_Recommendation, METHOD(imv_workitem_t, set_result, TNC_IMV_Action_Recommendation,
@@ -135,9 +148,10 @@ METHOD(imv_workitem_t, set_result, TNC_IMV_Action_Recommendation,
this->rec_final = this->rec_noresult; this->rec_final = this->rec_noresult;
break; break;
} }
DBG2(DBG_IMV, "workitem %N: %N%s%s", imv_workitem_type_names, this->type, DBG2(DBG_IMV, "IMV %d handled %N workitem %d: %N%s%s", this->imv_id,
TNC_IMV_Action_Recommendation_names, this->rec_final, imv_workitem_type_names, this->type, this->id,
strlen(result) ? " - " : "", result); TNC_IMV_Action_Recommendation_names, this->rec_final,
strlen(result) ? " - " : "", result);
return this->rec_final; return this->rec_final;
} }
@@ -155,7 +169,7 @@ METHOD(imv_workitem_t, get_result, TNC_IMV_Action_Recommendation,
METHOD(imv_workitem_t, destroy, void, METHOD(imv_workitem_t, destroy, void,
private_imv_workitem_t *this) private_imv_workitem_t *this)
{ {
free(this->argument); free(this->arg_str);
free(this->result); free(this->result);
free(this); free(this);
} }
@@ -164,7 +178,7 @@ METHOD(imv_workitem_t, destroy, void,
* See header * See header
*/ */
imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type, imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
char *argument, char *arg_str, int arg_int,
TNC_IMV_Action_Recommendation rec_fail, TNC_IMV_Action_Recommendation rec_fail,
TNC_IMV_Action_Recommendation rec_noresult) TNC_IMV_Action_Recommendation rec_noresult)
{ {
@@ -176,7 +190,8 @@ imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
.set_imv_id = _set_imv_id, .set_imv_id = _set_imv_id,
.get_imv_id = _get_imv_id, .get_imv_id = _get_imv_id,
.get_type = _get_type, .get_type = _get_type,
.get_argument = _get_argument, .get_arg_str = _get_arg_str,
.get_arg_int = _get_arg_int,
.set_result = _set_result, .set_result = _set_result,
.get_result = _get_result, .get_result = _get_result,
.destroy = _destroy, .destroy = _destroy,
@@ -184,7 +199,8 @@ imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
.id = id, .id = id,
.imv_id = TNC_IMVID_ANY, .imv_id = TNC_IMVID_ANY,
.type = type, .type = type,
.argument = strdup(argument), .arg_str = arg_str ? strdup(arg_str) : NULL,
.arg_int = arg_int,
.rec_fail = rec_fail, .rec_fail = rec_fail,
.rec_noresult = rec_noresult, .rec_noresult = rec_noresult,
.rec_final = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, .rec_final = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+18 -8
View File
@@ -36,10 +36,12 @@ enum imv_workitem_type_t {
IMV_WORKITEM_DEFAULT_PWD = 4, IMV_WORKITEM_DEFAULT_PWD = 4,
IMV_WORKITEM_FILE_REF_MEAS = 5, IMV_WORKITEM_FILE_REF_MEAS = 5,
IMV_WORKITEM_FILE_MEAS = 6, IMV_WORKITEM_FILE_MEAS = 6,
IMV_WORKITEM_DIR_REF_MEAS = 7, IMV_WORKITEM_FILE_META = 7,
IMV_WORKITEM_DIR_MEAS = 8, IMV_WORKITEM_DIR_REF_MEAS = 8,
IMV_WORKITEM_TCP_SCAN = 9, IMV_WORKITEM_DIR_MEAS = 9,
IMV_WORKITEM_UDP_SCAN = 10 IMV_WORKITEM_DIR_META = 10,
IMV_WORKITEM_TCP_SCAN = 11,
IMV_WORKITEM_UDP_SCAN = 12
}; };
extern enum_name_t *imv_workitem_type_names; extern enum_name_t *imv_workitem_type_names;
@@ -78,11 +80,18 @@ struct imv_workitem_t {
TNC_IMVID (*get_imv_id)(imv_workitem_t *this); TNC_IMVID (*get_imv_id)(imv_workitem_t *this);
/** /**
* Get argument string * Get string argument
* *
* @return Argument string * @return Argument string
*/ */
char* (*get_argument)(imv_workitem_t *this); char* (*get_arg_str)(imv_workitem_t *this);
/**
* Get integer argument
*
* @return Argument integer
*/
int (*get_arg_int)(imv_workitem_t *this);
/** /**
* Set result string * Set result string
@@ -114,12 +123,13 @@ struct imv_workitem_t {
* *
* @param id Primary workitem key * @param id Primary workitem key
* @param type Workitem type * @param type Workitem type
* @param argument Argument string * @param arg_str String argument
* @param arg_int Integer argument
* @param rec_fail Recommendation with minor/major non-compliance case * @param rec_fail Recommendation with minor/major non-compliance case
* @param rec_noresult Recommendation in don't know/error case * @param rec_noresult Recommendation in don't know/error case
*/ */
imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type, imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
char *argument, char *arg_str, int arg_int,
TNC_IMV_Action_Recommendation rec_fail, TNC_IMV_Action_Recommendation rec_fail,
TNC_IMV_Action_Recommendation rec_noresult); TNC_IMV_Action_Recommendation rec_noresult);
+2 -1
View File
@@ -107,7 +107,8 @@ CREATE TABLE workitems (
session integer NOT NULL REFERENCES sessions(id), session integer NOT NULL REFERENCES sessions(id),
enforcement integer NOT NULL REFERENCES enforcements(id), enforcement integer NOT NULL REFERENCES enforcements(id),
type integer NOT NULL, type integer NOT NULL,
argument text NOT NULL, arg_str text,
arg_int INTEGER DEFAULT 0,
rec_fail integer NOT NULL, rec_fail integer NOT NULL,
rec_noresult integer NOT NULL, rec_noresult integer NOT NULL,
rec_final integer, rec_final integer,
+29 -22
View File
@@ -184,8 +184,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
ietf_attr_product_info_t *attr_cast; ietf_attr_product_info_t *attr_cast;
pen_t vendor_id; pen_t vendor_id;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_PRODUCT_INFORMATION); IMV_OS_ATTR_PRODUCT_INFORMATION);
attr_cast = (ietf_attr_product_info_t*)attr; attr_cast = (ietf_attr_product_info_t*)attr;
os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL); os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
if (vendor_id != PEN_IETF) if (vendor_id != PEN_IETF)
@@ -205,8 +205,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
{ {
ietf_attr_string_version_t *attr_cast; ietf_attr_string_version_t *attr_cast;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_STRING_VERSION); IMV_OS_ATTR_STRING_VERSION);
attr_cast = (ietf_attr_string_version_t*)attr; attr_cast = (ietf_attr_string_version_t*)attr;
os_version = attr_cast->get_version(attr_cast, NULL, NULL); os_version = attr_cast->get_version(attr_cast, NULL, NULL);
if (os_version.len) if (os_version.len)
@@ -221,8 +221,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
ietf_attr_numeric_version_t *attr_cast; ietf_attr_numeric_version_t *attr_cast;
u_int32_t major, minor; u_int32_t major, minor;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_NUMERIC_VERSION); IMV_OS_ATTR_NUMERIC_VERSION);
attr_cast = (ietf_attr_numeric_version_t*)attr; attr_cast = (ietf_attr_numeric_version_t*)attr;
attr_cast->get_version(attr_cast, &major, &minor); attr_cast->get_version(attr_cast, &major, &minor);
DBG1(DBG_IMV, "operating system numeric version is %d.%d", DBG1(DBG_IMV, "operating system numeric version is %d.%d",
@@ -236,8 +236,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
op_result_t op_result; op_result_t op_result;
time_t last_boot; time_t last_boot;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_OPERATIONAL_STATUS); IMV_OS_ATTR_OPERATIONAL_STATUS);
attr_cast = (ietf_attr_op_status_t*)attr; attr_cast = (ietf_attr_op_status_t*)attr;
op_status = attr_cast->get_status(attr_cast); op_status = attr_cast->get_status(attr_cast);
op_result = attr_cast->get_result(attr_cast); op_result = attr_cast->get_result(attr_cast);
@@ -252,8 +252,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
ietf_attr_fwd_enabled_t *attr_cast; ietf_attr_fwd_enabled_t *attr_cast;
os_fwd_status_t fwd_status; os_fwd_status_t fwd_status;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_FORWARDING_ENABLED); IMV_OS_ATTR_FORWARDING_ENABLED);
attr_cast = (ietf_attr_fwd_enabled_t*)attr; attr_cast = (ietf_attr_fwd_enabled_t*)attr;
fwd_status = attr_cast->get_status(attr_cast); fwd_status = attr_cast->get_status(attr_cast);
DBG1(DBG_IMV, "IPv4 forwarding is %N", DBG1(DBG_IMV, "IPv4 forwarding is %N",
@@ -270,7 +270,7 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
ietf_attr_default_pwd_enabled_t *attr_cast; ietf_attr_default_pwd_enabled_t *attr_cast;
bool default_pwd_status; bool default_pwd_status;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED); IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
attr_cast = (ietf_attr_default_pwd_enabled_t*)attr; attr_cast = (ietf_attr_default_pwd_enabled_t*)attr;
default_pwd_status = attr_cast->get_status(attr_cast); default_pwd_status = attr_cast->get_status(attr_cast);
@@ -289,8 +289,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
enumerator_t *e; enumerator_t *e;
status_t status; status_t status;
os_state->set_received(os_state, state->set_action_flags(state,
IMV_OS_ATTR_INSTALLED_PACKAGES); IMV_OS_ATTR_INSTALLED_PACKAGES);
if (!this->db) if (!this->db)
{ {
break; break;
@@ -325,7 +325,7 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
char *name; char *name;
chunk_t value; chunk_t value;
os_state->set_received(os_state, IMV_OS_ATTR_SETTINGS); state->set_action_flags(state, IMV_OS_ATTR_SETTINGS);
attr_cast = (ita_attr_settings_t*)attr; attr_cast = (ita_attr_settings_t*)attr;
e = attr_cast->create_enumerator(attr_cast); e = attr_cast->create_enumerator(attr_cast);
@@ -349,7 +349,7 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
int device_id; int device_id;
chunk_t value; chunk_t value;
os_state->set_received(os_state, IMV_OS_ATTR_DEVICE_ID); state->set_action_flags(state, IMV_OS_ATTR_DEVICE_ID);
value = attr->get_value(attr); value = attr->get_value(attr);
DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr); DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
@@ -464,7 +464,7 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
/** /**
* Build an IETF Attribute Request attribute for missing attributes * Build an IETF Attribute Request attribute for missing attributes
*/ */
static pa_tnc_attr_t* build_attr_request(u_int received) static pa_tnc_attr_t* build_attr_request(u_int32_t received)
{ {
pa_tnc_attr_t *attr; pa_tnc_attr_t *attr;
ietf_attr_attr_request_t *attr_cast; ietf_attr_attr_request_t *attr_cast;
@@ -517,7 +517,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
TNC_Result result = TNC_RESULT_SUCCESS; TNC_Result result = TNC_RESULT_SUCCESS;
bool no_workitems = TRUE; bool no_workitems = TRUE;
enumerator_t *enumerator; enumerator_t *enumerator;
u_int received; u_int32_t received;
if (!this->agent->get_state(this->agent, id, &state)) if (!this->agent->get_state(this->agent, id, &state))
{ {
@@ -525,14 +525,18 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
} }
os_state = (imv_os_state_t*)state; os_state = (imv_os_state_t*)state;
handshake_state = os_state->get_handshake_state(os_state); handshake_state = os_state->get_handshake_state(os_state);
received = os_state->get_received(os_state); received = state->get_action_flags(state);
session = state->get_session(state); session = state->get_session(state);
imv_id = this->agent->get_id(this->agent); imv_id = this->agent->get_id(this->agent);
if (handshake_state == IMV_OS_STATE_END)
{
return TNC_RESULT_SUCCESS;
}
/* create an empty out message - we might need it */ /* create an empty out message - we might need it */
out_msg = imv_msg_create(this->agent, state, id, out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
this->agent->get_id(this->agent), msg_types[0]);
TNC_IMCID_ANY, msg_types[0]);
if (handshake_state == IMV_OS_STATE_INIT) if (handshake_state == IMV_OS_STATE_INIT)
{ {
@@ -627,7 +631,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
if (no_workitems) if (no_workitems)
{ {
DBG2(DBG_IMV, "no workitems generated - no evaluation requested"); DBG2(DBG_IMV, "IMV %d has no workitems - "
"no evaluation requested", imv_id);
state->set_recommendation(state, state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_ALLOW, TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
TNC_IMV_EVALUATION_RESULT_DONT_KNOW); TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
@@ -727,6 +732,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
/* finalized all workitems ? */ /* finalized all workitems ? */
if (session->get_workitem_count(session, imv_id) == 0) if (session->get_workitem_count(session, imv_id) == 0)
{ {
os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
result = out_msg->send_assessment(out_msg); result = out_msg->send_assessment(out_msg);
out_msg->destroy(out_msg); out_msg->destroy(out_msg);
if (result != TNC_RESULT_SUCCESS) if (result != TNC_RESULT_SUCCESS)
+19 -19
View File
@@ -64,6 +64,11 @@ struct private_imv_os_state_t {
*/ */
u_int32_t max_msg_len; u_int32_t max_msg_len;
/**
* Flags set for completed actions
*/
u_int32_t action_flags;
/** /**
* Access Requestor ID Type * Access Requestor ID Type
*/ */
@@ -159,11 +164,6 @@ struct private_imv_os_state_t {
*/ */
int count_ok; int count_ok;
/**
* Flags set for received attributes
*/
u_int received_flags;
/** /**
* OS Settings * OS Settings
*/ */
@@ -337,6 +337,18 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t,
return this->max_msg_len; return this->max_msg_len;
} }
METHOD(imv_state_t, set_action_flags, void,
private_imv_os_state_t *this, u_int32_t flags)
{
this->action_flags |= flags;
}
METHOD(imv_state_t, get_action_flags, u_int32_t,
private_imv_os_state_t *this)
{
return this->action_flags;
}
METHOD(imv_state_t, set_ar_id, void, METHOD(imv_state_t, set_ar_id, void,
private_imv_os_state_t *this, u_int32_t id_type, chunk_t id_value) private_imv_os_state_t *this, u_int32_t id_type, chunk_t id_value)
{ {
@@ -580,18 +592,6 @@ METHOD(imv_os_state_t, get_count, void,
} }
} }
METHOD(imv_os_state_t, set_received, void,
private_imv_os_state_t *this, u_int flags)
{
this->received_flags |= flags;
}
METHOD(imv_os_state_t, get_received, u_int,
private_imv_os_state_t *this)
{
return this->received_flags;
}
METHOD(imv_os_state_t, set_device_id, void, METHOD(imv_os_state_t, set_device_id, void,
private_imv_os_state_t *this, int id) private_imv_os_state_t *this, int id)
{ {
@@ -660,6 +660,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.set_flags = _set_flags, .set_flags = _set_flags,
.set_max_msg_len = _set_max_msg_len, .set_max_msg_len = _set_max_msg_len,
.get_max_msg_len = _get_max_msg_len, .get_max_msg_len = _get_max_msg_len,
.set_action_flags = _set_action_flags,
.get_action_flags = _get_action_flags,
.set_ar_id = _set_ar_id, .set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id, .get_ar_id = _get_ar_id,
.set_session = _set_session, .set_session = _set_session,
@@ -678,8 +680,6 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.get_info = _get_info, .get_info = _get_info,
.set_count = _set_count, .set_count = _set_count,
.get_count = _get_count, .get_count = _get_count,
.set_received = _set_received,
.get_received = _get_received,
.set_device_id = _set_device_id, .set_device_id = _set_device_id,
.get_device_id = _get_device_id, .get_device_id = _get_device_id,
.set_os_settings = _set_os_settings, .set_os_settings = _set_os_settings,
+2 -15
View File
@@ -39,7 +39,8 @@ enum imv_os_handshake_state_t {
IMV_OS_STATE_INIT, IMV_OS_STATE_INIT,
IMV_OS_STATE_ATTR_REQ, IMV_OS_STATE_ATTR_REQ,
IMV_OS_STATE_POLICY_START, IMV_OS_STATE_POLICY_START,
IMV_OS_STATE_WORKITEMS IMV_OS_STATE_WORKITEMS,
IMV_OS_STATE_END
}; };
/** /**
@@ -119,20 +120,6 @@ struct imv_os_state_t {
void (*get_count)(imv_os_state_t *this, int *count, int *count_update, void (*get_count)(imv_os_state_t *this, int *count, int *count_update,
int *count_blacklist, int *count_ok); int *count_blacklist, int *count_ok);
/**
* Set flags for received attributes
*
* @param flags Flags to be set
*/
void (*set_received)(imv_os_state_t *this, u_int flags);
/**
* Get flags set for received attributes
*
* @return Flags set for received attributes
*/
u_int (*get_received)(imv_os_state_t *this);
/** /**
* Set device ID * Set device ID
* *
@@ -34,6 +34,8 @@
#include <pts/pts_creds.h> #include <pts/pts_creds.h>
#include <tcg/tcg_attr.h> #include <tcg/tcg_attr.h>
#include <tcg/tcg_pts_attr_req_file_meas.h>
#include <tcg/tcg_pts_attr_req_file_meta.h>
#include <tncif_pa_subtypes.h> #include <tncif_pa_subtypes.h>
@@ -116,31 +118,6 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
} }
} }
/**
* Build a message to be sent
*/
static TNC_Result send_message(private_imv_attestation_agent_t *this,
imv_state_t *state, imv_msg_t *out_msg)
{
imv_attestation_state_t *attestation_state;
TNC_Result result;
attestation_state = (imv_attestation_state_t*)state;
if (imv_attestation_build(out_msg, attestation_state,
this->supported_algorithms,
this->supported_dh_groups, this->pts_db))
{
result = out_msg->send(out_msg, TRUE);
}
else
{
result = TNC_RESULT_FATAL;
}
return result;
}
/** /**
* Process a received message * Process a received message
*/ */
@@ -197,8 +174,7 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
DBG1(DBG_IMV, "received TCG-PTS error '%N'", DBG1(DBG_IMV, "received TCG-PTS error '%N'",
pts_error_code_names, error_code.type); pts_error_code_names, error_code.type);
DBG1(DBG_IMV, "error information: %B", &msg_info); DBG1(DBG_IMV, "error information: %B", &msg_info);
fatal_error = TRUE;
result = TNC_RESULT_FATAL;
} }
break; break;
} }
@@ -224,7 +200,7 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
} }
else if (type.vendor_id == PEN_TCG) else if (type.vendor_id == PEN_TCG)
{ {
if (!imv_attestation_process(attr, out_msg, attestation_state, if (!imv_attestation_process(attr, out_msg, state,
this->supported_algorithms, this->supported_dh_groups, this->supported_algorithms, this->supported_dh_groups,
this->pts_db, this->pts_credmgr)) this->pts_db, this->pts_credmgr))
{ {
@@ -235,6 +211,10 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
/**
* The IETF Product Information and String Version attributes
* are supposed to arrive in the same PA-TNC message
*/
if (os_name.len && os_version.len) if (os_name.len && os_version.len)
{ {
pts->set_platform_info(pts, os_name, os_version); pts->set_platform_info(pts, os_name, os_version);
@@ -256,64 +236,9 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
/* send PA-TNC message with excl flag set */ /* send PA-TNC message with excl flag set */
result = out_msg->send(out_msg, TRUE); result = out_msg->send(out_msg, TRUE);
if (result != TNC_RESULT_SUCCESS)
{
out_msg->destroy(out_msg);
return result;
}
/* check the IMV state for the next PA-TNC attributes to send */
result = send_message(this, state, out_msg);
if (result != TNC_RESULT_SUCCESS)
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
result = out_msg->send_assessment(out_msg);
out_msg->destroy(out_msg);
if (result != TNC_RESULT_SUCCESS)
{
return result;
}
return this->agent->provide_recommendation(this->agent, state);
}
if (attestation_state->get_handshake_state(attestation_state) ==
IMV_ATTESTATION_STATE_END)
{
if (attestation_state->get_file_meas_request_count(attestation_state))
{
DBG1(DBG_IMV, "failure due to %d pending file measurements",
attestation_state->get_file_meas_request_count(attestation_state));
attestation_state->set_measurement_error(attestation_state,
IMV_ATTESTATION_ERROR_FILE_MEAS_PEND);
}
if (attestation_state->get_measurement_error(attestation_state))
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR);
}
else
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
TNC_IMV_EVALUATION_RESULT_COMPLIANT);
}
result = out_msg->send_assessment(out_msg);
out_msg->destroy(out_msg);
if (result != TNC_RESULT_SUCCESS)
{
return result;
}
return this->agent->provide_recommendation(this->agent, state);
}
out_msg->destroy(out_msg); out_msg->destroy(out_msg);
return result; return result;
} }
METHOD(imv_agent_if_t, receive_message, TNC_Result, METHOD(imv_agent_if_t, receive_message, TNC_Result,
@@ -354,24 +279,224 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
in_msg->destroy(in_msg); in_msg->destroy(in_msg);
return result; return result;
} }
METHOD(imv_agent_if_t, batch_ending, TNC_Result, METHOD(imv_agent_if_t, batch_ending, TNC_Result,
private_imv_attestation_agent_t *this, TNC_ConnectionID id) private_imv_attestation_agent_t *this, TNC_ConnectionID id)
{ {
return TNC_RESULT_SUCCESS; imv_msg_t *out_msg;
imv_state_t *state;
imv_session_t *session;
imv_attestation_state_t *attestation_state;
TNC_IMVID imv_id;
TNC_Result result = TNC_RESULT_SUCCESS;
pts_t *pts;
char *platform_info;
if (!this->agent->get_state(this->agent, id, &state))
{
return TNC_RESULT_FATAL;
}
attestation_state = (imv_attestation_state_t*)state;
pts = attestation_state->get_pts(attestation_state);
platform_info = pts->get_platform_info(pts);
session = state->get_session(state);
imv_id = this->agent->get_id(this->agent);
/* create an empty out message - we might need it */
out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
msg_types[0]);
if (platform_info && session &&
(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ALGO) &&
!(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_FILE_MEAS))
{
imv_workitem_t *workitem;
bool is_dir, no_workitems = TRUE;
u_int32_t delimiter = SOLIDUS_UTF;
u_int16_t request_id;
pa_tnc_attr_t *attr;
char *pathname;
enumerator_t *enumerator;
enumerator = session->create_workitem_enumerator(session);
if (enumerator)
{
while (enumerator->enumerate(enumerator, &workitem))
{
if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY)
{
continue;
}
switch (workitem->get_type(workitem))
{
case IMV_WORKITEM_FILE_REF_MEAS:
case IMV_WORKITEM_FILE_MEAS:
case IMV_WORKITEM_FILE_META:
is_dir = FALSE;
break;
case IMV_WORKITEM_DIR_REF_MEAS:
case IMV_WORKITEM_DIR_MEAS:
case IMV_WORKITEM_DIR_META:
is_dir = TRUE;
break;
default:
continue;
}
pathname = this->pts_db->get_pathname(this->pts_db, is_dir,
workitem->get_arg_int(workitem));
if (!pathname)
{
continue;
}
workitem->set_imv_id(workitem, imv_id);
no_workitems = FALSE;
if (workitem->get_type(workitem) == IMV_WORKITEM_FILE_META)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
DBG2(DBG_IMV, "IMV %d requests metadata for %s '%s'",
imv_id, is_dir ? "directory" : "file", pathname);
attr = tcg_pts_attr_req_file_meta_create(is_dir,
delimiter, pathname);
/* currently just fire and forget metadata requests */
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
session->remove_workitem(session, enumerator);
rec = workitem->set_result(workitem, "", eval);
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, workitem);
workitem->destroy(workitem);
}
else
{
/* use lower 16 bits of the workitem ID as request ID */
request_id = workitem->get_id(workitem) & 0xffff;
DBG2(DBG_IMV, "IMV %d requests measurement %d for %s '%s'",
imv_id, request_id, is_dir ? "directory" : "file",
pathname);
attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
delimiter, pathname);
}
free(pathname);
attr->set_noskip_flag(attr, TRUE);
out_msg->add_attribute(out_msg, attr);
}
enumerator->destroy(enumerator);
/* sent all file and directory measurement and metadata requests */
state->set_action_flags(state, IMV_ATTESTATION_FLAG_FILE_MEAS);
if (no_workitems)
{
DBG2(DBG_IMV, "IMV %d has no workitems - "
"no evaluation requested", imv_id);
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
}
}
}
/* check the IMV state for the next PA-TNC attributes to send */
if (!imv_attestation_build(out_msg, attestation_state,
this->supported_algorithms,
this->supported_dh_groups, this->pts_db))
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
result = out_msg->send_assessment(out_msg);
out_msg->destroy(out_msg);
if (result != TNC_RESULT_SUCCESS)
{
return result;
}
return this->agent->provide_recommendation(this->agent, state);
}
/* finalized all workitems? */
if (session && session->get_workitem_count(session, imv_id) == 0 &&
attestation_state->get_handshake_state(attestation_state) ==
IMV_ATTESTATION_STATE_END)
{
result = out_msg->send_assessment(out_msg);
out_msg->destroy(out_msg);
if (result != TNC_RESULT_SUCCESS)
{
return result;
}
return this->agent->provide_recommendation(this->agent, state);
}
/* send non-empty PA-TNC message with excl flag not set */
if (out_msg->get_attribute_count(out_msg))
{
result = out_msg->send(out_msg, FALSE);
}
out_msg->destroy(out_msg);
return result;
} }
METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result, METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
private_imv_attestation_agent_t *this, TNC_ConnectionID id) private_imv_attestation_agent_t *this, TNC_ConnectionID id)
{ {
TNC_IMVID imv_id;
imv_state_t *state; imv_state_t *state;
imv_attestation_state_t *attestation_state;
imv_session_t *session;
if (!this->agent->get_state(this->agent, id, &state)) if (!this->agent->get_state(this->agent, id, &state))
{ {
return TNC_RESULT_FATAL; return TNC_RESULT_FATAL;
} }
attestation_state = (imv_attestation_state_t*)state;
session = state->get_session(state);
imv_id = this->agent->get_id(this->agent);
if (session)
{
imv_workitem_t *workitem;
enumerator_t *enumerator;
int pending_file_meas = 0;
enumerator = session->create_workitem_enumerator(session);
if (enumerator)
{
while (enumerator->enumerate(enumerator, &workitem))
{
if (workitem->get_imv_id(workitem) != imv_id)
{
continue;
}
switch (workitem->get_type(workitem))
{
case IMV_WORKITEM_FILE_REF_MEAS:
case IMV_WORKITEM_FILE_MEAS:
case IMV_WORKITEM_DIR_REF_MEAS:
case IMV_WORKITEM_DIR_MEAS:
pending_file_meas++;
break;
default:
break;
}
}
enumerator->destroy(enumerator);
if (pending_file_meas)
{
DBG1(DBG_IMV, "failure due to %d pending file measurements",
pending_file_meas);
attestation_state->set_measurement_error(attestation_state,
IMV_ATTESTATION_ERROR_FILE_MEAS_PEND);
}
}
}
return this->agent->provide_recommendation(this->agent, state); return this->agent->provide_recommendation(this->agent, state);
} }
@@ -406,7 +531,6 @@ imv_agent_if_t *imv_attestation_agent_create(const char *name, TNC_IMVID id,
"libimcv.plugins.imv-attestation.dh_group", "ecp256"); "libimcv.plugins.imv-attestation.dh_group", "ecp256");
cadir = lib->settings->get_str(lib->settings, cadir = lib->settings->get_str(lib->settings,
"libimcv.plugins.imv-attestation.cadir", NULL); "libimcv.plugins.imv-attestation.cadir", NULL);
libpts_init();
INIT(this, INIT(this,
.public = { .public = {
@@ -427,6 +551,8 @@ imv_agent_if_t *imv_attestation_agent_create(const char *name, TNC_IMVID id,
.pts_db = pts_database_create(imcv_db), .pts_db = pts_database_create(imcv_db),
); );
libpts_init();
if (!this->agent || if (!this->agent ||
!pts_meas_algo_probe(&this->supported_algorithms) || !pts_meas_algo_probe(&this->supported_algorithms) ||
!pts_dh_group_probe(&this->supported_dh_groups) || !pts_dh_group_probe(&this->supported_dh_groups) ||
@@ -24,8 +24,6 @@
#include <tcg/tcg_pts_attr_get_aik.h> #include <tcg/tcg_pts_attr_get_aik.h>
#include <tcg/tcg_pts_attr_req_func_comp_evid.h> #include <tcg/tcg_pts_attr_req_func_comp_evid.h>
#include <tcg/tcg_pts_attr_gen_attest_evid.h> #include <tcg/tcg_pts_attr_gen_attest_evid.h>
#include <tcg/tcg_pts_attr_req_file_meas.h>
#include <tcg/tcg_pts_attr_req_file_meta.h>
#include <utils/debug.h> #include <utils/debug.h>
@@ -49,8 +47,7 @@ bool imv_attestation_build(imv_msg_t *out_msg,
if (handshake_state == IMV_ATTESTATION_STATE_NONCE_REQ && if (handshake_state == IMV_ATTESTATION_STATE_NONCE_REQ &&
!(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D)) !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D))
{ {
DBG2(DBG_IMV, "PTS-IMC does not support DH Nonce negotiation - " DBG2(DBG_IMV, "PTS-IMC does not support DH Nonce negotiation");
"advancing to TPM Initialization");
handshake_state = IMV_ATTESTATION_STATE_TPM_INIT; handshake_state = IMV_ATTESTATION_STATE_TPM_INIT;
} }
@@ -61,9 +58,8 @@ bool imv_attestation_build(imv_msg_t *out_msg,
if (handshake_state == IMV_ATTESTATION_STATE_TPM_INIT && if (handshake_state == IMV_ATTESTATION_STATE_TPM_INIT &&
!(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T)) !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T))
{ {
DBG2(DBG_IMV, "PTS-IMC made no TPM available - " DBG2(DBG_IMV, "PTS-IMC made no TPM available");
"advancing to File Measurements"); handshake_state = IMV_ATTESTATION_STATE_END;
handshake_state = IMV_ATTESTATION_STATE_MEAS;
} }
switch (handshake_state) switch (handshake_state)
@@ -129,83 +125,9 @@ bool imv_attestation_build(imv_msg_t *out_msg,
attr->set_noskip_flag(attr, TRUE); attr->set_noskip_flag(attr, TRUE);
out_msg->add_attribute(out_msg, attr); out_msg->add_attribute(out_msg, attr);
attestation_state->set_handshake_state(attestation_state,
IMV_ATTESTATION_STATE_MEAS);
break;
}
case IMV_ATTESTATION_STATE_MEAS:
{
enumerator_t *enumerator;
u_int32_t delimiter = SOLIDUS_UTF;
char *platform_info, *pathname;
u_int16_t request_id;
int id, type;
bool is_dir, have_request = FALSE;
attestation_state->set_handshake_state(attestation_state, attestation_state->set_handshake_state(attestation_state,
IMV_ATTESTATION_STATE_COMP_EVID); IMV_ATTESTATION_STATE_COMP_EVID);
break;
/* Get Platform and OS of the PTS-IMC */
platform_info = pts->get_platform_info(pts);
if (!pts_db || !platform_info)
{
DBG1(DBG_IMV, "%s%s%s not available",
(pts_db) ? "" : "pts database",
(!pts_db && !platform_info) ? "and" : "",
(platform_info) ? "" : "platform info");
break;
}
DBG1(DBG_IMV, "platform is '%s'", platform_info);
/* Send Request File Metadata attribute */
enumerator = pts_db->create_file_meta_enumerator(pts_db,
platform_info);
if (!enumerator)
{
break;
}
while (enumerator->enumerate(enumerator, &type, &pathname))
{
is_dir = (type != 0);
DBG2(DBG_IMV, "metadata request for %s '%s'",
is_dir ? "directory" : "file", pathname);
attr = tcg_pts_attr_req_file_meta_create(is_dir, delimiter,
pathname);
attr->set_noskip_flag(attr, TRUE);
out_msg->add_attribute(out_msg, attr);
have_request = TRUE;
}
enumerator->destroy(enumerator);
/* Send Request File Measurement attribute */
enumerator = pts_db->create_file_meas_enumerator(pts_db,
platform_info);
if (!enumerator)
{
break;
}
while (enumerator->enumerate(enumerator, &id, &type, &pathname))
{
is_dir = (type != 0);
request_id = attestation_state->add_file_meas_request(
attestation_state, id, is_dir);
DBG2(DBG_IMV, "measurement request %d for %s '%s'",
request_id, is_dir ? "directory" : "file", pathname);
attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
delimiter, pathname);
attr->set_noskip_flag(attr, TRUE);
out_msg->add_attribute(out_msg, attr);
have_request = TRUE;
}
enumerator->destroy(enumerator);
/* do we have any file metadata or measurement requests? */
if (have_request)
{
break;
}
/* fall through to next state */
} }
case IMV_ATTESTATION_STATE_COMP_EVID: case IMV_ATTESTATION_STATE_COMP_EVID:
{ {
@@ -304,6 +226,8 @@ bool imv_attestation_build(imv_msg_t *out_msg,
} }
break; break;
case IMV_ATTESTATION_STATE_END: case IMV_ATTESTATION_STATE_END:
attestation_state->set_handshake_state(attestation_state,
IMV_ATTESTATION_STATE_END);
break; break;
} }
return TRUE; return TRUE;
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen * Copyright (C) 2011-2013 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil * HSR Hochschule fuer Technik Rapperswil
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -15,6 +15,7 @@
#include "imv_attestation_process.h" #include "imv_attestation_process.h"
#include <imcv.h>
#include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_pa_tnc_error.h>
#include <pts/pts.h> #include <pts/pts.h>
@@ -35,15 +36,17 @@
#include <inttypes.h> #include <inttypes.h>
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
imv_attestation_state_t *attestation_state, imv_state_t *state,
pts_meas_algorithms_t supported_algorithms, pts_meas_algorithms_t supported_algorithms,
pts_dh_group_t supported_dh_groups, pts_dh_group_t supported_dh_groups,
pts_database_t *pts_db, pts_database_t *pts_db,
credential_manager_t *pts_credmgr) credential_manager_t *pts_credmgr)
{ {
imv_attestation_state_t *attestation_state;
pen_type_t attr_type; pen_type_t attr_type;
pts_t *pts; pts_t *pts;
attestation_state = (imv_attestation_state_t*)state;
pts = attestation_state->get_pts(attestation_state); pts = attestation_state->get_pts(attestation_state);
attr_type = attr->get_type(attr); attr_type = attr->get_type(attr);
@@ -73,6 +76,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
return FALSE; return FALSE;
} }
pts->set_meas_algorithm(pts, selected_algorithm); pts->set_meas_algorithm(pts, selected_algorithm);
state->set_action_flags(state, IMV_ATTESTATION_FLAG_ALGO);
break; break;
} }
case TCG_PTS_DH_NONCE_PARAMS_RESP: case TCG_PTS_DH_NONCE_PARAMS_RESP:
@@ -190,28 +194,26 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
} }
case TCG_PTS_FILE_MEAS: case TCG_PTS_FILE_MEAS:
{ {
TNC_IMV_Evaluation_Result eval;
TNC_IMV_Action_Recommendation rec;
tcg_pts_attr_file_meas_t *attr_cast; tcg_pts_attr_file_meas_t *attr_cast;
u_int16_t request_id; u_int16_t request_id;
int file_count, file_id; int arg_int, file_count;
pts_meas_algorithms_t algo; pts_meas_algorithms_t algo;
pts_file_meas_t *measurements; pts_file_meas_t *measurements;
imv_session_t *session;
imv_workitem_t *workitem, *found = NULL;
imv_workitem_type_t type;
char *platform_info; char *platform_info;
enumerator_t *e_hash;
bool is_dir; bool is_dir;
enumerator_t *enumerator;
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
session = state->get_session(state);
algo = pts->get_meas_algorithm(pts);
platform_info = pts->get_platform_info(pts); platform_info = pts->get_platform_info(pts);
if (!pts_db || !platform_info)
{
DBG1(DBG_IMV, "%s%s%s not available",
(pts_db) ? "" : "pts database",
(!pts_db && !platform_info) ? "and" : "",
(platform_info) ? "" : "platform info");
break;
}
attr_cast = (tcg_pts_attr_file_meas_t*)attr; attr_cast = (tcg_pts_attr_file_meas_t*)attr;
measurements = attr_cast->get_measurements(attr_cast); measurements = attr_cast->get_measurements(attr_cast);
algo = pts->get_meas_algorithm(pts);
request_id = measurements->get_request_id(measurements); request_id = measurements->get_request_id(measurements);
file_count = measurements->get_file_count(measurements); file_count = measurements->get_file_count(measurements);
@@ -220,23 +222,94 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
if (request_id) if (request_id)
{ {
if (!attestation_state->check_off_file_meas_request( enumerator = session->create_workitem_enumerator(session);
attestation_state, request_id, &file_id, &is_dir)) while (enumerator->enumerate(enumerator, &workitem))
{
/* request ID consist of lower 16 bits of workitem ID */
if ((workitem->get_id(workitem) & 0xffff) == request_id)
{
found = workitem;
break;
}
}
if (!found)
{ {
DBG1(DBG_IMV, " no entry found for file measurement " DBG1(DBG_IMV, " no entry found for file measurement "
"request %d", request_id); "request %d", request_id);
enumerator->destroy(enumerator);
break; break;
} }
type = found->get_type(found);
/* check hashes from database against measurements */ arg_int = found->get_arg_int(found);
e_hash = pts_db->create_file_hash_enumerator(pts_db,
platform_info, algo, file_id, is_dir); switch (type)
if (!measurements->verify(measurements, e_hash, is_dir))
{ {
attestation_state->set_measurement_error(attestation_state, default:
IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL); case IMV_WORKITEM_FILE_REF_MEAS:
case IMV_WORKITEM_FILE_MEAS:
is_dir = FALSE;
break;
case IMV_WORKITEM_DIR_REF_MEAS:
case IMV_WORKITEM_DIR_MEAS:
is_dir = TRUE;
} }
e_hash->destroy(e_hash);
switch (type)
{
case IMV_WORKITEM_FILE_MEAS:
case IMV_WORKITEM_DIR_MEAS:
{
enumerator_t *e;
/* check hashes from database against measurements */
e = pts_db->create_file_hash_enumerator(pts_db,
platform_info, algo, is_dir, arg_int);
if (!e)
{
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
break;
}
if (!measurements->verify(measurements, e, is_dir))
{
attestation_state->set_measurement_error(
attestation_state,
IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL);
eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
}
e->destroy(e);
break;
}
case IMV_WORKITEM_FILE_REF_MEAS:
case IMV_WORKITEM_DIR_REF_MEAS:
{
enumerator_t *e;
char *filename;
chunk_t measurement;
e = measurements->create_enumerator(measurements);
while (e->enumerate(e, &filename, &measurement))
{
if (pts_db->add_file_measurement(pts_db,
platform_info, algo, measurement, filename,
is_dir, arg_int) != SUCCESS)
{
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
}
}
e->destroy(e);
break;
}
default:
break;
}
session->remove_workitem(session, enumerator);
enumerator->destroy(enumerator);
rec = found->set_result(found, "", eval);
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, found);
found->destroy(found);
} }
else else
{ {
@@ -40,7 +40,7 @@
* *
* @param attr PA-TNC attribute to be processed * @param attr PA-TNC attribute to be processed
* @param out_msg PA-TNC message containing error messages * @param out_msg PA-TNC message containing error messages
* @param attestation_state attestation state of a given connection * @param state state of a given connection
* @param supported_algorithms supported PTS measurement algorithms * @param supported_algorithms supported PTS measurement algorithms
* @param supported_dh_groups supported DH groups * @param supported_dh_groups supported DH groups
* @param pts_db PTS configuration database * @param pts_db PTS configuration database
@@ -48,7 +48,7 @@
* @return TRUE if successful * @return TRUE if successful
*/ */
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
imv_attestation_state_t *attestation_state, imv_state_t *state,
pts_meas_algorithms_t supported_algorithms, pts_meas_algorithms_t supported_algorithms,
pts_dh_group_t supported_dh_groups, pts_dh_group_t supported_dh_groups,
pts_database_t *pts_db, pts_database_t *pts_db,
@@ -65,6 +65,11 @@ struct private_imv_attestation_state_t {
*/ */
u_int32_t max_msg_len; u_int32_t max_msg_len;
/**
* Flags set for completed actions
*/
u_int32_t action_flags;
/** /**
* Access Requestor ID Type * Access Requestor ID Type
*/ */
@@ -95,16 +100,6 @@ struct private_imv_attestation_state_t {
*/ */
TNC_IMV_Evaluation_Result eval; TNC_IMV_Evaluation_Result eval;
/**
* File Measurement Request counter
*/
u_int16_t file_meas_request_counter;
/**
* List of PTS File/Directory Measurement requests
*/
linked_list_t *file_meas_requests;
/** /**
* List of Functional Components * List of Functional Components
*/ */
@@ -127,15 +122,6 @@ struct private_imv_attestation_state_t {
}; };
/**
* PTS File/Directory Measurement request entry
*/
struct file_meas_request_t {
u_int16_t id;
int file_id;
bool is_dir;
};
/** /**
* PTS Functional Component entry * PTS Functional Component entry
*/ */
@@ -233,6 +219,18 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t,
return this->max_msg_len; return this->max_msg_len;
} }
METHOD(imv_state_t, set_action_flags, void,
private_imv_attestation_state_t *this, u_int32_t flags)
{
this->action_flags |= flags;
}
METHOD(imv_state_t, get_action_flags, u_int32_t,
private_imv_attestation_state_t *this)
{
return this->action_flags;
}
METHOD(imv_state_t, set_ar_id, void, METHOD(imv_state_t, set_ar_id, void,
private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value) private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value)
{ {
@@ -345,7 +343,6 @@ METHOD(imv_state_t, destroy, void,
{ {
DESTROY_IF(this->session); DESTROY_IF(this->session);
DESTROY_IF(this->reason_string); DESTROY_IF(this->reason_string);
this->file_meas_requests->destroy_function(this->file_meas_requests, free);
this->components->destroy_function(this->components, (void *)free_func_comp); this->components->destroy_function(this->components, (void *)free_func_comp);
this->pts->destroy(this->pts); this->pts->destroy(this->pts);
free(this->ar_id_value.ptr); free(this->ar_id_value.ptr);
@@ -371,51 +368,6 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*,
return this->pts; return this->pts;
} }
METHOD(imv_attestation_state_t, add_file_meas_request, u_int16_t,
private_imv_attestation_state_t *this, int file_id, bool is_dir)
{
file_meas_request_t *request;
request = malloc_thing(file_meas_request_t);
request->id = ++this->file_meas_request_counter;
request->file_id = file_id;
request->is_dir = is_dir;
this->file_meas_requests->insert_last(this->file_meas_requests, request);
return this->file_meas_request_counter;
}
METHOD(imv_attestation_state_t, check_off_file_meas_request, bool,
private_imv_attestation_state_t *this, u_int16_t id, int *file_id,
bool* is_dir)
{
enumerator_t *enumerator;
file_meas_request_t *request;
bool found = FALSE;
enumerator = this->file_meas_requests->create_enumerator(this->file_meas_requests);
while (enumerator->enumerate(enumerator, &request))
{
if (request->id == id)
{
found = TRUE;
*file_id = request->file_id;
*is_dir = request->is_dir;
this->file_meas_requests->remove_at(this->file_meas_requests, enumerator);
free(request);
break;
}
}
enumerator->destroy(enumerator);
return found;
}
METHOD(imv_attestation_state_t, get_file_meas_request_count, int,
private_imv_attestation_state_t *this)
{
return this->file_meas_requests->get_count(this->file_meas_requests);
}
METHOD(imv_attestation_state_t, create_component, pts_component_t*, METHOD(imv_attestation_state_t, create_component, pts_component_t*,
private_imv_attestation_state_t *this, pts_comp_func_name_t *name, private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
u_int32_t depth, pts_database_t *pts_db) u_int32_t depth, pts_database_t *pts_db)
@@ -536,6 +488,8 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.set_flags = _set_flags, .set_flags = _set_flags,
.set_max_msg_len = _set_max_msg_len, .set_max_msg_len = _set_max_msg_len,
.get_max_msg_len = _get_max_msg_len, .get_max_msg_len = _get_max_msg_len,
.set_action_flags = _set_action_flags,
.get_action_flags = _get_action_flags,
.set_ar_id = _set_ar_id, .set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id, .get_ar_id = _get_ar_id,
.set_session = _set_session, .set_session = _set_session,
@@ -551,9 +505,6 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.get_handshake_state = _get_handshake_state, .get_handshake_state = _get_handshake_state,
.set_handshake_state = _set_handshake_state, .set_handshake_state = _set_handshake_state,
.get_pts = _get_pts, .get_pts = _get_pts,
.add_file_meas_request = _add_file_meas_request,
.check_off_file_meas_request = _check_off_file_meas_request,
.get_file_meas_request_count = _get_file_meas_request_count,
.create_component = _create_component, .create_component = _create_component,
.get_component = _get_component, .get_component = _get_component,
.finalize_components = _finalize_components, .finalize_components = _finalize_components,
@@ -566,7 +517,6 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.handshake_state = IMV_ATTESTATION_STATE_INIT, .handshake_state = IMV_ATTESTATION_STATE_INIT,
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.file_meas_requests = linked_list_create(),
.components = linked_list_create(), .components = linked_list_create(),
.pts = pts_create(FALSE), .pts = pts_create(FALSE),
); );
@@ -31,9 +31,18 @@
#include <library.h> #include <library.h>
typedef struct imv_attestation_state_t imv_attestation_state_t; typedef struct imv_attestation_state_t imv_attestation_state_t;
typedef enum imv_attestation_flag_t imv_attestation_flag_t;
typedef enum imv_attestation_handshake_state_t imv_attestation_handshake_state_t; typedef enum imv_attestation_handshake_state_t imv_attestation_handshake_state_t;
typedef enum imv_meas_error_t imv_meas_error_t; typedef enum imv_meas_error_t imv_meas_error_t;
/**
* IMV Attestation Flags set for completed actions
*/
enum imv_attestation_flag_t {
IMV_ATTESTATION_FLAG_ALGO = (1<<0),
IMV_ATTESTATION_FLAG_FILE_MEAS = (1<<1)
};
/** /**
* IMV Attestation Handshake States (state machine) * IMV Attestation Handshake States (state machine)
*/ */
@@ -41,7 +50,6 @@ enum imv_attestation_handshake_state_t {
IMV_ATTESTATION_STATE_INIT, IMV_ATTESTATION_STATE_INIT,
IMV_ATTESTATION_STATE_NONCE_REQ, IMV_ATTESTATION_STATE_NONCE_REQ,
IMV_ATTESTATION_STATE_TPM_INIT, IMV_ATTESTATION_STATE_TPM_INIT,
IMV_ATTESTATION_STATE_MEAS,
IMV_ATTESTATION_STATE_COMP_EVID, IMV_ATTESTATION_STATE_COMP_EVID,
IMV_ATTESTATION_STATE_EVID_FINAL, IMV_ATTESTATION_STATE_EVID_FINAL,
IMV_ATTESTATION_STATE_END, IMV_ATTESTATION_STATE_END,
@@ -91,34 +99,6 @@ struct imv_attestation_state_t {
*/ */
pts_t* (*get_pts)(imv_attestation_state_t *this); pts_t* (*get_pts)(imv_attestation_state_t *this);
/**
* Add an entry to the list of pending file/directory measurement requests
*
* @param file_id primary key into file table
* @param is_dir TRUE if directory
* @return unique request ID
*/
u_int16_t (*add_file_meas_request)(imv_attestation_state_t *this,
int file_id, bool is_dir);
/**
* Returns the number of pending file/directory measurement requests
*
* @return number of pending requests
*/
int (*get_file_meas_request_count)(imv_attestation_state_t *this);
/**
* Check for presence of request_id and if found remove it from the list
*
* @param id unique request ID
* @param file_id primary key into file table
* @param is_dir return TRUE if request was for a directory
* @return TRUE if request ID found, FALSE otherwise
*/
bool (*check_off_file_meas_request)(imv_attestation_state_t *this,
u_int16_t id, int *file_id, bool *is_dir);
/** /**
* Create and add an entry to the list of Functional Components * Create and add an entry to the list of Functional Components
* *
+158 -38
View File
@@ -13,6 +13,9 @@
* for more details. * for more details.
*/ */
#define _GNU_SOURCE
#include <stdio.h>
#include "pts_database.h" #include "pts_database.h"
#include <utils/debug.h> #include <utils/debug.h>
@@ -39,60 +42,69 @@ struct private_pts_database_t {
}; };
METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*, METHOD(pts_database_t, get_pathname, char*,
private_pts_database_t *this, char *product) private_pts_database_t *this, bool is_dir, int id)
{ {
enumerator_t *e; enumerator_t *e;
char *path, *name, *pathname;
/* look for all entries belonging to a product in the files table */ if (is_dir)
e = this->db->query(this->db, {
"SELECT f.id, f.type, f.path FROM files AS f " e = this->db->query(this->db,
"JOIN product_file AS pf ON f.id = pf.file " "SELECT path FROM directories WHERE id = ?",
"JOIN products AS p ON p.id = pf.product " DB_INT, id, DB_TEXT);
"WHERE p.name = ? AND pf.measurement = 1", if (!e || !e->enumerate(e, &path))
DB_TEXT, product, DB_INT, DB_INT, DB_TEXT); {
return e; pathname = NULL;
} }
else
{
pathname = strdup(path);
}
}
else
{
e = this->db->query(this->db,
"SELECT d.path, f.name FROM files AS f "
"JOIN directories AS d ON d.id = f.dir WHERE f.id = ?",
DB_INT, id, DB_TEXT, DB_TEXT);
if (!e || !e->enumerate(e, &path, &name) ||
asprintf(&pathname, "%s%s%s",
path, streq(path, "/") ? "" : "/", name) == -1)
{
pathname = NULL;
}
}
DESTROY_IF(e);
METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*, return pathname;
private_pts_database_t *this, char *product)
{
enumerator_t *e;
/* look for all entries belonging to a product in the files table */
e = this->db->query(this->db,
"SELECT f.type, f.path FROM files AS f "
"JOIN product_file AS pf ON f.id = pf.file "
"JOIN products AS p ON p.id = pf.product "
"WHERE p.name = ? AND pf.metadata = 1",
DB_TEXT, product, DB_INT, DB_TEXT);
return e;
} }
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*, METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
int id, bool is_dir) bool is_dir, int id)
{ {
enumerator_t *e; enumerator_t *e;
if (is_dir) if (is_dir)
{ {
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT f.path, fh.hash FROM file_hashes AS fh " "SELECT f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON fh.file = f.id " "JOIN files AS f ON f.id = fh.file "
"JOIN products AS p ON fh.product = p.id " "JOIN products AS p ON p.id = fh.product "
"WHERE p.name = ? AND fh.directory = ? AND fh.algo = ? " "JOIN directories as d ON d.id = f.dir "
"ORDER BY f.path", "WHERE p.name = ? AND fh.algo = ? AND d.id = ? "
DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); "ORDER BY f.name",
DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
} }
else else
{ {
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT f.path, fh.hash FROM file_hashes AS fh " "SELECT f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON fh.file = f.id " "JOIN files AS f ON f.id = fh.file "
"JOIN products AS p ON fh.product = p.id " "JOIN products AS p ON p.id = fh.product "
"WHERE p.name = ? AND fh.file = ? AND fh.algo = ?", "WHERE p.name = ? AND fh.algo = ? AND fh.file = ?",
DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
} }
return e; return e;
} }
@@ -121,6 +133,114 @@ METHOD(pts_database_t, check_aik_keyid, status_t,
return SUCCESS; return SUCCESS;
} }
METHOD(pts_database_t, add_file_measurement, status_t,
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
chunk_t measurement, char *filename, bool is_dir, int id)
{
enumerator_t *e;
char *name;
chunk_t hash_value;
int hash_id, fid, pid = 0;
status_t status = SUCCESS;
/* get primary key of product string */
e = this->db->query(this->db,
"SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT);
if (e)
{
e->enumerate(e, &pid);
e->destroy(e);
}
if (pid == 0)
{
return FAILED;
}
if (is_dir)
{
/* does filename entry already exist? */
e = this->db->query(this->db,
"SELECT id FROM files WHERE name = ? AND dir = ?",
DB_TEXT, filename, DB_INT, id);
if (!e)
{
return FAILED;
}
if (!e->enumerate(e, &fid))
{
/* create filename entry */
if (this->db->execute(this->db, &fid,
"INSERT INTO files (name, dir) VALUES (?, ?)",
DB_TEXT, filename, DB_INT, id) != 1)
{
DBG1(DBG_PTS, "could not insert filename into database");
status = FAILED;
}
}
e->destroy(e);
}
else
{
fid = id;
/* verify filename */
e = this->db->query(this->db,
"SELECT name FROM files WHERE id = ?", DB_INT, fid, DB_TEXT);
if (!e)
{
return FAILED;
}
if (!e->enumerate(e, &name) || !streq(name, filename))
{
DBG1(DBG_PTS, "filename of reference measurement does not match");
status = FAILED;
}
e->destroy(e);
}
if (status != SUCCESS)
{
return status;
}
/* does hash measurement value already exist? */
e = this->db->query(this->db,
"SELECT fh.id, fh.hash FROM file_hashes AS fh "
"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
DB_INT, pid, DB_INT, algo, DB_INT, fid, DB_INT, DB_BLOB);
if (!e)
{
return FAILED;
}
if (e->enumerate(e, &hash_id, &hash_value))
{
if (!chunk_equals(measurement, hash_value))
{
/* update hash measurement value */
if (this->db->execute(this->db, &hash_id,
"UPDATE file_hashes SET hash = ? WHERE id = ?",
DB_BLOB, measurement, DB_INT, hash_id) != 1)
{
status = FAILED;
}
}
}
else
{
/* insert hash measurement value */
if (this->db->execute(this->db, &hash_id,
"INSERT INTO file_hashes (file, product, algo, hash) "
"VALUES (?, ?, ?, ?)", DB_INT, fid, DB_INT, pid,
DB_INT, algo, DB_BLOB, measurement) != 1)
{
status = FAILED;
}
}
e->destroy(e);
return status;
}
METHOD(pts_database_t, check_file_measurement, status_t, METHOD(pts_database_t, check_file_measurement, status_t,
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
chunk_t measurement, char *filename) chunk_t measurement, char *filename)
@@ -325,11 +445,11 @@ pts_database_t *pts_database_create(imv_database_t *imv_db)
INIT(this, INIT(this,
.public = { .public = {
.create_file_meas_enumerator = _create_file_meas_enumerator, .get_pathname = _get_pathname,
.create_file_meta_enumerator = _create_file_meta_enumerator,
.create_comp_evid_enumerator = _create_comp_evid_enumerator, .create_comp_evid_enumerator = _create_comp_evid_enumerator,
.create_file_hash_enumerator = _create_file_hash_enumerator, .create_file_hash_enumerator = _create_file_hash_enumerator,
.check_aik_keyid = _check_aik_keyid, .check_aik_keyid = _check_aik_keyid,
.add_file_measurement = _add_file_measurement,
.check_file_measurement = _check_file_measurement, .check_file_measurement = _check_file_measurement,
.check_comp_measurement = _check_comp_measurement, .check_comp_measurement = _check_comp_measurement,
.insert_comp_measurement = _insert_comp_measurement, .insert_comp_measurement = _insert_comp_measurement,
+23 -16
View File
@@ -36,35 +36,26 @@ typedef struct pts_database_t pts_database_t;
struct pts_database_t { struct pts_database_t {
/** /**
* Get files/directories to be measured by PTS * Get absolute pathname for file or directory measurement
* *
* @param product Software product (os, vpn client, etc.) * @param is_dir TRUE if dir, FALSE if file
* @return Enumerator over all matching files/directories * @param id Primary key into directories or files table
* @return Absolute pathname as a text string
*/ */
enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, char* (*get_pathname)(pts_database_t *this, bool is_dir, int id);
char *product);
/**
* Get files/directories to request metadata of
*
* @param product Software product (os, vpn client, etc.)
* @return Enumerator over all matching files/directories
*/
enumerator_t* (*create_file_meta_enumerator)(pts_database_t *this,
char *product);
/** /**
* Get stored measurement hash for single file or directory entries * Get stored measurement hash for single file or directory entries
* *
* @param product Software product (os, vpn client, etc.) * @param product Software product (os, vpn client, etc.)
* @param algo Hash algorithm used for measurement * @param algo Hash algorithm used for measurement
* @param id Primary key of measured file/directory
* @param is_dir TRUE if directory was measured * @param is_dir TRUE if directory was measured
* @param id Primary key of measured file/directory
* @return Enumerator over all matching measurement hashes * @return Enumerator over all matching measurement hashes
*/ */
enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this, enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
char *product, pts_meas_algorithms_t algo, char *product, pts_meas_algorithms_t algo,
int id, bool is_dir); bool is_dir, int id);
/** /**
* Check if an AIK given by its keyid is registered in the database * Check if an AIK given by its keyid is registered in the database
@@ -83,6 +74,22 @@ struct pts_database_t {
*/ */
enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid); enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid);
/**
* Add PTS file measurement reference value
*
* @param product Software product (os, vpn client, etc.)
* @param algo File measurement hash algorithm used
* @param measurement File measurement hash
* @param filename Optional name of the file to be checked
* @param is_dir TRUE if part of directory measurement
* @param id Primary key into direcories/files table
* @return Status
*/
status_t (*add_file_measurement)(pts_database_t *this, char *product,
pts_meas_algorithms_t algo,
chunk_t measurement, char *filename,
bool is_dir, int id);
/** /**
* Check PTS file measurement against reference stored in database * Check PTS file measurement against reference stored in database
* *