libddwaf 1.15.0.0.0-java → 1.18.0.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,307 @@
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 '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
+ Gem::Platform.local.os == 'darwin' ? '.dylib' : '.so'
99
+ end
100
+
101
+ def self.shared_lib_path
102
+ File.join(libddwaf_dir, 'lib', "libddwaf#{shared_lib_extname}")
103
+ end
104
+
105
+ ffi_lib [shared_lib_path]
106
+
107
+ # version
108
+
109
+ attach_function :ddwaf_get_version, [], :string
110
+
111
+ # ddwaf::object data structure
112
+
113
+ DDWAF_OBJ_TYPE = enum :ddwaf_obj_invalid, 0,
114
+ :ddwaf_obj_signed, 1 << 0,
115
+ :ddwaf_obj_unsigned, 1 << 1,
116
+ :ddwaf_obj_string, 1 << 2,
117
+ :ddwaf_obj_array, 1 << 3,
118
+ :ddwaf_obj_map, 1 << 4,
119
+ :ddwaf_obj_bool, 1 << 5,
120
+ :ddwaf_obj_float, 1 << 6,
121
+ :ddwaf_obj_null, 1 << 7
122
+
123
+ typedef DDWAF_OBJ_TYPE, :ddwaf_obj_type
124
+
125
+ typedef :pointer, :charptr
126
+ typedef :pointer, :charptrptr
127
+
128
+ # Ruby representation of C uint32_t
129
+ class UInt32Ptr < ::FFI::Struct
130
+ layout :value, :uint32
131
+ end
132
+
133
+ typedef UInt32Ptr.by_ref, :uint32ptr
134
+
135
+ # Ruby representation of C uint64_t
136
+ class UInt64Ptr < ::FFI::Struct
137
+ layout :value, :uint64
138
+ end
139
+
140
+ typedef UInt64Ptr.by_ref, :uint64ptr
141
+
142
+ # Ruby representation of C size_t
143
+ class SizeTPtr < ::FFI::Struct
144
+ layout :value, :size_t
145
+ end
146
+
147
+ typedef SizeTPtr.by_ref, :sizeptr
148
+
149
+ # Ruby representation of C union
150
+ class ObjectValueUnion < ::FFI::Union
151
+ layout :stringValue, :charptr,
152
+ :uintValue, :uint64,
153
+ :intValue, :int64,
154
+ :array, :pointer,
155
+ :boolean, :bool,
156
+ :f64, :double
157
+ end
158
+
159
+ # Ruby representation of ddwaf_object
160
+ # See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L94C1-L115C3
161
+ class Object < ::FFI::Struct
162
+ layout :parameterName, :charptr,
163
+ :parameterNameLength, :uint64,
164
+ :valueUnion, ObjectValueUnion,
165
+ :nbEntries, :uint64,
166
+ :type, :ddwaf_obj_type
167
+ end
168
+
169
+ typedef Object.by_ref, :ddwaf_object
170
+
171
+ ## setters
172
+
173
+ attach_function :ddwaf_object_invalid, [:ddwaf_object], :ddwaf_object
174
+ attach_function :ddwaf_object_string, [:ddwaf_object, :string], :ddwaf_object
175
+ attach_function :ddwaf_object_stringl, [:ddwaf_object, :charptr, :size_t], :ddwaf_object
176
+ attach_function :ddwaf_object_stringl_nc, [:ddwaf_object, :charptr, :size_t], :ddwaf_object
177
+ attach_function :ddwaf_object_string_from_unsigned, [:ddwaf_object, :uint64], :ddwaf_object
178
+ attach_function :ddwaf_object_string_from_signed, [:ddwaf_object, :int64], :ddwaf_object
179
+ attach_function :ddwaf_object_unsigned, [:ddwaf_object, :uint64], :ddwaf_object
180
+ attach_function :ddwaf_object_signed, [:ddwaf_object, :int64], :ddwaf_object
181
+ attach_function :ddwaf_object_bool, [:ddwaf_object, :bool], :ddwaf_object
182
+ attach_function :ddwaf_object_null, [:ddwaf_object], :ddwaf_object
183
+ attach_function :ddwaf_object_float, [:ddwaf_object, :double], :ddwaf_object
184
+
185
+ attach_function :ddwaf_object_array, [:ddwaf_object], :ddwaf_object
186
+ attach_function :ddwaf_object_array_add, [:ddwaf_object, :ddwaf_object], :bool
187
+
188
+ attach_function :ddwaf_object_map, [:ddwaf_object], :ddwaf_object
189
+ attach_function :ddwaf_object_map_add, [:ddwaf_object, :string, :pointer], :bool
190
+ attach_function :ddwaf_object_map_addl, [:ddwaf_object, :charptr, :size_t, :pointer], :bool
191
+ attach_function :ddwaf_object_map_addl_nc, [:ddwaf_object, :charptr, :size_t, :pointer], :bool
192
+
193
+ ## getters
194
+
195
+ attach_function :ddwaf_object_type, [:ddwaf_object], DDWAF_OBJ_TYPE
196
+ attach_function :ddwaf_object_size, [:ddwaf_object], :uint64
197
+ attach_function :ddwaf_object_length, [:ddwaf_object], :size_t
198
+ attach_function :ddwaf_object_get_key, [:ddwaf_object, :sizeptr], :charptr
199
+ attach_function :ddwaf_object_get_string, [:ddwaf_object, :sizeptr], :charptr
200
+ attach_function :ddwaf_object_get_unsigned, [:ddwaf_object], :uint64
201
+ attach_function :ddwaf_object_get_signed, [:ddwaf_object], :int64
202
+ attach_function :ddwaf_object_get_index, [:ddwaf_object, :size_t], :ddwaf_object
203
+ attach_function :ddwaf_object_get_bool, [:ddwaf_object], :bool
204
+ attach_function :ddwaf_object_get_float, [:ddwaf_object], :double
205
+
206
+ ## freeers
207
+
208
+ ObjectFree = attach_function :ddwaf_object_free, [:ddwaf_object], :void
209
+ ObjectNoFree = ::FFI::Pointer::NULL
210
+
211
+ # main handle
212
+
213
+ typedef :pointer, :ddwaf_handle
214
+ typedef Object.by_ref, :ddwaf_rule
215
+
216
+ callback :ddwaf_object_free_fn, [:ddwaf_object], :void
217
+
218
+ # Ruby representation of ddwaf_config
219
+ # https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L129-L152
220
+ class Config < ::FFI::Struct
221
+ # Ruby representation of ddwaf_config_limits
222
+ # https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L131-L138
223
+ class Limits < ::FFI::Struct
224
+ layout :max_container_size, :uint32,
225
+ :max_container_depth, :uint32,
226
+ :max_string_length, :uint32
227
+ end
228
+
229
+ # Ruby representation of ddwaf_config_obfuscator
230
+ # https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L141-L146
231
+ class Obfuscator < ::FFI::Struct
232
+ layout :key_regex, :pointer, # should be :charptr
233
+ :value_regex, :pointer # should be :charptr
234
+ end
235
+
236
+ layout :limits, Limits,
237
+ :obfuscator, Obfuscator,
238
+ :free_fn, :pointer # :ddwaf_object_free_fn
239
+ end
240
+
241
+ typedef Config.by_ref, :ddwaf_config
242
+
243
+ attach_function :ddwaf_init, [:ddwaf_rule, :ddwaf_config, :ddwaf_object], :ddwaf_handle
244
+ attach_function :ddwaf_update, [:ddwaf_handle, :ddwaf_object, :ddwaf_object], :ddwaf_handle
245
+ attach_function :ddwaf_destroy, [:ddwaf_handle], :void
246
+
247
+ attach_function :ddwaf_known_addresses, [:ddwaf_handle, UInt32Ptr], :charptrptr
248
+
249
+ # updating
250
+
251
+ DDWAF_RET_CODE = enum :ddwaf_err_internal, -3,
252
+ :ddwaf_err_invalid_object, -2,
253
+ :ddwaf_err_invalid_argument, -1,
254
+ :ddwaf_ok, 0,
255
+ :ddwaf_match, 1
256
+ typedef DDWAF_RET_CODE, :ddwaf_ret_code
257
+
258
+ # running
259
+
260
+ typedef :pointer, :ddwaf_context
261
+
262
+ attach_function :ddwaf_context_init, [:ddwaf_handle], :ddwaf_context
263
+ attach_function :ddwaf_context_destroy, [:ddwaf_context], :void
264
+
265
+ # Ruby representation of ddwaf_result
266
+ # See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L154-L173
267
+ class Result < ::FFI::Struct
268
+ layout :timeout, :bool,
269
+ :events, Object,
270
+ :actions, Object,
271
+ :derivatives, Object,
272
+ :total_runtime, :uint64
273
+ end
274
+
275
+ typedef Result.by_ref, :ddwaf_result
276
+ typedef :uint64, :timeout_us
277
+
278
+ attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_object, :ddwaf_result, :timeout_us], :ddwaf_ret_code, blocking: true
279
+ attach_function :ddwaf_result_free, [:ddwaf_result], :void
280
+
281
+ # logging
282
+
283
+ DDWAF_LOG_LEVEL = enum :ddwaf_log_trace,
284
+ :ddwaf_log_debug,
285
+ :ddwaf_log_info,
286
+ :ddwaf_log_warn,
287
+ :ddwaf_log_error,
288
+ :ddwaf_log_off
289
+ typedef DDWAF_LOG_LEVEL, :ddwaf_log_level
290
+
291
+ callback :ddwaf_log_cb, [:ddwaf_log_level, :string, :string, :uint, :charptr, :uint64], :void
292
+
293
+ attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
294
+
295
+ DEFAULT_MAX_CONTAINER_SIZE = 256
296
+ DEFAULT_MAX_CONTAINER_DEPTH = 20
297
+ DEFAULT_MAX_STRING_LENGTH = 16_384 # in bytes, UTF-8 worst case being 4x size in terms of code point)
298
+
299
+ DDWAF_MAX_CONTAINER_SIZE = 256
300
+ DDWAF_MAX_CONTAINER_DEPTH = 20
301
+ DDWAF_MAX_STRING_LENGTH = 4096
302
+
303
+ DDWAF_RUN_TIMEOUT = 5000
304
+ end
305
+ end
306
+ end
307
+ 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
@@ -2,7 +2,7 @@ module Datadog
2
2
  module AppSec
3
3
  module WAF
4
4
  module VERSION
5
- BASE_STRING = '1.15.0'
5
+ BASE_STRING = '1.18.0'
6
6
  STRING = "#{BASE_STRING}.0.0"
7
7
  MINIMUM_RUBY_VERSION = '2.5'
8
8
  end