packetgen-plugin-smb 0.5.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/specs.yml +28 -0
  3. data/.rubocop.yml +26 -2
  4. data/Gemfile +15 -0
  5. data/README.md +51 -12
  6. data/Rakefile +10 -4
  7. data/examples/llmnr-responder +110 -0
  8. data/examples/smb-responder +233 -0
  9. data/lib/packetgen/plugin/gssapi.rb +16 -10
  10. data/lib/packetgen/plugin/llmnr.rb +4 -4
  11. data/lib/packetgen/plugin/netbios/datagram.rb +3 -3
  12. data/lib/packetgen/plugin/netbios/name.rb +4 -4
  13. data/lib/packetgen/plugin/netbios/session.rb +5 -5
  14. data/lib/packetgen/plugin/netbios.rb +2 -0
  15. data/lib/packetgen/plugin/ntlm/authenticate.rb +197 -0
  16. data/lib/packetgen/plugin/ntlm/av_pair.rb +115 -0
  17. data/lib/packetgen/plugin/ntlm/challenge.rb +140 -0
  18. data/lib/packetgen/plugin/ntlm/negotiate.rb +127 -0
  19. data/lib/packetgen/plugin/ntlm/ntlmv2_response.rb +59 -0
  20. data/lib/packetgen/plugin/ntlm.rb +211 -0
  21. data/lib/packetgen/plugin/smb/blocks.rb +2 -2
  22. data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +2 -2
  23. data/lib/packetgen/plugin/smb/browser/host_announcement.rb +2 -2
  24. data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +2 -2
  25. data/lib/packetgen/plugin/smb/browser.rb +2 -2
  26. data/lib/packetgen/plugin/smb/close/request.rb +2 -2
  27. data/lib/packetgen/plugin/smb/close/response.rb +2 -2
  28. data/lib/packetgen/plugin/smb/close.rb +2 -2
  29. data/lib/packetgen/plugin/smb/filetime.rb +10 -2
  30. data/lib/packetgen/plugin/smb/negotiate/dialect.rb +7 -0
  31. data/lib/packetgen/plugin/smb/negotiate/request.rb +7 -0
  32. data/lib/packetgen/plugin/smb/negotiate/response.rb +9 -3
  33. data/lib/packetgen/plugin/smb/negotiate.rb +2 -2
  34. data/lib/packetgen/plugin/smb/nt_create_and_x.rb +2 -2
  35. data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +4 -4
  36. data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +2 -2
  37. data/lib/packetgen/plugin/smb/string.rb +60 -23
  38. data/lib/packetgen/plugin/smb/trans/request.rb +3 -3
  39. data/lib/packetgen/plugin/smb/trans/response.rb +2 -2
  40. data/lib/packetgen/plugin/smb/trans.rb +2 -2
  41. data/lib/packetgen/plugin/smb.rb +12 -12
  42. data/lib/packetgen/plugin/smb2/base.rb +3 -3
  43. data/lib/packetgen/plugin/smb2/error.rb +3 -4
  44. data/lib/packetgen/plugin/smb2/guid.rb +4 -3
  45. data/lib/packetgen/plugin/smb2/negotiate/context.rb +3 -3
  46. data/lib/packetgen/plugin/smb2/negotiate/request.rb +3 -5
  47. data/lib/packetgen/plugin/smb2/negotiate/response.rb +9 -7
  48. data/lib/packetgen/plugin/smb2/negotiate.rb +2 -2
  49. data/lib/packetgen/plugin/smb2/session_setup/request.rb +9 -5
  50. data/lib/packetgen/plugin/smb2/session_setup/response.rb +10 -6
  51. data/lib/packetgen/plugin/smb2/session_setup.rb +2 -2
  52. data/lib/packetgen/plugin/smb2.rb +3 -3
  53. data/lib/packetgen/plugin/smb_version.rb +3 -1
  54. data/lib/packetgen-plugin-smb.rb +3 -2
  55. data/packetgen-plugin-smb.gemspec +8 -10
  56. metadata +21 -84
  57. data/.travis.yml +0 -12
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
8
+ module PacketGen::Plugin
9
+ # Base class for NTLM authentication protocol.
10
+ # @author Sylvain Daubert
11
+ class NTLM < PacketGen::Types::Fields
12
+ # NTLM message types
13
+ TYPES = {
14
+ 'negotiate' => 1,
15
+ 'challenge' => 2,
16
+ 'authenticate' => 3
17
+ }.freeze
18
+
19
+ # NTLM signature
20
+ SIGNATURE = "NTLMSSP\0"
21
+
22
+ # void version
23
+ VOID_VERSION = [0].pack('q').freeze
24
+ VOID_CHALLENGE = VOID_VERSION
25
+
26
+ # @!attribute signature
27
+ # 8-byte NTLM signature
28
+ # @return [String]
29
+ define_field :signature, PacketGen::Types::String, static_length: 8, default: SIGNATURE
30
+ # @!attribute type
31
+ # 4-byte message type
32
+ # @return [Integer]
33
+ define_field :type, PacketGen::Types::Int32leEnum, enum: TYPES
34
+ # @!attribute payload
35
+ # @return [String]
36
+ define_field :payload, PacketGen::Types::String
37
+
38
+ class <<self
39
+ # @api private
40
+ # Return fields defined in payload one.
41
+ # @return [Hash]
42
+ attr_accessor :payload_fields
43
+
44
+ # Create a NTLM object from a binary string
45
+ # @param [String] str
46
+ # @return [NTLM]
47
+ def read(str)
48
+ ntlm = self.new.read(str)
49
+ type = TYPES.key(ntlm.type)
50
+ return ntlm if type.nil?
51
+
52
+ klass = NTLM.const_get(type.capitalize)
53
+ klass.new.read(str)
54
+ end
55
+
56
+ # Define a flags field.
57
+ # @return [void]
58
+ def define_negotiate_flags
59
+ define_field_before :payload, :flags, PacketGen::Types::Int32le
60
+ define_bit_fields_on :flags, :flags_w, :flags_v, :flags_u, :flags_r13, 3,
61
+ :flags_t, :flags_r4, :flags_s, :flags_r,
62
+ :flags_r5, :flags_q, :flags_p, :flags_r6,
63
+ :flags_o, :flags_n, :flags_m, :flags_r7,
64
+ :flags_l, :flags_k, :flags_j, :flags_r8,
65
+ :flags_h, :flags_r9, :flags_g, :flags_f,
66
+ :flags_e, :flags_d, :flags_r10, :flags_c,
67
+ :flags_b, :flags_a
68
+ alias_method :nego56?, :flags_w?
69
+ alias_method :key_exch?, :flags_v?
70
+ alias_method :nego128?, :flags_u?
71
+ alias_method :version?, :flags_t?
72
+ alias_method :target_info?, :flags_s?
73
+ alias_method :non_nt_session_key?, :flags_r?
74
+ alias_method :identify?, :flags_q?
75
+ alias_method :ext_session_security?, :flags_p?
76
+ alias_method :target_type_server?, :flags_o?
77
+ alias_method :target_type_domain?, :flags_n?
78
+ alias_method :always_sign?, :flags_m?
79
+ alias_method :oem_workstation_supplied?, :flags_l?
80
+ alias_method :oem_domain_supplied?, :flags_k?
81
+ alias_method :anonymous?, :flags_j?
82
+ alias_method :ntlm?, :flags_h?
83
+ alias_method :lm_key?, :flags_g?
84
+ alias_method :datagram?, :flags_f?
85
+ alias_method :seal?, :flags_e?
86
+ alias_method :sign?, :flags_d?
87
+ alias_method :request_target?, :flags_c?
88
+ alias_method :oem?, :flags_b?
89
+ alias_method :unicode?, :flags_a?
90
+ alias_method :old_flags_a=, :flags_a=
91
+ alias_method :old_flags=, :flags=
92
+
93
+ class_eval do
94
+ def flags_a=(value)
95
+ self.old_flags_a = value
96
+ self.class.payload_fields.each do |name, _|
97
+ attr = send(name)
98
+ attr.unicode = value if attr.respond_to?(:unicode=)
99
+ end
100
+
101
+ value
102
+ end
103
+
104
+ def flags=(value)
105
+ self.old_flags = value
106
+ self.flags_a = value & 1
107
+ end
108
+ end
109
+ end
110
+
111
+ # Define a field in payload. Also add +name_len+, +name_maxlen+ and
112
+ # +name_offset+ fields.
113
+ # @param [Symbol] name name of field.
114
+ # @param [Class,nil] type type of +name+ field.
115
+ # @param [Hash] options type's options needed at build time
116
+ # @return [void]
117
+ def define_in_payload(name, type=SMB::String, options={})
118
+ @payload_fields ||= {}
119
+ @payload_fields[name] = [type, options]
120
+
121
+ define_field_before :payload, :"#{name}_len", PacketGen::Types::Int16le
122
+ define_field_before :payload, :"#{name}_maxlen", PacketGen::Types::Int16le
123
+ define_field_before :payload, :"#{name}_offset", PacketGen::Types::Int32le
124
+
125
+ attr_accessor name
126
+ end
127
+ end
128
+
129
+ # @abstract This method is meaningful for {NTLM} subclasses only.
130
+ def initialize(options={})
131
+ super
132
+ return if self.class.payload_fields.nil?
133
+
134
+ self.class.payload_fields.each do |name, type_and_opt|
135
+ type, options = type_and_opt
136
+ content = if type.new.respond_to?(:unicode?)
137
+ type.new(options.merge(unicode: unicode?))
138
+ else
139
+ type.new(options)
140
+ end
141
+ send(:"#{name}=", content)
142
+ end
143
+ end
144
+
145
+ # @abstract This class is meaningful for {NTLM} subclasses only.
146
+ # Populate object from a binary string
147
+ # @param [String] str
148
+ # @return [self]
149
+ def read(str)
150
+ super
151
+ return self if self.class.payload_fields.nil?
152
+
153
+ self.class.payload_fields.each do |name, type_and_opt|
154
+ type, options = type_and_opt
155
+ offset_in_payload = send(:"#{name}_offset") - offset_of(:payload)
156
+ length = send(:"#{name}_len")
157
+ content = if type.new.respond_to?(:unicode?)
158
+ type.new(options.merge(unicode: unicode?))
159
+ else
160
+ type.new(options)
161
+ end
162
+ content.read(payload[offset_in_payload, length]) if length.positive?
163
+ send(:"#{name}=", content)
164
+ end
165
+
166
+ self
167
+ end
168
+
169
+ # @abstract This class is meaningful for {NTLM} subclasses only.
170
+ # Calculate and set +len+, +maxlen+ and +offset+ fields defined for
171
+ # fields in {#payload}.
172
+ # @return [void]
173
+ def calc_length
174
+ return self if self.class.payload_fields.nil?
175
+
176
+ previous_len = 0
177
+ self.class.payload_fields.each do |name, _type_and_opt|
178
+ send(:"#{name}_len=", 0)
179
+ send(:"#{name}_offset=", offset_of(:payload) + previous_len)
180
+
181
+ field = send(name)
182
+ next unless field && !field.empty?
183
+
184
+ length = field.respond_to?(:sz) ? field.sz : field.size
185
+ send(:"#{name}_len=", length)
186
+ send(:"#{name}_maxlen=", length)
187
+ previous_len = length
188
+ end
189
+ end
190
+
191
+ # @abstract This class is meaningful for {NTLM} subclasses only.
192
+ # @return [String]
193
+ def to_s
194
+ s = super
195
+ return s if self.class.payload_fields.nil?
196
+
197
+ self.class.payload_fields.each do |name, _type_and_opt|
198
+ attr = send(name)
199
+ attr.unicode = unicode? if attr.respond_to?(:unicode=)
200
+ s << attr.to_s unless attr.nil? || send("#{name}_len").zero?
201
+ end
202
+ s
203
+ end
204
+ end
205
+ end
206
+
207
+ require_relative 'ntlm/av_pair'
208
+ require_relative 'ntlm/ntlmv2_response'
209
+ require_relative 'ntlm/negotiate'
210
+ require_relative 'ntlm/challenge'
211
+ require_relative 'ntlm/authenticate'
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Common blocks used for unsupported SMB messages.
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  class Browser
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  class Browser
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  class Browser
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Browser Trans sub-protocol.
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Close
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Close
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for CLOSE related classes
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # SMB FILETIME.
11
11
  # @author Sylvain Daubert
12
12
  class Filetime
13
+ include PacketGen::Types::Fieldable
14
+
13
15
  # Base time for SMB FILETIME.
14
16
  # This value also indicate no time.
15
17
  NO_TIME = Time.utc(1601).freeze
@@ -22,6 +24,12 @@ module PacketGen::Plugin
22
24
  # String to parse time
23
25
  PARSE_TIME_STR = '%Y-%m-%d %H:%M:%S.%N %Z'
24
26
 
27
+ # Return a new Filetime object initialized to current time.
28
+ # @return [Filetime]
29
+ def self.now
30
+ new(time: Time.now.utc)
31
+ end
32
+
25
33
  # @param [Hash] options
26
34
  # @option options [Integer] :filetime
27
35
  # @option options [Time] :time
@@ -1,3 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
1
8
  module PacketGen::Plugin
2
9
  class SMB
3
10
  module Negotiate
@@ -1,3 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
1
8
  module PacketGen::Plugin
2
9
  class SMB
3
10
  module Negotiate
@@ -1,13 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of packetgen-plugin-smb.
4
+ # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
5
+ # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # This program is published under MIT license.
7
+
1
8
  module PacketGen::Plugin
2
9
  class SMB
3
10
  module Negotiate
4
11
  # SMB Negotiation Response header.
5
12
  #
6
- # See also {Blocks}, as {Negotiate::Rersponse} is a specialization of {Blocks#words}
13
+ # See also {Blocks}, as {Negotiate::Response} is a specialization of {Blocks#words}
7
14
  # and {Blocks#bytes}.
8
15
  # @author Sylvain Daubert
9
16
  class Response < Blocks
10
-
11
17
  # Get index of the dialect selected by the server from the list presented in the request.
12
18
  # @return [Integer]
13
19
  def dialect_index
@@ -20,4 +26,4 @@ module PacketGen::Plugin
20
26
  end
21
27
  end
22
28
  end
23
- end
29
+ end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NEGOTIATE related classes
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -128,7 +128,7 @@ module PacketGen::Plugin
128
128
  # Padding before {#filename} to align it on 16-bit boundary. Only present
129
129
  # if {SMB#flags2_unicode?} is +true+.
130
130
  # @return [Integer]
131
- define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
131
+ define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h&.packet&.smb&.flags2_unicode? }
132
132
  # @!attribute filename
133
133
  # A string that represents the fully qualified name of the file
134
134
  # relative to the supplied TID
@@ -154,6 +154,6 @@ module PacketGen::Plugin
154
154
  self.byte_count = bcount
155
155
  end
156
156
  end
157
- end
157
+ end
158
158
  end
159
159
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for NT_CREATE_ANDX related classes
@@ -1,28 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
8
+ require 'forwardable'
7
9
 
8
10
  module PacketGen::Plugin
9
11
  class SMB
10
- # SMB strings (UTF-16 little-endian).
12
+ # SMB strings (UTF-16 little-endian or OEM).
11
13
  # @author Sylvain Daubert
12
- class String < PacketGen::Types::CString
13
- # @param [Boolean] value
14
+ class String
15
+ extend Forwardable
16
+ include PacketGen::Types::Fieldable
17
+
18
+ def_delegators :@string, :[], :length, :size, :inspect, :==, :<<,
19
+ :unpack, :force_encoding, :encoding, :index, :empty?,
20
+ :encode
21
+
22
+ # @return [::String]
23
+ attr_reader :string
24
+ # @param [Boolean] null_terminated
14
25
  # @return [Boolean]
15
- attr_writer :unicode
26
+ attr_writer :null_terminated
16
27
 
17
28
  # @param [Hash] options
18
- # @option options [Integer] :static_length set a static length for this string
19
29
  # @option options [Boolean] :unicode If +true+, string is encoded as a UTF-16
20
30
  # unicode string. If +false+, string is encode in ASCII. Defaults to +true+.
31
+ # @option options [Boolean] :null_terminated If +true+, string is null-terminated.
32
+ # If +false+, string is not null-terminated. Defaults to +true+.
21
33
  def initialize(options={})
22
- super
23
34
  @unicode = options.key?(:unicode) ? options[:unicode] : true
24
- self.encode!('UTF-16LE') if @unicode
25
- self.encode!('ASCII-8BIT') unless @unicode
35
+ @null_terminated = options.key?(:null_terminated) ? options[:null_terminated] : true
36
+ @string = +''.encode(self_encoding)
26
37
  end
27
38
 
28
39
  # @return [Boolean]
@@ -30,6 +41,19 @@ module PacketGen::Plugin
30
41
  @unicode
31
42
  end
32
43
 
44
+ # @param [Boolean] bool
45
+ # @return [Boolean]
46
+ def unicode=(bool)
47
+ @unicode = bool
48
+ @string.force_encoding(self_encoding)
49
+ bool
50
+ end
51
+
52
+ # @return [Boolean]
53
+ def null_terminated?
54
+ @null_terminated
55
+ end
56
+
33
57
  # @param [::String] str
34
58
  # @return [String] self
35
59
  def read(str)
@@ -37,34 +61,47 @@ module PacketGen::Plugin
37
61
 
38
62
  str2 = case str.encoding
39
63
  when Encoding::BINARY
40
- binidx = nil
41
- 0.step(to: str.size, by: 2) do |i|
42
- binidx = i if str[i, 2] == binary_terminator
43
- end
44
- s = if binidx.nil?
45
- str
46
- else
47
- str[0, binidx]
48
- end
49
- s.force_encoding(self_encoding)
64
+ str.dup.force_encoding(self_encoding)
50
65
  else
51
66
  str.encode(self_encoding)
52
67
  end
53
- str2 = str2[0, @static_length / 2] if @static_length.is_a? Integer
54
68
  idx = str2.index(+"\x00".encode(self_encoding))
55
69
  str2 = str2[0, idx] unless idx.nil?
56
- self.replace str2
70
+ @string = str2
57
71
  self
58
72
  end
59
73
 
74
+ # @return [String]
75
+ def to_s
76
+ str = string.dup.force_encoding('BINARY')
77
+ return str unless null_terminated?
78
+
79
+ str << binary_terminator.force_encoding('BINARY')
80
+ end
81
+
82
+ # Populate String from a human readable (ie UTF-8) string
83
+ # @param [String] str
84
+ # @return [self]
85
+ def from_human(str)
86
+ return self if str.nil?
87
+
88
+ @string = str.encode(self_encoding)
89
+ self
90
+ end
91
+
92
+ # @return [String]
93
+ def to_human
94
+ string.encode('UTF-8')
95
+ end
96
+
60
97
  private
61
98
 
62
99
  def self_encoding
63
- @unicode ? Encoding::UTF_16LE : Encoding:: ASCII_8BIT
100
+ @unicode ? Encoding::UTF_16LE : Encoding::ASCII_8BIT
64
101
  end
65
102
 
66
103
  def binary_terminator
67
- @unicode ? "\x00\x00" : "\x00"
104
+ [0].pack('C').encode(self_encoding)
68
105
  end
69
106
  end
70
107
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Trans
@@ -96,7 +96,7 @@ module PacketGen::Plugin
96
96
  # 8-bit optional padding to align {#name} on a 2-byte boundary. Only present
97
97
  # if {SMB#flags2_unicode?} is +true+.
98
98
  # @return [Integer]
99
- define_field :padname, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
99
+ define_field :padname, PacketGen::Types::Int8, optional: ->(h) { h&.packet&.smb&.flags2_unicode? }
100
100
  # @!attribute name
101
101
  # Pathname of the mailslot or named pipe.
102
102
  # @return [String]
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  module Trans
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of packetgen-plugin-smb.
2
4
  # See https://github.com/sdaubert/packetgen-plugin-smb for more informations
3
5
  # Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
6
  # This program is published under MIT license.
5
7
 
6
- # frozen_string_literal: true
7
-
8
8
  module PacketGen::Plugin
9
9
  class SMB
10
10
  # Namespace for TRANS related classes