mirror of
https://github.com/fenleon/open-madrid.git
synced 2026-10-22 16:12:35 +00:00
registration: GSA login-shape parity per the vendored source (2026-10-14 diff)
- cpd gains the hardware-identity headers (SRL-NO/MLB/ROM chained last) — the vendored get_cpd_data carries them in the login BODY; the gsservice HTTP header set does NOT (the earlier reading had this inverted). - GsaHeaderConfig.toHeaders(): drop the hardware headers, add Accept-Language (get_gsservice_headers carries it). - ProvisionedAnisette flavor doc corrected (FLAVOR_MAC=1/FLAVOR_IOS=0 — the inverted doc caused the failed vendored-state swap, GSA ec=-22421). - 'at' stays the recorded boolean false (vendored source writes Integer(0); both live-accepted).
This commit is contained in:
1 parent
478a473629
commit
f47fc49eaf
3 files changed
+29
-4
No files matched your search
+4
-1
@@ -125,7 +125,10 @@ data class ProvisionedAnisette(
|
|||||||
val mid: ByteArray,
|
val mid: ByteArray,
|
||||||
val metadata: ByteArray,
|
val metadata: ByteArray,
|
||||||
val rinfo: String,
|
val rinfo: String,
|
||||||
/** 0 = Mac, 1 = IOS (ClearAdiOtp's flavor convention; the reference's ProvisionedFlavor). */
|
/** 0 = IOS-era provisioning, 1 = Mac (ClearAdiOtp's flavor convention — FLAVOR_MAC=1,
|
||||||
|
* FLAVOR_IOS=0; the pre-2026-10-14 doc had this inverted and caused the failed
|
||||||
|
* vendored-state swap: a Mac MID written with flavor 0 dispatches the wrong OTP
|
||||||
|
* cipher → GSA ec=-22421). */
|
||||||
val flavor: Int,
|
val flavor: Int,
|
||||||
) {
|
) {
|
||||||
fun toJson(): String = buildJsonObject {
|
fun toJson(): String = buildJsonObject {
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ enum class GsaFlavor(
|
|||||||
* `X-Apple-Security-Upgrade-Context` = `com.apple.authkit.generic`, `cou` = `US`,
|
* `X-Apple-Security-Upgrade-Context` = `com.apple.authkit.generic`, `cou` = `US`,
|
||||||
* `loc` = `en_US`, and the booleans `X-Apple-Offer-Security-Upgrade`=true, `bootstrap`=true,
|
* `loc` = `en_US`, and the booleans `X-Apple-Offer-Security-Upgrade`=true, `bootstrap`=true,
|
||||||
* `ckgen`=true, `fcd`=true, `icdrsDisabled`=false, `icscrec`=true, `pbe`=false,
|
* `ckgen`=true, `fcd`=true, `icdrsDisabled`=false, `icscrec`=true, `pbe`=false,
|
||||||
* `prkgen`=true, `webAccessEnabled`=false, `at`=0 (the spec lists `at` among the booleans
|
* `prkgen`=true, `webAccessEnabled`=false, `at`=false (the recorded wire value is the plist
|
||||||
* but records its value as `0`; encoded as the plist boolean false).
|
* boolean false from a genuine Mac capture; the vendored Rust source writes Integer(0) —
|
||||||
|
* both live-accepted, the recording wins).
|
||||||
*/
|
*/
|
||||||
class GsaCpd(
|
class GsaCpd(
|
||||||
/** The §1.1 anisette headers (from [AnisetteHeaderProvider.headers]). */
|
/** The §1.1 anisette headers (from [AnisetteHeaderProvider.headers]). */
|
||||||
@@ -75,6 +76,14 @@ class GsaCpd(
|
|||||||
val flavor: GsaFlavor = GsaFlavor.MESSAGES,
|
val flavor: GsaFlavor = GsaFlavor.MESSAGES,
|
||||||
/** Optional APNs token (`ptkn`). */
|
/** Optional APNs token (`ptkn`). */
|
||||||
private val apnsToken: String? = null,
|
private val apnsToken: String? = null,
|
||||||
|
/**
|
||||||
|
* The Mac hardware-identity headers (§1.1) — chained into the cpd dict like the
|
||||||
|
* vendored reference's cpd construction (icloud-auth anisette.rs `get_cpd_data` chains
|
||||||
|
* `client_info.hardware_headers` LAST). This is the login-body machine anchor: the
|
||||||
|
* gsservice HTTP header set does NOT carry them (2026-10-14 source diff — the earlier
|
||||||
|
* reading had them as login HTTP headers and missing from the cpd, inverted).
|
||||||
|
*/
|
||||||
|
val hardwareHeaders: Map<String, String> = emptyMap(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/** The cpd dict for one login; [requestUuid] is the uppercase UUIDv4 shared by both steps. */
|
/** The cpd dict for one login; [requestUuid] is the uppercase UUIDv4 shared by both steps. */
|
||||||
@@ -92,6 +101,8 @@ class GsaCpd(
|
|||||||
dict["loc"] = "en_US"
|
dict["loc"] = "en_US"
|
||||||
dict["svct"] = flavor.akContextType
|
dict["svct"] = flavor.akContextType
|
||||||
dict["X-Apple-Offer-Security-Upgrade"] = true
|
dict["X-Apple-Offer-Security-Upgrade"] = true
|
||||||
|
// The recorded wire value is the boolean false (genuine Mac capture); the vendored
|
||||||
|
// Rust source writes Integer(0) — both live-accepted, keep the recording (2026-10-14).
|
||||||
dict["at"] = false
|
dict["at"] = false
|
||||||
dict["bootstrap"] = true
|
dict["bootstrap"] = true
|
||||||
dict["ckgen"] = true
|
dict["ckgen"] = true
|
||||||
@@ -102,6 +113,7 @@ class GsaCpd(
|
|||||||
dict["prkgen"] = true
|
dict["prkgen"] = true
|
||||||
dict["webAccessEnabled"] = false
|
dict["webAccessEnabled"] = false
|
||||||
apnsToken?.let { dict["ptkn"] = it }
|
apnsToken?.let { dict["ptkn"] = it }
|
||||||
|
hardwareHeaders.forEach { (key, value) -> dict[key] = value }
|
||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,13 +194,21 @@ data class GsaHeaderConfig(
|
|||||||
val signInClientInfo: String
|
val signInClientInfo: String
|
||||||
get() = "<$hardwareModel> <${osName};${osVersion};${osBuild}> <$AOSKIT_CLIENT_INFO>"
|
get() = "<$hardwareModel> <${osName};${osVersion};${osBuild}> <$AOSKIT_CLIENT_INFO>"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GSA login POST header set — the vendored reference's `get_gsservice_headers`
|
||||||
|
* (icloud-auth anisette.rs, 2026-10-14 source diff): the akd `User-Agent`, the akd
|
||||||
|
* `X-MMe-Client-Info`, the flavor's context/bundle headers and `Accept-Language`. The
|
||||||
|
* hardware-identity headers are NOT here — the reference carries them inside the cpd
|
||||||
|
* dict only ([GsaCpd.hardwareHeaders]).
|
||||||
|
*/
|
||||||
fun toHeaders(): Map<String, String> = linkedMapOf(
|
fun toHeaders(): Map<String, String> = linkedMapOf(
|
||||||
"X-MMe-Client-Info" to clientInfo,
|
"X-MMe-Client-Info" to clientInfo,
|
||||||
"User-Agent" to AKD_USER_AGENT,
|
"User-Agent" to AKD_USER_AGENT,
|
||||||
"X-Apple-AK-Context-Type" to flavor.akContextType,
|
"X-Apple-AK-Context-Type" to flavor.akContextType,
|
||||||
"X-Apple-Client-App-Name" to flavor.clientAppName,
|
"X-Apple-Client-App-Name" to flavor.clientAppName,
|
||||||
"X-Apple-I-Client-Bundle-Id" to flavor.clientBundleId,
|
"X-Apple-I-Client-Bundle-Id" to flavor.clientBundleId,
|
||||||
) + hardwareHeaders
|
"Accept-Language" to "en-US,en;q=0.9",
|
||||||
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The recorded akd `User-Agent` literal (§1.5, C59). */
|
/** The recorded akd `User-Agent` literal (§1.5, C59). */
|
||||||
|
|||||||
@@ -163,6 +163,8 @@ class GsaCpdTest {
|
|||||||
"X-Apple-AK-Context-Type" to "imessage",
|
"X-Apple-AK-Context-Type" to "imessage",
|
||||||
"X-Apple-Client-App-Name" to "Messages",
|
"X-Apple-Client-App-Name" to "Messages",
|
||||||
"X-Apple-I-Client-Bundle-Id" to "com.apple.MobileSMS",
|
"X-Apple-I-Client-Bundle-Id" to "com.apple.MobileSMS",
|
||||||
|
// The vendored reference's get_gsservice_headers carries it (2026-10-14 source diff).
|
||||||
|
"Accept-Language" to "en-US,en;q=0.9",
|
||||||
),
|
),
|
||||||
headers,
|
headers,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in new issue
Block a user