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

Implementation of the pure URL / address safety predicates. More...

#include "mdl_url_guard.h"
#include <arpa/inet.h>
#include <string.h>
#include "ra8_attributes.h"
Include dependency graph for mdl_url_guard.c:

Go to the source code of this file.

Enumerations

enum  mdl_v4_index_t : uint8_t {
  k_v4_o0 = 0 ,
  k_v4_o1 = 1
}
 IPv4 address byte layout used while classifying. More...
enum  mdl_v4_range_t : uint16_t {
  k_v4_zero_net = 0 ,
  k_v4_loopback_net = 127 ,
  k_v4_private_a = 10 ,
  k_v4_private_b = 172 ,
  k_v4_private_b_lo = 16 ,
  k_v4_private_b_hi = 31 ,
  k_v4_private_c = 192 ,
  k_v4_private_c_2 = 168 ,
  k_v4_linklocal = 169 ,
  k_v4_linklocal_2 = 254 ,
  k_v4_cgnat = 100 ,
  k_v4_cgnat_lo = 64 ,
  k_v4_cgnat_hi = 127 ,
  k_v4_multicast_min = 224
}
 IPv4 range boundaries that mark non-public address space. More...
enum  mdl_v6_index_t : uint8_t {
  k_v6_bytes = 16 ,
  k_v6_mapped_ff_a = 10 ,
  k_v6_mapped_ff_b = 11 ,
  k_v6_mapped_v4 = 12 ,
  k_v6_last = 15
}
 IPv6 address byte layout and the bytes classification inspects. More...
enum  mdl_v6_prefix_t : uint16_t {
  k_v6_byte_ff = 0xFF ,
  k_v6_ula_mask = 0xFE ,
  k_v6_ula_value = 0xFC ,
  k_v6_ll_lead = 0xFE ,
  k_v6_ll_mask = 0xC0 ,
  k_v6_ll_value = 0x80 ,
  k_v6_loopback_last = 0x01
}
 IPv6 prefix byte values that mark non-public address space. More...

Functions

static bool internal_starts_with_ci (const char *s, const char *prefix)
 Case-insensitive test that s begins with prefix.
bool mdl_url_scheme_allowed (const char *url)
 True when url uses an allowlisted scheme (http:// or https://).
static mdl_addr_class_t internal_classify_v4 (const unsigned char *o)
 Classify the four octets of an IPv4 address.
static bool internal_is_v4_mapped (const unsigned char *b)
 True if the 16 IPv6 bytes carry an IPv4-mapped ::ffff:a.b.c.d.
static bool internal_is_v6_loopback (const unsigned char *b)
 True if the 16 IPv6 bytes are the loopback address ::1.
static mdl_addr_class_t internal_classify_v6 (const unsigned char *b)
 Classify the sixteen bytes of an IPv6 address.
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.

Variables

static const char *const s_scheme_http = "http://"
 Scheme prefixes accepted by mdl_url_scheme_allowed.
static const char *const s_scheme_https = "https://"

Detailed Description

Implementation of the pure URL / address safety predicates.

Classifies schemes, hosts, and numeric addresses without network I/O so callers can reject unsafe origins before dispatch.

Definition in file mdl_url_guard.c.

Enumeration Type Documentation

◆ mdl_v4_index_t

enum mdl_v4_index_t : uint8_t

IPv4 address byte layout used while classifying.

Enumerator
k_v4_o0 

First octet index.

k_v4_o1 

Second octet index.

Definition at line 17 of file mdl_url_guard.c.

◆ mdl_v4_range_t

enum mdl_v4_range_t : uint16_t

IPv4 range boundaries that mark non-public address space.

Enumerator
k_v4_zero_net 

0.0.0.0/8 "this network" (unspecified).

k_v4_loopback_net 

127.0.0.0/8 loopback.

k_v4_private_a 

10.0.0.0/8.

k_v4_private_b 

172.16.0.0/12 first octet.

k_v4_private_b_lo 

172.16 low second octet (inclusive).

k_v4_private_b_hi 

172.31 high second octet (inclusive).

k_v4_private_c 

192.168.0.0/16 first octet.

k_v4_private_c_2 

192.168 second octet.

k_v4_linklocal 

169.254.0.0/16 first octet.

k_v4_linklocal_2 

169.254 second octet.

k_v4_cgnat 

100.64.0.0/10 (RFC6598) first octet.

k_v4_cgnat_lo 

100.64 low second octet (inclusive).

k_v4_cgnat_hi 

100.127 high second octet (inclusive).

k_v4_multicast_min 

224.0.0.0/4 and up: multicast/reserved.

Definition at line 23 of file mdl_url_guard.c.

◆ mdl_v6_index_t

enum mdl_v6_index_t : uint8_t

IPv6 address byte layout and the bytes classification inspects.

Enumerator
k_v6_bytes 

Total bytes in an IPv6 address.

k_v6_mapped_ff_a 

First 0xFF byte of an IPv4-mapped prefix.

k_v6_mapped_ff_b 

Second 0xFF byte of the mapped prefix.

k_v6_mapped_v4 

Offset of the embedded IPv4 address.

k_v6_last 

Index of the final byte (for ::1).

Definition at line 41 of file mdl_url_guard.c.

◆ mdl_v6_prefix_t

enum mdl_v6_prefix_t : uint16_t

IPv6 prefix byte values that mark non-public address space.

Enumerator
k_v6_byte_ff 

Multicast lead byte / mapped filler.

k_v6_ula_mask 

Mask isolating the fc00::/7 prefix.

k_v6_ula_value 

fc00::/7 unique-local value.

k_v6_ll_lead 

fe80::/10 lead byte.

k_v6_ll_mask 

Mask isolating the /10 boundary.

k_v6_ll_value 

fe80::/10 masked value.

k_v6_loopback_last 

Final byte of ::1.

Definition at line 50 of file mdl_url_guard.c.

Function Documentation

◆ internal_classify_v4()

mdl_addr_class_t internal_classify_v4 ( const unsigned char * o)
static

Classify the four octets of an IPv4 address.

Classifies ASCII URL and address bytes without locale side effects. Inputs stay borrowed for the call and no caller object is retained.

Parameters
[in]oFour parsed IPv4 octets.
Returns
Address class of the four octets in o.
Return values
k_mdl_addr_publicRoutable public address.
k_mdl_addr_privatePrivate or carrier-grade NAT address.
k_mdl_addr_loopbackLoopback address.
k_mdl_addr_linklocalLink-local address.
k_mdl_addr_unknownUnspecified, multicast, or reserved address.
Precondition
Every required pointer is non-null and remains valid for the call.
Lengths and capacities describe complete referenced objects without overflow.
Postcondition
Documented outputs and the return value describe the same outcome.
A rejected or failed operation is never reported as successful.
Note
Thread safety follows ownership of the supplied context; no synchronization is added.
Since
Version 0.1.0

Definition at line 122 of file mdl_url_guard.c.

References k_mdl_addr_linklocal, k_mdl_addr_loopback, k_mdl_addr_private, k_mdl_addr_public, k_mdl_addr_unknown, k_v4_cgnat, k_v4_cgnat_hi, k_v4_cgnat_lo, k_v4_linklocal, k_v4_linklocal_2, k_v4_loopback_net, k_v4_multicast_min, k_v4_o0, k_v4_o1, k_v4_private_a, k_v4_private_b, k_v4_private_b_hi, k_v4_private_b_lo, k_v4_private_c, k_v4_private_c_2, k_v4_zero_net, and RA8_INTERNAL.

Referenced by internal_classify_v6(), and mdl_classify_ip().

◆ internal_classify_v6()

mdl_addr_class_t internal_classify_v6 ( const unsigned char * b)
static

Classify the sixteen bytes of an IPv6 address.

Classifies ASCII URL and address bytes without locale side effects. Inputs stay borrowed for the call and no caller object is retained.

Parameters
[in]bSixteen parsed IPv6 address bytes.
Returns
Address class of the sixteen bytes in b.
Return values
k_mdl_addr_publicRoutable public address.
k_mdl_addr_privateIPv4-mapped private address.
k_mdl_addr_loopbackIPv6 or mapped IPv4 loopback address.
k_mdl_addr_linklocalLink-local address.
k_mdl_addr_unknownMulticast or unsupported address.
Precondition
Every required pointer is non-null and remains valid for the call.
Lengths and capacities describe complete referenced objects without overflow.
Postcondition
Documented outputs and the return value describe the same outcome.
A rejected or failed operation is never reported as successful.
Note
Thread safety follows ownership of the supplied context; no synchronization is added.
Since
Version 0.1.0

Definition at line 213 of file mdl_url_guard.c.

References internal_classify_v4(), internal_is_v4_mapped(), internal_is_v6_loopback(), k_mdl_addr_linklocal, k_mdl_addr_loopback, k_mdl_addr_private, k_mdl_addr_public, k_mdl_addr_unknown, k_v4_o0, k_v4_o1, k_v6_byte_ff, k_v6_ll_lead, k_v6_ll_mask, k_v6_ll_value, k_v6_mapped_v4, k_v6_ula_mask, k_v6_ula_value, and RA8_INTERNAL.

Referenced by mdl_classify_ip().

◆ internal_is_v4_mapped()

bool internal_is_v4_mapped ( const unsigned char * b)
static

True if the 16 IPv6 bytes carry an IPv4-mapped ::ffff:a.b.c.d.

Classifies ASCII URL and address bytes without locale side effects. Inputs stay borrowed for the call and no caller object is retained.

Parameters
[in]bSixteen parsed IPv6 address bytes.
Returns
True when b contains an IPv4-mapped IPv6 address.
Return values
trueThe documented predicate holds or the requested operation completed.
falseThe predicate does not hold or validation rejected the operation.
Precondition
Every required pointer is non-null and remains valid for the call.
Lengths and capacities describe complete referenced objects without overflow.
Postcondition
Documented outputs and the return value describe the same outcome.
A rejected or failed operation is never reported as successful.
Note
Thread safety follows ownership of the supplied context; no synchronization is added.
Since
Version 0.1.0

Definition at line 161 of file mdl_url_guard.c.

References k_v6_byte_ff, k_v6_mapped_ff_a, k_v6_mapped_ff_b, and RA8_INTERNAL.

Referenced by internal_classify_v6().

◆ internal_is_v6_loopback()

bool internal_is_v6_loopback ( const unsigned char * b)
static

True if the 16 IPv6 bytes are the loopback address ::1.

Classifies ASCII URL and address bytes without locale side effects. Inputs stay borrowed for the call and no caller object is retained.

Parameters
[in]bSixteen parsed IPv6 address bytes.
Returns
True when b is exactly the IPv6 loopback address.
Return values
trueThe documented predicate holds or the requested operation completed.
falseThe predicate does not hold or validation rejected the operation.
Precondition
Every required pointer is non-null and remains valid for the call.
Lengths and capacities describe complete referenced objects without overflow.
Postcondition
Documented outputs and the return value describe the same outcome.
A rejected or failed operation is never reported as successful.
Note
Thread safety follows ownership of the supplied context; no synchronization is added.
Since
Version 0.1.0

Definition at line 186 of file mdl_url_guard.c.

References k_v6_last, k_v6_loopback_last, and RA8_INTERNAL.

Referenced by internal_classify_v6().

◆ internal_starts_with_ci()

bool internal_starts_with_ci ( const char * s,
const char * prefix )
static

Case-insensitive test that s begins with prefix.

Classifies ASCII URL and address bytes without locale side effects. Inputs stay borrowed for the call and no caller object is retained.

Parameters
[in]sReadable text or byte sequence.
[in]prefixPrefix to compare.
Returns
True when s begins with prefix ignoring ASCII case.
Return values
trueThe documented predicate holds or the requested operation completed.
falseThe predicate does not hold or validation rejected the operation.
Precondition
Every required pointer is non-null and remains valid for the call.
Lengths and capacities describe complete referenced objects without overflow.
Postcondition
Documented outputs and the return value describe the same outcome.
A rejected or failed operation is never reported as successful.
Note
Thread safety follows ownership of the supplied context; no synchronization is added.
Since
Version 0.1.0

Definition at line 79 of file mdl_url_guard.c.

References RA8_INTERNAL.

Referenced by mdl_url_scheme_allowed().

◆ 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().

Variable Documentation

◆ s_scheme_http

const char* const s_scheme_http = "http://"
static

Scheme prefixes accepted by mdl_url_scheme_allowed.

Definition at line 61 of file mdl_url_guard.c.

Referenced by mdl_url_scheme_allowed().

◆ s_scheme_https

const char* const s_scheme_https = "https://"
static

Definition at line 62 of file mdl_url_guard.c.

Referenced by mdl_url_scheme_allowed().