Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion AltServer/Anisette Data/RemoteAnisetteDataFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ actor RemoteAnisetteDataFetcher
private static let timeout: TimeInterval = 90
private static let placeholderSerialNumber = "C02LKHBBFD57"

// Apple rejects the client info anisette servers currently report with -23782 ("A Mac with macOS version 10.13 or later is required"),
// so identify as akd on macOS instead until servers report client info Apple accepts. Same override as iloader v2.4.1 (nab138/iloader@d319ce7).
private static let clientInfoOverride: (clientInfo: String, userAgent: String)? = ("<Mac15,7> <macOS;27.0;26A5378j> <com.apple.AuthKit/1 (com.apple.akd/1.0)>", "akd/1.0 CFNetwork/811.5.4")

private let session: URLSession
private let sessionDelegate = AnisetteSessionDelegate()

Expand Down Expand Up @@ -265,7 +269,7 @@ private extension RemoteAnisetteDataFetcher
throw AnisetteError.remoteServerInvalidResponse(serverURL: serverURL)
}

// 5. Assemble the result. deviceDescription and userAgent must be the server's, so they match the client that generated the anisette data.
// 5. Assemble the result. deviceDescription and userAgent must match the client info used for provisioning.
let anisetteData = RemoteAnisetteData(machineID: machineID,
oneTimePassword: oneTimePassword,
localUserID: identity.localUserID,
Expand All @@ -279,6 +283,11 @@ private extension RemoteAnisetteDataFetcher

func fetchClientInfo(from serverURL: URL) async throws -> (clientInfo: String, userAgent: String)
{
if let clientInfoOverride = RemoteAnisetteDataFetcher.clientInfoOverride
{
return clientInfoOverride
}

struct Response: Decodable
{
var clientInfo: String
Expand Down
20 changes: 19 additions & 1 deletion AltStore/Operations/FetchAnisetteDataOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>, @unchecked S
{
let context: OperationContext

// Apple rejects the client info anisette servers currently report with -23782 ("A Mac with macOS version 10.13 or later is required"),
// so identify as akd on macOS instead until servers report client info Apple accepts. Same override as AltServer and iloader v2.4.1 (nab138/iloader@d319ce7).
fileprivate static let clientInfoOverride: (clientInfo: String, userAgent: String)? = ("<Mac15,7> <macOS;27.0;26A5378j> <com.apple.AuthKit/1 (com.apple.akd/1.0)>", "akd/1.0 CFNetwork/811.5.4")

// Set to Apple's X-Apple-I-MD-DATA to resynchronize the existing anisette data instead of fetching it normally.
var resynchronizationData: String?

Expand Down Expand Up @@ -126,6 +130,12 @@ class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>, @unchecked S
anisetteData.deviceDescription = sanitizedDescription
}

if let clientInfoOverride = FetchAnisetteDataOperation.clientInfoOverride
{
// GrandSlam also rejects akd's client info unless it's sent with a matching user agent, including anisette data from AltServer.
ALTAppleAPI.shared.authenticationUserAgent = clientInfoOverride.userAgent
}

self.finish(.success(anisetteData))
}
catch
Expand Down Expand Up @@ -245,7 +255,15 @@ private extension FetchAnisetteDataOperation
let decoder = Foundation.JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

let response: Response = try await self.send(URLRequest(url: clientInfoURL), decoder: decoder, anisetteServerURL: serverURL)
let response: Response
if let clientInfoOverride = FetchAnisetteDataOperation.clientInfoOverride
{
response = Response(clientInfo: clientInfoOverride.clientInfo, userAgent: clientInfoOverride.userAgent)
}
else
{
response = try await self.send(URLRequest(url: clientInfoURL), decoder: decoder, anisetteServerURL: serverURL)
}

// 2. Provision against this server unless we have a cached anisette identifier + adi.pb with the same client info.
// A cached adi.pb from a different anisette implementation is no longer accepted, so discard it when the client info changes.
Expand Down