diff options
-rw-r--r-- | src/libimcv/Makefile.am | 1 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_attr_request.c | 6 | ||||
-rw-r--r-- | src/libimcv/ita/ita_attr.c | 8 | ||||
-rw-r--r-- | src/libimcv/ita/ita_attr.h | 3 | ||||
-rw-r--r-- | src/libimcv/ita/ita_attr_device_id.c | 144 | ||||
-rw-r--r-- | src/libimcv/ita/ita_attr_device_id.h | 55 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os.c | 93 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os.c | 262 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.c | 56 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.h | 60 |
10 files changed, 519 insertions, 169 deletions
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 50cfbf937..268fff023 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -34,6 +34,7 @@ libimcv_la_SOURCES = \ ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \ ita/ita_attr_settings.h ita/ita_attr_settings.c \ ita/ita_attr_angel.h ita/ita_attr_angel.c \ + ita/ita_attr_device_id.h ita/ita_attr_device_id.c \ os_info/os_info.h os_info/os_info.c \ pa_tnc/pa_tnc_attr.h \ pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \ diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c index 5dc487030..3b4fd26cd 100644 --- a/src/libimcv/ietf/ietf_attr_attr_request.c +++ b/src/libimcv/ietf/ietf_attr_attr_request.c @@ -234,7 +234,11 @@ pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type) .list = linked_list_create(), .ref = 1, ); - add(this, vendor_id, type); + + if (vendor_id != PEN_RESERVED) + { + add(this, vendor_id, type); + } return &this->public.pa_tnc_attribute; } diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c index 590bc9b5a..f3956717d 100644 --- a/src/libimcv/ita/ita_attr.c +++ b/src/libimcv/ita/ita_attr.c @@ -19,15 +19,17 @@ #include "ita/ita_attr_get_settings.h" #include "ita/ita_attr_settings.h" #include "ita/ita_attr_angel.h" +#include "ita/ita_attr_device_id.h" -ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_ECHO, +ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DEVICE_ID, "Command", "Dummy", "Get Settings", "Settings", "Start Angel", "Stop Angel", - "Echo" + "Echo", + "Device ID" ); /** @@ -49,6 +51,8 @@ pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value) return ita_attr_angel_create_from_data(TRUE, value); case ITA_ATTR_STOP_ANGEL: return ita_attr_angel_create_from_data(FALSE, value); + case ITA_ATTR_DEVICE_ID: + return ita_attr_device_id_create_from_data(value); default: return NULL; } diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h index 446fa032a..ac5d8abaa 100644 --- a/src/libimcv/ita/ita_attr.h +++ b/src/libimcv/ita/ita_attr.h @@ -37,7 +37,8 @@ enum ita_attr_t { ITA_ATTR_SETTINGS = 4, ITA_ATTR_START_ANGEL = 5, ITA_ATTR_STOP_ANGEL = 6, - ITA_ATTR_ECHO = 7 + ITA_ATTR_ECHO = 7, + ITA_ATTR_DEVICE_ID = 8 }; /** diff --git a/src/libimcv/ita/ita_attr_device_id.c b/src/libimcv/ita/ita_attr_device_id.c new file mode 100644 index 000000000..36907eb34 --- /dev/null +++ b/src/libimcv/ita/ita_attr_device_id.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ita_attr.h" +#include "ita_attr_device_id.h" + +#include <pen/pen.h> + +#include <utils/debug.h> + +typedef struct private_ita_attr_device_id_t private_ita_attr_device_id_t; + +/** + * Private data of an ita_attr_device_id_t object. + */ +struct private_ita_attr_device_id_t { + + /** + * Public members of ita_attr_device_id_t + */ + ita_attr_device_id_t public; + + /** + * Vendor-specific attribute type + */ + pen_type_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(pa_tnc_attr_t, get_type, pen_type_t, + private_ita_attr_device_id_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ita_attr_device_id_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ita_attr_device_id_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ita_attr_device_id_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ita_attr_device_id_t *this) +{ + return; +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ita_attr_device_id_t *this, u_int32_t *offset) +{ + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, + private_ita_attr_device_id_t *this) +{ + ref_get(&this->ref); + return &this->public.pa_tnc_attribute; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ita_attr_device_id_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->value.ptr); + free(this); + } +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ita_attr_device_id_create_from_data(chunk_t value) +{ + private_ita_attr_device_id_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_type = _get_type, + .get_value = _get_value, + .get_noskip_flag = _get_noskip_flag, + .set_noskip_flag = _set_noskip_flag, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .type = { PEN_ITA, ITA_ATTR_DEVICE_ID }, + .value = chunk_clone(value), + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ita_attr_device_id_create(chunk_t value) +{ + return ita_attr_device_id_create_from_data(value); +} + diff --git a/src/libimcv/ita/ita_attr_device_id.h b/src/libimcv/ita/ita_attr_device_id.h new file mode 100644 index 000000000..558a8e055 --- /dev/null +++ b/src/libimcv/ita/ita_attr_device_id.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup ita_attr_device_id ita_attr_device_id + * @{ @ingroup ita_attr + */ + +#ifndef ITA_ATTR_DEVICE_ID_H_ +#define ITA_ATTR_DEVICE_ID_H_ + +typedef struct ita_attr_device_id_t ita_attr_device_id_t; + +#include "pa_tnc/pa_tnc_attr.h" + +/** + * Class implementing the ITA Device ID PA-TNC attribute. + * + */ +struct ita_attr_device_id_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + +}; + +/** + * Creates an ita_attr_device_id_t object + * + * @param size ITA Device ID attribute value + */ +pa_tnc_attr_t* ita_attr_device_id_create(chunk_t value); + +/** + * Creates an ita_attr_device_id_t object from received data + * + * @param value binary value blob + */ +pa_tnc_attr_t* ita_attr_device_id_create_from_data(chunk_t value); + +#endif /** ITA_ATTR_DEVICE_ID_H_ @}*/ diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index f6e205ce7..98eac2480 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -30,6 +30,7 @@ #include <ita/ita_attr_get_settings.h> #include <ita/ita_attr_settings.h> #include <ita/ita_attr_angel.h> +#include <ita/ita_attr_device_id.h> #include <os_info/os_info.h> #include <tncif_pa_subtypes.h> @@ -213,7 +214,7 @@ static void add_fwd_enabled(imc_msg_t *msg) os_fwd_status_t fwd_status; fwd_status = os->get_fwd_status(os); - DBG1(DBG_IMC, "IPv4 forwarding status: %N", + DBG1(DBG_IMC, "IPv4 forwarding is %N", os_fwd_status_names, fwd_status); attr = ietf_attr_fwd_enabled_create(fwd_status); msg->add_attribute(msg, attr); @@ -226,12 +227,37 @@ static void add_default_pwd_enabled(imc_msg_t *msg) { pa_tnc_attr_t *attr; - DBG1(DBG_IMC, "factory default password: disabled"); + DBG1(DBG_IMC, "factory default password is disabled"); attr = ietf_attr_default_pwd_enabled_create(FALSE); msg->add_attribute(msg, attr); } /** + * Add ITA Device ID attribute to the send queue + */ +static void add_device_id(imc_msg_t *msg) +{ + pa_tnc_attr_t *attr; + chunk_t value; + char *name; + + name = os->get_type(os) == OS_TYPE_ANDROID ? + "android_id" : "/var/lib/dbus/machine-id"; + value = os->get_setting(os, name); + + /* trim trailing newline character */ + if (value.ptr[value.len - 1] == '\n') + { + value.len--; + } + + DBG1(DBG_IMC, "device ID is %.*s", value.len, value.ptr); + attr = ita_attr_device_id_create(value); + msg->add_attribute(msg, attr); + free(value.ptr); +} + +/** * Add an IETF Installed Packages attribute to the send queue */ static void add_installed_packages(imc_state_t *state, imc_msg_t *msg) @@ -365,6 +391,7 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, add_op_status(out_msg); add_fwd_enabled(out_msg); add_default_pwd_enabled(out_msg); + add_device_id(out_msg); /* send PA-TNC message with the excl flag not set */ result = out_msg->send(out_msg, FALSE); @@ -410,35 +437,45 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg) e = attr_cast->create_enumerator(attr_cast); while (e->enumerate(e, &entry)) { - if (entry->vendor_id != PEN_IETF) + if (entry->vendor_id == PEN_IETF) { - continue; + switch (entry->type) + { + case IETF_ATTR_PRODUCT_INFORMATION: + add_product_info(out_msg); + break; + case IETF_ATTR_STRING_VERSION: + add_string_version(out_msg); + break; + case IETF_ATTR_NUMERIC_VERSION: + add_numeric_version(out_msg); + break; + case IETF_ATTR_OPERATIONAL_STATUS: + add_op_status(out_msg); + break; + case IETF_ATTR_FORWARDING_ENABLED: + add_fwd_enabled(out_msg); + break; + case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED: + add_default_pwd_enabled(out_msg); + break; + case IETF_ATTR_INSTALLED_PACKAGES: + add_installed_packages(state, out_msg); + break; + default: + break; + } } - switch (entry->type) + else if (entry->vendor_id == PEN_ITA) { - case IETF_ATTR_PRODUCT_INFORMATION: - add_product_info(out_msg); - break; - case IETF_ATTR_STRING_VERSION: - add_string_version(out_msg); - break; - case IETF_ATTR_NUMERIC_VERSION: - add_numeric_version(out_msg); - break; - case IETF_ATTR_OPERATIONAL_STATUS: - add_op_status(out_msg); - break; - case IETF_ATTR_FORWARDING_ENABLED: - add_fwd_enabled(out_msg); - break; - case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED: - add_default_pwd_enabled(out_msg); - break; - case IETF_ATTR_INSTALLED_PACKAGES: - add_installed_packages(state, out_msg); - break; - default: - break; + switch (entry->type) + { + case ITA_ATTR_DEVICE_ID: + add_device_id(out_msg); + break; + default: + break; + } } } e->destroy(e); diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index 560b8bf11..44b29077f 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -33,6 +33,7 @@ #include <ita/ita_attr_get_settings.h> #include <ita/ita_attr_settings.h> #include <ita/ita_attr_angel.h> +#include <ita/ita_attr_device_id.h> #include <tncif_names.h> #include <tncif_pa_subtypes.h> @@ -53,6 +54,22 @@ static pen_type_t msg_types[] = { static imv_agent_t *imv_os; /** + * Flag set when corresponding attribute has been received + */ +typedef enum imv_os_attr_t imv_os_attr_t; + +enum imv_os_attr_t { + IMV_OS_ATTR_PRODUCT_INFORMATION = (1<<0), + IMV_OS_ATTR_STRING_VERSION = (1<<1), + IMV_OS_ATTR_NUMERIC_VERSION = (1<<2), + IMV_OS_ATTR_OPERATIONAL_STATUS = (1<<3), + IMV_OS_ATTR_FORWARDING_ENABLED = (1<<4), + IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED = (1<<5), + IMV_OS_ATTR_DEVICE_ID = (1<<6), + IMV_OS_ATTR_ALL = (1<<7)-1 +}; + +/** * IMV OS database */ static imv_os_database_t *os_db; @@ -135,8 +152,6 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) chunk_t os_version = chunk_empty; bool fatal_error = FALSE, assessment = FALSE; char non_market_apps_str[] = "install_non_market_apps"; - char android_id_str[] = "android_id"; - char machine_id_str[] = "/var/lib/dbus/machine-id"; os_state = (imv_os_state_t*)state; @@ -164,6 +179,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) ietf_attr_product_info_t *attr_cast; pen_t vendor_id; + os_state->set_received(os_state, + IMV_OS_ATTR_PRODUCT_INFORMATION); attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL); if (vendor_id != PEN_IETF) @@ -183,6 +200,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) { ietf_attr_string_version_t *attr_cast; + os_state->set_received(os_state, + IMV_OS_ATTR_STRING_VERSION); attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); if (os_version.len) @@ -197,6 +216,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) ietf_attr_numeric_version_t *attr_cast; u_int32_t major, minor; + os_state->set_received(os_state, + IMV_OS_ATTR_NUMERIC_VERSION); attr_cast = (ietf_attr_numeric_version_t*)attr; attr_cast->get_version(attr_cast, &major, &minor); DBG1(DBG_IMV, "operating system numeric version is %d.%d", @@ -210,6 +231,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) op_result_t op_result; time_t last_boot; + os_state->set_received(os_state, + IMV_OS_ATTR_OPERATIONAL_STATUS); attr_cast = (ietf_attr_op_status_t*)attr; op_status = attr_cast->get_status(attr_cast); op_result = attr_cast->get_result(attr_cast); @@ -224,9 +247,11 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) ietf_attr_fwd_enabled_t *attr_cast; os_fwd_status_t fwd_status; + os_state->set_received(os_state, + IMV_OS_ATTR_FORWARDING_ENABLED); attr_cast = (ietf_attr_fwd_enabled_t*)attr; fwd_status = attr_cast->get_status(attr_cast); - DBG1(DBG_IMV, "IPv4 forwarding status: %N", + DBG1(DBG_IMV, "IPv4 forwarding is %N", os_fwd_status_names, fwd_status); if (fwd_status == OS_FWD_ENABLED) { @@ -240,9 +265,11 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) ietf_attr_default_pwd_enabled_t *attr_cast; bool default_pwd_status; + os_state->set_received(os_state, + IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED); attr_cast = (ietf_attr_default_pwd_enabled_t*)attr; default_pwd_status = attr_cast->get_status(attr_cast); - DBG1(DBG_IMV, "factory default password: %sabled", + DBG1(DBG_IMV, "factory default password is %sabled", default_pwd_status ? "en":"dis"); if (default_pwd_status) { @@ -257,9 +284,6 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) enumerator_t *e; status_t status; - /* Received at least one Installed Packages attribute */ - os_state->set_package_request(os_state, FALSE); - if (!os_db) { break; @@ -290,9 +314,7 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) case ITA_ATTR_SETTINGS: { ita_attr_settings_t *attr_cast; - imv_database_t *imv_db; enumerator_t *e; - int session_id, device_id; char *name; chunk_t value; @@ -306,27 +328,32 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) os_state->set_os_settings(os_state, OS_SETTINGS_NON_MARKET_APPS); } - else if ((streq(name, android_id_str) || - streq(name, machine_id_str)) && os_db) - { - imv_db = imv_os->get_database(imv_os); - if (imv_db) - { - session_id = state->get_session_id(state); - device_id = imv_db->add_device(imv_db, - session_id, value); - os_state->set_device_id(os_state, device_id); - - /* trigger the policy manager */ - imv_db->policy_script(imv_db, session_id, TRUE); - } - } DBG1(DBG_IMV, "setting '%s'\n %.*s", name, value.len, value.ptr); } e->destroy(e); break; } + case ITA_ATTR_DEVICE_ID: + { + imv_database_t *imv_db; + int session_id, device_id; + chunk_t value; + + os_state->set_received(os_state, + IMV_OS_ATTR_DEVICE_ID); + value = attr->get_value(attr); + DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr); + + imv_db = imv_os->get_database(imv_os); + if (imv_db) + { + session_id = state->get_session_id(state); + device_id = imv_db->add_device(imv_db, session_id, value); + os_state->set_device_id(os_state, device_id); + } + break; + } case ITA_ATTR_START_ANGEL: os_state->set_angel_count(os_state, TRUE); break; @@ -340,10 +367,13 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) } 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) { os_type_t os_type; - ita_attr_get_settings_t *attr_cast; imv_database_t *imv_db; /* set the OS type, name and version */ @@ -356,33 +386,9 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) imv_db->add_product(imv_db, state->get_session_id(state), os_state->get_info(os_state, NULL, NULL, NULL)); } - - /* requesting installed packages */ - os_state->set_package_request(os_state, TRUE); - attr = ietf_attr_attr_request_create(PEN_IETF, - IETF_ATTR_INSTALLED_PACKAGES); - out_msg->add_attribute(out_msg, attr); - - /* requesting Android or Linux settings */ - attr = ita_attr_get_settings_create(); - attr_cast = (ita_attr_get_settings_t*)attr; - - if (os_type == OS_TYPE_ANDROID) - { - attr_cast->add(attr_cast, android_id_str); - attr_cast->add(attr_cast, non_market_apps_str); - } - else - { - attr_cast->add(attr_cast, machine_id_str); - attr_cast->add(attr_cast, "/proc/sys/kernel/tainted"); - } - out_msg->add_attribute(out_msg, attr); } - if (fatal_error || - (os_state->get_attribute_request(os_state) && - os_state->get_info(os_state, NULL, NULL, NULL) == NULL)) + if (fatal_error) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, @@ -392,9 +398,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) /* If all Installed Packages attributes were received, go to assessment */ if (!assessment && - !os_state->get_package_request(os_state) && - !os_state->get_angel_count(os_state) && - os_state->get_info(os_state, NULL, NULL, NULL)) + os_state->get_handshake_state(os_state) == IMV_OS_STATE_POLICY_START && + !os_state->get_angel_count(os_state)) { int count, count_update, count_blacklist, count_ok; u_int os_settings; @@ -532,16 +537,61 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id, } /** + * Build an IETF Attribute Request attribute for missing attributes + */ +static pa_tnc_attr_t* build_attr_request(u_int received) +{ + pa_tnc_attr_t *attr; + ietf_attr_attr_request_t *attr_cast; + + attr = ietf_attr_attr_request_create(PEN_RESERVED, 0); + attr_cast = (ietf_attr_attr_request_t*)attr; + + if (!(received & IMV_OS_ATTR_PRODUCT_INFORMATION) || + !(received & IMV_OS_ATTR_STRING_VERSION)) + { + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION); + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION); + } + if (!(received & IMV_OS_ATTR_NUMERIC_VERSION)) + { + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_NUMERIC_VERSION); + } + if (!(received & IMV_OS_ATTR_OPERATIONAL_STATUS)) + { + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS); + } + if (!(received & IMV_OS_ATTR_FORWARDING_ENABLED)) + { + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED); + } + if (!(received & IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED)) + { + attr_cast->add(attr_cast, PEN_IETF, + IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED); + } + if (!(received & IMV_OS_ATTR_DEVICE_ID)) + { + attr_cast->add(attr_cast, PEN_ITA, ITA_ATTR_DEVICE_ID); + } + + return attr; +} + +/** * see section 3.8.8 of TCG TNC IF-IMV Specification 1.3 */ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id) { + imv_msg_t *out_msg; imv_state_t *state; + imv_database_t *imv_db; imv_os_state_t *os_state; - TNC_IMV_Action_Recommendation rec; - TNC_IMV_Evaluation_Result eval; - TNC_Result result = TNC_RESULT_SUCCESS; + imv_os_handshake_state_t handshake_state; + pa_tnc_attr_t *attr; + TNC_Result result; + u_int received; if (!imv_os) { @@ -554,43 +604,83 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, } os_state = (imv_os_state_t*)state; - state->get_recommendation(state, &rec, &eval); + handshake_state = os_state->get_handshake_state(os_state); + received = os_state->get_received(os_state); - /* - * Don't send an attribute request if an evaluation is available - * or if an attribute request has already been sent - */ - if (eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW || - os_state->get_attribute_request(os_state)) + if (handshake_state == IMV_OS_STATE_INIT) { - return TNC_RESULT_SUCCESS; - } + if (received != IMV_OS_ATTR_ALL) + { + /* send an attribute request for missing attributes */ + out_msg = imv_msg_create(imv_os, state, connection_id, imv_id, + TNC_IMCID_ANY, msg_types[0]); + out_msg->add_attribute(out_msg, build_attr_request(received)); + + /* send PA-TNC message with excl flag not set */ + result = out_msg->send(out_msg, FALSE); + out_msg->destroy(out_msg); - if (os_state->get_info(os_state, NULL, NULL, NULL) == NULL) + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + } + } + if (handshake_state < IMV_OS_STATE_POLICY_START) { - imv_msg_t *out_msg; - pa_tnc_attr_t *attr; - ietf_attr_attr_request_t *attr_cast; - - out_msg = imv_msg_create(imv_os, state, connection_id, imv_id, - TNC_IMCID_ANY, msg_types[0]); - attr = ietf_attr_attr_request_create(PEN_IETF, - IETF_ATTR_PRODUCT_INFORMATION); - attr_cast = (ietf_attr_attr_request_t*)attr; - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION); - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_NUMERIC_VERSION); - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS); - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED); - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED); - out_msg->add_attribute(out_msg, attr); - os_state->set_attribute_request(os_state, TRUE); + if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) && + (received & IMV_OS_ATTR_STRING_VERSION)) && + ((received & IMV_OS_ATTR_DEVICE_ID) || + (handshake_state == IMV_OS_STATE_ATTR_REQ))) + { + imv_db = imv_os->get_database(imv_os); + if (imv_db) + { + /* trigger the policy manager */ + imv_db->policy_script(imv_db, state->get_session_id(state), + TRUE); + } + os_state->set_handshake_state(os_state, IMV_OS_STATE_POLICY_START); - /* send PA-TNC message with excl flag not set */ - result = out_msg->send(out_msg, FALSE); - out_msg->destroy(out_msg); + /* requesting installed packages */ + attr = ietf_attr_attr_request_create(PEN_IETF, + IETF_ATTR_INSTALLED_PACKAGES); + out_msg = imv_msg_create(imv_os, state, connection_id, imv_id, + TNC_IMCID_ANY, msg_types[0]); + out_msg->add_attribute(out_msg, attr); + + /* send PA-TNC message with excl flag set */ + result = out_msg->send(out_msg, TRUE); + out_msg->destroy(out_msg); + + return result; + } + if (handshake_state == IMV_OS_STATE_ATTR_REQ) + { + /** + * Both the IETF Product Information and IETF String Version + * attribute should have been present + */ + state->set_recommendation(state, + TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, + TNC_IMV_EVALUATION_RESULT_ERROR); + + /* send assessment */ + out_msg = imv_msg_create(imv_os, state, connection_id, imv_id, + TNC_IMCID_ANY, msg_types[0]); + result = out_msg->send_assessment(out_msg); + out_msg->destroy(out_msg); + + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + return imv_os->provide_recommendation(imv_os, state); + } + os_state->set_handshake_state(os_state, IMV_OS_STATE_ATTR_REQ); } - return result; + return TNC_RESULT_SUCCESS; } /** diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index e9661ec88..ff6bc12fa 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -87,6 +87,11 @@ struct private_imv_os_state_t { TNC_IMV_Evaluation_Result eval; /** + * IMV OS handshake state + */ + imv_os_handshake_state_t handshake_state; + + /** * OS Product Information (concatenation of OS Name and Version) */ char *info; @@ -152,14 +157,9 @@ struct private_imv_os_state_t { int count_ok; /** - * Attribute request sent - mandatory response expected - */ - bool attribute_request; - - /** - * OS Installed Package request sent - mandatory response expected + * Flags set for received attributes */ - bool package_request; + u_int received_flags; /** * OS Settings @@ -490,6 +490,18 @@ METHOD(imv_state_t, destroy, void, free(this); } +METHOD(imv_os_state_t, set_handshake_state, void, + private_imv_os_state_t *this, imv_os_handshake_state_t new_state) +{ + this->handshake_state = new_state; +} + +METHOD(imv_os_state_t, get_handshake_state, imv_os_handshake_state_t, + private_imv_os_state_t *this) +{ + return this->handshake_state; +} + METHOD(imv_os_state_t, set_info, void, private_imv_os_state_t *this, os_type_t type, chunk_t name, chunk_t version) { @@ -556,28 +568,16 @@ METHOD(imv_os_state_t, get_count, void, } } -METHOD(imv_os_state_t, set_attribute_request, void, - private_imv_os_state_t *this, bool set) -{ - this->attribute_request = set; -} - -METHOD(imv_os_state_t, get_attribute_request, bool, - private_imv_os_state_t *this) -{ - return this->attribute_request; -} - -METHOD(imv_os_state_t, set_package_request, void, - private_imv_os_state_t *this, bool set) +METHOD(imv_os_state_t, set_received, void, + private_imv_os_state_t *this, u_int flags) { - this->package_request = set; + this->received_flags |= flags; } -METHOD(imv_os_state_t, get_package_request, bool, +METHOD(imv_os_state_t, get_received, u_int, private_imv_os_state_t *this) { - return this->package_request; + return this->received_flags; } METHOD(imv_os_state_t, set_device_id, void, @@ -659,14 +659,14 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .get_remediation_instructions = _get_remediation_instructions, .destroy = _destroy, }, + .set_handshake_state = _set_handshake_state, + .get_handshake_state = _get_handshake_state, .set_info = _set_info, .get_info = _get_info, .set_count = _set_count, .get_count = _get_count, - .set_attribute_request = _set_attribute_request, - .get_attribute_request = _get_attribute_request, - .set_package_request = _set_package_request, - .get_package_request = _get_package_request, + .set_received = _set_received, + .get_received = _get_received, .set_device_id = _set_device_id, .get_device_id = _get_device_id, .set_os_settings = _set_os_settings, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 1c2adeaf9..038acb67a 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -29,12 +29,25 @@ #include <library.h> typedef struct imv_os_state_t imv_os_state_t; +typedef enum imv_os_handshake_state_t imv_os_handshake_state_t; typedef enum os_settings_t os_settings_t; +/** + * IMV OS Handshake States (state machine) + */ +enum imv_os_handshake_state_t { + IMV_OS_STATE_INIT, + IMV_OS_STATE_ATTR_REQ, + IMV_OS_STATE_POLICY_START +}; + +/** + * Flags for detected OS Settings + */ enum os_settings_t { - OS_SETTINGS_FWD_ENABLED = 1, - OS_SETTINGS_DEFAULT_PWD_ENABLED = 2, - OS_SETTINGS_NON_MARKET_APPS = 4 + OS_SETTINGS_FWD_ENABLED = (1<<0), + OS_SETTINGS_DEFAULT_PWD_ENABLED = (1<<1), + OS_SETTINGS_NON_MARKET_APPS = (1<<2) }; /** @@ -48,6 +61,21 @@ struct imv_os_state_t { imv_state_t interface; /** + * Set state of the handshake + * + * @param new_state the handshake state of IMV + */ + void (*set_handshake_state)(imv_os_state_t *this, + imv_os_handshake_state_t new_state); + + /** + * Get state of the handshake + * + * @return the handshake state of IMV + */ + imv_os_handshake_state_t (*get_handshake_state)(imv_os_state_t *this); + + /** * Set OS Product Information * * @param type OS type (enumerated) @@ -91,32 +119,18 @@ struct imv_os_state_t { int *count_blacklist, int *count_ok); /** - * Set/reset attribute request status - * - * @param set TRUE to set, FALSE to clear - */ - void (*set_attribute_request)(imv_os_state_t *this, bool set); - - /** - * Get attribute request status - * - * @return TRUE if set, FALSE if unset - */ - bool (*get_attribute_request)(imv_os_state_t *this); - - /** - * Set/reset OS Installed Packages request status + * Set flags for received attributes * - * @param set TRUE to set, FALSE to clear + * @param flags Flags to be set */ - void (*set_package_request)(imv_os_state_t *this, bool set); + void (*set_received)(imv_os_state_t *this, u_int flags); /** - * Get OS Installed Packages request status + * Get flags set for received attributes * - * @return TRUE if set, FALSE if unset + * @return Flags set for received attributes */ - bool (*get_package_request)(imv_os_state_t *this); + u_int (*get_received)(imv_os_state_t *this); /** * Set device ID |