From c5a526735109a27d919b340148db6a5a99f9ad09 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 25 Nov 2014 10:52:24 +0100 Subject: ssh: Implements and tests erl_tar read from remote host. --- lib/ssh/doc/src/ssh_sftp.xml | 106 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 6 deletions(-) (limited to 'lib/ssh/doc') diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index 251f5a4be3..ab111562f9 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -196,19 +196,113 @@ - open_tar(ChannelPid, Path) -> - open_tar(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, Reason} - Open a tar file on the server to which ChannelPid is connected and return a handle + open_tar(ChannelPid, Path, Mode) -> + open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | {error, Reason} + Opens a tar file on the server to which ChannelPid is connected and returns a handle ChannelPid = pid() Path = string() + Mode = [read] | [write] | [read,EncryptOpt] | [write,DecryptOpt] + EncryptOpt = {crypto,{InitFun,EncryptFun,CloseFun}} + DecryptOpt = {crypto,{InitFun,DecryptFun}} + InitFun = (fun() -> {ok,CryptoState}) | (fun() -> {ok,CryptoState,ChunkSize}) + CryptoState = any() + ChunkSize = undefined | pos_integer() + EncryptFun = (fun(PlainBin,CryptoState) -> EncryptResult) + EncryptResult = {ok,EncryptedBin,CryptoState} | {ok,EncryptedBin,CryptoState,ChunkSize} + PlainBin = binary() + EncryptedBin = binary() + DecryptFun = (fun(EncryptedBin,CryptoState) -> DecryptResult) + DecryptResult = {ok,PlainBin,CryptoState} | {ok,PlainBin,CryptoState,ChunkSize} + CloseFun = (fun(PlainBin,CryptoState) -> {ok,EncryptedBin}) Timeout = timeout() Reason = term() -

Opens a handle to a tar file on the server, the handle - can be used for remote tar manipulation as defined by the - erl_tar:init/3 function.

+

Opens a handle to a tar file on the server associated with ChannelPid. The handle + can be used for remote tar creation and extraction as defined by the + erl_tar:init/3 function. +

+

An example of writing and then reading a tar file:

+ + {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]), + ok = erl_tar:add(HandleWrite, .... ), + ok = erl_tar:add(HandleWrite, .... ), + ... + ok = erl_tar:add(HandleWrite, .... ), + ok = erl_tar:close(HandleWrite), + + %% And for reading + {ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read]), + {ok,NameValueList} = erl_tar:extract(HandleRead,[memory]), + ok = erl_tar:close(HandleRead), + + +

The crypto mode option is applied to the generated stream of bytes just prior to sending + them to the sftp server. This is intended for encryption but could of course be used for other + purposes. +

+

The InitFun is applied once + prior to any other crypto operation. The returned CryptoState is then folded into + repeated applications of the EncryptFun or DecryptFun. The binary returned + from those Funs are sent further to the remote sftp server. Finally - if doing encryption + - the CloseFun is applied to the last piece of data. The CloseFun is + responsible for padding (if needed) and encryption of that last piece. +

+

The ChunkSize defines the size of the PlainBins that EncodeFun is applied + to. If the ChunkSize is undefined the size of the PlainBins varies because + this is inteded for stream crypto while a fixed ChunkSize is intended for block crypto. It + is possible to change the ChunkSizes in the return from the EncryptFun or + DecryptFun. It is in fact possible to change the value between pos_integer() and + undefined. +

+

The write and read example above can be extended with encryption and decryption:

+ + %% First three parameters depending on which crypto type we select: + Key = <<"This is a 256 bit key. abcdefghi">>, + Ivec0 = crypto:rand_bytes(16), + DataSize = 1024, % DataSize rem 16 = 0 for aes_cbc + + %% Initialization of the CryptoState, in this case it is the Ivector. + InitFun = fun() -> {ok, Ivec0, DataSize} end, + + %% How to encrypt: + EncryptFun = + fun(PlainBin,Ivec) -> + EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec, PlainBin), + {ok, EncryptedBin, crypto:next_iv(aes_cbc,EncryptedBin)} + end, + + %% What to do with the very last block: + CloseFun = + fun(PlainBin, Ivec) -> + EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec, + pad(16,PlainBin) %% Last chunk + ), + {ok, EncryptedBin} + end, + + Cw = {InitFun,EncryptFun,CloseFun}, + {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write,{crypto,Cw}]), + ok = erl_tar:add(HandleWrite, .... ), + ok = erl_tar:add(HandleWrite, .... ), + ... + ok = erl_tar:add(HandleWrite, .... ), + ok = erl_tar:close(HandleWrite), + + %% And for decryption (in this crypto example we could use the same InitFun + %% as for encryption): + DecryptFun = + fun(EncryptedBin,Ivec) -> + PlainBin = crypto:block_decrypt(aes_cbc256, Key, Ivec, EncryptedBin), + {ok, PlainBin, crypto:next_iv(aes_cbc,EncryptedBin)} + end, + + Cr = {InitFun,DecryptFun}, + {ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read,{crypto,Cw}]), + {ok,NameValueList} = erl_tar:extract(HandleRead,[memory]), + ok = erl_tar:close(HandleRead), +
-- cgit v1.2.3