ruby_smb 2.0.5 → 2.0.10

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 (40) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.github/workflows/verify.yml +57 -0
  5. data/README.md +0 -1
  6. data/examples/delete_file.rb +0 -0
  7. data/examples/net_share_enum_all.rb +0 -0
  8. data/examples/pipes.rb +0 -0
  9. data/examples/rename_file.rb +0 -0
  10. data/lib/ruby_smb.rb +3 -2
  11. data/lib/ruby_smb/client.rb +25 -21
  12. data/lib/ruby_smb/client/negotiation.rb +10 -12
  13. data/lib/ruby_smb/compression.rb +7 -0
  14. data/lib/ruby_smb/compression/lznt1.rb +164 -0
  15. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +9 -0
  16. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +10 -0
  17. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +7 -0
  18. data/lib/ruby_smb/dispatcher/socket.rb +1 -1
  19. data/lib/ruby_smb/smb1/file.rb +1 -1
  20. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
  21. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
  22. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
  23. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
  24. data/lib/ruby_smb/smb1/tree.rb +1 -1
  25. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
  26. data/lib/ruby_smb/smb2/tree.rb +1 -1
  27. data/lib/ruby_smb/version.rb +1 -1
  28. data/spec/lib/ruby_smb/client_spec.rb +17 -7
  29. data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
  30. data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -1
  31. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
  32. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
  33. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
  34. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
  35. data/spec/lib/ruby_smb/smb1/tree_spec.rb +4 -4
  36. data/spec/lib/ruby_smb/smb2/tree_spec.rb +5 -5
  37. data/spec/spec_helper.rb +1 -1
  38. metadata +23 -19
  39. metadata.gz.sig +0 -0
  40. data/.travis.yml +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 896580b7c9baf63e5028f31462f29555a8db4e74e85d5e16b451f41336d3be62
4
- data.tar.gz: 534d7f287cd36e68e1a385f5f639ade86a6f1b8b2ca308417ce8f5a66239743e
3
+ metadata.gz: 6a940f63ee744f0a05d22023d31d1712d97f43bb267b186705df9d0f2f7c3f76
4
+ data.tar.gz: cdbf67cbbdda11e5c25c4773d776899664dd6aba252a65d1ebab7426b6e65d7a
5
5
  SHA512:
6
- metadata.gz: 656efd29de839b2eb6ef4cc79aa098ca2570d13795510987ccb9b30a6d0e5ec3d052626c17dcb9a879aab6ca9a9993e0361912dffde303a254f72c0c5e504abc
7
- data.tar.gz: 9c88d2a160ed0dfa16ec3a953f3b91a74b380b4c132e3d681d36bcf2fbd4a6a78f8ac7aa5f29920e739f41dacb74b661b5cbf81750ea78359b893ec044139a80
6
+ metadata.gz: 550932f77f53fc427e0470db3699832bbf29c86fadd823ce8d7589813a0d7cad13dae5573bf0b8e744fdbef1d62cbab6360ee8c189ed63ee6d79f952c58361a3
7
+ data.tar.gz: d5bbb37e144ee6ac920c3b577f22ff11cae9848d75649177ad77d4051a241ce7f7e5df2c1114ba1e4f566eeb2283bdc95aa56be419fbba415e5662afe12221a6
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -0,0 +1,57 @@
1
+ name: Verify
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-16.04
14
+ timeout-minutes: 40
15
+
16
+ strategy:
17
+ fail-fast: true
18
+ matrix:
19
+ ruby:
20
+ - 2.5
21
+ - 2.6
22
+ - 2.7
23
+ - 3.0
24
+ test_cmd:
25
+ - bundle exec rspec
26
+
27
+ env:
28
+ RAILS_ENV: test
29
+
30
+ name: Ruby ${{ matrix.ruby }} - ${{ matrix.test_cmd }}
31
+ steps:
32
+ - name: Checkout code
33
+ uses: actions/checkout@v2
34
+
35
+ - uses: actions/setup-ruby@v1
36
+ with:
37
+ ruby-version: ${{ matrix.ruby }}
38
+
39
+ - name: Setup bundler
40
+ run: |
41
+ gem install bundler
42
+ - uses: actions/cache@v2
43
+ with:
44
+ path: vendor/bundle
45
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
46
+ restore-keys: |
47
+ ${{ runner.os }}-gems-
48
+ - name: Bundle install
49
+ run: |
50
+ bundle config path vendor/bundle
51
+ bundle install --jobs 4 --retry 3
52
+ - name: ${{ matrix.test_cmd }}
53
+ run: |
54
+ echo "${CMD}"
55
+ bash -c "${CMD}"
56
+ env:
57
+ CMD: ${{ matrix.test_cmd }}
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # RubySMB
2
2
 
3
- [![Build Status](https://travis-ci.org/rapid7/ruby_smb.svg?branch=master)](https://travis-ci.org/rapid7/ruby_smb)
4
3
  [![Code Climate](https://codeclimate.com/github/rapid7/ruby_smb.png)](https://codeclimate.com/github/rapid7/ruby_smb)
5
4
  [![Coverage Status](https://coveralls.io/repos/github/rapid7/ruby_smb/badge.svg?branch=master)](https://coveralls.io/github/rapid7/ruby_smb?branch=master)
6
5
 
File without changes
File without changes
data/examples/pipes.rb CHANGED
File without changes
File without changes
data/lib/ruby_smb.rb CHANGED
@@ -8,8 +8,8 @@ require 'windows_error'
8
8
  require 'windows_error/nt_status'
9
9
  # A packet parsing and manipulation library for the SMB1 and SMB2 protocols
10
10
  #
11
- # [[MS-SMB] Server Mesage Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
- # [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
11
+ # [[MS-SMB] Server Message Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
+ # [[MS-SMB2] Server Message Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
13
13
  module RubySMB
14
14
  require 'ruby_smb/error'
15
15
  require 'ruby_smb/dispositions'
@@ -26,4 +26,5 @@ module RubySMB
26
26
  require 'ruby_smb/smb1'
27
27
  require 'ruby_smb/client'
28
28
  require 'ruby_smb/crypto'
29
+ require 'ruby_smb/compression'
29
30
  end
@@ -277,7 +277,8 @@ module RubySMB
277
277
  # @param smb1 [Boolean] whether or not to enable SMB1 support
278
278
  # @param smb2 [Boolean] whether or not to enable SMB2 support
279
279
  # @param smb3 [Boolean] whether or not to enable SMB3 support
280
- def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.', local_workstation: 'WORKSTATION', always_encrypt: true)
280
+ def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.',
281
+ local_workstation: 'WORKSTATION', always_encrypt: true, ntlm_flags: default_flags)
281
282
  raise ArgumentError, 'No Dispatcher provided' unless dispatcher.is_a? RubySMB::Dispatcher::Base
282
283
  if smb1 == false && smb2 == false && smb3 == false
283
284
  raise ArgumentError, 'You must enable at least one Protocol'
@@ -296,7 +297,7 @@ module RubySMB
296
297
  @smb3 = smb3
297
298
  @username = username.encode('utf-8') || ''.encode('utf-8')
298
299
  @max_buffer_size = MAX_BUFFER_SIZE
299
- # These sizes will be modifed during negotiation
300
+ # These sizes will be modified during negotiation
300
301
  @server_max_buffer_size = SERVER_MAX_BUFFER_SIZE
301
302
  @server_max_read_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
302
303
  @server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
@@ -306,18 +307,12 @@ module RubySMB
306
307
  # SMB 3.x options
307
308
  @session_encrypt_data = always_encrypt
308
309
 
309
- negotiate_version_flag = 0x02000000
310
- flags = Net::NTLM::Client::DEFAULT_FLAGS |
311
- Net::NTLM::FLAGS[:TARGET_INFO] |
312
- negotiate_version_flag ^
313
- Net::NTLM::FLAGS[:OEM]
314
-
315
310
  @ntlm_client = Net::NTLM::Client.new(
316
311
  @username,
317
312
  @password,
318
313
  workstation: @local_workstation,
319
314
  domain: @domain,
320
- flags: flags
315
+ flags: ntlm_flags
321
316
  )
322
317
 
323
318
  @tree_connects = []
@@ -368,31 +363,28 @@ module RubySMB
368
363
 
369
364
  # Performs protocol negotiation and session setup. It defaults to using
370
365
  # the credentials supplied during initialization, but can take a new set of credentials if needed.
371
- def login(username: self.username, password: self.password, domain: self.domain, local_workstation: self.local_workstation)
366
+ def login(username: self.username, password: self.password,
367
+ domain: self.domain, local_workstation: self.local_workstation,
368
+ ntlm_flags: default_flags)
372
369
  negotiate
373
- session_setup(username, password, domain, true,
374
- local_workstation: local_workstation)
370
+ session_setup(username, password, domain,
371
+ local_workstation: local_workstation,
372
+ ntlm_flags: ntlm_flags)
375
373
  end
376
374
 
377
375
  def session_setup(user, pass, domain, do_recv=true,
378
- local_workstation: self.local_workstation)
376
+ local_workstation: self.local_workstation, ntlm_flags: default_flags)
379
377
  @domain = domain
380
378
  @local_workstation = local_workstation
381
379
  @password = pass.encode('utf-8') || ''.encode('utf-8')
382
380
  @username = user.encode('utf-8') || ''.encode('utf-8')
383
381
 
384
- negotiate_version_flag = 0x02000000
385
- flags = Net::NTLM::Client::DEFAULT_FLAGS |
386
- Net::NTLM::FLAGS[:TARGET_INFO] |
387
- negotiate_version_flag ^
388
- Net::NTLM::FLAGS[:OEM]
389
-
390
382
  @ntlm_client = Net::NTLM::Client.new(
391
383
  @username,
392
384
  @password,
393
385
  workstation: @local_workstation,
394
386
  domain: @domain,
395
- flags: flags
387
+ flags: ntlm_flags
396
388
  )
397
389
 
398
390
  authenticate
@@ -431,7 +423,7 @@ module RubySMB
431
423
  end
432
424
 
433
425
  # Sends a packet and receives the raw response through the Dispatcher.
434
- # It will also sign the packet if neccessary.
426
+ # It will also sign the packet if necessary.
435
427
  #
436
428
  # @param packet [RubySMB::GenericPacket] the request to be sent
437
429
  # @param encrypt [Boolean] true if encryption has to be enabled for this transaction
@@ -654,5 +646,17 @@ module RubySMB
654
646
  @preauth_integrity_hash_value + data.to_binary_s
655
647
  )
656
648
  end
649
+
650
+ private
651
+
652
+ def default_flags
653
+ negotiate_version_flag = 0x02000000
654
+ flags = Net::NTLM::Client::DEFAULT_FLAGS |
655
+ Net::NTLM::FLAGS[:TARGET_INFO] |
656
+ negotiate_version_flag ^
657
+ Net::NTLM::FLAGS[:OEM]
658
+
659
+ flags
660
+ end
657
661
  end
658
662
  end
@@ -57,15 +57,20 @@ module RubySMB
57
57
 
58
58
  # Takes the raw response data from the server and tries
59
59
  # parse it into a valid Response packet object.
60
- # This method currently assumes that all SMB1 will use Extended Security.
61
60
  #
62
61
  # @param raw_data [String] the raw binary response from the server
63
62
  # @return [RubySMB::SMB1::Packet::NegotiateResponseExtended] when the response is an SMB1 Extended Security Negotiate Response Packet
63
+ # @return [RubySMB::SMB1::Packet::NegotiateResponse] when the response is an SMB1 Negotiate Response Packet
64
64
  # @return [RubySMB::SMB2::Packet::NegotiateResponse] when the response is an SMB2 Negotiate Response Packet
65
65
  def negotiate_response(raw_data)
66
66
  response = nil
67
67
  if smb1
68
68
  packet = RubySMB::SMB1::Packet::NegotiateResponseExtended.read raw_data
69
+
70
+ unless packet.valid?
71
+ packet = RubySMB::SMB1::Packet::NegotiateResponse.read raw_data
72
+ end
73
+
69
74
  response = packet if packet.valid?
70
75
  end
71
76
  if (smb2 || smb3) && response.nil?
@@ -74,17 +79,10 @@ module RubySMB
74
79
  end
75
80
  if response.nil?
76
81
  if packet.packet_smb_version == 'SMB1'
77
- extended_security = if packet.is_a? RubySMB::SMB1::Packet::NegotiateResponseExtended
78
- packet.parameter_block.capabilities.extended_security
79
- else
80
- "n/a"
81
- end
82
82
  raise RubySMB::Error::InvalidPacket.new(
83
83
  expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
84
- expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
85
- expected_custom: "extended_security=1",
86
- packet: packet,
87
- received_custom: "extended_security=#{extended_security}"
84
+ expected_cmd: RubySMB::SMB1::Packet::NegotiateResponse::COMMAND,
85
+ packet: packet
88
86
  )
89
87
  elsif packet.packet_smb_version == 'SMB2'
90
88
  raise RubySMB::Error::InvalidPacket.new(
@@ -275,8 +273,8 @@ module RubySMB
275
273
  context_type: RubySMB::SMB2::NegotiateContext::SMB2_COMPRESSION_CAPABILITIES
276
274
  )
277
275
  # Adding all possible compression algorithm even if we don't support
278
- # them yet. This will force the server to disclose the support
279
- # algorithms in the repsonse.
276
+ # them yet. This will force the server to disclose the supported
277
+ # algorithms in the response.
280
278
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZNT1
281
279
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZ77
282
280
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZ77_Huffman
@@ -0,0 +1,7 @@
1
+ module RubySMB
2
+ module Compression
3
+
4
+ require 'ruby_smb/compression/lznt1'
5
+
6
+ end
7
+ end
@@ -0,0 +1,164 @@
1
+ module RubySMB
2
+ module Compression
3
+ module LZNT1
4
+ def self.compress(buf, chunk_size: 0x1000)
5
+ out = ''
6
+ until buf.empty?
7
+ chunk = buf[0...chunk_size]
8
+ compressed = compress_chunk(chunk)
9
+ # chunk is compressed
10
+ if compressed.length < chunk.length
11
+ out << [0xb000 | (compressed.length - 1)].pack('v')
12
+ out << compressed
13
+ else
14
+ out << [0x3000 | (chunk.length - 1)].pack('v')
15
+ out << chunk
16
+ end
17
+ buf = buf[chunk_size..-1]
18
+ break if buf.nil?
19
+ end
20
+
21
+ out
22
+ end
23
+
24
+ def self.compress_chunk(chunk)
25
+ blob = chunk
26
+ out = ''
27
+ pow2 = 0x10
28
+ l_mask3 = 0x1002
29
+ o_shift = 12
30
+ until blob.empty?
31
+ bits = 0
32
+ tmp = ''
33
+ i = -1
34
+ loop do
35
+ i += 1
36
+ bits >>= 1
37
+ while pow2 < (chunk.length - blob.length)
38
+ pow2 <<= 1
39
+ l_mask3 = (l_mask3 >> 1) + 1
40
+ o_shift -= 1
41
+ end
42
+
43
+ max_len = [blob.length, l_mask3].min
44
+ offset, length = find(chunk[0...(chunk.length - blob.length)], blob, max_len)
45
+
46
+ # try to find more compressed pattern
47
+ _offset2, length2 = find(chunk[0...chunk.length - blob.length + 1], blob[1..-1], max_len)
48
+
49
+ length = 0 if length < length2
50
+
51
+ if length > 0
52
+ symbol = ((offset - 1) << o_shift) | (length - 3)
53
+ tmp << [symbol].pack('v')
54
+ # set the highest bit
55
+ bits |= 0x80
56
+ blob = blob[length..-1]
57
+ else
58
+ tmp += blob[0]
59
+ blob = blob[1..-1]
60
+ end
61
+
62
+ break if blob.empty? || i == 7
63
+ end
64
+
65
+ out << [bits >> (7 - i)].pack('C')
66
+ out << tmp
67
+ end
68
+
69
+ out
70
+ end
71
+
72
+ def self.decompress(buf, length_check: true)
73
+ out = ''
74
+ until buf.empty?
75
+ header = buf.unpack1('v')
76
+ length = (header & 0xfff) + 1
77
+ raise EncodingError, 'invalid chunk length' if length_check && length > (buf.length - 2)
78
+
79
+ chunk = buf[2...length + 2]
80
+ out << if header & 0x8000 == 0
81
+ chunk
82
+ else
83
+ decompress_chunk(chunk)
84
+ end
85
+ buf = buf[length + 2..-1]
86
+ end
87
+
88
+ out
89
+ end
90
+
91
+ def self.decompress_chunk(chunk)
92
+ out = ''
93
+ until chunk.empty?
94
+ flags = chunk[0].unpack1('C')
95
+ chunk = chunk[1..-1]
96
+ 8.times do |i|
97
+ if (flags >> i & 1) == 0
98
+ out << chunk[0]
99
+ chunk = chunk[1..-1]
100
+ else
101
+ flag = chunk.unpack1('v')
102
+ pos = out.length - 1
103
+ l_mask = 0xfff
104
+ o_shift = 12
105
+ while pos >= 0x10
106
+ l_mask >>= 1
107
+ o_shift -= 1
108
+ pos >>= 1
109
+ end
110
+
111
+ length = (flag & l_mask) + 3
112
+ offset = (flag >> o_shift) + 1
113
+
114
+ if length >= offset
115
+ out_offset = out[-offset..-1]
116
+ tmp = out_offset * (0xfff / out_offset.length + 1)
117
+ out << tmp[0...length]
118
+ else
119
+ out << out[-offset..-offset + length - 1]
120
+ end
121
+ chunk = chunk[2..-1]
122
+ end
123
+ break if chunk.empty?
124
+ end
125
+ end
126
+
127
+ out
128
+ end
129
+
130
+ class << self
131
+ private
132
+
133
+ def find(src, target, max_len)
134
+ result_offset = 0
135
+ result_length = 0
136
+ 1.upto(max_len - 1) do |i|
137
+ offset = src.rindex(target[0...i])
138
+ next if offset.nil?
139
+
140
+ tmp_offset = src.length - offset
141
+ tmp_length = i
142
+ if tmp_offset == tmp_length
143
+ src_offset = src[offset..-1]
144
+ tmp = src_offset * (0xfff / src_offset.length + 1)
145
+ i.upto(max_len) do |j|
146
+ offset = tmp.rindex(target[0...j])
147
+ break if offset.nil?
148
+
149
+ tmp_length = j
150
+ end
151
+ end
152
+
153
+ if tmp_length > result_length
154
+ result_offset = tmp_offset
155
+ result_length = tmp_length
156
+ end
157
+ end
158
+
159
+ result_length < 3 ? [0, 0] : [result_offset, result_length]
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -11,10 +11,13 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  logonsrv_handle :primary_name
14
+ string :pad1, length: -> { pad_length(self.primary_name) }
14
15
  ndr_string :account_name
15
16
  netlogon_secure_channel_type :secure_channel_type
17
+ string :pad2, length: -> { pad_length(self.secure_channel_type) }
16
18
  ndr_string :computer_name
17
19
  netlogon_credential :client_credential
20
+ string :pad3, length: -> { pad_length(self.client_credential) }
18
21
  uint32 :flags
19
22
 
20
23
  def initialize_instance
@@ -22,6 +25,12 @@ module RubySMB
22
25
  @opnum = NETR_SERVER_AUTHENTICATE3
23
26
  end
24
27
 
28
+ # Determines the correct length for the padding, so that the next
29
+ # field is 4-byte aligned.
30
+ def pad_length(prev_element)
31
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
32
+ (4 - offset) % 4
33
+ end
25
34
  end
26
35
  end
27
36
  end
@@ -11,9 +11,12 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  logonsrv_handle :primary_name
14
+ string :pad1, length: -> { pad_length(self.primary_name) }
14
15
  ndr_string :account_name
15
16
  netlogon_secure_channel_type :secure_channel_type
17
+ string :pad2, length: -> { pad_length(self.secure_channel_type) }
16
18
  ndr_string :computer_name
19
+ string :pad3, length: -> { pad_length(self.computer_name) }
17
20
  netlogon_authenticator :authenticator
18
21
  ndr_fixed_byte_array :clear_new_password, length: 516 # this is an encrypted NL_TRUST_PASSWORD
19
22
 
@@ -21,6 +24,13 @@ module RubySMB
21
24
  super
22
25
  @opnum = Netlogon::NETR_SERVER_PASSWORD_SET2
23
26
  end
27
+
28
+ # Determines the correct length for the padding, so that the next
29
+ # field is 4-byte aligned.
30
+ def pad_length(prev_element)
31
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
32
+ (4 - offset) % 4
33
+ end
24
34
  end
25
35
  end
26
36
  end
@@ -11,6 +11,7 @@ module RubySMB
11
11
  endian :little
12
12
 
13
13
  logonsrv_handle :primary_name
14
+ string :pad1, length: -> { pad_length(self.primary_name) }
14
15
  ndr_string :computer_name
15
16
  netlogon_credential :client_challenge
16
17
 
@@ -19,6 +20,12 @@ module RubySMB
19
20
  @opnum = NETR_SERVER_REQ_CHALLENGE
20
21
  end
21
22
 
23
+ # Determines the correct length for the padding, so that the next
24
+ # field is 4-byte aligned.
25
+ def pad_length(prev_element)
26
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
27
+ (4 - offset) % 4
28
+ end
22
29
  end
23
30
  end
24
31
  end
@@ -55,7 +55,7 @@ module RubySMB
55
55
 
56
56
  # Read a packet off the wire and parse it into a string
57
57
  #
58
- # @param full_response [Boolean] whether to include the NetBios Session Service header in the repsonse
58
+ # @param full_response [Boolean] whether to include the NetBios Session Service header in the response
59
59
  # @return [String] the raw response (including the NetBios Session Service header if full_response is true)
60
60
  # @raise [RubySMB::Error::NetBiosSessionService] if there's an error reading the first 4 bytes,
61
61
  # which are assumed to be the NetBiosSessionService header.
@@ -301,7 +301,7 @@ module RubySMB
301
301
  passthrough_info_level = RubySMB::Fscc::FileInformation::FILE_RENAME_INFORMATION +
302
302
  RubySMB::Fscc::FileInformation::SMB_INFO_PASSTHROUGH
303
303
  rename_request.data_block.trans2_parameters.information_level = passthrough_info_level
304
- rename_request.data_block.trans2_data.info_level_struct.file_name = new_file_name.encode('utf-16le')
304
+ rename_request.data_block.trans2_data.info_level_struct.file_name = new_file_name
305
305
  set_trans2_params(rename_request)
306
306
  end
307
307
 
@@ -40,7 +40,6 @@ module RubySMB
40
40
 
41
41
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
42
42
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
43
- uint8 :name, label: 'Name', initial_value: 0x00
44
43
  string :pad1, length: -> { pad1_length }
45
44
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
46
45
  string :pad2, length: -> { pad2_length }
@@ -39,7 +39,6 @@ module RubySMB
39
39
 
40
40
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
41
41
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
42
- uint8 :name, label: 'Name', initial_value: 0x00
43
42
  string :pad1, length: -> { pad1_length }
44
43
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
45
44
  string :pad2, length: -> { pad2_length }
@@ -44,8 +44,7 @@ module RubySMB
44
44
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
45
45
  string :pad1, length: -> { pad1_length }
46
46
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
47
- string :pad2, length: -> { pad2_length }
48
- string :trans2_data, label: 'Trans2 Data', length: 0
47
+ # trans2_data: No data is sent by this message.
49
48
  end
50
49
 
51
50
  smb_header :smb_header
@@ -23,23 +23,11 @@ module RubySMB
23
23
  end
24
24
  end
25
25
 
26
- # The Trans2 Data Block for this particular Subcommand
27
- class Trans2Data < BinData::Record
28
-
29
- # Returns the length of the Trans2Data struct
30
- # in number of bytes
31
- def length
32
- do_num_bytes
33
- end
34
- end
35
-
36
26
  # The {RubySMB::SMB1::DataBlock} specific to this packet type.
37
27
  class DataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
38
- uint8 :name, label: 'Name', initial_value: 0x00
39
28
  string :pad1, length: -> { pad1_length }
40
29
  trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
41
- string :pad2, length: -> { pad2_length }
42
- trans2_data :trans2_data, label: 'Trans2 Data'
30
+ # trans2_data: No data is sent by this message.
43
31
  end
44
32
 
45
33
  smb_header :smb_header
@@ -60,7 +60,7 @@ module RubySMB
60
60
  opts = opts.dup
61
61
  opts[:filename] = opts[:filename].dup
62
62
  opts[:filename].prepend('\\') unless opts[:filename].start_with?('\\')
63
- open_file(opts)
63
+ open_file(**opts)
64
64
  end
65
65
 
66
66
  # Open a file on the remote share.
@@ -3,6 +3,9 @@ module RubySMB
3
3
  module Packet
4
4
  # An SMB2 COMPRESSION_TRANSFORM_HEADER Packet as defined in
5
5
  # [2.2.42 SMB2 COMPRESSION_TRANSFORM_HEADER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1d435f21-9a21-4f4c-828e-624a176cf2a0)
6
+ # NOTE: On 2021-04-06 the official documentation split the definition of COMPRESSION_TRANSFORM_HEADER into the following two variants:
7
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_CHAINED
8
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_UNCHAINED
6
9
  class CompressionTransformHeader < BinData::Record
7
10
  endian :little
8
11
 
@@ -11,6 +14,7 @@ module RubySMB
11
14
  uint16 :compression_algorithm, label: 'Compression Algorithm'
12
15
  uint16 :flags, label: 'Flags'
13
16
  uint32 :offset, label: 'Offset / Length'
17
+ array :compressed_data, label: 'Compressed Data', type: :uint8, read_until: :eof
14
18
  end
15
19
 
16
20
  # An SMB2 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD Packet as defined in
@@ -61,7 +61,7 @@ module RubySMB
61
61
  opts = opts.dup
62
62
  opts[:filename] = opts[:filename].dup
63
63
  opts[:filename] = opts[:filename][1..-1] if opts[:filename].start_with? '\\'
64
- open_file(opts)
64
+ open_file(**opts)
65
65
  end
66
66
 
67
67
  def open_file(filename:, attributes: nil, options: nil, disposition: RubySMB::Dispositions::FILE_OPEN,
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '2.0.5'.freeze
2
+ VERSION = '2.0.10'.freeze
3
3
  end
@@ -809,6 +809,18 @@ RSpec.describe RubySMB::Client do
809
809
  smb1_extended_response.to_binary_s
810
810
  }
811
811
 
812
+ let(:smb1_response) {
813
+ packet = RubySMB::SMB1::Packet::NegotiateResponse.new
814
+ smb1_capabilities_dup = smb1_capabilities.dup
815
+ smb1_capabilities_dup[:extended_security] = 0
816
+
817
+ packet.parameter_block.capabilities = smb1_capabilities_dup
818
+ packet
819
+ }
820
+ let(:smb1_response_raw) {
821
+ smb1_response.to_binary_s
822
+ }
823
+
812
824
  let(:smb2_response) { RubySMB::SMB2::Packet::NegotiateResponse.new(dialect_revision: 0x200) }
813
825
  let(:smb3_response) { RubySMB::SMB2::Packet::NegotiateResponse.new(dialect_revision: 0x300) }
814
826
 
@@ -997,10 +1009,14 @@ RSpec.describe RubySMB::Client do
997
1009
 
998
1010
  describe '#negotiate_response' do
999
1011
  context 'with only SMB1' do
1000
- it 'returns a properly formed packet' do
1012
+ it 'returns a properly formed NegotiateResponseExtended packet if extended_security is set as 1' do
1001
1013
  expect(smb1_client.negotiate_response(smb1_extended_response_raw)).to eq smb1_extended_response
1002
1014
  end
1003
1015
 
1016
+ it 'returns a properly formed NegotiateResponse packet if extended_security is set as 0' do
1017
+ expect(smb1_client.negotiate_response(smb1_response_raw)).to eq smb1_response
1018
+ end
1019
+
1004
1020
  it 'raises an exception if the response is not a SMB packet' do
1005
1021
  expect { smb1_client.negotiate_response(random_junk) }.to raise_error(RubySMB::Error::InvalidPacket)
1006
1022
  end
@@ -1015,12 +1031,6 @@ RSpec.describe RubySMB::Client do
1015
1031
  bogus_response.smb_header.command = 0xff
1016
1032
  expect { smb1_client.negotiate_response(bogus_response.to_binary_s) }.to raise_error(RubySMB::Error::InvalidPacket)
1017
1033
  end
1018
-
1019
- it 'considers the response invalid if Extended Security is not enabled' do
1020
- bogus_response = smb1_extended_response
1021
- bogus_response.parameter_block.capabilities.extended_security = 0
1022
- expect { smb1_client.negotiate_response(bogus_response.to_binary_s) }.to raise_error(RubySMB::Error::InvalidPacket)
1023
- end
1024
1034
  end
1025
1035
 
1026
1036
  context 'with only SMB2' do
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Compression::LZNT1 do
4
+ describe '.compress' do
5
+ it 'generates an empty blob when provided an empty blob' do
6
+ expected = "".b
7
+ expect(described_class.compress('')).to eq(expected)
8
+ end
9
+
10
+ it 'generates a compressed blob when provided a string with non-reoccurring characters' do
11
+ expect(described_class.compress('RubySMB')).to eq("\x060RubySMB".b)
12
+ end
13
+
14
+ it 'generates a compressed blob when provided a string of reoccurring characters' do
15
+ expect(described_class.compress("\x01" * 0x200)).to eq("\x03\xB0\x02\x01\xFC\x01".b)
16
+ end
17
+ end
18
+
19
+ describe '.decompress' do
20
+ it 'generates a decompressed blob for a string with non-reoccurring characters' do
21
+ expect(described_class.decompress("\x060RubySMB".b)).to eq('RubySMB')
22
+ end
23
+
24
+ it 'generates a decompressed blob for a string of reoccurring characters' do
25
+ expect(described_class.decompress("\x03\xB0\x02\x01\xFC\x01".b)).to eq("\x01" * 0x200)
26
+ end
27
+
28
+ it 'raises an EncodingError when the length is invalid' do
29
+ expect { described_class.decompress("\x010".b) }.to raise_error(EncodingError)
30
+ end
31
+ end
32
+ end
@@ -473,7 +473,7 @@ RSpec.describe RubySMB::SMB1::File do
473
473
  end
474
474
 
475
475
  it 'sets the File Information #rename_pending field of the packet' do
476
- expect(file.rename_packet(filename).data_block.trans2_data.info_level_struct.file_name).to eq filename.encode('utf-16le').force_encoding('ASCII-8BIT')
476
+ expect(file.rename_packet(filename).data_block.trans2_data.info_level_struct.file_name).to eq filename
477
477
  end
478
478
 
479
479
  it 'sets the Trans2 ParameterBlock fields' do
@@ -32,7 +32,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
32
32
  describe '#data_block' do
33
33
  subject(:data_block) { packet.data_block }
34
34
 
35
- it { is_expected.to respond_to :name }
36
35
  it { is_expected.to respond_to :trans2_parameters }
37
36
  it { is_expected.to respond_to :trans2_data }
38
37
 
@@ -32,7 +32,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
32
32
  describe '#data_block' do
33
33
  subject(:data_block) { packet.data_block }
34
34
 
35
- it { is_expected.to respond_to :name }
36
35
  it { is_expected.to respond_to :trans2_parameters }
37
36
  it { is_expected.to respond_to :trans2_data }
38
37
 
@@ -35,16 +35,11 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::Open2Response do
35
35
  end
36
36
 
37
37
  it { is_expected.to respond_to :trans2_parameters }
38
- it { is_expected.to respond_to :trans2_data }
39
38
 
40
39
  it 'should keep #trans2_parameters 4-byte aligned' do
41
40
  expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
42
41
  end
43
42
 
44
- it 'should keep #trans2_data 4-byte aligned' do
45
- expect(data_block.trans2_data.abs_offset % 4).to eq 0
46
- end
47
-
48
43
  describe '#trans2_parameters' do
49
44
  subject(:parameters) { data_block.trans2_parameters }
50
45
 
@@ -28,18 +28,12 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse do
28
28
  describe '#data_block' do
29
29
  subject(:data_block) { packet.data_block }
30
30
 
31
- it { is_expected.to respond_to :name }
32
31
  it { is_expected.to respond_to :trans2_parameters }
33
- it { is_expected.to respond_to :trans2_data }
34
32
 
35
33
  it 'should keep #trans2_parameters 4-byte aligned' do
36
34
  expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
37
35
  end
38
36
 
39
- it 'should keep #trans2_data 4-byte aligned' do
40
- expect(data_block.trans2_data.abs_offset % 4).to eq 0
41
- end
42
-
43
37
  describe '#trans2_parameters' do
44
38
  subject(:parameters) { data_block.trans2_parameters }
45
39
 
@@ -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
@@ -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/spec/spec_helper.rb CHANGED
@@ -7,7 +7,7 @@ end
7
7
  require 'coveralls'
8
8
  require 'ruby_smb'
9
9
 
10
- if ENV['TRAVIS'] == 'true'
10
+ if ENV['CI'] == 'true'
11
11
  # don't generate local report as it is inaccessible on travis-ci, which is
12
12
  # why coveralls is being used.
13
13
  SimpleCov.formatter = Coveralls::SimpleCov::Formatter
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.5
4
+ version: 2.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -68,20 +68,20 @@ cert_chain:
68
68
  -----END CERTIFICATE-----
69
69
  - |
70
70
  -----BEGIN CERTIFICATE-----
71
- MIIFIzCCBAugAwIBAgIQDX9ZkVJ2eNVTlibR5ALyJTANBgkqhkiG9w0BAQsFADBy
71
+ MIIFIzCCBAugAwIBAgIQCMePMbkSxvnPeJhYXIfaxzANBgkqhkiG9w0BAQsFADBy
72
72
  MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
73
73
  d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg
74
- SUQgQ29kZSBTaWduaW5nIENBMB4XDTE5MTAxNjAwMDAwMFoXDTIwMTAxOTEyMDAw
74
+ SUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTAwNzAwMDAwMFoXDTIzMTEwNjEyMDAw
75
75
  MFowYDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNV
76
76
  BAcTBkJvc3RvbjETMBEGA1UEChMKUmFwaWQ3IExMQzETMBEGA1UEAxMKUmFwaWQ3
77
- IExMQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANHnKegPAghKuZk4
78
- Gy1jKaZEXbWc4fxioTemv/F1yIYzAjCWP65qjKtyeeFDe4/kJzG9nseF9oa93YBf
79
- 1nyEqxNSZMw/sCAZ87lOl713dRi73uxOoszy2PT5xEB+Q5R6cbzExkWG2zrLdXDr
80
- so0Bd6VHw+IsAoBBkAq5FrZOJQYGn5VY20xw/2DqtCeoW4QDWyqTnbJmwO9tZrfr
81
- 3Le2crfk2eOgafaPNhLon5uuIKCZsk2YkUSNURSS3M7gosMwU9Gg4JTBi7X5+oww
82
- rY43dJT28YklxmNVu8o5kJxW4dqLKJLOIgSXZ63nceT/EaCSg7DcofHNcUzejFwb
83
- M7Zbb2kCAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZl
84
- dQ5YMB0GA1UdDgQWBBR18CAeMsIEU+0pXal/XXw9LCtMADAOBgNVHQ8BAf8EBAMC
77
+ IExMQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNTz4zvAy7h/vQp
78
+ 4dr1txXHlABAagkwYYwTMCtHs5PXsJITx/5SAjx5swuaLfze5kPBNF2YImvFlOXY
79
+ WaB+0PsOnXnaARsDZU683xFlj8izU6IN6VrAHzDLKFBzruJENrOJD/ikbEtbjO/q
80
+ gFbmS9J9v5ohG/pcRSS0t4ZPAwymf8eCp6QsvOKK/Aymp1RhlRaP8N6N5CIpkhz1
81
+ 9p968iCE+DjOXVYxcWE+jE/7uB1dbgrXykNBujMSS3GULOvVEY28n6NCmrPlo23g
82
+ yRjYVJ2Vy14nBqnxDZ/yRIfWRVjWoT9TsAEbe9gY29oDpSCSs4wSmLQd5zGCpZ9h
83
+ r0HDFB8CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZl
84
+ dQ5YMB0GA1UdDgQWBBTLBL7DTwumVEKtdCdpHVYMXOFeDzAOBgNVHQ8BAf8EBAMC
85
85
  B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDov
86
86
  L2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGG
87
87
  L2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3Js
@@ -90,14 +90,14 @@ cert_chain:
90
90
  JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcw
91
91
  AoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3Vy
92
92
  ZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEL
93
- BQADggEBAFpzR9s7lcYKDzSJucOHztEPj+iSIeCzxEw34NTE9M2AfkYIu82c4r2a
94
- bzIGmzZWiCGufjOp0gF5xW6sSSJ9n0TqH0nhHhvjtZQkmkGtOBbN1zeYDFS2ozAp
95
- sljF/g68Y1eYs3NaFf7kQUa6vb6RdjW3J8M9AQ8gthBt7gr/guVxd/gJUYbdDdBX
96
- cWfJJi/X7GVBOBmmvA43qoKideuhOBrVGBHvIF/yO9p23dIiUrGmW9kxXCSxgute
97
- JI/W23RbIRksG2pioMhd4dCXq3FLLlkOV1YfCwWixNB+iIhQPPZVaPNfgPhCn4Dt
98
- DeGjje/qA4fkLtRmOtb9PUBq3ToRDE4=
93
+ BQADggEBAN+GL5/myPWg7oH4mVrG7/OhXF1MoYQF0ddaNiqaweEHMuKJBQCVZRbL
94
+ 37HojoKXXv2yyRJBCeTB+ojrxX+5PdLVZa0ss7toWzJ2A1poPXZ1eZvm5xeFD32z
95
+ YQaTmmNWNI3PCDTyJ2PXUc+bDiNNwcZ7yc5o78UNRvp9Jxghya17Q76c9Ov9wvnv
96
+ dxxQKWGOQy0m4fBrkyjAyH9Djjn81RbQrqYgPuhd5nD0HjN3VUQLhQbIJrk9TVs0
97
+ EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
98
+ 9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
99
99
  -----END CERTIFICATE-----
100
- date: 2020-09-21 00:00:00.000000000 Z
100
+ date: 2021-05-28 00:00:00.000000000 Z
101
101
  dependencies:
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: redcarpet
@@ -246,10 +246,10 @@ executables: []
246
246
  extensions: []
247
247
  extra_rdoc_files: []
248
248
  files:
249
+ - ".github/workflows/verify.yml"
249
250
  - ".gitignore"
250
251
  - ".rspec"
251
252
  - ".simplecov"
252
- - ".travis.yml"
253
253
  - ".yardopts"
254
254
  - CONTRIBUTING.md
255
255
  - Gemfile
@@ -284,6 +284,8 @@ files:
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
287
+ - lib/ruby_smb/compression.rb
288
+ - lib/ruby_smb/compression/lznt1.rb
287
289
  - lib/ruby_smb/crypto.rb
288
290
  - lib/ruby_smb/dcerpc.rb
289
291
  - lib/ruby_smb/dcerpc/bind.rb
@@ -526,6 +528,7 @@ files:
526
528
  - lib/ruby_smb/version.rb
527
529
  - ruby_smb.gemspec
528
530
  - spec/lib/ruby_smb/client_spec.rb
531
+ - spec/lib/ruby_smb/compression/lznt1_spec.rb
529
532
  - spec/lib/ruby_smb/crypto_spec.rb
530
533
  - spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb
531
534
  - spec/lib/ruby_smb/dcerpc/bind_spec.rb
@@ -760,6 +763,7 @@ specification_version: 4
760
763
  summary: A pure Ruby implementation of the SMB Protocol Family
761
764
  test_files:
762
765
  - spec/lib/ruby_smb/client_spec.rb
766
+ - spec/lib/ruby_smb/compression/lznt1_spec.rb
763
767
  - spec/lib/ruby_smb/crypto_spec.rb
764
768
  - spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb
765
769
  - spec/lib/ruby_smb/dcerpc/bind_spec.rb
metadata.gz.sig CHANGED
Binary file
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- rvm:
4
- - '2.5.8'
5
- - '2.6.6'
6
- - '2.7.0'