mirror of
https://github.com/esphome/esphome.git
synced 2026-02-08 00:31:58 +00:00
[wireguard] Store configuration strings in flash instead of heap
This commit is contained in:
@@ -30,6 +30,7 @@ _WG_KEY_REGEX = re.compile(r"^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=$")
|
||||
|
||||
wireguard_ns = cg.esphome_ns.namespace("wireguard")
|
||||
Wireguard = wireguard_ns.class_("Wireguard", cg.Component, cg.PollingComponent)
|
||||
AllowedIP = wireguard_ns.struct("AllowedIP")
|
||||
WireguardPeerOnlineCondition = wireguard_ns.class_(
|
||||
"WireguardPeerOnlineCondition", automation.Condition
|
||||
)
|
||||
@@ -108,8 +109,18 @@ async def to_code(config):
|
||||
)
|
||||
)
|
||||
|
||||
for ip in allowed_ips:
|
||||
cg.add(var.add_allowed_ip(str(ip.network_address), str(ip.netmask)))
|
||||
cg.add(
|
||||
var.set_allowed_ips(
|
||||
[
|
||||
cg.StructInitializer(
|
||||
AllowedIP,
|
||||
("ip", str(ip.network_address)),
|
||||
("netmask", str(ip.netmask)),
|
||||
)
|
||||
for ip in allowed_ips
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
cg.add(var.set_srctime(await cg.get_variable(config[CONF_TIME_ID])))
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
#include <esp_wireguard.h>
|
||||
#include <esp_wireguard_err.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace wireguard {
|
||||
namespace esphome::wireguard {
|
||||
|
||||
static const char *const TAG = "wireguard";
|
||||
|
||||
@@ -28,16 +27,16 @@ static const char *const LOGMSG_ONLINE = "online";
|
||||
static const char *const LOGMSG_OFFLINE = "offline";
|
||||
|
||||
void Wireguard::setup() {
|
||||
this->wg_config_.address = this->address_.c_str();
|
||||
this->wg_config_.private_key = this->private_key_.c_str();
|
||||
this->wg_config_.endpoint = this->peer_endpoint_.c_str();
|
||||
this->wg_config_.public_key = this->peer_public_key_.c_str();
|
||||
this->wg_config_.address = this->address_;
|
||||
this->wg_config_.private_key = this->private_key_;
|
||||
this->wg_config_.endpoint = this->peer_endpoint_;
|
||||
this->wg_config_.public_key = this->peer_public_key_;
|
||||
this->wg_config_.port = this->peer_port_;
|
||||
this->wg_config_.netmask = this->netmask_.c_str();
|
||||
this->wg_config_.netmask = this->netmask_;
|
||||
this->wg_config_.persistent_keepalive = this->keepalive_;
|
||||
|
||||
if (!this->preshared_key_.empty())
|
||||
this->wg_config_.preshared_key = this->preshared_key_.c_str();
|
||||
if (this->preshared_key_ != nullptr)
|
||||
this->wg_config_.preshared_key = this->preshared_key_;
|
||||
|
||||
this->publish_enabled_state();
|
||||
|
||||
@@ -131,6 +130,10 @@ void Wireguard::update() {
|
||||
}
|
||||
|
||||
void Wireguard::dump_config() {
|
||||
char private_key_masked[MASK_KEY_BUFFER_SIZE];
|
||||
char preshared_key_masked[MASK_KEY_BUFFER_SIZE];
|
||||
mask_key_to(private_key_masked, sizeof(private_key_masked), this->private_key_);
|
||||
mask_key_to(preshared_key_masked, sizeof(preshared_key_masked), this->preshared_key_);
|
||||
// clang-format off
|
||||
ESP_LOGCONFIG(
|
||||
TAG,
|
||||
@@ -142,13 +145,13 @@ void Wireguard::dump_config() {
|
||||
" Peer Port: " LOG_SECRET("%d") "\n"
|
||||
" Peer Public Key: " LOG_SECRET("%s") "\n"
|
||||
" Peer Pre-shared Key: " LOG_SECRET("%s"),
|
||||
this->address_.c_str(), this->netmask_.c_str(), mask_key(this->private_key_).c_str(),
|
||||
this->peer_endpoint_.c_str(), this->peer_port_, this->peer_public_key_.c_str(),
|
||||
(!this->preshared_key_.empty() ? mask_key(this->preshared_key_).c_str() : "NOT IN USE"));
|
||||
this->address_, this->netmask_, private_key_masked,
|
||||
this->peer_endpoint_, this->peer_port_, this->peer_public_key_,
|
||||
(this->preshared_key_ != nullptr ? preshared_key_masked : "NOT IN USE"));
|
||||
// clang-format on
|
||||
ESP_LOGCONFIG(TAG, " Peer Allowed IPs:");
|
||||
for (auto &allowed_ip : this->allowed_ips_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s/%s", std::get<0>(allowed_ip).c_str(), std::get<1>(allowed_ip).c_str());
|
||||
for (const AllowedIP &allowed_ip : this->allowed_ips_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s/%s", allowed_ip.ip, allowed_ip.netmask);
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Peer Persistent Keepalive: %d%s", this->keepalive_,
|
||||
(this->keepalive_ > 0 ? "s" : " (DISABLED)"));
|
||||
@@ -176,18 +179,6 @@ time_t Wireguard::get_latest_handshake() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Wireguard::set_address(const std::string &address) { this->address_ = address; }
|
||||
void Wireguard::set_netmask(const std::string &netmask) { this->netmask_ = netmask; }
|
||||
void Wireguard::set_private_key(const std::string &key) { this->private_key_ = key; }
|
||||
void Wireguard::set_peer_endpoint(const std::string &endpoint) { this->peer_endpoint_ = endpoint; }
|
||||
void Wireguard::set_peer_public_key(const std::string &key) { this->peer_public_key_ = key; }
|
||||
void Wireguard::set_peer_port(const uint16_t port) { this->peer_port_ = port; }
|
||||
void Wireguard::set_preshared_key(const std::string &key) { this->preshared_key_ = key; }
|
||||
|
||||
void Wireguard::add_allowed_ip(const std::string &ip, const std::string &netmask) {
|
||||
this->allowed_ips_.emplace_back(ip, netmask);
|
||||
}
|
||||
|
||||
void Wireguard::set_keepalive(const uint16_t seconds) { this->keepalive_ = seconds; }
|
||||
void Wireguard::set_reboot_timeout(const uint32_t seconds) { this->reboot_timeout_ = seconds; }
|
||||
void Wireguard::set_srctime(time::RealTimeClock *srctime) { this->srctime_ = srctime; }
|
||||
@@ -274,9 +265,8 @@ void Wireguard::start_connection_() {
|
||||
|
||||
ESP_LOGD(TAG, "Configuring allowed IPs list");
|
||||
bool allowed_ips_ok = true;
|
||||
for (std::tuple<std::string, std::string> ip : this->allowed_ips_) {
|
||||
allowed_ips_ok &=
|
||||
(esp_wireguard_add_allowed_ip(&(this->wg_ctx_), std::get<0>(ip).c_str(), std::get<1>(ip).c_str()) == ESP_OK);
|
||||
for (const AllowedIP &ip : this->allowed_ips_) {
|
||||
allowed_ips_ok &= (esp_wireguard_add_allowed_ip(&(this->wg_ctx_), ip.ip, ip.netmask) == ESP_OK);
|
||||
}
|
||||
|
||||
if (allowed_ips_ok) {
|
||||
@@ -299,8 +289,25 @@ void Wireguard::stop_connection_() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); }
|
||||
void mask_key_to(char *buffer, size_t len, const char *key) {
|
||||
// Format: "XXXXX[...]=\0" = MASK_KEY_BUFFER_SIZE chars minimum
|
||||
if (len < MASK_KEY_BUFFER_SIZE || key == nullptr) {
|
||||
if (len > 0)
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
// Copy first 5 characters of the key
|
||||
size_t i = 0;
|
||||
for (; i < 5 && key[i] != '\0'; ++i) {
|
||||
buffer[i] = key[i];
|
||||
}
|
||||
// Append "[...]="
|
||||
const char *suffix = "[...]=";
|
||||
for (size_t j = 0; suffix[j] != '\0' && (i + j) < len - 1; ++j) {
|
||||
buffer[i + j] = suffix[j];
|
||||
}
|
||||
buffer[i + 6] = '\0';
|
||||
}
|
||||
|
||||
} // namespace wireguard
|
||||
} // namespace esphome
|
||||
} // namespace esphome::wireguard
|
||||
#endif
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_WIREGUARD
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/time/real_time_clock.h"
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
@@ -22,8 +22,13 @@
|
||||
|
||||
#include <esp_wireguard.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace wireguard {
|
||||
namespace esphome::wireguard {
|
||||
|
||||
/// Allowed IP entry for WireGuard peer configuration.
|
||||
struct AllowedIP {
|
||||
const char *ip;
|
||||
const char *netmask;
|
||||
};
|
||||
|
||||
/// Main Wireguard component class.
|
||||
class Wireguard : public PollingComponent {
|
||||
@@ -37,15 +42,25 @@ class Wireguard : public PollingComponent {
|
||||
|
||||
float get_setup_priority() const override { return esphome::setup_priority::BEFORE_CONNECTION; }
|
||||
|
||||
void set_address(const std::string &address);
|
||||
void set_netmask(const std::string &netmask);
|
||||
void set_private_key(const std::string &key);
|
||||
void set_peer_endpoint(const std::string &endpoint);
|
||||
void set_peer_public_key(const std::string &key);
|
||||
void set_peer_port(uint16_t port);
|
||||
void set_preshared_key(const std::string &key);
|
||||
void set_address(const char *address) { this->address_ = address; }
|
||||
void set_netmask(const char *netmask) { this->netmask_ = netmask; }
|
||||
void set_private_key(const char *key) { this->private_key_ = key; }
|
||||
void set_peer_endpoint(const char *endpoint) { this->peer_endpoint_ = endpoint; }
|
||||
void set_peer_public_key(const char *key) { this->peer_public_key_ = key; }
|
||||
void set_peer_port(uint16_t port) { this->peer_port_ = port; }
|
||||
void set_preshared_key(const char *key) { this->preshared_key_ = key; }
|
||||
|
||||
void add_allowed_ip(const std::string &ip, const std::string &netmask);
|
||||
/// Prevent accidental use of std::string which would dangle
|
||||
void set_address(const std::string &address) = delete;
|
||||
void set_netmask(const std::string &netmask) = delete;
|
||||
void set_private_key(const std::string &key) = delete;
|
||||
void set_peer_endpoint(const std::string &endpoint) = delete;
|
||||
void set_peer_public_key(const std::string &key) = delete;
|
||||
void set_preshared_key(const std::string &key) = delete;
|
||||
|
||||
void set_allowed_ips(std::initializer_list<AllowedIP> ips) { this->allowed_ips_ = ips; }
|
||||
/// Prevent accidental use of std::string which would dangle
|
||||
void set_allowed_ips(std::initializer_list<std::tuple<std::string, std::string>> ips) = delete;
|
||||
|
||||
void set_keepalive(uint16_t seconds);
|
||||
void set_reboot_timeout(uint32_t seconds);
|
||||
@@ -83,14 +98,14 @@ class Wireguard : public PollingComponent {
|
||||
time_t get_latest_handshake() const;
|
||||
|
||||
protected:
|
||||
std::string address_;
|
||||
std::string netmask_;
|
||||
std::string private_key_;
|
||||
std::string peer_endpoint_;
|
||||
std::string peer_public_key_;
|
||||
std::string preshared_key_;
|
||||
const char *address_{nullptr};
|
||||
const char *netmask_{nullptr};
|
||||
const char *private_key_{nullptr};
|
||||
const char *peer_endpoint_{nullptr};
|
||||
const char *peer_public_key_{nullptr};
|
||||
const char *preshared_key_{nullptr};
|
||||
|
||||
std::vector<std::tuple<std::string, std::string>> allowed_ips_;
|
||||
FixedVector<AllowedIP> allowed_ips_;
|
||||
|
||||
uint16_t peer_port_;
|
||||
uint16_t keepalive_;
|
||||
@@ -142,8 +157,11 @@ class Wireguard : public PollingComponent {
|
||||
void suspend_wdt();
|
||||
void resume_wdt();
|
||||
|
||||
/// Size of buffer required for mask_key_to: 5 chars + "[...]=" + null = 12
|
||||
static constexpr size_t MASK_KEY_BUFFER_SIZE = 12;
|
||||
|
||||
/// Strip most part of the key only for secure printing
|
||||
std::string mask_key(const std::string &key);
|
||||
void mask_key_to(char *buffer, size_t len, const char *key);
|
||||
|
||||
/// Condition to check if remote peer is online.
|
||||
template<typename... Ts> class WireguardPeerOnlineCondition : public Condition<Ts...>, public Parented<Wireguard> {
|
||||
@@ -169,6 +187,5 @@ template<typename... Ts> class WireguardDisableAction : public Action<Ts...>, pu
|
||||
void play(const Ts &...x) override { this->parent_->disable(); }
|
||||
};
|
||||
|
||||
} // namespace wireguard
|
||||
} // namespace esphome
|
||||
} // namespace esphome::wireguard
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user