예제 #1
0
int get_clamd_version(const struct optstruct *opts)
{
	char *buff;
	int len, sockd;
	struct RCVLN rcv;

    isremote(opts);
    if((sockd = dconnect()) < 0) return 2;
    recvlninit(&rcv, sockd);

    if(sendln(sockd, "zVERSION", 9)) {
	closesocket(sockd);
	return 2;
    }

    while((len = recvln(&rcv, &buff, NULL))) {
	if(len == -1) {
	    logg("!Error occoured while receiving version information.\n");
	    break;
	}
	printf("%s\n", buff);
    }

    closesocket(sockd);
    return 0;
}
예제 #2
0
/* Sends a proper scan request to clamd and parses its replies
 * This is used only in IDSESSION mode
 * Returns 0 on success, 1 on hard failures, 2 on len == 0 (bb#1717) */
static int dspresult(struct client_parallel_data *c) {
    const char *filename;
    char *bol, *eol;
    unsigned int rid;
    int len;
    struct SCANID **id = NULL;
    struct RCVLN rcv;

    recvlninit(&rcv, c->sockd);
    do {
	len = recvln(&rcv, &bol, &eol);
	if(len < 0) return 1;
	if(!len) return 2;
	if((rid = atoi(bol))) {
	    id = &c->ids;
	    while(*id) {
		if((*id)->id == rid) break;
		id = &((*id)->next);
	    }
	    if(!*id) id = NULL;
	}
	if(!id) {
	    logg("!Bogus session id from clamd\n");
	    return 1;
	}
	filename = (*id)->file;
	if(len > 7) {
	    char *colon = strrchr(bol, ':');
	    if(!colon) {
		logg("!Failed to parse reply\n");
		free((void *)filename);
		return 1;
	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
		c->infected++;
		c->printok = 0;
		logg("~%s%s\n", filename, colon);
		if(action) action(filename);
	    } else if(!memcmp(eol-7, " ERROR", 6)) {
		c->errors++;
		c->printok = 0;
		logg("~%s%s\n", filename, colon);
	    }
	}
	free((void *)filename);
	bol = (char *)*id;
	*id = (*id)->next;
	free(bol);
    } while(rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume
				    more data can be recv()'d with close to zero latency */
    return 0;
}
예제 #3
0
int reload_clamd_database(const struct optstruct *opts)
{
	char *buff;
	int len, sockd;
	struct RCVLN rcv;

    isremote(opts);
    if((sockd = dconnect()) < 0) return 2;
    recvlninit(&rcv, sockd);

    if(sendln(sockd, "zRELOAD", 8)) {
	closesocket(sockd);
	return 2;
    }

    if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) {
	logg("!Clamd did not reload the database\n");
	closesocket(sockd);
	return 2;
    }
    closesocket(sockd);
    return 0;
}
예제 #4
0
/* Sends a proper scan request to clamd and parses its replies
 * This is used only in non IDSESSION mode
 * Returns the number of infected files or -1 on error
 * NOTE: filename may be NULL for STREAM scantype. */
int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) {
    int infected = 0, len = 0, beenthere = 0;
    char *bol, *eol;
    struct RCVLN rcv;
    STATBUF sb;

    if(filename && chkpath(filename))
	return 0;
    recvlninit(&rcv, sockd);

    switch(scantype) {
    case MULTI:
    case CONT:
    case ALLMATCH:
    if (!filename) {
	logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
	return -1;
    }
    len = strlen(filename) + strlen(scancmd[scantype]) + 3;
    if (!(bol = malloc(len))) {
	logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
	return -1;
    }
    sprintf(bol, "z%s %s", scancmd[scantype], filename);
    if(sendln(sockd, bol, len)) {
	free(bol);
	return -1;
    }
    free(bol);
    break;

    case STREAM:
        /* NULL filename safe in send_stream() */
	len = send_stream(sockd, filename);
	break;
#ifdef HAVE_FD_PASSING
    case FILDES:
        /* NULL filename safe in send_fdpass() */
	len = send_fdpass(sockd, filename);
	break;
#endif
    }

    if(len <=0) {
	*printok = 0;
	if(errors)
	    (*errors)++;
	return len;
    }

    while((len = recvln(&rcv, &bol, &eol))) {
	if(len == -1) return -1;
	beenthere = 1;
	if(!filename) logg("~%s\n", bol);
	if(len > 7) {
	    char *colon = strrchr(bol, ':');
	    if(colon && colon[1] != ' ') {
		char *br;
		*colon = 0;
		br = strrchr(bol, '(');
		if(br)
		    *br = 0;
		colon = strrchr(bol, ':');
	    }
	    if(!colon) {
		char * unkco = "UNKNOWN COMMAND";
		if (!strncmp(bol, unkco, sizeof(unkco) - 1))
		    logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", 
			 (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" :
			                                             scancmd[scantype]);
		else
		    logg("Failed to parse reply: \"%s\"\n", bol);
		return -1;
	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
		*(eol - 7) = 0;
		*printok = 0;
		infected++;
		if(filename) {
		    if(scantype >= STREAM) {
			logg("~%s%s FOUND\n", filename, colon);
			if(action) action(filename);
		    } else {
			logg("~%s FOUND\n", bol);
			*colon = '\0';
			if(action)
			    action(bol);
		    }
		}
	    } else if(!memcmp(eol-7, " ERROR", 6)) {
		if(errors)
		    (*errors)++;
		*printok = 0;
		if(filename) {
		    if(scantype >= STREAM)
			logg("~%s%s\n", filename, colon);
		    else
			logg("~%s\n", bol);
		}
	    }
	}
    }
    if(!beenthere) {
        if (!filename) {
	    logg("STDIN: noreply from clamd\n.");
	    return -1;
	}
        if(CLAMSTAT(filename, &sb) == -1) {
	    logg("~%s: stat() failed with %s, clamd may not be responding\n",
		 filename, strerror(errno));
	    return -1;
	}
	if(!S_ISDIR(sb.st_mode)) {
	    logg("~%s: no reply from clamd\n", filename);
	    return -1;
	}
    }
    return infected;
}
예제 #5
0
파일: proto.c 프로젝트: OPSF/uClinux
/* Sends a proper scan request to clamd and parses its replies
 * This is used only in non IDSESSION mode
 * Returns the number of infected files or -1 on error */
int dsresult(int sockd, int scantype, const char *filename, int *printok) {
    int infected = 0, len, beenthere = 0;
    char *bol, *eol;
    struct RCVLN rcv;

    recvlninit(&rcv, sockd);

    switch(scantype) {
    case MULTI:
    case CONT:
        len = strlen(filename) + strlen(scancmd[scantype]) + 3;
        if (!(bol = malloc(len))) {
            logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
            return -1;
        }
        sprintf(bol, "z%s %s", scancmd[scantype], filename);
        if(sendln(sockd, bol, len)) return -1;
        free(bol);
        break;

    case STREAM:
        len = send_stream(sockd, filename);
        break;
#ifdef HAVE_FD_PASSING
    case FILDES:
        len = send_fdpass(sockd, filename);
        break;
#endif
    }

    if(len <=0) {
        *printok = 0;
        return len;
    }

    while((len = recvln(&rcv, &bol, &eol))) {
        if(len == -1) return -1;
        beenthere = 1;
        if(!filename) logg("~%s\n", bol);
        if(len > 7) {
            char *colon = strrchr(bol, ':');
            if(!colon) {
                logg("Failed to parse reply\n");
                return -1;
            } else if(!memcmp(eol - 7, " FOUND", 6)) {
                *printok = 0;
                infected++;
                if(filename) {
                    if(scantype >= STREAM) {
                        logg("~%s%s\n", filename, colon);
                        if(action) action(filename);
                    } else {
                        logg("~%s\n", bol);
                        *colon = '\0';
                        if(action)
                            action(bol);
                    }
                }
            } else if(!memcmp(eol-7, " ERROR", 6)) {
                *printok = 0;
                if(filename) {
                    if(scantype >= STREAM)
                        logg("~%s%s\n", filename, colon);
                    else
                        logg("~%s\n", bol);
                }
            }
        }
    }
    if(!beenthere) {
        logg("~%s: no reply from clamd\n", filename ? filename : "STDIN");
        return -1;
    }
    return infected;
}