git-svn: trunk@2023
Tomasz Kojm authored on 2006/06/15 20:59:39... | ... |
@@ -40,363 +40,341 @@ |
40 | 40 |
#include <sys/wait.h> |
41 | 41 |
#include <dirent.h> |
42 | 42 |
|
43 |
-#include "options.h" |
|
44 |
-#include "others.h" |
|
45 |
-#include "strings.h" |
|
46 |
-#include "md5.h" |
|
47 |
-#include "cvd.h" |
|
48 |
-#include "str.h" |
|
49 |
-#include "memory.h" |
|
50 |
-#include "output.h" |
|
51 |
-#include "cfgparser.h" |
|
52 |
-#include "misc.h" |
|
53 | 43 |
#include "vba.h" |
54 |
-#include "../clamscan/others.h" |
|
55 |
-#include "../libclamav/others.h" |
|
56 |
-#include "../libclamav/str.h" |
|
57 |
-#include "../libclamav/ole2_extract.h" |
|
58 |
-#include "../libclamav/htmlnorm.h" |
|
59 |
- |
|
60 |
-#ifndef O_BINARY |
|
61 |
-#define O_BINARY 0 |
|
62 |
-#endif |
|
63 |
- |
|
64 |
-void help(void); |
|
65 |
-char *getdsig(const char *host, const char *user, const char *data); |
|
66 |
-void cvdinfo(struct optstruct *opt); |
|
67 |
-int build(struct optstruct *opt); |
|
68 |
-int unpack(struct optstruct *opt); |
|
69 |
-int listdb(const char *filename); |
|
70 |
-int listdir(const char *dirname); |
|
71 |
-void listsigs(struct optstruct *opt); |
|
72 | 44 |
|
45 |
+#include "shared/options.h" |
|
46 |
+#include "shared/memory.h" |
|
47 |
+#include "shared/output.h" |
|
48 |
+#include "shared/cfgparser.h" |
|
49 |
+#include "shared/misc.h" |
|
73 | 50 |
|
74 |
-int main(int argc, char **argv) |
|
75 |
-{ |
|
76 |
- struct optstruct *opt; |
|
77 |
- const char *short_options = "hvVb:i:u:l::"; |
|
78 |
- static struct option long_options[] = { |
|
79 |
- {"help", 0, 0, 'h'}, |
|
80 |
- {"quiet", 0, 0, 0}, |
|
81 |
- {"debug", 0, 0, 0}, |
|
82 |
- {"verbose", 0, 0, 'v'}, |
|
83 |
- {"stdout", 0, 0, 0}, |
|
84 |
- {"version", 0, 0, 'V'}, |
|
85 |
- {"tempdir", 1, 0, 0}, |
|
86 |
- {"hex-dump", 0, 0, 0}, |
|
87 |
- {"md5", 0, 0, 0}, |
|
88 |
- {"html-normalise", 1, 0, 0}, |
|
89 |
- {"build", 1, 0, 'b'}, |
|
90 |
- {"server", 1, 0, 0}, |
|
91 |
- {"unpack", 1, 0, 'u'}, |
|
92 |
- {"unpack-current", 1, 0, 0}, |
|
93 |
- {"info", 1, 0, 'i'}, |
|
94 |
- {"list-sigs", 2, 0, 'l'}, |
|
95 |
- {"vba", 1, 0 ,0}, |
|
96 |
- {"vba-hex", 1, 0, 0}, |
|
97 |
- {0, 0, 0, 0} |
|
98 |
- }; |
|
99 |
- |
|
100 |
- |
|
101 |
- opt = opt_parse(argc, argv, short_options, long_options, NULL); |
|
102 |
- if(!opt) { |
|
103 |
- mprintf("!Can't parse the command line\n"); |
|
104 |
- return 1; |
|
105 |
- } |
|
106 |
- |
|
107 |
- if(opt_check(opt, "quiet")) |
|
108 |
- mprintf_quiet = 1; |
|
51 |
+#include "libclamav/cvd.h" |
|
52 |
+#include "libclamav/others.h" |
|
53 |
+#include "libclamav/str.h" |
|
54 |
+#include "libclamav/ole2_extract.h" |
|
55 |
+#include "libclamav/htmlnorm.h" |
|
109 | 56 |
|
110 |
- if(opt_check(opt, "stdout")) |
|
111 |
- mprintf_stdout = 1; |
|
112 | 57 |
|
113 |
- if(opt_check(opt, "debug")) |
|
114 |
- cl_debug(); |
|
58 |
+static int hexdump(void) |
|
59 |
+{ |
|
60 |
+ char buffer[FILEBUFF], *pt; |
|
61 |
+ int bytes; |
|
115 | 62 |
|
116 |
- if(opt_check(opt, "version")) { |
|
117 |
- print_version(); |
|
118 |
- opt_free(opt); |
|
119 |
- exit(0); |
|
120 |
- } |
|
121 | 63 |
|
122 |
- if(opt_check(opt, "help")) { |
|
123 |
- opt_free(opt); |
|
124 |
- help(); |
|
64 |
+ while((bytes = read(0, buffer, FILEBUFF)) > 0) { |
|
65 |
+ pt = cli_str2hex(buffer, bytes); |
|
66 |
+ if(write(1, pt, 2 * bytes) == -1) { |
|
67 |
+ logg("!hexdump: Can't write to stdout\n"); |
|
68 |
+ free(pt); |
|
69 |
+ return -1; |
|
70 |
+ } |
|
71 |
+ free(pt); |
|
125 | 72 |
} |
126 | 73 |
|
127 |
- if(opt_check(opt, "hex-dump")) { |
|
128 |
- char buffer[FILEBUFF]; |
|
129 |
- int bytes; |
|
130 |
- char *pt; |
|
74 |
+ if(bytes == -1) |
|
75 |
+ return -1; |
|
131 | 76 |
|
132 |
- while((bytes = read(0, buffer, FILEBUFF)) > 0) { |
|
133 |
- pt = cli_str2hex(buffer, bytes); |
|
134 |
- write(1, pt, 2 * bytes); |
|
135 |
- free(pt); |
|
136 |
- } |
|
77 |
+ return 0; |
|
78 |
+} |
|
137 | 79 |
|
138 |
- } else if(opt_check(opt, "md5")) { |
|
139 |
- char *md5, *filename; |
|
140 |
- int i; |
|
141 |
- struct stat sb; |
|
80 |
+static int md5sig(struct optstruct *opt) |
|
81 |
+{ |
|
82 |
+ char *md5, *filename; |
|
83 |
+ int i; |
|
84 |
+ struct stat sb; |
|
142 | 85 |
|
143 |
- mprintf_stdout = 1; |
|
144 | 86 |
|
145 |
- if(opt->filename) { |
|
146 |
- |
|
147 |
- for(i = 0; (filename = cli_strtok(opt->filename, i, "\t")); i++) { |
|
148 |
- if(stat(filename, &sb) == -1) { |
|
149 |
- logg("!Can't access file %s\n", filename); |
|
150 |
- perror(filename); |
|
151 |
- } else { |
|
152 |
- if((sb.st_mode & S_IFMT) == S_IFREG) { |
|
153 |
- if((md5 = cli_md5file(filename))) { |
|
154 |
- logg("%s:%d:%s\n", md5, sb.st_size, filename); |
|
155 |
- free(md5); |
|
156 |
- } else |
|
157 |
- logg("!Can't generate MD5 checksum for %s\n", filename); |
|
87 |
+ if(opt->filename) { |
|
88 |
+ for(i = 0; (filename = cli_strtok(opt->filename, i, "\t")); i++) { |
|
89 |
+ if(stat(filename, &sb) == -1) { |
|
90 |
+ logg("!md5sig: Can't access file %s\n", filename); |
|
91 |
+ perror("md5sig"); |
|
92 |
+ free(filename); |
|
93 |
+ return -1; |
|
94 |
+ } else { |
|
95 |
+ if((sb.st_mode & S_IFMT) == S_IFREG) { |
|
96 |
+ if((md5 = cli_md5file(filename))) { |
|
97 |
+ logg("%s:%d:%s\n", md5, sb.st_size, filename); |
|
98 |
+ free(md5); |
|
99 |
+ } else { |
|
100 |
+ logg("!md5sig: Can't generate MD5 checksum for %s\n", filename); |
|
101 |
+ free(filename); |
|
102 |
+ return -1; |
|
158 | 103 |
} |
159 | 104 |
} |
160 |
- |
|
161 |
- free(filename); |
|
162 | 105 |
} |
163 | 106 |
|
164 |
- } else { |
|
165 |
- |
|
166 |
- md5 = cli_md5stream(stdin, NULL); |
|
167 |
- logg("%s\n", md5); |
|
168 |
- free(md5); |
|
169 |
- } |
|
170 |
- |
|
171 |
- } else if(opt_check(opt, "html-normalise")) { |
|
172 |
- int fd; |
|
173 |
- |
|
174 |
- if((fd = open(opt_arg(opt, "html-normalise"), O_RDONLY)) == -1) { |
|
175 |
- logg("Can't open file %s\n", opt_arg(opt, "html-normalise")); |
|
176 |
- opt_free(opt); |
|
177 |
- exit(1); |
|
107 |
+ free(filename); |
|
178 | 108 |
} |
179 | 109 |
|
180 |
- html_normalise_fd(fd, ".", NULL); |
|
181 |
- |
|
182 |
- close(fd); |
|
183 |
- |
|
184 |
- } else if(opt_check(opt, "build")) { |
|
185 |
- if(!opt_check(opt, "server")) { |
|
186 |
- logg("!--server is required in this mode\n"); |
|
187 |
- opt_free(opt); |
|
188 |
- exit(10); |
|
110 |
+ } else { /* stream */ |
|
111 |
+ md5 = cli_md5stream(stdin, NULL); |
|
112 |
+ if(!md5) { |
|
113 |
+ logg("!md5sig: Can't generate MD5 checksum for input stream\n"); |
|
114 |
+ return -1; |
|
189 | 115 |
} |
116 |
+ logg("%s\n", md5); |
|
117 |
+ free(md5); |
|
118 |
+ } |
|
190 | 119 |
|
191 |
- build(opt); |
|
120 |
+ return 0; |
|
121 |
+} |
|
192 | 122 |
|
193 |
- } else if(opt_check(opt, "unpack")) { |
|
123 |
+static int htmlnorm(struct optstruct *opt) |
|
124 |
+{ |
|
125 |
+ int fd; |
|
194 | 126 |
|
195 |
- unpack(opt); |
|
196 | 127 |
|
197 |
- } else if(opt_check(opt, "unpack-current")) { |
|
128 |
+ if((fd = open(opt_arg(opt, "html-normalise"), O_RDONLY)) == -1) { |
|
129 |
+ logg("!htmlnorm: Can't open file %s\n", opt_arg(opt, "html-normalise")); |
|
130 |
+ return -1; |
|
131 |
+ } |
|
198 | 132 |
|
199 |
- unpack(opt); |
|
133 |
+ html_normalise_fd(fd, ".", NULL); |
|
134 |
+ close(fd); |
|
200 | 135 |
|
201 |
- } else if(opt_check(opt, "info")) { |
|
136 |
+ return 0; |
|
137 |
+} |
|
202 | 138 |
|
203 |
- cvdinfo(opt); |
|
139 |
+static unsigned int countlines(const char *filename) |
|
140 |
+{ |
|
141 |
+ FILE *fd; |
|
142 |
+ char buff[1024]; |
|
143 |
+ unsigned int lines = 0; |
|
204 | 144 |
|
205 |
- } else if(opt_check(opt, "list-sigs")) { |
|
206 | 145 |
|
207 |
- listsigs(opt); |
|
146 |
+ if((fd = fopen(filename, "r")) == NULL) |
|
147 |
+ return 0; |
|
208 | 148 |
|
209 |
- } else if(opt_check(opt, "vba") || opt_check(opt, "vba-hex")) { |
|
210 |
- int fd, hex_output=0; |
|
211 |
- char *dir; |
|
149 |
+ while(fgets(buff, sizeof(buff), fd)) { |
|
150 |
+ if(buff[0] == '#') continue; |
|
151 |
+ lines++; |
|
152 |
+ } |
|
212 | 153 |
|
154 |
+ fclose(fd); |
|
155 |
+ return lines; |
|
156 |
+} |
|
213 | 157 |
|
214 |
- if (opt_check(opt, "vba-hex")) |
|
215 |
- hex_output = 1; |
|
216 |
- |
|
217 |
- /* generate the temporary directory */ |
|
218 |
- dir = cli_gentemp(NULL); |
|
219 |
- if(mkdir(dir, 0700)) { |
|
220 |
- logg("vba dump: Can't create temporary directory %s\n", dir); |
|
221 |
- free(dir); |
|
222 |
- opt_free(opt); |
|
223 |
- return 1; |
|
224 |
- } |
|
225 |
- |
|
226 |
- if((fd = open(opt_arg(opt, "vba"), O_RDONLY)) == -1) { |
|
227 |
- if((fd = open(opt_arg(opt, "vba-hex"), O_RDONLY)) == -1) { |
|
228 |
- logg("Can't open file %s\n", opt_arg(opt, "vba")); |
|
229 |
- opt_free(opt); |
|
230 |
- exit(1); |
|
231 |
- } |
|
232 |
- } |
|
158 |
+static char *getdsig(const char *host, const char *user, const char *data) |
|
159 |
+{ |
|
160 |
+ char buff[256], cmd[128], *pass, *pt; |
|
161 |
+ struct sockaddr_in server; |
|
162 |
+ int sockd, bread, len; |
|
233 | 163 |
|
234 |
- if(cli_ole2_extract(fd, dir, NULL)) { |
|
235 |
- cli_rmdirs(dir); |
|
236 |
- free(dir); |
|
237 |
- close(fd); |
|
238 |
- opt_free(opt); |
|
239 |
- return 1; |
|
240 |
- } |
|
241 | 164 |
|
242 |
- close(fd); |
|
243 |
- sigtool_vba_scandir(dir, hex_output); |
|
244 |
- cli_rmdirs(dir); |
|
245 |
- free(dir); |
|
165 |
+#ifdef PF_INET |
|
166 |
+ if((sockd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { |
|
167 |
+#else |
|
168 |
+ if((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
169 |
+#endif |
|
170 |
+ perror("socket()"); |
|
171 |
+ logg("!getdsig: Can't create socket\n"); |
|
172 |
+ return NULL; |
|
173 |
+ } |
|
246 | 174 |
|
247 |
- } else { |
|
175 |
+ server.sin_family = AF_INET; |
|
176 |
+ server.sin_addr.s_addr = inet_addr(host); |
|
177 |
+ server.sin_port = htons(33101); |
|
248 | 178 |
|
249 |
- help(); |
|
179 |
+ if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) { |
|
180 |
+ close(sockd); |
|
181 |
+ perror("connect()"); |
|
182 |
+ logg("!getdsig: Can't connect to ClamAV Signing Service at %s\n", host); |
|
183 |
+ return NULL; |
|
250 | 184 |
} |
251 | 185 |
|
252 |
-} |
|
253 |
- |
|
254 |
-static int countlines(const char *filename) |
|
255 |
-{ |
|
256 |
- FILE *fd; |
|
257 |
- char buff[65536]; |
|
258 |
- int lines = 0; |
|
186 |
+ memset(cmd, 0, sizeof(cmd)); |
|
187 |
+ pass = getpass("Password:"); |
|
188 |
+ snprintf(cmd, sizeof(cmd) - 16, "ClamSign:%s:%s:", user, pass); |
|
189 |
+ len = strlen(cmd); |
|
190 |
+ pt = cmd + len; |
|
191 |
+ memcpy(pt, data, 16); |
|
192 |
+ len += 16; |
|
259 | 193 |
|
194 |
+ if(write(sockd, cmd, len) < 0) { |
|
195 |
+ logg("!getdsig: Can't write to socket\n"); |
|
196 |
+ close(sockd); |
|
197 |
+ memset(cmd, 0, len); |
|
198 |
+ memset(pass, 0, strlen(pass)); |
|
199 |
+ return NULL; |
|
200 |
+ } |
|
260 | 201 |
|
261 |
- if((fd = fopen(filename, "r")) == NULL) |
|
262 |
- return 0; |
|
202 |
+ memset(cmd, 0, len); |
|
203 |
+ memset(pass, 0, strlen(pass)); |
|
204 |
+ memset(buff, 0, sizeof(buff)); |
|
263 | 205 |
|
264 |
- while(fgets(buff, sizeof(buff), fd)) { |
|
265 |
- if(buff[0] == '#') continue; |
|
266 |
- lines++; |
|
206 |
+ if((bread = read(sockd, buff, sizeof(buff))) > 0) { |
|
207 |
+ if(!strstr(buff, "Signature:")) { |
|
208 |
+ logg("!getdsig: Error generating digital signature\n"); |
|
209 |
+ logg("!getdsig: Answer from remote server: %s\n", buff); |
|
210 |
+ close(sockd); |
|
211 |
+ return NULL; |
|
212 |
+ } else { |
|
213 |
+ logg("Signature received (length = %d)\n", strlen(buff) - 10); |
|
214 |
+ } |
|
267 | 215 |
} |
268 | 216 |
|
269 |
- fclose(fd); |
|
270 |
- return lines; |
|
217 |
+ close(sockd); |
|
218 |
+ pt = buff; |
|
219 |
+ pt += 10; |
|
220 |
+ return strdup(pt); |
|
271 | 221 |
} |
272 | 222 |
|
273 |
-int build(struct optstruct *opt) |
|
223 |
+static int build(struct optstruct *opt) |
|
274 | 224 |
{ |
275 |
- int ret, no = 0, realno = 0, bytes, itmp; |
|
225 |
+ int ret, itmp; |
|
226 |
+ size_t bytes; |
|
227 |
+ unsigned int sigs = 0, lines = 0; |
|
276 | 228 |
struct stat foo; |
277 |
- char buffer[FILEBUFF], *tarfile = NULL, *gzfile = NULL, header[513], |
|
229 |
+ char buffer[FILEBUFF], *tarfile, *gzfile, header[513], |
|
278 | 230 |
smbuff[30], *pt, *dbdir; |
279 | 231 |
struct cl_node *root = NULL; |
280 |
- FILE *tar, *cvd, *fd; |
|
232 |
+ FILE *tar, *cvd; |
|
281 | 233 |
gzFile *gz; |
282 | 234 |
time_t timet; |
283 | 235 |
struct tm *brokent; |
284 | 236 |
struct cl_cvd *oldcvd = NULL; |
285 | 237 |
|
286 | 238 |
|
287 |
- if(stat("COPYING", &foo) == -1) { |
|
288 |
- logg("COPYING file not found in current working directory.\n"); |
|
289 |
- opt_free(opt); |
|
290 |
- exit(1); |
|
239 |
+ if(!opt_check(opt, "server")) { |
|
240 |
+ logg("!build: --server is required for --build\n"); |
|
241 |
+ return -1; |
|
291 | 242 |
} |
292 | 243 |
|
293 |
- if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 && stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 && stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 && stat("main.zmd", &foo) == -1 && stat("main.rmd", &foo) == -1 && stat("daily.zmd", &foo) == -1 && stat("daily.rmd", &foo) == -1) { |
|
294 |
- logg("Virus database not found in current working directory.\n"); |
|
295 |
- opt_free(opt); |
|
296 |
- exit(1); |
|
244 |
+ if(stat("COPYING", &foo) == -1) { |
|
245 |
+ logg("!build: COPYING file not found in current working directory.\n"); |
|
246 |
+ return -1; |
|
297 | 247 |
} |
298 | 248 |
|
299 |
- cl_debug(); /* enable debug messages */ |
|
300 |
- |
|
301 |
- if((ret = cl_loaddbdir(".", &root, &no))) { |
|
302 |
- logg("!Can't load database: %s\n", cl_strerror(ret)); |
|
303 |
- opt_free(opt); |
|
304 |
- exit(1); |
|
249 |
+ if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 && |
|
250 |
+ stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 && |
|
251 |
+ stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 && |
|
252 |
+ stat("main.zmd", &foo) == -1 && stat("daily.zmd", &foo) == -1 && |
|
253 |
+ stat("main.rmd", &foo) == -1 && stat("daily.rmd", &foo) == -1) |
|
254 |
+ { |
|
255 |
+ logg("!build: No virus database file found in current directory\n"); |
|
256 |
+ return -1; |
|
305 | 257 |
} |
306 | 258 |
|
307 |
- cl_free(root); |
|
259 |
+ cl_debug(); /* enable debug messages in libclamav */ |
|
308 | 260 |
|
309 |
- logg("Database properly parsed.\n"); |
|
261 |
+ if((ret = cl_loaddbdir(".", &root, &sigs))) { |
|
262 |
+ logg("!build: Can't load database: %s\n", cl_strerror(ret)); |
|
263 |
+ return -1; |
|
264 |
+ } else { |
|
265 |
+ cl_free(root); |
|
266 |
+ } |
|
310 | 267 |
|
311 |
- if(!no) { |
|
312 |
- logg("^There are no signatures in the database(s).\n"); |
|
268 |
+ if(!sigs) { |
|
269 |
+ logg("!build: There are no signatures in database files\n"); |
|
313 | 270 |
} else { |
314 |
- logg("Signatures: %d\n", no); |
|
315 |
- realno = countlines("main.db") + countlines("daily.db") + countlines("main.hdb") + countlines("daily.hdb") + countlines("main.ndb") + countlines("daily.ndb") + countlines("main.zmd") + countlines("daily.zmd") + countlines("main.rmd") + countlines("daily.rmd") + countlines("main.fp") + countlines("daily.fp"); |
|
316 |
- if(realno != no) { |
|
317 |
- logg("!Signatures in database: %d. Loaded: %d.\n", realno, no); |
|
318 |
- logg("Please check the current directory and remove unnecessary databases\n"); |
|
319 |
- logg("or install the latest ClamAV version.\n"); |
|
320 |
- opt_free(opt); |
|
321 |
- exit(1); |
|
271 |
+ logg("Signatures: %d\n", sigs); |
|
272 |
+ lines = countlines("main.db") + countlines("daily.db") + |
|
273 |
+ countlines("main.hdb") + countlines("daily.hdb") + |
|
274 |
+ countlines("main.ndb") + countlines("daily.ndb") + |
|
275 |
+ countlines("main.zmd") + countlines("daily.zmd") + |
|
276 |
+ countlines("main.rmd") + countlines("daily.rmd") + |
|
277 |
+ countlines("main.fp") + countlines("daily.fp"); |
|
278 |
+ |
|
279 |
+ if(lines != sigs) { |
|
280 |
+ logg("!build: Signatures in database: %d, loaded by libclamav: %d\n", lines, sigs); |
|
281 |
+ logg("!build: Please check the current directory and remove unnecessary databases\n"); |
|
282 |
+ logg("!build: or install the latest ClamAV version.\n"); |
|
283 |
+ return -1; |
|
322 | 284 |
} |
323 | 285 |
} |
324 | 286 |
|
325 |
- tarfile = cli_gentemp("."); |
|
287 |
+ if(!(tarfile = cli_gentemp("."))) { |
|
288 |
+ logg("!build: Can't generate temporary name for tarfile\n"); |
|
289 |
+ return -1; |
|
290 |
+ } |
|
326 | 291 |
|
327 | 292 |
switch(fork()) { |
328 | 293 |
case -1: |
329 |
- logg("!Can't fork.\n"); |
|
330 |
- opt_free(opt); |
|
331 |
- exit(1); |
|
294 |
+ logg("!build: Can't fork.\n"); |
|
295 |
+ free(tarfile); |
|
296 |
+ return -1; |
|
332 | 297 |
case 0: |
333 | 298 |
{ |
334 |
- char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db", "daily.db", "Notes", "viruses.db3", "main.hdb", "daily.hdb", "main.ndb", "daily.ndb", "main.zmd", "daily.zmd", "main.rmd", "daily.rmd", "main.fp", "daily.fp", NULL }; |
|
299 |
+ char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db", |
|
300 |
+ "daily.db", "main.hdb", "daily.hdb", |
|
301 |
+ "main.ndb", "daily.ndb", "main.zmd", |
|
302 |
+ "daily.zmd", "main.rmd", "daily.rmd", |
|
303 |
+ "main.fp", "daily.fp", NULL }; |
|
335 | 304 |
args[2] = tarfile; |
336 | 305 |
execv("/bin/tar", args); |
337 |
- logg("!Can't execute tar\n"); |
|
306 |
+ logg("!build: Can't execute tar\n"); |
|
338 | 307 |
perror("tar"); |
339 |
- opt_free(opt); |
|
340 |
- exit(1); |
|
308 |
+ free(tarfile); |
|
309 |
+ return -1; |
|
341 | 310 |
} |
342 | 311 |
default: |
343 | 312 |
wait(NULL); |
344 | 313 |
} |
345 | 314 |
|
346 | 315 |
if(stat(tarfile, &foo) == -1) { |
347 |
- logg("!Can't generate tar file.\n"); |
|
348 |
- opt_free(opt); |
|
349 |
- exit(1); |
|
316 |
+ logg("!build: Tar archive was not created\n"); |
|
317 |
+ free(tarfile); |
|
318 |
+ return -1; |
|
350 | 319 |
} |
351 | 320 |
|
352 | 321 |
if((tar = fopen(tarfile, "rb")) == NULL) { |
353 |
- logg("!Can't open file %s\n", tarfile); |
|
354 |
- opt_free(opt); |
|
355 |
- exit(1); |
|
322 |
+ logg("!build: Can't open file %s\n", tarfile); |
|
323 |
+ free(tarfile); |
|
324 |
+ return -1; |
|
325 |
+ } |
|
326 |
+ |
|
327 |
+ if(!(gzfile = cli_gentemp("."))) { |
|
328 |
+ logg("!build: Can't generate temporary name for gzfile\n"); |
|
329 |
+ free(tarfile); |
|
330 |
+ fclose(tar); |
|
331 |
+ return -1; |
|
356 | 332 |
} |
357 | 333 |
|
358 |
- gzfile = cli_gentemp("."); |
|
359 | 334 |
if((gz = gzopen(gzfile, "wb")) == NULL) { |
360 |
- logg("!Can't open file %s to write.\n", gzfile); |
|
361 |
- opt_free(opt); |
|
362 |
- exit(1); |
|
335 |
+ logg("!build: Can't open file %s to write.\n", gzfile); |
|
336 |
+ free(tarfile); |
|
337 |
+ fclose(tar); |
|
338 |
+ free(gzfile); |
|
339 |
+ return -1; |
|
363 | 340 |
} |
364 | 341 |
|
365 |
- while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) |
|
366 |
- gzwrite(gz, buffer, bytes); |
|
342 |
+ while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) { |
|
343 |
+ if(!gzwrite(gz, buffer, bytes)) { |
|
344 |
+ logg("!build: Can't gzwrite to %s\n", gzfile); |
|
345 |
+ fclose(tar); |
|
346 |
+ gzclose(gz); |
|
347 |
+ free(tarfile); |
|
348 |
+ free(gzfile); |
|
349 |
+ return -1; |
|
350 |
+ } |
|
351 |
+ } |
|
367 | 352 |
|
368 | 353 |
fclose(tar); |
354 |
+ gzclose(gz); |
|
369 | 355 |
unlink(tarfile); |
370 | 356 |
free(tarfile); |
371 | 357 |
|
372 |
- gzclose(gz); |
|
373 |
- |
|
374 |
- |
|
375 |
- /* try to read cvd header of old database */ |
|
358 |
+ /* try to read cvd header of current database */ |
|
376 | 359 |
dbdir = freshdbdir(); |
377 |
- sprintf(buffer, "%s/%s", dbdir, opt_arg(opt, "build")); |
|
360 |
+ snprintf(buffer, sizeof(buffer), "%s/%s", dbdir, opt_arg(opt, "build")); |
|
378 | 361 |
free(dbdir); |
379 |
- if((oldcvd = cl_cvdhead(buffer)) == NULL) |
|
380 |
- logg("^CAN'T READ CVD HEADER OF CURRENT DATABASE %s\n", buffer); |
|
381 |
- |
|
382 |
- /* generate header */ |
|
383 |
- |
|
384 |
- /* magic string */ |
|
362 |
+ if((oldcvd = cl_cvdhead(buffer)) == NULL) { |
|
363 |
+ logg("^build: CAN'T READ CVD HEADER OF CURRENT DATABASE %s\n", buffer); |
|
364 |
+ sleep(3); |
|
365 |
+ } |
|
385 | 366 |
|
367 |
+ /* build header */ |
|
386 | 368 |
strcpy(header, "ClamAV-VDB:"); |
387 | 369 |
|
388 | 370 |
/* time */ |
389 |
- |
|
390 | 371 |
time(&timet); |
391 | 372 |
brokent = localtime(&timet); |
392 | 373 |
setlocale(LC_TIME, "C"); |
393 |
- strftime(smbuff, 30, "%d %b %Y %H-%M %z", brokent); |
|
374 |
+ strftime(smbuff, sizeof(smbuff), "%d %b %Y %H-%M %z", brokent); |
|
394 | 375 |
strcat(header, smbuff); |
395 | 376 |
|
396 |
- /* version number */ |
|
397 |
- |
|
398 |
- /* ... increment version number by one */ |
|
399 |
- |
|
377 |
+ /* increment version number by one */ |
|
400 | 378 |
if(oldcvd) { |
401 | 379 |
sprintf(smbuff, ":%d:", oldcvd->version + 1); |
402 | 380 |
} else { |
... | ... |
@@ -408,7 +386,7 @@ int build(struct optstruct *opt) |
408 | 408 |
strcat(header, smbuff); |
409 | 409 |
|
410 | 410 |
/* number of signatures */ |
411 |
- sprintf(smbuff, "%d:", no); |
|
411 |
+ sprintf(smbuff, "%d:", sigs); |
|
412 | 412 |
strcat(header, smbuff); |
413 | 413 |
|
414 | 414 |
/* functionality level */ |
... | ... |
@@ -416,28 +394,52 @@ int build(struct optstruct *opt) |
416 | 416 |
strcat(header, smbuff); |
417 | 417 |
|
418 | 418 |
/* MD5 */ |
419 |
- pt = cli_md5file(gzfile); |
|
419 |
+ if(!(pt = cli_md5file(gzfile))) { |
|
420 |
+ logg("!build: Can't generate MD5 checksum for gzfile\n"); |
|
421 |
+ unlink(gzfile); |
|
422 |
+ free(gzfile); |
|
423 |
+ return -1; |
|
424 |
+ } |
|
420 | 425 |
strcat(header, pt); |
421 | 426 |
free(pt); |
422 | 427 |
strcat(header, ":"); |
423 | 428 |
|
424 | 429 |
/* ask for builder name */ |
425 | 430 |
fflush(stdin); |
426 |
- logg("Builder id: "); |
|
427 |
- fscanf(stdin, "%s", smbuff); |
|
431 |
+ logg("Builder name: "); |
|
432 |
+ if(fgets(smbuff, sizeof(smbuff), stdin)) { |
|
433 |
+ cli_chomp(smbuff); |
|
434 |
+ } else { |
|
435 |
+ logg("!build: Can't get builder name\n"); |
|
436 |
+ unlink(gzfile); |
|
437 |
+ free(gzfile); |
|
438 |
+ return -1; |
|
439 |
+ } |
|
428 | 440 |
|
429 | 441 |
/* digital signature */ |
430 |
- fd = fopen(gzfile, "rb"); |
|
431 |
- pt = cli_md5stream(fd, buffer); |
|
432 |
- fclose(fd); |
|
442 |
+ if(!(tar = fopen(gzfile, "rb"))) { |
|
443 |
+ logg("!build: Can't open file %s for reading\n", gzfile); |
|
444 |
+ unlink(gzfile); |
|
445 |
+ free(gzfile); |
|
446 |
+ return -1; |
|
447 |
+ } |
|
448 |
+ |
|
449 |
+ if(!(pt = cli_md5stream(tar, (unsigned char *) buffer))) { |
|
450 |
+ logg("!build: Can't generate MD5 checksum for %s\n", gzfile); |
|
451 |
+ unlink(gzfile); |
|
452 |
+ free(gzfile); |
|
453 |
+ return -1; |
|
454 |
+ } |
|
433 | 455 |
free(pt); |
456 |
+ rewind(tar); |
|
457 |
+ |
|
434 | 458 |
if(!(pt = getdsig(opt_arg(opt, "server"), smbuff, buffer))) { |
435 |
- logg("No digital signature - no CVD file...\n"); |
|
459 |
+ logg("!build: Can't get digital signature from remote server\n"); |
|
436 | 460 |
unlink(gzfile); |
437 |
- opt_free(opt); |
|
438 |
- exit(1); |
|
461 |
+ free(gzfile); |
|
462 |
+ fclose(tar); |
|
463 |
+ return -1; |
|
439 | 464 |
} |
440 |
- |
|
441 | 465 |
strcat(header, pt); |
442 | 466 |
free(pt); |
443 | 467 |
strcat(header, ":"); |
... | ... |
@@ -449,194 +451,191 @@ int build(struct optstruct *opt) |
449 | 449 |
sprintf(header + strlen(header), ":%d", (int) timet); |
450 | 450 |
|
451 | 451 |
/* fill up with spaces */ |
452 |
- |
|
453 |
- while(strlen(header) < 512) |
|
452 |
+ while(strlen(header) < sizeof(header) - 1) |
|
454 | 453 |
strcat(header, " "); |
455 | 454 |
|
456 | 455 |
/* build the final database */ |
457 |
- |
|
458 | 456 |
pt = opt_arg(opt, "build"); |
459 |
- if((cvd = fopen(pt, "wb")) == NULL) { |
|
460 |
- logg("!Can't write the final database %s\n", pt); |
|
457 |
+ if(!(cvd = fopen(pt, "wb"))) { |
|
458 |
+ logg("!build: Can't create final database %s\n", pt); |
|
461 | 459 |
unlink(gzfile); |
462 |
- opt_free(opt); |
|
463 |
- exit(1); |
|
460 |
+ free(gzfile); |
|
461 |
+ fclose(tar); |
|
462 |
+ return -1; |
|
464 | 463 |
} |
465 | 464 |
|
466 |
- fwrite(header, 1, 512, cvd); |
|
467 |
- |
|
468 |
- if((tar = fopen(gzfile, "rb")) == NULL) { |
|
469 |
- logg("!Can't open file %s for reading.\n", gzfile); |
|
470 |
- opt_free(opt); |
|
471 |
- exit(1); |
|
465 |
+ if(fwrite(header, 1, 512, cvd) != 512) { |
|
466 |
+ logg("!build: Can't write to %s\n", pt); |
|
467 |
+ fclose(cvd); |
|
468 |
+ fclose(tar); |
|
469 |
+ unlink(pt); |
|
470 |
+ unlink(gzfile); |
|
471 |
+ free(gzfile); |
|
472 |
+ return -1; |
|
472 | 473 |
} |
473 | 474 |
|
474 |
- while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) |
|
475 |
- fwrite(buffer, 1, bytes, cvd); |
|
475 |
+ while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) { |
|
476 |
+ if(fwrite(buffer, 1, bytes, cvd) != bytes) { |
|
477 |
+ fclose(tar); |
|
478 |
+ fclose(cvd); |
|
479 |
+ unlink(pt); |
|
480 |
+ logg("!build: Can't write to %s\n", gzfile); |
|
481 |
+ unlink(gzfile); |
|
482 |
+ free(gzfile); |
|
483 |
+ return -1; |
|
484 |
+ } |
|
485 |
+ } |
|
476 | 486 |
|
477 | 487 |
fclose(tar); |
478 | 488 |
fclose(cvd); |
479 |
- |
|
480 |
- unlink(gzfile); |
|
489 |
+ if(unlink(gzfile) == -1) { |
|
490 |
+ logg("^build: Can't unlink %s\n", gzfile); |
|
491 |
+ return -1; |
|
492 |
+ } |
|
481 | 493 |
free(gzfile); |
482 | 494 |
|
483 |
- logg("Database %s created.\n", pt); |
|
495 |
+ logg("Database %s created\n", pt); |
|
496 |
+ |
|
497 |
+ return 0; |
|
498 |
+} |
|
499 |
+ |
|
500 |
+static int unpack(struct optstruct *opt) |
|
501 |
+{ |
|
502 |
+ char *name, *dbdir; |
|
503 |
+ |
|
504 |
+ |
|
505 |
+ if(opt_check(opt, "unpack-current")) { |
|
506 |
+ dbdir = freshdbdir(); |
|
507 |
+ name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 2, sizeof(char)); |
|
508 |
+ sprintf(name, "%s/%s", dbdir, opt_arg(opt, "unpack-current")); |
|
509 |
+ free(dbdir); |
|
510 |
+ } else |
|
511 |
+ name = strdup(opt_arg(opt, "unpack")); |
|
484 | 512 |
|
485 |
- /* try to load final cvd */ |
|
513 |
+ if(cvd_unpack(name, ".") == -1) { |
|
514 |
+ logg("!unpack: Can't unpack CVD file %s\n", name); |
|
515 |
+ free(name); |
|
516 |
+ return -1; |
|
517 |
+ } |
|
518 |
+ |
|
519 |
+ free(name); |
|
486 | 520 |
return 0; |
487 | 521 |
} |
488 | 522 |
|
489 |
-void cvdinfo(struct optstruct *opt) |
|
523 |
+static int cvdinfo(struct optstruct *opt) |
|
490 | 524 |
{ |
491 | 525 |
struct cl_cvd *cvd; |
492 | 526 |
char *pt; |
493 | 527 |
int ret; |
494 | 528 |
|
529 |
+ |
|
495 | 530 |
pt = opt_arg(opt, "info"); |
496 | 531 |
if((cvd = cl_cvdhead(pt)) == NULL) { |
497 |
- logg("!Can't read/parse CVD header from %s\n", pt); |
|
498 |
- opt_free(opt); |
|
499 |
- exit(1); |
|
532 |
+ logg("!cvdinfo: Can't read/parse CVD header of %s\n", pt); |
|
533 |
+ return -1; |
|
500 | 534 |
} |
501 | 535 |
|
536 |
+ pt = strchr(cvd->time, '-'); |
|
537 |
+ *pt = ':'; |
|
502 | 538 |
logg("Build time: %s\n", cvd->time); |
503 | 539 |
logg("Version: %d\n", cvd->version); |
504 | 540 |
logg("Signatures: %d\n", cvd->sigs); |
505 | 541 |
logg("Functionality level: %d\n", cvd->fl); |
506 | 542 |
logg("Builder: %s\n", cvd->builder); |
507 | 543 |
logg("MD5: %s\n", cvd->md5); |
508 |
- |
|
509 | 544 |
logg("Digital signature: %s\n", cvd->dsig); |
510 | 545 |
|
511 | 546 |
#ifndef HAVE_GMP |
512 |
- logg("Digital signature support not compiled in.\n"); |
|
547 |
+ logg("^Digital signature support not compiled in.\n"); |
|
513 | 548 |
#endif |
514 | 549 |
|
550 |
+ pt = opt_arg(opt, "info"); |
|
515 | 551 |
if((ret = cl_cvdverify(pt))) |
516 |
- logg("!Verification: %s\n", cl_strerror(ret)); |
|
552 |
+ logg("!cvdinfo: Verification: %s\n", cl_strerror(ret)); |
|
517 | 553 |
else |
518 | 554 |
logg("Verification OK.\n"); |
519 | 555 |
|
520 |
- /* free */ |
|
556 |
+ cl_cvdfree(cvd); |
|
557 |
+ return 0; |
|
521 | 558 |
} |
522 | 559 |
|
523 |
-char *getdsig(const char *host, const char *user, const char *data) |
|
524 |
-{ |
|
525 |
- char buff[300], cmd[100], *pass, *pt; |
|
526 |
- struct sockaddr_in server; |
|
527 |
- int sockd, bread, len; |
|
528 |
- |
|
560 |
+static int listdb(const char *filename); |
|
529 | 561 |
|
530 |
-#ifdef PF_INET |
|
531 |
- if((sockd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { |
|
532 |
-#else |
|
533 |
- if((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
534 |
-#endif |
|
535 |
- perror("socket()"); |
|
536 |
- logg("!Can't create the socket.\n"); |
|
537 |
- return NULL; |
|
538 |
- } |
|
562 |
+static int listdir(const char *dirname) |
|
563 |
+{ |
|
564 |
+ DIR *dd; |
|
565 |
+ struct dirent *dent; |
|
566 |
+ char *dbfile; |
|
539 | 567 |
|
540 |
- server.sin_family = AF_INET; |
|
541 |
- server.sin_addr.s_addr = inet_addr(host); |
|
542 |
- server.sin_port = htons(33101); |
|
543 | 568 |
|
544 |
- if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) { |
|
545 |
- close(sockd); |
|
546 |
- perror("connect()"); |
|
547 |
- logg("!Can't connect to ClamAV Signing Service at %s.\n", host); |
|
548 |
- return NULL; |
|
569 |
+ if((dd = opendir(dirname)) == NULL) { |
|
570 |
+ logg("!listdir: Can't open directory %s\n", dirname); |
|
571 |
+ return -1; |
|
549 | 572 |
} |
550 | 573 |
|
551 |
- memset(cmd, 0, sizeof(cmd)); |
|
552 |
- pass = getpass("Password:"); |
|
553 |
- sprintf(cmd, "ClamSign:%s:%s:", user, pass); |
|
554 |
- len = strlen(cmd); |
|
555 |
- pt = cmd; |
|
556 |
- pt += len; |
|
557 |
- memcpy(pt, data, 16); |
|
558 |
- len += 16; |
|
574 |
+ while((dent = readdir(dd))) { |
|
575 |
+#ifndef C_INTERIX |
|
576 |
+ if(dent->d_ino) |
|
577 |
+#endif |
|
578 |
+ { |
|
579 |
+ if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && |
|
580 |
+ (cli_strbcasestr(dent->d_name, ".db") || |
|
581 |
+ cli_strbcasestr(dent->d_name, ".hdb") || |
|
582 |
+ cli_strbcasestr(dent->d_name, ".ndb") || |
|
583 |
+ cli_strbcasestr(dent->d_name, ".zmd") || |
|
584 |
+ cli_strbcasestr(dent->d_name, ".rmd") || |
|
585 |
+ cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
559 | 586 |
|
560 |
- if(write(sockd, cmd, len) < 0) { |
|
561 |
- logg("!Can't write to the socket.\n"); |
|
562 |
- close(sockd); |
|
563 |
- memset(cmd, 0, len); |
|
564 |
- memset(pass, 0, strlen(pass)); |
|
565 |
- return NULL; |
|
566 |
- } |
|
587 |
+ dbfile = (char *) mcalloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char)); |
|
567 | 588 |
|
568 |
- memset(cmd, 0, len); |
|
569 |
- memset(pass, 0, strlen(pass)); |
|
589 |
+ if(!dbfile) { |
|
590 |
+ logg("!listdir: Can't allocate memory for dbfile\n"); |
|
591 |
+ closedir(dd); |
|
592 |
+ return -1; |
|
593 |
+ } |
|
594 |
+ sprintf(dbfile, "%s/%s", dirname, dent->d_name); |
|
570 | 595 |
|
571 |
- memset(buff, 0, sizeof(buff)); |
|
572 |
- if((bread = read(sockd, buff, sizeof(buff))) > 0) { |
|
573 |
- if(!strstr(buff, "Signature:")) { |
|
574 |
- logg("!Signature generation error.\n"); |
|
575 |
- logg("ClamAV SDaemon: %s.\n", buff); |
|
576 |
- close(sockd); |
|
577 |
- return NULL; |
|
578 |
- } else { |
|
579 |
- logg("Signature received (length = %d).\n", strlen(buff) - 10); |
|
596 |
+ if(listdb(dbfile) == -1) { |
|
597 |
+ logg("!listdb: Error listing database %s\n", dbfile); |
|
598 |
+ free(dbfile); |
|
599 |
+ closedir(dd); |
|
600 |
+ return -1; |
|
601 |
+ } |
|
602 |
+ free(dbfile); |
|
603 |
+ } |
|
580 | 604 |
} |
581 | 605 |
} |
582 | 606 |
|
583 |
- close(sockd); |
|
584 |
- pt = buff; |
|
585 |
- pt += 10; |
|
586 |
- return strdup(pt); |
|
587 |
-} |
|
588 |
- |
|
589 |
-int unpack(struct optstruct *opt) |
|
590 |
-{ |
|
591 |
- char *name, *dbdir; |
|
592 |
- |
|
593 |
- if(opt_check(opt, "unpack-current")) { |
|
594 |
- dbdir = freshdbdir(); |
|
595 |
- name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 2, sizeof(char)); |
|
596 |
- sprintf(name, "%s/%s", dbdir, opt_arg(opt, "unpack-current")); |
|
597 |
- free(dbdir); |
|
598 |
- } else |
|
599 |
- name = strdup(opt_arg(opt, "unpack")); |
|
600 |
- |
|
601 |
- if(cvd_unpack(name, ".") == -1) { |
|
602 |
- logg("!Can't unpack CVD file %s\n", name); |
|
603 |
- free(name); |
|
604 |
- opt_free(opt); |
|
605 |
- exit(1); |
|
606 |
- } |
|
607 |
- |
|
608 |
- free(name); |
|
609 |
- opt_free(opt); |
|
610 |
- exit(0); |
|
607 |
+ closedir(dd); |
|
608 |
+ return 0; |
|
611 | 609 |
} |
612 | 610 |
|
613 |
-int listdb(const char *filename) |
|
611 |
+static int listdb(const char *filename) |
|
614 | 612 |
{ |
615 |
- FILE *fd, *tmpd; |
|
616 |
- char *buffer, *pt, *start, *dir, *tmp; |
|
617 |
- int line = 0, bytes; |
|
613 |
+ FILE *fd; |
|
614 |
+ char *buffer, *pt, *start, *dir; |
|
615 |
+ int line = 0; |
|
618 | 616 |
const char *tmpdir; |
619 | 617 |
|
620 | 618 |
|
621 | 619 |
if((fd = fopen(filename, "rb")) == NULL) { |
622 |
- logg("!listdb(): Can't open file %s\n", filename); |
|
620 |
+ logg("!listdb: Can't open file %s\n", filename); |
|
623 | 621 |
return -1; |
624 | 622 |
} |
625 | 623 |
|
626 |
- if(!(buffer = (char *) mmalloc(FILEBUFF))) { |
|
627 |
- logg("!listdb(): Can't allocate memory.\n"); |
|
624 |
+ if(!(buffer = (char *) mcalloc(FILEBUFF, 1))) { |
|
625 |
+ logg("!listdb: Can't allocate memory for buffer\n"); |
|
628 | 626 |
fclose(fd); |
629 | 627 |
return -1; |
630 | 628 |
} |
631 | 629 |
|
632 |
- memset(buffer, 0, FILEBUFF); |
|
633 | 630 |
/* check for CVD file */ |
634 | 631 |
fgets(buffer, 12, fd); |
635 | 632 |
rewind(fd); |
636 | 633 |
|
637 | 634 |
if(!strncmp(buffer, "ClamAV-VDB:", 11)) { |
638 |
- |
|
639 |
- fseek(fd, 512, SEEK_SET); |
|
635 |
+ free(buffer); |
|
636 |
+ fclose(fd); |
|
640 | 637 |
|
641 | 638 |
tmpdir = getenv("TMPDIR"); |
642 | 639 |
if(tmpdir == NULL) |
... | ... |
@@ -646,73 +645,45 @@ int listdb(const char *filename) |
646 | 646 |
tmpdir = "/tmp"; |
647 | 647 |
#endif |
648 | 648 |
|
649 |
- dir = cli_gentemp(tmpdir); |
|
650 |
- if(mkdir(dir, 0700)) { |
|
651 |
- logg("!listdb(): Can't create temporary directory %s\n", dir); |
|
652 |
- free(buffer); |
|
653 |
- fclose(fd); |
|
649 |
+ if(!(dir = cli_gentemp(tmpdir))) { |
|
650 |
+ logg("!listdb: Can't generate temporary name\n"); |
|
654 | 651 |
return -1; |
655 | 652 |
} |
656 | 653 |
|
657 |
- /* FIXME: it seems there is some problem with current position indicator |
|
658 |
- * after gzdopen() call in cli_untgz(). Temporarily we need this wrapper: |
|
659 |
- */ |
|
660 |
- |
|
661 |
- /* start */ |
|
662 |
- |
|
663 |
- tmp = cli_gentemp(tmpdir); |
|
664 |
- if((tmpd = fopen(tmp, "wb+")) == NULL) { |
|
665 |
- logg("!listdb(): Can't create temporary file %s\n", tmp); |
|
654 |
+ if(mkdir(dir, 0700)) { |
|
655 |
+ logg("!listdb: Can't create temporary directory %s\n", dir); |
|
666 | 656 |
free(dir); |
667 |
- free(tmp); |
|
668 |
- free(buffer); |
|
669 |
- fclose(fd); |
|
670 | 657 |
return -1; |
671 | 658 |
} |
672 | 659 |
|
673 |
- while((bytes = fread(buffer, 1, FILEBUFF, fd)) > 0) |
|
674 |
- fwrite(buffer, 1, bytes, tmpd); |
|
675 |
- |
|
676 |
- free(buffer); |
|
677 |
- fclose(fd); |
|
678 |
- |
|
679 |
- fflush(tmpd); |
|
680 |
- fseek(tmpd, 0L, SEEK_SET); |
|
681 |
- |
|
682 |
- if(cli_untgz(fileno(tmpd), dir)) { |
|
683 |
- logg("!listdb(): Can't unpack CVD file.\n"); |
|
684 |
- cli_rmdirs(dir); |
|
660 |
+ if(cvd_unpack(filename, dir) == -1) { |
|
661 |
+ logg("!listdb: Can't unpack CVD file %s\n", filename); |
|
662 |
+ rmdirs(dir); |
|
685 | 663 |
free(dir); |
686 |
- fclose(tmpd); |
|
687 |
- unlink(tmp); |
|
688 |
- free(tmp); |
|
689 |
- free(buffer); |
|
690 | 664 |
return -1; |
691 | 665 |
} |
692 | 666 |
|
693 |
- fclose(tmpd); |
|
694 |
- unlink(tmp); |
|
695 |
- free(tmp); |
|
696 |
- |
|
697 |
- /* wrapper end */ |
|
698 |
- |
|
699 | 667 |
/* list extracted directory */ |
700 |
- listdir(dir); |
|
668 |
+ if(listdir(dir) == -1) { |
|
669 |
+ logg("!listdb: Can't unpack CVD file %s\n", filename); |
|
670 |
+ rmdirs(dir); |
|
671 |
+ free(dir); |
|
672 |
+ return -1; |
|
673 |
+ } |
|
701 | 674 |
|
702 |
- cli_rmdirs(dir); |
|
675 |
+ rmdirs(dir); |
|
703 | 676 |
free(dir); |
704 | 677 |
|
705 | 678 |
return 0; |
706 | 679 |
} |
707 | 680 |
|
708 |
- if(cli_strbcasestr(filename, ".db") || cli_strbcasestr(filename, ".db2")) { |
|
709 |
- /* old style database */ |
|
681 |
+ if(cli_strbcasestr(filename, ".db")) { /* old style database */ |
|
710 | 682 |
|
711 | 683 |
while(fgets(buffer, FILEBUFF, fd)) { |
712 | 684 |
line++; |
713 | 685 |
pt = strchr(buffer, '='); |
714 | 686 |
if(!pt) { |
715 |
- logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename); |
|
687 |
+ logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename); |
|
716 | 688 |
fclose(fd); |
717 | 689 |
free(buffer); |
718 | 690 |
return -1; |
... | ... |
@@ -727,7 +698,7 @@ int listdb(const char *filename) |
727 | 727 |
logg("%s\n", start); |
728 | 728 |
} |
729 | 729 |
|
730 |
- } else if(cli_strbcasestr(filename, ".hdb")) { |
|
730 |
+ } else if(cli_strbcasestr(filename, ".hdb")) { /* hash database */ |
|
731 | 731 |
|
732 | 732 |
while(fgets(buffer, FILEBUFF, fd)) { |
733 | 733 |
line++; |
... | ... |
@@ -735,7 +706,7 @@ int listdb(const char *filename) |
735 | 735 |
start = cli_strtok(buffer, 2, ":"); |
736 | 736 |
|
737 | 737 |
if(!start) { |
738 |
- logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename); |
|
738 |
+ logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename); |
|
739 | 739 |
fclose(fd); |
740 | 740 |
free(buffer); |
741 | 741 |
return -1; |
... | ... |
@@ -756,7 +727,7 @@ int listdb(const char *filename) |
756 | 756 |
start = cli_strtok(buffer, 0, ":"); |
757 | 757 |
|
758 | 758 |
if(!start) { |
759 |
- logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename); |
|
759 |
+ logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename); |
|
760 | 760 |
fclose(fd); |
761 | 761 |
free(buffer); |
762 | 762 |
return -1; |
... | ... |
@@ -775,62 +746,13 @@ int listdb(const char *filename) |
775 | 775 |
return 0; |
776 | 776 |
} |
777 | 777 |
|
778 |
-int listdir(const char *dirname) |
|
779 |
-{ |
|
780 |
- DIR *dd; |
|
781 |
- struct dirent *dent; |
|
782 |
- char *dbfile; |
|
783 |
- |
|
784 |
- |
|
785 |
- if((dd = opendir(dirname)) == NULL) { |
|
786 |
- logg("!Can't open directory %s\n", dirname); |
|
787 |
- return -1; |
|
788 |
- } |
|
789 |
- |
|
790 |
- while((dent = readdir(dd))) { |
|
791 |
-#ifndef C_INTERIX |
|
792 |
- if(dent->d_ino) |
|
793 |
-#endif |
|
794 |
- { |
|
795 |
- if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && |
|
796 |
- (cli_strbcasestr(dent->d_name, ".db") || |
|
797 |
- cli_strbcasestr(dent->d_name, ".db2") || |
|
798 |
- cli_strbcasestr(dent->d_name, ".hdb") || |
|
799 |
- cli_strbcasestr(dent->d_name, ".ndb") || |
|
800 |
- cli_strbcasestr(dent->d_name, ".zmd") || |
|
801 |
- cli_strbcasestr(dent->d_name, ".rmd") || |
|
802 |
- cli_strbcasestr(dent->d_name, ".cvd"))) { |
|
803 |
- |
|
804 |
- dbfile = (char *) mcalloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char)); |
|
805 |
- |
|
806 |
- if(!dbfile) { |
|
807 |
- logg("!listdir(): Can't allocate memory.\n"); |
|
808 |
- closedir(dd); |
|
809 |
- return -1; |
|
810 |
- } |
|
811 |
- sprintf(dbfile, "%s/%s", dirname, dent->d_name); |
|
812 |
- |
|
813 |
- if(listdb(dbfile)) { |
|
814 |
- logg("!listdb(): error listing database %s\n", dbfile); |
|
815 |
- free(dbfile); |
|
816 |
- closedir(dd); |
|
817 |
- return -1; |
|
818 |
- } |
|
819 |
- free(dbfile); |
|
820 |
- } |
|
821 |
- } |
|
822 |
- } |
|
823 |
- |
|
824 |
- closedir(dd); |
|
825 |
- return 0; |
|
826 |
-} |
|
827 |
- |
|
828 |
-void listsigs(struct optstruct *opt) |
|
778 |
+static int listsigs(struct optstruct *opt) |
|
829 | 779 |
{ |
830 | 780 |
int ret; |
831 | 781 |
const char *name; |
832 | 782 |
char *dbdir; |
833 | 783 |
|
784 |
+ |
|
834 | 785 |
mprintf_stdout = 1; |
835 | 786 |
|
836 | 787 |
if((name = opt_arg(opt, "list-sigs"))) { |
... | ... |
@@ -841,15 +763,53 @@ void listsigs(struct optstruct *opt) |
841 | 841 |
free(dbdir); |
842 | 842 |
} |
843 | 843 |
|
844 |
- opt_free(opt); |
|
845 |
- ret ? exit(1) : exit(0); |
|
844 |
+ return ret; |
|
845 |
+} |
|
846 |
+ |
|
847 |
+static int vbadump(struct optstruct *opt) |
|
848 |
+{ |
|
849 |
+ int fd, hex_output=0; |
|
850 |
+ char *dir; |
|
851 |
+ |
|
852 |
+ |
|
853 |
+ if(opt_check(opt, "vba-hex")) |
|
854 |
+ hex_output = 1; |
|
855 |
+ |
|
856 |
+ if((fd = open(opt_arg(opt, "vba"), O_RDONLY)) == -1) { |
|
857 |
+ if((fd = open(opt_arg(opt, "vba-hex"), O_RDONLY)) == -1) { |
|
858 |
+ logg("!vbadump: Can't open file %s\n", opt_arg(opt, "vba")); |
|
859 |
+ return -1; |
|
860 |
+ } |
|
861 |
+ } |
|
862 |
+ |
|
863 |
+ /* generate the temporary directory */ |
|
864 |
+ dir = cli_gentemp(NULL); |
|
865 |
+ if(mkdir(dir, 0700)) { |
|
866 |
+ logg("!vbadump: Can't create temporary directory %s\n", dir); |
|
867 |
+ free(dir); |
|
868 |
+ close(fd); |
|
869 |
+ return -1; |
|
870 |
+ } |
|
871 |
+ |
|
872 |
+ if(cli_ole2_extract(fd, dir, NULL)) { |
|
873 |
+ cli_rmdirs(dir); |
|
874 |
+ free(dir); |
|
875 |
+ close(fd); |
|
876 |
+ return -1; |
|
877 |
+ } |
|
878 |
+ |
|
879 |
+ close(fd); |
|
880 |
+ sigtool_vba_scandir(dir, hex_output); |
|
881 |
+ rmdirs(dir); |
|
882 |
+ free(dir); |
|
883 |
+ return 0; |
|
846 | 884 |
} |
847 | 885 |
|
848 | 886 |
void help(void) |
849 | 887 |
{ |
850 | 888 |
mprintf("\n"); |
851 | 889 |
mprintf(" Clam AntiVirus: Signature Tool (sigtool) "VERSION"\n"); |
852 |
- mprintf(" (C) 2002 - 2005 ClamAV Team - http://www.clamav.net/team.html\n\n"); |
|
890 |
+ mprintf(" (C) 2002 - 2006 ClamAV Team - http://www.clamav.net/team.html\n\n"); |
|
853 | 891 |
|
854 | 892 |
mprintf(" --help -h show help\n"); |
855 | 893 |
mprintf(" --version -V print version number and exit\n"); |
... | ... |
@@ -871,5 +831,85 @@ void help(void) |
871 | 871 |
mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n"); |
872 | 872 |
mprintf("\n"); |
873 | 873 |
|
874 |
- exit(0); |
|
874 |
+ return; |
|
875 |
+} |
|
876 |
+ |
|
877 |
+int main(int argc, char **argv) |
|
878 |
+{ |
|
879 |
+ int ret = 1; |
|
880 |
+ struct optstruct *opt; |
|
881 |
+ const char *short_options = "hvVb:i:u:l::"; |
|
882 |
+ static struct option long_options[] = { |
|
883 |
+ {"help", 0, 0, 'h'}, |
|
884 |
+ {"quiet", 0, 0, 0}, |
|
885 |
+ {"debug", 0, 0, 0}, |
|
886 |
+ {"verbose", 0, 0, 'v'}, |
|
887 |
+ {"stdout", 0, 0, 0}, |
|
888 |
+ {"version", 0, 0, 'V'}, |
|
889 |
+ {"tempdir", 1, 0, 0}, |
|
890 |
+ {"hex-dump", 0, 0, 0}, |
|
891 |
+ {"md5", 0, 0, 0}, |
|
892 |
+ {"html-normalise", 1, 0, 0}, |
|
893 |
+ {"build", 1, 0, 'b'}, |
|
894 |
+ {"server", 1, 0, 0}, |
|
895 |
+ {"unpack", 1, 0, 'u'}, |
|
896 |
+ {"unpack-current", 1, 0, 0}, |
|
897 |
+ {"info", 1, 0, 'i'}, |
|
898 |
+ {"list-sigs", 2, 0, 'l'}, |
|
899 |
+ {"vba", 1, 0 ,0}, |
|
900 |
+ {"vba-hex", 1, 0, 0}, |
|
901 |
+ {0, 0, 0, 0} |
|
902 |
+ }; |
|
903 |
+ |
|
904 |
+ |
|
905 |
+ opt = opt_parse(argc, argv, short_options, long_options, NULL); |
|
906 |
+ if(!opt) { |
|
907 |
+ mprintf("!Can't parse the command line\n"); |
|
908 |
+ return 1; |
|
909 |
+ } |
|
910 |
+ |
|
911 |
+ if(opt_check(opt, "quiet")) |
|
912 |
+ mprintf_quiet = 1; |
|
913 |
+ |
|
914 |
+ if(opt_check(opt, "stdout")) |
|
915 |
+ mprintf_stdout = 1; |
|
916 |
+ |
|
917 |
+ if(opt_check(opt, "debug")) |
|
918 |
+ cl_debug(); |
|
919 |
+ |
|
920 |
+ if(opt_check(opt, "version")) { |
|
921 |
+ print_version(); |
|
922 |
+ opt_free(opt); |
|
923 |
+ return 0; |
|
924 |
+ } |
|
925 |
+ |
|
926 |
+ if(opt_check(opt, "help")) { |
|
927 |
+ opt_free(opt); |
|
928 |
+ help(); |
|
929 |
+ } |
|
930 |
+ |
|
931 |
+ if(opt_check(opt, "hex-dump")) |
|
932 |
+ ret = hexdump(); |
|
933 |
+ else if(opt_check(opt, "md5")) |
|
934 |
+ ret = md5sig(opt); |
|
935 |
+ else if(opt_check(opt, "html-normalise")) |
|
936 |
+ ret = htmlnorm(opt); |
|
937 |
+ else if(opt_check(opt, "build")) |
|
938 |
+ ret = build(opt); |
|
939 |
+ else if(opt_check(opt, "unpack")) |
|
940 |
+ ret = unpack(opt); |
|
941 |
+ else if(opt_check(opt, "unpack-current")) |
|
942 |
+ ret = unpack(opt); |
|
943 |
+ else if(opt_check(opt, "info")) |
|
944 |
+ ret = cvdinfo(opt); |
|
945 |
+ else if(opt_check(opt, "list-sigs")) |
|
946 |
+ ret = listsigs(opt); |
|
947 |
+ else if(opt_check(opt, "vba") || opt_check(opt, "vba-hex")) |
|
948 |
+ ret = vbadump(opt); |
|
949 |
+ else |
|
950 |
+ help(); |
|
951 |
+ |
|
952 |
+ |
|
953 |
+ opt_free(opt); |
|
954 |
+ return ret ? 1 : 0; |
|
875 | 955 |
} |