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

« back to all changes in this revision

Viewing changes to clamscan/treewalk.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2002 - 2007 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 version 2 as
6
 
 *  published by the Free Software Foundation.
7
 
 *
8
 
 *  This program is distributed in the hope that it will be useful,
9
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 *  GNU General Public License for more details.
12
 
 *
13
 
 *  You should have received a copy of the GNU General Public License
14
 
 *  along with this program; if not, write to the Free Software
15
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
 
 *  MA 02110-1301, USA.
17
 
 */
18
 
 
19
 
#if HAVE_CONFIG_H
20
 
#include "clamav-config.h"
21
 
#endif
22
 
 
23
 
#include <stdio.h>
24
 
#include <stdlib.h>
25
 
#include <string.h>
26
 
#ifdef  HAVE_UNISTD_H
27
 
#include <unistd.h>
28
 
#endif
29
 
#include <sys/stat.h>
30
 
#include <sys/types.h>
31
 
#ifndef C_WINDOWS
32
 
#include <sys/wait.h>
33
 
#endif
34
 
#ifdef HAVE_PWD_H
35
 
#include <pwd.h>
36
 
#endif
37
 
#ifdef HAVE_GRP_H
38
 
#include <grp.h>
39
 
#endif
40
 
#ifndef C_WINDOWS
41
 
#include <dirent.h>
42
 
#endif
43
 
#include <errno.h>
44
 
 
45
 
#include "global.h"
46
 
#include "manager.h"
47
 
#include "others.h"
48
 
#include "treewalk.h"
49
 
 
50
 
#include "shared/options.h"
51
 
#include "shared/output.h"
52
 
#include "shared/misc.h"
53
 
 
54
 
#include "libclamav/clamav.h"
55
 
#include "libclamav/others.h"
56
 
 
57
 
int treewalk(const char *dirname, struct cl_engine *engine, const struct passwd *user, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options, unsigned int depth)
58
 
{
59
 
        DIR *dd;
60
 
        struct dirent *dent;
61
 
        struct stat statbuf;
62
 
        char *fname;
63
 
        int scanret = 0, included;
64
 
        unsigned int maxdepth;
65
 
        const struct optnode *optnode;
66
 
        char *argument;
67
 
 
68
 
 
69
 
    if(opt_check(opt, "exclude-dir")) {
70
 
        argument = opt_firstarg(opt, "exclude-dir", &optnode);
71
 
        while(argument) {
72
 
            if(match_regex(dirname, argument) == 1) {
73
 
                if(!printinfected)
74
 
                    logg("~%s: Excluded\n", dirname);
75
 
                return 0;
76
 
            }
77
 
            argument = opt_nextarg(&optnode, "exclude-dir");
78
 
        }
79
 
    }
80
 
 
81
 
   if(opt_check(opt, "include-dir")) {
82
 
        included = 0;
83
 
        argument = opt_firstarg(opt, "include-dir", &optnode);
84
 
        while(argument && !included) {
85
 
            if(match_regex(dirname, argument) == 1) {
86
 
                included = 1;
87
 
                break;
88
 
            }
89
 
            argument = opt_nextarg(&optnode, "include-dir");
90
 
        }
91
 
 
92
 
        if(!included) {
93
 
            if(!printinfected)
94
 
                logg("~%s: Excluded\n", dirname);
95
 
            return 0;
96
 
        }
97
 
    }
98
 
 
99
 
    if(opt_check(opt, "max-dir-recursion"))
100
 
        maxdepth = atoi(opt_arg(opt, "max-dir-recursion"));
101
 
    else
102
 
        maxdepth = 15;
103
 
 
104
 
    if(depth > maxdepth)
105
 
        return 0;
106
 
 
107
 
    info.dirs++;
108
 
    depth++;
109
 
 
110
 
    if((dd = opendir(dirname)) != NULL) {
111
 
        while((dent = readdir(dd))) {
112
 
#if !defined(C_INTERIX) && !defined(C_WINDOWS) && !defined(C_CYGWIN)
113
 
            if(dent->d_ino)
114
 
#endif
115
 
            {
116
 
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
117
 
                    /* build the full name */
118
 
                    fname = malloc(strlen(dirname) + strlen(dent->d_name) + 2);
119
 
                    sprintf(fname, "%s/%s", dirname, dent->d_name);
120
 
 
121
 
                    /* stat the file */
122
 
                    if(lstat(fname, &statbuf) != -1) {
123
 
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) {
124
 
                            if(treewalk(fname, engine, user, opt, limits, options, depth) == 1)
125
 
                                scanret++;
126
 
                        } else {
127
 
                            if(S_ISREG(statbuf.st_mode))
128
 
                                scanret += scanfile(fname, engine, user, opt, limits, options);
129
 
                        }
130
 
                    }
131
 
                    free(fname);
132
 
                }
133
 
 
134
 
            }
135
 
        }
136
 
    } else {
137
 
        if(!printinfected)
138
 
            logg("~%s: Can't open directory.\n", dirname);
139
 
        return 53;
140
 
    }
141
 
 
142
 
    closedir(dd);
143
 
 
144
 
    if(scanret)
145
 
        return 1;
146
 
    else
147
 
        return 0;
148
 
 
149
 
}
150
 
 
151
 
#ifdef C_WINDOWS
152
 
int clamav_rmdirs(const char *dir)
153
 
{
154
 
    return cli_rmdirs(dir);
155
 
}
156
 
#else
157
 
int clamav_rmdirs(const char *dir)
158
 
{
159
 
#ifndef C_CYGWIN
160
 
        struct passwd *user;
161
 
#endif
162
 
        pid_t pid;
163
 
        int status;
164
 
 
165
 
 
166
 
    switch(pid = fork()) {
167
 
        case -1:
168
 
            return -1;
169
 
        case 0:
170
 
#ifndef C_CYGWIN
171
 
            if(!geteuid()) { 
172
 
                if((user = getpwnam(CLAMAVUSER)) == NULL)
173
 
                    return -3;
174
 
 
175
 
#ifdef HAVE_SETGROUPS
176
 
                if(setgroups(1, &user->pw_gid)) {
177
 
                    fprintf(stderr, "ERROR: setgroups() failed.\n");
178
 
                    return -3;
179
 
                }
180
 
#endif
181
 
 
182
 
                if(setgid(user->pw_gid)) {
183
 
                    fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
184
 
                    return -3;
185
 
                }
186
 
 
187
 
                if(setuid(user->pw_uid)) {
188
 
                    fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
189
 
                    return -3;
190
 
                }
191
 
            }
192
 
#endif
193
 
            cli_rmdirs(dir);
194
 
            exit(0);
195
 
            break;
196
 
        default:
197
 
            waitpid(pid, &status, 0);
198
 
            if(WIFEXITED(status))
199
 
                return 0;
200
 
            else
201
 
                return -2;
202
 
    }
203
 
}
204
 
#endif
205
 
 
206
 
int fixperms(const char *dirname)
207
 
{
208
 
        DIR *dd;
209
 
        struct dirent *dent;
210
 
        struct stat statbuf;
211
 
        char *fname;
212
 
        int scanret = 0;
213
 
 
214
 
    if((dd = opendir(dirname)) != NULL) {
215
 
        while((dent = readdir(dd))) {
216
 
#if !defined(C_INTERIX) && !defined(C_WINDOWS) && !defined(C_CYGWIN)
217
 
            if(dent->d_ino)
218
 
#endif
219
 
            {
220
 
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
221
 
                    /* build full name */
222
 
                    fname = malloc(strlen(dirname) + strlen(dent->d_name) + 2);
223
 
                    sprintf(fname, "%s/%s", dirname, dent->d_name);
224
 
 
225
 
                    /* stat the file */
226
 
                    if(lstat(fname, &statbuf) != -1) {
227
 
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
228
 
                            chmod(fname, 0700);
229
 
                            fixperms(fname);
230
 
                        } else if(S_ISREG(statbuf.st_mode))
231
 
                            chmod(fname, 0700);
232
 
                    }
233
 
 
234
 
                    free(fname);
235
 
                }
236
 
            }
237
 
        }
238
 
    } else {
239
 
        if(!printinfected)
240
 
            logg("~%s: Can't open directory.\n", dirname);
241
 
        return 53;
242
 
    }
243
 
 
244
 
    closedir(dd);
245
 
 
246
 
    if(scanret)
247
 
        return 1;
248
 
    else
249
 
        return 0;
250
 
 
251
 
}
252
 
 
253
 
int du(const char *dirname, struct s_du *n)
254
 
{
255
 
        DIR *dd;
256
 
        struct dirent *dent;
257
 
        struct stat statbuf;
258
 
        char *fname;
259
 
 
260
 
    if((dd = opendir(dirname)) != NULL) {
261
 
        while((dent = readdir(dd))) {
262
 
#if !defined(C_INTERIX) && !defined(C_WINDOWS) && !defined(C_CYGWIN)
263
 
            if(dent->d_ino)
264
 
#endif
265
 
            {
266
 
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
267
 
                    n->files++;
268
 
 
269
 
                    /* build the full name */
270
 
                    fname = malloc(strlen(dirname) + strlen(dent->d_name) + 2);
271
 
                    sprintf(fname, "%s/%s", dirname, dent->d_name);
272
 
 
273
 
                    /* stat the file */
274
 
                    if(lstat(fname, &statbuf) != -1) {
275
 
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
276
 
                            du(fname, n);
277
 
                        } else {
278
 
                            n->space += statbuf.st_size / 1024;
279
 
                        }
280
 
                    }
281
 
 
282
 
                    free(fname);
283
 
                }
284
 
            }
285
 
        }
286
 
    } else {
287
 
        if(!printinfected)
288
 
            logg("~%s: Can't open directory.\n", dirname);
289
 
        return 53;
290
 
    }
291
 
 
292
 
    closedir(dd);
293
 
 
294
 
    return 0;
295
 
}