|
Packit |
762fc5 |
/* aide, Advanced Intrusion Detection Environment
|
|
Packit |
762fc5 |
*
|
|
Packit |
762fc5 |
* Copyright (C) 1999-2003,2005,2006,2010,2011,2013 Rami Lehti, Pablo
|
|
Packit |
762fc5 |
* Virolainen, 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 |
#include <string.h>
|
|
Packit |
762fc5 |
#include <stdio.h>
|
|
Packit |
762fc5 |
#include <stdlib.h>
|
|
Packit |
762fc5 |
#include <stdarg.h>
|
|
Packit |
762fc5 |
#include <unistd.h>
|
|
Packit |
762fc5 |
#include <errno.h>
|
|
Packit |
762fc5 |
#include "db_config.h"
|
|
Packit |
762fc5 |
#include "db_file.h"
|
|
Packit |
762fc5 |
#include "report.h"
|
|
Packit |
762fc5 |
#include "util.h"
|
|
Packit |
762fc5 |
#ifdef WITH_CURL
|
|
Packit |
762fc5 |
#include "fopen.h"
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
#include "be.h"
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
#ifdef WITH_PSQL
|
|
Packit |
762fc5 |
#include "libpq-fe.h"
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
/*for locale support*/
|
|
Packit |
762fc5 |
#include "locale-aide.h"
|
|
Packit |
762fc5 |
/*for locale support*/
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
#ifdef WITH_PSQL
|
|
Packit |
762fc5 |
static int be_sql_readinit(psql_data* ret) {
|
|
Packit |
762fc5 |
/* Yes.. we don't want to know about two first result..
|
|
Packit |
762fc5 |
and we want no memoryleaking.
|
|
Packit |
762fc5 |
*/
|
|
Packit |
762fc5 |
int i,j,nFields;
|
|
Packit |
762fc5 |
char* s;
|
|
Packit |
762fc5 |
char declare []="DECLARE aidecursor CURSOR FOR select * from ";
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
s = (char*)malloc(strlen(declare)+strlen(ret->table)+1);
|
|
Packit |
762fc5 |
s[0]=0;
|
|
Packit |
762fc5 |
s=strcat(s,declare);
|
|
Packit |
762fc5 |
s=strcat(s,ret->table);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
ret->res=PQexec(ret->conn,s);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (!ret->res || PQresultStatus(ret->res) != PGRES_COMMAND_OK) {
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (ret->res!=NULL) {
|
|
Packit |
762fc5 |
error(255,"Psql error: %s\n",PQresStatus(PQresultStatus(ret->res)));
|
|
Packit |
762fc5 |
PQclear(ret->res);
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
return RETFAIL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
PQclear(ret->res);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
ret -> res = PQexec(ret->conn, "FETCH ALL in aidecursor");
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (!ret->res || PQresultStatus(ret->res) != PGRES_TUPLES_OK)
|
|
Packit |
762fc5 |
{
|
|
Packit |
762fc5 |
error(0, "FETCH ALL command didn't return tuples properly\n");
|
|
Packit |
762fc5 |
PQclear(ret->res);
|
|
Packit |
762fc5 |
abort();
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
/* first, print out the attribute names */
|
|
Packit |
762fc5 |
nFields = PQnfields(ret->res);
|
|
Packit |
762fc5 |
for (i = 0; i < nFields; i++)
|
|
Packit |
762fc5 |
error(255,"%-15s", PQfname(ret->res, i));
|
|
Packit |
762fc5 |
error(255,"\n\n");
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
for(i=0;i
|
|
Packit |
762fc5 |
ret->des[i]=PQfnumber(ret->res,db_names[i]);
|
|
Packit |
762fc5 |
if (ret->des[i]!=-1) {
|
|
Packit |
762fc5 |
error(255,"Field %i,%s \n",ret->des[i],db_names[i]);
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
ret->curread=0;
|
|
Packit |
762fc5 |
ret->maxread=PQntuples(ret->res);
|
|
Packit |
762fc5 |
/* And now we know how many fields we have.. */
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
error(0,"%i tuples\n",ret->maxread);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
return RETOK;
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
static char* get_first_value(char** in){
|
|
Packit |
762fc5 |
int i=0;
|
|
Packit |
762fc5 |
char* ret = (*in);
|
|
Packit |
762fc5 |
while((*in)[i]!=':' && (*in)[i]!='\0') {
|
|
Packit |
762fc5 |
i++;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
if ((*in)[i]!='\0') { /* Lets not go beond the sting.. */
|
|
Packit |
762fc5 |
(*in)[i]='\0';
|
|
Packit |
762fc5 |
(*in)+=i+1;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
return ret;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
FILE* be_init(int inout,url_t* u,int iszipped)
|
|
Packit |
762fc5 |
{
|
|
Packit |
762fc5 |
FILE* fh=NULL;
|
|
Packit |
762fc5 |
long a=0;
|
|
Packit |
762fc5 |
char* err=NULL;
|
|
Packit |
762fc5 |
int fd;
|
|
Packit |
762fc5 |
#if HAVE_FCNTL && HAVE_FTRUNCATE
|
|
Packit |
762fc5 |
struct flock fl;
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (u==NULL) {
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
switch (u->type) {
|
|
Packit |
762fc5 |
case url_file : {
|
|
Packit |
762fc5 |
u->value = expand_tilde(u->value);
|
|
Packit |
762fc5 |
error(200,_("Opening file \"%s\" for %s\n"),u->value,inout?"r":"w+");
|
|
Packit |
762fc5 |
#if HAVE_FCNTL && HAVE_FTRUNCATE
|
|
Packit |
762fc5 |
fd=open(u->value,inout?O_RDONLY:O_CREAT|O_RDWR,0666);
|
|
Packit |
762fc5 |
#else
|
|
Packit |
762fc5 |
fd=open(u->value,inout?O_RDONLY:O_CREAT|O_RDWR|O_TRUNC,0666);
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
error(255,"Opened file \"%s\" with fd=%i\n",u->value,fd);
|
|
Packit |
762fc5 |
if(fd==-1) {
|
|
Packit |
762fc5 |
error(0,_("Couldn't open file %s for %s"),u->value,
|
|
Packit |
762fc5 |
inout?"reading\n":"writing\n");
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#if HAVE_FCNTL && HAVE_FTRUNCATE
|
|
Packit |
762fc5 |
if(!inout) {
|
|
Packit |
762fc5 |
fl.l_type = F_WRLCK;
|
|
Packit |
762fc5 |
fl.l_whence = SEEK_SET;
|
|
Packit |
762fc5 |
fl.l_start = 0;
|
|
Packit |
762fc5 |
fl.l_len = 0;
|
|
Packit |
762fc5 |
if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
Packit |
762fc5 |
if (fcntl(fd, F_SETLK, &fl) == -1)
|
|
Packit |
762fc5 |
error(0,_("File %s is locked by another process.\n"),u->value);
|
|
Packit |
762fc5 |
else
|
|
Packit |
762fc5 |
error(0,_("Cannot get lock for file %s"),u->value);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
if(ftruncate(fd,0)==-1)
|
|
Packit |
762fc5 |
error(0,_("Error truncating file %s"),u->value);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
if(iszipped && !inout){
|
|
Packit |
762fc5 |
fh=gzdopen(fd,"wb9");
|
|
Packit |
762fc5 |
if(fh==NULL){
|
|
Packit |
762fc5 |
error(0,_("Couldn't open file %s for %s"),u->value,
|
|
Packit |
762fc5 |
inout?"reading\n":"writing\n");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
else{
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
fh=fdopen(fd,inout?"r":"w+");
|
|
Packit |
762fc5 |
if(fh==NULL){
|
|
Packit |
762fc5 |
error(0,_("Couldn't open file %s for %s"),u->value,
|
|
Packit |
762fc5 |
inout?"reading\n":"writing\n");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
return fh;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
case url_stdout : {
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
if(iszipped){
|
|
Packit |
762fc5 |
return gzdopen(fileno(stdout),"wb");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
else{
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
return stdout;
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
case url_stdin : {
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
if(iszipped){
|
|
Packit |
762fc5 |
return gzdopen(fileno(stdin),"r");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
else{
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
return stdin;
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
case url_stderr : {
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
if(iszipped){
|
|
Packit |
762fc5 |
return gzdopen(fileno(stderr),"wb");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
else{
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
return stderr;
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
case url_fd : {
|
|
Packit |
762fc5 |
a=strtol(u->value,&err,10);
|
|
Packit |
762fc5 |
if(*err!='\0'||errno==ERANGE){
|
|
Packit |
762fc5 |
error(0,"Illegal file descriptor value:%s\n",u->value);
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
if(iszipped && !inout){
|
|
Packit |
762fc5 |
fh=gzdopen(a,"w");
|
|
Packit |
762fc5 |
if(fh==NULL){
|
|
Packit |
762fc5 |
error(0,"Couldn't reopen file descriptor %li\n",a);
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
else{
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
fh=fdopen(a,inout?"r":"w");
|
|
Packit |
762fc5 |
if(fh==NULL){
|
|
Packit |
762fc5 |
error(0,"Couldn't reopen file descriptor %li\n",a);
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#ifdef WITH_ZLIB
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
return fh;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#ifdef WITH_PSQL
|
|
Packit |
762fc5 |
case url_sql : {
|
|
Packit |
762fc5 |
char *pghost, *pgport, *pgoptions, *pgtty, *dbName, *login, *pwd;
|
|
Packit |
762fc5 |
char *tmp,*tmp2;
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
psql_data* ret = (psql_data*) malloc(sizeof(psql_data)*1);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (ret==NULL) {
|
|
Packit |
762fc5 |
error(0,"Not enough memory for postgres sql connection\n");
|
|
Packit |
762fc5 |
return ret;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
tmp=strdup(u->value);
|
|
Packit |
762fc5 |
tmp2=tmp;
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
pgtty=NULL;pgoptions=NULL;
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if ((pghost=get_first_value(&tmp)) == NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define host for Postgres sql connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
error(100,"Psql host is %s\n",pghost);
|
|
Packit |
762fc5 |
if ((pgport=get_first_value(&tmp)) == NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define port for Postgres sql connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
error(100,"Psql port is %s\n",pgport);
|
|
Packit |
762fc5 |
if ((dbName=get_first_value(&tmp)) == NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define name for database for Postgres sql connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
error(100,"Psql db is %s\n",dbName);
|
|
Packit |
762fc5 |
if ((login=get_first_value(&tmp)) == NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define login for Postgres sql connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
error(100,"Psql login is %s\n",login);
|
|
Packit |
762fc5 |
if ((pwd=get_first_value(&tmp)) == NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define password for database for Postgres sql connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
error(100,"Psql passwd is %s\n",pwd);
|
|
Packit |
762fc5 |
if ((ret->table=get_first_value(&tmp))==NULL) {
|
|
Packit |
762fc5 |
error(0,"Must define table for sql..\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
if (ret->table[0]=='\0') {
|
|
Packit |
762fc5 |
error(0,"Must define table for sql..\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
/* everything went ok.. */
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (login[0] == '\0' ) {
|
|
Packit |
762fc5 |
login = NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
if (pwd[0] == '\0' ) {
|
|
Packit |
762fc5 |
pwd = NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
ret->conn = PQsetdbLogin(pghost,pgport,pgoptions,pgtty,dbName,login,pwd);
|
|
Packit |
762fc5 |
if (PQstatus(ret->conn) == CONNECTION_BAD){
|
|
Packit |
762fc5 |
error(0,"Postgres sql error during connection\n");
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
/* Otherwise we would become to situation that name of table would
|
|
Packit |
762fc5 |
be freeed
|
|
Packit |
762fc5 |
*/
|
|
Packit |
762fc5 |
ret->table = strdup(ret->table);
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
/* And now we have made a connection to database..
|
|
Packit |
762fc5 |
Next thing we do is to begin a new transaction block */
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
ret->res = PQexec(ret->conn, "BEGIN");
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
if (!ret->res || PQresultStatus(ret->res) != PGRES_COMMAND_OK) {
|
|
Packit |
762fc5 |
error(0,"BEGIN command failed... \n");
|
|
Packit |
762fc5 |
PQclear(ret->res);
|
|
Packit |
762fc5 |
free(ret);
|
|
Packit |
762fc5 |
ret=NULL;
|
|
Packit |
762fc5 |
} else {
|
|
Packit |
762fc5 |
PQclear(ret->res);
|
|
Packit |
762fc5 |
if ((inout?be_sql_readinit(ret):RETOK)!=RETOK) {
|
|
Packit |
762fc5 |
error(255,"Something went wrong with sql backend init.\n");
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
free(tmp2);
|
|
Packit |
762fc5 |
return ret;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif
|
|
Packit |
762fc5 |
#ifdef WITH_CURL
|
|
Packit |
762fc5 |
case url_http:
|
|
Packit |
762fc5 |
case url_https:
|
|
Packit |
762fc5 |
case url_ftp:
|
|
Packit |
762fc5 |
{
|
|
Packit |
762fc5 |
error(200,_("Opening curl \"%s\" for %s\n"),u->value,inout?"r":"w+");
|
|
Packit |
762fc5 |
if (iszipped) {
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
return url_fopen(u->value,inout?"r":"w+");
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
#endif /* WITH CURL */
|
|
Packit |
762fc5 |
default:{
|
|
Packit |
762fc5 |
error(0,"Unsupported backend: %i", u->type);
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
/* Not reached */
|
|
Packit |
762fc5 |
return NULL;
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
}
|
|
Packit |
762fc5 |
|
|
Packit |
762fc5 |
const char* aide_key_8=CONFHMACKEY_08;
|
|
Packit |
762fc5 |
const char* db_key_8=DBHMACKEY_08;
|