hrr_rb_ssh 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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