ruby_smb 2.0.5 → 2.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![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
|
|
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
|