~ubuntu-branches/ubuntu/raring/clamav/raring

« back to all changes in this revision

Viewing changes to clamd/others.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Gran
  • Date: 2008-09-05 17:25:34 UTC
  • mfrom: (0.35.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080905172534-yi3f8fkye1o7u1r3
* New upstream version (closes: #497662, #497773)
  - lots of new options for clamd.conf
  - fixes CVEs CVE-2008-3912, CVE-2008-3913, CVE-2008-3914, and
    CVE-2008-1389
* No longer supports --unzip option, so typo is gone (closes: #496276)
* Translations:
  - sv (thanks Martin Bagge <brother@bsnet.se>) (closes: #491760)

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
#ifdef HAVE_SYS_FILIO_H
56
56
#include <sys/filio.h>
57
57
#endif
58
 
#ifdef HAVE_SYS_UIO_H
59
 
#include <sys/uio.h>
60
 
#endif
61
58
 
62
59
/* submitted by breiter@wolfereiter.com: do not use poll(2) on Interix */
63
60
#ifdef C_INTERIX
93
90
}
94
91
 
95
92
#else
96
 
 
97
93
void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt)
98
94
{
99
95
        pid_t pid;
100
96
        const struct cfgstruct *cpt;
101
 
 
102
 
    if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
103
 
        return;
104
 
 
105
 
    /* NB: we need to fork here since this function modifies the environment. 
106
 
       (Modifications to the env. are not reentrant, but we need to be.) */
107
 
    pid = fork();
108
 
 
109
 
    if ( pid == 0 ) {
110
 
        /* child... */
111
 
        char *buffer, *pt, *cmd;
 
97
        char *buffer, *pt, *cmd, *buffer_file, *buffer_vir;
 
98
        size_t j;
 
99
        char *env[4];
 
100
 
 
101
        if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
 
102
                return;
 
103
 
 
104
        env[0] = getenv("PATH");
 
105
        j = env[0] ? 1 : 0;
 
106
        /* Allocate env vars.. to be portable env vars should not be freed */
 
107
        buffer_file = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
 
108
        if(buffer_file) {
 
109
                sprintf(buffer_file, "%s=%s", ENV_FILE, filename);
 
110
                env[j++] = buffer_file;
 
111
        }
 
112
 
 
113
        buffer_vir = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
 
114
        if(buffer_vir) {
 
115
                sprintf(buffer_vir, "%s=%s", ENV_VIRUS, virname);
 
116
                env[j++] = buffer_vir;
 
117
        }
 
118
        env[j++] = NULL;
112
119
 
113
120
        cmd = strdup(cpt->strarg);
114
121
 
115
 
        if((pt = strstr(cmd, "%v"))) {
116
 
            buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
117
 
            *pt = 0; pt += 2;
118
 
            strcpy(buffer, cmd);
119
 
            strcat(buffer, virname);
120
 
            strcat(buffer, pt);
121
 
            free(cmd);
122
 
            cmd = strdup(buffer);
123
 
            free(buffer);
124
 
        }
125
 
 
126
 
        /* Allocate env vars.. to be portable env vars should not be freed */
127
 
        buffer = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
128
 
        sprintf(buffer, "%s=%s", ENV_FILE, filename);
129
 
        putenv(buffer);
130
 
 
131
 
        buffer = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
132
 
        sprintf(buffer, "%s=%s", ENV_VIRUS, virname);
133
 
        putenv(buffer);
134
 
 
135
 
        /* WARNING: this is uninterruptable ! */
136
 
        exit(system(cmd));
137
 
 
138
 
        /* The below is not reached but is here for completeness to remind
139
 
           maintainers that this buffer is still allocated.. */
 
122
        if(cmd && (pt = strstr(cmd, "%v"))) {
 
123
                buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
 
124
                if(buffer) {
 
125
                        *pt = 0; pt += 2;
 
126
                        strcpy(buffer, cmd);
 
127
                        strcat(buffer, virname);
 
128
                        strcat(buffer, pt);
 
129
                        free(cmd);
 
130
                        cmd = strdup(buffer);
 
131
                        free(buffer);
 
132
                }
 
133
        }
 
134
 
 
135
        if(!cmd) {
 
136
                free(buffer_file);
 
137
                free(buffer_vir);
 
138
                return;
 
139
        }
 
140
        /* We can only call async-signal-safe functions after fork(). */
 
141
        pid = fork();
 
142
 
 
143
        if ( pid == 0 ) {
 
144
                /* child... */
 
145
                /* WARNING: this is uninterruptable ! */
 
146
                exit(execle("/bin/sh", "sh", "-c", cmd, NULL, env));
 
147
        } else if (pid > 0) {
 
148
                /* parent */
 
149
                waitpid(pid, NULL, 0);
 
150
        } else {
 
151
                /* error.. */
 
152
                logg("!VirusAction: fork failed.\n");
 
153
        }
140
154
        free(cmd);
141
 
    } else if (pid > 0) {
142
 
        /* parent */      
143
 
        waitpid(pid, NULL, 0);
144
 
    } else {
145
 
        /* error.. */
146
 
        logg("!VirusAction: fork failed.\n");
147
 
    }
 
155
        free(buffer_file);
 
156
        free(buffer_vir);
148
157
}
149
158
#endif /* C_WINDOWS */
150
159
 
334
343
/*
335
344
   This procedure does timed clamd command and delimited input processing.  
336
345
   It is complex for several reasons:
337
 
       1) FD commands are delivered on Unix domain sockets via recvnsg() on platforms which can do this.  
338
 
          These command messages are accompanied by a single byte of data which is a NUL character.
339
346
       2) Newline delimited commands are indicated by a command which is prefixed by an 'n' character.  
340
347
          This character serves to indicate that the command will contain a newline which will cause
341
348
          command data to be read until the command input buffer is full or a newline is encountered.
347
354
*/
348
355
int readsock(int sockfd, char *buf, size_t size, unsigned char delim, int timeout_sec, int force_delim, int read_command)
349
356
{
350
 
        int fd;
351
357
        ssize_t n;
352
358
        size_t boff = 0;
353
359
        char *pdelim;
354
 
#ifdef HAVE_RECVMSG
355
 
        struct msghdr msg;
356
 
        struct iovec iov[1];
357
 
#endif
358
 
#ifdef HAVE_CONTROL_IN_MSGHDR
359
 
#ifndef CMSG_SPACE
360
 
#define CMSG_SPACE(len)     (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
361
 
#endif
362
 
#ifndef CMSG_LEN
363
 
#define CMSG_LEN(len)       (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
364
 
#endif
365
 
        struct cmsghdr *cmsg;
366
 
        char tmp[CMSG_SPACE(sizeof(fd))];
367
 
#endif
368
360
        time_t starttime, timenow;
369
361
 
370
362
    time(&starttime);
384
376
    if(n < 0)
385
377
        return -1;
386
378
    if(read_command) {
387
 
        if((n >= 1) && (buf[0] == 0)) { /* FD message */
388
 
#ifdef HAVE_RECVMSG
389
 
            iov[0].iov_base = buf;
390
 
            iov[0].iov_len = size;
391
 
            memset(&msg, 0, sizeof(msg));
392
 
            msg.msg_iov = iov;
393
 
            msg.msg_iovlen = 1;
394
 
#endif
395
 
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
396
 
            msg.msg_accrights = (caddr_t)&fd;
397
 
            msg.msg_accrightslen = sizeof(fd);
398
 
#endif
399
 
#ifdef HAVE_CONTROL_IN_MSGHDR
400
 
            msg.msg_control = tmp;
401
 
            msg.msg_controllen = sizeof(tmp);
402
 
#endif
403
 
#if defined(HAVE_RECVMSG) && !defined(C_OS2) && !defined(INCOMPLETE_CMSG)
404
 
            n = recvmsg(sockfd, &msg, 0);
405
 
#else
406
 
            n = recv(sockfd, buf, size, 0);
407
 
#endif
408
 
            if (n <= 0)
409
 
                return n;
410
 
            errno = EBADF;
411
 
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
412
 
            if(msg.msg_accrightslen != sizeof(fd))
413
 
                return -1;
414
 
#endif
415
 
#ifdef HAVE_CONTROL_IN_MSGHDR
416
 
            cmsg = CMSG_FIRSTHDR(&msg);
417
 
            if(cmsg == NULL)
418
 
                return -1;
419
 
            if(cmsg->cmsg_type != SCM_RIGHTS)
420
 
                return -1;
421
 
            if(cmsg->cmsg_len != CMSG_LEN(sizeof(fd)))
422
 
                return -1;
423
 
            fd = *(int *)CMSG_DATA(cmsg);
424
 
#endif
425
 
            if(fd < 0)
426
 
                return -1;
427
 
            n = snprintf(buf, size, "FD %d", fd);
428
 
            if((size_t) n >= size)
429
 
                return -1;
430
 
            return n;
431
 
        }
432
379
        if((n >= 1) && (buf[0] == 'n')) { /* Newline delimited command */
433
380
            force_delim = 1;
434
381
            delim = '\n';