libddwaf 1.3.0.1.0-x86_64-darwin → 1.5.1.0.0-x86_64-darwin

Sign up to get free protection for your applications and to get access to all the features.
@@ -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-darwin
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-darwin-x86_64/include/ddwaf.h
45
- - vendor/libddwaf/libddwaf-1.3.0-darwin-x86_64/lib/libddwaf.dylib
46
- homepage: https://github.com/DataDog/libddwaf
45
+ - vendor/libddwaf/libddwaf-1.5.1-darwin-x86_64/lib/libddwaf.dylib
46
+ homepage: https://github.com/DataDog/libddwaf-rb
47
47
  licenses:
48
48
  - BSD-3-Clause
49
49
  metadata:
@@ -63,7 +63,7 @@ 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.33
66
+ rubygems_version: 3.3.22
67
67
  signing_key:
68
68
  specification_version: 4
69
69
  summary: Datadog WAF