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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.github/workflows/verify.yml +57 -0
- data/README.md +0 -1
- data/examples/delete_file.rb +0 -0
- data/examples/net_share_enum_all.rb +0 -0
- data/examples/pipes.rb +0 -0
- data/examples/rename_file.rb +0 -0
- data/lib/ruby_smb.rb +3 -2
- data/lib/ruby_smb/client.rb +25 -21
- data/lib/ruby_smb/client/negotiation.rb +10 -12
- data/lib/ruby_smb/compression.rb +7 -0
- data/lib/ruby_smb/compression/lznt1.rb +164 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +9 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +10 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +7 -0
- data/lib/ruby_smb/dispatcher/socket.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
- data/lib/ruby_smb/smb1/tree.rb +1 -1
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
- data/lib/ruby_smb/smb2/tree.rb +1 -1
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +17 -7
- data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
- data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +4 -4
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +5 -5
- data/spec/spec_helper.rb +1 -1
- metadata +23 -19
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a940f63ee744f0a05d22023d31d1712d97f43bb267b186705df9d0f2f7c3f76
|
4
|
+
data.tar.gz: cdbf67cbbdda11e5c25c4773d776899664dd6aba252a65d1ebab7426b6e65d7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
[](https://travis-ci.org/rapid7/ruby_smb)
|
4
3
|
[](https://codeclimate.com/github/rapid7/ruby_smb)
|
5
4
|
[](https://coveralls.io/github/rapid7/ruby_smb?branch=master)
|
6
5
|
|
data/examples/delete_file.rb
CHANGED
File without changes
|
File without changes
|
data/examples/pipes.rb
CHANGED
File without changes
|
data/examples/rename_file.rb
CHANGED
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
|
12
|
-
# [[MS-SMB2] Server
|
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
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -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: '.',
|
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
|
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:
|
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,
|
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,
|
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:
|
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
|
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::
|
85
|
-
|
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
|
279
|
-
# algorithms in the
|
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,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
|
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.
|
data/lib/ruby_smb/smb1/file.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
data/lib/ruby_smb/smb1/tree.rb
CHANGED
@@ -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
|
data/lib/ruby_smb/smb2/tree.rb
CHANGED
@@ -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,
|
data/lib/ruby_smb/version.rb
CHANGED
@@ -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
|
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(
|
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(
|
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['
|
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.
|
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
|
-
|
71
|
+
MIIFIzCCBAugAwIBAgIQCMePMbkSxvnPeJhYXIfaxzANBgkqhkiG9w0BAQsFADBy
|
72
72
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
73
73
|
d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg
|
74
|
-
|
74
|
+
SUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTAwNzAwMDAwMFoXDTIzMTEwNjEyMDAw
|
75
75
|
MFowYDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNV
|
76
76
|
BAcTBkJvc3RvbjETMBEGA1UEChMKUmFwaWQ3IExMQzETMBEGA1UEAxMKUmFwaWQ3
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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:
|
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
|