module Graphics.XHB.Connection.Auth (getAuthInfo) where
import Data.Bits
import Data.Word
import System.IO
import Graphics.X11.Xauth
import Network.Socket
import Network.BSD (getHostName)
import Foreign.C (CChar)
import Foreign.C.String (castCharToCChar)
getAuthInfo :: Socket -> Int -> IO (Maybe Xauth)
getAuthInfo fd display = do
sock <- getPeerName fd
(addr, fam) <- f sock
getAuthByAddr fam addr (cstring $ show display) (cstring atype)
where
f x | isLocal x = getHostName >>= \h ->
return (cstring h, 256)
| isIPv4 x || isIPv6Mappedv4 x = return (host x, 0)
| otherwise = return (host x, 6)
isLocal (SockAddrUnix _) = True
isLocal (SockAddrInet _ h) = h == 16777343
isLocal (SockAddrInet6 _ _ (0,0,0,1) _) = True
isLocal _ = False
isIPv4 (SockAddrInet _ _) = True
isIPv4 _ = False
isIPv6Mappedv4 (SockAddrInet6 _ _ (0,0,0xFFFF,x) _) = True
isIPv6Mappedv4 _ = False
bytes :: Word32 -> [CChar]
bytes x = foldr g [] [0,8..24] where
g a = let r = (x `shiftR` a) .&. 0xFF
in ((fromIntegral r):)
host (SockAddrInet _ h) = bytes h
host (SockAddrInet6 _ _ (x,y,z,w) _) = concatMap bytes [x,y,z,w]
atype = "MIT-MAGIC-COOKIE-1"
cstring :: String -> [CChar]
cstring = map castCharToCChar