From ef8aee01bb71ba24b66a56490710f15e3f2ac2aa Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sat, 14 Dec 2024 00:06:24 +0100 Subject: [PATCH 1/7] Ported https://github.com/jomjol/AI-on-the-edge-device/pull/2241 to latest main and extended it for all REST APIs --- .../jomjol_controlGPIO/server_GPIO.cpp | 3 +- .../jomjol_controlcamera/server_camera.cpp | 12 +- .../jomjol_fileserver_ota/server_file.cpp | 15 +-- .../jomjol_fileserver_ota/server_ota.cpp | 5 +- .../jomjol_flowcontroll/MainFlowControl.cpp | 41 +++---- code/components/jomjol_mqtt/server_mqtt.cpp | 3 +- code/components/jomjol_wlan/read_wlanini.cpp | 23 ++++ code/components/jomjol_wlan/read_wlanini.h | 2 + code/include/basic_auth.cpp | 105 ++++++++++++++++++ code/include/basic_auth.h | 8 ++ code/main/main.cpp | 4 + code/main/server_main.cpp | 11 +- code/main/softAP.cpp | 9 +- sd-card/wlan.ini | 10 ++ 14 files changed, 206 insertions(+), 45 deletions(-) create mode 100644 code/include/basic_auth.cpp create mode 100644 code/include/basic_auth.h diff --git a/code/components/jomjol_controlGPIO/server_GPIO.cpp b/code/components/jomjol_controlGPIO/server_GPIO.cpp index 3d6f86595..f86efe933 100644 --- a/code/components/jomjol_controlGPIO/server_GPIO.cpp +++ b/code/components/jomjol_controlGPIO/server_GPIO.cpp @@ -25,6 +25,7 @@ #include "server_mqtt.h" #endif //ENABLE_MQTT +#include "basic_auth.h" static const char *TAG = "GPIO"; QueueHandle_t gpio_queue_handle = NULL; @@ -458,7 +459,7 @@ void GpioHandler::registerGpioUri() httpd_uri_t camuri = { }; camuri.method = HTTP_GET; camuri.uri = "/GPIO"; - camuri.handler = callHandleHttpRequest; + camuri.handler = APPLY_BASIC_AUTH_FILTER(callHandleHttpRequest); camuri.user_ctx = (void*)this; httpd_register_uri_handler(_httpServer, &camuri); } diff --git a/code/components/jomjol_controlcamera/server_camera.cpp b/code/components/jomjol_controlcamera/server_camera.cpp index 71eeba471..d79fbcdb7 100644 --- a/code/components/jomjol_controlcamera/server_camera.cpp +++ b/code/components/jomjol_controlcamera/server_camera.cpp @@ -10,6 +10,8 @@ #include "ClassLogFile.h" #include "esp_log.h" +#include "basic_auth.h" + #include "../../include/defines.h" static const char *TAG = "server_cam"; @@ -280,27 +282,27 @@ void register_server_camera_uri(httpd_handle_t server) camuri.method = HTTP_GET; camuri.uri = "/lighton"; - camuri.handler = handler_lightOn; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_lightOn); camuri.user_ctx = (void *)"Light On"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/lightoff"; - camuri.handler = handler_lightOff; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_lightOff); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/capture"; - camuri.handler = handler_capture; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture); camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); camuri.uri = "/capture_with_flashlight"; - camuri.handler = handler_capture_with_light; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture_with_light); camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); camuri.uri = "/save"; - camuri.handler = handler_capture_save_to_file; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture_save_to_file); camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); } diff --git a/code/components/jomjol_fileserver_ota/server_file.cpp b/code/components/jomjol_fileserver_ota/server_file.cpp index 50e2c8f2d..eb69913aa 100644 --- a/code/components/jomjol_fileserver_ota/server_file.cpp +++ b/code/components/jomjol_fileserver_ota/server_file.cpp @@ -46,6 +46,7 @@ extern "C" { #include "Helper.h" #include "miniz.h" +#include "basic_auth.h" static const char *TAG = "OTA FILE"; @@ -1174,7 +1175,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_download = { .uri = "/fileserver*", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = download_get_handler, + .handler = APPLY_BASIC_AUTH_FILTER(download_get_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_download); @@ -1183,7 +1184,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_datafileact = { .uri = "/datafileact", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = datafileact_get_full_handler, + .handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_full_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_datafileact); @@ -1192,7 +1193,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_datafile_last_part_handle = { .uri = "/data", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = datafileact_get_last_part_handler, + .handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_last_part_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_datafile_last_part_handle); @@ -1200,7 +1201,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_logfileact = { .uri = "/logfileact", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = logfileact_get_full_handler, + .handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_full_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_logfileact); @@ -1209,7 +1210,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_logfile_last_part_handle = { .uri = "/log", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = logfileact_get_last_part_handler, + .handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_last_part_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_logfile_last_part_handle); @@ -1219,7 +1220,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_upload = { .uri = "/upload/*", // Match all URIs of type /upload/path/to/file .method = HTTP_POST, - .handler = upload_post_handler, + .handler = APPLY_BASIC_AUTH_FILTER(upload_post_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_upload); @@ -1228,7 +1229,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) httpd_uri_t file_delete = { .uri = "/delete/*", // Match all URIs of type /delete/path/to/file .method = HTTP_POST, - .handler = delete_post_handler, + .handler = APPLY_BASIC_AUTH_FILTER(delete_post_handler), .user_ctx = server_data // Pass server data as context }; httpd_register_uri_handler(server, &file_delete); diff --git a/code/components/jomjol_fileserver_ota/server_ota.cpp b/code/components/jomjol_fileserver_ota/server_ota.cpp index ad7b1b598..523939784 100644 --- a/code/components/jomjol_fileserver_ota/server_ota.cpp +++ b/code/components/jomjol_fileserver_ota/server_ota.cpp @@ -42,6 +42,7 @@ #include "Helper.h" #include "statusled.h" +#include "basic_auth.h" #include "../../include/defines.h" /*an ota data write buffer ready to write to the flash*/ @@ -690,13 +691,13 @@ void register_server_ota_sdcard_uri(httpd_handle_t server) httpd_uri_t camuri = { }; camuri.method = HTTP_GET; camuri.uri = "/ota"; - camuri.handler = handler_ota_update; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_ota_update); camuri.user_ctx = (void*) "Do OTA"; httpd_register_uri_handler(server, &camuri); camuri.method = HTTP_GET; camuri.uri = "/reboot"; - camuri.handler = handler_reboot; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_reboot); camuri.user_ctx = (void*) "Reboot"; httpd_register_uri_handler(server, &camuri); diff --git a/code/components/jomjol_flowcontroll/MainFlowControl.cpp b/code/components/jomjol_flowcontroll/MainFlowControl.cpp index 8a98010c7..9f189af56 100644 --- a/code/components/jomjol_flowcontroll/MainFlowControl.cpp +++ b/code/components/jomjol_flowcontroll/MainFlowControl.cpp @@ -27,6 +27,7 @@ #include "read_wlanini.h" #include "connect_wlan.h" #include "psram.h" +#include "basic_auth.h" // support IDF 5.x #ifndef portTICK_RATE_MS @@ -1782,108 +1783,108 @@ void register_server_main_flow_task_uri(httpd_handle_t server) camuri.method = HTTP_GET; camuri.uri = "/doinit"; - camuri.handler = handler_init; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_init); camuri.user_ctx = (void *)"Light On"; httpd_register_uri_handler(server, &camuri); // Legacy API => New: "/setPreValue" camuri.uri = "/setPreValue.html"; - camuri.handler = handler_prevalue; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_prevalue); camuri.user_ctx = (void *)"Prevalue"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/setPreValue"; - camuri.handler = handler_prevalue; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_prevalue); camuri.user_ctx = (void *)"Prevalue"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/flow_start"; - camuri.handler = handler_flow_start; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_flow_start); camuri.user_ctx = (void *)"Flow Start"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/statusflow.html"; - camuri.handler = handler_statusflow; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_statusflow); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/statusflow"; - camuri.handler = handler_statusflow; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_statusflow); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); // Legacy API => New: "/cpu_temperature" camuri.uri = "/cputemp.html"; - camuri.handler = handler_cputemp; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_cputemp); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/cpu_temperature"; - camuri.handler = handler_cputemp; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_cputemp); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); // Legacy API => New: "/rssi" camuri.uri = "/rssi.html"; - camuri.handler = handler_rssi; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_rssi); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/rssi"; - camuri.handler = handler_rssi; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_rssi); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/date"; - camuri.handler = handler_current_date; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_current_date); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/uptime"; - camuri.handler = handler_uptime; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_uptime); camuri.user_ctx = (void *)"Light Off"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/editflow"; - camuri.handler = handler_editflow; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_editflow); camuri.user_ctx = (void *)"EditFlow"; httpd_register_uri_handler(server, &camuri); // Legacy API => New: "/value" camuri.uri = "/value.html"; - camuri.handler = handler_wasserzaehler; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler); camuri.user_ctx = (void *)"Value"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/value"; - camuri.handler = handler_wasserzaehler; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler); camuri.user_ctx = (void *)"Value"; httpd_register_uri_handler(server, &camuri); // Legacy API => New: "/value" camuri.uri = "/wasserzaehler.html"; - camuri.handler = handler_wasserzaehler; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler); camuri.user_ctx = (void *)"Wasserzaehler"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/json"; - camuri.handler = handler_json; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_json); camuri.user_ctx = (void *)"JSON"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/heap"; - camuri.handler = handler_get_heap; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_get_heap); camuri.user_ctx = (void *)"Heap"; httpd_register_uri_handler(server, &camuri); camuri.uri = "/stream"; - camuri.handler = handler_stream; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_stream); camuri.user_ctx = (void *)"stream"; httpd_register_uri_handler(server, &camuri); /** will handle metrics requests */ camuri.uri = "/metrics"; - camuri.handler = handler_openmetrics; + camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_openmetrics); camuri.user_ctx = (void *)"metrics"; httpd_register_uri_handler(server, &camuri); diff --git a/code/components/jomjol_mqtt/server_mqtt.cpp b/code/components/jomjol_mqtt/server_mqtt.cpp index d20c102c9..9869bb448 100644 --- a/code/components/jomjol_mqtt/server_mqtt.cpp +++ b/code/components/jomjol_mqtt/server_mqtt.cpp @@ -12,6 +12,7 @@ #include "interface_mqtt.h" #include "time_sntp.h" #include "../../include/defines.h" +#include "basic_auth.h" @@ -347,7 +348,7 @@ void register_server_mqtt_uri(httpd_handle_t server) { uri.method = HTTP_GET; uri.uri = "/mqtt_publish_discovery"; - uri.handler = scheduleSendingDiscovery_and_static_Topics; + uri.handler = APPLY_BASIC_AUTH_FILTER(scheduleSendingDiscovery_and_static_Topics); uri.user_ctx = (void*) ""; httpd_register_uri_handler(server, &uri); } diff --git a/code/components/jomjol_wlan/read_wlanini.cpp b/code/components/jomjol_wlan/read_wlanini.cpp index 7ebca23da..8473a8886 100644 --- a/code/components/jomjol_wlan/read_wlanini.cpp +++ b/code/components/jomjol_wlan/read_wlanini.cpp @@ -145,6 +145,29 @@ int LoadWlanFromFile(std::string fn) wlan_config.dns = tmp; LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns); } + + else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_USERNAME")){ + tmp = splitted[1]; + if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){ + tmp = tmp.substr(1, tmp.length()-2); + } + wlan_config.http_username = tmp; + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_USERNAME: " + wlan_config.http_username); + } + + else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_PASSWORD")){ + tmp = splitted[1]; + if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){ + tmp = tmp.substr(1, tmp.length()-2); + } + wlan_config.http_password = tmp; + #ifndef __HIDE_PASSWORD + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: " + wlan_config.http_password); + #else + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: XXXXXXXX"); + #endif + } + #if (defined WLAN_USE_ROAMING_BY_SCANNING || (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)) else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")){ tmp = trim(splitted[1]); diff --git a/code/components/jomjol_wlan/read_wlanini.h b/code/components/jomjol_wlan/read_wlanini.h index 6a31490f7..759f68332 100644 --- a/code/components/jomjol_wlan/read_wlanini.h +++ b/code/components/jomjol_wlan/read_wlanini.h @@ -13,6 +13,8 @@ struct wlan_config { std::string gateway = ""; std::string netmask = ""; std::string dns = ""; + std::string http_username = ""; + std::string http_password = ""; int rssi_threshold = 0; // Default: 0 -> ROAMING disabled }; extern struct wlan_config wlan_config; diff --git a/code/include/basic_auth.cpp b/code/include/basic_auth.cpp new file mode 100644 index 000000000..8d467d090 --- /dev/null +++ b/code/include/basic_auth.cpp @@ -0,0 +1,105 @@ +#include "basic_auth.h" +#include "read_wlanini.h" +#include +#include + + +#define HTTPD_401 "401 UNAUTHORIZED" + +static const char *TAG = "HTTPAUTH"; + +typedef struct { + const char *username; + const char *password; +} basic_auth_info_t; + +basic_auth_info_t basic_auth_info = { NULL, NULL }; + +void init_basic_auth() { + if (!wlan_config.http_username.empty() && !wlan_config.http_password.empty()) { + basic_auth_info.username = wlan_config.http_username.c_str(); + basic_auth_info.password = wlan_config.http_password.c_str(); + } +} + +static char *http_auth_basic(const char *username, const char *password) +{ + int out; + char *user_info = NULL; + char *digest = NULL; + size_t n = 0; + asprintf(&user_info, "%s:%s", username, password); + if (!user_info) { + ESP_LOGE(TAG, "No enough memory for user information"); + return NULL; + } + esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info)); + + /* 6: The length of the "Basic " string + * n: Number of bytes for a base64 encode format + * 1: Number of bytes for a reserved which be used to fill zero + */ + digest = static_cast(calloc(1, 6 + n + 1)); + if (digest) { + strcpy(digest, "Basic "); + esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info)); + } + free(user_info); + return digest; +} + +esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler(httpd_req_t *)) +{ + char *buf = NULL; + size_t buf_len = 0; + esp_err_t ret = ESP_OK; + + if (basic_auth_info.username == NULL || basic_auth_info.password == NULL) { + ret = original_handler(req); + } else { + buf_len = httpd_req_get_hdr_value_len(req, "Authorization") + 1; + if (buf_len > 1) { + buf = static_cast(calloc(1, buf_len)); + if (!buf) { + ESP_LOGE(TAG, "No enough memory for basic authorization"); + return ESP_ERR_NO_MEM; + } + + if (httpd_req_get_hdr_value_str(req, "Authorization", buf, buf_len) == ESP_OK) { + ESP_LOGI(TAG, "Found header => Authorization: %s", buf); + } else { + ESP_LOGE(TAG, "No auth value received"); + } + + char *auth_credentials = http_auth_basic(basic_auth_info.username, basic_auth_info.password); + if (!auth_credentials) { + ESP_LOGE(TAG, "No enough memory for basic authorization credentials"); + free(buf); + return ESP_ERR_NO_MEM; + } + + if (strncmp(auth_credentials, buf, buf_len)) { + ESP_LOGE(TAG, "Not authenticated"); + httpd_resp_set_status(req, HTTPD_401); + httpd_resp_set_type(req, "application/json"); + httpd_resp_set_hdr(req, "Connection", "keep-alive"); + httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\""); + httpd_resp_send(req, NULL, 0); + } else { + ESP_LOGI(TAG, "Authenticated calling http handler now!"); + ret=original_handler(req); + } + free(auth_credentials); + free(buf); + } else { + ESP_LOGE(TAG, "No auth header received"); + httpd_resp_set_status(req, HTTPD_401); + httpd_resp_set_type(req, "application/json"); + httpd_resp_set_hdr(req, "Connection", "keep-alive"); + httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\""); + httpd_resp_send(req, NULL, 0); + } + } + + return ret; +} diff --git a/code/include/basic_auth.h b/code/include/basic_auth.h new file mode 100644 index 000000000..51e021eb4 --- /dev/null +++ b/code/include/basic_auth.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +void init_basic_auth(); +esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler(httpd_req_t *)); + +#define APPLY_BASIC_AUTH_FILTER(method) [](httpd_req_t *req){ return basic_auth_request_filter(req, method); } diff --git a/code/main/main.cpp b/code/main/main.cpp index d1e14ebd8..91c54d1be 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -33,6 +33,8 @@ #include "configFile.h" #include "server_main.h" #include "server_camera.h" +#include "basic_auth.h" + #ifdef ENABLE_MQTT #include "server_mqtt.h" #endif //ENABLE_MQTT @@ -429,6 +431,8 @@ extern "C" void app_main(void) StatusLED(WLAN_INIT, 3, true); return; } + + init_basic_auth(); } else if (iWLANStatus == -1) { // wlan.ini not available, potentially empty or content not readable StatusLED(WLAN_INIT, 1, true); diff --git a/code/main/server_main.cpp b/code/main/server_main.cpp index 58b55e900..a38a7e129 100644 --- a/code/main/server_main.cpp +++ b/code/main/server_main.cpp @@ -17,6 +17,7 @@ #include "MainFlowControl.h" #include "esp_log.h" +#include "basic_auth.h" #include "esp_chip_info.h" #include @@ -408,7 +409,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t info_get_handle = { .uri = "/info", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = info_get_handler, + .handler = APPLY_BASIC_AUTH_FILTER(info_get_handler), .user_ctx = (void*) base_path // Pass server data as context }; httpd_register_uri_handler(server, &info_get_handle); @@ -416,7 +417,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t sysinfo_handle = { .uri = "/sysinfo", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = sysinfo_handler, + .handler = APPLY_BASIC_AUTH_FILTER(sysinfo_handler), .user_ctx = (void*) base_path // Pass server data as context }; httpd_register_uri_handler(server, &sysinfo_handle); @@ -424,7 +425,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t starttime_tmp_handle = { .uri = "/starttime", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = starttime_get_handler, + .handler = APPLY_BASIC_AUTH_FILTER(starttime_get_handler), .user_ctx = NULL // Pass server data as context }; httpd_register_uri_handler(server, &starttime_tmp_handle); @@ -432,7 +433,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t img_tmp_handle = { .uri = "/img_tmp/*", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = img_tmp_virtual_handler, + .handler = APPLY_BASIC_AUTH_FILTER(img_tmp_virtual_handler), .user_ctx = (void*) base_path // Pass server data as context }; httpd_register_uri_handler(server, &img_tmp_handle); @@ -440,7 +441,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t main_rest_handle = { .uri = "/*", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = hello_main_handler, + .handler = APPLY_BASIC_AUTH_FILTER(hello_main_handler), .user_ctx = (void*) base_path // Pass server data as context }; httpd_register_uri_handler(server, &main_rest_handle); diff --git a/code/main/softAP.cpp b/code/main/softAP.cpp index fe903fd11..e1aab5f2d 100644 --- a/code/main/softAP.cpp +++ b/code/main/softAP.cpp @@ -29,6 +29,7 @@ #include "Helper.h" #include "statusled.h" #include "server_ota.h" +#include "basic_auth.h" #include "lwip/err.h" #include "lwip/sys.h" @@ -468,7 +469,7 @@ httpd_handle_t start_webserverAP(void) httpd_uri_t reboot_handle = { .uri = "/reboot", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = reboot_handlerAP, + .handler = APPLY_BASIC_AUTH_FILTER(reboot_handlerAP), .user_ctx = NULL // Pass server data as context }; httpd_register_uri_handler(server, &reboot_handle); @@ -476,7 +477,7 @@ httpd_handle_t start_webserverAP(void) httpd_uri_t config_ini_handle = { .uri = "/config", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = config_ini_handler, + .handler = APPLY_BASIC_AUTH_FILTER(config_ini_handler), .user_ctx = NULL // Pass server data as context }; httpd_register_uri_handler(server, &config_ini_handle); @@ -485,7 +486,7 @@ httpd_handle_t start_webserverAP(void) httpd_uri_t file_uploadAP = { .uri = "/upload/*", // Match all URIs of type /upload/path/to/file .method = HTTP_POST, - .handler = upload_post_handlerAP, + .handler = APPLY_BASIC_AUTH_FILTER(upload_post_handlerAP), .user_ctx = NULL // Pass server data as context }; httpd_register_uri_handler(server, &file_uploadAP); @@ -493,7 +494,7 @@ httpd_handle_t start_webserverAP(void) httpd_uri_t test_uri = { .uri = "*", .method = HTTP_GET, - .handler = test_handler, + .handler = APPLY_BASIC_AUTH_FILTER(test_handler), .user_ctx = NULL }; httpd_register_uri_handler(server, &test_uri); diff --git a/sd-card/wlan.ini b/sd-card/wlan.ini index a1ba7454a..200f8c50c 100644 --- a/sd-card/wlan.ini +++ b/sd-card/wlan.ini @@ -36,3 +36,13 @@ password = "" ; Default: 0 = Disable client requested roaming query RSSIThreshold = 0 + + +;++++++++++++++++++++++++++++++++++ +; Password Protection of the Web Interface and the REST API +; When those parameters are active, the Web Interface and the REST API are protected by a username and password. +; Note: This might be a weak and insecure way to protect the Web Interface and the REST API. +; There was no audith nor a security review to check the security of the protection! +; Use at your own risk! +;http_username = "test" +;http_password = "changeme" \ No newline at end of file From 4841e34a83b56ac979ee83e40872d3b0831354fd Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sat, 14 Dec 2024 00:13:50 +0100 Subject: [PATCH 2/7] . --- code/components/jomjol_flowcontroll/ClassFlowControll.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index b14cfa8ae..d0b4f737e 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -26,6 +26,7 @@ extern "C" { #include "server_help.h" #include "MainFlowControl.h" +#include "basic_auth.h" #include "../../include/defines.h" static const char* TAG = "FLOWCTRL"; From 5f1dc34800e09d6d6a6b0f03c08ba72044acca11 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 14 Dec 2024 01:35:58 +0100 Subject: [PATCH 3/7] fix compile errors --- code/{include => components/jomjol_wlan}/basic_auth.cpp | 0 code/{include => components/jomjol_wlan}/basic_auth.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename code/{include => components/jomjol_wlan}/basic_auth.cpp (100%) rename code/{include => components/jomjol_wlan}/basic_auth.h (100%) diff --git a/code/include/basic_auth.cpp b/code/components/jomjol_wlan/basic_auth.cpp similarity index 100% rename from code/include/basic_auth.cpp rename to code/components/jomjol_wlan/basic_auth.cpp diff --git a/code/include/basic_auth.h b/code/components/jomjol_wlan/basic_auth.h similarity index 100% rename from code/include/basic_auth.h rename to code/components/jomjol_wlan/basic_auth.h From 4640c041fd4d5419f5adf94760ce1c5f20169698 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sat, 14 Dec 2024 11:38:27 +0100 Subject: [PATCH 4/7] . --- Changelog.md | 23 ++++++++++++++++++++-- code/components/jomjol_wlan/basic_auth.cpp | 16 ++++++++------- sd-card/wlan.ini | 11 ++++++----- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Changelog.md b/Changelog.md index 569048ffc..9ac79c02e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,22 @@ +## [16.0.0-RC6] - 2024-12-xx + +For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0) + +#### Known issues +Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and +[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue. + +#### Core Changes +Only changes since RC5 are listed: +- Added basic authentification of the Web Interface and the REST API + xxxxx + + **:warning: Please check your Homeassistant instance to make sure it is handled correctly!** + +#### Bug Fixes +Only changes since RC5 are listed: + - xxx + ## [16.0.0-RC5] - 2024-12-05 For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0) @@ -22,11 +41,11 @@ Only changes since RC4 are listed: **:warning: Please check your Homeassistant instance to make sure it is handled correctly!** #### Bug Fixes -Only changes since RC3 are listed: +Only changes since RC4 are listed: - Added fix for ledintensity (#3418) - Added fix for OV2640 brightness contrast saturation (#3417) - Added fix for 'AnalogToDigitTransitionStart' always using 9.2 regardless of the configured value (#3393) - - Addef fix for HA menu entry (#3342) + - Added fix for HA menu entry (#3342) ## [16.0.0-RC4] - 2024-10-06 diff --git a/code/components/jomjol_wlan/basic_auth.cpp b/code/components/jomjol_wlan/basic_auth.cpp index 8d467d090..09d46b547 100644 --- a/code/components/jomjol_wlan/basic_auth.cpp +++ b/code/components/jomjol_wlan/basic_auth.cpp @@ -4,7 +4,7 @@ #include -#define HTTPD_401 "401 UNAUTHORIZED" +#define HTTPD_401 "401 UNAUTHORIZED" static const char *TAG = "HTTPAUTH"; @@ -54,6 +54,8 @@ esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler size_t buf_len = 0; esp_err_t ret = ESP_OK; + char unauthorized[] = "You are not authorized to use this website!"; + if (basic_auth_info.username == NULL || basic_auth_info.password == NULL) { ret = original_handler(req); } else { @@ -81,10 +83,10 @@ esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler if (strncmp(auth_credentials, buf, buf_len)) { ESP_LOGE(TAG, "Not authenticated"); httpd_resp_set_status(req, HTTPD_401); - httpd_resp_set_type(req, "application/json"); + httpd_resp_set_type(req, HTTPD_TYPE_TEXT); httpd_resp_set_hdr(req, "Connection", "keep-alive"); - httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\""); - httpd_resp_send(req, NULL, 0); + httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\""); + httpd_resp_send(req, unauthorized, strlen(unauthorized)); } else { ESP_LOGI(TAG, "Authenticated calling http handler now!"); ret=original_handler(req); @@ -94,10 +96,10 @@ esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler } else { ESP_LOGE(TAG, "No auth header received"); httpd_resp_set_status(req, HTTPD_401); - httpd_resp_set_type(req, "application/json"); + httpd_resp_set_type(req, HTTPD_TYPE_TEXT); httpd_resp_set_hdr(req, "Connection", "keep-alive"); - httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\""); - httpd_resp_send(req, NULL, 0); + httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\""); + httpd_resp_send(req, unauthorized, strlen(unauthorized)); } } diff --git a/sd-card/wlan.ini b/sd-card/wlan.ini index 200f8c50c..2967f477b 100644 --- a/sd-card/wlan.ini +++ b/sd-card/wlan.ini @@ -37,12 +37,13 @@ password = "" RSSIThreshold = 0 - ;++++++++++++++++++++++++++++++++++ ; Password Protection of the Web Interface and the REST API ; When those parameters are active, the Web Interface and the REST API are protected by a username and password. ; Note: This might be a weak and insecure way to protect the Web Interface and the REST API. -; There was no audith nor a security review to check the security of the protection! -; Use at your own risk! -;http_username = "test" -;http_password = "changeme" \ No newline at end of file +; There was no audit nor a security review to check the correct implementation of the protection! +; The password gets transmitted unencrypted (plain text), this means it is very easy to extract it +; once somebody has access to your WIFI! +; USE AT YOUR OWN RISK! +;http_username = "myusername" +;http_password = "mypassword" \ No newline at end of file From f53cc1c7aec0c79939c7d2cb539c04b3fb5e95a2 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sat, 14 Dec 2024 13:37:48 +0100 Subject: [PATCH 5/7] . --- sd-card/wlan.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sd-card/wlan.ini b/sd-card/wlan.ini index 2967f477b..13eab43b3 100644 --- a/sd-card/wlan.ini +++ b/sd-card/wlan.ini @@ -40,10 +40,10 @@ RSSIThreshold = 0 ;++++++++++++++++++++++++++++++++++ ; Password Protection of the Web Interface and the REST API ; When those parameters are active, the Web Interface and the REST API are protected by a username and password. -; Note: This might be a weak and insecure way to protect the Web Interface and the REST API. +; Note: This is be a WEAK and INSECURE way to protect the Web Interface and the REST API. ; There was no audit nor a security review to check the correct implementation of the protection! ; The password gets transmitted unencrypted (plain text), this means it is very easy to extract it -; once somebody has access to your WIFI! +; for somebody who has access to your WIFI! ; USE AT YOUR OWN RISK! ;http_username = "myusername" -;http_password = "mypassword" \ No newline at end of file +;http_password = "mypassword" From 238d5835f865dbbf92b5da5028a4a39e631350c1 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Wed, 25 Dec 2024 20:26:46 +0100 Subject: [PATCH 6/7] Update Changelog.md --- Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9ac79c02e..3c3fbeea5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,8 +8,8 @@ Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues #### Core Changes Only changes since RC5 are listed: -- Added basic authentification of the Web Interface and the REST API - xxxxx +- Added basic authentification of the Web Interface and the REST API, see https://jomjol.github.io/AI-on-the-edge-device-docs/Password-Protection/ +- xxx **:warning: Please check your Homeassistant instance to make sure it is handled correctly!** From d2428b2519e734d82fe2afd06963e925ae6ae0db Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Wed, 25 Dec 2024 20:49:08 +0100 Subject: [PATCH 7/7] Update Changelog.md --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 3c3fbeea5..647fa7106 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -## [16.0.0-RC6] - 2024-12-xx +## [16.0.0-RC6] - 2024-xx-xx For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0)