~ubuntu-branches/ubuntu/hardy/aide/hardy-proposed

« back to all changes in this revision

Viewing changes to src/gen_list.c

  • Committer: Bazaar Package Importer
  • Author(s): Mike Markley
  • Date: 2002-03-15 20:20:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020315202006-fywvbk2rzaqe5ku2
Tags: upstream-0.8
ImportĀ upstreamĀ versionĀ 0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* aide, Advanced Intrusion Detection Environment
 
2
 *
 
3
 * Copyright (C) 1999,2000 Rami Lehti,Pablo Virolainen
 
4
 * $Header: /cvs-root-aide/aide/src/gen_list.c,v 1.82 2002/02/11 09:27:23 rammer Exp $
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License as
 
8
 * published by the Free Software Foundation; either version 2 of the
 
9
 * License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 */
 
20
 
 
21
#include "aide.h"
 
22
#include <assert.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <dirent.h>
 
26
#include <unistd.h>
 
27
#include <limits.h>
 
28
#include <sys/stat.h>
 
29
#include <sys/types.h>
 
30
#include <ustat.h>
 
31
#include <errno.h>
 
32
#include <time.h>
 
33
#include "report.h"
 
34
#include "config.h"
 
35
#include "gnu_regex.h"
 
36
#include "list.h"
 
37
#include "gen_list.h"
 
38
#include "seltree.h"
 
39
#include "db_config.h"
 
40
#include "report.h"
 
41
/*for locale support*/
 
42
#include "locale-aide.h"
 
43
/*for locale support*/
 
44
 
 
45
#define CLOCK_SKEW 5
 
46
 
 
47
#ifdef WITH_MHASH
 
48
#include <mhash.h>
 
49
#endif
 
50
 
 
51
#include <gcrypt.h>
 
52
 
 
53
 
 
54
char* strrxtok(char* rx)
 
55
{
 
56
  char*p=NULL;
 
57
  int i=0;
 
58
 
 
59
  /* This assumes that the first character is a slash */
 
60
  int lastslash=1;
 
61
 
 
62
  /* i=0 because we want to return at least the first slash */
 
63
  for(i=1;i<strlen(rx);i++){
 
64
    switch(rx[i])
 
65
      {
 
66
      case '/':
 
67
        lastslash=i;
 
68
        break;
 
69
      case '(':
 
70
      case '^':
 
71
      case '$':
 
72
      case '*':
 
73
      case '.':
 
74
      case '[':
 
75
        /* FIXME: The '\\' character should be handled more gracefully. */
 
76
        /* That is, if it is the only special character then */
 
77
        /* The next character should be taken literally so */
 
78
        /* that the search would be more efficient */
 
79
      case '\\':
 
80
        i=strlen(rx);
 
81
        break;
 
82
      default:
 
83
        break;
 
84
      }
 
85
  }
 
86
 
 
87
  p=(char*)malloc(sizeof(char)*lastslash+1);
 
88
  strncpy(p,rx,lastslash);
 
89
  p[lastslash]='\0';
 
90
 
 
91
 
 
92
  return p;
 
93
}
 
94
 
 
95
char* strlastslash(char*str)
 
96
{
 
97
  char* p=NULL;
 
98
  int lastslash=1;
 
99
  int i=0;
 
100
 
 
101
  for(i=1;i<strlen(str);i++){
 
102
    if(str[i]=='/'){
 
103
      lastslash=i;
 
104
    }
 
105
  }
 
106
  
 
107
  p=(char*)malloc(sizeof(char)*lastslash+1);
 
108
  strncpy(p,str,lastslash);
 
109
  p[lastslash]='\0';
 
110
 
 
111
  return p;
 
112
}
 
113
 
 
114
seltree* get_seltree_node(seltree* tree,char* path)
 
115
{
 
116
  seltree* node=NULL;
 
117
  list* r=NULL;
 
118
 
 
119
  if(tree==NULL){
 
120
    return NULL;
 
121
  }
 
122
 
 
123
  if(strncmp(path,tree->path,strlen(path)+1)==0){
 
124
    return tree;
 
125
  }
 
126
  else{
 
127
    for(r=tree->childs;r;r=r->next){
 
128
      node=get_seltree_node((seltree*)r->data,path);
 
129
      if(node!=NULL){
 
130
        return node;
 
131
      }
 
132
    }
 
133
  }
 
134
  return NULL;
 
135
}
 
136
 
 
137
void copy_rule_ref(seltree* node, rx_rule* r)
 
138
{
 
139
    if( r!=NULL ){
 
140
        node->conf_lineno = r->conf_lineno;  
 
141
        node->rx=(char*)malloc(strlen(r->rx)+1);
 
142
        strcpy(node->rx,r->rx);
 
143
    } else {
 
144
        node->conf_lineno = -1;
 
145
        node->rx=NULL;
 
146
    }
 
147
}
 
148
 
 
149
seltree* new_seltree_node(
 
150
        seltree* tree,
 
151
        char*path,
 
152
        int isrx,
 
153
        rx_rule*r)
 
154
{
 
155
  seltree* node=NULL;
 
156
  seltree* parent=NULL;
 
157
 
 
158
  node=(seltree*)malloc(sizeof(seltree));
 
159
  node->childs=NULL;
 
160
  node->path=path;
 
161
  node->sel_rx_lst=NULL;
 
162
  node->neg_rx_lst=NULL;
 
163
  node->equ_rx_lst=NULL;
 
164
  node->checked=0;
 
165
 
 
166
  copy_rule_ref(node,r);
 
167
 
 
168
  if(tree!=NULL){
 
169
    if(isrx){
 
170
      parent=get_seltree_node(tree,strrxtok(path));
 
171
    }else {
 
172
      parent=get_seltree_node(tree,strlastslash(path));
 
173
    }      
 
174
    if(parent==NULL){
 
175
      if(isrx){
 
176
        parent=new_seltree_node(tree,strrxtok(path),isrx,r);
 
177
      }else {
 
178
        parent=new_seltree_node(tree,strlastslash(path),isrx,r);
 
179
      }
 
180
    }
 
181
    
 
182
    parent->childs=list_append(parent->childs,(void*)node);
 
183
    node->parent=parent;
 
184
  }else {
 
185
    node->parent=NULL;
 
186
  }
 
187
  return node;
 
188
}
 
189
 
 
190
void gen_seltree(list* rxlist,seltree* tree,char type)
 
191
{
 
192
  regex_t*     rxtmp   = NULL;
 
193
  seltree*     curnode = NULL;
 
194
  list*        r       = NULL;
 
195
  char*        rxtok   = NULL;
 
196
  rx_rule*     rxc     = NULL;
 
197
 
 
198
  for(r=rxlist;r;r=r->next){
 
199
    char* data;
 
200
    rx_rule* curr_rule = (rx_rule*)r->data;
 
201
    
 
202
    
 
203
    rxtok=strrxtok(curr_rule->rx);
 
204
    curnode=get_seltree_node(tree,rxtok);
 
205
    if(curnode==NULL){
 
206
      curnode=new_seltree_node(tree,rxtok,1,curr_rule);
 
207
    }
 
208
    
 
209
    /* We have to add '^' to the first charaster of string... 
 
210
     *
 
211
     */
 
212
 
 
213
    data=(char*)malloc(strlen(curr_rule->rx)+1+1);
 
214
 
 
215
    if (data==NULL){
 
216
      error(0,_("Not enough memory for regexpr compile... exiting..\n"));
 
217
      abort();
 
218
    }
 
219
    
 
220
    /* FIX ME! (returnvalue) */
 
221
    
 
222
    strcpy(data+1,curr_rule->rx);
 
223
    
 
224
    data[0]='^';
 
225
    
 
226
    rxtmp=(regex_t*)malloc(sizeof(regex_t));
 
227
    if( regcomp(rxtmp,data,REG_EXTENDED|REG_NOSUB)){
 
228
      error(0,_("Error in selective regexp:%s"),curr_rule->rx);
 
229
      free(data);
 
230
    }else{
 
231
      /* replace regexp text with regexp compiled */
 
232
      rxc=(rx_rule*)malloc(sizeof(rx_rule));
 
233
      rxc->rx=data;
 
234
      /* and copy the rest */
 
235
      rxc->crx=rxtmp;
 
236
      rxc->attr=curr_rule->attr;
 
237
      rxc->conf_lineno=curr_rule->conf_lineno;
 
238
 
 
239
      switch (type){
 
240
      case 's':{
 
241
        curnode->sel_rx_lst=list_append(curnode->sel_rx_lst,(void*)rxc);
 
242
        break;
 
243
      }
 
244
      case 'n':{
 
245
        curnode->neg_rx_lst=list_append(curnode->neg_rx_lst,(void*)rxc);
 
246
        break;
 
247
      }
 
248
      case 'e':{
 
249
        curnode->equ_rx_lst=list_append(curnode->equ_rx_lst,(void*)rxc);
 
250
        break;
 
251
      }
 
252
      }
 
253
    }
 
254
    /* Data should not be free'ed because it's in rxc struct
 
255
     * and freeing is done if error occour.
 
256
     */
 
257
  }
 
258
 
 
259
 
 
260
}
 
261
 
 
262
list* add_file_to_list(list* listp,char*filename,int attr,int* addok)
 
263
{
 
264
  db_line* fil=NULL;
 
265
  time_t cur_time;
 
266
  struct AIDE_STAT_TYPE fs;
 
267
  int sres=0;
 
268
  
 
269
  error(220, _("Adding %s to filelist\n"),filename);
 
270
  
 
271
  fil=(db_line*)malloc(sizeof(db_line));
 
272
  fil->attr=attr|DB_FILENAME|DB_LINKNAME;
 
273
  fil->filename=(char*)malloc(sizeof(char)*strlen(filename)+1);
 
274
  strncpy(fil->filename,filename,strlen(filename));
 
275
  fil->filename[strlen(filename)]='\0';
 
276
  /* We want to use lstat here instead of stat since we want *
 
277
   * symlinks stats not the file that it points to. */
 
278
  sres=AIDE_LSTAT_FUNC(fil->filename,&fs);
 
279
  if(sres==-1){
 
280
    char* er=strerror(errno);
 
281
    if (er==NULL) {
 
282
      error(0,"lstat() failed for %s. strerror failed for %i\n",fil->filename,errno);
 
283
    } else {
 
284
      error(0,"lstat() failed for %s:%s\n",fil->filename,strerror(errno));
 
285
    }
 
286
    free(fil->filename);
 
287
    free(fil);
 
288
    *addok=RETFAIL;
 
289
    return listp;
 
290
  } 
 
291
  
 
292
  cur_time=time(NULL);
 
293
 
 
294
  if (cur_time==(time_t)-1) {
 
295
    char* er=strerror(errno);
 
296
    if (er==NULL) {
 
297
      error(0,_("Can not get current time. strerror failed for %i\n"),errno);
 
298
    } else {
 
299
      error(0,_("Can not get current time with reason %s\n"),er);
 
300
    }
 
301
  } else {
 
302
    
 
303
    if(fs.st_atime>cur_time){
 
304
      error(CLOCK_SKEW,_("%s atime in future\n"),fil->filename);
 
305
    }
 
306
    if(fs.st_mtime>cur_time){
 
307
      error(CLOCK_SKEW,_("%s mtime in future\n"),fil->filename);
 
308
    }
 
309
    if(fs.st_ctime>cur_time){
 
310
      error(CLOCK_SKEW,_("%s ctime in future\n"),fil->filename);
 
311
    }
 
312
  }
 
313
  
 
314
  /*
 
315
    Here we should check if we need to add it..
 
316
   */  
 
317
  
 
318
  {
 
319
    struct ustat buf;
 
320
    if (ustat(fs.st_dev, &buf) != 0 || buf.f_fname[0]==0) {
 
321
      
 
322
    } else {
 
323
      
 
324
    }
 
325
 
 
326
  }
 
327
  
 
328
  
 
329
  fil->perm_o=fs.st_mode;
 
330
  fil->size_o=fs.st_size;
 
331
 
 
332
  if((S_ISLNK(fs.st_mode))){
 
333
    char* lnktmp=NULL;
 
334
    char* lnkbuf=NULL;
 
335
    int len=0;
 
336
    
 
337
#ifdef WITH_ACL   
 
338
    if(conf->no_acl_on_symlinks!=-1) {
 
339
      fil->attr&=(~DB_ACL);
 
340
    }
 
341
#endif   
 
342
 
 
343
    if(conf->warn_dead_symlinks!=-1) {
 
344
      struct AIDE_STAT_TYPE fs;
 
345
      int sres;
 
346
      sres=AIDE_STAT_FUNC(fil->filename,&fs);
 
347
      if (sres!=0) {
 
348
        error(5,"Dead symlink detected at %s\n",fil->filename);
 
349
      }
 
350
    }
 
351
    
 
352
    if(conf->symlinks_found==0){
 
353
      int it=0;
 
354
      DB_FIELD dbtmp;
 
355
      DB_FIELD dbtmp2;
 
356
      dbtmp=conf->db_out_order[1];
 
357
      conf->db_out_order[1]=db_linkname;
 
358
      for(it=2;it<conf->db_out_size;it++){
 
359
        dbtmp2=conf->db_out_order[it];
 
360
        conf->db_out_order[it]=dbtmp;
 
361
        dbtmp=dbtmp2;
 
362
      }
 
363
      conf->db_out_order[conf->db_out_size++]=dbtmp;
 
364
      conf->symlinks_found=1;
 
365
    }
 
366
 
 
367
    lnktmp=(char*)malloc(_POSIX_PATH_MAX+1);
 
368
    if(lnktmp==NULL){
 
369
      error(0,_("malloc failed in add_file_to_list()\n"));
 
370
      abort();
 
371
    }
 
372
 
 
373
    len=readlink(fil->filename,lnktmp,_POSIX_PATH_MAX+1);
 
374
    lnkbuf=(char*)malloc(len+1);
 
375
    if(lnkbuf==NULL){
 
376
      error(0,_("malloc failed in add_file_to_list()\n"));
 
377
      abort();
 
378
    }
 
379
 
 
380
    strncpy(lnkbuf,lnktmp,len);
 
381
    lnkbuf[len]='\0';
 
382
    fil->linkname=lnkbuf;
 
383
    free(lnktmp);
 
384
    fil->attr|=DB_LINKNAME;
 
385
  }else {
 
386
    fil->linkname=NULL;
 
387
    /* Just remove linkname avaivilibity bit from this entry */
 
388
    fil->attr&=(~DB_LINKNAME); 
 
389
  }
 
390
 
 
391
  
 
392
  if(DB_INODE&fil->attr){
 
393
    fil->inode=fs.st_ino;
 
394
  } else {
 
395
    fil->inode=0;
 
396
  }
 
397
 
 
398
  if(DB_UID&fil->attr) {
 
399
    fil->uid=fs.st_uid;
 
400
  }else {
 
401
    fil->uid=0;
 
402
  }
 
403
 
 
404
  if(DB_GID&fil->attr){
 
405
    fil->gid=fs.st_gid;
 
406
  }else{
 
407
    fil->gid=0;
 
408
  }
 
409
 
 
410
  if(DB_PERM&fil->attr){
 
411
    fil->perm=fs.st_mode;
 
412
  }else{
 
413
    fil->perm=0;
 
414
  }
 
415
 
 
416
  if(DB_SIZE&fil->attr||DB_SIZEG&fil->attr){
 
417
    fil->size=fs.st_size;
 
418
  }else{
 
419
    fil->size=0;
 
420
  }
 
421
  
 
422
  if(DB_LNKCOUNT&fil->attr){
 
423
    fil->nlink=fs.st_nlink;
 
424
  }else {
 
425
    fil->nlink=0;
 
426
  }
 
427
 
 
428
  if(DB_MTIME&fil->attr){
 
429
    fil->mtime=fs.st_mtime;
 
430
  }else{
 
431
    fil->mtime=0;
 
432
  }
 
433
 
 
434
  if(DB_CTIME&fil->attr){
 
435
    fil->ctime=fs.st_ctime;
 
436
  }else{
 
437
    fil->ctime=0;
 
438
  }
 
439
  
 
440
  if(DB_ATIME&fil->attr){
 
441
    fil->atime=fs.st_atime;
 
442
  }else{
 
443
    fil->atime=0;
 
444
  }
 
445
 
 
446
  if(DB_BCOUNT&fil->attr){
 
447
    fil->bcount=fs.st_blocks;
 
448
  } else {
 
449
    fil->bcount=0;
 
450
  }
 
451
 
 
452
#ifdef WITH_ACL
 
453
  if(DB_ACL&fil->attr) { /* There might be a bug here. */
 
454
    int res;
 
455
    fil->acl=malloc(sizeof(acl_type));
 
456
    fil->acl->entries=acl(fil->filename,GETACLCNT,0,NULL);
 
457
    if (fil->acl->entries==-1) {
 
458
      char* er=strerror(errno);
 
459
      fil->acl->entries=0;
 
460
      if (er==NULL) {
 
461
        error(0,"ACL query failed for %s. strerror failed for %i\n",fil->filename,errno);
 
462
      } else {
 
463
        error(0,"ACL query failed for %s:%s\n",fil->filename,er);
 
464
      }
 
465
    } else {
 
466
      fil->acl->acl=malloc(sizeof(aclent_t)*fil->acl->entries);
 
467
      res=acl(fil->filename,GETACL,fil->acl->entries,fil->acl->acl);
 
468
      if (res==-1) {
 
469
        error(0,"ACL error %s\n",strerror(errno));
 
470
      } else {
 
471
        if (res!=fil->acl->entries) {
 
472
          error(0,"Tried to read %i acl but got %i\n",fil->acl->entries,res);
 
473
        }
 
474
      }
 
475
    }
 
476
  }else{
 
477
    fil->acl=NULL;
 
478
  }
 
479
 
 
480
#endif
 
481
  
 
482
  if(S_ISDIR(fs.st_mode)||S_ISCHR(fs.st_mode)
 
483
     ||S_ISBLK(fs.st_mode)||S_ISFIFO(fs.st_mode)
 
484
     ||S_ISLNK(fs.st_mode)||S_ISSOCK(fs.st_mode)){
 
485
    
 
486
    fil->attr&=(~DB_MD5)&(~DB_SHA1)&(~DB_RMD160)&(~DB_TIGER);
 
487
    
 
488
    fil->md5=NULL;
 
489
    fil->sha1=NULL;
 
490
    fil->tiger=NULL;
 
491
    fil->rmd160=NULL;
 
492
#ifdef WITH_MHASH
 
493
 
 
494
    fil->attr&=(~DB_CRC32)&(~DB_HAVAL)&(~DB_CRC32B);
 
495
 
 
496
    fil->crc32=NULL;
 
497
    fil->crc32b=NULL;
 
498
    fil->haval=NULL;
 
499
    fil->gost=NULL;
 
500
#endif
 
501
  }else {
 
502
    /* 1 if needs to be set
 
503
     * 0 otherwise */
 
504
    fil->md5=DB_MD5&fil->attr?(byte*)"":NULL;
 
505
    fil->sha1=DB_SHA1&fil->attr?(byte*)"":NULL;
 
506
    fil->tiger=DB_TIGER&fil->attr?(byte*)"":NULL;
 
507
    fil->rmd160=DB_RMD160&fil->attr?(byte*)"":NULL;
 
508
#ifdef WITH_MHASH
 
509
    fil->crc32=DB_CRC32&fil->attr?(byte*)"":NULL;
 
510
    fil->crc32b=DB_CRC32B&fil->attr?(byte*)"":NULL;
 
511
    fil->gost=DB_GOST&fil->attr?(byte*)"":NULL;
 
512
    fil->haval=DB_HAVAL&fil->attr?(byte*)"":NULL;
 
513
#endif
 
514
  }
 
515
  listp=list_append(listp,(void*)fil);
 
516
 
 
517
  *addok=RETOK;
 
518
  return listp;
 
519
}
 
520
 
 
521
int check_list_for_match(list* rxrlist,char* text,int* attr)
 
522
{
 
523
  list* r=NULL;
 
524
  int retval=1;
 
525
  for(r=rxrlist;r;r=r->next){
 
526
    if((retval=regexec((regex_t*)((rx_rule*)r->data)->crx,text,0,0,0))==0){
 
527
      *attr=((rx_rule*)r->data)->attr;
 
528
        error(231,"Matches rule from line #%ld: %s\n",((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
 
529
      break;
 
530
    }
 
531
  }
 
532
  return retval;
 
533
}
 
534
 
 
535
/* 
 
536
 * Function check_node_for_match()
 
537
 * calls itself recursively to go to the top and then back down.
 
538
 * uses check_list_for_match()
 
539
 * returns:
 
540
 * 0,  if a negative rule was matched 
 
541
 * 1,  if a selective rule was matched
 
542
 * 2,  if a equals rule was matched
 
543
 * retval if no rule was matched.
 
544
 * retval&3 if no rule was matched and first in the recursion
 
545
 *
 
546
 */    
 
547
 
 
548
int check_node_for_match(seltree*node,char*text,int retval,int* attr)
 
549
{
 
550
  int top=0;
 
551
  
 
552
  if(node==NULL){
 
553
    return retval;
 
554
  }
 
555
  
 
556
  /* We need this to check whether this was the first one *
 
557
   * to be called and not a recursive call */
 
558
  if(!((retval&16)==16)){
 
559
    retval|=16;
 
560
    top=1;
 
561
  } else{
 
562
    top=0;
 
563
  }
 
564
    
 
565
  /* if no deeper match found */
 
566
  if(!((retval&8)==8)&&!((retval&4)==4)){
 
567
        if(!check_list_for_match(node->equ_rx_lst,text,attr)){
 
568
                retval|=(2|4);
 
569
        };
 
570
  };
 
571
  /* We'll use retval to pass information on whether to recurse 
 
572
   * the dir or not */
 
573
 
 
574
 
 
575
  if(!((retval&8)==8)&&!((retval&4)==4)){
 
576
    if(!check_list_for_match(node->sel_rx_lst,text,attr))
 
577
      retval|=(1|8);
 
578
  }
 
579
 
 
580
  /* Now let's check the ancestors */
 
581
  retval=check_node_for_match(node->parent,text,retval,attr);
 
582
 
 
583
 
 
584
  /* Negative regexps are the strongest so they are checked last */
 
585
  /* If this file is to be added */
 
586
  if(retval){
 
587
    if(!check_list_for_match(node->neg_rx_lst,text,attr)){
 
588
      retval=0;
 
589
    }
 
590
  }
 
591
  /* Now we discard the info whether a match was made or not *
 
592
   * and just return 0,1 or 2 */
 
593
  if(top){
 
594
    retval&=3;
 
595
  }
 
596
  return retval;
 
597
}
 
598
 
 
599
list* traverse_tree(seltree* tree,list* file_lst,int attr)
 
600
{
 
601
  list* r=NULL;
 
602
  seltree* a=NULL;
 
603
  DIR* dirh=NULL;
 
604
  struct AIDE_DIRENT_TYPE* entp=NULL;
 
605
  struct AIDE_DIRENT_TYPE** resp=NULL;
 
606
  int rdres=0;
 
607
  int addfile=0;
 
608
  char* fullname=NULL;
 
609
  int e=0;
 
610
  int matchattr=attr;
 
611
#  ifndef HAVE_READDIR_R
 
612
  long td=-1;
 
613
#  endif
 
614
  int addok=RETOK;
 
615
 
 
616
  /* Root is special and it must be checked on it's own. */
 
617
  if( tree->path[0]=='/' && tree->path[1]=='\0' ){
 
618
    addfile=check_node_for_match(tree,"/",0,&matchattr);
 
619
    if(addfile){
 
620
      error(240,"%s match=%d\n",fullname, addfile);
 
621
      file_lst=add_file_to_list(file_lst,"/",matchattr,&addok);
 
622
    }
 
623
  }
 
624
 
 
625
  if(!(dirh=opendir(tree->path))){
 
626
    error(5,"traverse_tree():%s: %s\n", strerror(errno),tree->path);
 
627
    return file_lst;
 
628
  }
 
629
  
 
630
#  ifdef HAVE_READDIR_R
 
631
  resp=(struct AIDE_DIRENT_TYPE**)
 
632
    malloc(sizeof(struct AIDE_DIRENT_TYPE)+_POSIX_PATH_MAX);
 
633
  entp=(struct AIDE_DIRENT_TYPE*)
 
634
    malloc(sizeof(struct AIDE_DIRENT_TYPE)+_POSIX_PATH_MAX);
 
635
  
 
636
  for(rdres=AIDE_READDIR_R_FUNC(dirh,entp,resp);
 
637
      (rdres==0&&(*resp)!=NULL);
 
638
      rdres=AIDE_READDIR_R_FUNC(dirh,entp,resp)){
 
639
#  else
 
640
#   ifdef HAVE_READDIR
 
641
  for(entp=AIDE_READDIR_FUNC(dirh);
 
642
      (entp!=NULL&&td!=telldir(dirh));
 
643
      entp=AIDE_READDIR_FUNC(dirh)){
 
644
    td=telldir(dirh);
 
645
#   else
 
646
#    error AIDE needs readdir or readdir_r
 
647
#   endif
 
648
#  endif
 
649
 
 
650
    if(strncmp(entp->d_name,".",1)==0){
 
651
      if(strncmp(entp->d_name,".",strlen(entp->d_name))==0)
 
652
        continue;
 
653
      if(strncmp(entp->d_name,"..",strlen(entp->d_name))==0)
 
654
        continue;
 
655
    }
 
656
    /* Construct fully qualified pathname for the file in question */
 
657
    fullname=(char*)
 
658
      malloc(sizeof(char)*(strlen(entp->d_name)+strlen(tree->path)+2));
 
659
    strncpy(fullname,tree->path,strlen(tree->path));
 
660
    if(strncmp(tree->path,"/",strlen(tree->path))!=0){
 
661
      strncpy(fullname+strlen(tree->path),"/",1);
 
662
      e=1;
 
663
    }else {
 
664
      e=0;
 
665
    }
 
666
    strncpy(fullname+strlen(tree->path)+e,entp->d_name,strlen(entp->d_name));
 
667
    fullname[(strlen(tree->path)+e+strlen(entp->d_name))]='\0';
 
668
    error(230,_("Checking %s for match\n"),fullname);
 
669
    if(attr){ /* This dir and all its subs are added by default */
 
670
      addfile=1;
 
671
      
 
672
      addfile=check_node_for_match(tree,fullname,addfile,&matchattr);
 
673
      
 
674
      if(addfile){
 
675
        error(240,"%s match=%d\n",fullname, addfile); 
 
676
 
 
677
        file_lst=add_file_to_list(file_lst,fullname,matchattr,&addok);
 
678
        if( !(addfile&2) && addok!=RETFAIL){
 
679
          if(S_ISDIR(((db_line*)file_lst->header->tail->data)->perm_o)){
 
680
            a=get_seltree_node(tree,
 
681
                               ((db_line*)file_lst->header->tail->data)
 
682
                               ->filename);
 
683
            if(a==NULL){
 
684
              a=new_seltree_node(tree,
 
685
                                 ((db_line*)file_lst->header->tail->data)
 
686
                                 ->filename,0,NULL);
 
687
            }
 
688
            file_lst=traverse_tree(a,file_lst,attr);
 
689
          }
 
690
        }
 
691
      } else {
 
692
        error(230,_("File %s does not match\n"),fullname);
 
693
      }
 
694
    } else{ /* This dir is not added by default */
 
695
      addfile=0;
 
696
      
 
697
      addfile=check_node_for_match(tree,fullname,addfile,&matchattr);
 
698
      
 
699
      if(addfile){
 
700
        error(240,"%s match=%d\n",fullname, addfile); 
 
701
        file_lst=add_file_to_list(file_lst,fullname,matchattr,&addok);
 
702
        if(addfile!=2 && addok!=RETFAIL){
 
703
          if(S_ISDIR(((db_line*)file_lst->header->tail->data)->perm_o)){
 
704
            a=get_seltree_node(tree,
 
705
                               ((db_line*)file_lst->header->tail->data)
 
706
                               ->filename);
 
707
            if(a==NULL){
 
708
              a=new_seltree_node(tree,
 
709
                                 ((db_line*)file_lst->header->tail->data)
 
710
                                 ->filename,0,NULL);
 
711
            }
 
712
            file_lst=traverse_tree(a,file_lst,matchattr); 
 
713
          }
 
714
        }
 
715
      } else {
 
716
        error(230,_("File %s does not match\n"),fullname);
 
717
      }
 
718
      
 
719
    }
 
720
    free(fullname);
 
721
  }
 
722
 
 
723
  if(closedir(dirh)==-1){
 
724
    error(0,"Closedir() failed for %s\n",tree->path);
 
725
  };
 
726
  
 
727
#  ifdef HAVE_READDIR_R
 
728
  free(resp);
 
729
  free(entp);
 
730
#  endif
 
731
  
 
732
  /* All childs are not necessarily checked yet */
 
733
  if(tree->childs!=NULL){
 
734
    for(r=tree->childs;r;r=r->next){
 
735
      if(!(((seltree*)r->data)->checked)) {
 
736
        file_lst=traverse_tree((seltree*)r->data,file_lst,attr);
 
737
      }
 
738
    }
 
739
  }
 
740
  tree->checked=1;
 
741
  
 
742
  return file_lst;
 
743
}
 
744
 
 
745
list* gen_list(list* prxlist,list* nrxlist,list* erxlist)
 
746
{
 
747
  list* r=NULL;
 
748
  seltree* tree=NULL;
 
749
 
 
750
  tree=new_seltree_node(NULL,"/",0,NULL);
 
751
 
 
752
  gen_seltree(prxlist,tree,'s');
 
753
  gen_seltree(nrxlist,tree,'n');
 
754
  gen_seltree(erxlist,tree,'e');
 
755
  
 
756
  if(tree==NULL){
 
757
    return NULL;
 
758
  }
 
759
  
 
760
  
 
761
  r=traverse_tree(tree,NULL,0);
 
762
  
 
763
  return r;
 
764
}