diff --git a/AltServer/Anisette Data/RemoteAnisetteDataFetcher.swift b/AltServer/Anisette Data/RemoteAnisetteDataFetcher.swift index 8f2706735b..3515361bae 100644 --- a/AltServer/Anisette Data/RemoteAnisetteDataFetcher.swift +++ b/AltServer/Anisette Data/RemoteAnisetteDataFetcher.swift @@ -294,8 +294,34 @@ private extension RemoteAnisetteDataFetcher guard !response.clientInfo.isEmpty, !response.clientInfo.contains("\r"), !response.clientInfo.contains("\n"), !response.userAgent.isEmpty, !response.userAgent.contains("\r"), !response.userAgent.contains("\n") else { throw AnisetteError.remoteServerInvalidResponse(serverURL: serverURL, debugDescription: "The server must supply a client_info and a user_agent.") } + + // Public anisette servers identify as macOS 10.12, which accounts with Advanced Data Protection can't sign in from + // (the 2FA code never arrives, and manually generated codes are rejected). Apple accepts their anisette data + // with a current client info, so identify as this Mac instead. + if !UserDefaults.standard.usesAnisetteServerClientInfo, let currentMac = self.currentMacClientInfo() + { + return currentMac + } + return (response.clientInfo, response.userAgent) } + + func currentMacClientInfo() -> (clientInfo: String, userAgent: String)? + { + guard let deviceModel = ProcessInfo.processInfo.deviceModel, + let buildVersion = ProcessInfo.processInfo.operatingSystemBuildVersion, + let cfNetworkVersion = Bundle(identifier: "com.apple.CFNetwork")?.infoDictionary?["CFBundleVersion"] as? String + else { return nil } + + var systemInfo = utsname() + uname(&systemInfo) + let darwinVersion = withUnsafeBytes(of: &systemInfo.release) { String(decoding: $0.prefix(while: { $0 != 0 }), as: UTF8.self) } + + let osVersion = ProcessInfo.processInfo.operatingSystemVersion.stringValue + let clientInfo = "<\(deviceModel)> " + let userAgent = "akd/1.0 CFNetwork/\(cfNetworkVersion) Darwin/\(darwinVersion)" + return (clientInfo, userAgent) + } enum HeadersResult { diff --git a/AltServer/Extensions/UserDefaults+AltServer.swift b/AltServer/Extensions/UserDefaults+AltServer.swift index 5e47d645ff..09a20b381e 100644 --- a/AltServer/Extensions/UserDefaults+AltServer.swift +++ b/AltServer/Extensions/UserDefaults+AltServer.swift @@ -60,6 +60,7 @@ extension UserDefaults { private static let altJITTimeoutKey = "JITTimeout" private static let anisetteServerURLKey = "RemoteAltServerURL" + private static let usesAnisetteServerClientInfoKey = "UseAnisetteServerClientInfo" var altJITTimeout: TimeInterval? { let timeout = self.double(forKey: UserDefaults.altJITTimeoutKey) // Coerces strings into doubles. @@ -71,4 +72,9 @@ extension UserDefaults var anisetteServerURLOverride: URL? { return self.string(forKey: UserDefaults.anisetteServerURLKey).flatMap { URL(string: $0) } } + + // Opts out of identifying as this Mac, and uses the anisette server's (outdated) client info instead. + var usesAnisetteServerClientInfo: Bool { + return self.bool(forKey: UserDefaults.usesAnisetteServerClientInfoKey) + } }