mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-17 13:22:53 +01:00
Clean up CORS implemention (#662)
This commit is contained in:
parent
40bf6b5ebc
commit
06be7f5ddb
@ -34,6 +34,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
static const char * TAG = "http_server";
|
||||
static const char * CORS_TAG = "CORS";
|
||||
|
||||
static GlobalState * GLOBAL_STATE;
|
||||
static httpd_handle_t server = NULL;
|
||||
@ -61,60 +62,85 @@ typedef struct rest_server_context
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
static esp_err_t ip_in_private_range(uint32_t ip){
|
||||
//Private IP ranges (little endian, 192.168.0.0 => 0.0.168.192)
|
||||
//192.168.0.0
|
||||
uint32_t sixteen_bit_block = 0b00000000000000001010100011000000;
|
||||
uint32_t sixteen_bit_mask = 0b00000000000000001111111111111111;
|
||||
static esp_err_t ip_in_private_range(uint32_t address) {
|
||||
uint32_t ip_address = ntohl(address);
|
||||
|
||||
if((ip & sixteen_bit_mask) == sixteen_bit_block){
|
||||
return ESP_OK;
|
||||
// 10.0.0.0 - 10.255.255.255 (Class A)
|
||||
if ((ip_address >= 0x0A000000) && (ip_address <= 0x0AFFFFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
//172.16.0.0
|
||||
uint32_t twenty_bit_block = 0b00000000000000000001000010101100;
|
||||
uint32_t twenty_bit_mask = 0b00000000000000001111000011111111;
|
||||
if((ip & twenty_bit_mask) == twenty_bit_block){
|
||||
return ESP_OK;
|
||||
|
||||
// 172.16.0.0 - 172.31.255.255 (Class B)
|
||||
if ((ip_address >= 0xAC100000) && (ip_address <= 0xAC1FFFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
//10.0.0.0
|
||||
uint32_t twenty_four_bit_block = 0b00000000000000000000000000001010;
|
||||
uint32_t twenty_four_bit_mask = 0b00000000000000000000000011111111;
|
||||
if((ip & twenty_four_bit_mask) == twenty_four_bit_block){
|
||||
return ESP_OK;
|
||||
|
||||
// 192.168.0.0 - 192.168.255.255 (Class C)
|
||||
if ((ip_address >= 0xC0A80000) && (ip_address <= 0xC0A8FFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
static esp_err_t check_is_same_network(httpd_req_t * req){
|
||||
|
||||
wifi_mode_t mode;
|
||||
esp_err_t err = esp_wifi_get_mode(&mode);
|
||||
static uint32_t extract_origin_ip_addr(httpd_req_t *req)
|
||||
{
|
||||
char origin[128];
|
||||
char ip_str[16];
|
||||
uint32_t origin_ip_addr = 0;
|
||||
|
||||
if (err == ESP_OK) {
|
||||
switch (mode) {
|
||||
case WIFI_MODE_STA:
|
||||
case WIFI_MODE_APSTA:
|
||||
ESP_LOGI(TAG, "WiFi is in AP+/STA mode.");
|
||||
return ESP_OK;
|
||||
default:
|
||||
break;
|
||||
// Attempt to get the Origin header.
|
||||
if (httpd_req_get_hdr_value_str(req, "Origin", origin, sizeof(origin)) != ESP_OK) {
|
||||
ESP_LOGD(CORS_TAG, "No origin header found.");
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGD(CORS_TAG, "Origin header: %s", origin);
|
||||
|
||||
// Find the start of the IP address in the Origin header
|
||||
const char *prefix = "http://";
|
||||
char *ip_start = strstr(origin, prefix);
|
||||
if (ip_start) {
|
||||
ip_start += strlen(prefix); // Move past "http://"
|
||||
|
||||
// Extract the IP address portion (up to the next '/')
|
||||
char *ip_end = strchr(ip_start, '/');
|
||||
size_t ip_len = ip_end ? (size_t)(ip_end - ip_start) : strlen(ip_start);
|
||||
if (ip_len < sizeof(ip_str)) {
|
||||
strncpy(ip_str, ip_start, ip_len);
|
||||
ip_str[ip_len] = '\0'; // Null-terminate the string
|
||||
|
||||
// Convert the IP address string to uint32_t
|
||||
origin_ip_addr = inet_addr(ip_str);
|
||||
if (origin_ip_addr == INADDR_NONE) {
|
||||
ESP_LOGW(CORS_TAG, "Invalid IP address: %s", ip_str);
|
||||
} else {
|
||||
ESP_LOGD(CORS_TAG, "Extracted IP address %lu", origin_ip_addr);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(CORS_TAG, "IP address string is too long: %s", ip_start);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to get WiFi mode: %s", esp_err_to_name(err));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return origin_ip_addr;
|
||||
}
|
||||
|
||||
static esp_err_t is_network_allowed(httpd_req_t * req)
|
||||
{
|
||||
if (GLOBAL_STATE->SYSTEM_MODULE.ap_enabled == true) {
|
||||
ESP_LOGI(CORS_TAG, "Device in AP mode. Allowing CORS.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int sockfd = httpd_req_to_sockfd(req);
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in6 addr; // esp_http_server uses IPv6 addressing
|
||||
socklen_t addr_size = sizeof(addr);
|
||||
|
||||
|
||||
if (getpeername(sockfd, (struct sockaddr *)&addr, &addr_size) < 0) {
|
||||
ESP_LOGE(TAG, "Error getting client IP");
|
||||
ESP_LOGE(CORS_TAG, "Error getting client IP");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
uint32_t request_ip_addr = addr.sin6_addr.un.u32_addr[3];
|
||||
|
||||
// // Convert to IPv6 string
|
||||
@ -123,55 +149,19 @@ static esp_err_t check_is_same_network(httpd_req_t * req){
|
||||
// Convert to IPv4 string
|
||||
inet_ntop(AF_INET, &request_ip_addr, ipstr, sizeof(ipstr));
|
||||
|
||||
|
||||
|
||||
char origin[128];
|
||||
char ip_str[16]; // Buffer to hold the extracted IP address string
|
||||
uint32_t origin_ip_addr = 0;
|
||||
// Attempt to get the Origin header
|
||||
if (httpd_req_get_hdr_value_str(req, "Origin", origin, sizeof(origin)) == ESP_OK) {
|
||||
ESP_LOGI("CORS", "Origin header: %s", origin);
|
||||
|
||||
// Find the start of the IP address in the Origin header
|
||||
const char *prefix = "http://";
|
||||
char *ip_start = strstr(origin, prefix);
|
||||
if (ip_start) {
|
||||
ip_start += strlen(prefix); // Move past "http://"
|
||||
|
||||
// Extract the IP address portion (up to the next '/')
|
||||
char *ip_end = strchr(ip_start, '/');
|
||||
size_t ip_len = ip_end ? (size_t)(ip_end - ip_start) : strlen(ip_start);
|
||||
if (ip_len < sizeof(ip_str)) {
|
||||
strncpy(ip_str, ip_start, ip_len);
|
||||
ip_str[ip_len] = '\0'; // Null-terminate the string
|
||||
|
||||
// Convert the IP address string to uint32_t
|
||||
origin_ip_addr = inet_addr(ip_str);
|
||||
if (origin_ip_addr == INADDR_NONE) {
|
||||
ESP_LOGW("CORS", "Invalid IP address: %s", ip_str);
|
||||
} else {
|
||||
ESP_LOGI("CORS", "Extracted IP address %lu", origin_ip_addr);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW("CORS", "IP address string is too long");
|
||||
}
|
||||
}
|
||||
}else {
|
||||
// Origin is sent for CSRF sensitive requests, if there is no header it's not a concern.
|
||||
uint32_t origin_ip_addr = extract_origin_ip_addr(req);
|
||||
if (origin_ip_addr == 0) {
|
||||
origin_ip_addr = request_ip_addr;
|
||||
}
|
||||
|
||||
|
||||
if(ip_in_private_range(origin_ip_addr) == ESP_OK && ip_in_private_range(request_ip_addr) == ESP_OK){
|
||||
if (ip_in_private_range(origin_ip_addr) == ESP_OK && ip_in_private_range(request_ip_addr) == ESP_OK) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Client is NOT in the private ip ranges or same range as server.");
|
||||
ESP_LOGI(CORS_TAG, "Client is NOT in the private ip ranges or same range as server.");
|
||||
return ESP_FAIL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
esp_err_t init_fs(void)
|
||||
{
|
||||
esp_vfs_spiffs_conf_t conf = {.base_path = "", .partition_label = NULL, .max_files = 5, .format_if_mount_failed = false};
|
||||
@ -253,7 +243,7 @@ static esp_err_t set_cors_headers(httpd_req_t * req)
|
||||
/* Recovery handler */
|
||||
static esp_err_t rest_recovery_handler(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -325,7 +315,7 @@ static esp_err_t rest_common_get_handler(httpd_req_t * req)
|
||||
|
||||
static esp_err_t handle_options_request(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -344,7 +334,7 @@ static esp_err_t handle_options_request(httpd_req_t * req)
|
||||
static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
{
|
||||
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -446,7 +436,7 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
|
||||
static esp_err_t POST_restart(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -475,7 +465,7 @@ static esp_err_t POST_restart(httpd_req_t * req)
|
||||
/* Simple handler for getting system handler */
|
||||
static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -586,7 +576,7 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
|
||||
esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -644,7 +634,7 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
*/
|
||||
esp_err_t POST_OTA_update(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
@ -767,7 +757,7 @@ void send_log_to_websocket(char *message)
|
||||
*/
|
||||
esp_err_t echo_handler(httpd_req_t * req)
|
||||
{
|
||||
if(check_is_same_network(req) != ESP_OK){
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user