Beispiel #1
0
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;
 }
Beispiel #2
0
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;
}