-
Notifications
You must be signed in to change notification settings - Fork 922
Expand file tree
/
Copy pathclamav.h
More file actions
2489 lines (2311 loc) · 102 KB
/
Copy pathclamav.h
File metadata and controls
2489 lines (2311 loc) · 102 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
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
394
395
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
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (C) 2013-2026 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2013 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef __CLAMAV_H
#define __CLAMAV_H
#ifdef _WIN32
#ifndef OWN_WINSOCK
#include <winsock2.h>
#endif
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Certain OSs already use 64bit variables in their stat struct */
#if (!defined(__FreeBSD__) && !defined(__APPLE__))
#define STAT64_OK 1
#else
#define STAT64_OK 0
#endif
#if defined(HAVE_STAT64) && STAT64_OK
#include <unistd.h>
#define STATBUF struct stat64
#define CLAMSTAT stat64
#define LSTAT lstat64
#define FSTAT fstat64
#define safe_open(a, b) open(a, b | O_LARGEFILE)
#else
#define STATBUF struct stat
#define CLAMSTAT stat
#define LSTAT lstat
#define FSTAT fstat
/* Nothing is safe in windows, not even open, safe_open defined under /win32 */
#ifndef _WIN32
#define safe_open open
#endif
#endif
/* Apple does not define __pid_t */
#ifdef __APPLE__
typedef pid_t __pid_t;
#endif
#define UNUSEDPARAM(x) (void)(x)
#include <sys/types.h>
#include <sys/stat.h>
#include <stdbool.h>
#include "clamav-types.h"
#include "clamav-version.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CL_COUNT_PRECISION 4096
/**
* @brief Scan verdicts for cl_scanmap_ex(), cl_scanfile_ex(), and cl_scandesc_ex().
*/
typedef enum cl_verdict_t {
CL_VERDICT_NOTHING_FOUND = 0, /**< No alerting signatures matched. */
CL_VERDICT_TRUSTED, /**< The scan target has been deemed trusted (e.g. by FP signature or Authenticode). */
CL_VERDICT_STRONG_INDICATOR, /**< One or more strong indicator signatures matched. */
CL_VERDICT_POTENTIALLY_UNWANTED, /**< One or more potentially unwanted signatures matched. */
} cl_verdict_t;
/**
* @brief Return codes used by libclamav functions.
*/
typedef enum cl_error_t {
/* libclamav specific */
CL_CLEAN = 0,
CL_SUCCESS = 0,
CL_VIRUS,
CL_ENULLARG,
CL_EARG,
CL_EMALFDB,
CL_ECVD,
CL_EVERIFY,
CL_EUNPACK,
/* I/O and memory errors */
CL_EOPEN,
CL_ECREAT,
CL_EUNLINK,
CL_ESTAT,
CL_EREAD,
CL_ESEEK,
CL_EWRITE,
CL_EDUP,
CL_EACCES,
CL_ETMPFILE,
CL_ETMPDIR,
CL_EMAP,
CL_EMEM,
CL_ETIMEOUT,
/* internal (not reported outside libclamav) */
CL_BREAK,
CL_EMAXREC,
CL_EMAXSIZE,
CL_EMAXFILES,
CL_EFORMAT,
CL_EPARSE,
CL_EBYTECODE, /** may be reported in testmode */
CL_EBYTECODE_TESTFAIL, /** may be reported in testmode */
CL_ELOCK,
CL_EBUSY,
CL_ESTATE,
CL_VERIFIED, /** The scan target has been deemed trusted */
CL_ERROR, /** Unspecified / generic error */
/* no error codes below this line please */
CL_ELAST_ERROR
} cl_error_t;
/* db options */
// clang-format off
#define CL_DB_PHISHING 0x2
#define CL_DB_PHISHING_URLS 0x8
#define CL_DB_PUA 0x10
#define CL_DB_CVDNOTMP 0x20 /** @deprecated obsolete */
#define CL_DB_OFFICIAL 0x40 /** internal */
#define CL_DB_PUA_MODE 0x80
#define CL_DB_PUA_INCLUDE 0x100
#define CL_DB_PUA_EXCLUDE 0x200
#define CL_DB_COMPILED 0x400 /** internal */
#define CL_DB_DIRECTORY 0x800 /** internal */
#define CL_DB_OFFICIAL_ONLY 0x1000
#define CL_DB_BYTECODE 0x2000
#define CL_DB_SIGNED 0x4000 /** internal */
#define CL_DB_BYTECODE_UNSIGNED 0x8000 /** Caution: You should never run bytecode signatures from untrusted sources.
* Doing so may result in arbitrary code execution. */
#define CL_DB_UNSIGNED 0x10000 /** internal */
#define CL_DB_BYTECODE_STATS 0x20000
#define CL_DB_ENHANCED 0x40000
#define CL_DB_PCRE_STATS 0x80000
#define CL_DB_YARA_EXCLUDE 0x100000
#define CL_DB_YARA_ONLY 0x200000
#define CL_DB_FIPS_LIMITS 0x400000 /** Disable MD5 and SHA1 methods for trusting files and verifying certificates.
* Means: 1. CVD must be signed with external `.sign` file.
* 2. Disables support for `.fp` signatures. */
/* recommended db settings */
#define CL_DB_STDOPT (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE)
/*** scan options ***/
struct cl_scan_options {
uint32_t general;
uint32_t parse;
uint32_t heuristic;
uint32_t mail;
uint32_t dev;
};
/* general */
#define CL_SCAN_GENERAL_ALLMATCHES 0x1 /** scan in all-match mode */
#define CL_SCAN_GENERAL_COLLECT_METADATA 0x2 /** collect metadata (--gen-json) */
#define CL_SCAN_GENERAL_HEURISTICS 0x4 /** option to enable heuristic alerts */
#define CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE 0x8 /** allow heuristic match to take precedence */
#define CL_SCAN_GENERAL_UNPRIVILEGED 0x10 /** scanner will not have read access to files */
#define CL_SCAN_GENERAL_STORE_HTML_URIS 0x20 /** when collect-metadata enabled: store uris found in html <a and <form tags */
#define CL_SCAN_GENERAL_STORE_PDF_URIS 0x40 /** when collect-metadata enabled: store uris found in pdf /URI tags */
#define CL_SCAN_GENERAL_STORE_EXTRA_HASHES 0x80 /** when collect-metadata enabled: calculate and store each type of supported file hash */
/* parsing capabilities options */
#define CL_SCAN_PARSE_ARCHIVE 0x1
#define CL_SCAN_PARSE_ELF 0x2
#define CL_SCAN_PARSE_PDF 0x4
#define CL_SCAN_PARSE_SWF 0x8
#define CL_SCAN_PARSE_HWP3 0x10
#define CL_SCAN_PARSE_XMLDOCS 0x20
#define CL_SCAN_PARSE_MAIL 0x40
#define CL_SCAN_PARSE_OLE2 0x80
#define CL_SCAN_PARSE_HTML 0x100
#define CL_SCAN_PARSE_PE 0x200
#define CL_SCAN_PARSE_ONENOTE 0x400
#define CL_SCAN_PARSE_IMAGE 0x800 /** option to enable/disable parsing images (graphics) */
#define CL_SCAN_PARSE_IMAGE_FUZZY_HASH 0x1000 /** option to enable/disable image fuzzy hash calculation. */
/* heuristic alerting options */
#define CL_SCAN_HEURISTIC_BROKEN 0x2 /** alert on broken PE and broken ELF files */
#define CL_SCAN_HEURISTIC_EXCEEDS_MAX 0x4 /** alert when files exceed scan limits (filesize, max scansize, or max recursion depth) */
#define CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH 0x8 /** alert on SSL mismatches */
#define CL_SCAN_HEURISTIC_PHISHING_CLOAK 0x10 /** alert on cloaked URLs in emails */
#define CL_SCAN_HEURISTIC_MACROS 0x20 /** alert on OLE2 files containing macros */
#define CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE 0x40 /** alert if archive is encrypted (rar, zip, etc) */
#define CL_SCAN_HEURISTIC_ENCRYPTED_DOC 0x80 /** alert if a document is encrypted (pdf, docx, etc) */
#define CL_SCAN_HEURISTIC_PARTITION_INTXN 0x100 /** alert if partition table size doesn't make sense */
#define CL_SCAN_HEURISTIC_STRUCTURED 0x200 /** data loss prevention options, i.e. alert when detecting personal information */
#define CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL 0x400 /** alert when detecting social security numbers */
#define CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED 0x800 /** alert when detecting stripped social security numbers */
#define CL_SCAN_HEURISTIC_STRUCTURED_CC 0x1000 /** alert when detecting credit card numbers */
#define CL_SCAN_HEURISTIC_BROKEN_MEDIA 0x2000 /** alert if a file does not match the identified file format, works with JPEG, TIFF, GIF, PNG */
/* mail scanning options */
#define CL_SCAN_MAIL_PARTIAL_MESSAGE 0x1
/* dev options */
#define CL_SCAN_DEV_COLLECT_SHA 0x1 /** @deprecated (functionality removed) */
#define CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO 0x2 /** collect performance timings */
/* cl_countsigs options */
#define CL_COUNTSIGS_OFFICIAL 0x1
#define CL_COUNTSIGS_UNOFFICIAL 0x2
#define CL_COUNTSIGS_ALL (CL_COUNTSIGS_OFFICIAL | CL_COUNTSIGS_UNOFFICIAL)
/* For the new engine_options bit field in the engine */
#define ENGINE_OPTIONS_NONE 0x0
#define ENGINE_OPTIONS_DISABLE_CACHE 0x1
#define ENGINE_OPTIONS_FORCE_TO_DISK 0x2
/* 0x4 was ENGINE_OPTIONS_DISABLE_PE_STATS; keep later bits stable. */
#define ENGINE_OPTIONS_DISABLE_PE_CERTS 0x8
#define ENGINE_OPTIONS_PE_DUMPCERTS 0x10
#define ENGINE_OPTIONS_TMPDIR_RECURSION 0x20
#define ENGINE_OPTIONS_FIPS_LIMITS 0x40
// clang-format on
struct cl_engine;
struct cl_settings;
/* ----------------------------------------------------------------------------
* Enable global libclamav features.
*/
/**
* @brief Enable debug messages
*/
extern void cl_debug(void);
/**
* @brief Set libclamav to always create section hashes for PE files.
*
* Section hashes are used in .mdb signature.
*/
extern void cl_always_gen_section_hash(void);
/* ----------------------------------------------------------------------------
* Scan engine functions.
*/
/**
* @brief This function initializes the openssl crypto system.
*
* Called by cl_init() and does not need to be cleaned up as de-init
* is handled automatically by openssl 1.0.2.h and 1.1.0
*
* @return Always returns 0
*/
int cl_initialize_crypto(void);
/**
* @brief Clean up ssl crypto inits.
*
* @deprecated This function is deprecated and will be removed in a future release.
* Call to EVP_cleanup() has been removed since cleanup is now handled by
* auto-deinit as of openssl 1.0.2h and 1.1.0.
*/
void cl_cleanup_crypto(void);
#define CL_INIT_DEFAULT 0x0
/**
* @brief Initialize the ClamAV library.
*
* @param initoptions Unused.
* @return cl_error_t CL_SUCCESS if everything initialized correctly.
*/
extern cl_error_t cl_init(unsigned int initoptions);
/**
* @brief Allocate a new scanning engine and initialize default settings.
*
* The engine must be freed with `cl_engine_free()`.
*
* @return struct cl_engine* Pointer to the scanning engine.
*/
extern struct cl_engine *cl_engine_new(void);
enum cl_engine_field {
CL_ENGINE_MAX_SCANSIZE, /** uint64_t */
CL_ENGINE_MAX_FILESIZE, /** uint64_t */
CL_ENGINE_MAX_RECURSION, /** uint32_t */
CL_ENGINE_MAX_FILES, /** uint32_t */
CL_ENGINE_MIN_CC_COUNT, /** uint32_t */
CL_ENGINE_MIN_SSN_COUNT, /** uint32_t */
CL_ENGINE_PUA_CATEGORIES, /** (char *) */
CL_ENGINE_DB_OPTIONS, /** uint32_t */
CL_ENGINE_DB_VERSION, /** uint32_t */
CL_ENGINE_DB_TIME, /** time_t */
CL_ENGINE_AC_ONLY, /** uint32_t */
CL_ENGINE_AC_MINDEPTH, /** uint32_t */
CL_ENGINE_AC_MAXDEPTH, /** uint32_t */
CL_ENGINE_TMPDIR, /** (char *) */
CL_ENGINE_KEEPTMP, /** uint32_t */
CL_ENGINE_BYTECODE_SECURITY, /** uint32_t */
CL_ENGINE_BYTECODE_TIMEOUT, /** uint32_t */
CL_ENGINE_BYTECODE_MODE, /** uint32_t */
CL_ENGINE_MAX_EMBEDDEDPE, /** uint64_t */
CL_ENGINE_MAX_HTMLNORMALIZE, /** uint64_t */
CL_ENGINE_MAX_HTMLNOTAGS, /** uint64_t */
CL_ENGINE_MAX_SCRIPTNORMALIZE, /** uint64_t */
CL_ENGINE_MAX_ZIPTYPERCG, /** uint64_t */
CL_ENGINE_FORCETODISK, /** uint32_t */
CL_ENGINE_CACHE_SIZE, /** uint32_t */
CL_ENGINE_DISABLE_CACHE, /** uint32_t */
CL_ENGINE_MAX_PARTITIONS, /** uint32_t */
CL_ENGINE_MAX_ICONSPE, /** uint32_t */
CL_ENGINE_MAX_RECHWP3, /** uint32_t */
CL_ENGINE_MAX_SCANTIME, /** uint32_t */
CL_ENGINE_PCRE_MATCH_LIMIT, /** uint64_t */
CL_ENGINE_PCRE_RECMATCH_LIMIT, /** uint64_t */
CL_ENGINE_PCRE_MAX_FILESIZE, /** uint64_t */
CL_ENGINE_DISABLE_PE_CERTS, /** uint32_t */
CL_ENGINE_PE_DUMPCERTS, /** uint32_t */
CL_ENGINE_CVDCERTSDIR, /** (char *) */
CL_ENGINE_TMPDIR_RECURSION, /** uint32_t */
CL_ENGINE_FIPS_LIMITS, /** uint32_t */
};
enum bytecode_security {
CL_BYTECODE_TRUST_ALL = 0, /** @deprecated obsolete */
CL_BYTECODE_TRUST_SIGNED, /** default */
CL_BYTECODE_TRUST_NOTHING /** paranoid setting */
};
enum bytecode_mode {
CL_BYTECODE_MODE_AUTO = 0, /** JIT if possible, fallback to interpreter */
CL_BYTECODE_MODE_JIT, /** force JIT */
CL_BYTECODE_MODE_INTERPRETER, /** force interpreter */
CL_BYTECODE_MODE_TEST, /** both JIT and interpreter, compare results, all failures are fatal */
CL_BYTECODE_MODE_OFF /** for query only, not settable */
};
/**
* @brief Set a numerical engine option.
*
* Caution: changing options for an engine that is in-use is not thread-safe!
*
* @param engine An initialized scan engine.
* @param cl_engine_field A CL_ENGINE option.
* @param num The new engine option value.
* @return cl_error_t CL_SUCCESS if successfully set.
* @return cl_error_t CL_EARG if the field number was incorrect.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long long num);
/**
* @brief Get a numerical engine option.
*
* @param engine An initialized scan engine.
* @param cl_engine_field A CL_ENGINE option.
* @param err (optional) A cl_error_t status code.
* @return long long The numerical option value.
*/
extern long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field field, int *err);
/**
* @brief Set a string engine option.
*
* If the string option has already been set, the existing string will be free'd
* and the new string will replace it.
*
* Caution: changing options for an engine that is in-use is not thread-safe!
*
* @param engine An initialized scan engine.
* @param cl_engine_field A CL_ENGINE option.
* @param str The new engine option value.
* @return cl_error_t CL_SUCCESS if successfully set.
* @return cl_error_t CL_EARG if the field number was incorrect.
* @return cl_error_t CL_EMEM if a memory allocation error occurred.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_set_str(struct cl_engine *engine, enum cl_engine_field field, const char *str);
/**
* @brief Get a string engine option.
*
* @param engine An initialized scan engine.
* @param cl_engine_field A CL_ENGINE option.
* @param err (optional) A cl_error_t status code.
* @return const char * The string option value.
*/
extern const char *cl_engine_get_str(const struct cl_engine *engine, enum cl_engine_field field, int *err);
/**
* @brief Copy the settings from an existing scan engine.
*
* The cl_settings pointer is allocated and must be freed with cl_engine_settings_free().
*
* @param engine An configured scan engine.
* @return struct cl_settings* The settings.
*/
extern struct cl_settings *cl_engine_settings_copy(const struct cl_engine *engine);
/**
* @brief Apply settings from a settings structure to a scan engine.
*
* Caution: changing options for an engine that is in-use is not thread-safe!
*
* @param engine A scan engine.
* @param settings The settings.
* @return cl_error_t CL_SUCCESS if successful.
* @return cl_error_t CL_EMEM if a memory allocation error occurred.
*/
extern cl_error_t cl_engine_settings_apply(struct cl_engine *engine, const struct cl_settings *settings);
/**
* @brief Free a settings struct pointer.
*
* @param settings The settings struct pointer.
* @return cl_error_t CL_SUCCESS if successful.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_settings_free(struct cl_settings *settings);
/**
* @brief Prepare the scanning engine.
*
* Call this after all required databases have been loaded and settings have
* been applied.
*
* @param engine A scan engine.
* @return cl_error_t CL_SUCCESS if successful.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_compile(struct cl_engine *engine);
/**
* @brief Add a reference count to the engine.
*
* Thread safety mechanism so that the engine is not free'd by another thread.
*
* The engine is initialized with refcount = 1, so this only needs to be called
* for additional scanning threads.
*
* @param engine A scan engine.
* @return cl_error_t CL_SUCCESS if successful.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_addref(struct cl_engine *engine);
/**
* @brief Free an engine.
*
* Will lower the reference count on an engine. If the reference count hits
* zero, the engine will be freed.
*
* @param engine A scan engine.
* @return cl_error_t CL_SUCCESS if successful.
* @return cl_error_t CL_ENULLARG null arguments were provided.
*/
extern cl_error_t cl_engine_free(struct cl_engine *engine);
/* ----------------------------------------------------------------------------
* ClamAV File Map Abstraction Public API.
*/
struct cl_fmap;
typedef struct cl_fmap cl_fmap_t;
/**
* @brief Read callback function type.
*
* A callback function pointer type for reading data from a cl_fmap_t that uses
* reads data from a handle interface.
*
* Read 'count' bytes starting at 'offset' into the buffer 'buf'
*
* Thread safety: It is guaranteed that only one callback is executing for a
* specific handle at any time, but there might be multiple callbacks executing
* for different handle at the same time.
*
* @param handle The handle passed to cl_fmap_open_handle, its meaning is up
* to the callback's implementation
* @param buf A buffer to read data into, must be at least offset + count
* bytes in size.
* @param count The number of bytes to read.
* @param offset The offset into buf to read the data to. If successful,
* the number of bytes actually read is returned. Upon reading
* end-of-file, zero is returned. Otherwise, a -1 is returned
* and the global variable errno is set to indicate the error.
*/
typedef off_t (*clcb_pread)(void *handle, void *buf, size_t count, off_t offset);
/**
* @brief Open a map given a handle.
*
* Open a map for scanning custom data accessed by a handle and pread (lseek +
* read)-like interface. For example a file descriptor or a WIN32 HANDLE.
* By default fmap will use aging to discard old data, unless you tell it not
* to.
*
* The handle will be passed to the callback each time.
*
* TIP: Check the size limits before calling this function so you don't map a
* file that is larger than the maximum size the engine is configured to scan.
*
* Note that the offset and len is for the start through the end of an _entire_
* file, which may be contained within another larger file.
* You can't give it parts of a file and expect detection to work.
*
* @param handle A handle that may be accessed using lseek + read.
* @param offset Initial offset to start scanning.
* @param len Length of the data from the start (not the offset).
* @param pread_cb A callback function to read data from the handle.
* @param use_aging Set to a non-zero value to enable aging.
* @return cl_fmap_t* A map representing the handle interface.
*/
extern cl_fmap_t *cl_fmap_open_handle(
void *handle,
size_t offset,
size_t len,
clcb_pread pread_cb,
int use_aging);
/**
* @brief Open a map given a buffer.
*
* Open a map for scanning custom data, where the data is already in memory,
* either in the form of a buffer, a memory mapped file, etc.
*
* Note that the memory [start, start+len) must be the _entire_ file,
* you can't give it parts of a file and expect detection to work.
*
* @param start Pointer to a buffer of data.
* @param len Length in bytes of the data.
* @return cl_fmap_t* A map representing the buffer.
*/
extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len);
/**
* @brief Set the utf8 name of a file map. E.g. "invoice.exe"
*
* The name is used for debugging and logging purposes.
* In a future release, the file extension may help determine refine file type
* detection. E.g. ".js" may indicate that something previously identified as
* a text file is more specifically a JavaScript file.
* That is - at this time setting the name will have no impact on detection,
* but it may in the future.
*
* @param map The file map to modify.
* @param name The new name for the file map.
* @return cl_error_t CL_SUCCESS if the name was set successfully.
*/
extern cl_error_t cl_fmap_set_name(cl_fmap_t *map, const char *name);
/**
* @brief Get the utf8 name of a file map.
*
* The name is used for debugging and logging purposes.
*
* @param map The file map to query.
* @param[out] name_out Pointer to a variable to receive the name of the file map.
* @return const char* The name of the file map, or NULL if not set.
*/
extern cl_error_t cl_fmap_get_name(cl_fmap_t *map, const char **name_out);
/**
* @brief Set the utf8 path of a file map. E.g. "/tmp/invoice.exe"
*
* This is used to set the actual file path of the mapped map.
* The path may be used for debugging or logging purposes.
*
* You might want to set the path if you opened the map with `cl_fmap_open_handle()`.
*
* @param map The file map to modify.
* @param path The new path for the file map.
* @return cl_error_t CL_SUCCESS if the path was set successfully.
*/
extern cl_error_t cl_fmap_set_path(cl_fmap_t *map, const char *path);
/**
* @brief Get the utf8 path of a file map.
*
* The path is used for debugging and logging purposes.
*
* This may be NULL even if there is a file descriptor associated with the map.
* There is no guarantee that the path was set by whomever created the map.
* For example, if the map was created from a file descriptor that was provided
* to clamd by clamonacc or clamdscan using fd-passing, then the path may not be
* known.
*
* This of course will be NULL if the map was created from a memory buffer.
*
* If you need a temp file for each file extracted, you can use ClamAV's
* force-to-disk feature. Note: There is no option to force-to-memory.
* Many of the parser modules will create temporary files no matter what.
*
* If the fmap represents a temp file created during the scan, then unless you
* use CL_ENGINE_KEEPTMP, it will be deleted when the scan is done with this
* layer.
*
* @param map The file map to query.
* @param[out] path_out Pointer to a variable to receive the path of the file map.
* @param[out] offset_out (optional) Pointer to a variable to receive the offset of the current layer within the given file.
* @param[out] len_out (optional) Pointer to a variable to receive the length of the current layer within the given file.
* @return cl_error_t CL_SUCCESS if the path was successfully retrieved.
* CL_EACCES if the map does not have a file descriptor.
* CL_ENULLARG if null arguments were provided.
*/
extern cl_error_t cl_fmap_get_path(cl_fmap_t *map, const char **path_out, size_t *offset_out, size_t *len_out);
/**
* @brief Get the file descriptor of a file map.
*
* The file descriptor is used to access the file represented by the file map.
* If the file map was created from a file descriptor, this will return that
* descriptor. Otherwise, it will return -1.
*
* If you need a temp file for each file extracted, you can use ClamAV's
* force-to-disk feature. Note: There is no option to force-to-memory.
* Many of the parser modules will create temporary files no matter what.
*
* Don't close this file descriptor. Don't dup it either.
*
* @param map The file map to query.
* @param[out] fd_out Pointer to a variable to receive the file descriptor.
* @param[out] offset_out (optional) Pointer to a variable to receive the offset of the current layer within the given file.
* @param[out] len_out (optional) Pointer to a variable to receive the length of the current layer within the given file.
* @return cl_error_t CL_SUCCESS if the file descriptor was successfully retrieved.
* CL_EACCES if the map does not have a file descriptor.
* CL_ENULLARG if null arguments were provided.
*/
extern cl_error_t cl_fmap_get_fd(const cl_fmap_t *map, int *fd_out, size_t *offset_out, size_t *len_out);
/**
* @brief Get the file size of the current layer from a file map.
*
* This function retrieves the size of the file represented by the file map.
* If the file map was created from a handle, it will use the pread callback
* to determine the size.
*
* @param map The file map to query.
* @param[out] size_out Pointer to a variable to receive the size of the file.
* @return cl_error_t CL_SUCCESS if the file size was successfully retrieved.
*/
extern cl_error_t cl_fmap_get_size(const cl_fmap_t *map, size_t *size_out);
/**
* @brief Set the file hash for a file map.
*
* This function sets the hash of the file represented by the file map.
* If a hash of the requested type has already been calculated, it will be
* overwritten with the new value.
*
* @param map The file map to modify.
* @param hash_alg The hash algorithm to use (e.g., "md5", "sha1", "sha2-256").
* @param hash The hash value to set.
* @return cl_error_t CL_SUCCESS if the hash was successfully set.
*/
extern cl_error_t cl_fmap_set_hash(const cl_fmap_t *map, const char *hash_alg, char hash);
/**
* @brief Check if we already calculated a file hash of a specific type.
*
* This function checks if the file represented by the file map has a hash
* of the requested type already calculated.
*
* @param map A file map.
* @param hash_alg The hash algorithm to check (e.g., "md5", "sha1", "sha2-256").
* @param[out] have_hash_out Pointer to a boolean that will be set to true if the hash exists, false otherwise.
* @return cl_error_t CL_SUCCESS if the check was successful.
*/
extern cl_error_t cl_fmap_have_hash(const cl_fmap_t *map, const char *hash_alg, bool *have_hash_out);
/**
* @brief Indicate that we will need a file hash of a specific type later.
*
* This function indicates that we will need the file hash of the requested
* type in the future. The next time a hash is calculated, (e.g. when you run
* `cl_fmap_get_hash()`, it will also calculate the requested hash type.
*
* This is an optimization to avoid iterating over the file contents multiple times
* which might happen if you call `cl_fmap_get_hash()` without calling this first.
*
* @param map A file map.
* @param hash_alg The hash algorithm to indicate (e.g., "md5", "sha1", "sha2-256").
* @return cl_error_t CL_SUCCESS if the indication was successful.
*/
extern cl_error_t cl_fmap_will_need_hash_later(const cl_fmap_t *map, const char *hash_alg);
/**
* @brief Get the file hash from a file map.
*
* This function retrieves the hash of the file represented by the file map.
* If a hash of the requested type has NOT already been calculated then it will
* be calculated when you call this function, and stored for future use.
*
* You are responsible for freeing the hash string when you're done with it.
*
* @param map A file map.
* @param hash_alg The hash algorithm to use (e.g., "md5", "sha1", "sha2-256").
* @param[out] hash_out Malloced string containing the hash value.
* @return cl_error_t CL_SUCCESS if the hash was successfully retrieved.
*/
extern cl_error_t cl_fmap_get_hash(const cl_fmap_t *map, const char *hash_alg, char **hash_out);
/**
* @brief Get the file contents from a file map.
*
* This function will get you a pointer to the contents of the file represented
* by the file map. This is read-only and is not malloced.
* If you want a copy to keep, you must copy it yourself.
*
* Use the offset and length parameters to specify the range of the file you
* want to retrieve. If you don't need the whole file, don't ask for the whole file.
*
* @param map A file map.
* @param offset The offset in the file from which to access.
* @param len The length of the data to read.
* If 0, then the rest of the file will be provided.
* @param[out] data_out A valid pointer to data file contents. Will be NULL if failed.
* @param[out] data_len_out The length of the file contents. May be less than requested if the end of file is reached.
* @return cl_error_t CL_SUCCESS if the contents were successfully retrieved.
*/
extern cl_error_t cl_fmap_get_data(
const cl_fmap_t *map,
size_t offset,
size_t len,
const uint8_t **data_out,
size_t *data_len_out);
/**
* @brief Releases resources associated with the map.
*
* You must release any resources you hold only after (handles, maps) calling
* this function.
*
* @param map Map to be closed.
*/
extern void cl_fmap_close(cl_fmap_t *);
/* ----------------------------------------------------------------------------
* ClamAV Recursive Scan Layer Public API.
*/
struct cl_scan_layer;
typedef struct cl_scan_layer cl_scan_layer_t;
/**
* @brief Get the file map associated with a scan layer.
*
* @param layer The scan layer to query.
* @param[out] fmap_out Pointer to a variable to receive the file map.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_fmap(
cl_scan_layer_t *layer,
cl_fmap_t **fmap_out);
/**
* @brief Get the parent layer of a scan layer.
*
* You may use this in a loop/recursively to walk the scan layers.
* Also consider using `cl_scan_layer_get_recursion_level()` to determine the
* depth of the current layer.
*
* @param layer The scan layer to query.
* @param[out] parent_layer_out Pointer to a variable to receive the parent layer.
* Will be NULL if the layer has no parent.
* For example, the root layer has no parent.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_parent_layer(
cl_scan_layer_t *layer,
cl_scan_layer_t **parent_layer_out);
/**
* @brief Get the file type of a scan layer.
*
* The file type as clamav currently believes it to be.
* It may change later in the scan, so consider using `clcb_file_type_correction`
* callback to access the file again if it is re-typed.
*
* @param layer The scan layer to query.
* @param[out] type_out Pointer to a variable to receive the file type.
* This is a static reference and must not be freed.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_type(
cl_scan_layer_t *layer,
const char **type_out);
/**
* @brief Get the recursion level of a scan layer.
*
* @param layer The scan layer to query.
* @param[out] recursion_level_out Pointer to a variable to receive the recursion level.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_recursion_level(
cl_scan_layer_t *layer,
uint32_t *recursion_level_out);
/**
* @brief Get the object ID of a scan layer.
*
* Object ID is a unique identifier for the scan layer. It counts up from 0, although the callback interface
* may skip some IDs if the scan layer is processed immediately rather than being handled as distinct file type.
* For example, HTML may be normalized several ways and they're each given an Object ID, but we immediately
* pattern match them and do not handle them as distinct file types that were contained within the HTML.
*
* @param layer The scan layer to query.
* @param[out] object_id_out Pointer to a variable to receive the object ID.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_object_id(
cl_scan_layer_t *layer,
uint64_t *object_id_out);
/**
* @brief Get the last detected alert name from a scan layer.
*
* Do not free the alert name, and make a copy if you need one.
*
* @param layer The scan layer to query.
* @param[out] alert_name_out Pointer to a variable to receive the alert name.
* If the layer has no alerts, this will be set to NULL.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_last_alert(
cl_scan_layer_t *layer,
const char **alert_name_out);
/*
* Attributes of each layer in scan.
*/
#define LAYER_ATTRIBUTES_NONE 0x0 /**< No attributes set. */
#define LAYER_ATTRIBUTES_NORMALIZED 0x1 /**< This layer was modified to make matching more generic, reliable. */
#define LAYER_ATTRIBUTES_DECRYPTED 0x2 /**< Decryption was used to extract this layer. \
* E.g. ClamAV was able to decrypt an encrypted file entry in the parent layer. */
#define LAYER_ATTRIBUTES_RETYPED 0x4 /**< This layer is a re-scan of the parent layer but as a new type (e.g. using HandlerType). */
#define LAYER_ATTRIBUTES_EMBEDDED 0x8 /**< This layer was found within the parent layer using FTM signatures \
* (e.g. like ZIP entries found within an executable). */
/**
* @brief Get the attributes of a scan layer.
*
* @param layer The scan layer to query.
* @param[out] attributes_out Pointer to a variable to receive the layer attributes.
* @return cl_error_t CL_SUCCESS if successful.
*/
extern cl_error_t cl_scan_layer_get_attributes(
cl_scan_layer_t *layer,
uint32_t *attributes_out);
/* ----------------------------------------------------------------------------
* Callback function type definitions.
*/
typedef enum scan_callback {
/** Pre-hash
*
* Occurs just after basic file-type detection and before any hashes have been calculated either for the cache or
* the gen-json metadata.
* If you want any hashes other than SHA2-256, the most efficient option is to run the
* `cl_fmap_will_need_hash_later()` function in this callback for each and then run the `cl_fmap_get_hash()`
* function afterwards (now or later) to gather the hashes.
*
* Using this callback will appear in-order for ClamAV's depth-first approach.
*/
CL_SCAN_CALLBACK_PRE_HASH,
/** Pre-scan
*
* Occurs before parser modules run and before pattern matching.
*
* Using this callback will appear in-order for ClamAV's depth-first approach.
*/
CL_SCAN_CALLBACK_PRE_SCAN,
/** Post-scan
*
* Occurs after pattern matching and after running parser modules (i.e. scan complete for this layer).
* This callback is useful for post-processing the results of the scan, but is the most likely of the callbacks to
* be skipped if something goes critically wrong or the hash for the layer appeared in the clean-cache.
*
* Using this callback will appear in REVERSE-order for ClamAV's depth-first approach.
*/
CL_SCAN_CALLBACK_POST_SCAN,
/** Alert
*
* Occurs each time an alert (detection) would be triggered during a scan.
* In all-match mode, you may receive multiple alerts for the same file, and even the same layer, corresponding with
* each signature that matched.
*/
CL_SCAN_CALLBACK_ALERT,
/** File type
*
* Occurs each time the file type determination is refined.
* This may happen more than once per LAYER!
*
* Outside of using this callback, The most accurate time to check the file type would be:
* - For each layer: Use `cl_scan_layer_get_type()` in the `CL_SCAN_CALLBACK_POST_SCAN` callback.
* - For just the top layer: Use the `file_type_out` parameter provided by the `cl_scan*ex()` functions.
*/
CL_SCAN_CALLBACK_FILE_TYPE
} cl_scan_callback_t;
/**
* @brief Callback interface to get access to the current layer using the scan-
* layer abstraction. This grants access to file content and attributes as well
* as those of each ancestor layers (if any).
*
* Called for each processed file including both the top level file (i.e. the
* zeroeth layer) and all contained files (recursively).
*
* @param layer Scan layer (abstraction) for the current layer being scanned.
* Use the `cl_scan_layer_*` functions to access layer data and metadata.
* You may want to use `cl_scan_layer_get_fmap()` to get the file map for the current layer.
* You may also use it to access ancestor layers using `cl_scan_layer_get_parent_layer()`.
*
* @param context The application context pointer passed in to the `cl_scan*()` function.
*
* @return CL_BREAK
*
* Scan aborted by callback (the rest of the scan is skipped).
* This does not mark the file as clean or infected, it just skips the rest of the scan.
*
* @return CL_SUCCESS
*
* File scan will continue.
*
* For CL_SCAN_CALLBACK_ALERT: Means you want to ignore this specific alert and keep scanning.
* This is different than CL_VERIFIED because it does not affect prior or future alerts.
* Return CL_VERIFIED instead if you want to remove prior alerts for this layer and skip
* the rest of the scan for this layer.
*
* @return CL_VIRUS
*
* This will mark the file as infected. A new alert will be added.
*
* For CL_SCAN_CALLBACK_ALERT: Means you agree with the alert (no extra alert needed).
* Remember that CL_SUCCESS means you want to ignore the alert.
*
* @return CL_VERIFIED
*
* Layer explicitly trusted by the callback and previous alerts removed FOR THIS layer.
* You might want to do this if you trust the hash or verified a digital signature.
* The rest of the scan will be skipped FOR THIS layer.
* For contained files, this does NOT mean that the parent or adjacent layers are trusted.
*/
typedef cl_error_t (*clcb_scan)(cl_scan_layer_t *layer, void *context);
/**
* @brief Set a callback function using the clcb_scan callback type.
*
* Select the callback location using the `cl_scan_callback_t` enum.
*
* Caution: changing options for an engine that is in-use is not thread-safe!
*
* @param engine The initialized scanning engine.
* @param callback The callback function pointer.
* @param location The location of the callback.
*/
extern void cl_engine_set_scan_callback(struct cl_engine *engine, clcb_scan callback, cl_scan_callback_t location);
/**
* @brief Pre-cache callback.
*
* @deprecated This function is deprecated and will be removed in a future release.
* Use `CL_SCAN_CALLBACK_PRE_HASH` with `cl_engine_set_scan_callback()` instead.
*
* Called for each processed file (both the entry level - AKA 'outer' - file and
* inner files - those generated when processing archive and container files), before
* the actual scanning takes place.
*
* @param fd File descriptor which is about to be scanned.
* @param type File type detected via magic - i.e. NOT on the fly - (e.g. "CL_TYPE_MSEXE").
* @param context Opaque application provided data.
* @return CL_SUCCESS = File is scanned.
* @return CL_BREAK = Allowed by callback - file is skipped and marked as clean.