Blame src/gen_list.c

Packit 762fc5
/* aide, Advanced Intrusion Detection Environment
Packit 762fc5
 *
Packit 762fc5
 * Copyright (C) 1999-2006,2009-2012,2015,2016 Rami Lehti,Pablo Virolainen,
Packit 762fc5
 * Mike Markley, Richard van den Berg, Hannes von Haugwitz
Packit 762fc5
 * $Header$
Packit 762fc5
 *
Packit 762fc5
 * This program is free software; you can redistribute it and/or
Packit 762fc5
 * modify it under the terms of the GNU General Public License as
Packit 762fc5
 * published by the Free Software Foundation; either version 2 of the
Packit 762fc5
 * License, or (at your option) any later version.
Packit 762fc5
 *
Packit 762fc5
 * This program is distributed in the hope that it will be useful, but
Packit 762fc5
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 762fc5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit 762fc5
 * General Public License for more details.
Packit 762fc5
 *
Packit 762fc5
 * You should have received a copy of the GNU General Public License
Packit 762fc5
 * along with this program; if not, write to the Free Software
Packit 762fc5
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 762fc5
 */
Packit 762fc5
Packit 762fc5
#include "aide.h"
Packit 762fc5
	       
Packit 762fc5
#include <string.h>
Packit 762fc5
#include <assert.h>
Packit 762fc5
#include <stdlib.h>
Packit 762fc5
#include <dirent.h>
Packit 762fc5
#include <unistd.h>
Packit 762fc5
#include <limits.h>
Packit 762fc5
#include <sys/stat.h>
Packit 762fc5
#include <sys/types.h>
Packit 762fc5
#include <errno.h>
Packit 762fc5
#include <time.h>
Packit 762fc5
#include <pcre.h>
Packit 762fc5
Packit 762fc5
#include "report.h"
Packit 762fc5
#include "list.h"
Packit 762fc5
#include "gen_list.h"
Packit 762fc5
#include "seltree.h"
Packit 762fc5
#include "db.h"
Packit 762fc5
#include "db_config.h"
Packit 762fc5
#include "commandconf.h"
Packit 762fc5
#include "report.h"
Packit 762fc5
/*for locale support*/
Packit 762fc5
#include "locale-aide.h"
Packit 762fc5
/*for locale support*/
Packit 762fc5
Packit 762fc5
#define CLOCK_SKEW 5
Packit 762fc5
Packit 762fc5
#ifdef WITH_MHASH
Packit 762fc5
#include <mhash.h>
Packit 762fc5
#endif
Packit 762fc5
#include "md.h"
Packit 762fc5
#include "do_md.h"
Packit 762fc5
Packit 762fc5
void hsymlnk(db_line* line);
Packit 762fc5
void fs2db_line(struct AIDE_STAT_TYPE* fs,db_line* line);
Packit 762fc5
void calc_md(struct AIDE_STAT_TYPE* old_fs,db_line* line);
Packit 762fc5
void no_hash(db_line* line);
Packit 762fc5
Packit 762fc5
static DB_ATTR_TYPE get_special_report_group(char* group) {
Packit 762fc5
    DB_ATTR_TYPE attr = get_groupval(group);
Packit 762fc5
    return attr==DB_ATTR_UNDEF?0:attr;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int bytecmp(byte *b1, byte *b2, size_t len) {
Packit 762fc5
  return strncmp((char *)b1, (char *)b2, len);
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int has_str_changed(char* old,char* new) {
Packit 762fc5
    return (((old!=NULL && new!=NULL) &&
Packit 762fc5
                strcmp(old,new)!=0 ) ||
Packit 762fc5
            ((old!=NULL && new==NULL) ||
Packit 762fc5
             (old==NULL && new!=NULL)));
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int has_md_changed(byte* old,byte* new,int len) {
Packit 762fc5
    error(255,"Debug, has_md_changed %p %p\n",old,new);
Packit 762fc5
    return (((old!=NULL && new!=NULL) &&
Packit 762fc5
                (bytecmp(old,new,len)!=0)) ||
Packit 762fc5
            ((old!=NULL && new==NULL) ||
Packit 762fc5
             (old==NULL && new!=NULL)));
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
#ifdef WITH_ACL
Packit 762fc5
#ifdef WITH_SUN_ACL
Packit 762fc5
static int compare_single_acl(aclent_t* a1,aclent_t* a2) {
Packit 762fc5
  if (a1->a_type!=a2->a_type ||
Packit 762fc5
      a1->a_id!=a2->a_id ||
Packit 762fc5
      a1->a_perm!=a2->a_perm) {
Packit 762fc5
    return RETFAIL;
Packit 762fc5
  }
Packit 762fc5
  return RETOK;
Packit 762fc5
}
Packit 762fc5
#endif
Packit 762fc5
static int has_acl_changed(acl_type* old, acl_type* new) {
Packit 762fc5
#ifdef WITH_SUN_ACL
Packit 762fc5
    int i;
Packit 762fc5
#endif
Packit 762fc5
    if (old==NULL && new==NULL) {
Packit 762fc5
        return RETOK;
Packit 762fc5
    }
Packit 762fc5
    if (old==NULL || new==NULL) {
Packit 762fc5
        return RETFAIL;
Packit 762fc5
    }
Packit 762fc5
#ifdef WITH_POSIX_ACL
Packit 762fc5
    if ((!old->acl_a != !new->acl_a)
Packit 762fc5
            || (!old->acl_d != !new->acl_d)
Packit 762fc5
            || (old->acl_a && strcmp(old->acl_a, new->acl_a))
Packit 762fc5
            || (old->acl_d && strcmp(old->acl_d, new->acl_d))){
Packit 762fc5
        return RETFAIL;
Packit 762fc5
    }
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_SUN_ACL
Packit 762fc5
    if (old->entries!=new->entries) {
Packit 762fc5
        return RETFAIL;
Packit 762fc5
    }
Packit 762fc5
    /* Sort em up. */
Packit 762fc5
    aclsort(old->entries,0,old->acl);
Packit 762fc5
    aclsort(new->entries,0,new->acl);
Packit 762fc5
    for(i=0;i<old->entries;i++){
Packit 762fc5
        if (compare_single_acl(old->acl+i,new->acl+i)==RETFAIL) {
Packit 762fc5
            return RETFAIL;
Packit 762fc5
        }
Packit 762fc5
    }
Packit 762fc5
#endif
Packit 762fc5
    return RETOK;
Packit 762fc5
}
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_XATTR
Packit 762fc5
static int cmp_xattr_node(const void *c1, const void *c2)
Packit 762fc5
{
Packit 762fc5
  const xattr_node *x1 = c1;
Packit 762fc5
  const xattr_node *x2 = c2;
Packit 762fc5
Packit 762fc5
  return (strcmp(x1->key, x2->key));
Packit 762fc5
}
Packit 762fc5
static int have_xattrs_changed(xattrs_type* x1,xattrs_type* x2) {
Packit 762fc5
  size_t num = 0;
Packit 762fc5
Packit 762fc5
  if (x1 && (x1->num == 0)) x1 = NULL;
Packit 762fc5
  if (x2 && (x2->num == 0)) x2 = NULL;
Packit 762fc5
Packit 762fc5
  if (x1==NULL && x2==NULL) {
Packit 762fc5
    return RETOK;
Packit 762fc5
  }
Packit 762fc5
  if (x1==NULL || x2==NULL) {
Packit 762fc5
    return RETFAIL;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  if (x1->num != x2->num) {
Packit 762fc5
    return RETFAIL;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  qsort(x1->ents, x1->num, sizeof(xattr_node), cmp_xattr_node);
Packit 762fc5
  qsort(x2->ents, x2->num, sizeof(xattr_node), cmp_xattr_node);
Packit 762fc5
Packit 762fc5
  while (num++ < x1->num) {
Packit 762fc5
    const char *x1key = NULL;
Packit 762fc5
    const byte *x1val = NULL;
Packit 762fc5
    size_t x1vsz = 0;
Packit 762fc5
    const char *x2key = NULL;
Packit 762fc5
    const byte *x2val = NULL;
Packit 762fc5
    size_t x2vsz = 0;
Packit 762fc5
Packit 762fc5
    x1key = x1->ents[num - 1].key;
Packit 762fc5
    x1val = x1->ents[num - 1].val;
Packit 762fc5
    x1vsz = x1->ents[num - 1].vsz;
Packit 762fc5
Packit 762fc5
    x2key = x2->ents[num - 1].key;
Packit 762fc5
    x2val = x2->ents[num - 1].val;
Packit 762fc5
    x2vsz = x2->ents[num - 1].vsz;
Packit 762fc5
Packit 762fc5
    if (strcmp(x1key, x2key) ||
Packit 762fc5
        x1vsz != x2vsz ||
Packit 762fc5
        memcmp(x1val, x2val, x1vsz))
Packit 762fc5
      return RETFAIL;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  return RETOK;
Packit 762fc5
}
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_E2FSATTRS
Packit 762fc5
static int has_e2fsattrs_changed(unsigned long old, unsigned long new) {
Packit 762fc5
    return (~(conf->report_ignore_e2fsattrs)&(old^new));
Packit 762fc5
}
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
/*
Packit 762fc5
 * Returns the changed attributes for two database lines.
Packit 762fc5
 *
Packit 762fc5
 * Attributes are only compared if they exist in both database lines.
Packit 762fc5
*/
Packit 762fc5
static DB_ATTR_TYPE get_changed_attributes(db_line* l1,db_line* l2) {
Packit 762fc5
Packit 762fc5
#define easy_compare(a,b) \
Packit 762fc5
    if((a&l1->attr && (a&l2->attr)) && l1->b!=l2->b){\
Packit 762fc5
        ret|=a;\
Packit 762fc5
    }
Packit 762fc5
Packit 762fc5
#define easy_md_compare(a,b,c) \
Packit 762fc5
    if((a&l1->attr && (a&l2->attr)) && has_md_changed(l1->b,l2->b, c)){ \
Packit 762fc5
        ret|=a; \
Packit 762fc5
    }
Packit 762fc5
Packit 762fc5
#define easy_function_compare(a,b,c) \
Packit 762fc5
    if((a&l1->attr && (a&l2->attr)) && c(l1->b,l2->b)){ \
Packit 762fc5
        ret|=a; \
Packit 762fc5
    }
Packit 762fc5
Packit 762fc5
    DB_ATTR_TYPE ret=0;
Packit 762fc5
Packit 762fc5
    if ((DB_FTYPE&l1->attr && DB_FTYPE&l2->attr) && (l1->perm&S_IFMT)!=(l2->perm&S_IFMT)) { ret|=DB_FTYPE; }
Packit 762fc5
    easy_function_compare(DB_LINKNAME,linkname,has_str_changed);
Packit 762fc5
    if ((DB_SIZEG&l1->attr && DB_SIZEG&l2->attr) && l1->size>l2->size){ ret|=DB_SIZEG; }
Packit 762fc5
    easy_compare(DB_SIZE,size);
Packit 762fc5
    easy_compare(DB_BCOUNT,bcount);
Packit 762fc5
    easy_compare(DB_PERM,perm);
Packit 762fc5
    easy_compare(DB_UID,uid);
Packit 762fc5
    easy_compare(DB_GID,gid);
Packit 762fc5
    easy_compare(DB_ATIME,atime);
Packit 762fc5
    easy_compare(DB_MTIME,mtime);
Packit 762fc5
    easy_compare(DB_CTIME,ctime);
Packit 762fc5
    easy_compare(DB_INODE,inode);
Packit 762fc5
    easy_compare(DB_LNKCOUNT,nlink);
Packit 762fc5
Packit 762fc5
    easy_md_compare(DB_MD5,md5,HASH_MD5_LEN);
Packit 762fc5
    easy_md_compare(DB_SHA1,sha1,HASH_SHA1_LEN);
Packit 762fc5
    easy_md_compare(DB_RMD160,rmd160,HASH_RMD160_LEN);
Packit 762fc5
    easy_md_compare(DB_TIGER,tiger,HASH_TIGER_LEN);
Packit 762fc5
    easy_md_compare(DB_SHA256,sha256,HASH_SHA256_LEN);
Packit 762fc5
    easy_md_compare(DB_SHA512,sha512,HASH_SHA512_LEN);
Packit 762fc5
Packit 762fc5
#ifdef WITH_MHASH
Packit 762fc5
    easy_md_compare(DB_CRC32,crc32,HASH_CRC32_LEN);
Packit 762fc5
    easy_md_compare(DB_HAVAL,haval,HASH_HAVAL256_LEN);
Packit 762fc5
    easy_md_compare(DB_GOST,gost,HASH_GOST_LEN);
Packit 762fc5
    easy_md_compare(DB_CRC32B,crc32b,HASH_CRC32B_LEN);
Packit 762fc5
    easy_md_compare(DB_WHIRLPOOL,whirlpool,HASH_WHIRLPOOL_LEN);
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_ACL
Packit 762fc5
    easy_function_compare(DB_ACL,acl,has_acl_changed);
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_XATTR
Packit 762fc5
    easy_function_compare(DB_XATTRS,xattrs,have_xattrs_changed);
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_SELINUX
Packit 762fc5
    easy_function_compare(DB_SELINUX,cntx,has_str_changed);
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_E2FSATTRS
Packit 762fc5
    easy_function_compare(DB_E2FSATTRS,e2fsattrs,has_e2fsattrs_changed);
Packit 762fc5
#endif
Packit 762fc5
    error(255,"Debug, changed attributes for entry %s [%llx %llx]: %llx\n", l1->filename,l1->attr,l2->attr,ret);
Packit 762fc5
    return ret;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
int compare_node_by_path(const void *n1, const void *n2)
Packit 762fc5
{
Packit 762fc5
    const seltree *x1 = n1;
Packit 762fc5
    const seltree *x2 = n2;
Packit 762fc5
    return strcmp(x1->path, x2->path);
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
char* strrxtok(char* rx)
Packit 762fc5
{
Packit 762fc5
  char*p=NULL;
Packit 762fc5
  char*t=NULL;
Packit 762fc5
  size_t i=0;
Packit 762fc5
Packit 762fc5
  /* The following code assumes that the first character is a slash */
Packit 762fc5
  size_t lastslash=1;
Packit 762fc5
Packit 762fc5
  p=strdup(rx);
Packit 762fc5
  p[0]='/';
Packit 762fc5
Packit 762fc5
  for(i=1;i
Packit 762fc5
    switch(p[i])
Packit 762fc5
      {
Packit 762fc5
      case '/':
Packit 762fc5
	lastslash=i;
Packit 762fc5
	break;
Packit 762fc5
      case '(':
Packit 762fc5
      case '^':
Packit 762fc5
      case '$':
Packit 762fc5
      case '*':
Packit 762fc5
      case '[':
Packit 762fc5
	i=strlen(p);
Packit 762fc5
	break;
Packit 762fc5
      case '\\':
Packit 762fc5
	t=strdup(p);
Packit 762fc5
	strcpy(p+i,t+i+1);
Packit 762fc5
	free(t);
Packit 762fc5
	t=NULL;
Packit 762fc5
	break;
Packit 762fc5
      default:
Packit 762fc5
	break;
Packit 762fc5
      }
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  p[lastslash]='\0';
Packit 762fc5
Packit 762fc5
  return p;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
char* strlastslash(char*str)
Packit 762fc5
{
Packit 762fc5
  char* p=NULL;
Packit 762fc5
  size_t lastslash=1;
Packit 762fc5
  size_t i=0;
Packit 762fc5
Packit 762fc5
  for(i=1;i
Packit 762fc5
    if(str[i]=='/'){
Packit 762fc5
      lastslash=i;
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
  p=(char*)malloc(sizeof(char)*lastslash+1);
Packit 762fc5
  strncpy(p,str,lastslash);
Packit 762fc5
  p[lastslash]='\0';
Packit 762fc5
Packit 762fc5
  return p;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
char* strgetndirname(char* path,int depth)
Packit 762fc5
{
Packit 762fc5
  char* r=NULL;
Packit 762fc5
  char* tmp=NULL;
Packit 762fc5
  int i=0;
Packit 762fc5
Packit 762fc5
  for(r=path;;r+=1){
Packit 762fc5
    if(*r=='/')
Packit 762fc5
      i++;
Packit 762fc5
    if(*r=='\0')
Packit 762fc5
      break;
Packit 762fc5
    if(i==depth)
Packit 762fc5
      break;
Packit 762fc5
  }
Packit 762fc5
  /* If we ran out string return the whole string */
Packit 762fc5
  if(!(*r))
Packit 762fc5
    return strdup(path);
Packit 762fc5
Packit 762fc5
  tmp=strdup(path);
Packit 762fc5
Packit 762fc5
  tmp[r-path]='\0';
Packit 762fc5
Packit 762fc5
  return tmp;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
int treedepth(seltree* node)
Packit 762fc5
{
Packit 762fc5
  seltree* r=NULL;
Packit 762fc5
  int depth=0;
Packit 762fc5
Packit 762fc5
  for(r=node;r;r=r->parent)
Packit 762fc5
    depth++;
Packit 762fc5
  
Packit 762fc5
  return depth;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/* This function returns a node with the same inode value as the 'file' */
Packit 762fc5
/* The only place it is used is in add_file_to_tree() function */
Packit 762fc5
static seltree* get_seltree_inode(seltree* tree, db_line* file, int db)
Packit 762fc5
{
Packit 762fc5
  seltree* node=NULL;
Packit 762fc5
  list* r=NULL;
Packit 762fc5
  char* tmp=NULL;
Packit 762fc5
Packit 762fc5
  if(tree==NULL){
Packit 762fc5
    return NULL;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  /* found the match */
Packit 762fc5
  if((db == DB_NEW &&
Packit 762fc5
      tree->new_data != NULL &&
Packit 762fc5
      file->inode == tree->new_data->inode) ||
Packit 762fc5
     (db == DB_OLD &&
Packit 762fc5
      tree->old_data != NULL &&
Packit 762fc5
      file->inode == tree->old_data->inode)) {
Packit 762fc5
    return tree;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  /* tmp is the directory of the file->filename */
Packit 762fc5
  tmp=strgetndirname(file->filename,treedepth(tree)+1);
Packit 762fc5
  for(r=tree->childs;r;r=r->next){
Packit 762fc5
    /* We are interested only in files with the same regexp specification */
Packit 762fc5
    if(strlen(tmp) == strlen(file->filename) ||
Packit 762fc5
       strncmp(((seltree*)r->data)->path,tmp,strlen(tmp)+1)==0){
Packit 762fc5
      node=get_seltree_inode((seltree*)r->data,file,db);
Packit 762fc5
      if(node!=NULL){
Packit 762fc5
	break;
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  free(tmp);
Packit 762fc5
  return node;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
seltree* get_seltree_node(seltree* tree,char* path)
Packit 762fc5
{
Packit 762fc5
  seltree* node=NULL;
Packit 762fc5
  list* r=NULL;
Packit 762fc5
  char* tmp=NULL;
Packit 762fc5
Packit 762fc5
  if(tree==NULL){
Packit 762fc5
    return NULL;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  if(strncmp(path,tree->path,strlen(path)+1)==0){
Packit 762fc5
    return tree;
Packit 762fc5
  }
Packit 762fc5
  else{
Packit 762fc5
    tmp=strgetndirname(path,treedepth(tree)+1);
Packit 762fc5
    for(r=tree->childs;r;r=r->next){
Packit 762fc5
      if(strncmp(((seltree*)r->data)->path,tmp,strlen(tmp)+1)==0){
Packit 762fc5
	node=get_seltree_node((seltree*)r->data,path);
Packit 762fc5
	if(node!=NULL){
Packit 762fc5
	  /* Don't leak memory */
Packit 762fc5
	  free(tmp);
Packit 762fc5
	  return node;
Packit 762fc5
	}
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
    free(tmp);
Packit 762fc5
  }
Packit 762fc5
  return NULL;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void copy_rule_ref(seltree* node, rx_rule* r)
Packit 762fc5
{
Packit 762fc5
    if( r!=NULL ){
Packit 762fc5
        node->conf_lineno = r->conf_lineno;  
Packit 762fc5
        node->rx=strdup(r->rx);
Packit 762fc5
    } else {
Packit 762fc5
        node->conf_lineno = -1;
Packit 762fc5
        node->rx=NULL;
Packit 762fc5
    }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
seltree* new_seltree_node(
Packit 762fc5
        seltree* tree,
Packit 762fc5
        char*path,
Packit 762fc5
        int isrx,
Packit 762fc5
        rx_rule* r)
Packit 762fc5
{
Packit 762fc5
  seltree* node=NULL;
Packit 762fc5
  seltree* parent=NULL;
Packit 762fc5
  char* tmprxtok = NULL;
Packit 762fc5
Packit 762fc5
  node=(seltree*)malloc(sizeof(seltree));
Packit 762fc5
  node->childs=NULL;
Packit 762fc5
  node->path=strdup(path);
Packit 762fc5
  node->sel_rx_lst=NULL;
Packit 762fc5
  node->neg_rx_lst=NULL;
Packit 762fc5
  node->equ_rx_lst=NULL;
Packit 762fc5
  node->checked=0;
Packit 762fc5
  node->attr=0;
Packit 762fc5
  node->new_data=NULL;
Packit 762fc5
  node->old_data=NULL;
Packit 762fc5
Packit 762fc5
  copy_rule_ref(node,r);
Packit 762fc5
Packit 762fc5
  if(tree!=NULL){
Packit 762fc5
    tmprxtok = strrxtok(path);
Packit 762fc5
    if(isrx){
Packit 762fc5
      parent=get_seltree_node(tree,tmprxtok);
Packit 762fc5
    }else {
Packit 762fc5
      char* dirn=strlastslash(path);
Packit 762fc5
      parent=get_seltree_node(tree,dirn);
Packit 762fc5
      free(dirn);
Packit 762fc5
    }      
Packit 762fc5
    if(parent==NULL){
Packit 762fc5
      if(isrx){
Packit 762fc5
	parent=new_seltree_node(tree,tmprxtok,isrx,r);
Packit 762fc5
      }else {
Packit 762fc5
        char* dirn=strlastslash(path);
Packit 762fc5
        parent=new_seltree_node(tree,dirn,isrx,r);
Packit 762fc5
        free(dirn);
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
    free(tmprxtok);
Packit 762fc5
    parent->childs=list_sorted_insert(parent->childs,(void*)node, compare_node_by_path);
Packit 762fc5
    node->parent=parent;
Packit 762fc5
  }else {
Packit 762fc5
    node->parent=NULL;
Packit 762fc5
  }
Packit 762fc5
  return node;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void gen_seltree(list* rxlist,seltree* tree,char type)
Packit 762fc5
{
Packit 762fc5
  pcre*        rxtmp = NULL;
Packit 762fc5
  const char*  pcre_error;
Packit 762fc5
  int          pcre_erroffset;
Packit 762fc5
Packit 762fc5
  seltree*     curnode = NULL;
Packit 762fc5
  list*        r       = NULL;
Packit 762fc5
  char*        rxtok   = NULL;
Packit 762fc5
  rx_rule*     rxc     = NULL;
Packit 762fc5
Packit 762fc5
  for(r=rxlist;r;r=r->next){
Packit 762fc5
    rx_rule* curr_rule = (rx_rule*)r->data;
Packit 762fc5
    
Packit 762fc5
    
Packit 762fc5
    rxtok=strrxtok(curr_rule->rx);
Packit 762fc5
    curnode=get_seltree_node(tree,rxtok);
Packit 762fc5
Packit 762fc5
    if(curnode==NULL){
Packit 762fc5
      curnode=new_seltree_node(tree,rxtok,1,curr_rule);
Packit 762fc5
    }
Packit 762fc5
Packit 762fc5
    error(240,"Handling %s with %c \"%s\" with node \"%s\"\n",rxtok,type,curr_rule->rx,curnode->path);
Packit 762fc5
Packit 762fc5
    if((rxtmp=pcre_compile(curr_rule->rx, PCRE_ANCHORED, &pcre_error, &pcre_erroffset, NULL)) == NULL) {
Packit 762fc5
      error(0,_("Error in regexp '%s' at %i: %s\n"),curr_rule->rx, pcre_erroffset, pcre_error);
Packit 762fc5
    }else{
Packit 762fc5
      /* replace regexp text with regexp compiled */
Packit 762fc5
      rxc=(rx_rule*)malloc(sizeof(rx_rule));
Packit 762fc5
      /* and copy the rest */
Packit 762fc5
      rxc->rx=curr_rule->rx;
Packit 762fc5
      rxc->crx=rxtmp;
Packit 762fc5
      rxc->attr=curr_rule->attr;
Packit 762fc5
      rxc->conf_lineno=curr_rule->conf_lineno;
Packit 762fc5
      rxc->restriction=curr_rule->restriction;
Packit 762fc5
Packit 762fc5
      switch (type){
Packit 762fc5
      case 's':{
Packit 762fc5
	curnode->sel_rx_lst=list_append(curnode->sel_rx_lst,(void*)rxc);
Packit 762fc5
	break;
Packit 762fc5
      }
Packit 762fc5
      case 'n':{
Packit 762fc5
	curnode->neg_rx_lst=list_append(curnode->neg_rx_lst,(void*)rxc);
Packit 762fc5
	break;
Packit 762fc5
      }
Packit 762fc5
      case 'e':{
Packit 762fc5
	curnode->equ_rx_lst=list_append(curnode->equ_rx_lst,(void*)rxc);
Packit 762fc5
	break;
Packit 762fc5
      }
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
    /* Data should not be free'ed because it's in rxc struct
Packit 762fc5
     * and freeing is done if error occour.
Packit 762fc5
     */
Packit 762fc5
      free(rxtok);
Packit 762fc5
  }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static RESTRICTION_TYPE get_file_type(mode_t mode) {
Packit 762fc5
    switch (mode & S_IFMT) {
Packit 762fc5
        case S_IFREG: return RESTRICTION_FT_REG;
Packit 762fc5
        case S_IFDIR: return RESTRICTION_FT_DIR;
Packit 762fc5
#ifdef S_IFIFO
Packit 762fc5
        case S_IFIFO: return RESTRICTION_FT_FIFO;
Packit 762fc5
#endif
Packit 762fc5
        case S_IFLNK: return RESTRICTION_FT_LNK;
Packit 762fc5
        case S_IFBLK: return RESTRICTION_FT_BLK;
Packit 762fc5
        case S_IFCHR: return RESTRICTION_FT_CHR;
Packit 762fc5
#ifdef S_IFSOCK
Packit 762fc5
        case S_IFSOCK: return RESTRICTION_FT_SOCK;
Packit 762fc5
#endif
Packit 762fc5
#ifdef S_IFDOOR
Packit 762fc5
        case S_IFDOOR: return RESTRICTION_FT_DOOR;
Packit 762fc5
#endif
Packit 762fc5
#ifdef S_IFDOOR
Packit 762fc5
        case S_IFPORT: return RESTRICTION_FT_PORT;
Packit 762fc5
#endif
Packit 762fc5
        default: return RESTRICTION_NULL;
Packit 762fc5
    }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int check_list_for_match(list* rxrlist,char* text,DB_ATTR_TYPE* attr, RESTRICTION_TYPE file_type)
Packit 762fc5
{
Packit 762fc5
  list* r=NULL;
Packit 762fc5
  int retval=1;
Packit 762fc5
  int pcre_retval;
Packit 762fc5
  pcre_extra *pcre_extra = NULL;
Packit 762fc5
  for(r=rxrlist;r;r=r->next){
Packit 762fc5
      pcre_retval=pcre_exec((pcre*)((rx_rule*)r->data)->crx, pcre_extra, text, strlen(text), 0, PCRE_PARTIAL_SOFT, NULL, 0);
Packit 762fc5
      if (pcre_retval >= 0) {
Packit 762fc5
              error(231,"\"%s\" matches (pcre_exec return value: %i) rule from line #%ld: %s\n",text, pcre_retval, ((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
Packit 762fc5
          if (!((rx_rule*)r->data)->restriction || file_type&((rx_rule*)r->data)->restriction) {
Packit 762fc5
              *attr=((rx_rule*)r->data)->attr;
Packit 762fc5
              error(231,"\"%s\" matches restriction (%u) for rule from line #%ld: %s\n",text, ((rx_rule*)r->data)->restriction, ((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
Packit 762fc5
              return 0;
Packit 762fc5
          } else {
Packit 762fc5
              error(232,"\"%s\" doesn't match restriction (%u) for rule from line #%ld: %s\n",text, ((rx_rule*)r->data)->restriction, ((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
Packit 762fc5
              retval=-1;
Packit 762fc5
          }
Packit 762fc5
      } else if (pcre_retval == PCRE_ERROR_PARTIAL) {
Packit 762fc5
          error(232,"\"%s\" PARTIAL matches (pcre_exec return value: %i) rule from line #%ld: %s\n",text, pcre_retval, ((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
Packit 762fc5
          retval=-1;
Packit 762fc5
      } else {
Packit 762fc5
          error(232,"\"%s\" doesn't match (pcre_exec return value: %i) rule from line #%ld: %s\n",text, pcre_retval,((rx_rule*)r->data)->conf_lineno,((rx_rule*)r->data)->rx);
Packit 762fc5
      }
Packit 762fc5
  }
Packit 762fc5
  return retval;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/* 
Packit 762fc5
 * Function check_node_for_match()
Packit 762fc5
 * calls itself recursively to go to the top and then back down.
Packit 762fc5
 * uses check_list_for_match()
Packit 762fc5
 * returns:
Packit 762fc5
 * 0,  if a negative rule was matched 
Packit 762fc5
 * 1,  if a selective rule was matched
Packit 762fc5
 * 2,  if a equals rule was matched
Packit 762fc5
 * retval if no rule was matched.
Packit 762fc5
 * retval&3 if no rule was matched and first in the recursion
Packit 762fc5
 * to keep state revat is orred with:
Packit 762fc5
 * 4,  matched deeper on equ rule
Packit 762fc5
 * 8,  matched deeper on sel rule
Packit 762fc5
 *16,  this is a recursed call
Packit 762fc5
 */    
Packit 762fc5
Packit 762fc5
static int check_node_for_match(seltree*node,char*text, mode_t perm, int retval,DB_ATTR_TYPE* attr)
Packit 762fc5
{
Packit 762fc5
  int top=0;
Packit 762fc5
  RESTRICTION_TYPE file_type;
Packit 762fc5
  
Packit 762fc5
  if(node==NULL){
Packit 762fc5
    return retval;
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
   file_type = get_file_type(perm);
Packit 762fc5
Packit 762fc5
  /* if this call is not recursive we check the equals list and we set top *
Packit 762fc5
   * and retval so we know following calls are recursive */
Packit 762fc5
  if(!(retval&16)){
Packit 762fc5
    top=1;
Packit 762fc5
    retval|=16;
Packit 762fc5
Packit 762fc5
      switch (check_list_for_match(node->equ_rx_lst, text, attr, file_type)) {
Packit 762fc5
          case 0: {
Packit 762fc5
              error(220, "check_node_for_match: equal match for '%s'\n", text);
Packit 762fc5
              retval|=2|4;
Packit 762fc5
              break;
Packit 762fc5
          }
Packit 762fc5
          case -1: {
Packit 762fc5
           if(S_ISDIR(perm) && get_seltree_node(node,text)==NULL) {
Packit 762fc5
               error(220, "check_node_for_match: creating new seltree node for '%s'\n", text);
Packit 762fc5
               new_seltree_node(node,text,0,NULL);
Packit 762fc5
           }
Packit 762fc5
           break;
Packit 762fc5
          }
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  /* We'll use retval to pass information on whether to recurse 
Packit 762fc5
   * the dir or not */
Packit 762fc5
Packit 762fc5
Packit 762fc5
  /* If 4 and 8 are not set, we will check for matches */
Packit 762fc5
  if(!(retval&(4|8))){
Packit 762fc5
      switch (check_list_for_match(node->sel_rx_lst, text, attr, file_type)) {
Packit 762fc5
          case 0: {
Packit 762fc5
              error(220, "check_node_for_match: selective match for '%s'\n", text);
Packit 762fc5
              retval|=1|8;
Packit 762fc5
              break;
Packit 762fc5
          }
Packit 762fc5
          case -1: {
Packit 762fc5
           if(S_ISDIR(perm) && get_seltree_node(node,text)==NULL) {
Packit 762fc5
               error(220, "check_node_for_match: creating new seltree node for '%s'\n", text);
Packit 762fc5
               new_seltree_node(node,text,0,NULL);
Packit 762fc5
           }
Packit 762fc5
           break;
Packit 762fc5
          }
Packit 762fc5
      }
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  /* Now let's check the ancestors */
Packit 762fc5
  retval=check_node_for_match(node->parent,text, perm, retval,attr);
Packit 762fc5
Packit 762fc5
Packit 762fc5
  /* Negative regexps are the strongest so they are checked last */
Packit 762fc5
  /* If this file is to be added */
Packit 762fc5
  if(retval){
Packit 762fc5
    if(!check_list_for_match(node->neg_rx_lst, text, attr, file_type)){
Packit 762fc5
      error(220, "check_node_for_match: negative match for '%s'\n", text);
Packit 762fc5
      retval=0;
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  /* Now we discard the info whether a match was made or not *
Packit 762fc5
   * and just return 0,1 or 2 */
Packit 762fc5
  if(top){
Packit 762fc5
    retval&=3;
Packit 762fc5
  }
Packit 762fc5
  return retval;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void print_tree(seltree* tree) {
Packit 762fc5
  
Packit 762fc5
  list* r;
Packit 762fc5
  rx_rule* rxc;
Packit 762fc5
  error(220,"tree: \"%s\"\n",tree->path);
Packit 762fc5
Packit 762fc5
  for(r=tree->sel_rx_lst;r!=NULL;r=r->next) {
Packit 762fc5
	rxc=r->data;
Packit 762fc5
	error(220,"%li\t%s\n",rxc->conf_lineno,rxc->rx);
Packit 762fc5
  }
Packit 762fc5
  for(r=tree->equ_rx_lst;r!=NULL;r=r->next) {
Packit 762fc5
        rxc=r->data;
Packit 762fc5
        error(220,"%li=\t%s\n",rxc->conf_lineno,rxc->rx);
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
  for(r=tree->neg_rx_lst;r!=NULL;r=r->next) {
Packit 762fc5
	  rxc=r->data;
Packit 762fc5
	  error(220,"%li!\t%s\n",rxc->conf_lineno,rxc->rx);
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
  for(r=tree->childs;r!=NULL;r=r->next) {
Packit 762fc5
	print_tree(r->data);
Packit 762fc5
  }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
seltree* gen_tree(list* prxlist,list* nrxlist,list* erxlist)
Packit 762fc5
{
Packit 762fc5
  seltree* tree=NULL;
Packit 762fc5
Packit 762fc5
  tree=new_seltree_node(NULL,"/",0,NULL);
Packit 762fc5
Packit 762fc5
  gen_seltree(prxlist,tree,'s');
Packit 762fc5
  gen_seltree(nrxlist,tree,'n');
Packit 762fc5
  gen_seltree(erxlist,tree,'e');
Packit 762fc5
Packit 762fc5
  print_tree(tree);
Packit 762fc5
Packit 762fc5
  return tree;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/*
Packit 762fc5
 * strip_dbline()
Packit 762fc5
 * strips given dbline
Packit 762fc5
 */
Packit 762fc5
void strip_dbline(db_line* line)
Packit 762fc5
{
Packit 762fc5
#define checked_free(x) do { free(x); x=NULL; } while (0)
Packit 762fc5
Packit 762fc5
    DB_ATTR_TYPE attr = line->attr;
Packit 762fc5
Packit 762fc5
  /* filename is always needed, hence it is never stripped */
Packit 762fc5
  if(!(attr&DB_LINKNAME)){
Packit 762fc5
    checked_free(line->linkname);
Packit 762fc5
  }
Packit 762fc5
  /* permissions are always needed for file type detection, hence they are
Packit 762fc5
   * never stripped */
Packit 762fc5
  if(!(attr&DB_UID)){
Packit 762fc5
    line->uid=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_GID)){
Packit 762fc5
    line->gid=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_ATIME)){
Packit 762fc5
    line->atime=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_CTIME)){
Packit 762fc5
    line->ctime=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_MTIME)){
Packit 762fc5
    line->mtime=0;
Packit 762fc5
  }
Packit 762fc5
  /* inode is always needed for ignoring changed filename, hence it is
Packit 762fc5
   * never stripped */
Packit 762fc5
  if(!(attr&DB_LNKCOUNT)){
Packit 762fc5
    line->nlink=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_SIZE)&&!(attr&DB_SIZEG)){
Packit 762fc5
    line->size=0;
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_BCOUNT)){
Packit 762fc5
    line->bcount=0;
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  if(!(attr&DB_MD5)){
Packit 762fc5
    checked_free(line->md5);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_SHA1)){
Packit 762fc5
    checked_free(line->sha1);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_RMD160)){
Packit 762fc5
    checked_free(line->rmd160);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_TIGER)){
Packit 762fc5
    checked_free(line->tiger);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_HAVAL)){
Packit 762fc5
    checked_free(line->haval);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_CRC32)){
Packit 762fc5
    checked_free(line->crc32);
Packit 762fc5
  }
Packit 762fc5
#ifdef WITH_MHASH
Packit 762fc5
  if(!(attr&DB_CRC32B)){
Packit 762fc5
    checked_free(line->crc32b);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_GOST)){
Packit 762fc5
    checked_free(line->gost);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_WHIRLPOOL)){
Packit 762fc5
    checked_free(line->whirlpool);
Packit 762fc5
  }
Packit 762fc5
#endif
Packit 762fc5
  if(!(attr&DB_SHA256)){
Packit 762fc5
    checked_free(line->sha256);
Packit 762fc5
  }
Packit 762fc5
  if(!(attr&DB_SHA512)){
Packit 762fc5
    checked_free(line->sha512);
Packit 762fc5
  }
Packit 762fc5
#ifdef WITH_ACL
Packit 762fc5
  if(!(attr&DB_ACL)){
Packit 762fc5
    if (line->acl)
Packit 762fc5
    {
Packit 762fc5
      free(line->acl->acl_a);
Packit 762fc5
      free(line->acl->acl_d);
Packit 762fc5
    }
Packit 762fc5
    checked_free(line->acl);
Packit 762fc5
  }
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_XATTR
Packit 762fc5
  if(!(attr&DB_XATTRS)){
Packit 762fc5
    if (line->xattrs)
Packit 762fc5
      free(line->xattrs->ents);
Packit 762fc5
    checked_free(line->xattrs);
Packit 762fc5
  }
Packit 762fc5
#endif
Packit 762fc5
#ifdef WITH_SELINUX
Packit 762fc5
  if(!(attr&DB_SELINUX)){
Packit 762fc5
    checked_free(line->cntx);
Packit 762fc5
  }
Packit 762fc5
#endif
Packit 762fc5
  /* e2fsattrs is stripped within e2fsattrs2line in do_md */
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/*
Packit 762fc5
 * add_file_to_tree
Packit 762fc5
 * db = which db this file belongs to
Packit 762fc5
 * attr attributes to add
Packit 762fc5
 */
Packit 762fc5
static void add_file_to_tree(seltree* tree,db_line* file,int db,
Packit 762fc5
                      DB_ATTR_TYPE attr)
Packit 762fc5
{
Packit 762fc5
  seltree* node=NULL;
Packit 762fc5
  DB_ATTR_TYPE localignorelist=0;
Packit 762fc5
  DB_ATTR_TYPE ignored_added_attrs, ignored_removed_attrs, ignored_changed_attrs;
Packit 762fc5
Packit d0fd42
  if(file==NULL){
Packit d0fd42
    error(0, "add_file_to_tree was called with NULL db_line\n");
Packit d0fd42
  }
Packit d0fd42
Packit 762fc5
  node=get_seltree_node(tree,file->filename);
Packit 762fc5
Packit 762fc5
  if(!node){
Packit 762fc5
    node=new_seltree_node(tree,file->filename,0,NULL);
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  /* add note to this node which db has modified it */
Packit 762fc5
  node->checked|=db;
Packit 762fc5
Packit 762fc5
  node->attr=attr;
Packit 762fc5
Packit 762fc5
  strip_dbline(file);
Packit 762fc5
Packit 762fc5
  switch (db) {
Packit 762fc5
  case DB_OLD: {
Packit 762fc5
    node->old_data=file;
Packit 762fc5
    break;
Packit 762fc5
  }
Packit 762fc5
  case DB_NEW: {
Packit 762fc5
    node->new_data=file;
Packit 762fc5
    break;
Packit 762fc5
  }
Packit 762fc5
  case DB_OLD|DB_NEW: {
Packit 762fc5
    node->new_data=file;
Packit 762fc5
    if(conf->action&DO_INIT) {
Packit 762fc5
        node->checked|=NODE_FREE;
Packit 762fc5
    } else {
Packit 762fc5
        free_db_line(node->new_data);
Packit 762fc5
        free(node->new_data);
Packit 762fc5
        node->new_data=NULL;
Packit 762fc5
    }
Packit 762fc5
    return;
Packit 762fc5
  }
Packit 762fc5
  }
Packit 762fc5
  /* We have a way to ignore some changes... */
Packit 762fc5
  ignored_added_attrs = get_special_report_group("report_ignore_added_attrs");
Packit 762fc5
  ignored_removed_attrs = get_special_report_group("report_ignore_removed_attrs");
Packit 762fc5
  ignored_changed_attrs = get_special_report_group("report_ignore_changed_attrs");
Packit 762fc5
Packit 762fc5
  if((node->checked&DB_OLD)&&(node->checked&DB_NEW)){
Packit 762fc5
      if (((node->old_data)->attr&~((node->new_data)->attr)&~(ignored_removed_attrs))|(~((node->old_data)->attr)&(node->new_data)->attr&~(ignored_added_attrs))) {
Packit 762fc5
      error(2,"Entry %s in databases has different attributes: %llx %llx\n",
Packit 762fc5
            node->old_data->filename,node->old_data->attr,node->new_data->attr);
Packit 762fc5
    }
Packit 762fc5
Packit 762fc5
    node->changed_attrs=get_changed_attributes(node->old_data,node->new_data);
Packit 762fc5
    /* Free the data if same else leave as is for report_tree */
Packit 762fc5
    if((~(ignored_changed_attrs)&node->changed_attrs)==RETOK){
Packit 762fc5
      /* FIXME this messes up the tree on SunOS. Don't know why. Fix
Packit 762fc5
	 needed badly otherwise we leak memory like hell. */
Packit 762fc5
Packit 762fc5
      node->changed_attrs=0;
Packit 762fc5
Packit 762fc5
      free_db_line(node->old_data);
Packit 762fc5
      free(node->old_data);
Packit 762fc5
      node->old_data=NULL;
Packit 762fc5
Packit 762fc5
      /* Free new data if not needed for write_tree */
Packit 762fc5
      if(conf->action&DO_INIT) {
Packit 762fc5
          node->checked|=NODE_FREE;
Packit 762fc5
      } else {
Packit 762fc5
          free_db_line(node->new_data);
Packit 762fc5
          free(node->new_data);
Packit 762fc5
          node->new_data=NULL;
Packit 762fc5
      }
Packit 762fc5
      return;
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  /* Do verification if file was moved only if we are asked for it.
Packit 762fc5
   * old and new data are NULL only if file present in both DBs
Packit 762fc5
   * and has not been changed.
Packit 762fc5
   */
Packit 762fc5
  if( (node->old_data!=NULL || node->new_data!=NULL) &&
Packit 762fc5
    (file->attr & DB_CHECKINODE)) {
Packit 762fc5
    /* Check if file was moved (same inode, different name in the other DB)*/
Packit 762fc5
    db_line *oldData;
Packit 762fc5
    db_line *newData;
Packit 762fc5
    seltree* moved_node;
Packit 762fc5
Packit 762fc5
    moved_node=get_seltree_inode(tree,file,db==DB_OLD?DB_NEW:DB_OLD);
Packit 762fc5
    if(!(moved_node == NULL || moved_node == node)) {
Packit 762fc5
        /* There's mo match for inode or it matches the node with the same name.
Packit 762fc5
         * In first case we don't have a match to compare with.
Packit 762fc5
         * In the second - we already compared those files. */
Packit 762fc5
      if(db == DB_NEW) {
Packit 762fc5
        newData = node->new_data;
Packit 762fc5
        oldData = moved_node->old_data;
Packit 762fc5
      } else {
Packit 762fc5
        newData = moved_node->new_data;
Packit 762fc5
        oldData = node->old_data;
Packit 762fc5
      }
Packit 762fc5
Packit 762fc5
      localignorelist=(oldData->attr^newData->attr)&(~(DB_NEWFILE|DB_RMFILE|DB_CHECKINODE));
Packit 762fc5
Packit 762fc5
      if (localignorelist!=0) {
Packit 762fc5
         error(220,"Ignoring moved entry (\"%s\" [%llx] => \"%s\" [%llx]) due to different attributes: %llx\n",
Packit 762fc5
                 oldData->filename, oldData->attr, newData->filename, newData->attr, localignorelist);
Packit 762fc5
     } else {
Packit 762fc5
         /* Free the data if same else leave as is for report_tree */
Packit 762fc5
         if ((get_changed_attributes(oldData, newData)&~(ignored_changed_attrs|DB_CTIME)) == RETOK) {
Packit 762fc5
             node->checked |= db==DB_NEW ? NODE_MOVED_IN : NODE_MOVED_OUT;
Packit 762fc5
             moved_node->checked |= db==DB_NEW ? NODE_MOVED_OUT : NODE_MOVED_IN;
Packit 762fc5
             error(220,_("Entry was moved: %s [%llx] => %s [%llx]\n"),
Packit 762fc5
                     oldData->filename , oldData->attr, newData->filename, newData->attr);
Packit 762fc5
         } else {
Packit 762fc5
             error(220,"Ignoring moved entry (\"%s\" => \"%s\") because the entries mismatch\n",
Packit 762fc5
                     oldData->filename, newData->filename);
Packit 762fc5
         }
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  if( (db == DB_NEW) &&
Packit 762fc5
      (node->new_data!=NULL) &&
Packit 762fc5
      (file->attr & DB_NEWFILE) ){
Packit 762fc5
	 node->checked|=NODE_ALLOW_NEW;
Packit 762fc5
  }
Packit 762fc5
  if( (db == DB_OLD) &&
Packit 762fc5
      (node->old_data!=NULL) &&
Packit 762fc5
      (file->attr & DB_RMFILE) ){
Packit 762fc5
	  node->checked|=NODE_ALLOW_RM;
Packit 762fc5
  }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
int check_rxtree(char* filename,seltree* tree,DB_ATTR_TYPE* attr, mode_t perm)
Packit 762fc5
{
Packit 762fc5
  int retval=0;
Packit 762fc5
  char * tmp=NULL;
Packit 762fc5
  char * parentname=NULL;
Packit 762fc5
  seltree* pnode=NULL;
Packit 762fc5
Packit 762fc5
  parentname=strdup(filename);
Packit 762fc5
  tmp=strrchr(parentname,'/');
Packit 762fc5
  if(tmp!=parentname){
Packit 762fc5
    *tmp='\0';
Packit 762fc5
  }else {
Packit 762fc5
    
Packit 762fc5
    if(parentname[1]!='\0'){
Packit 762fc5
      /* we are in the root dir */
Packit 762fc5
      parentname[1]='\0';
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  if(conf->limit!=NULL) {
Packit 762fc5
      retval=pcre_exec(conf->limit_crx, NULL, filename, strlen(filename), 0, PCRE_PARTIAL_SOFT, NULL, 0);
Packit 762fc5
      if (retval >= 0) {
Packit 762fc5
          error(220, "check_rxtree: %s does match limit: %s\n", filename, conf->limit);
Packit 762fc5
      } else if (retval == PCRE_ERROR_PARTIAL) {
Packit 762fc5
          error(220, "check_rxtree: %s does PARTIAL match limit: %s\n", filename, conf->limit);
Packit 762fc5
          if(S_ISDIR(perm) && get_seltree_node(tree,filename)==NULL){
Packit 762fc5
              error(220, "check_rxtree: creating new seltree node for '%s'\n", filename);
Packit 762fc5
              new_seltree_node(tree,filename,0,NULL);
Packit 762fc5
          }
Packit 762fc5
          return -1;
Packit 762fc5
      } else {
Packit 762fc5
          error(220, "check_rxtree: %s does NOT match limit: %s\n", filename, conf->limit);
Packit 762fc5
          return -2;
Packit 762fc5
      }
Packit 762fc5
  }
Packit 762fc5
Packit 762fc5
  pnode=get_seltree_node(tree,parentname);
Packit 762fc5
Packit 762fc5
  *attr=0;
Packit 762fc5
  retval=check_node_for_match(pnode,filename, perm, 0,attr);
Packit 762fc5
    
Packit 762fc5
  free(parentname);
Packit 762fc5
Packit 762fc5
  return retval;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
db_line* get_file_attrs(char* filename,DB_ATTR_TYPE attr, struct AIDE_STAT_TYPE *fs)
Packit 762fc5
{
Packit 762fc5
  db_line* line=NULL;
Packit 762fc5
  time_t cur_time;
Packit 762fc5
Packit 762fc5
  if(!(attr&DB_RDEV))
Packit 762fc5
    fs->st_rdev=0;
Packit 762fc5
  /*
Packit 762fc5
    Get current time for future time notification.
Packit 762fc5
   */
Packit 762fc5
  cur_time=time(NULL);
Packit 762fc5
  
Packit 762fc5
  if (cur_time==(time_t)-1) {
Packit 762fc5
    char* er=strerror(errno);
Packit 762fc5
    if (er==NULL) {
Packit 762fc5
      error(0,_("Can not get current time. strerror failed for %i\n"),errno);
Packit 762fc5
    } else {
Packit 762fc5
      error(0,_("Can not get current time with reason %s\n"),er);
Packit 762fc5
    }
Packit 762fc5
  } else {
Packit 762fc5
    
Packit 762fc5
    if(fs->st_atime>cur_time){
Packit 762fc5
      error(CLOCK_SKEW,_("%s atime in future\n"),filename);
Packit 762fc5
    }
Packit 762fc5
    if(fs->st_mtime>cur_time){
Packit 762fc5
      error(CLOCK_SKEW,_("%s mtime in future\n"),filename);
Packit 762fc5
    }
Packit 762fc5
    if(fs->st_ctime>cur_time){
Packit 762fc5
      error(CLOCK_SKEW,_("%s ctime in future\n"),filename);
Packit 762fc5
    }
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
  /*
Packit 762fc5
    Malloc if we have something to store..
Packit 762fc5
  */
Packit 762fc5
  
Packit 762fc5
  line=(db_line*)malloc(sizeof(db_line));
Packit 762fc5
  
Packit 762fc5
  memset(line,0,sizeof(db_line));
Packit 762fc5
  
Packit 762fc5
  /*
Packit 762fc5
    We want filename
Packit 762fc5
  */
Packit 762fc5
Packit 762fc5
  line->attr=attr|DB_FILENAME;
Packit 762fc5
  
Packit 762fc5
  /*
Packit 762fc5
    Just copy some needed fields.
Packit 762fc5
  */
Packit 762fc5
  
Packit 762fc5
  line->fullpath=filename;
Packit 762fc5
  line->filename=&filename[conf->root_prefix_length];
Packit 762fc5
  line->perm_o=fs->st_mode;
Packit 762fc5
  line->size_o=fs->st_size;
Packit 762fc5
  line->linkname=NULL;
Packit 762fc5
Packit 762fc5
  /*
Packit 762fc5
    Handle symbolic link
Packit 762fc5
  */
Packit 762fc5
  
Packit 762fc5
  hsymlnk(line);
Packit 762fc5
  
Packit 762fc5
  /*
Packit 762fc5
    Set normal part
Packit 762fc5
  */
Packit 762fc5
  
Packit 762fc5
  fs2db_line(fs,line);
Packit 762fc5
  
Packit 762fc5
  /*
Packit 762fc5
    ACL stuff
Packit 762fc5
  */
Packit 762fc5
Packit 762fc5
#ifdef WITH_ACL
Packit 762fc5
  acl2line(line);
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_XATTR
Packit 762fc5
  xattrs2line(line);
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_SELINUX
Packit 762fc5
  selinux2line(line);
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_E2FSATTRS
Packit 762fc5
    e2fsattrs2line(line);
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
  if (attr&DB_HASHES && S_ISREG(fs->st_mode)) {
Packit 762fc5
    calc_md(fs,line);
Packit 762fc5
  } else {
Packit 762fc5
    /*
Packit 762fc5
      We cannot calculate hash for nonfile.
Packit 762fc5
      Mark it to attr.
Packit 762fc5
    */
Packit 762fc5
    no_hash(line);
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
  return line;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static void write_tree(seltree* node) {
Packit 762fc5
    list* r=NULL;
Packit 762fc5
    if (node->checked&DB_NEW) {
Packit 762fc5
        db_writeline(node->new_data,conf);
Packit 762fc5
        if (node->checked&NODE_FREE) {
Packit 762fc5
            free_db_line(node->new_data);
Packit 762fc5
            free(node->new_data);
Packit 762fc5
            node->new_data=NULL;
Packit 762fc5
        }
Packit 762fc5
    }
Packit 762fc5
    for (r=node->childs;r;r=r->next) {
Packit 762fc5
        write_tree((seltree*)r->data);
Packit 762fc5
    }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void populate_tree(seltree* tree)
Packit 762fc5
{
Packit 762fc5
  /* FIXME this function could really use threads */
Packit 762fc5
  int add=0;
Packit 762fc5
  db_line* old=NULL;
Packit 762fc5
  db_line* new=NULL;
Packit 762fc5
  int initdbwarningprinted=0;
Packit 762fc5
  DB_ATTR_TYPE attr=0;
Packit 762fc5
  seltree* node=NULL;
Packit 762fc5
  
Packit 762fc5
  /* With this we avoid unnecessary checking of removed files. */
Packit 762fc5
  if(conf->action&DO_INIT){
Packit 762fc5
    initdbwarningprinted=1;
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
    if(conf->action&DO_DIFF){
Packit 762fc5
      while((new=db_readline(DB_NEW)) != NULL){
Packit 762fc5
	/* FIXME add support config checking at this stage 
Packit 762fc5
	   config check = add only those files that match config rxs
Packit 762fc5
	   make this configurable
Packit 762fc5
	   Only configurability is not implemented.
Packit 762fc5
	*/
Packit 762fc5
	/* This is needed because check_rxtree assumes there is a parent
Packit 762fc5
	   for the node for old->filename */
Packit 762fc5
	if((node=get_seltree_node(tree,new->filename))==NULL){
Packit 762fc5
	  node=new_seltree_node(tree,new->filename,0,NULL);
Packit 762fc5
	}
Packit 762fc5
	if((add=check_rxtree(new->filename,tree,&attr, new->perm))>0){
Packit 762fc5
	  add_file_to_tree(tree,new,DB_NEW,attr);
Packit 762fc5
	} else {
Packit 762fc5
          free_db_line(new);
Packit 762fc5
          free(new);
Packit 762fc5
          new=NULL;
Packit 762fc5
	}
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
    
Packit 762fc5
    if((conf->action&DO_INIT)||(conf->action&DO_COMPARE)){
Packit 762fc5
      /* FIXME  */
Packit 762fc5
      new=NULL;
Packit 762fc5
      while((new=db_readline(DB_DISK)) != NULL) {
Packit 762fc5
	    add_file_to_tree(tree,new,DB_NEW,attr);
Packit 762fc5
      }
Packit 762fc5
    }
Packit 762fc5
    if((conf->action&DO_COMPARE)||(conf->action&DO_DIFF)){
Packit 762fc5
            while((old=db_readline(DB_OLD)) != NULL) {
Packit 762fc5
                /* This is needed because check_rxtree assumes there is a parent
Packit 762fc5
                   for the node for old->filename */
Packit 762fc5
                if((node=get_seltree_node(tree,old->filename))==NULL){
Packit 762fc5
                    node=new_seltree_node(tree,old->filename,0,NULL);
Packit 762fc5
                }
Packit 762fc5
                add=check_rxtree(old->filename,tree,&attr, old->perm);
Packit 762fc5
                if(add > 0) {
Packit 762fc5
                    add_file_to_tree(tree,old,DB_OLD,attr);
Packit 762fc5
                } else if (conf->limit!=NULL && add < 0) {
Packit 762fc5
                    add_file_to_tree(tree,old,DB_OLD|DB_NEW,attr);
Packit 762fc5
                }else{
Packit 762fc5
                    free_db_line(old);
Packit 762fc5
                    free(old);
Packit 762fc5
                    old=NULL;
Packit 762fc5
                    if(!initdbwarningprinted){
Packit 762fc5
                        error(3,_("WARNING: Old db contains a entry that shouldn\'t be there, run --init or --update\n"));
Packit 762fc5
                        initdbwarningprinted=1;
Packit 762fc5
                    }
Packit 762fc5
                }
Packit 762fc5
            }
Packit 762fc5
    }
Packit 762fc5
    if(conf->action&DO_INIT) {
Packit 762fc5
        write_tree(tree);
Packit 762fc5
    }
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void hsymlnk(db_line* line) {
Packit 762fc5
  
Packit 762fc5
  if((S_ISLNK(line->perm_o))){
Packit 762fc5
    int len=0;
Packit 762fc5
#ifdef WITH_ACL   
Packit 762fc5
    if(conf->no_acl_on_symlinks!=1) {
Packit 762fc5
      line->attr&=(~DB_ACL);
Packit 762fc5
    }
Packit 762fc5
#endif   
Packit 762fc5
    
Packit 762fc5
    if(conf->warn_dead_symlinks==1) {
Packit 762fc5
      struct AIDE_STAT_TYPE fs;
Packit 762fc5
      int sres;
Packit 762fc5
      sres=AIDE_STAT_FUNC(line->fullpath,&fs);
Packit 762fc5
      if (sres!=0 && sres!=EACCES) {
Packit 762fc5
	error(4,"Dead symlink detected at %s\n",line->fullpath);
Packit 762fc5
      }
Packit 762fc5
      if(!(line->attr&DB_RDEV))
Packit 762fc5
	fs.st_rdev=0;
Packit 762fc5
    }
Packit 762fc5
    /*
Packit 762fc5
      Is this valid?? 
Packit 762fc5
      No, We should do this elsewhere.
Packit 762fc5
    */
Packit 762fc5
    line->linkname=(char*)malloc(_POSIX_PATH_MAX+1);
Packit 762fc5
    if(line->linkname==NULL){
Packit 762fc5
      error(0,_("malloc failed in hsymlnk()\n"));
Packit 762fc5
      abort();
Packit 762fc5
    }
Packit 762fc5
    
Packit 762fc5
    /*
Packit 762fc5
      Remember to nullify the buffer, because man page says
Packit 762fc5
      
Packit 762fc5
      readlink  places the contents of the symbolic link path in
Packit 762fc5
      the buffer buf, which has size bufsiz.  readlink does  not
Packit 762fc5
      append  a NUL character to buf.  It will truncate the con-
Packit 762fc5
      tents (to a length of  bufsiz  characters),  in  case  the
Packit 762fc5
      buffer is too small to hold all of the contents.
Packit 762fc5
      
Packit 762fc5
    */
Packit 762fc5
    memset(line->linkname,0,_POSIX_PATH_MAX+1);
Packit 762fc5
    
Packit 762fc5
    len=readlink(line->fullpath,line->linkname,_POSIX_PATH_MAX+1);
Packit 762fc5
    
Packit 762fc5
    /*
Packit 762fc5
     * We use realloc :)
Packit 762fc5
     */
Packit 762fc5
    line->linkname=realloc(line->linkname,len+1);
Packit 762fc5
  } else {
Packit 762fc5
      line->attr&=(~DB_LINKNAME);
Packit 762fc5
  }
Packit 762fc5
  
Packit 762fc5
}
Packit 762fc5
// vi: ts=8 sw=2