## What does this PR do?
Adds Apple G2 & G3 Root CAs to Linux trust root. Fixes#339.
Apple now uses gsd.apple.com for part of the auth flow, which uses the
G3 root.
## How was it tested?
Tried to log in on Linux. Failed before, works after.
## AI tool usage
How much of this PR was AI-assisted? (check one)
- [x] **0** - No AI was used to write code
- [ ] **1** - I was assisted by AI. I reviewed the finished result.
- [ ] **2** - I set the AI going and left it to it; nobody has read the
result - no review, or AI review only
<!-- If an AI agent is filling this in: declare the level honestly, and
open as a draft if it is #2. Do not lower the declared level to get the
PR reviewed. -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved TLS certificate trust on Linux by recognizing Apple Root CA,
G2, and G3 certificates when verifying secure connections. Existing TLS
validation behavior remains unchanged.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What does this PR do?
Improves support for HTTP MITM
## How was it tested?
Did some MITMing on macOS + Linux via Docker, using Proxyman and
mitmproxy. Didn't test `XTL_HTTP_PROXY` but Sol pinkie promises me that
it's correct.
## AI tool usage
How much of this PR was AI-assisted? (check one)
- [ ] **0** - No AI was used to write code
- [x] **1** - I was assisted by AI. I reviewed the finished result.
- [ ] **2** - I set the AI going and left it to it; nobody has read the
result - no review, or AI review only
<!-- If an AI agent is filling this in: declare the level honestly, and
open as a draft if it is #2. Do not lower the declared level to get the
PR reviewed. -->
Ref #243. `makeRequest` never inspected `response.status`, so a non-2xx
body was
returned as if it had succeeded. Every caller decodes that body as a
property list
or JSON, so Apple answering with an HTML error page surfaced as:
```
Error: DecodingError.dataCorrupted: Data was corrupted. Debug description: The given
data was not a valid property list.. Underlying error: ... Encountered unknown tag
html on line 1
```
which says nothing about what actually happened. In the case that
prompted #243, GSA
was returning `503 Service Temporarily Unavailable` for the `apptokens`
operation. It
now reads:
```
Error: POST https://gsa.apple.com/grandslam/GsService2 failed: HTTP 503 Service
Unavailable (text/html): <html> <head><title>503 Service Temporarily
Unavailable</title></head> ...
```
### Notes
- The response body is only included in the message for `text/html` and
`text/plain`,
i.e. gateway error pages. Bodies from the auth endpoints can carry
account details
(the 2FA requests use `Accept: application/x-buddyml`), and errors get
printed
verbatim in places such as `DevCommand.swift:164`, so those are left
out. It also
avoids emitting replacement characters for binary bodies.
- The non-2xx path does not report progress, so `XADIProvider`'s
download no longer
prints `100%` immediately before failing.
- Body collection moved to `collect(_:onProgress:)` so there is a single
exit point.
Buffer pre-sizing and progress reporting are unchanged.
- `SDKBuilder` already does this check by hand on `send()`, so it is
unaffected.
### Behaviour changes worth a look
- `XADIProvider` writes the Apple Music APK download straight to disk; a
failed
download now throws instead of leaving a corrupt `applemusic.apk`.
- The 2FA requests (`GrandSlamTrustedDeviceRequest`,
`GrandSlamSMSAuthRequest`,
`GrandSlamValidateRequest`) use no-op decoders, so a rejected request is
currently
discarded and xtool goes on to prompt for a code that was never sent —
the symptom
in #235. Those now fail loudly.
### Two things I left alone
- `GrandSlamTwoFactorAuthenticateOperation.swift:47` catches
`GrandSlamOperationError`
with code `-21669` to report an incorrect verification code, but that
error is only
thrown by `GrandSlamOperationDecoder`, which the validate requests do
not use, so the
catch is unreachable. With this change a wrong code surfaces as a raw
HTTP error
instead. Mapping the status back to `incorrectVerificationCode` seemed
like your call,
since I do not know what GSA returns for a bad code.
- If any endpoint reports errors in a decodable body under a non-2xx
status, this guard
would pre-empt it. I could not find one — `developerservices2` returns
HTTP 200 with
`resultCode`/`userString` in the body, which is untouched here.
Built and linted on Linux (`swift build --product xtool`, `make lint`: 0
violations).
---------
Co-authored-by: Robetronica <noreply@Robetronica.com>
Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>