|
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 |
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 |
if(file==NULL){
|
|
Packit |
762fc5 |
error(0, "add_file_to_tree was called with NULL db_line\n");
|
|
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
|