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.
@@ -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(__dir__, "../../../vendor/libddwaf/libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{local_os}-#{local_cpu}/lib/libddwaf#{shared_lib_extname}")
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
- class Version < ::FFI::Struct
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, DDWAF_OBJ_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
- callback :ddwaf_object_free_fn, [:ddwaf_object], :void
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
- DDWAF_RET_CODE = enum :ddwaf_err_internal, -3,
204
- :ddwaf_err_invalid_object, -2,
205
- :ddwaf_err_invalid_argument, -1,
206
- :ddwaf_good, 0,
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], DDWAF_RET_CODE, blocking: true
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
- callback :ddwaf_log_cb, [DDWAF_LOG_LEVEL, :string, :string, :uint, :charptr, :uint64], :void
284
+ attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
232
285
 
233
- attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, DDWAF_LOG_LEVEL], :bool
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
- version = LibDDWAF::Version.new
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
- val.each do |e|
253
- res = LibDDWAF.ddwaf_object_array_add(obj, ruby_to_object(e))
254
- unless res
255
- fail LibDDWAF::Error, "Could not add to map object: #{k.inspect} => #{v.inspect}"
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
- end
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
- val.each do |k, v|
268
- res = LibDDWAF.ddwaf_object_map_addl(obj, k.to_s, k.to_s.size, ruby_to_object(v))
269
- unless res
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
- end
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
- res = LibDDWAF.ddwaf_object_stringl(obj, val, val.size)
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
- res = LibDDWAF.ddwaf_object_stringl(obj, val.to_s, val.size)
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 = LibDDWAF.ddwaf_object_string(obj, val.to_s)
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 = LibDDWAF.ddwaf_object_string(obj, val.to_s)
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
- @log_cb = proc do |level, func, file, line, message, len|
350
- logger.debug { { level: level, func: func, file: file, line: line, message: message.read_bytes(len) }.inspect }
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
- Datadog::AppSec::WAF::LibDDWAF.ddwaf_set_log_cb(@log_cb, :ddwaf_log_trace)
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
- ObjectSpace.define_finalizer(self, Handle.finalizer(handle_obj))
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 self.finalizer(handle_obj)
404
- proc do |object_id|
405
- Datadog::AppSec::WAF::LibDDWAF.ddwaf_destroy(handle_obj)
406
- end
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 = Struct.new(:action, :data, :total_runtime, :timeout)
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
- free_func = Datadog::AppSec::WAF::LibDDWAF::ObjectNoFree
603
+ retain(handle)
427
604
 
428
- @context_obj = Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_init(handle_obj, free_func)
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
- @input_objs = []
434
-
435
- ObjectSpace.define_finalizer(self, Context.finalizer(context_obj, @input_objs))
610
+ validate!
436
611
  end
437
612
 
438
- def self.finalizer(context_obj, input_objs)
439
- proc do |object_id|
440
- input_objs.each do |input_obj|
441
- Datadog::AppSec::WAF::LibDDWAF.ddwaf_object_free(input_obj)
442
- end
443
- Datadog::AppSec::WAF::LibDDWAF.ddwaf_context_destroy(context_obj)
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
- DEFAULT_TIMEOUT_US = 10_0000
448
- ACTION_MAP_OUT = {
449
- ddwaf_err_internal: :err_internal,
450
- ddwaf_err_invalid_object: :err_invalid_object,
451
- ddwaf_err_invalid_argument: :err_invalid_argument,
452
- ddwaf_good: :good,
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
- def run(input, timeout = DEFAULT_TIMEOUT_US)
458
- input_obj = Datadog::AppSec::WAF.ruby_to_object(input)
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
- @input_objs << input_obj
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
- ACTION_MAP_OUT[code],
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
- [ACTION_MAP_OUT[code], result]
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
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.3.0.1.0
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-29 00:00:00.000000000 Z
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.3.0-linux-x86_64/include/ddwaf.h
45
- - vendor/libddwaf/libddwaf-1.3.0-linux-x86_64/lib/libddwaf.so
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: