mirror of
https://github.com/fenleon/open-madrid.git
synced 2026-10-22 16:12:35 +00:00
Live-session port (2026-10-02→04): the packed courier codec (C19 closed — ALPN apns-pack-v1:4096:4096 negotiated live, packed chain anchors at the Apple Server Authentication CA intermediate, no TLS client cert on that path), the <Protocol>-span extraction for wrapped activation responses, the accepted Albert shapes (DeviceCertRequest as <data>(base64(PEM)), three-cert FairPlayCertChain), kebab-case sign-in response + client-id parsing, fresh anisette per SRP run and per 2FA call (the 434/-22421 fixes), the GSA postdata liveness client (fired AFTER the delegate sign-in, ptkn + hb-token binding), and the validation-stamp replay guard (one mint = one device record — the 409's true root cause); nullable next-hbi was already end-to-end
This commit is contained in:
1 parent
2efd4d0f19
commit
7f960dbdfc
25 files changed
+1138
-84
No files matched your search
@@ -149,10 +149,17 @@ object XmlPlist {
|
||||
/**
|
||||
* The Albert activation response (§1.2): an XML document whose outer `<Protocol>` block
|
||||
* wraps a plist document. Parses the plist inside the Protocol element.
|
||||
*
|
||||
* Apple sometimes wraps the `<Protocol>` inside a larger response document (rev 26,
|
||||
* live 2026-10-02: the activation answered `<Document><Protocol>…</Protocol><ScrollView>…`,
|
||||
* whose surrounding UI XML is not well-formed enough for the parser) — the Protocol block
|
||||
* is extracted by span first and parsed alone; a bare `<Protocol>` document parses as before.
|
||||
*/
|
||||
fun decodeProtocol(bytes: ByteArray): Any? {
|
||||
val text = PROTOCOL_SPAN.find(String(bytes, Charsets.UTF_8))?.value
|
||||
?: String(bytes, Charsets.UTF_8)
|
||||
val document = try {
|
||||
builder().parse(ByteArrayInputStream(bytes))
|
||||
builder().parse(ByteArrayInputStream(text.toByteArray(Charsets.UTF_8)))
|
||||
} catch (e: SAXParseException) {
|
||||
throw PlistFormatException("malformed XML at line ${e.lineNumber}: ${e.message}")
|
||||
} catch (e: Exception) {
|
||||
@@ -241,4 +248,7 @@ object XmlPlist {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/** The §1.2 activation response's `<Protocol>` span, extracted from larger documents (rev 26). */
|
||||
private val PROTOCOL_SPAN = Regex("<Protocol>.*</Protocol>", RegexOption.DOT_MATCHES_ALL)
|
||||
}
|
||||
@@ -205,4 +205,28 @@ class XmlPlistTest {
|
||||
assertFailsWith<PlistFormatException> { XmlPlist.encode(mapOf("a" to BpUid(1uL))) }
|
||||
assertFailsWith<PlistFormatException> { XmlPlist.encode(mapOf<String, Any?>("a" to null)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decodeProtocolParsesTheBareProtocolDocument() {
|
||||
val document = "<Protocol><plist version=\"1.0\"><dict><key>a</key><integer>1</integer></dict></plist></Protocol>"
|
||||
assertEquals(mapOf("a" to 1L), XmlPlist.decodeProtocol(document.toByteArray()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decodeProtocolExtractsTheSpanFromALargerResponseDocument() {
|
||||
// rev 26 (live 2026-10-02): the activation answered <Document><Protocol>…</Protocol>
|
||||
// <ScrollView>… — the surrounding UI XML is not well-formed enough for the parser, so
|
||||
// the Protocol span is extracted and parsed alone.
|
||||
val wrapped = """
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Document>
|
||||
<Protocol><plist version="1.0"><dict><key>device-activation</key><dict/></dict></plist></Protocol>
|
||||
<ScrollView xmlns="http://www.apple.com/ui" broken="& <unclosed>
|
||||
</Document>
|
||||
""".trimIndent()
|
||||
assertEquals(
|
||||
mapOf("device-activation" to emptyMap<String, Any?>()),
|
||||
XmlPlist.decodeProtocol(wrapped.toByteArray()),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user