ruby_smb 2.0.10 → 2.0.11
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/examples/auth_capture.rb +71 -0
- data/lib/ruby_smb/client/negotiation.rb +1 -1
- data/lib/ruby_smb/client.rb +9 -8
- data/lib/ruby_smb/dialect.rb +45 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
- data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
- data/lib/ruby_smb/gss/provider.rb +35 -0
- data/lib/ruby_smb/gss.rb +56 -63
- data/lib/ruby_smb/ntlm.rb +45 -0
- data/lib/ruby_smb/server/server_client/negotiation.rb +155 -0
- data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
- data/lib/ruby_smb/server/server_client.rb +163 -0
- data/lib/ruby_smb/server.rb +54 -0
- data/lib/ruby_smb/signing.rb +59 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
- data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
- data/lib/ruby_smb/smb2.rb +3 -1
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +2 -1
- data/spec/lib/ruby_smb/client_spec.rb +7 -9
- data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
- data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
- data/spec/lib/ruby_smb/server_spec.rb +32 -0
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +25 -3
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/client/signing.rb +0 -64
@@ -0,0 +1,35 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module Gss
|
3
|
+
#
|
4
|
+
# This module provides GSS based authentication.
|
5
|
+
#
|
6
|
+
module Provider
|
7
|
+
# A special constant implying that the authenticated user is anonymous.
|
8
|
+
IDENTITY_ANONYMOUS = :anonymous
|
9
|
+
# The result of a processed GSS request.
|
10
|
+
Result = Struct.new(:buffer, :nt_status, :identity)
|
11
|
+
|
12
|
+
#
|
13
|
+
# The base class for a GSS authentication provider. This class defines a common interface and is not usable as a
|
14
|
+
# provider on its own.
|
15
|
+
#
|
16
|
+
class Base
|
17
|
+
# Create a new, client-specific authenticator instance. This new instance is then able to track the unique state
|
18
|
+
# of a particular client / connection.
|
19
|
+
#
|
20
|
+
# @param [Server::ServerClient] server_client the client instance that this the authenticator will be for
|
21
|
+
def new_authenticator(server_client)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Whether or not anonymous authentication attempts should be permitted.
|
27
|
+
#
|
28
|
+
attr_accessor :allow_anonymous
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'ruby_smb/gss/provider/authenticator'
|
35
|
+
require 'ruby_smb/gss/provider/ntlm'
|
data/lib/ruby_smb/gss.rb
CHANGED
@@ -2,6 +2,27 @@ module RubySMB
|
|
2
2
|
# module containing methods required for using the [GSS-API](http://www.rfc-editor.org/rfc/rfc2743.txt)
|
3
3
|
# for Secure Protected Negotiation(SPNEGO) in SMB Authentication.
|
4
4
|
module Gss
|
5
|
+
require 'ruby_smb/gss/provider'
|
6
|
+
|
7
|
+
OID_SPNEGO = OpenSSL::ASN1::ObjectId.new('1.3.6.1.5.5.2')
|
8
|
+
OID_NEGOEX = OpenSSL::ASN1::ObjectId.new('1.3.6.1.4.1.311.2.2.30')
|
9
|
+
OID_NTLMSSP = OpenSSL::ASN1::ObjectId.new('1.3.6.1.4.1.311.2.2.10')
|
10
|
+
|
11
|
+
# Allow safe navigation of a decoded ASN.1 data structure. Similar to Ruby's
|
12
|
+
# builtin Hash#dig method but using the #value attribute of each ASN object.
|
13
|
+
#
|
14
|
+
# @param asn The ASN object to apply the traversal path on.
|
15
|
+
# @param [Array] path The path to traverse, each element is passed to the
|
16
|
+
# ASN object's #value's #[] operator.
|
17
|
+
def self.asn1dig(asn, *path)
|
18
|
+
path.each do |part|
|
19
|
+
return nil unless asn&.value
|
20
|
+
asn = asn.value[part]
|
21
|
+
end
|
22
|
+
|
23
|
+
asn
|
24
|
+
end
|
25
|
+
|
5
26
|
# Cargo culted from Rex. Hacked Together ASN1 encoding that works for our GSS purposes
|
6
27
|
# @todo Document these magic numbers
|
7
28
|
def self.asn1encode(str = '')
|
@@ -25,78 +46,50 @@ module RubySMB
|
|
25
46
|
end
|
26
47
|
|
27
48
|
# Create a GSS Security Blob of an NTLM Type 1 Message.
|
28
|
-
# This code has been cargo culted and needs to be researched
|
29
|
-
# and refactored into something better later.
|
30
|
-
# @todo Refactor this into non-magical code
|
31
49
|
def self.gss_type1(type1)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
type1
|
48
|
-
)
|
49
|
-
)
|
50
|
-
)
|
51
|
-
)
|
52
|
-
)
|
50
|
+
OpenSSL::ASN1::ASN1Data.new([
|
51
|
+
OID_SPNEGO,
|
52
|
+
OpenSSL::ASN1::ASN1Data.new([
|
53
|
+
OpenSSL::ASN1::Sequence.new([
|
54
|
+
OpenSSL::ASN1::ASN1Data.new([
|
55
|
+
OpenSSL::ASN1::Sequence.new([
|
56
|
+
OID_NTLMSSP
|
57
|
+
])
|
58
|
+
], 0, :CONTEXT_SPECIFIC),
|
59
|
+
OpenSSL::ASN1::ASN1Data.new([
|
60
|
+
OpenSSL::ASN1::OctetString.new(type1)
|
61
|
+
], 2, :CONTEXT_SPECIFIC)
|
62
|
+
])
|
63
|
+
], 0, :CONTEXT_SPECIFIC)
|
64
|
+
], 0, :APPLICATION).to_der
|
53
65
|
end
|
54
66
|
|
55
67
|
# Create a GSS Security Blob of an NTLM Type 2 Message.
|
56
|
-
# This code has been cargo culted and needs to be researched
|
57
|
-
# and refactored into something better later.
|
58
68
|
def self.gss_type2(type2)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
"\xa2" + asn1encode(
|
73
|
-
"\x04" + asn1encode(
|
74
|
-
type2
|
75
|
-
)
|
76
|
-
)
|
77
|
-
)
|
78
|
-
)
|
79
|
-
|
80
|
-
blob
|
69
|
+
OpenSSL::ASN1::ASN1Data.new([
|
70
|
+
OpenSSL::ASN1::Sequence.new([
|
71
|
+
OpenSSL::ASN1::ASN1Data.new([
|
72
|
+
OpenSSL::ASN1::Enumerated.new(OpenSSL::BN.new(1))
|
73
|
+
], 0, :CONTEXT_SPECIFIC),
|
74
|
+
OpenSSL::ASN1::ASN1Data.new([
|
75
|
+
OID_NTLMSSP
|
76
|
+
], 1, :CONTEXT_SPECIFIC),
|
77
|
+
OpenSSL::ASN1::ASN1Data.new([
|
78
|
+
OpenSSL::ASN1::OctetString.new(type2)
|
79
|
+
], 2, :CONTEXT_SPECIFIC)
|
80
|
+
])
|
81
|
+
], 1, :CONTEXT_SPECIFIC).to_der
|
81
82
|
end
|
82
83
|
|
83
84
|
# Create a GSS Security Blob of an NTLM Type 3 Message.
|
84
|
-
# This code has been cargo culted and needs to be researched
|
85
|
-
# and refactored into something better later.
|
86
|
-
# @todo Refactor this into non-magical code
|
87
85
|
def self.gss_type3(type3)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
)
|
96
|
-
)
|
97
|
-
)
|
98
|
-
|
99
|
-
gss
|
86
|
+
OpenSSL::ASN1::ASN1Data.new([
|
87
|
+
OpenSSL::ASN1::Sequence.new([
|
88
|
+
OpenSSL::ASN1::ASN1Data.new([
|
89
|
+
OpenSSL::ASN1::OctetString.new(type3)
|
90
|
+
], 2, :CONTEXT_SPECIFIC)
|
91
|
+
])
|
92
|
+
], 1, :CONTEXT_SPECIFIC).to_der
|
100
93
|
end
|
101
94
|
end
|
102
95
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module NTLM
|
3
|
+
# [[MS-NLMP] 2.2.2.5](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832)
|
4
|
+
NEGOTIATE_FLAGS = {
|
5
|
+
:UNICODE => 1 << 0,
|
6
|
+
:OEM => 1 << 1,
|
7
|
+
:REQUEST_TARGET => 1 << 2,
|
8
|
+
:SIGN => 1 << 4,
|
9
|
+
:SEAL => 1 << 5,
|
10
|
+
:DATAGRAM => 1 << 6,
|
11
|
+
:LAN_MANAGER_KEY => 1 << 7,
|
12
|
+
:NTLM => 1 << 9,
|
13
|
+
:NT_ONLY => 1 << 10,
|
14
|
+
:ANONYMOUS => 1 << 11,
|
15
|
+
:OEM_DOMAIN_SUPPLIED => 1 << 12,
|
16
|
+
:OEM_WORKSTATION_SUPPLIED => 1 << 13,
|
17
|
+
:ALWAYS_SIGN => 1 << 15,
|
18
|
+
:TARGET_TYPE_DOMAIN => 1 << 16,
|
19
|
+
:TARGET_TYPE_SERVER => 1 << 17,
|
20
|
+
:TARGET_TYPE_SHARE => 1 << 18,
|
21
|
+
:EXTENDED_SECURITY => 1 << 19,
|
22
|
+
:IDENTIFY => 1 << 20,
|
23
|
+
:NON_NT_SESSION => 1 << 22,
|
24
|
+
:TARGET_INFO => 1 << 23,
|
25
|
+
:VERSION_INFO => 1 << 25,
|
26
|
+
:KEY128 => 1 << 29,
|
27
|
+
:KEY_EXCHANGE => 1 << 30,
|
28
|
+
:KEY56 => 1 << 31
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
class OSVersion < BinData::Record
|
32
|
+
endian :big
|
33
|
+
|
34
|
+
uint8 :major
|
35
|
+
uint8 :minor
|
36
|
+
uint16 :build
|
37
|
+
uint32 :ntlm_revision, initial_value: 15
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"Version #{major}.#{minor} (Build #{build}); NTLM Current Revision #{ntlm_revision}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module RubySMB
|
4
|
+
class Server
|
5
|
+
class ServerClient
|
6
|
+
module Negotiation
|
7
|
+
#
|
8
|
+
# Handle an SMB negotiation request. Once negotiation is complete, the state will be updated to :session_setup.
|
9
|
+
# At this point the @dialect will have been set along with other dialect-specific values.
|
10
|
+
#
|
11
|
+
# @param [String] raw_request the negotiation request to process
|
12
|
+
def handle_negotiate(raw_request)
|
13
|
+
response = nil
|
14
|
+
case raw_request[0...4].unpack1('L>')
|
15
|
+
when RubySMB::SMB1::SMB_PROTOCOL_ID
|
16
|
+
request = SMB1::Packet::NegotiateRequest.read(raw_request)
|
17
|
+
response = do_negotiate_smb1(request) if request.is_a?(SMB1::Packet::NegotiateRequest)
|
18
|
+
when RubySMB::SMB2::SMB2_PROTOCOL_ID
|
19
|
+
request = SMB2::Packet::NegotiateRequest.read(raw_request)
|
20
|
+
response = do_negotiate_smb2(request) if request.is_a?(SMB2::Packet::NegotiateRequest)
|
21
|
+
end
|
22
|
+
|
23
|
+
if response.nil?
|
24
|
+
disconnect!
|
25
|
+
else
|
26
|
+
send_packet(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def do_negotiate_smb1(request)
|
33
|
+
client_dialects = request.dialects.map(&:dialect_string).map(&:value)
|
34
|
+
|
35
|
+
if client_dialects.include?(Client::SMB1_DIALECT_SMB2_WILDCARD) && \
|
36
|
+
@server.dialects.any? { |dialect| Dialect[dialect].order == Dialect::ORDER_SMB2 }
|
37
|
+
response = SMB2::Packet::NegotiateResponse.new
|
38
|
+
response.smb2_header.credits = 1
|
39
|
+
response.security_mode.signing_enabled = 1
|
40
|
+
response.dialect_revision = SMB2::SMB2_WILDCARD_REVISION
|
41
|
+
response.server_guid = @server.guid
|
42
|
+
|
43
|
+
response.max_transact_size = 0x800000
|
44
|
+
response.max_read_size = 0x800000
|
45
|
+
response.max_write_size = 0x800000
|
46
|
+
response.system_time.set(Time.now)
|
47
|
+
response.security_buffer_offset = response.security_buffer.abs_offset
|
48
|
+
response.security_buffer = process_gss.buffer
|
49
|
+
return response
|
50
|
+
end
|
51
|
+
|
52
|
+
server_dialects = @server.dialects.select { |dialect| Dialect[dialect].order == Dialect::ORDER_SMB1 }
|
53
|
+
dialect = (server_dialects & client_dialects).first
|
54
|
+
if dialect.nil?
|
55
|
+
# 'NT LM 0.12' is currently the only supported dialect
|
56
|
+
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/80850595-e301-4464-9745-58e4945eb99b
|
57
|
+
response = SMB1::Packet::NegotiateResponse.new
|
58
|
+
response.parameter_block.word_count = 1
|
59
|
+
response.parameter_block.dialect_index = 0xffff
|
60
|
+
response.data_block.byte_count = 0
|
61
|
+
return response
|
62
|
+
end
|
63
|
+
|
64
|
+
response = SMB1::Packet::NegotiateResponseExtended.new
|
65
|
+
response.parameter_block.dialect_index = client_dialects.index(dialect)
|
66
|
+
response.parameter_block.max_mpx_count = 50
|
67
|
+
response.parameter_block.max_number_vcs = 1
|
68
|
+
response.parameter_block.max_buffer_size = 16644
|
69
|
+
response.parameter_block.max_raw_size = 65536
|
70
|
+
server_time = Time.now
|
71
|
+
response.parameter_block.system_time.set(server_time)
|
72
|
+
response.parameter_block.server_time_zone = server_time.utc_offset
|
73
|
+
response.data_block.server_guid = @server.guid
|
74
|
+
response.data_block.security_blob = process_gss.buffer
|
75
|
+
|
76
|
+
@state = :session_setup
|
77
|
+
@dialect = dialect
|
78
|
+
response
|
79
|
+
end
|
80
|
+
|
81
|
+
def do_negotiate_smb2(request)
|
82
|
+
client_dialects = request.dialects.map { |d| "0x%04x" % d }
|
83
|
+
server_dialects = @server.dialects.select { |dialect| Dialect[dialect].order == Dialect::ORDER_SMB2 }
|
84
|
+
dialect = (server_dialects & client_dialects).first
|
85
|
+
|
86
|
+
response = SMB2::Packet::NegotiateResponse.new
|
87
|
+
response.smb2_header.credits = 1
|
88
|
+
response.security_mode.signing_enabled = 1
|
89
|
+
response.server_guid = @server.guid
|
90
|
+
response.max_transact_size = 0x800000
|
91
|
+
response.max_read_size = 0x800000
|
92
|
+
response.max_write_size = 0x800000
|
93
|
+
response.system_time.set(Time.now)
|
94
|
+
if dialect.nil?
|
95
|
+
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/b39f253e-4963-40df-8dff-2f9040ebbeb1
|
96
|
+
# > If a common dialect is not found, the server MUST fail the request with STATUS_NOT_SUPPORTED.
|
97
|
+
response.smb2_header.nt_status = WindowsError::NTStatus::STATUS_NOT_SUPPORTED.value
|
98
|
+
return response
|
99
|
+
end
|
100
|
+
|
101
|
+
contexts = []
|
102
|
+
hash_algorithm = hash_value = nil
|
103
|
+
if dialect == '0x0311'
|
104
|
+
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/b39f253e-4963-40df-8dff-2f9040ebbeb1
|
105
|
+
nc = request.find_negotiate_context(SMB2::NegotiateContext::SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
|
106
|
+
hash_algorithm = SMB2::PreauthIntegrityCapabilities::HASH_ALGORITM_MAP[nc&.data&.hash_algorithms&.first]
|
107
|
+
hash_value = "\x00" * 64
|
108
|
+
unless hash_algorithm
|
109
|
+
response.smb2_header.nt_status = WindowsError::NTStatus::STATUS_INVALID_PARAMETER.value
|
110
|
+
return response
|
111
|
+
end
|
112
|
+
|
113
|
+
contexts << SMB2::NegotiateContext.new(
|
114
|
+
context_type: SMB2::NegotiateContext::SMB2_PREAUTH_INTEGRITY_CAPABILITIES,
|
115
|
+
data: {
|
116
|
+
hash_algorithms: [ SMB2::PreauthIntegrityCapabilities::SHA_512 ],
|
117
|
+
salt: SecureRandom.random_bytes(32)
|
118
|
+
}
|
119
|
+
)
|
120
|
+
|
121
|
+
nc = request.find_negotiate_context(SMB2::NegotiateContext::SMB2_ENCRYPTION_CAPABILITIES)
|
122
|
+
cipher = nc&.data&.ciphers&.first
|
123
|
+
cipher = 0 unless SMB2::EncryptionCapabilities::ENCRYPTION_ALGORITHM_MAP.include? cipher
|
124
|
+
contexts << SMB2::NegotiateContext.new(
|
125
|
+
context_type: SMB2::NegotiateContext::SMB2_ENCRYPTION_CAPABILITIES,
|
126
|
+
data: {
|
127
|
+
ciphers: [ cipher ]
|
128
|
+
}
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# the order in which the response is built is important to ensure it is valid
|
133
|
+
response.dialect_revision = dialect.to_i(16)
|
134
|
+
response.security_buffer_offset = response.security_buffer.abs_offset
|
135
|
+
response.security_buffer = process_gss.buffer
|
136
|
+
if dialect == '0x0311'
|
137
|
+
response.negotiate_context_offset = response.negotiate_context_list.abs_offset
|
138
|
+
contexts.each { |nc| response.add_negotiate_context(nc) }
|
139
|
+
end
|
140
|
+
@preauth_integrity_hash_algorithm = hash_algorithm
|
141
|
+
@preauth_integrity_hash_value = hash_value
|
142
|
+
|
143
|
+
if dialect == '0x0311'
|
144
|
+
update_preauth_hash(request)
|
145
|
+
update_preauth_hash(response)
|
146
|
+
end
|
147
|
+
|
148
|
+
@state = :session_setup
|
149
|
+
@dialect = dialect
|
150
|
+
response
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module RubySMB
|
2
|
+
class Server
|
3
|
+
class ServerClient
|
4
|
+
module SessionSetup
|
5
|
+
#
|
6
|
+
# Setup a new session based on the negotiated dialect. Once session setup is complete, the state will be updated
|
7
|
+
# to :authenticated.
|
8
|
+
#
|
9
|
+
# @param [String] raw_request the session setup request to process
|
10
|
+
def handle_session_setup(raw_request)
|
11
|
+
response = nil
|
12
|
+
|
13
|
+
case metadialect.order
|
14
|
+
when Dialect::ORDER_SMB1
|
15
|
+
request = SMB1::Packet::SessionSetupRequest.read(raw_request)
|
16
|
+
response = do_session_setup_smb1(request)
|
17
|
+
when Dialect::ORDER_SMB2
|
18
|
+
request = SMB2::Packet::SessionSetupRequest.read(raw_request)
|
19
|
+
response = do_session_setup_smb2(request)
|
20
|
+
end
|
21
|
+
|
22
|
+
if response.nil?
|
23
|
+
disconnect!
|
24
|
+
else
|
25
|
+
send_packet(response)
|
26
|
+
end
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def do_session_setup_smb1(request)
|
32
|
+
gss_result = process_gss(request.data_block.security_blob)
|
33
|
+
return if gss_result.nil?
|
34
|
+
|
35
|
+
response = SMB1::Packet::SessionSetupResponse.new
|
36
|
+
response.smb_header.pid_low = request.smb_header.pid_low
|
37
|
+
response.smb_header.uid = rand(0x10000)
|
38
|
+
response.smb_header.mid = request.smb_header.mid
|
39
|
+
response.smb_header.nt_status = gss_result.nt_status.value
|
40
|
+
response.smb_header.flags.reply = true
|
41
|
+
response.smb_header.flags2.unicode = true
|
42
|
+
response.smb_header.flags2.extended_security = true
|
43
|
+
unless gss_result.buffer.nil?
|
44
|
+
response.parameter_block.security_blob_length = gss_result.buffer.length
|
45
|
+
response.data_block.security_blob = gss_result.buffer
|
46
|
+
end
|
47
|
+
|
48
|
+
if gss_result.nt_status == WindowsError::NTStatus::STATUS_SUCCESS
|
49
|
+
@state = :authenticated
|
50
|
+
@identity = gss_result.identity
|
51
|
+
end
|
52
|
+
|
53
|
+
response
|
54
|
+
end
|
55
|
+
|
56
|
+
def do_session_setup_smb2(request)
|
57
|
+
gss_result = process_gss(request.buffer)
|
58
|
+
return if gss_result.nil?
|
59
|
+
|
60
|
+
response = SMB2::Packet::SessionSetupResponse.new
|
61
|
+
response.smb2_header.nt_status = gss_result.nt_status.value
|
62
|
+
response.smb2_header.credits = 1
|
63
|
+
response.smb2_header.message_id = @message_id += 1
|
64
|
+
response.smb2_header.session_id = @session_id = @session_id || SecureRandom.random_bytes(4).unpack1('V')
|
65
|
+
response.buffer = gss_result.buffer
|
66
|
+
|
67
|
+
update_preauth_hash(request) if @dialect == '0x0311'
|
68
|
+
if gss_result.nt_status == WindowsError::NTStatus::STATUS_SUCCESS
|
69
|
+
@state = :authenticated
|
70
|
+
@identity = gss_result.identity
|
71
|
+
@session_key = @gss_authenticator.session_key
|
72
|
+
elsif gss_result.nt_status == WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED && @dialect == '0x0311'
|
73
|
+
update_preauth_hash(response)
|
74
|
+
end
|
75
|
+
|
76
|
+
response
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|