feat: allow talkingq OTA domains
This commit is contained in:
@@ -87,6 +87,7 @@ SRC_FILES+= \
|
||||
battery.c \
|
||||
gnss.c \
|
||||
ota_fullfota2.c \
|
||||
ota_url_policy.c \
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef BANBAN_OTA_URL_POLICY_H
|
||||
#define BANBAN_OTA_URL_POLICY_H
|
||||
|
||||
int banban_ota_url_is_allowed(const char *url);
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "build_macro.h"
|
||||
#include "ql_log.h"
|
||||
#include "ota_fullfota2.h"
|
||||
#include "ota_url_policy.h"
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +47,6 @@
|
||||
#define OTA_STATE_FORMAT_VERSION 1U
|
||||
#define OTA_PROMPT_PLAY_TIMEOUT_MS 10000
|
||||
#define OTA_PROMPT_POLL_MS 50
|
||||
#define OTA_ALLOWED_URL_PREFIX "http://101.35.224.118:8080/assets/firmware/"
|
||||
|
||||
static ql_timer_t mqtt_event_task_timer = NULL;
|
||||
|
||||
@@ -297,24 +297,6 @@ static int ota_compare_version(const char *left, const char *right, int *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ota_url_is_allowed(const char *url)
|
||||
{
|
||||
size_t prefix_len = strlen(OTA_ALLOWED_URL_PREFIX);
|
||||
|
||||
if (url == NULL || url[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp(url, OTA_ALLOWED_URL_PREFIX, prefix_len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (url[prefix_len] == '\0' || strstr(url + prefix_len, "..") != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strstr(url + prefix_len, ".bin") != NULL;
|
||||
}
|
||||
/* ==================== 解析函数 ==================== */
|
||||
|
||||
/**
|
||||
@@ -1318,7 +1300,7 @@ static void handle_ota_upgrade(command_t *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ota_url_is_allowed(cmd->params.ota.url)) {
|
||||
if (!banban_ota_url_is_allowed(cmd->params.ota.url)) {
|
||||
RLOGE("OTA URL is not allowed: %s", cmd->params.ota.url);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ota_url_policy.h"
|
||||
|
||||
#define BANBAN_OTA_LEGACY_URL_PREFIX \
|
||||
"http://101.35.224.118:8080/assets/firmware/"
|
||||
#define BANBAN_OTA_BASE_DOMAIN "talkingq.com"
|
||||
|
||||
static int banban_ascii_equal_nocase(const char *left,
|
||||
const char *right,
|
||||
size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
unsigned char a = (unsigned char)left[i];
|
||||
unsigned char b = (unsigned char)right[i];
|
||||
|
||||
if (a >= 'A' && a <= 'Z') {
|
||||
a = (unsigned char)(a + ('a' - 'A'));
|
||||
}
|
||||
if (b >= 'A' && b <= 'Z') {
|
||||
b = (unsigned char)(b + ('a' - 'A'));
|
||||
}
|
||||
if (a != b) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int banban_hostname_is_valid(const char *host, size_t host_length)
|
||||
{
|
||||
size_t i;
|
||||
int label_has_character = 0;
|
||||
int previous_was_hyphen = 0;
|
||||
|
||||
if (host_length == 0 || host_length > 253) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < host_length; ++i) {
|
||||
unsigned char character = (unsigned char)host[i];
|
||||
|
||||
if ((character >= 'A' && character <= 'Z') ||
|
||||
(character >= 'a' && character <= 'z') ||
|
||||
(character >= '0' && character <= '9')) {
|
||||
label_has_character = 1;
|
||||
previous_was_hyphen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (character == '-') {
|
||||
if (!label_has_character) {
|
||||
return 0;
|
||||
}
|
||||
previous_was_hyphen = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (character == '.') {
|
||||
if (!label_has_character || previous_was_hyphen) {
|
||||
return 0;
|
||||
}
|
||||
label_has_character = 0;
|
||||
previous_was_hyphen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return label_has_character && !previous_was_hyphen;
|
||||
}
|
||||
|
||||
static int banban_host_is_talkingq(const char *host, size_t host_length)
|
||||
{
|
||||
const size_t base_length = sizeof(BANBAN_OTA_BASE_DOMAIN) - 1;
|
||||
|
||||
if (!banban_hostname_is_valid(host, host_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (host_length == base_length) {
|
||||
return banban_ascii_equal_nocase(host,
|
||||
BANBAN_OTA_BASE_DOMAIN,
|
||||
base_length);
|
||||
}
|
||||
|
||||
if (host_length <= base_length + 1 ||
|
||||
host[host_length - base_length - 1] != '.') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return banban_ascii_equal_nocase(host + host_length - base_length,
|
||||
BANBAN_OTA_BASE_DOMAIN,
|
||||
base_length);
|
||||
}
|
||||
|
||||
static int banban_port_is_valid(const char *port, size_t port_length)
|
||||
{
|
||||
size_t i;
|
||||
unsigned long value = 0;
|
||||
|
||||
if (port_length == 0 || port_length > 5) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < port_length; ++i) {
|
||||
if (port[i] < '0' || port[i] > '9') {
|
||||
return 0;
|
||||
}
|
||||
value = value * 10 + (unsigned long)(port[i] - '0');
|
||||
}
|
||||
|
||||
return value > 0 && value <= 65535;
|
||||
}
|
||||
|
||||
static int banban_path_is_fbf(const char *path)
|
||||
{
|
||||
const char *path_end;
|
||||
const char *query;
|
||||
|
||||
if (path == NULL || path[0] != '/' || path[1] == '\0' ||
|
||||
strstr(path, "..") != NULL || strchr(path, '\\') != NULL ||
|
||||
strchr(path, '#') != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
query = strchr(path, '?');
|
||||
path_end = query != NULL ? query : path + strlen(path);
|
||||
if ((size_t)(path_end - path) < 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return banban_ascii_equal_nocase(path_end - 4, ".bin", 4);
|
||||
}
|
||||
|
||||
int banban_ota_url_is_allowed(const char *url)
|
||||
{
|
||||
const char *authority;
|
||||
const char *path;
|
||||
const char *host_end;
|
||||
const char *colon;
|
||||
const size_t legacy_prefix_length =
|
||||
sizeof(BANBAN_OTA_LEGACY_URL_PREFIX) - 1;
|
||||
|
||||
if (url == NULL || url[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp(url, BANBAN_OTA_LEGACY_URL_PREFIX,
|
||||
legacy_prefix_length) == 0) {
|
||||
return banban_path_is_fbf(url + legacy_prefix_length - 1);
|
||||
}
|
||||
|
||||
if (strncmp(url, "http://", 7) == 0) {
|
||||
authority = url + 7;
|
||||
} else if (strncmp(url, "https://", 8) == 0) {
|
||||
authority = url + 8;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = strchr(authority, '/');
|
||||
if (path == NULL || path == authority) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memchr(authority, '@', (size_t)(path - authority)) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
colon = memchr(authority, ':', (size_t)(path - authority));
|
||||
host_end = colon != NULL ? colon : path;
|
||||
if (!banban_host_is_talkingq(authority,
|
||||
(size_t)(host_end - authority))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (colon != NULL &&
|
||||
!banban_port_is_valid(colon + 1, (size_t)(path - colon - 1))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return banban_path_is_fbf(path);
|
||||
}
|
||||
Reference in New Issue
Block a user