ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_url_guard.h File Reference

Pure URL / address safety predicates for the libcurl backend. More...

#include <stddef.h>
#include <stdint.h>
Include dependency graph for mdl_url_guard.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  mdl_addr_class_t : uint8_t {
  k_mdl_addr_public = 0 ,
  k_mdl_addr_loopback = 1 ,
  k_mdl_addr_private = 2 ,
  k_mdl_addr_linklocal = 3 ,
  k_mdl_addr_unknown = 4
}
 Reachability class of a resolved peer address. More...

Functions

bool mdl_url_scheme_allowed (const char *url)
 True when url uses an allowlisted scheme (http:// or https://).
mdl_addr_class_t mdl_classify_ip (const char *ip)
 Classify a resolved peer IP string into a mdl_addr_class_t.
bool mdl_addr_is_fetchable (mdl_addr_class_t cls, bool allow_private)
 Decide whether an address class is fetchable under the active policy.
bool mdl_size_exceeds (uint64_t have, uint64_t add, uint64_t cap)
 True when appending add bytes to have would exceed cap.
bool mdl_url_host (const char *url, char *out, size_t cap)
 Extract the authority (host and optional port) from an http(s) URL.
bool mdl_url_path (const char *url, char *out, size_t cap)
 Extract the path (with leading /, without query/fragment) from a URL.

Detailed Description

Pure URL / address safety predicates for the libcurl backend.

mdl fetches attacker-influenced URLs by design: the first URL comes from argv or a config, and every subsequent image URL is extracted from hostile HTML. The libcurl backend (mdl_net_curl.c) must therefore refuse a file:// read, refuse a redirect that resolves to loopback / private / link-local address space (the SSRF sharp edge), and bound a response's size.

The decisions themselves are pure functions with no libcurl dependency so they are unit-testable host-side without a network seam: the backend calls them, and the tests call them directly. Address classification uses the host's inet_pton rather than a hand-rolled parser – this is host tooling, not firmware, so the platform's battle-tested parser is the right choice.

Definition in file mdl_url_guard.h.

Enumeration Type Documentation

◆ mdl_addr_class_t

enum mdl_addr_class_t : uint8_t

Reachability class of a resolved peer address.

The SSRF guard maps every resolved IP into one of these buckets and then asks mdl_addr_is_fetchable whether the active policy permits it. Only k_mdl_addr_public is fetchable by default; the rest name the address spaces a hostile page would use to turn the downloader into a fetch primitive against the local host or network.

Invariant
An address that inet_pton cannot parse is k_mdl_addr_unknown, which is never fetchable under any policy.
See also
mdl_classify_ip()
mdl_addr_is_fetchable()
Since
0.1.0
Enumerator
k_mdl_addr_public 

Routable public unicast address.

k_mdl_addr_loopback 

127.0.0.0/8 or ::1.

k_mdl_addr_private 

RFC1918, RFC6598 (CGNAT), or fc00::/7.

k_mdl_addr_linklocal 

169.254.0.0/16 or fe80::/10.

k_mdl_addr_unknown 

Unparseable, unspecified, or reserved.

Definition at line 43 of file mdl_url_guard.h.

Function Documentation

◆ mdl_addr_is_fetchable()

bool mdl_addr_is_fetchable ( mdl_addr_class_t cls,
bool allow_private )

Decide whether an address class is fetchable under the active policy.

k_mdl_addr_public is always fetchable. Loopback, private and link-local addresses are fetchable only when allow_private is set (the explicit --allow-private opt-in). k_mdl_addr_unknown is never fetchable, so an address the parser could not classify can never be reached even with the opt-in.

Parameters
[in]clsAddress class from mdl_classify_ip.
[in]allow_privateWhether the private-space opt-in is active.
Returns
Whether a fetch to an address of this class is permitted.
Return values
trueThe class is public, or private-space and the opt-in is set.
falseThe class is unknown, or private-space without the opt-in.
Precondition
cls is a value produced by mdl_classify_ip.
allow_private reflects the caller's --allow-private flag.
Postcondition
No state is modified.
The return is a pure function of the two arguments.
Note
Thread-safe: depends only on its arguments.
Since
0.1.0

Definition at line 250 of file mdl_url_guard.c.

References k_mdl_addr_public, and k_mdl_addr_unknown.

Referenced by internal_on_prereq().

◆ mdl_classify_ip()

mdl_addr_class_t mdl_classify_ip ( const char * ip)

Classify a resolved peer IP string into a mdl_addr_class_t.

Accepts either dotted-quad IPv4 or an IPv6 literal (including the IPv4-mapped ::ffff:a.b.c.d form, which is unwrapped and classified as IPv4). Anything inet_pton rejects, plus the unspecified and multicast/reserved ranges, becomes k_mdl_addr_unknown so the caller fails closed.

Parameters
[in]ipResolved address literal (e.g. libcurl's CURLINFO_PRIMARY_IP), or NULL.
Returns
The reachability class of ip.
Return values
k_mdl_addr_publicRoutable public unicast.
k_mdl_addr_loopback127.0.0.0/8 or ::1.
k_mdl_addr_privateRFC1918 / RFC6598 / fc00::/7.
k_mdl_addr_linklocal169.254.0.0/16 or fe80::/10.
k_mdl_addr_unknownNULL, unparseable, unspecified, or reserved.
Precondition
ip, when non-NULL, is a NUL-terminated string.
The caller maps k_mdl_addr_unknown to a refusal.
Postcondition
ip is not modified.
No allocation or I/O is performed.
Note
Thread-safe: inet_pton writes only caller-local storage.
Since
0.1.0

Definition at line 234 of file mdl_url_guard.c.

References internal_classify_v4(), internal_classify_v6(), and k_mdl_addr_unknown.

Referenced by internal_on_prereq().

◆ mdl_size_exceeds()

bool mdl_size_exceeds ( uint64_t have,
uint64_t add,
uint64_t cap )

True when appending add bytes to have would exceed cap.

Overflow-safe running-total check for the response-size cap enforced in the write callbacks. A cap of zero means "no cap" and always returns false, matching libcurl's own convention for unlimited transfer options.

Parameters
[in]haveBytes already accepted.
[in]addBytes about to be appended.
[in]capMaximum permitted total, or 0 for unlimited.
Returns
Whether accepting add would breach cap.
Return values
truecap is non-zero and have + add > cap.
falsecap is zero, or the total still fits.
Precondition
have <= cap or cap == 0 (the running total never starts over cap).
The caller aborts the transfer when the result is true.
Postcondition
No state is modified.
Note
Thread-safe: depends only on its arguments.
Since
0.1.0
Postcondition
Documented outputs and the return value describe the same outcome.

Definition at line 261 of file mdl_url_guard.c.

Referenced by priv_mdl_net_curl_body_write().

◆ mdl_url_host()

bool mdl_url_host ( const char * url,
char * out,
size_t cap )

Extract the authority (host and optional port) from an http(s) URL.

Copies the host[:port] of url into out, lower-cased, dropping any scheme://, user:pass@ userinfo, and trailing path. The port is kept: a robots.txt policy and a same-host redirect check are both scoped per (scheme, host, port) origin, so :8080 is part of the identity. A URL with no recognisable authority yields an empty string and a false return.

Parameters
[in]urlURL to inspect (NUL-terminated), or NULL.
[out]outDestination buffer for the NUL-terminated host.
[in]capCapacity of out in bytes.
Returns
Whether a host was extracted and fit in out.
Return values
trueA non-empty host was written to out.
falseurl/out was NULL, cap was 0, no authority was found, or the host did not fit.
Precondition
out, when non-NULL, has room for at least cap bytes.
url, when non-NULL, is a NUL-terminated string.
Postcondition
On false, out[0] is set to '\0' when cap > 0.
url is not modified.
Note
Thread-safe: writes only caller-provided storage.
Since
0.1.0

Definition at line 272 of file mdl_url_guard.c.

References strchr(), and strstr().

Referenced by internal_apply_req(), internal_cache_paths(), internal_cache_record_valid(), internal_discover_fetch(), internal_init_site_identity(), internal_mdl_fetch_chapter_html(), internal_mdl_fetch_page_host(), internal_mdl_fetch_page_host(), internal_redirect_host_ok(), mdl_session_url_allowed(), priv_mdl_app_ensure_series_cover(), and priv_mdl_export_validate_source_url().

◆ mdl_url_path()

bool mdl_url_path ( const char * url,
char * out,
size_t cap )

Extract the path (with leading /, without query/fragment) from a URL.

Copies the path component of an http(s) URL into out, defaulting to "/" when the authority is followed by no path. The query string and fragment are dropped. Used to test a target against parsed robots.txt rules, which match on the path only.

Parameters
[in]urlURL to inspect (NUL-terminated), or NULL.
[out]outDestination buffer for the NUL-terminated path.
[in]capCapacity of out in bytes.
Returns
Whether a path was written (including the "/" default).
Return values
trueA path (possibly "/") was written to out.
falseurl/out was NULL, cap was 0, no authority was found, or the path did not fit.
Precondition
out, when non-NULL, has room for at least cap bytes.
url, when non-NULL, is a NUL-terminated string.
Postcondition
On false with cap > 0, out[0] is '\0'.
url is not modified.
Note
Thread-safe: writes only caller-provided storage.
Since
0.1.0

Definition at line 311 of file mdl_url_guard.c.

References strchr(), and strstr().

◆ mdl_url_scheme_allowed()

bool mdl_url_scheme_allowed ( const char * url)

True when url uses an allowlisted scheme (http:// or https://).

The scheme test is case-insensitive and anchored at the start of the string, so file://, ftp://, gopher://, data: and every other scheme are rejected. It is a belt-and-suspenders complement to libcurl's CURLOPT_PROTOCOLS_STR: the option pins the transport, this refuses the URL before it is ever handed to libcurl.

Parameters
[in]urlCandidate URL, or NULL.
Returns
Whether the scheme is on the allowlist.
Return values
trueurl begins with http:// or https://.
falseurl is NULL, empty, or uses any other scheme.
Precondition
url, when non-NULL, is a NUL-terminated string.
The caller treats false as a hard refusal, not a warning.
Postcondition
url is not modified.
No allocation or I/O is performed.
Note
Thread-safe: depends only on its argument.
Since
0.1.0

Definition at line 96 of file mdl_url_guard.c.

References internal_starts_with_ci(), s_scheme_http, and s_scheme_https.

Referenced by internal_curl_get_body(), internal_curl_get_buf(), and priv_mdl_export_validate_source_url().