47
50
#include "client.h"
50
# define SOCKET_INET PF_INET
52
# define SOCKET_INET AF_INET
55
/* #define ENABLE_FD_PASSING FIXME: Doesn't work yet */
51
#include "clamd_fdscan.h"
53
#define SOCKET_INET AF_INET
57
55
void move_infected(const char *filename, const struct optstruct *opt);
58
56
int notremoved = 0, notmoved = 0;
57
int printinfected = 0;
60
59
static int dsresult(int sockd, const struct optstruct *opt)
84
83
move_infected(buff, opt);
86
mprintf("@Broken data format. File not %s.\n", opt_check(opt, "move") ? "moved" : "copied");
85
logg("!Incorrect output from clamd. File not %s.\n", opt_check(opt, "move") ? "moved" : "copied");
89
88
} else if(opt_check(opt, "remove")) {
90
89
if(!(pt = strrchr(buff, ':'))) {
91
mprintf("@Broken data format. File not removed.\n");
90
logg("!Incorrect output from clamd. File not removed.\n");
95
mprintf("~%s: Can't remove.\n", buff);
96
logg("~%s: Can't remove.\n", buff);
94
logg("!%s: Can't remove.\n", buff);
99
mprintf("~%s: Removed.\n", buff);
100
97
logg("~%s: Removed.\n", buff);
136
133
ret = dsresult(sockd, opt);
135
if(!ret && !printinfected)
139
136
logg("~%s: OK\n", filename);
144
#if defined(ENABLE_FD_PASSING) && defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN)
146
/* Submitted by Richard Lyons <frob-clamav*webcentral.com.au> */
147
static int dsfd(int sockfd, int fd, const struct optstruct *opt)
151
#ifdef HAVE_CONTROL_IN_MSGHDR
153
#define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
156
#define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
158
struct cmsghdr *cmsg;
159
char tmp[CMSG_SPACE(sizeof(fd))];
162
iov[0].iov_base = "";
164
memset(&msg, 0, sizeof(msg));
167
#ifdef HAVE_CONTROL_IN_MSGHDR
168
msg.msg_control = tmp;
169
msg.msg_controllen = sizeof(tmp);
170
cmsg = CMSG_FIRSTHDR(&msg);
171
cmsg->cmsg_level = SOL_SOCKET;
172
cmsg->cmsg_type = SCM_RIGHTS;
173
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
174
*(int *)CMSG_DATA(cmsg) = fd;
176
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
177
msg.msg_accrights = (caddr_t)&fd;
178
msg.msg_accrightslen = sizeof(fd);
180
if (sendmsg(sockfd, &msg, 0) != iov[0].iov_len) {
181
logg("^Can't write to the socket.\n");
184
return dsresult(sockfd, opt);
188
141
static int dsstream(int sockd, const struct optstruct *opt)
190
143
int wsockd, loopw = 60, bread, port, infected = 0;
235
#define PATH_MAX 1024
281
238
static char *abpath(const char *filename)
284
char *fullpath, cwd[200];
241
char *fullpath, cwd[PATH_MAX + 1];
286
243
if(stat(filename, &foo) == -1) {
287
244
logg("^Can't access file %s\n", filename);
288
245
perror(filename);
291
fullpath = malloc(200 + strlen(filename) + 10);
293
sprintf(fullpath, "%s", filename);
295
if(!getcwd(cwd, 200)) {
248
fullpath = malloc(PATH_MAX + strlen(filename) + 10);
249
if(!getcwd(cwd, PATH_MAX)) {
296
250
logg("^Can't get absolute pathname of current working directory.\n");
299
253
sprintf(fullpath, "%s/%s", cwd, filename);
306
static int dconnect(const struct optstruct *opt)
259
static int dconnect(const struct optstruct *opt, int *is_unix)
308
261
struct sockaddr_un server;
309
262
struct sockaddr_in server2;
333
287
server.sun_family = AF_UNIX;
334
288
strncpy(server.sun_path, cpt->strarg, sizeof(server.sun_path));
289
server.sun_path[sizeof(server.sun_path)-1]='\0';
336
291
if((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
337
292
perror("socket()");
349
int get_clamd_version(const struct optstruct *opt)
355
if((sockd = dconnect(opt, NULL)) < 0)
358
if(write(sockd, "VERSION", 7) <= 0) {
359
logg("^Can't write to the socket.\n");
364
while((bread = read(sockd, buff, sizeof(buff)-1)) > 0) {
366
printf("%s\n", buff);
373
int reload_clamd_database(const struct optstruct *opt)
379
if((sockd = dconnect(opt, NULL)) < 0)
382
if(write(sockd, "RELOAD", 6) <= 0) {
383
logg("!Can't write to the socket.\n");
388
bread = read(sockd, buff, sizeof(buff) - 1);
389
if(bread == -1 || strncmp(buff, "RELOADING", 9)) {
390
logg("!Incorrect reply from clamd\n");
393
399
int client(const struct optstruct *opt, int *infected)
395
char cwd[200], *fullpath;
401
char cwd[PATH_MAX+1], *fullpath;
396
402
int sockd, ret, errors = 0;
398
404
const char *scantype = "CONTSCAN";
406
412
/* parse argument list */
407
413
if(opt->filename == NULL || strlen(opt->filename) == 0) {
408
414
/* scan current directory */
409
if(!getcwd(cwd, 200)) {
415
if(!getcwd(cwd, PATH_MAX)) {
410
416
logg("^Can't get absolute pathname of current working directory.\n");
414
if((sockd = dconnect(opt)) < 0)
420
if((sockd = dconnect(opt, NULL)) < 0)
417
423
if((ret = dsfile(sockd, scantype, cwd, opt)) >= 0)
424
#if defined(ENABLE_FD_PASSING) && defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) && !defined(C_CYGWIN)
425
430
} else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */
426
if((sockd = dconnect(opt)) < 0)
432
if((sockd = dconnect(opt, &is_unix)) < 0)
429
if((ret = dsfd(sockd, 0, opt)) >= 0)
435
if(opt_check(opt,"fdpass")) {
436
#ifndef HAVE_FD_PASSING
437
logg("^File descriptor pass support not compiled in, falling back to stream scan\n");
438
ret = dsstream(sockd, opt);
436
} else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */
437
if((sockd = dconnect(opt)) < 0)
440
if((ret = dsstream(sockd, opt)) >= 0)
441
logg("^File descriptor passing can only work on local (unix) sockets! Falling back to stream scan\n");
442
/* fall back to stream */
443
ret = dsstream(sockd, opt);
446
memset(buff, 0, sizeof(buff));
447
ret = clamd_fdscan(sockd, 0, buff, sizeof(buff));
448
if(ret == 1 || ret == -1)
449
logg("fd: %s%s\n",buff, ret == 1 ? " FOUND" : " ERROR");
450
else if(!printinfected)
455
ret = dsstream(sockd, opt);
469
484
switch(sb.st_mode & S_IFMT) {
472
if((sockd = dconnect(opt)) < 0)
487
if((sockd = dconnect(opt, NULL)) < 0)
475
490
if((ret = dsfile(sockd, scantype, fullpath, opt)) >= 0)