drivers: wifi: esp_at: escape SSID and PSK

According to [1], SSID and PSK need to be escaped:

  Escape character syntax is needed if SSID or password contains any
  special characters, such as , or " or \

Implement character escaping to fix connection attempt to WiFi APs
containing special characters as part of SSID, like "My_2,4GHz_AP".
Increase "connect command" buffer length to handle worst-case scenario of
all the SSID and PSK characters being special characters.

[1] https://docs.espressif.com/projects/esp-at/en/release-v2.4.0.0/esp32/AT_Command_Set/Wi-Fi_AT_Commands.html#id6

Signed-off-by: Marcin Niestroj <m.niestroj@emb.dev>
This commit is contained in:
Marcin Niestroj 2024-02-20 09:18:14 +01:00 committed by Fabio Baltieri
commit de30757d21
2 changed files with 88 additions and 15 deletions

View file

@ -996,11 +996,71 @@ out:
esp_flags_clear(dev, EDF_STA_CONNECTING);
}
static int esp_conn_cmd_append(struct esp_data *data, size_t *off,
const char *chunk, size_t chunk_len)
{
char *str_end = &data->conn_cmd[sizeof(data->conn_cmd)];
char *str = &data->conn_cmd[*off];
const char *chunk_end = chunk + chunk_len;
for (; chunk < chunk_end; chunk++) {
if (str_end - str < 1) {
return -ENOSPC;
}
*str = *chunk;
str++;
}
*off = str - data->conn_cmd;
return 0;
}
#define esp_conn_cmd_append_literal(data, off, chunk) \
esp_conn_cmd_append(data, off, chunk, sizeof(chunk) - 1)
static int esp_conn_cmd_escape_and_append(struct esp_data *data, size_t *off,
const char *chunk, size_t chunk_len)
{
char *str_end = &data->conn_cmd[sizeof(data->conn_cmd)];
char *str = &data->conn_cmd[*off];
const char *chunk_end = chunk + chunk_len;
for (; chunk < chunk_end; chunk++) {
switch (*chunk) {
case ',':
case '\\':
case '"':
if (str_end - str < 2) {
return -ENOSPC;
}
*str = '\\';
str++;
break;
}
if (str_end - str < 1) {
return -ENOSPC;
}
*str = *chunk;
str++;
}
*off = str - data->conn_cmd;
return 0;
}
static int esp_mgmt_connect(const struct device *dev,
struct wifi_connect_req_params *params)
{
struct esp_data *data = dev->data;
int len;
size_t off = 0;
int err;
if (!net_if_is_carrier_ok(data->net_iface) ||
!net_if_is_admin_up(data->net_iface)) {
@ -1013,21 +1073,34 @@ static int esp_mgmt_connect(const struct device *dev,
esp_flags_set(data, EDF_STA_CONNECTING);
len = snprintk(data->conn_cmd, sizeof(data->conn_cmd),
"AT+"_CWJAP"=\"");
memcpy(&data->conn_cmd[len], params->ssid, params->ssid_length);
len += params->ssid_length;
len += snprintk(&data->conn_cmd[len],
sizeof(data->conn_cmd) - len, "\",\"");
if (params->security == WIFI_SECURITY_TYPE_PSK) {
memcpy(&data->conn_cmd[len], params->psk, params->psk_length);
len += params->psk_length;
err = esp_conn_cmd_append_literal(data, &off, "AT+"_CWJAP"=\"");
if (err) {
return err;
}
len += snprintk(&data->conn_cmd[len], sizeof(data->conn_cmd) - len,
"\"");
err = esp_conn_cmd_escape_and_append(data, &off,
params->ssid, params->ssid_length);
if (err) {
return err;
}
err = esp_conn_cmd_append_literal(data, &off, "\",\"");
if (err) {
return err;
}
if (params->security == WIFI_SECURITY_TYPE_PSK) {
err = esp_conn_cmd_escape_and_append(data, &off,
params->psk, params->psk_length);
if (err) {
return err;
}
}
err = esp_conn_cmd_append_literal(data, &off, "\"");
if (err) {
return err;
}
k_work_submit_to_queue(&data->workq, &data->connect_work);

View file

@ -77,7 +77,7 @@ extern "C" {
STRINGIFY(_UART_BAUD)",8,1,0,"_FLOW_CONTROL
#define CONN_CMD_MAX_LEN (sizeof("AT+"_CWJAP"=\"\",\"\"") + \
WIFI_SSID_MAX_LEN + WIFI_PSK_MAX_LEN)
WIFI_SSID_MAX_LEN * 2 + WIFI_PSK_MAX_LEN * 2)
#if defined(CONFIG_WIFI_ESP_AT_DNS_USE)
#define ESP_MAX_DNS MIN(3, CONFIG_DNS_RESOLVER_MAX_SERVERS)