From 9f19677e4da0b7303c7dacbac518a0b2fc9d1207 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:55:55 +0200 Subject: [PATCH 1/3] integrate v201 basic authentication --- src/MicroOcppMongooseClient.cpp | 60 ++++++++++++++++++++++++++------- src/MicroOcppMongooseClient.h | 16 +++++++++ 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/MicroOcppMongooseClient.cpp b/src/MicroOcppMongooseClient.cpp index 2a0e1fe..e518d98 100644 --- a/src/MicroOcppMongooseClient.cpp +++ b/src/MicroOcppMongooseClient.cpp @@ -6,6 +6,10 @@ #include #include +#if MO_ENABLE_V201 +#include +#endif + #define DEBUG_MSG_INTERVAL 5000UL #define WS_UNRESPONSIVE_THRESHOLD_MS 15000UL @@ -63,21 +67,34 @@ MOcppMongooseClient::MOcppMongooseClient(struct mg_mgr *mgr, MO_CONFIG_EXT_PREFIX "BackendUrl", backend_url_factory, MO_WSCONN_FN, readonly, true); setting_cb_id_str = declareConfiguration( MO_CONFIG_EXT_PREFIX "ChargeBoxId", charge_box_id_factory, MO_WSCONN_FN, readonly, true); - - if (auth_key_factory_len > MO_AUTHKEY_LEN_MAX) { - MO_DBG_WARN("auth_key_factory too long - will be cropped"); - auth_key_factory_len = MO_AUTHKEY_LEN_MAX; - } - char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1]; - auth_key_hex[0] = '\0'; - if (auth_key_factory) { - for (size_t i = 0; i < auth_key_factory_len; i++) { - snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key_factory[i]); + +#if MO_ENABLE_V201 + if (protocolVersion.major == 2) { + websocketSettings = makeVariableContainerVolatile(MO_WSCONN_FN_V201, true); + auto variable = websocketSettings->createVariable(Variable::InternalDataType::String, Variable::AttributeType::Actual); + variable->setComponentId("SecurityCtrlr"); + variable->setName("BasicAuthPassword"); + variable->setString(auth_key_factory ? (const char*)auth_key_factory : ""); + websocketSettings->add(std::move(variable)); + basicAuthPasswordString = websocketSettings->getVariable("SecurityCtrlr", "BasicAuthPassword"); + } else +#endif + { + if (auth_key_factory_len > MO_AUTHKEY_LEN_MAX) { + MO_DBG_WARN("auth_key_factory too long - will be cropped"); + auth_key_factory_len = MO_AUTHKEY_LEN_MAX; } + char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1]; + auth_key_hex[0] = '\0'; + if (auth_key_factory) { + for (size_t i = 0; i < auth_key_factory_len; i++) { + snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key_factory[i]); + } + } + setting_auth_key_hex_str = declareConfiguration( + "AuthorizationKey", auth_key_hex, MO_WSCONN_FN, readonly, true); + registerConfigurationValidator("AuthorizationKey", validateAuthorizationKeyHex); } - setting_auth_key_hex_str = declareConfiguration( - "AuthorizationKey", auth_key_hex, MO_WSCONN_FN, readonly, true); - registerConfigurationValidator("AuthorizationKey", validateAuthorizationKeyHex); ws_ping_interval_int = declareConfiguration( "WebSocketPingInterval", 5, MO_WSCONN_FN); @@ -384,6 +401,11 @@ void MOcppMongooseClient::setAuthKey(const unsigned char *auth_key, size_t len) snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key[i]); } +#if MO_ENABLE_V201 + if (protocolVersion.major == 2 && basicAuthPasswordString) { + basicAuthPasswordString->setString((const char*)auth_key); + } else +#endif if (setting_auth_key_hex_str) { setting_auth_key_hex_str->setString(auth_key_hex); configuration_save(); @@ -409,6 +431,12 @@ void MOcppMongooseClient::reloadConfigs() { cb_id = setting_cb_id_str->getString(); } +#if MO_ENABLE_V201 + if (protocolVersion.major == 2 && basicAuthPasswordString) { + snprintf((char*)auth_key, sizeof(auth_key), "%s", basicAuthPasswordString->getString()); + auth_key_len = strlen((char*)auth_key); + } else +#endif if (setting_auth_key_hex_str) { auto auth_key_hex = setting_auth_key_hex_str->getString(); @@ -480,6 +508,12 @@ unsigned long MOcppMongooseClient::getLastConnected() { return last_connection_established; } +#if MO_ENABLE_V201 +std::shared_ptr MOcppMongooseClient::getVariableContainer() { + return websocketSettings; +} +#endif + #if MO_MG_USE_VERSION == MO_MG_V614 void ws_cb(struct mg_connection *nc, int ev, void *ev_data, void *user_data) { diff --git a/src/MicroOcppMongooseClient.h b/src/MicroOcppMongooseClient.h index 1160230..fc8cafa 100644 --- a/src/MicroOcppMongooseClient.h +++ b/src/MicroOcppMongooseClient.h @@ -19,6 +19,7 @@ #ifndef MO_WSCONN_FN #define MO_WSCONN_FN (MO_FILENAME_PREFIX "ws-conn.jsn") +#define MO_WSCONN_FN_V201 (MO_FILENAME_PREFIX "ws-conn-v201.jsn") #endif #define MO_AUTHKEY_LEN_MAX 20 //AuthKey in Bytes. Hex value has double length @@ -28,6 +29,11 @@ namespace MicroOcpp { class FilesystemAdapter; class Configuration; +#if MO_ENABLE_V201 +class Variable; +class VariableContainer; +#endif + class MOcppMongooseClient : public MicroOcpp::Connection { private: struct mg_mgr *mgr {nullptr}; @@ -47,6 +53,10 @@ class MOcppMongooseClient : public MicroOcpp::Connection { std::shared_ptr stale_timeout_int; //inactivity period after which the connection will be closed std::shared_ptr ws_ping_interval_int; //heartbeat intervall in s. 0 sets hb off unsigned long last_hb {0}; +#if MO_ENABLE_V201 + std::shared_ptr websocketSettings; + Variable *basicAuthPasswordString = nullptr; +#endif bool connection_established {false}; unsigned long last_connection_established {-1UL / 2UL}; bool connection_closing {false}; @@ -115,6 +125,12 @@ class MOcppMongooseClient : public MicroOcpp::Connection { void updateRcvTimer(); unsigned long getLastRecv(); //get time of last successful receive in millis unsigned long getLastConnected(); //get time of last connection establish + +#if MO_ENABLE_V201 + //WS client creates and manages its own Variables. This getter function is a temporary solution, in future + //the WS client will be initialized with a Context reference for registering the Variables directly + std::shared_ptr getVariableContainer(); +#endif }; } From 5cc0ce0a3b65103a9b4e8800a069062b48872467 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:06:15 +0200 Subject: [PATCH 2/3] fix BasicAuthPassword --- src/MicroOcppMongooseClient.cpp | 71 +++++++++++++++++++-------------- src/MicroOcppMongooseClient.h | 6 ++- 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/MicroOcppMongooseClient.cpp b/src/MicroOcppMongooseClient.cpp index e518d98..9b10019 100644 --- a/src/MicroOcppMongooseClient.cpp +++ b/src/MicroOcppMongooseClient.cpp @@ -67,6 +67,11 @@ MOcppMongooseClient::MOcppMongooseClient(struct mg_mgr *mgr, MO_CONFIG_EXT_PREFIX "BackendUrl", backend_url_factory, MO_WSCONN_FN, readonly, true); setting_cb_id_str = declareConfiguration( MO_CONFIG_EXT_PREFIX "ChargeBoxId", charge_box_id_factory, MO_WSCONN_FN, readonly, true); + + if (auth_key_factory_len > MO_AUTHKEY_LEN_MAX) { + MO_DBG_WARN("auth_key_factory too long - will be cropped"); + auth_key_factory_len = MO_AUTHKEY_LEN_MAX; + } #if MO_ENABLE_V201 if (protocolVersion.major == 2) { @@ -74,16 +79,14 @@ MOcppMongooseClient::MOcppMongooseClient(struct mg_mgr *mgr, auto variable = websocketSettings->createVariable(Variable::InternalDataType::String, Variable::AttributeType::Actual); variable->setComponentId("SecurityCtrlr"); variable->setName("BasicAuthPassword"); - variable->setString(auth_key_factory ? (const char*)auth_key_factory : ""); + char basicAuthPassword [MO_AUTHKEY_LEN_MAX + 1]; + snprintf(basicAuthPassword, sizeof(basicAuthPassword), "%.*s", (int)auth_key_factory_len, auth_key_factory ? (const char*)auth_key_factory : ""); + variable->setString(basicAuthPassword); websocketSettings->add(std::move(variable)); basicAuthPasswordString = websocketSettings->getVariable("SecurityCtrlr", "BasicAuthPassword"); } else #endif { - if (auth_key_factory_len > MO_AUTHKEY_LEN_MAX) { - MO_DBG_WARN("auth_key_factory too long - will be cropped"); - auth_key_factory_len = MO_AUTHKEY_LEN_MAX; - } char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1]; auth_key_hex[0] = '\0'; if (auth_key_factory) { @@ -395,20 +398,26 @@ void MOcppMongooseClient::setAuthKey(const unsigned char *auth_key, size_t len) return; } - char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1]; - auth_key_hex[0] = '\0'; - for (size_t i = 0; i < len; i++) { - snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key[i]); - } #if MO_ENABLE_V201 - if (protocolVersion.major == 2 && basicAuthPasswordString) { - basicAuthPasswordString->setString((const char*)auth_key); + if (protocolVersion.major == 2) { + char basicAuthPassword [MO_AUTHKEY_LEN_MAX + 1]; + snprintf(basicAuthPassword, sizeof(basicAuthPassword), "%.*s", (int)len, auth_key ? (const char*)auth_key : ""); + if (basicAuthPasswordString) { + basicAuthPasswordString->setString(basicAuthPassword); + } } else #endif - if (setting_auth_key_hex_str) { - setting_auth_key_hex_str->setString(auth_key_hex); - configuration_save(); + { + char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1]; + auth_key_hex[0] = '\0'; + for (size_t i = 0; i < len; i++) { + snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key[i]); + } + if (setting_auth_key_hex_str) { + setting_auth_key_hex_str->setString(auth_key_hex); + configuration_save(); + } } } @@ -432,24 +441,28 @@ void MOcppMongooseClient::reloadConfigs() { } #if MO_ENABLE_V201 - if (protocolVersion.major == 2 && basicAuthPasswordString) { - snprintf((char*)auth_key, sizeof(auth_key), "%s", basicAuthPasswordString->getString()); - auth_key_len = strlen((char*)auth_key); + if (protocolVersion.major == 2) { + if (basicAuthPasswordString) { + snprintf((char*)auth_key, sizeof(auth_key), "%s", basicAuthPasswordString->getString()); + auth_key_len = strlen((char*)auth_key); + } } else #endif - if (setting_auth_key_hex_str) { - auto auth_key_hex = setting_auth_key_hex_str->getString(); + { + if (setting_auth_key_hex_str) { + auto auth_key_hex = setting_auth_key_hex_str->getString(); - #if MO_MG_VERSION_614 - cs_from_hex((char*)auth_key, auth_key_hex, strlen(auth_key_hex)); - #elif MO_MG_USE_VERSION <= MO_MG_V713 - mg_unhex(auth_key_hex, strlen(auth_key_hex), auth_key); - #else - mg_str_to_num(mg_str(auth_key_hex), 16, auth_key, MO_AUTHKEY_LEN_MAX); - #endif + #if MO_MG_VERSION_614 + cs_from_hex((char*)auth_key, auth_key_hex, strlen(auth_key_hex)); + #elif MO_MG_USE_VERSION <= MO_MG_V713 + mg_unhex(auth_key_hex, strlen(auth_key_hex), auth_key); + #else + mg_str_to_num(mg_str(auth_key_hex), 16, auth_key, MO_AUTHKEY_LEN_MAX); + #endif - auth_key_len = strlen(setting_auth_key_hex_str->getString()) / 2; - auth_key[auth_key_len] = '\0'; //need null-termination as long as deprecated `const char *getAuthKey()` exists + auth_key_len = strlen(setting_auth_key_hex_str->getString()) / 2; + auth_key[auth_key_len] = '\0'; //need null-termination as long as deprecated `const char *getAuthKey()` exists + } } /* diff --git a/src/MicroOcppMongooseClient.h b/src/MicroOcppMongooseClient.h index fc8cafa..149b3d3 100644 --- a/src/MicroOcppMongooseClient.h +++ b/src/MicroOcppMongooseClient.h @@ -22,7 +22,11 @@ #define MO_WSCONN_FN_V201 (MO_FILENAME_PREFIX "ws-conn-v201.jsn") #endif +#if MO_ENABLE_V201 +#define MO_AUTHKEY_LEN_MAX 40 //BasicAuthPassword length +#else #define MO_AUTHKEY_LEN_MAX 20 //AuthKey in Bytes. Hex value has double length +#endif namespace MicroOcpp { @@ -41,7 +45,7 @@ class MOcppMongooseClient : public MicroOcpp::Connection { std::string backend_url; std::string cb_id; std::string url; //url = backend_url + '/' + cb_id - unsigned char auth_key [MO_AUTHKEY_LEN_MAX + 1]; //AuthKey in bytes encoding ("FF01" = {0xFF, 0x01}) + unsigned char auth_key [MO_AUTHKEY_LEN_MAX + 1]; //OCPP 2.0.1: BasicAuthPassword. OCPP 1.6: AuthKey in bytes encoding ("FF01" = {0xFF, 0x01}). Both versions append a terminating '\0' size_t auth_key_len; const char *ca_cert; //zero-copy. The host system must ensure that this pointer remains valid during the lifetime of this class std::shared_ptr setting_backend_url_str; From 06d08ca6e7ef77cc23fbc78baffa3db2500524d1 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:01:23 +0200 Subject: [PATCH 3/3] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4868681..5b417fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ## Unreleased ### Added -- Mongoose v7.13 support ([#11](https://github.com/matth-x/MicroOcppMongoose/pull/11) +- Mongoose v7.13 support ([#11](https://github.com/matth-x/MicroOcppMongoose/pull/11)) +- OCPP 2.0.1 BasicAuthPassword integration ([#13](https://github.com/matth-x/MicroOcppMongoose/pull/13)) ### Fixed - AuthorizationKey hex conversion ([#12](https://github.com/matth-x/MicroOcppMongoose/pull/12))