hrr_rb_ssh 0.1.1 → 0.1.2
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 +1 -1
- data/demo/server.rb +23 -3
- data/hrr_rb_ssh.gemspec +2 -2
- data/lib/hrr_rb_ssh/authentication/method/method.rb +34 -0
- data/lib/hrr_rb_ssh/authentication/method/none.rb +5 -14
- data/lib/hrr_rb_ssh/authentication/method/password.rb +6 -12
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/algorithm.rb +41 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/codable.rb +33 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_dss.rb +105 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_rsa.rb +85 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm.rb +28 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey.rb +9 -25
- data/lib/hrr_rb_ssh/authentication/method.rb +12 -9
- data/lib/hrr_rb_ssh/connection/channel/channel_type/channel_type.rb +30 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb +46 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb +44 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb +54 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/request_type.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb +41 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb +44 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb +34 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type.rb +33 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +30 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type.rb +25 -0
- data/lib/hrr_rb_ssh/connection/channel.rb +2 -12
- data/lib/hrr_rb_ssh/transport/compression_algorithm/compression_algorithm.rb +34 -0
- data/lib/hrr_rb_ssh/transport/compression_algorithm/functionable.rb +31 -0
- data/lib/hrr_rb_ssh/transport/compression_algorithm/none.rb +7 -19
- data/lib/hrr_rb_ssh/transport/compression_algorithm/unfunctionable.rb +20 -0
- data/lib/hrr_rb_ssh/transport/compression_algorithm/zlib.rb +7 -24
- data/lib/hrr_rb_ssh/transport/compression_algorithm.rb +11 -9
- data/lib/hrr_rb_ssh/transport/direction.rb +11 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes128_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes128_ctr.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes192_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes192_ctr.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes256_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes256_ctr.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/arcfour.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/blowfish_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/cast128_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/encryption_algorithm.rb +34 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/functionable.rb +61 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/none.rb +6 -33
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/three_des_cbc.rb +19 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/unfunctionable.rb +35 -0
- data/lib/hrr_rb_ssh/transport/encryption_algorithm.rb +20 -9
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +3 -4
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group14_sha1.rb +4 -8
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group1_sha1.rb +4 -8
- data/lib/hrr_rb_ssh/transport/kex_algorithm/kex_algorithm.rb +34 -0
- data/lib/hrr_rb_ssh/transport/kex_algorithm.rb +10 -9
- data/lib/hrr_rb_ssh/transport/mac_algorithm/functionable.rb +32 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm/hmac_md5.rb +21 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm/hmac_md5_96.rb +21 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm/hmac_sha1.rb +5 -29
- data/lib/hrr_rb_ssh/transport/mac_algorithm/hmac_sha1_96.rb +21 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm/mac_algorithm.rb +34 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm/none.rb +6 -22
- data/lib/hrr_rb_ssh/transport/mac_algorithm/unfunctionable.rb +24 -0
- data/lib/hrr_rb_ssh/transport/mac_algorithm.rb +14 -9
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/server_host_key_algorithm.rb +34 -0
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_dss.rb +106 -0
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_rsa.rb +4 -11
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +10 -8
- data/lib/hrr_rb_ssh/transport.rb +23 -15
- data/lib/hrr_rb_ssh/version.rb +1 -1
- metadata +51 -17
- data/lib/hrr_rb_ssh/authentication/method/publickey/ssh_rsa.rb +0 -116
- data/lib/hrr_rb_ssh/connection/channel/session/env/context.rb +0 -43
- data/lib/hrr_rb_ssh/connection/channel/session/env.rb +0 -31
- data/lib/hrr_rb_ssh/connection/channel/session/exec/context.rb +0 -41
- data/lib/hrr_rb_ssh/connection/channel/session/exec.rb +0 -31
- data/lib/hrr_rb_ssh/connection/channel/session/pty_req/context.rb +0 -50
- data/lib/hrr_rb_ssh/connection/channel/session/pty_req.rb +0 -31
- data/lib/hrr_rb_ssh/connection/channel/session/shell/context.rb +0 -37
- data/lib/hrr_rb_ssh/connection/channel/session/shell.rb +0 -31
- data/lib/hrr_rb_ssh/connection/channel/session/subsystem/context.rb +0 -40
- data/lib/hrr_rb_ssh/connection/channel/session/subsystem.rb +0 -31
- data/lib/hrr_rb_ssh/connection/channel/session.rb +0 -31
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/aes_128_cbc.rb +0 -73
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a15e10f1895dfd1a8e0159fc18355de0128cc033bbe5f5ee49e483e2de7bc1e3
|
|
4
|
+
data.tar.gz: 6e1cb80d55521f431dff77735cb843c37fdc440640ffd9ae958119fdd9eb96d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b63d6c8658d97b862f81e9beed336d04768894fffe1339c86cd2f8f9c22310f5f1d1be1f7abc381a0a0a5bbb18fd9a343959355aa77d849c321041de954d3749
|
|
7
|
+
data.tar.gz: db9de741c096e3024231760c25e3d0ed04fee0a7d3083f1ad71b1deecbe389c401576f37c31714052408bca4c6431861e40f7ccafc04be8b4277c096147ef32f
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://codeclimate.com/github/hirura/hrr_rb_ssh/test_coverage)
|
|
6
6
|
[](https://badge.fury.io/rb/hrr_rb_ssh)
|
|
7
7
|
|
|
8
|
-
hrr_rb_ssh is a pure Ruby
|
|
8
|
+
hrr_rb_ssh is a pure Ruby SSH 2.0 server implementation.
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
data/demo/server.rb
CHANGED
|
@@ -23,8 +23,23 @@ auth_none = HrrRbSsh::Authentication::Authenticator.new { |context|
|
|
|
23
23
|
}
|
|
24
24
|
auth_publickey = HrrRbSsh::Authentication::Authenticator.new { |context|
|
|
25
25
|
username = 'user1'
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
dss_public_key_algorithm_name = 'ssh-dss'
|
|
27
|
+
dss_public_key = <<-'EOB'
|
|
28
|
+
-----BEGIN PUBLIC KEY-----
|
|
29
|
+
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAKh2ZJp4ao8Xaexa0sk68VqMCaOaTi19
|
|
30
|
+
YIqo2+t2t8ve4QSHvk/NbFIDTGq90lHziakTqwKaaswWLB7cSRPTcXjLv16Zmazg
|
|
31
|
+
JRvh1jZ3ikuBME2G/B+EptlQ00dMa+5W/Acp2P6Cv5NRgA/tx0AyCJaItSpLXG+k
|
|
32
|
+
B+HMp9LQ8WotAhUAk/yyvpsY9sVSyeN3lHvg5Nsl568CgYEAj4rqF241ROP2olNh
|
|
33
|
+
VJUF0K5N4dSBCfcPnSPYuGPCi7qV229RISET3LOwrCXEUwSwlKoe/lLb2mcaeC84
|
|
34
|
+
NIeN6pQnRTE6zajJ9UUeGErOFRm1x6E+FMtlVp/fwUE1Ra+AscHVKwMUehz7sA6A
|
|
35
|
+
ZxJK7UvLs+R6s1eYhrES0bcorLIDgYQAAoGAd6XKzevlwzt6aCYdBRdN+BT4BQUw
|
|
36
|
+
/L3MVYG0kDV9WqPcyAFvLO54xAUf9LxYM0e8X8J5ECp4oEGOcK1ilXEw3LPMJGmY
|
|
37
|
+
IB56R9izS1t636kxnJTYNGQY+XvjAeuP7nC2WVNHNz7vXprT4Sq+hQaNkaKPu/3/
|
|
38
|
+
48xJs2mYbxfyHCQ=
|
|
39
|
+
-----END PUBLIC KEY-----
|
|
40
|
+
EOB
|
|
41
|
+
rsa_public_key_algorithm_name = 'ssh-rsa'
|
|
42
|
+
rsa_public_key = <<-'EOB'
|
|
28
43
|
-----BEGIN PUBLIC KEY-----
|
|
29
44
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3OnIQcRTdeTZFjhGcx8f
|
|
30
45
|
ssCgeqzY47p5KhT/gKMz2nOANNLCBr9e6IGaRePew03St3Cn0ApikuGzPnWxSlBT
|
|
@@ -35,7 +50,12 @@ wqbQt4paM0aEuypWE+CaizA0I+El7f0y+59sUqTAN/7F9UlXaOBdd9SZkhACBrAR
|
|
|
35
50
|
nQIDAQAB
|
|
36
51
|
-----END PUBLIC KEY-----
|
|
37
52
|
EOB
|
|
38
|
-
|
|
53
|
+
[
|
|
54
|
+
[dss_public_key_algorithm_name, dss_public_key],
|
|
55
|
+
[rsa_public_key_algorithm_name, rsa_public_key],
|
|
56
|
+
].any? { |public_key_algorithm_name, public_key|
|
|
57
|
+
context.verify username, public_key_algorithm_name, public_key
|
|
58
|
+
}
|
|
39
59
|
}
|
|
40
60
|
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
|
|
41
61
|
user_and_pass = [
|
data/hrr_rb_ssh.gemspec
CHANGED
|
@@ -7,8 +7,8 @@ Gem::Specification.new do |spec|
|
|
|
7
7
|
spec.name = "hrr_rb_ssh"
|
|
8
8
|
spec.version = HrrRbSsh::VERSION
|
|
9
9
|
spec.license = 'Apache-2.0'
|
|
10
|
-
spec.summary = %q{Pure Ruby
|
|
11
|
-
spec.description = %q{Pure Ruby
|
|
10
|
+
spec.summary = %q{Pure Ruby SSH 2.0 server implementation}
|
|
11
|
+
spec.description = %q{Pure Ruby SSH 2.0 server implementation}
|
|
12
12
|
spec.authors = ["hirura"]
|
|
13
13
|
spec.email = ["hirura@gmail.com"]
|
|
14
14
|
spec.homepage = "https://github.com/hirura/hrr_rb_ssh"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
require 'hrr_rb_ssh/logger'
|
|
5
|
+
|
|
6
|
+
module HrrRbSsh
|
|
7
|
+
class Authentication
|
|
8
|
+
module Method
|
|
9
|
+
class Method
|
|
10
|
+
@@list = Array.new
|
|
11
|
+
|
|
12
|
+
def self.inherited klass
|
|
13
|
+
@@list.push klass
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.list
|
|
17
|
+
@@list
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.name_list
|
|
21
|
+
@@list.map{ |klass| klass::NAME }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.[] key
|
|
25
|
+
@@list.find{ |klass| key == klass::NAME }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize options
|
|
29
|
+
@logger = HrrRbSsh::Logger.new self.class.name
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
# vim: et ts=2 sw=2
|
|
3
3
|
|
|
4
|
-
require 'hrr_rb_ssh/
|
|
5
|
-
require 'hrr_rb_ssh/authentication/method/none/context'
|
|
4
|
+
require 'hrr_rb_ssh/authentication/method/method'
|
|
6
5
|
|
|
7
6
|
module HrrRbSsh
|
|
8
7
|
class Authentication
|
|
9
8
|
module Method
|
|
10
|
-
|
|
11
|
-
'none'
|
|
12
|
-
]
|
|
9
|
+
class None < Method
|
|
10
|
+
NAME = 'none'
|
|
13
11
|
|
|
14
|
-
class None
|
|
15
12
|
def initialize options
|
|
16
|
-
|
|
13
|
+
super
|
|
17
14
|
|
|
18
15
|
@authenticator = options.fetch( 'authentication_none_authenticator', Authenticator.new { false } )
|
|
19
16
|
end
|
|
@@ -25,14 +22,8 @@ module HrrRbSsh
|
|
|
25
22
|
@authenticator.authenticate context
|
|
26
23
|
end
|
|
27
24
|
end
|
|
28
|
-
|
|
29
|
-
@@list ||= Hash.new
|
|
30
|
-
name_list.each do |name|
|
|
31
|
-
@@list[name] = None
|
|
32
|
-
end
|
|
33
25
|
end
|
|
34
26
|
end
|
|
35
27
|
end
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
require 'hrr_rb_ssh/authentication/method/none/context'
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
# vim: et ts=2 sw=2
|
|
3
3
|
|
|
4
|
-
require 'hrr_rb_ssh/
|
|
5
|
-
require 'hrr_rb_ssh/authentication/method/password/context'
|
|
4
|
+
require 'hrr_rb_ssh/authentication/method/method'
|
|
6
5
|
|
|
7
6
|
module HrrRbSsh
|
|
8
7
|
class Authentication
|
|
9
8
|
module Method
|
|
10
|
-
|
|
11
|
-
'password'
|
|
12
|
-
]
|
|
9
|
+
class Password < Method
|
|
10
|
+
NAME = 'password'
|
|
13
11
|
|
|
14
|
-
class Password
|
|
15
12
|
def initialize options
|
|
16
|
-
|
|
13
|
+
super
|
|
17
14
|
|
|
18
15
|
@authenticator = options.fetch( 'authentication_password_authenticator', Authenticator.new { false } )
|
|
19
16
|
end
|
|
@@ -27,11 +24,8 @@ module HrrRbSsh
|
|
|
27
24
|
@authenticator.authenticate context
|
|
28
25
|
end
|
|
29
26
|
end
|
|
30
|
-
|
|
31
|
-
@@list ||= Hash.new
|
|
32
|
-
name_list.each do |name|
|
|
33
|
-
@@list[name] = Password
|
|
34
|
-
end
|
|
35
27
|
end
|
|
36
28
|
end
|
|
37
29
|
end
|
|
30
|
+
|
|
31
|
+
require 'hrr_rb_ssh/authentication/method/password/context'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
require 'hrr_rb_ssh/logger'
|
|
5
|
+
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/codable'
|
|
6
|
+
|
|
7
|
+
module HrrRbSsh
|
|
8
|
+
class Authentication
|
|
9
|
+
module Method
|
|
10
|
+
class Publickey
|
|
11
|
+
module Algorithm
|
|
12
|
+
class Algorithm
|
|
13
|
+
@@list = Array.new
|
|
14
|
+
|
|
15
|
+
def self.inherited klass
|
|
16
|
+
@@list.push klass
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.list
|
|
20
|
+
@@list
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.name_list
|
|
24
|
+
@@list.map{ |klass| klass::NAME }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.[] key
|
|
28
|
+
@@list.find{ |klass| key == klass::NAME }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize
|
|
32
|
+
@logger = HrrRbSsh::Logger.new self.class.name
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
include Codable
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
require 'hrr_rb_ssh/transport/data_type'
|
|
5
|
+
|
|
6
|
+
module HrrRbSsh
|
|
7
|
+
class Authentication
|
|
8
|
+
module Method
|
|
9
|
+
class Publickey
|
|
10
|
+
module Algorithm
|
|
11
|
+
module Codable
|
|
12
|
+
def encode definition, payload
|
|
13
|
+
definition.map{ |data_type, field_name|
|
|
14
|
+
field_value = if payload[field_name].instance_of? ::Proc then payload[field_name].call else payload[field_name] end
|
|
15
|
+
HrrRbSsh::Transport::DataType[data_type].encode(field_value)
|
|
16
|
+
}.join
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def decode definition, payload
|
|
20
|
+
payload_io = StringIO.new payload, 'r'
|
|
21
|
+
definition.map{ |data_type, field_name|
|
|
22
|
+
[
|
|
23
|
+
field_name,
|
|
24
|
+
HrrRbSsh::Transport::DataType[data_type].decode(payload_io)
|
|
25
|
+
]
|
|
26
|
+
}.to_h
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
module HrrRbSsh
|
|
5
|
+
class Authentication
|
|
6
|
+
module Method
|
|
7
|
+
class Publickey
|
|
8
|
+
module Algorithm
|
|
9
|
+
class SshDss < Algorithm
|
|
10
|
+
NAME = 'ssh-dss'
|
|
11
|
+
DIGEST = 'sha1'
|
|
12
|
+
|
|
13
|
+
PUBLIC_KEY_BLOB_DEFINITION = [
|
|
14
|
+
['string', 'public key algorithm name'],
|
|
15
|
+
['mpint', 'p'],
|
|
16
|
+
['mpint', 'q'],
|
|
17
|
+
['mpint', 'g'],
|
|
18
|
+
['mpint', 'y'],
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
SIGNATURE_DEFINITION = [
|
|
22
|
+
['string', 'public key algorithm name'],
|
|
23
|
+
['string', 'signature blob'],
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
SIGNATURE_BLOB_DEFINITION = [
|
|
27
|
+
['string', 'session identifier'],
|
|
28
|
+
['byte', 'message number'],
|
|
29
|
+
['string', 'user name'],
|
|
30
|
+
['string', 'service name'],
|
|
31
|
+
['string', 'method name'],
|
|
32
|
+
['boolean', 'with signature'],
|
|
33
|
+
['string', 'public key algorithm name'],
|
|
34
|
+
['string', 'public key blob'],
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
def verify_public_key public_key_algorithm_name, public_key, public_key_blob
|
|
38
|
+
public_key = case public_key
|
|
39
|
+
when String
|
|
40
|
+
OpenSSL::PKey::DSA.new(public_key)
|
|
41
|
+
when OpenSSL::PKey::DSA
|
|
42
|
+
public_key
|
|
43
|
+
else
|
|
44
|
+
return false
|
|
45
|
+
end
|
|
46
|
+
public_key_message = {
|
|
47
|
+
'public key algorithm name' => public_key_algorithm_name,
|
|
48
|
+
'p' => public_key.p.to_i,
|
|
49
|
+
'g' => public_key.g.to_i,
|
|
50
|
+
'q' => public_key.q.to_i,
|
|
51
|
+
'y' => public_key.pub_key.to_i,
|
|
52
|
+
}
|
|
53
|
+
public_key_blob == encode(PUBLIC_KEY_BLOB_DEFINITION, public_key_message)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def verify_signature session_id, message
|
|
57
|
+
signature_message = decode SIGNATURE_DEFINITION, message['signature']
|
|
58
|
+
signature_algorithm = signature_message['public key algorithm name']
|
|
59
|
+
signature_blob = signature_message['signature blob']
|
|
60
|
+
|
|
61
|
+
public_key = decode PUBLIC_KEY_BLOB_DEFINITION, message['public key blob']
|
|
62
|
+
algorithm = OpenSSL::PKey::DSA.new
|
|
63
|
+
if algorithm.respond_to?(:set_pqg)
|
|
64
|
+
algorithm.set_pqg public_key['p'], public_key['q'], public_key['g']
|
|
65
|
+
else
|
|
66
|
+
algorithm.p = public_key['p']
|
|
67
|
+
algorithm.q = public_key['q']
|
|
68
|
+
algorithm.g = public_key['g']
|
|
69
|
+
end
|
|
70
|
+
if algorithm.respond_to?(:set_key)
|
|
71
|
+
algorithm.set_key public_key['y'], nil
|
|
72
|
+
else
|
|
73
|
+
algorithm.pub_key = public_key['y']
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
data_message = {
|
|
77
|
+
'session identifier' => session_id,
|
|
78
|
+
'message number' => message['message number'],
|
|
79
|
+
'user name' => message['user name'],
|
|
80
|
+
'service name' => message['service name'],
|
|
81
|
+
'method name' => message['method name'],
|
|
82
|
+
'with signature' => message['with signature'],
|
|
83
|
+
'public key algorithm name' => message['public key algorithm name'],
|
|
84
|
+
'public key blob' => message['public key blob'],
|
|
85
|
+
}
|
|
86
|
+
data_blob = encode SIGNATURE_BLOB_DEFINITION, data_message
|
|
87
|
+
|
|
88
|
+
hash = OpenSSL::Digest.digest(DIGEST, data_blob)
|
|
89
|
+
sign_r = signature_blob[ 0, 20]
|
|
90
|
+
sign_s = signature_blob[20, 20]
|
|
91
|
+
sign_asn1 = OpenSSL::ASN1::Sequence.new(
|
|
92
|
+
[
|
|
93
|
+
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(sign_r, 2)),
|
|
94
|
+
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(sign_s, 2)),
|
|
95
|
+
]
|
|
96
|
+
)
|
|
97
|
+
sign_der = sign_asn1.to_der
|
|
98
|
+
(signature_algorithm == message['public key algorithm name']) && algorithm.sysverify(hash, sign_der)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
module HrrRbSsh
|
|
5
|
+
class Authentication
|
|
6
|
+
module Method
|
|
7
|
+
class Publickey
|
|
8
|
+
module Algorithm
|
|
9
|
+
class SshRsa < Algorithm
|
|
10
|
+
NAME = 'ssh-rsa'
|
|
11
|
+
DIGEST = 'sha1'
|
|
12
|
+
|
|
13
|
+
PUBLIC_KEY_BLOB_DEFINITION = [
|
|
14
|
+
['string', 'public key algorithm name'],
|
|
15
|
+
['mpint', 'e'],
|
|
16
|
+
['mpint', 'n'],
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
SIGNATURE_DEFINITION = [
|
|
20
|
+
['string', 'public key algorithm name'],
|
|
21
|
+
['string', 'signature blob'],
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
SIGNATURE_BLOB_DEFINITION = [
|
|
25
|
+
['string', 'session identifier'],
|
|
26
|
+
['byte', 'message number'],
|
|
27
|
+
['string', 'user name'],
|
|
28
|
+
['string', 'service name'],
|
|
29
|
+
['string', 'method name'],
|
|
30
|
+
['boolean', 'with signature'],
|
|
31
|
+
['string', 'public key algorithm name'],
|
|
32
|
+
['string', 'public key blob'],
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
def verify_public_key public_key_algorithm_name, public_key, public_key_blob
|
|
36
|
+
public_key = case public_key
|
|
37
|
+
when String
|
|
38
|
+
OpenSSL::PKey::RSA.new(public_key)
|
|
39
|
+
when OpenSSL::PKey::RSA
|
|
40
|
+
public_key
|
|
41
|
+
else
|
|
42
|
+
return false
|
|
43
|
+
end
|
|
44
|
+
public_key_message = {
|
|
45
|
+
'public key algorithm name' => public_key_algorithm_name,
|
|
46
|
+
'e' => public_key.e.to_i,
|
|
47
|
+
'n' => public_key.n.to_i,
|
|
48
|
+
}
|
|
49
|
+
public_key_blob == encode(PUBLIC_KEY_BLOB_DEFINITION, public_key_message)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def verify_signature session_id, message
|
|
53
|
+
signature_message = decode SIGNATURE_DEFINITION, message['signature']
|
|
54
|
+
signature_algorithm = signature_message['public key algorithm name']
|
|
55
|
+
signature_blob = signature_message['signature blob']
|
|
56
|
+
|
|
57
|
+
public_key = decode PUBLIC_KEY_BLOB_DEFINITION, message['public key blob']
|
|
58
|
+
algorithm = OpenSSL::PKey::RSA.new
|
|
59
|
+
if algorithm.respond_to?(:set_key)
|
|
60
|
+
algorithm.set_key public_key['n'], public_key['e'], nil
|
|
61
|
+
else
|
|
62
|
+
algorithm.e = public_key['e']
|
|
63
|
+
algorithm.n = public_key['n']
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
data_message = {
|
|
67
|
+
'session identifier' => session_id,
|
|
68
|
+
'message number' => message['message number'],
|
|
69
|
+
'user name' => message['user name'],
|
|
70
|
+
'service name' => message['service name'],
|
|
71
|
+
'method name' => message['method name'],
|
|
72
|
+
'with signature' => message['with signature'],
|
|
73
|
+
'public key algorithm name' => message['public key algorithm name'],
|
|
74
|
+
'public key blob' => message['public key blob'],
|
|
75
|
+
}
|
|
76
|
+
data_blob = encode SIGNATURE_BLOB_DEFINITION, data_message
|
|
77
|
+
|
|
78
|
+
(signature_algorithm == message['public key algorithm name']) && algorithm.verify(DIGEST, signature_blob, data_blob)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
module HrrRbSsh
|
|
5
|
+
class Authentication
|
|
6
|
+
module Method
|
|
7
|
+
class Publickey
|
|
8
|
+
module Algorithm
|
|
9
|
+
def self.list
|
|
10
|
+
Algorithm.list
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.name_list
|
|
14
|
+
Algorithm.name_list
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.[] key
|
|
18
|
+
Algorithm[key]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/algorithm'
|
|
27
|
+
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_dss'
|
|
28
|
+
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_rsa'
|
|
@@ -1,30 +1,16 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
# vim: et ts=2 sw=2
|
|
3
3
|
|
|
4
|
-
require 'hrr_rb_ssh/
|
|
5
|
-
require 'hrr_rb_ssh/authentication/method/publickey/context'
|
|
6
|
-
require 'hrr_rb_ssh/authentication/method/publickey/ssh_rsa'
|
|
4
|
+
require 'hrr_rb_ssh/authentication/method/method'
|
|
7
5
|
|
|
8
6
|
module HrrRbSsh
|
|
9
7
|
class Authentication
|
|
10
8
|
module Method
|
|
11
|
-
|
|
12
|
-
'publickey'
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
class Publickey
|
|
16
|
-
@@algorithm_list ||= Hash.new
|
|
17
|
-
|
|
18
|
-
def self.[] key
|
|
19
|
-
@@algorithm_list[key]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def self.algorithm_name_list
|
|
23
|
-
@@algorithm_list.keys
|
|
24
|
-
end
|
|
9
|
+
class Publickey < Method
|
|
10
|
+
NAME = 'publickey'
|
|
25
11
|
|
|
26
12
|
def initialize options
|
|
27
|
-
|
|
13
|
+
super
|
|
28
14
|
|
|
29
15
|
@session_id = options['session id']
|
|
30
16
|
@authenticator = options.fetch( 'authentication_publickey_authenticator', Authenticator.new { false } )
|
|
@@ -32,7 +18,7 @@ module HrrRbSsh
|
|
|
32
18
|
|
|
33
19
|
def authenticate userauth_request_message
|
|
34
20
|
public_key_algorithm_name = userauth_request_message['public key algorithm name']
|
|
35
|
-
unless
|
|
21
|
+
unless Algorithm.name_list.include?(public_key_algorithm_name)
|
|
36
22
|
@logger.info("unsupported public key algorithm: #{public_key_algorithm_name}")
|
|
37
23
|
return false
|
|
38
24
|
end
|
|
@@ -43,7 +29,7 @@ module HrrRbSsh
|
|
|
43
29
|
else
|
|
44
30
|
@logger.info("verify signature")
|
|
45
31
|
username = userauth_request_message['user name']
|
|
46
|
-
algorithm =
|
|
32
|
+
algorithm = Algorithm[public_key_algorithm_name].new
|
|
47
33
|
context = Context.new(username, algorithm, @session_id, userauth_request_message)
|
|
48
34
|
@authenticator.authenticate context
|
|
49
35
|
end
|
|
@@ -58,11 +44,9 @@ module HrrRbSsh
|
|
|
58
44
|
payload = HrrRbSsh::Message::SSH_MSG_USERAUTH_PK_OK.encode message
|
|
59
45
|
end
|
|
60
46
|
end
|
|
61
|
-
|
|
62
|
-
@@list ||= Hash.new
|
|
63
|
-
name_list.each do |name|
|
|
64
|
-
@@list[name] = Publickey
|
|
65
|
-
end
|
|
66
47
|
end
|
|
67
48
|
end
|
|
68
49
|
end
|
|
50
|
+
|
|
51
|
+
require 'hrr_rb_ssh/authentication/method/publickey/context'
|
|
52
|
+
require 'hrr_rb_ssh/authentication/method/publickey/algorithm'
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
# vim: et ts=2 sw=2
|
|
3
3
|
|
|
4
|
-
require 'hrr_rb_ssh/authentication/method/none'
|
|
5
|
-
require 'hrr_rb_ssh/authentication/method/password'
|
|
6
|
-
require 'hrr_rb_ssh/authentication/method/publickey'
|
|
7
|
-
|
|
8
4
|
module HrrRbSsh
|
|
9
5
|
class Authentication
|
|
10
6
|
module Method
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def self.[] key
|
|
14
|
-
@@list[key]
|
|
7
|
+
def self.list
|
|
8
|
+
Method.list
|
|
15
9
|
end
|
|
16
10
|
|
|
17
11
|
def self.name_list
|
|
18
|
-
|
|
12
|
+
Method.name_list
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.[] key
|
|
16
|
+
Method[key]
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
end
|
|
22
20
|
end
|
|
21
|
+
|
|
22
|
+
require 'hrr_rb_ssh/authentication/method/method'
|
|
23
|
+
require 'hrr_rb_ssh/authentication/method/none'
|
|
24
|
+
require 'hrr_rb_ssh/authentication/method/password'
|
|
25
|
+
require 'hrr_rb_ssh/authentication/method/publickey'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
module HrrRbSsh
|
|
5
|
+
class Connection
|
|
6
|
+
class Channel
|
|
7
|
+
module ChannelType
|
|
8
|
+
class ChannelType
|
|
9
|
+
@@list = Array.new
|
|
10
|
+
|
|
11
|
+
def self.inherited klass
|
|
12
|
+
@@list.push klass
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.list
|
|
16
|
+
@@list
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.name_list
|
|
20
|
+
@@list.map{ |klass| klass::NAME }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.[] key
|
|
24
|
+
@@list.find{ |klass| key == klass::NAME }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# vim: et ts=2 sw=2
|
|
3
|
+
|
|
4
|
+
require 'hrr_rb_ssh/logger'
|
|
5
|
+
|
|
6
|
+
module HrrRbSsh
|
|
7
|
+
class Connection
|
|
8
|
+
class Channel
|
|
9
|
+
module ChannelType
|
|
10
|
+
class Session
|
|
11
|
+
module RequestType
|
|
12
|
+
class Env
|
|
13
|
+
class Context
|
|
14
|
+
attr_reader \
|
|
15
|
+
:logger,
|
|
16
|
+
:username,
|
|
17
|
+
:io,
|
|
18
|
+
:variables,
|
|
19
|
+
:vars,
|
|
20
|
+
:variable_name,
|
|
21
|
+
:variable_value
|
|
22
|
+
|
|
23
|
+
def initialize proc_chain, username, io, variables, message
|
|
24
|
+
@logger = HrrRbSsh::Logger.new self.class.name
|
|
25
|
+
|
|
26
|
+
@proc_chain = proc_chain
|
|
27
|
+
@username = username
|
|
28
|
+
@io = io
|
|
29
|
+
@variables = variables
|
|
30
|
+
@vars = variables
|
|
31
|
+
|
|
32
|
+
@variable_name = message['variable name']
|
|
33
|
+
@variable_value = message['variable value']
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def chain_proc &block
|
|
37
|
+
@proc = block || @proc
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|