libddwaf 1.15.0.0.0-x86_64-linux → 1.18.0.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 +6 -0
- data/lib/datadog/appsec/waf/context.rb +126 -0
- data/lib/datadog/appsec/waf/converter.rb +172 -0
- data/lib/datadog/appsec/waf/handle.rb +108 -0
- data/lib/datadog/appsec/waf/lib_ddwaf.rb +313 -0
- data/lib/datadog/appsec/waf/result.rb +33 -0
- data/lib/datadog/appsec/waf/version.rb +2 -2
- data/lib/datadog/appsec/waf.rb +17 -679
- data/vendor/libddwaf/libddwaf-1.18.0-linux-x86_64/lib/libddwaf.so +0 -0
- metadata +9 -4
- data/vendor/libddwaf/libddwaf-1.15.0-linux-x86_64/lib/libddwaf.so +0 -0
@@ -0,0 +1,313 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
require 'datadog/appsec/waf/version'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module AppSec
|
8
|
+
module WAF
|
9
|
+
# FFI-binding for C-libddwaf
|
10
|
+
# See https://github.com/DataDog/libddwaf
|
11
|
+
module LibDDWAF
|
12
|
+
# An exception binding raises in most of the cases
|
13
|
+
class Error < StandardError
|
14
|
+
attr_reader :diagnostics
|
15
|
+
|
16
|
+
def initialize(msg, diagnostics: nil)
|
17
|
+
@diagnostics = diagnostics
|
18
|
+
|
19
|
+
super(msg)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
extend ::FFI::Library
|
24
|
+
|
25
|
+
def self.local_os
|
26
|
+
if RUBY_ENGINE == 'jruby'
|
27
|
+
os_name = java.lang.System.get_property('os.name')
|
28
|
+
|
29
|
+
os = case os_name
|
30
|
+
when /linux/i then 'linux'
|
31
|
+
when /mac/i then 'darwin'
|
32
|
+
else raise Error, "unsupported JRuby os.name: #{os_name.inspect}"
|
33
|
+
end
|
34
|
+
|
35
|
+
return os
|
36
|
+
end
|
37
|
+
|
38
|
+
Gem::Platform.local.os
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.local_version
|
42
|
+
return nil unless local_os == 'linux'
|
43
|
+
|
44
|
+
# Old rubygems don't handle non-gnu linux correctly
|
45
|
+
return ::Regexp.last_match(1) if RUBY_PLATFORM =~ /linux-(.+)$/
|
46
|
+
|
47
|
+
'gnu'
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.local_cpu
|
51
|
+
if RUBY_ENGINE == 'jruby'
|
52
|
+
os_arch = java.lang.System.get_property('os.arch')
|
53
|
+
|
54
|
+
cpu = case os_arch
|
55
|
+
when 'amd64' then 'x86_64'
|
56
|
+
when 'aarch64' then local_os == 'darwin' ? 'arm64' : 'aarch64'
|
57
|
+
else raise Error, "unsupported JRuby os.arch: #{os_arch.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
return cpu
|
61
|
+
end
|
62
|
+
|
63
|
+
Gem::Platform.local.cpu
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.source_dir
|
67
|
+
__dir__ || raise('__dir__ is nil: eval?')
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.vendor_dir
|
71
|
+
File.join(source_dir, '../../../../vendor')
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.libddwaf_vendor_dir
|
75
|
+
File.join(vendor_dir, 'libddwaf')
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.shared_lib_triplet(version: local_version)
|
79
|
+
version ? "#{local_os}-#{version}-#{local_cpu}" : "#{local_os}-#{local_cpu}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.libddwaf_dir
|
83
|
+
default = File.join(libddwaf_vendor_dir,
|
84
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet}")
|
85
|
+
candidates = [
|
86
|
+
default
|
87
|
+
]
|
88
|
+
|
89
|
+
if local_os == 'linux'
|
90
|
+
candidates << File.join(libddwaf_vendor_dir,
|
91
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet(version: nil)}")
|
92
|
+
end
|
93
|
+
|
94
|
+
candidates.find { |d| Dir.exist?(d) } || default
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.shared_lib_extname
|
98
|
+
if Gem::Platform.local.os == 'darwin'
|
99
|
+
'.dylib'
|
100
|
+
elsif Gem::Platform.local.os == 'java' && java.lang.System.get_property('os.name').match(/mac/i)
|
101
|
+
'.dylib'
|
102
|
+
else
|
103
|
+
'.so'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.shared_lib_path
|
108
|
+
File.join(libddwaf_dir, 'lib', "libddwaf#{shared_lib_extname}")
|
109
|
+
end
|
110
|
+
|
111
|
+
ffi_lib [shared_lib_path]
|
112
|
+
|
113
|
+
# version
|
114
|
+
|
115
|
+
attach_function :ddwaf_get_version, [], :string
|
116
|
+
|
117
|
+
# ddwaf::object data structure
|
118
|
+
|
119
|
+
DDWAF_OBJ_TYPE = enum :ddwaf_obj_invalid, 0,
|
120
|
+
:ddwaf_obj_signed, 1 << 0,
|
121
|
+
:ddwaf_obj_unsigned, 1 << 1,
|
122
|
+
:ddwaf_obj_string, 1 << 2,
|
123
|
+
:ddwaf_obj_array, 1 << 3,
|
124
|
+
:ddwaf_obj_map, 1 << 4,
|
125
|
+
:ddwaf_obj_bool, 1 << 5,
|
126
|
+
:ddwaf_obj_float, 1 << 6,
|
127
|
+
:ddwaf_obj_null, 1 << 7
|
128
|
+
|
129
|
+
typedef DDWAF_OBJ_TYPE, :ddwaf_obj_type
|
130
|
+
|
131
|
+
typedef :pointer, :charptr
|
132
|
+
typedef :pointer, :charptrptr
|
133
|
+
|
134
|
+
# Ruby representation of C uint32_t
|
135
|
+
class UInt32Ptr < ::FFI::Struct
|
136
|
+
layout :value, :uint32
|
137
|
+
end
|
138
|
+
|
139
|
+
typedef UInt32Ptr.by_ref, :uint32ptr
|
140
|
+
|
141
|
+
# Ruby representation of C uint64_t
|
142
|
+
class UInt64Ptr < ::FFI::Struct
|
143
|
+
layout :value, :uint64
|
144
|
+
end
|
145
|
+
|
146
|
+
typedef UInt64Ptr.by_ref, :uint64ptr
|
147
|
+
|
148
|
+
# Ruby representation of C size_t
|
149
|
+
class SizeTPtr < ::FFI::Struct
|
150
|
+
layout :value, :size_t
|
151
|
+
end
|
152
|
+
|
153
|
+
typedef SizeTPtr.by_ref, :sizeptr
|
154
|
+
|
155
|
+
# Ruby representation of C union
|
156
|
+
class ObjectValueUnion < ::FFI::Union
|
157
|
+
layout :stringValue, :charptr,
|
158
|
+
:uintValue, :uint64,
|
159
|
+
:intValue, :int64,
|
160
|
+
:array, :pointer,
|
161
|
+
:boolean, :bool,
|
162
|
+
:f64, :double
|
163
|
+
end
|
164
|
+
|
165
|
+
# Ruby representation of ddwaf_object
|
166
|
+
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L94C1-L115C3
|
167
|
+
class Object < ::FFI::Struct
|
168
|
+
layout :parameterName, :charptr,
|
169
|
+
:parameterNameLength, :uint64,
|
170
|
+
:valueUnion, ObjectValueUnion,
|
171
|
+
:nbEntries, :uint64,
|
172
|
+
:type, :ddwaf_obj_type
|
173
|
+
end
|
174
|
+
|
175
|
+
typedef Object.by_ref, :ddwaf_object
|
176
|
+
|
177
|
+
## setters
|
178
|
+
|
179
|
+
attach_function :ddwaf_object_invalid, [:ddwaf_object], :ddwaf_object
|
180
|
+
attach_function :ddwaf_object_string, [:ddwaf_object, :string], :ddwaf_object
|
181
|
+
attach_function :ddwaf_object_stringl, [:ddwaf_object, :charptr, :size_t], :ddwaf_object
|
182
|
+
attach_function :ddwaf_object_stringl_nc, [:ddwaf_object, :charptr, :size_t], :ddwaf_object
|
183
|
+
attach_function :ddwaf_object_string_from_unsigned, [:ddwaf_object, :uint64], :ddwaf_object
|
184
|
+
attach_function :ddwaf_object_string_from_signed, [:ddwaf_object, :int64], :ddwaf_object
|
185
|
+
attach_function :ddwaf_object_unsigned, [:ddwaf_object, :uint64], :ddwaf_object
|
186
|
+
attach_function :ddwaf_object_signed, [:ddwaf_object, :int64], :ddwaf_object
|
187
|
+
attach_function :ddwaf_object_bool, [:ddwaf_object, :bool], :ddwaf_object
|
188
|
+
attach_function :ddwaf_object_null, [:ddwaf_object], :ddwaf_object
|
189
|
+
attach_function :ddwaf_object_float, [:ddwaf_object, :double], :ddwaf_object
|
190
|
+
|
191
|
+
attach_function :ddwaf_object_array, [:ddwaf_object], :ddwaf_object
|
192
|
+
attach_function :ddwaf_object_array_add, [:ddwaf_object, :ddwaf_object], :bool
|
193
|
+
|
194
|
+
attach_function :ddwaf_object_map, [:ddwaf_object], :ddwaf_object
|
195
|
+
attach_function :ddwaf_object_map_add, [:ddwaf_object, :string, :pointer], :bool
|
196
|
+
attach_function :ddwaf_object_map_addl, [:ddwaf_object, :charptr, :size_t, :pointer], :bool
|
197
|
+
attach_function :ddwaf_object_map_addl_nc, [:ddwaf_object, :charptr, :size_t, :pointer], :bool
|
198
|
+
|
199
|
+
## getters
|
200
|
+
|
201
|
+
attach_function :ddwaf_object_type, [:ddwaf_object], DDWAF_OBJ_TYPE
|
202
|
+
attach_function :ddwaf_object_size, [:ddwaf_object], :uint64
|
203
|
+
attach_function :ddwaf_object_length, [:ddwaf_object], :size_t
|
204
|
+
attach_function :ddwaf_object_get_key, [:ddwaf_object, :sizeptr], :charptr
|
205
|
+
attach_function :ddwaf_object_get_string, [:ddwaf_object, :sizeptr], :charptr
|
206
|
+
attach_function :ddwaf_object_get_unsigned, [:ddwaf_object], :uint64
|
207
|
+
attach_function :ddwaf_object_get_signed, [:ddwaf_object], :int64
|
208
|
+
attach_function :ddwaf_object_get_index, [:ddwaf_object, :size_t], :ddwaf_object
|
209
|
+
attach_function :ddwaf_object_get_bool, [:ddwaf_object], :bool
|
210
|
+
attach_function :ddwaf_object_get_float, [:ddwaf_object], :double
|
211
|
+
|
212
|
+
## freeers
|
213
|
+
|
214
|
+
ObjectFree = attach_function :ddwaf_object_free, [:ddwaf_object], :void
|
215
|
+
ObjectNoFree = ::FFI::Pointer::NULL
|
216
|
+
|
217
|
+
# main handle
|
218
|
+
|
219
|
+
typedef :pointer, :ddwaf_handle
|
220
|
+
typedef Object.by_ref, :ddwaf_rule
|
221
|
+
|
222
|
+
callback :ddwaf_object_free_fn, [:ddwaf_object], :void
|
223
|
+
|
224
|
+
# Ruby representation of ddwaf_config
|
225
|
+
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L129-L152
|
226
|
+
class Config < ::FFI::Struct
|
227
|
+
# Ruby representation of ddwaf_config_limits
|
228
|
+
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L131-L138
|
229
|
+
class Limits < ::FFI::Struct
|
230
|
+
layout :max_container_size, :uint32,
|
231
|
+
:max_container_depth, :uint32,
|
232
|
+
:max_string_length, :uint32
|
233
|
+
end
|
234
|
+
|
235
|
+
# Ruby representation of ddwaf_config_obfuscator
|
236
|
+
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L141-L146
|
237
|
+
class Obfuscator < ::FFI::Struct
|
238
|
+
layout :key_regex, :pointer, # should be :charptr
|
239
|
+
:value_regex, :pointer # should be :charptr
|
240
|
+
end
|
241
|
+
|
242
|
+
layout :limits, Limits,
|
243
|
+
:obfuscator, Obfuscator,
|
244
|
+
:free_fn, :pointer # :ddwaf_object_free_fn
|
245
|
+
end
|
246
|
+
|
247
|
+
typedef Config.by_ref, :ddwaf_config
|
248
|
+
|
249
|
+
attach_function :ddwaf_init, [:ddwaf_rule, :ddwaf_config, :ddwaf_object], :ddwaf_handle
|
250
|
+
attach_function :ddwaf_update, [:ddwaf_handle, :ddwaf_object, :ddwaf_object], :ddwaf_handle
|
251
|
+
attach_function :ddwaf_destroy, [:ddwaf_handle], :void
|
252
|
+
|
253
|
+
attach_function :ddwaf_known_addresses, [:ddwaf_handle, UInt32Ptr], :charptrptr
|
254
|
+
|
255
|
+
# updating
|
256
|
+
|
257
|
+
DDWAF_RET_CODE = enum :ddwaf_err_internal, -3,
|
258
|
+
:ddwaf_err_invalid_object, -2,
|
259
|
+
:ddwaf_err_invalid_argument, -1,
|
260
|
+
:ddwaf_ok, 0,
|
261
|
+
:ddwaf_match, 1
|
262
|
+
typedef DDWAF_RET_CODE, :ddwaf_ret_code
|
263
|
+
|
264
|
+
# running
|
265
|
+
|
266
|
+
typedef :pointer, :ddwaf_context
|
267
|
+
|
268
|
+
attach_function :ddwaf_context_init, [:ddwaf_handle], :ddwaf_context
|
269
|
+
attach_function :ddwaf_context_destroy, [:ddwaf_context], :void
|
270
|
+
|
271
|
+
# Ruby representation of ddwaf_result
|
272
|
+
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L154-L173
|
273
|
+
class Result < ::FFI::Struct
|
274
|
+
layout :timeout, :bool,
|
275
|
+
:events, Object,
|
276
|
+
:actions, Object,
|
277
|
+
:derivatives, Object,
|
278
|
+
:total_runtime, :uint64
|
279
|
+
end
|
280
|
+
|
281
|
+
typedef Result.by_ref, :ddwaf_result
|
282
|
+
typedef :uint64, :timeout_us
|
283
|
+
|
284
|
+
attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_object, :ddwaf_result, :timeout_us], :ddwaf_ret_code, blocking: true
|
285
|
+
attach_function :ddwaf_result_free, [:ddwaf_result], :void
|
286
|
+
|
287
|
+
# logging
|
288
|
+
|
289
|
+
DDWAF_LOG_LEVEL = enum :ddwaf_log_trace,
|
290
|
+
:ddwaf_log_debug,
|
291
|
+
:ddwaf_log_info,
|
292
|
+
:ddwaf_log_warn,
|
293
|
+
:ddwaf_log_error,
|
294
|
+
:ddwaf_log_off
|
295
|
+
typedef DDWAF_LOG_LEVEL, :ddwaf_log_level
|
296
|
+
|
297
|
+
callback :ddwaf_log_cb, [:ddwaf_log_level, :string, :string, :uint, :charptr, :uint64], :void
|
298
|
+
|
299
|
+
attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
|
300
|
+
|
301
|
+
DEFAULT_MAX_CONTAINER_SIZE = 256
|
302
|
+
DEFAULT_MAX_CONTAINER_DEPTH = 20
|
303
|
+
DEFAULT_MAX_STRING_LENGTH = 16_384 # in bytes, UTF-8 worst case being 4x size in terms of code point)
|
304
|
+
|
305
|
+
DDWAF_MAX_CONTAINER_SIZE = 256
|
306
|
+
DDWAF_MAX_CONTAINER_DEPTH = 20
|
307
|
+
DDWAF_MAX_STRING_LENGTH = 4096
|
308
|
+
|
309
|
+
DDWAF_RUN_TIMEOUT = 5000
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module WAF
|
6
|
+
# Ruby representation of the ddwaf_result of a libddwaf run.
|
7
|
+
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L159-L173
|
8
|
+
class Result
|
9
|
+
attr_reader :status, :events, :total_runtime, :timeout, :actions, :derivatives
|
10
|
+
|
11
|
+
def initialize(status, events, total_runtime, timeout, actions, derivatives)
|
12
|
+
@status = status
|
13
|
+
@events = events
|
14
|
+
@total_runtime = total_runtime
|
15
|
+
@timeout = timeout
|
16
|
+
@actions = actions
|
17
|
+
@derivatives = derivatives
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_h
|
21
|
+
{
|
22
|
+
status: @status,
|
23
|
+
events: @events,
|
24
|
+
total_runtime: @total_runtime,
|
25
|
+
timeout: @timeout,
|
26
|
+
actions: @actions,
|
27
|
+
derivatives: @derivatives
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|