Blame src/do_md.c

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