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,73 @@
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
+ class EncryptionAlgorithm
11
+ name_list = [
12
+ 'aes128-cbc'
13
+ ]
14
+
15
+ class Aes128Cbc
16
+ CIPHER_NAME = "AES-128-CBC"
17
+
18
+ BLOCK_SIZE = OpenSSL::Cipher.new(CIPHER_NAME).block_size
19
+ IV_LENGTH = OpenSSL::Cipher.new(CIPHER_NAME).iv_len
20
+ KEY_LENGTH = OpenSSL::Cipher.new(CIPHER_NAME).key_len
21
+
22
+ def initialize iv, key
23
+ @logger = HrrRbSsh::Logger.new self.class.name
24
+
25
+ @encryptor = OpenSSL::Cipher.new(CIPHER_NAME)
26
+ @encryptor.encrypt
27
+ @encryptor.padding = 0
28
+ @encryptor.iv = iv
29
+ @encryptor.key = key
30
+
31
+ @decryptor = OpenSSL::Cipher.new(CIPHER_NAME)
32
+ @decryptor.decrypt
33
+ @decryptor.padding = 0
34
+ @decryptor.iv = iv
35
+ @decryptor.key = key
36
+ end
37
+
38
+ def block_size
39
+ BLOCK_SIZE
40
+ end
41
+
42
+ def iv_length
43
+ IV_LENGTH
44
+ end
45
+
46
+ def key_length
47
+ KEY_LENGTH
48
+ end
49
+
50
+ def encrypt data
51
+ if data.empty?
52
+ data
53
+ else
54
+ @encryptor.update(data) + @encryptor.final
55
+ end
56
+ end
57
+
58
+ def decrypt data
59
+ if data.empty?
60
+ data
61
+ else
62
+ @decryptor.update(data) + @decryptor.final
63
+ end
64
+ end
65
+ end
66
+
67
+ @@list ||= Hash.new
68
+ name_list.each do |name|
69
+ @@list[name] = Aes128Cbc
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
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 EncryptionAlgorithm
9
+ name_list = [
10
+ 'none'
11
+ ]
12
+
13
+ class None
14
+ BLOCK_SIZE = 0
15
+ IV_LENGTH = 0
16
+ KEY_LENGTH = 0
17
+
18
+ def initialize iv=nil, key=nil
19
+ @logger = HrrRbSsh::Logger.new self.class.name
20
+ end
21
+
22
+ def block_size
23
+ BLOCK_SIZE
24
+ end
25
+
26
+ def iv_length
27
+ IV_LENGTH
28
+ end
29
+
30
+ def key_length
31
+ KEY_LENGTH
32
+ end
33
+
34
+ def encrypt data
35
+ data
36
+ end
37
+
38
+ def decrypt data
39
+ data
40
+ end
41
+ end
42
+
43
+ @@list ||= Hash.new
44
+ name_list.each do |name|
45
+ @@list[name] = None
46
+ end
47
+ end
48
+ end
49
+ 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/encryption_algorithm/none'
6
+ require 'hrr_rb_ssh/transport/encryption_algorithm/aes_128_cbc'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ class EncryptionAlgorithm
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,129 @@
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
+ class Transport
9
+ class KexAlgorithm
10
+ class DiffieHellman
11
+ H0_DEFINITION = [
12
+ ['string', 'V_C'],
13
+ ['string', 'V_S'],
14
+ ['string', 'I_C'],
15
+ ['string', 'I_S'],
16
+ ['string', 'K_S'],
17
+ ['mpint', 'e'],
18
+ ['mpint', 'f'],
19
+ ['mpint', 'k'],
20
+ ]
21
+
22
+ def initialize
23
+ @logger = HrrRbSsh::Logger.new self.class.name
24
+
25
+ @dh = OpenSSL::PKey::DH.new
26
+ if @dh.respond_to?(:set_pqg)
27
+ @dh.set_pqg OpenSSL::BN.new(self.class::P, 16), nil, OpenSSL::BN.new(self.class::G)
28
+ else
29
+ @dh.p = OpenSSL::BN.new(self.class::P, 16)
30
+ @dh.g = OpenSSL::BN.new(self.class::G)
31
+ end
32
+ @dh.generate_key!
33
+ end
34
+
35
+ def encode definition, payload
36
+ definition.map{ |data_type, field_name|
37
+ field_value = if payload[field_name].instance_of? ::Proc then payload[field_name].call else payload[field_name] end
38
+ HrrRbSsh::Transport::DataType[data_type].encode(field_value)
39
+ }.join
40
+ end
41
+
42
+ def set_e e
43
+ @e = e
44
+ end
45
+
46
+ def shared_secret
47
+ k = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
48
+ end
49
+
50
+ def pub_key
51
+ f = @dh.pub_key.to_i
52
+ end
53
+
54
+ def hash transport
55
+ e = @e
56
+ k = shared_secret
57
+ f = pub_key
58
+
59
+ h0_payload = {
60
+ 'V_C' => transport.v_c,
61
+ 'V_S' => transport.v_s,
62
+ 'I_C' => transport.i_c,
63
+ 'I_S' => transport.i_s,
64
+ 'K_S' => transport.server_host_key_algorithm.server_public_host_key,
65
+ 'e' => e,
66
+ 'f' => f,
67
+ 'k' => k,
68
+ }
69
+ h0 = encode H0_DEFINITION, h0_payload
70
+
71
+ h = OpenSSL::Digest.digest self.class::DIGEST, h0
72
+
73
+ h
74
+ end
75
+
76
+ def sign transport
77
+ h = hash transport
78
+ s = transport.server_host_key_algorithm.sign self.class::DIGEST, h
79
+
80
+ s
81
+ end
82
+
83
+ def build_key(_k, h, _x, session_id, key_length)
84
+ k = HrrRbSsh::Transport::DataType::Mpint.encode _k
85
+ x = HrrRbSsh::Transport::DataType::Byte.encode _x
86
+
87
+ key = OpenSSL::Digest.digest(self.class::DIGEST, k + h + x + session_id)
88
+
89
+ while key.length < key_length
90
+ key = key + OpenSSL::Digest.digest(self.class::DIGEST, k + h + key )
91
+ end
92
+
93
+ key[0, key_length]
94
+ end
95
+
96
+ def iv_c_to_s transport, encryption_algorithm_c_to_s_name
97
+ key_length = HrrRbSsh::Transport::EncryptionAlgorithm[encryption_algorithm_c_to_s_name]::IV_LENGTH
98
+ build_key(shared_secret, hash(transport), 'A'.ord, transport.session_id, key_length)
99
+ end
100
+
101
+ def iv_s_to_c transport, encryption_algorithm_s_to_c_name
102
+ key_length = HrrRbSsh::Transport::EncryptionAlgorithm[encryption_algorithm_s_to_c_name]::IV_LENGTH
103
+ build_key(shared_secret, hash(transport), 'B'.ord, transport.session_id, key_length)
104
+ end
105
+
106
+ def key_c_to_s transport, encryption_algorithm_c_to_s_name
107
+ key_length = HrrRbSsh::Transport::EncryptionAlgorithm[encryption_algorithm_c_to_s_name]::KEY_LENGTH
108
+ build_key(shared_secret, hash(transport), 'C'.ord, transport.session_id, key_length)
109
+ end
110
+
111
+ def key_s_to_c transport, encryption_algorithm_s_to_c_name
112
+ key_length = HrrRbSsh::Transport::EncryptionAlgorithm[encryption_algorithm_s_to_c_name]::KEY_LENGTH
113
+ build_key(shared_secret, hash(transport), 'D'.ord, transport.session_id, key_length)
114
+ end
115
+
116
+ def mac_c_to_s transport, mac_algorithm_c_to_s_name
117
+ key_length = HrrRbSsh::Transport::MacAlgorithm[mac_algorithm_c_to_s_name]::KEY_LENGTH
118
+ build_key(shared_secret, hash(transport), 'E'.ord, transport.session_id, key_length)
119
+ end
120
+
121
+ def mac_s_to_c transport, mac_algorithm_s_to_c_name
122
+ key_length = HrrRbSsh::Transport::MacAlgorithm[mac_algorithm_s_to_c_name]::KEY_LENGTH
123
+ build_key(shared_secret, hash(transport), 'F'.ord, transport.session_id, key_length)
124
+ end
125
+
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,42 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/transport/kex_algorithm/diffie_hellman'
5
+
6
+ module HrrRbSsh
7
+ class Transport
8
+ class KexAlgorithm
9
+ name_list = [
10
+ 'diffie-hellman-group14-sha1'
11
+ ]
12
+
13
+ class DiffieHellmanGroup14Sha1 < DiffieHellman
14
+ P = \
15
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" \
16
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" \
17
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" \
18
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" \
19
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" \
20
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" \
21
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" \
22
+ "49286651" "ECE45B3D" "C2007CB8" "A163BF05" \
23
+ "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" \
24
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" \
25
+ "9ED52907" "7096966D" "670C354E" "4ABC9804" \
26
+ "F1746C08" "CA18217C" "32905E46" "2E36CE3B" \
27
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" \
28
+ "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" \
29
+ "3995497C" "EA956AE5" "15D22618" "98FA0510" \
30
+ "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
31
+ G = 2
32
+
33
+ DIGEST = 'sha1'
34
+ end
35
+
36
+ @@list ||= Hash.new
37
+ name_list.each do |name|
38
+ @@list[name] = DiffieHellmanGroup14Sha1
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/transport/kex_algorithm/diffie_hellman'
5
+
6
+ module HrrRbSsh
7
+ class Transport
8
+ class KexAlgorithm
9
+ name_list = [
10
+ 'diffie-hellman-group1-sha1'
11
+ ]
12
+
13
+ class DiffieHellmanGroup1Sha1 < DiffieHellman
14
+ P = \
15
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" \
16
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" \
17
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" \
18
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" \
19
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" \
20
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" \
21
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" \
22
+ "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
23
+ G = 2
24
+
25
+ DIGEST = 'sha1'
26
+ end
27
+
28
+ @@list ||= Hash.new
29
+ name_list.each do |name|
30
+ @@list[name] = DiffieHellmanGroup1Sha1
31
+ end
32
+ end
33
+ end
34
+ 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/kex_algorithm/diffie_hellman_group1_sha1'
6
+ require 'hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group14_sha1'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ class KexAlgorithm
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,45 @@
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 MacAlgorithm
9
+ name_list = [
10
+ 'hmac-sha1'
11
+ ]
12
+
13
+ class HmacSha1
14
+ DIGEST = 'sha1'
15
+
16
+ DIGEST_LENGTH = 20
17
+ KEY_LENGTH = 20
18
+
19
+ def initialize key
20
+ @logger = HrrRbSsh::Logger.new self.class.name
21
+
22
+ @key = key
23
+ end
24
+
25
+ def compute sequence_number, unencrypted_packet
26
+ data = HrrRbSsh::Transport::DataType::Uint32.encode(sequence_number) + unencrypted_packet
27
+ OpenSSL::HMAC.digest DIGEST, @key, data
28
+ end
29
+
30
+ def digest_length
31
+ DIGEST_LENGTH
32
+ end
33
+
34
+ def key_length
35
+ KEY_LENGTH
36
+ end
37
+ end
38
+
39
+ @@list ||= Hash.new
40
+ name_list.each do |name|
41
+ @@list[name] = HmacSha1
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
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 MacAlgorithm
9
+ name_list = [
10
+ 'none'
11
+ ]
12
+
13
+ class None
14
+ DIGEST_LENGTH = 0
15
+ KEY_LENGTH = 0
16
+
17
+ def initialize key=nil
18
+ @logger = HrrRbSsh::Logger.new self.class.name
19
+ end
20
+
21
+ def compute sequence_number, unencrypted_packet
22
+ String.new
23
+ end
24
+
25
+ def digest_length
26
+ DIGEST_LENGTH
27
+ end
28
+
29
+ def key_length
30
+ KEY_LENGTH
31
+ end
32
+ end
33
+
34
+ @@list ||= Hash.new
35
+ name_list.each do |name|
36
+ @@list[name] = None
37
+ end
38
+ end
39
+ end
40
+ 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/mac_algorithm/none'
6
+ require 'hrr_rb_ssh/transport/mac_algorithm/hmac_sha1'
7
+
8
+ module HrrRbSsh
9
+ class Transport
10
+ class MacAlgorithm
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 Mode
7
+ SERVER = :server
8
+ CLIENT = :client
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+ # vim: et ts=2 sw=2
3
+
4
+ require 'hrr_rb_ssh/logger'
5
+ #require 'hrr_rb_ssh/transport/packet'
6
+
7
+ module HrrRbSsh
8
+ class Transport
9
+ class Receiver
10
+ def initialize
11
+ @logger = HrrRbSsh::Logger.new self.class.name
12
+ end
13
+
14
+ def depacketize transport, packet
15
+ packet_length_field_length = 4
16
+ padding_length_field_length = 1
17
+
18
+ packet_length = packet[0,4].unpack("N")[0]
19
+ padding_length = packet[4,1].unpack("C")[0]
20
+ deflated_payload_length = packet_length - padding_length_field_length - padding_length
21
+ deflated_payload = packet[packet_length_field_length + padding_length_field_length, deflated_payload_length]
22
+ payload = transport.incoming_compression_algorithm.inflate deflated_payload
23
+
24
+ payload
25
+ end
26
+
27
+ def receive_packet transport
28
+ packet_length_field_length = 4
29
+ minimum_block_size = 8
30
+
31
+ block_size = [transport.incoming_encryption_algorithm.block_size, minimum_block_size].max
32
+ initial_encrypted_packet = transport.io.read block_size
33
+ if (initial_encrypted_packet == nil) || (initial_encrypted_packet.length != block_size)
34
+ @logger.warn("IO is EOF")
35
+ raise EOFError
36
+ end
37
+ initial_unencrypted_packet = transport.incoming_encryption_algorithm.decrypt initial_encrypted_packet
38
+ packet_length = initial_unencrypted_packet[0,4].unpack("N")[0]
39
+ last_packet_length = packet_length_field_length + packet_length - block_size
40
+ last_encrypted_packet = transport.io.read last_packet_length
41
+ if (last_encrypted_packet == nil) || (last_encrypted_packet.length != last_packet_length)
42
+ @logger.warn("IO is EOF")
43
+ raise EOFError
44
+ end
45
+ last_unencrypted_packet = transport.incoming_encryption_algorithm.decrypt last_encrypted_packet
46
+ encrypted_packet = initial_encrypted_packet + last_encrypted_packet
47
+ unencrypted_packet = initial_unencrypted_packet + last_unencrypted_packet
48
+
49
+ unencrypted_packet
50
+ end
51
+
52
+ def receive_mac transport
53
+ mac_length = transport.incoming_mac_algorithm.digest_length
54
+ mac = transport.io.read mac_length
55
+ if (mac == nil) || (mac.length != mac_length)
56
+ @logger.warn("IO is EOF")
57
+ raise EOFError
58
+ end
59
+ mac
60
+ end
61
+
62
+ def receive transport
63
+ unencrypted_packet = receive_packet transport
64
+ payload = depacketize transport, unencrypted_packet
65
+ mac = receive_mac transport
66
+
67
+ raise if mac != transport.incoming_mac_algorithm.compute( transport.incoming_sequence_number.sequence_number, unencrypted_packet )
68
+
69
+ transport.incoming_sequence_number.increment
70
+
71
+ payload
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,57 @@
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 Sender
9
+ def initialize
10
+ @logger = HrrRbSsh::Logger.new self.class.name
11
+ end
12
+
13
+ def packetize transport, payload
14
+ packet_length_field_length = 4
15
+ padding_length_field_length = 1
16
+ minimum_padding_length = 4
17
+ minimum_block_size = 8
18
+
19
+ block_size = [transport.outgoing_encryption_algorithm.block_size, minimum_block_size].max
20
+ deflated_payload = transport.outgoing_compression_algorithm.deflate payload
21
+ tmp_total_length = packet_length_field_length + padding_length_field_length + deflated_payload.length + minimum_padding_length
22
+ total_length = tmp_total_length + (block_size - (tmp_total_length % block_size))
23
+ packet_length = total_length - packet_length_field_length
24
+ padding_length = packet_length - padding_length_field_length - deflated_payload.length
25
+ padding = OpenSSL::Random.random_bytes( padding_length )
26
+ packet = [packet_length, padding_length].pack("NC") + deflated_payload + padding
27
+
28
+ packet
29
+ end
30
+
31
+ def encrypt transport, packet
32
+ encrypted_packet = transport.outgoing_encryption_algorithm.encrypt packet
33
+
34
+ encrypted_packet
35
+ end
36
+
37
+ def send_packet transport, packet
38
+ encrypted_packet = encrypt transport, packet
39
+ transport.io.write encrypted_packet
40
+ end
41
+
42
+ def send_mac transport, packet
43
+ mac = transport.outgoing_mac_algorithm.compute transport.outgoing_sequence_number.sequence_number, packet
44
+ transport.io.write mac
45
+ end
46
+
47
+ def send transport, payload
48
+ packet = packetize transport, payload
49
+
50
+ send_packet transport, packet
51
+ send_mac transport, packet
52
+
53
+ transport.outgoing_sequence_number.increment
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,22 @@
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 SequenceNumber
9
+ attr_reader :sequence_number
10
+
11
+ def initialize
12
+ @sequence_number = 0
13
+
14
+ @logger = HrrRbSsh::Logger.new self.class.name
15
+ end
16
+
17
+ def increment
18
+ @sequence_number = (@sequence_number + 1) % 0x1_0000_0000
19
+ end
20
+ end
21
+ end
22
+ end