hrr_rb_ssh 0.3.0.pre1 → 0.4.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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -3
  3. data/.travis.yml +1 -0
  4. data/README.md +208 -46
  5. data/demo/client.rb +71 -0
  6. data/demo/echo_server.rb +8 -3
  7. data/demo/more_flexible_auth.rb +105 -0
  8. data/demo/multi_step_auth.rb +99 -0
  9. data/demo/server.rb +10 -4
  10. data/demo/subsystem_echo_server.rb +8 -3
  11. data/hrr_rb_ssh.gemspec +6 -6
  12. data/lib/hrr_rb_ssh.rb +1 -1
  13. data/lib/hrr_rb_ssh/algorithm/publickey.rb +0 -1
  14. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2.rb +12 -9
  15. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/ecdsa_signature_blob.rb +2 -4
  16. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/public_key_blob.rb +2 -4
  17. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/signature.rb +2 -4
  18. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss.rb +10 -7
  19. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/public_key_blob.rb +2 -4
  20. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/signature.rb +2 -4
  21. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa.rb +9 -6
  22. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/public_key_blob.rb +2 -4
  23. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/signature.rb +2 -4
  24. data/lib/hrr_rb_ssh/authentication.rb +103 -22
  25. data/lib/hrr_rb_ssh/authentication/constant.rb +14 -0
  26. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive.rb +44 -7
  27. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/context.rb +16 -9
  28. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_request.rb +7 -6
  29. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_response.rb +5 -2
  30. data/lib/hrr_rb_ssh/authentication/method/none.rb +23 -7
  31. data/lib/hrr_rb_ssh/authentication/method/none/context.rb +15 -7
  32. data/lib/hrr_rb_ssh/authentication/method/password.rb +28 -7
  33. data/lib/hrr_rb_ssh/authentication/method/password/context.rb +16 -7
  34. data/lib/hrr_rb_ssh/authentication/method/publickey.rb +63 -10
  35. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm.rb +0 -1
  36. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/functionable.rb +32 -8
  37. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/signature_blob.rb +2 -4
  38. data/lib/hrr_rb_ssh/authentication/method/publickey/context.rb +11 -2
  39. data/lib/hrr_rb_ssh/client.rb +234 -0
  40. data/lib/hrr_rb_ssh/codable.rb +15 -13
  41. data/lib/hrr_rb_ssh/compat/ruby.rb +0 -1
  42. data/lib/hrr_rb_ssh/connection.rb +145 -75
  43. data/lib/hrr_rb_ssh/connection/channel.rb +342 -109
  44. data/lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb +24 -19
  45. data/lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb +24 -19
  46. data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +19 -12
  47. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain.rb +0 -2
  48. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain/chain_context.rb +0 -3
  49. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb +2 -5
  50. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb +5 -4
  51. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb +2 -5
  52. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb +5 -4
  53. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb +2 -5
  54. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb +5 -4
  55. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb +2 -5
  56. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb +5 -4
  57. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb +2 -5
  58. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb +5 -4
  59. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change.rb +2 -5
  60. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change/context.rb +5 -4
  61. data/lib/hrr_rb_ssh/connection/global_request_handler.rb +14 -12
  62. data/lib/hrr_rb_ssh/connection/request_handler.rb +1 -3
  63. data/lib/hrr_rb_ssh/connection/request_handler/reference_env_request_handler.rb +0 -2
  64. data/lib/hrr_rb_ssh/connection/request_handler/reference_exec_request_handler.rb +4 -6
  65. data/lib/hrr_rb_ssh/connection/request_handler/reference_pty_req_request_handler.rb +10 -12
  66. data/lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb +4 -6
  67. data/lib/hrr_rb_ssh/connection/request_handler/reference_window_change_request_handler.rb +0 -2
  68. data/lib/hrr_rb_ssh/error/closed_authentication.rb +1 -1
  69. data/lib/hrr_rb_ssh/error/closed_connection.rb +1 -1
  70. data/lib/hrr_rb_ssh/error/closed_transport.rb +1 -1
  71. data/lib/hrr_rb_ssh/loggable.rb +42 -0
  72. data/lib/hrr_rb_ssh/message/001_ssh_msg_disconnect.rb +2 -4
  73. data/lib/hrr_rb_ssh/message/002_ssh_msg_ignore.rb +2 -4
  74. data/lib/hrr_rb_ssh/message/003_ssh_msg_unimplemented.rb +2 -4
  75. data/lib/hrr_rb_ssh/message/004_ssh_msg_debug.rb +2 -4
  76. data/lib/hrr_rb_ssh/message/005_ssh_msg_service_request.rb +2 -4
  77. data/lib/hrr_rb_ssh/message/006_ssh_msg_service_accept.rb +2 -4
  78. data/lib/hrr_rb_ssh/message/020_ssh_msg_kexinit.rb +2 -4
  79. data/lib/hrr_rb_ssh/message/021_ssh_msg_newkeys.rb +2 -4
  80. data/lib/hrr_rb_ssh/message/030_ssh_msg_kex_dh_gex_request_old.rb +2 -4
  81. data/lib/hrr_rb_ssh/message/030_ssh_msg_kexdh_init.rb +2 -4
  82. data/lib/hrr_rb_ssh/message/030_ssh_msg_kexecdh_init.rb +2 -4
  83. data/lib/hrr_rb_ssh/message/031_ssh_msg_kex_dh_gex_group.rb +2 -4
  84. data/lib/hrr_rb_ssh/message/031_ssh_msg_kexdh_reply.rb +2 -4
  85. data/lib/hrr_rb_ssh/message/031_ssh_msg_kexecdh_reply.rb +2 -4
  86. data/lib/hrr_rb_ssh/message/032_ssh_msg_kex_dh_gex_init.rb +2 -4
  87. data/lib/hrr_rb_ssh/message/033_ssh_msg_kex_dh_gex_reply.rb +2 -4
  88. data/lib/hrr_rb_ssh/message/034_ssh_msg_kex_dh_gex_request.rb +2 -4
  89. data/lib/hrr_rb_ssh/message/050_ssh_msg_userauth_request.rb +2 -4
  90. data/lib/hrr_rb_ssh/message/051_ssh_msg_userauth_failure.rb +2 -4
  91. data/lib/hrr_rb_ssh/message/052_ssh_msg_userauth_success.rb +2 -4
  92. data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_info_request.rb +2 -4
  93. data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok.rb +2 -4
  94. data/lib/hrr_rb_ssh/message/061_ssh_msg_userauth_info_response.rb +2 -4
  95. data/lib/hrr_rb_ssh/message/080_ssh_msg_global_request.rb +2 -4
  96. data/lib/hrr_rb_ssh/message/081_ssh_msg_request_success.rb +2 -4
  97. data/lib/hrr_rb_ssh/message/082_ssh_msg_request_failure.rb +2 -4
  98. data/lib/hrr_rb_ssh/message/090_ssh_msg_channel_open.rb +2 -4
  99. data/lib/hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb +2 -4
  100. data/lib/hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb +2 -4
  101. data/lib/hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb +2 -4
  102. data/lib/hrr_rb_ssh/message/094_ssh_msg_channel_data.rb +2 -4
  103. data/lib/hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb +2 -4
  104. data/lib/hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb +2 -4
  105. data/lib/hrr_rb_ssh/message/097_ssh_msg_channel_close.rb +2 -4
  106. data/lib/hrr_rb_ssh/message/098_ssh_msg_channel_request.rb +3 -5
  107. data/lib/hrr_rb_ssh/message/099_ssh_msg_channel_success.rb +2 -4
  108. data/lib/hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb +2 -4
  109. data/lib/hrr_rb_ssh/server.rb +16 -10
  110. data/lib/hrr_rb_ssh/transport.rb +113 -77
  111. data/lib/hrr_rb_ssh/transport/compression_algorithm/functionable.rb +5 -3
  112. data/lib/hrr_rb_ssh/transport/compression_algorithm/unfunctionable.rb +5 -3
  113. data/lib/hrr_rb_ssh/transport/encryption_algorithm/functionable.rb +5 -3
  114. data/lib/hrr_rb_ssh/transport/encryption_algorithm/unfunctionable.rb +5 -3
  115. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +43 -37
  116. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman/h0.rb +2 -4
  117. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange.rb +87 -52
  118. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange/h0.rb +2 -4
  119. data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman.rb +43 -37
  120. data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman/h0.rb +2 -4
  121. data/lib/hrr_rb_ssh/transport/mac_algorithm/functionable.rb +5 -3
  122. data/lib/hrr_rb_ssh/transport/mac_algorithm/unfunctionable.rb +5 -3
  123. data/lib/hrr_rb_ssh/transport/receiver.rb +8 -7
  124. data/lib/hrr_rb_ssh/transport/sender.rb +5 -3
  125. data/lib/hrr_rb_ssh/transport/sequence_number.rb +0 -4
  126. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +0 -1
  127. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/functionable.rb +5 -3
  128. data/lib/hrr_rb_ssh/version.rb +1 -1
  129. metadata +18 -51
  130. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519.rb +0 -61
  131. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key.rb +0 -29
  132. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key_content.rb +0 -26
  133. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/pkey.rb +0 -158
  134. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/public_key_blob.rb +0 -23
  135. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/signature.rb +0 -23
  136. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519.rb +0 -21
  137. data/lib/hrr_rb_ssh/compat/ruby/array.rb +0 -14
  138. data/lib/hrr_rb_ssh/logger.rb +0 -56
  139. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_ed25519.rb +0 -20
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
  require 'hrr_rb_ssh/authentication/method/keyboard_interactive/info_request'
6
6
  require 'hrr_rb_ssh/authentication/method/keyboard_interactive/info_response'
7
7
 
@@ -10,24 +10,31 @@ module HrrRbSsh
10
10
  class Method
11
11
  class KeyboardInteractive
12
12
  class Context
13
+ include Loggable
14
+
13
15
  attr_reader \
14
16
  :username,
15
17
  :submethods,
16
- :info_response
18
+ :info_response,
19
+ :variables,
20
+ :vars,
21
+ :authentication_methods
17
22
 
18
- def initialize transport, username, submethods
23
+ def initialize transport, username, submethods, variables, authentication_methods, logger: nil
24
+ self.logger = logger
19
25
  @transport = transport
20
26
  @username = username
21
27
  @submethods = submethods
22
-
23
- @logger = Logger.new self.class.name
28
+ @variables = variables
29
+ @vars = variables
30
+ @authentication_methods = authentication_methods
24
31
  end
25
32
 
26
33
  def info_request name, instruction, language_tag, prompts
27
- @logger.info { "send userauth info request" }
28
- @transport.send InfoRequest.new(name, instruction, language_tag, prompts).to_payload
29
- @logger.info { "receive userauth info response" }
30
- @info_response = InfoResponse.new @transport.receive
34
+ log_info { "send userauth info request" }
35
+ @transport.send InfoRequest.new(name, instruction, language_tag, prompts, logger: logger).to_payload
36
+ log_info { "receive userauth info response" }
37
+ @info_response = InfoResponse.new @transport.receive, logger: logger
31
38
  end
32
39
  end
33
40
  end
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
  require 'hrr_rb_ssh/message'
6
6
 
7
7
  module HrrRbSsh
@@ -9,13 +9,14 @@ module HrrRbSsh
9
9
  class Method
10
10
  class KeyboardInteractive
11
11
  class InfoRequest
12
- def initialize name, instruction, language_tag, prompts
12
+ include Loggable
13
+
14
+ def initialize name, instruction, language_tag, prompts, logger: nil
15
+ self.logger = logger
13
16
  @name = name
14
17
  @instruction = instruction
15
18
  @language_tag = language_tag
16
19
  @prompts = prompts
17
-
18
- @logger = Logger.new self.class.name
19
20
  end
20
21
 
21
22
  def to_message
@@ -30,13 +31,13 @@ module HrrRbSsh
30
31
  [
31
32
  [:"prompt[#{i+1}]", prompt],
32
33
  [:"echo[#{i+1}]", echo],
33
- ].to_h
34
+ ].inject(Hash.new){ |h, (k, v)| h.update({k => v}) }
34
35
  }.inject(Hash.new){ |a, b| a.merge(b) }
35
36
  message.merge(message_prompts)
36
37
  end
37
38
 
38
39
  def to_payload
39
- Message::SSH_MSG_USERAUTH_INFO_REQUEST.encode self.to_message
40
+ Message::SSH_MSG_USERAUTH_INFO_REQUEST.new(logger: logger).encode self.to_message
40
41
  end
41
42
  end
42
43
  end
@@ -8,14 +8,17 @@ module HrrRbSsh
8
8
  class Method
9
9
  class KeyboardInteractive
10
10
  class InfoResponse
11
+ include Loggable
12
+
11
13
  attr_reader \
12
14
  :num_responses,
13
15
  :responses
14
16
 
15
- def initialize payload
17
+ def initialize payload, logger: nil
18
+ self.logger = logger
16
19
  case payload[0,1].unpack("C")[0]
17
20
  when Message::SSH_MSG_USERAUTH_INFO_RESPONSE::VALUE
18
- message = Message::SSH_MSG_USERAUTH_INFO_RESPONSE.decode payload
21
+ message = Message::SSH_MSG_USERAUTH_INFO_RESPONSE.new(logger: logger).decode payload
19
22
  @num_responses = message[:'num-responses']
20
23
  @responses = Array.new(message[:'num-responses']){ |i| message[:"response[#{i+1}]"] }
21
24
  else
@@ -1,26 +1,42 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
 
6
6
  module HrrRbSsh
7
7
  class Authentication
8
8
  class Method
9
9
  class None < Method
10
+ include Loggable
11
+
10
12
  NAME = 'none'
11
13
  PREFERENCE = 0
12
14
 
13
- def initialize transport, options
14
- @logger = Logger.new(self.class.name)
15
- @authenticator = options.fetch( 'authentication_none_authenticator', Authenticator.new { false } )
15
+ def initialize transport, options, variables, authentication_methods, logger: nil
16
+ self.logger = logger
17
+ @transport = transport
18
+ @authenticator = options.fetch( 'authentication_none_authenticator', Authenticator.new{ false } )
19
+ @variables = variables
20
+ @authentication_methods = authentication_methods
16
21
  end
17
22
 
18
23
  def authenticate userauth_request_message
19
- @logger.info { "authenticate" }
20
- @logger.debug { "userauth request: " + userauth_request_message.inspect }
21
- context = Context.new(userauth_request_message[:'user name'])
24
+ log_info { "authenticate" }
25
+ context = Context.new(userauth_request_message[:'user name'], @variables, @authentication_methods, logger: logger)
22
26
  @authenticator.authenticate context
23
27
  end
28
+
29
+ def request_authentication username, service_name
30
+ message = {
31
+ :'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
32
+ :"user name" => username,
33
+ :"service name" => service_name,
34
+ :"method name" => NAME,
35
+ }
36
+ payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
37
+ @transport.send payload
38
+ payload = @transport.receive
39
+ end
24
40
  end
25
41
  end
26
42
  end
@@ -1,24 +1,32 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
 
6
6
  module HrrRbSsh
7
7
  class Authentication
8
8
  class Method
9
9
  class None
10
10
  class Context
11
- attr_reader :username
11
+ include Loggable
12
12
 
13
- def initialize username
14
- @username = username
13
+ attr_reader \
14
+ :username,
15
+ :variables,
16
+ :vars,
17
+ :authentication_methods
15
18
 
16
- @logger = Logger.new self.class.name
19
+ def initialize username, variables, authentication_methods, logger: nil
20
+ self.logger = logger
21
+ @username = username
22
+ @variables = variables
23
+ @vars = variables
24
+ @authentication_methods = authentication_methods
17
25
  end
18
26
 
19
27
  def verify username
20
- @logger.info { "verify username" }
21
- @logger.debug { "username is #{username}, @username is #{@username}" }
28
+ log_info { "verify username" }
29
+ log_debug { "username is #{username}, @username is #{@username}" }
22
30
  username == @username
23
31
  end
24
32
  end
@@ -1,28 +1,49 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
 
6
6
  module HrrRbSsh
7
7
  class Authentication
8
8
  class Method
9
9
  class Password < Method
10
+ include Loggable
11
+
10
12
  NAME = 'password'
11
13
  PREFERENCE = 10
12
14
 
13
- def initialize transport, options
14
- @logger = Logger.new(self.class.name)
15
- @authenticator = options.fetch( 'authentication_password_authenticator', Authenticator.new { false } )
15
+ def initialize transport, options, variables, authentication_methods, logger: nil
16
+ self.logger = logger
17
+ @transport = transport
18
+ @authenticator = options.fetch( 'authentication_password_authenticator', Authenticator.new{ false } )
19
+ @options = options
20
+ @variables = variables
21
+ @authentication_methods = authentication_methods
16
22
  end
17
23
 
18
24
  def authenticate userauth_request_message
19
- @logger.info { "authenticate" }
20
- @logger.debug { "userauth request: " + userauth_request_message.inspect }
25
+ log_info { "authenticate" }
21
26
  username = userauth_request_message[:'user name']
22
27
  password = userauth_request_message[:'plaintext password']
23
- context = Context.new(username, password)
28
+ context = Context.new(username, password, @variables, @authentication_methods, logger: logger)
24
29
  @authenticator.authenticate context
25
30
  end
31
+
32
+ def request_authentication username, service_name
33
+ password = @options['client_authentication_password']
34
+ message = {
35
+ :'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
36
+ :"user name" => username,
37
+ :"service name" => service_name,
38
+ :"method name" => NAME,
39
+ :"FALSE" => false,
40
+ :"plaintext password" => password,
41
+ }
42
+ payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
43
+ @transport.send payload
44
+
45
+ payload = @transport.receive
46
+ end
26
47
  end
27
48
  end
28
49
  end
@@ -1,25 +1,34 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
 
6
6
  module HrrRbSsh
7
7
  class Authentication
8
8
  class Method
9
9
  class Password
10
10
  class Context
11
- attr_reader :username, :password
11
+ include Loggable
12
12
 
13
- def initialize username, password
13
+ attr_reader \
14
+ :username,
15
+ :password,
16
+ :variables,
17
+ :vars,
18
+ :authentication_methods
19
+
20
+ def initialize username, password, variables, authentication_methods, logger: nil
21
+ self.logger = logger
14
22
  @username = username
15
23
  @password = password
16
-
17
- @logger = Logger.new self.class.name
24
+ @variables = variables
25
+ @vars = variables
26
+ @authentication_methods = authentication_methods
18
27
  end
19
28
 
20
29
  def verify username, password
21
- @logger.info { "verify username and password" }
22
- @logger.debug { "username is #{username}, @username is #{@username}, and password is #{password}, @password is #{@password}" }
30
+ log_info { "verify username and password" }
31
+ log_debug { "username is #{username}, @username is #{@username}, and password is #{password}, @password is #{@password}" }
23
32
  username == @username and password == @password
24
33
  end
25
34
  end
@@ -1,36 +1,42 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
 
6
6
  module HrrRbSsh
7
7
  class Authentication
8
8
  class Method
9
9
  class Publickey < Method
10
+ include Loggable
11
+
10
12
  NAME = 'publickey'
11
13
  PREFERENCE = 20
12
14
 
13
- def initialize transport, options
14
- @logger = Logger.new(self.class.name)
15
+ def initialize transport, options, variables, authentication_methods, logger: nil
16
+ self.logger = logger
17
+ @transport = transport
18
+ @options = options
15
19
  @session_id = options['session id']
16
- @authenticator = options.fetch( 'authentication_publickey_authenticator', Authenticator.new { false } )
20
+ @authenticator = options.fetch( 'authentication_publickey_authenticator', Authenticator.new{ false } )
21
+ @variables = variables
22
+ @authentication_methods = authentication_methods
17
23
  end
18
24
 
19
25
  def authenticate userauth_request_message
20
26
  public_key_algorithm_name = userauth_request_message[:'public key algorithm name']
21
27
  unless Algorithm.list_preferred.include?(public_key_algorithm_name)
22
- @logger.info { "unsupported public key algorithm: #{public_key_algorithm_name}" }
28
+ log_info { "unsupported public key algorithm: #{public_key_algorithm_name}" }
23
29
  return false
24
30
  end
25
31
  unless userauth_request_message[:'with signature']
26
- @logger.info { "public key algorithm is ok, require signature" }
32
+ log_info { "public key algorithm is ok, require signature" }
27
33
  public_key_blob = userauth_request_message[:'public key blob']
28
34
  userauth_pk_ok_message public_key_algorithm_name, public_key_blob
29
35
  else
30
- @logger.info { "verify signature" }
36
+ log_info { "verify signature" }
31
37
  username = userauth_request_message[:'user name']
32
- algorithm = Algorithm[public_key_algorithm_name].new
33
- context = Context.new(username, algorithm, @session_id, userauth_request_message)
38
+ algorithm = Algorithm[public_key_algorithm_name].new logger: logger
39
+ context = Context.new(username, algorithm, @session_id, userauth_request_message, @variables, @authentication_methods, logger: logger)
34
40
  @authenticator.authenticate context
35
41
  end
36
42
  end
@@ -41,7 +47,54 @@ module HrrRbSsh
41
47
  :'public key algorithm name from the request' => public_key_algorithm_name,
42
48
  :'public key blob from the request' => public_key_blob,
43
49
  }
44
- payload = Message::SSH_MSG_USERAUTH_PK_OK.encode message
50
+ payload = Message::SSH_MSG_USERAUTH_PK_OK.new(logger: logger).encode message
51
+ end
52
+
53
+ def request_authentication username, service_name
54
+ public_key_algorithm_name, secret_key = @options['client_authentication_publickey']
55
+ send_request_without_signature username, service_name, public_key_algorithm_name, secret_key
56
+ payload = @transport.receive
57
+ case payload[0,1].unpack("C")[0]
58
+ when Message::SSH_MSG_USERAUTH_PK_OK::VALUE
59
+ send_request_with_signature username, service_name, public_key_algorithm_name, secret_key
60
+ @transport.receive
61
+ else
62
+ payload
63
+ end
64
+ end
65
+
66
+ def send_request_without_signature username, service_name, public_key_algorithm_name, secret_key
67
+ algorithm = Algorithm[public_key_algorithm_name].new logger: logger
68
+ public_key_blob = algorithm.generate_public_key_blob(secret_key)
69
+ message = {
70
+ :'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
71
+ :"user name" => username,
72
+ :"service name" => service_name,
73
+ :"method name" => NAME,
74
+ :"with signature" => false,
75
+ :'public key algorithm name' => public_key_algorithm_name,
76
+ :'public key blob' => public_key_blob,
77
+ }
78
+ payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
79
+ @transport.send payload
80
+ end
81
+
82
+ def send_request_with_signature username, service_name, public_key_algorithm_name, secret_key
83
+ algorithm = Algorithm[public_key_algorithm_name].new logger: logger
84
+ public_key_blob = algorithm.generate_public_key_blob(secret_key)
85
+ signature = algorithm.generate_signature(@session_id, username, service_name, 'publickey', secret_key)
86
+ message = {
87
+ :'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
88
+ :"user name" => username,
89
+ :"service name" => service_name,
90
+ :"method name" => NAME,
91
+ :"with signature" => true,
92
+ :'public key algorithm name' => public_key_algorithm_name,
93
+ :'public key blob' => public_key_blob,
94
+ :'signature' => signature,
95
+ }
96
+ payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
97
+ @transport.send payload
45
98
  end
46
99
  end
47
100
  end
@@ -23,4 +23,3 @@ require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_rsa'
23
23
  require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp256'
24
24
  require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp384'
25
25
  require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp521'
26
- require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519'
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
  require 'hrr_rb_ssh/algorithm/publickey'
6
6
 
7
7
  module HrrRbSsh
@@ -10,16 +10,18 @@ module HrrRbSsh
10
10
  class Publickey
11
11
  class Algorithm
12
12
  module Functionable
13
- def initialize
14
- @logger = Logger.new(self.class.name)
13
+ include Loggable
14
+
15
+ def initialize logger: nil
16
+ self.logger = logger
15
17
  end
16
18
 
17
19
  def verify_public_key public_key_algorithm_name, public_key, public_key_blob
18
20
  begin
19
- publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new public_key
21
+ publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new public_key, logger: logger
20
22
  public_key_algorithm_name == self.class::NAME && public_key_blob == publickey.to_public_key_blob
21
23
  rescue => e
22
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
24
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
23
25
  false
24
26
  end
25
27
  end
@@ -36,14 +38,36 @@ module HrrRbSsh
36
38
  :'public key algorithm name' => message[:'public key algorithm name'],
37
39
  :'public key blob' => message[:'public key blob'],
38
40
  }
39
- signature_blob = SignatureBlob.encode signature_blob_h
40
- publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new message[:'public key blob']
41
+ signature_blob = SignatureBlob.new(logger: logger).encode signature_blob_h
42
+ publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new message[:'public key blob'], logger: logger
41
43
  publickey.verify message[:'signature'], signature_blob
42
44
  rescue => e
43
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
45
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
44
46
  false
45
47
  end
46
48
  end
49
+
50
+ def generate_public_key_blob secret_key
51
+ publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new secret_key, logger: logger
52
+ publickey.to_public_key_blob
53
+ end
54
+
55
+ def generate_signature session_id, username, service_name, method_name, secret_key
56
+ publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new secret_key, logger: logger
57
+ publickey_blob = publickey.to_public_key_blob
58
+ signature_blob_h = {
59
+ :'session identifier' => session_id,
60
+ :'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
61
+ :'user name' => username,
62
+ :'service name' => service_name,
63
+ :'method name' => method_name,
64
+ :'with signature' => true,
65
+ :'public key algorithm name' => self.class::NAME,
66
+ :'public key blob' => publickey_blob
67
+ }
68
+ signature_blob = SignatureBlob.new(logger: logger).encode signature_blob_h
69
+ publickey.sign signature_blob
70
+ end
47
71
  end
48
72
  end
49
73
  end