Removing problematic call to convert file descriptors to filepaths.
Added filename and tempfile names to scandesc calls in clamd.
Added a general scan option to treat the scan engine as unprivileged,
meaning that the scan engine will not have read access to the file.
Added check to drop a temp file for RAR's where the we don't have
read access to the filepath provided (i.e. unprivileged is set, or
access() check fails).
... | ... |
@@ -391,7 +391,7 @@ int scanfd( |
391 | 391 |
context.filename = fdstr; |
392 | 392 |
context.virsize = 0; |
393 | 393 |
context.scandata = NULL; |
394 |
- ret = cl_scandesc_callback(fd, NULL, &virname, scanned, engine, options, &context); |
|
394 |
+ ret = cl_scandesc_callback(fd, conn->filename, &virname, scanned, engine, options, &context); |
|
395 | 395 |
thrmgr_setactivetask(NULL, NULL); |
396 | 396 |
|
397 | 397 |
if (thrmgr_group_need_terminate(conn->group)) { |
... | ... |
@@ -564,7 +564,7 @@ int scanstream( |
564 | 564 |
context.filename = peer_addr; |
565 | 565 |
context.virsize = 0; |
566 | 566 |
context.scandata = NULL; |
567 |
- ret = cl_scandesc_callback(tmpd, NULL, &virname, scanned, engine, options, &context); |
|
567 |
+ ret = cl_scandesc_callback(tmpd, tmpname, &virname, scanned, engine, options, &context); |
|
568 | 568 |
thrmgr_setactivetask(NULL, NULL); |
569 | 569 |
} else { |
570 | 570 |
ret = -1; |
... | ... |
@@ -160,10 +160,11 @@ struct cl_scan_options { |
160 | 160 |
}; |
161 | 161 |
|
162 | 162 |
/* general */ |
163 |
-#define CL_SCAN_GENERAL_ALLMATCHES 0x1 /* scan in all-match mode */ |
|
164 |
-#define CL_SCAN_GENERAL_COLLECT_METADATA 0x2 /* collect metadata (--gen-json) */ |
|
165 |
-#define CL_SCAN_GENERAL_HEURISTICS 0x4 /* option to enable heuristic alerts */ |
|
166 |
-#define CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE 0x8 /* allow heuristic match to take precedence. */ |
|
163 |
+#define CL_SCAN_GENERAL_ALLMATCHES 0x1 /* scan in all-match mode */ |
|
164 |
+#define CL_SCAN_GENERAL_COLLECT_METADATA 0x2 /* collect metadata (--gen-json) */ |
|
165 |
+#define CL_SCAN_GENERAL_HEURISTICS 0x4 /* option to enable heuristic alerts */ |
|
166 |
+#define CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE 0x8 /* allow heuristic match to take precedence. */ |
|
167 |
+#define CL_SCAN_GENERAL_UNPRIVILEGED 0x10 /* scanner will not have read access to files. */ |
|
167 | 168 |
|
168 | 169 |
/* parsing capabilities options */ |
169 | 170 |
#define CL_SCAN_PARSE_ARCHIVE 0x1 |
... | ... |
@@ -493,6 +493,7 @@ extern int have_rar; |
493 | 493 |
#define SCAN_COLLECT_METADATA (ctx->options->general & CL_SCAN_GENERAL_COLLECT_METADATA) |
494 | 494 |
#define SCAN_HEURISTICS (ctx->options->general & CL_SCAN_GENERAL_HEURISTICS) |
495 | 495 |
#define SCAN_HEURISTIC_PRECEDENCE (ctx->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE) |
496 |
+#define SCAN_UNPRIVILEGED (ctx->options->general & CL_SCAN_GENERAL_UNPRIVILEGED) |
|
496 | 497 |
|
497 | 498 |
#define SCAN_PARSE_ARCHIVE (ctx->options->parse & CL_SCAN_PARSE_ARCHIVE) |
498 | 499 |
#define SCAN_PARSE_ELF (ctx->options->parse & CL_SCAN_PARSE_ELF) |
... | ... |
@@ -276,6 +276,9 @@ static cl_error_t cli_scanrar(const char *filepath, int desc, cli_ctx *ctx) |
276 | 276 |
if (unrar_ret == UNRAR_EMEM) { |
277 | 277 |
status = CL_EMEM; |
278 | 278 |
goto done; |
279 |
+ } else if (unrar_ret == UNRAR_EOPEN) { |
|
280 |
+ status = CL_EOPEN; |
|
281 |
+ goto done; |
|
279 | 282 |
} else { |
280 | 283 |
status = CL_EFORMAT; |
281 | 284 |
goto done; |
... | ... |
@@ -2871,11 +2874,15 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_ |
2871 | 2871 |
cli_set_container(ctx, CL_TYPE_RAR, csize); |
2872 | 2872 |
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int)fpt->offset); |
2873 | 2873 |
|
2874 |
- if ((ctx->sub_filepath == NULL) || (fpt->offset != 0)) { |
|
2874 |
+#ifdef _WIN32 |
|
2875 |
+ if ((fpt->offset != 0) || (SCAN_UNPRIVILEGED) || (NULL == ctx->sub_filepath) || (0 != _access_s(ctx->sub_filepath, R_OK))) { |
|
2876 |
+#else |
|
2877 |
+ if ((fpt->offset != 0) || (SCAN_UNPRIVILEGED) || (NULL == ctx->sub_filepath) || (0 != access(ctx->sub_filepath, R_OK))) { |
|
2878 |
+#endif |
|
2875 | 2879 |
/* |
2876 |
- * If map is not file-backed, or offset is not at the start of the file... |
|
2877 |
- * ...have to dump to file for scanrar. |
|
2878 |
- */ |
|
2880 |
+ * If map is not file-backed, or offset is not at the start of the file... |
|
2881 |
+ * ...have to dump to file for scanrar. |
|
2882 |
+ */ |
|
2879 | 2883 |
nret = fmap_dump_to_file(map, ctx->sub_filepath, ctx->engine->tmpdir, &tmpname, &tmpfd, fpt->offset, fpt->offset + csize); |
2880 | 2884 |
if (nret != CL_SUCCESS) { |
2881 | 2885 |
cli_dbgmsg("cli_scanraw: failed to generate temporary file.\n"); |
... | ... |
@@ -2894,6 +2901,25 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_ |
2894 | 2894 |
/* scan file */ |
2895 | 2895 |
nret = cli_scanrar(filepath, fd, ctx); |
2896 | 2896 |
|
2897 |
+ if ((NULL == tmpname) && (CL_EOPEN == nret)) { |
|
2898 |
+ /* |
|
2899 |
+ * Failed to open the file using the original filename. |
|
2900 |
+ * Try writing the file descriptor to a temp file and try again. |
|
2901 |
+ */ |
|
2902 |
+ nret = fmap_dump_to_file(map, ctx->sub_filepath, ctx->engine->tmpdir, &tmpname, &tmpfd, fpt->offset, fpt->offset + csize); |
|
2903 |
+ if (nret != CL_SUCCESS) { |
|
2904 |
+ cli_dbgmsg("cli_scanraw: failed to generate temporary file.\n"); |
|
2905 |
+ ret = nret; |
|
2906 |
+ break_loop = 1; |
|
2907 |
+ break; |
|
2908 |
+ } |
|
2909 |
+ filepath = tmpname; |
|
2910 |
+ fd = tmpfd; |
|
2911 |
+ |
|
2912 |
+ /* try to scan again */ |
|
2913 |
+ nret = cli_scanrar(filepath, fd, ctx); |
|
2914 |
+ } |
|
2915 |
+ |
|
2897 | 2916 |
if (tmpfd != -1) { |
2898 | 2917 |
/* If dumped tempfile, need to cleanup */ |
2899 | 2918 |
close(tmpfd); |
... | ... |
@@ -3521,7 +3547,11 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3521 | 3521 |
char *tmpname = NULL; |
3522 | 3522 |
int tmpfd = -1; |
3523 | 3523 |
|
3524 |
- if (ctx->sub_filepath == NULL) { |
|
3524 |
+#ifdef _WIN32 |
|
3525 |
+ if ((SCAN_UNPRIVILEGED) || (NULL == ctx->sub_filepath) || (0 != _access_s(ctx->sub_filepath, R_OK))) { |
|
3526 |
+#else |
|
3527 |
+ if ((SCAN_UNPRIVILEGED) || (NULL == ctx->sub_filepath) || (0 != access(ctx->sub_filepath, R_OK))) { |
|
3528 |
+#endif |
|
3525 | 3529 |
/* If map is not file-backed have to dump to file for scanrar. */ |
3526 | 3530 |
ret = fmap_dump_to_file(*ctx->fmap, ctx->sub_filepath, ctx->engine->tmpdir, &tmpname, &tmpfd, 0, SIZE_MAX); |
3527 | 3531 |
if (ret != CL_SUCCESS) { |
... | ... |
@@ -3539,6 +3569,23 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3539 | 3539 |
/* scan file */ |
3540 | 3540 |
ret = cli_scanrar(filepath, fd, ctx); |
3541 | 3541 |
|
3542 |
+ if ((NULL == tmpname) && (CL_EOPEN == ret)) { |
|
3543 |
+ /* |
|
3544 |
+ * Failed to open the file using the original filename. |
|
3545 |
+ * Try writing the file descriptor to a temp file and try again. |
|
3546 |
+ */ |
|
3547 |
+ ret = fmap_dump_to_file(*ctx->fmap, ctx->sub_filepath, ctx->engine->tmpdir, &tmpname, &tmpfd, 0, SIZE_MAX); |
|
3548 |
+ if (ret != CL_SUCCESS) { |
|
3549 |
+ cli_dbgmsg("cli_scanraw: failed to generate temporary file.\n"); |
|
3550 |
+ break; |
|
3551 |
+ } |
|
3552 |
+ filepath = tmpname; |
|
3553 |
+ fd = tmpfd; |
|
3554 |
+ |
|
3555 |
+ /* try to scan again */ |
|
3556 |
+ ret = cli_scanrar(filepath, fd, ctx); |
|
3557 |
+ } |
|
3558 |
+ |
|
3542 | 3559 |
if (tmpfd != -1) { |
3543 | 3560 |
/* If dumped tempfile, need to cleanup */ |
3544 | 3561 |
close(tmpfd); |
... | ... |
@@ -4265,17 +4312,7 @@ static cl_error_t scan_common(int desc, cl_fmap_t *map, const char *filepath, co |
4265 | 4265 |
} |
4266 | 4266 |
} |
4267 | 4267 |
|
4268 |
- /* Best effort to determine the filename if not provided. |
|
4269 |
- * May still be NULL if filename could not be determined. */ |
|
4270 |
- if (filepath == NULL) { |
|
4271 |
- char *fpath = NULL; |
|
4272 |
- |
|
4273 |
- if (desc >= 0) { |
|
4274 |
- (void)cli_get_filepath_from_filedesc(desc, &fpath); |
|
4275 |
- } |
|
4276 |
- |
|
4277 |
- ctx.target_filepath = fpath; |
|
4278 |
- } else { |
|
4268 |
+ if (filepath != NULL) { |
|
4279 | 4269 |
ctx.target_filepath = strdup(filepath); |
4280 | 4270 |
} |
4281 | 4271 |
|