~ubuntu-branches/ubuntu/precise/clamav/precise-updates

« back to all changes in this revision

Viewing changes to .pc/0002-Add-an-additional-n-after-the-number-in-the-pidfile.patch/clamd/server-th.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-01-30 09:01:52 UTC
  • mfrom: (118.1.5 precise-security)
  • Revision ID: package-import@ubuntu.com-20150130090152-es6oz6eg0wsa4r40
Tags: 0.98.6+dfsg-0ubuntu0.12.04.1
* Updated to 0.98.6 to fix security issues, including CVE-2014-9328.
* Removed upstreamed patches:
  - d/p/0002-Add-an-additional-n-after-the-number-in-the-pidfile.patch
  - d/p/0017-Bump-.so-version-number.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
3
 
 *
4
 
 *  Authors: Tomasz Kojm, Trog, Török Edvin
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 
 *  MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#if HAVE_CONFIG_H
23
 
#include "clamav-config.h"
24
 
#endif
25
 
 
26
 
#include <pthread.h>
27
 
#include <errno.h>
28
 
#include <signal.h>
29
 
#include <stdio.h>
30
 
#include <string.h>
31
 
#include <time.h>
32
 
#include <sys/types.h>
33
 
#ifndef _WIN32
34
 
#include <sys/socket.h>
35
 
#include <sys/time.h>
36
 
#include <sys/resource.h>
37
 
#include <arpa/inet.h>
38
 
#endif
39
 
#ifdef  HAVE_UNISTD_H
40
 
#include <unistd.h>
41
 
#endif
42
 
 
43
 
#include <fcntl.h>
44
 
#ifdef C_SOLARIS
45
 
#include <stdio_ext.h>
46
 
#endif
47
 
#include "libclamav/clamav.h"
48
 
 
49
 
#include "shared/output.h"
50
 
#include "shared/optparser.h"
51
 
 
52
 
#include "fan.h"
53
 
#include "server.h"
54
 
#include "thrmgr.h"
55
 
#include "session.h"
56
 
#include "others.h"
57
 
#include "shared.h"
58
 
#include "libclamav/others.h"
59
 
#include "libclamav/readdb.h"
60
 
#include "libclamav/cltypes.h"
61
 
 
62
 
#define BUFFSIZE 1024
63
 
 
64
 
int progexit = 0;
65
 
pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
66
 
int reload = 0;
67
 
time_t reloaded_time = 0;
68
 
pthread_mutex_t reload_mutex = PTHREAD_MUTEX_INITIALIZER;
69
 
int sighup = 0;
70
 
extern pthread_mutex_t logg_mutex;
71
 
static struct cl_stat dbstat;
72
 
 
73
 
void *event_wake_recv = NULL;
74
 
void *event_wake_accept = NULL;
75
 
 
76
 
static void scanner_thread(void *arg)
77
 
{
78
 
        client_conn_t *conn = (client_conn_t *) arg;
79
 
#ifndef _WIN32
80
 
        sigset_t sigset;
81
 
#endif
82
 
        int ret;
83
 
        int virus=0, errors = 0;
84
 
 
85
 
#ifndef _WIN32
86
 
    /* ignore all signals */
87
 
    sigfillset(&sigset);
88
 
    /* The behavior of a process is undefined after it ignores a 
89
 
     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
90
 
    sigdelset(&sigset, SIGFPE);
91
 
    sigdelset(&sigset, SIGILL);
92
 
    sigdelset(&sigset, SIGSEGV);
93
 
#ifdef SIGBUS
94
 
    sigdelset(&sigset, SIGBUS);
95
 
#endif
96
 
    sigdelset(&sigset, SIGTSTP);
97
 
    sigdelset(&sigset, SIGCONT);
98
 
    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
99
 
#endif
100
 
 
101
 
    ret = command(conn, &virus);
102
 
    if (ret == -1) {
103
 
        pthread_mutex_lock(&exit_mutex);
104
 
        progexit = 1;
105
 
        pthread_mutex_unlock(&exit_mutex);
106
 
        errors = 1;
107
 
    } else
108
 
        errors = ret;
109
 
 
110
 
    thrmgr_setactiveengine(NULL);
111
 
 
112
 
    if (conn->filename)
113
 
        free(conn->filename);
114
 
    logg("$Finished scanthread\n");
115
 
    if (thrmgr_group_finished(conn->group, virus ? EXIT_OTHER :
116
 
                              errors ? EXIT_ERROR : EXIT_OK)) {
117
 
        logg("$Scanthread: connection shut down (FD %d)\n", conn->sd);
118
 
        /* close connection if we were last in group */
119
 
        shutdown(conn->sd, 2);
120
 
        closesocket(conn->sd);
121
 
    }
122
 
    cl_engine_free(conn->engine);
123
 
    free(conn);
124
 
    return;
125
 
}
126
 
 
127
 
static int syncpipe_wake_recv_w = -1;
128
 
 
129
 
void sighandler_th(int sig)
130
 
{
131
 
    int action = 0;
132
 
    switch(sig) {
133
 
        case SIGINT:
134
 
        case SIGTERM:
135
 
            progexit = 1;
136
 
            action = 1;
137
 
            break;
138
 
 
139
 
#ifdef  SIGHUP
140
 
        case SIGHUP:
141
 
            sighup = 1;
142
 
            action = 1;
143
 
            break;
144
 
#endif
145
 
 
146
 
#ifdef  SIGUSR2
147
 
        case SIGUSR2:
148
 
            reload = 1;
149
 
            action = 1;
150
 
            break;
151
 
#endif
152
 
 
153
 
        default:
154
 
            break; /* Take no action on other signals - e.g. SIGPIPE */
155
 
    }
156
 
    /* a signal doesn't always wake poll(), for example on FreeBSD */
157
 
    if (action && syncpipe_wake_recv_w != -1)
158
 
        if (write(syncpipe_wake_recv_w, "", 1) != 1)
159
 
            logg("$Failed to write to syncpipe\n");
160
 
}
161
 
 
162
 
static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts, int do_check, int *ret)
163
 
{
164
 
        const char *dbdir;
165
 
        int retval;
166
 
        unsigned int sigs = 0;
167
 
        struct cl_settings *settings = NULL;
168
 
 
169
 
    *ret = 0;
170
 
    if(do_check) {
171
 
        if(!dbstat.entries) {
172
 
            logg("No stats for Database check - forcing reload\n");
173
 
            return engine;
174
 
        }
175
 
 
176
 
        if(cl_statchkdir(&dbstat) == 1) {
177
 
            logg("SelfCheck: Database modification detected. Forcing reload.\n");
178
 
            return engine;
179
 
        } else {
180
 
            logg("SelfCheck: Database status OK.\n");
181
 
            return NULL;
182
 
        }
183
 
    }
184
 
 
185
 
    /* release old structure */
186
 
    if(engine) {
187
 
        /* copy current settings */
188
 
        settings = cl_engine_settings_copy(engine);
189
 
        if(!settings)
190
 
            logg("^Can't make a copy of the current engine settings\n");
191
 
 
192
 
        thrmgr_setactiveengine(NULL);
193
 
        cl_engine_free(engine);
194
 
    }
195
 
 
196
 
    dbdir = optget(opts, "DatabaseDirectory")->strarg;
197
 
    logg("Reading databases from %s\n", dbdir);
198
 
 
199
 
    if(dbstat.entries)
200
 
        cl_statfree(&dbstat);
201
 
 
202
 
    memset(&dbstat, 0, sizeof(struct cl_stat));
203
 
    if((retval = cl_statinidir(dbdir, &dbstat))) {
204
 
        logg("!cl_statinidir() failed: %s\n", cl_strerror(retval));
205
 
        *ret = 1;
206
 
        if(settings)
207
 
            cl_engine_settings_free(settings);
208
 
        return NULL;
209
 
    }
210
 
 
211
 
    if(!(engine = cl_engine_new())) {
212
 
        logg("!Can't initialize antivirus engine\n");
213
 
        *ret = 1;
214
 
        if(settings)
215
 
            cl_engine_settings_free(settings);
216
 
        return NULL;
217
 
    }
218
 
 
219
 
    if(settings) {
220
 
        retval = cl_engine_settings_apply(engine, settings);
221
 
        if(retval != CL_SUCCESS) {
222
 
            logg("^Can't apply previous engine settings: %s\n", cl_strerror(retval));
223
 
            logg("^Using default engine settings\n");
224
 
        }
225
 
        cl_engine_settings_free(settings);
226
 
    }
227
 
 
228
 
    if((retval = cl_load(dbdir, engine, &sigs, dboptions))) {
229
 
        logg("!reload db failed: %s\n", cl_strerror(retval));
230
 
        cl_engine_free(engine);
231
 
        *ret = 1;
232
 
        return NULL;
233
 
    }
234
 
 
235
 
    if((retval = cl_engine_compile(engine)) != 0) {
236
 
        logg("!Database initialization error: can't compile engine: %s\n", cl_strerror(retval));
237
 
        cl_engine_free(engine);
238
 
        *ret = 1;
239
 
        return NULL;
240
 
    }
241
 
    logg("Database correctly reloaded (%u signatures)\n", sigs);
242
 
 
243
 
    thrmgr_setactiveengine(engine);
244
 
    return engine;
245
 
}
246
 
 
247
 
/*
248
 
 * zCOMMANDS are delimited by \0
249
 
 * nCOMMANDS are delimited by \n
250
 
 * Old-style non-prefixed commands are one packet, optionally delimited by \n,
251
 
 * with trailing \r|\n ignored
252
 
 */
253
 
static const char *get_cmd(struct fd_buf *buf, size_t off, size_t *len, char *term, int *oldstyle)
254
 
{
255
 
    char *pos;
256
 
    if (!buf->off || off >= buf->off) {
257
 
        *len = 0;
258
 
        return NULL;
259
 
    }
260
 
 
261
 
    *term = '\n';
262
 
    switch (buf->buffer[off]) {
263
 
        /* commands terminated by delimiters */
264
 
        case 'z':
265
 
            *term = '\0';
266
 
        case 'n':
267
 
            pos = memchr(buf->buffer + off, *term, buf->off - off);
268
 
            if (!pos) {
269
 
                /* we don't have another full command yet */
270
 
                *len = 0;
271
 
                return NULL;
272
 
            }
273
 
            *pos = '\0';
274
 
            if (*term) {
275
 
                *len = cli_chomp(buf->buffer + off);
276
 
            } else {
277
 
                *len = pos - buf->buffer - off;
278
 
            }
279
 
            *oldstyle = 0;
280
 
            return buf->buffer + off + 1;
281
 
        default:
282
 
            /* one packet = one command */
283
 
            if (off)
284
 
                return NULL;
285
 
            pos = memchr(buf->buffer, '\n', buf->off);
286
 
            if (pos) {
287
 
                *len = pos - buf->buffer;
288
 
                *pos = '\0';
289
 
            } else {
290
 
                *len = buf->off;
291
 
                buf->buffer[buf->off] = '\0';
292
 
            }
293
 
            cli_chomp(buf->buffer);
294
 
            *oldstyle = 1;
295
 
            return buf->buffer;
296
 
    }
297
 
}
298
 
 
299
 
struct acceptdata {
300
 
    struct fd_data fds;
301
 
    struct fd_data recv_fds;
302
 
    pthread_cond_t cond_nfds;
303
 
    int max_queue;
304
 
    int commandtimeout;
305
 
    int syncpipe_wake_recv[2];
306
 
    int syncpipe_wake_accept[2];
307
 
};
308
 
 
309
 
#define ACCEPTDATA_INIT(mutex1, mutex2) { FDS_INIT(mutex1), FDS_INIT(mutex2), PTHREAD_COND_INITIALIZER, 0, 0, {-1, -1}, {-1, -1}}
310
 
 
311
 
static void *acceptloop_th(void *arg)
312
 
{
313
 
    char buff[BUFFSIZE + 1];
314
 
    size_t i;
315
 
    struct acceptdata *data = (struct acceptdata*)arg;
316
 
    struct fd_data *fds = &data->fds;
317
 
    struct fd_data *recv_fds = &data->recv_fds;
318
 
    int max_queue = data->max_queue;
319
 
    int commandtimeout = data->commandtimeout;
320
 
 
321
 
    pthread_mutex_lock(fds->buf_mutex);
322
 
    for (;;) {
323
 
        /* Block waiting for data to become available for reading */
324
 
        int new_sd = fds_poll_recv(fds, -1, 0, event_wake_accept);
325
 
#ifdef _WIN32
326
 
        ResetEvent(event_wake_accept);
327
 
#endif
328
 
        /* TODO: what about sockets that get rm-ed? */
329
 
        if (!fds->nfds) {
330
 
            /* no more sockets to poll, all gave an error */
331
 
            logg("!Main socket gone: fatal\n");
332
 
            break;
333
 
        }
334
 
 
335
 
        if (new_sd == -1 && errno != EINTR) {
336
 
            logg("!Failed to poll sockets, fatal\n");
337
 
            pthread_mutex_lock(&exit_mutex);
338
 
            progexit = 1;
339
 
            pthread_mutex_unlock(&exit_mutex);
340
 
            break;
341
 
        }
342
 
 
343
 
        /* accept() loop */
344
 
        for (i=0;i < fds->nfds && new_sd >= 0; i++) {
345
 
            struct fd_buf *buf = &fds->buf[i];
346
 
            if (!buf->got_newdata)
347
 
                continue;
348
 
#ifndef _WIN32
349
 
            if (buf->fd == data->syncpipe_wake_accept[0]) {
350
 
                /* dummy sync pipe, just to wake us */
351
 
                if (read(buf->fd, buff, sizeof(buff)) < 0) {
352
 
                    logg("^Syncpipe read failed\n");
353
 
                }
354
 
                continue;
355
 
            }
356
 
#endif
357
 
            if (buf->got_newdata == -1) {
358
 
                logg("$Acceptloop closed FD: %d\n", buf->fd);
359
 
                shutdown(buf->fd, 2);
360
 
                closesocket(buf->fd);
361
 
                buf->fd = -1;
362
 
                continue;
363
 
            }
364
 
 
365
 
            /* don't accept unlimited number of connections, or
366
 
             * we'll run out of file descriptors */
367
 
            pthread_mutex_lock(recv_fds->buf_mutex);
368
 
            while (recv_fds->nfds > (unsigned)max_queue) {
369
 
                pthread_mutex_lock(&exit_mutex);
370
 
                if(progexit) {
371
 
                    pthread_mutex_unlock(&exit_mutex);
372
 
                    break;
373
 
                }
374
 
                pthread_mutex_unlock(&exit_mutex);
375
 
                pthread_cond_wait(&data->cond_nfds, recv_fds->buf_mutex);
376
 
            }
377
 
            pthread_mutex_unlock(recv_fds->buf_mutex);
378
 
 
379
 
            pthread_mutex_lock(&exit_mutex);
380
 
            if(progexit) {
381
 
                pthread_mutex_unlock(&exit_mutex);
382
 
                break;
383
 
            }
384
 
            pthread_mutex_unlock(&exit_mutex);
385
 
 
386
 
            /* listen only socket */
387
 
            new_sd = accept(fds->buf[i].fd, NULL, NULL);
388
 
 
389
 
            if (new_sd >= 0) {
390
 
                int ret, flags;
391
 
#ifdef F_GETFL
392
 
                flags = fcntl(new_sd, F_GETFL, 0);
393
 
                if (flags != -1) {
394
 
                    if (fcntl(new_sd, F_SETFL, flags | O_NONBLOCK) == -1) {
395
 
                        logg("^Can't set socket to nonblocking mode, errno %d\n",
396
 
                             errno);
397
 
                    }
398
 
                } else {
399
 
                        logg("^Can't get socket flags, errno %d\n", errno);
400
 
                }
401
 
#else
402
 
                logg("^Nonblocking sockets not available!\n");
403
 
#endif
404
 
                logg("$Got new connection, FD %d\n", new_sd);
405
 
                pthread_mutex_lock(recv_fds->buf_mutex);
406
 
                ret = fds_add(recv_fds, new_sd, 0, commandtimeout);
407
 
                pthread_mutex_unlock(recv_fds->buf_mutex);
408
 
 
409
 
                if (ret == -1) {
410
 
                    logg("!fds_add failed\n");
411
 
                    closesocket(new_sd);
412
 
                    continue;
413
 
                }
414
 
 
415
 
                /* notify recvloop */
416
 
#ifdef _WIN32
417
 
                SetEvent(event_wake_recv);
418
 
#else
419
 
                if (write(data->syncpipe_wake_recv[1], "", 1) == -1) {
420
 
                    logg("!write syncpipe failed\n");
421
 
                    continue;
422
 
                }
423
 
#endif
424
 
            } else if (errno != EINTR) {
425
 
                /* very bad - need to exit or restart */
426
 
#ifdef HAVE_STRERROR_R
427
 
                strerror_r(errno, buff, BUFFSIZE);
428
 
                logg("!accept() failed: %s\n", buff);
429
 
#else
430
 
                logg("!accept() failed\n");
431
 
#endif
432
 
                /* give the poll loop a chance to close disconnected FDs */
433
 
                break;
434
 
            }
435
 
 
436
 
        }
437
 
 
438
 
        /* handle progexit */
439
 
        pthread_mutex_lock(&exit_mutex);
440
 
        if (progexit) {
441
 
            pthread_mutex_unlock(&exit_mutex);
442
 
            break;
443
 
        }
444
 
        pthread_mutex_unlock(&exit_mutex);
445
 
    }
446
 
    pthread_mutex_unlock(fds->buf_mutex);
447
 
 
448
 
    for (i=0;i < fds->nfds; i++) {
449
 
        if (fds->buf[i].fd == -1)
450
 
            continue;
451
 
        logg("$Shutdown: closed fd %d\n", fds->buf[i].fd);
452
 
        shutdown(fds->buf[i].fd, 2);
453
 
        closesocket(fds->buf[i].fd);
454
 
    }
455
 
    fds_free(fds);
456
 
    pthread_mutex_destroy(fds->buf_mutex);
457
 
    pthread_mutex_lock(&exit_mutex);
458
 
    progexit = 1;
459
 
    pthread_mutex_unlock(&exit_mutex);
460
 
#ifdef _WIN32
461
 
    SetEvent(event_wake_recv);
462
 
#else
463
 
    if (write(data->syncpipe_wake_recv[1], "", 1) < 0) {
464
 
        logg("$Syncpipe write failed\n");
465
 
    }
466
 
#endif
467
 
    return NULL;
468
 
}
469
 
 
470
 
static const char* parse_dispatch_cmd(client_conn_t *conn, struct fd_buf *buf, size_t *ppos, int *error, const struct optstruct *opts, int readtimeout)
471
 
{
472
 
    const char *cmd = NULL;
473
 
    int rc;
474
 
    size_t cmdlen;
475
 
    char term;
476
 
    int oldstyle;
477
 
    size_t pos = *ppos;
478
 
    /* Parse & dispatch commands */
479
 
    while ((conn->mode == MODE_COMMAND) &&
480
 
           (cmd = get_cmd(buf, pos, &cmdlen, &term, &oldstyle)) != NULL) {
481
 
        const char *argument;
482
 
        enum commands cmdtype;
483
 
        if (conn->group && oldstyle) {
484
 
            logg("$Received oldstyle command inside IDSESSION: %s\n", cmd);
485
 
            conn_reply_error(conn, "Only nCMDS\\n and zCMDS\\0 are accepted inside IDSESSION.");
486
 
            *error = 1;
487
 
            break;
488
 
        }
489
 
        cmdtype = parse_command(cmd, &argument, oldstyle);
490
 
        logg("$got command %s (%u, %u), argument: %s\n",
491
 
             cmd, (unsigned)cmdlen, (unsigned)cmdtype, argument ? argument : "");
492
 
        if (cmdtype == COMMAND_FILDES) {
493
 
            if (buf->buffer + buf->off <= cmd + strlen("FILDES\n")) {
494
 
                /* we need the extra byte from recvmsg */
495
 
                conn->mode = MODE_WAITANCILL;
496
 
                buf->mode = MODE_WAITANCILL;
497
 
                /* put term back */
498
 
                buf->buffer[pos + cmdlen] = term;
499
 
                cmdlen = 0;
500
 
                logg("$RECVTH: mode -> MODE_WAITANCILL\n");
501
 
                break;
502
 
            }
503
 
            /* eat extra \0 for controlmsg */
504
 
            cmdlen++;
505
 
            logg("$RECVTH: FILDES command complete\n");
506
 
        }
507
 
        conn->term = term;
508
 
        buf->term = term;
509
 
 
510
 
        if ((rc = execute_or_dispatch_command(conn, cmdtype, argument)) < 0) {
511
 
            logg("!Command dispatch failed\n");
512
 
            if(rc == -1 && optget(opts, "ExitOnOOM")->enabled) {
513
 
                pthread_mutex_lock(&exit_mutex);
514
 
                progexit = 1;
515
 
                pthread_mutex_unlock(&exit_mutex);
516
 
            }
517
 
            *error = 1;
518
 
        }
519
 
        if (thrmgr_group_need_terminate(conn->group)) {
520
 
            logg("$Receive thread: have to terminate group\n");
521
 
            *error = CL_ETIMEOUT;
522
 
            break;
523
 
        }
524
 
        if (*error || !conn->group || rc) {
525
 
            if (rc && thrmgr_group_finished(conn->group, EXIT_OK)) {
526
 
                logg("$Receive thread: closing conn (FD %d), group finished\n", conn->sd);
527
 
                /* if there are no more active jobs */
528
 
                shutdown(conn->sd, 2);
529
 
                closesocket(conn->sd);
530
 
                buf->fd = -1;
531
 
                conn->group = NULL;
532
 
            } else if (conn->mode != MODE_STREAM) {
533
 
                logg("$mode -> MODE_WAITREPLY\n");
534
 
                /* no more commands are accepted */
535
 
                conn->mode = MODE_WAITREPLY;
536
 
                /* Stop monitoring this FD, it will be closed either
537
 
                 * by us, or by the scanner thread. 
538
 
                 * Never close a file descriptor that is being
539
 
                 * monitored by poll()/select() from another thread,
540
 
                 * because this can lead to subtle bugs such as:
541
 
                 * Other thread closes file descriptor -> POLLHUP is
542
 
                 * set, but the poller thread doesn't wake up yet.
543
 
                 * Another client opens a connection and sends some
544
 
                 * data. If the socket reuses the previous file descriptor,
545
 
                 * then POLLIN is set on the file descriptor too.
546
 
                 * When poll() wakes up it sees POLLIN | POLLHUP
547
 
                 * and thinks that the client has sent some data,
548
 
                 * and closed the connection, so clamd closes the
549
 
                 * connection in turn resulting in a bug.
550
 
                 *
551
 
                 * If we wouldn't have poll()-ed the file descriptor
552
 
                 * we closed in another thread, but rather made sure
553
 
                 * that we don't put a FD that we're about to close
554
 
                 * into poll()'s list of watched fds; then POLLHUP
555
 
                 * would be set, but the file descriptor would stay
556
 
                 * open, until we wake up from poll() and close it.
557
 
                 * Thus a new connection won't be able to reuse the
558
 
                 * same FD, and there is no bug.
559
 
                 * */
560
 
                buf->fd = -1;
561
 
            }
562
 
        }
563
 
        /* we received a command, set readtimeout */
564
 
        time(&buf->timeout_at);
565
 
        buf->timeout_at += readtimeout;
566
 
        pos += cmdlen+1;
567
 
        if (conn->mode == MODE_STREAM) {
568
 
            /* TODO: this doesn't belong here */
569
 
            buf->dumpname = conn->filename;
570
 
            buf->dumpfd = conn->scanfd;
571
 
            logg("$Receive thread: INSTREAM: %s fd %u\n", buf->dumpname, buf->dumpfd);
572
 
        }
573
 
        if (conn->mode != MODE_COMMAND) {
574
 
            logg("$Breaking command loop, mode is no longer MODE_COMMAND\n");
575
 
            break;
576
 
        }
577
 
        conn->id++;
578
 
    }
579
 
    *ppos = pos;
580
 
    buf->mode = conn->mode;
581
 
    buf->id = conn->id;
582
 
    buf->group = conn->group;
583
 
    buf->quota = conn->quota;
584
 
    if (conn->scanfd != -1 && conn->scanfd != buf->dumpfd) {
585
 
        logg("$Unclaimed file descriptor received, closing: %d\n", conn->scanfd);
586
 
        close(conn->scanfd);
587
 
        /* protocol error */
588
 
        conn_reply_error(conn, "PROTOCOL ERROR: ancillary data sent without FILDES.");
589
 
        *error = 1;
590
 
        return NULL;
591
 
    }
592
 
    if (!*error) {
593
 
        /* move partial command to beginning of buffer */
594
 
        if (pos < buf->off) {
595
 
            memmove (buf->buffer, &buf->buffer[pos], buf->off - pos);
596
 
            buf->off -= pos;
597
 
        } else
598
 
            buf->off = 0;
599
 
        if (buf->off)
600
 
            logg("$Moved partial command: %lu\n", (unsigned long)buf->off);
601
 
        else
602
 
            logg("$Consumed entire command\n");
603
 
        /* adjust pos to account for the buffer shuffle */
604
 
        pos = 0;
605
 
    }
606
 
    *ppos = pos;
607
 
    return cmd;
608
 
}
609
 
 
610
 
/* static const unsigned char* parse_dispatch_cmd(client_conn_t *conn, struct fd_buf *buf, size_t *ppos, int *error, const struct optstruct *opts, int readtimeout) */
611
 
static int handle_stream(client_conn_t *conn, struct fd_buf *buf, const struct optstruct *opts, int *error, size_t *ppos, int readtimeout)
612
 
{
613
 
    int rc;
614
 
    size_t pos = *ppos;
615
 
    size_t cmdlen;
616
 
    
617
 
    logg("$mode == MODE_STREAM\n");
618
 
    /* we received some data, set readtimeout */
619
 
    time(&buf->timeout_at);
620
 
    buf->timeout_at += readtimeout;
621
 
    while (pos <= buf->off) {
622
 
        if (!buf->chunksize) {
623
 
            /* read chunksize */
624
 
            if (buf->off-pos >= 4) {
625
 
                uint32_t cs;
626
 
                memmove(&cs, buf->buffer + pos, 4);
627
 
                pos += 4;
628
 
                buf->chunksize = ntohl(cs);
629
 
                logg("$Got chunksize: %u\n", buf->chunksize);
630
 
                if (!buf->chunksize) {
631
 
                    /* chunksize 0 marks end of stream */
632
 
                    conn->scanfd = buf->dumpfd;
633
 
                    conn->term = buf->term;
634
 
                    buf->dumpfd = -1;
635
 
                    buf->mode = buf->group ? MODE_COMMAND : MODE_WAITREPLY;
636
 
                    if (buf->mode == MODE_WAITREPLY)
637
 
                        buf->fd = -1;
638
 
                    logg("$Chunks complete\n");
639
 
                    buf->dumpname = NULL;
640
 
                    if ((rc = execute_or_dispatch_command(conn, COMMAND_INSTREAMSCAN, NULL)) < 0) {
641
 
                        logg("!Command dispatch failed\n");
642
 
                        if(rc == -1 && optget(opts, "ExitOnOOM")->enabled) {
643
 
                            pthread_mutex_lock(&exit_mutex);
644
 
                            progexit = 1;
645
 
                            pthread_mutex_unlock(&exit_mutex);
646
 
                        }
647
 
                        *error = 1;
648
 
                    } else {
649
 
                        memmove (buf->buffer, &buf->buffer[pos], buf->off - pos);
650
 
                        buf->off -= pos;
651
 
                        *ppos = 0;
652
 
                        buf->id++;
653
 
                        return 0;
654
 
                    }
655
 
                }
656
 
                if (buf->chunksize > buf->quota) {
657
 
                    logg("^INSTREAM: Size limit reached, (requested: %lu, max: %lu)\n",
658
 
                         (unsigned long)buf->chunksize, (unsigned long)buf->quota);
659
 
                    conn_reply_error(conn, "INSTREAM size limit exceeded.");
660
 
                    *error = 1;
661
 
                    *ppos = pos;
662
 
                    return -1;
663
 
                } else {
664
 
                    buf->quota -= buf->chunksize;
665
 
                }
666
 
                logg("$Quota Remaining: %lu\n", buf->quota);
667
 
            } else {
668
 
                /* need more data, so return and wait for some */
669
 
                memmove (buf->buffer, &buf->buffer[pos], buf->off - pos);
670
 
                buf->off -= pos;
671
 
                *ppos = 0;
672
 
                return -1;
673
 
            }
674
 
        }
675
 
        if (pos + buf->chunksize < buf->off)
676
 
            cmdlen = buf->chunksize;
677
 
        else
678
 
            cmdlen = buf->off - pos;
679
 
        buf->chunksize -= cmdlen;
680
 
        if (cli_writen(buf->dumpfd, buf->buffer + pos, cmdlen) < 0) {
681
 
            conn_reply_error(conn, "Error writing to temporary file");
682
 
            logg("!INSTREAM: Can't write to temporary file.\n");
683
 
            *error = 1;
684
 
        }
685
 
        logg("$Processed %lu bytes of chunkdata, pos %lu\n", cmdlen, pos);
686
 
        pos += cmdlen;
687
 
        if (pos == buf->off) {
688
 
            buf->off = 0;
689
 
            pos = 0;
690
 
            /* need more data, so return and wait for some */
691
 
            *ppos = pos;
692
 
            return -1;
693
 
        }
694
 
    }
695
 
    *ppos = pos;
696
 
    return 0;
697
 
}
698
 
 
699
 
int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts)
700
 
{
701
 
        int max_threads, max_queue, readtimeout, ret = 0;
702
 
        unsigned int options = 0;
703
 
        char timestr[32];
704
 
#ifndef _WIN32
705
 
        struct sigaction sigact;
706
 
        sigset_t sigset;
707
 
        struct rlimit rlim;
708
 
#endif
709
 
        mode_t old_umask;
710
 
        const struct optstruct *opt;
711
 
        char buff[BUFFSIZE + 1];
712
 
        pid_t mainpid;
713
 
        int idletimeout;
714
 
        unsigned long long val;
715
 
        size_t i, j, rr_last = 0;
716
 
        pthread_t accept_th;
717
 
        pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER;
718
 
        pthread_mutex_t recvfds_mutex = PTHREAD_MUTEX_INITIALIZER;
719
 
        struct acceptdata acceptdata = ACCEPTDATA_INIT(&fds_mutex, &recvfds_mutex);
720
 
        struct fd_data *fds = &acceptdata.recv_fds;
721
 
        time_t start_time, current_time;
722
 
        unsigned int selfchk;
723
 
        threadpool_t *thr_pool;
724
 
 
725
 
#if defined(FANOTIFY) || defined(CLAMAUTH)
726
 
        pthread_t fan_pid;
727
 
        pthread_attr_t fan_attr;
728
 
        struct thrarg *tharg = NULL; /* shut up gcc */
729
 
#endif
730
 
 
731
 
#ifndef _WIN32
732
 
        memset(&sigact, 0, sizeof(struct sigaction));
733
 
#endif
734
 
 
735
 
    /* set up limits */
736
 
    if((opt = optget(opts, "MaxScanSize"))->active) {
737
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) {
738
 
            logg("!cl_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
739
 
            cl_engine_free(engine);
740
 
            return 1;
741
 
        }
742
 
    }
743
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL);
744
 
    if(val)
745
 
        logg("Limits: Global size limit set to %llu bytes.\n", val);
746
 
    else
747
 
        logg("^Limits: Global size limit protection disabled.\n");
748
 
 
749
 
    if((opt = optget(opts, "MaxFileSize"))->active) {
750
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) {
751
 
            logg("!cl_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
752
 
            cl_engine_free(engine);
753
 
            return 1;
754
 
        }
755
 
    }
756
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL);
757
 
    if(val)
758
 
        logg("Limits: File size limit set to %llu bytes.\n", val);
759
 
    else
760
 
        logg("^Limits: File size limit protection disabled.\n");
761
 
 
762
 
#ifndef _WIN32
763
 
    if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
764
 
        if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL))
765
 
            logg("^System limit for file size is lower than engine->maxfilesize\n");
766
 
        if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL))
767
 
            logg("^System limit for file size is lower than engine->maxscansize\n");
768
 
    } else {
769
 
        logg("^Cannot obtain resource limits for file size\n");
770
 
    }
771
 
#endif
772
 
 
773
 
    if((opt = optget(opts, "MaxRecursion"))->active) {
774
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) {
775
 
            logg("!cl_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
776
 
            cl_engine_free(engine);
777
 
            return 1;
778
 
        }
779
 
    }
780
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_RECURSION, NULL);
781
 
    if(val)
782
 
        logg("Limits: Recursion level limit set to %u.\n", (unsigned int) val);
783
 
    else
784
 
        logg("^Limits: Recursion level limit protection disabled.\n");
785
 
 
786
 
    if((opt = optget(opts, "MaxFiles"))->active) {
787
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) {
788
 
            logg("!cl_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
789
 
            cl_engine_free(engine);
790
 
            return 1;
791
 
        }
792
 
    }
793
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILES, NULL);
794
 
    if(val)
795
 
        logg("Limits: Files limit set to %u.\n", (unsigned int) val);
796
 
    else
797
 
        logg("^Limits: Files limit protection disabled.\n");
798
 
 
799
 
#ifndef _WIN32
800
 
    if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
801
 
        logg("*Limits: Core-dump limit is %lu.\n", (unsigned long)rlim.rlim_cur);
802
 
    }
803
 
#endif
804
 
 
805
 
    /* Engine max sizes */
806
 
 
807
 
    if((opt = optget(opts, "MaxEmbeddedPE"))->active) {
808
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) {
809
 
            logg("!cli_engine_set_num(CL_ENGINE_MAX_EMBEDDEDPE) failed: %s\n", cl_strerror(ret));
810
 
            cl_engine_free(engine);
811
 
            return 1;
812
 
        }
813
 
    }
814
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, NULL);
815
 
    logg("Limits: MaxEmbeddedPE limit set to %llu bytes.\n", val);
816
 
 
817
 
    if((opt = optget(opts, "MaxHTMLNormalize"))->active) {
818
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) {
819
 
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNORMALIZE) failed: %s\n", cl_strerror(ret));
820
 
            cl_engine_free(engine);
821
 
            return 1;
822
 
        }
823
 
    }
824
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, NULL);
825
 
    logg("Limits: MaxHTMLNormalize limit set to %llu bytes.\n", val);
826
 
 
827
 
    if((opt = optget(opts, "MaxHTMLNoTags"))->active) {
828
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) {
829
 
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNOTAGS) failed: %s\n", cl_strerror(ret));
830
 
            cl_engine_free(engine);
831
 
            return 1;
832
 
        }
833
 
    }
834
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, NULL);
835
 
    logg("Limits: MaxHTMLNoTags limit set to %llu bytes.\n", val);
836
 
 
837
 
    if((opt = optget(opts, "MaxScriptNormalize"))->active) {
838
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) {
839
 
            logg("!cli_engine_set_num(CL_ENGINE_MAX_SCRIPTNORMALIZE) failed: %s\n", cl_strerror(ret));
840
 
            cl_engine_free(engine);
841
 
            return 1;
842
 
        }
843
 
    }
844
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, NULL);
845
 
    logg("Limits: MaxScriptNormalize limit set to %llu bytes.\n", val);
846
 
 
847
 
    if((opt = optget(opts, "MaxZipTypeRcg"))->active) {
848
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) {
849
 
            logg("!cli_engine_set_num(CL_ENGINE_MAX_ZIPTYPERCG) failed: %s\n", cl_strerror(ret));
850
 
            cl_engine_free(engine);
851
 
            return 1;
852
 
        }
853
 
    }
854
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, NULL);
855
 
    logg("Limits: MaxZipTypeRcg limit set to %llu bytes.\n", val);
856
 
 
857
 
    if((opt = optget(opts, "MaxPartitions"))->active) {
858
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) {
859
 
            logg("!cli_engine_set_num(MaxPartitions) failed: %s\n", cl_strerror(ret));
860
 
            cl_engine_free(engine);
861
 
            return 1;
862
 
        }
863
 
    }
864
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_PARTITIONS, NULL);
865
 
    logg("Limits: MaxPartitions limit set to %llu.\n", val);
866
 
 
867
 
    if((opt = optget(opts, "MaxIconsPE"))->active) {
868
 
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) {
869
 
            logg("!cli_engine_set_num(MaxIconsPE) failed: %s\n", cl_strerror(ret));
870
 
            cl_engine_free(engine);
871
 
            return 1;
872
 
        }
873
 
    }
874
 
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_ICONSPE, NULL);
875
 
    logg("Limits: MaxIconsPE limit set to %llu.\n", val);
876
 
 
877
 
    if(optget(opts, "ScanArchive")->enabled) {
878
 
        logg("Archive support enabled.\n");
879
 
        options |= CL_SCAN_ARCHIVE;
880
 
 
881
 
        if(optget(opts, "ArchiveBlockEncrypted")->enabled) {
882
 
            logg("Archive: Blocking encrypted archives.\n");
883
 
            options |= CL_SCAN_BLOCKENCRYPTED;
884
 
        }
885
 
 
886
 
    } else {
887
 
        logg("Archive support disabled.\n");
888
 
    }
889
 
 
890
 
    if(optget(opts, "AlgorithmicDetection")->enabled) {
891
 
        logg("Algorithmic detection enabled.\n");
892
 
        options |= CL_SCAN_ALGORITHMIC;
893
 
    } else {
894
 
        logg("Algorithmic detection disabled.\n");
895
 
    }
896
 
 
897
 
    if(optget(opts, "ScanPE")->enabled) {
898
 
        logg("Portable Executable support enabled.\n");
899
 
        options |= CL_SCAN_PE;
900
 
    } else {
901
 
        logg("Portable Executable support disabled.\n");
902
 
    }
903
 
 
904
 
    if(optget(opts, "ScanELF")->enabled) {
905
 
        logg("ELF support enabled.\n");
906
 
        options |= CL_SCAN_ELF;
907
 
    } else {
908
 
        logg("ELF support disabled.\n");
909
 
    }
910
 
 
911
 
    if(optget(opts, "ScanPE")->enabled || optget(opts, "ScanELF")->enabled) {
912
 
        if(optget(opts, "DetectBrokenExecutables")->enabled) {
913
 
            logg("Detection of broken executables enabled.\n");
914
 
            options |= CL_SCAN_BLOCKBROKEN;
915
 
        }
916
 
    }
917
 
 
918
 
    if(optget(opts, "ScanMail")->enabled) {
919
 
        logg("Mail files support enabled.\n");
920
 
        options |= CL_SCAN_MAIL;
921
 
 
922
 
        if(optget(opts, "ScanPartialMessages")->enabled) {
923
 
            logg("Mail: RFC1341 handling enabled.\n");
924
 
            options |= CL_SCAN_PARTIAL_MESSAGE;
925
 
        }
926
 
 
927
 
    } else {
928
 
        logg("Mail files support disabled.\n");
929
 
    }
930
 
 
931
 
    if(optget(opts, "ScanOLE2")->enabled) {
932
 
        logg("OLE2 support enabled.\n");
933
 
        options |= CL_SCAN_OLE2;
934
 
        if(optget(opts, "OLE2BlockMacros")->enabled) {
935
 
            logg("OLE2: Blocking all VBA macros.\n");
936
 
            options |= CL_SCAN_BLOCKMACROS;
937
 
        }
938
 
    } else {
939
 
        logg("OLE2 support disabled.\n");
940
 
    }
941
 
 
942
 
    if(optget(opts, "ScanPDF")->enabled) {
943
 
        logg("PDF support enabled.\n");
944
 
        options |= CL_SCAN_PDF;
945
 
    } else {
946
 
        logg("PDF support disabled.\n");
947
 
    }
948
 
 
949
 
    if(optget(opts, "ScanSWF")->enabled) {
950
 
        logg("SWF support enabled.\n");
951
 
        options |= CL_SCAN_SWF;
952
 
    } else {
953
 
        logg("SWF support disabled.\n");
954
 
    }
955
 
 
956
 
    if(optget(opts, "ScanHTML")->enabled) {
957
 
        logg("HTML support enabled.\n");
958
 
        options |= CL_SCAN_HTML;
959
 
    } else {
960
 
        logg("HTML support disabled.\n");
961
 
    }
962
 
 
963
 
    if(optget(opts,"PhishingScanURLs")->enabled) {
964
 
 
965
 
        if(optget(opts,"PhishingAlwaysBlockCloak")->enabled) {
966
 
            options |= CL_SCAN_PHISHING_BLOCKCLOAK; 
967
 
            logg("Phishing: Always checking for cloaked urls\n");
968
 
        }
969
 
 
970
 
        if(optget(opts,"PhishingAlwaysBlockSSLMismatch")->enabled) {
971
 
            options |= CL_SCAN_PHISHING_BLOCKSSL;
972
 
            logg("Phishing: Always checking for ssl mismatches\n");
973
 
        }
974
 
    }
975
 
 
976
 
    if(optget(opts,"PartitionIntersection")->enabled) {
977
 
        options |= CL_SCAN_PARTITION_INTXN;
978
 
        logg("Raw DMG: Always checking for partitons intersections\n");
979
 
    }
980
 
 
981
 
    if(optget(opts,"HeuristicScanPrecedence")->enabled) {
982
 
            options |= CL_SCAN_HEURISTIC_PRECEDENCE;
983
 
            logg("Heuristic: precedence enabled\n");
984
 
    }
985
 
 
986
 
    if(optget(opts, "StructuredDataDetection")->enabled) {
987
 
        options |= CL_SCAN_STRUCTURED;
988
 
 
989
 
        if((opt = optget(opts, "StructuredMinCreditCardCount"))->enabled) {
990
 
            if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) {
991
 
                logg("!cl_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
992
 
                cl_engine_free(engine);
993
 
                return 1;
994
 
            }
995
 
        }
996
 
        val = cl_engine_get_num(engine, CL_ENGINE_MIN_CC_COUNT, NULL);
997
 
        logg("Structured: Minimum Credit Card Number Count set to %u\n", (unsigned int) val);
998
 
 
999
 
        if((opt = optget(opts, "StructuredMinSSNCount"))->enabled) {
1000
 
            if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) {
1001
 
                logg("!cl_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
1002
 
                cl_engine_free(engine);
1003
 
                return 1;
1004
 
            }
1005
 
        }
1006
 
        val = cl_engine_get_num(engine, CL_ENGINE_MIN_SSN_COUNT, NULL);
1007
 
        logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int) val);
1008
 
 
1009
 
        if(optget(opts, "StructuredSSNFormatNormal")->enabled)
1010
 
            options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
1011
 
 
1012
 
        if(optget(opts, "StructuredSSNFormatStripped")->enabled)
1013
 
            options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;
1014
 
    }
1015
 
 
1016
 
#ifdef HAVE__INTERNAL__SHA_COLLECT
1017
 
    if(optget(opts, "DevCollectHashes")->enabled)
1018
 
        options |= CL_SCAN_INTERNAL_COLLECT_SHA;
1019
 
#endif
1020
 
 
1021
 
    selfchk = optget(opts, "SelfCheck")->numarg;
1022
 
    if(!selfchk) {
1023
 
        logg("Self checking disabled.\n");
1024
 
    } else {
1025
 
        logg("Self checking every %u seconds.\n", selfchk);
1026
 
    }
1027
 
    memset(&dbstat, 0, sizeof(dbstat));
1028
 
 
1029
 
    /* save the PID */
1030
 
    mainpid = getpid();
1031
 
    if((opt = optget(opts, "PidFile"))->enabled) {
1032
 
            FILE *fd;
1033
 
        old_umask = umask(0002);
1034
 
        if((fd = fopen(opt->strarg, "w")) == NULL) {
1035
 
            logg("!Can't save PID in file %s\n", opt->strarg);
1036
 
        } else {
1037
 
            if (fprintf(fd, "%u", (unsigned int) mainpid)<0) {
1038
 
                logg("!Can't save PID in file %s\n", opt->strarg);
1039
 
            }
1040
 
            fclose(fd);
1041
 
        }
1042
 
        umask(old_umask);
1043
 
    }
1044
 
 
1045
 
    logg("*Listening daemon: PID: %u\n", (unsigned int) mainpid);
1046
 
    max_threads = optget(opts, "MaxThreads")->numarg;
1047
 
    max_queue = optget(opts, "MaxQueue")->numarg;
1048
 
    acceptdata.commandtimeout = optget(opts, "CommandReadTimeout")->numarg;
1049
 
    readtimeout = optget(opts, "ReadTimeout")->numarg;
1050
 
 
1051
 
#if !defined(_WIN32) && defined(RLIMIT_NOFILE)
1052
 
    if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
1053
 
        /* don't warn if default value is too high, silently fix it */
1054
 
        unsigned maxrec;
1055
 
        int max_max_queue;
1056
 
        unsigned warn = optget(opts, "MaxQueue")->active;
1057
 
        const unsigned clamdfiles = 6;
1058
 
        /* Condition to not run out of file descriptors:
1059
 
         * MaxThreads * MaxRecursion + (MaxQueue - MaxThreads) + CLAMDFILES < RLIMIT_NOFILE 
1060
 
         * CLAMDFILES is 6: 3 standard FD + logfile + 2 FD for reloading the DB
1061
 
         * */
1062
 
#ifdef C_SOLARIS
1063
 
#ifdef HAVE_ENABLE_EXTENDED_FILE_STDIO
1064
 
        if (enable_extended_FILE_stdio(-1, -1) == -1) {
1065
 
            logg("^Unable to set extended FILE stdio, clamd will be limited to max 256 open files\n");
1066
 
            rlim.rlim_cur = rlim.rlim_cur > 255 ? 255 : rlim.rlim_cur;
1067
 
        }
1068
 
#elif !defined(_LP64)
1069
 
        if (rlim.rlim_cur > 255) {
1070
 
            rlim.rlim_cur = 255;
1071
 
            logg("^Solaris only supports 256 open files for 32-bit processes, you need at least Solaris 10u4, or compile as 64-bit to support more!\n");
1072
 
        }
1073
 
#endif
1074
 
#endif
1075
 
        opt = optget(opts,"MaxRecursion");
1076
 
        maxrec = opt->numarg;
1077
 
        max_max_queue = rlim.rlim_cur - maxrec * max_threads - clamdfiles + max_threads;
1078
 
        if (max_queue < max_threads) {
1079
 
            max_queue = max_threads;
1080
 
            if (warn)
1081
 
                logg("^MaxQueue value too low, increasing to: %d\n", max_queue);
1082
 
        }
1083
 
        if (max_max_queue < max_threads) {
1084
 
            logg("^MaxThreads * MaxRecursion is too high: %d, open file descriptor limit is: %lu\n",
1085
 
                 maxrec*max_threads, (unsigned long)rlim.rlim_cur);
1086
 
            max_max_queue = max_threads;
1087
 
        }
1088
 
        if (max_queue > max_max_queue) {
1089
 
            max_queue = max_max_queue;
1090
 
            if (warn)
1091
 
                logg("^MaxQueue value too high, lowering to: %d\n", max_queue);
1092
 
        } else if (max_queue < 2*max_threads && max_queue < max_max_queue) {
1093
 
            max_queue = 2*max_threads;
1094
 
            if (max_queue > max_max_queue)
1095
 
                max_queue = max_max_queue;
1096
 
            /* always warn here */
1097
 
            logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue);
1098
 
        }
1099
 
    }
1100
 
#endif
1101
 
    logg("*MaxQueue set to: %d\n", max_queue);
1102
 
    acceptdata.max_queue = max_queue;
1103
 
 
1104
 
    if(optget(opts, "ScanOnAccess")->enabled)
1105
 
#if defined(FANOTIFY) || defined(CLAMAUTH)
1106
 
    {
1107
 
        do {
1108
 
            if(pthread_attr_init(&fan_attr)) break;
1109
 
            pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE);
1110
 
            if(!(tharg = (struct thrarg *) malloc(sizeof(struct thrarg)))) break;
1111
 
            tharg->opts = opts;
1112
 
            tharg->engine = engine;
1113
 
            tharg->options = options;
1114
 
            if(!pthread_create(&fan_pid, &fan_attr, fan_th, tharg)) break;
1115
 
            free(tharg);
1116
 
            tharg=NULL;
1117
 
        } while(0);
1118
 
        if (!tharg) logg("!Unable to start on-access scan\n");
1119
 
    }
1120
 
#else
1121
 
        logg("!On-access scan is not available\n");
1122
 
#endif
1123
 
 
1124
 
#ifndef _WIN32
1125
 
    /* set up signal handling */
1126
 
    sigfillset(&sigset);
1127
 
    sigdelset(&sigset, SIGINT);
1128
 
    sigdelset(&sigset, SIGTERM);
1129
 
    sigdelset(&sigset, SIGSEGV);
1130
 
    sigdelset(&sigset, SIGHUP);
1131
 
    sigdelset(&sigset, SIGPIPE);
1132
 
    sigdelset(&sigset, SIGUSR2);
1133
 
    /* The behavior of a process is undefined after it ignores a 
1134
 
     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
1135
 
    sigdelset(&sigset, SIGFPE);
1136
 
    sigdelset(&sigset, SIGILL);
1137
 
    sigdelset(&sigset, SIGSEGV);
1138
 
#ifdef SIGBUS    
1139
 
    sigdelset(&sigset, SIGBUS);
1140
 
#endif
1141
 
    sigdelset(&sigset, SIGTSTP);
1142
 
    sigdelset(&sigset, SIGCONT);
1143
 
    sigprocmask(SIG_SETMASK, &sigset, NULL);
1144
 
 
1145
 
    /* SIGINT, SIGTERM, SIGSEGV */
1146
 
    sigact.sa_handler = sighandler_th;
1147
 
    sigemptyset(&sigact.sa_mask);
1148
 
    sigaddset(&sigact.sa_mask, SIGINT);
1149
 
    sigaddset(&sigact.sa_mask, SIGTERM);
1150
 
    sigaddset(&sigact.sa_mask, SIGHUP);
1151
 
    sigaddset(&sigact.sa_mask, SIGPIPE);
1152
 
    sigaddset(&sigact.sa_mask, SIGUSR2);
1153
 
    sigaction(SIGINT, &sigact, NULL);
1154
 
    sigaction(SIGTERM, &sigact, NULL);
1155
 
    sigaction(SIGHUP, &sigact, NULL);
1156
 
    sigaction(SIGPIPE, &sigact, NULL);
1157
 
    sigaction(SIGUSR2, &sigact, NULL);
1158
 
#endif
1159
 
 
1160
 
    idletimeout = optget(opts, "IdleTimeout")->numarg;
1161
 
 
1162
 
    for (i=0;i < nsockets;i++)
1163
 
        if (fds_add(&acceptdata.fds, socketds[i], 1, 0) == -1) {
1164
 
            logg("!fds_add failed\n");
1165
 
            cl_engine_free(engine);
1166
 
            return 1;
1167
 
        }
1168
 
#ifdef _WIN32
1169
 
        event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL);
1170
 
        event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL);
1171
 
#else
1172
 
    if (pipe(acceptdata.syncpipe_wake_recv) == -1 ||
1173
 
        (pipe(acceptdata.syncpipe_wake_accept) == -1)) {
1174
 
 
1175
 
        logg("!pipe failed\n");
1176
 
        exit(-1);
1177
 
    }
1178
 
    syncpipe_wake_recv_w = acceptdata.syncpipe_wake_recv[1];
1179
 
 
1180
 
    if (fds_add(fds, acceptdata.syncpipe_wake_recv[0], 1, 0) == -1 ||
1181
 
        fds_add(&acceptdata.fds, acceptdata.syncpipe_wake_accept[0], 1, 0)) {
1182
 
        logg("!failed to add pipe fd\n");
1183
 
        exit(-1);
1184
 
    }
1185
 
#endif
1186
 
 
1187
 
    if ((thr_pool = thrmgr_new(max_threads, idletimeout, max_queue, scanner_thread)) == NULL) {
1188
 
        logg("!thrmgr_new failed\n");
1189
 
        exit(-1);
1190
 
    }
1191
 
 
1192
 
    if (pthread_create(&accept_th, NULL, acceptloop_th, &acceptdata)) {
1193
 
        logg("!pthread_create failed\n");
1194
 
        exit(-1);
1195
 
    }
1196
 
 
1197
 
    time(&start_time);
1198
 
    for(;;) {
1199
 
        int new_sd;
1200
 
 
1201
 
        /* Block waiting for connection on any of the sockets */
1202
 
        pthread_mutex_lock(fds->buf_mutex);
1203
 
        fds_cleanup(fds);
1204
 
        /* signal that we can accept more connections */
1205
 
        if (fds->nfds <= (unsigned)max_queue)
1206
 
            pthread_cond_signal(&acceptdata.cond_nfds);
1207
 
        new_sd = fds_poll_recv(fds, selfchk ? (int)selfchk : -1, 1, event_wake_recv);
1208
 
#ifdef _WIN32
1209
 
        ResetEvent(event_wake_recv);
1210
 
#else
1211
 
        if (!fds->nfds) {
1212
 
            /* at least the dummy/sync pipe should have remained */
1213
 
            logg("!All recv() descriptors gone: fatal\n");
1214
 
            pthread_mutex_lock(&exit_mutex);
1215
 
            progexit = 1;
1216
 
            pthread_mutex_unlock(&exit_mutex);
1217
 
            pthread_mutex_unlock(fds->buf_mutex);
1218
 
            break;
1219
 
        }
1220
 
#endif
1221
 
        if (new_sd == -1 && errno != EINTR) {
1222
 
            logg("!Failed to poll sockets, fatal\n");
1223
 
            pthread_mutex_lock(&exit_mutex);
1224
 
            progexit = 1;
1225
 
            pthread_mutex_unlock(&exit_mutex);
1226
 
        }
1227
 
 
1228
 
 
1229
 
        if(fds->nfds) i = (rr_last + 1) % fds->nfds;
1230
 
        for (j = 0;  j < fds->nfds && new_sd >= 0; j++, i = (i+1) % fds->nfds) {
1231
 
            size_t pos = 0;
1232
 
            int error = 0;
1233
 
            struct fd_buf *buf = &fds->buf[i];
1234
 
            if (!buf->got_newdata)
1235
 
                continue;
1236
 
 
1237
 
#ifndef _WIN32
1238
 
            if (buf->fd == acceptdata.syncpipe_wake_recv[0]) {
1239
 
                /* dummy sync pipe, just to wake us */
1240
 
                if (read(buf->fd, buff, sizeof(buff)) < 0) {
1241
 
                    logg("^Syncpipe read failed\n");
1242
 
                }
1243
 
                continue;
1244
 
            }
1245
 
#endif
1246
 
            if (buf->got_newdata == -1) {
1247
 
                if (buf->mode == MODE_WAITREPLY) {
1248
 
                    logg("$mode WAIT_REPLY -> closed\n");
1249
 
                    buf->fd = -1;
1250
 
                    thrmgr_group_terminate(buf->group);
1251
 
                    thrmgr_group_finished(buf->group, EXIT_ERROR);
1252
 
                    continue;
1253
 
                } else {
1254
 
                    logg("$client read error or EOF on read\n");
1255
 
                    error = 1;
1256
 
                }
1257
 
            }
1258
 
 
1259
 
            if (buf->fd != -1 && buf->got_newdata == -2) {
1260
 
                logg("$Client read timed out\n");
1261
 
                mdprintf(buf->fd, "COMMAND READ TIMED OUT\n");
1262
 
                error = 1;
1263
 
            }
1264
 
 
1265
 
            rr_last = i;
1266
 
            if (buf->mode == MODE_WAITANCILL) {
1267
 
                buf->mode = MODE_COMMAND;
1268
 
                logg("$mode -> MODE_COMMAND\n");
1269
 
            }
1270
 
            while (!error && buf->fd != -1 && buf->buffer && pos < buf->off &&
1271
 
                   buf->mode != MODE_WAITANCILL) {
1272
 
                client_conn_t conn;
1273
 
                const char *cmd = NULL;
1274
 
                int rc;
1275
 
                /* New data available to read on socket. */
1276
 
 
1277
 
                memset(&conn, 0, sizeof(conn));
1278
 
                conn.scanfd = buf->recvfd;
1279
 
                buf->recvfd = -1;
1280
 
                conn.sd = buf->fd;
1281
 
                conn.options = options;
1282
 
                conn.opts = opts;
1283
 
                conn.thrpool = thr_pool;
1284
 
                conn.engine = engine;
1285
 
                conn.group = buf->group;
1286
 
                conn.id = buf->id;
1287
 
                conn.quota = buf->quota;
1288
 
                conn.filename = buf->dumpname;
1289
 
                conn.mode = buf->mode;
1290
 
                conn.term = buf->term;
1291
 
 
1292
 
                /* Parse & dispatch command */
1293
 
                cmd = parse_dispatch_cmd(&conn, buf, &pos, &error, opts, readtimeout);
1294
 
 
1295
 
                if (conn.mode == MODE_COMMAND && !cmd)
1296
 
                    break;
1297
 
                if (!error) {
1298
 
                    if (buf->mode == MODE_WAITREPLY && buf->off) {
1299
 
                        /* Client is not supposed to send anything more */
1300
 
                        logg("^Client sent garbage after last command: %lu bytes\n", (unsigned long)buf->off);
1301
 
                        buf->buffer[buf->off] = '\0';
1302
 
                        logg("$Garbage: %s\n", buf->buffer);
1303
 
                        error = 1;
1304
 
                    } else if (buf->mode == MODE_STREAM) {
1305
 
                        rc = handle_stream(&conn, buf, opts, &error, &pos, readtimeout);
1306
 
                        if (rc == -1)
1307
 
                            break;
1308
 
                        else
1309
 
                            continue;
1310
 
                    }
1311
 
                }
1312
 
                if (error && error != CL_ETIMEOUT) {
1313
 
                    conn_reply_error(&conn, "Error processing command.");
1314
 
                }
1315
 
            }
1316
 
            if (error) {
1317
 
                if (buf->dumpfd != -1) {
1318
 
                    close(buf->dumpfd);
1319
 
                    if (buf->dumpname) {
1320
 
                        cli_unlink(buf->dumpname);
1321
 
                        free(buf->dumpname);
1322
 
                    }
1323
 
                    buf->dumpfd = -1;
1324
 
                }
1325
 
                thrmgr_group_terminate(buf->group);
1326
 
                if (thrmgr_group_finished(buf->group, EXIT_ERROR)) {
1327
 
                    if (buf->fd < 0) {
1328
 
                        logg("$Skipping shutdown of bad socket after error (FD %d)\n", buf->fd);
1329
 
                    }
1330
 
                    else {
1331
 
                        logg("$Shutting down socket after error (FD %d)\n", buf->fd);
1332
 
                        shutdown(buf->fd, 2);
1333
 
                        closesocket(buf->fd);
1334
 
                    }
1335
 
                } else
1336
 
                    logg("$Socket not shut down due to active tasks\n");
1337
 
                buf->fd = -1;
1338
 
            }
1339
 
        }
1340
 
        pthread_mutex_unlock(fds->buf_mutex);
1341
 
 
1342
 
        /* handle progexit */
1343
 
        pthread_mutex_lock(&exit_mutex);
1344
 
        if (progexit) {
1345
 
            pthread_mutex_unlock(&exit_mutex);
1346
 
            pthread_mutex_lock(fds->buf_mutex);
1347
 
            for (i=0;i < fds->nfds; i++) {
1348
 
                if (fds->buf[i].fd == -1)
1349
 
                    continue;
1350
 
                thrmgr_group_terminate(fds->buf[i].group);
1351
 
                if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR)) {
1352
 
                    logg("$Shutdown closed fd %d\n", fds->buf[i].fd);
1353
 
                    shutdown(fds->buf[i].fd, 2);
1354
 
                    closesocket(fds->buf[i].fd);
1355
 
                    fds->buf[i].fd = -1;
1356
 
                }
1357
 
            }
1358
 
            pthread_mutex_unlock(fds->buf_mutex);
1359
 
            break;
1360
 
        }
1361
 
        pthread_mutex_unlock(&exit_mutex);
1362
 
 
1363
 
        /* SIGHUP */
1364
 
        if (sighup) {
1365
 
            logg("SIGHUP caught: re-opening log file.\n");
1366
 
            logg_close();
1367
 
            sighup = 0;
1368
 
            if(!logg_file && (opt = optget(opts, "LogFile"))->enabled)
1369
 
                logg_file = opt->strarg;
1370
 
        }
1371
 
 
1372
 
        /* SelfCheck */
1373
 
        if(selfchk) {
1374
 
            time(&current_time);
1375
 
            if((current_time - start_time) >= (time_t)selfchk) {
1376
 
                if(reload_db(engine, dboptions, opts, TRUE, &ret)) {
1377
 
                    pthread_mutex_lock(&reload_mutex);
1378
 
                    reload = 1;
1379
 
                    pthread_mutex_unlock(&reload_mutex);
1380
 
                }
1381
 
                time(&start_time);
1382
 
            }
1383
 
        }
1384
 
 
1385
 
        /* DB reload */
1386
 
        pthread_mutex_lock(&reload_mutex);
1387
 
        if(reload) {
1388
 
            pthread_mutex_unlock(&reload_mutex);
1389
 
#if defined(FANOTIFY) || defined(CLAMAUTH)
1390
 
            if(optget(opts, "ScanOnAccess")->enabled && tharg) {
1391
 
                logg("Restarting on-access scan\n");
1392
 
                pthread_mutex_lock(&logg_mutex);
1393
 
                pthread_kill(fan_pid, SIGUSR1);
1394
 
                pthread_mutex_unlock(&logg_mutex);
1395
 
                pthread_join(fan_pid, NULL);
1396
 
            }
1397
 
#endif
1398
 
            engine = reload_db(engine, dboptions, opts, FALSE, &ret);
1399
 
            if(ret) {
1400
 
                logg("Terminating because of a fatal error.\n");
1401
 
                if(new_sd >= 0)
1402
 
                    closesocket(new_sd);
1403
 
                break;
1404
 
            }
1405
 
 
1406
 
            pthread_mutex_lock(&reload_mutex);
1407
 
            reload = 0;
1408
 
            time(&reloaded_time);
1409
 
            pthread_mutex_unlock(&reload_mutex);
1410
 
#if defined(FANOTIFY) || defined(CLAMAUTH)
1411
 
            if(optget(opts, "ScanOnAccess")->enabled && tharg) {
1412
 
                tharg->engine = engine;
1413
 
                pthread_create(&fan_pid, &fan_attr, fan_th, tharg);
1414
 
            }
1415
 
#endif
1416
 
            time(&start_time);
1417
 
        } else {
1418
 
            pthread_mutex_unlock(&reload_mutex);
1419
 
        }
1420
 
    }
1421
 
 
1422
 
    pthread_mutex_lock(&exit_mutex);
1423
 
    progexit = 1;
1424
 
    pthread_mutex_unlock(&exit_mutex);
1425
 
#ifdef _WIN32
1426
 
    SetEvent(event_wake_accept);
1427
 
#else
1428
 
    if (write(acceptdata.syncpipe_wake_accept[1], "", 1) < 0) {
1429
 
        logg("^Write to syncpipe failed\n");
1430
 
    }
1431
 
#endif
1432
 
    /* Destroy the thread manager.
1433
 
     * This waits for all current tasks to end
1434
 
     */
1435
 
    logg("*Waiting for all threads to finish\n");
1436
 
    thrmgr_destroy(thr_pool);
1437
 
#if defined(FANOTIFY) || defined(CLAMAUTH)
1438
 
    if(optget(opts, "ScanOnAccess")->enabled && tharg) {
1439
 
        logg("Stopping on-access scan\n");
1440
 
        pthread_mutex_lock(&logg_mutex);
1441
 
        pthread_kill(fan_pid, SIGUSR1);
1442
 
        pthread_mutex_unlock(&logg_mutex);
1443
 
        pthread_join(fan_pid, NULL);
1444
 
    free(tharg);
1445
 
    }
1446
 
#endif
1447
 
    if(engine) {
1448
 
        thrmgr_setactiveengine(NULL);
1449
 
        cl_engine_free(engine);
1450
 
    }
1451
 
 
1452
 
    pthread_join(accept_th, NULL);
1453
 
    fds_free(fds);
1454
 
    pthread_mutex_destroy(fds->buf_mutex);
1455
 
    pthread_cond_destroy(&acceptdata.cond_nfds);
1456
 
#ifdef _WIN32
1457
 
    CloseHandle(event_wake_accept);
1458
 
    CloseHandle(event_wake_recv);
1459
 
#else
1460
 
    close(acceptdata.syncpipe_wake_accept[1]);
1461
 
    close(acceptdata.syncpipe_wake_recv[1]);
1462
 
#endif
1463
 
    if(dbstat.entries)
1464
 
        cl_statfree(&dbstat);
1465
 
    logg("*Shutting down the main socket%s.\n", (nsockets > 1) ? "s" : "");
1466
 
    for (i = 0; i < nsockets; i++)
1467
 
        shutdown(socketds[i], 2);
1468
 
 
1469
 
    if((opt = optget(opts, "PidFile"))->enabled) {
1470
 
        if(unlink(opt->strarg) == -1)
1471
 
            logg("!Can't unlink the pid file %s\n", opt->strarg);
1472
 
        else
1473
 
            logg("Pid file removed.\n");
1474
 
    }
1475
 
 
1476
 
    time(&current_time);
1477
 
    logg("--- Stopped at %s", cli_ctime(&current_time, timestr, sizeof(timestr)));
1478
 
 
1479
 
    return ret;
1480
 
}