git-svn-id: file:///var/lib/svn/clamav-devel/branches/clamd-proto@4634 77e5149b-7576-45b1-b177-96237e5ba77b
aCaB authored on 2009/01/23 18:59:40... | ... |
@@ -55,11 +55,11 @@ |
55 | 55 |
int notremoved = 0, notmoved = 0; |
56 | 56 |
int printinfected = 0; |
57 | 57 |
|
58 |
-struct sockaddr *mainsa = NULL; |
|
59 |
-int mainsasz; |
|
60 |
-struct sockaddr_un nixsock; |
|
61 |
-struct sockaddr_in tcpsock; |
|
62 |
-struct sockaddr_in strmsock; |
|
58 |
+static struct sockaddr *mainsa = NULL; |
|
59 |
+static int mainsasz; |
|
60 |
+static struct sockaddr_un nixsock; |
|
61 |
+static struct sockaddr_in tcpsock; |
|
62 |
+static struct sockaddr_in strmsock; |
|
63 | 63 |
enum { |
64 | 64 |
CONT, |
65 | 65 |
MULTI, |
... | ... |
@@ -170,11 +170,11 @@ static int recvln(struct RCVLN *s, char **rbol, char **reol) { |
170 | 170 |
|
171 | 171 |
static int dsresult(int sockd, int scantype, const char *filename) |
172 | 172 |
{ |
173 |
- int infected = 0, waserror = 0, fd; |
|
173 |
+ int infected = 0, waserror = 0, fd; |
|
174 | 174 |
int len; |
175 | 175 |
char *bol, *eol; |
176 |
- struct RCVLN rcv; |
|
177 | 176 |
char buf[BUFSIZ]; |
177 |
+ struct RCVLN rcv; |
|
178 | 178 |
|
179 | 179 |
recvlninit(&rcv, sockd); |
180 | 180 |
|
... | ... |
@@ -197,7 +197,7 @@ static int dsresult(int sockd, int scantype, const char *filename) |
197 | 197 |
|
198 | 198 |
if(!(fd = open(filename, O_RDONLY))) { |
199 | 199 |
logg("!Open failed on %s.\n", filename); |
200 |
- return -1; /* FIXME: grave ? */ |
|
200 |
+ return -1; |
|
201 | 201 |
} |
202 | 202 |
if(sendln(sockd, "zSTREAM", 8)) return -1; |
203 | 203 |
if(!(len = recvln(&rcv, &bol, &eol)) || len < 7 || memcmp(bol, "PORT ", 5) || !(len = atoi(bol + 5))) return -1; |
... | ... |
@@ -240,10 +240,13 @@ static int dsresult(int sockd, int scantype, const char *filename) |
240 | 240 |
unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; |
241 | 241 |
char dummy[]=""; |
242 | 242 |
|
243 |
- if(!(fd = open(filename, O_RDONLY))) { |
|
244 |
- logg("!Open failed on %s.\n", filename); |
|
245 |
- return -1; /* FIXME: grave ? */ |
|
246 |
- |
|
243 |
+ if(filename) { |
|
244 |
+ if(!(fd = open(filename, O_RDONLY))) { |
|
245 |
+ logg("!Open failed on %s.\n", filename); |
|
246 |
+ return -1; |
|
247 |
+ } |
|
248 |
+ } else { |
|
249 |
+ fd = 0; |
|
247 | 250 |
} |
248 | 251 |
if(sendln(sockd, "zFILDES", 8)) return -1; |
249 | 252 |
|
... | ... |
@@ -321,56 +324,56 @@ static int dconnect() |
321 | 321 |
return sockd; |
322 | 322 |
} |
323 | 323 |
|
324 |
-int get_clamd_version(const struct optstruct *opts) |
|
325 |
-{ |
|
326 |
- char buff[64]; |
|
327 |
- int bread, sockd; |
|
328 |
- |
|
329 |
- |
|
330 |
- /* FIXME: call isremote */ |
|
331 |
- if((sockd = dconnect()) < 0) |
|
332 |
- return 2; |
|
324 |
+static int isremote(const struct optstruct *opts) { |
|
325 |
+ int s, ret; |
|
326 |
+ const struct optstruct *opt; |
|
327 |
+ struct hostent *he; |
|
328 |
+ struct optstruct *clamdopts; |
|
329 |
+ const char *clamd_conf = optget(opts, "config-file")->strarg; |
|
333 | 330 |
|
334 |
- if(write(sockd, "VERSION", 7) <= 0) { |
|
335 |
- logg("!Can't write to the socket.\n"); |
|
336 |
- close(sockd); |
|
337 |
- return 2; |
|
331 |
+ if((clamdopts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { |
|
332 |
+ logg("!Can't parse clamd configuration file %s\n", clamd_conf); |
|
333 |
+ return 0; |
|
338 | 334 |
} |
339 |
- |
|
340 |
- while((bread = read(sockd, buff, sizeof(buff)-1)) > 0) { |
|
341 |
- buff[bread] = '\0'; |
|
342 |
- printf("%s\n", buff); |
|
335 |
+ if(optget(clamdopts, "LocalSocket")->enabled) { |
|
336 |
+ memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
337 |
+ nixsock.sun_family = AF_UNIX; |
|
338 |
+ strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); |
|
339 |
+ nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; |
|
340 |
+ mainsa = (struct sockaddr *)&nixsock; |
|
341 |
+ mainsasz = sizeof(nixsock); |
|
342 |
+ optfree(clamdopts); |
|
343 |
+ return 0; |
|
343 | 344 |
} |
344 |
- |
|
345 |
- close(sockd); |
|
346 |
- return 0; |
|
347 |
-} |
|
348 |
- |
|
349 |
-int reload_clamd_database(const struct optstruct *opts) |
|
350 |
-{ |
|
351 |
- char buff[64]; |
|
352 |
- int bread, sockd; |
|
353 |
- |
|
354 |
- |
|
355 |
- /* FIXME: call isremote */ |
|
356 |
- if((sockd = dconnect()) < 0) |
|
357 |
- return 2; |
|
358 |
- |
|
359 |
- if(write(sockd, "RELOAD", 6) <= 0) { |
|
360 |
- logg("!Can't write to the socket.\n"); |
|
361 |
- close(sockd); |
|
362 |
- return 2; |
|
345 |
+ if(!(opt = optget(clamdopts, "TCPSocket"))->enabled) { |
|
346 |
+ optfree(clamdopts); |
|
347 |
+ return 0; |
|
363 | 348 |
} |
364 |
- |
|
365 |
- bread = read(sockd, buff, sizeof(buff) - 1); |
|
366 |
- if(bread == -1 || strncmp(buff, "RELOADING", 9)) { |
|
367 |
- logg("!Incorrect reply from clamd\n"); |
|
368 |
- close(sockd); |
|
369 |
- return 2; |
|
349 |
+ mainsa = (struct sockaddr *)&tcpsock; |
|
350 |
+ mainsasz = sizeof(tcpsock); |
|
351 |
+ memset((void *)&tcpsock, 0, sizeof(tcpsock)); |
|
352 |
+ memset((void *)&strmsock, 0, sizeof(strmsock)); |
|
353 |
+ tcpsock.sin_family = strmsock.sin_family = AF_INET; |
|
354 |
+ tcpsock.sin_port = htons(opt->numarg); |
|
355 |
+ if(!(opt = optget(clamdopts, "TCPAddr"))->enabled) { |
|
356 |
+ tcpsock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
357 |
+ optfree(clamdopts); |
|
358 |
+ return 0; |
|
370 | 359 |
} |
371 |
- |
|
372 |
- close(sockd); |
|
373 |
- return 0; |
|
360 |
+ he = gethostbyname(opt->strarg); |
|
361 |
+ optfree(clamdopts); |
|
362 |
+ if(!he) { |
|
363 |
+ perror("gethostbyname()"); |
|
364 |
+ logg("!Can't lookup clamd hostname.\n"); |
|
365 |
+ mainsa = NULL; |
|
366 |
+ return 0; |
|
367 |
+ } |
|
368 |
+ strmsock.sin_port = htons(INADDR_ANY); |
|
369 |
+ tcpsock.sin_addr = strmsock.sin_addr = *(struct in_addr *) he->h_addr_list[0]; |
|
370 |
+ if(!(s = socket(tcpsock.sin_family, SOCK_STREAM, 0))) return 0; |
|
371 |
+ ret = (bind(s, (struct sockaddr *)&strmsock, sizeof(strmsock)) != 0); |
|
372 |
+ close(s); |
|
373 |
+ return ret; |
|
374 | 374 |
} |
375 | 375 |
|
376 | 376 |
static int client_scan(const char *file, int scantype, int *infected, int *errors) { |
... | ... |
@@ -430,7 +433,6 @@ static int client_scan(const char *file, int scantype, int *infected, int *error |
430 | 430 |
case S_IFREG: |
431 | 431 |
if((sockd = dconnect()) < 0) |
432 | 432 |
return 1; |
433 |
- |
|
434 | 433 |
if((ret = dsresult(sockd, scantype, fullpath)) >= 0) |
435 | 434 |
*infected += ret; |
436 | 435 |
else |
... | ... |
@@ -447,65 +449,82 @@ static int client_scan(const char *file, int scantype, int *infected, int *error |
447 | 447 |
return 0; |
448 | 448 |
} |
449 | 449 |
|
450 |
-static int isremote(struct optstruct *clamdopts) { |
|
451 |
- int s, ret; |
|
452 |
- const struct optstruct *opt; |
|
453 |
- struct hostent *he; |
|
450 |
+int get_clamd_version(const struct optstruct *opts) |
|
451 |
+{ |
|
452 |
+ char *buff; |
|
453 |
+ int len, sockd; |
|
454 |
+ struct RCVLN rcv; |
|
454 | 455 |
|
455 |
- if(optget(clamdopts, "LocalSocket")->enabled) { |
|
456 |
- memset((void *)&nixsock, 0, sizeof(nixsock)); |
|
457 |
- nixsock.sun_family = AF_UNIX; |
|
458 |
- strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); |
|
459 |
- nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; |
|
460 |
- mainsa = (struct sockaddr *)&nixsock; |
|
461 |
- mainsasz = sizeof(nixsock); |
|
462 |
- return 0; |
|
456 |
+ recvlninit(&rcv, sockd); |
|
457 |
+ isremote(opts); |
|
458 |
+ if(!mainsa) return 2; |
|
459 |
+ if((sockd = dconnect()) < 0) return 2; |
|
460 |
+ |
|
461 |
+ if(sendln(sockd, "zVERSION", 9)) { |
|
462 |
+ logg("!Can't write to the socket.\n"); |
|
463 |
+ close(sockd); |
|
464 |
+ return 2; |
|
463 | 465 |
} |
464 |
- if(!(opt = optget(clamdopts, "TCPSocket"))->enabled) return 0; |
|
465 |
- mainsa = (struct sockaddr *)&tcpsock; |
|
466 |
- mainsasz = sizeof(tcpsock); |
|
467 |
- memset((void *)&tcpsock, 0, sizeof(tcpsock)); |
|
468 |
- memset((void *)&strmsock, 0, sizeof(strmsock)); |
|
469 |
- tcpsock.sin_family = strmsock.sin_family = AF_INET; |
|
470 |
- tcpsock.sin_port = htons(opt->numarg); |
|
471 |
- if(!(opt = optget(clamdopts, "TCPAddr"))->enabled) { |
|
472 |
- tcpsock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
473 |
- return 0; |
|
466 |
+ |
|
467 |
+ while((len = recvln(&rcv, &buff, NULL))) { |
|
468 |
+ if(len == -1) { |
|
469 |
+ logg("!Error occoured while receiving version information.\n"); |
|
470 |
+ break; |
|
471 |
+ } |
|
472 |
+ printf("%s\n", buff); |
|
474 | 473 |
} |
475 |
- if(!(he = gethostbyname(opt->strarg))) { |
|
476 |
- perror("gethostbyname()"); |
|
477 |
- logg("!Can't lookup clamd hostname.\n"); |
|
478 |
- mainsa = NULL; |
|
479 |
- return 0; |
|
474 |
+ |
|
475 |
+ close(sockd); |
|
476 |
+ return 0; |
|
477 |
+} |
|
478 |
+ |
|
479 |
+int reload_clamd_database(const struct optstruct *opts) |
|
480 |
+{ |
|
481 |
+ char *buff; |
|
482 |
+ int len, sockd; |
|
483 |
+ struct RCVLN rcv; |
|
484 |
+ |
|
485 |
+ recvlninit(&rcv, sockd); |
|
486 |
+ isremote(opts); |
|
487 |
+ if(!mainsa) return 2; |
|
488 |
+ if((sockd = dconnect()) < 0) return 2; |
|
489 |
+ |
|
490 |
+ if(sendln(sockd, "zRELOAD", 8)) { |
|
491 |
+ logg("!Can't write to the socket.\n"); |
|
492 |
+ close(sockd); |
|
493 |
+ return 2; |
|
480 | 494 |
} |
481 |
- strmsock.sin_port = htons(INADDR_ANY); |
|
482 |
- tcpsock.sin_addr = strmsock.sin_addr = *(struct in_addr *) he->h_addr_list[0]; |
|
483 |
- if(!(s = socket(tcpsock.sin_family, SOCK_STREAM, 0))) return 0; |
|
484 |
- ret = (bind(s, (struct sockaddr *)&strmsock, sizeof(strmsock)) != 0); |
|
485 |
- close(s); |
|
486 |
- return ret; |
|
495 |
+ |
|
496 |
+ if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) { |
|
497 |
+ logg("!Incorrect reply from clamd\n"); |
|
498 |
+ close(sockd); |
|
499 |
+ return 2; |
|
500 |
+ } |
|
501 |
+ |
|
502 |
+ close(sockd); |
|
503 |
+ return 0; |
|
487 | 504 |
} |
488 | 505 |
|
489 | 506 |
int client(const struct optstruct *opts, int *infected) |
490 | 507 |
{ |
491 |
- int errors = 0; |
|
492 | 508 |
const char *clamd_conf = optget(opts, "config-file")->strarg; |
493 | 509 |
struct optstruct *clamdopts; |
494 |
- int scantype, session = 0; |
|
510 |
+ int scantype, session = 0, errors = 0, scandash = 0; |
|
495 | 511 |
|
496 | 512 |
if((clamdopts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { |
497 | 513 |
logg("!Can't parse clamd configuration file %s\n", clamd_conf); |
498 | 514 |
return 2; |
499 | 515 |
} |
500 | 516 |
|
501 |
- /* FIXME: save the connection method once for all */ |
|
502 |
- if(isremote(clamdopts)) { |
|
517 |
+ scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !opts->filename[1]); |
|
518 |
+ if(isremote(opts)) { |
|
503 | 519 |
scantype = STREAM; |
504 | 520 |
session = optget(opts, "multiscan")->enabled; |
505 | 521 |
#ifdef HAVE_FD_PASSING |
506 |
- } else if(optget(clamdopts, "LocalSocket")->enabled && optget(opts, "fdpass")->enabled) { |
|
522 |
+ } else if(optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) { |
|
507 | 523 |
scantype = FILDES; |
508 | 524 |
session = optget(opts, "multiscan")->enabled; |
525 |
+ scandash <<= 1; |
|
509 | 526 |
#endif |
510 | 527 |
} else if(optget(opts, "multiscan")->enabled) scantype = MULTI; |
511 | 528 |
else scantype = CONT; |
... | ... |
@@ -519,9 +538,20 @@ int client(const struct optstruct *opts, int *infected) |
519 | 519 |
|
520 | 520 |
*infected = 0; |
521 | 521 |
|
522 |
- if(opts->filename) { |
|
522 |
+ if(scandash == 2) { |
|
523 |
+ int sockd, ret; |
|
524 |
+ if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, FILDES, NULL)) >= 0) |
|
525 |
+ *infected += ret; |
|
526 |
+ else |
|
527 |
+ errors++; |
|
528 |
+ close(sockd); |
|
529 |
+ } else if(opts->filename) { |
|
523 | 530 |
unsigned int i; |
524 | 531 |
for (i = 0; opts->filename[i]; i++) { |
532 |
+ if(!strcmp(opts->filename[i], "-")) { |
|
533 |
+ logg("!Standard input scan requires FD passing support and \"-\" must be the only file argument\n"); |
|
534 |
+ continue; |
|
535 |
+ } |
|
525 | 536 |
client_scan(opts->filename[i], scantype, infected, &errors); |
526 | 537 |
} |
527 | 538 |
} else { |