module Network.SSH.Client.LibSSH2.Foreign
(
KnownHosts, KnownHostResult (..), KnownHostType (..),
Direction (..),
initialize, exit,
initSession, freeSession, disconnectSession,
handshake,
blockedDirections,
setBlocking,
initKnownHosts, freeKnownHosts, knownHostsReadFile,
getHostKey, checkKnownHost,
publicKeyAuthFile,
openChannelSession, closeChannel, freeChannel,
channelSendEOF,
readChannel, writeChannel,
writeChannelFromHandle, readChannelToHandle,
channelProcess, channelExecute, channelShell,
requestPTY, requestPTYEx,
channelExitStatus, channelExitSignal,
scpSendChannel, scpReceiveChannel,
TraceFlag (..), setTraceMode
) where
import Control.Exception
import Control.Monad
import Foreign
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import System.IO
import Network.Socket
import Data.Bits
import Data.Int
import Data.Time.Clock.POSIX
import Text.Printf
import Network.SSH.Client.LibSSH2.Types
import Network.SSH.Client.LibSSH2.Errors
data KnownHostType =
TYPE_MASK
| TYPE_PLAIN
| TYPE_SHA1
| TYPE_CUSTOM
| KEYENC_MASK
| KEYENC_RAW
| KEYENC_BASE64
| KEY_MASK
| KEY_SHIFT
| KEY_RSA1
| KEY_SSHRSA
| KEY_SSHDSS
deriving (Eq, Show)
kht2int :: KnownHostType -> CInt
kht2int TYPE_MASK = 0xffff
kht2int TYPE_PLAIN = 1
kht2int TYPE_SHA1 = 2
kht2int TYPE_CUSTOM = 3
kht2int KEYENC_MASK = 3 `shiftL` 16
kht2int KEYENC_RAW = 1 `shiftL` 16
kht2int KEYENC_BASE64 = 2 `shiftL` 16
kht2int KEY_MASK = 3 `shiftL` 18
kht2int KEY_SHIFT = 18
kht2int KEY_RSA1 = 1 `shiftL` 18
kht2int KEY_SSHRSA = 2 `shiftL` 18
kht2int KEY_SSHDSS = 3 `shiftL` 18
typemask2int :: [KnownHostType] -> CInt
typemask2int list = foldr (.|.) 0 (map kht2int list)
data KnownHostResult =
MATCH
| MISMATCH
| NOTFOUND
| FAILURE
deriving (Eq, Show, Ord, Enum)
int2khresult :: CInt -> KnownHostResult
int2khresult = toEnum . fromIntegral
data KnownHost = KnownHost {
khMagic :: CUInt,
khNode :: Ptr (),
khName :: String,
khKey :: String,
khTypeMask :: [KnownHostType] }
deriving (Eq, Show)
data Direction = INBOUND | OUTBOUND
deriving (Eq, Show)
int2dir 1 = [INBOUND]
int2dir 2 = [OUTBOUND]
int2dir 3 = [INBOUND, OUTBOUND]
int2dir x = error $ "Unknown direction: " ++ show x
init_crypto :: Bool -> CInt
init_crypto False = 1
init_crypto True = 0
ssh2socket :: Socket -> CInt
ssh2socket (MkSocket s _ _ _ _) = s
initialize :: Bool -> IO (Int)
initialize a1 =
let {a1' = init_crypto a1} in
initialize'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
exit :: IO ()
exit =
exit'_ >>= \res ->
return ()
initSession :: IO Session
initSession = do
ptr <- libssh2_session_init_ex nullFunPtr nullFunPtr nullFunPtr nullPtr
handleNullPtr ptr
freeSession :: Session -> IO (Int)
freeSession a1 =
let {a1' = toPointer a1} in
freeSession'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
disconnectSessionEx :: Session -> Int -> String -> String -> IO (Int)
disconnectSessionEx a1 a2 a3 a4 =
let {a1' = toPointer a1} in
let {a2' = fromIntegral a2} in
withCString a3 $ \a3' ->
withCString a4 $ \a4' ->
disconnectSessionEx'_ a1' a2' a3' a4' >>= \res ->
handleInt res >>= \res' ->
return (res')
disconnectSession :: Session
-> String
-> IO Int
disconnectSession s msg = disconnectSessionEx s 11 msg ""
setBlocking :: Session -> Bool -> IO ()
setBlocking a1 a2 =
let {a1' = toPointer a1} in
let {a2' = bool2int a2} in
setBlocking'_ a1' a2' >>= \res ->
return ()
bool2int :: Bool -> CInt
bool2int True = 1
bool2int False = 0
handshake :: Session -> Socket -> IO (Int)
handshake a1 a2 =
let {a1' = toPointer a1} in
let {a2' = ssh2socket a2} in
handshake'_ a1' a2' >>= \res ->
handleInt res >>= \res' ->
return (res')
initKnownHosts :: Session -> IO (KnownHosts)
initKnownHosts a1 =
let {a1' = toPointer a1} in
initKnownHosts'_ a1' >>= \res ->
handleNullPtr res >>= \res' ->
return (res')
freeKnownHosts :: KnownHosts -> IO ()
freeKnownHosts a1 =
let {a1' = toPointer a1} in
freeKnownHosts'_ a1' >>= \res ->
return ()
knownHostsReadFile_ :: KnownHosts -> String -> CInt -> IO (Int)
knownHostsReadFile_ a1 a2 a3 =
let {a1' = toPointer a1} in
withCString a2 $ \a2' ->
let {a3' = id a3} in
knownHostsReadFile_'_ a1' a2' a3' >>= \res ->
handleInt res >>= \res' ->
return (res')
knownHostsReadFile :: KnownHosts
-> FilePath
-> IO Int
knownHostsReadFile kh path = knownHostsReadFile_ kh path 1
getHostKey :: Session -> IO (String, Size, CInt)
getHostKey a1 =
let {a1' = toPointer a1} in
alloca $ \a2' ->
alloca $ \a3' ->
getHostKey'_ a1' a2' a3' >>= \res ->
peek a2'>>= \a2'' ->
peek a3'>>= \a3'' ->
peekCString res >>= \res' ->
return (res', a2'', a3'')
checkKnownHost_ :: KnownHosts -> String -> Int -> String -> Int -> [KnownHostType] -> Ptr () -> IO (KnownHostResult)
checkKnownHost_ a1 a2 a3 a4 a5 a6 a7 =
let {a1' = toPointer a1} in
withCString a2 $ \a2' ->
let {a3' = fromIntegral a3} in
withCString a4 $ \a4' ->
let {a5' = fromIntegral a5} in
let {a6' = typemask2int a6} in
let {a7' = castPtr a7} in
checkKnownHost_'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
let {res' = int2khresult res} in
return (res')
checkKnownHost :: KnownHosts
-> String
-> Int
-> String
-> [KnownHostType]
-> IO KnownHostResult
checkKnownHost kh host port key mask = checkKnownHost_ kh host port key (length key) mask nullPtr
publicKeyAuthFile :: Session -> String -> String -> String -> String -> IO (Int)
publicKeyAuthFile a1 a2 a3 a4 a5 =
let {a1' = toPointer a1} in
withCStringLenIntConv a2 $ \(a2'1, a2'2) ->
withCString a3 $ \a3' ->
withCString a4 $ \a4' ->
withCString a5 $ \a5' ->
publicKeyAuthFile'_ a1' a2'1 a2'2 a3' a4' a5' >>= \res ->
handleInt res >>= \res' ->
return (res')
openSessionChannelEx :: Session -> String -> Int -> Int -> String -> IO (Channel)
openSessionChannelEx a1 a2 a3 a4 a5 =
let {a1' = toPointer a1} in
withCStringLenIntConv a2 $ \(a2'1, a2'2) ->
let {a3' = fromIntegral a3} in
let {a4' = fromIntegral a4} in
withCStringLenIntConv a5 $ \(a5'1, a5'2) ->
openSessionChannelEx'_ a1' a2'1 a2'2 a3' a4' a5'1 a5'2 >>= \res ->
handleNullPtr res >>= \res' ->
return (res')
openChannelSession :: Session -> IO Channel
openChannelSession s = openSessionChannelEx s "session" 65536 32768 ""
channelProcess :: Channel -> String -> String -> IO Int
channelProcess ch kind command = do
withCStringLenIntConv kind $ \(kindptr, kindlen) ->
withCStringLenIntConv command $ \(commandptr, commandlen) ->
libssh2_channel_process_startup
(toPointer ch)
kindptr kindlen
commandptr commandlen >>= handleInt
channelExecute :: Channel -> String -> IO Int
channelExecute c command = channelProcess c "exec" command
channelShell :: Channel -> IO Int
channelShell c = do
withCStringLenIntConv "shell" $ \(kindptr, kindlen) ->
libssh2_channel_process_startup
(toPointer c)
kindptr
kindlen
nullPtr 0 >>= handleInt
requestPTYEx :: Channel -> String -> String -> Int -> Int -> Int -> Int -> IO (Int)
requestPTYEx a1 a2 a3 a4 a5 a6 a7 =
let {a1' = toPointer a1} in
withCStringLenIntConv a2 $ \(a2'1, a2'2) ->
withCStringLenIntConv a3 $ \(a3'1, a3'2) ->
let {a4' = fromIntegral a4} in
let {a5' = fromIntegral a5} in
let {a6' = fromIntegral a6} in
let {a7' = fromIntegral a7} in
requestPTYEx'_ a1' a2'1 a2'2 a3'1 a3'2 a4' a5' a6' a7' >>= \res ->
handleInt res >>= \res' ->
return (res')
requestPTY :: Channel -> String -> IO Int
requestPTY ch term = requestPTYEx ch term "" 0 0 0 0
readChannelEx :: Channel -> Int -> Size -> IO (SSize, String)
readChannelEx ch i size =
allocaBytes (fromIntegral size) $ \buffer -> do
rc <- libssh2_channel_read_ex (toPointer ch) (fromIntegral i) buffer size
when (rc < 0) $
throw (int2error rc)
str <- peekCAStringLen (buffer, fromIntegral rc)
return (rc, str)
readChannel :: Channel
-> Size
-> IO (SSize, String)
readChannel c sz = readChannelEx c 0 sz
writeChannelEx :: Channel -> Int -> String -> IO (Int)
writeChannelEx a1 a2 a3 =
let {a1' = toPointer a1} in
let {a2' = fromIntegral a2} in
withCStringLenIntConv a3 $ \(a3'1, a3'2) ->
writeChannelEx'_ a1' a2' a3'1 a3'2 >>= \res ->
handleInt res >>= \res' ->
return (res')
writeChannel :: Channel -> String -> IO Int
writeChannel ch str = writeChannelEx ch 0 str
channelSendEOF :: Channel -> IO (Int)
channelSendEOF a1 =
let {a1' = toPointer a1} in
channelSendEOF'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
data TraceFlag =
T_TRANS
| T_KEX
| T_AUTH
| T_CONN
| T_SCP
| T_SFTP
| T_ERROR
| T_PUBLICKEY
| T_SOCKET
deriving (Eq, Show)
tf2int :: TraceFlag -> CInt
tf2int T_TRANS = 1 `shiftL` 1
tf2int T_KEX = 1 `shiftL` 2
tf2int T_AUTH = 1 `shiftL` 3
tf2int T_CONN = 1 `shiftL` 4
tf2int T_SCP = 1 `shiftL` 5
tf2int T_SFTP = 1 `shiftL` 6
tf2int T_ERROR = 1 `shiftL` 7
tf2int T_PUBLICKEY = 1 `shiftL` 8
tf2int T_SOCKET = 1 `shiftL` 9
trace2int :: [TraceFlag] -> CInt
trace2int flags = foldr (.|.) 0 (map tf2int flags)
setTraceMode :: Session -> [TraceFlag] -> IO (Int)
setTraceMode a1 a2 =
let {a1' = toPointer a1} in
let {a2' = trace2int a2} in
setTraceMode'_ a1' a2' >>= \res ->
handleInt res >>= \res' ->
return (res')
writeChannelFromHandle session ch handle =
let
go h done fileSize buffer = do
sz <- hGetBuf h buffer bufferSize
sent <- send 0 (fromIntegral sz) buffer
let newDone = done + sent
if sz < bufferSize
then do
return $ fromIntegral sz
else do
rest <- go h newDone fileSize buffer
return $ fromIntegral sz + rest
send written 0 _ = return written
send written size buffer = do
sent <- libssh2_channel_write_ex
(toPointer ch)
0
(plusPtr buffer written)
(fromIntegral size)
when (sent < 0) $ do
throw (int2error sent)
send (written + fromIntegral sent) (size sent) buffer
bufferSize = 0x100000
in do
fileSize <- hFileSize handle
libssh2_trace (toPointer session) (512)
allocaBytes bufferSize $ \buffer ->
go handle 0 fileSize buffer
readChannelToHandle :: Channel -> Handle -> Offset -> IO Integer
readChannelToHandle ch handle fileSize = do
allocaBytes bufferSize $ \buffer ->
readChannelCB ch buffer bufferSize fileSize callback
where
callback buffer size = hPutBuf handle buffer size
bufferSize :: Int
bufferSize = 0x100000
readChannelCB :: Channel -> CString -> Int -> Offset -> (CString -> Int -> IO a) -> IO Integer
readChannelCB ch buffer bufferSize fileSize callback =
let go got = do
let toRead = min (fromIntegral fileSize got) (fromIntegral bufferSize)
sz <- libssh2_channel_read_ex
(toPointer ch)
0
buffer
(fromIntegral toRead)
when (sz < 0) $
throw (int2error sz)
let isz :: Integer
isz = fromIntegral sz
callback buffer (fromIntegral sz)
eof <- libssh2_channel_eof (toPointer ch)
let newGot = got + fromIntegral sz
if (eof == 1) || (newGot == fromIntegral fileSize)
then do
return isz
else do
rest <- go newGot
return $ isz + rest
in go 0
channelIsEOF :: Channel -> IO (Bool)
channelIsEOF a1 =
let {a1' = toPointer a1} in
channelIsEOF'_ a1' >>= \res ->
handleBool res >>= \res' ->
return (res')
closeChannel :: Channel -> IO (Int)
closeChannel a1 =
let {a1' = toPointer a1} in
closeChannel'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
freeChannel :: Channel -> IO (Int)
freeChannel a1 =
let {a1' = toPointer a1} in
freeChannel'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
blockedDirections :: Session -> IO ([Direction])
blockedDirections a1 =
let {a1' = toPointer a1} in
blockedDirections'_ a1' >>= \res ->
let {res' = int2dir res} in
return (res')
channelExitStatus :: Channel -> IO (Int)
channelExitStatus a1 =
let {a1' = toPointer a1} in
channelExitStatus'_ a1' >>= \res ->
handleInt res >>= \res' ->
return (res')
channelExitSignal_ :: Channel -> Ptr Int -> Ptr Int -> Ptr Int -> IO (Int, String, Maybe String, Maybe String)
channelExitSignal_ a1 a3 a5 a7 =
let {a1' = toPointer a1} in
alloca $ \a2' ->
let {a3' = castPtr a3} in
alloca $ \a4' ->
let {a5' = castPtr a5} in
alloca $ \a6' ->
let {a7' = castPtr a7} in
channelExitSignal_'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
peekCStringPtr a2'>>= \a2'' ->
peekMaybeCStringPtr a4'>>= \a4'' ->
peekMaybeCStringPtr a6'>>= \a6'' ->
handleInt res >>= \res' ->
return (res', a2'', a4'', a6'')
channelExitSignal :: Channel -> IO (Int, String, Maybe String, Maybe String)
channelExitSignal ch = channelExitSignal_ ch nullPtr nullPtr nullPtr
scpSendChannel :: Session -> String -> Int -> Int64 -> POSIXTime -> POSIXTime -> IO (Channel)
scpSendChannel a1 a2 a3 a4 a5 a6 =
let {a1' = toPointer a1} in
withCString a2 $ \a2' ->
let {a3' = fromIntegral a3} in
let {a4' = fromIntegral a4} in
let {a5' = round a5} in
let {a6' = round a6} in
scpSendChannel'_ a1' a2' a3' a4' a5' a6' >>= \res ->
handleNullPtr res >>= \res' ->
return (res')
type Offset = (CLong)
newtype Stat = Stat (Ptr (Stat))
scpReceiveChannel :: Session -> FilePath -> IO (Channel, Offset)
scpReceiveChannel s path = do
(ptr, sz) <- withCString path $ \pathptr ->
allocaBytes 88 $ \statptr -> do
p <- libssh2_scp_recv (toPointer s) pathptr statptr
size <- (\ptr -> do {peekByteOff ptr 44 ::IO CLong}) statptr
return (p, size)
channel <- handleNullPtr ptr
return (channel, sz)
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_init"
initialize'_ :: (CInt -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_exit"
exit'_ :: (IO ())
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_init_ex"
libssh2_session_init_ex :: ((FunPtr (CUInt -> ((Ptr (Ptr ())) -> (IO (Ptr ()))))) -> ((FunPtr ((Ptr ()) -> ((Ptr (Ptr ())) -> (IO ())))) -> ((FunPtr ((Ptr ()) -> (CUInt -> ((Ptr (Ptr ())) -> (IO (Ptr ())))))) -> ((Ptr ()) -> (IO (Ptr ()))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_free"
freeSession'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_disconnect_ex"
disconnectSessionEx'_ :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> ((Ptr CChar) -> (IO CInt)))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_set_blocking"
setBlocking'_ :: ((Ptr ()) -> (CInt -> (IO ())))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_handshake"
handshake'_ :: ((Ptr ()) -> (CInt -> (IO CInt)))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_init"
initKnownHosts'_ :: ((Ptr ()) -> (IO (Ptr ())))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_free"
freeKnownHosts'_ :: ((Ptr ()) -> (IO ()))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_readfile"
knownHostsReadFile_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (IO CInt))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_hostkey"
getHostKey'_ :: ((Ptr ()) -> ((Ptr CUInt) -> ((Ptr CInt) -> (IO (Ptr CChar)))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_checkp"
checkKnownHost_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> ((Ptr CChar) -> (CUInt -> (CInt -> ((Ptr (Ptr ())) -> (IO CInt))))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_userauth_publickey_fromfile_ex"
publicKeyAuthFile'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> ((Ptr CChar) -> ((Ptr CChar) -> (IO CInt)))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_open_ex"
openSessionChannelEx'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> (CUInt -> (CUInt -> ((Ptr CChar) -> (CUInt -> (IO (Ptr ())))))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_process_startup"
libssh2_channel_process_startup :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> (CUInt -> (IO CInt))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_request_pty_ex"
requestPTYEx'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> (CUInt -> (CInt -> (CInt -> (CInt -> (CInt -> (IO CInt))))))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_read_ex"
libssh2_channel_read_ex :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> (CUInt -> (IO CInt)))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_write_ex"
writeChannelEx'_ :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> (CUInt -> (IO CInt)))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_send_eof"
channelSendEOF'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_trace"
setTraceMode'_ :: ((Ptr ()) -> (CInt -> (IO CInt)))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_write_ex"
libssh2_channel_write_ex :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> (CUInt -> (IO CInt)))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_trace"
libssh2_trace :: ((Ptr ()) -> (CInt -> (IO CInt)))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_eof"
libssh2_channel_eof :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_eof"
channelIsEOF'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_close"
closeChannel'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_free"
freeChannel'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_block_directions"
blockedDirections'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_get_exit_status"
channelExitStatus'_ :: ((Ptr ()) -> (IO CInt))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_get_exit_signal"
channelExitSignal_'_ :: ((Ptr ()) -> ((Ptr (Ptr CChar)) -> ((Ptr CUInt) -> ((Ptr (Ptr CChar)) -> ((Ptr CUInt) -> ((Ptr (Ptr CChar)) -> ((Ptr CUInt) -> (IO CInt))))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_scp_send64"
scpSendChannel'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (CLLong -> (CLong -> (CLong -> (IO (Ptr ()))))))))
foreign import ccall safe "Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_scp_recv"
libssh2_scp_recv :: ((Ptr ()) -> ((Ptr CChar) -> ((Ptr ()) -> (IO (Ptr ())))))