Beispiel #1
0
/* FTW callback for scanning in non IDSESSION mode
 * Returns SUCCESS or BREAK on success, CL_EXXX on error */
static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
    struct client_serial_data *c = (struct client_serial_data *)data->data;
    int sockd, ret;
    const char *f = filename;

    UNUSEDPARAM(sb);

    if(chkpath(path))
	return CL_SUCCESS;
    c->files++;
    switch(reason) {
    case error_stat:
	logg("!Can't access file %s\n", path);
	c->errors++;
	return CL_SUCCESS;
    case error_mem:
	logg("!Memory allocation failed in ftw\n");
	c->errors++;
	return CL_EMEM;
    case warning_skipped_dir:
	logg("^Directory recursion limit reached\n");
    case warning_skipped_link:
	return CL_SUCCESS;
    case warning_skipped_special:
	logg("^%s: Not supported file type\n", path);
	c->errors++;
	return CL_SUCCESS;
    case visit_directory_toplev:
	if(c->scantype >= STREAM)
	    return CL_SUCCESS;
	f = path;
	filename = NULL;
    case visit_file:
	break;
    }

    if((sockd = dconnect()) < 0) {
	if(filename) free(filename);
	c->errors++;
	return CL_EOPEN;
    }
    ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors);
    if(filename) free(filename);
    closesocket(sockd);
    if(ret < 0) {
	c->errors++;
	return CL_EOPEN;
    }
    c->infected += ret;
    if(reason == visit_directory_toplev)
	return CL_BREAK;
    return CL_SUCCESS;
}
Beispiel #2
0
/* Submitted by Richard Lyons <frob-clamav*webcentral.com.au> */
int dsfd(int sockfd, int fd, const struct optstruct *opt)
{
	struct iovec iov[1];
	struct msghdr msg;
#ifdef HAVE_CONTROL_IN_MSGHDR
#ifndef CMSG_SPACE
#define CMSG_SPACE(len)	    (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
#endif
#ifndef CMSG_LEN
#define CMSG_LEN(len)	    (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
	struct cmsghdr *cmsg;
	char tmp[CMSG_SPACE(sizeof(fd))];
#endif

    iov[0].iov_base = "";
    iov[0].iov_len = 1;
    memset(&msg, 0, sizeof(msg));
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;
#ifdef HAVE_CONTROL_IN_MSGHDR
    msg.msg_control = tmp;
    msg.msg_controllen = sizeof(tmp);
    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
    *(int *)CMSG_DATA(cmsg) = fd;
#endif
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof(fd);
#endif
    if (sendmsg(sockfd, &msg, 0) != iov[0].iov_len) {
	mprintf("@Can't write to the socket.\n");
	return -1;
    }
    return dsresult(sockfd, opt);
}
Beispiel #3
0
int client(const struct optstruct *opts, int *infected, int *err)
{
	int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
	const char *fname;

    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
    remote = isremote(opts) | optget(opts, "stream")->enabled;
#ifdef HAVE_FD_PASSING
    if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
	scantype = FILDES;
	session = optget(opts, "multiscan")->enabled;
    } else 
#endif
    if(remote || scandash) {
	scantype = STREAM;
	session = optget(opts, "multiscan")->enabled;
    } 
    else if(optget(opts, "multiscan")->enabled) scantype = MULTI;
    else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH;
    else scantype = CONT;

    maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
    maxstream = optget(clamdopts, "StreamMaxLength")->numarg;
    if (optget(clamdopts, "FollowDirectorySymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
    if (optget(clamdopts, "FollowFileSymlinks")->enabled)
	flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
    flags |= CLI_FTW_TRIM_SLASHES;

    *infected = 0;

    if(scandash) {
	int sockd, ret;
	STATBUF sb;
	if(FSTAT(0, &sb) < 0) {
	    logg("client.c: fstat failed for file name \"%s\", with %s\n.", 
		 opts->filename[0], strerror(errno));
	    return 2;
	}
	if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
	if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
	    *infected = ret;
	else
	    errors = 1;
	if(sockd >= 0) closesocket(sockd);
    } else if(opts->filename || optget(opts, "file-list")->enabled) {
	if(opts->filename && optget(opts, "file-list")->enabled)
	    logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");

	while((fname = filelist(opts, NULL))) {
	    if(!strcmp(fname, "-")) {
		logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
		continue;
	    }
	    errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
	    /* this may be too strict
	    if(errors >= 10) {
		logg("!Too many errors\n");
		break;
	    }
	    */
	}
    } else {
	errors = client_scan("", scantype, infected, err, maxrec, session, flags);
    }
    return *infected ? 1 : (errors ? 2 : 0);
}
Beispiel #4
0
int dsresult(int sockd, const struct optstruct *opt)
{
	int infected = 0, waserror = 0;
	char buff[4096], *pt;
	FILE *fd;


#ifndef C_OS2
    if((fd = fdopen(dup(sockd), "r")) == NULL) {
#else /* FIXME: accoriding to YD OS/2 does not support dup() for sockets */
    if((fd = fdopen(sockd, "r")) == NULL) {
#endif
	mprintf("@Can't open descriptor for reading.\n");
	return -1;
    }

    while(fgets(buff, sizeof(buff), fd)) {
	if(strstr(buff, "FOUND\n")) {
	    infected++;
	    logg("%s", buff);
	    mprintf("%s", buff);
	    if(optl(opt, "move")) {
		/* filename: Virus FOUND */
		if((pt = strrchr(buff, ':'))) {
		    *pt = 0;
		    move_infected(buff, opt);
		} else {
		    mprintf("@Broken data format. File not moved.\n");
		}

	    } else if(optl(opt, "remove")) {
		if(!(pt = strrchr(buff, ':'))) {
		    mprintf("@Broken data format. File not removed.\n");
		} else {
		    *pt = 0;
		    if(unlink(buff)) {
			mprintf("%s: Can't remove.\n", buff);
			logg("%s: Can't remove.\n", buff);
			notremoved++;
		    } else {
			mprintf("%s: Removed.\n", buff);
			logg("%s: Removed.\n", buff);
		    }
		}
	    }
	}

	if(strstr(buff, "ERROR\n")) {
	    logg("%s", buff);
	    mprintf("%s", buff);
	    waserror = 1;
	}
    }

#ifndef C_OS2 /* Small memory leak under OS/2 (see above) */
    fclose(fd);
#endif

    return infected ? infected : (waserror ? -1 : 0);
}

int dsfile(int sockd, const char *filename, const struct optstruct *opt)
{
	int ret;
	char *scancmd;


    scancmd = mcalloc(strlen(filename) + 20, sizeof(char));
    sprintf(scancmd, "CONTSCAN %s", filename);

    if(write(sockd, scancmd, strlen(scancmd)) <= 0) {
	mprintf("@Can't write to the socket.\n");
	free(scancmd);
	return -1;
    }

    free(scancmd);

    ret = dsresult(sockd, opt);

    if(!ret)
	mprintf("%s: OK\n", filename);

    return ret;
}