net-ssh 6.1.0 → 7.3.0

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 (116) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +94 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +4 -0
  10. data/.rubocop.yml +12 -1
  11. data/.rubocop_todo.yml +475 -376
  12. data/CHANGES.txt +64 -3
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +29 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +2 -0
  17. data/Gemfile.noed25519 +2 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/README.md +38 -22
  20. data/Rakefile +92 -0
  21. data/SECURITY.md +4 -0
  22. data/docker-compose.yml +25 -0
  23. data/lib/net/ssh/authentication/agent.rb +29 -13
  24. data/lib/net/ssh/authentication/certificate.rb +14 -11
  25. data/lib/net/ssh/authentication/constants.rb +0 -1
  26. data/lib/net/ssh/authentication/ed25519.rb +14 -11
  27. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  28. data/lib/net/ssh/authentication/key_manager.rb +65 -36
  29. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  30. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  31. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
  32. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  33. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  34. data/lib/net/ssh/authentication/methods/publickey.rb +57 -17
  35. data/lib/net/ssh/authentication/pageant.rb +97 -97
  36. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +3 -3
  37. data/lib/net/ssh/authentication/session.rb +25 -17
  38. data/lib/net/ssh/buffer.rb +71 -51
  39. data/lib/net/ssh/buffered_io.rb +25 -26
  40. data/lib/net/ssh/config.rb +33 -20
  41. data/lib/net/ssh/connection/channel.rb +84 -82
  42. data/lib/net/ssh/connection/constants.rb +0 -4
  43. data/lib/net/ssh/connection/event_loop.rb +30 -24
  44. data/lib/net/ssh/connection/keepalive.rb +12 -12
  45. data/lib/net/ssh/connection/session.rb +109 -108
  46. data/lib/net/ssh/connection/term.rb +56 -58
  47. data/lib/net/ssh/errors.rb +12 -12
  48. data/lib/net/ssh/key_factory.rb +7 -8
  49. data/lib/net/ssh/known_hosts.rb +86 -18
  50. data/lib/net/ssh/loggable.rb +8 -9
  51. data/lib/net/ssh/packet.rb +1 -1
  52. data/lib/net/ssh/prompt.rb +9 -11
  53. data/lib/net/ssh/proxy/command.rb +1 -1
  54. data/lib/net/ssh/proxy/errors.rb +2 -4
  55. data/lib/net/ssh/proxy/http.rb +18 -20
  56. data/lib/net/ssh/proxy/https.rb +8 -10
  57. data/lib/net/ssh/proxy/jump.rb +8 -10
  58. data/lib/net/ssh/proxy/socks4.rb +2 -4
  59. data/lib/net/ssh/proxy/socks5.rb +3 -5
  60. data/lib/net/ssh/service/forward.rb +7 -7
  61. data/lib/net/ssh/test/channel.rb +24 -26
  62. data/lib/net/ssh/test/extensions.rb +35 -35
  63. data/lib/net/ssh/test/kex.rb +6 -8
  64. data/lib/net/ssh/test/local_packet.rb +0 -2
  65. data/lib/net/ssh/test/packet.rb +3 -3
  66. data/lib/net/ssh/test/remote_packet.rb +6 -8
  67. data/lib/net/ssh/test/script.rb +25 -27
  68. data/lib/net/ssh/test/socket.rb +12 -15
  69. data/lib/net/ssh/test.rb +4 -5
  70. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  71. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  72. data/lib/net/ssh/transport/algorithms.rb +51 -19
  73. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  75. data/lib/net/ssh/transport/cipher_factory.rb +56 -29
  76. data/lib/net/ssh/transport/constants.rb +3 -3
  77. data/lib/net/ssh/transport/ctr.rb +7 -7
  78. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  79. data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac.rb +12 -12
  87. data/lib/net/ssh/transport/identity_cipher.rb +19 -13
  88. data/lib/net/ssh/transport/kex/abstract.rb +12 -5
  89. data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
  90. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  92. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
  95. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
  96. data/lib/net/ssh/transport/kex.rb +8 -6
  97. data/lib/net/ssh/transport/key_expander.rb +7 -8
  98. data/lib/net/ssh/transport/openssl.rb +51 -26
  99. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  100. data/lib/net/ssh/transport/packet_stream.rb +46 -26
  101. data/lib/net/ssh/transport/server_version.rb +17 -16
  102. data/lib/net/ssh/transport/session.rb +9 -7
  103. data/lib/net/ssh/transport/state.rb +44 -44
  104. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  105. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  106. data/lib/net/ssh/verifiers/always.rb +6 -4
  107. data/lib/net/ssh/verifiers/never.rb +0 -2
  108. data/lib/net/ssh/version.rb +2 -2
  109. data/lib/net/ssh.rb +15 -8
  110. data/net-ssh-public_cert.pem +19 -18
  111. data/net-ssh.gemspec +7 -4
  112. data/support/ssh_tunnel_bug.rb +3 -3
  113. data.tar.gz.sig +0 -0
  114. metadata +76 -29
  115. metadata.gz.sig +0 -0
  116. data/.travis.yml +0 -52
data/CHANGES.txt CHANGED
@@ -1,6 +1,67 @@
1
+ === 7.3.0 rc0
2
+
3
+ * aes(128|256)gcm [#946]
4
+
5
+ === 7.2.2
6
+
7
+ * ruby 3.3.0: base64 fix
8
+
9
+ === 7.2.1 rc1
10
+
11
+ * feat: allow load of certkey from string [#926]
12
+ * fix: fix for Socket#recv returning nil on ruby 3.3.0 [#928]
13
+
14
+ === 7.2.0
15
+
16
+ * Add debugging information for algorithm of pubkey in use [#918]
17
+
18
+ === 7.2.0 rc1
19
+
20
+ * Allow IdentityAgent as option to Net::SSH.start [#912]
21
+
22
+ === 7.2.0 beta1
23
+
24
+ * Support `chacha20-poly1305@opnessh.com` cypher if `RbNaCl` gem is installed [#908]
25
+
26
+ === 7.1.0
27
+
28
+ * Accept pubkey_algorithms option when starting a new connection [#891]
29
+
30
+ === 7.1.0 beta1
31
+
32
+ * Don't use the deprecated set_XXX methods on RSA keys. [#875]
33
+ * Raise error when BCryptPbkdf fails [#876]
34
+
35
+ === 7.0.1
36
+
37
+ * Drop leftover debug statement [#866]
38
+
39
+ === 7.0.0
40
+
41
+ * BREAKING: Drop support for Ruby 2.5
42
+ * Fix decoding of ecdsa-sha2-nistp256 private keys [#657, #854]
43
+ * Fix missing require [#855]
44
+ * Support `~` in the path to the SSH agent's unix socket [#850]
45
+ * Add support for RSA client authentication with SHA-2 [a45f54]
46
+ * openssl: DSA: don't hardcode expected signature size, see ruby/openssl#483 [23a15c]
47
+ * Internal housekeeping (rubocop, codecov, remove travis, adding/improving tests)
48
+
49
+ === 6.3.0 beta1
50
+
51
+ * Support cert based host key auth, fix asterisk in known_hosts [#833]
52
+ * Support kex dh-group14-sha256 [#795]
53
+ * Fix StrictHostKeyChecking ssh config parameter translation [#765]
54
+
55
+ === 6.2.0 rc1
56
+
57
+ === 6.2.0 beta1
58
+
59
+ * rsa-sha2-512, rsa-sha2-256 host_key algs [#771]
60
+ * JRuby aes*-ctr suppport [#767]
61
+
1
62
  === 6.1.0
2
63
 
3
- * adapt to ssh's default bahaviors when no username is provided.
64
+ * Adapt to ssh's default behaviors when no username is provided.
4
65
  When Net::SSH.start user is nil and config has no entry
5
66
  we default to Etc.getpwuid.name() instead of Etc.getlogin(). [#749]
6
67
 
@@ -36,7 +97,7 @@
36
97
  === 5.2.0.rc3
37
98
 
38
99
  * Fix check_host_ip read from config
39
- * Support ssh-ed25519 in kown hosts
100
+ * Support ssh-ed25519 in known hosts
40
101
 
41
102
  === 5.2.0.rc2
42
103
 
@@ -59,7 +120,7 @@
59
120
 
60
121
  === 5.0.2
61
122
 
62
- * fix ctr for jruby [#612]
123
+ * Fix ctr for jruby [#612]
63
124
 
64
125
  === 5.0.1
65
126
 
data/DEVELOPMENT.md ADDED
@@ -0,0 +1,23 @@
1
+ ### Development notes
2
+
3
+ ## Building/running ssh server in debug mode
4
+
5
+ clone the openssh server from `https://github.com/openssh/openssh-portable`
6
+
7
+ ```sh
8
+ brew install openssl
9
+ /usr/local/Cellar/openssl@3/3.1.0/bin/openssl
10
+
11
+ autoreconf
12
+ ./configure --with-ssl-dir=/usr/local/Cellar/openssl@3/3.1.0/ --with-audit=debug --enable-debug CPPFLAGS="-DDEBUG -DPACKET_DEBUG" CFLAGS="-g -O0"
13
+ make
14
+ ```
15
+
16
+ To run server in debug mode:
17
+ ```sh
18
+ echo '#' > /tmp/sshd_config
19
+ ssh-keygen -t rsa -f /tmp/ssh_host_rsa_key
20
+ # /Users/boga/Work/OSS/NetSSH/openssh-portable/sshd -p 2222 -D -d -d -d -e -f /tmp/sshd_config
21
+ /Users/boga/Work/OSS/NetSSH/openssh-portable/sshd -p 2222 -D -d -d -d -e -f /tmp/sshd_config -h /tmp/ssh_host_rsa_key
22
+
23
+ ```
data/Dockerfile ADDED
@@ -0,0 +1,29 @@
1
+ ARG RUBY_VERSION=3.1
2
+ FROM ruby:${RUBY_VERSION}
3
+
4
+ ARG BUNDLERV=
5
+
6
+ RUN apt update && apt install -y openssh-server sudo netcat-openbsd \
7
+ && useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_1' \
8
+ && useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_2' \
9
+ && echo net_ssh_1:foopwd | chpasswd \
10
+ && echo net_ssh_2:foo2pwd | chpasswd \
11
+ && mkdir -p /home/net_ssh_1/.ssh \
12
+ && mkdir -p /home/net_ssh_2/.ssh \
13
+ && echo "net_ssh_1 ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
14
+ && echo "net_ssh_2 ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
15
+ && ssh-keygen -f /etc/ssh/users_ca -N ''
16
+
17
+ ENV INSTALL_PATH="/netssh"
18
+
19
+ WORKDIR $INSTALL_PATH
20
+
21
+ COPY Gemfile net-ssh.gemspec $INSTALL_PATH/
22
+
23
+ COPY lib/net/ssh/version.rb $INSTALL_PATH/lib/net/ssh/version.rb
24
+
25
+ RUN gem install bundler ${BUNDLERV} && bundle install
26
+
27
+ COPY . $INSTALL_PATH/
28
+
29
+ CMD service ssh start && rake test && NET_SSH_NO_ED25519=1 rake test
@@ -0,0 +1,17 @@
1
+ FROM ubuntu:22.04
2
+
3
+ ENV INSTALL_PATH="/netssh"
4
+
5
+ RUN apt update && apt install -y openssl ruby ruby-dev git build-essential
6
+
7
+ WORKDIR $INSTALL_PATH
8
+
9
+ COPY Gemfile net-ssh.gemspec $INSTALL_PATH/
10
+
11
+ COPY lib/net/ssh/version.rb $INSTALL_PATH/lib/net/ssh/version.rb
12
+
13
+ RUN ls -l && gem install bundler && bundle install
14
+
15
+ COPY . $INSTALL_PATH/
16
+
17
+ CMD openssl version && ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION' && rake test
data/Gemfile CHANGED
@@ -9,3 +9,5 @@ if ENV["CI"]
9
9
  gem 'codecov', require: false, group: :test
10
10
  gem 'simplecov', require: false, group: :test
11
11
  end
12
+
13
+ gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
data/Gemfile.noed25519 CHANGED
@@ -8,3 +8,5 @@ if ENV["CI"] && !Gem.win_platform?
8
8
  gem 'simplecov', require: false, group: :test
9
9
  gem 'codecov', require: false, group: :test
10
10
  end
11
+
12
+ gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
data/Gemfile.norbnacl ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ENV['NET_SSH_NO_RBNACL'] = 'true'
4
+ # Specify your gem's dependencies in mygem.gemspec
5
+ gemspec
6
+
7
+ if ENV["CI"] && !Gem.win_platform?
8
+ gem 'simplecov', require: false, group: :test
9
+ gem 'codecov', require: false, group: :test
10
+ end
11
+
12
+ gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/net-ssh.svg)](https://badge.fury.io/rb/net-ssh)
2
2
  [![Join the chat at https://gitter.im/net-ssh/net-ssh](https://badges.gitter.im/net-ssh/net-ssh.svg)](https://gitter.im/net-ssh/net-ssh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
3
- [![Build Status](https://travis-ci.org/net-ssh/net-ssh.svg?branch=master)](https://travis-ci.org/net-ssh/net-ssh)
3
+ [![Build status](https://github.com/net-ssh/net-ssh/actions/workflows/ci.yml/badge.svg)](https://github.com/net-ssh/net-ssh/actions/workflows/ci.yml)
4
4
  [![Coverage status](https://codecov.io/gh/net-ssh/net-ssh/branch/master/graph/badge.svg)](https://codecov.io/gh/net-ssh/net-ssh)
5
5
  [![Backers on Open Collective](https://opencollective.com/net-ssh/backers/badge.svg)](#backers])
6
6
  [![Sponsors on Open Collective](https://opencollective.com/net-ssh/sponsors/badge.svg)](#sponsors)
7
7
 
8
- # Net::SSH 6.x
8
+ # Net::SSH 7.x
9
9
 
10
- * Docs: http://net-ssh.github.com/net-ssh
10
+ * Docs: http://net-ssh.github.io/net-ssh
11
11
  * Issues: https://github.com/net-ssh/net-ssh/issues
12
12
  * Codes: https://github.com/net-ssh/net-ssh
13
13
  * Email: net-ssh@solutious.com
@@ -33,7 +33,7 @@ We strongly recommend that you install a servers's version that supports the lat
33
33
 
34
34
  It is possible to return to the previous behavior by adding the option : `append_all_supported_algorithms: true`
35
35
 
36
- Unsecure algoritms will definitely be removed in Net::SSH 7.*.
36
+ Unsecure algoritms will definitely be removed in Net::SSH 8.*.
37
37
 
38
38
  ### Host Keys
39
39
 
@@ -44,7 +44,7 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
44
44
  | ecdsa-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
45
45
  | ecdsa-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
46
46
  | ecdsa-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
47
- | ssh-dss | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
47
+ | ssh-dss | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
48
48
 
49
49
  ### Key Exchange
50
50
 
@@ -54,9 +54,9 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
54
54
  | ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
55
55
  | ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
56
56
  | ecdh-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
57
- | diffie-hellman-group1-sha1 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
57
+ | diffie-hellman-group1-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
58
58
  | diffie-hellman-group14-sha1 | OK | |
59
- | diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
59
+ | diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
60
60
  | diffie-hellman-group-exchange-sha256 | OK | |
61
61
 
62
62
  ### Encryption algorithms (ciphers)
@@ -64,13 +64,14 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
64
64
  | Name | Support | Details |
65
65
  |--------------------------------------|-----------------------|----------|
66
66
  | aes256-ctr / aes192-ctr / aes128-ctr | OK | |
67
- | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
68
- | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
69
- | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
70
- | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
71
- | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
72
- | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
73
- | none | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
67
+ | chacha20-poly1305@openssh.com | OK. | Requires the gem `rbnacl` |
68
+ | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
69
+ | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
70
+ | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
71
+ | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
72
+ | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
73
+ | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
74
+ | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
74
75
 
75
76
  ### Message Authentication Code algorithms
76
77
 
@@ -80,14 +81,14 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
80
81
  | hmac-sha2-256-etm | OK | |
81
82
  | hmac-sha2-512 | OK | |
82
83
  | hmac-sha2-256 | OK | |
83
- | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 7.0 |
84
- | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 7.0 |
84
+ | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
85
+ | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
85
86
  | hmac-sha1 | OK | for backward compatibility |
86
- | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
87
- | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
88
- | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
89
- | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
90
- | none | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
87
+ | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
88
+ | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
89
+ | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
90
+ | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
91
+ | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
91
92
 
92
93
  ## SYNOPSIS:
93
94
 
@@ -211,13 +212,19 @@ Run the test suite from the net-ssh directory with the following command:
211
212
  bundle exec rake test
212
213
  ```
213
214
 
215
+ NOTE : you can run test on all ruby versions with docker :
216
+
217
+ ```
218
+ docker-compose up --build
219
+ ```
220
+
214
221
  Run a single test file like this:
215
222
 
216
223
  ```sh
217
224
  ruby -Ilib -Itest test/transport/test_server_version.rb
218
225
  ```
219
226
 
220
- To run integration tests see test/integration/README.txt
227
+ To run integration tests see [here](test/integration/README.md)
221
228
 
222
229
  ### BUILDING GEM
223
230
 
@@ -241,6 +248,12 @@ mv gem-public_cert.pem net-ssh-public_cert.pem
241
248
  gem cert --add net-ssh-public_cert.pem
242
249
  ```
243
250
 
251
+ or `rake cert:update_public_when_expired`
252
+
253
+ ## Security contact information
254
+
255
+ See [SECURITY.md](SECURITY.md)
256
+
244
257
  ## CREDITS
245
258
 
246
259
  ### Contributors
@@ -261,6 +274,9 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
261
274
 
262
275
  [![Sponsor](https://opencollective.com/net-ssh/sponsor/0/avatar.svg)](https://opencollective.com/net-ssh/sponsor/0/website)
263
276
 
277
+ [<img src="https://github.com/net-ssh/net-ssh/assets/52435/9690bf3e-34ea-4c52-8aea-1cc4cb5bcb6d" width="320">](https://ubicloud.com)
278
+
279
+
264
280
  ## LICENSE:
265
281
 
266
282
  (The MIT License)
data/Rakefile CHANGED
@@ -48,12 +48,100 @@ namespace :cert do
48
48
  raw = File.read "net-ssh-public_cert.pem"
49
49
  certificate = OpenSSL::X509::Certificate.new raw
50
50
  raise Exception, "Not yet expired: #{certificate.not_after}" unless certificate.not_after < Time.now
51
+
51
52
  sh "gem cert --build netssh@solutious.com --days 365*5 --private-key /mnt/gem/net-ssh-private_key.pem"
52
53
  sh "mv gem-public_cert.pem net-ssh-public_cert.pem"
53
54
  sh "gem cert --add net-ssh-public_cert.pem"
54
55
  end
55
56
  end
56
57
 
58
+ def change_version(&block)
59
+ version_file = 'lib/net/ssh/version.rb'
60
+ require_relative version_file
61
+ pre = Net::SSH::Version::PRE
62
+ tiny = Net::SSH::Version::TINY
63
+ result = block[pre: pre, tiny: Net::SSH::Version::TINY]
64
+ raise ArgumentError, "Version change logic should always return a pre" unless result.key?(:pre)
65
+
66
+ new_pre = result[:pre]
67
+ new_tiny = result[:tiny] || tiny
68
+ found = { pre: false, tiny: false }
69
+ File.open("#{version_file}.new", "w") do |f|
70
+ File.readlines(version_file).each do |line|
71
+ match =
72
+ if pre.nil?
73
+ /^(\s+PRE\s+=\s+)nil(\s*)$/.match(line)
74
+ else
75
+ /^(\s+PRE\s+=\s+")#{pre}("\s*)$/.match(line)
76
+ end
77
+ if match
78
+ prefix = match[1]
79
+ postfix = match[2]
80
+ prefix.delete_suffix!('"')
81
+ postfix.delete_prefix!('"')
82
+ new_line = "#{prefix}#{new_pre.inspect}#{postfix}"
83
+ puts "Changing:\n - #{line} + #{new_line}"
84
+ line = new_line
85
+ found[:pre] = true
86
+ end
87
+
88
+ if new_tiny != tiny
89
+ match = /^(\s+TINY\s+=\s+)#{tiny}(\s*)$/.match(line)
90
+ if match
91
+ prefix = match[1]
92
+ postfix = match[2]
93
+ new_line = "#{prefix}#{new_tiny}#{postfix}"
94
+ puts "Changing:\n - #{line} + #{new_line}"
95
+ line = new_line
96
+ found[:tiny] = true
97
+ end
98
+ end
99
+
100
+ f.write(line)
101
+ end
102
+ raise ArgumentError, "Cound not find line: PRE = \"#{pre}\" in #{version_file}" unless found[:pre]
103
+ raise ArgumentError, "Cound not find line: TINY = \"#{tiny}\" in #{version_file}" unless found[:tiny] || new_tiny == tiny
104
+ end
105
+
106
+ FileUtils.mv version_file, "#{version_file}.old"
107
+ FileUtils.mv "#{version_file}.new", version_file
108
+ end
109
+
110
+ namespace :vbump do
111
+ desc "Final release"
112
+ task :final do
113
+ change_version do |pre:, tiny:|
114
+ _ = tiny
115
+ if pre.nil?
116
+ { tiny: tiny + 1, pre: nil }
117
+ else
118
+ raise ArgumentError, "Unexpected pre: #{pre}" if pre.nil?
119
+
120
+ { pre: nil }
121
+ end
122
+ end
123
+ end
124
+
125
+ desc "Increment prerelease"
126
+ task :pre, [:type] do |_t, args|
127
+ change_version do |pre:, tiny:|
128
+ puts " PRE => #{pre.inspect}"
129
+ match = /^([a-z]+)(\d+)/.match(pre)
130
+ raise ArgumentError, "Unexpected pre: #{pre}" if match.nil? && args[:type].nil?
131
+
132
+ if match.nil? || (!args[:type].nil? && args[:type] != match[1])
133
+ if pre.nil?
134
+ { pre: "#{args[:type]}1", tiny: tiny + 1 }
135
+ else
136
+ { pre: "#{args[:type]}1" }
137
+ end
138
+ else
139
+ { pre: "#{match[1]}#{match[2].to_i + 1}" }
140
+ end
141
+ end
142
+ end
143
+ end
144
+
57
145
  namespace :rdoc do
58
146
  desc "Update gh-pages branch"
59
147
  task :publish do
@@ -94,6 +182,10 @@ Rake::TestTask.new do |t|
94
182
  t.test_files = test_files
95
183
  end
96
184
 
185
+ # We need to enable the OpenSSL 3.0 legacy providers for our test suite
186
+ require 'openssl'
187
+ ENV['OPENSSL_CONF'] = 'test/openssl3.conf' if OpenSSL::OPENSSL_LIBRARY_VERSION.start_with? "OpenSSL 3"
188
+
97
189
  desc "Run tests of Net::SSH:Test"
98
190
  Rake::TestTask.new do |t|
99
191
  t.name = "test_test"
data/SECURITY.md ADDED
@@ -0,0 +1,4 @@
1
+ ## Security contact information
2
+
3
+ To report a security vulnerability, please use the
4
+ [GitHub private vulnerability reporting feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability).
@@ -0,0 +1,25 @@
1
+ version: '3'
2
+
3
+ services:
4
+ ruby-3.1:
5
+ build:
6
+ context: .
7
+ args:
8
+ RUBY_VERSION: 3.1
9
+ ruby-3.0:
10
+ build:
11
+ context: .
12
+ args:
13
+ RUBY_VERSION: 3.0
14
+ ruby-2.7:
15
+ build:
16
+ context: .
17
+ args:
18
+ RUBY_VERSION: 2.7
19
+ BUNDLERV: "-v 2.2.28"
20
+ ruby-2.6:
21
+ build:
22
+ context: .
23
+ args:
24
+ RUBY_VERSION: 2.6
25
+ BUNDLERV: "-v 2.4.22"
@@ -13,6 +13,7 @@ module Net
13
13
  module Authentication
14
14
  # Class for representing agent-specific errors.
15
15
  class AgentError < Net::SSH::Exception; end
16
+
16
17
  # An exception for indicating that the SSH agent is not available.
17
18
  class AgentNotAvailable < AgentError; end
18
19
 
@@ -39,6 +40,8 @@ module Net
39
40
  SSH2_AGENT_ADD_IDENTITY = 17
40
41
  SSH2_AGENT_REMOVE_IDENTITY = 18
41
42
  SSH2_AGENT_REMOVE_ALL_IDENTITIES = 19
43
+ SSH2_AGENT_LOCK = 22
44
+ SSH2_AGENT_UNLOCK = 23
42
45
  SSH2_AGENT_ADD_ID_CONSTRAINED = 25
43
46
  SSH2_AGENT_FAILURE = 30
44
47
  SSH2_AGENT_VERSION_RESPONSE = 103
@@ -62,7 +65,7 @@ module Net
62
65
 
63
66
  # Instantiates a new agent object, connects to a running SSH agent,
64
67
  # negotiates the agent protocol version, and returns the agent object.
65
- def self.connect(logger=nil, agent_socket_factory = nil, identity_agent = nil)
68
+ def self.connect(logger = nil, agent_socket_factory = nil, identity_agent = nil)
66
69
  agent = new(logger)
67
70
  agent.connect!(agent_socket_factory, identity_agent)
68
71
  agent.negotiate!
@@ -71,7 +74,7 @@ module Net
71
74
 
72
75
  # Creates a new Agent object, using the optional logger instance to
73
76
  # report status.
74
- def initialize(logger=nil)
77
+ def initialize(logger = nil)
75
78
  self.logger = logger
76
79
  end
77
80
 
@@ -85,9 +88,9 @@ module Net
85
88
  if agent_socket_factory
86
89
  agent_socket_factory.call
87
90
  elsif identity_agent
88
- unix_socket_class.open(identity_agent)
91
+ unix_socket_class.open(File.expand_path(identity_agent))
89
92
  elsif ENV['SSH_AUTH_SOCK'] && unix_socket_class
90
- unix_socket_class.open(ENV['SSH_AUTH_SOCK'])
93
+ unix_socket_class.open(File.expand_path(ENV['SSH_AUTH_SOCK']))
91
94
  elsif Gem.win_platform? && RUBY_ENGINE != "jruby"
92
95
  Pageant::Socket.open
93
96
  else
@@ -105,6 +108,7 @@ module Net
105
108
  type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION)
106
109
 
107
110
  raise AgentNotAvailable, "SSH2 agents are not yet supported" if type == SSH2_AGENT_VERSION_RESPONSE
111
+
108
112
  if type == SSH2_AGENT_FAILURE
109
113
  debug { "Unexpected response type==#{type}, this will be ignored" }
110
114
  elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2
@@ -173,7 +177,7 @@ module Net
173
177
 
174
178
  req_type = constraints.empty? ? SSH2_AGENT_ADD_IDENTITY : SSH2_AGENT_ADD_ID_CONSTRAINED
175
179
  type, = send_and_wait(req_type, :string, priv_key.ssh_type, :raw, blob_for_add(priv_key),
176
- :string, comment, :raw, constraints)
180
+ :string, comment, :raw, constraints)
177
181
  raise AgentError, "could not add identity to agent" if type != SSH_AGENT_SUCCESS
178
182
  end
179
183
 
@@ -189,6 +193,18 @@ module Net
189
193
  raise AgentError, "could not remove all identity from agent" if type != SSH_AGENT_SUCCESS
190
194
  end
191
195
 
196
+ # lock the ssh agent with password
197
+ def lock(password)
198
+ type, = send_and_wait(SSH2_AGENT_LOCK, :string, password)
199
+ raise AgentError, "could not lock agent" if type != SSH_AGENT_SUCCESS
200
+ end
201
+
202
+ # unlock the ssh agent with password
203
+ def unlock(password)
204
+ type, = send_and_wait(SSH2_AGENT_UNLOCK, :string, password)
205
+ raise AgentError, "could not unlock agent" if type != SSH_AGENT_SUCCESS
206
+ end
207
+
192
208
  private
193
209
 
194
210
  def unix_socket_class
@@ -235,31 +251,31 @@ module Net
235
251
  case priv_key.ssh_type
236
252
  when /^ssh-dss$/
237
253
  Net::SSH::Buffer.from(:bignum, priv_key.p, :bignum, priv_key.q, :bignum, priv_key.g,
238
- :bignum, priv_key.pub_key, :bignum, priv_key.priv_key).to_s
254
+ :bignum, priv_key.pub_key, :bignum, priv_key.priv_key).to_s
239
255
  when /^ssh-dss-cert-v01@openssh\.com$/
240
256
  Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.priv_key).to_s
241
257
  when /^ecdsa\-sha2\-(\w*)$/
242
258
  curve_name = OpenSSL::PKey::EC::CurveNameAliasInv[priv_key.group.curve_name]
243
259
  Net::SSH::Buffer.from(:string, curve_name, :mstring, priv_key.public_key.to_bn.to_s(2),
244
- :bignum, priv_key.private_key).to_s
260
+ :bignum, priv_key.private_key).to_s
245
261
  when /^ecdsa\-sha2\-(\w*)-cert-v01@openssh\.com$/
246
262
  Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.private_key).to_s
247
263
  when /^ssh-ed25519$/
248
264
  Net::SSH::Buffer.from(:string, priv_key.public_key.verify_key.to_bytes,
249
- :string, priv_key.sign_key.keypair).to_s
265
+ :string, priv_key.sign_key.keypair).to_s
250
266
  when /^ssh-ed25519-cert-v01@openssh\.com$/
251
267
  # Unlike the other certificate types, the public key is included after the certifiate.
252
268
  Net::SSH::Buffer.from(:string, priv_key.to_blob,
253
- :string, priv_key.key.public_key.verify_key.to_bytes,
254
- :string, priv_key.key.sign_key.keypair).to_s
269
+ :string, priv_key.key.public_key.verify_key.to_bytes,
270
+ :string, priv_key.key.sign_key.keypair).to_s
255
271
  when /^ssh-rsa$/
256
272
  # `n` and `e` are reversed compared to the ordering in `OpenSSL::PKey::RSA#to_blob`.
257
273
  Net::SSH::Buffer.from(:bignum, priv_key.n, :bignum, priv_key.e, :bignum, priv_key.d,
258
- :bignum, priv_key.iqmp, :bignum, priv_key.p, :bignum, priv_key.q).to_s
274
+ :bignum, priv_key.iqmp, :bignum, priv_key.p, :bignum, priv_key.q).to_s
259
275
  when /^ssh-rsa-cert-v01@openssh\.com$/
260
276
  Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.d,
261
- :bignum, priv_key.key.iqmp, :bignum, priv_key.key.p,
262
- :bignum, priv_key.key.q).to_s
277
+ :bignum, priv_key.key.iqmp, :bignum, priv_key.key.p,
278
+ :bignum, priv_key.key.q).to_s
263
279
  end
264
280
  end
265
281
  end
@@ -31,12 +31,13 @@ module Net
31
31
  cert.key_id = buffer.read_string
32
32
  cert.valid_principals = buffer.read_buffer.read_all(&:read_string)
33
33
  cert.valid_after = Time.at(buffer.read_int64)
34
-
34
+
35
35
  cert.valid_before = if RUBY_PLATFORM == "java"
36
36
  # 0x20c49ba5e353f7 = 0x7fffffffffffffff/1000, the largest value possible for JRuby
37
37
  # JRuby Time.at multiplies the arg by 1000, and then stores it in a signed long.
38
- # 0x20c49ba5e353f7 = 292278994-08-17 01:12:55 -0600
39
- Time.at([0x20c49ba5e353f7, buffer.read_int64].min)
38
+ # 0x20c49ba2d52500 = 292278993-01-01 00:00:00 +0000
39
+ # JRuby 9.1 does not accept the year 292278994 because of edge cases (https://github.com/JodaOrg/joda-time/issues/190)
40
+ Time.at([0x20c49ba2d52500, buffer.read_int64].min)
40
41
  else
41
42
  Time.at(buffer.read_int64)
42
43
  end
@@ -65,12 +66,12 @@ module Net
65
66
  ).to_s
66
67
  end
67
68
 
68
- def ssh_do_sign(data)
69
- key.ssh_do_sign(data)
69
+ def ssh_do_sign(data, sig_alg = nil)
70
+ key.ssh_do_sign(data, sig_alg)
70
71
  end
71
72
 
72
- def ssh_do_verify(sig, data)
73
- key.ssh_do_verify(sig, data)
73
+ def ssh_do_verify(sig, data, options = {})
74
+ key.ssh_do_verify(sig, data, options)
74
75
  end
75
76
 
76
77
  def to_pem
@@ -82,7 +83,7 @@ module Net
82
83
  end
83
84
 
84
85
  # Signs the certificate with key.
85
- def sign!(key, sign_nonce=nil)
86
+ def sign!(key, sign_nonce = nil)
86
87
  # ssh-keygen uses 32 bytes of nonce.
87
88
  self.nonce = sign_nonce || SecureRandom.random_bytes(32)
88
89
  self.signature_key = key
@@ -93,7 +94,7 @@ module Net
93
94
  self
94
95
  end
95
96
 
96
- def sign(key, sign_nonce=nil)
97
+ def sign(key, sign_nonce = nil)
97
98
  cert = clone
98
99
  cert.sign!(key, sign_nonce)
99
100
  end
@@ -101,8 +102,8 @@ module Net
101
102
  # Checks whether the certificate's signature was signed by signature key.
102
103
  def signature_valid?
103
104
  buffer = Buffer.new(signature)
104
- buffer.read_string # skip signature format
105
- signature_key.ssh_do_verify(buffer.read_string, to_blob_without_signature)
105
+ sig_format = buffer.read_string
106
+ signature_key.ssh_do_verify(buffer.read_string, to_blob_without_signature, host_key: sig_format)
106
107
  end
107
108
 
108
109
  def self.read_options(buffer)
@@ -124,6 +125,7 @@ module Net
124
125
  def self.type_symbol(type)
125
126
  types = { 1 => :user, 2 => :host }
126
127
  raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
128
+
127
129
  types.fetch(type)
128
130
  end
129
131
  private_class_method :type_symbol
@@ -133,6 +135,7 @@ module Net
133
135
  def type_value(type)
134
136
  types = { user: 1, host: 2 }
135
137
  raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
138
+
136
139
  types.fetch(type)
137
140
  end
138
141
 
@@ -1,7 +1,6 @@
1
1
  module Net
2
2
  module SSH
3
3
  module Authentication
4
-
5
4
  # Describes the constants used by the Net::SSH::Authentication components
6
5
  # of the Net::SSH library. Individual authentication method implemenations
7
6
  # may define yet more constants that are specific to their implementation.