hrr_rb_ssh 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/f5dfdb97d72f24ca5939/test_coverage)](https://codeclimate.com/github/hirura/hrr_rb_ssh/test_coverage)
|
6
6
|
[![Gem Version](https://badge.fury.io/rb/hrr_rb_ssh.svg)](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
|