Blame src/db_disk.c

Packit 762fc5
/* aide, Advanced Intrusion Detection Environment
Packit 762fc5
 * vi: ts=2 sw=2
Packit 762fc5
 *
Packit 762fc5
 * Copyright (C) 1999-2006,2010,2011,2016 Rami Lehti, Pablo Virolainen,
Packit 762fc5
 * Richard van den Berg, Mike Markley, 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
#ifndef _POSIX_C_SOURCE
Packit 762fc5
# define _POSIX_C_SOURCE 199506L
Packit 762fc5
#endif
Packit 762fc5
#include <unistd.h>
Packit 762fc5
#include <stdio.h>
Packit 762fc5
#include <string.h>
Packit 762fc5
#include <sys/stat.h>
Packit 762fc5
#include <stdlib.h>
Packit 762fc5
#include <time.h>
Packit 762fc5
#include <dirent.h>
Packit 762fc5
#include <limits.h>
Packit 762fc5
#include <errno.h>
Packit 762fc5
Packit 762fc5
#include "seltree.h"
Packit 762fc5
#include "gen_list.h"
Packit 762fc5
#include "types.h"
Packit 762fc5
#include "base64.h"
Packit 762fc5
#include "db_disk.h"
Packit 762fc5
#include "conf_yacc.h"
Packit 762fc5
#include "util.h"
Packit 762fc5
#include "commandconf.h"
Packit 762fc5
/*for locale support*/
Packit 762fc5
#include "locale-aide.h"
Packit 762fc5
/*for locale support*/
Packit 762fc5
Packit 762fc5
#ifdef WITH_MHASH
Packit 762fc5
#include <mhash.h>
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
#ifdef WITH_ZLIB
Packit 762fc5
#include <zlib.h>
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
static DIR *dirh = NULL;
Packit 762fc5
static struct AIDE_DIRENT_TYPE *entp = NULL;
Packit 762fc5
static struct AIDE_DIRENT_TYPE **resp = NULL;
Packit 762fc5
Packit 762fc5
static struct seltree *r = NULL;
Packit 762fc5
Packit 762fc5
Packit 762fc5
#if defined HAVE_READDIR && !defined HAVE_READDIR_R
Packit 762fc5
static long td = -1;
Packit 762fc5
#endif
Packit 762fc5
static int rdres = 0;
Packit 762fc5
Packit 762fc5
static int root_handled = 0;
Packit 762fc5
Packit 762fc5
static DIR *open_dir(char* path) {
Packit 762fc5
   if (dirh != NULL) {
Packit 762fc5
       if (closedir(dirh) != 0) {
Packit 762fc5
           /* Closedir did not success? */
Packit 762fc5
       }
Packit 762fc5
   }
Packit 762fc5
   return opendir(path);
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static void next_in_dir (void)
Packit 762fc5
{
Packit 762fc5
#ifdef HAVE_READDIR_R
Packit 762fc5
	if (dirh != NULL)
Packit 762fc5
		rdres = AIDE_READDIR_R_FUNC (dirh, entp, resp);
Packit 762fc5
#else
Packit 762fc5
#ifdef HAVE_READDIR
Packit 762fc5
	if (dirh != NULL) {
Packit 762fc5
		entp = AIDE_READDIR_FUNC (dirh);
Packit 762fc5
		if(entp!=NULL)
Packit 762fc5
			td = telldir(dirh);
Packit 762fc5
		else
Packit 762fc5
			td=-1;
Packit 762fc5
	}
Packit 762fc5
#endif
Packit 762fc5
#endif
Packit 762fc5
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int in_this (void)
Packit 762fc5
{
Packit 762fc5
#ifdef HAVE_READDIR_R
Packit 762fc5
	return (dirh != NULL && rdres == 0 && (*resp) != NULL);
Packit 762fc5
#else
Packit 762fc5
#ifdef HAVE_READDIR
Packit 762fc5
	return (dirh != NULL && entp != NULL && td >= 0);
Packit 762fc5
#endif
Packit 762fc5
#endif
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static char *name_construct (const char *s)
Packit 762fc5
{
Packit 762fc5
	char *ret;
Packit 762fc5
	int len2 = strlen (r->path);
Packit 762fc5
	int len = len2 + strlen (s) + 2 + conf->root_prefix_length;
Packit 762fc5
Packit 762fc5
	if (r->path[len2 - 1] != '/') {
Packit 762fc5
		len++;
Packit 762fc5
	}
Packit 762fc5
Packit 762fc5
	ret = (char *) malloc (len);
Packit 762fc5
	ret[0] = (char) 0;
Packit 762fc5
	strncpy(ret, conf->root_prefix, conf->root_prefix_length+1);
Packit 762fc5
	strncat (ret, r->path, len2);
Packit 762fc5
	if (r->path[len2 - 1] != '/') {
Packit 762fc5
		strncat (ret, "/", 1);
Packit 762fc5
	}
Packit 762fc5
	strcat (ret, s);
Packit 762fc5
	return ret;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
void add_child (db_line * fil)
Packit 762fc5
{
Packit 762fc5
	int i;
Packit 762fc5
	struct seltree *new_r;
Packit 762fc5
Packit 762fc5
	error (255, "Adding child %s\n", fil->filename);
Packit 762fc5
Packit 762fc5
	new_r = get_seltree_node (r, fil->filename);
Packit 762fc5
	if (new_r != NULL) {
Packit 762fc5
		if (S_ISDIR (fil->perm_o)) {
Packit 762fc5
			;
Packit 762fc5
		} else {
Packit 762fc5
			new_r->checked |= NODE_CHECKED;
Packit 762fc5
			new_r->checked |= NODE_TRAVERSE;
Packit 762fc5
		}
Packit 762fc5
		return;
Packit 762fc5
	}
Packit 762fc5
Packit 762fc5
	new_r = malloc (sizeof (seltree));
Packit 762fc5
Packit 762fc5
	new_r->attr = 0;
Packit 762fc5
	i = strlen (fil->filename);
Packit 762fc5
Packit 762fc5
	new_r->path = malloc (i + 1);
Packit 762fc5
	strncpy(new_r->path, fil->filename, i+1);
Packit 762fc5
	new_r->childs = NULL;
Packit 762fc5
	new_r->sel_rx_lst = NULL;
Packit 762fc5
	new_r->neg_rx_lst = NULL;
Packit 762fc5
	new_r->equ_rx_lst = NULL;
Packit 762fc5
	new_r->parent = r;
Packit 762fc5
	new_r->checked = 0;
Packit 762fc5
	new_r->new_data = NULL;
Packit 762fc5
	new_r->old_data = NULL;
Packit 762fc5
	if (S_ISDIR (fil->perm_o)) {
Packit 762fc5
		;
Packit 762fc5
	} else {
Packit 762fc5
		new_r->checked |= NODE_CHECKED;
Packit 762fc5
		new_r->checked |= NODE_TRAVERSE;
Packit 762fc5
	}
Packit 762fc5
	r->childs = list_sorted_insert (r->childs, new_r, compare_node_by_path);
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
static int get_file_status(char *filename, struct AIDE_STAT_TYPE *fs) {
Packit 762fc5
    int sres = 0;
Packit 762fc5
    sres = AIDE_LSTAT_FUNC(filename,fs);
Packit 762fc5
    if(sres == -1){
Packit 762fc5
        char* er = strerror(errno);
Packit 762fc5
        if (er == NULL) {
Packit 762fc5
            error(0,"get_file_status: lstat() failed for %s. strerror() failed for %i\n", filename, errno);
Packit 762fc5
        } else {
Packit 762fc5
            error(0,"get_file_status: lstat() failed for %s: %s\n", filename, er);
Packit 762fc5
        }
Packit 762fc5
    }
Packit 762fc5
    return sres;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/*
Packit 762fc5
  It might be a good idea to make this non recursive.
Packit 762fc5
  Now implemented with goto-statement. Yeah, it's ugly and easy.
Packit 762fc5
*/
Packit 762fc5
Packit 762fc5
db_line *db_readline_disk ()
Packit 762fc5
{
Packit 762fc5
	db_line *fil = NULL;
Packit 762fc5
	DB_ATTR_TYPE attr;
Packit 762fc5
	char *fullname;
Packit 762fc5
	int add = 0;
Packit 762fc5
	struct AIDE_STAT_TYPE fs;
Packit 762fc5
Packit 762fc5
	/* root needs special handling */
Packit 762fc5
	if (!root_handled) {
Packit 762fc5
		root_handled = 1;
Packit 762fc5
		fullname=malloc((conf->root_prefix_length+2)*sizeof(char));
Packit 762fc5
		strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1);
Packit 762fc5
		strncat (fullname, "/", 1);
Packit 762fc5
		if (!get_file_status(&fullname[conf->root_prefix_length], &fs)) {
Packit 762fc5
		add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode);
Packit 762fc5
		error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add,
Packit 762fc5
					 conf->tree, attr);
Packit 762fc5
Packit 762fc5
		if (add > 0) {
Packit 762fc5
			fil = get_file_attrs (fullname, attr, &fs);
Packit 762fc5
Packit 762fc5
			error (240, "%s attr=%llu\n", &fullname[conf->root_prefix_length], attr);
Packit 762fc5
Packit 762fc5
			if (fil != NULL) {
Packit 762fc5
				error (240, "%s attr=%llu\n", fil->filename, fil->attr);
Packit 762fc5
				return fil;
Packit 762fc5
			}
Packit 762fc5
        }
Packit 762fc5
		}
Packit 762fc5
		free (fullname);
Packit 762fc5
	}
Packit 762fc5
recursion:
Packit 762fc5
	next_in_dir ();
Packit 762fc5
Packit 762fc5
	if (in_this ()) {
Packit 762fc5
Packit 762fc5
		/*
Packit 762fc5
		   Let's check if we have '.' or '..' entry.
Packit 762fc5
		   If have, just skipit.
Packit 762fc5
		   If don't do the 'normal' thing.
Packit 762fc5
		 */
Packit 762fc5
		if (strcmp (entp->d_name, ".") == 0 || strcmp (entp->d_name, "..") == 0) {
Packit 762fc5
			goto recursion;						// return db_readline_disk(db);
Packit 762fc5
		}
Packit 762fc5
Packit 762fc5
		/*
Packit 762fc5
		   Now we know that we actually can do something.
Packit 762fc5
		 */
Packit 762fc5
Packit 762fc5
		fullname = name_construct (entp->d_name);
Packit 762fc5
Packit 762fc5
		/*
Packit 762fc5
		   Now we have a filename, which we must remember to free if it is
Packit 762fc5
		   not used. 
Packit 762fc5
Packit 762fc5
		   Next thing is to see if we want to do something with it.
Packit 762fc5
		   If not call, db_readline_disk again...
Packit 762fc5
		 */
Packit 762fc5
Packit 762fc5
		if (get_file_status(&fullname[conf->root_prefix_length], &fs)) {
Packit 762fc5
		    free (fullname);
Packit 762fc5
		    goto recursion;
Packit 762fc5
		}
Packit 762fc5
		add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode);
Packit 762fc5
		error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add,
Packit 762fc5
					 conf->tree, attr);
Packit 762fc5
Packit 762fc5
		if (add > 0) {
Packit 762fc5
			fil = get_file_attrs (fullname, attr, &fs);
Packit 762fc5
Packit 762fc5
			error (240, "%s attr=%llu\n", &fullname[conf->root_prefix_length], attr);
Packit 762fc5
Packit 762fc5
			if (fil != NULL) {
Packit 762fc5
				error (240, "%s attr=%llu\n", fil->filename, fil->attr);
Packit 762fc5
			} else {
Packit 762fc5
				/*
Packit 762fc5
				   Something went wrong during read process -> 
Packit 762fc5
				   Let's try next one.
Packit 762fc5
				 */
Packit 762fc5
				free (fullname);
Packit 762fc5
				goto recursion;					// return db_readline_disk(db);
Packit 762fc5
			}
Packit 762fc5
Packit 762fc5
			if (add == 1) {
Packit 762fc5
				/*
Packit 762fc5
				   add_children -> if dir, then add to children list.
Packit 762fc5
				 */
Packit 762fc5
				/* If ee are adding a file that is not a dir */
Packit 762fc5
				/* add_child can make the determination and mark the tree
Packit 762fc5
				   accordingly
Packit 762fc5
				 */
Packit 762fc5
				add_child (fil);
Packit 762fc5
			} else if (add == 2) {
Packit 762fc5
				/*
Packit 762fc5
				   Don't add to children list.
Packit 762fc5
				 */
Packit 762fc5
Packit 762fc5
				/*
Packit 762fc5
				   Should we do something?
Packit 762fc5
				 */
Packit 762fc5
			}
Packit 762fc5
		} else {
Packit 762fc5
			/*
Packit 762fc5
			   Make us traverse the tree:)
Packit 762fc5
			 */
Packit 762fc5
Packit 762fc5
			/*
Packit 762fc5
			   We have no use for fullname.
Packit 762fc5
			 */
Packit 762fc5
Packit 762fc5
			free (fullname);
Packit 762fc5
			goto recursion;
Packit 762fc5
		}
Packit 762fc5
		/*
Packit 762fc5
		   Make sure that next time we enter
Packit 762fc5
		   we have something.
Packit 762fc5
		 */
Packit 762fc5
	} else {
Packit 762fc5
Packit 762fc5
		if (r == NULL) {
Packit 762fc5
			return NULL;
Packit 762fc5
		}
Packit 762fc5
Packit 762fc5
		error (255, "r->childs %p, r->parent %p, r->checked %i\n", r->childs,
Packit 762fc5
					 r->parent, r->checked);
Packit 762fc5
Packit 762fc5
		if ((0 == (r->checked & NODE_CHECKED)) && r->childs != NULL) {
Packit 762fc5
			seltree *rr;
Packit 762fc5
			list *l;
Packit 762fc5
			l = r->childs->header->head;
Packit 762fc5
Packit 762fc5
			while (l != NULL
Packit 762fc5
						 && (((seltree *) (l->data))->checked & NODE_TRAVERSE) != 0) {
Packit 762fc5
				l = l->next;
Packit 762fc5
			}
Packit 762fc5
			if (l != NULL) {
Packit 762fc5
				if (l == l->header->tail) {
Packit 762fc5
					r->checked |= NODE_CHECKED;
Packit 762fc5
				}
Packit 762fc5
Packit 762fc5
				rr = (seltree *) l->data;
Packit 762fc5
Packit 762fc5
				error (255, "rr->checked %i\n", rr->checked);
Packit 762fc5
				rr->checked |= NODE_TRAVERSE;
Packit 762fc5
Packit 762fc5
				r = rr;
Packit 762fc5
Packit 762fc5
				error (255, "r->childs %p, r->parent %p,r->checked %i\n",
Packit 762fc5
							 r->childs, r->parent, r->checked);
Packit 762fc5
				fullname=malloc((conf->root_prefix_length+strlen(r->path)+1)*sizeof(char));
Packit 762fc5
				strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1);
Packit 762fc5
				strncat(fullname, r->path, strlen(r->path));
Packit 762fc5
				dirh=open_dir(fullname);
Packit 762fc5
				if (! dirh) {
Packit 762fc5
Packit 762fc5
					/* open_dir failed so we need to know why and print 
Packit 762fc5
					   an errormessage if needed.
Packit 762fc5
					   errno should still be the one from opendir() since it's global
Packit 762fc5
					 */
Packit 762fc5
					if (errno == ENOENT && r->old_data != NULL &&
Packit 762fc5
							r->sel_rx_lst == NULL && r->neg_rx_lst == NULL &&
Packit 762fc5
							r->equ_rx_lst == NULL) {
Packit 762fc5
						/* The path did not exist and there is old data for this node
Packit 762fc5
						   and there are no regexps for this node
Packit 762fc5
						   There is no new data for this node otherwise it would not
Packit 762fc5
						   come to this part of the code.
Packit 762fc5
						   So we don't print any error message.
Packit 762fc5
						 */
Packit 762fc5
					} else if (errno == ENOENT &&
Packit 762fc5
										 ((r->sel_rx_lst != NULL || r->neg_rx_lst != NULL ||
Packit 762fc5
											r->equ_rx_lst != NULL) || r->childs != NULL)) {
Packit 762fc5
						/* The dir did not exist and there are regexps referring to
Packit 762fc5
						   this node or there are children to this node. 
Packit 762fc5
						   The only way a nonexistent dirnode can have children is by 
Packit 762fc5
						   having rules referring to them.
Packit 762fc5
						 */
Packit 762fc5
						error (10,
Packit 762fc5
									 "There are rules referring to non-existent directory %s\n", fullname);
Packit 762fc5
					} else if (errno != ENOTDIR) {
Packit 762fc5
						/* We print the message unless it is "Not a directory". */
Packit 762fc5
						char *er = strerror (errno);
Packit 762fc5
						if (er != NULL) {
Packit 762fc5
							error (3, "open_dir(): %s: %s\n", er, fullname);
Packit 762fc5
						} else {
Packit 762fc5
							error (3, "open_dir(): %i: %s\n", errno, fullname);
Packit 762fc5
						}
Packit 762fc5
					}
Packit 762fc5
					r->checked |= NODE_TRAVERSE | NODE_CHECKED;
Packit 762fc5
					r = r->parent;
Packit 762fc5
					error (255, "dropping back to parent\n");
Packit 762fc5
				}
Packit 762fc5
				free(fullname);
Packit 762fc5
			} else {
Packit 762fc5
				r->checked |= NODE_TRAVERSE | NODE_CHECKED;
Packit 762fc5
				r = r->parent;
Packit 762fc5
				/* We have gone out of the tree. This happens in some instances */
Packit 762fc5
				if (r == NULL) {
Packit 762fc5
					return NULL;
Packit 762fc5
				}
Packit 762fc5
				error (255, "dropping back to parent\n");
Packit 762fc5
			}
Packit 762fc5
			goto recursion;
Packit 762fc5
		}
Packit 762fc5
Packit 762fc5
		if (r->parent != NULL) {
Packit 762fc5
			/*
Packit 762fc5
			   Go back in time:)
Packit 762fc5
			 */
Packit 762fc5
			r->checked |= NODE_CHECKED;
Packit 762fc5
Packit 762fc5
			r = r->parent;
Packit 762fc5
Packit 762fc5
			goto recursion;
Packit 762fc5
		}
Packit 762fc5
		/*
Packit 762fc5
		   The end has been reached. Nothing to do.
Packit 762fc5
		 */
Packit 762fc5
	}
Packit 762fc5
Packit 762fc5
	return fil;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
int db_disk_init ()
Packit 762fc5
{
Packit 762fc5
Packit 762fc5
	r = conf->tree;
Packit 762fc5
Packit 762fc5
#  ifdef HAVE_READDIR_R
Packit 762fc5
	resp = (struct AIDE_DIRENT_TYPE **)
Packit 762fc5
		malloc (sizeof (struct AIDE_DIRENT_TYPE) + _POSIX_PATH_MAX);
Packit 762fc5
	entp = (struct AIDE_DIRENT_TYPE *)
Packit 762fc5
		malloc (sizeof (struct AIDE_DIRENT_TYPE) + _POSIX_PATH_MAX);
Packit 762fc5
#  else
Packit 762fc5
#   ifdef HAVE_READDIR
Packit 762fc5
	/*
Packit 762fc5
	   Should we do something here?
Packit 762fc5
Packit 762fc5
	 */
Packit 762fc5
#   else
Packit 762fc5
#    error AIDE needs readdir or readdir_r
Packit 762fc5
#   endif
Packit 762fc5
#  endif
Packit 762fc5
Packit 762fc5
Packit 762fc5
	char* fullname=malloc((conf->root_prefix_length+2)*sizeof(char));
Packit 762fc5
	strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1);
Packit 762fc5
	strncat (fullname, "/", 1);
Packit 762fc5
	dirh=open_dir(fullname);
Packit 762fc5
	free(fullname);
Packit 762fc5
Packit 762fc5
	return RETOK;
Packit 762fc5
}
Packit 762fc5
Packit 762fc5
/*
Packit 762fc5
  We don't support writing to the pseudo-database disk, since we are'n a
Packit 762fc5
  backup/restore software. Hence the functions db_writespec_disk,
Packit 762fc5
  db_writeline_disk and db_close_disk aren't declared.
Packit 762fc5
 */
Packit 762fc5
Packit 762fc5
const char *aide_key_6 = CONFHMACKEY_06;
Packit 762fc5
const char *db_key_6 = DBHMACKEY_06;