Browse code

api drafted

git-svn-id: file:///var/lib/svn/clamav-devel/branches/newlimits@3552 77e5149b-7576-45b1-b177-96237e5ba77b

aCaB authored on 2008/01/28 10:46:00
Showing 4 changed files
... ...
@@ -161,15 +161,17 @@ void cab_free(struct cab_archive *cab)
161 161
 
162 162
 
163 163
     if(cab->state) {
164
-	switch(cab->state->cmethod & 0x000f) {
165
-	    case 0x0001:
166
-		mszip_free(cab->state->stream);
167
-		break;
168
-	    case 0x0002:
169
-		qtm_free(cab->state->stream);
170
-		break;
171
-	    case 0x0003:
172
-		lzx_free(cab->state->stream);
164
+	if(cab->state->stream) {
165
+	    switch(cab->state->cmethod & 0x000f) {
166
+		case 0x0001:
167
+		    mszip_free(cab->state->stream);
168
+		    break;
169
+		case 0x0002:
170
+		    qtm_free(cab->state->stream);
171
+		    break;
172
+		case 0x0003:
173
+		    lzx_free(cab->state->stream);
174
+	    }
173 175
 	}
174 176
 	free(cab->state);
175 177
     }
... ...
@@ -604,19 +606,21 @@ static int cab_unstore(struct cab_file *file, int bytes)
604 604
 #define CAB_CHGFOLDER							\
605 605
     if(!file->cab->actfol || (file->folder != file->cab->actfol)) {	\
606 606
 	if(file->cab->state) {						\
607
-	    switch(file->cab->state->cmethod & 0x000f) {		\
608
-		case 0x0001:						\
609
-		    mszip_free(file->cab->state->stream);		\
610
-		    break;						\
611
-		case 0x0002:						\
612
-		    qtm_free(file->cab->state->stream);			\
613
-		    break;						\
614
-		case 0x0003:						\
615
-		    lzx_free(file->cab->state->stream);			\
607
+	    if(file->cab->state->stream) {				\
608
+		switch(file->cab->state->cmethod & 0x000f) {		\
609
+		    case 0x0001:					\
610
+			mszip_free(file->cab->state->stream);		\
611
+			break;						\
612
+		    case 0x0002:					\
613
+			qtm_free(file->cab->state->stream);		\
614
+			break;						\
615
+		    case 0x0003:					\
616
+			lzx_free(file->cab->state->stream);		\
617
+		}							\
616 618
 	    }								\
617 619
 	    free(file->cab->state);					\
620
+	    file->cab->state = NULL;					\
618 621
 	}								\
619
-	file->cab->actfol = file->folder;				\
620 622
 	if(lseek(file->fd, file->folder->offset, SEEK_SET) == -1) {	\
621 623
 	    cli_dbgmsg("cab_extract: Can't lseek to %u\n", (unsigned int) file->folder->offset);							\
622 624
 	    return CL_EFORMAT; /* truncated file? */			\
... ...
@@ -638,10 +642,10 @@ static int cab_unstore(struct cab_file *file, int bytes)
638 638
 		file->cab->state->stream = (struct lzx_stream *) lzx_init(file->fd, file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 0, 4096, 0, file, &cab_read);									\
639 639
 	}								\
640 640
 	if((file->folder->cmethod & 0x000f) && !file->cab->state->stream) { \
641
-	    free(file->cab->state);					\
642 641
 	    close(file->ofd);						\
643 642
 	    return CL_EMSCAB;						\
644 643
 	}								\
644
+	file->cab->actfol = file->folder;				\
645 645
     }
646 646
 
647 647
 
... ...
@@ -663,7 +667,6 @@ int cab_extract(struct cab_file *file, const char *name)
663 663
     file->ofd = open(name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
664 664
     if(file->ofd == -1) {
665 665
 	cli_errmsg("cab_extract: Can't open file %s in write mode\n", name);
666
-	free(file->cab->state);
667 666
 	return CL_EIO;
668 667
     }
669 668
 
... ...
@@ -196,6 +196,49 @@ const char *cl_strerror(int clerror)
196 196
     }
197 197
 }
198 198
 
199
+int cli_sizelimits(cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) {
200
+  int ret = CL_SUCCESS;
201
+  unsigned long needed;
202
+
203
+  /* if called without limits, go on, unpack */
204
+  if(!ctx || !ctx->limits) return CL_SUCCESS;
205
+
206
+  needed = (need1>need2)?need1:need2;
207
+  needed = (needed>need3)?needed:need3;
208
+
209
+  /* if we have global scan limits */
210
+  if(ctx->limits->maxscansize) {
211
+    /* if the remaining scansize is too small... */
212
+    if(ctx->limits->maxscansize-ctx->scansize<needed) {
213
+      cli_dbgmsg("cli_limits: scansize exceeded (initial: %u, remaining: %u, needed: %u)\n", ctx->limits->maxscansize, ctx->scansize, needed);
214
+      /* ... we return INFECTED only upon request */ 
215
+      if(BLOCKMAX) {
216
+	*ctx->virname = "Archive.ExceededScanSize";
217
+	return CL_VIRUS;
218
+      }
219
+      /* ... otherwise we tell the caller to skip this file */
220
+      ret = CL_BREAK;
221
+    } else {
222
+      /* if the remaining scanzise is big enough, we update it */
223
+      ctx->scansize+=needed;
224
+    }
225
+  }
226
+
227
+  /* if we have per-file size limits, and we are overlimit... */
228
+  if(ctx->limits->maxfilesize && ctx->limits->maxfilesize<needed) {
229
+    /* ... we return INFECTED only upon request */ 
230
+    if(BLOCKMAX) {
231
+      *ctx->virname = "Archive.ExceededFileSize";
232
+      return CL_VIRUS;
233
+    }
234
+    /* ... otherwise we tell the caller to skip this file */
235
+    ret = CL_BREAK;
236
+  }
237
+
238
+  return ret;
239
+  /* FIXME: set/check ctx->scanned in magic_scandesc */
240
+}
241
+
199 242
 unsigned char *cli_md5digest(int desc)
200 243
 {
201 244
 	unsigned char *digest;
... ...
@@ -628,11 +671,7 @@ int cli_rmdirs(const char *dirname)
628 628
 			    return -1;
629 629
 			}
630 630
 
631
-#ifdef	C_WINDOWS
632
-			sprintf(path, "%s\\%s", dirname, dent->d_name);
633
-#else
634 631
 			sprintf(path, "%s/%s", dirname, dent->d_name);
635
-#endif
636 632
 
637 633
 			/* stat the file */
638 634
 			if(lstat(path, &statbuf) != -1) {
... ...
@@ -82,7 +82,8 @@ typedef struct {
82 82
     const struct cl_limits *limits;
83 83
     unsigned long scansize;
84 84
     unsigned int options;
85
-    unsigned int arec;
85
+    unsigned int recursion;
86
+    unsigned int scanned;
86 87
     unsigned int found_possibly_unwanted;
87 88
     struct cli_dconf *dconf;
88 89
 } cli_ctx;
... ...
@@ -1969,16 +1969,18 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1969 1969
 int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
1970 1970
 {
1971 1971
     cli_ctx ctx;
1972
+    cl_limits l_limits;
1972 1973
     int rc;
1973 1974
 
1974 1975
     memset(&ctx, '\0', sizeof(cli_ctx));
1975 1976
     ctx.engine = engine;
1976 1977
     ctx.virname = virname;
1977
-    ctx.limits = limits;
1978
+    ctx.limits = &l_limits;
1978 1979
     ctx.scanned = scanned;
1979 1980
     ctx.options = options;
1980 1981
     ctx.found_possibly_unwanted = 0;
1981 1982
     ctx.dconf = (struct cli_dconf *) engine->dconf;
1983
+    memcpy(&l_limits, limits, sizeof(struct cl_limits));
1982 1984
 
1983 1985
     rc = cli_magic_scandesc(desc, &ctx);
1984 1986
     if(rc == CL_CLEAN && ctx.found_possibly_unwanted)