libddwaf 1.3.0.1.0-x86_64-linux → 1.5.1.0.0-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 +74 -0
- data/lib/datadog/appsec/waf/version.rb +2 -2
- data/lib/datadog/appsec/waf.rb +306 -90
- data/vendor/libddwaf/libddwaf-1.5.1-linux-x86_64/lib/libddwaf.so +0 -0
- metadata +5 -5
- data/vendor/libddwaf/libddwaf-1.3.0-linux-x86_64/include/ddwaf.h +0 -624
- data/vendor/libddwaf/libddwaf-1.3.0-linux-x86_64/lib/libddwaf.so +0 -0
data/lib/datadog/appsec/waf.rb
CHANGED
@@ -32,12 +32,22 @@ module Datadog
|
|
32
32
|
Gem::Platform.local.os
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.local_version
|
36
|
+
return nil unless local_os == 'linux'
|
37
|
+
|
38
|
+
# Old rubygems don't handle non-gnu linux correctly
|
39
|
+
return $1 if RUBY_PLATFORM =~ /linux-(.+)$/
|
40
|
+
|
41
|
+
'gnu'
|
42
|
+
end
|
43
|
+
|
35
44
|
def self.local_cpu
|
36
45
|
if RUBY_ENGINE == 'jruby'
|
37
46
|
os_arch = java.lang.System.get_property('os.arch')
|
38
47
|
|
39
48
|
cpu = case os_arch
|
40
49
|
when 'amd64' then 'x86_64'
|
50
|
+
when 'aarch64' then 'aarch64'
|
41
51
|
else raise Error, "unsupported JRuby os.arch: #{os_arch.inspect}"
|
42
52
|
end
|
43
53
|
|
@@ -47,27 +57,50 @@ module Datadog
|
|
47
57
|
Gem::Platform.local.cpu
|
48
58
|
end
|
49
59
|
|
60
|
+
def self.source_dir
|
61
|
+
__dir__ || raise('__dir__ is nil: eval?')
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.vendor_dir
|
65
|
+
File.join(source_dir, '../../../vendor')
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.libddwaf_vendor_dir
|
69
|
+
File.join(vendor_dir, 'libddwaf')
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.shared_lib_triplet(version: local_version)
|
73
|
+
version ? "#{local_os}-#{version}-#{local_cpu}" : "#{local_os}-#{local_cpu}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.libddwaf_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
|
89
|
+
end
|
90
|
+
|
50
91
|
def self.shared_lib_extname
|
51
92
|
Gem::Platform.local.os == 'darwin' ? '.dylib' : '.so'
|
52
93
|
end
|
53
94
|
|
54
95
|
def self.shared_lib_path
|
55
|
-
File.join(
|
96
|
+
File.join(libddwaf_dir, 'lib', "libddwaf#{shared_lib_extname}")
|
56
97
|
end
|
57
98
|
|
58
99
|
ffi_lib [shared_lib_path]
|
59
100
|
|
60
101
|
# version
|
61
102
|
|
62
|
-
|
63
|
-
layout :major, :uint16,
|
64
|
-
:minor, :uint16,
|
65
|
-
:patch, :uint16
|
66
|
-
end
|
67
|
-
|
68
|
-
typedef Version.by_ref, :ddwaf_version
|
69
|
-
|
70
|
-
attach_function :ddwaf_get_version, [:ddwaf_version], :void
|
103
|
+
attach_function :ddwaf_get_version, [], :string
|
71
104
|
|
72
105
|
# ddwaf::object data structure
|
73
106
|
|
@@ -76,7 +109,9 @@ module Datadog
|
|
76
109
|
:ddwaf_obj_unsigned, 1 << 1,
|
77
110
|
:ddwaf_obj_string, 1 << 2,
|
78
111
|
:ddwaf_obj_array, 1 << 3,
|
79
|
-
: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
|
80
115
|
|
81
116
|
typedef :pointer, :charptr
|
82
117
|
typedef :pointer, :charptrptr
|
@@ -103,7 +138,8 @@ module Datadog
|
|
103
138
|
layout :stringValue, :charptr,
|
104
139
|
:uintValue, :uint64,
|
105
140
|
:intValue, :int64,
|
106
|
-
:array, :pointer
|
141
|
+
:array, :pointer,
|
142
|
+
:boolean, :bool
|
107
143
|
end
|
108
144
|
|
109
145
|
class Object < ::FFI::Struct
|
@@ -111,7 +147,7 @@ module Datadog
|
|
111
147
|
:parameterNameLength, :uint64,
|
112
148
|
:valueUnion, ObjectValueUnion,
|
113
149
|
:nbEntries, :uint64,
|
114
|
-
:type,
|
150
|
+
:type, :ddwaf_obj_type
|
115
151
|
end
|
116
152
|
|
117
153
|
typedef Object.by_ref, :ddwaf_object
|
@@ -126,6 +162,7 @@ module Datadog
|
|
126
162
|
attach_function :ddwaf_object_signed, [:ddwaf_object, :int64], :ddwaf_object
|
127
163
|
attach_function :ddwaf_object_unsigned_force, [:ddwaf_object, :uint64], :ddwaf_object
|
128
164
|
attach_function :ddwaf_object_signed_force, [:ddwaf_object, :int64], :ddwaf_object
|
165
|
+
attach_function :ddwaf_object_bool, [:ddwaf_object, :bool], :ddwaf_object
|
129
166
|
|
130
167
|
attach_function :ddwaf_object_array, [:ddwaf_object], :ddwaf_object
|
131
168
|
attach_function :ddwaf_object_array_add, [:ddwaf_object, :ddwaf_object], :bool
|
@@ -156,6 +193,8 @@ module Datadog
|
|
156
193
|
typedef :pointer, :ddwaf_handle
|
157
194
|
typedef Object.by_ref, :ddwaf_rule
|
158
195
|
|
196
|
+
callback :ddwaf_object_free_fn, [:ddwaf_object], :void
|
197
|
+
|
159
198
|
class Config < ::FFI::Struct
|
160
199
|
class Limits < ::FFI::Struct
|
161
200
|
layout :max_container_size, :uint32,
|
@@ -169,7 +208,8 @@ module Datadog
|
|
169
208
|
end
|
170
209
|
|
171
210
|
layout :limits, Limits,
|
172
|
-
:obfuscator, Obfuscator
|
211
|
+
:obfuscator, Obfuscator,
|
212
|
+
:free_fn, :pointer #:ddwaf_object_free_fn
|
173
213
|
end
|
174
214
|
|
175
215
|
typedef Config.by_ref, :ddwaf_config
|
@@ -190,33 +230,43 @@ module Datadog
|
|
190
230
|
attach_function :ddwaf_destroy, [:ddwaf_handle], :void
|
191
231
|
|
192
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
|
193
246
|
|
194
247
|
# running
|
195
248
|
|
196
249
|
typedef :pointer, :ddwaf_context
|
197
250
|
|
198
|
-
|
199
|
-
|
200
|
-
attach_function :ddwaf_context_init, [:ddwaf_handle, :ddwaf_object_free_fn], :ddwaf_context
|
251
|
+
attach_function :ddwaf_context_init, [:ddwaf_handle], :ddwaf_context
|
201
252
|
attach_function :ddwaf_context_destroy, [:ddwaf_context], :void
|
202
253
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
:ddwaf_monitor, 1,
|
208
|
-
:ddwaf_block, 2
|
254
|
+
class ResultActions < ::FFI::Struct
|
255
|
+
layout :array, :charptrptr,
|
256
|
+
:size, :uint32
|
257
|
+
end
|
209
258
|
|
210
259
|
class Result < ::FFI::Struct
|
211
260
|
layout :timeout, :bool,
|
212
261
|
:data, :string,
|
262
|
+
:actions, ResultActions,
|
213
263
|
:total_runtime, :uint64
|
214
264
|
end
|
215
265
|
|
216
266
|
typedef Result.by_ref, :ddwaf_result
|
217
267
|
typedef :uint64, :timeout_us
|
218
268
|
|
219
|
-
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
|
220
270
|
attach_function :ddwaf_result_free, [:ddwaf_result], :void
|
221
271
|
|
222
272
|
# logging
|
@@ -227,20 +277,28 @@ module Datadog
|
|
227
277
|
:ddwaf_log_warn,
|
228
278
|
:ddwaf_log_error,
|
229
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
|
230
283
|
|
231
|
-
|
284
|
+
attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
|
232
285
|
|
233
|
-
|
286
|
+
DEFAULT_MAX_CONTAINER_SIZE = 0
|
287
|
+
DEFAULT_MAX_CONTAINER_DEPTH = 0
|
288
|
+
DEFAULT_MAX_STRING_LENGTH = 0
|
289
|
+
|
290
|
+
DDWAF_MAX_CONTAINER_SIZE = 256
|
291
|
+
DDWAF_MAX_CONTAINER_DEPTH = 20
|
292
|
+
DDWAF_MAX_STRING_LENGTH = 4096
|
293
|
+
|
294
|
+
DDWAF_RUN_TIMEOUT = 5000
|
234
295
|
end
|
235
296
|
|
236
297
|
def self.version
|
237
|
-
|
238
|
-
LibDDWAF.ddwaf_get_version(version.pointer)
|
239
|
-
|
240
|
-
[version[:major], version[:minor], version[:patch]]
|
298
|
+
LibDDWAF.ddwaf_get_version
|
241
299
|
end
|
242
300
|
|
243
|
-
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)
|
244
302
|
case val
|
245
303
|
when Array
|
246
304
|
obj = LibDDWAF::Object.new
|
@@ -249,12 +307,20 @@ module Datadog
|
|
249
307
|
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
250
308
|
end
|
251
309
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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}"
|
256
320
|
end
|
257
|
-
|
321
|
+
|
322
|
+
break val if max_index && i >= max_index
|
323
|
+
end unless max_container_depth == 0
|
258
324
|
|
259
325
|
obj
|
260
326
|
when Hash
|
@@ -264,35 +330,56 @@ module Datadog
|
|
264
330
|
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
265
331
|
end
|
266
332
|
|
267
|
-
|
268
|
-
|
269
|
-
|
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
|
270
345
|
fail LibDDWAF::Error, "Could not add to map object: #{k.inspect} => #{v.inspect}"
|
271
346
|
end
|
272
|
-
|
347
|
+
|
348
|
+
break val if max_index && i >= max_index
|
349
|
+
end unless max_container_depth == 0
|
273
350
|
|
274
351
|
obj
|
275
352
|
when String
|
276
353
|
obj = LibDDWAF::Object.new
|
277
|
-
|
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)
|
278
357
|
if res.null?
|
279
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
358
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
280
359
|
end
|
281
360
|
|
282
361
|
obj
|
283
362
|
when Symbol
|
284
363
|
obj = LibDDWAF::Object.new
|
285
|
-
|
364
|
+
val = val.to_s[0, max_string_length] if max_string_length
|
365
|
+
str = val.to_s
|
366
|
+
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
286
367
|
if res.null?
|
287
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
368
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
288
369
|
end
|
289
370
|
|
290
371
|
obj
|
291
372
|
when Integer
|
292
373
|
obj = LibDDWAF::Object.new
|
293
|
-
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
|
294
381
|
if res.null?
|
295
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
382
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
296
383
|
end
|
297
384
|
|
298
385
|
obj
|
@@ -300,15 +387,19 @@ module Datadog
|
|
300
387
|
obj = LibDDWAF::Object.new
|
301
388
|
res = LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
302
389
|
if res.null?
|
303
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
390
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
304
391
|
end
|
305
392
|
|
306
393
|
obj
|
307
394
|
when TrueClass, FalseClass
|
308
395
|
obj = LibDDWAF::Object.new
|
309
|
-
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
|
310
401
|
if res.null?
|
311
|
-
fail LibDDWAF::Error, "Could not convert into object: #{val}"
|
402
|
+
fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
312
403
|
end
|
313
404
|
|
314
405
|
obj
|
@@ -321,6 +412,8 @@ module Datadog
|
|
321
412
|
case obj[:type]
|
322
413
|
when :ddwaf_obj_invalid
|
323
414
|
nil
|
415
|
+
when :ddwaf_obj_bool
|
416
|
+
obj[:valueUnion][:boolean]
|
324
417
|
when :ddwaf_obj_string
|
325
418
|
obj[:valueUnion][:stringValue].read_bytes(obj[:nbEntries])
|
326
419
|
when :ddwaf_obj_signed
|
@@ -345,21 +438,47 @@ module Datadog
|
|
345
438
|
end
|
346
439
|
end
|
347
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
|
+
|
348
459
|
def self.logger=(logger)
|
349
|
-
@
|
350
|
-
|
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
|
351
466
|
end
|
352
467
|
|
353
|
-
|
468
|
+
@logger = logger
|
354
469
|
end
|
355
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
|
+
|
356
479
|
class Handle
|
357
480
|
attr_reader :handle_obj
|
358
481
|
|
359
|
-
DEFAULT_MAX_CONTAINER_SIZE = 0
|
360
|
-
DEFAULT_MAX_CONTAINER_DEPTH = 0
|
361
|
-
DEFAULT_MAX_STRING_LENGTH = 0
|
362
|
-
|
363
482
|
attr_reader :ruleset_info
|
364
483
|
|
365
484
|
def initialize(rule, limits: {}, obfuscator: {})
|
@@ -372,12 +491,14 @@ module Datadog
|
|
372
491
|
if config_obj.null?
|
373
492
|
fail LibDDWAF::Error, 'Could not create config struct'
|
374
493
|
end
|
494
|
+
retain(config_obj)
|
375
495
|
|
376
|
-
config_obj[:limits][:max_container_size] = limits[:max_container_size] || DEFAULT_MAX_CONTAINER_SIZE
|
377
|
-
config_obj[:limits][:max_container_depth] = limits[:max_container_depth] || DEFAULT_MAX_CONTAINER_DEPTH
|
378
|
-
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
|
379
499
|
config_obj[:obfuscator][:key_regex] = FFI::MemoryPointer.from_string(obfuscator[:key_regex]) if obfuscator[:key_regex]
|
380
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
|
381
502
|
|
382
503
|
ruleset_info = LibDDWAF::RuleSetInfo.new
|
383
504
|
|
@@ -394,19 +515,21 @@ module Datadog
|
|
394
515
|
fail LibDDWAF::Error.new('Could not create handle', ruleset_info: @ruleset_info)
|
395
516
|
end
|
396
517
|
|
397
|
-
|
518
|
+
validate!
|
398
519
|
ensure
|
399
520
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_ruleset_info_free(ruleset_info) if ruleset_info
|
400
521
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(rule_obj) if rule_obj
|
401
522
|
end
|
402
523
|
|
403
|
-
def
|
404
|
-
|
405
|
-
|
406
|
-
|
524
|
+
def finalize
|
525
|
+
invalidate!
|
526
|
+
|
527
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_destroy(handle_obj)
|
407
528
|
end
|
408
529
|
|
409
530
|
def required_addresses
|
531
|
+
valid!
|
532
|
+
|
410
533
|
count = Datadog::AppSec::WAF::LibDDWAF::UInt32Ptr.new
|
411
534
|
list = Datadog::AppSec::WAF::LibDDWAF.ddwaf_required_addresses(handle_obj, count)
|
412
535
|
|
@@ -414,48 +537,102 @@ module Datadog
|
|
414
537
|
|
415
538
|
list.get_array_of_string(0, count[:value])
|
416
539
|
end
|
540
|
+
|
541
|
+
def update_rule_data(data)
|
542
|
+
res = Datadog::AppSec::WAF::LibDDWAF.ddwaf_update_rule_data(@handle_obj, Datadog::AppSec::WAF.ruby_to_object(data, coerce: false))
|
543
|
+
|
544
|
+
RESULT_CODE[res]
|
545
|
+
end
|
546
|
+
|
547
|
+
def toggle_rules(map)
|
548
|
+
res = Datadog::AppSec::WAF::LibDDWAF.ddwaf_toggle_rules(@handle_obj, Datadog::AppSec::WAF.ruby_to_object(map, coerce: false))
|
549
|
+
|
550
|
+
RESULT_CODE[res]
|
551
|
+
end
|
552
|
+
|
553
|
+
private
|
554
|
+
|
555
|
+
def validate!
|
556
|
+
@valid = true
|
557
|
+
end
|
558
|
+
|
559
|
+
def invalidate!
|
560
|
+
@valid = false
|
561
|
+
end
|
562
|
+
|
563
|
+
def valid?
|
564
|
+
@valid
|
565
|
+
end
|
566
|
+
|
567
|
+
def valid!
|
568
|
+
return if valid?
|
569
|
+
|
570
|
+
fail LibDDWAF::Error, "Attempt to use an invalid instance: #{inspect}"
|
571
|
+
end
|
572
|
+
|
573
|
+
def retained
|
574
|
+
@retained ||= []
|
575
|
+
end
|
576
|
+
|
577
|
+
def retain(object)
|
578
|
+
retained << object
|
579
|
+
end
|
580
|
+
|
581
|
+
def release(object)
|
582
|
+
retained.delete(object)
|
583
|
+
end
|
417
584
|
end
|
418
585
|
|
419
|
-
Result
|
586
|
+
class Result
|
587
|
+
attr_reader :status, :data, :total_runtime, :timeout, :actions
|
588
|
+
|
589
|
+
def initialize(status, data, total_runtime, timeout, actions)
|
590
|
+
@status = status
|
591
|
+
@data = data
|
592
|
+
@total_runtime = total_runtime
|
593
|
+
@timeout = timeout
|
594
|
+
@actions = actions
|
595
|
+
end
|
596
|
+
end
|
420
597
|
|
421
598
|
class Context
|
422
599
|
attr_reader :context_obj
|
423
600
|
|
424
601
|
def initialize(handle)
|
425
602
|
handle_obj = handle.handle_obj
|
426
|
-
|
603
|
+
retain(handle)
|
427
604
|
|
428
|
-
@context_obj = Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_init(handle_obj
|
605
|
+
@context_obj = Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_init(handle_obj)
|
429
606
|
if @context_obj.null?
|
430
607
|
fail LibDDWAF::Error, 'Could not create context'
|
431
608
|
end
|
432
609
|
|
433
|
-
|
434
|
-
|
435
|
-
ObjectSpace.define_finalizer(self, Context.finalizer(context_obj, @input_objs))
|
610
|
+
validate!
|
436
611
|
end
|
437
612
|
|
438
|
-
def
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
613
|
+
def finalize
|
614
|
+
invalidate!
|
615
|
+
|
616
|
+
retained.each do |retained_obj|
|
617
|
+
next unless retained_obj.is_a?(Datadog::AppSec::WAF::LibDDWAF::Object)
|
618
|
+
|
619
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(retained_obj)
|
444
620
|
end
|
621
|
+
|
622
|
+
Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_destroy(context_obj)
|
445
623
|
end
|
446
624
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
ddwaf_monitor: :monitor,
|
454
|
-
ddwaf_block: :block,
|
455
|
-
}
|
625
|
+
def run(input, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT)
|
626
|
+
valid!
|
627
|
+
|
628
|
+
max_container_size = LibDDWAF::DDWAF_MAX_CONTAINER_SIZE
|
629
|
+
max_container_depth = LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH
|
630
|
+
max_string_length = LibDDWAF::DDWAF_MAX_CONTAINER_SIZE
|
456
631
|
|
457
|
-
|
458
|
-
|
632
|
+
input_obj = Datadog::AppSec::WAF.ruby_to_object(input,
|
633
|
+
max_container_size: max_container_size,
|
634
|
+
max_container_depth: max_container_depth,
|
635
|
+
max_string_length: max_string_length)
|
459
636
|
if input_obj.null?
|
460
637
|
fail LibDDWAF::Error, "Could not convert input: #{input.inspect}"
|
461
638
|
end
|
@@ -466,21 +643,60 @@ module Datadog
|
|
466
643
|
end
|
467
644
|
|
468
645
|
# retain C objects in memory for subsequent calls to run
|
469
|
-
|
646
|
+
retain(input_obj)
|
470
647
|
|
471
648
|
code = Datadog::AppSec::WAF::LibDDWAF.ddwaf_run(@context_obj, input_obj, result_obj, timeout)
|
472
649
|
|
650
|
+
actions = if result_obj[:actions][:size] > 0
|
651
|
+
result_obj[:actions][:array].get_array_of_string(0, result_obj[:actions][:size])
|
652
|
+
else
|
653
|
+
[]
|
654
|
+
end
|
655
|
+
|
473
656
|
result = Result.new(
|
474
|
-
|
657
|
+
RESULT_CODE[code],
|
475
658
|
(JSON.parse(result_obj[:data]) if result_obj[:data] != nil),
|
476
659
|
result_obj[:total_runtime],
|
477
660
|
result_obj[:timeout],
|
661
|
+
actions,
|
478
662
|
)
|
479
663
|
|
480
|
-
[
|
664
|
+
[RESULT_CODE[code], result]
|
481
665
|
ensure
|
482
666
|
Datadog::AppSec::WAF::LibDDWAF.ddwaf_result_free(result_obj) if result_obj
|
483
667
|
end
|
668
|
+
|
669
|
+
private
|
670
|
+
|
671
|
+
def validate!
|
672
|
+
@valid = true
|
673
|
+
end
|
674
|
+
|
675
|
+
def invalidate!
|
676
|
+
@valid = false
|
677
|
+
end
|
678
|
+
|
679
|
+
def valid?
|
680
|
+
@valid
|
681
|
+
end
|
682
|
+
|
683
|
+
def valid!
|
684
|
+
return if valid?
|
685
|
+
|
686
|
+
fail LibDDWAF::Error, "Attempt to use an invalid instance: #{inspect}"
|
687
|
+
end
|
688
|
+
|
689
|
+
def retained
|
690
|
+
@retained ||= []
|
691
|
+
end
|
692
|
+
|
693
|
+
def retain(object)
|
694
|
+
retained << object
|
695
|
+
end
|
696
|
+
|
697
|
+
def release(object)
|
698
|
+
retained.delete(object)
|
699
|
+
end
|
484
700
|
end
|
485
701
|
end
|
486
702
|
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.0
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04
|
11
|
+
date: 2022-10-04 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,9 +42,8 @@ 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:
|