diff --git a/Sources/XKit/DeveloperServices/DeveloperServicesClient.swift b/Sources/XKit/DeveloperServices/DeveloperServicesClient.swift index f34f0443..ebc6edd0 100644 --- a/Sources/XKit/DeveloperServices/DeveloperServicesClient.swift +++ b/Sources/XKit/DeveloperServices/DeveloperServicesClient.swift @@ -54,7 +54,6 @@ public struct DeveloperServicesClient: Sendable { } } - @Dependency(\.deviceInfoProvider) var deviceInfoProvider @Dependency(\.anisetteDataProvider) var anisetteDataProvider @Dependency(\.httpClient) var httpClient @@ -76,8 +75,6 @@ public struct DeveloperServicesClient: Sendable { throw Error.malformedRequest } - let deviceInfo = try deviceInfoProvider.fetch() - var httpRequest = HTTPRequest(method: .post, url: url) let acceptedLanguages = Locale.preferredLanguages.joined(separator: ", ") @@ -88,8 +85,6 @@ public struct DeveloperServicesClient: Sendable { request.methodOverride.map { httpRequest.headerFields[.init("X-HTTP-Method-Override")!] = $0 } httpRequest.headerFields[.init(DeviceInfo.xcodeVersionKey)!] = DeviceInfo.xcodeVersion - httpRequest.headerFields[.init(DeviceInfo.clientInfoKey)!] = deviceInfo.clientInfo.clientString - httpRequest.headerFields[.init(DeviceInfo.deviceIDKey)!] = deviceInfo.deviceID httpRequest.headerFields[.init("X-Apple-I-Identity-Id")!] = loginToken.adsid httpRequest.headerFields[.init("X-Apple-App-Info")!] = AppTokenKey.xcode.rawValue @@ -103,8 +98,6 @@ public struct DeveloperServicesClient: Sendable { let (_, data) = try await httpClient.makeRequest(httpRequest, body: body) -// String(data: data, encoding: .utf8).map { print("\(url): \($0)") } - let decoded: R.Response = try request.apiVersion.decode(response: data) return try await request.parse(decoded) diff --git a/Sources/XKit/DeveloperServices/OpenAPI/DeveloperServices+OpenAPI.swift b/Sources/XKit/DeveloperServices/OpenAPI/DeveloperServices+OpenAPI.swift index 523cbcbf..cc95f4d1 100644 --- a/Sources/XKit/DeveloperServices/OpenAPI/DeveloperServices+OpenAPI.swift +++ b/Sources/XKit/DeveloperServices/OpenAPI/DeveloperServices+OpenAPI.swift @@ -105,7 +105,6 @@ public struct XcodeAuthData: Sendable { } public struct DeveloperAPIXcodeAuthMiddleware: ClientMiddleware { - @Dependency(\.deviceInfoProvider) private var deviceInfoProvider @Dependency(\.anisetteDataProvider) private var anisetteDataProvider public var authData: XcodeAuthData @@ -130,7 +129,7 @@ public struct DeveloperAPIXcodeAuthMiddleware: ClientMiddleware { ) async throws -> (HTTPResponse, HTTPBody?) { var request = request - let deviceInfo = try deviceInfoProvider.fetch() + let anisetteData = try await anisetteDataProvider.fetchAnisetteData() // General request.headerFields[.acceptLanguage] = Locale.preferredLanguages.joined(separator: ", ") @@ -142,17 +141,12 @@ public struct DeveloperAPIXcodeAuthMiddleware: ClientMiddleware { request.headerFields[.userAgent] = "Xcode" request.headerFields[.init(DeviceInfo.xcodeVersionKey)!] = DeviceInfo.xcodeVersion - // MobileMe identity - request.headerFields[.init(DeviceInfo.clientInfoKey)!] = deviceInfo.clientInfo.clientString - request.headerFields[.init(DeviceInfo.deviceIDKey)!] = deviceInfo.deviceID - // GrandSlam authentication request.headerFields[.init("X-Apple-App-Info")!] = AppTokenKey.xcode.rawValue request.headerFields[.init("X-Apple-I-Identity-Id")!] = authData.loginToken.adsid request.headerFields[.init("X-Apple-GS-Token")!] = authData.loginToken.token // Anisette - let anisetteData = try await anisetteDataProvider.fetchAnisetteData() for (key, value) in anisetteData.dictionary { request.headerFields[.init(key)!] = value } diff --git a/Sources/XKit/GrandSlam/Anisette/ADIDataProvider.swift b/Sources/XKit/GrandSlam/Anisette/ADIDataProvider.swift index 2290f1f5..d4104767 100644 --- a/Sources/XKit/GrandSlam/Anisette/ADIDataProvider.swift +++ b/Sources/XKit/GrandSlam/Anisette/ADIDataProvider.swift @@ -18,15 +18,6 @@ public protocol RawADIProvider: Sendable { ) async throws -> (machineID: Data, otp: Data) } -extension RawADIProvider { - public func clientInfo() async throws -> String { - // Looks like Apple detects attempts to use a macOS client string on Windows :/ - """ - - """ - } -} - private struct UnimplementedRawADIProvider: RawADIProvider { func startProvisioning( spim: Data, @@ -44,6 +35,11 @@ private struct UnimplementedRawADIProvider: RawADIProvider { let closure: (UUID, inout UInt64, Data) async throws -> (Data, Data) = unimplemented() return try await closure(userID, &routingInfo, provisioningInfo) } + + func clientInfo() async throws -> String { + let closure: () async throws -> String = unimplemented() + return try await closure() + } } private enum RawADIProviderDependencyKey: DependencyKey { @@ -179,15 +175,12 @@ public struct ADIDataProvider: AnisetteDataProvider { ] request.headerFields[.init("X-MMe-Country")!] = Locale.current.region?.identifier - request.headerFields[.init(DeviceInfo.clientInfoKey)!] = try await clientInfo() - request.headerFields[.init(DeviceInfo.deviceIDKey)!] = self.localUserUID.uuidString -// request.headers[DeviceInfo.clientInfoKey] = self.deviceInfo.clientInfo.clientString -// self.deviceInfo.dictionary.forEach { request.headers[$0] = $1 } + for (key, value) in try await deviceInfo().dictionary { + request.headerFields[.init(key)!] = value + } let (_, response) = try await self.httpClient.makeRequest(request, body: body) -// print(String(data: response, encoding: .utf8) ?? "") - return try GrandSlamOperationDecoder.decode(data: response) } @@ -239,7 +232,7 @@ public struct ADIDataProvider: AnisetteDataProvider { machineID: mid.base64EncodedString(), localUserID: self.localUserID, oneTimePassword: otp.base64EncodedString(), - deviceID: self.localUserUID.uuidString + deviceInfo: try await deviceInfo(), ) } @@ -287,6 +280,13 @@ public struct ADIDataProvider: AnisetteDataProvider { ) } + public func deviceInfo() async throws -> DeviceInfo { + DeviceInfo( + deviceID: localUserUID.uuidString, + clientInfo: try await clientInfo(), + ) + } + } public struct ADIError: Error, CustomStringConvertible { diff --git a/Sources/XKit/GrandSlam/Anisette/AnisetteData.swift b/Sources/XKit/GrandSlam/Anisette/AnisetteData.swift index 810a48a0..0352e23c 100644 --- a/Sources/XKit/GrandSlam/Anisette/AnisetteData.swift +++ b/Sources/XKit/GrandSlam/Anisette/AnisetteData.swift @@ -49,10 +49,9 @@ public struct AnisetteData { static let oneTimePasswordKey = "X-Apple-I-MD" public let oneTimePassword: String - static let deviceIDKey = "X-Mme-Device-Id" - public var deviceID: String? + public let deviceInfo: DeviceInfo - var dictionary: [String: String] { + public var dictionary: [String: String] { // GSA doesn't like "en_US@rg=..."; it has to be just "en_US". let localeIdentifier = if let language = locale.language.languageCode?.identifier, let region = locale.region?.identifier { @@ -60,7 +59,7 @@ public struct AnisetteData { } else { "en_US" } - var dictionary = [ + return [ Self.localeKey: localeIdentifier, Self.timeZoneKey: timeZone.abbreviation() ?? "UTC", Self.clientTimeKey: Self.dateFormatter.string(from: clientTime), @@ -69,10 +68,7 @@ public struct AnisetteData { Self.localUserIDKey: localUserID, Self.oneTimePasswordKey: oneTimePassword, ] - if let deviceID { - dictionary[Self.deviceIDKey] = deviceID - } - return dictionary + .merging(deviceInfo.dictionary) { _, b in b } } } diff --git a/Sources/XKit/GrandSlam/Anisette/AnisetteDataProvider.swift b/Sources/XKit/GrandSlam/Anisette/AnisetteDataProvider.swift index 554eec8a..f71d82f8 100644 --- a/Sources/XKit/GrandSlam/Anisette/AnisetteDataProvider.swift +++ b/Sources/XKit/GrandSlam/Anisette/AnisetteDataProvider.swift @@ -22,6 +22,8 @@ public protocol AnisetteDataProvider: Sendable { func resetProvisioning() async func provisioningData() -> ProvisioningData? + func deviceInfo() async throws -> DeviceInfo + func fetchAnisetteData() async throws -> AnisetteData } @@ -54,4 +56,9 @@ private struct UnimplementedAnisetteDataProvider: AnisetteDataProvider { let closure: () async throws -> AnisetteData = unimplemented() return try await closure() } + + func deviceInfo() async throws -> DeviceInfo { + let closure: () async throws -> DeviceInfo = unimplemented() + return try await closure() + } } diff --git a/Sources/XKit/GrandSlam/Anisette/DeviceInfo+Fetching.swift b/Sources/XKit/GrandSlam/Anisette/DeviceInfo+Fetching.swift deleted file mode 100644 index ab0ad0b6..00000000 --- a/Sources/XKit/GrandSlam/Anisette/DeviceInfo+Fetching.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// DeviceInfo+Fetching.swift -// XKit -// -// Created by Kabir Oberai on 18/06/20. -// Copyright © 2020 Kabir Oberai. All rights reserved. -// - -import Foundation - -#if os(macOS) -extension DeviceInfo { - - private static func fetchDeviceID() -> String? { - var waitTime = timespec(tv_sec: 0, tv_nsec: 0) // wait indefinitely - let bytes = [UInt8](unsafeUninitializedCapacity: MemoryLayout.size) { buf, count in - // force unwrapping is safe because uuid_t has a non-zero size - count = (gethostuuid(buf.baseAddress!, &waitTime) == 0) ? buf.count : 0 - } - guard !bytes.isEmpty else { return nil } - return bytes.withUnsafeBufferPointer { - UUID(uuid: UnsafeRawBufferPointer($0).load(as: uuid_t.self)).uuidString - } - } - - private static func hardwareProperty(forKey key: String) -> Data? { - let entry = IORegistryEntryFromPath(kIOMainPortDefault, "IODeviceTree:/options") - guard entry != 0 else { return nil } - defer { IOObjectRelease(entry) } - - return IORegistryEntryCreateCFProperty( - entry, key as CFString, kCFAllocatorDefault, 0 - )?.takeRetainedValue() as? Data - } - - private static func fetchROMAddress() -> String? { - hardwareProperty(forKey: "4D1EDE05-38C7-4a6a-9CC6-4BCCA8B38C14:ROM")? - .map { String(format: "%02hhx", $0) } - .joined() - } - - private static func fetchMLBSerialNumber() -> String? { - hardwareProperty(forKey: "4D1EDE05-38C7-4a6a-9CC6-4BCCA8B38C14:MLB")? - .map { String(format: isprint(Int32($0)) != 0 ? "%c" : "%02hhx", $0) } - .joined() - } - - private static func fetchSerialNumber() -> String? { - let service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice")) - guard service != 0 else { return nil } - defer { IOObjectRelease(service) } - return IORegistryEntryCreateCFProperty( - service, "IOPlatformSerialNumber" as CFString, kCFAllocatorDefault, 0 - )?.takeRetainedValue() as? String - } - - private static func fetchHardwareModel() -> String? { - var modelSize = 0 - guard sysctlbyname("hw.model", nil, &modelSize, nil, 0) == 0, - modelSize > 0 else { return nil } - return String(unsafeUninitializedCapacity: modelSize) { buf in - var len = modelSize - guard sysctlbyname("hw.model", buf.baseAddress, &len, nil, 0) == 0, - len == modelSize else { return 0 } - return len - 1 // exclude NUL - } - } - - public static func current() -> DeviceInfo? { - let romAddress = fetchROMAddress() ?? "" - let mlbSerialNumber = fetchMLBSerialNumber() ?? "" - - guard let deviceID = fetchDeviceID(), - let serialNumber = fetchSerialNumber(), - let modelID = fetchHardwareModel() - else { return nil } - return DeviceInfo( - deviceID: deviceID, - romAddress: romAddress, - mlbSerialNumber: mlbSerialNumber, - serialNumber: serialNumber, - modelID: modelID - ) - } - -} -#else -extension DeviceInfo { - public static func current() -> DeviceInfo? { - return DeviceInfo( - deviceID: "99B5D9D4-B068-5CEE-A799-5EBB5B0894A6", - romAddress: "94f6a300e9a0", - mlbSerialNumber: "C02520301W0GF2D1U", - serialNumber: "C02PQKRJG8WP", - modelID: "Mac16,1" - ) - } -} -#endif - -// FIXME: Figure out DeviceInfo.current() outside macOS -// (see above) diff --git a/Sources/XKit/GrandSlam/Anisette/DeviceInfo.swift b/Sources/XKit/GrandSlam/Anisette/DeviceInfo.swift index 42c1d7f4..bc0b0451 100644 --- a/Sources/XKit/GrandSlam/Anisette/DeviceInfo.swift +++ b/Sources/XKit/GrandSlam/Anisette/DeviceInfo.swift @@ -1,116 +1,20 @@ -// -// DeviceInfo.swift -// XKit -// -// Created by Kabir Oberai on 19/11/19. -// Copyright © 2019 Kabir Oberai. All rights reserved. -// - import Foundation -import Dependencies public struct DeviceInfo: Codable, Sendable { - - /// `X-Xcode-Version` - static let xcodeVersionKey = "X-Xcode-Version" - /// Not included in `dictionary` + public static let xcodeVersionKey = "X-Xcode-Version" public static let xcodeVersion = "26.5 (17F42)" + public static let akdUserAgent = "akd/1.0 CFNetwork/808.1.4" - public struct ClientInfo: Codable { - public let modelID: String // e.g. MacBookPro11,5 - - var clientString: String { - """ - - """ - } - - var userAgent: String { - "AuthKit/1 (Macintosh; OS X 27.0) (com.apple.dt.Xcode/26.5)" - } - - public init(modelID: String) { - self.modelID = modelID - } - } - - /// `X-Mme-Device-Id` - static let deviceIDKey = "X-Mme-Device-Id" + public static let deviceIDKey = "X-Mme-Device-Id" public let deviceID: String - /// `X-Apple-I-ROM` - static let romAddressKey = "X-Apple-I-ROM" - public let romAddress: String + public static let clientInfoKey = "X-MMe-Client-Info" + public let clientInfo: String - /// `X-Apple-I-MLB` - static let mlbSerialNumberKey = "X-Apple-I-MLB" - /// main logic board serial number - public let mlbSerialNumber: String - - /// `X-Apple-I-SRL-NO` - static let serialNumberKey = "X-Apple-I-SRL-NO" - public let serialNumber: String - - public let modelID: String - - /// `X-MMe-Client-Info` - static let clientInfoKey = "X-MMe-Client-Info" - public var clientInfo: ClientInfo { .init(modelID: modelID) } - - public init( - deviceID: String, - romAddress: String, - mlbSerialNumber: String, - serialNumber: String, - modelID: String - ) { - self.deviceID = deviceID - self.romAddress = romAddress - self.mlbSerialNumber = mlbSerialNumber - self.serialNumber = serialNumber - self.modelID = modelID - } - - var dictionary: [String: String] { + public var dictionary: [String: String] { [ + Self.clientInfoKey: clientInfo, Self.deviceIDKey: deviceID, - Self.romAddressKey: romAddress, - Self.mlbSerialNumberKey: mlbSerialNumber, - Self.serialNumberKey: serialNumber ] } - -} - -extension DeviceInfo { - public enum FetchError: Error { - case couldNotFetch - } - - fileprivate static func fetch() throws -> Self { - guard let deviceInfo = DeviceInfo.current() else { - throw FetchError.couldNotFetch - } - return deviceInfo - } -} - -public struct DeviceInfoProvider: DependencyKey, Sendable { - public var fetch: @Sendable () throws -> DeviceInfo - - public init(fetch: @escaping @Sendable () throws -> DeviceInfo) { - self.fetch = fetch - } - - private static let current = Result { try DeviceInfo.fetch() } - - public static let testValue = DeviceInfoProvider(fetch: unimplemented()) - public static let liveValue = DeviceInfoProvider { try current.get() } -} - -extension DependencyValues { - public var deviceInfoProvider: DeviceInfoProvider { - get { self[DeviceInfoProvider.self] } - set { self[DeviceInfoProvider.self] = newValue } - } } diff --git a/Sources/XKit/GrandSlam/Anisette/XADIProvider.swift b/Sources/XKit/GrandSlam/Anisette/XADIProvider.swift index b1bd2420..03189d53 100644 --- a/Sources/XKit/GrandSlam/Anisette/XADIProvider.swift +++ b/Sources/XKit/GrandSlam/Anisette/XADIProvider.swift @@ -84,9 +84,11 @@ public actor XADIProvider: RawADIProvider { try await loadTask.value } + /// XADI's Anisette data comes from Android ADI, so every GSA request (including + /// provisioning) has to identify as an Android device or GSA rejects it (-80045). public func clientInfo() async throws -> String { """ - + """ } diff --git a/Sources/XKit/GrandSlam/GrandSlamClient.swift b/Sources/XKit/GrandSlam/GrandSlamClient.swift index 2a7b23ab..d7135059 100644 --- a/Sources/XKit/GrandSlam/GrandSlamClient.swift +++ b/Sources/XKit/GrandSlam/GrandSlamClient.swift @@ -15,22 +15,19 @@ struct GrandSlamClient: Sendable { private let lookupManager = GrandSlamLookupManager() - @Dependency(\.deviceInfoProvider) var deviceInfoProvider @Dependency(\.anisetteDataProvider) var anisetteDataProvider @Dependency(\.httpClient) var httpClient init() {} func send(_ request: R) async throws -> R.Decoder.Value { - let deviceInfo = try deviceInfoProvider.fetch() - let anisetteData = try await anisetteDataProvider.fetchAnisetteData() let url = try await lookupManager.fetchURL(forEndpoint: R.endpoint) - let method = request.method(deviceInfo: deviceInfo, anisetteData: anisetteData) + let method = request.method(anisetteData: anisetteData) var httpRequest = HTTPRequest(method: method.httpMethod, url: url) httpRequest.headerFields[.contentType] = "text/x-xml-plist" - httpRequest.headerFields[.init(DeviceInfo.clientInfoKey)!] = deviceInfo.clientInfo.clientString + httpRequest.headerFields[.init(DeviceInfo.clientInfoKey)!] = anisetteData.deviceInfo.clientInfo let body: Data? = switch method { case .get: nil @@ -39,7 +36,7 @@ struct GrandSlamClient: Sendable { fromPropertyList: body, format: .xml, options: 0 ) } - request.configure(request: &httpRequest, deviceInfo: deviceInfo, anisetteData: anisetteData) + request.configure(request: &httpRequest, anisetteData: anisetteData) // GrandSlam doesn't seem to like reused (keep-alive) connections so create a // new one for each request. cf https://github.com/rileytestut/AltSign/pull/52 diff --git a/Sources/XKit/GrandSlam/Lookup/GrandSlamLookupManager.swift b/Sources/XKit/GrandSlam/Lookup/GrandSlamLookupManager.swift index 4301e1db..91dd3443 100644 --- a/Sources/XKit/GrandSlam/Lookup/GrandSlamLookupManager.swift +++ b/Sources/XKit/GrandSlam/Lookup/GrandSlamLookupManager.swift @@ -21,33 +21,27 @@ actor GrandSlamLookupManager { private let decoder = PropertyListDecoder() private var endpoints: GrandSlamEndpoints? - @Dependency(\.deviceInfoProvider) var deviceInfoProvider + @Dependency(\.anisetteDataProvider) var anisetteDataProvider @Dependency(\.httpClient) var httpClient init() {} private func performLookup() async throws -> GrandSlamEndpoints { - let deviceInfo = try deviceInfoProvider.fetch() + let deviceInfo = try await anisetteDataProvider.deviceInfo() - /* { - "X-Apple-I-Locale" = "en_IN"; - "X-Apple-I-TimeZone" = "Asia/Kolkata"; - "X-Apple-I-TimeZone-Offset" = 19800; - "X-MMe-Client-Info" = " "; - "X-MMe-Country" = IN; - "X-Mme-Device-Id" = "[REDACTED]"; - } */ var request = HTTPRequest(url: Self.lookupURL) request.headerFields = [ - .userAgent: deviceInfo.clientInfo.userAgent, - .init(DeviceInfo.clientInfoKey)!: deviceInfo.clientInfo.clientString, - .init(DeviceInfo.deviceIDKey)!: deviceInfo.deviceID, + .userAgent: DeviceInfo.akdUserAgent, .init(AnisetteData.iLocaleKey)!: Locale.current.identifier, .init(AnisetteData.timeZoneKey)!: TimeZone.current.identifier, .init("X-Apple-I-TimeZone-Offset")!: "\(TimeZone.current.secondsFromGMT())" ] request.headerFields[.init("X-MMe-Country")!] = Locale.current.region?.identifier + for (key, value) in deviceInfo.dictionary { + request.headerFields[.init(key)!] = value + } + let (_, body) = try await httpClient.makeRequest(request) return try self.decoder.decode(Response.self, from: body).urls diff --git a/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamTrustedDeviceRequest.swift b/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamTrustedDeviceRequest.swift index 28123a9e..f2ff726e 100644 --- a/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamTrustedDeviceRequest.swift +++ b/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamTrustedDeviceRequest.swift @@ -40,7 +40,7 @@ struct GrandSlamSMSAuthRequest: GrandSlamTwoFactorRequest { let loginData: GrandSlamLoginData let phoneNumberID: String - func method(deviceInfo: DeviceInfo, anisetteData: AnisetteData) -> GrandSlamMethod { + func method(anisetteData: AnisetteData) -> GrandSlamMethod { .post([ "serverInfo": [ "phoneNumber.id": phoneNumberID diff --git a/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamValidateRequest.swift b/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamValidateRequest.swift index 281241fa..523d7e04 100644 --- a/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamValidateRequest.swift +++ b/Sources/XKit/GrandSlam/Requests/Concrete/GrandSlamValidateRequest.swift @@ -36,7 +36,7 @@ struct GrandSlamValidateSMSRequest: GrandSlamTwoFactorRequest { let phoneNumberID: String let verificationCode: String - func method(deviceInfo: DeviceInfo, anisetteData: AnisetteData) -> GrandSlamMethod { + func method(anisetteData: AnisetteData) -> GrandSlamMethod { .post([ "securityCode.code": verificationCode, "serverInfo": [ diff --git a/Sources/XKit/GrandSlam/Requests/GrandSlamOperationRequest.swift b/Sources/XKit/GrandSlam/Requests/GrandSlamOperationRequest.swift index ca30b7df..13f94bf1 100644 --- a/Sources/XKit/GrandSlam/Requests/GrandSlamOperationRequest.swift +++ b/Sources/XKit/GrandSlam/Requests/GrandSlamOperationRequest.swift @@ -69,12 +69,12 @@ extension GrandSlamOperationRequest { static var endpoint: GrandSlamEndpoint { .lookup(\.gsService) } - func configure(request: inout HTTPRequest, deviceInfo: DeviceInfo, anisetteData: AnisetteData) { + func configure(request: inout HTTPRequest, anisetteData: AnisetteData) { request.headerFields[.accept] = "*/*" - request.headerFields[.userAgent] = deviceInfo.clientInfo.userAgent + request.headerFields[.userAgent] = DeviceInfo.akdUserAgent } - func method(deviceInfo: DeviceInfo, anisetteData: AnisetteData) -> GrandSlamMethod { + func method(anisetteData: AnisetteData) -> GrandSlamMethod { var clientData: [String: Any] = [ "bootstrap": true, "icscrec": true, @@ -83,7 +83,6 @@ extension GrandSlamOperationRequest { "svct": "iCloud", "loc": Locale.current.identifier ] - clientData.merge(deviceInfo.dictionary) { _, b in b } clientData.merge(anisetteData.dictionary) { _, b in b } var request: [String: Any] = [ diff --git a/Sources/XKit/GrandSlam/Requests/GrandSlamRequest.swift b/Sources/XKit/GrandSlam/Requests/GrandSlamRequest.swift index db05d5af..43c8d0a3 100644 --- a/Sources/XKit/GrandSlam/Requests/GrandSlamRequest.swift +++ b/Sources/XKit/GrandSlam/Requests/GrandSlamRequest.swift @@ -30,6 +30,6 @@ protocol GrandSlamRequest: Sendable { static var endpoint: GrandSlamEndpoint { get } - func configure(request: inout HTTPRequest, deviceInfo: DeviceInfo, anisetteData: AnisetteData) - func method(deviceInfo: DeviceInfo, anisetteData: AnisetteData) -> GrandSlamMethod + func configure(request: inout HTTPRequest, anisetteData: AnisetteData) + func method(anisetteData: AnisetteData) -> GrandSlamMethod } diff --git a/Sources/XKit/GrandSlam/Requests/GrandSlamTwoFactorRequest.swift b/Sources/XKit/GrandSlam/Requests/GrandSlamTwoFactorRequest.swift index 305d4a18..67e02598 100644 --- a/Sources/XKit/GrandSlam/Requests/GrandSlamTwoFactorRequest.swift +++ b/Sources/XKit/GrandSlam/Requests/GrandSlamTwoFactorRequest.swift @@ -17,9 +17,10 @@ extension GrandSlamTwoFactorRequest { var extraHeaders: [String: String] { [:] } - func configure(request: inout HTTPRequest, deviceInfo: DeviceInfo, anisetteData: AnisetteData) { + func configure(request: inout HTTPRequest, anisetteData: AnisetteData) { request.headerFields[.accept] = "application/x-buddyml" request.headerFields[.contentType] = "application/x-plist" + request.headerFields[.userAgent] = "" request.headerFields[.init("X-Apple-App-Info")!] = "com.apple.gs.xcode.auth" request.headerFields[.init(DeviceInfo.xcodeVersionKey)!] = DeviceInfo.xcodeVersion request.headerFields[.init("X-Apple-Identity-Token")!] = loginData.identityToken @@ -27,7 +28,7 @@ extension GrandSlamTwoFactorRequest { extraHeaders.forEach { request.headerFields[.init($0)!] = $1 } } - func method(deviceInfo: DeviceInfo, anisetteData: AnisetteData) -> GrandSlamMethod { + func method(anisetteData: AnisetteData) -> GrandSlamMethod { .get } diff --git a/Sources/XKit/Integration/Superconfig.swift b/Sources/XKit/Integration/Superconfig.swift deleted file mode 100644 index 51d65e74..00000000 --- a/Sources/XKit/Integration/Superconfig.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Superconfig.swift -// -// -// Created by Kabir Oberai on 02/05/21. -// - -import Foundation - -public struct Superconfig: Codable, Sendable { - // Stuff that needs to come from the installer - public let udid: String - public let pairingKeys: Data - public let deviceInfo: DeviceInfo - - // Stuff that can also be fetched in-app - public let preferredTeamID: String - public let preferredSigningInfo: SigningInfo? - public let appleID: String - public let provisioningData: ProvisioningData? - public let token: DeveloperServicesLoginToken - - public init( - udid: String, - pairingKeys: Data, - deviceInfo: DeviceInfo, - preferredTeamID: String, - preferredSigningInfo: SigningInfo?, - appleID: String, - provisioningData: ProvisioningData?, - token: DeveloperServicesLoginToken - ) { - self.udid = udid - self.pairingKeys = pairingKeys - self.deviceInfo = deviceInfo - self.preferredTeamID = preferredTeamID - self.preferredSigningInfo = preferredSigningInfo - self.appleID = appleID - self.provisioningData = provisioningData - self.token = token - } - - public static let filename = "Superconfig.plist" - public static let encoder = PropertyListEncoder() - public func save(inAppDir appDir: URL) throws { - try Self.encoder.encode(self).write(to: appDir.appendingPathComponent(Self.filename)) - } -} diff --git a/Sources/XToolSupport/DSCommands/DSCommand.swift b/Sources/XToolSupport/DSCommands/DSCommand.swift index d5e59df7..58b7323a 100644 --- a/Sources/XToolSupport/DSCommands/DSCommand.swift +++ b/Sources/XToolSupport/DSCommands/DSCommand.swift @@ -4,48 +4,17 @@ import ArgumentParser import Dependencies struct DSAnisetteCommand: AsyncParsableCommand { - private final class Provider: RawADIProvider, RawADIProvisioningSession { - func startProvisioning(spim: Data, userID: UUID) async throws -> (RawADIProvisioningSession, Data) { - print("spim: \(spim.base64EncodedString())") - return (self, Data(base64Encoded: try await Console.prompt("cpim: "))!) - } - - func endProvisioning( - routingInfo: UInt64, - ptm: Data, - tk: Data - ) async throws -> Data { - print(""" - rinfo: \(routingInfo) - ptm: \(ptm.base64EncodedString()) - tk: \(tk.base64EncodedString()) - """) - return Data(base64Encoded: try await Console.prompt("pinfo: "))! - } - - func requestOTP( - userID: UUID, - routingInfo: inout UInt64, - provisioningInfo: Data - ) -> (machineID: Data, otp: Data) { - print("otp; pinfo: \(provisioningInfo)") - return (Data(), Data()) - } - } - static let configuration = CommandConfiguration( commandName: "anisette", abstract: "Test out Anisette data" ) func run() async throws { - let provider = withDependencies { - $0.rawADIProvider = Provider() - } operation: { - ADIDataProvider() - } + @Dependency(\.anisetteDataProvider) var provider let res = try await provider.fetchAnisetteData() - print(res) + for (key, value) in res.dictionary.sorted(by: { $0.key < $1.key }) { + print("\(key): \(value)") + } } }