Browse code

fix minor leaks and improve --md5

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

Tomasz Kojm authored on 2004/08/31 20:44:51
Showing 8 changed files
... ...
@@ -1,3 +1,10 @@
1
+Tue Aug 31 00:09:42 CEST 2004 (tk)
2
+----------------------------------
3
+  * sigtool: --md5 now can generate MD5 sigs from file list (requested by
4
+	     Christoph Cordes)
5
+  * Fix minor file descriptor leaks (reported by Christophe GRENIER
6
+    <grenier*cgsecurity.org>)
7
+
1 8
 Tue Aug 31 10:46:48 CEST 2004 (acab)
2 9
 ------------------------------------
3 10
   * libclamav/petite.c: Fixed inflooping (thx Christoph)
... ...
@@ -14,7 +21,7 @@ Mon Aug 30 14:00:43 CEST 2004 (tk)
14 14
 Mon Aug 30 12:36:49 BST 2004 (njh)
15 15
 ----------------------------------
16 16
   * libclamav/blob.c:	Fix compilation errors on AIX and OSF reported by
17
-				Fajar A. Nugraha <fajar@telkom.co.id>
17
+				Fajar A. Nugraha <fajar*telkom.co.id>
18 18
 
19 19
 Sat Aug 28 20:25:44 CEST 2004 (tk)
20 20
 ----------------------------------
... ...
@@ -165,7 +172,7 @@ Sat Aug 21 12:59:43 BST 2004 (njh)
165 165
 ----------------------------------
166 166
   * libclamav:	Changed the handling of miltipart messages, that is scanning
167 167
 			emails with attachments. Reports on impact on memory
168
-			usage and speed welcome to clamav-devel@lists.sf.net.
168
+			usage and speed welcome to clamav-devel*lists.sf.net.
169 169
 
170 170
 Fri Aug 20 21:05:04 CEST 2004 (tk)
171 171
 ----------------------------------
... ...
@@ -1,5 +1,5 @@
1 1
 .\" Manual page created by Tomasz Kojm, 20020629
2
-.TH "sigtool" "1" "August 18, 2004" "Tomasz Kojm" "Clam AntiVirus"
2
+.TH "sigtool" "1" "August 31, 2004" "Tomasz Kojm" "Clam AntiVirus"
3 3
 .SH "NAME"
4 4
 .LP 
5 5
 sigtool \- signature and database management tool
... ...
@@ -29,8 +29,8 @@ Write all messages to standard output (stdout), instead of standard error output
29 29
 \fB\-\-hex\-dump\fR
30 30
 Read data from stdin and write hex string to stdout.
31 31
 .TP 
32
-\fB\-\-md5\fR
33
-Generate MD5 checksum from stdin.
32
+\fB\-\-md5 [FILES]\fR
33
+Generate MD5 checksum from stdin or MD5 sigs for FILES.
34 34
 .TP 
35 35
 \fB\-i, \-\-info\fR
36 36
 Print a CVD information and verify MD5 and a digital signature.
... ...
@@ -564,11 +564,15 @@ int get_database(const char *dbfile, int socketfd, const char *file, const char
564 564
 
565 565
     if ((bread = recv(socketfd, buffer, FILEBUFF, 0)) == -1) {
566 566
       mprintf("@Error while reading database from %s\n", hostname);
567
+      close(fd);
568
+      unlink(file);
567 569
       return 52;
568 570
     }
569 571
 
570 572
     if ((strstr(buffer, "HTTP/1.1 404")) != NULL) { 
571 573
       mprintf("@%s not found on remote server\n", dbfile);
574
+      close(fd);
575
+      unlink(file);
572 576
       return 58;
573 577
     }
574 578
 
... ...
@@ -124,6 +124,7 @@ int cli_untgz(int fd, const char *destdir)
124 124
 		cli_errmsg("Invalid size in header.\n");
125 125
 		free(fullname);
126 126
 	        gzclose(infile);
127
+		fclose(outfile);
127 128
 		return -1;
128 129
 	    }
129 130
 
... ...
@@ -369,8 +370,12 @@ int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
369 369
 		return CL_ETMPFILE;
370 370
 	    }
371 371
 
372
-	    if(!(buffer = (char *) cli_malloc(FILEBUFF)))
372
+	    if(!(buffer = (char *) cli_malloc(FILEBUFF))) {
373
+		free(dir);
374
+		free(tmp);
375
+		fclose(tmpd);
373 376
 		return CL_EMEM;
377
+	    }
374 378
 
375 379
 	    while((bytes = fread(buffer, 1, FILEBUFF, fd)) > 0)
376 380
 		fwrite(buffer, 1, bytes, tmpd);
... ...
@@ -384,6 +389,7 @@ int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
384 384
 		cli_errmsg("cli_cvdload(): Can't unpack CVD file.\n");
385 385
 		cli_rmdirs(dir);
386 386
 		free(dir);
387
+		fclose(tmpd);
387 388
 		unlink(tmp);
388 389
 		free(tmp);
389 390
 		return CL_ECVDEXTR;
... ...
@@ -123,10 +123,8 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
123 123
 	};
124 124
 
125 125
 
126
-    if((fs = fopen(cfgfile, "r")) == NULL) {
126
+    if((fs = fopen(cfgfile, "r")) == NULL)
127 127
 	return NULL;
128
-    }
129
-
130 128
 
131 129
     while(fgets(buff, LINE_LENGTH, fs)) {
132 130
 
... ...
@@ -138,6 +136,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
138 138
 	if(!strncmp("Example", buff, 7)) {
139 139
 	    if(messages)
140 140
 		fprintf(stderr, "ERROR: Please edit the example config file %s.\n", cfgfile);
141
+	    fclose(fs);
141 142
 	    return NULL;
142 143
 	}
143 144
 
... ...
@@ -155,6 +154,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
155 155
 				if(!arg) {
156 156
 				    if(messages)
157 157
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string as argument.\n", line, name);
158
+				    fclose(fs);
158 159
 				    return NULL;
159 160
 				}
160 161
 				copt = regcfg(copt, name, arg, 0);
... ...
@@ -163,6 +163,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
163 163
 				if(!arg) {
164 164
 				    if(messages)
165 165
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string as argument.\n", line, name);
166
+				    fclose(fs);
166 167
 				    return NULL;
167 168
 				}
168 169
 				/* FIXME: this one is an ugly hack of the above case */
... ...
@@ -175,6 +176,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
175 175
 				if(!arg || !isnumb(arg)) {
176 176
 				    if(messages)
177 177
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical argument.\n", line, name);
178
+				    fclose(fs);
178 179
 				    return NULL;
179 180
 				}
180 181
 				copt = regcfg(copt, name, NULL, atoi(arg));
... ...
@@ -184,6 +186,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
184 184
 				if(!arg) {
185 185
 				    if(messages)
186 186
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires argument.\n", line, name);
187
+				    fclose(fs);
187 188
 				    return NULL;
188 189
 				}
189 190
 				ctype = tolower(arg[strlen(arg) - 1]);
... ...
@@ -193,6 +196,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
193 193
 				    if(!isnumb(cpy)) {
194 194
 					if(messages)
195 195
 					    fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical (raw/K/M) argument.\n", line, name);
196
+					fclose(fs);
196 197
 					return NULL;
197 198
 				    }
198 199
 				    if(ctype == 'm')
... ...
@@ -204,6 +208,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
204 204
 				    if(!isnumb(arg)) {
205 205
 					if(messages)
206 206
 					    fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical (raw/K/M) argument.\n", line, name);
207
+					fclose(fs);
207 208
 					return NULL;
208 209
 				    }
209 210
 				    calc = atoi(arg);
... ...
@@ -215,6 +220,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
215 215
 				if(arg) {
216 216
 				    if(messages)
217 217
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s doesn't support arguments (got '%s').\n", line, name, arg);
218
+				    fclose(fs);
218 219
 				    return NULL;
219 220
 				}
220 221
 				copt = regcfg(copt, name, NULL, 0);
... ...
@@ -237,6 +243,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
237 237
 	    if(!found) {
238 238
 		if(messages)
239 239
 		    fprintf(stderr, "ERROR: Parse error at line %d: Unknown option %s.\n", line, name);
240
+		fclose(fs);
240 241
 		return NULL;
241 242
 	    }
242 243
 	}
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2001-2003 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2001-2002 Tomasz Kojm <zolw@konarski.edu.pl>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -14,6 +14,7 @@
14 14
  *  You should have received a copy of the GNU General Public License
15 15
  *  along with this program; if not, write to the Free Software
16 16
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ *
17 18
  */
18 19
 
19 20
 #if HAVE_CONFIG_H
... ...
@@ -27,14 +28,9 @@
27 27
 #define _GNU_SOURCE
28 28
 #include "getopt.h"
29 29
 
30
-#if defined(C_LINUX) && defined(CL_DEBUG)
31
-#include <sys/resource.h>
32
-#endif
33
-
34 30
 #include "options.h"
35
-#include "others.h"
36
-#include "output.h"
37 31
 #include "memory.h"
32
+#include "output.h"
38 33
 
39 34
 void sigtool(struct optstruct *opt);
40 35
 
... ...
@@ -43,7 +39,7 @@ int main(int argc, char **argv)
43 43
 	int ret, opt_index, i, len;
44 44
 	struct optstruct *opt;
45 45
 
46
-	const char *getopt_parameters = "hvVc:s:f:b:i:u:l::";
46
+	const char *getopt_parameters = "hvVb:i:u:l::";
47 47
 
48 48
 	static struct option long_options[] = {
49 49
 	    {"help", 0, 0, 'h'},
... ...
@@ -64,18 +60,11 @@ int main(int argc, char **argv)
64 64
 	    {0, 0, 0, 0}
65 65
     	};
66 66
 
67
-#if defined(C_LINUX) && defined(CL_DEBUG)
68
-	/* njh@bandsman.co.uk: create a dump if needed */
69
-	struct rlimit rlim;
70
-
71
-    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
72
-    if(setrlimit(RLIMIT_CORE, &rlim) < 0)
73
-	perror("setrlimit");
74
-#endif
75 67
 
76
-    opt=(struct optstruct*)mcalloc(1, sizeof(struct optstruct));
68
+    opt=(struct optstruct*) mcalloc(1, sizeof(struct optstruct));
77 69
     opt->optlist = NULL;
78 70
 
71
+
79 72
     while(1) {
80 73
 
81 74
 	opt_index=0;
... ...
@@ -90,9 +79,13 @@ int main(int argc, char **argv)
90 90
 		break;
91 91
 
92 92
     	    default:
93
-		if(strchr(getopt_parameters, ret))
94
-		    register_char_option(opt, ret);
95
-		else {
93
+		if(strchr(getopt_parameters, ret)) {
94
+		    if(opt_index)
95
+			register_char_option(opt, ret, long_options[opt_index].name);
96
+		    else
97
+			register_char_option(opt, ret, NULL);
98
+
99
+		} else {
96 100
 		    mprintf("!Unknown option passed.\n");
97 101
 		    free_opt(opt);
98 102
 		    exit(40);
... ...
@@ -115,23 +108,22 @@ int main(int argc, char **argv)
115 115
         for(i=optind; i<argc; i++) {
116 116
 	    strncat(opt->filename, argv[i], strlen(argv[i]));
117 117
 	    if(i != argc-1)
118
-		strncat(opt->filename, " ", 1);
118
+		strncat(opt->filename, "\t", 1);
119 119
 	}
120 120
 
121
-    } else
122
-	/* FIXME !!! Without this, we have segfault */
123
-	opt->filename=(char*)mcalloc(1, sizeof(char));
124
-
121
+    }
125 122
 
126 123
     sigtool(opt);
124
+    free_opt(opt);
127 125
 
128
-    return(0);
126
+    return 0;
129 127
 }
130 128
 
131
-void register_char_option(struct optstruct *opt, char ch)
129
+void register_char_option(struct optstruct *opt, char ch, const char *longname)
132 130
 {
133 131
 	struct optnode *newnode;
134 132
 
133
+
135 134
     newnode = (struct optnode *) mmalloc(sizeof(struct optnode));
136 135
     newnode->optchar = ch;
137 136
     if(optarg != NULL) {
... ...
@@ -148,6 +140,7 @@ void register_long_option(struct optstruct *opt, const char *optname)
148 148
 {
149 149
 	struct optnode *newnode;
150 150
 
151
+
151 152
     newnode = (struct optnode *) mmalloc(sizeof(struct optnode));
152 153
     newnode->optchar = 0;
153 154
     if(optarg != NULL) {
... ...
@@ -231,10 +224,9 @@ void free_opt(struct optstruct *opt)
231 231
 {
232 232
 	struct optnode *handler, *prev;
233 233
 
234
-    if(!opt || !opt->optlist)
234
+    if(!opt)
235 235
 	return;
236 236
 
237
-    mprintf("*Freeing option list... ");
238 237
     handler = opt->optlist;
239 238
 
240 239
     while(handler != NULL) {
... ...
@@ -246,7 +238,7 @@ void free_opt(struct optstruct *opt)
246 246
 	free(prev);
247 247
     }
248 248
 
249
-    free(opt->filename);
249
+    if (opt->filename)
250
+    	free(opt->filename);
250 251
     free(opt);
251
-    mprintf("*done\n");
252 252
 }
... ...
@@ -33,14 +33,10 @@ struct optstruct {
33 33
 
34 34
 int optc(const struct optstruct *opt, char ch);
35 35
 int optl(const struct optstruct *opt, const char *optname);
36
-void register_char_option(struct optstruct *opt, char ch);
36
+void register_char_option(struct optstruct *opt, char ch, const char *longname);
37 37
 void register_long_option(struct optstruct *opt, const char *optname);
38 38
 char *getargc(const struct optstruct *opt, char ch);
39
-char *getfirstargc(const struct optstruct *opt, char ch, struct optnode **optnode);
40
-char *getnextargc(struct optnode **optnode, char ch);
41 39
 char *getargl(const struct optstruct *opt, const char *optname);
42
-char *getfirstargl(const struct optstruct *opt, const char *optname, struct optnode **optnode);
43
-char *getnextargl(struct optnode **optnode, const char *optname);
44 40
 void free_opt(struct optstruct *opt);
45 41
 
46 42
 #endif
... ...
@@ -21,7 +21,6 @@
21 21
 #include "clamav-config.h"
22 22
 #endif
23 23
 
24
-
25 24
 #include <stdio.h>
26 25
 #include <stdlib.h>
27 26
 #include <string.h>
... ...
@@ -52,10 +51,6 @@
52 52
 #include "../libclamav/others.h"
53 53
 #include "../libclamav/str.h"
54 54
 
55
-#define LINE 1024
56
-
57
-#define MIN_LENGTH 15
58
-#define MAX_LENGTH 200
59 55
 
60 56
 void help(void);
61 57
 char *getdsig(const char *host, const char *user, const char *data);
... ...
@@ -65,21 +60,16 @@ int unpack(struct optstruct *opt);
65 65
 int listdb(const char *filename);
66 66
 int listdir(const char *dirname);
67 67
 void listsigs(struct optstruct *opt);
68
-int cli_rmdirs(const char *dirname); /* libclamav's internal */
69 68
 
70 69
 
71 70
 void sigtool(struct optstruct *opt)
72 71
 {
73
-	    char buffer[FILEBUFF];
74
-	    int bytes;
75
-	    char *pt;
76
-
77 72
 
78
-    if(optl(opt, "quiet")) mprintf_quiet = 1;
79
-    else mprintf_quiet = 0;
73
+    if(optl(opt, "quiet"))
74
+	mprintf_quiet = 1;
80 75
 
81
-    if(optl(opt, "stdout")) mprintf_stdout = 1;
82
-    else mprintf_stdout = 0;
76
+    if(optl(opt, "stdout"))
77
+	mprintf_stdout = 1;
83 78
 
84 79
     if(optl(opt, "debug"))
85 80
 	cl_debug();
... ...
@@ -95,6 +85,9 @@ void sigtool(struct optstruct *opt)
95 95
     }
96 96
 
97 97
     if(optl(opt, "hex-dump")) {
98
+	    char buffer[FILEBUFF];
99
+	    int bytes;
100
+	    char *pt;
98 101
 
99 102
 	while((bytes = read(0, buffer, FILEBUFF)) > 0) {
100 103
 	    pt = cli_str2hex(buffer, bytes);
... ...
@@ -103,10 +96,37 @@ void sigtool(struct optstruct *opt)
103 103
 	}
104 104
 
105 105
     } else if(optl(opt, "md5")) {
106
+	    char *md5, *filename;
107
+	    int i;
108
+	    struct stat sb;
106 109
 
107
-	char *md5 = cli_md5stream(stdin);
108
-	mprintf("%s\n", md5);
109
-	free(md5);
110
+	mprintf_stdout = 1;
111
+
112
+	if(opt->filename) {
113
+
114
+	    for(i = 0; (filename = cli_strtok(opt->filename, i, "\t")); i++) {
115
+		if(stat(filename, &sb) == -1) {
116
+		    mprintf("!Can't access file %s\n", filename);
117
+		    perror(filename);
118
+		} else {
119
+		    if((sb.st_mode & S_IFMT) == S_IFREG) {
120
+			if((md5 = cli_md5file(filename))) {
121
+			    mprintf("%s:%d:%s\n", md5, sb.st_size, filename);
122
+			    free(md5);
123
+			} else
124
+			    mprintf("!Can't generate MD5 checksum for %s\n", filename);
125
+		    }
126
+		}
127
+
128
+		free(filename);
129
+	    }
130
+
131
+	} else {
132
+
133
+	    md5 = cli_md5stream(stdin);
134
+	    mprintf("%s\n", md5);
135
+	    free(md5);
136
+	}
110 137
 
111 138
     } else if(optc(opt, 'b')) {
112 139
 	if(!optl(opt, "server")) {
... ...
@@ -137,7 +157,6 @@ void sigtool(struct optstruct *opt)
137 137
 	help();
138 138
     }
139 139
 
140
-    free_opt(opt);
141 140
 }
142 141
 
143 142
 int countlines(const char *filename)
... ...
@@ -539,6 +558,7 @@ int listdb(const char *filename)
539 539
 
540 540
     if(!(buffer = (char *) mmalloc(FILEBUFF))) {
541 541
 	mprintf("!listdb(): Can't allocate memory.\n");
542
+	fclose(fd);
542 543
 	return -1;
543 544
     }
544 545
 
... ...
@@ -596,6 +616,7 @@ int listdb(const char *filename)
596 596
 	    mprintf("!listdb(): Can't unpack CVD file.\n");
597 597
 	    cli_rmdirs(dir);
598 598
 	    free(dir);
599
+	    fclose(tmpd);
599 600
 	    unlink(tmp);
600 601
 	    free(tmp);
601 602
 	    free(buffer);
... ...
@@ -718,7 +739,8 @@ void help(void)
718 718
     mprintf("    --stdout                               write to stdout instead of stderr\n");
719 719
     mprintf("    --hex-dump                             convert data from stdin to a hex\n");
720 720
     mprintf("                                           string and print it on stdout\n");
721
-    mprintf("    --md5                                  generate MD5 checksum from stdin\n");
721
+    mprintf("    --md5 [FILES]                          generate MD5 checksum from stdin\n");
722
+    mprintf("                                           or MD5 sigs for FILES\n");
722 723
     mprintf("    --info=FILE            -i FILE         print database information\n");
723 724
     mprintf("    --build=NAME           -b NAME         build a CVD file\n");
724 725
     mprintf("    --server=ADDR                          ClamAV Signing Service address\n");