Browse code

BytecodeSecurity setting.

Török Edvin authored on 2010/01/22 21:36:56
Showing 13 changed files
... ...
@@ -192,7 +192,7 @@ int main(int argc, char *argv[])
192 192
     bcs.all_bcs = bc;
193 193
     bcs.count = 1;
194 194
 
195
-    rc = cli_bytecode_load(bc, f, NULL);
195
+    rc = cli_bytecode_load(bc, f, NULL, 0);
196 196
     if (rc != CL_SUCCESS) {
197 197
 	fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc));
198 198
 	optfree(opts);
... ...
@@ -410,6 +410,23 @@ int main(int argc, char **argv)
410 410
     if(optget(opts,"Bytecode")->enabled)
411 411
 	dboptions |= CL_DB_BYTECODE;
412 412
 
413
+    if((opt = optget(opts,"BytecodeSecurity"))->enabled) {
414
+	enum bytecode_security s;
415
+	if (!strcmp(opt->strarg, "TrustSigned"))
416
+	    s = CL_BYTECODE_TRUST_SIGNED;
417
+	else if (!strcmp(opt->strarg, "None"))
418
+	    s = CL_BYTECODE_TRUST_ALL;
419
+	else if (!strcmp(opt->strarg, "Paranoid"))
420
+	    s = CL_BYTECODE_TRUST_NOTHING;
421
+	else {
422
+	    logg("!Unable to parse bytecode security setting:%s\n",
423
+		 opt->strarg);
424
+	    ret = 1;
425
+	    break;
426
+	}
427
+	cl_engine_set_num(engine, CL_ENGINE_BYTECODE_SECURITY, s);
428
+    }
429
+
413 430
     if(optget(opts,"PhishingScanURLs")->enabled)
414 431
 	dboptions |= CL_DB_PHISHING_URLS;
415 432
     else
... ...
@@ -442,3 +442,14 @@ LocalSocket /tmp/clamd.socket
442 442
 # Set the exclude paths. All subdirectories are also excluded. (Dazuko only)
443 443
 # Default: disabled
444 444
 #ClamukoExcludePath /home/bofh
445
+
446
+# Set bytecode security level.
447
+# Possible values:
448
+#       None - no security at all, meant for debugging. DO NOT USE THIS ON PRODUCTION SYSTEMS
449
+#       TrustSigned - trust bytecode loaded from signed .c[lv]d files,
450
+#                insert runtime safety checks for bytecode loaded from other sources
451
+#       Paranoid - don't trust any bytecode, insert runtime checks for all
452
+# Recommended: TrustSigned, because bytecode in .cvd files already has these checks
453
+#
454
+# Default: TrustSigned
455
+#BytecodeSecurity TrustSigned
... ...
@@ -1222,7 +1222,7 @@ enum parse_state {
1222 1222
     PARSE_BB
1223 1223
 };
1224 1224
 
1225
-int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
1225
+int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int trust)
1226 1226
 {
1227 1227
     unsigned row = 0, current_func = 0, bb=0;
1228 1228
     char *buffer;
... ...
@@ -1232,6 +1232,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
1232 1232
     int rc;
1233 1233
 
1234 1234
     memset(bc, 0, sizeof(*bc));
1235
+    bc->trusted = trust;
1235 1236
     if (!f && !dbio) {
1236 1237
 	cli_errmsg("Unable to load bytecode (null file)\n");
1237 1238
 	return CL_ENULLARG;
... ...
@@ -67,6 +67,7 @@ struct cli_bc {
67 67
   struct cli_bc_dbgnode *dbgnodes;
68 68
   unsigned dbgnode_cnt;
69 69
   unsigned hook_lsig_id;
70
+  unsigned trusted;
70 71
 };
71 72
 
72 73
 struct cli_all_bc {
... ...
@@ -99,7 +100,7 @@ extern int have_clamjit;
99 99
 }
100 100
 #endif
101 101
 int cli_bytecode_init(struct cli_all_bc *allbc);
102
-int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio);
102
+int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int security);
103 103
 int cli_bytecode_prepare(struct cli_all_bc *allbc);
104 104
 int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx);
105 105
 void cli_bytecode_destroy(struct cli_bc *bc);
... ...
@@ -1204,6 +1204,9 @@ public:
1204 1204
 		}
1205 1205
 	  }
1206 1206
 	}
1207
+	if (!bc->trusted) {
1208
+	    //TODO: call verifier to insert runtime checks
1209
+	}
1207 1210
 	delete [] Functions;
1208 1211
 	return true;
1209 1212
     }
... ...
@@ -134,7 +134,14 @@ enum cl_engine_field {
134 134
     CL_ENGINE_AC_MINDEPTH,	    /* uint32_t */
135 135
     CL_ENGINE_AC_MAXDEPTH,	    /* uint32_t */
136 136
     CL_ENGINE_TMPDIR,		    /* (char *) */
137
-    CL_ENGINE_KEEPTMP		    /* uint32_t */
137
+    CL_ENGINE_KEEPTMP,		    /* uint32_t */
138
+    CL_ENGINE_BYTECODE_SECURITY     /* uint32_t */
139
+};
140
+
141
+enum bytecode_security {
142
+    CL_BYTECODE_TRUST_ALL=0, /* insecure, debug setting */
143
+    CL_BYTECODE_TRUST_SIGNED, /* default */
144
+    CL_BYTECODE_TRUST_NOTHING /* paranoid setting */
138 145
 };
139 146
 
140 147
 extern int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long long num);
... ...
@@ -300,6 +300,7 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
300 300
 	dbio->readpt = dbio->buf;
301 301
 	cli_md5_init(&dbio->md5ctx);
302 302
 	dbio->bread = 0;
303
+	dbio->secure = 0;
303 304
 
304 305
 	/* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */
305 306
 	if(compr)
... ...
@@ -33,6 +33,7 @@ struct cli_dbio {
33 33
     unsigned int size, bread;
34 34
     char *buf, *bufpt, *readpt;
35 35
     unsigned int usebuf, bufsize, readsize;
36
+    unsigned secure;
36 37
     cli_md5_ctx md5ctx; /* TODO: replace with sha256 */
37 38
 };
38 39
 
... ...
@@ -291,6 +291,7 @@ struct cl_engine *cl_engine_new(void)
291 291
     new->min_cc_count = CLI_DEFAULT_MIN_CC_COUNT;
292 292
     new->min_ssn_count = CLI_DEFAULT_MIN_SSN_COUNT;
293 293
 
294
+    new->bytecode_security = CL_BYTECODE_TRUST_SIGNED;
294 295
     new->refcount = 1;
295 296
     new->ac_only = 0;
296 297
     new->ac_mindepth = CLI_DEFAULT_AC_MINDEPTH;
... ...
@@ -373,6 +374,9 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long
373 373
 	case CL_ENGINE_KEEPTMP:
374 374
 	    engine->keeptmp = num;
375 375
 	    break;
376
+	case CL_ENGINE_BYTECODE_SECURITY:
377
+	    engine->bytecode_security = num;
378
+	    break;
376 379
 	default:
377 380
 	    cli_errmsg("cl_engine_set_num: Incorrect field number\n");
378 381
 	    return CL_EARG;
... ...
@@ -246,6 +246,7 @@ struct cl_engine {
246 246
     unsigned *hooks[_BC_LAST_HOOK - _BC_START_HOOKS];
247 247
     unsigned hooks_cnt[_BC_LAST_HOOK - _BC_START_HOOKS];
248 248
     unsigned hook_lsig_ids;
249
+    enum bytecode_security bytecode_security;
249 250
 };
250 251
 
251 252
 struct cl_settings {
... ...
@@ -1316,6 +1316,8 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1316 1316
     struct cli_all_bc *bcs = &engine->bcs;
1317 1317
     struct cli_bc *bc;
1318 1318
     unsigned sigs = 0;
1319
+    unsigned security_trust = 0;
1320
+
1319 1321
 
1320 1322
     /* TODO: virusname have a common prefix, and whitelist by that */
1321 1323
     if((rc = cli_initroots(engine, options)))
... ...
@@ -1331,7 +1333,25 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1331 1331
     }
1332 1332
     bcs->count++;
1333 1333
     bc = &bcs->all_bcs[bcs->count-1];
1334
-    rc = cli_bytecode_load(bc, fs, dbio);
1334
+
1335
+    switch (engine->bytecode_security) {
1336
+	case CL_BYTECODE_TRUST_ALL:
1337
+	    security_trust = 1;
1338
+	    cli_dbgmsg("bytecode: trusting all bytecode!\n");
1339
+	    break;
1340
+	case CL_BYTECODE_TRUST_SIGNED:
1341
+	    if (dbio && (!engine->dbinfo || !engine->dbinfo->cvd
1342
+			 || !engine->dbinfo->cvd->dsig)) {
1343
+		cli_errmsg("CVD without signed .info?\n");
1344
+		return CL_EMALFDB;
1345
+	    }
1346
+	    security_trust = dbio ? 1 : 0;
1347
+	    break;
1348
+	default:
1349
+	    security_trust = 0;
1350
+    }
1351
+
1352
+    rc = cli_bytecode_load(bc, fs, dbio, security_trust);
1335 1353
     if (rc != CL_SUCCESS) {
1336 1354
 	cli_errmsg("Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
1337 1355
 	return rc;
... ...
@@ -240,6 +240,8 @@ const struct clam_option __clam_options[] = {
240 240
 
241 241
     /* Scan options */
242 242
     { "Bytecode", "bytecode", 0, TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled ClamAV will load bytecode from the database. It is highly recommended you keep this option on, otherwise you'll miss detections for many new viruses.", "yes" },
243
+    { "BytecodeSecurity", NULL, 0, TYPE_STRING, "^(None|TrustSigned|Paranoid)$", -1, "TrustSigned", 0, OPT_CLAMD, 
244
+	"Set bytecode security level.\nPossible values:\n\tNone - no security at all, meant for debugging. DO NOT USE THIS ON PRODUCTION SYSTEMS\n\tTrustSigned - trust bytecode loaded from signed .c[lv]d files,\n\t\t insert runtime safety checks for bytecode loaded from other sources\n\tParanoid - don't trust any bytecode, insert runtime checks for all\nRecommended: TrustSigned, because bytecode in .cvd files already has these checks\n","TrustSigned"},
243 245
     { "DetectPUA", "detect-pua", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" },
244 246
 
245 247
     { "ExcludePUA", "exclude-pua", 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_CLAMSCAN, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/support/pua for the complete list of PUA\ncategories.", "NetTool\nPWTool" },