@@ -317,23 +317,44 @@ public extension DeveloperPortal {
317317 request . httpMethod = " POST "
318318 request . httpBody = plistData
319319
320- // SideInstaller 1.6.1 (grandslam.rs MAC_CLIENT_INFO):
321- // Remote Mac anisette servers still *name* macOS 10.12 / old MacBookPros.
322- // Apple rejects that after the verification code (-80046) or as too old (-23782).
323- // SideInstaller always reports a *current* Mac for GrandSlam headers.
324- let macClientInfo = " <Mac15,7> <macOS;27.0;26A5378j> <com.apple.AuthKit/1 (com.apple.akd/1.0)> "
320+ // SideInstaller client_info_to_use (remote_v3/mod.rs) — exact:
321+ // empty/Android → Windows; Mac older than 10.13 → CURRENT_MAC; else advertised.
322+ // Wrong client after the SMS code is what causes -80046.
323+ let windowsClientInfo = " <PC> <Windows;6.2(0,0);9200> <com.apple.AuthKit/1 (com.apple.iTunes/12.12.4.1)> "
324+ let currentMacClientInfo = " <MacBookPro18,3> <macOS;26.6;25F84> <com.apple.AuthKit/1 (com.apple.akd/1.0)> "
325+ let currentMacUserAgent = " AuthKit/1 (Macintosh; OS X 26.6) (com.apple.akd/1.0) "
325326 let akdUserAgent = " akd/1.0 CFNetwork/808.1.4 "
326- let clientInfo = macClientInfo
327- var userAgent = anisetteData . userAgent . trimmingCharacters ( in : . whitespacesAndNewlines )
328- if userAgent . isEmpty {
329- userAgent = h . grandSlam . userAgent . trimmingCharacters ( in : . whitespacesAndNewlines )
330- }
331- if userAgent . isEmpty
332- || userAgent . contains ( " Macintosh " )
333- || userAgent . contains ( " Mac OS " )
334- || userAgent . contains ( " Xcode " )
335- || userAgent . contains ( " AuthKit/1 (Macintosh " ) {
327+ let advertised = anisetteData . clientInfo . trimmingCharacters ( in : . whitespacesAndNewlines )
328+ let clientInfo : String
329+ let userAgent : String
330+ if advertised . isEmpty || advertised . contains ( " <Android; " ) {
331+ clientInfo = windowsClientInfo
336332 userAgent = akdUserAgent
333+ } else if advertised . contains ( " Mac OS X;10.12 " )
334+ || advertised . contains ( " macOS;10.12 " )
335+ || advertised . contains ( " <Mac OS X;10. " )
336+ || ( advertised . contains ( " Mac OS X; " ) && ! advertised . contains ( " Mac OS X;10.13 " ) && ! advertised . contains ( " Mac OS X;10.14 " ) && ! advertised . contains ( " Mac OS X;10.15 " ) && ! advertised . contains ( " macOS;1 " ) )
337+ || advertised . contains ( " <macOS;10.12 " ) {
338+ // mac_version < (10, 13) → current Mac
339+ clientInfo = currentMacClientInfo
340+ userAgent = currentMacUserAgent
341+ } else if advertised . contains ( " <macOS; " ) || advertised . contains ( " <Mac OS X; " ) || advertised . contains ( " MacBook " ) || advertised . contains ( " <Mac " ) {
342+ // Mac 10.13+ — keep advertised (or still upgrade ancient strings)
343+ if advertised . contains ( " 10.12 " ) {
344+ clientInfo = currentMacClientInfo
345+ userAgent = currentMacUserAgent
346+ } else {
347+ clientInfo = advertised
348+ var ua = anisetteData . userAgent . trimmingCharacters ( in : . whitespacesAndNewlines )
349+ if ua . isEmpty { ua = akdUserAgent }
350+ userAgent = ua
351+ }
352+ } else if advertised . contains ( " <PC> " ) || advertised . contains ( " Windows " ) {
353+ clientInfo = advertised . isEmpty ? windowsClientInfo : advertised
354+ userAgent = akdUserAgent
355+ } else {
356+ clientInfo = currentMacClientInfo
357+ userAgent = currentMacUserAgent
337358 }
338359
339360 let headers : [ String : String ] = [
@@ -1037,7 +1058,7 @@ public extension DeveloperPortal {
10371058 /// SideInstaller MAC_CLIENT_INFO: gsa.apple.com/auth 2FA pages often return a bare 403
10381059 /// for the Windows client used on GrandSlam; retry those requests as a Mac.
10391060 private static let macClientInfoFor2FA =
1040- " <Mac15,7 > <macOS;27.0;26A5378j > <com.apple.AuthKit/1 (com.apple.akd/1.0)> "
1061+ " <MacBookPro18,3 > <macOS;26.6;25F84 > <com.apple.AuthKit/1 (com.apple.akd/1.0)> "
10411062
10421063 private func makeTwoFactorAuthRequest ( url : URL , context : TwoFactorAuthContext , asMac : Bool = false ) -> URLRequest {
10431064 let identityToken = " \( context . dsid ) : \( context . idmsToken ) "
0 commit comments