Commit Graph
21957 Commits
Author SHA1 Message Date
J. Nick Koston 140629a323 Merge branch 'merge_read_message' into integration 2026-02-08 10:19:57 -06:00
J. Nick Koston 2376c020e8 Merge auth check into base read_message, eliminate APIServerConnection
Move the authentication/connection check switch into
APIServerConnectionBase::read_message before the dispatch switch,
eliminating the APIServerConnection class entirely. APIConnection
now inherits directly from APIServerConnectionBase.
2026-02-08 10:11:42 -06:00
J. Nick Koston d28c3e2641 Collapse APIServerConnection intermediary layer
Remove the 48 on_xxx overrides and 48 pure virtual methods from
the generated APIServerConnection class. APIConnection now overrides
on_xxx() directly from APIServerConnectionBase, eliminating one
virtual call per message dispatch and ~96 vtable entries.
2026-02-08 10:05:10 -06:00
J. Nick Koston 4cf1d7babf Revert "Collapse APIServerConnection intermediary layer"
This reverts commit cac82280b3.
2026-02-08 09:57:03 -06:00
J. Nick Koston cac82280b3 Collapse APIServerConnection intermediary layer
Remove the 48 on_xxx overrides and 48 pure virtual methods from
the generated APIServerConnection class. APIConnection now overrides
on_xxx() directly from APIServerConnectionBase, eliminating one
virtual call per message dispatch and ~96 vtable entries.
2026-02-08 09:55:31 -06:00
J. Nick Koston df7e837e3e Merge branch 'empty_messages_reduce' into integration 2026-02-08 09:35:48 -06:00
J. Nick Koston 25b1ce4268 Merge branch 'dev' into empty_messages_reduce 2026-02-08 09:33:42 -06:00
J. Nick Koston aa38ec379a Address review: fix RECEIVE_CASES type annotation and log format
- Update RECEIVE_CASES type hint from 2-tuple to 3-tuple to match
  the actual stored shape (case, ifdef, message_name)
- Use consistent log format "%s: {}" for empty message overload
  to match the "%s: %s" pattern of non-empty messages
2026-02-08 09:32:40 -06:00
J. Nick Koston 639a704411 Merge branch 'empty_messages_reduce' into integration 2026-02-08 09:21:27 -06:00
J. Nick Koston c641256396 empty messages 2026-02-08 09:16:53 -06:00
J. Nick Koston e4dd75f0b5 empty messages 2026-02-08 09:15:15 -06:00
J. Nick Koston a7d1686cfd empty messages 2026-02-08 09:14:15 -06:00
J. Nick Koston d71f7df367 empty messages 2026-02-08 09:12:41 -06:00
J. Nick Koston a56415ca3f empty messages 2026-02-08 09:10:48 -06:00
J. Nick Koston 5cb3af9e0e Merge branch 'hardening/api-varint-guard' into integration 2026-02-08 08:38:46 -06:00
J. Nick Koston 11774df7f6 [api] Guard varint parsing against overlong encodings
Limit varint parsing to 10 bytes maximum (ceil(64/7)) to prevent
undefined behavior from shifting uint64_t by >= 64 bits when
processing malformed protobuf data with excessive continuation bytes.
2026-02-08 08:37:24 -06:00
J. Nick KostonandClyde Stubbs 41fedaedb3 [udp] Eliminate per-loop heap allocation using std::span (#13838)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-02-08 08:26:47 -06:00
J. Nick Koston 380a669377 Merge branch 'cleanup/remove-dead-host-method' into integration 2026-02-08 08:24:03 -06:00
J. Nick Koston 9299d83eeb Remove unused host() method from AsyncWebServerRequest
Dead code with no callers. Also avoids an unchecked .value() on
optional<string> that would crash on HTTP/1.0 requests without
a Host header.
2026-02-08 08:23:27 -06:00
J. Nick Koston 381f4e9f34 Revert "Remove unused host() method from AsyncWebServerRequest"
This reverts commit 99b7996759.
2026-02-08 08:23:04 -06:00
J. Nick Koston 99b7996759 Remove unused host() method from AsyncWebServerRequest
Dead code with no callers. Also avoids an unchecked .value() on
optional<string> that would crash on HTTP/1.0 requests without
a Host header.
2026-02-08 08:22:24 -06:00
J. Nick Koston 31ca8984ed Merge branch 'web_server_idf_heap' into integration 2026-02-08 08:05:13 -06:00
J. Nick Koston 02687615b3 Merge upstream/dev into web_server_idf_heap
Resolve conflict in utils.cpp: use query_len parameter (from dev)
instead of query_url.size() (query_url is const char*, not string).
2026-02-08 08:04:57 -06:00
J. Nick Koston b283f1ae75 Merge all hardening branches into integration
Resolve conflict in web_server_idf.cpp: keep constant-time compare
logic adapted to stack-allocated digest buffer from integration.
2026-02-08 08:03:23 -06:00
J. Nick Koston 2ceb6ee95b Add comment explaining Windows-specific multiple_dots behavior
On Windows, Path.resolve() treats '....' as parent traversal (403),
while on Unix it is a literal directory name that stays inside the
base directory (404).
2026-02-08 07:55:48 -06:00
J. Nick Koston 4cdd73904f Encode usernames as UTF-8 bytes for hmac.compare_digest
hmac.compare_digest() on str inputs raises TypeError if either
contains non-ASCII characters. Encode both sides as UTF-8 bytes.
Add test with non-ASCII username to prevent regressions.
2026-02-08 07:49:53 -06:00
J. Nick Koston b8cad678b1 URL-encode whitespace in empty file name test parameter
Replace raw spaces with %20%20 to avoid flakiness from HTTP clients
handling unencoded spaces differently.
2026-02-08 07:48:41 -06:00
J. Nick Koston 5c5bf50e49 Update test docstring to reflect validation instead of sanitization 2026-02-08 07:41:00 -06:00
J. Nick Koston f2e1c2c650 Derive provided_len from string size and bound loop to digest_len
- Use auth.value().size() instead of strlen() to avoid rescanning
  attacker-controlled header content.
- Iterate over digest_len (expected length) instead of max_len so a
  long Authorization header cannot force extra work. The full-width
  length XOR already rejects any length mismatch.
2026-02-08 07:39:09 -06:00
J. Nick Koston 401d3c2056 Fix idedata test mock to use Path instead of str
The test set mock_image.path to str, but FlashImage.path is a Path.
This masked a pre-existing bug where Path.endswith() doesn't exist.
Fix the mock to match the real type so as_posix() works correctly.
2026-02-08 07:36:02 -06:00
J. Nick Koston 30662bc11b Update module docstring to reflect auth test coverage 2026-02-08 07:34:14 -06:00
J. Nick Koston b650d2df31 Reject empty file names and fix FlashImage.path endswith call
- Return 400 for empty or whitespace-only file_name to prevent the
  idedata fallback from matching everything via empty-string suffix.
- Use image.path.as_posix().endswith() since FlashImage.path is a Path
  object which does not have a string endswith method.
- Add parametrized test for empty/whitespace file name values.
2026-02-08 07:32:00 -06:00
J. Nick Koston bb2d7c9742 Use full-width accumulator and iterate max_len in constant-time compare
- Change result accumulator from volatile uint8_t to volatile size_t
  to prevent truncation bypass (e.g. digest_len + 256 XOR).
- Iterate over max(digest_len, provided_len) so trailing bytes in
  either string are also compared.
2026-02-08 07:25:50 -06:00
J. Nick Koston 4795971f1c Use usefixtures for tests that don't reference mock_auth_settings
Replace unused mock_auth_settings parameter with
@pytest.mark.usefixtures decorator to avoid PLW0613 lint warnings.
2026-02-08 07:25:19 -06:00
J. Nick Koston ea99593575 Build auth_settings on dashboard_settings and monkeypatch env
- Refactor auth_settings fixture to extend dashboard_settings instead
  of duplicating setup.
- Explicitly clear DISABLE_HA_AUTHENTICATION in HA add-on test to
  prevent order-dependent flakiness.
2026-02-08 07:24:44 -06:00
J. Nick Koston bf7ede1d43 Make mock_token_hex strict on unexpected nbytes
Raise ValueError for unexpected nbytes values so tests fail clearly
if production code starts calling token_hex with an incorrect size.
2026-02-08 07:24:11 -06:00
J. Nick Koston 43448d55f1 Guard against None firmware_bin_path and mock subprocess in tests
- Add None check for storage_json.firmware_bin_path before computing
  base_dir (covers configs from StorageJSON.from_wizard()).
- Mock async_run_system_command in path traversal tests so paths that
  pass validation but don't exist return 404 deterministically.
- Add test for firmware_bin_path=None case.
2026-02-08 07:23:24 -06:00
J. Nick Koston e362e6fe2f Fix multiple_dots test for Windows path resolution
On Windows, ....//secrets.yaml escapes the base directory (403),
while on Unix it stays inside (404). Use sys.platform to set the
expected status code per platform.
2026-02-08 07:22:08 -06:00
J. Nick Koston 82d9616f1b Add explicit binascii.Error catch and bad-padding test
binascii.Error is already a subclass of ValueError, but listing it
explicitly makes the intent clear. Added test for incorrect base64
padding (e.g. "Basic abc").
2026-02-08 07:18:29 -06:00
J. Nick Koston 999774889d Add comments explaining constant-time comparison logic 2026-02-08 07:17:24 -06:00
J. Nick Koston c90ca4df87 Use encoder output length and remove early return on length mismatch
Use the out length from esp_crypto_base64_encode instead of strlen.
Fold length mismatch into the accumulator to make comparison fully
constant-time without early return.
2026-02-08 07:16:19 -06:00
J. Nick Koston a167332518 Fix password_hash type and add HA add-on regression test
Initialize password_hash as b"" (bytes) to match password_hash()
return type, preventing TypeError in hmac.compare_digest when
HA add-on auth is enabled without a password.
2026-02-08 07:14:20 -06:00
J. Nick Koston 1b7efdd051 Match cnonce length to hash algorithm digest size
Use nonce_size // 2 as token_hex argument so MD5 auth produces
a 32-char cnonce and SHA256 auth produces a 64-char cnonce,
matching the original protocol behavior.

Rename mock_random fixture to mock_token_hex and use separate
mock cnonce constants per hash algorithm.
2026-02-08 07:11:56 -06:00
J. Nick Koston caff93d7b8 Add test coverage for secrets.choice in fallback PSK generation
Verifies that wizard_file uses secrets.choice (not random.choice)
to generate the 12-character fallback hotspot password.
2026-02-08 07:08:25 -06:00
J. Nick Koston 806a86a6ad Add test coverage for is_authenticated base64 handling
Tests malformed base64, invalid UTF-8, missing colon separator,
valid credentials, wrong credentials, and auth-disabled cases.
2026-02-08 07:06:24 -06:00
J. Nick Koston 42126bae72 Add test coverage for check_password
Tests correct credentials, wrong password, wrong username,
both wrong, and auth-disabled cases.
2026-02-08 07:03:29 -06:00
J. Nick Koston 803b9a7a18 Update path traversal tests for resolve/relative_to behavior
Real traversals that escape the base directory now return 403.
Paths like '....' that resolve inside the base directory but
don't exist return 404.
2026-02-08 07:01:37 -06:00
J. Nick Koston a8fd6c132e Update tests to mock secrets.token_hex instead of random.random
The cnonce generation was changed to use secrets.token_hex(32),
so the test mocks and assertions need to match.
2026-02-08 06:59:32 -06:00
J. Nick Koston 1dcffdc872 [web_server_idf] Use constant-time comparison for Basic Auth
Replace strcmp() with a constant-time XOR accumulation loop
for comparing base64-encoded credentials in HTTP Basic Auth.
2026-02-08 06:51:52 -06:00
J. Nick Koston a40c87eeed [dashboard] Use resolve/relative_to for download path validation
Replace string-based path sanitization (.replace/.lstrip) with
Path.resolve() and relative_to() validation, matching the
pattern used by other dashboard endpoints (e.g. settings.rel_path).

The previous approach was not exploitable but was inconsistent
with the rest of the codebase.
2026-02-08 06:48:38 -06:00