From 7761f415a57d889bea92764c714b2ef82fb28963 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Thu, 9 Dec 2021 14:56:06 +0100 Subject: [PATCH] Added security to json backend --- main/presets.cpp | 2 +- main/webserver.cpp | 35 ++++++++++++++++++ main/webserver.h | 1 + main/webserver_displaycontrol.cpp | 8 +++- main/webserver_ota.cpp | 61 ++++++++++++++++++++++++++++++- main/webserver_ota.h | 1 + 6 files changed, 104 insertions(+), 4 deletions(-) diff --git a/main/presets.cpp b/main/presets.cpp index 17e1055..d764ba1 100644 --- a/main/presets.cpp +++ b/main/presets.cpp @@ -58,7 +58,7 @@ StringSettings makeDefaultStringSettings() #ifdef FEATURE_OTA .otaServerBranch = {}, #endif - .webserver_password = STRING(AP_PASSWORD), + .webserver_password = {}, }; } } // namespace presets diff --git a/main/webserver.cpp b/main/webserver.cpp index d98e657..a9bc32b 100644 --- a/main/webserver.cpp +++ b/main/webserver.cpp @@ -33,6 +33,7 @@ void initWebserver() httpd_uri_t { .uri = "/reboot", .method = HTTP_GET, .handler = webserver_reboot_handler, .user_ctx = NULL }, #ifdef FEATURE_OTA httpd_uri_t { .uri = "/ota", .method = HTTP_GET, .handler = webserver_ota_handler, .user_ctx = NULL }, + httpd_uri_t { .uri = "/otaPercent", .method = HTTP_GET, .handler = webserver_ota_percentage_handler, .user_ctx = NULL }, httpd_uri_t { .uri = "/triggerOta", .method = HTTP_GET, .handler = webserver_trigger_ota_handler, .user_ctx = NULL }, #endif httpd_uri_t { .uri = "/settings", .method = HTTP_GET, .handler = webserver_settings_handler, .user_ctx = NULL }, @@ -42,6 +43,7 @@ void initWebserver() #ifdef OLD_NVS httpd_uri_t { .uri = "/dumpnvs", .method = HTTP_GET, .handler = webserver_dump_nvs_handler, .user_ctx = NULL }, #endif + httpd_uri_t { .uri = "/check", .method = HTTP_GET, .handler = webserver_status_handler, .user_ctx = NULL }, }) { const auto result = httpd_register_uri_handler(httpdHandle, &uri); @@ -66,4 +68,37 @@ esp_err_t webserver_reboot_handler(httpd_req_t *req) CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, "text/plain", "REBOOT called...") } +esp_err_t webserver_status_handler(httpd_req_t *req) +{ + espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil(5s).count()}; + if (!helper.locked()) + { + constexpr const std::string_view msg = "could not lock webserver_lock"; + ESP_LOGE(TAG, "%.*s", msg.size(), msg.data()); + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg); + } + + std::string body; + + std::string wants_json_query; + if (auto result = esphttpdutils::webserver_get_query(req)) + wants_json_query = *result; + else + { + ESP_LOGE(TAG, "%.*s", result.error().size(), result.error().data()); + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", result.error()); + } + + char tmpBuf[256]; + const auto key_result = httpd_query_key_value(wants_json_query.data(), "json", tmpBuf, 256); + if (key_result == ESP_OK && (tmpBuf == stringSettings.webserver_password || stringSettings.webserver_password.empty())) + { + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, "text/plain", "Ok."); + } + else + { + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Unauthorized, "text/plain", ""); + } +} + #endif diff --git a/main/webserver.h b/main/webserver.h index c312174..f349b3a 100644 --- a/main/webserver.h +++ b/main/webserver.h @@ -32,4 +32,5 @@ extern httpd_handle_t httpdHandle; void initWebserver(); void handleWebserver(); esp_err_t webserver_reboot_handler(httpd_req_t *req); +esp_err_t webserver_status_handler(httpd_req_t *req); #endif diff --git a/main/webserver_displaycontrol.cpp b/main/webserver_displaycontrol.cpp index a51140c..379aa81 100644 --- a/main/webserver_displaycontrol.cpp +++ b/main/webserver_displaycontrol.cpp @@ -30,7 +30,7 @@ esp_err_t webserver_root_handler(httpd_req_t *req) char tmpBuf[256]; const auto key_result = httpd_query_key_value(wants_json_query.data(), "json", tmpBuf, 256); - if (key_result == ESP_OK) + if (key_result == ESP_OK && (tmpBuf == stringSettings.webserver_password || stringSettings.webserver_password.empty())) { body += "{"; if (auto currentDisplay = static_cast(espgui::currentDisplay.get())) @@ -46,7 +46,7 @@ esp_err_t webserver_root_handler(httpd_req_t *req) body += fmt::format("\"index\":{},\"items\":[", menuDisplay->selectedIndex()); menuDisplay->runForEveryMenuItem([&,selectedIndex=menuDisplay->selectedIndex()](const espgui::MenuItem &menuItem){ body += "{"; - body += fmt::format("\"name\":\"{}\",\"icon\":\"{}\"", menuItem.text(), "none"); // menuItem.icon()->name + body += fmt::format("\"name\":\"{}\",\"icon\":\"{}\"", menuItem.text(), menuItem.icon()->name); body += "},"; }); body += "],"; @@ -66,6 +66,10 @@ esp_err_t webserver_root_handler(httpd_req_t *req) } body += "}"; } + else if (tmpBuf != stringSettings.webserver_password) + { + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Unauthorized, "text/plain", ""); + } else { HtmlTag htmlTag{"html", body}; diff --git a/main/webserver_ota.cpp b/main/webserver_ota.cpp index 322bf18..a5cc84e 100644 --- a/main/webserver_ota.cpp +++ b/main/webserver_ota.cpp @@ -11,6 +11,61 @@ namespace { constexpr const char * const TAG = "BOBBYWEB"; } // namespace +esp_err_t webserver_ota_percentage_handler(httpd_req_t *req) +{ + espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil(5s).count()}; + if (!helper.locked()) + { + constexpr const std::string_view msg = "could not lock webserver_lock"; + ESP_LOGE(TAG, "%.*s", msg.size(), msg.data()); + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg); + } + + std::string body; + + std::string wants_json_query; + if (auto result = esphttpdutils::webserver_get_query(req)) + wants_json_query = *result; + else + { + ESP_LOGE(TAG, "%.*s", result.error().size(), result.error().data()); + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", result.error()); + } + + char tmpBuf[256]; + const auto key_result = httpd_query_key_value(wants_json_query.data(), "json", tmpBuf, 256); + if (key_result == ESP_OK && (tmpBuf == stringSettings.webserver_password || stringSettings.webserver_password.empty())) + { + body += "{"; + if (asyncOta) + { + if (const auto &appDesc = asyncOta->appDesc()) + { + const auto progress = asyncOta->progress(); + const auto totalSize = asyncOta->totalSize(); + + body += fmt::format("\"cur_ota_percent\":\"{}\",", (totalSize && *totalSize > 0) ? fmt::format("{:.02f}", float(progress) / *totalSize * 100) : "?"); + } + else + { + body += "\"err\":\"Could not access asyncOta->appDesc()\","; + } + } + else + { + body += "\"info\":\"Updater is not constructed.\""; + } + + body += "}"; + } + else if (tmpBuf != stringSettings.webserver_password) + { + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Unauthorized, "text/plain", ""); + } + + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, (key_result == ESP_OK) ? "application/json" : "text/html", body) +} + esp_err_t webserver_ota_handler(httpd_req_t *req) { espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil(5s).count()}; @@ -34,7 +89,7 @@ esp_err_t webserver_ota_handler(httpd_req_t *req) char tmpBuf[256]; const auto key_result = httpd_query_key_value(wants_json_query.data(), "json", tmpBuf, 256); - if (key_result == ESP_OK) + if (key_result == ESP_OK && (tmpBuf == stringSettings.webserver_password || stringSettings.webserver_password.empty())) { body += "{"; @@ -86,6 +141,10 @@ esp_err_t webserver_ota_handler(httpd_req_t *req) body += "}}"; } + else if (tmpBuf != stringSettings.webserver_password) + { + CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Unauthorized, "text/plain", ""); + } else { HtmlTag htmlTag{"html", body}; diff --git a/main/webserver_ota.h b/main/webserver_ota.h index cef270b..81c11e3 100644 --- a/main/webserver_ota.h +++ b/main/webserver_ota.h @@ -24,5 +24,6 @@ #if defined(FEATURE_WEBSERVER) && defined(FEATURE_OTA) esp_err_t webserver_ota_handler(httpd_req_t *req); +esp_err_t webserver_ota_percentage_handler(httpd_req_t *req); esp_err_t webserver_trigger_ota_handler(httpd_req_t *req); #endif