ruby_smb 2.0.8 → 2.0.12

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 (45) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +5 -15
  4. data/examples/auth_capture.rb +71 -0
  5. data/lib/ruby_smb/client/negotiation.rb +9 -11
  6. data/lib/ruby_smb/client.rb +30 -25
  7. data/lib/ruby_smb/dialect.rb +45 -0
  8. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  9. data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
  10. data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
  11. data/lib/ruby_smb/gss/provider.rb +35 -0
  12. data/lib/ruby_smb/gss.rb +56 -63
  13. data/lib/ruby_smb/ntlm.rb +45 -0
  14. data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
  15. data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
  16. data/lib/ruby_smb/server/server_client.rb +162 -0
  17. data/lib/ruby_smb/server.rb +54 -0
  18. data/lib/ruby_smb/signing.rb +59 -0
  19. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
  20. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
  21. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  22. data/lib/ruby_smb/smb1/tree.rb +1 -1
  23. data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
  24. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
  25. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
  26. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
  27. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
  28. data/lib/ruby_smb/smb2/tree.rb +1 -1
  29. data/lib/ruby_smb/smb2.rb +3 -1
  30. data/lib/ruby_smb/version.rb +1 -1
  31. data/lib/ruby_smb.rb +2 -1
  32. data/spec/lib/ruby_smb/client_spec.rb +24 -16
  33. data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
  34. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
  35. data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
  36. data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
  37. data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
  38. data/spec/lib/ruby_smb/server_spec.rb +32 -0
  39. data/spec/lib/ruby_smb/smb1/tree_spec.rb +4 -4
  40. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
  41. data/spec/lib/ruby_smb/smb2/tree_spec.rb +5 -5
  42. data.tar.gz.sig +0 -0
  43. metadata +25 -3
  44. metadata.gz.sig +0 -0
  45. data/lib/ruby_smb/client/signing.rb +0 -64
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::Account do
2
+ let(:username) { 'RubySMB' }
3
+ let(:password) { 'password' }
4
+ let(:domain) { 'WORKGROUP' }
5
+ subject(:account) { RubySMB::Gss::Provider::NTLM::Account.new(username, password, domain) }
6
+
7
+ it { is_expected.to respond_to :username }
8
+ it { is_expected.to respond_to :password }
9
+ it { is_expected.to respond_to :domain }
10
+
11
+ it 'sets the username correct' do
12
+ expect(account.username).to eq username
13
+ end
14
+
15
+ it 'sets the password correctly' do
16
+ expect(account.password).to eq password
17
+ end
18
+
19
+ it 'sets the domain correctly' do
20
+ expect(account.domain).to eq domain
21
+ end
22
+
23
+ describe '#to_s' do
24
+ it 'converts to a string' do
25
+ expect(account.to_s).to be_a String
26
+ end
27
+
28
+ it 'formats the username and domain correctly' do
29
+ expect(account.to_s).to eq "#{domain}\\#{username}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,101 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::Authenticator do
2
+ let(:username) { 'RubySMB' }
3
+ let(:domain) { 'WORKGROUP' }
4
+ let(:password) { 'password' }
5
+ let(:provider) { RubySMB::Gss::Provider::NTLM.new.tap { |provider| provider.put_account(username, password, domain: domain) } }
6
+ let(:authenticator) { described_class.new(provider, nil) }
7
+ let(:type1_msg) do
8
+ Net::NTLM::Message::Type1.new.tap do |msg|
9
+ msg.domain = domain
10
+ end
11
+ end
12
+ let(:type3_msg) do
13
+ Net::NTLM::Message::Type2.new.response(user: username, password: '', domain: domain)
14
+ end
15
+
16
+ describe '#initialize' do
17
+ it 'defaults to a null session key' do
18
+ expect(authenticator.session_key).to be_nil
19
+ end
20
+
21
+ it 'defaults to a null server challenge' do
22
+ expect(authenticator.server_challenge).to be_nil
23
+ end
24
+ end
25
+
26
+ describe '#process' do
27
+ it 'should handle an empty GSS buffer' do
28
+ result = authenticator.process
29
+ expect(result).to be_a RubySMB::Gss::Provider::Result
30
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
31
+ expect(result.buffer).to_not be_empty
32
+ expect(result.identity).to be_nil
33
+ end
34
+
35
+ it 'should handle an embedded NTLM type 1 message' do
36
+ expect(authenticator).to receive(:process_ntlm_type1).and_call_original
37
+ result = authenticator.process(RubySMB::Gss.gss_type1(type1_msg.serialize))
38
+ expect(result).to be_a RubySMB::Gss::Provider::Result
39
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED
40
+ expect(result.buffer).to_not be_empty
41
+ expect(result.identity).to be_nil
42
+ expect(authenticator.session_key).to be_nil
43
+ end
44
+
45
+ it 'should handle an embedded NTLM type 3 message' do
46
+ authenticator.server_challenge = Random.new.bytes(8)
47
+ expect(authenticator).to receive(:process_ntlm_type3).and_call_original
48
+ result = authenticator.process(RubySMB::Gss.gss_type3(type3_msg.serialize))
49
+ expect(result).to be_a RubySMB::Gss::Provider::Result
50
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
51
+ expect(result.buffer).to be_nil
52
+ expect(result.identity).to be_nil
53
+ expect(authenticator.session_key).to be_nil
54
+ end
55
+ end
56
+
57
+ describe '#process_ntlm_type1' do
58
+ it 'should process a NTLM type 1 message and return a type2 message' do
59
+ expect(authenticator.process_ntlm_type1(type1_msg)).to be_a Net::NTLM::Message::Type2
60
+ end
61
+ end
62
+
63
+ describe '#process_ntlm_type3' do
64
+ it 'should process a NTLM type 3 message and return an error code' do
65
+ expect(authenticator.process_ntlm_type3(type3_msg)).to be_a WindowsError::ErrorCode
66
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
67
+ end
68
+ end
69
+
70
+ describe '#reset!' do
71
+ it 'should clear the server challenge' do
72
+ authenticator.instance_variable_set(:@server_challenge, Random.new.bytes(8))
73
+ authenticator.reset!
74
+ expect(authenticator.instance_variable_get(:@server_challenge)).to be_nil
75
+ end
76
+
77
+ it 'should clear the session key' do
78
+ authenticator.instance_variable_set(:@session_key, Random.new.bytes(16))
79
+ authenticator.reset!
80
+ expect(authenticator.instance_variable_get(:@session_key)).to be_nil
81
+ end
82
+ end
83
+
84
+ describe 'a full Net-NTLMv2 authentication exchange' do
85
+ let(:type2_msg) { authenticator.process_ntlm_type1(type1_msg)}
86
+
87
+ it 'should respond to a correct password with STATUS_SUCCESS' do
88
+ type3_msg = type2_msg.response({user: username, domain: domain, password: password}, ntlmv2: true)
89
+ type3_msg.user.force_encoding('UTF-16LE')
90
+ type3_msg.domain.force_encoding('UTF-16LE')
91
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_SUCCESS
92
+ end
93
+
94
+ it 'should respond to an incorrect password with STATUS_LOGON_FAILURE' do
95
+ type3_msg = type2_msg.response({user: username, domain: domain, password: password + rand(0x41..0x5b).chr}, ntlmv2: true)
96
+ type3_msg.user.force_encoding('UTF-16LE')
97
+ type3_msg.domain.force_encoding('UTF-16LE')
98
+ expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Gss::Provider::NTLM::OSVersion do
2
+ subject(:os_version) { RubySMB::Gss::Provider::NTLM::OSVersion.new }
3
+
4
+ it { is_expected.to respond_to :major }
5
+ it { is_expected.to respond_to :minor }
6
+ it { is_expected.to respond_to :build }
7
+ it { is_expected.to respond_to :ntlm_revision }
8
+
9
+ describe '#initialize' do
10
+ it 'defaults to an NTLM revision of 15' do
11
+ expect(os_version.ntlm_revision).to eq 15
12
+ end
13
+ end
14
+
15
+ describe '#read' do
16
+ it 'reads a packed version correctly' do
17
+ # Version 6.1 (Build 7601); NTLM Current Revision 15
18
+ os_version = RubySMB::Gss::Provider::NTLM::OSVersion.read("\x06\x01\x1d\xb1\x00\x00\x00\x0f")
19
+ expect(os_version.major).to eq 6
20
+ expect(os_version.minor).to eq 1
21
+ expect(os_version.build).to eq 7601
22
+ expect(os_version.ntlm_revision).to eq 15
23
+ end
24
+ end
25
+
26
+ describe '#to_s' do
27
+ it 'creates a string representation of the OS version' do
28
+ expect(os_version.to_s).to be_a String
29
+ expect(os_version.to_s).to match /Version \d+\.\d+ \(Build \d+\); NTLM Current Revision \d+/
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Gss::Provider::NTLM do
4
+ let(:provider) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :allow_anonymous }
7
+ it { is_expected.to respond_to :default_domain }
8
+
9
+ describe '#initialize' do
10
+ it 'defaults to false for allowing anonymous access' do
11
+ expect(provider.allow_anonymous).to be false
12
+ end
13
+
14
+ it 'defaults to a default domain of WORKGROUP' do
15
+ expect(provider.default_domain).to eq 'WORKGROUP'
16
+ end
17
+
18
+ it 'defaults to a random challenge generator' do
19
+ expect(provider.generate_server_challenge).to_not eq provider.generate_server_challenge
20
+ end
21
+ end
22
+
23
+ describe '#generate_server_challenge' do
24
+ it 'generates a valid 8-byte challenge' do
25
+ challenge = provider.generate_server_challenge
26
+ expect(challenge).to be_a String
27
+ expect(challenge.length).to eq 8
28
+ end
29
+
30
+ it 'should take a generator block' do
31
+ random_challenge = Random.new.bytes(8)
32
+ provider.generate_server_challenge do
33
+ random_challenge
34
+ end
35
+ expect(provider.generate_server_challenge).to eq random_challenge
36
+ end
37
+ end
38
+
39
+ describe '#get_account' do
40
+ let(:username) { 'RubySMB' }
41
+ let(:password) { 'password' }
42
+ let(:domain) { 'WORKGROUP' }
43
+
44
+ context 'when getting accounts' do
45
+ before(:each) do
46
+ provider.put_account(username, password)
47
+ end
48
+
49
+ it 'should return nil for an unknown account' do
50
+ account = provider.get_account('Spencer')
51
+ expect(account).to be_nil
52
+ end
53
+
54
+ it 'should work with a case sensitive name' do
55
+ account = provider.get_account(username)
56
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
57
+ expect(account.username).to eq username
58
+ end
59
+
60
+ it 'should work with a case insensitive name' do
61
+ account = provider.get_account(username.downcase)
62
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
63
+ expect(account.username).to eq username
64
+ end
65
+
66
+ it 'should work with a case sensitive domain' do
67
+ account = provider.get_account(username, domain: domain)
68
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
69
+ expect(account.domain).to eq domain
70
+ end
71
+
72
+ it 'should work with a case insensitive domain' do
73
+ account = provider.get_account(username, domain: domain.downcase)
74
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
75
+ expect(account.domain).to eq domain
76
+ end
77
+
78
+ it 'should work with the special . domain' do
79
+ account = provider.get_account(username, domain: '.')
80
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
81
+ expect(account.domain).to eq domain
82
+ end
83
+
84
+ # UTF-16LE is optionally used for encoding some Net-NTLM message fields, the #get_account method should handle it
85
+ # transparently
86
+ it 'should work with a UTF16-LE name' do
87
+ account = provider.get_account(username.encode('UTF-16LE'))
88
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
89
+ expect(account.username).to eq username
90
+ end
91
+
92
+ it 'should work with a UTF16-LE domain' do
93
+ account = provider.get_account(username, domain: domain.encode('UTF-16LE'))
94
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
95
+ expect(account.domain).to eq domain
96
+ end
97
+ end
98
+
99
+ context 'when putting accounts' do
100
+ it 'should accept new accounts with the default domain' do
101
+ provider.put_account(username, password)
102
+ end
103
+
104
+ after(:each) do
105
+ account = provider.get_account(username, domain: domain)
106
+ expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
107
+ expect(account.username).to eq username
108
+ expect(account.password).to eq password
109
+ expect(account.domain).to eq domain
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,156 @@
1
+ RSpec.describe RubySMB::Server::ServerClient do
2
+ let(:server) { RubySMB::Server.new(server_sock: ::TCPServer.new(0)) }
3
+ let(:sock) { double('Socket', peeraddr: '192.168.1.5') }
4
+ let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
5
+ subject(:server_client) { described_class.new(server, dispatcher) }
6
+
7
+ it { is_expected.to respond_to :dialect }
8
+ it { is_expected.to respond_to :identity }
9
+ it { is_expected.to respond_to :state }
10
+ it { is_expected.to respond_to :session_key }
11
+
12
+ describe '#disconnect!' do
13
+ it 'closes the socket' do
14
+ expect(dispatcher.tcp_socket).to receive(:close).with(no_args).and_return(nil)
15
+ server_client.disconnect!
16
+ end
17
+ end
18
+
19
+ describe '#initialize' do
20
+ it 'starts in the negotiate state' do
21
+ expect(server_client.state).to eq :negotiate
22
+ end
23
+
24
+ it 'starts without a dialect' do
25
+ expect(server_client.dialect).to be_nil
26
+ expect(server_client.metadialect).to be_nil
27
+ end
28
+
29
+ it 'starts without an identity' do
30
+ expect(server_client.identity).to be_nil
31
+ end
32
+
33
+ it 'starts without a session_key' do
34
+ expect(server_client.session_key).to be_nil
35
+ end
36
+
37
+ it 'creates a new authenticator instance' do
38
+ expect(server.gss_provider).to receive(:new_authenticator).and_call_original
39
+ described_class.new(server, dispatcher)
40
+ end
41
+ end
42
+
43
+ describe '#process_gss' do
44
+ before(:each) do
45
+ expect(server_client.instance_eval { @gss_authenticator }).to receive(:process).and_call_original
46
+ end
47
+
48
+ it 'should handle an empty GSS buffer' do
49
+ result = server_client.process_gss
50
+ expect(result).to be_a RubySMB::Gss::Provider::Result
51
+ expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
52
+ expect(result.buffer).to_not be_empty
53
+ expect(result.identity).to be_nil
54
+ end
55
+ end
56
+
57
+ describe '#recv_packet' do
58
+ it 'receives a new packet from the dispatcher' do
59
+ expect(dispatcher).to receive(:recv_packet).with(no_args)
60
+ server_client.recv_packet
61
+ end
62
+ end
63
+
64
+ describe '#run' do
65
+ let(:packet) { Random.new.bytes(16) }
66
+ before(:each) do
67
+ expect(server_client).to receive(:recv_packet).and_return(packet)
68
+ # this hook should ensure that the dispatcher loop returns after processing a single request
69
+ expect(dispatcher.tcp_socket).to receive(:closed?).and_return(true)
70
+ end
71
+
72
+ it 'calls #handle_negotiate when the state is negotiate' do
73
+ expect(server_client).to receive(:handle_negotiate).with(packet).and_return(nil)
74
+ server_client.instance_eval { @state = :negotiate }
75
+ server_client.run
76
+ end
77
+
78
+ it 'calls #handle_session_setup when the state is session_setup' do
79
+ expect(server_client).to receive(:handle_session_setup).with(packet).and_return(nil)
80
+ server_client.instance_eval { @state = :session_setup }
81
+ server_client.run
82
+ end
83
+
84
+ it 'calls #authenticated when the state is authenticated' do
85
+ expect(server_client).to receive(:handle_authenticated).with(packet).and_return(nil)
86
+ server_client.instance_eval { @state = :authenticated }
87
+ server_client.run
88
+ end
89
+ end
90
+
91
+ describe '#send_packet' do
92
+ let(:packet) { RubySMB::GenericPacket.new }
93
+
94
+ before(:each) do
95
+ expect(dispatcher).to receive(:send_packet).with(packet).and_return(nil)
96
+ end
97
+
98
+ it 'sends a packet to the dispatcher' do
99
+ server_client.send_packet(packet)
100
+ end
101
+
102
+ %w{ 0x0202 0x0210 0x0300 0x0302 0x0311 }.each do |dialect|
103
+ context "when the dialect is #{dialect}" do
104
+ before(:each) do
105
+ server_client.instance_eval { @dialect = dialect }
106
+ end
107
+
108
+ context 'and the state is authenticated' do
109
+ before(:each) do
110
+ server_client.instance_eval { @state = :authenticated }
111
+ end
112
+
113
+ context 'and the identity is anonymous' do
114
+ before(:each) do
115
+ server_client.instance_eval { @identity = RubySMB::Gss::Provider::IDENTITY_ANONYMOUS }
116
+ end
117
+
118
+ it 'does not sign packets' do
119
+ expect(server_client).to_not receive(:smb2_sign)
120
+ expect(server_client).to_not receive(:smb3_sign)
121
+ server_client.send_packet(packet)
122
+ end
123
+ end
124
+
125
+ context 'and the identity is not anonymous' do
126
+ before(:each) do
127
+ server_client.instance_eval { @identity = 'WORKGROUP\RubySMB'; @session_key = Random.new.bytes(16) }
128
+ end
129
+
130
+ it 'does sign packets' do
131
+ packet = RubySMB::GenericPacket.new
132
+ dialect_family = RubySMB::Dialect[dialect].family
133
+ if dialect_family == RubySMB::Dialect::FAMILY_SMB2
134
+ expect(server_client).to receive(:smb2_sign).with(packet).and_return(packet)
135
+ expect(server_client).to_not receive(:smb3_sign)
136
+ elsif dialect_family == RubySMB::Dialect::FAMILY_SMB3
137
+ expect(server_client).to receive(:smb3_sign).with(packet).and_return(packet)
138
+ expect(server_client).to_not receive(:smb2_sign)
139
+ end
140
+ server_client.send_packet(packet)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ describe '#update_preauth_hash' do
149
+ it 'raises an EncryptionError exception if the preauth integrity hash algorithm is not known' do
150
+ expect { server_client.update_preauth_hash('Test') }.to raise_error(
151
+ RubySMB::Error::EncryptionError,
152
+ 'Cannot compute the Preauth Integrity Hash value: Preauth Integrity Hash Algorithm is nil'
153
+ )
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.describe RubySMB::Server do
2
+ before(:each) do
3
+ allow(::TCPServer).to receive(:new).and_return(::TCPServer.new(0))
4
+ end
5
+
6
+ it { is_expected.to respond_to :dialects }
7
+ it { is_expected.to respond_to :gss_provider }
8
+ it { is_expected.to respond_to :guid }
9
+
10
+ describe '#initialize' do
11
+ it 'should bind to TCP port 445 by default' do
12
+ expect(::TCPServer).to receive(:new).with(445).and_return(::TCPServer.new(0))
13
+ described_class.new
14
+ end
15
+
16
+ it 'should create a new NTLM GSS provider by default' do
17
+ expect(RubySMB::Gss::Provider::NTLM).to receive(:new).and_call_original
18
+ described_class.new
19
+ end
20
+
21
+ it 'should generate a random 16-byte GUID' do
22
+ server_guid = described_class.new.guid
23
+ expect(server_guid).to be_a String
24
+ expect(server_guid.length).to eq 16
25
+ expect(server_guid).to_not eq described_class.new.guid
26
+ end
27
+
28
+ it 'should support some dialects' do
29
+ expect(described_class.new.dialects).to_not be_empty
30
+ end
31
+ end
32
+ end
@@ -501,16 +501,16 @@ RSpec.describe RubySMB::SMB1::Tree do
501
501
  it 'calls #open_file with the provided options' do
502
502
  opts[:filename] ='\\test'
503
503
  expect(tree).to receive(:open_file).with(opts)
504
- tree.open_pipe(opts)
504
+ tree.open_pipe(**opts)
505
505
  end
506
506
 
507
507
  it 'prepends the filename with \\ if needed' do
508
- expect(tree).to receive(:open_file).with( { filename: '\\test', write: true } )
509
- tree.open_pipe(opts)
508
+ expect(tree).to receive(:open_file).with(filename: '\\test', write: true)
509
+ tree.open_pipe(**opts)
510
510
  end
511
511
 
512
512
  it 'does not modify the original option hash' do
513
- tree.open_pipe(opts)
513
+ tree.open_pipe(**opts)
514
514
  expect(opts).to eq( { filename: 'test', write: true } )
515
515
  end
516
516
  end
@@ -162,7 +162,7 @@ RSpec.describe RubySMB::SMB2::CompressionCapabilities do
162
162
  end
163
163
  end
164
164
 
165
- RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
165
+ RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
166
166
  subject(:capability) { described_class.new }
167
167
 
168
168
  it { is_expected.to respond_to :net_name }
@@ -173,7 +173,7 @@ RSpec.describe RubySMB::SMB2::NetnameNegotiateContextId do
173
173
 
174
174
  describe '#net_name' do
175
175
  it 'is a unicode string' do
176
- expect(capability.net_name).to be_a RubySMB::Field::Stringz16
176
+ expect(capability.net_name).to be_a RubySMB::Field::String16
177
177
  end
178
178
  end
179
179
 
@@ -540,17 +540,17 @@ RSpec.describe RubySMB::SMB2::Tree do
540
540
 
541
541
  it 'calls #open_file with the provided options' do
542
542
  opts[:filename] ='test'
543
- expect(tree).to receive(:open_file).with(opts)
544
- tree.open_pipe(opts)
543
+ expect(tree).to receive(:open_file).with(**opts)
544
+ tree.open_pipe(**opts)
545
545
  end
546
546
 
547
547
  it 'remove the leading \\ from the filename if needed' do
548
- expect(tree).to receive(:open_file).with( { filename: 'test', write: true } )
549
- tree.open_pipe(opts)
548
+ expect(tree).to receive(:open_file).with(filename: 'test', write: true)
549
+ tree.open_pipe(**opts)
550
550
  end
551
551
 
552
552
  it 'does not modify the original option hash' do
553
- tree.open_pipe(opts)
553
+ tree.open_pipe(**opts)
554
554
  expect(opts).to eq( { filename: '\\test', write: true } )
555
555
  end
556
556
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_smb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -97,7 +97,7 @@ cert_chain:
97
97
  EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
98
98
  9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
99
99
  -----END CERTIFICATE-----
100
- date: 2021-04-09 00:00:00.000000000 Z
100
+ date: 2021-12-01 00:00:00.000000000 Z
101
101
  dependencies:
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: redcarpet
@@ -258,6 +258,7 @@ files:
258
258
  - Rakefile
259
259
  - examples/anonymous_auth.rb
260
260
  - examples/append_file.rb
261
+ - examples/auth_capture.rb
261
262
  - examples/authenticate.rb
262
263
  - examples/delete_file.rb
263
264
  - examples/enum_registry_key.rb
@@ -280,7 +281,6 @@ files:
280
281
  - lib/ruby_smb/client/echo.rb
281
282
  - lib/ruby_smb/client/encryption.rb
282
283
  - lib/ruby_smb/client/negotiation.rb
283
- - lib/ruby_smb/client/signing.rb
284
284
  - lib/ruby_smb/client/tree_connect.rb
285
285
  - lib/ruby_smb/client/utils.rb
286
286
  - lib/ruby_smb/client/winreg.rb
@@ -347,6 +347,7 @@ files:
347
347
  - lib/ruby_smb/dcerpc/winreg/regsam.rb
348
348
  - lib/ruby_smb/dcerpc/winreg/save_key_request.rb
349
349
  - lib/ruby_smb/dcerpc/winreg/save_key_response.rb
350
+ - lib/ruby_smb/dialect.rb
350
351
  - lib/ruby_smb/dispatcher.rb
351
352
  - lib/ruby_smb/dispatcher/base.rb
352
353
  - lib/ruby_smb/dispatcher/socket.rb
@@ -381,12 +382,21 @@ files:
381
382
  - lib/ruby_smb/fscc/file_information/file_rename_information.rb
382
383
  - lib/ruby_smb/generic_packet.rb
383
384
  - lib/ruby_smb/gss.rb
385
+ - lib/ruby_smb/gss/provider.rb
386
+ - lib/ruby_smb/gss/provider/authenticator.rb
387
+ - lib/ruby_smb/gss/provider/ntlm.rb
384
388
  - lib/ruby_smb/impersonation_levels.rb
385
389
  - lib/ruby_smb/nbss.rb
386
390
  - lib/ruby_smb/nbss/negative_session_response.rb
387
391
  - lib/ruby_smb/nbss/netbios_name.rb
388
392
  - lib/ruby_smb/nbss/session_header.rb
389
393
  - lib/ruby_smb/nbss/session_request.rb
394
+ - lib/ruby_smb/ntlm.rb
395
+ - lib/ruby_smb/server.rb
396
+ - lib/ruby_smb/server/server_client.rb
397
+ - lib/ruby_smb/server/server_client/negotiation.rb
398
+ - lib/ruby_smb/server/server_client/session_setup.rb
399
+ - lib/ruby_smb/signing.rb
390
400
  - lib/ruby_smb/smb1.rb
391
401
  - lib/ruby_smb/smb1/andx_block.rb
392
402
  - lib/ruby_smb/smb1/bit_field.rb
@@ -613,10 +623,16 @@ files:
613
623
  - spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb
614
624
  - spec/lib/ruby_smb/fscc/fscc_file_attributes_spec.rb
615
625
  - spec/lib/ruby_smb/generic_packet_spec.rb
626
+ - spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb
627
+ - spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb
628
+ - spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb
629
+ - spec/lib/ruby_smb/gss/provider/ntlm_spec.rb
616
630
  - spec/lib/ruby_smb/nbss/negative_session_response_spec.rb
617
631
  - spec/lib/ruby_smb/nbss/netbios_name_spec.rb
618
632
  - spec/lib/ruby_smb/nbss/session_header_spec.rb
619
633
  - spec/lib/ruby_smb/nbss/session_request_spec.rb
634
+ - spec/lib/ruby_smb/server/server_client_spec.rb
635
+ - spec/lib/ruby_smb/server_spec.rb
620
636
  - spec/lib/ruby_smb/smb1/andx_block_spec.rb
621
637
  - spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb
622
638
  - spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb
@@ -848,10 +864,16 @@ test_files:
848
864
  - spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb
849
865
  - spec/lib/ruby_smb/fscc/fscc_file_attributes_spec.rb
850
866
  - spec/lib/ruby_smb/generic_packet_spec.rb
867
+ - spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb
868
+ - spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb
869
+ - spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb
870
+ - spec/lib/ruby_smb/gss/provider/ntlm_spec.rb
851
871
  - spec/lib/ruby_smb/nbss/negative_session_response_spec.rb
852
872
  - spec/lib/ruby_smb/nbss/netbios_name_spec.rb
853
873
  - spec/lib/ruby_smb/nbss/session_header_spec.rb
854
874
  - spec/lib/ruby_smb/nbss/session_request_spec.rb
875
+ - spec/lib/ruby_smb/server/server_client_spec.rb
876
+ - spec/lib/ruby_smb/server_spec.rb
855
877
  - spec/lib/ruby_smb/smb1/andx_block_spec.rb
856
878
  - spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb
857
879
  - spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb
metadata.gz.sig CHANGED
Binary file