Module: Datadog::AppSec::WAF

Defined in:
lib/datadog/appsec/waf.rb,
lib/datadog/appsec/waf/version.rb

Overview

rubocop:disable Metrics/ModuleLength

Defined Under Namespace

Modules: LibDDWAF, VERSION Classes: Context, Handle, Result

Constant Summary collapse

RESULT_CODE =
{
  ddwaf_err_internal:         :err_internal,
  ddwaf_err_invalid_object:   :err_invalid_object,
  ddwaf_err_invalid_argument: :err_invalid_argument,
  ddwaf_ok:                   :ok,
  ddwaf_match:                :match,
}

Class Method Summary collapse

Class Method Details

.log_callback(level, func, file, line, message, len) ⇒ Object



426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/datadog/appsec/waf.rb', line 426

def self.log_callback(level, func, file, line, message, len)
  return if logger.nil?

  logger.debug do
    {
      level: level,
      func: func,
      file: file,
      line: line,
      message: message.read_bytes(len)
    }.inspect
  end
end

.loggerObject



440
441
442
# File 'lib/datadog/appsec/waf.rb', line 440

def self.logger
  @logger
end

.logger=(logger) ⇒ Object



444
445
446
447
448
449
450
451
452
453
454
# File 'lib/datadog/appsec/waf.rb', line 444

def self.logger=(logger)
  unless @log_callback
    log_callback = method(:log_callback)
    Datadog::AppSec::WAF::LibDDWAF.ddwaf_set_log_cb(log_callback, :ddwaf_log_trace)

    # retain logging proc if set properly
    @log_callback = log_callback
  end

  @logger = logger
end

.object_to_ruby(obj) ⇒ Object

rubocop:enable Metrics/MethodLength



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/datadog/appsec/waf.rb', line 396

def self.object_to_ruby(obj)
  case obj[:type]
  when :ddwaf_obj_invalid
    nil
  when :ddwaf_obj_bool
    obj[:valueUnion][:boolean]
  when :ddwaf_obj_string
    obj[:valueUnion][:stringValue].read_bytes(obj[:nbEntries])
  when :ddwaf_obj_signed
    obj[:valueUnion][:intValue]
  when :ddwaf_obj_unsigned
    obj[:valueUnion][:uintValue]
  when :ddwaf_obj_array
    (0...obj[:nbEntries]).each.with_object([]) do |i, a|
      ptr = obj[:valueUnion][:array] + i * LibDDWAF::Object.size
      e = object_to_ruby(LibDDWAF::Object.new(ptr))
      a << e
    end
  when :ddwaf_obj_map
    (0...obj[:nbEntries]).each.with_object({}) do |i, h|
      ptr = obj[:valueUnion][:array] + i * Datadog::AppSec::WAF::LibDDWAF::Object.size
      o = Datadog::AppSec::WAF::LibDDWAF::Object.new(ptr)
      l = o[:parameterNameLength]
      k = o[:parameterName].read_bytes(l)
      v = object_to_ruby(LibDDWAF::Object.new(ptr))
      h[k] = v
    end
  end
end

.ruby_to_object(val, max_container_size: nil, max_container_depth: nil, max_string_length: nil, coerce: true) ⇒ Object

rubocop:disable Metrics/MethodLength



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/datadog/appsec/waf.rb', line 284

def self.ruby_to_object(val, max_container_size: nil, max_container_depth: nil, max_string_length: nil, coerce: true)
  case val
  when Array
    obj = LibDDWAF::Object.new
    res = LibDDWAF.ddwaf_object_array(obj)
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val}"
    end

    max_index = max_container_size - 1 if max_container_size
    val.each.with_index do |e, i|
      member = ruby_to_object(e,
                              max_container_size: max_container_size,
                              max_container_depth: (max_container_depth - 1 if max_container_depth),
                              max_string_length: max_string_length,
                              coerce: coerce)
      e_res = LibDDWAF.ddwaf_object_array_add(obj, member)
      unless e_res
        fail LibDDWAF::Error, "Could not add to array object: #{e.inspect}"
      end

      break val if max_index && i >= max_index
    end unless max_container_depth == 0

    obj
  when Hash
    obj = LibDDWAF::Object.new
    res = LibDDWAF.ddwaf_object_map(obj)
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val}"
    end

    max_index = max_container_size - 1 if max_container_size
    val.each.with_index do |e, i|
      k, v = e[0], e[1] # for Steep, which doesn't handle |(k, v), i|

      k = k.to_s[0, max_string_length] if max_string_length
      member = ruby_to_object(v,
                              max_container_size: max_container_size,
                              max_container_depth: (max_container_depth - 1 if max_container_depth),
                              max_string_length: max_string_length,
                              coerce: coerce)
      kv_res = LibDDWAF.ddwaf_object_map_addl(obj, k.to_s, k.to_s.bytesize, member)
      unless kv_res
        fail LibDDWAF::Error, "Could not add to map object: #{k.inspect} => #{v.inspect}"
      end

      break val if max_index && i >= max_index
    end unless max_container_depth == 0

    obj
  when String
    obj = LibDDWAF::Object.new
    encoded_val = val.to_s.encode('utf-8', invalid: :replace, undef: :replace)
    val = encoded_val[0, max_string_length] if max_string_length
    str = val.to_s
    res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
    end

    obj
  when Symbol
    obj = LibDDWAF::Object.new
    val = val.to_s[0, max_string_length] if max_string_length
    str = val.to_s
    res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
    end

    obj
  when Integer
    obj = LibDDWAF::Object.new
    res = if coerce
            LibDDWAF.ddwaf_object_string(obj, val.to_s)
          elsif val < 0
            LibDDWAF.ddwaf_object_signed_force(obj, val)
          else
            LibDDWAF.ddwaf_object_unsigned_force(obj, val)
          end
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
    end

    obj
  when Float
    obj = LibDDWAF::Object.new
    res = LibDDWAF.ddwaf_object_string(obj, val.to_s)
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
    end

    obj
  when TrueClass, FalseClass
    obj = LibDDWAF::Object.new
    res = if coerce
            LibDDWAF.ddwaf_object_string(obj, val.to_s)
          else
            LibDDWAF.ddwaf_object_bool(obj, val)
          end
    if res.null?
      fail LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
    end

    obj
  else
    ruby_to_object(''.freeze)
  end
end

.versionObject



279
280
281
# File 'lib/datadog/appsec/waf.rb', line 279

def self.version
  LibDDWAF.ddwaf_get_version
end