hrr_rb_ssh 0.1.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.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +22 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +201 -0
  8. data/README.md +47 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/demo/server.rb +134 -0
  13. data/hrr_rb_ssh.gemspec +27 -0
  14. data/lib/hrr_rb_ssh/authentication/authenticator.rb +16 -0
  15. data/lib/hrr_rb_ssh/authentication/method/none/context.rb +28 -0
  16. data/lib/hrr_rb_ssh/authentication/method/none.rb +38 -0
  17. data/lib/hrr_rb_ssh/authentication/method/password/context.rb +29 -0
  18. data/lib/hrr_rb_ssh/authentication/method/password.rb +37 -0
  19. data/lib/hrr_rb_ssh/authentication/method.rb +21 -0
  20. data/lib/hrr_rb_ssh/authentication.rb +107 -0
  21. data/lib/hrr_rb_ssh/closed_authentication_error.rb +7 -0
  22. data/lib/hrr_rb_ssh/closed_connection_error.rb +7 -0
  23. data/lib/hrr_rb_ssh/closed_transport_error.rb +7 -0
  24. data/lib/hrr_rb_ssh/compat.rb +65 -0
  25. data/lib/hrr_rb_ssh/connection/channel/proc_chain/chain_context.rb +22 -0
  26. data/lib/hrr_rb_ssh/connection/channel/proc_chain.rb +25 -0
  27. data/lib/hrr_rb_ssh/connection/channel/session/env/context.rb +43 -0
  28. data/lib/hrr_rb_ssh/connection/channel/session/env.rb +31 -0
  29. data/lib/hrr_rb_ssh/connection/channel/session/exec/context.rb +41 -0
  30. data/lib/hrr_rb_ssh/connection/channel/session/exec.rb +31 -0
  31. data/lib/hrr_rb_ssh/connection/channel/session/pty_req/context.rb +50 -0
  32. data/lib/hrr_rb_ssh/connection/channel/session/pty_req.rb +31 -0
  33. data/lib/hrr_rb_ssh/connection/channel/session/shell/context.rb +37 -0
  34. data/lib/hrr_rb_ssh/connection/channel/session/shell.rb +31 -0
  35. data/lib/hrr_rb_ssh/connection/channel/session/subsystem/context.rb +40 -0
  36. data/lib/hrr_rb_ssh/connection/channel/session/subsystem.rb +31 -0
  37. data/lib/hrr_rb_ssh/connection/channel/session.rb +31 -0
  38. data/lib/hrr_rb_ssh/connection/channel.rb +278 -0
  39. data/lib/hrr_rb_ssh/connection/request_handler.rb +18 -0
  40. data/lib/hrr_rb_ssh/connection.rb +170 -0
  41. data/lib/hrr_rb_ssh/logger.rb +52 -0
  42. data/lib/hrr_rb_ssh/message/001_ssh_msg_disconnect.rb +44 -0
  43. data/lib/hrr_rb_ssh/message/002_ssh_msg_ignore.rb +24 -0
  44. data/lib/hrr_rb_ssh/message/003_ssh_msg_unimplemented.rb +24 -0
  45. data/lib/hrr_rb_ssh/message/004_ssh_msg_debug.rb +26 -0
  46. data/lib/hrr_rb_ssh/message/005_ssh_msg_service_request.rb +24 -0
  47. data/lib/hrr_rb_ssh/message/006_ssh_msg_service_accept.rb +24 -0
  48. data/lib/hrr_rb_ssh/message/020_ssh_msg_kexinit.rb +51 -0
  49. data/lib/hrr_rb_ssh/message/021_ssh_msg_newkeys.rb +23 -0
  50. data/lib/hrr_rb_ssh/message/030_ssh_msg_kexdh_init.rb +24 -0
  51. data/lib/hrr_rb_ssh/message/031_ssh_msg_kexdh_reply.rb +26 -0
  52. data/lib/hrr_rb_ssh/message/050_ssh_msg_userauth_request.rb +58 -0
  53. data/lib/hrr_rb_ssh/message/051_ssh_msg_userauth_failure.rb +25 -0
  54. data/lib/hrr_rb_ssh/message/052_ssh_msg_userauth_success.rb +23 -0
  55. data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok.rb +25 -0
  56. data/lib/hrr_rb_ssh/message/080_ssh_msg_global_request.rb +47 -0
  57. data/lib/hrr_rb_ssh/message/081_ssh_msg_request_success.rb +36 -0
  58. data/lib/hrr_rb_ssh/message/082_ssh_msg_request_failure.rb +23 -0
  59. data/lib/hrr_rb_ssh/message/090_ssh_msg_channel_open.rb +67 -0
  60. data/lib/hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb +67 -0
  61. data/lib/hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb +34 -0
  62. data/lib/hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb +25 -0
  63. data/lib/hrr_rb_ssh/message/094_ssh_msg_channel_data.rb +25 -0
  64. data/lib/hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb +30 -0
  65. data/lib/hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb +24 -0
  66. data/lib/hrr_rb_ssh/message/097_ssh_msg_channel_close.rb +24 -0
  67. data/lib/hrr_rb_ssh/message/098_ssh_msg_channel_request.rb +139 -0
  68. data/lib/hrr_rb_ssh/message/099_ssh_msg_channel_success.rb +24 -0
  69. data/lib/hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb +24 -0
  70. data/lib/hrr_rb_ssh/message/codable.rb +67 -0
  71. data/lib/hrr_rb_ssh/message.rb +36 -0
  72. data/lib/hrr_rb_ssh/transport/compression_algorithm/none.rb +33 -0
  73. data/lib/hrr_rb_ssh/transport/compression_algorithm/zlib.rb +38 -0
  74. data/lib/hrr_rb_ssh/transport/compression_algorithm.rb +22 -0
  75. data/lib/hrr_rb_ssh/transport/constant.rb +11 -0
  76. data/lib/hrr_rb_ssh/transport/data_type.rb +163 -0
  77. data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes_128_cbc.rb +73 -0
  78. data/lib/hrr_rb_ssh/transport/encryption_algorithm/none.rb +49 -0
  79. data/lib/hrr_rb_ssh/transport/encryption_algorithm.rb +22 -0
  80. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +129 -0
  81. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group14_sha1.rb +42 -0
  82. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group1_sha1.rb +34 -0
  83. data/lib/hrr_rb_ssh/transport/kex_algorithm.rb +22 -0
  84. data/lib/hrr_rb_ssh/transport/mac_algorithm/hmac_sha1.rb +45 -0
  85. data/lib/hrr_rb_ssh/transport/mac_algorithm/none.rb +40 -0
  86. data/lib/hrr_rb_ssh/transport/mac_algorithm.rb +22 -0
  87. data/lib/hrr_rb_ssh/transport/mode.rb +11 -0
  88. data/lib/hrr_rb_ssh/transport/receiver.rb +75 -0
  89. data/lib/hrr_rb_ssh/transport/sender.rb +57 -0
  90. data/lib/hrr_rb_ssh/transport/sequence_number.rb +22 -0
  91. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_rsa.rb +108 -0
  92. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +21 -0
  93. data/lib/hrr_rb_ssh/transport.rb +459 -0
  94. data/lib/hrr_rb_ssh/version.rb +6 -0
  95. data/lib/hrr_rb_ssh.rb +13 -0
  96. metadata +193 -0
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_EXTENDED_DATA
10
+ module DataTypeCode
11
+ SSH_EXTENDED_DATA_STDERR = 1
12
+ end
13
+
14
+ class << self
15
+ include Codable
16
+ end
17
+
18
+ ID = self.name.split('::').last
19
+ VALUE = 95
20
+
21
+ DEFINITION = [
22
+ # [Data Type, Field Name]
23
+ ['byte', 'SSH_MSG_CHANNEL_EXTENDED_DATA'],
24
+ ['uint32', 'recipient channel'],
25
+ ['uint32', 'data type code'],
26
+ ['string', 'data'],
27
+ ]
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_EOF
10
+ class << self
11
+ include Codable
12
+ end
13
+
14
+ ID = self.name.split('::').last
15
+ VALUE = 96
16
+
17
+ DEFINITION = [
18
+ # [Data Type, Field Name]
19
+ ['byte', 'SSH_MSG_CHANNEL_EOF'],
20
+ ['uint32', 'recipient channel'],
21
+ ]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_CLOSE
10
+ class << self
11
+ include Codable
12
+ end
13
+
14
+ ID = self.name.split('::').last
15
+ VALUE = 97
16
+
17
+ DEFINITION = [
18
+ # [Data Type, Field Name]
19
+ ['byte', 'SSH_MSG_CHANNEL_CLOSE'],
20
+ ['uint32', 'recipient channel'],
21
+ ]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,139 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_REQUEST
10
+ module SignalName
11
+ ABRT = 'ABRT'
12
+ ALRM = 'ALRM'
13
+ FPE = 'FPE'
14
+ HUP = 'HUP'
15
+ ILL = 'ILL'
16
+ INT = 'INT'
17
+ KILL = 'KILL'
18
+ PIPE = 'PIPE'
19
+ QUIT = 'QUIT'
20
+ SEGV = 'SEGV'
21
+ TERM = 'TERM'
22
+ USR1 = 'USR1'
23
+ USR2 = 'USR2'
24
+ end
25
+
26
+ class << self
27
+ include Codable
28
+ end
29
+
30
+ ID = self.name.split('::').last
31
+ VALUE = 98
32
+
33
+ DEFINITION = [
34
+ # [Data Type, Field Name]
35
+ ['byte', 'SSH_MSG_CHANNEL_REQUEST'],
36
+ ['uint32', 'recipient channel'],
37
+ ['string', 'request type'],
38
+ ['boolean', 'want reply'],
39
+ ]
40
+
41
+ PTY_REQ_DEFINITION = [
42
+ # [Data Type, Field Name]
43
+ # ['string', 'request type' : "pty-req"],
44
+ ['string', 'TERM environment variable value'],
45
+ ['uint32', 'terminal width, characters'],
46
+ ['uint32', 'terminal height, rows'],
47
+ ['uint32', 'terminal width, pixels'],
48
+ ['uint32', 'terminal height, pixels'],
49
+ ['string', 'encoded terminal modes'],
50
+ ]
51
+
52
+ X11_REQ_DEFINITION = [
53
+ # [Data Type, Field Name]
54
+ # ['string', 'request type' : "x11-req"],
55
+ ['boolean', 'single connection'],
56
+ ['string', 'x11 authentication protocol'],
57
+ ['string', 'x11 authentication cookie'],
58
+ ['uint32', 'x11 screen number'],
59
+ ]
60
+
61
+ ENV_DEFINITION = [
62
+ # [Data Type, Field Name]
63
+ # ['string', 'request type' : "env"],
64
+ ['string', 'variable name'],
65
+ ['string', 'variable value'],
66
+ ]
67
+
68
+ SHELL_DEFINITION = [
69
+ # [Data Type, Field Name]
70
+ # ['string', 'request type' : "shell"],
71
+ ]
72
+
73
+ EXEC_DEFINITION = [
74
+ # [Data Type, Field Name]
75
+ # ['string', 'request type' : "exec"],
76
+ ['string', 'command'],
77
+ ]
78
+
79
+ SUBSYSTEM_DEFINITION = [
80
+ # [Data Type, Field Name]
81
+ # ['string', 'request type' : "subsystem"],
82
+ ['string', 'subsystem name'],
83
+ ]
84
+
85
+ WINDOW_CHANGE_DEFINITION = [
86
+ # [Data Type, Field Name]
87
+ # ['string', 'request type' : "window-change"],
88
+ ['uint32', 'terminal width, columns'],
89
+ ['uint32', 'terminal height, rows'],
90
+ ['uint32', 'terminal width, pixels'],
91
+ ['uint32', 'terminal height, pixels'],
92
+ ]
93
+
94
+ XON_XOFF_DEFINITION = [
95
+ # [Data Type, Field Name]
96
+ # ['string', 'request type' : "xon-xoff"],
97
+ ['boolean', 'client can do'],
98
+ ]
99
+
100
+ SIGNAL_DEFINITION = [
101
+ # [Data Type, Field Name]
102
+ # ['string', 'request type' : "signal"],
103
+ ['string', 'signal name'],
104
+ ]
105
+
106
+ EXIT_STATUS_DEFINITION = [
107
+ # [Data Type, Field Name]
108
+ # ['string', 'request type' : "exit-status"],
109
+ ['uint32', 'exit status'],
110
+ ]
111
+
112
+ EXIT_SIGNAL_DEFINITION = [
113
+ # [Data Type, Field Name]
114
+ # ['string', 'request type' : "exit-signal"],
115
+ ['string', 'signal name'],
116
+ ['boolean', 'core dumped'],
117
+ ['string', 'error message'],
118
+ ['string', 'language tag'],
119
+ ]
120
+
121
+ CONDITIONAL_DEFINITION = {
122
+ # Field Name => {Field Value => Conditional Definition}
123
+ 'request type' => {
124
+ 'pty-req' => PTY_REQ_DEFINITION,
125
+ 'x11-req' => X11_REQ_DEFINITION,
126
+ 'env' => ENV_DEFINITION,
127
+ 'shell' => SHELL_DEFINITION,
128
+ 'exec' => EXEC_DEFINITION,
129
+ 'subsystem' => SUBSYSTEM_DEFINITION,
130
+ 'window-change' => WINDOW_CHANGE_DEFINITION,
131
+ 'xon-xoff' => XON_XOFF_DEFINITION,
132
+ 'signal' => SIGNAL_DEFINITION,
133
+ 'exit-status' => EXIT_STATUS_DEFINITION,
134
+ 'exit-signal' => EXIT_SIGNAL_DEFINITION,
135
+ },
136
+ }
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_SUCCESS
10
+ class << self
11
+ include Codable
12
+ end
13
+
14
+ ID = self.name.split('::').last
15
+ VALUE = 99
16
+
17
+ DEFINITION = [
18
+ # [Data Type, Field Name]
19
+ ['byte', 'SSH_MSG_CHANNEL_SUCCESS'],
20
+ ['uint32', 'recipient channel'],
21
+ ]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/message/codable'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module SSH_MSG_CHANNEL_FAILURE
10
+ class << self
11
+ include Codable
12
+ end
13
+
14
+ ID = self.name.split('::').last
15
+ VALUE = 100
16
+
17
+ DEFINITION = [
18
+ # [Data Type, Field Name]
19
+ ['byte', 'SSH_MSG_CHANNEL_FAILURE'],
20
+ ['uint32', 'recipient channel'],
21
+ ]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/transport/data_type'
6
+
7
+ module HrrRbSsh
8
+ module Message
9
+ module Codable
10
+ def logger
11
+ @logger ||= HrrRbSsh::Logger.new self.name
12
+ end
13
+
14
+ def common_definition
15
+ self::DEFINITION
16
+ end
17
+
18
+ def conditional_definition message
19
+ message.inject([]){ |a, (k,v)|
20
+ field_name = k
21
+ field_value = if v.instance_of? ::Proc then v.call else v end
22
+ a + ((self::CONDITIONAL_DEFINITION rescue {}).fetch(field_name, {})[field_value] || [])
23
+ }
24
+ end
25
+
26
+ def encode message, complementary_message={}
27
+ logger.debug('encoding message: ' + message.inspect)
28
+ definition = common_definition + conditional_definition(message.merge complementary_message)
29
+ definition.map{ |data_type, field_name|
30
+ field_value = if message[field_name].instance_of? ::Proc then message[field_name].call else message[field_name] end
31
+ HrrRbSsh::Transport::DataType[data_type].encode( field_value )
32
+ }.join
33
+ end
34
+
35
+ def decode payload, complementary_message={}
36
+ def decode_recursively payload_io, message=nil
37
+ if message.class == Array and message.size == 0
38
+ []
39
+ else
40
+ definition = case message
41
+ when nil
42
+ common_definition
43
+ when Array
44
+ conditional_definition(message)
45
+ end
46
+ decoded_message = definition.map{ |data_type, field_name|
47
+ [
48
+ field_name,
49
+ HrrRbSsh::Transport::DataType[data_type].decode( payload_io )
50
+ ]
51
+ }
52
+
53
+ decoded_message + decode_recursively(payload_io, decoded_message)
54
+ end
55
+ end
56
+
57
+ payload_io = StringIO.new payload
58
+ decoded_message = decode_recursively(payload_io).to_h
59
+ if complementary_message.any?
60
+ decoded_message.merge! decode_recursively(payload_io, complementary_message.to_a).to_h
61
+ end
62
+ logger.debug('decoded message: ' + decoded_message.inspect)
63
+ decoded_message
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/message/001_ssh_msg_disconnect'
5
+ require 'hrr_rb_ssh/message/002_ssh_msg_ignore'
6
+ require 'hrr_rb_ssh/message/003_ssh_msg_unimplemented'
7
+ require 'hrr_rb_ssh/message/004_ssh_msg_debug'
8
+ require 'hrr_rb_ssh/message/005_ssh_msg_service_request'
9
+ require 'hrr_rb_ssh/message/006_ssh_msg_service_accept'
10
+ require 'hrr_rb_ssh/message/020_ssh_msg_kexinit'
11
+ require 'hrr_rb_ssh/message/021_ssh_msg_newkeys'
12
+ require 'hrr_rb_ssh/message/030_ssh_msg_kexdh_init'
13
+ require 'hrr_rb_ssh/message/031_ssh_msg_kexdh_reply'
14
+ require 'hrr_rb_ssh/message/050_ssh_msg_userauth_request'
15
+ require 'hrr_rb_ssh/message/051_ssh_msg_userauth_failure'
16
+ require 'hrr_rb_ssh/message/052_ssh_msg_userauth_success'
17
+ require 'hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok'
18
+ require 'hrr_rb_ssh/message/080_ssh_msg_global_request.rb'
19
+ require 'hrr_rb_ssh/message/081_ssh_msg_request_success.rb'
20
+ require 'hrr_rb_ssh/message/082_ssh_msg_request_failure.rb'
21
+ require 'hrr_rb_ssh/message/090_ssh_msg_channel_open.rb'
22
+ require 'hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb'
23
+ require 'hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb'
24
+ require 'hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb'
25
+ require 'hrr_rb_ssh/message/094_ssh_msg_channel_data.rb'
26
+ require 'hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb'
27
+ require 'hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb'
28
+ require 'hrr_rb_ssh/message/097_ssh_msg_channel_close.rb'
29
+ require 'hrr_rb_ssh/message/098_ssh_msg_channel_request.rb'
30
+ require 'hrr_rb_ssh/message/099_ssh_msg_channel_success.rb'
31
+ require 'hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb'
32
+
33
+ module HrrRbSsh
34
+ module Message
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+
6
+ module HrrRbSsh
7
+ class Transport
8
+ class CompressionAlgorithm
9
+ name_list = [
10
+ 'none'
11
+ ]
12
+
13
+ class None
14
+ def initialize
15
+ @logger = HrrRbSsh::Logger.new self.class.name
16
+ end
17
+
18
+ def deflate data
19
+ data
20
+ end
21
+
22
+ def inflate data
23
+ data
24
+ end
25
+ end
26
+
27
+ @@list ||= Hash.new
28
+ name_list.each do |name|
29
+ @@list[name] = None
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'zlib'
5
+
6
+ require 'hrr_rb_ssh/logger'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ class CompressionAlgorithm
11
+ name_list = [
12
+ 'zlib'
13
+ ]
14
+
15
+ class Zlib
16
+ def initialize
17
+ @logger = HrrRbSsh::Logger.new self.class.name
18
+
19
+ @deflator = ::Zlib::Deflate.new
20
+ @inflator = ::Zlib::Inflate.new
21
+ end
22
+
23
+ def deflate data
24
+ @deflator.deflate(data, ::Zlib::SYNC_FLUSH)
25
+ end
26
+
27
+ def inflate data
28
+ @inflator.inflate(data)
29
+ end
30
+ end
31
+
32
+ @@list ||= Hash.new
33
+ name_list.each do |name|
34
+ @@list[name] = Zlib
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/transport/compression_algorithm/none'
6
+ require 'hrr_rb_ssh/transport/compression_algorithm/zlib'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ class CompressionAlgorithm
11
+ @@list ||= Hash.new
12
+
13
+ def self.[] key
14
+ @@list[key]
15
+ end
16
+
17
+ def self.name_list
18
+ @@list.keys
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ module HrrRbSsh
5
+ class Transport
6
+ module Constant
7
+ CR = 0x0d.chr
8
+ LF = 0x0a.chr
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,163 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'openssl'
5
+
6
+ require 'hrr_rb_ssh/logger'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ module DataType
11
+ def self.[] key
12
+ case key
13
+ when 'byte'
14
+ Byte
15
+ when 'boolean'
16
+ Boolean
17
+ when 'uint32'
18
+ Uint32
19
+ when 'uint64'
20
+ Uint64
21
+ when 'string'
22
+ String
23
+ when 'mpint'
24
+ Mpint
25
+ when 'name-list'
26
+ NameList
27
+ end
28
+ end
29
+
30
+ class Byte
31
+ def self.encode arg
32
+ case arg
33
+ when 0x00..0xff
34
+ [arg].pack("C")
35
+ else
36
+ raise
37
+ end
38
+ end
39
+
40
+ def self.decode io
41
+ io.read(1).unpack("C")[0]
42
+ end
43
+ end
44
+
45
+ class Boolean
46
+ def self.encode arg
47
+ case arg
48
+ when false
49
+ [0].pack("C")
50
+ when true
51
+ [1].pack("C")
52
+ else
53
+ raise
54
+ end
55
+ end
56
+
57
+ def self.decode io
58
+ if 0 == io.read(1).unpack("C")[0]
59
+ false
60
+ else
61
+ true
62
+ end
63
+ end
64
+ end
65
+
66
+ class Uint32
67
+ def self.encode arg
68
+ case arg
69
+ when 0x0000_0000..0xffff_ffff
70
+ [arg].pack("N")
71
+ else
72
+ raise
73
+ end
74
+ end
75
+
76
+ def self.decode io
77
+ io.read(4).unpack("N")[0]
78
+ end
79
+ end
80
+
81
+ class Uint64
82
+ def self.encode arg
83
+ case arg
84
+ when 0x0000_0000_0000_0000..0xffff_ffff_ffff_ffff
85
+ [arg >> 32].pack("N") + [arg & 0x0000_0000_ffff_ffff].pack("N")
86
+ else
87
+ raise
88
+ end
89
+ end
90
+
91
+ def self.decode io
92
+ (io.read(4).unpack("N")[0] << 32) + (io.read(4).unpack("N")[0])
93
+ end
94
+ end
95
+
96
+ class String
97
+ def self.encode arg
98
+ raise unless arg.kind_of? ::String
99
+ raise if arg.length > 0xffff_ffff
100
+ [arg.length, arg].pack("Na*")
101
+ end
102
+
103
+ def self.decode io
104
+ length = io.read(4).unpack("N")[0]
105
+ io.read(length).unpack("a*")[0]
106
+ end
107
+ end
108
+
109
+ class Mpint
110
+ def self.encode arg
111
+ raise unless arg.kind_of? ::Integer
112
+ raise if arg.size > 0xffff_ffff
113
+ bn = ::OpenSSL::BN.new(arg)
114
+
115
+ if bn < 0
116
+ # get 2's complement
117
+ tc = bn.to_i & ((1 << (bn.num_bytes * 8)) - 1)
118
+ # get hex representation
119
+ hex_str = "%x" % tc
120
+
121
+ if tc[(bn.num_bytes * 8) - 1] == 1
122
+ [bn.num_bytes, hex_str].pack("NH*")
123
+ else
124
+ [bn.num_bytes + 1, "ff" + hex_str].pack("NH*")
125
+ end
126
+ else
127
+ bn.to_s(0)
128
+ end
129
+ end
130
+
131
+ def self.decode io
132
+ length = io.read(4).unpack("N")[0]
133
+ hex_str = io.read(length).unpack("H*")[0]
134
+ # get temporal integer value
135
+ value = hex_str.hex
136
+
137
+ if length == 0
138
+ 0
139
+ elsif value[(length * 8) - 1] == 0
140
+ value
141
+ else
142
+ num_bytes = if hex_str.start_with?("ff") then length - 1 else length end
143
+ - (((~ value) & ((1 << (num_bytes * 8)) - 1)) + 1)
144
+ end
145
+ end
146
+ end
147
+
148
+ class NameList
149
+ def self.encode arg
150
+ raise unless arg.kind_of? Array
151
+ raise unless (arg.map(&:class) - [::String]).empty?
152
+ raise if arg.join(',').length > 0xffff_ffff
153
+ [arg.join(',').length, arg.join(',')].pack("Na*")
154
+ end
155
+
156
+ def self.decode io
157
+ length = io.read(4).unpack("N")[0]
158
+ io.read(length).unpack("a*")[0].split(',')
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end