Skip to content

Commit 1ddd1d8

Browse files
docs(psl): clarify DAFSA reader deviations from libpsl
Module docs now call out the two intentional deviations from libpsl's psl_is_public_suffix: no prevailing-star rule for unknown single-label TLDs (so localhost works as its own rp.id), and no multibyte key support (WebAuthn only ever passes IDN-ASCII, and the DAFSA stores IDN rules in punycode form regardless of encoding mode). Test comment for the exception-overrides-wildcard case rewritten to describe the actual lookup chain rather than conflating two mechanisms.
1 parent 8ad6308 commit 1ddd1d8

1 file changed

Lines changed: 21 additions & 9 deletions

File tree

  • libwebauthn/src/ops/webauthn/psl

libwebauthn/src/ops/webauthn/psl/dafsa.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,18 @@
33
//! Format reference: <https://github.com/rockdaboot/libpsl/blob/master/src/psl-make-dafsa>
44
//! (writer) and <https://github.com/rockdaboot/libpsl/blob/master/src/lookup_string_in_fixed_set.c>
55
//! (reader). The on-disk file is a 16-byte ASCII header (`.DAFSA@PSL_<ver>` padded
6-
//! to 16 bytes with spaces and terminated by LF) followed by a byte-coded DAFSA.
7-
//! Only version 0 exists today.
6+
//! to 16 bytes with spaces and terminated by LF) followed by a byte-coded DAFSA,
7+
//! optionally with a trailing `0x01` byte in UTF-8 mode. Only version 0 exists today.
8+
//!
9+
//! Deviations from libpsl `psl_is_public_suffix`:
10+
//!
11+
//! * No prevailing `*` rule for unknown single-label TLDs. libpsl treats any
12+
//! single-label host as a public suffix; this reader returns `None`, so
13+
//! `localhost` can be used as a relying-party id against itself.
14+
//! * Multibyte (UTF-8) keys are not supported. WebAuthn rp.ids and origin
15+
//! hosts are always IDN-ASCII (punycode) by the time they reach the PSL,
16+
//! and the DAFSA stores IDN rules in punycode form regardless of its
17+
//! internal encoding mode, so ASCII queries match correctly.
818
919
use std::path::{Path, PathBuf};
1020

@@ -180,6 +190,7 @@ fn lookup(graph: &[u8], key: &[u8]) -> Option<u8> {
180190
}
181191
offset += 1;
182192
key_pos += 1;
193+
// Dive into the child node.
183194
pos = offset;
184195
}
185196
None
@@ -328,14 +339,15 @@ mod tests {
328339
#[test]
329340
fn public_suffix_exception_overrides_wildcard() {
330341
let psl = loaded();
331-
// foo.kw has the exception flag, so it is NOT a public suffix even
332-
// though *.kw would otherwise make it one. The longest suffix that
333-
// applies is `kw` itself (which is a suffix because *.kw implicitly
334-
// makes the parent a public suffix per the libpsl/PSL algorithm).
342+
// foo.kw has the EXCEPTION flag so direct lookup returns "not a
343+
// suffix"; the search then strips a label to "kw", which is in the
344+
// DAFSA with the WILDCARD flag (no EXCEPTION), so kw itself is the
345+
// public suffix.
335346
assert_eq!(psl.public_suffix("foo.kw").as_deref(), Some("kw"));
336-
// The exception rule matches sub.foo.kw too (its rightmost two
337-
// labels are foo.kw), so the prevailing rule is the exception with
338-
// its leftmost label stripped, giving "kw".
347+
// For sub.foo.kw: exact lookup misses; parent foo.kw is found but
348+
// has no WILDCARD bit, so the wildcard-fallback rejects it; the
349+
// search then strips down to foo.kw (still excepted) and finally to
350+
// kw (wildcard, suffix).
339351
assert_eq!(psl.public_suffix("sub.foo.kw").as_deref(), Some("kw"));
340352
}
341353

0 commit comments

Comments
 (0)