packetgen-plugin-smb 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/packetgen-plugin-smb.rb +7 -5
  3. data/lib/packetgen/plugin/gssapi.rb +125 -0
  4. data/lib/packetgen/plugin/smb.rb +26 -32
  5. data/lib/packetgen/plugin/smb/blocks.rb +2 -2
  6. data/lib/packetgen/plugin/smb/browser.rb +3 -3
  7. data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +3 -3
  8. data/lib/packetgen/plugin/smb/browser/host_announcement.rb +4 -4
  9. data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +3 -3
  10. data/lib/packetgen/plugin/smb/close.rb +9 -59
  11. data/lib/packetgen/plugin/smb/close/request.rb +45 -0
  12. data/lib/packetgen/plugin/smb/close/response.rb +36 -0
  13. data/lib/packetgen/plugin/smb/filetime.rb +10 -9
  14. data/lib/packetgen/plugin/smb/nt_create_and_x.rb +9 -264
  15. data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +159 -0
  16. data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +128 -0
  17. data/lib/packetgen/plugin/smb/string.rb +4 -4
  18. data/lib/packetgen/plugin/smb/trans.rb +9 -190
  19. data/lib/packetgen/plugin/smb/trans/request.rb +121 -0
  20. data/lib/packetgen/plugin/smb/trans/response.rb +94 -0
  21. data/lib/packetgen/plugin/smb2.rb +181 -0
  22. data/lib/packetgen/plugin/smb2/base.rb +31 -0
  23. data/lib/packetgen/plugin/smb2/error.rb +50 -0
  24. data/lib/packetgen/plugin/smb2/guid.rb +68 -0
  25. data/lib/packetgen/plugin/smb2/negotiate.rb +22 -0
  26. data/lib/packetgen/plugin/smb2/negotiate/context.rb +131 -0
  27. data/lib/packetgen/plugin/smb2/negotiate/request.rb +166 -0
  28. data/lib/packetgen/plugin/smb2/negotiate/response.rb +190 -0
  29. data/lib/packetgen/plugin/smb2/session_setup.rb +21 -0
  30. data/lib/packetgen/plugin/smb2/session_setup/request.rb +98 -0
  31. data/lib/packetgen/plugin/smb2/session_setup/response.rb +69 -0
  32. data/lib/packetgen/plugin/smb_version.rb +1 -1
  33. data/packetgen-plugin-smb.gemspec +2 -1
  34. metadata +42 -4
@@ -0,0 +1,131 @@
1
+ # This file is part of packetgen-plugin-smb.
2
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen::Plugin
9
+ class SMB2
10
+ module Negotiate
11
+ # NegotiateContext structure.
12
+ # 0 1 2 3
13
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | Type | DataLength |
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | Reserved |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | Data (variable) |
20
+ # + +
21
+ # | ... |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # @author Sylvain Daubert
24
+ class Context < PacketGen::Types::Fields
25
+ # Known types
26
+ TYPES = {
27
+ 'PREAUTH_INTEGRITY_CAP' => 1,
28
+ 'ENCRYPTION_CAP' => 2
29
+ }.freeze
30
+
31
+ # @!attribute type
32
+ # 16-bit context type
33
+ # @return [Integer]
34
+ define_field :type, PacketGen::Types::Int16leEnum, enum: TYPES
35
+ # @!attribute data_length
36
+ # 16-bit data length
37
+ # @return [Integer]
38
+ define_field :data_length, PacketGen::Types::Int16le
39
+ # @!attribute reserved
40
+ # 32-bit reserved field
41
+ # @return [Integer]
42
+ define_field :reserved, PacketGen::Types::Int32le
43
+ # @!attribute data
44
+ # context data
45
+ # @return [String]
46
+ define_field :data, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:data_length]) }
47
+ # @!attribute pad
48
+ # Padding to align next context on a 8-byte offset
49
+ # @return [String]
50
+ define_field :pad, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: -> { v = 8 - (h.offset_of(:data) + h.data_length) % 8; v == 8 ? 0 : v }) }
51
+
52
+ # @private
53
+ alias old_read read
54
+
55
+ # Populate object from a binary string
56
+ # @param [String] str
57
+ # @return [Context]
58
+ def read(str)
59
+ return self if str.nil?
60
+ if self.instance_of? Context
61
+ self[:type].read str[0, 2]
62
+ name = TYPES.key(type)
63
+ return old_read(str) if name.nil?
64
+
65
+ klassname = name.downcase.capitalize.gsub(/_(\w)/) { $1.upcase }
66
+ return old_read(str) unless Negotiate.const_defined? klassname
67
+
68
+ klass = Negotiate.const_get(klassname)
69
+ klass.new.read str
70
+ else
71
+ old_read str
72
+ end
73
+ end
74
+
75
+ # Get human-readable type
76
+ # @return [String]
77
+ def human_type
78
+ self[:type].to_human
79
+ end
80
+
81
+ # Get human-readable context
82
+ # @return [String]
83
+ def to_human
84
+ human_type
85
+ end
86
+ end
87
+
88
+ class PreauthIntegrityCap < Context
89
+ remove_field :data
90
+ # @!attribute hash_alg_count
91
+ # 16-bit number of hash algorithm in {#hash_alg}
92
+ # @return [Integer]
93
+ define_field_before :pad, :hash_alg_count, PacketGen::Types::Int16le
94
+ # @!attribute salt_length
95
+ # 16-bit length of {#salt} field, in bytes.
96
+ # @return [Integer]
97
+ define_field_before :pad, :salt_length, PacketGen::Types::Int16le
98
+ # @!attribute hash_alg
99
+ # Array of 16-bit integer IDs specifying the supported preauthentication
100
+ # hash algorithms
101
+ # @return [PacketGen::Types::ArrayOfInt16le]
102
+ define_field_before :pad, :hash_alg, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:hash_alg_count]) }
103
+ # @!attribute salt
104
+ # Salt value for hash
105
+ # @return [String]
106
+ define_field_before :pad, :salt, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:salt_length]) }
107
+ update_field :pad, builder: ->(h, t) { t.new(length_from: -> { v = 8 - (h.offset_of(:salt) + h.salt_length) % 8; v == 8 ? 0 : v }) }
108
+ end
109
+
110
+ class EncryptionCap < Context
111
+ remove_field :data
112
+ # @!attribute cipher_count
113
+ # 16-bit number of cipher algorithm in {#ciphers}
114
+ # @return [Integer]
115
+ define_field_before :pad, :cipher_count, PacketGen::Types::Int16le
116
+ # @!attribute ciphers
117
+ # Array of 16-bit integer IDs specifying the supported encryption
118
+ # algorithms
119
+ # @return [PacketGen::Types::ArrayOfInt16le]
120
+ define_field_before :pad, :ciphers, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:hash_alg_count]) }
121
+ update_field :pad, builder: ->(h, t) { t.new(length_from: -> { v = 8 - (h.offset_of(:cipher_count) + h[:cipher_count].sz) % 8; v == 8 ? 0 : v }) }
122
+ end
123
+
124
+ # Array of {Context}
125
+ # @author Sylvain Daubert
126
+ class ArrayOfContext < PacketGen::Types::Array
127
+ set_of Context
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,166 @@
1
+ # This file is part of packetgen-plugin-smb.
2
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen::Plugin
9
+ class SMB2
10
+ module Negotiate
11
+ # SMB2 Negotiate request structure
12
+ # 0 1 2 3
13
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | StructureSize | DialectCount |
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | SecurityMode | Reserved |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | Capabilities |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # | ClientGUID |
22
+ # + +
23
+ # | |
24
+ # + +
25
+ # | |
26
+ # + +
27
+ # | |
28
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
+ # | ContextOffset |
30
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
+ # | ContextCount | Reserved2 |
32
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
+ # | Dialects (variable) |
34
+ # + +
35
+ # | ... |
36
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37
+ # | Pad (variable) |
38
+ # + +
39
+ # | ... |
40
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41
+ # | ContextList (variable) |
42
+ # + +
43
+ # | ... |
44
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
+ # @author Sylvain Daubert
46
+ class Request < Base
47
+ # Security modes
48
+ SECURITY_MODES = {
49
+ 'signing_enabled' => 1,
50
+ 'signing required' => 2
51
+ }
52
+
53
+ # @!attribute structure_size
54
+ # 16-bit negotiate request structure size. Should be 36.
55
+ # @return [Integer]
56
+ define_field :structure_size, PacketGen::Types::Int16le, default: 36
57
+ # @!attribute dialect_count
58
+ # 16-bit number of dialects that are contained in {#dialects}.
59
+ # @return [Integer]
60
+ define_field :dialect_count, PacketGen::Types::Int16le
61
+ # @!attribute security_mode
62
+ # 16-bit security mode field.
63
+ # @return [Integer]
64
+ define_field :security_mode, PacketGen::Types::Int16leEnum, enum: SECURITY_MODES
65
+ # @!attribute reserved
66
+ # 16-bit reserved field.
67
+ # @return [Integer]
68
+ define_field :reserved, PacketGen::Types::Int16le
69
+ # @!attribute capabilities
70
+ # 32-bit capabilities field.
71
+ # @return [Integer]
72
+ define_field :capabilities, PacketGen::Types::Int32le
73
+ # @!attribute cap_encryption
74
+ # Indicates if encryption is supported
75
+ # @return [Boolean]
76
+ # @!attribute cap_dir_leasing
77
+ # Indicates if directory leasing is supported
78
+ # @return [Boolean]
79
+ # @!attribute cap_persistent_handles
80
+ # Indicates if persisten handles are supported
81
+ # @return [Boolean]
82
+ # @!attribute cap_multi_channel
83
+ # Indicates if multiple channels are supported for a single session
84
+ # @return [Boolean]
85
+ # @!attribute cap_large_mtu
86
+ # Indicates if multi credit operations are supported
87
+ # @return [Boolean]
88
+ # @!attribute cap_leasing
89
+ # Indicates if leasing is supported
90
+ # @return [Boolean]
91
+ # @!attribute cap_dfs
92
+ # Indicates if Distributed File system (DFS) is supported
93
+ # @return [Boolean]
94
+ define_bit_fields_on :capabilities, :cap_rsv, 25, :cap_encryption, :cap_dir_leasing,
95
+ :cap_persistent_handles, :cap_multi_channel,
96
+ :cap_large_mtu, :cap_leasing, :cap_dfs
97
+ # @!attribute client_guid
98
+ # @return []
99
+ define_field :client_guid, GUID
100
+ # @!attribute context_offset
101
+ # Only for SMB3 dialect.
102
+ # @return [Integer]
103
+ define_field :context_offset, PacketGen::Types::Int32le
104
+ # @!attribute context_count
105
+ # Only for SMB3 dialect.
106
+ # @return [Integer]
107
+ define_field :context_count, PacketGen::Types::Int16le
108
+ # @!attribute reserved2
109
+ # Only for SMB3 dialect.
110
+ # @return [Integer]
111
+ define_field :reserved2, PacketGen::Types::Int16le
112
+ # @!attribute dialects
113
+ # Array of 16-bit integers specifying the supported dialtec revisions.
114
+ # @return [Array<PacketGen::Types::Int16le>]
115
+ define_field :dialects, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:dialect_count]) }
116
+ # @!attribute pad
117
+ # Optional padding between the end of the {#dialects} array and the first negotiate
118
+ # context in {#context_list} so that the first negotiate context is 8-byte aligned.
119
+ # @return [String]
120
+ define_smb2_pad_field :pad
121
+ # @!attribute context_list
122
+ # If {#dialects} contains the value 0x0311, then this field must contain an array
123
+ # of {Context}
124
+ # @return [ArrayOfContext]
125
+ define_field :context_list, ArrayOfContext, builder: ->(h, t) { t.new(counter: h[:context_count]) }
126
+
127
+ # @return [String]
128
+ def inspect
129
+ super do |attr|
130
+ case attr
131
+ when :capabilities
132
+ value = bits_on(attr).reject { |_, v| v > 1 }
133
+ .keys
134
+ .select { |b| send("#{b}?") }
135
+ .map(&:to_s)
136
+ .join(',')
137
+ .gsub!(/cap_/, '')
138
+ value = '%-16s (0x%08x)' % [value, self[attr].to_i]
139
+ str = PacketGen::Inspect.shift_level
140
+ str << PacketGen::Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
141
+ attr, value]
142
+ when :dialects
143
+ list = self.dialects.map { |v| "%#04x" % v.to_i }.join(',')
144
+ str = PacketGen::Inspect.shift_level
145
+ str << PacketGen::Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
146
+ attr, list]
147
+ end
148
+ end
149
+ end
150
+
151
+ # Calculate and set {#context_offset} field. Also calculate
152
+ # lengths in {Context contexts}.
153
+ # @return [Integer]
154
+ def calc_length
155
+ self.context_offset = SMB2.new.sz + offset_of(:context_list)
156
+ end
157
+
158
+ # Protocol name
159
+ # @return [String]
160
+ def protocol_name
161
+ 'SMB2::Negotiate::Request'
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,190 @@
1
+ # This file is part of packetgen-plugin-smb.
2
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen::Plugin
9
+ class SMB2
10
+ module Negotiate
11
+ # SMB2 Negotiate response structure
12
+ # 0 1 2 3
13
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | StructureSize | SecurityMode |
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | DialectRevision | ContextCount |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | ServerGUID |
20
+ # + +
21
+ # | |
22
+ # + +
23
+ # | |
24
+ # + +
25
+ # | |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # | Capabilities |
28
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
+ # | MaxTranSize |
30
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
+ # | MaxReadSize |
32
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
+ # | MaxWriteSize |
34
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35
+ # | SystemTime |
36
+ # + +
37
+ # | |
38
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39
+ # | StartTime |
40
+ # + +
41
+ # | |
42
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
+ # | BufferOffset | BufferLength |
44
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
+ # | ContextOffset |
46
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
+ # | Buffer (variable) |
48
+ # + +
49
+ # | ... |
50
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51
+ # | Pad (variable) |
52
+ # + +
53
+ # | ... |
54
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55
+ # | ContextList (variable) |
56
+ # + +
57
+ # | ... |
58
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59
+ # @author Sylvain Daubert
60
+ class Response < Base
61
+ # @!attribute structure_size
62
+ # 16-bit negotiate request structure size. Should be 65.
63
+ # @return [Integer]
64
+ define_field :structure_size, PacketGen::Types::Int16le, default: 65
65
+ # @!attribute security_mode
66
+ # 16-bit security mode field.
67
+ # @return [Integer]
68
+ define_field :security_mode, PacketGen::Types::Int16leEnum, enum: Negotiate::Request::SECURITY_MODES
69
+ # @!attribute dialect
70
+ # 16-bit prefered SMB2 protocol dialect number.
71
+ # @return [Integer]
72
+ define_field :dialect, PacketGen::Types::Int16le
73
+ # @!attribute context_count
74
+ # Only for SMB3 dialect.
75
+ # @return [Integer]
76
+ define_field :context_count, PacketGen::Types::Int16le
77
+ # @!attribute server_guid
78
+ # @return []
79
+ define_field :server_guid, GUID
80
+ # @!attribute capabilities
81
+ # 32-bit capabilities field.
82
+ # @return [Integer]
83
+ define_field :capabilities, PacketGen::Types::Int32le
84
+ # @!attribute cap_encryption
85
+ # Indicates if encryption is supported
86
+ # @return [Boolean]
87
+ # @!attribute cap_dir_leasing
88
+ # Indicates if directory leasing is supported
89
+ # @return [Boolean]
90
+ # @!attribute cap_persistent_handles
91
+ # Indicates if persisten handles are supported
92
+ # @return [Boolean]
93
+ # @!attribute cap_multi_channel
94
+ # Indicates if multiple channels are supported for a single session
95
+ # @return [Boolean]
96
+ # @!attribute cap_large_mtu
97
+ # Indicates if multi credit operations are supported
98
+ # @return [Boolean]
99
+ # @!attribute cap_leasing
100
+ # Indicates if leasing is supported
101
+ # @return [Boolean]
102
+ # @!attribute cap_dfs
103
+ # Indicates if Distributed File system (DFS) is supported
104
+ # @return [Boolean]
105
+ define_bit_fields_on :capabilities, :cap_rsv, 25, :cap_encryption, :cap_dir_leasing,
106
+ :cap_persistent_handles, :cap_multi_channel,
107
+ :cap_large_mtu, :cap_leasing, :cap_dfs
108
+ # @!attribute max_trans_size
109
+ # 32-bit value indicating the maximum size of the buffer used for
110
+ # QUERY_INFO, QUERY_DIRECTORY, SET_INFO and CHANGE_NOTIFY operations.
111
+ # @return [Integer]
112
+ define_field :max_trans_size, PacketGen::Types::Int32le
113
+ # @!attribute max_read_size
114
+ # 32-bit value indicating the maximum size of a READ request
115
+ # @return [Integer]
116
+ define_field :max_read_size, PacketGen::Types::Int32le
117
+ # @!attribute max_write_size
118
+ # 32-bit value indicating the maximum size of a WRITE request
119
+ # @return [Integer]
120
+ define_field :max_write_size, PacketGen::Types::Int32le
121
+ # @!attribute system_time
122
+ # System time of the SMB2 server
123
+ # @return [SMB::Filetime]
124
+ define_field :system_time, SMB::Filetime
125
+ # @!attribute start_time
126
+ # Start time of the SMB2 server
127
+ # @return [SMB::Filetime]
128
+ define_field :start_time, SMB::Filetime
129
+ # @!attribute buffer_offset
130
+ # The offset, from the beginning of the SMB2 header of the {#buffer}.
131
+ # @return [Integer]
132
+ define_field :buffer_offset, PacketGen::Types::Int16le
133
+ # @!attribute buffer_length
134
+ # The length of the {#buffer} field.
135
+ # @return [Integer]
136
+ define_field :buffer_length, PacketGen::Types::Int16le
137
+ # @!attribute context_offset
138
+ # Only for SMB3 dialect.
139
+ # @return [Integer]
140
+ define_field :context_offset, PacketGen::Types::Int32le
141
+ # @!attribute buffer
142
+ # @return [GSSAPI]
143
+ define_field :buffer, GSSAPI, token: :init
144
+ # @!attribute pad
145
+ # Optional padding between the end of the {#buffer} field and the first negotiate
146
+ # context in {#context_list} so that the first negotiate context is 8-byte aligned.
147
+ # @return [String]
148
+ define_smb2_pad_field :pad
149
+ # @!attribute context_list
150
+ # If {#dialect} has the value 0x0311, then this field must contain an array
151
+ # of {Context}
152
+ # @return [ArrayOfContext]
153
+ define_field :context_list, ArrayOfContext, builder: ->(h, t) { t.new(counter: h[:context_count]) }
154
+
155
+ # @return [String]
156
+ def inspect
157
+ super do |attr|
158
+ next unless attr == :capabilities
159
+ value = bits_on(attr).reject { |_, v| v > 1 }
160
+ .keys
161
+ .select { |b| send("#{b}?") }
162
+ .map(&:to_s)
163
+ .join(',')
164
+ .gsub!(/cap_/, '')
165
+ value = '%-16s (0x%08x)' % [value, self[attr].to_i]
166
+ str = PacketGen::Inspect.shift_level
167
+ str << PacketGen::Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''),
168
+ attr, value]
169
+ end
170
+ end
171
+
172
+ # Calculate and set {#context_offset}, {#buffer_offset} and {#buffer_length} fields.
173
+ # Also calculate lengths in {Context contexts}.
174
+ # @return [void]
175
+ def calc_length
176
+ self.context_offset = SMB2.new.sz + offset_of(:context_list)
177
+ self.buffer_offset = SMB2.new.sz + offset_of(:buffer)
178
+ self.buffer_length = buffer.sz
179
+ context_list.each { |ctx| ctx.calc_length if ctx.respond_to? :calc_length }
180
+ end
181
+
182
+ # Protocol name
183
+ # @return [String]
184
+ def protocol_name
185
+ 'SMB2::Negotiate::Response'
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end