hrr_rb_sftp 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +23 -0
- data/lib/hrr_rb_sftp.rb +79 -1
- data/lib/hrr_rb_sftp/loggable.rb +34 -0
- data/lib/hrr_rb_sftp/protocol.rb +39 -33
- data/lib/hrr_rb_sftp/protocol/common.rb +6 -3
- data/lib/hrr_rb_sftp/protocol/common/data_types.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/byte.rb +40 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/extension_pair.rb +41 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/extension_pairs.rb +42 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/string.rb +42 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/uint32.rb +40 -0
- data/lib/hrr_rb_sftp/protocol/common/data_types/uint64.rb +40 -0
- data/lib/hrr_rb_sftp/protocol/common/packets.rb +16 -0
- data/lib/hrr_rb_sftp/protocol/common/packets/001_ssh_fxp_init.rb +27 -0
- data/lib/hrr_rb_sftp/protocol/common/packets/002_ssh_fxp_version.rb +28 -0
- data/lib/hrr_rb_sftp/protocol/common/packets/packet.rb +96 -0
- data/lib/hrr_rb_sftp/protocol/version1.rb +11 -3
- data/lib/hrr_rb_sftp/protocol/version1/data_types.rb +15 -0
- data/lib/hrr_rb_sftp/protocol/version1/data_types/attrs.rb +91 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets.rb +72 -0
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/003_ssh_fxp_open.rb +94 -43
- data/lib/hrr_rb_sftp/protocol/version1/packets/004_ssh_fxp_close.rb +61 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/005_ssh_fxp_read.rb +72 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/006_ssh_fxp_write.rb +64 -0
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/007_ssh_fxp_lstat.rb +27 -9
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/008_ssh_fxp_fstat.rb +26 -9
- data/lib/hrr_rb_sftp/protocol/version1/packets/009_ssh_fxp_setstat.rb +92 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/010_ssh_fxp_fsetstat.rb +85 -0
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/011_ssh_fxp_opendir.rb +32 -11
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/012_ssh_fxp_readdir.rb +73 -49
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/013_ssh_fxp_remove.rb +27 -9
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/014_ssh_fxp_mkdir.rb +28 -10
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/015_ssh_fxp_rmdir.rb +32 -12
- data/lib/hrr_rb_sftp/protocol/version1/packets/016_ssh_fxp_realpath.rb +47 -0
- data/lib/hrr_rb_sftp/protocol/version1/{packet → packets}/017_ssh_fxp_stat.rb +27 -9
- data/lib/hrr_rb_sftp/protocol/version1/packets/101_ssh_fxp_status.rb +73 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/102_ssh_fxp_handle.rb +28 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/103_ssh_fxp_data.rb +28 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/104_ssh_fxp_name.rb +48 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/105_ssh_fxp_attrs.rb +28 -0
- data/lib/hrr_rb_sftp/protocol/version1/packets/packet.rb +57 -0
- data/lib/hrr_rb_sftp/protocol/version2.rb +11 -3
- data/lib/hrr_rb_sftp/protocol/version2/data_types.rb +13 -0
- data/lib/hrr_rb_sftp/protocol/version2/packets.rb +14 -0
- data/lib/hrr_rb_sftp/protocol/version2/packets/018_ssh_fxp_rename.rb +91 -0
- data/lib/hrr_rb_sftp/protocol/version3.rb +12 -3
- data/lib/hrr_rb_sftp/protocol/version3/data_types.rb +13 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions.rb +94 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions/extension.rb +58 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions/fsync_at_openssh_com.rb +59 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions/hardlink_at_openssh_com.rb +84 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions/lsetstat_at_openssh_com.rb +132 -0
- data/lib/hrr_rb_sftp/protocol/version3/extensions/posix_rename_at_openssh_com.rb +76 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/014_ssh_fxp_mkdir.rb +75 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/019_ssh_fxp_readlink.rb +76 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/020_ssh_fxp_symlink.rb +76 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/101_ssh_fxp_status.rb +25 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/200_ssh_fxp_extended.rb +95 -0
- data/lib/hrr_rb_sftp/protocol/version3/packets/201_ssh_fxp_extended_reply.rb +60 -0
- data/lib/hrr_rb_sftp/receiver.rb +17 -2
- data/lib/hrr_rb_sftp/sender.rb +15 -1
- data/lib/hrr_rb_sftp/server.rb +43 -12
- data/lib/hrr_rb_sftp/version.rb +5 -1
- metadata +54 -47
- data/lib/hrr_rb_sftp/protocol/common/data_type.rb +0 -15
- data/lib/hrr_rb_sftp/protocol/common/data_type/byte.rb +0 -22
- data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pair.rb +0 -23
- data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pairs.rb +0 -24
- data/lib/hrr_rb_sftp/protocol/common/data_type/string.rb +0 -24
- data/lib/hrr_rb_sftp/protocol/common/data_type/uint32.rb +0 -22
- data/lib/hrr_rb_sftp/protocol/common/data_type/uint64.rb +0 -22
- data/lib/hrr_rb_sftp/protocol/common/packet.rb +0 -11
- data/lib/hrr_rb_sftp/protocol/common/packet/001_ssh_fxp_init.rb +0 -18
- data/lib/hrr_rb_sftp/protocol/common/packet/002_ssh_fxp_version.rb +0 -19
- data/lib/hrr_rb_sftp/protocol/common/packetable.rb +0 -72
- data/lib/hrr_rb_sftp/protocol/version1/data_type.rb +0 -11
- data/lib/hrr_rb_sftp/protocol/version1/data_type/attrs.rb +0 -54
- data/lib/hrr_rb_sftp/protocol/version1/packet.rb +0 -29
- data/lib/hrr_rb_sftp/protocol/version1/packet/004_ssh_fxp_close.rb +0 -44
- data/lib/hrr_rb_sftp/protocol/version1/packet/005_ssh_fxp_read.rb +0 -53
- data/lib/hrr_rb_sftp/protocol/version1/packet/006_ssh_fxp_write.rb +0 -46
- data/lib/hrr_rb_sftp/protocol/version1/packet/009_ssh_fxp_setstat.rb +0 -63
- data/lib/hrr_rb_sftp/protocol/version1/packet/010_ssh_fxp_fsetstat.rb +0 -48
- data/lib/hrr_rb_sftp/protocol/version1/packet/016_ssh_fxp_realpath.rb +0 -30
- data/lib/hrr_rb_sftp/protocol/version1/packet/101_ssh_fxp_status.rb +0 -29
- data/lib/hrr_rb_sftp/protocol/version1/packet/102_ssh_fxp_handle.rb +0 -19
- data/lib/hrr_rb_sftp/protocol/version1/packet/103_ssh_fxp_data.rb +0 -19
- data/lib/hrr_rb_sftp/protocol/version1/packet/104_ssh_fxp_name.rb +0 -33
- data/lib/hrr_rb_sftp/protocol/version1/packet/105_ssh_fxp_attrs.rb +0 -19
- data/lib/hrr_rb_sftp/protocol/version2/data_type.rb +0 -9
- data/lib/hrr_rb_sftp/protocol/version2/packet.rb +0 -11
- data/lib/hrr_rb_sftp/protocol/version2/packet/018_ssh_fxp_rename.rb +0 -70
- data/lib/hrr_rb_sftp/protocol/version3/data_type.rb +0 -9
- data/lib/hrr_rb_sftp/protocol/version3/packet.rb +0 -16
- data/lib/hrr_rb_sftp/protocol/version3/packet/014_ssh_fxp_mkdir.rb +0 -58
- data/lib/hrr_rb_sftp/protocol/version3/packet/019_ssh_fxp_readlink.rb +0 -57
- data/lib/hrr_rb_sftp/protocol/version3/packet/020_ssh_fxp_symlink.rb +0 -58
- data/lib/hrr_rb_sftp/protocol/version3/packet/101_ssh_fxp_status.rb +0 -31
- data/lib/hrr_rb_sftp/protocol/version3/packet/200_ssh_fxp_extended.rb +0 -34
- data/lib/hrr_rb_sftp/protocol/version3/packet/201_ssh_fxp_extended_reply.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6abfc35304fc1fc0475db003dd172814dc2a1e2308f811efdc9e527b8abebfb3
|
4
|
+
data.tar.gz: 38d78a957ea3650ca0942e6425179dec884b9497fa0f8466dd14eaa2daba149e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '082c34d8f7976f2a5443d5a93782c3265541f43e894afaf93ae7230ab9f6d6ef010323752aa83d66ea62c30f53c1df5d1adc9e1e7ab826dad285461dabf65817'
|
7
|
+
data.tar.gz: 87e00e812bf6bea182e6641860cd7a2422f1d7c333881df826e686a570756ee4653d2d51a663383ee027100303e0ea0c78aa251ca9316a2a024e566086fa36ab
|
data/README.md
CHANGED
@@ -13,6 +13,8 @@ hrr_rb_sftp can be run on SSH 2.0 server like OpenSSH or [hrr_rb_ssh](https://gi
|
|
13
13
|
- [Usage](#usage)
|
14
14
|
- [hrr\_rb\_ssh's SFTP subsystem](#hrr_rb_sshs-sftp-subsystem)
|
15
15
|
- [OpenSSH's SFTP subsystem](#opensshs-sftp-subsystem)
|
16
|
+
- [Note](#note)
|
17
|
+
- [Supported extensions](#supported-extensions)
|
16
18
|
- [Development](#development)
|
17
19
|
- [Contributing](#contributing)
|
18
20
|
- [License](#license)
|
@@ -115,6 +117,27 @@ hrr_rb_sftp can be an alternative with replacing the line in the config file. (A
|
|
115
117
|
|
116
118
|
Where, the /path/to/hrr_rb_sftp_server.rb code is the same as shown above.
|
117
119
|
|
120
|
+
## Note
|
121
|
+
|
122
|
+
- Reversal of SSH_FXP_SYMLINK arguments
|
123
|
+
Because OpenSSH's sftp-server implementation takes SSH_FXP_SYMLINK request linkpath and targetpath arguments in reverse order, this library follows it.
|
124
|
+
The SSH_FXP_SYMLINK request format is as follows:
|
125
|
+
|
126
|
+
```
|
127
|
+
uint32 id
|
128
|
+
string targetpath
|
129
|
+
string linkpath
|
130
|
+
```
|
131
|
+
|
132
|
+
## Supported extensions
|
133
|
+
|
134
|
+
The following extensions are supported.
|
135
|
+
|
136
|
+
- hardlink@openssh.com version 1
|
137
|
+
- fsync@openssh.com version 1
|
138
|
+
- posix-rename@openssh.com version 1
|
139
|
+
- lsetstat@openssh.com version 1
|
140
|
+
|
118
141
|
## Development
|
119
142
|
|
120
143
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/hrr_rb_sftp.rb
CHANGED
@@ -1,7 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# hrr_rb_sftp is a pure Ruby SFTP server implementation.
|
3
|
+
# hrr_rb_sftp now supports SFTP protocol version 1, 2, and 3.
|
4
|
+
# hrr_rb_sftp can be run on SSH 2.0 server like OpenSSH or hrr_rb_ssh.
|
5
|
+
#
|
6
|
+
# It is straightforward to implement SFTP server on SSH 2.0 server library written in Ruby like hrr_rb_ssh.
|
7
|
+
# There are two ways to work with hrr_rb_ssh, on same process or spawning child process.
|
8
|
+
# On both cases, hrr_rb_ssh's request handler mechanism is used.
|
9
|
+
#
|
10
|
+
# To run hrr_rb_sftp server on the same process that hrr_rb_ssh is running, instantiate and start the hrr_rb_sftp server in a sftp subsystem request.
|
11
|
+
# On the other hand, because the arguments for the hrr_rb_sftp server can be standard input, output, and error, so hrr_rb_sftp can be a independent program and be spawned as a child process.
|
12
|
+
#
|
13
|
+
# OpenSSH has capability to run user-defined subsystems. Subsystems that the OpenSSH server recognizes are listed in /etc/ssh/sshd_config file.
|
14
|
+
# Usually SFTP subsystem is defined by default to use OpenSSH's SFTP server implementation.
|
15
|
+
# hrr_rb_sftp can be an alternative with replacing the line in the config file. (After editing the config, reloading or restarting sshd is required.)
|
16
|
+
#
|
17
|
+
# The following extensions are supported.
|
18
|
+
# - hardlink@openssh.com
|
19
|
+
# - fsync@openssh.com
|
20
|
+
# - posix-rename@openssh.com
|
21
|
+
# - lsetstat@openssh.com
|
22
|
+
#
|
23
|
+
# @note
|
24
|
+
# - Reversal of SSH_FXP_SYMLINK arguments
|
25
|
+
# Because OpenSSH's sftp-server implementation takes SSH_FXP_SYMLINK request linkpath and targetpath arguments in reverse order, this library follows it.
|
26
|
+
# The SSH_FXP_SYMLINK request format is as follows:
|
27
|
+
#
|
28
|
+
# uint32 id
|
29
|
+
# string targetpath
|
30
|
+
# string linkpath
|
31
|
+
#
|
32
|
+
# @example On the same process that hrr_rb_ssh is running
|
33
|
+
# subsys = HrrRbSsh::Connection::RequestHandler.new { |ctx|
|
34
|
+
# ctx.chain_proc { |chain|
|
35
|
+
# case ctx.subsystem_name
|
36
|
+
# when 'sftp'
|
37
|
+
# begin
|
38
|
+
# sftp_server = HrrRbSftp::Server.new(logger: nil)
|
39
|
+
# sftp_server.start(ctx.io[0], ctx.io[1], ctx.io[2])
|
40
|
+
# exitstatus = 0
|
41
|
+
# rescue
|
42
|
+
# exitstatus = 1
|
43
|
+
# end
|
44
|
+
# else
|
45
|
+
# # Do something for other subsystem, or just return exitstatus
|
46
|
+
# exitstatus = 0
|
47
|
+
# end
|
48
|
+
# exitstatus
|
49
|
+
# }
|
50
|
+
# }
|
51
|
+
# options['connection_channel_request_subsystem'] = subsys
|
52
|
+
#
|
53
|
+
# @example Spawnning SFTP server process
|
54
|
+
# subsys = HrrRbSsh::Connection::RequestHandler.new { |ctx|
|
55
|
+
# ctx.chain_proc { |chain|
|
56
|
+
# case ctx.subsystem_name
|
57
|
+
# when 'sftp'
|
58
|
+
# pid = spawn("/path/to/hrr_rb_sftp_server.rb", {in: ctx.io[0], out: ctx.io[1], err: ctx.io[2]})
|
59
|
+
# exitstatus = Process.waitpid(pid).to_i
|
60
|
+
# else
|
61
|
+
# # Do something for other subsystem, or just return exitstatus
|
62
|
+
# exitstatus = 0
|
63
|
+
# end
|
64
|
+
# exitstatus
|
65
|
+
# }
|
66
|
+
# }
|
67
|
+
# options['connection_channel_request_subsystem'] = subsys
|
68
|
+
#
|
69
|
+
# @example hrr_rb_sftp_server.rb
|
70
|
+
# #!/usr/bin/env ruby
|
71
|
+
# require "hrr_rb_sftp"
|
72
|
+
# server = HrrRbSftp::Server.new(logger: nil)
|
73
|
+
# server.start($stdin, $stdout, $stderr)
|
74
|
+
#
|
75
|
+
# @example Replacing OpenSSH's sftp-server
|
76
|
+
# $ cat /etc/ssh/sshd_config | grep Subsystem
|
77
|
+
# #Subsystem sftp /usr/lib/openssh/sftp-server # Comment out the original line
|
78
|
+
# Subsystem sftp /path/to/hrr_rb_sftp_server.rb
|
79
|
+
#
|
1
80
|
module HrrRbSftp
|
2
81
|
end
|
3
82
|
|
4
|
-
require "fileutils"
|
5
83
|
require "stringio"
|
6
84
|
require "etc"
|
7
85
|
|
data/lib/hrr_rb_sftp/loggable.rb
CHANGED
@@ -1,31 +1,65 @@
|
|
1
1
|
module HrrRbSftp
|
2
|
+
|
3
|
+
#
|
4
|
+
# This module is used to log message with useful logging key.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class SomeClass
|
8
|
+
# include HrrRbSftp::Loggable
|
9
|
+
# def initialize logger
|
10
|
+
# self.logger = logger
|
11
|
+
# end
|
12
|
+
# def log_some_info
|
13
|
+
# log_info { "something" }
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
2
17
|
module Loggable
|
18
|
+
|
19
|
+
#
|
20
|
+
# A logger instance that has #fatal, #error, #warn, #info, and #debug methods.
|
21
|
+
#
|
3
22
|
attr_accessor :logger
|
4
23
|
|
24
|
+
#
|
25
|
+
# Outputs fatal message when the logger's log level fatal or higher.
|
26
|
+
#
|
5
27
|
def log_fatal
|
6
28
|
if logger
|
7
29
|
logger.fatal(log_key){ yield }
|
8
30
|
end
|
9
31
|
end
|
10
32
|
|
33
|
+
#
|
34
|
+
# Outputs error message when the logger's log level error or higher.
|
35
|
+
#
|
11
36
|
def log_error
|
12
37
|
if logger
|
13
38
|
logger.error(log_key){ yield }
|
14
39
|
end
|
15
40
|
end
|
16
41
|
|
42
|
+
#
|
43
|
+
# Outputs warn message when the logger's log level warn or higher.
|
44
|
+
#
|
17
45
|
def log_warn
|
18
46
|
if logger
|
19
47
|
logger.warn(log_key){ yield }
|
20
48
|
end
|
21
49
|
end
|
22
50
|
|
51
|
+
#
|
52
|
+
# Outputs info message when the logger's log level info or higher.
|
53
|
+
#
|
23
54
|
def log_info
|
24
55
|
if logger
|
25
56
|
logger.info(log_key){ yield }
|
26
57
|
end
|
27
58
|
end
|
28
59
|
|
60
|
+
#
|
61
|
+
# Outputs debug message when the logger's log level debug or higher.
|
62
|
+
#
|
29
63
|
def log_debug
|
30
64
|
if logger
|
31
65
|
logger.debug(log_key){ yield }
|
data/lib/hrr_rb_sftp/protocol.rb
CHANGED
@@ -1,56 +1,62 @@
|
|
1
1
|
module HrrRbSftp
|
2
|
+
|
3
|
+
#
|
4
|
+
# This class implements SFTP protocol operations.
|
5
|
+
#
|
2
6
|
class Protocol
|
3
7
|
include Loggable
|
4
8
|
|
9
|
+
#
|
10
|
+
# @return [Array] A list of SFTP protocol versions that the library supports.
|
11
|
+
#
|
5
12
|
def self.versions
|
6
13
|
constants.select{|c| c.to_s.start_with?("Version")}.map{|c| const_get(c)}.map{|klass| klass::PROTOCOL_VERSION}
|
7
14
|
end
|
8
15
|
|
16
|
+
#
|
17
|
+
# @return [Array] A list of extension-pair that the library supports.
|
18
|
+
#
|
19
|
+
def self.extension_pairs version
|
20
|
+
version_class = const_get(:"Version#{version}")
|
21
|
+
if version_class.const_defined?(:Extensions)
|
22
|
+
version_class::Extensions.extension_pairs
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# @param version [Integer] Protocol version.
|
30
|
+
# @param logger [Logger] Logger.
|
31
|
+
#
|
9
32
|
def initialize version, logger: nil
|
10
33
|
self.logger = logger
|
11
34
|
|
12
|
-
@
|
13
|
-
@version = version
|
14
|
-
@
|
15
|
-
|
16
|
-
@packets = packet_classes.map{|pkt| [pkt::TYPE, pkt.new(@handles, logger: logger)]}.inject(Hash.new){|h,(k,v)| h.update({k => v})}
|
35
|
+
@context = Hash.new
|
36
|
+
@context[:version] = version
|
37
|
+
@context[:handles] = Hash.new
|
38
|
+
@packets = self.class.const_get(:"Version#{version}")::Packets.new(@context, logger: logger)
|
17
39
|
end
|
18
40
|
|
41
|
+
#
|
42
|
+
# Responds to a request.
|
43
|
+
#
|
44
|
+
# @param request_payload [String] Request payload.
|
45
|
+
# @return [String] Response payload that is encoded packet generated by each SFTP protocol version and each request responder.
|
46
|
+
#
|
19
47
|
def respond_to request_payload
|
20
|
-
|
21
|
-
response_packet = if @packets.has_key?(request_type)
|
22
|
-
begin
|
23
|
-
request_packet = @packets[request_type].decode request_payload
|
24
|
-
rescue => e
|
25
|
-
{
|
26
|
-
:"type" => @version_class::Packet::SSH_FXP_STATUS::TYPE,
|
27
|
-
:"request-id" => (request_payload[1,4].unpack("N")[0] || 0),
|
28
|
-
:"code" => @version_class::Packet::SSH_FXP_STATUS::SSH_FX_BAD_MESSAGE,
|
29
|
-
:"error message" => e.message,
|
30
|
-
:"language tag" => "",
|
31
|
-
}
|
32
|
-
else
|
33
|
-
@packets[request_type].respond_to request_packet
|
34
|
-
end
|
35
|
-
else
|
36
|
-
{
|
37
|
-
:"type" => @version_class::Packet::SSH_FXP_STATUS::TYPE,
|
38
|
-
:"request-id" => (request_payload[1,4].unpack("N")[0] || 0),
|
39
|
-
:"code" => @version_class::Packet::SSH_FXP_STATUS::SSH_FX_OP_UNSUPPORTED,
|
40
|
-
:"error message" => "Unsupported type: #{request_type}",
|
41
|
-
:"language tag" => "",
|
42
|
-
}
|
43
|
-
end
|
44
|
-
response_type = response_packet[:"type"]
|
45
|
-
@packets[response_type].encode response_packet
|
48
|
+
@packets.respond_to request_payload
|
46
49
|
end
|
47
50
|
|
51
|
+
#
|
52
|
+
# Closes opened and not closed handles.
|
53
|
+
#
|
48
54
|
def close_handles
|
49
55
|
log_info { "closing handles" }
|
50
|
-
@handles.each do |k, v|
|
56
|
+
@context[:handles].each do |k, v|
|
51
57
|
v.close rescue nil
|
52
58
|
end
|
53
|
-
@handles.clear
|
59
|
+
@context[:handles].clear
|
54
60
|
log_info { "handles closed" }
|
55
61
|
end
|
56
62
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module HrrRbSftp
|
2
2
|
class Protocol
|
3
|
+
|
4
|
+
#
|
5
|
+
# This module implements SFTP protocol version independent common functions.
|
6
|
+
#
|
3
7
|
module Common
|
4
8
|
end
|
5
9
|
end
|
6
10
|
end
|
7
11
|
|
8
|
-
require "hrr_rb_sftp/protocol/common/
|
9
|
-
require "hrr_rb_sftp/protocol/common/
|
10
|
-
require "hrr_rb_sftp/protocol/common/packet"
|
12
|
+
require "hrr_rb_sftp/protocol/common/data_types"
|
13
|
+
require "hrr_rb_sftp/protocol/common/packets"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
module Common
|
4
|
+
|
5
|
+
#
|
6
|
+
# This module implements SFTP protocol version common data types to be used to encode or decode packet.
|
7
|
+
#
|
8
|
+
module DataTypes
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require "hrr_rb_sftp/protocol/common/data_types/byte"
|
15
|
+
require "hrr_rb_sftp/protocol/common/data_types/uint32"
|
16
|
+
require "hrr_rb_sftp/protocol/common/data_types/uint64"
|
17
|
+
require 'hrr_rb_sftp/protocol/common/data_types/string'
|
18
|
+
require 'hrr_rb_sftp/protocol/common/data_types/extension_pair'
|
19
|
+
require 'hrr_rb_sftp/protocol/common/data_types/extension_pairs'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
module Common
|
4
|
+
module DataTypes
|
5
|
+
|
6
|
+
#
|
7
|
+
# This module provides methods to convert ::Integer value and 8-bit unsigned binary string each other.
|
8
|
+
#
|
9
|
+
module Byte
|
10
|
+
|
11
|
+
#
|
12
|
+
# Convert ::Integer value into 8-bit unsigned binary string.
|
13
|
+
#
|
14
|
+
# @param arg [::Integer] ::Integer value to be converted.
|
15
|
+
# @raise [::ArgumentError] When arg is not between 0x00 and 0xff.
|
16
|
+
# @return [::String] Converted 8-bit unsigned binary string.
|
17
|
+
#
|
18
|
+
def self.encode arg
|
19
|
+
case arg
|
20
|
+
when 0x00..0xff
|
21
|
+
[arg].pack("C")
|
22
|
+
else
|
23
|
+
raise ArgumentError, "must be in #{0x00}..#{0xff}, but got #{arg.inspect}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Convert 8-bit unsigned binary into ::Integer value.
|
29
|
+
#
|
30
|
+
# @param io [::IO] ::IO instance that has buffer to be read.
|
31
|
+
# @return [::Integer] Converted ::Integer value.
|
32
|
+
#
|
33
|
+
def self.decode io
|
34
|
+
io.read(1).unpack("C")[0]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
module Common
|
4
|
+
module DataTypes
|
5
|
+
|
6
|
+
#
|
7
|
+
# This module provides methods to convert extension-name and extension-data pair represented in ::Hash and binary string each other.
|
8
|
+
#
|
9
|
+
module ExtensionPair
|
10
|
+
|
11
|
+
#
|
12
|
+
# Convert extension-name and extension-data pair represented in ::Hash into binary string.
|
13
|
+
#
|
14
|
+
# @param arg [::Hash{::Symbol=>::String}] Extension-name and extension-data pair represented in ::Hash to be converted.
|
15
|
+
# @raise [::ArgumentError] When arg is not ::Hash value.
|
16
|
+
# @return [::String] Converted binary string.
|
17
|
+
#
|
18
|
+
def self.encode arg
|
19
|
+
unless arg.kind_of? ::Hash
|
20
|
+
raise ArgumentError, "must be a kind of Hash, but got #{arg.inspect}"
|
21
|
+
end
|
22
|
+
DataTypes::String.encode(arg[:"extension-name"]) + DataTypes::String.encode(arg[:"extension-data"])
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Convert binary string into extension-name and extension-data pair represented in ::Hash.
|
27
|
+
#
|
28
|
+
# @param io [::IO] ::IO instance that has buffer to be read.
|
29
|
+
# @return [::Hash{::Symbol=>::String}] Converted extension-name and extension-data pair represented in ::Hash.
|
30
|
+
#
|
31
|
+
def self.decode io
|
32
|
+
{
|
33
|
+
:"extension-name" => DataTypes::String.decode(io),
|
34
|
+
:"extension-data" => DataTypes::String.decode(io),
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
module Common
|
4
|
+
module DataTypes
|
5
|
+
|
6
|
+
#
|
7
|
+
# This module provides methods to convert list of extension-name and extension-data pair represented in ::Array and binary string each other.
|
8
|
+
#
|
9
|
+
module ExtensionPairs
|
10
|
+
|
11
|
+
#
|
12
|
+
# Convert list of extension-name and extension-data pair represented in ::Array into binary string.
|
13
|
+
#
|
14
|
+
# @param arg [::Array<::Hash{::Symbol=>::String}>] List of extension-name and extension-data pair represented in ::Array to be converted.
|
15
|
+
# @raise [::ArgumentError] When arg is not ::Array value.
|
16
|
+
# @return [::String] Converted binary string.
|
17
|
+
#
|
18
|
+
def self.encode arg
|
19
|
+
unless arg.kind_of? ::Array
|
20
|
+
raise ArgumentError, "must be a kind of Array, but got #{arg.inspect}"
|
21
|
+
end
|
22
|
+
arg.map{|arg| ExtensionPair.encode(arg)}.join
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Convert binary string into list of extension-name and extension-data pair represented in ::Array.
|
27
|
+
#
|
28
|
+
# @param io [::IO] ::IO instance that has buffer to be read.
|
29
|
+
# @return [::Array<::Hash{::Symbol=>::String}>] Converted list of extension-name and extension-data pair represented in ::Array.
|
30
|
+
#
|
31
|
+
def self.decode io
|
32
|
+
extension_pairs = Array.new
|
33
|
+
until io.eof?
|
34
|
+
extension_pairs.push ExtensionPair.decode(io)
|
35
|
+
end
|
36
|
+
extension_pairs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|