Blame src/do_md.c

Packit Service 5e8d2a
/* aide, Advanced Intrusion Detection Environment
Packit Service 5e8d2a
 * vi: ts=8 sw=8
Packit Service 5e8d2a
 *
Packit Service 5e8d2a
 * Copyright (C) 1999-2002,2004-2006,2009-2011,2013 Rami Lehti, Pablo
Packit Service 5e8d2a
 * Virolainen, Mike Markley, Richard van den Berg, Hannes von Haugwitz
Packit Service 5e8d2a
 * $Header$
Packit Service 5e8d2a
 *
Packit Service 5e8d2a
 * This program is free software; you can redistribute it and/or
Packit Service 5e8d2a
 * modify it under the terms of the GNU General Public License as
Packit Service 5e8d2a
 * published by the Free Software Foundation; either version 2 of the
Packit Service 5e8d2a
 * License, or (at your option) any later version.
Packit Service 5e8d2a
 *
Packit Service 5e8d2a
 * This program is distributed in the hope that it will be useful, but
Packit Service 5e8d2a
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 5e8d2a
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 5e8d2a
 * General Public License for more details.
Packit Service 5e8d2a
 *
Packit Service 5e8d2a
 * You should have received a copy of the GNU General Public License
Packit Service 5e8d2a
 * along with this program; if not, write to the Free Software
Packit Service 5e8d2a
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit Service 5e8d2a
 */
Packit Service 5e8d2a
Packit Service 5e8d2a
#include "aide.h"
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifndef _POSIX_C_SOURCE
Packit Service 5e8d2a
#define _POSIX_C_SOURCE 200112L
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
#include <limits.h>
Packit Service 5e8d2a
#include <stdio.h>
Packit Service 5e8d2a
#include <stdlib.h>
Packit Service 5e8d2a
#include <string.h>
Packit Service 5e8d2a
#include <errno.h>
Packit Service 5e8d2a
#include <sys/types.h>
Packit Service 5e8d2a
#include <sys/stat.h>
Packit Service 5e8d2a
#include <fcntl.h>
Packit Service 5e8d2a
#include <unistd.h>
Packit Service 5e8d2a
#include <sys/mman.h>
Packit Service 5e8d2a
Packit Service 5e8d2a
#include "md.h"
Packit Service 5e8d2a
Packit Service 5e8d2a
#include "db_config.h"
Packit Service 5e8d2a
#include "do_md.h"
Packit Service 5e8d2a
#include "report.h"
Packit Service 5e8d2a
#include "list.h"
Packit Service 5e8d2a
/*for locale support*/
Packit Service 5e8d2a
#include "locale-aide.h"
Packit Service 5e8d2a
/*for locale support*/
Packit Service 5e8d2a
Packit Service 5e8d2a
Packit Service 5e8d2a
/* This define should be somewhere else */
Packit Service 5e8d2a
#define READ_BLOCK_SIZE 16777216
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_MHASH
Packit Service 5e8d2a
#include <mhash.h>
Packit Service 5e8d2a
#endif /* WITH_MHASH */
Packit Service 5e8d2a
Packit Service 5e8d2a
/* Redhat 5.0 needs this */
Packit Service 5e8d2a
#ifdef HAVE_MMAP
Packit Service 5e8d2a
#ifndef MAP_FAILED
Packit Service 5e8d2a
#define MAP_FAILED  (-1)
Packit Service 5e8d2a
#endif /* MAP_FAILED */
Packit Service 5e8d2a
#define MMAP_BLOCK_SIZE 16777216
Packit Service 5e8d2a
#endif /* HAVE_MMAP */
Packit Service 5e8d2a
Packit Service 5e8d2a
/*
Packit Service 5e8d2a
#include <gcrypt.h>
Packit Service 5e8d2a
*/
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
#include <sys/wait.h>
Packit Service 5e8d2a
#include <gelf.h>
Packit Service 5e8d2a
Packit Service 5e8d2a
/*
Packit Service 5e8d2a
 *  Is file descriptor prelinked binary/library?
Packit Service 5e8d2a
 *  Return: 1(yes) / 0(no)
Packit Service 5e8d2a
 *  
Packit Service 5e8d2a
 */
Packit Service 5e8d2a
int is_prelinked(int fd) {
Packit Service 5e8d2a
        Elf *elf = NULL;
Packit Service 5e8d2a
        Elf_Scn *scn = NULL;
Packit Service 5e8d2a
        Elf_Data *data = NULL;
Packit Service 5e8d2a
        GElf_Ehdr ehdr;
Packit Service 5e8d2a
        GElf_Shdr shdr;
Packit Service 5e8d2a
        GElf_Dyn dyn;
Packit Service 5e8d2a
        int bingo;
Packit Service 5e8d2a
Packit Service 5e8d2a
        (void) elf_version(EV_CURRENT);
Packit Service 5e8d2a
Packit Service 5e8d2a
        if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL
Packit Service 5e8d2a
            || elf_kind(elf) != ELF_K_ELF
Packit Service 5e8d2a
            || gelf_getehdr(elf, &ehdr) == NULL
Packit Service 5e8d2a
            || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
Packit Service 5e8d2a
                return 0;
Packit Service 5e8d2a
Packit Service 5e8d2a
        bingo = 0;
Packit Service 5e8d2a
        while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
Packit Service 5e8d2a
                (void) gelf_getshdr(scn, &shdr);
Packit Service 5e8d2a
Packit Service 5e8d2a
                if (shdr.sh_type != SHT_DYNAMIC)
Packit Service 5e8d2a
                        continue;
Packit Service 5e8d2a
Packit Service 5e8d2a
                while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
Packit Service ea4ed9
                        int maxndx;
Packit Service 5e8d2a
                        int ndx;
Packit Service ea4ed9
			
Packit Service ea4ed9
                        if (shdr.sh_entsize != 0)
Packit Service ea4ed9
                                maxndx = data->d_size / shdr.sh_entsize;
Packit Service ea4ed9
                        else
Packit Service ea4ed9
                                continue;
Packit Service 5e8d2a
Packit Service 5e8d2a
                        for (ndx = 0; ndx < maxndx; ++ndx) {
Packit Service 5e8d2a
                                (void) gelf_getdyn (data, ndx, &dyn);
Packit Service 5e8d2a
                                if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
Packit Service 5e8d2a
                                        continue;
Packit Service 5e8d2a
                                bingo = 1;
Packit Service 5e8d2a
                                break;
Packit Service 5e8d2a
                        }
Packit Service 5e8d2a
                }
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
Packit Service 5e8d2a
        return bingo;
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
/*
Packit Service 5e8d2a
 * Open path via prelink -y, set fd
Packit Service 5e8d2a
 * Return: 0 failure / > 0 success
Packit Service 5e8d2a
 *
Packit Service 5e8d2a
 */
Packit Service 5e8d2a
pid_t open_prelinked(const char * path, int * fd) {
Packit Service 5e8d2a
        const char *cmd = PRELINK_PATH;
Packit Service 5e8d2a
        pid_t pid = 0;
Packit Service 5e8d2a
        int pipes[2];
Packit Service 5e8d2a
Packit Service 5e8d2a
        pipes[0] = pipes[1] = -1;
Packit Service 5e8d2a
        if (pipe(pipes) < 0)
Packit Service 5e8d2a
           return 0;
Packit Service 5e8d2a
        pid = fork();
Packit Service 5e8d2a
        switch (pid) {
Packit Service 5e8d2a
           case 0:
Packit Service 5e8d2a
              /* child */
Packit Service 5e8d2a
              close(pipes[0]);
Packit Service 5e8d2a
              dup2(pipes[1], STDOUT_FILENO);
Packit Service 5e8d2a
              close(pipes[1]);
Packit Service 5e8d2a
              unsetenv("MALLOC_CHECK_");
Packit Service 5e8d2a
              execl(cmd, cmd, "--verify", path, (char *) NULL);
Packit Service 5e8d2a
              exit(1);
Packit Service 5e8d2a
              break;
Packit Service 5e8d2a
           case -1:
Packit Service 5e8d2a
              close(pipes[0]);
Packit Service 5e8d2a
              close(pipes[1]);
Packit Service 5e8d2a
              return 0;
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
        /* parent */
Packit Service 5e8d2a
        close(pipes[1]);
Packit Service 5e8d2a
        *fd = pipes[0];
Packit Service 5e8d2a
        return pid;
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
void free_hashes(db_line* dl){
Packit Service 5e8d2a
Packit Service 5e8d2a
#define free_hash(a) dl->a=NULL
Packit Service 5e8d2a
Packit Service 5e8d2a
  free_hash(md5);
Packit Service 5e8d2a
  free_hash(sha1);
Packit Service 5e8d2a
  free_hash(rmd160);
Packit Service 5e8d2a
  free_hash(tiger);
Packit Service 5e8d2a
#ifdef WITH_MHASH
Packit Service 5e8d2a
  free_hash(crc32);
Packit Service 5e8d2a
  free_hash(haval);
Packit Service 5e8d2a
  free_hash(gost);
Packit Service 5e8d2a
  free_hash(crc32b);  
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
  free_hash(sha256);
Packit Service 5e8d2a
  free_hash(sha512);
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
int stat_cmp(struct AIDE_STAT_TYPE* f1,struct AIDE_STAT_TYPE* f2) {
Packit Service 5e8d2a
  if (f1==NULL || f2==NULL) {
Packit Service 5e8d2a
    return RETFAIL;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
#define stat_cmp_helper(n,n2) ((f1->n!=f2->n)*n2)
Packit Service 5e8d2a
Packit Service 5e8d2a
  return (stat_cmp_helper(st_ino,DB_INODE)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_mode,DB_PERM)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_nlink,DB_LNKCOUNT)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_size,DB_SIZE)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_mtime,DB_MTIME)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_ctime,DB_CTIME)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_blocks,DB_BCOUNT)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_blksize,DB_BSIZE)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_rdev,DB_RDEV)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_gid,DB_GID)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_uid,DB_UID)|
Packit Service 5e8d2a
	  stat_cmp_helper(st_dev,DB_DEV));
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
Packit Service 5e8d2a
void no_hash(db_line* line);
Packit Service 5e8d2a
Packit Service 5e8d2a
void calc_md(struct AIDE_STAT_TYPE* old_fs,db_line* line) {
Packit Service 5e8d2a
  /*
Packit Service 5e8d2a
    We stat after opening just to make sure that the file
Packit Service 5e8d2a
    from we are about to calculate the hash is the correct one,
Packit Service 5e8d2a
    and we don't read from a pipe :)
Packit Service 5e8d2a
   */
Packit Service 5e8d2a
  struct AIDE_STAT_TYPE fs;
Packit Service 5e8d2a
  int stat_diff,filedes;
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
  pid_t pid;
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
  error(255,"calc_md called\n");
Packit Service 5e8d2a
#ifdef _PARAMETER_CHECK_
Packit Service 5e8d2a
  if (line==NULL) {
Packit Service 5e8d2a
    abort();
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
#endif  
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef HAVE_O_NOATIME
Packit Service 5e8d2a
  filedes=open(line->fullpath,O_RDONLY|O_NOATIME);
Packit Service 5e8d2a
  if(filedes<0)
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
    filedes=open(line->fullpath,O_RDONLY);
Packit Service 5e8d2a
Packit Service 5e8d2a
  if (filedes==-1) {
Packit Service 5e8d2a
    char* er=strerror(errno);
Packit Service 5e8d2a
    if (er!=NULL) {
Packit Service 5e8d2a
      error(3,"do_md(): open() for %s failed: %s\n",
Packit Service 5e8d2a
	    line->fullpath,er);
Packit Service 5e8d2a
    } else {
Packit Service 5e8d2a
      error(3,"do_md(): open() for %s failed: %i\n",
Packit Service 5e8d2a
	    line->fullpath,errno);
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
    /*
Packit Service 5e8d2a
      Nop. Cannot cal hashes. Mark it.
Packit Service 5e8d2a
     */
Packit Service 5e8d2a
    no_hash(line);
Packit Service 5e8d2a
    return;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  
Packit Service c89282
  AIDE_FSTAT_FUNC(filedes,&fs);
Packit Service 5e8d2a
  if(!(line->attr&DB_RDEV))
Packit Service 5e8d2a
	  fs.st_rdev=0;
Packit Service 5e8d2a
  
Packit Service 5e8d2a
#ifdef HAVE_POSIX_FADVISE
Packit Service 5e8d2a
  if (posix_fadvise(filedes,0,fs.st_size,POSIX_FADV_NOREUSE)!=0) {
Packit Service 5e8d2a
	error(255,"posix_fadvise error %s\n",strerror(errno));
Packit Service 5e8d2a
  } else {
Packit Service 5e8d2a
	error(255,"posix_fadvise(%i,0,%li,POSIX_FADV_NOREUSE) ok\n",filedes,fs.st_size);
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
  if ((stat_diff=stat_cmp(&fs,old_fs))==RETOK) {
Packit Service 5e8d2a
    /*
Packit Service 5e8d2a
      Now we have a 'valid' filehandle to read from a file.
Packit Service 5e8d2a
     */
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
    /*
Packit Service 5e8d2a
     * Let's take care of prelinked libraries/binaries 	
Packit Service 5e8d2a
     */
Packit Service 5e8d2a
    pid=0;
Packit Service 5e8d2a
    if ( is_prelinked(filedes) ) {
Packit Service 5e8d2a
      close(filedes);
Packit Service 5e8d2a
      pid = open_prelinked(line->fullpath, &filedes);
Packit Service 5e8d2a
      if (pid == 0) {
Packit Service 5e8d2a
        error(0, "Error on starting prelink undo\n");
Packit Service 5e8d2a
	return;
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
    off_t r_size=0;
Packit Service 5e8d2a
    off_t size=0;
Packit Service 5e8d2a
    char* buf;
Packit Service 5e8d2a
Packit Service 5e8d2a
    struct md_container mdc;
Packit Service 5e8d2a
    
Packit Service 5e8d2a
    mdc.todo_attr=line->attr;
Packit Service 5e8d2a
    
Packit Service 5e8d2a
    if (init_md(&mdc)==RETOK) {
Packit Service 5e8d2a
#ifdef HAVE_MMAP
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
      if (pid == 0) {
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
        off_t curpos=0;
Packit Service 5e8d2a
Packit Service 5e8d2a
        r_size=fs.st_size;
Packit Service 5e8d2a
        /* in mmap branch r_size is used as size remaining */
Packit Service 5e8d2a
        while(r_size>0){
Packit Service 5e8d2a
         if(r_size
Packit Service 5e8d2a
#ifdef __hpux
Packit Service 5e8d2a
           buf = mmap(0,r_size,PROT_READ,MAP_PRIVATE,filedes,curpos);
Packit Service 5e8d2a
#else
Packit Service 5e8d2a
           buf = mmap(0,r_size,PROT_READ,MAP_SHARED,filedes,curpos);
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
           curpos+=r_size;
Packit Service 5e8d2a
           size=r_size;
Packit Service 5e8d2a
           r_size=0;
Packit Service 5e8d2a
         }else {
Packit Service 5e8d2a
#ifdef __hpux
Packit Service 5e8d2a
	   buf = mmap(0,MMAP_BLOCK_SIZE,PROT_READ,MAP_PRIVATE,filedes,curpos);
Packit Service 5e8d2a
#else
Packit Service 5e8d2a
	   buf = mmap(0,MMAP_BLOCK_SIZE,PROT_READ,MAP_SHARED,filedes,curpos);
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
	   curpos+=MMAP_BLOCK_SIZE;
Packit Service 5e8d2a
	   size=MMAP_BLOCK_SIZE;
Packit Service 5e8d2a
	   r_size-=MMAP_BLOCK_SIZE;
Packit Service 5e8d2a
	 }
Packit Service 5e8d2a
	 if ( buf == MAP_FAILED ) {
Packit Service 5e8d2a
	   error(0,"error mmap'ing %s: %s\n", line->fullpath,strerror(errno));
Packit Service 5e8d2a
	   close(filedes);
Packit Service 5e8d2a
	   close_md(&mdc;;
Packit Service 5e8d2a
	   return;
Packit Service 5e8d2a
	 }
Packit Service 5e8d2a
	 conf->catch_mmap=1;
Packit Service 5e8d2a
	 if (update_md(&mdc,buf,size)!=RETOK) {
Packit Service 5e8d2a
	   error(0,"Message digest failed during update\n");
Packit Service 5e8d2a
	   close(filedes);
Packit Service 5e8d2a
	   close_md(&mdc;;
Packit Service 5e8d2a
	   munmap(buf,size);
Packit Service 5e8d2a
	   return;
Packit Service 5e8d2a
	 }
Packit Service 5e8d2a
	 munmap(buf,size);
Packit Service 5e8d2a
	 conf->catch_mmap=0;
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
	/* we have used MMAP, let's return */
Packit Service 5e8d2a
        close_md(&mdc;;
Packit Service 5e8d2a
        md2line(&mdc,line);
Packit Service 5e8d2a
        close(filedes);
Packit Service 5e8d2a
        return;
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
#endif /* not HAVE_MMAP */
Packit Service c89282
//      buf=malloc(READ_BLOCK_SIZE);
Packit Service 5e8d2a
#if READ_BLOCK_SIZE>SSIZE_MAX
Packit Service 5e8d2a
#error "READ_BLOCK_SIZE" is too large. Max value is SSIZE_MAX, and current is READ_BLOCK_SIZE
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
      while ((size=TEMP_FAILURE_RETRY(read(filedes,buf,READ_BLOCK_SIZE)))>0) {
Packit Service 5e8d2a
	if (update_md(&mdc,buf,size)!=RETOK) {
Packit Service 5e8d2a
	  error(0,"Message digest failed during update\n");
Packit Service 5e8d2a
	  close(filedes);
Packit Service 5e8d2a
	  close_md(&mdc;;
Packit Service 5e8d2a
	  return;
Packit Service 5e8d2a
	}
Packit Service 5e8d2a
	r_size+=size;
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_PRELINK
Packit Service 5e8d2a
      if (pid) {
Packit Service 5e8d2a
        int status;
Packit Service 5e8d2a
        (void) waitpid(pid, &status, 0);
Packit Service 5e8d2a
        if (!WIFEXITED(status) || WEXITSTATUS(status)) {
Packit Service 5e8d2a
          error(0, "Error on exit of prelink child process\n");
Packit Service 5e8d2a
	  close(filedes);
Packit Service 5e8d2a
	  close_md(&mdc;;
Packit Service 5e8d2a
          return;
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
      free(buf);
Packit Service 5e8d2a
      close_md(&mdc;;
Packit Service 5e8d2a
      md2line(&mdc,line);
Packit Service 5e8d2a
Packit Service 5e8d2a
    } else {
Packit Service 5e8d2a
      error(3,"Message digest initialization failed.\n");
Packit Service 5e8d2a
      no_hash(line);
Packit Service 5e8d2a
      close(filedes);
Packit Service 5e8d2a
      return;
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
  } else {
Packit Service 5e8d2a
    unsigned i;
Packit Service 5e8d2a
    /*
Packit Service 5e8d2a
      Something just wasn't correct, so no hash calculated.
Packit Service 5e8d2a
    */
Packit Service 5e8d2a
    
Packit Service 5e8d2a
    error(5,"Entry %s was changed so that hash cannot be calculated for it\n"
Packit Service 5e8d2a
	  ,line->fullpath);
Packit Service 5e8d2a
Packit Service 5e8d2a
    for(i=0;i
Packit Service 5e8d2a
      if (((1<
Packit Service 5e8d2a
	error(5,"Attribute %s has been changed\n",db_names[i]);
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
    
Packit Service 5e8d2a
    no_hash(line);
Packit Service 5e8d2a
    close(filedes);
Packit Service 5e8d2a
    return;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  close(filedes);
Packit Service 5e8d2a
  return;
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
void fs2db_line(struct AIDE_STAT_TYPE* fs,db_line* line) {
Packit Service 5e8d2a
  
Packit Service 5e8d2a
  line->inode=fs->st_ino;
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_UID&line->attr) {
Packit Service 5e8d2a
    line->uid=fs->st_uid;
Packit Service 5e8d2a
  }else {
Packit Service 5e8d2a
    line->uid=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_GID&line->attr){
Packit Service 5e8d2a
    line->gid=fs->st_gid;
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->gid=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
Packit Service 5e8d2a
  line->perm=fs->st_mode;
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_SIZE&line->attr||DB_SIZEG&line->attr){
Packit Service 5e8d2a
    line->size=fs->st_size;
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->size=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  
Packit Service 5e8d2a
  if(DB_LNKCOUNT&line->attr){
Packit Service 5e8d2a
    line->nlink=fs->st_nlink;
Packit Service 5e8d2a
  }else {
Packit Service 5e8d2a
    line->nlink=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_MTIME&line->attr){
Packit Service 5e8d2a
    line->mtime=fs->st_mtime;
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->mtime=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_CTIME&line->attr){
Packit Service 5e8d2a
    line->ctime=fs->st_ctime;
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->ctime=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  
Packit Service 5e8d2a
  if(DB_ATIME&line->attr){
Packit Service 5e8d2a
    line->atime=fs->st_atime;
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->atime=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
Packit Service 5e8d2a
  if(DB_BCOUNT&line->attr){
Packit Service 5e8d2a
    line->bcount=fs->st_blocks;
Packit Service 5e8d2a
  } else {
Packit Service 5e8d2a
    line->bcount=0;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_ACL
Packit Service 5e8d2a
void acl2line(db_line* line) {
Packit Service 5e8d2a
  acl_type *ret = NULL;
Packit Service 5e8d2a
  
Packit Service 5e8d2a
#ifdef WITH_POSIX_ACL
Packit Service 5e8d2a
  if(DB_ACL&line->attr) {
Packit Service 5e8d2a
    acl_t acl_a;
Packit Service 5e8d2a
    acl_t acl_d;
Packit Service 5e8d2a
    char *tmp = NULL;
Packit Service 5e8d2a
Packit Service 5e8d2a
    acl_a = acl_get_file(line->fullpath, ACL_TYPE_ACCESS);
Packit Service 5e8d2a
    acl_d = acl_get_file(line->fullpath, ACL_TYPE_DEFAULT);
Packit Service 5e8d2a
    if ((acl_a == NULL) && (errno == ENOTSUP)) {
Packit Service 5e8d2a
      line->attr&=(~DB_ACL);
Packit Service 5e8d2a
      return;
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
    if (acl_a == NULL)
Packit Service 5e8d2a
      error(0, "Tried to read access ACL on %s but failed with: %s\n",
Packit Service 5e8d2a
            line->fullpath, strerror(errno));
Packit Service 5e8d2a
    if ((acl_d == NULL) && (errno != EACCES)) /* ignore DEFAULT on files */
Packit Service 5e8d2a
    {
Packit Service 5e8d2a
      acl_free(acl_a);
Packit Service 5e8d2a
      error(0, "Tried to read default ACL on %s but failed with: %s\n",
Packit Service 5e8d2a
            line->fullpath, strerror(errno));
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    /* assume memory allocs work, like rest of AIDE code... */
Packit Service 5e8d2a
    ret = malloc(sizeof(acl_type));
Packit Service 5e8d2a
Packit Service 5e8d2a
    /* use tmp, so free() can be called instead of acl_free() */
Packit Service 5e8d2a
    tmp = acl_to_text(acl_a, NULL);
Packit Service 5e8d2a
    if (!tmp || !*tmp)
Packit Service 5e8d2a
      ret->acl_a = NULL;
Packit Service 5e8d2a
    else
Packit Service 5e8d2a
      ret->acl_a = strdup(tmp);
Packit Service 5e8d2a
    acl_free(tmp);
Packit Service 5e8d2a
Packit Service 5e8d2a
    if (!acl_d)
Packit Service 5e8d2a
      ret->acl_d = NULL;
Packit Service 5e8d2a
    else
Packit Service 5e8d2a
    {
Packit Service 5e8d2a
      tmp = acl_to_text(acl_d, NULL);
Packit Service 5e8d2a
      if (!tmp || !*tmp)
Packit Service 5e8d2a
        ret->acl_d = NULL;
Packit Service 5e8d2a
      else
Packit Service 5e8d2a
        ret->acl_d = strdup(tmp);
Packit Service 5e8d2a
      acl_free(tmp);
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    acl_free(acl_a);
Packit Service 5e8d2a
    acl_free(acl_d);
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
  line->acl = ret;
Packit Service 5e8d2a
#endif  
Packit Service 5e8d2a
#ifdef WITH_SUN_ACL
Packit Service 5e8d2a
  if(DB_ACL&line->attr) { /* There might be a bug here. */
Packit Service 5e8d2a
    int res;
Packit Service 5e8d2a
    line->acl=malloc(sizeof(acl_type));
Packit Service 5e8d2a
    line->acl->entries=acl(line->fullpath,GETACLCNT,0,NULL);
Packit Service 5e8d2a
    if (line->acl->entries==-1) {
Packit Service 5e8d2a
      char* er=strerror(errno);
Packit Service 5e8d2a
      line->acl->entries=0;
Packit Service 5e8d2a
      if (er==NULL) {
Packit Service 5e8d2a
	error(0,"ACL query failed for %s. strerror failed for %i\n",line->fullpath,errno);
Packit Service 5e8d2a
      } else {
Packit Service 5e8d2a
	error(0,"ACL query failed for %s:%s\n",line->fullpath,er);
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
    } else {
Packit Service 5e8d2a
      line->acl->acl=malloc(sizeof(aclent_t)*line->acl->entries);
Packit Service 5e8d2a
      res=acl(line->fullpath,GETACL,line->acl->entries,line->acl->acl);
Packit Service 5e8d2a
      if (res==-1) {
Packit Service 5e8d2a
	error(0,"ACL error %s\n",strerror(errno));
Packit Service 5e8d2a
      } else {
Packit Service 5e8d2a
	if (res!=line->acl->entries) {
Packit Service 5e8d2a
	  error(0,"Tried to read %i acl but got %i\n",line->acl->entries,res);
Packit Service 5e8d2a
	}
Packit Service 5e8d2a
      }
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
  }else{
Packit Service 5e8d2a
    line->acl=NULL;
Packit Service 5e8d2a
  }
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
}
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_XATTR
Packit Service 5e8d2a
static xattrs_type *xattr_new(void) {
Packit Service 5e8d2a
    xattrs_type *ret = NULL;
Packit Service 5e8d2a
Packit Service 5e8d2a
    ret = malloc(sizeof(xattrs_type));
Packit Service 5e8d2a
    ret->num = 0;
Packit Service 5e8d2a
    ret->sz  = 2;
Packit Service 5e8d2a
    ret->ents = malloc(sizeof(xattr_node) * ret->sz);
Packit Service 5e8d2a
Packit Service 5e8d2a
    return (ret);
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
static void *xzmemdup(const void *ptr, size_t len) {
Packit Service 5e8d2a
    /* always keeps a 0 at the end... */
Packit Service 5e8d2a
    void *ret = NULL;
Packit Service 5e8d2a
Packit Service 5e8d2a
    ret = malloc(len+1);
Packit Service 5e8d2a
    memcpy(ret, ptr, len);
Packit Service 5e8d2a
    ((char*)ret)[len] = 0;
Packit Service 5e8d2a
Packit Service 5e8d2a
    return (ret);
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
static void xattr_add(xattrs_type *xattrs, const char *key, const char
Packit Service 5e8d2a
        *val, size_t vsz) {
Packit Service 5e8d2a
    if (xattrs->num >= xattrs->sz) {
Packit Service 5e8d2a
        xattrs->sz <<= 1;
Packit Service 5e8d2a
        xattrs->ents = realloc(xattrs->ents, sizeof(xattr_node) * xattrs->sz);
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    xattrs->ents[xattrs->num].key = strdup(key);
Packit Service 5e8d2a
    xattrs->ents[xattrs->num].val = xzmemdup(val, vsz);
Packit Service 5e8d2a
    xattrs->ents[xattrs->num].vsz = vsz;
Packit Service 5e8d2a
Packit Service 5e8d2a
    xattrs->num += 1;
Packit Service 5e8d2a
}
Packit Service 5e8d2a
Packit Service 5e8d2a
void xattrs2line(db_line *line) {
Packit Service 5e8d2a
    /* get all generic user xattrs. */
Packit Service 5e8d2a
    xattrs_type *xattrs = NULL;
Packit Service 5e8d2a
    static ssize_t xsz = 1024;
Packit Service 5e8d2a
    static char *xatrs = NULL;
Packit Service 5e8d2a
    ssize_t xret = -1;
Packit Service 5e8d2a
Packit Service 5e8d2a
    if (!(DB_XATTRS&line->attr))
Packit Service 5e8d2a
        return;
Packit Service 5e8d2a
Packit Service 5e8d2a
    /* assume memory allocs work, like rest of AIDE code... */
Packit Service 5e8d2a
    if (!xatrs) xatrs = malloc(xsz);
Packit Service 5e8d2a
Packit Service 5e8d2a
    while (((xret = llistxattr(line->fullpath, xatrs, xsz)) == -1) && (errno == ERANGE)) {
Packit Service 5e8d2a
        xsz <<= 1;
Packit Service 5e8d2a
        xatrs = realloc(xatrs, xsz);
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    if ((xret == -1) && ((errno == ENOSYS) || (errno == ENOTSUP))) {
Packit Service 5e8d2a
        line->attr&=(~DB_XATTRS);
Packit Service 5e8d2a
    } else if (xret == -1) {
Packit Service 5e8d2a
        error(0, "listxattrs failed for %s:%s\n", line->fullpath, strerror(errno));
Packit Service 5e8d2a
    } else if (xret) {
Packit Service 5e8d2a
        const char *attr = xatrs;
Packit Service 5e8d2a
        static ssize_t asz = 1024;
Packit Service 5e8d2a
        static char *val = NULL;
Packit Service 5e8d2a
Packit Service 5e8d2a
        if (!val) val = malloc(asz);
Packit Service 5e8d2a
Packit Service 5e8d2a
        xattrs = xattr_new();
Packit Service 5e8d2a
Packit Service 5e8d2a
        while (xret > 0) {
Packit Service 5e8d2a
            size_t len = strlen(attr);
Packit Service 5e8d2a
            ssize_t aret = 0;
Packit Service 5e8d2a
Packit Service 5e8d2a
            if (strncmp(attr, "user.", strlen("user.")) &&
Packit Service 5e8d2a
                    strncmp(attr, "root.", strlen("root.")))
Packit Service 5e8d2a
                goto next_attr; /* only store normal xattrs, and SELinux */
Packit Service 5e8d2a
Packit Service 5e8d2a
            while (((aret = getxattr(line->fullpath, attr, val, asz)) ==
Packit Service 5e8d2a
                        -1) && (errno == ERANGE)) {
Packit Service 5e8d2a
                asz <<= 1;
Packit Service 5e8d2a
                val = realloc (val, asz);
Packit Service 5e8d2a
            }
Packit Service 5e8d2a
Packit Service 5e8d2a
            if (aret != -1)
Packit Service 5e8d2a
                xattr_add(xattrs, attr, val, aret);
Packit Service 5e8d2a
            else if (errno != ENOATTR)
Packit Service 5e8d2a
                error(0, "getxattr failed for %s:%s\n", line->fullpath, strerror(errno));
Packit Service 5e8d2a
Packit Service 5e8d2a
next_attr:
Packit Service 5e8d2a
            attr += len + 1;
Packit Service 5e8d2a
            xret -= len + 1;
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    line->xattrs = xattrs;
Packit Service 5e8d2a
}
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_SELINUX
Packit Service 5e8d2a
void selinux2line(db_line *line) {
Packit Service 5e8d2a
    char *cntx = NULL;
Packit Service 5e8d2a
Packit Service 5e8d2a
    if (!(DB_SELINUX&line->attr))
Packit Service 5e8d2a
        return;
Packit Service 5e8d2a
Packit Service 5e8d2a
    if (lgetfilecon_raw(line->fullpath, &cntx) == -1) {
Packit Service 5e8d2a
        line->attr&=(~DB_SELINUX);
Packit Service 5e8d2a
        if ((errno != ENOATTR) && (errno != EOPNOTSUPP))
Packit Service 5e8d2a
            error(0, "lgetfilecon_raw failed for %s:%s\n", line->fullpath, strerror(errno));
Packit Service 5e8d2a
        return;
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
Packit Service 5e8d2a
    line->cntx = strdup(cntx);
Packit Service 5e8d2a
Packit Service 5e8d2a
    freecon(cntx);
Packit Service 5e8d2a
}
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
#ifdef WITH_E2FSATTRS
Packit Service 5e8d2a
void e2fsattrs2line(db_line* line) {
Packit Service 5e8d2a
    unsigned long flags;
Packit Service 5e8d2a
    if (DB_E2FSATTRS&line->attr) {
Packit Service 5e8d2a
        if (fgetflags(line->fullpath, &flags) == 0) {
Packit Service 5e8d2a
            line->e2fsattrs=flags;
Packit Service 5e8d2a
        } else {
Packit Service 5e8d2a
            line->attr&=(~DB_E2FSATTRS);
Packit Service 5e8d2a
            line->e2fsattrs=0;
Packit Service 5e8d2a
        }
Packit Service 5e8d2a
    } else {
Packit Service 5e8d2a
        line->e2fsattrs=0;
Packit Service 5e8d2a
    }
Packit Service 5e8d2a
}
Packit Service 5e8d2a
#endif
Packit Service 5e8d2a
Packit Service 5e8d2a
void no_hash(db_line* line) {
Packit Service 5e8d2a
  line->attr&=~DB_HASHES;
Packit Service 5e8d2a
}
Packit Service 5e8d2a