~vcs-imports/clamav/main-old

« back to all changes in this revision

Viewing changes to clamd/clamd.c

  • Committer: nervoso
  • Date: 2006-05-21 15:16:39 UTC
  • Revision ID: Arch-1:clamav@arch.ubuntu.com%clamav--MAIN--0--patch-1959
repository moved to cvs.clamav.net

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3
 
 *
4
 
 *  This program is free software; you can redistribute it and/or modify
5
 
 *  it under the terms of the GNU General Public License as published by
6
 
 *  the Free Software Foundation; either version 2 of the License, or
7
 
 *  (at your option) any later version.
8
 
 *
9
 
 *  This program is distributed in the hope that it will be useful,
10
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 *  GNU General Public License for more details.
13
 
 *
14
 
 *  You should have received a copy of the GNU General Public License
15
 
 *  along with this program; if not, write to the Free Software
16
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
 
 *  MA 02110-1301, USA.
18
 
 */
19
 
 
20
 
#if HAVE_CONFIG_H
21
 
#include "clamav-config.h"
22
 
#endif
23
 
 
24
 
#include <stdio.h>
25
 
#include <stdlib.h>
26
 
#include <string.h>
27
 
#include <unistd.h>
28
 
#include <sys/time.h>
29
 
#include <sys/types.h>
30
 
#include <sys/stat.h>
31
 
#include <fcntl.h>
32
 
#include <time.h>
33
 
#include <pwd.h>
34
 
#include <grp.h>
35
 
#include <clamav.h>
36
 
 
37
 
#if defined(USE_SYSLOG) && !defined(C_AIX)
38
 
#include <syslog.h>
39
 
#endif
40
 
 
41
 
#ifdef C_LINUX
42
 
#include <sys/resource.h>
43
 
#endif
44
 
 
45
 
#include "options.h"
46
 
#include "cfgparser.h"
47
 
#include "others.h"
48
 
/* Fixes gcc warning */
49
 
#include "../libclamav/others.h"
50
 
#include "tcpserver.h"
51
 
#include "localserver.h"
52
 
#include "others.h"
53
 
#include "memory.h"
54
 
#include "output.h"
55
 
#include "shared.h"
56
 
#include "target.h"
57
 
#include "misc.h"
58
 
 
59
 
void help(void);
60
 
void daemonize(void);
61
 
 
62
 
short debug_mode = 0, logok = 0;
63
 
 
64
 
short foreground = 0;
65
 
 
66
 
void clamd(struct optstruct *opt)
67
 
{
68
 
        struct cfgstruct *copt, *cpt;
69
 
        struct passwd *user;
70
 
        time_t currtime;
71
 
        struct cl_node *root = NULL;
72
 
        const char *dbdir, *cfgfile;
73
 
        int ret, virnum = 0, tcpsock = 0, localsock = 0;
74
 
        int lsockets[2], nlsockets = 0;
75
 
        unsigned int dboptions = 0;
76
 
#ifdef C_LINUX
77
 
        struct stat sb;
78
 
#endif
79
 
 
80
 
    /* initialize some important variables */
81
 
 
82
 
    if(optc(opt, 'V')) {
83
 
        print_version();
84
 
        exit(0);
85
 
    }
86
 
 
87
 
    if(optc(opt, 'h')) {
88
 
        help();
89
 
    }
90
 
 
91
 
    if(optl(opt, "debug")) {
92
 
#if defined(C_LINUX)
93
 
            /* njh@bandsman.co.uk: create a dump if needed */
94
 
            struct rlimit rlim;
95
 
 
96
 
        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
97
 
        if(setrlimit(RLIMIT_CORE, &rlim) < 0)
98
 
            perror("setrlimit");
99
 
#endif
100
 
        debug_mode = 1;
101
 
 
102
 
    }
103
 
 
104
 
    /* parse the config file */
105
 
    if(optc(opt, 'c'))
106
 
        cfgfile = getargc(opt, 'c');
107
 
    else
108
 
        cfgfile = CONFDIR"/clamd.conf";
109
 
 
110
 
    if((copt = getcfg(cfgfile, 1)) == NULL) {
111
 
        fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", cfgfile);
112
 
        exit(1);
113
 
    }
114
 
 
115
 
    umask(0);
116
 
 
117
 
    /* drop privileges */
118
 
#ifndef C_OS2
119
 
    if(geteuid() == 0 && (cpt = cfgopt(copt, "User"))->enabled) {
120
 
        if((user = getpwnam(cpt->strarg)) == NULL) {
121
 
            fprintf(stderr, "ERROR: Can't get information about user %s.\n", cpt->strarg);
122
 
            logg("!Can't get information about user %s.\n", cpt->strarg);
123
 
            exit(1);
124
 
        }
125
 
 
126
 
        if(cfgopt(copt, "AllowSupplementaryGroups")->enabled) {
127
 
#ifdef HAVE_INITGROUPS
128
 
            if(initgroups(cpt->strarg, user->pw_gid)) {
129
 
                fprintf(stderr, "ERROR: initgroups() failed.\n");
130
 
                logg("!initgroups() failed.\n");
131
 
                exit(1);
132
 
            }
133
 
#else
134
 
            logg("AllowSupplementaryGroups: initgroups() not supported.\n");
135
 
#endif
136
 
        } else {
137
 
#ifdef HAVE_SETGROUPS
138
 
            if(setgroups(1, &user->pw_gid)) {
139
 
                fprintf(stderr, "ERROR: setgroups() failed.\n");
140
 
                logg("!setgroups() failed.\n");
141
 
                exit(1);
142
 
            }
143
 
#endif
144
 
        }
145
 
 
146
 
        if(setgid(user->pw_gid)) {
147
 
            fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
148
 
            logg("!setgid(%d) failed.\n", (int) user->pw_gid);
149
 
            exit(1);
150
 
        }
151
 
 
152
 
        if(setuid(user->pw_uid)) {
153
 
            fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
154
 
            logg("!setuid(%d) failed.\n", (int) user->pw_uid);
155
 
            exit(1);
156
 
        }
157
 
 
158
 
        logg("Running as user %s (UID %d, GID %d)\n", user->pw_name, user->pw_uid, user->pw_gid);
159
 
    }
160
 
#endif
161
 
 
162
 
    /* initialize logger */
163
 
 
164
 
    logg_lock = cfgopt(copt, "LogFileUnlock")->enabled;
165
 
    logg_time = cfgopt(copt, "LogTime")->enabled;
166
 
    logok = cfgopt(copt, "LogClean")->enabled;
167
 
    logg_size = cfgopt(copt, "LogFileMaxSize")->numarg;
168
 
    logg_verbose = mprintf_verbose = cfgopt(copt, "LogVerbose")->enabled;
169
 
 
170
 
    if(cfgopt(copt, "Debug")->enabled) /* enable debug messages in libclamav */
171
 
        cl_debug();
172
 
 
173
 
    if((cpt = cfgopt(copt, "LogFile"))->enabled) {
174
 
        logg_file = cpt->strarg;
175
 
        if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) {
176
 
            fprintf(stderr, "ERROR: LogFile requires full path.\n");
177
 
            exit(1);
178
 
        }
179
 
        time(&currtime);
180
 
        if(logg("+++ Started at %s", ctime(&currtime))) {
181
 
            fprintf(stderr, "ERROR: Problem with internal logger. Please check the permissions on the %s file.\n", logg_file);
182
 
            exit(1);
183
 
        }
184
 
    } else
185
 
        logg_file = NULL;
186
 
 
187
 
#if defined(USE_SYSLOG) && !defined(C_AIX)
188
 
    if(cfgopt(copt, "LogSyslog")->enabled) {
189
 
            int fac = LOG_LOCAL6;
190
 
 
191
 
        cpt = cfgopt(copt, "LogFacility");
192
 
        if((fac = logg_facility(cpt->strarg)) == -1) {
193
 
            fprintf(stderr, "ERROR: LogFacility: %s: No such facility.\n", cpt->strarg);
194
 
            exit(1);
195
 
        }
196
 
 
197
 
        openlog("clamd", LOG_PID, fac);
198
 
        logg_syslog = 1;
199
 
    }
200
 
#endif
201
 
 
202
 
    logg("clamd daemon "VERSION" (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n");
203
 
 
204
 
    if(logg_size)
205
 
        logg("Log file size limited to %d bytes.\n", logg_size);
206
 
    else
207
 
        logg("Log file size limit disabled.\n");
208
 
 
209
 
    logg("*Verbose logging activated.\n");
210
 
 
211
 
#ifdef C_LINUX
212
 
    procdev = 0;
213
 
    if(stat("/proc", &sb) != -1 && !sb.st_size)
214
 
        procdev = sb.st_dev;
215
 
#endif
216
 
 
217
 
    /* check socket type */
218
 
 
219
 
    if(cfgopt(copt, "TCPSocket")->enabled)
220
 
        tcpsock = 1;
221
 
 
222
 
    if(cfgopt(copt, "LocalSocket")->enabled)
223
 
        localsock = 1;
224
 
 
225
 
    if(!tcpsock && !localsock) {
226
 
        fprintf(stderr, "ERROR: You must select server type (local/tcp).\n");
227
 
        logg("!Please select server type (local/TCP).\n");
228
 
        exit(1);
229
 
    }
230
 
 
231
 
    /* set the temporary dir */
232
 
    if((cpt = cfgopt(copt, "TemporaryDirectory"))->enabled)
233
 
        cl_settempdir(cpt->strarg, 0);
234
 
 
235
 
    if(cfgopt(copt, "LeaveTemporaryFiles")->enabled)
236
 
        cl_settempdir(NULL, 1);
237
 
 
238
 
    /* load the database(s) */
239
 
    dbdir = cfgopt(copt, "DatabaseDirectory")->strarg;
240
 
    logg("Reading databases from %s\n", dbdir);
241
 
 
242
 
    if(!cfgopt(copt, "DetectPhishing")->enabled) {
243
 
        dboptions |= CL_DB_NOPHISHING;
244
 
        logg("Not loading phishing signatures.\n");
245
 
    }
246
 
 
247
 
    if((ret = cl_load(dbdir, &root, &virnum, dboptions))) {
248
 
        fprintf(stderr, "ERROR: %s\n", cl_strerror(ret));
249
 
        logg("!%s\n", cl_strerror(ret));
250
 
        exit(1);
251
 
    }
252
 
 
253
 
    if(!root) {
254
 
        fprintf(stderr, "ERROR: Database initialization error.\n");
255
 
        logg("!Database initialization error.\n");
256
 
        exit(1);
257
 
    }
258
 
 
259
 
    logg("Protecting against %d viruses.\n", virnum);
260
 
    if((ret = cl_build(root)) != 0) {
261
 
        fprintf(stderr, "ERROR: Database initialization error: %s\n", cl_strerror(ret));;
262
 
        logg("!Database initialization error: %s\n", cl_strerror(ret));;
263
 
        exit(1);
264
 
    }
265
 
 
266
 
 
267
 
    /* fork into background */
268
 
    if(!cfgopt(copt, "Foreground")->enabled)
269
 
        daemonize();
270
 
    else
271
 
        foreground = 1;
272
 
 
273
 
    if(tcpsock)
274
 
        lsockets[nlsockets++] = tcpserver(copt, root);
275
 
 
276
 
    if(localsock)
277
 
        lsockets[nlsockets++] = localserver(copt, root);
278
 
 
279
 
    ret = acceptloop_th(lsockets, nlsockets, root, copt);
280
 
 
281
 
    logg_close();
282
 
    freecfg(copt);
283
 
}
284
 
 
285
 
void help(void)
286
 
{
287
 
 
288
 
    printf("\n");
289
 
    printf("                      Clam AntiVirus Daemon "VERSION"\n");
290
 
    printf("    (C) 2002 - 2005 ClamAV Team - http://www.clamav.net/team.html\n\n");
291
 
 
292
 
    printf("    --help                   -h             Show this help.\n");
293
 
    printf("    --version                -V             Show version number.\n");
294
 
    printf("    --debug                                 Enable debug mode.\n");
295
 
    printf("    --config-file=FILE       -c FILE        Read configuration from FILE.\n\n");
296
 
 
297
 
    exit(0);
298
 
}
299
 
 
300
 
void daemonize(void)
301
 
{
302
 
        int i;
303
 
 
304
 
 
305
 
#ifdef C_OS2
306
 
    return;
307
 
#else
308
 
 
309
 
    if((i = open("/dev/null", O_WRONLY)) == -1) {
310
 
        logg("!Cannot open /dev/null. Only use Debug if Foreground is enabled.\n");
311
 
        for(i = 0; i <= 2; i++)
312
 
            close(i);
313
 
 
314
 
    } else {
315
 
        close(0);
316
 
        dup2(i, 1);
317
 
        dup2(i, 2);
318
 
    }
319
 
 
320
 
    if(!debug_mode)
321
 
        chdir("/");
322
 
 
323
 
    if(fork())
324
 
        exit(0);
325
 
 
326
 
    setsid();
327
 
#endif
328
 
}