static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) { imv_msg_t *out_msg; imv_os_state_t *os_state; enumerator_t *enumerator; pa_tnc_attr_t *attr; pen_type_t type; TNC_Result result; chunk_t os_name = chunk_empty; 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; /* parse received PA-TNC message and handle local and remote errors */ result = in_msg->receive(in_msg, &fatal_error); if (result != TNC_RESULT_SUCCESS) { return result; } out_msg = imv_msg_create_as_reply(in_msg); /* analyze PA-TNC attributes */ enumerator = in_msg->create_attribute_enumerator(in_msg); while (enumerator->enumerate(enumerator, &attr)) { type = attr->get_type(attr); if (type.vendor_id == PEN_IETF) { switch (type.type) { case IETF_ATTR_PRODUCT_INFORMATION: { ietf_attr_product_info_t *attr_cast; pen_t vendor_id; attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL); if (vendor_id != PEN_IETF) { DBG1(DBG_IMV, "operating system name is '%.*s' " "from vendor %N", os_name.len, os_name.ptr, pen_names, vendor_id); } else { DBG1(DBG_IMV, "operating system name is '%.*s'", os_name.len, os_name.ptr); } break; } case IETF_ATTR_STRING_VERSION: { ietf_attr_string_version_t *attr_cast; attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); if (os_version.len) { DBG1(DBG_IMV, "operating system version is '%.*s'", os_version.len, os_version.ptr); } break; } case IETF_ATTR_NUMERIC_VERSION: { ietf_attr_numeric_version_t *attr_cast; u_int32_t major, minor; 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", major, minor); break; } case IETF_ATTR_OPERATIONAL_STATUS: { ietf_attr_op_status_t *attr_cast; op_status_t op_status; op_result_t op_result; time_t last_boot; attr_cast = (ietf_attr_op_status_t*)attr; op_status = attr_cast->get_status(attr_cast); op_result = attr_cast->get_result(attr_cast); last_boot = attr_cast->get_last_use(attr_cast); DBG1(DBG_IMV, "operational status: %N, result: %N", op_status_names, op_status, op_result_names, op_result); DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE); break; } case IETF_ATTR_FORWARDING_ENABLED: { ietf_attr_fwd_enabled_t *attr_cast; os_fwd_status_t fwd_status; attr_cast = (ietf_attr_fwd_enabled_t*)attr; fwd_status = attr_cast->get_status(attr_cast); DBG1(DBG_IMV, "IPv4 forwarding status: %N", os_fwd_status_names, fwd_status); if (fwd_status == OS_FWD_ENABLED) { os_state->set_os_settings(os_state, OS_SETTINGS_FWD_ENABLED); } break; } case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED: { ietf_attr_default_pwd_enabled_t *attr_cast; bool default_pwd_status; 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", default_pwd_status ? "en":"dis"); if (default_pwd_status) { os_state->set_os_settings(os_state, OS_SETTINGS_DEFAULT_PWD_ENABLED); } break; } case IETF_ATTR_INSTALLED_PACKAGES: { ietf_attr_installed_packages_t *attr_cast; 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; } attr_cast = (ietf_attr_installed_packages_t*)attr; e = attr_cast->create_enumerator(attr_cast); status = os_db->check_packages(os_db, os_state, e); e->destroy(e); if (status == FAILED) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); assessment = TRUE; } break; } default: break; } } else if (type.vendor_id == PEN_ITA) { switch (type.type) { case ITA_ATTR_SETTINGS: { ita_attr_settings_t *attr_cast; enumerator_t *e; char *name; chunk_t value; attr_cast = (ita_attr_settings_t*)attr; e = attr_cast->create_enumerator(attr_cast); while (e->enumerate(e, &name, &value)) { if (streq(name, non_market_apps_str) && chunk_equals(value, chunk_from_chars('1'))) { 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) { os_state->set_device_id(os_state, os_db->get_device_id(os_db, value)); } DBG1(DBG_IMV, "setting '%s'\n %.*s", name, value.len, value.ptr); } e->destroy(e); break; } case ITA_ATTR_START_ANGEL: os_state->set_angel_count(os_state, TRUE); break; case ITA_ATTR_STOP_ANGEL: os_state->set_angel_count(os_state, FALSE); break; default: break; } } } enumerator->destroy(enumerator); if (os_name.len && os_version.len) { os_type_t os_type; ita_attr_get_settings_t *attr_cast; /* set the OS type, name and version */ os_type = os_type_from_name(os_name); os_state->set_info(os_state,os_type, os_name, os_version); /* 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)) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); assessment = TRUE; } /* 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)) { int device_id, count, count_update, count_blacklist, count_ok; u_int os_settings; os_settings = os_state->get_os_settings(os_state); os_state->get_count(os_state, &count, &count_update, &count_blacklist, &count_ok); DBG1(DBG_IMV, "processed %d packages: %d not updated, %d blacklisted, " "%d ok, %d not found", count, count_update, count_blacklist, count_ok, count - count_update - count_blacklist - count_ok); /* Store device information in database */ device_id = os_state->get_device_id(os_state); if (os_db && device_id) { os_db->set_device_info(os_db, device_id, os_state->get_info(os_state, NULL, NULL, NULL), count, count_update, count_blacklist, os_settings); } if (count_update || count_blacklist || os_settings) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR); } else { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_ALLOW, TNC_IMV_EVALUATION_RESULT_COMPLIANT); } assessment = TRUE; } if (assessment) { 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); } /* send PA-TNC message with excl flag set */ result = out_msg->send(out_msg, TRUE); out_msg->destroy(out_msg); return result; }
static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) { imv_attestation_state_t *attestation_state; imv_msg_t *out_msg; enumerator_t *enumerator; pa_tnc_attr_t *attr; pen_type_t type; TNC_Result result; pts_t *pts; chunk_t os_name = chunk_empty; chunk_t os_version = chunk_empty; bool fatal_error = FALSE; /* parse received PA-TNC message and handle local and remote errors */ result = in_msg->receive(in_msg, &fatal_error); if (result != TNC_RESULT_SUCCESS) { return result; } attestation_state = (imv_attestation_state_t*)state; pts = attestation_state->get_pts(attestation_state); out_msg = imv_msg_create_as_reply(in_msg); out_msg->set_msg_type(out_msg, msg_types[0]); /* analyze PA-TNC attributes */ enumerator = in_msg->create_attribute_enumerator(in_msg); while (enumerator->enumerate(enumerator, &attr)) { type = attr->get_type(attr); if (type.vendor_id == PEN_IETF) { switch (type.type) { case IETF_ATTR_PA_TNC_ERROR: { ietf_attr_pa_tnc_error_t *error_attr; pen_type_t error_code; chunk_t msg_info; error_attr = (ietf_attr_pa_tnc_error_t*)attr; error_code = error_attr->get_error_code(error_attr); if (error_code.vendor_id == PEN_TCG) { msg_info = error_attr->get_msg_info(error_attr); DBG1(DBG_IMV, "received TCG-PTS error '%N'", pts_error_code_names, error_code.type); DBG1(DBG_IMV, "error information: %B", &msg_info); result = TNC_RESULT_FATAL; } break; } case IETF_ATTR_PRODUCT_INFORMATION: { ietf_attr_product_info_t *attr_cast; attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, NULL, NULL); break; } case IETF_ATTR_STRING_VERSION: { ietf_attr_string_version_t *attr_cast; attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); break; } default: break; } } else if (type.vendor_id == PEN_TCG) { if (!imv_attestation_process(attr, out_msg, attestation_state, supported_algorithms,supported_dh_groups, pts_db, pts_credmgr)) { result = TNC_RESULT_FATAL; break; } } } enumerator->destroy(enumerator); if (os_name.len && os_version.len) { pts->set_platform_info(pts, os_name, os_version); } if (fatal_error || result != TNC_RESULT_SUCCESS) { out_msg->delete_attributes(out_msg); state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, 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 imv_attestation->provide_recommendation(imv_attestation, state); } /* send PA-TNC message with excl flag set */ 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(state, out_msg); if (result != TNC_RESULT_SUCCESS) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); out_msg->delete_attributes(out_msg); result = out_msg->send_assessment(out_msg); if (result != TNC_RESULT_SUCCESS) { return result; } return imv_attestation->provide_recommendation(imv_attestation, 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 imv_attestation->provide_recommendation(imv_attestation, state); } out_msg->destroy(out_msg); return result; }