-
Notifications
You must be signed in to change notification settings - Fork 22
/
callback.go
199 lines (175 loc) · 6.79 KB
/
callback.go
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
// Copyright 2013 the Go ClamAV authors
// Use of this source code is governed by a
// license that can be found in the LICENSE file.
// Package clamav is a wrapper around libclamav.
// For more information about libclamav see http://www.clamav.net
package clamav
/*
#include <clamav.h>
#include <stdlib.h>
cl_error_t precache_cgo(int fd, const char *type, void *context);
cl_error_t prescan_cgo(int fd, const char *type, void *context);
cl_error_t postscan_cgo(int fd, int result, char *virname, void *context);
void hash_cgo(int fd, unsigned long long size, const unsigned char *md5, const char *virname, void *context);
*/
import "C"
import "unsafe"
var callbackFuncs = map[string]interface{}{
"precache": nil,
"prescan": nil,
"postscan": nil,
"sigload": nil,
"hash": nil,
"msg": nil,
"meta": nil,
}
//export precacheCallback
func precacheCallback(fd C.int, ftype *C.char, context unsafe.Pointer) C.cl_error_t {
fn := callbackFuncs["precache"]
if fn == nil {
return Clean
}
ctx := findContext(context)
return C.cl_error_t(fn.(CallbackPreCache)(int(fd), C.GoString(ftype), ctx))
}
// SetPreCacheCallback sets the callback function to use with ClamAV's
// pre_cache callback
func (e *Engine) SetPreCacheCallback(cb CallbackPreCache) {
callbackFuncs["precache"] = cb
C.cl_engine_set_clcb_pre_cache((*C.struct_cl_engine)(unsafe.Pointer(e)), (C.clcb_pre_cache)(unsafe.Pointer(C.precache_cgo)))
}
//export prescanCallback
func prescanCallback(fd C.int, ftype *C.char, context unsafe.Pointer) C.cl_error_t {
v := callbackFuncs["prescan"]
if v == nil {
return Clean
}
ctx := findContext(context)
return C.cl_error_t(v.(CallbackPreScan)(int(fd), C.GoString(ftype), ctx))
}
// SetPreScanCallback will set the callback function ClamAV will call before a
// scan commences to the specified function
func (e *Engine) SetPreScanCallback(cb CallbackPreScan) {
callbackFuncs["prescan"] = cb
C.cl_engine_set_clcb_pre_scan((*C.struct_cl_engine)(unsafe.Pointer(e)), C.clcb_pre_scan(unsafe.Pointer(C.prescan_cgo)))
}
//export postscanCallback
func postscanCallback(fd, result C.int, virname *C.char, context unsafe.Pointer) C.cl_error_t {
v := callbackFuncs["postscan"]
if v == nil {
return Clean
}
ctx := findContext(context)
return C.cl_error_t(v.(CallbackPostScan)(int(fd), ErrorCode(result), C.GoString(virname), ctx))
}
// SetPostScanCallback will set the callback function ClamAV will call before the
// cache is consulted for a particular scan to cb
func (e *Engine) SetPostScanCallback(cb CallbackPostScan) {
callbackFuncs["postscan"] = cb
C.cl_engine_set_clcb_post_scan((*C.struct_cl_engine)(unsafe.Pointer(e)), (C.clcb_post_scan)(unsafe.Pointer(C.postscan_cgo)))
}
// PreadHandleCallbacks stores a pread function associated with each handle passed
// through FmapOpenHandle. The callbacks are used to read from the file/memory location
// associated with the handle
var preadHandleCallbacks = map[*interface{}]CallbackPread{}
//export preadCallback
func preadCallback(handle unsafe.Pointer, buf unsafe.Pointer, count C.size_t, offset C.off_t) C.off_t {
v, ok := preadHandleCallbacks[(*interface{})(handle)]
if !ok {
return -1 // couldn't find callback
}
return C.off_t(v((*interface{})(handle), C.GoBytes(buf, C.int(count)), int64(offset)))
}
// SetSigLoadCallback will set the callback function ClamAV will call before the
// cache is consulted for a particular scan to cb
// func (e *Engine) SetSigLoadCallback(cb CallbackSigLoad) ErrorCode {
// return 0
// }
//export msgcb
var msgcb = func(severity C.enum_cl_msg, fullmsg *C.char, msg *C.char, context unsafe.Pointer) {
v := callbackFuncs["msg"]
if v == nil {
return
}
ctx := findContext(context)
v.(CallbackMsg)(Msg(severity), C.GoString(fullmsg), C.GoString(msg), ctx)
}
// SetMsgCallback will set the callback function ClamAV will call for any error and warning
// messages. The specified callback will be called instead of logging to stderr.
// Messages of lower severity than specified are logged as usual.
//
// Just like with cl_debug() this must be called before going multithreaded.
// Callable before cl_init, if you want to log messages from cl_init() itself.
func SetMsgCallback(cb CallbackMsg) {
callbackFuncs["msg"] = cb
C.cl_set_clcb_msg((C.clcb_msg)(unsafe.Pointer(&msgcb)))
}
//export hashCallback
func hashCallback(fd C.int, size C.ulonglong, md5 *C.uchar, virname *C.char, context unsafe.Pointer) {
v := callbackFuncs["hash"]
if v == nil {
return
}
ctx := findContext(context)
v.(CallbackHash)(int(fd), uint64(size), []byte(C.GoBytes(unsafe.Pointer(md5), 16)), C.GoString(virname), ctx)
}
// SetHashCallback will set the callback function ClamAV will call with statistics
// about the scanned file
func (e *Engine) SetHashCallback(cb CallbackHash) {
callbackFuncs["hash"] = cb
C.cl_engine_set_clcb_hash((*C.struct_cl_engine)(unsafe.Pointer(e)), (C.clcb_hash)(unsafe.Pointer(C.hash_cgo)))
}
// FmapOpenHandle opens a file map for scanning custom data accessed by a handle and pread (lseek +
// read)-like interface, for example a WIN32 HANDLE.
// By default fmap will use aging to discard old data, unless you tell it not
// to via the parameter "age". The handle will be passed to the callback each time.
//
// FmapOpenHandle is currently unumplemented
func FmapOpenHandle(handle *interface{}, offset int64, length uint32, cb CallbackPread, age bool) *Fmap {
return nil
}
// FmapOpenMemory opens 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.
func FmapOpenMemory(buf []byte) *Fmap {
if len(buf) == 0 {
return nil
}
return (*Fmap)(C.cl_fmap_open_memory(unsafe.Pointer(&buf[0]), C.size_t(len(buf))))
}
// Close resources associated with the map, you should release any resources
// you hold only after (handles, maps) calling this function */
func (f *Fmap) Close() {
C.cl_fmap_close((*C.struct_cl_fmap)(f))
}
/* These below do not seem to exist in libclamav.a
* type cbData struct {
* cb interface{} // callback function
* }
*
*
* func metacb(container_type *C.char, fsize_container C.ulong, filename *C.char,
* realSize C.ulong, is_encrypted C.int, filepos_container C.uint, _ unsafe.Pointer) ErrorCode {
* var v cbData
* if v, ok := cb["meta"]; !ok || v.cb == nil {
* return
* }
* encr := false
* if(is_encrypted > 0) {
* encr = true
* }
* v.cb(C.GoString(container_type), uint64(fsize_container), C.GoString(filename), uint64(fsize_real), encr, uint64(filepos_container), v.ctx)
*}
*
*func (e *Engine) SetMetaCallback(cb CallbackMeta, context interface{}) ErrorCode {
* var v cbData
* if v, ok := cb["meta"]; !ok || v.cb == nil {
* return
* }
* v.cb = cb
* v.ctx = context
*
* return C.cl_engine_set_clcb_meta((C.clcb_meta)(unsafe.Pointer(metacb)))
*}
*/