~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to .pc/0003-Add-an-additional-n-after-the-number-in-the-pidfile.patch/clamav-milter/clamav-milter.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Scott Kitterman, Andreas Cadhalpun, Julien Patriarca, Sebastian Andrzej Siewior
  • Date: 2014-07-04 10:17:03 UTC
  • mto: This revision was merged to the branch mainline in revision 130.
  • Revision ID: package-import@ubuntu.com-20140704101703-eak56dsfwdlu6ekz
Tags: 0.98.4+dfsg-2
[ Scott Kitterman ]
* Urgency high due to fix for undocumented API/ABI break
* debian/patches/0002-Fix-STAT64-definition-and-add-missing-includes.patch:
  Removed, because the remaining changes are not needed to fix FTBFS and
  upstream recommends drop due to potential issues with scanning large
  files.

[ Andreas Cadhalpun ]
* Fix debian/watch to properly detect release candidates.
* Add patches to fix building on Hurd:
   - 0008-Fix-compiling-on-Hurd.patch
   - 0009-Workaround-a-bug-in-libc-on-Hurd.patch
* Fix 0004-Fix-FTBFS-with-LLVM-3.1-3.4.patch to correctly detect the
  new LLVM version scheme X.Y.Z (instead of X.Y).
* Add versioned dependencies on procps (for 'pkill -F') and on dpkg
  (for 'start-stop-daemon --status').
* Remove useless code from debian/freshclam.init.in.
* Avoid creation of an empty freshclam.pid file.
* Switch the watchfile to look at github.com, because the sf.net
  website doesn't work correctly at the moment, see #752384.
* Add DEP-5 header with Files-Excluded field to debian/copyright
  in order to let uscan remove unneeded files.

[ Julien Patriarca ]
* Updated French Debconf template translation (Closes: #752388)

[ Sebastian Andrzej Siewior ]
* Add 0010-Call-cl_initialize_crypto-in-cl_init.patch from upstream. The
  cl_initialize_crypto() will now be invoked within libclamav in cl_init()
  so there is now no need to force third party to invoke that function on
  their own.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C)2008 Sourcefire, Inc.
3
 
 *
4
 
 *  Author: aCaB <acab@clamav.net>
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 <sys/types.h>
27
 
#include <unistd.h>
28
 
#include <pwd.h>
29
 
#include <grp.h>
30
 
#include <string.h>
31
 
#ifdef USE_SYSLOG
32
 
#include <syslog.h>
33
 
#endif
34
 
#include <time.h>
35
 
#include <libmilter/mfapi.h>
36
 
 
37
 
#include <openssl/ssl.h>
38
 
#include <openssl/err.h>
39
 
#include "libclamav/crypto.h"
40
 
 
41
 
#include "clamav.h"
42
 
 
43
 
#include "shared/output.h"
44
 
#include "shared/optparser.h"
45
 
#include "shared/misc.h"
46
 
#include "libclamav/default.h"
47
 
 
48
 
#include "connpool.h"
49
 
#include "netcode.h"
50
 
#include "clamfi.h"
51
 
#include "whitelist.h"
52
 
 
53
 
struct smfiDesc descr;
54
 
 
55
 
int main(int argc, char **argv) {
56
 
    char *my_socket, *pt;
57
 
    const struct optstruct *opt;
58
 
    struct optstruct *opts;
59
 
    time_t currtime;
60
 
    mode_t umsk;
61
 
    int ret;
62
 
 
63
 
    memset(&descr, 0, sizeof(struct smfiDesc));
64
 
    descr.xxfi_name = "ClamAV";                 /* filter name */
65
 
    descr.xxfi_version = SMFI_VERSION;          /* milter version */
66
 
    descr.xxfi_flags = SMFIF_QUARANTINE;        /* flags */
67
 
    descr.xxfi_connect = clamfi_connect;        /* connection info filter */
68
 
    descr.xxfi_envfrom = clamfi_envfrom;        /* envelope sender filter */
69
 
    descr.xxfi_envrcpt = clamfi_envrcpt;        /* envelope recipient filter */
70
 
    descr.xxfi_header = clamfi_header;          /* header filter */
71
 
    descr.xxfi_body = clamfi_body;              /* body block */
72
 
    descr.xxfi_eom = clamfi_eom;                /* end of message */
73
 
    descr.xxfi_abort = clamfi_abort;            /* message aborted */
74
 
 
75
 
    opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL);
76
 
    if (!opts) {
77
 
        mprintf("!Can't parse command line options\n");
78
 
        return 1;
79
 
    }
80
 
 
81
 
    if(optget(opts, "help")->enabled) {
82
 
        printf("Usage: %s [-c <config-file>]\n\n", argv[0]);
83
 
        printf("    --help                   -h       Show this help\n");
84
 
        printf("    --version                -V       Show version and exit\n");
85
 
        printf("    --config-file <file>     -c       Read configuration from file\n\n");
86
 
        optfree(opts);
87
 
        return 0;
88
 
    }
89
 
 
90
 
    if(opts->filename) {
91
 
        int x;
92
 
        for(x = 0; opts->filename[x]; x++)
93
 
            mprintf("^Ignoring option %s\n", opts->filename[x]);
94
 
    }
95
 
 
96
 
    if(optget(opts, "version")->enabled) {
97
 
        printf("clamav-milter %s\n", get_version());
98
 
        optfree(opts);
99
 
        return 0;
100
 
    }
101
 
 
102
 
    pt = strdup(optget(opts, "config-file")->strarg);
103
 
    if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) {
104
 
        printf("%s: cannot parse config file %s\n", argv[0], pt);
105
 
        free(pt);
106
 
        return 1;
107
 
    }
108
 
    free(pt);
109
 
 
110
 
    if((opt = optget(opts, "Chroot"))->enabled) {
111
 
        if(chdir(opt->strarg) != 0) {
112
 
            logg("!Cannot change directory to %s\n", opt->strarg);
113
 
            return 1;
114
 
        }
115
 
        if(chroot(opt->strarg) != 0) {
116
 
            logg("!chroot to %s failed. Are you root?\n", opt->strarg);
117
 
            return 1;
118
 
        }
119
 
    }
120
 
 
121
 
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
122
 
        struct passwd *user = NULL;
123
 
        if((user = getpwnam(opt->strarg)) == NULL) {
124
 
            fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
125
 
            optfree(opts);
126
 
            return 1;
127
 
        }
128
 
 
129
 
        if(optget(opts, "AllowSupplementaryGroups")->enabled) {
130
 
#ifdef HAVE_INITGROUPS
131
 
            if(initgroups(opt->strarg, user->pw_gid)) {
132
 
                fprintf(stderr, "ERROR: initgroups() failed.\n");
133
 
                optfree(opts);
134
 
                return 1;
135
 
            }
136
 
#else
137
 
            mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups\n");
138
 
            optfree(opts);
139
 
            return 1;
140
 
#endif
141
 
        } else {
142
 
#ifdef HAVE_SETGROUPS
143
 
            if(setgroups(1, &user->pw_gid)) {
144
 
                fprintf(stderr, "ERROR: setgroups() failed.\n");
145
 
                optfree(opts);
146
 
                return 1;
147
 
            }
148
 
#endif
149
 
        }
150
 
 
151
 
        if(setgid(user->pw_gid)) {
152
 
            fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
153
 
            optfree(opts);
154
 
            return 1;
155
 
        }
156
 
 
157
 
        if(setuid(user->pw_uid)) {
158
 
            fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
159
 
            optfree(opts);
160
 
            return 1;
161
 
        }
162
 
    }
163
 
 
164
 
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
165
 
    logg_time = optget(opts, "LogTime")->enabled;
166
 
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
167
 
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
168
 
    if (logg_size)
169
 
        logg_rotate = optget(opts, "LogRotate")->enabled;
170
 
 
171
 
    if((opt = optget(opts, "LogFile"))->enabled) {
172
 
        logg_file = opt->strarg;
173
 
        if(!cli_is_abspath(logg_file)) {
174
 
            fprintf(stderr, "ERROR: LogFile requires full path.\n");
175
 
            logg_close();
176
 
            optfree(opts);
177
 
            return 1;
178
 
        }
179
 
    } else
180
 
        logg_file = NULL;
181
 
 
182
 
#if defined(USE_SYSLOG) && !defined(C_AIX)
183
 
    if(optget(opts, "LogSyslog")->enabled) {
184
 
        int fac;
185
 
 
186
 
        opt = optget(opts, "LogFacility");
187
 
        if((fac = logg_facility(opt->strarg)) == -1) {
188
 
            logg("!LogFacility: %s: No such facility.\n", opt->strarg);
189
 
            logg_close();
190
 
            optfree(opts);
191
 
            return 1;
192
 
        }
193
 
 
194
 
        openlog("clamav-milter", LOG_PID, fac);
195
 
        logg_syslog = 1;
196
 
    }
197
 
#endif
198
 
 
199
 
    time(&currtime);
200
 
    if(logg("#+++ Started at %s", ctime(&currtime))) {
201
 
        fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
202
 
        logg_close();
203
 
        optfree(opts);
204
 
        return 1;
205
 
    }
206
 
    if((opt = optget(opts, "TemporaryDirectory"))->enabled)
207
 
        tempdir = opt->strarg;
208
 
 
209
 
    if(localnets_init(opts) || init_actions(opts)) {
210
 
        logg_close();
211
 
        optfree(opts);
212
 
        return 1;
213
 
    }
214
 
 
215
 
    if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) {
216
 
        localnets_free();
217
 
        logg_close();
218
 
        optfree(opts);
219
 
        return 1;
220
 
    }
221
 
 
222
 
    if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) {
223
 
        localnets_free();
224
 
        whitelist_free();
225
 
        logg_close();
226
 
        optfree(opts);
227
 
        return 1;
228
 
    }
229
 
 
230
 
    pt = optget(opts, "AddHeader")->strarg;
231
 
    if(strcasecmp(pt, "No")) {
232
 
        char myname[255];
233
 
 
234
 
        if(((opt = optget(opts, "ReportHostname"))->enabled && strncpy(myname, opt->strarg, sizeof(myname))) || !gethostname(myname, sizeof(myname))) {
235
 
            myname[sizeof(myname)-1] = '\0';
236
 
            snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", get_version(), myname);
237
 
        } else
238
 
            snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", get_version());
239
 
        xvirushdr[sizeof(xvirushdr)-1] = '\0';
240
 
 
241
 
        descr.xxfi_flags |= SMFIF_ADDHDRS;
242
 
 
243
 
        if(strcasecmp(pt, "Add")) { /* Replace or Yes */
244
 
            descr.xxfi_flags |= SMFIF_CHGHDRS;
245
 
            addxvirus = 1;
246
 
        } else { /* Add */
247
 
            addxvirus = 2;
248
 
        }
249
 
    }
250
 
 
251
 
    multircpt = optget(opts, "SupportMultipleRecipients")->enabled;
252
 
    
253
 
    if(!(my_socket = optget(opts, "MilterSocket")->strarg)) {
254
 
        logg("!Please configure the MilterSocket directive\n");
255
 
        localnets_free();
256
 
        whitelist_free();
257
 
        logg_close();
258
 
        optfree(opts);
259
 
        return 1;
260
 
    }
261
 
 
262
 
    if(!optget(opts, "Foreground")->enabled) {
263
 
        if(daemonize() == -1) {
264
 
            logg("!daemonize() failed\n");
265
 
            localnets_free();
266
 
            whitelist_free();
267
 
            cpool_free();
268
 
            logg_close();
269
 
            optfree(opts);
270
 
            return 1;
271
 
        }
272
 
        if(chdir("/") == -1)
273
 
            logg("^Can't change current working directory to root\n");
274
 
    }
275
 
 
276
 
    if(smfi_setconn(my_socket) == MI_FAILURE) {
277
 
        logg("!smfi_setconn failed\n");
278
 
        localnets_free();
279
 
        whitelist_free();
280
 
        logg_close();
281
 
        optfree(opts);
282
 
        return 1;
283
 
    }
284
 
    if(smfi_register(descr) == MI_FAILURE) {
285
 
        logg("!smfi_register failed\n");
286
 
        localnets_free();
287
 
        whitelist_free();
288
 
        logg_close();
289
 
        optfree(opts);
290
 
        return 1;
291
 
    }
292
 
    opt = optget(opts, "FixStaleSocket");
293
 
    umsk = umask(0777); /* socket is created with 000 to avoid races */ 
294
 
    if(smfi_opensocket(opt->enabled) == MI_FAILURE) {
295
 
        logg("!Failed to create socket %s\n", my_socket);
296
 
        localnets_free();
297
 
        whitelist_free();
298
 
        logg_close();
299
 
        optfree(opts);
300
 
        return 1;
301
 
    }
302
 
    umask(umsk); /* restore umask */
303
 
    if(strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) {
304
 
        /* set group ownership and perms on the local socket */
305
 
        char *sock_name = my_socket;
306
 
        mode_t sock_mode;
307
 
        if(!strncmp(my_socket, "unix:", 5))
308
 
            sock_name += 5;
309
 
        if(!strncmp(my_socket, "local:", 6))
310
 
            sock_name += 6;
311
 
        if(*my_socket == ':')
312
 
            sock_name ++;
313
 
 
314
 
        if(optget(opts, "MilterSocketGroup")->enabled) {
315
 
            char *gname = optget(opts, "MilterSocketGroup")->strarg, *end;
316
 
            gid_t sock_gid = strtol(gname, &end, 10);
317
 
            if(*end) {
318
 
                struct group *pgrp = getgrnam(gname);
319
 
                if(!pgrp) {
320
 
                    logg("!Unknown group %s\n", gname);
321
 
                    localnets_free();
322
 
                    whitelist_free();
323
 
                    logg_close();
324
 
                    optfree(opts);
325
 
                    return 1;
326
 
                }
327
 
                sock_gid = pgrp->gr_gid;
328
 
            }
329
 
            if(chown(sock_name, -1, sock_gid)) {
330
 
                logg("!Failed to change socket ownership to group %s\n", gname);
331
 
                localnets_free();
332
 
                whitelist_free();
333
 
                logg_close();
334
 
                optfree(opts);
335
 
                return 1;
336
 
            }
337
 
        }
338
 
        if(optget(opts, "MilterSocketMode")->enabled) {
339
 
            char *end;
340
 
            sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8);
341
 
            if(*end) {
342
 
                logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg);
343
 
                localnets_free();
344
 
                whitelist_free();
345
 
                logg_close();
346
 
                optfree(opts);
347
 
                return 1;
348
 
            }
349
 
        } else
350
 
            sock_mode = 0777 & ~umsk;
351
 
 
352
 
        if(chmod(sock_name, sock_mode & 0666)) {
353
 
            logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg);
354
 
            localnets_free();
355
 
            whitelist_free();
356
 
            logg_close();
357
 
            optfree(opts);
358
 
            return 1;
359
 
        }
360
 
    }
361
 
 
362
 
    maxfilesize = optget(opts, "MaxFileSize")->numarg;
363
 
    if(!maxfilesize) {
364
 
        logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE);
365
 
        maxfilesize = CLI_DEFAULT_MAXFILESIZE;
366
 
    }
367
 
    readtimeout = optget(opts, "ReadTimeout")->numarg;
368
 
 
369
 
    cpool_init(opts);
370
 
    if (!cp) {
371
 
        logg("!Failed to init the socket pool\n");
372
 
        localnets_free();
373
 
        whitelist_free();
374
 
        logg_close();
375
 
        optfree(opts);
376
 
        return 1;
377
 
    }   
378
 
 
379
 
    if((opt = optget(opts, "PidFile"))->enabled) {
380
 
        FILE *fd;
381
 
        mode_t old_umask = umask(0002);
382
 
 
383
 
        if((fd = fopen(opt->strarg, "w")) == NULL) {
384
 
            logg("!Can't save PID in file %s\n", opt->strarg);
385
 
        } else {
386
 
            if (fprintf(fd, "%u", (unsigned int)getpid())<0) {
387
 
                logg("!Can't save PID in file %s\n", opt->strarg);
388
 
            }
389
 
            fclose(fd);
390
 
        }
391
 
        umask(old_umask);
392
 
    }
393
 
 
394
 
    ret = smfi_main();
395
 
 
396
 
    optfree(opts);
397
 
 
398
 
    logg_close();
399
 
    cpool_free();
400
 
    localnets_free();
401
 
    whitelist_free();
402
 
 
403
 
    return ret;
404
 
}
405
 
 
406
 
/*
407
 
 * Local Variables:
408
 
 * mode: c
409
 
 * c-basic-offset: 4
410
 
 * tab-width: 8
411
 
 * End: 
412
 
 * vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8: 
413
 
 */