~ubuntu-branches/ubuntu/wily/clamav/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/0009-fix-ssize_t-size_t-off_t-printf-modifier.patch/clamd/clamd.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Sebastian Andrzej Siewior, Andreas Cadhalpun, Scott Kitterman, Javier Fernández-Sanguino
  • Date: 2015-01-28 00:25:13 UTC
  • mfrom: (0.48.14 sid)
  • Revision ID: package-import@ubuntu.com-20150128002513-lil2oi74cooy4lzr
Tags: 0.98.6+dfsg-1
[ Sebastian Andrzej Siewior ]
* update "fix-ssize_t-size_t-off_t-printf-modifier", include of misc.h was
  missing but was pulled in via the systemd patch.
* Don't leak return codes from libmspack to clamav API. (Closes: #774686).

[ Andreas Cadhalpun ]
* Add patch to avoid emitting incremental progress messages when not
  outputting to a terminal. (Closes: #767350)
* Update lintian-overrides for unused-file-paragraph-in-dep5-copyright.
* clamav-base.postinst: always chown /var/log/clamav and /var/lib/clamav
  to clamav:clamav, not only on fresh installations. (Closes: #775400)
* Adapt the clamav-daemon and clamav-freshclam logrotate scripts,
  so that they correctly work under systemd.
* Move the PidFile variable from the clamd/freshclam configuration files
  to the init scripts. This makes the init scripts more robust against
  misconfiguration and avoids error messages with systemd. (Closes: #767353)
* debian/copyright: drop files from Files-Excluded only present in github
  tarballs
* Drop Workaround-a-bug-in-libc-on-Hurd.patch, because hurd got fixed.
  (see #752237)
* debian/rules: Remove useless --with-system-tommath --without-included-ltdl
  configure options.

[ Scott Kitterman ]
* Stop stripping llvm when repacking the tarball as the system llvm on some
  releases is too old to use
* New upstream bugfix release
  - Library shared object revisions.
  - Includes a patch from Sebastian Andrzej Siewior making ClamAV pid files
    compatible with systemd.
  - Fix a heap out of bounds condition with crafted Yoda's crypter files.
    This issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted mew packer files. This
    issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted upx packer files. This
    issue was discovered by Kevin Szkudlapski of Quarkslab.
  - Fix a heap out of bounds condition with crafted upack packer files. This
    issue was discovered by Sebastian Andrzej Siewior. CVE-2014-9328.
  - Compensate a crash due to incorrect compiler optimization when handling
    crafted petite packer files. This issue was discovered by Sebastian
    Andrzej Siewior.
* Update lintian override for embedded zlib to match new so version

[ Javier Fernández-Sanguino ]
* Updated Spanish Debconf template translation (Closes: #773563)

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
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 version 2 as
8
 
 *  published by the Free Software Foundation.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 
 *  MA 02110-1301, USA.
19
 
 */
20
 
 
21
 
#if HAVE_CONFIG_H
22
 
#include "clamav-config.h"
23
 
#endif
24
 
 
25
 
#include <stdio.h>
26
 
#include <stdlib.h>
27
 
#include <string.h>
28
 
#ifdef HAVE_UNISTD_H
29
 
#include <unistd.h>
30
 
#endif
31
 
#ifndef _WIN32
32
 
#include <sys/time.h>
33
 
#include <sys/resource.h>
34
 
#endif
35
 
#include <sys/types.h>
36
 
#include <sys/stat.h>
37
 
#include <fcntl.h>
38
 
#include <time.h>
39
 
#ifdef HAVE_PWD_H
40
 
#include <pwd.h>
41
 
#endif
42
 
#ifdef HAVE_GRP_H
43
 
#include <grp.h>
44
 
#endif
45
 
#include <signal.h>
46
 
#include <errno.h>
47
 
 
48
 
#if defined(USE_SYSLOG) && !defined(C_AIX)
49
 
#include <syslog.h>
50
 
#endif
51
 
 
52
 
#ifdef C_LINUX
53
 
#include <sys/resource.h>
54
 
#endif
55
 
 
56
 
#include "target.h"
57
 
 
58
 
#include "libclamav/clamav.h"
59
 
#include "libclamav/others.h"
60
 
#include "libclamav/matcher-ac.h"
61
 
#include "libclamav/readdb.h"
62
 
 
63
 
#include "shared/output.h"
64
 
#include "shared/optparser.h"
65
 
#include "shared/misc.h"
66
 
 
67
 
#include "server.h"
68
 
#include "tcpserver.h"
69
 
#include "localserver.h"
70
 
#include "others.h"
71
 
#include "shared.h"
72
 
#include "scanner.h"
73
 
 
74
 
short debug_mode = 0, logok = 0;
75
 
short foreground = -1;
76
 
char hostid[37];
77
 
 
78
 
char *get_hostid(void *cbdata);
79
 
int is_valid_hostid(void);
80
 
 
81
 
static void help(void)
82
 
{
83
 
    printf("\n");
84
 
    printf("                      Clam AntiVirus Daemon %s\n", get_version());
85
 
    printf("           By The ClamAV Team: http://www.clamav.net/about.html#credits\n");
86
 
    printf("           (C) 2007-2009 Sourcefire, Inc.\n\n");
87
 
 
88
 
    printf("    --help                   -h             Show this help.\n");
89
 
    printf("    --version                -V             Show version number.\n");
90
 
    printf("    --debug                                 Enable debug mode.\n");
91
 
    printf("    --config-file=FILE       -c FILE        Read configuration from FILE.\n\n");
92
 
}
93
 
 
94
 
static struct optstruct *opts;
95
 
 
96
 
/* When running under valgrind and daemonizing, valgrind incorrectly reports
97
 
 * leaks from the engine, because it can't see that all the memory is still
98
 
 * reachable (some pointers are stored mangled in the JIT). 
99
 
 * So free the engine on exit from the parent too (during daemonize)
100
 
 */
101
 
static struct cl_engine *gengine = NULL;
102
 
static void free_engine(void)
103
 
{
104
 
    if (gengine) {
105
 
        cl_engine_free(gengine);
106
 
        gengine = NULL;
107
 
    }
108
 
}
109
 
 
110
 
int main(int argc, char **argv)
111
 
{
112
 
    static struct cl_engine *engine = NULL;
113
 
    const struct optstruct *opt;
114
 
#ifndef _WIN32
115
 
    struct passwd *user = NULL;
116
 
    struct sigaction sa;
117
 
    struct rlimit rlim;
118
 
#endif
119
 
    time_t currtime;
120
 
    const char *dbdir, *cfgfile;
121
 
    char *pua_cats = NULL, *pt;
122
 
    int ret, tcpsock = 0, localsock = 0, min_port, max_port;
123
 
    unsigned int sigs = 0;
124
 
    int *lsockets=NULL;
125
 
    unsigned int nlsockets = 0;
126
 
    unsigned int dboptions = 0;
127
 
    unsigned int i;
128
 
#ifdef C_LINUX
129
 
    STATBUF sb;
130
 
#endif
131
 
 
132
 
    if(check_flevel())
133
 
        exit(1);
134
 
 
135
 
#ifndef _WIN32
136
 
    memset(&sa, 0, sizeof(sa));
137
 
    sa.sa_handler = SIG_IGN;
138
 
    sigaction(SIGHUP, &sa, NULL);
139
 
    sigaction(SIGUSR2, &sa, NULL);
140
 
#endif
141
 
 
142
 
    if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
143
 
        mprintf("!Can't parse command line options\n");
144
 
        return 1;
145
 
    }
146
 
 
147
 
    if(optget(opts, "help")->enabled) {
148
 
        help();
149
 
        optfree(opts);
150
 
        return 0;
151
 
    }
152
 
 
153
 
    if(optget(opts, "debug")->enabled) {
154
 
#if defined(C_LINUX)
155
 
        /* njh@bandsman.co.uk: create a dump if needed */
156
 
        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
157
 
        if(setrlimit(RLIMIT_CORE, &rlim) < 0)
158
 
            perror("setrlimit");
159
 
#endif
160
 
        debug_mode = 1;
161
 
    }
162
 
 
163
 
    /* check foreground option from command line to override config file */
164
 
    int j;
165
 
    for(j = 0; j < argc; j += 1)
166
 
    {
167
 
        if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
168
 
        {
169
 
            /* found */
170
 
            break;
171
 
        }
172
 
    }
173
 
 
174
 
    if (j < argc)
175
 
    {
176
 
        if(optget(opts, "Foreground")->enabled)
177
 
        {
178
 
            foreground = 1;
179
 
        }
180
 
        else
181
 
        {
182
 
            foreground = 0;
183
 
        }
184
 
    }
185
 
 
186
 
    int num_fd = sd_listen_fds(0);
187
 
 
188
 
    /* parse the config file */
189
 
    cfgfile = optget(opts, "config-file")->strarg;
190
 
    pt = strdup(cfgfile);
191
 
    if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
192
 
        fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
193
 
        free(pt);
194
 
        return 1;
195
 
    }
196
 
    free(pt);
197
 
 
198
 
    if(optget(opts, "version")->enabled) {
199
 
        print_version(optget(opts, "DatabaseDirectory")->strarg);
200
 
        optfree(opts);
201
 
        return 0;
202
 
    }
203
 
 
204
 
    /* drop privileges */
205
 
#ifndef _WIN32
206
 
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
207
 
        if((user = getpwnam(opt->strarg)) == NULL) {
208
 
            fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
209
 
            optfree(opts);
210
 
            return 1;
211
 
        }
212
 
 
213
 
        if(optget(opts, "AllowSupplementaryGroups")->enabled) {
214
 
#ifdef HAVE_INITGROUPS
215
 
            if(initgroups(opt->strarg, user->pw_gid)) {
216
 
                fprintf(stderr, "ERROR: initgroups() failed.\n");
217
 
                optfree(opts);
218
 
                return 1;
219
 
            }
220
 
#else
221
 
            mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups in %s\n", cfgfile);
222
 
            optfree(opts);
223
 
            return 1;
224
 
#endif
225
 
        } else {
226
 
#ifdef HAVE_SETGROUPS
227
 
            if(setgroups(1, &user->pw_gid)) {
228
 
                fprintf(stderr, "ERROR: setgroups() failed.\n");
229
 
                optfree(opts);
230
 
                return 1;
231
 
            }
232
 
#endif
233
 
        }
234
 
 
235
 
        if(setgid(user->pw_gid)) {
236
 
            fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
237
 
            optfree(opts);
238
 
            return 1;
239
 
        }
240
 
 
241
 
        if(setuid(user->pw_uid)) {
242
 
            fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
243
 
            optfree(opts);
244
 
            return 1;
245
 
        }
246
 
    }
247
 
#endif
248
 
 
249
 
    /* initialize logger */
250
 
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
251
 
    logg_time = optget(opts, "LogTime")->enabled;
252
 
    logok = optget(opts, "LogClean")->enabled;
253
 
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
254
 
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
255
 
    if (logg_size)
256
 
        logg_rotate = optget(opts, "LogRotate")->enabled;
257
 
    mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;
258
 
 
259
 
    do { /* logger initialized */
260
 
        if((opt = optget(opts, "LogFile"))->enabled) {
261
 
            char timestr[32];
262
 
            logg_file = opt->strarg;
263
 
            if(!cli_is_abspath(logg_file)) {
264
 
                fprintf(stderr, "ERROR: LogFile requires full path.\n");
265
 
                ret = 1;
266
 
                break;
267
 
            }
268
 
            time(&currtime);
269
 
            if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
270
 
                fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
271
 
                ret = 1;
272
 
                break;
273
 
            }
274
 
        } else {
275
 
            logg_file = NULL;
276
 
        }
277
 
 
278
 
        if (optget(opts,"DevLiblog")->enabled)
279
 
            cl_set_clcb_msg(msg_callback);
280
 
 
281
 
        if((ret = cl_init(CL_INIT_DEFAULT))) {
282
 
            logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
283
 
            ret = 1;
284
 
            break;
285
 
        }
286
 
 
287
 
        if(optget(opts, "Debug")->enabled) {
288
 
            /* enable debug messages in libclamav */
289
 
            cl_debug();
290
 
            logg_verbose = 2;
291
 
        }
292
 
 
293
 
#if defined(USE_SYSLOG) && !defined(C_AIX)
294
 
        if(optget(opts, "LogSyslog")->enabled) {
295
 
            int fac = LOG_LOCAL6;
296
 
 
297
 
            opt = optget(opts, "LogFacility");
298
 
            if((fac = logg_facility(opt->strarg)) == -1) {
299
 
                logg("!LogFacility: %s: No such facility.\n", opt->strarg);
300
 
                ret = 1;
301
 
                break;
302
 
            }
303
 
 
304
 
            openlog("clamd", LOG_PID, fac);
305
 
            logg_syslog = 1;
306
 
        }
307
 
#endif
308
 
 
309
 
#ifdef C_LINUX
310
 
        procdev = 0;
311
 
        if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
312
 
            procdev = sb.st_dev;
313
 
#endif
314
 
 
315
 
        /* check socket type */
316
 
 
317
 
        if(optget(opts, "TCPSocket")->enabled)
318
 
            tcpsock = 1;
319
 
 
320
 
        if(optget(opts, "LocalSocket")->enabled)
321
 
            localsock = 1;
322
 
 
323
 
        logg("#Received %d file descriptor(s) from systemd.\n", num_fd);
324
 
 
325
 
        if(!tcpsock && !localsock && num_fd == 0) {
326
 
            logg("!Please define server type (local and/or TCP).\n");
327
 
            ret = 1;
328
 
            break;
329
 
        }
330
 
 
331
 
        logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());
332
 
 
333
 
#ifndef _WIN32
334
 
        if(user)
335
 
            logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
336
 
#endif
337
 
 
338
 
#if defined(RLIMIT_DATA) && defined(C_BSD)
339
 
        if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
340
 
           /* bb #1941.
341
 
            * On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail
342
 
            * too soon (after ~120 MB).
343
 
            * Set limit lower than 2G if on 32-bit */
344
 
           uint64_t lim = rlim.rlim_cur;
345
 
           if (sizeof(void*) == 4 &&
346
 
               lim > (1ULL << 31)) {
347
 
               rlim.rlim_cur = 1ULL << 31;
348
 
               if (setrlimit(RLIMIT_DATA, &rlim) < 0)
349
 
                   logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
350
 
               else
351
 
                   logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
352
 
           }
353
 
        }
354
 
#endif
355
 
 
356
 
 
357
 
        if(logg_size)
358
 
            logg("#Log file size limited to %u bytes.\n", logg_size);
359
 
        else
360
 
            logg("#Log file size limit disabled.\n");
361
 
 
362
 
        min_port = optget(opts, "StreamMinPort")->numarg;
363
 
        max_port = optget(opts, "StreamMaxPort")->numarg;
364
 
        if (min_port < 1024 || min_port > max_port || max_port > 65535) {
365
 
            logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
366
 
            ret = 1;
367
 
            break;
368
 
        }
369
 
 
370
 
        if(!(engine = cl_engine_new())) {
371
 
            logg("!Can't initialize antivirus engine\n");
372
 
            ret = 1;
373
 
            break;
374
 
        }
375
 
 
376
 
        if (optget(opts, "disable-cache")->enabled)
377
 
            cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1);
378
 
 
379
 
        /* load the database(s) */
380
 
        dbdir = optget(opts, "DatabaseDirectory")->strarg;
381
 
        logg("#Reading databases from %s\n", dbdir);
382
 
 
383
 
        if(optget(opts, "DetectPUA")->enabled) {
384
 
            dboptions |= CL_DB_PUA;
385
 
 
386
 
            if((opt = optget(opts, "ExcludePUA"))->enabled) {
387
 
                dboptions |= CL_DB_PUA_EXCLUDE;
388
 
                i = 0;
389
 
                logg("#Excluded PUA categories:");
390
 
 
391
 
                while(opt) {
392
 
                    if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
393
 
                        logg("!Can't allocate memory for pua_cats\n");
394
 
                        cl_engine_free(engine);
395
 
                        ret = 1;
396
 
                        break;
397
 
                    }
398
 
 
399
 
                    logg("# %s", opt->strarg);
400
 
 
401
 
                    sprintf(pua_cats + i, ".%s", opt->strarg);
402
 
                    i += strlen(opt->strarg) + 1;
403
 
                    pua_cats[i] = 0;
404
 
                    opt = opt->nextarg;
405
 
                }
406
 
 
407
 
                if (ret)
408
 
                    break;
409
 
 
410
 
                logg("#\n");
411
 
                pua_cats[i] = '.';
412
 
                pua_cats[i + 1] = 0;
413
 
            }
414
 
 
415
 
            if((opt = optget(opts, "IncludePUA"))->enabled) {
416
 
                if(pua_cats) {
417
 
                    logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
418
 
                    free(pua_cats);
419
 
                    ret = 1;
420
 
                    break;
421
 
                }
422
 
 
423
 
                dboptions |= CL_DB_PUA_INCLUDE;
424
 
                i = 0;
425
 
                logg("#Included PUA categories:");
426
 
                while(opt) {
427
 
                    if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
428
 
                        logg("!Can't allocate memory for pua_cats\n");
429
 
                        ret = 1;
430
 
                        break;
431
 
                    }
432
 
 
433
 
                    logg("# %s", opt->strarg);
434
 
 
435
 
                    sprintf(pua_cats + i, ".%s", opt->strarg);
436
 
                    i += strlen(opt->strarg) + 1;
437
 
                    pua_cats[i] = 0;
438
 
                    opt = opt->nextarg;
439
 
                }
440
 
 
441
 
                if (ret)
442
 
                    break;
443
 
 
444
 
                logg("#\n");
445
 
                pua_cats[i] = '.';
446
 
                pua_cats[i + 1] = 0;
447
 
            }
448
 
 
449
 
            if(pua_cats) {
450
 
                if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
451
 
                    logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
452
 
                    free(pua_cats);
453
 
                    ret = 1;
454
 
                    break;
455
 
                }
456
 
                free(pua_cats);
457
 
            }
458
 
        } else {
459
 
            logg("#Not loading PUA signatures.\n");
460
 
        }
461
 
 
462
 
        if (optget(opts, "StatsEnabled")->enabled) {
463
 
            cl_engine_stats_enable(engine);
464
 
        }
465
 
 
466
 
        if (optget(opts, "StatsPEDisabled")->enabled) {
467
 
            cl_engine_set_num(engine, CL_ENGINE_DISABLE_PE_STATS, 1);
468
 
        }
469
 
 
470
 
        if (optget(opts, "StatsTimeout")->enabled) {
471
 
            cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg);
472
 
        }
473
 
 
474
 
        if (optget(opts, "StatsHostID")->enabled) {
475
 
            char *p = optget(opts, "StatsHostID")->strarg;
476
 
 
477
 
            if (strcmp(p, "default")) {
478
 
                if (!strcmp(p, "none")) {
479
 
                    cl_engine_set_clcb_stats_get_hostid(engine, NULL);
480
 
                } else if (!strcmp(p, "anonymous")) {
481
 
                    strcpy(hostid, STATS_ANON_UUID);
482
 
                } else {
483
 
                    if (strlen(p) > 36) {
484
 
                        logg("!Invalid HostID\n");
485
 
                        cl_engine_set_clcb_stats_submit(engine, NULL);
486
 
                        cl_engine_free(engine);
487
 
                        ret = 1;
488
 
                        break;
489
 
                    }
490
 
 
491
 
                    strcpy(hostid, p);
492
 
                }
493
 
 
494
 
                cl_engine_set_clcb_stats_get_hostid(engine, get_hostid);
495
 
            }
496
 
        }
497
 
 
498
 
        if(optget(opts, "OfficialDatabaseOnly")->enabled) {
499
 
            dboptions |= CL_DB_OFFICIAL_ONLY;
500
 
            logg("#Only loading official signatures.\n");
501
 
        }
502
 
 
503
 
        /* set the temporary dir */
504
 
        if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
505
 
            if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
506
 
                logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
507
 
                ret = 1;
508
 
                break;
509
 
            }
510
 
        }
511
 
 
512
 
        cl_engine_set_clcb_hash(engine, hash_callback);
513
 
 
514
 
        if(optget(opts, "LeaveTemporaryFiles")->enabled)
515
 
            cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);
516
 
 
517
 
        if(optget(opts, "ForceToDisk")->enabled)
518
 
            cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1);
519
 
 
520
 
        if(optget(opts, "PhishingSignatures")->enabled)
521
 
            dboptions |= CL_DB_PHISHING;
522
 
        else
523
 
            logg("#Not loading phishing signatures.\n");
524
 
 
525
 
        if(optget(opts,"Bytecode")->enabled) {
526
 
            dboptions |= CL_DB_BYTECODE;
527
 
            if((opt = optget(opts,"BytecodeSecurity"))->enabled) {
528
 
                enum bytecode_security s;
529
 
 
530
 
                if (!strcmp(opt->strarg, "TrustSigned")) {
531
 
                    s = CL_BYTECODE_TRUST_SIGNED;
532
 
                    logg("#Bytecode: Security mode set to \"TrustSigned\".\n");
533
 
                } else if (!strcmp(opt->strarg, "Paranoid")) {
534
 
                    s = CL_BYTECODE_TRUST_NOTHING;
535
 
                    logg("#Bytecode: Security mode set to \"Paranoid\".\n");
536
 
                } else {
537
 
                    logg("!Unable to parse bytecode security setting:%s\n",
538
 
                        opt->strarg);
539
 
                    ret = 1;
540
 
                    break;
541
 
                }
542
 
 
543
 
                if ((ret = cl_engine_set_num(engine, CL_ENGINE_BYTECODE_SECURITY, s))) {
544
 
                    logg("^Invalid bytecode security setting %s: %s\n", opt->strarg, cl_strerror(ret));
545
 
                    ret = 1;
546
 
                    break;
547
 
                }
548
 
            }
549
 
            if((opt = optget(opts,"BytecodeUnsigned"))->enabled) {
550
 
                dboptions |= CL_DB_BYTECODE_UNSIGNED;
551
 
                logg("#Bytecode: Enabled support for unsigned bytecode.\n");
552
 
            }
553
 
 
554
 
            if((opt = optget(opts,"BytecodeMode"))->enabled) {
555
 
                enum bytecode_mode mode;
556
 
 
557
 
                if (!strcmp(opt->strarg, "ForceJIT"))
558
 
                    mode = CL_BYTECODE_MODE_JIT;
559
 
                else if(!strcmp(opt->strarg, "ForceInterpreter"))
560
 
                    mode = CL_BYTECODE_MODE_INTERPRETER;
561
 
                else if(!strcmp(opt->strarg, "Test"))
562
 
                    mode = CL_BYTECODE_MODE_TEST;
563
 
                else
564
 
                    mode = CL_BYTECODE_MODE_AUTO;
565
 
                cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode);
566
 
            }
567
 
 
568
 
            if((opt = optget(opts,"BytecodeTimeout"))->enabled) {
569
 
                cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg);
570
 
            }
571
 
        } else {
572
 
            logg("#Bytecode support disabled.\n");
573
 
        }
574
 
 
575
 
        if(optget(opts,"PhishingScanURLs")->enabled)
576
 
            dboptions |= CL_DB_PHISHING_URLS;
577
 
        else
578
 
            logg("#Disabling URL based phishing detection.\n");
579
 
 
580
 
        if(optget(opts,"DevACOnly")->enabled) {
581
 
            logg("#Only using the A-C matcher.\n");
582
 
            cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
583
 
        }
584
 
 
585
 
        if((opt = optget(opts, "DevACDepth"))->enabled) {
586
 
            cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
587
 
            logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
588
 
        }
589
 
 
590
 
        if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
591
 
            logg("!%s\n", cl_strerror(ret));
592
 
            ret = 1;
593
 
            break;
594
 
        }
595
 
 
596
 
        if (optget(opts, "DisableCertCheck")->enabled)
597
 
            engine->dconf->pe |= PE_CONF_DISABLECERT;
598
 
 
599
 
        logg("#Loaded %u signatures.\n", sigs);
600
 
 
601
 
        if((ret = cl_engine_compile(engine)) != 0) {
602
 
            logg("!Database initialization error: %s\n", cl_strerror(ret));
603
 
            ret = 1;
604
 
            break;
605
 
        }
606
 
 
607
 
        if(tcpsock || num_fd > 0) {
608
 
            int *t;
609
 
 
610
 
            opt = optget(opts, "TCPAddr");
611
 
            if (opt->enabled) {
612
 
                int breakout = 0;
613
 
 
614
 
                while (opt && opt->strarg) {
615
 
                    char *ipaddr = (!strcmp(opt->strarg, "all") ? NULL : opt->strarg);
616
 
 
617
 
                    if (tcpserver(&lsockets, &nlsockets, ipaddr, opts) == -1) {
618
 
                        ret = 1;
619
 
                        breakout = 1;
620
 
                        break;
621
 
                    }
622
 
 
623
 
                    opt = opt->nextarg;
624
 
                }
625
 
 
626
 
                if (breakout)
627
 
                    break;
628
 
            } else {
629
 
                if (tcpserver(&lsockets, &nlsockets, NULL, opts) == -1) {
630
 
                    ret = 1;
631
 
                    break;
632
 
                }
633
 
            }
634
 
        }
635
 
#ifndef _WIN32
636
 
        if(localsock && num_fd == 0) {
637
 
            int *t;
638
 
            mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */
639
 
 
640
 
            t = realloc(lsockets, sizeof(int) * (nlsockets + 1));
641
 
            if (!(t)) {
642
 
                ret = 1;
643
 
                break;
644
 
            }
645
 
            lsockets = t;
646
 
 
647
 
            if ((lsockets[nlsockets] = localserver(opts)) == -1) {
648
 
                ret = 1;
649
 
                umask(umsk);
650
 
                break;
651
 
            }
652
 
            umask(umsk); /* restore umask */
653
 
 
654
 
            if(optget(opts, "LocalSocketGroup")->enabled) {
655
 
                char *gname = optget(opts, "LocalSocketGroup")->strarg, *end;
656
 
                gid_t sock_gid = strtol(gname, &end, 10);
657
 
 
658
 
                if(*end) {
659
 
                    struct group *pgrp = getgrnam(gname);
660
 
 
661
 
                    if(!pgrp) {
662
 
                        logg("!Unknown group %s\n", gname);
663
 
                        ret = 1;
664
 
                        break;
665
 
                    }
666
 
 
667
 
                    sock_gid = pgrp->gr_gid;
668
 
                }
669
 
                if(chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) {
670
 
                    logg("!Failed to change socket ownership to group %s\n", gname);
671
 
                    ret = 1;
672
 
                    break;
673
 
                }
674
 
            }
675
 
            if(optget(opts, "LocalSocketMode")->enabled) {
676
 
                char *end;
677
 
 
678
 
                sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8);
679
 
 
680
 
                if(*end) {
681
 
                    logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg);
682
 
                    ret = 1;
683
 
                    break;
684
 
                }
685
 
            } else {
686
 
                sock_mode = 0777 /* & ~umsk*/; /* conservative default: umask was 0 in clamd < 0.96 */
687
 
            }
688
 
 
689
 
            if(chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) {
690
 
                logg("!Cannot set socket permission to %s\n", optget(opts, "LocalSocketMode")->strarg);
691
 
                ret = 1;
692
 
                break;
693
 
            }
694
 
 
695
 
            nlsockets++;
696
 
        }
697
 
 
698
 
        /* check for local sockets passed by systemd */
699
 
        if (num_fd > 0)
700
 
        {
701
 
            int *t;
702
 
            t = realloc(lsockets, sizeof(int) * (nlsockets + 1));
703
 
            if (!(t)) {
704
 
                ret = 1;
705
 
                break;
706
 
            }
707
 
            lsockets = t;
708
 
 
709
 
            lsockets[nlsockets] = localserver(opts);
710
 
            if (lsockets[nlsockets] == -1)
711
 
            {
712
 
                ret = 1;
713
 
                break;
714
 
            }
715
 
            else if (lsockets[nlsockets] > 0)
716
 
            {
717
 
                nlsockets++;
718
 
            }
719
 
        }
720
 
 
721
 
        /* fork into background */
722
 
        if (foreground == -1)
723
 
        {
724
 
            if (optget(opts, "Foreground")->enabled)
725
 
            {
726
 
                foreground = 1;
727
 
            }
728
 
            else
729
 
            {
730
 
                foreground = 0;
731
 
            }
732
 
        }
733
 
        if(foreground == 0)
734
 
        {
735
 
#ifdef C_BSD        
736
 
            /* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
737
 
            for(ret=0;(unsigned int)ret<nlsockets;ret++) {
738
 
                if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK) == -1) {
739
 
                    logg("!fcntl for lsockets[] failed\n");
740
 
                    close(lsockets[ret]);
741
 
                    ret = 1;
742
 
                    break;
743
 
                }
744
 
            }
745
 
#endif
746
 
            gengine = engine;
747
 
            atexit(free_engine);
748
 
            if(daemonize() == -1) {
749
 
                logg("!daemonize() failed: %s\n", strerror(errno));
750
 
                ret = 1;
751
 
                break;
752
 
            }
753
 
            gengine = NULL;
754
 
#ifdef C_BSD
755
 
            for(ret=0;(unsigned int)ret<nlsockets;ret++) {
756
 
                if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK) == -1) {
757
 
                    logg("!fcntl for lsockets[] failed\n");
758
 
                    close(lsockets[ret]);
759
 
                    ret = 1;
760
 
                    break;
761
 
                }
762
 
            }
763
 
#endif
764
 
            if(!debug_mode)
765
 
                if(chdir("/") == -1)
766
 
                    logg("^Can't change current working directory to root\n");
767
 
 
768
 
        }
769
 
#endif
770
 
 
771
 
        if (nlsockets == 0) {
772
 
            logg("!Not listening on any interfaces\n");
773
 
            ret = 1;
774
 
            break;
775
 
        }
776
 
 
777
 
        ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);
778
 
 
779
 
    } while (0);
780
 
 
781
 
    if (num_fd == 0)
782
 
    {
783
 
        logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");
784
 
 
785
 
        for (i = 0; i < nlsockets; i++) {
786
 
            closesocket(lsockets[i]);
787
 
        }
788
 
#ifndef _WIN32
789
 
        if(nlsockets && localsock) {
790
 
            opt = optget(opts, "LocalSocket");
791
 
 
792
 
            if(unlink(opt->strarg) == -1)
793
 
                logg("!Can't unlink the socket file %s\n", opt->strarg);
794
 
            else
795
 
                logg("Socket file removed.\n");
796
 
        }
797
 
#endif
798
 
    }
799
 
 
800
 
    free(lsockets);
801
 
 
802
 
    logg_close();
803
 
    optfree(opts);
804
 
 
805
 
    cl_cleanup_crypto();
806
 
 
807
 
    return ret;
808
 
}
809
 
 
810
 
int is_valid_hostid(void)
811
 
{
812
 
    int count, i;
813
 
 
814
 
    if (strlen(hostid) != 36)
815
 
        return 0;
816
 
 
817
 
    count=0;
818
 
    for (i=0; i < 36; i++)
819
 
        if (hostid[i] == '-')
820
 
            count++;
821
 
 
822
 
    if (count != 4)
823
 
        return 0;
824
 
 
825
 
    if (hostid[8] != '-' || hostid[13] != '-' || hostid[18] != '-' || hostid[23] != '-')
826
 
        return 0;
827
 
 
828
 
    return 1;
829
 
}
830
 
 
831
 
char *get_hostid(void *cbdata)
832
 
{
833
 
    UNUSEDPARAM(cbdata);
834
 
 
835
 
    if (!strcmp(hostid, "none"))
836
 
        return NULL;
837
 
 
838
 
    if (!is_valid_hostid())
839
 
        return strdup(STATS_ANON_UUID);
840
 
 
841
 
    return strdup(hostid);
842
 
}