Browse code

callback draft - WIP

aCaB authored on 2010/06/22 22:41:19
Showing 6 changed files
... ...
@@ -174,6 +174,52 @@ extern int cl_engine_addref(struct cl_engine *engine);
174 174
 extern int cl_engine_free(struct cl_engine *engine);
175 175
 
176 176
 
177
+/* CALLBACKS - WARNING: unstable API - WIP */
178
+
179
+
180
+typedef cl_error_t (*clcb_pre_scan)(int fd, void *context);
181
+/* PRE-SCAN
182
+Input:
183
+fd      = File descriptor which is about to be scanned
184
+context = Opaque application provided data
185
+
186
+Output:
187
+CL_CLEAN = File is scanned
188
+CL_BREAK = Whitelisted by callback - file is skipped and marked as clean
189
+CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected
190
+*/
191
+extern void cl_engine_set_clcb_pre_scan(struct cl_engine *engine, clcb_pre_scan callback, void *context);
192
+
193
+
194
+typedef cl_error_t (*clcb_post_scan)(int fd, int result, void *context);
195
+/* POST-SCAN
196
+Input:
197
+fd      = File descriptor which is was scanned
198
+result  = The scan result for the file
199
+context = Opaque application provided data
200
+
201
+Output:
202
+CL_CLEAN = Scan result is not overridden
203
+CL_BREAK = Whitelisted by callback - scan result is set to CL_CLEAN
204
+CL_VIRUS = Blacklisted by callback - scan result is set to CL_VIRUS
205
+*/
206
+extern void cl_engine_set_clcb_post_scan(struct cl_engine *engine, clcb_post_scan callback, void *context);
207
+
208
+
209
+typedef int (*clcb_sigload)(const char *type, const char *name, void *context);
210
+/* SIGNATURE LOAD
211
+Input:
212
+type = The signature type (e.g. "db", "ndb", "mdb", etc.)
213
+name = The virus name
214
+context = Opaque application provided data
215
+
216
+Output:
217
+0     = Load the current signature
218
+Non 0 = Skip the current signature
219
+*/
220
+extern void cl_engine_set_clcb_sigload(struct cl_engine *engine, clcb_sigload callback, void *context);
221
+
222
+
177 223
 struct cl_stat {
178 224
     char *dir;
179 225
     struct stat *stattab;
... ...
@@ -11,6 +11,9 @@ CLAMAV_PUBLIC {
11 11
     cl_engine_get_num;
12 12
     cl_engine_set_str;
13 13
     cl_engine_get_str;
14
+    cl_engine_set_clcb_pre_scan;
15
+    cl_engine_set_clcb_post_scan;
16
+    cl_engine_set_clcb_sigload;
14 17
     cl_engine_settings_copy;
15 18
     cl_engine_settings_apply;
16 19
     cl_engine_settings_free;
... ...
@@ -1008,3 +1008,18 @@ int cli_bitset_test(bitset_t *bs, unsigned long bit_offset)
1008 1008
 	}
1009 1009
 	return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset));
1010 1010
 }
1011
+
1012
+void cl_engine_set_clcb_pre_scan(struct cl_engine *engine, clcb_pre_scan callback, void *context) {
1013
+    engine->cb_pre_scan = callback;
1014
+    engine->cb_pre_scan_ctx = callback ? context : NULL;
1015
+}
1016
+
1017
+void cl_engine_set_clcb_post_scan(struct cl_engine *engine, clcb_post_scan callback, void *context) {
1018
+    engine->cb_post_scan = callback;
1019
+    engine->cb_post_scan_ctx = callback ? context : NULL;
1020
+}
1021
+
1022
+void cl_engine_set_clcb_sigload(struct cl_engine *engine, clcb_sigload callback, void *context) {
1023
+    engine->cb_sigload = callback;
1024
+    engine->cb_sigload_ctx = callback ? context : NULL;
1025
+}
... ...
@@ -247,6 +247,14 @@ struct cl_engine {
247 247
     /* Used for memory pools */
248 248
     mpool_t *mempool;
249 249
 
250
+    /* Callback(s) */
251
+    clcb_pre_scan cb_pre_scan;
252
+    void *cb_pre_scan_ctx;
253
+    clcb_post_scan cb_post_scan;
254
+    void *cb_post_scan_ctx;
255
+    clcb_sigload cb_sigload;
256
+    void *cb_sigload_ctx;
257
+
250 258
     /* Used for bytecode */
251 259
     struct cli_all_bc bcs;
252 260
     unsigned *hooks[_BC_LAST_HOOK - _BC_START_HOOKS];
... ...
@@ -549,6 +549,11 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
549 549
 	if(engine->ignored && cli_chkign(engine->ignored, start, buffer_cpy))
550 550
 	    continue;
551 551
 
552
+	if(engine->cb_sigload && engine->cb_sigload("db", start, engine->cb_sigload_ctx)) {
553
+	    cli_dbgmsg("cli_loaddb: skipping %s due to callback\n", start);
554
+	    continue;
555
+	}
556
+
552 557
 	if(*pt == '=') continue;
553 558
 
554 559
 	if((ret = cli_parse_add(root, start, pt, 0, 0, "*", 0, NULL, options))) {
... ...
@@ -623,6 +628,11 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
623 623
 	if(engine->ignored && cli_chkign(engine->ignored, tokens[0], buffer_cpy))
624 624
 	    continue;
625 625
 
626
+	if(engine->cb_sigload && engine->cb_sigload("idb", tokens[0], engine->cb_sigload_ctx)) {
627
+	    cli_dbgmsg("cli_loadidb: skipping %s due to callback\n", tokens[0]);
628
+	    continue;
629
+	}
630
+
626 631
 	hash = (uint8_t *)tokens[3];
627 632
 	if(cli_hexnibbles((char *)hash, 124)) {
628 633
 	    cli_errmsg("cli_loadidb: Malformed hash at line %u (bad chars)\n", line);
... ...
@@ -892,6 +902,11 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
892 892
 	if(engine->ignored && cli_chkign(engine->ignored, virname, buffer_cpy))
893 893
 	    continue;
894 894
 
895
+	if(engine->cb_sigload && engine->cb_sigload("ndb", virname, engine->cb_sigload_ctx)) {
896
+	    cli_dbgmsg("cli_loadndb: skipping %s due to callback\n", virname);
897
+	    continue;
898
+	}
899
+
895 900
 	if(tokens_count > 4) { /* min version */
896 901
 	    pt = tokens[4];
897 902
 
... ...
@@ -1195,6 +1210,11 @@ static int load_oneldb(char *buffer, int chkpua, int chkign, struct cl_engine *e
1195 1195
     if (chkign && cli_chkign(engine->ignored, virname, buffer_cpy))
1196 1196
 	return CL_SUCCESS;
1197 1197
 
1198
+    if(engine->cb_sigload && engine->cb_sigload("ldb", virname, engine->cb_sigload_ctx)) {
1199
+	cli_dbgmsg("cli_loadldb: skipping %s due to callback\n", virname);
1200
+	return CL_SUCCESS;
1201
+    }
1202
+
1198 1203
     subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, NULL, 1);
1199 1204
     if(subsigs == -1) {
1200 1205
 	return CL_EMALFDB;
... ...
@@ -1894,6 +1914,11 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1894 1894
 	if(engine->ignored && cli_chkign(engine->ignored, pt, buffer_cpy))
1895 1895
 	    continue;
1896 1896
 
1897
+	if(engine->cb_sigload && engine->cb_sigload("md5", pt, engine->cb_sigload_ctx)) {
1898
+	    cli_dbgmsg("cli_loadmd5: skipping %s due to callback\n", pt);
1899
+	    continue;
1900
+	}
1901
+
1897 1902
 	new = (struct cli_bm_patt *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt));
1898 1903
 	if(!new) {
1899 1904
 	    ret = CL_EMEM;
... ...
@@ -2045,6 +2070,13 @@ static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, i
2045 2045
 	    continue;
2046 2046
 	}
2047 2047
 
2048
+	if(engine->cb_sigload && engine->cb_sigload("md", new->virname, engine->cb_sigload_ctx)) {
2049
+	    cli_dbgmsg("cli_loadmd: skipping %s due to callback\n", new->virname);
2050
+	    mpool_free(engine->mempool, new->virname);
2051
+	    mpool_free(engine->mempool, new);
2052
+	    continue;
2053
+	}
2054
+
2048 2055
 	new->encrypted = strcmp(tokens[1], "*") ? atoi(tokens[1]) : 2;
2049 2056
 
2050 2057
 	if(strcmp(tokens[2], "*") && cli_regcomp(&new->name, tokens[2], REG_EXTENDED | REG_NOSUB)) {
... ...
@@ -2178,6 +2210,13 @@ static int cli_loadcdb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
2178 2178
 	    continue;
2179 2179
 	}
2180 2180
 
2181
+	if(engine->cb_sigload && engine->cb_sigload("cdb", new->virname, engine->cb_sigload_ctx)) {
2182
+	    cli_dbgmsg("cli_loadcdb: skipping %s due to callback\n", new->virname);
2183
+	    mpool_free(engine->mempool, new->virname);
2184
+	    mpool_free(engine->mempool, new);
2185
+	    continue;
2186
+	}
2187
+
2181 2188
 	if(!strcmp(tokens[1], "*")) {
2182 2189
 	    new->ctype = CL_TYPE_ANY;
2183 2190
 	} else if((new->ctype = cli_ftcode(tokens[1])) == CL_TYPE_ERROR) {
... ...
@@ -1894,9 +1894,25 @@ static void emax_reached(cli_ctx *ctx) {
1894 1894
 #define LINESTR(x) #x
1895 1895
 #define LINESTR2(x) LINESTR(x)
1896 1896
 #define __AT__  " at line "LINESTR2(__LINE__)
1897
-#define ret_from_magicscan(retcode) do {					\
1898
-    cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);	\
1899
-    return retcode;							\
1897
+#define ret_from_magicscan(retcode) do {							\
1898
+    cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);			\
1899
+    if(ctx->engine->cb_post_scan) {								\
1900
+	switch(ctx->engine->cb_post_scan(desc, retcode, ctx->engine->cb_post_scan_ctx)) {	\
1901
+	case CL_BREAK:										\
1902
+	    cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");			\
1903
+	    return CL_CLEAN;									\
1904
+	case CL_VIRUS:										\
1905
+	    cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");			\
1906
+	    if(ctx->virname)									\
1907
+		*ctx->virname = "Detected.By.Callback";						\
1908
+	    return CL_VIRUS;									\
1909
+	case CL_CLEAN:										\
1910
+	    break;										\
1911
+	default:										\
1912
+	    cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");	\
1913
+	}											\
1914
+    }												\
1915
+    return retcode;										\
1900 1916
     } while(0)
1901 1917
 
1902 1918
 int cli_magic_scandesc(int desc, cli_ctx *ctx)
... ...
@@ -1953,6 +1969,27 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1953 1953
 	ret_from_magicscan(CL_EMEM);
1954 1954
     }
1955 1955
 
1956
+    if(ctx->engine->cb_pre_scan) {
1957
+	switch(ctx->engine->cb_pre_scan(desc, ctx->engine->cb_pre_scan_ctx)) {
1958
+	case CL_BREAK:
1959
+	    cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");
1960
+	    funmap(*ctx->fmap);
1961
+	    ctx->fmap--;
1962
+	    ret_from_magicscan(CL_CLEAN);
1963
+	case CL_VIRUS:
1964
+	    cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");
1965
+	    if(ctx->virname)
1966
+		*ctx->virname = "Detected.By.Callback";
1967
+	    funmap(*ctx->fmap);
1968
+	    ctx->fmap--;
1969
+	    ret_from_magicscan(CL_VIRUS);
1970
+	case CL_CLEAN:
1971
+	    break;
1972
+	default:
1973
+	    cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");
1974
+	}
1975
+    }
1976
+
1956 1977
     if(cache_check(hash, ctx) == CL_CLEAN) {
1957 1978
 	funmap(*ctx->fmap);
1958 1979
 	ctx->fmap--;