-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle SFTP V6 extensions commands - md5-hash-handle - check-file-handle - space-available - home-directory
- Loading branch information
1 parent
c1393ae
commit 5414bd7
Showing
4 changed files
with
167 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
require 'net/sftp/protocol/06/base' | ||
|
||
module Net; module SFTP; module Protocol; module V06 | ||
|
||
# Wraps the low-level SFTP calls for version 6 of the SFTP protocol. | ||
# | ||
# None of these protocol methods block--all of them return immediately, | ||
# requiring the SSH event loop to be run while the server response is | ||
# pending. | ||
# | ||
# You will almost certainly never need to use this driver directly. Please | ||
# see Net::SFTP::Session for the recommended interface. | ||
class Extended < V06::Base | ||
|
||
# Parses the given "md5-hash" FXP_EXTENDED_REPL packet and returns a | ||
# hash with one key, :md5, which references the computed hash. | ||
def parse_md5_packet(data) | ||
md5 = "" | ||
|
||
if !data.empty? | ||
md5 = data.read_string | ||
end | ||
|
||
{ :md5 => md5 } | ||
end | ||
|
||
# Parses the given "check-file" FXP_EXTENDED_REPL packet and returns a hash | ||
# with two keys, :algo, which references the hash algorithm used and | ||
# :hashes which references the computed hashes. | ||
def parse_hash_packet(data) | ||
hashes = [] | ||
|
||
algo = data.read_string | ||
size = case algo | ||
when "md5" then 128 | ||
when "sha256" then 256 | ||
when "sha384" then 284 | ||
when "sha512" then 512 | ||
else raise NotImplementedError, "unsupported algorithm: #{algo}" | ||
end | ||
|
||
while !data.eof? do | ||
hashes << data.read(size) | ||
end | ||
|
||
{ :algo => algo, :hashes => hashes } | ||
end | ||
|
||
# Parses the given "home-directory" FXP_EXTENDED_REPL packet and returns a | ||
# hash with one key, :home, which references the home directory returned by | ||
# the server. | ||
def parse_home_packet(data) | ||
{ :home => data.read_string } | ||
end | ||
|
||
# Parses the given FXP_EXTENDED_REPL packet and returns a hash, with | ||
# :extension key, which references SFTP extension and the associated keys | ||
def parse_extented_reply_packet(packet) | ||
packet.read_string do |extension| | ||
data = packet.remainder_as_buffer | ||
parsed_packet = case extension | ||
when "md5-hash" then parse_md5_packet(data) | ||
when "check-file" then parse_hash_packet(data) | ||
when "home-directory" then parse_home_packet(data) | ||
else raise NotImplementedError, "unknown packet type: #{extension}" | ||
end | ||
end | ||
|
||
{ :extension => extension }.merge(parsed_packet) | ||
end | ||
|
||
# Sends a FXP_EXTENDED packet to the server to request MD5 checksum | ||
# computation for file (or portion of file) obtained on the given +handle+, | ||
# for the given byte +offset+ and +length+. The +quick_hash+ parameter is | ||
# the hash over the first 2048 bytes of the data. It allows the server to | ||
# quickly check if it is worth the resources to hash a big file. | ||
def md5(handle, offset, length, quick_hash) | ||
send_request(FXP_EXTENDED, :string, "md5-hash-handle", :int64, offset, :int64, length, :string, quick_hash) | ||
end | ||
|
||
# Sends a FXP_EXTENDED packet to the server to request checksum computation | ||
# for file (or portion of file) obtained on the given +handle+, for the | ||
# given byte +offset+ and +length+. The +block_size+ parameter is used to | ||
# compute over every +block_size+ block in the file. If the +block_size+ is | ||
# 0, then only one hash, over the entire range, is made. | ||
def hash(handle, offset, length, block_size=0) | ||
if block_size != 0 && block_size < 255 | ||
block_size = 256 | ||
end | ||
send_request(FXP_EXTENDED, :string, "check-file-handle", :string, handle, :string, "md5,sha256,sha384,sha512", :int64, offset, :int64, length, :long, block_size) | ||
end | ||
|
||
# Sends a FXP_EXTENDED packet to the server to request disk space availability | ||
# for the given +path+ location. | ||
def space_available(path) | ||
send_request(FXP_EXTENDED, :string, "space-available", :string, path) | ||
end | ||
|
||
# Sends a FXP_EXTENDED packet to the server to request home directory | ||
# for the given +username+. | ||
def home(username) | ||
send_request(FXP_EXTENDED, :string, "home-directory", :string, username) | ||
end | ||
|
||
end | ||
|
||
end; end; end; end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
require 'common' | ||
require 'protocol/06/test_base' | ||
|
||
class Protocol::V06::TestExtended < Protocol::V06::TestBase | ||
|
||
def setup | ||
@session = stub('session', :logger => nil) | ||
@base = driver.new(@session) | ||
end | ||
|
||
def test_version | ||
assert_equal 6, @base.version | ||
end | ||
|
||
def test_md5_should_send_md5_hash_packet | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "md5-hash-handle", :int64, 112233, :int64, 445566, :string, "ABCDEF") | ||
assert_equal 0, @base.md5("test", 112233, 445566, "ABCDEF") | ||
end | ||
|
||
def test_hash_should_send_hash_packet | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "check-file-handle", :string, "test", :string, "md5,sha256,sha384,sha512", :int64, 112233, :int64, 445566, :long, 0) | ||
assert_equal 0, @base.hash("test", 112233, 445566) | ||
end | ||
|
||
def test_hash_should_send_hash_packet_with_block_size | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "check-file-handle", :string, "test", :string, "md5,sha256,sha384,sha512", :int64, 112233, :int64, 445566, :long, 256) | ||
assert_equal 0, @base.hash("test", 112233, 445566, 123) | ||
end | ||
|
||
def test_hash_should_send_hash_packet_with_valid_block_size | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "check-file-handle", :string, "test", :string, "md5,sha256,sha384,sha512", :int64, 112233, :int64, 445566, :long, 256) | ||
assert_equal 0, @base.hash("test", 112233, 445566, -1) | ||
end | ||
|
||
def test_space_available_should_send_space_available_packet | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "space-available", :string, "/var/log/Xorg.0.log") | ||
assert_equal 0, @base.space_available("/var/log/Xorg.0.log") | ||
end | ||
|
||
def test_home_should_send_home_directory_packet | ||
@session.expects(:send_packet).with(FXP_EXTENDED, :long, 0, :string, "home-directory", :string, "test") | ||
assert_equal 0, @base.home("test") | ||
end | ||
|
||
private | ||
|
||
def driver | ||
Net::SFTP::Protocol::V06::Extended | ||
end | ||
end |