Coverage Report

Created: 2023-09-25 07:12

/src/yara/libyara/libyara.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2013. The YARA Authors. All Rights Reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
1. Redistributions of source code must retain the above copyright notice, this
8
list of conditions and the following disclaimer.
9
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
this list of conditions and the following disclaimer in the documentation and/or
12
other materials provided with the distribution.
13
14
3. Neither the name of the copyright holder nor the names of its contributors
15
may be used to endorse or promote products derived from this software without
16
specific prior written permission.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#if defined(JEMALLOC)
31
#include <jemalloc/jemalloc.h>
32
#endif
33
34
#include <ctype.h>
35
#include <stdio.h>
36
#include <string.h>
37
#include <yara/error.h>
38
#include <yara/globals.h>
39
#include <yara/mem.h>
40
#include <yara/modules.h>
41
#include <yara/re.h>
42
#include <yara/threading.h>
43
44
#include "crypto.h"
45
46
#if defined(_WIN32) || defined(__CYGWIN__)
47
#if !defined(_MSC_VER) || (defined(_MSC_VER) && (_MSC_VER < 1900))
48
#define snprintf _snprintf
49
#endif
50
#endif
51
52
YR_THREAD_STORAGE_KEY yr_yyfatal_trampoline_tls;
53
YR_THREAD_STORAGE_KEY yr_trycatch_trampoline_tls;
54
55
static int init_count = 0;
56
57
static struct yr_config_var
58
{
59
  union
60
  {
61
    size_t sz;
62
    uint32_t ui32;
63
    uint64_t ui64;
64
    char *str;
65
  };
66
67
} yr_cfgs[YR_CONFIG_LAST];
68
69
// Global variables. See globals.h for their descriptions.
70
71
uint8_t yr_lowercase[256];
72
uint8_t yr_altercase[256];
73
74
#if 0 == YR_DEBUG_VERBOSITY
75
76
#else
77
78
uint64_t yr_debug_verbosity = YR_DEBUG_VERBOSITY;
79
80
YR_TLS int yr_debug_indent = 0;
81
82
YR_TLS int yr_debug_stopwatch_unstarted = 1;
83
84
YR_TLS YR_STOPWATCH yr_debug_stopwatch;
85
86
const char yr_debug_spaces[] = "                " /* 16 spaces * 1 */
87
                               "                " /* 16 spaces * 2 */
88
                               "                " /* 16 spaces * 3 */
89
                               "                " /* 16 spaces * 4 */
90
                               "                " /* 16 spaces * 5 */
91
                               "                " /* 16 spaces * 6 */
92
                               "                " /* 16 spaces * 7 */
93
                               "                " /* 16 spaces * 8 */;
94
95
size_t yr_debug_spaces_len = sizeof(yr_debug_spaces);
96
97
double yr_debug_get_elapsed_seconds(void)
98
{
99
  if (yr_debug_stopwatch_unstarted)
100
  {
101
    yr_debug_stopwatch_unstarted = 0;
102
    yr_stopwatch_start(&yr_debug_stopwatch);
103
  }
104
105
  uint64_t elapsed_ns = yr_stopwatch_elapsed_ns(&yr_debug_stopwatch);
106
107
  double seconds = (double) elapsed_ns / 1000000000;
108
109
  return seconds;
110
}
111
112
char *yr_debug_callback_message_as_string(int message)
113
{
114
  char *s = "CALLBACK_MSG_?";
115
  switch (message)
116
  {  // clang-format off
117
  case CALLBACK_MSG_RULE_MATCHING    : s = "CALLBACK_MSG_RULE_MATCHING"    ; break;
118
  case CALLBACK_MSG_RULE_NOT_MATCHING: s = "CALLBACK_MSG_RULE_NOT_MATCHING"; break;
119
  case CALLBACK_MSG_SCAN_FINISHED    : s = "CALLBACK_MSG_SCAN_FINISHED"    ; break;
120
  case CALLBACK_MSG_IMPORT_MODULE    : s = "CALLBACK_MSG_IMPORT_MODULE"    ; break;
121
  case CALLBACK_MSG_MODULE_IMPORTED  : s = "CALLBACK_MSG_MODULE_IMPORTED"  ; break;
122
  }  // clang-format on
123
  return s;
124
}
125
126
char *yr_debug_error_as_string(int error)
127
{
128
  char *s = "ERROR_?";
129
  switch (error)
130
  {  // clang-format off
131
  case ERROR_SUCCESS                       : s = "ERROR_SUCCESS 0"                     ; break;
132
  case ERROR_INSUFFICIENT_MEMORY           : s = "ERROR_INSUFFICIENT_MEMORY"           ; break;
133
  case ERROR_COULD_NOT_ATTACH_TO_PROCESS   : s = "ERROR_COULD_NOT_ATTACH_TO_PROCESS"   ; break;
134
  case ERROR_COULD_NOT_OPEN_FILE           : s = "ERROR_COULD_NOT_OPEN_FILE"           ; break;
135
  case ERROR_COULD_NOT_MAP_FILE            : s = "ERROR_COULD_NOT_MAP_FILE"            ; break;
136
  case ERROR_INVALID_FILE                  : s = "ERROR_INVALID_FILE"                  ; break;
137
  case ERROR_CORRUPT_FILE                  : s = "ERROR_CORRUPT_FILE"                  ; break;
138
  case ERROR_UNSUPPORTED_FILE_VERSION      : s = "ERROR_UNSUPPORTED_FILE_VERSION"      ; break;
139
  case ERROR_INVALID_REGULAR_EXPRESSION    : s = "ERROR_INVALID_REGULAR_EXPRESSION"    ; break;
140
  case ERROR_INVALID_HEX_STRING            : s = "ERROR_INVALID_HEX_STRING"            ; break;
141
  case ERROR_SYNTAX_ERROR                  : s = "ERROR_SYNTAX_ERROR"                  ; break;
142
  case ERROR_LOOP_NESTING_LIMIT_EXCEEDED   : s = "ERROR_LOOP_NESTING_LIMIT_EXCEEDED"   ; break;
143
  case ERROR_DUPLICATED_LOOP_IDENTIFIER    : s = "ERROR_DUPLICATED_LOOP_IDENTIFIER"    ; break;
144
  case ERROR_DUPLICATED_IDENTIFIER         : s = "ERROR_DUPLICATED_IDENTIFIER"         ; break;
145
  case ERROR_DUPLICATED_TAG_IDENTIFIER     : s = "ERROR_DUPLICATED_TAG_IDENTIFIER"     ; break;
146
  case ERROR_DUPLICATED_META_IDENTIFIER    : s = "ERROR_DUPLICATED_META_IDENTIFIER"    ; break;
147
  case ERROR_DUPLICATED_STRING_IDENTIFIER  : s = "ERROR_DUPLICATED_STRING_IDENTIFIER"  ; break;
148
  case ERROR_UNREFERENCED_STRING           : s = "ERROR_UNREFERENCED_STRING"           ; break;
149
  case ERROR_UNDEFINED_STRING              : s = "ERROR_UNDEFINED_STRING"              ; break;
150
  case ERROR_UNDEFINED_IDENTIFIER          : s = "ERROR_UNDEFINED_IDENTIFIER"          ; break;
151
  case ERROR_MISPLACED_ANONYMOUS_STRING    : s = "ERROR_MISPLACED_ANONYMOUS_STRING"    ; break;
152
  case ERROR_INCLUDES_CIRCULAR_REFERENCE   : s = "ERROR_INCLUDES_CIRCULAR_REFERENCE"   ; break;
153
  case ERROR_INCLUDE_DEPTH_EXCEEDED        : s = "ERROR_INCLUDE_DEPTH_EXCEEDED"        ; break;
154
  case ERROR_WRONG_TYPE                    : s = "ERROR_WRONG_TYPE"                    ; break;
155
  case ERROR_EXEC_STACK_OVERFLOW           : s = "ERROR_EXEC_STACK_OVERFLOW"           ; break;
156
  case ERROR_SCAN_TIMEOUT                  : s = "ERROR_SCAN_TIMEOUT"                  ; break;
157
  case ERROR_TOO_MANY_SCAN_THREADS         : s = "ERROR_TOO_MANY_SCAN_THREADS"         ; break;
158
  case ERROR_CALLBACK_ERROR                : s = "ERROR_CALLBACK_ERROR"                ; break;
159
  case ERROR_INVALID_ARGUMENT              : s = "ERROR_INVALID_ARGUMENT"              ; break;
160
  case ERROR_TOO_MANY_MATCHES              : s = "ERROR_TOO_MANY_MATCHES"              ; break;
161
  case ERROR_INTERNAL_FATAL_ERROR          : s = "ERROR_INTERNAL_FATAL_ERROR"          ; break;
162
  case ERROR_NESTED_FOR_OF_LOOP            : s = "ERROR_NESTED_FOR_OF_LOOP"            ; break;
163
  case ERROR_INVALID_FIELD_NAME            : s = "ERROR_INVALID_FIELD_NAME"            ; break;
164
  case ERROR_UNKNOWN_MODULE                : s = "ERROR_UNKNOWN_MODULE"                ; break;
165
  case ERROR_NOT_A_STRUCTURE               : s = "ERROR_NOT_A_STRUCTURE"               ; break;
166
  case ERROR_NOT_INDEXABLE                 : s = "ERROR_NOT_INDEXABLE"                 ; break;
167
  case ERROR_NOT_A_FUNCTION                : s = "ERROR_NOT_A_FUNCTION"                ; break;
168
  case ERROR_INVALID_FORMAT                : s = "ERROR_INVALID_FORMAT"                ; break;
169
  case ERROR_TOO_MANY_ARGUMENTS            : s = "ERROR_TOO_MANY_ARGUMENTS"            ; break;
170
  case ERROR_WRONG_ARGUMENTS               : s = "ERROR_WRONG_ARGUMENTS"               ; break;
171
  case ERROR_WRONG_RETURN_TYPE             : s = "ERROR_WRONG_RETURN_TYPE"             ; break;
172
  case ERROR_DUPLICATED_STRUCTURE_MEMBER   : s = "ERROR_DUPLICATED_STRUCTURE_MEMBER"   ; break;
173
  case ERROR_EMPTY_STRING                  : s = "ERROR_EMPTY_STRING"                  ; break;
174
  case ERROR_DIVISION_BY_ZERO              : s = "ERROR_DIVISION_BY_ZERO"              ; break;
175
  case ERROR_REGULAR_EXPRESSION_TOO_LARGE  : s = "ERROR_REGULAR_EXPRESSION_TOO_LARGE"  ; break;
176
  case ERROR_TOO_MANY_RE_FIBERS            : s = "ERROR_TOO_MANY_RE_FIBERS"            ; break;
177
  case ERROR_COULD_NOT_READ_PROCESS_MEMORY : s = "ERROR_COULD_NOT_READ_PROCESS_MEMORY" ; break;
178
  case ERROR_INVALID_EXTERNAL_VARIABLE_TYPE: s = "ERROR_INVALID_EXTERNAL_VARIABLE_TYPE"; break;
179
  case ERROR_REGULAR_EXPRESSION_TOO_COMPLEX: s = "ERROR_REGULAR_EXPRESSION_TOO_COMPLEX"; break;
180
  case ERROR_INVALID_MODULE_NAME           : s = "ERROR_INVALID_MODULE_NAME"           ; break;
181
  case ERROR_TOO_MANY_STRINGS              : s = "ERROR_TOO_MANY_STRINGS"              ; break;
182
  case ERROR_INTEGER_OVERFLOW              : s = "ERROR_INTEGER_OVERFLOW"              ; break;
183
  case ERROR_CALLBACK_REQUIRED             : s = "ERROR_CALLBACK_REQUIRED"             ; break;
184
  case ERROR_INVALID_OPERAND               : s = "ERROR_INVALID_OPERAND"               ; break;
185
  case ERROR_COULD_NOT_READ_FILE           : s = "ERROR_COULD_NOT_READ_FILE"           ; break;
186
  case ERROR_DUPLICATED_EXTERNAL_VARIABLE  : s = "ERROR_DUPLICATED_EXTERNAL_VARIABLE"  ; break;
187
  case ERROR_INVALID_MODULE_DATA           : s = "ERROR_INVALID_MODULE_DATA"           ; break;
188
  case ERROR_WRITING_FILE                  : s = "ERROR_WRITING_FILE"                  ; break;
189
  case ERROR_INVALID_MODIFIER              : s = "ERROR_INVALID_MODIFIER"              ; break;
190
  case ERROR_DUPLICATED_MODIFIER           : s = "ERROR_DUPLICATED_MODIFIER"           ; break;
191
  case ERROR_BLOCK_NOT_READY               : s = "ERROR_BLOCK_NOT_READY"               ; break;
192
  }  // clang-format on
193
  return s;
194
}
195
196
#endif
197
198
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER < 0x10100000L
199
200
// The OpenSSL library before version 1.1 requires some locks in order
201
// to be thread-safe. These locks are initialized in yr_initialize
202
// function.
203
204
static YR_MUTEX *openssl_locks;
205
206
static void _thread_id(CRYPTO_THREADID *id)
207
{
208
  CRYPTO_THREADID_set_numeric(id, (unsigned long) yr_current_thread_id());
209
}
210
211
static void _locking_function(int mode, int n, const char *file, int line)
212
{
213
  if (mode & CRYPTO_LOCK)
214
    yr_mutex_lock(&openssl_locks[n]);
215
  else
216
    yr_mutex_unlock(&openssl_locks[n]);
217
}
218
219
#endif
220
221
#if defined(HAVE_WINCRYPT_H)
222
223
HCRYPTPROV yr_cryptprov;
224
225
#endif
226
227
////////////////////////////////////////////////////////////////////////////////
228
// Should be called by main thread before using any other
229
// function from libyara.
230
//
231
YR_API int yr_initialize(void)
232
2
{
233
2
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
234
235
2
  uint32_t def_stack_size = DEFAULT_STACK_SIZE;
236
2
  uint32_t def_max_strings_per_rule = DEFAULT_MAX_STRINGS_PER_RULE;
237
2
  uint32_t def_max_match_data = DEFAULT_MAX_MATCH_DATA;
238
2
  uint64_t def_max_process_memory_chunk = DEFAULT_MAX_PROCESS_MEMORY_CHUNK;
239
240
2
  init_count++;
241
242
2
  if (init_count > 1)
243
0
    return ERROR_SUCCESS;
244
245
  // Initialize random number generator, as it is used for generating object
246
  // canaries.
247
2
  srand((unsigned) time(NULL));
248
249
514
  for (int i = 0; i < 256; i++)
250
512
  {
251
512
    if (i >= 'a' && i <= 'z')
252
52
      yr_altercase[i] = i - 32;
253
460
    else if (i >= 'A' && i <= 'Z')
254
52
      yr_altercase[i] = i + 32;
255
408
    else
256
408
      yr_altercase[i] = i;
257
258
512
    yr_lowercase[i] = tolower(i);
259
512
  }
260
261
2
  FAIL_ON_ERROR(yr_heap_alloc());
262
2
  FAIL_ON_ERROR(yr_thread_storage_create(&yr_yyfatal_trampoline_tls));
263
2
  FAIL_ON_ERROR(yr_thread_storage_create(&yr_trycatch_trampoline_tls));
264
265
#if defined HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER < 0x10100000L
266
267
  openssl_locks = (YR_MUTEX *) OPENSSL_malloc(
268
      CRYPTO_num_locks() * sizeof(YR_MUTEX));
269
270
  for (int i = 0; i < CRYPTO_num_locks(); i++)
271
    yr_mutex_create(&openssl_locks[i]);
272
273
  CRYPTO_THREADID_set_callback(_thread_id);
274
  CRYPTO_set_locking_callback(_locking_function);
275
276
#elif defined(HAVE_WINCRYPT_H)
277
278
  if (!CryptAcquireContext(
279
          &yr_cryptprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
280
  {
281
    return ERROR_INTERNAL_FATAL_ERROR;
282
  }
283
284
#elif defined(HAVE_COMMON_CRYPTO)
285
286
  ...
287
288
#endif
289
290
2
  FAIL_ON_ERROR(yr_modules_initialize());
291
292
  // Initialize default configuration options
293
294
2
  FAIL_ON_ERROR(yr_set_configuration(YR_CONFIG_STACK_SIZE, &def_stack_size));
295
296
2
  FAIL_ON_ERROR(yr_set_configuration(
297
2
      YR_CONFIG_MAX_STRINGS_PER_RULE, &def_max_strings_per_rule));
298
299
2
  FAIL_ON_ERROR(yr_set_configuration(
300
2
      YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, &def_max_process_memory_chunk));
301
302
2
  FAIL_ON_ERROR(
303
2
      yr_set_configuration(YR_CONFIG_MAX_MATCH_DATA, &def_max_match_data));
304
305
2
  YR_DEBUG_FPRINTF(2, stderr, "} // %s()\n", __FUNCTION__);
306
307
2
  return ERROR_SUCCESS;
308
2
}
309
310
////////////////////////////////////////////////////////////////////////////////
311
// Should be called by main thread before exiting.
312
//
313
YR_API int yr_finalize(void)
314
0
{
315
0
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
316
317
#if defined HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER < 0x10100000L
318
  int i;
319
#endif
320
321
  // yr_finalize shouldn't be called without calling yr_initialize first
322
323
0
  if (init_count == 0)
324
0
    return ERROR_INTERNAL_FATAL_ERROR;
325
326
0
  init_count--;
327
328
0
  if (init_count > 0)
329
0
    return ERROR_SUCCESS;
330
331
#if defined HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER < 0x10100000L
332
333
  for (i = 0; i < CRYPTO_num_locks(); i++) yr_mutex_destroy(&openssl_locks[i]);
334
335
  OPENSSL_free(openssl_locks);
336
  CRYPTO_THREADID_set_callback(NULL);
337
  CRYPTO_set_locking_callback(NULL);
338
339
#elif defined(HAVE_WINCRYPT_H)
340
341
  CryptReleaseContext(yr_cryptprov, 0);
342
343
#endif
344
345
0
  FAIL_ON_ERROR(yr_thread_storage_destroy(&yr_yyfatal_trampoline_tls));
346
0
  FAIL_ON_ERROR(yr_thread_storage_destroy(&yr_trycatch_trampoline_tls));
347
0
  FAIL_ON_ERROR(yr_modules_finalize());
348
0
  FAIL_ON_ERROR(yr_heap_free());
349
350
#if defined(JEMALLOC)
351
  malloc_stats_print(NULL, NULL, NULL);
352
  mallctl("prof.dump", NULL, NULL, NULL, 0);
353
#endif
354
355
0
  YR_DEBUG_FPRINTF(2, stderr, "} // %s()\n", __FUNCTION__);
356
357
0
  return ERROR_SUCCESS;
358
0
}
359
360
////////////////////////////////////////////////////////////////////////////////
361
// Set a configuration option.
362
//
363
// This function receives a configuration name, as defined by the YR_CONFIG_NAME
364
// enum, and a pointer to the value being set. The type of the value depends on
365
// the configuration name.
366
//
367
// The caller must ensure that the pointer passed to the function is the correct
368
// type. Using yr_set_configuration_uintXX is preferred, as those functions will
369
// perform the necessary type checking.
370
//
371
// Args:
372
//   name: Any of the values defined by the YR_CONFIG_NAME enum. Possible values
373
//         are:
374
//              YR_CONFIG_STACK_SIZE                data type: uint32_t
375
//              YR_CONFIG_MAX_STRINGS_PER_RULE      data type: uint32_t
376
//              YR_CONFIG_MAX_MATCH_DATA            data type: uint32_t
377
//              YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK  data type: uint64_t
378
//
379
//   src: Pointer to the value being set for the option.
380
//
381
// Returns:
382
//   ERROR_SUCCESS
383
//   ERROR_INVALID_ARGUMENT
384
//
385
YR_API int yr_set_configuration(YR_CONFIG_NAME name, void *src)
386
8
{
387
8
  if (src == NULL)
388
0
    return ERROR_INTERNAL_FATAL_ERROR;
389
390
8
  switch (name)
391
8
  {  // lump all the cases using same types together in one cascade
392
2
  case YR_CONFIG_STACK_SIZE:
393
4
  case YR_CONFIG_MAX_STRINGS_PER_RULE:
394
6
  case YR_CONFIG_MAX_MATCH_DATA:
395
6
    yr_cfgs[name].ui32 = *(uint32_t *) src;
396
6
    break;
397
398
2
  case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
399
2
    yr_cfgs[name].ui64 = *(uint64_t *) src;
400
2
    break;
401
402
0
  default:
403
0
    return ERROR_INTERNAL_FATAL_ERROR;
404
8
  }
405
406
8
  return ERROR_SUCCESS;
407
8
}
408
409
////////////////////////////////////////////////////////////////////////////////
410
// Set a configuration option.
411
//
412
// This function receives a configuration name, as defined by the YR_CONFIG_NAME
413
// and a value for the configuration being set. Only configuration names with
414
// type uint32_t will be accepted, if not ERROR_INVALID_ARGUMENT will be
415
// returned.
416
//
417
// Returns:
418
//   ERROR_SUCCESS
419
//   ERROR_INVALID_ARGUMENT
420
//
421
YR_API int yr_set_configuration_uint32(YR_CONFIG_NAME name, uint32_t value)
422
0
{
423
0
  switch (name)
424
0
  {
425
  // Accept only the configuration options that are of type uint32_t.
426
0
  case YR_CONFIG_STACK_SIZE:
427
0
  case YR_CONFIG_MAX_STRINGS_PER_RULE:
428
0
  case YR_CONFIG_MAX_MATCH_DATA:
429
0
    return yr_set_configuration(name, &value);
430
0
  default:
431
0
    return ERROR_INVALID_ARGUMENT;
432
0
  }
433
0
}
434
435
////////////////////////////////////////////////////////////////////////////////
436
// Set a configuration option.
437
//
438
// See yr_set_configuration_uint32 for more details.
439
//
440
YR_API int yr_set_configuration_uint64(YR_CONFIG_NAME name, uint64_t value)
441
0
{
442
0
  switch (name)
443
0
  {
444
0
  case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
445
0
    return yr_set_configuration(name, &value);
446
0
  default:
447
0
    return ERROR_INVALID_ARGUMENT;
448
0
  }
449
0
}
450
451
////////////////////////////////////////////////////////////////////////////////
452
// Get a configuration option.
453
//
454
// This function receives a configuration name, as defined by the YR_CONFIG_NAME
455
// enum, and a pointer to the variable that will receive the value for that
456
// option. The type of the value depends on the configuration name.
457
//
458
// The caller must ensure that the pointer passed to the function is the correct
459
// type. Using yr_get_configuration_uintXX is preferred.
460
//
461
// Args:
462
//   name: Any of the values defined by the YR_CONFIG_NAME enum. Possible values
463
//         are:
464
//              YR_CONFIG_STACK_SIZE                data type: uint32_t
465
//              YR_CONFIG_MAX_STRINGS_PER_RULE      data type: uint32_t
466
//              YR_CONFIG_MAX_MATCH_DATA            data type: uint32_t
467
//              YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK  data type: uint64_t
468
//
469
//   dest: Pointer to a variable that will receive the value for the option.
470
//
471
// Returns:
472
//   ERROR_SUCCESS
473
//   ERROR_INVALID_ARGUMENT
474
//
475
YR_API int yr_get_configuration(YR_CONFIG_NAME name, void *dest)
476
13.9k
{
477
13.9k
  if (dest == NULL)
478
0
    return ERROR_INVALID_ARGUMENT;
479
480
13.9k
  switch (name)
481
13.9k
  {  // lump all the cases using same types together in one cascade
482
6.97k
  case YR_CONFIG_STACK_SIZE:
483
6.97k
  case YR_CONFIG_MAX_STRINGS_PER_RULE:
484
13.9k
  case YR_CONFIG_MAX_MATCH_DATA:
485
13.9k
    *(uint32_t *) dest = yr_cfgs[name].ui32;
486
13.9k
    break;
487
488
0
  case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
489
0
    *(uint64_t *) dest = yr_cfgs[name].ui64;
490
0
    break;
491
492
0
  default:
493
0
    return ERROR_INVALID_ARGUMENT;
494
13.9k
  }
495
496
13.9k
  return ERROR_SUCCESS;
497
13.9k
}
498
499
////////////////////////////////////////////////////////////////////////////////
500
// Get a configuration option.
501
//
502
// This function receives a configuration name, as defined by the YR_CONFIG_NAME
503
// and a value for the configuration being set. Only configuration names with
504
// type uint32_t will be accepted, if not ERROR_INVALID_ARGUMENT will be
505
// returned.
506
//
507
// Returns:
508
//   ERROR_SUCCESS
509
//   ERROR_INVALID_ARGUMENT
510
//
511
YR_API int yr_get_configuration_uint32(YR_CONFIG_NAME name, uint32_t *dest)
512
13.9k
{
513
13.9k
  switch (name)
514
13.9k
  {
515
  // Accept only the configuration options that are of type uint32_t.
516
6.97k
  case YR_CONFIG_STACK_SIZE:
517
6.97k
  case YR_CONFIG_MAX_STRINGS_PER_RULE:
518
13.9k
  case YR_CONFIG_MAX_MATCH_DATA:
519
13.9k
    return yr_get_configuration(name, (void *) dest);
520
0
  default:
521
0
    return ERROR_INVALID_ARGUMENT;
522
13.9k
  }
523
13.9k
}
524
525
////////////////////////////////////////////////////////////////////////////////
526
// Get a configuration option.
527
//
528
// See yr_get_configuration_uint64 for more details.
529
//
530
YR_API int yr_get_configuration_uint64(YR_CONFIG_NAME name, uint64_t *value)
531
0
{
532
0
  switch (name)
533
0
  {
534
0
  case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
535
0
    return yr_get_configuration(name, (void *) value);
536
0
  default:
537
0
    return ERROR_INVALID_ARGUMENT;
538
0
  }
539
0
}