aide/SOURCES/aide-0.16-CVE-2025-54389.patch
2025-08-26 09:24:29 +00:00

1054 lines
34 KiB
Diff

diff --git a/ChangeLog b/ChangeLog
index 263c438f4a2a38edc45f91c0d5a216112a8fa38c..5d286a8e07d0b3235f97272223175a1dd85848b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,27 +1,30 @@
+2025-08-07 Hannes von Haugwitz <hannes@vonhaugwitz.com>
+ * Escape control characters in report and log output (CVE-2025-54389)
+
2016-07-25 Hannes von Haugwitz <hannes@vonhaugwitz.com>
- * Release version 0.16
+ * Release version 0.16
2016-07-11 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Fix example aide.conf (xattr -> xattrs)
* aide.conf.5: update "SELECTION LINES" section
* Released version 0.16rc1
2016-07-10 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Fix compilation with latest libaudit
* Use AC_PROG_CC_C99 instead of AC_PROG_CC
* Add AM_PROG_CC_C_O
* aide.conf.in: logfile -> file
* Update README
* Update manual pages (aide.1 and aide.conf.5)
2016-07-07 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Adapt manual to version 0.16
2016-06-08 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Add missing break statements
2016-04-15 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Released version 0.16b1
2016-04-13 Hannes von Haugwitz <hannes@vonhaugwitz.com>
* Fix spelling errors
diff --git a/doc/aide.1.in b/doc/aide.1.in
index 932810eebd2eda353c2f30ce89a042e5f9d69a51..e932b8d0273e9144b09b3e1f8cf61cba2be12155 100644
--- a/doc/aide.1.in
+++ b/doc/aide.1.in
@@ -71,51 +71,61 @@ output. See aide.conf (5) section URLS for available values.
Prints out the standard help message.
.PP
.SH DIAGNOSTICS
Normally, the exit status is 0 if no errors occurred. Except when the
.BR --check ,
.BR --compare " or"
.B --update
command was requested, in which case the exit status is defined as:
.IP "1 * (new files detected?) +"
.IP "2 * (removed files detected?) +"
.IP "4 * (changed files detected?)"
.PP
Additionally, the following exit codes are defined for generic error
conditions:
.IP "14 Error writing error"
.IP "15 Invalid argument error"
.IP "16 Unimplemented function error"
.IP "17 Invalid configureline error"
.IP "18 IO error"
.IP "19 Version mismatch error"
.PP
.SH NOTES
Please note that due to mmap issues, aide cannot be terminated with
SIGTERM. Use SIGKILL to terminate.
+.IP "Checksum encoding"
+
The checksums in the database and in the output are by default base64
encoded (see also report_base16 option).
To decode them you can use the following shell command:
echo <encoded_checksum> | base64 \-d | hexdump \-v \-e '32/1 "%02x" "\\n"'
+.IP "Control characters"
+
+Control characters (00-31 and 127) are always escaped in log and plain report
+output. They are escaped by a literal backslash (\\) followed by exactly 3
+digits representing the character in octal notation (e.g. a newline is output
+as "\\012"). A literal backslash is not escaped unless it is followed by 3 digits
+(0-9), in this case the literal backslash is escaped as "\\134".
+
.PP
.SH FILES
.IP \fB@sysconfdir@/aide.conf\fR
Default aide configuration file.
.IP \fB@localstatedir@/lib/aide/aide.db\fR
Default aide database.
.IP \fB@localstatedir@/lib/aide/aide.db.new\fR
Default aide output database.
.SH SEE ALSO
.BR aide.conf (5)
.BR manual.html
.SH BUGS
There are probably bugs in this release. Please report them
at http://sourceforge.net/projects/aide . Bug fixes are more than welcome.
Unified diffs are preferred.
.SH DISCLAIMER
All trademarks are the property of their respective owners.
No animals were harmed while making this webpage or this piece of
software. Although some pizza delivery guy's feelings were hurt.
.BR
diff --git a/include/util.h b/include/util.h
index 79988536c974ca83b14696380f6006031e0fa5e4..68e6ee2a905856bc7b73f1a67633585e0c1d814d 100644
--- a/include/util.h
+++ b/include/util.h
@@ -22,48 +22,51 @@
#ifndef _UTIL_H_INCLUDED
#define _UTIL_H_INCLUDED
#include <string.h>
#include <sys/types.h>
#include "db_config.h"
#define HEXD2ASC(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'A'))
#define ASC2HEXD(x) (((x) >= '0' && (x) <= '9') ? \
((x) - '0') : (toupper(x) - 'A' + 10))
#define ISXDIGIT(x) isxdigit ((unsigned char)(x))
#define CLEANDUP(x) (contains_unsafe (x) ? encode_string (x) : strdup (x))
#ifndef HAVE_STRICMP
# define stricmp(a,b) strcasecmp( (a), (b) )
#endif
int cmpurl(url_t*, url_t*);
url_t* parse_url(char*);
int contains_unsafe(const char*);
+char *strnesc(const char *, size_t);
+char *stresc(const char *);
+
void decode_string(char*);
char* encode_string(const char*);
char* perm_to_char(mode_t perm);
void sig_handler(int signal);
void init_sighandler(void);
char *expand_tilde(char * path);
#ifndef HAVE_STRNSTR
char* strnstr(char* haystack,char* needle,int n);
#endif
#ifndef HAVE_STRNLEN
size_t strnlen(const char *s, size_t maxlen);
#endif
int syslog_facility_lookup(char *);
#endif
diff --git a/src/aide.c b/src/aide.c
index 8dd38b7c5a7130cc1136d0ee30f5addc9c2226e5..2b7eee14b6e1d4351ca5ddc9387344bd88a8951c 100644
--- a/src/aide.c
+++ b/src/aide.c
@@ -164,54 +164,60 @@ static int read_param(int argc,char**argv)
error(0,_("-B must have a parameter\n"));
exit(INVALID_ARGUMENT_ERROR);
}
break;
}
case 'A': {
if (optarg!=NULL) {
int errorno=commandconf('A',optarg);
if (errorno!=0){
error(0,_("Configuration error in after statement:%s\n"),optarg);
exit(INVALID_CONFIGURELINE_ERROR);
}
} else {
error(0,_("-A must have a parameter\n"));
exit(INVALID_ARGUMENT_ERROR);
}
break;
}
case 'l': {
if (optarg!=NULL) {
const char* pcre_error;
int pcre_erroffset;
conf->limit=malloc(strlen(optarg)+1);
strcpy(conf->limit,optarg);
if((conf->limit_crx=pcre_compile(conf->limit, PCRE_ANCHORED, &pcre_error, &pcre_erroffset, NULL)) == NULL) {
- error(0,_("Error in limit regexp '%s' at %i: %s\n"), conf->limit, pcre_erroffset, pcre_error);
+ char *limit_safe = stresc(conf->limit);
+ error(0,_("Error in limit regexp '%s' at %i: %s\n"), limit_safe, pcre_erroffset, pcre_error);
+ free(limit_safe);
exit(INVALID_ARGUMENT_ERROR);
}
- error(200,_("Limit set to '%s'\n"), conf->limit);
+ {
+ char *limit_safe = stresc(conf->limit);
+ error(200,_("Limit set to '%s'\n"), limit_safe);
+ free(limit_safe);
+ }
} else {
error(0,_("-l must have an argument\n"));
exit(INVALID_ARGUMENT_ERROR);
}
break;
}
case 'r': {
if(optarg!=NULL) {
do_repurldef(optarg);
}else {
error(0,_("-r must have an argument\n"));
}
break;
}
case 'i': {
if(conf->action==0){
conf->action=DO_INIT;
}else {
error(0,
_("Cannot have multiple commands on a single commandline.\n"));
exit(INVALID_ARGUMENT_ERROR);
};
break;
}
case 'C': {
@@ -566,53 +572,57 @@ int main(int argc,char**argv)
if(cmpurl(conf->db_in_url,conf->db_out_url)==RETOK){
error(4,_("WARNING:Input and output database urls are the same.\n"));
if((conf->action&DO_INIT)&&(conf->action&DO_COMPARE)){
error(0,_("Input and output database urls cannot be the same "
"when doing database update\n"));
exit(INVALID_ARGUMENT_ERROR);
}
if(conf->action&DO_DIFF){
error(0,_("Both input databases cannot be the same "
"when doing database compare\n"));
exit(INVALID_ARGUMENT_ERROR);
}
};
if((conf->action&DO_DIFF)&&(!(conf->db_new_url)||!(conf->db_in_url))){
error(0,_("Must have both input databases defined for "
"database compare.\n"));
exit(INVALID_ARGUMENT_ERROR);
}
if (conf->action&(DO_INIT|DO_COMPARE) && conf->root_prefix_length > 0) {
DIR *dir;
if((dir = opendir(conf->root_prefix)) != NULL) {
closedir(dir);
} else {
char* er=strerror(errno);
if (er!=NULL) {
- error(0,"opendir() for root prefix %s failed: %s\n", conf->root_prefix,er);
+ char *rp_safe = stresc(conf->root_prefix);
+ error(0,"opendir() for root prefix %s failed: %s\n", rp_safe,er);
+ free(rp_safe);
} else {
- error(0,"opendir() for root prefix %s failed: %i\n", conf->root_prefix,errno);
+ char *rp_safe = stresc(conf->root_prefix);
+ error(0,"opendir() for root prefix %s failed: %i\n", rp_safe,errno);
+ free(rp_safe);
}
exit(INVALID_ARGUMENT_ERROR);
}
}
#ifdef WITH_MHASH
byte* dig=NULL;
char* digstr=NULL;
if(conf->config_check&&FORCECONFIGMD){
error(0,"Can't give config checksum when compiled with --enable-forced_configmd\n");
exit(INVALID_ARGUMENT_ERROR);
}
if((conf->do_configmd||conf->config_check)&& conf->confmd!=0){
/* The patch automatically adds a newline so will also have to add it. */
if(newlinelastinconfig==0){
mhash(conf->confmd,"\n",1);
};
mhash(conf->confmd, NULL,0);
dig=(byte*)malloc(sizeof(byte)*mhash_get_block_size(conf->confhmactype));
mhash_deinit(conf->confmd,(void*)dig);
digstr=encode_base64(dig,mhash_get_block_size(conf->confhmactype));
if(!conf->config_check||FORCECONFIGMD){
if(strncmp(digstr,conf->old_confmdstr,strlen(digstr))!=0){
diff --git a/src/compare_db.c b/src/compare_db.c
index c17828d3e8b732096e00253f21623339f2168ccf..41e216527a9b05b90f1b601a61279fd408e2df71 100644
--- a/src/compare_db.c
+++ b/src/compare_db.c
@@ -504,175 +504,225 @@ static void print_line(seltree* node) {
c = '<';
}
u = '=';
break;
}
if (summary_attributes[i]&node->changed_attrs&(forced_attrs|(~ignored_changed_attrs))) {
summary[i]=c;
} else if (summary_attributes[i]&((node->old_data)->attr&~((node->new_data)->attr)&(forced_attrs|~(ignored_removed_attrs)))) {
summary[i]=r;
} else if (summary_attributes[i]&~((node->old_data)->attr)&(node->new_data)->attr&(forced_attrs|~(ignored_added_attrs))) {
summary[i]=a;
} else if (summary_attributes[i]& (
(((node->old_data)->attr&~((node->new_data)->attr)&ignored_removed_attrs))|
(~((node->old_data)->attr)&(node->new_data)->attr&ignored_added_attrs)|
(((node->old_data)->attr&(node->new_data)->attr)&ignored_changed_attrs)
) ) {
summary[i]=g;
} else if (summary_attributes[i]&((node->old_data)->attr&(node->new_data)->attr)) {
summary[i]=u;
} else {
summary[i]=s;
}
}
}
summary[length]='\0';
- error(2,"\n%s: %s", summary, (node->checked&NODE_REMOVED?node->old_data:node->new_data)->filename);
+ {
+ char *filename_safe = stresc((node->checked&NODE_REMOVED?node->old_data:node->new_data)->filename);
+ error(2,"\n%s: %s", summary, filename_safe);
+ free(filename_safe);
+ }
free(summary); summary=NULL;
} else {
if (node->checked&NODE_ADDED) {
- error(2,"added: %s\n",(node->new_data)->filename);
+ {
+ char *filename_safe = stresc((node->new_data)->filename);
+ error(2,"added: %s\n",filename_safe);
+ free(filename_safe);
+ }
} else if (node->checked&NODE_REMOVED) {
- error(2,"removed: %s\n",(node->old_data)->filename);
+ {
+ char *filename_safe = stresc((node->old_data)->filename);
+ error(2,"removed: %s\n",filename_safe);
+ free(filename_safe);
+ }
} else if (node->checked&NODE_CHANGED) {
- error(2,"changed: %s\n",(node->new_data)->filename);
+ {
+ char *filename_safe = stresc((node->new_data)->filename);
+ error(2,"changed: %s\n",filename_safe);
+ free(filename_safe);
+ }
}
}
}
static void print_dbline_attributes(db_line* oline, db_line* nline, DB_ATTR_TYPE
changed_attrs, DB_ATTR_TYPE force_attrs) {
char **ovalue, **nvalue;
int onumber, nnumber, olen, nlen, i, j, k, c;
int length = sizeof(details_attributes)/sizeof(DB_ATTR_TYPE);
int p = (width_details-(width_details%2?13:14))/2;
DB_ATTR_TYPE attrs;
error(2,"\n");
char *file_type = get_file_type_string((nline==NULL?oline:nline)->perm);
if (file_type) {
error(2,"%s: ", file_type);
}
- error(2,"%s\n", (nline==NULL?oline:nline)->filename);
+ {
+ char *filename_safe = stresc((nline==NULL?oline:nline)->filename);
+ error(2,"%s\n", filename_safe);
+ free(filename_safe);
+ }
attrs=force_attrs|(~(ignored_changed_attrs)&changed_attrs);
for (j=0; j < length; ++j) {
if (details_attributes[j]&attrs) {
onumber=get_attribute_values(details_attributes[j], oline, &ovalue);
nnumber=get_attribute_values(details_attributes[j], nline, &nvalue);
i = 0;
while (i<onumber || i<nnumber) {
- olen = i<onumber?strlen(ovalue[i]):0;
- nlen = i<nnumber?strlen(nvalue[i]):0;
+ char *ov = i<onumber?stresc(ovalue[i]):NULL;
+ char *nv = i<nnumber?stresc(nvalue[i]):NULL;
+ olen = ov?strlen(ov):0;
+ nlen = nv?strlen(nv):0;
k = 0;
while (olen-p*k >= 0 || nlen-p*k >= 0) {
c = k*(p-1);
if (!onumber) {
- error(2," %s%-9s%c %-*c %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p, ' ', p-1, nlen-c>0?&nvalue[i][c]:"");
+ error(2," %s%-9s%c %-*c %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p, ' ', p-1, nlen-c>0?&nv[c]:"");
} else if (!nnumber) {
- error(2," %s%-9s%c %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p-1, olen-c>0?&ovalue[i][c]:"");
+ error(2," %s%-9s%c %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p-1, olen-c>0?&ov[c]:"");
} else {
- error(2," %s%-9s%c %-*.*s| %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p, p-1, olen-c>0?&ovalue[i][c]:"", p-1, nlen-c>0?&nvalue[i][c]:"");
+ error(2," %s%-9s%c %-*.*s| %.*s\n", width_details%2?"":" ", i+k?"":details_string[j], i+k?' ':':', p, p-1, olen-c>0?&ov[c]:"", p-1, nlen-c>0?&nv[c]:"");
}
k++;
}
++i;
+ free(ov);
+ free(nv);
}
for(i=0; i < onumber; ++i) { free(ovalue[i]); ovalue[i]=NULL; } free(ovalue); ovalue=NULL;
for(i=0; i < nnumber; ++i) { free(nvalue[i]); nvalue[i]=NULL; } free(nvalue); nvalue=NULL;
}
}
}
static void print_dbline_attributes_syslog(db_line* oline, db_line* nline, DB_ATTR_TYPE
changed_attrs, DB_ATTR_TYPE force_attrs) {
char **ovalue, **nvalue;
int onumber, nnumber, i, j;
int length = sizeof(details_attributes)/sizeof(DB_ATTR_TYPE);
DB_ATTR_TYPE attrs;
char *file_type = get_file_type_string((nline==NULL?oline:nline)->perm);
if (file_type) {
error(0,"%s=", file_type);
}
- error(0,"%s", (nline==NULL?oline:nline)->filename);
+ {
+ char *filename_safe = stresc((nline==NULL?oline:nline)->filename);
+ error(0,"%s", filename_safe);
+ free(filename_safe);
+ }
attrs=force_attrs|(~(ignored_changed_attrs)&changed_attrs);
for (j=0; j < length; ++j) {
if (details_attributes[j]&attrs) {
onumber=get_attribute_values(details_attributes[j], oline, &ovalue);
nnumber=get_attribute_values(details_attributes[j], nline, &nvalue);
if (details_attributes[j] == DB_ACL || details_attributes[j] == DB_XATTRS) {
error(0, ";%s_old=|", details_string[j]);
for (i = 0 ; i < onumber ; i++) {
- error(0, "%s|", ovalue[i]);
+ {
+ char *val_safe = stresc(ovalue[i]);
+ error(0, "%s|", val_safe);
+ free(val_safe);
+ }
}
error(0, ";%s_new=|", details_string[j]);
for (i = 0 ; i < nnumber ; i++) {
- error(0, "%s|", nvalue[i]);
+ {
+ char *val_safe = stresc(nvalue[i]);
+ error(0, "%s|", val_safe);
+ free(val_safe);
+ }
}
} else {
- error(0, ";%s_old=%s;%s_new=%s", details_string[j], *ovalue, details_string[j], *nvalue);
+ {
+ char *ov_safe = stresc(*ovalue);
+ char *nv_safe = stresc(*nvalue);
+ error(0, ";%s_old=%s;%s_new=%s", details_string[j], ov_safe, details_string[j], nv_safe);
+ free(ov_safe);
+ free(nv_safe);
+ }
}
for(i=0; i < onumber; ++i) { free(ovalue[i]); ovalue[i]=NULL; } free(ovalue); ovalue=NULL;
for(i=0; i < nnumber; ++i) { free(nvalue[i]); nvalue[i]=NULL; } free(nvalue); nvalue=NULL;
}
}
error(0, "\n");
}
static void print_attributes_added_node(db_line* line) {
print_dbline_attributes(NULL, line, 0, line->attr);
}
static void print_attributes_removed_node(db_line* line) {
print_dbline_attributes(line, NULL, 0, line->attr);
}
static void print_attributes_added_node_syslog(db_line* line) {
char *file_type = get_file_type_string(line->perm);
if (file_type) {
error(0,"%s=", file_type);
}
- error(0,"%s; added\n", line->filename);
+ {
+ char *filename_safe = stresc(line->filename);
+ error(0,"%s; added\n", filename_safe);
+ free(filename_safe);
+ }
}
static void print_attributes_removed_node_syslog(db_line* line) {
char *file_type = get_file_type_string(line->perm);
if (file_type) {
error(0,"%s=", file_type);
}
- error(0,"%s; removed\n", line->filename);
+ {
+ char *filename_safe = stresc(line->filename);
+ error(0,"%s; removed\n", filename_safe);
+ free(filename_safe);
+ }
}
static void terse_report(seltree* node) {
list* r=NULL;
if ((node->checked&(DB_OLD|DB_NEW)) != 0) {
ntotal += ((node->checked&DB_NEW) != 0);
if (!(node->checked&DB_OLD)){
/* File is in new db but not old. (ADDED) */
/* unless it was moved in */
if (!((node->checked&NODE_ALLOW_NEW)||(node->checked&NODE_MOVED_IN))) {
nadd++;
node->checked|=NODE_ADDED;
}
} else if (!(node->checked&DB_NEW)){
/* File is in old db but not new. (REMOVED) */
/* unless it was moved out */
if (!((node->checked&NODE_ALLOW_RM)||(node->checked&NODE_MOVED_OUT))) {
nrem++;
node->checked|=NODE_REMOVED;
}
} else if ((node->old_data!=NULL)&&(node->new_data!=NULL)){
/* File is in both db's and the data is still there. (CHANGED) */
if (!(node->checked&(NODE_MOVED_IN|NODE_MOVED_OUT))){
nchg++;
@@ -739,51 +789,53 @@ static void print_syslog_format(seltree* node) {
}
static void print_report_header() {
char *time;
int first = 1;
time = malloc(time_string_len * sizeof (char));
strftime(time, time_string_len, time_format, localtime(&(conf->start_time)));
error(2,_("Start timestamp: %s (AIDE " AIDEVERSION ")\n"), time);
free(time); time=NULL;
error(0,_("AIDE"));
if(conf->action&(DO_COMPARE|DO_DIFF)) {
error(0,_(" found %sdifferences between %s%s!!\n"), (nadd||nrem||nchg)?"":"NO ", conf->action&DO_COMPARE?_("database and filesystem"):_("the two databases"), (nadd||nrem||nchg)?"":_(". Looks okay"));
if(conf->action&(DO_INIT)) {
error(0,_("New AIDE database written to %s\n"),conf->db_out_url->value);
}
} else {
error(0,_(" initialized database at %s\n"),conf->db_out_url->value);
}
if(conf->config_version)
error(2,_("Config version used: %s\n"),conf->config_version);
if (conf->limit != NULL) {
- error (2,_("Limit: %s"), conf->limit);
+ char *limit_safe = stresc(conf->limit);
+ error (2,_("Limit: %s"), limit_safe);
+ free(limit_safe);
first = 0;
}
if (conf->action&(DO_INIT|DO_COMPARE) && conf->root_prefix_length > 0) {
if (first) { first=0; }
else { error (2," | "); }
error (2,_("Root prefix: %s"),conf->root_prefix);
}
if (conf->verbose_level != 5) {
if (first) { first=0; }
else { error (2," | "); }
error (2,_("Verbose level: %d"), conf->verbose_level);
}
if (!first) { error (2,"\n"); }
if (ignored_added_attrs) {
error (2,_("Ignored added attributes: %s\n"),report_attrs(ignored_added_attrs));
}
if (ignored_removed_attrs) {
error (2,_("Ignored removed attributes: %s\n"),report_attrs(ignored_removed_attrs));
}
if (ignored_changed_attrs) {
error (2,_("Ignored changed attributes: %s\n"),report_attrs(ignored_changed_attrs));
}
if (forced_attrs) {
error (2,_("Forced attributes: %s\n"),report_attrs(forced_attrs));
}
diff --git a/src/db_sql.c b/src/db_sql.c
index 154579070ccacb6e9b6b8393b989eb50c843e71d..09a32504c317607150174d2bec0fcddf47992995 100644
--- a/src/db_sql.c
+++ b/src/db_sql.c
@@ -16,50 +16,51 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "aide.h"
/*for locale support*/
#include "locale-aide.h"
/*for locale support*/
#ifdef WITH_PSQL
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <gcrypt.h>
#include "base64.h"
#include "db.h"
#include "db_sql.h"
#include "db_config.h"
#include "libpq-fe.h"
#include "report.h"
+#include "util.h"
#ifdef WITH_MHASH
#include <mhash.h>
#endif
char* db_get_sql(db_line*,db_config*);
int _db_check_result(PGconn *conn, PGresult *res, char *query)
{
int status = 0;
int ret = RETOK;
if (!res || ( (PQresultStatus(res) != PGRES_COMMAND_OK) &&
(PQresultStatus(res) != PGRES_TUPLES_OK) )){
ret = RETFAIL;
if (res!=NULL) {
error(0,"Sql error %s while doing %s\n", PQerrorMessage(conn), query);
} else {
error(0,"Sql error while doing %s.\n",query);
}
} else {
error(255,"Sql went ok.\n");
status = 1;
}
@@ -281,51 +282,55 @@ db_line* db_readline_sql(int db, db_config* conf) {
db_readline_sql_byte((void*)&(rline->haval),db,db_haval, conf);
db_readline_sql_byte((void*)&(rline->gost),db,db_gost, conf);
#endif
db_readline_sql_char((void*)&(rline->fullpath),db,db_filename, conf);
rline->filename=rline->fullpath;
db_readline_sql_char((void*)&(rline->linkname),db,db_linkname, conf);
db_readline_sql_int((void*)&(rline->perm),db,db_perm, conf);
db_readline_sql_int((void*)&(rline->uid),db,db_uid, conf);
db_readline_sql_int((void*)&(rline->gid),db,db_gid, conf);
db_readline_sql_int((void*)&(rline->inode),db,db_inode, conf);
db_readline_sql_int((void*)&(rline->nlink),db,db_lnkcount, conf);
db_readline_sql_int((void*)&(rline->size),db,*db_osize, conf);
db_readline_sql_int((void*)&(rline->bcount),db,db_bcount, conf);
db_readline_sql_int((void*)&(rline->attr),db,db_attr, conf);
db_readline_sql_time((void*)&(rline->atime),db,db_atime, conf);
db_readline_sql_time((void*)&(rline->ctime),db,db_ctime, conf);
db_readline_sql_time((void*)&(rline->mtime),db,db_mtime, conf);
#ifdef WITH_ACL
rline->acl=NULL;
#endif
((psql_data*)(*db_filep))->curread++;
- error(255,"filename %s\n",rline->filename);
+ {
+ char *filename_safe = stresc(rline->filename);
+ error(255,"filename %s\n",filename_safe);
+ free(filename_safe);
+ }
return rline;
}
void sql_writeint(int data,char *s,int i){
char t[10];
t[0]=0;
if (i!=0) {
s = strcat(s,",");
}
sprintf(t,"%i",data);
strcat(s,t);
}
void sql_writeoct(int data,char *s,int i){
char t[10];
t[0]=0;
if (i!=0) {
s = strcat(s,",");
}
sprintf(t,"%lo",data);
diff --git a/src/do_md.c b/src/do_md.c
index 77d2e15f5f9cdba5168a92feaf2f97128e705f36..4a648b6f5ff14edd553a3f8d94b1171708ccadaf 100644
--- a/src/do_md.c
+++ b/src/do_md.c
@@ -16,50 +16,51 @@
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "aide.h"
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "md.h"
+#include "util.h"
#include "db_config.h"
#include "do_md.h"
#include "report.h"
#include "list.h"
/*for locale support*/
#include "locale-aide.h"
/*for locale support*/
/* This define should be somewhere else */
#define READ_BLOCK_SIZE 16777216
#ifdef WITH_MHASH
#include <mhash.h>
#endif /* WITH_MHASH */
/* Redhat 5.0 needs this */
#ifdef HAVE_MMAP
#ifndef MAP_FAILED
#define MAP_FAILED (-1)
#endif /* MAP_FAILED */
#define MMAP_BLOCK_SIZE 16777216
#endif /* HAVE_MMAP */
@@ -206,55 +207,59 @@ void calc_md(struct AIDE_STAT_TYPE* old_fs,db_line* line) {
from we are about to calculate the hash is the correct one,
and we don't read from a pipe :)
*/
struct AIDE_STAT_TYPE fs;
int stat_diff,filedes;
#ifdef WITH_PRELINK
pid_t pid;
#endif
error(255,"calc_md called\n");
#ifdef _PARAMETER_CHECK_
if (line==NULL) {
abort();
}
#endif
#ifdef HAVE_O_NOATIME
filedes=open(line->fullpath,O_RDONLY|O_NOATIME);
if(filedes<0)
#endif
filedes=open(line->fullpath,O_RDONLY);
if (filedes==-1) {
char* er=strerror(errno);
if (er!=NULL) {
+ char *fp_safe = stresc(line->fullpath);
error(3,"do_md(): open() for %s failed: %s\n",
- line->fullpath,er);
+ fp_safe,er);
+ free(fp_safe);
} else {
+ char *fp_safe = stresc(line->fullpath);
error(3,"do_md(): open() for %s failed: %i\n",
- line->fullpath,errno);
+ fp_safe,errno);
+ free(fp_safe);
}
/*
Nop. Cannot cal hashes. Mark it.
*/
no_hash(line);
return;
}
AIDE_FSTAT_FUNC(filedes,&fs);
if(!(line->attr&DB_RDEV))
fs.st_rdev=0;
#ifdef HAVE_POSIX_FADVISE
if (posix_fadvise(filedes,0,fs.st_size,POSIX_FADV_NOREUSE)!=0) {
error(255,"posix_fadvise error %s\n",strerror(errno));
} else {
error(255,"posix_fadvise(%i,0,%li,POSIX_FADV_NOREUSE) ok\n",filedes,fs.st_size);
}
#endif
if ((stat_diff=stat_cmp(&fs,old_fs))==RETOK) {
/*
Now we have a 'valid' filehandle to read from a file.
*/
#ifdef WITH_PRELINK
@@ -288,51 +293,55 @@ void calc_md(struct AIDE_STAT_TYPE* old_fs,db_line* line) {
off_t curpos=0;
r_size=fs.st_size;
/* in mmap branch r_size is used as size remaining */
while(r_size>0){
if(r_size<MMAP_BLOCK_SIZE){
#ifdef __hpux
buf = mmap(0,r_size,PROT_READ,MAP_PRIVATE,filedes,curpos);
#else
buf = mmap(0,r_size,PROT_READ,MAP_SHARED,filedes,curpos);
#endif
curpos+=r_size;
size=r_size;
r_size=0;
}else {
#ifdef __hpux
buf = mmap(0,MMAP_BLOCK_SIZE,PROT_READ,MAP_PRIVATE,filedes,curpos);
#else
buf = mmap(0,MMAP_BLOCK_SIZE,PROT_READ,MAP_SHARED,filedes,curpos);
#endif
curpos+=MMAP_BLOCK_SIZE;
size=MMAP_BLOCK_SIZE;
r_size-=MMAP_BLOCK_SIZE;
}
if ( buf == MAP_FAILED ) {
- error(0,"error mmap'ing %s: %s\n", line->fullpath,strerror(errno));
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0,"error mmap'ing %s: %s\n", fp_safe,strerror(errno));
+ free(fp_safe);
+ }
close(filedes);
close_md(&mdc);
return;
}
conf->catch_mmap=1;
if (update_md(&mdc,buf,size)!=RETOK) {
error(0,"Message digest failed during update\n");
close(filedes);
close_md(&mdc);
munmap(buf,size);
return;
}
munmap(buf,size);
conf->catch_mmap=0;
}
/* we have used MMAP, let's return */
close_md(&mdc);
md2line(&mdc,line);
close(filedes);
return;
#ifdef WITH_PRELINK
}
#endif
#endif /* not HAVE_MMAP */
// buf=malloc(READ_BLOCK_SIZE);
@@ -491,53 +500,61 @@ void acl2line(db_line* line) {
ret->acl_d = NULL;
else
{
tmp = acl_to_text(acl_d, NULL);
if (!tmp || !*tmp)
ret->acl_d = NULL;
else
ret->acl_d = strdup(tmp);
acl_free(tmp);
}
acl_free(acl_a);
acl_free(acl_d);
}
line->acl = ret;
#endif
#ifdef WITH_SUN_ACL
if(DB_ACL&line->attr) { /* There might be a bug here. */
int res;
line->acl=malloc(sizeof(acl_type));
line->acl->entries=acl(line->fullpath,GETACLCNT,0,NULL);
if (line->acl->entries==-1) {
char* er=strerror(errno);
line->acl->entries=0;
if (er==NULL) {
- error(0,"ACL query failed for %s. strerror failed for %i\n",line->fullpath,errno);
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0,"ACL query failed for %s. strerror failed for %i\n",fp_safe,errno);
+ free(fp_safe);
+ }
} else {
- error(0,"ACL query failed for %s:%s\n",line->fullpath,er);
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0,"ACL query failed for %s:%s\n",fp_safe,er);
+ free(fp_safe);
+ }
}
} else {
line->acl->acl=malloc(sizeof(aclent_t)*line->acl->entries);
res=acl(line->fullpath,GETACL,line->acl->entries,line->acl->acl);
if (res==-1) {
error(0,"ACL error %s\n",strerror(errno));
} else {
if (res!=line->acl->entries) {
error(0,"Tried to read %i acl but got %i\n",line->acl->entries,res);
}
}
}
}else{
line->acl=NULL;
}
#endif
}
#endif
#ifdef WITH_XATTR
static xattrs_type *xattr_new(void) {
xattrs_type *ret = NULL;
ret = malloc(sizeof(xattrs_type));
ret->num = 0;
@@ -571,100 +588,112 @@ static void xattr_add(xattrs_type *xattrs, const char *key, const char
xattrs->num += 1;
}
void xattrs2line(db_line *line) {
/* get all generic user xattrs. */
xattrs_type *xattrs = NULL;
static ssize_t xsz = 1024;
static char *xatrs = NULL;
ssize_t xret = -1;
if (!(DB_XATTRS&line->attr))
return;
/* assume memory allocs work, like rest of AIDE code... */
if (!xatrs) xatrs = malloc(xsz);
while (((xret = llistxattr(line->fullpath, xatrs, xsz)) == -1) && (errno == ERANGE)) {
xsz <<= 1;
xatrs = realloc(xatrs, xsz);
}
if ((xret == -1) && ((errno == ENOSYS) || (errno == ENOTSUP))) {
line->attr&=(~DB_XATTRS);
} else if (xret == -1) {
- error(0, "listxattrs failed for %s:%s\n", line->fullpath, strerror(errno));
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0, "listxattrs failed for %s:%s\n", fp_safe, strerror(errno));
+ free(fp_safe);
+ }
} else if (xret) {
const char *attr = xatrs;
static ssize_t asz = 1024;
static char *val = NULL;
if (!val) val = malloc(asz);
xattrs = xattr_new();
while (xret > 0) {
size_t len = strlen(attr);
ssize_t aret = 0;
if (strncmp(attr, "user.", strlen("user.")) &&
strncmp(attr, "root.", strlen("root.")))
goto next_attr; /* only store normal xattrs, and SELinux */
while (((aret = getxattr(line->fullpath, attr, val, asz)) ==
-1) && (errno == ERANGE)) {
asz <<= 1;
val = realloc (val, asz);
}
if (aret != -1)
xattr_add(xattrs, attr, val, aret);
else if (errno != ENOATTR)
- error(0, "getxattr failed for %s:%s\n", line->fullpath, strerror(errno));
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0, "getxattr failed for %s:%s\n", fp_safe, strerror(errno));
+ free(fp_safe);
+ }
next_attr:
attr += len + 1;
xret -= len + 1;
}
}
line->xattrs = xattrs;
}
#endif
#ifdef WITH_SELINUX
void selinux2line(db_line *line) {
char *cntx = NULL;
if (!(DB_SELINUX&line->attr))
return;
if (lgetfilecon_raw(line->fullpath, &cntx) == -1) {
line->attr&=(~DB_SELINUX);
if ((errno != ENOATTR) && (errno != EOPNOTSUPP))
- error(0, "lgetfilecon_raw failed for %s:%s\n", line->fullpath, strerror(errno));
+ {
+ char *fp_safe = stresc(line->fullpath);
+ error(0, "lgetfilecon_raw failed for %s:%s\n", fp_safe, strerror(errno));
+ free(fp_safe);
+ }
return;
}
line->cntx = strdup(cntx);
freecon(cntx);
}
#endif
#ifdef WITH_E2FSATTRS
void e2fsattrs2line(db_line* line) {
unsigned long flags;
if (DB_E2FSATTRS&line->attr) {
if (fgetflags(line->fullpath, &flags) == 0) {
line->e2fsattrs=flags;
} else {
line->attr&=(~DB_E2FSATTRS);
line->e2fsattrs=0;
}
} else {
line->e2fsattrs=0;
}
}
#endif