Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

574 validate token #796

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions include/ocpp/common/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ namespace ocpp {
/// \brief Case insensitive compare for a case insensitive (Ci)String
bool iequals(const std::string& lhs, const std::string rhs);

std::vector<std::string> get_vector_from_csv(const std::string& csv_str);

bool is_integer(const std::string& value);
std::tuple<bool, int> is_positive_integer(const std::string& value);
bool is_decimal_number(const std::string& value);
Expand Down
10 changes: 0 additions & 10 deletions lib/ocpp/common/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ bool iequals(const std::string& lhs, const std::string rhs) {
return boost::algorithm::iequals(lhs, rhs);
}

std::vector<std::string> get_vector_from_csv(const std::string& csv_str) {
std::vector<std::string> csv;
std::string str;
std::stringstream ss(csv_str);
while (std::getline(ss, str, ',')) {
csv.push_back(str);
}
return csv;
}

bool is_integer(const std::string& value) {
if (value.empty()) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion lib/ocpp/v16/charge_point_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ std::string to_csl(const std::vector<std::string>& vec) {
}

void ChargePointConfiguration::init_supported_measurands() {
const auto _supported_measurands = ocpp::get_vector_from_csv(this->config["Internal"]["SupportedMeasurands"]);
const auto _supported_measurands = ocpp::split_string(this->config["Internal"]["SupportedMeasurands"], ',');
for (const auto& measurand : _supported_measurands) {
try {
const auto _measurand = conversions::string_to_measurand(measurand);
Expand Down
2 changes: 1 addition & 1 deletion lib/ocpp/v16/charge_point_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4165,7 +4165,7 @@ void ChargePointImpl::stop_transaction(int32_t connector, Reason reason, std::op

std::vector<Measurand> ChargePointImpl::get_measurands_vec(const std::string& measurands_csv) {
std::vector<Measurand> measurands;
std::vector<std::string> measurands_strings = ocpp::get_vector_from_csv(measurands_csv);
std::vector<std::string> measurands_strings = ocpp::split_string(measurands_csv, ',');

for (const auto& measurand_string : measurands_strings) {
try {
Expand Down
46 changes: 28 additions & 18 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,13 +687,22 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:

AuthorizeResponse response;

bool is_online = this->connectivity_manager->is_websocket_connected();
bool local_authorize_offline =
this->device_model->get_optional_value<bool>(ControllerComponentVariables::LocalAuthorizeOffline)
.value_or(true);

// C03.FR.01 && C05.FR.01: We SHALL NOT send an authorize reqeust for IdTokenType Central
if (id_token.type == IdTokenEnum::Central or
!this->device_model->get_optional_value<bool>(ControllerComponentVariables::AuthCtrlrEnabled).value_or(true)) {
response.idTokenInfo.status = AuthorizationStatusEnum::Accepted;
return response;
}

bool disabled_remote_auth =
this->device_model->get_optional_value<bool>(ControllerComponentVariables::DisableRemoteAuthorization)
.value_or(false);

// C07: Authorization using contract certificates
if (id_token.type == IdTokenEnum::eMAID) {
// Temporary variable that is set to true to avoid immediate response to allow the local auth list
Expand All @@ -702,7 +711,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
bool forwarded_to_csms = false;

// If OCSP data is provided as argument, use it
if (this->connectivity_manager->is_websocket_connected() and ocsp_request_data.has_value()) {
if (is_online and ocsp_request_data.has_value() and !disabled_remote_auth) {
EVLOG_info << "Online: Pass provided OCSP data to CSMS";
response = this->authorize_req(id_token, std::nullopt, ocsp_request_data);
forwarded_to_csms = true;
Expand All @@ -719,14 +728,11 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
bool contract_validation_offline =
this->device_model->get_optional_value<bool>(ControllerComponentVariables::ContractValidationOffline)
.value_or(true);
bool local_authorize_offline =
this->device_model->get_optional_value<bool>(ControllerComponentVariables::LocalAuthorizeOffline)
.value_or(true);

// C07.FR.01: When CS is online, it shall send an AuthorizeRequest
// C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data
// TODO: local validation results are ignored if response is based only on OCSP data, is that acceptable?
if (this->connectivity_manager->is_websocket_connected()) {
if (is_online and !disabled_remote_auth) {
// If no OCSP data was provided, check for a contract root
if (local_verify_result == CertificateValidationResult::IssuerNotFound) {
// C07.FR.06: Pass contract validation to CSMS when no contract root is found
Expand Down Expand Up @@ -808,8 +814,12 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
}
}

if (this->device_model->get_optional_value<bool>(ControllerComponentVariables::LocalAuthListCtrlrEnabled)
.value_or(false)) {
bool local_pre_authorize = this->device_model->get_value<bool>(ControllerComponentVariables::LocalPreAuthorize);
bool local_auth_list_enabled =
this->device_model->get_optional_value<bool>(ControllerComponentVariables::LocalAuthListCtrlrEnabled)
.value_or(false);

if (local_auth_list_enabled and ((is_online and local_pre_authorize) or (!is_online and local_authorize_offline))) {
std::optional<IdTokenInfo> id_token_info = std::nullopt;
try {
id_token_info = this->database_handler->get_local_authorization_list_entry(id_token);
Expand All @@ -820,7 +830,9 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
}

if (id_token_info.has_value()) {
if (id_token_info.value().status == AuthorizationStatusEnum::Accepted) {
if ((is_online and id_token_info.value().status == AuthorizationStatusEnum::Accepted) or
(!is_online and local_authorize_offline and
id_token_info.value().status == AuthorizationStatusEnum::Accepted)) {
// C14.FR.02: If found in local list we shall start charging without an AuthorizeRequest
EVLOG_info << "Found valid entry in local authorization list";
response.idTokenInfo = id_token_info.value();
Expand All @@ -830,7 +842,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
EVLOG_info << "Found invalid entry in local authorization list but not sending Authorize.req because "
"RemoteAuthorization is disabled";
response.idTokenInfo.status = AuthorizationStatusEnum::Unknown;
} else if (this->connectivity_manager->is_websocket_connected()) {
} else if (is_online) {
// C14.FR.03: If a value found but not valid we shall send an authorize request
EVLOG_info << "Found invalid entry in local authorization list: Sending Authorize.req";
response = this->authorize_req(id_token, certificate, ocsp_request_data);
Expand All @@ -848,7 +860,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
this->device_model->get_optional_value<bool>(ControllerComponentVariables::AuthCacheCtrlrEnabled)
.value_or(false);

if (auth_cache_enabled) {
if (auth_cache_enabled and ((is_online and local_pre_authorize) or (!is_online and local_authorize_offline))) {
try {
const auto cache_entry = this->database_handler->authorization_cache_get_entry(hashed_id_token);
if (cache_entry.has_value()) {
Expand All @@ -869,8 +881,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
<< ": Removing from cache and sending new request";
this->database_handler->authorization_cache_delete_entry(hashed_id_token);
this->update_authorization_cache_size();
} else if (this->device_model->get_value<bool>(ControllerComponentVariables::LocalPreAuthorize) and
id_token_info.status == AuthorizationStatusEnum::Accepted) {
} else if (cache_entry.value().status == AuthorizationStatusEnum::Accepted) {
EVLOG_info << "Found valid entry in AuthCache";
this->database_handler->authorization_cache_update_last_used(hashed_id_token);
response.idTokenInfo = id_token_info;
Expand All @@ -895,7 +906,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:
}
}

if (!this->connectivity_manager->is_websocket_connected() and
if (!is_online and
this->device_model->get_optional_value<bool>(ControllerComponentVariables::OfflineTxForUnknownIdEnabled)
.value_or(false)) {
EVLOG_info << "Offline authorization due to OfflineTxForUnknownIdEnabled being enabled";
Expand All @@ -905,8 +916,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std:

// When set to true this instructs the Charging Station to not issue any AuthorizationRequests, but only use
// Authorization Cache and Local Authorization List to determine validity of idTokens.
if (!this->device_model->get_optional_value<bool>(ControllerComponentVariables::DisableRemoteAuthorization)
.value_or(false)) {
if (disabled_remote_auth) {
response = this->authorize_req(id_token, certificate, ocsp_request_data);

if (auth_cache_enabled) {
Expand Down Expand Up @@ -1090,8 +1100,8 @@ void ChargePoint::remove_network_connection_profiles_below_actual_security_profi
VARIABLE_ATTRIBUTE_VALUE_SOURCE_INTERNAL);

// Update the NetworkConfigurationPriority so only remaining profiles are in there
const auto network_priority = ocpp::get_vector_from_csv(
this->device_model->get_value<std::string>(ControllerComponentVariables::NetworkConfigurationPriority));
const auto network_priority = ocpp::split_string(
this->device_model->get_value<std::string>(ControllerComponentVariables::NetworkConfigurationPriority), ',');

auto in_network_profiles = [&network_connection_profiles](const std::string& item) {
auto is_same_slot = [&item](const SetNetworkProfileRequest& profile) {
Expand Down Expand Up @@ -1691,7 +1701,7 @@ void ChargePoint::handle_variables_changed(const std::map<SetVariableData, SetVa
bool ChargePoint::validate_set_variable(const SetVariableData& set_variable_data) {
ComponentVariable cv = {set_variable_data.component, std::nullopt, set_variable_data.variable};
if (cv == ControllerComponentVariables::NetworkConfigurationPriority) {
const auto network_configuration_priorities = ocpp::get_vector_from_csv(set_variable_data.attributeValue.get());
const auto network_configuration_priorities = ocpp::split_string(set_variable_data.attributeValue.get(), ',');
const auto active_security_profile =
this->device_model->get_value<int>(ControllerComponentVariables::SecurityProfile);
for (const auto configuration_slot : network_configuration_priorities) {
Expand Down
4 changes: 2 additions & 2 deletions lib/ocpp/v201/connectivity_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ void ConnectivityManager::cache_network_connection_profiles() {
this->network_connection_profiles =
json::parse(this->device_model.get_value<std::string>(ControllerComponentVariables::NetworkConnectionProfiles));

this->network_connection_priorities = ocpp::get_vector_from_csv(
this->device_model.get_value<std::string>(ControllerComponentVariables::NetworkConfigurationPriority));
this->network_connection_priorities = ocpp::split_string(
this->device_model.get_value<std::string>(ControllerComponentVariables::NetworkConfigurationPriority), ',');

if (this->network_connection_priorities.empty()) {
EVLOG_AND_THROW(std::runtime_error("NetworkConfigurationPriority must not be empty"));
Expand Down
6 changes: 3 additions & 3 deletions lib/ocpp/v201/device_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ bool validate_value(const VariableCharacteristics& characteristics, const std::s
if (!characteristics.valuesList.has_value()) {
return true;
}
const auto values_list = ocpp::get_vector_from_csv(characteristics.valuesList.value().get());
const auto values_list = ocpp::split_string(characteristics.valuesList.value().get(), ',');
return std::find(values_list.begin(), values_list.end(), value) != values_list.end();
}
default: // same validation for MemberList or SequenceList
Expand All @@ -186,8 +186,8 @@ bool validate_value(const VariableCharacteristics& characteristics, const std::s
if (!characteristics.valuesList.has_value()) {
return true;
}
const auto values_list = ocpp::get_vector_from_csv(characteristics.valuesList.value().get());
const auto value_csv = get_vector_from_csv(value);
const auto values_list = ocpp::split_string(characteristics.valuesList.value().get(), ',');
const auto value_csv = ocpp::split_string(value, ',');
for (const auto& v : value_csv) {
if (std::find(values_list.begin(), values_list.end(), v) == values_list.end()) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion lib/ocpp/v201/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace utils {

std::vector<MeasurandEnum> get_measurands_vec(const std::string& measurands_csv) {
std::vector<MeasurandEnum> measurands;
std::vector<std::string> measurands_strings = ocpp::get_vector_from_csv(measurands_csv);
std::vector<std::string> measurands_strings = ocpp::split_string(measurands_csv, ',');

for (const auto& measurand_string : measurands_strings) {
try {
Expand Down