@@ -1,9 +1,13 @@
1import Prelude hiding (catch)
2import Prelude hiding (catch)
2−import System.Environment (getArgs)
3+import System.Environment (getArgs, getEnv)
3import System.IO (IOMode(ReadWriteMode), hClose)
4import System.IO (IOMode(ReadWriteMode), hClose)
5+import System.FilePath ((</>), takeFileName)
4import Data.IORef (IORef, writeIORef, readIORef, newIORef)
6import Data.IORef (IORef, writeIORef, readIORef, newIORef)
5import qualified Data.ByteString.Lazy.Char8 as BSLC (pack, putStrLn)
7import qualified Data.ByteString.Lazy.Char8 as BSLC (pack, putStrLn)
6import Control.Exception (SomeException, catch)
8import Control.Exception (SomeException, catch)
7import qualified Crypto.Random.AESCtr as RNG (makeSystem)
11import qualified Crypto.Random.AESCtr as RNG (makeSystem)
8import Network.Azure.ServiceManagement
12import Network.Azure.ServiceManagement
9 ( fileReadCertificate
13 ( fileReadCertificate
@@ -56,9 +60,96 @@ import Network.TLS.Extra
57import Data.Certificate.X509 (X509)
61import Data.Certificate.X509 (X509)
64+import Network.SSH.Client.LibSSH2
72+import Network.SSH.Client.LibSSH2.Foreign
78+import Codec.Binary.UTF8.String (decodeString)
59main :: IO ()
80main :: IO ()
61− [subscriptionId, pathToCert, pathToKey] <- getArgs
82+ args <- getArgs
84+ ["azure", subscriptionId, pathToCert, pathToKey] ->
85+ tryConnectToAzure subscriptionId pathToCert pathToKey
86+ ["command", user, host, port, cmd] ->
87+ runCommand user host (read port) cmd
88+ ["send", user, host, port, path] ->
89+ sendFile user host (read port) path
90+ ["receive", user, host, port, path] ->
91+ receiveFile user host (read port) path
93+ putStrLn "Invalid command line arguments"
95+--------------------------------------------------------------------------------
96+-- Taken from libssh2/ssh-client --
97+--------------------------------------------------------------------------------
99+runCommand login host port command =
100+ ssh login host port $ \ch -> do
101+ channelExecute ch command
102+ result <- readAllChannel ch
103+ let r = decodeString result
104+ print (length result)
108+sendFile login host port path = do
110+ home <- getEnv "HOME"
111+ let known_hosts = home </> ".ssh" </> "known_hosts"
112+ public = home </> ".ssh" </> "id_rsa.pub"
113+ private = home </> ".ssh" </> "id_rsa"
115+ withSession host port $ \_ s -> do
116+ r <- checkHost s host port known_hosts
118+ publicKeyAuthFile s login public private ""
119+ sz <- scpSendFile s 0o644 path (takeFileName path)
120+ putStrLn $ "Sent: " ++ show sz ++ " bytes."
123+receiveFile login host port path = do
125+ home <- getEnv "HOME"
126+ let known_hosts = home </> ".ssh" </> "known_hosts"
127+ public = home </> ".ssh" </> "id_rsa.pub"
128+ private = home </> ".ssh" </> "id_rsa"
130+ withSession host port $ \_ s -> do
131+ r <- checkHost s host port known_hosts
133+ publicKeyAuthFile s login public private ""
134+ sz <- scpReceiveFile s (takeFileName path) path
135+ putStrLn $ "Received: " ++ show sz ++ " bytes."
138+ssh login host port actions = do
140+ home <- getEnv "HOME"
141+ let known_hosts = home </> ".ssh" </> "known_hosts"
142+ public = home </> ".ssh" </> "id_rsa.pub"
143+ private = home </> ".ssh" </> "id_rsa"
144+ withSSH2 known_hosts public private login host port $ actions
147+--------------------------------------------------------------------------------
148+-- Taken from tls-debug/src/SimpleClient.hs --
149+--------------------------------------------------------------------------------
151+tryConnectToAzure :: String -> String -> String -> IO ()
152+tryConnectToAzure subscriptionId pathToCert pathToKey = do
62 cert <- fileReadCertificate pathToCert
153 cert <- fileReadCertificate pathToCert
63 key <- fileReadPrivateKey pathToKey
154 key <- fileReadPrivateKey pathToKey
64 sessionState <- newIORef undefined
155 sessionState <- newIORef undefined
@@ -77,10 +168,6 @@ main = do
78 BSLC.putStrLn d
169 BSLC.putStrLn d
80−--------------------------------------------------------------------------------
81−-- Taken from tls-debug/src/SimpleClient.hs --
82−--------------------------------------------------------------------------------
84runTLS :: Params -> HostName -> PortNumber -> (Context -> IO a) -> IO ()
171runTLS :: Params -> HostName -> PortNumber -> (Context -> IO a) -> IO ()
85runTLS params hostname portNumber f = do
172runTLS params hostname portNumber f = do
86 rng <- RNG.makeSystem
173 rng <- RNG.makeSystem