libddwaf 1.3.0.2.0-x86_64-linux → 1.5.1.0.1-x86_64-linux
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
- data/CHANGELOG.md +79 -0
- data/lib/datadog/appsec/waf/version.rb +2 -2
- data/lib/datadog/appsec/waf.rb +289 -94
- data/vendor/libddwaf/libddwaf-1.5.1-linux-x86_64/lib/libddwaf.so +0 -0
- metadata +9 -9
- data/vendor/libddwaf/libddwaf-1.3.0-linux-gnu-x86_64/lib/libddwaf.so +0 -0
- data/vendor/libddwaf/libddwaf-1.3.0-linux-musl-x86_64/lib/libddwaf.so +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2a6f7b24f148c4006312358bff78f50d4eda13e8d9030015b542a92e1da11d4
|
4
|
+
data.tar.gz: 38e73b24bfd553c2264812084c5d51cb384ae22ea5e300eb5d471db18c6826c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 501700975140d85057f38c3a46e309f1bbd51d70a76e1d18fd2d3d540a8ea5ac6ff03656d002628d8f0a061fd6aaabb4385bb653a09b865cec96d7e67d616d53
|
7
|
+
data.tar.gz: ceb4f7b7a66992857d0057322d1af44dc56a873fa4894317f5ebe99f2111c168410bce8cb18294a35900d535095d5bcc56fdc2677ba6be35461c8323ef5ce3c9
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# 2023-02-01 v1.5.1.0.1
|
2
|
+
|
3
|
+
- Fix incorrect size in input string limit
|
4
|
+
- Fix object freeing on `update_rule_data` and `toggle_rules`
|
5
|
+
|
6
|
+
# 2022-10-04 v1.5.1.0.0
|
7
|
+
|
8
|
+
- Update to libddwaf 1.5.1
|
9
|
+
- Add live rule data update API
|
10
|
+
- Add live rule toggle API
|
11
|
+
- Add libddwaf boolean type support
|
12
|
+
- Add Ruby to libddwaf object conversion limits
|
13
|
+
- Add Ruby to libddwaf object converter optional coercion of scalars to string
|
14
|
+
- Add static type checking via RBS+Steep
|
15
|
+
- Change version to return a string
|
16
|
+
- Change free function to be passed as config instead of context init argument
|
17
|
+
- Change result to include action list
|
18
|
+
- Change return code from action to status
|
19
|
+
- Change handle and context freeing model from GC-based to explicit
|
20
|
+
- Fix double-free upon finalization of retained C objects
|
21
|
+
- Fix context crash by retaining necessary C objects
|
22
|
+
|
23
|
+
# 2022-05-20 v1.3.0.2.0
|
24
|
+
|
25
|
+
- Fix multibyte string handling
|
26
|
+
- Support JRuby
|
27
|
+
|
28
|
+
# 2022-04-29 v1.3.0.1.0
|
29
|
+
|
30
|
+
Promotion of v1.3.0.1.0.beta1 to stable
|
31
|
+
|
32
|
+
# 2022-04-25 v1.3.0.1.0.beta1
|
33
|
+
|
34
|
+
- Add obfuscator configuration
|
35
|
+
- Add nested object limit configuration
|
36
|
+
- Add report ruleset information
|
37
|
+
|
38
|
+
# 2022-04-29 v1.3.0.0.0
|
39
|
+
|
40
|
+
- Promote v1.3.0.0.0.beta1 to stable
|
41
|
+
|
42
|
+
# 2022-04-20 v1.3.0.0.0.beta1
|
43
|
+
|
44
|
+
- Update to libddwaf 1.3.0
|
45
|
+
|
46
|
+
# 2022-03-18 v1.2.1.0.0.beta1
|
47
|
+
|
48
|
+
- Update to libddwaf 1.2.1
|
49
|
+
- Fix incorrect types for a few binding functions
|
50
|
+
|
51
|
+
# 2022-03-04 v1.0.14.2.1.beta1
|
52
|
+
|
53
|
+
- Fix incorrect return code
|
54
|
+
- Fix passing nil in libddwaf object containers
|
55
|
+
|
56
|
+
# 2022-02-07 v1.0.14.2.0.beta1
|
57
|
+
|
58
|
+
- Change Datadog::Security to Datadog::AppSec
|
59
|
+
|
60
|
+
# 2022-02-01 v1.0.14.1.0.beta2
|
61
|
+
|
62
|
+
- Add support for Ruby 3.1
|
63
|
+
|
64
|
+
# 2021-12-14 v1.0.14.1.0.beta1
|
65
|
+
|
66
|
+
- Fix sequential runs on a single context by retaining C input data objects
|
67
|
+
|
68
|
+
# 2021-11-24 v1.0.14.0.0.beta1
|
69
|
+
|
70
|
+
- Update to libddwaf 1.0.14
|
71
|
+
|
72
|
+
# 2021-11-24 v1.0.13.0.0.beta1
|
73
|
+
|
74
|
+
- Add ruby platform fallback for unsupported platforms
|
75
|
+
- Update to libddwaf 1.0.13
|
76
|
+
|
77
|
+
# 2021-10-13 v1.0.12.0.0.beta1
|
78
|
+
|
79
|
+
- Initial release
|
data/lib/datadog/appsec/waf.rb
CHANGED
@@ -57,20 +57,35 @@ module Datadog
|
|
57
57
|
Gem::Platform.local.cpu
|
58
58
|
end
|
59
59
|
|
60
|
+
def self.source_dir
|
61
|
+
__dir__ || raise('__dir__ is nil: eval?')
|
62
|
+
end
|
63
|
+
|
60
64
|
def self.vendor_dir
|
61
|
-
File.join(
|
65
|
+
File.join(source_dir, '../../../vendor')
|
62
66
|
end
|
63
67
|
|
64
68
|
def self.libddwaf_vendor_dir
|
65
69
|
File.join(vendor_dir, 'libddwaf')
|
66
70
|
end
|
67
71
|
|
68
|
-
def self.shared_lib_triplet
|
69
|
-
|
72
|
+
def self.shared_lib_triplet(version: local_version)
|
73
|
+
version ? "#{local_os}-#{version}-#{local_cpu}" : "#{local_os}-#{local_cpu}"
|
70
74
|
end
|
71
75
|
|
72
76
|
def self.libddwaf_dir
|
73
|
-
File.join(libddwaf_vendor_dir,
|
77
|
+
default = File.join(libddwaf_vendor_dir,
|
78
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet}")
|
79
|
+
candidates = [
|
80
|
+
default
|
81
|
+
]
|
82
|
+
|
83
|
+
if local_os == 'linux'
|
84
|
+
candidates << File.join(libddwaf_vendor_dir,
|
85
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet(version: nil)}")
|
86
|
+
end
|
87
|
+
|
88
|
+
candidates.find { |d| Dir.exist?(d) } || default
|
74
89
|
end
|
75
90
|
|
76
91
|
def self.shared_lib_extname
|
@@ -85,15 +100,7 @@ module Datadog
|
|
85
100
|
|
86
101
|
# version
|
87
102
|
|
88
|
-
|
89
|
-
layout :major, :uint16,
|
90
|
-
:minor, :uint16,
|
91
|
-
:patch, :uint16
|
92
|
-
end
|
93
|
-
|
94
|
-
typedef Version.by_ref, :ddwaf_version
|
95
|
-
|
96
|
-
attach_function :ddwaf_get_version, [:ddwaf_version], :void
|
103
|
+
attach_function :ddwaf_get_version, [], :string
|
97
104
|
|
98
105
|
# ddwaf::object data structure
|
99
106
|
|
@@ -102,7 +109,9 @@ module Datadog
|
|
102
109
|
:ddwaf_obj_unsigned, 1 << 1,
|
103
110
|
:ddwaf_obj_string, 1 << 2,
|
104
111
|
:ddwaf_obj_array, 1 << 3,
|
105
|
-
:ddwaf_obj_map, 1 << 4
|
112
|
+
:ddwaf_obj_map, 1 << 4,
|
113
|
+
:ddwaf_obj_bool, 1 << 5
|
114
|
+
typedef DDWAF_OBJ_TYPE, :ddwaf_obj_type
|
106
115
|
|
107
116
|
typedef :pointer, :charptr
|
108
117
|
typedef :pointer, :charptrptr
|
@@ -129,7 +138,8 @@ module Datadog
|
|
129
138
|
layout :stringValue, :charptr,
|
130
139
|
:uintValue, :uint64,
|
131
140
|
:intValue, :int64,
|
132
|
-
:array, :pointer
|
141
|
+
:array, :pointer,
|
142
|
+
:boolean, :bool
|
133
143
|
end
|
134
144
|
|
135
145
|
class Object < ::FFI::Struct
|
@@ -137,7 +147,7 @@ module Datadog
|
|
137
147
|
:parameterNameLength, :uint64,
|
138
148
|
:valueUnion, ObjectValueUnion,
|
139
149
|
:nbEntries, :uint64,
|
140
|
-
:type,
|
150
|
+
:type, :ddwaf_obj_type
|
141
151
|
end
|
142
152
|
|
143
153
|
typedef Object.by_ref, :ddwaf_object
|
@@ -152,6 +162,7 @@ module Datadog
|
|
152
162
|
attach_function :ddwaf_object_signed, [:ddwaf_object, :int64], :ddwaf_object
|
153
163
|
attach_function :ddwaf_object_unsigned_force, [:ddwaf_object, :uint64], :ddwaf_object
|
154
164
|
attach_function :ddwaf_object_signed_force, [:ddwaf_object, :int64], :ddwaf_object
|
165
|
+
attach_function :ddwaf_object_bool, [:ddwaf_object, :bool], :ddwaf_object
|
155
166
|
|
156
167
|
attach_function :ddwaf_object_array, [:ddwaf_object], :ddwaf_object
|
157
168
|
attach_function :ddwaf_object_array_add, [:ddwaf_object, :ddwaf_object], :bool
|
@@ -182,6 +193,8 @@ module Datadog
|
|
182
193
|
typedef :pointer, :ddwaf_handle
|
183
194
|
typedef Object.by_ref, :ddwaf_rule
|
184
195
|
|
196
|
+
callback :ddwaf_object_free_fn, [:ddwaf_object], :void
|
197
|
+
|
185
198
|
class Config < ::FFI::Struct
|
186
199
|
class Limits < ::FFI::Struct
|
187
200
|
layout :max_container_size, :uint32,
|
@@ -190,12 +203,13 @@ module Datadog
|
|
190
203
|
end
|
191
204
|
|
192
205
|
class Obfuscator < ::FFI::Struct
|
193
|
-
layout :key_regex, :pointer, # :charptr
|
194
|
-
:value_regex, :pointer # :charptr
|
206
|
+
layout :key_regex, :pointer, # should be :charptr
|
207
|
+
:value_regex, :pointer # should be :charptr
|
195
208
|
end
|
196
209
|
|
197
210
|
layout :limits, Limits,
|
198
|
-
:obfuscator, Obfuscator
|
211
|
+
:obfuscator, Obfuscator,
|
212
|
+
:free_fn, :pointer #:ddwaf_object_free_fn
|
199
213
|
end
|
200
214
|
|
201
215
|
typedef Config.by_ref, :ddwaf_config
|
@@ -216,33 +230,43 @@ module Datadog
|
|
216
230
|
attach_function :ddwaf_destroy, [:ddwaf_handle], :void
|
217
231
|
|
218
232
|
attach_function :ddwaf_required_addresses, [:ddwaf_handle, UInt32Ptr], :charptrptr
|
233
|
+
attach_function :ddwaf_required_rule_data_ids, [:ddwaf_handle, UInt32Ptr], :charptrptr
|
234
|
+
|
235
|
+
# updating
|
236
|
+
|
237
|
+
DDWAF_RET_CODE = enum :ddwaf_err_internal, -3,
|
238
|
+
:ddwaf_err_invalid_object, -2,
|
239
|
+
:ddwaf_err_invalid_argument, -1,
|
240
|
+
:ddwaf_ok, 0,
|
241
|
+
:ddwaf_match, 1
|
242
|
+
typedef DDWAF_RET_CODE, :ddwaf_ret_code
|
243
|
+
|
244
|
+
attach_function :ddwaf_update_rule_data, [:ddwaf_handle, :ddwaf_object], :ddwaf_ret_code
|
245
|
+
attach_function :ddwaf_toggle_rules, [:ddwaf_handle, :ddwaf_object], :ddwaf_ret_code
|
219
246
|
|
220
247
|
# running
|
221
248
|
|
222
249
|
typedef :pointer, :ddwaf_context
|
223
250
|
|
224
|
-
|
225
|
-
|
226
|
-
attach_function :ddwaf_context_init, [:ddwaf_handle, :ddwaf_object_free_fn], :ddwaf_context
|
251
|
+
attach_function :ddwaf_context_init, [:ddwaf_handle], :ddwaf_context
|
227
252
|
attach_function :ddwaf_context_destroy, [:ddwaf_context], :void
|
228
253
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
:ddwaf_monitor, 1,
|
234
|
-
:ddwaf_block, 2
|
254
|
+
class ResultActions < ::FFI::Struct
|
255
|
+
layout :array, :charptrptr,
|
256
|
+
:size, :uint32
|
257
|
+
end
|
235
258
|
|
236
259
|
class Result < ::FFI::Struct
|
237
260
|
layout :timeout, :bool,
|
238
261
|
:data, :string,
|
262
|
+
:actions, ResultActions,
|
239
263
|
:total_runtime, :uint64
|
240
264
|
end
|
241
265
|
|
242
266
|
typedef Result.by_ref, :ddwaf_result
|
243
267
|
typedef :uint64, :timeout_us
|
244
268
|
|
245
|
-
attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_result, :timeout_us],
|
269
|
+
attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_result, :timeout_us], :ddwaf_ret_code, blocking: true
|
246
270
|
attach_function :ddwaf_result_free, [:ddwaf_result], :void
|
247
271
|
|
248
272
|
# logging
|
@@ -253,20 +277,28 @@ module Datadog
|
|
253
277
|
:ddwaf_log_warn,
|
254
278
|
:ddwaf_log_error,
|
255
279
|
:ddwaf_log_off
|
280
|
+
typedef DDWAF_LOG_LEVEL, :ddwaf_log_level
|
281
|
+
|
282
|
+
callback :ddwaf_log_cb, [:ddwaf_log_level, :string, :string, :uint, :charptr, :uint64], :void
|
283
|
+
|
284
|
+
attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
|
285
|
+
|
286
|
+
DEFAULT_MAX_CONTAINER_SIZE = 0
|
287
|
+
DEFAULT_MAX_CONTAINER_DEPTH = 0
|
288
|
+
DEFAULT_MAX_STRING_LENGTH = 0
|
256
289
|
|
257
|
-
|
290
|
+
DDWAF_MAX_CONTAINER_SIZE = 256
|
291
|
+
DDWAF_MAX_CONTAINER_DEPTH = 20
|
292
|
+
DDWAF_MAX_STRING_LENGTH = 4096
|
258
293
|
|
259
|
-
|
294
|
+
DDWAF_RUN_TIMEOUT = 5000
|
260
295
|
end
|
261
296
|
|
262
297
|
def self.version
|
263
|
-
|
264
|
-
LibDDWAF.ddwaf_get_version(version.pointer)
|
265
|
-
|
266
|
-
[version[:major], version[:minor], version[:patch]]
|
298
|
+
LibDDWAF.ddwaf_get_version
|
267
299
|
end
|
268
300
|
|
269
|
-
def self.ruby_to_object(val)
|
301
|
+
def self.ruby_to_object(val, max_container_size: nil, max_container_depth: nil, max_string_length: nil, coerce: true)
|
270
302
|
case val
|
271
303
|
when Array
|
272
304
|
obj = LibDDWAF::Object.new
|
@@ -275,12 +307,20 @@ module Datadog
|
|
275
307
|
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
276
308
|
end
|
277
309
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
310
|
+
max_index = max_container_size - 1 if max_container_size
|
311
|
+
val.each.with_index do |e, i|
|
312
|
+
member = ruby_to_object(e,
|
313
|
+
max_container_size: max_container_size,
|
314
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
315
|
+
max_string_length: max_string_length,
|
316
|
+
coerce: coerce)
|
317
|
+
e_res = LibDDWAF.ddwaf_object_array_add(obj, member)
|
318
|
+
unless e_res
|
319
|
+
fail LibDDWAF::Error, "Could not add to array object: #{e.inspect}"
|
282
320
|
end
|
283
|
-
|
321
|
+
|
322
|
+
break val if max_index && i >= max_index
|
323
|
+
end unless max_container_depth == 0
|
284
324
|
|
285
325
|
obj
|
286
326
|
when Hash
|
@@ -290,36 +330,56 @@ module Datadog
|
|
290
330
|
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
291
331
|
end
|
292
332
|
|
293
|
-
|
294
|
-
|
295
|
-
|
333
|
+
max_index = max_container_size - 1 if max_container_size
|
334
|
+
val.each.with_index do |e, i|
|
335
|
+
k, v = e[0], e[1] # for Steep, which doesn't handle |(k, v), i|
|
336
|
+
|
337
|
+
k = k.to_s[0, max_string_length] if max_string_length
|
338
|
+
member = ruby_to_object(v,
|
339
|
+
max_container_size: max_container_size,
|
340
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
341
|
+
max_string_length: max_string_length,
|
342
|
+
coerce: coerce)
|
343
|
+
kv_res = LibDDWAF.ddwaf_object_map_addl(obj, k.to_s, k.to_s.bytesize, member)
|
344
|
+
unless kv_res
|
296
345
|
fail LibDDWAF::Error, "Could not add to map object: #{k.inspect} => #{v.inspect}"
|
297
346
|
end
|
298
|
-
|
347
|
+
|
348
|
+
break val if max_index && i >= max_index
|
349
|
+
end unless max_container_depth == 0
|
299
350
|
|
300
351
|
obj
|
301
352
|
when String
|
302
353
|
obj = LibDDWAF::Object.new
|
303
|
-
|
354
|
+
val = val.to_s[0, max_string_length] if max_string_length
|
355
|
+
str = val.to_s
|
356
|
+
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
304
357
|
if res.null?
|
305
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
358
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
306
359
|
end
|
307
360
|
|
308
361
|
obj
|
309
362
|
when Symbol
|
310
363
|
obj = LibDDWAF::Object.new
|
364
|
+
val = val.to_s[0, max_string_length] if max_string_length
|
311
365
|
str = val.to_s
|
312
366
|
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
313
367
|
if res.null?
|
314
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
368
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
315
369
|
end
|
316
370
|
|
317
371
|
obj
|
318
372
|
when Integer
|
319
373
|
obj = LibDDWAF::Object.new
|
320
|
-
res =
|
374
|
+
res = if coerce
|
375
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
376
|
+
elsif val < 0
|
377
|
+
LibDDWAF.ddwaf_object_signed_force(obj, val)
|
378
|
+
else
|
379
|
+
LibDDWAF.ddwaf_object_unsigned_force(obj, val)
|
380
|
+
end
|
321
381
|
if res.null?
|
322
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
382
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
323
383
|
end
|
324
384
|
|
325
385
|
obj
|
@@ -327,15 +387,19 @@ module Datadog
|
|
327
387
|
obj = LibDDWAF::Object.new
|
328
388
|
res = LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
329
389
|
if res.null?
|
330
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
390
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
331
391
|
end
|
332
392
|
|
333
393
|
obj
|
334
394
|
when TrueClass, FalseClass
|
335
395
|
obj = LibDDWAF::Object.new
|
336
|
-
res =
|
396
|
+
res = if coerce
|
397
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
398
|
+
else
|
399
|
+
LibDDWAF.ddwaf_object_bool(obj, val)
|
400
|
+
end
|
337
401
|
if res.null?
|
338
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
402
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
339
403
|
end
|
340
404
|
|
341
405
|
obj
|
@@ -348,6 +412,8 @@ module Datadog
|
|
348
412
|
case obj[:type]
|
349
413
|
when :ddwaf_obj_invalid
|
350
414
|
nil
|
415
|
+
when :ddwaf_obj_bool
|
416
|
+
obj[:valueUnion][:boolean]
|
351
417
|
when :ddwaf_obj_string
|
352
418
|
obj[:valueUnion][:stringValue].read_bytes(obj[:nbEntries])
|
353
419
|
when :ddwaf_obj_signed
|
@@ -372,21 +438,47 @@ module Datadog
|
|
372
438
|
end
|
373
439
|
end
|
374
440
|
|
441
|
+
def self.log_callback(level, func, file, line, message, len)
|
442
|
+
return if logger.nil?
|
443
|
+
|
444
|
+
logger.debug do
|
445
|
+
{
|
446
|
+
level: level,
|
447
|
+
func: func,
|
448
|
+
file: file,
|
449
|
+
line: line,
|
450
|
+
message: message.read_bytes(len)
|
451
|
+
}.inspect
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def self.logger
|
456
|
+
@logger
|
457
|
+
end
|
458
|
+
|
375
459
|
def self.logger=(logger)
|
376
|
-
@
|
377
|
-
|
460
|
+
unless @log_callback
|
461
|
+
log_callback = method(:log_callback)
|
462
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_set_log_cb(log_callback, :ddwaf_log_trace)
|
463
|
+
|
464
|
+
# retain logging proc if set properly
|
465
|
+
@log_callback = log_callback
|
378
466
|
end
|
379
467
|
|
380
|
-
|
468
|
+
@logger = logger
|
381
469
|
end
|
382
470
|
|
471
|
+
RESULT_CODE = {
|
472
|
+
ddwaf_err_internal: :err_internal,
|
473
|
+
ddwaf_err_invalid_object: :err_invalid_object,
|
474
|
+
ddwaf_err_invalid_argument: :err_invalid_argument,
|
475
|
+
ddwaf_ok: :ok,
|
476
|
+
ddwaf_match: :match,
|
477
|
+
}
|
478
|
+
|
383
479
|
class Handle
|
384
480
|
attr_reader :handle_obj
|
385
481
|
|
386
|
-
DEFAULT_MAX_CONTAINER_SIZE = 0
|
387
|
-
DEFAULT_MAX_CONTAINER_DEPTH = 0
|
388
|
-
DEFAULT_MAX_STRING_LENGTH = 0
|
389
|
-
|
390
482
|
attr_reader :ruleset_info
|
391
483
|
|
392
484
|
def initialize(rule, limits: {}, obfuscator: {})
|
@@ -399,12 +491,14 @@ module Datadog
|
|
399
491
|
if config_obj.null?
|
400
492
|
fail LibDDWAF::Error, 'Could not create config struct'
|
401
493
|
end
|
494
|
+
retain(config_obj)
|
402
495
|
|
403
|
-
config_obj[:limits][:max_container_size] = limits[:max_container_size] || DEFAULT_MAX_CONTAINER_SIZE
|
404
|
-
config_obj[:limits][:max_container_depth] = limits[:max_container_depth] || DEFAULT_MAX_CONTAINER_DEPTH
|
405
|
-
config_obj[:limits][:max_string_length] = limits[:max_string_length] || DEFAULT_MAX_STRING_LENGTH
|
496
|
+
config_obj[:limits][:max_container_size] = limits[:max_container_size] || LibDDWAF::DEFAULT_MAX_CONTAINER_SIZE
|
497
|
+
config_obj[:limits][:max_container_depth] = limits[:max_container_depth] || LibDDWAF::DEFAULT_MAX_CONTAINER_DEPTH
|
498
|
+
config_obj[:limits][:max_string_length] = limits[:max_string_length] || LibDDWAF::DEFAULT_MAX_STRING_LENGTH
|
406
499
|
config_obj[:obfuscator][:key_regex] = FFI::MemoryPointer.from_string(obfuscator[:key_regex]) if obfuscator[:key_regex]
|
407
500
|
config_obj[:obfuscator][:value_regex] = FFI::MemoryPointer.from_string(obfuscator[:value_regex]) if obfuscator[:value_regex]
|
501
|
+
config_obj[:free_fn] = Datadog::AppSec::WAF::LibDDWAF::ObjectNoFree
|
408
502
|
|
409
503
|
ruleset_info = LibDDWAF::RuleSetInfo.new
|
410
504
|
|
@@ -421,19 +515,21 @@ module Datadog
|
|
421
515
|
fail LibDDWAF::Error.new('Could not create handle', ruleset_info: @ruleset_info)
|
422
516
|
end
|
423
517
|
|
424
|
-
|
518
|
+
validate!
|
425
519
|
ensure
|
426
520
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_ruleset_info_free(ruleset_info) if ruleset_info
|
427
521
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(rule_obj) if rule_obj
|
428
522
|
end
|
429
523
|
|
430
|
-
def
|
431
|
-
|
432
|
-
|
433
|
-
|
524
|
+
def finalize
|
525
|
+
invalidate!
|
526
|
+
|
527
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_destroy(handle_obj)
|
434
528
|
end
|
435
529
|
|
436
530
|
def required_addresses
|
531
|
+
valid!
|
532
|
+
|
437
533
|
count = Datadog::AppSec::WAF::LibDDWAF::UInt32Ptr.new
|
438
534
|
list = Datadog::AppSec::WAF::LibDDWAF.ddwaf_required_addresses(handle_obj, count)
|
439
535
|
|
@@ -441,48 +537,108 @@ module Datadog
|
|
441
537
|
|
442
538
|
list.get_array_of_string(0, count[:value])
|
443
539
|
end
|
540
|
+
|
541
|
+
def update_rule_data(data)
|
542
|
+
data_obj = Datadog::AppSec::WAF.ruby_to_object(data, coerce: false)
|
543
|
+
res = Datadog::AppSec::WAF::LibDDWAF.ddwaf_update_rule_data(@handle_obj, data_obj)
|
544
|
+
|
545
|
+
RESULT_CODE[res]
|
546
|
+
ensure
|
547
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(data_obj) if data_obj
|
548
|
+
end
|
549
|
+
|
550
|
+
def toggle_rules(map)
|
551
|
+
map_obj = Datadog::AppSec::WAF.ruby_to_object(map, coerce: false)
|
552
|
+
res = Datadog::AppSec::WAF::LibDDWAF.ddwaf_toggle_rules(@handle_obj, map_obj)
|
553
|
+
|
554
|
+
RESULT_CODE[res]
|
555
|
+
ensure
|
556
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(map_obj) if map_obj
|
557
|
+
end
|
558
|
+
|
559
|
+
private
|
560
|
+
|
561
|
+
def validate!
|
562
|
+
@valid = true
|
563
|
+
end
|
564
|
+
|
565
|
+
def invalidate!
|
566
|
+
@valid = false
|
567
|
+
end
|
568
|
+
|
569
|
+
def valid?
|
570
|
+
@valid
|
571
|
+
end
|
572
|
+
|
573
|
+
def valid!
|
574
|
+
return if valid?
|
575
|
+
|
576
|
+
fail LibDDWAF::Error, "Attempt to use an invalid instance: #{inspect}"
|
577
|
+
end
|
578
|
+
|
579
|
+
def retained
|
580
|
+
@retained ||= []
|
581
|
+
end
|
582
|
+
|
583
|
+
def retain(object)
|
584
|
+
retained << object
|
585
|
+
end
|
586
|
+
|
587
|
+
def release(object)
|
588
|
+
retained.delete(object)
|
589
|
+
end
|
444
590
|
end
|
445
591
|
|
446
|
-
Result
|
592
|
+
class Result
|
593
|
+
attr_reader :status, :data, :total_runtime, :timeout, :actions
|
594
|
+
|
595
|
+
def initialize(status, data, total_runtime, timeout, actions)
|
596
|
+
@status = status
|
597
|
+
@data = data
|
598
|
+
@total_runtime = total_runtime
|
599
|
+
@timeout = timeout
|
600
|
+
@actions = actions
|
601
|
+
end
|
602
|
+
end
|
447
603
|
|
448
604
|
class Context
|
449
605
|
attr_reader :context_obj
|
450
606
|
|
451
607
|
def initialize(handle)
|
452
608
|
handle_obj = handle.handle_obj
|
453
|
-
|
609
|
+
retain(handle)
|
454
610
|
|
455
|
-
@context_obj = Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_init(handle_obj
|
611
|
+
@context_obj = Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_init(handle_obj)
|
456
612
|
if @context_obj.null?
|
457
613
|
fail LibDDWAF::Error, 'Could not create context'
|
458
614
|
end
|
459
615
|
|
460
|
-
|
461
|
-
|
462
|
-
ObjectSpace.define_finalizer(self, Context.finalizer(context_obj, @input_objs))
|
616
|
+
validate!
|
463
617
|
end
|
464
618
|
|
465
|
-
def
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
619
|
+
def finalize
|
620
|
+
invalidate!
|
621
|
+
|
622
|
+
retained.each do |retained_obj|
|
623
|
+
next unless retained_obj.is_a?(Datadog::AppSec::WAF::LibDDWAF::Object)
|
624
|
+
|
625
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(retained_obj)
|
471
626
|
end
|
627
|
+
|
628
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_destroy(context_obj)
|
472
629
|
end
|
473
630
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
ddwaf_monitor: :monitor,
|
481
|
-
ddwaf_block: :block,
|
482
|
-
}
|
631
|
+
def run(input, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT)
|
632
|
+
valid!
|
633
|
+
|
634
|
+
max_container_size = LibDDWAF::DDWAF_MAX_CONTAINER_SIZE
|
635
|
+
max_container_depth = LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH
|
636
|
+
max_string_length = LibDDWAF::DDWAF_MAX_STRING_LENGTH
|
483
637
|
|
484
|
-
|
485
|
-
|
638
|
+
input_obj = Datadog::AppSec::WAF.ruby_to_object(input,
|
639
|
+
max_container_size: max_container_size,
|
640
|
+
max_container_depth: max_container_depth,
|
641
|
+
max_string_length: max_string_length)
|
486
642
|
if input_obj.null?
|
487
643
|
fail LibDDWAF::Error, "Could not convert input: #{input.inspect}"
|
488
644
|
end
|
@@ -493,21 +649,60 @@ module Datadog
|
|
493
649
|
end
|
494
650
|
|
495
651
|
# retain C objects in memory for subsequent calls to run
|
496
|
-
|
652
|
+
retain(input_obj)
|
497
653
|
|
498
654
|
code = Datadog::AppSec::WAF::LibDDWAF.ddwaf_run(@context_obj, input_obj, result_obj, timeout)
|
499
655
|
|
656
|
+
actions = if result_obj[:actions][:size] > 0
|
657
|
+
result_obj[:actions][:array].get_array_of_string(0, result_obj[:actions][:size])
|
658
|
+
else
|
659
|
+
[]
|
660
|
+
end
|
661
|
+
|
500
662
|
result = Result.new(
|
501
|
-
|
663
|
+
RESULT_CODE[code],
|
502
664
|
(JSON.parse(result_obj[:data]) if result_obj[:data] != nil),
|
503
665
|
result_obj[:total_runtime],
|
504
666
|
result_obj[:timeout],
|
667
|
+
actions,
|
505
668
|
)
|
506
669
|
|
507
|
-
[
|
670
|
+
[RESULT_CODE[code], result]
|
508
671
|
ensure
|
509
672
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_result_free(result_obj) if result_obj
|
510
673
|
end
|
674
|
+
|
675
|
+
private
|
676
|
+
|
677
|
+
def validate!
|
678
|
+
@valid = true
|
679
|
+
end
|
680
|
+
|
681
|
+
def invalidate!
|
682
|
+
@valid = false
|
683
|
+
end
|
684
|
+
|
685
|
+
def valid?
|
686
|
+
@valid
|
687
|
+
end
|
688
|
+
|
689
|
+
def valid!
|
690
|
+
return if valid?
|
691
|
+
|
692
|
+
fail LibDDWAF::Error, "Attempt to use an invalid instance: #{inspect}"
|
693
|
+
end
|
694
|
+
|
695
|
+
def retained
|
696
|
+
@retained ||= []
|
697
|
+
end
|
698
|
+
|
699
|
+
def retain(object)
|
700
|
+
retained << object
|
701
|
+
end
|
702
|
+
|
703
|
+
def release(object)
|
704
|
+
retained.delete(object)
|
705
|
+
end
|
511
706
|
end
|
512
707
|
end
|
513
708
|
end
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libddwaf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.1.0.1
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -33,6 +33,7 @@ executables: []
|
|
33
33
|
extensions: []
|
34
34
|
extra_rdoc_files: []
|
35
35
|
files:
|
36
|
+
- CHANGELOG.md
|
36
37
|
- LICENSE
|
37
38
|
- LICENSE-3rdparty.csv
|
38
39
|
- LICENSE.Apache
|
@@ -41,14 +42,13 @@ files:
|
|
41
42
|
- lib/datadog/appsec/waf.rb
|
42
43
|
- lib/datadog/appsec/waf/version.rb
|
43
44
|
- lib/libddwaf.rb
|
44
|
-
- vendor/libddwaf/libddwaf-1.
|
45
|
-
|
46
|
-
homepage: https://github.com/DataDog/libddwaf
|
45
|
+
- vendor/libddwaf/libddwaf-1.5.1-linux-x86_64/lib/libddwaf.so
|
46
|
+
homepage: https://github.com/DataDog/libddwaf-rb
|
47
47
|
licenses:
|
48
48
|
- BSD-3-Clause
|
49
49
|
metadata:
|
50
50
|
allowed_push_host: https://rubygems.org
|
51
|
-
post_install_message:
|
51
|
+
post_install_message:
|
52
52
|
rdoc_options: []
|
53
53
|
require_paths:
|
54
54
|
- lib
|
@@ -63,8 +63,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
63
|
- !ruby/object:Gem::Version
|
64
64
|
version: 2.0.0
|
65
65
|
requirements: []
|
66
|
-
rubygems_version: 3.2
|
67
|
-
signing_key:
|
66
|
+
rubygems_version: 3.1.2
|
67
|
+
signing_key:
|
68
68
|
specification_version: 4
|
69
69
|
summary: Datadog WAF
|
70
70
|
test_files: []
|
Binary file
|
Binary file
|