diff --git a/components/esp_websocket_client/esp_websocket_client.c b/components/esp_websocket_client/esp_websocket_client.c index 90a897cdf..af5e3fc1a 100644 --- a/components/esp_websocket_client/esp_websocket_client.c +++ b/components/esp_websocket_client/esp_websocket_client.c @@ -18,6 +18,7 @@ #include "freertos/event_groups.h" #include "esp_log.h" #include "esp_timer.h" +#include "esp_tls_crypto.h" static const char *TAG = "WEBSOCKET_CLIENT"; @@ -55,6 +56,7 @@ static const char *TAG = "WEBSOCKET_CLIENT"; #define WS_OVER_TCP_SCHEME "ws" #define WS_OVER_TLS_SCHEME "wss" +#define WS_HTTP_BASIC_AUTH "Basic " const static int STOPPED_BIT = BIT0; const static int CLOSE_FRAME_SENT_BIT = BIT1; // Indicates that a close frame was sent by the client @@ -72,6 +74,7 @@ typedef struct { char *scheme; char *username; char *password; + char *auth; int port; bool auto_reconnect; void *user_context; @@ -249,6 +252,32 @@ static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client return ESP_OK; } +static char *http_auth_basic(const char *username, const char *password) +{ + int out; + char *user_info = NULL; + char *digest = NULL; + size_t n = 0; + + if (asprintf(&user_info, "%s:%s", username, password) < 0) { + return NULL; + } + + 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)); + digest = calloc(1, strlen(WS_HTTP_BASIC_AUTH) + n + 1); + if (digest) { + strcpy(digest, WS_HTTP_BASIC_AUTH); + 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; +} + static esp_err_t esp_websocket_client_set_config(esp_websocket_client_handle_t client, const esp_websocket_client_config_t *config) { websocket_config_storage_t *cfg = client->config; @@ -285,6 +314,12 @@ static esp_err_t esp_websocket_client_set_config(esp_websocket_client_handle_t c ESP_WS_CLIENT_MEM_CHECK(TAG, cfg->password, return ESP_ERR_NO_MEM); } + if (cfg->username && cfg->password) { + free(cfg->auth); + cfg->auth = http_auth_basic(cfg->username, cfg->password); + ESP_WS_CLIENT_MEM_CHECK(TAG, cfg->auth, return ESP_ERR_NO_MEM); + } + if (config->uri) { free(cfg->uri); cfg->uri = strdup(config->uri); @@ -357,6 +392,7 @@ static esp_err_t esp_websocket_client_destroy_config(esp_websocket_client_handle free(cfg->scheme); free(cfg->username); free(cfg->password); + free(cfg->auth); free(cfg->subprotocol); free(cfg->user_agent); free(cfg->headers); @@ -396,6 +432,7 @@ static esp_err_t set_websocket_transport_optional_settings(esp_websocket_client_ .sub_protocol = client->config->subprotocol, .user_agent = client->config->user_agent, .headers = client->config->headers, + .auth = client->config->auth, .propagate_control_frames = true }; return esp_transport_ws_set_config(trans, &config); diff --git a/components/esp_websocket_client/include/esp_websocket_client.h b/components/esp_websocket_client/include/esp_websocket_client.h index 8c710cad0..ea8a8df63 100644 --- a/components/esp_websocket_client/include/esp_websocket_client.h +++ b/components/esp_websocket_client/include/esp_websocket_client.h @@ -68,8 +68,8 @@ typedef struct { const char *uri; /*!< Websocket URI, the information on the URI can be overrides the other fields below, if any */ const char *host; /*!< Domain or IP as string */ int port; /*!< Port to connect, default depend on esp_websocket_transport_t (80 or 443) */ - const char *username; /*!< Using for Http authentication - Not supported for now */ - const char *password; /*!< Using for Http authentication - Not supported for now */ + const char *username; /*!< Using for Http authentication, only support basic auth now */ + const char *password; /*!< Using for Http authentication */ const char *path; /*!< HTTP Path, if not set, default is `/` */ bool disable_auto_reconnect; /*!< Disable the automatic reconnect function when disconnected */ void *user_context; /*!< HTTP user data context */