From 8aa88ecba3b87d23b91b128f4b2c9a9b80f76f91 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Fri, 26 Jun 2026 09:10:06 -0400 Subject: [PATCH] import Oracle_OSS aide-0.19.2-5.el9_8.1 --- .aide.metadata | 3 +- .gitignore | 3 +- SOURCES/aide-0.15-syslog-format.patch | 496 ----- SOURCES/aide-0.16-CVE-2021-45417.patch | 123 -- SOURCES/aide-0.16-CVE-2025-54389.patch | 1662 ----------------- ...ding-curl-library-to-the-linker-comm.patch | 58 - SOURCES/aide-0.16-crash-elf.patch | 17 - ...0.16-crypto-disable-haval-and-others.patch | 153 -- SOURCES/aide-0.16b1-fipsfix.patch | 103 - SOURCES/aide-0.16rc1-man.patch | 15 - SOURCES/aide-0.19.2-syslog-format.patch | 657 +++++++ SOURCES/aide-0.19.2.tar.gz.asc | 14 + SOURCES/aide-configure.patch | 51 - SOURCES/aide-db-problem.patch | 11 - SOURCES/aide-migrate-config | 588 ++++++ SOURCES/aide-static-analysis.patch | 171 -- SOURCES/aide-tmpfiles.conf | 2 + SOURCES/aide.conf | 498 ++--- SOURCES/coverity.patch | 642 ------- SOURCES/rootPrefix.patch | 21 - SPECS/aide.spec | 105 +- 21 files changed, 1610 insertions(+), 3783 deletions(-) delete mode 100644 SOURCES/aide-0.15-syslog-format.patch delete mode 100644 SOURCES/aide-0.16-CVE-2021-45417.patch delete mode 100644 SOURCES/aide-0.16-CVE-2025-54389.patch delete mode 100644 SOURCES/aide-0.16-Use-LDADD-for-adding-curl-library-to-the-linker-comm.patch delete mode 100644 SOURCES/aide-0.16-crash-elf.patch delete mode 100644 SOURCES/aide-0.16-crypto-disable-haval-and-others.patch delete mode 100644 SOURCES/aide-0.16b1-fipsfix.patch delete mode 100644 SOURCES/aide-0.16rc1-man.patch create mode 100644 SOURCES/aide-0.19.2-syslog-format.patch create mode 100644 SOURCES/aide-0.19.2.tar.gz.asc delete mode 100644 SOURCES/aide-configure.patch delete mode 100644 SOURCES/aide-db-problem.patch create mode 100755 SOURCES/aide-migrate-config delete mode 100644 SOURCES/aide-static-analysis.patch create mode 100644 SOURCES/aide-tmpfiles.conf delete mode 100644 SOURCES/coverity.patch delete mode 100644 SOURCES/rootPrefix.patch diff --git a/.aide.metadata b/.aide.metadata index a8e59ce..70ec0d0 100644 --- a/.aide.metadata +++ b/.aide.metadata @@ -1 +1,2 @@ -b97f65bb12701a42baa2cce45b41ed6367a70734 SOURCES/aide-0.16.tar.gz +8f5a43df4256133b66902fd412b2d03a9e770435 SOURCES/aide-0.19.2.tar.gz +ff960034941c33f56690697d06bba03c2b9f702c SOURCES/gpgkey-aide.gpg diff --git a/.gitignore b/.gitignore index f8be39e..5934c6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -SOURCES/aide-0.16.tar.gz +SOURCES/aide-0.19.2.tar.gz +SOURCES/gpgkey-aide.gpg diff --git a/SOURCES/aide-0.15-syslog-format.patch b/SOURCES/aide-0.15-syslog-format.patch deleted file mode 100644 index 0361434..0000000 --- a/SOURCES/aide-0.15-syslog-format.patch +++ /dev/null @@ -1,496 +0,0 @@ -diff -up ./doc/aide.conf.5.in.syslog_format ./doc/aide.conf.5.in ---- ./doc/aide.conf.5.in.syslog_format 2016-07-25 22:58:12.000000000 +0200 -+++ ./doc/aide.conf.5.in 2018-09-27 19:09:09.697371212 +0200 -@@ -57,6 +57,25 @@ inclusive. This parameter can only be gi - occurrence is used. If \-\-verbose or \-V is used then the value from that - is used. The default is 5. If verbosity is 20 then additional report - output is written when doing \-\-check, \-\-update or \-\-compare. -+.IP "syslog_format" -+Valid values are yes,true,no and false. This option enables new syslog format -+which is suitable for logging. Every change is logged as one simple line. This option -+changes verbose level to 0 and prints everything that was changed. It is suggested -+to use this option with "report_url=syslog:...". Default value is "false/no". -+Maximum size of message is 1KB which is limitation of syslog call. If message is -+greater than limit, message will be truncated. -+Option summarize_changes has no impact for this format. -+.nf -+.eo -+ -+Output always starts with: -+"AIDE found differences between database and filesystem!!" -+And it is followed by summary: -+summary;total_number_of_files=1000;added_files=0;removed_files=0;changed_files=1 -+And finally there are logs about changes: -+dir=/usr/sbin;Mtime_old=0000-00-00 00:00:00;Mtime_new=0000-00-00 00:00:00;... -+.ec -+.fi - .IP "report_url" - The url that the output is written to. There can be multiple instances - of this parameter. Output is written to all of them. The default is -diff -up ./include/db_config.h.syslog_format ./include/db_config.h ---- ./include/db_config.h.syslog_format 2016-07-25 22:56:55.000000000 +0200 -+++ ./include/db_config.h 2018-09-27 19:09:09.697371212 +0200 -@@ -311,6 +311,7 @@ typedef struct db_config { - FILE* db_out; - - int config_check; -+ int syslog_format; - - struct md_container *mdc_in; - struct md_container *mdc_out; -diff -up ./src/aide.c.syslog_format ./src/aide.c ---- ./src/aide.c.syslog_format 2018-09-27 19:09:09.695371197 +0200 -+++ ./src/aide.c 2018-09-27 19:09:09.698371220 +0200 -@@ -283,6 +283,7 @@ static void setdefaults_before_config() - } - - /* Setting some defaults */ -+ conf->syslog_format=0; - conf->report_db=0; - conf->tree=NULL; - conf->config_check=0; -@@ -495,6 +496,10 @@ static void setdefaults_after_config() - if(conf->verbose_level==-1){ - conf->verbose_level=5; - } -+ if(conf->syslog_format==1){ -+ conf->verbose_level=0; -+ } -+ - } - - -diff -up ./src/compare_db.c.syslog_format ./src/compare_db.c ---- ./src/compare_db.c.syslog_format 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/compare_db.c 2018-09-27 19:09:09.698371220 +0200 -@@ -110,7 +110,7 @@ const DB_ATTR_TYPE details_attributes[] - #endif - }; - --const char* details_string[] = { _("File type") , _("Lname"), _("Size"), _("Size (>)"), _("Bcount"), _("Perm"), _("Uid"), _("Gid"), _("Atime"), _("Mtime"), _("Ctime"), _("Inode"), _("Linkcount"), _("MD5"), _("SHA1"), _("RMD160"), _("TIGER"), _("SHA256"), _("SHA512") -+const char* details_string[] = { _("File type") , _("Lname"), _("Size"), _("Size"), _("Bcount"), _("Perm"), _("Uid"), _("Gid"), _("Atime"), _("Mtime"), _("Ctime"), _("Inode"), _("Linkcount"), _("MD5"), _("SHA1"), _("RMD160"), _("TIGER"), _("SHA256"), _("SHA512") - #ifdef WITH_MHASH - , _("CRC32"), _("HAVAL"), _("GOST"), _("CRC32B"), _("WHIRLPOOL") - #endif -@@ -269,12 +269,19 @@ static int xattrs2array(xattrs_type* xat - if ((len == xattrs->ents[num - 1].vsz) || ((len == (xattrs->ents[num - 1].vsz - 1)) && !val[len])) { - length = 8 + width + strlen(xattrs->ents[num - 1].key) + strlen(val); - (*values)[num]=malloc(length *sizeof(char)); -- snprintf((*values)[num], length , "[%.*zd] %s = %s", width, num, xattrs->ents[num - 1].key, val); -+ -+ char * fmt = "[%.*zd] %s = %s"; -+ if (conf->syslog_format) fmt = "[%.*zd]%s=%s"; // its smaller so it has to be enough space allocated. -+ snprintf((*values)[num], length , fmt, width, num, xattrs->ents[num - 1].key, val); -+ - } else { - val = encode_base64(xattrs->ents[num - 1].val, xattrs->ents[num - 1].vsz); - length = 10 + width + strlen(xattrs->ents[num - 1].key) + strlen(val); - (*values)[num]=malloc( length *sizeof(char)); -- snprintf((*values)[num], length , "[%.*zd] %s <=> %s", width, num, xattrs->ents[num - 1].key, val); -+ -+ char * fmt = "[%.*zd] %s <=> %s"; -+ if (conf->syslog_format) fmt = "[%.*zd]%s<=>%s"; // its smaller so it has to be enough space allocated. -+ snprintf((*values)[num], length , fmt, width, num, xattrs->ents[num - 1].key, val); - free(val); - } - } -@@ -302,6 +309,26 @@ static int acl2array(acl_type* acl, char - } - if (acl->acl_a || acl->acl_d) { - int j, k, i; -+ if (conf->syslog_format) { -+ *values = malloc(2 * sizeof(char*)); -+ -+ char *A, *D = ""; -+ -+ if (acl->acl_a) { A = acl->acl_a; } -+ if (acl->acl_d) { D = acl->acl_d; } -+ -+ (*values)[0] = (char*) malloc(strlen(A) + 3); // "A:" and \0 -+ snprintf((*values)[0], strlen(A) + 3, "A:%s", A); -+ -+ (*values)[1] = (char*) malloc(strlen(D) + 3); // "D:" and \0 -+ snprintf((*values)[1], strlen(D) + 3, "D:%s", D); -+ -+ i = 0; while ( (*values)[0][i] ) { if ( (*values)[0][i]=='\n') { (*values)[0][i] = ' '; } i++; } -+ i = 0; while ( (*values)[1][i] ) { if ( (*values)[1][i]=='\n') { (*values)[1][i] = ' '; } i++; } -+ -+ return 2; -+ } -+ - if (acl->acl_a) { i = 0; while (acl->acl_a[i]) { if (acl->acl_a[i++]=='\n') { n++; } } } - if (acl->acl_d) { i = 0; while (acl->acl_d[i]) { if (acl->acl_d[i++]=='\n') { n++; } } } - *values = malloc(n * sizeof(char*)); -@@ -338,25 +365,25 @@ static char* e2fsattrs2string(unsigned l - - static char* get_file_type_string(mode_t mode) { - switch (mode & S_IFMT) { -- case S_IFREG: return _("File"); -- case S_IFDIR: return _("Directory"); -+ case S_IFREG: return conf->syslog_format ? "file" : _("File"); -+ case S_IFDIR: return conf->syslog_format ? "dir" : _("Directory"); - #ifdef S_IFIFO -- case S_IFIFO: return _("FIFO"); -+ case S_IFIFO: return conf->syslog_format ? "fifo" : _("FIFO"); - #endif -- case S_IFLNK: return _("Link"); -- case S_IFBLK: return _("Block device"); -- case S_IFCHR: return _("Character device"); -+ case S_IFLNK: return conf->syslog_format ? "link" : _("Link"); -+ case S_IFBLK: return conf->syslog_format ? "blockd" : _("Block device"); -+ case S_IFCHR: return conf->syslog_format ? "chard" : _("Character device"); - #ifdef S_IFSOCK -- case S_IFSOCK: return _("Socket"); -+ case S_IFSOCK: return conf->syslog_format ? "socket" : _("Socket"); - #endif - #ifdef S_IFDOOR -- case S_IFDOOR: return _("Door"); -+ case S_IFDOOR: return conf->syslog_format ? "door" : _("Door"); - #endif - #ifdef S_IFPORT -- case S_IFPORT: return _("Port"); -+ case S_IFPORT: return conf->syslog_format ? "port" : _("Port"); - #endif - case 0: return NULL; -- default: return _("Unknown file type"); -+ default: return conf->syslog_format ? "unknown" : _("Unknown file type"); - } - } - -@@ -554,6 +581,51 @@ static void print_dbline_attributes(db_l - } - } - -+ -+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); -+ 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]); -+ } -+ -+ error(0, ";%s_new=|", details_string[j]); -+ -+ for (i = 0 ; i < nnumber ; i++) { -+ error(0, "%s|", nvalue[i]); -+ } -+ -+ } else { -+ -+ error(0, ";%s_old=%s;%s_new=%s", details_string[j], *ovalue, details_string[j], *nvalue); -+ -+ } -+ -+ 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); - } -@@ -562,6 +634,26 @@ static void print_attributes_removed_nod - 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); -+ -+} -+ -+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); -+ -+} -+ - static void terse_report(seltree* node) { - list* r=NULL; - if ((node->checked&(DB_OLD|DB_NEW)) != 0) { -@@ -626,6 +718,26 @@ static void print_report_details(seltree - } - } - -+static void print_syslog_format(seltree* node) { -+ list* r=NULL; -+ -+ if (node->checked&NODE_CHANGED) { -+ print_dbline_attributes_syslog(node->old_data, node->new_data, node->changed_attrs, forced_attrs); -+ } -+ -+ if (node->checked&NODE_ADDED) { -+ print_attributes_added_node_syslog(node->new_data); -+ } -+ -+ if (node->checked&NODE_REMOVED) { -+ print_attributes_removed_node_syslog(node->old_data); -+ } -+ -+ for(r=node->childs;r;r=r->next){ -+ print_syslog_format((seltree*)r->data); -+ } -+} -+ - static void print_report_header() { - char *time; - int first = 1; -@@ -747,39 +859,53 @@ int gen_report(seltree* node) { - send_audit_report(); - #endif - if ((nadd|nrem|nchg) > 0 || conf->report_quiet == 0) { -- print_report_header(); -- if(conf->action&(DO_COMPARE|DO_DIFF) || (conf->action&DO_INIT && conf->report_detailed_init) ) { -- if (conf->grouped) { -- if (nadd) { -- error(2,(char*)report_top_format,_("Added entries")); -- print_report_list(node, NODE_ADDED); -- } -- if (nrem) { -- error(2,(char*)report_top_format,_("Removed entries")); -- print_report_list(node, NODE_REMOVED); -- } -- if (nchg) { -- error(2,(char*)report_top_format,_("Changed entries")); -- print_report_list(node, NODE_CHANGED); -- } -- } else if (nadd || nrem || nchg) { -- if (nadd && nrem && nchg) { error(2,(char*)report_top_format,_("Added, removed and changed entries")); } -- else if (nadd && nrem) { error(2,(char*)report_top_format,_("Added and removed entries")); } -- else if (nadd && nchg) { error(2,(char*)report_top_format,_("Added and changed entries")); } -- else if (nrem && nchg) { error(2,(char*)report_top_format,_("Removed and changed entries")); } -- else if (nadd) { error(2,(char*)report_top_format,_("Added entries")); } -- else if (nrem) { error(2,(char*)report_top_format,_("Removed entries")); } -- else if (nchg) { error(2,(char*)report_top_format,_("Changed entries")); } -- print_report_list(node, NODE_ADDED|NODE_REMOVED|NODE_CHANGED); -- } -- if (nadd || nrem || nchg) { -- error(nchg?5:7,(char*)report_top_format,_("Detailed information about changes")); -- print_report_details(node); -- } -- } -- print_report_databases(); -- conf->end_time=time(&(conf->end_time)); -- print_report_footer(); -+ -+ if (!conf->syslog_format) { -+ print_report_header(); -+ } -+ -+ if(conf->action&(DO_COMPARE|DO_DIFF) || (conf->action&DO_INIT && conf->report_detailed_init) ) { -+ if (!conf->syslog_format && conf->grouped) { -+ if (nadd) { -+ error(2,(char*)report_top_format,_("Added entries")); -+ print_report_list(node, NODE_ADDED); -+ } -+ if (nrem) { -+ error(2,(char*)report_top_format,_("Removed entries")); -+ print_report_list(node, NODE_REMOVED); -+ } -+ if (nchg) { -+ error(2,(char*)report_top_format,_("Changed entries")); -+ print_report_list(node, NODE_CHANGED); -+ } -+ } else if (!conf->syslog_format && ( nadd || nrem || nchg ) ) { -+ if (nadd && nrem && nchg) { error(2,(char*)report_top_format,_("Added, removed and changed entries")); } -+ else if (nadd && nrem) { error(2,(char*)report_top_format,_("Added and removed entries")); } -+ else if (nadd && nchg) { error(2,(char*)report_top_format,_("Added and changed entries")); } -+ else if (nrem && nchg) { error(2,(char*)report_top_format,_("Removed and changed entries")); } -+ else if (nadd) { error(2,(char*)report_top_format,_("Added entries")); } -+ else if (nrem) { error(2,(char*)report_top_format,_("Removed entries")); } -+ else if (nchg) { error(2,(char*)report_top_format,_("Changed entries")); } -+ print_report_list(node, NODE_ADDED|NODE_REMOVED|NODE_CHANGED); -+ } -+ if (nadd || nrem || nchg) { -+ if (!conf->syslog_format) { -+ error(nchg?5:7,(char*)report_top_format,_("Detailed information about changes")); -+ print_report_details(node); -+ } else { -+ /* Syslog Format */ -+ error(0, "AIDE found differences between database and filesystem!!\n"); -+ error(0, "summary;total_number_of_files=%ld;added_files=%ld;" -+ "removed_files=%ld;changed_files=%ld\n",ntotal,nadd,nrem,nchg); -+ print_syslog_format(node); -+ } -+ } -+ } -+ if (!conf->syslog_format) { -+ print_report_databases(); -+ conf->end_time=time(&(conf->end_time)); -+ print_report_footer(); -+ } - } - - return conf->action&(DO_COMPARE|DO_DIFF) ? (nadd!=0)*1+(nrem!=0)*2+(nchg!=0)*4 : 0; -diff -up ./src/conf_lex.l.syslog_format ./src/conf_lex.l ---- ./src/conf_lex.l.syslog_format 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/conf_lex.l 2018-09-27 19:09:09.698371220 +0200 -@@ -401,6 +401,12 @@ int var_in_conflval=0; - return (TROOT_PREFIX); - } - -+^[\t\ ]*"syslog_format"{E} { -+ error(230,"%li:syslog_format =\n",conf_lineno); -+ BEGIN CONFVALHUNT; -+ return (SYSLOG_FORMAT); -+} -+ - ^[\t\ ]*"recstop"{E} { - error(230,"%li:recstop =\n",conf_lineno); - BEGIN CONFVALHUNT; -diff -up ./src/conf_yacc.y.syslog_format ./src/conf_yacc.y ---- ./src/conf_yacc.y.syslog_format 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/conf_yacc.y 2018-09-27 19:09:09.699371228 +0200 -@@ -89,6 +89,7 @@ extern long conf_lineno; - %token TREPORT_URL - %token TGZIPDBOUT - %token TROOT_PREFIX -+%token SYSLOG_FORMAT - %token TUMASK - %token TTRUE - %token TFALSE -@@ -160,7 +161,7 @@ line : rule | equrule | negrule | define - | ifdefstmt | ifndefstmt | ifhoststmt | ifnhoststmt - | groupdef | db_in | db_out | db_new | db_attrs | verbose | report_detailed_init | config_version - | database_add_metadata | report | gzipdbout | root_prefix | report_base16 | report_quiet -- | report_ignore_e2fsattrs | recursion_stopper | warn_dead_symlinks | grouped -+ | report_ignore_e2fsattrs | syslogformat | recursion_stopper | warn_dead_symlinks | grouped - | summarize_changes | acl_no_symlink_follow | beginconfigstmt | endconfigstmt - | TEOF { - newlinelastinconfig=1; -@@ -408,6 +409,15 @@ conf->gzip_dbout=0; - #endif - } ; - -+syslogformat : SYSLOG_FORMAT TTRUE { -+conf->syslog_format=1; -+} | -+ SYSLOG_FORMAT TFALSE { -+conf->syslog_format=0; -+} ; -+ -+ -+ - recursion_stopper : TRECSTOP TSTRING { - /* FIXME implement me */ - -diff -up ./src/error.c.syslog_format ./src/error.c ---- ./src/error.c.syslog_format 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/error.c 2018-09-27 19:13:40.312416750 +0200 -@@ -38,6 +38,9 @@ - /*for locale support*/ - #include "util.h" - -+#define MAX_BUFFER_SIZE 1024 -+static char syslog_buffer[MAX_BUFFER_SIZE+1]; -+ - int cmp_url(url_t* url1,url_t* url2){ - - return ((url1->type==url2->type)&&(strcmp(url1->value,url2->value)==0)); -@@ -48,7 +51,9 @@ int error_init(url_t* url,int initial) - { - list* r=NULL; - FILE* fh=NULL; -- int sfac; -+ int sfac; -+ -+ memset(syslog_buffer, 0, MAX_BUFFER_SIZE+1); - - if (url->type==url_database) { - conf->report_db++; -@@ -163,13 +168,24 @@ void error(int errorlevel,char* error_ms - } - #ifdef HAVE_SYSLOG - if(conf->initial_report_url->type==url_syslog){ --#ifdef HAVE_VSYSLOG -- vsyslog(SYSLOG_PRIORITY,error_msg,ap); --#else -- char buf[1024]; -- vsnprintf(buf,1024,error_msg,ap); -- syslog(SYSLOG_PRIORITY,"%s",buf); --#endif -+ -+ char buff[MAX_BUFFER_SIZE+1]; -+ vsnprintf(buff,MAX_BUFFER_SIZE,error_msg,ap); -+ size_t buff_len = strlen(buff); -+ -+ char result_buff[MAX_BUFFER_SIZE+1]; -+#pragma GCC diagnostic push -+#pragma GCC diagnostic ignored "-Wformat-truncation" -+ snprintf(result_buff, MAX_BUFFER_SIZE, "%s%s", syslog_buffer, buff); -+#pragma GCC diagnostic pop -+ -+ if(buff[buff_len-1] == '\n'){ -+ syslog(SYSLOG_PRIORITY,"%s",result_buff); -+ memset(syslog_buffer, 0, MAX_BUFFER_SIZE+1); -+ } else { -+ memcpy(syslog_buffer, result_buff, MAX_BUFFER_SIZE); -+ } -+ - va_end(ap); - return; - } -@@ -181,17 +197,25 @@ void error(int errorlevel,char* error_ms - - #ifdef HAVE_SYSLOG - if (conf->report_syslog!=0) { --#ifdef HAVE_VSYSLOG -- va_start(ap,error_msg); -- vsyslog(SYSLOG_PRIORITY,error_msg,ap); -- va_end(ap); --#else -- char buf[1024]; -- va_start(ap,error_msg); -- vsnprintf(buf,1024,error_msg,ap); -+ va_start(ap, error_msg); -+ -+ char buff[MAX_BUFFER_SIZE+1]; -+ vsnprintf(buff,MAX_BUFFER_SIZE,error_msg,ap); -+ size_t buff_len = strlen(buff); -+ -+ char result_buff[MAX_BUFFER_SIZE+1]; -+#pragma GCC diagnostic push -+#pragma GCC diagnostic ignored "-Wformat-truncation" -+ snprintf(result_buff, MAX_BUFFER_SIZE, "%s%s", syslog_buffer, buff); -+#pragma GCC diagnostic pop -+ -+ if(buff[buff_len-1] == '\n'){ -+ syslog(SYSLOG_PRIORITY,"%s",result_buff); -+ memset(syslog_buffer, 0, MAX_BUFFER_SIZE+1); -+ } else { -+ memcpy(syslog_buffer, result_buff, MAX_BUFFER_SIZE); -+ } - va_end(ap); -- syslog(SYSLOG_PRIORITY,"%s",buf); --#endif - } - #endif - diff --git a/SOURCES/aide-0.16-CVE-2021-45417.patch b/SOURCES/aide-0.16-CVE-2021-45417.patch deleted file mode 100644 index 1752df3..0000000 --- a/SOURCES/aide-0.16-CVE-2021-45417.patch +++ /dev/null @@ -1,123 +0,0 @@ -diff --git a/include/base64.h b/include/base64.h -index 0ff7116..381ef5d 100644 ---- a/include/base64.h -+++ b/include/base64.h -@@ -36,7 +36,6 @@ - #include - #include "types.h" - --#define B64_BUF 16384 - #define FAIL -1 - #define SKIP -2 - -diff --git a/src/base64.c b/src/base64.c -index fd01bac..1b0f301 100644 ---- a/src/base64.c -+++ b/src/base64.c -@@ -85,11 +85,9 @@ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL - }; - - /* Returns NULL on error */ --/* FIXME Possible buffer overflow on outputs larger than B64_BUF */ - char* encode_base64(byte* src,size_t ssize) - { - char* outbuf; -- char* retbuf; - int pos; - int i, l, left; - unsigned long triple; -@@ -101,7 +99,10 @@ char* encode_base64(byte* src,size_t ssize) - error(240,"\n"); - return NULL; - } -- outbuf = (char *)malloc(sizeof(char)*B64_BUF); -+ -+ /* length of encoded base64 string (padded) */ -+ size_t length = sizeof(char)* ((ssize + 2) / 3) * 4; -+ outbuf = (char *)malloc(length + 1); - - /* Initialize working pointers */ - inb = src; -@@ -162,20 +163,14 @@ char* encode_base64(byte* src,size_t ssize) - inb++; - } - -- /* outbuf is not completely used so we use retbuf */ -- retbuf=(char*)malloc(sizeof(char)*(pos+1)); -- memcpy(retbuf,outbuf,pos); -- retbuf[pos]='\0'; -- free(outbuf); -+ outbuf[pos]='\0'; - -- return retbuf; -+ return outbuf; - } - --/* FIXME Possible buffer overflow on outputs larger than B64_BUF */ - byte* decode_base64(char* src,size_t ssize, size_t *ret_len) - { - byte* outbuf; -- byte* retbuf; - char* inb; - int i; - int l; -@@ -188,10 +183,18 @@ byte* decode_base64(char* src,size_t ssize, size_t *ret_len) - if (!ssize||src==NULL) - return NULL; - -+ /* exit on unpadded input */ -+ if (ssize % 4) { -+ error(3, "decode_base64: '%s' has invalid length (missing padding characters?)", src); -+ return NULL; -+ } -+ -+ /* calculate length of decoded string, substract padding chars if any (ssize is >= 4) */ -+ size_t length = sizeof(byte) * ((ssize / 4) * 3)- (src[ssize-1] == '=') - (src[ssize-2] == '='); - - /* Initialize working pointers */ - inb = src; -- outbuf = (byte *)malloc(sizeof(byte)*B64_BUF); -+ outbuf = (byte *)malloc(length + 1); - - l = 0; - triple = 0; -@@ -243,15 +246,11 @@ byte* decode_base64(char* src,size_t ssize, size_t *ret_len) - inb++; - } - -- retbuf=(byte*)malloc(sizeof(byte)*(pos+1)); -- memcpy(retbuf,outbuf,pos); -- retbuf[pos]='\0'; -- -- free(outbuf); -+ outbuf[pos]='\0'; - - if (ret_len) *ret_len = pos; - -- return retbuf; -+ return outbuf; - } - - size_t length_base64(char* src,size_t ssize) -diff --git a/src/db.c b/src/db.c -index 858240d..62c4faa 100644 ---- a/src/db.c -+++ b/src/db.c -@@ -664,13 +664,15 @@ db_line* db_char2line(char** ss,int db){ - - time_t base64totime_t(char* s){ - -+ if(strcmp(s,"0")==0){ -+ return 0; -+ } - byte* b=decode_base64(s,strlen(s),NULL); - char* endp; - -- if (b==NULL||strcmp(s,"0")==0) { -+ if (b==NULL) { - - /* Should we print error here? */ -- free(b); - - return 0; - } else { diff --git a/SOURCES/aide-0.16-CVE-2025-54389.patch b/SOURCES/aide-0.16-CVE-2025-54389.patch deleted file mode 100644 index 7263d0e..0000000 --- a/SOURCES/aide-0.16-CVE-2025-54389.patch +++ /dev/null @@ -1,1662 +0,0 @@ -diff --git a/ChangeLog b/ChangeLog -index 263c438f4a2a38edc45f91c0d5a216112a8fa38c..5d286a8e07d0b3235f97272223175a1dd85848b2 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,27 +1,30 @@ -+2025-08-07 Hannes von Haugwitz -+ * Escape control characters in report and log output (CVE-2025-54389) -+ - 2016-07-25 Hannes von Haugwitz -- * Release version 0.16 -+ * Release version 0.16 - - 2016-07-11 Hannes von Haugwitz - * Fix example aide.conf (xattr -> xattrs) - * aide.conf.5: update "SELECTION LINES" section - * Released version 0.16rc1 - - 2016-07-10 Hannes von Haugwitz - * 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 - * Adapt manual to version 0.16 - - 2016-06-08 Hannes von Haugwitz - * Add missing break statements - - 2016-04-15 Hannes von Haugwitz - * Released version 0.16b1 - - 2016-04-13 Hannes von Haugwitz - * 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 | 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 - #include - #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= 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_disk.c b/src/db_disk.c -index 6161af38010633cbc2c4519a76e997c992439562..11f0d1c348a097a4175640e0f554979f7c74f7c1 100644 ---- a/src/db_disk.c -+++ b/src/db_disk.c -@@ -117,181 +117,197 @@ static char *name_construct (const char *s) - { - char *ret; - int len2 = strlen (r->path); - int len = len2 + strlen (s) + 2 + conf->root_prefix_length; - - if (r->path[len2 - 1] != '/') { - len++; - } - - ret = (char *) malloc (len); - ret[0] = (char) 0; - strcpy(ret, conf->root_prefix); - strcat (ret, r->path); - if (r->path[len2 - 1] != '/') { - strcat (ret, "/"); - } - strcat (ret, s); - return ret; - } - - void add_child (db_line * fil) - { - int i; - struct seltree *new_r; - -- error (255, "Adding child %s\n", fil->filename); -+ { -+ char *fname_safe = stresc(fil->filename); -+ error (255, "Adding child %s\n", fname_safe); -+ free(fname_safe); -+ } - - new_r = get_seltree_node (r, fil->filename); - if (new_r != NULL) { - if (S_ISDIR (fil->perm_o)) { - ; - } else { - new_r->checked |= NODE_CHECKED; - new_r->checked |= NODE_TRAVERSE; - } - return; - } - - new_r = malloc (sizeof (seltree)); - - new_r->attr = 0; - i = strlen (fil->filename); - - new_r->path = malloc (i + 1); - strncpy(new_r->path, fil->filename, i+1); - new_r->childs = NULL; - new_r->sel_rx_lst = NULL; - new_r->neg_rx_lst = NULL; - new_r->equ_rx_lst = NULL; - new_r->parent = r; - new_r->checked = 0; - new_r->new_data = NULL; - new_r->old_data = NULL; - if (S_ISDIR (fil->perm_o)) { - ; - } else { - new_r->checked |= NODE_CHECKED; - new_r->checked |= NODE_TRAVERSE; - } - r->childs = list_sorted_insert (r->childs, new_r, compare_node_by_path); - } - - static int get_file_status(char *filename, struct AIDE_STAT_TYPE *fs) { - int sres = 0; - sres = AIDE_LSTAT_FUNC(filename,fs); - if(sres == -1){ - char* er = strerror(errno); - if (er == NULL) { -- error(0,"get_file_status: lstat() failed for %s. strerror() failed for %i\n", filename, errno); -+ char *filename_safe = stresc(filename); -+ error(0,"get_file_status: lstat() failed for %s. strerror() failed for %i\n", filename_safe, errno); -+ free(filename_safe); - } else { -- error(0,"get_file_status: lstat() failed for %s: %s\n", filename, er); -+ char *filename_safe = stresc(filename); -+ error(0,"get_file_status: lstat() failed for %s: %s\n", filename_safe, er); -+ free(filename_safe); - } - } - return sres; - } - - /* - It might be a good idea to make this non recursive. - Now implemented with goto-statement. Yeah, it's ugly and easy. - */ - - db_line *db_readline_disk () - { - db_line *fil = NULL; - DB_ATTR_TYPE attr; - char *fullname; - int add = 0; - struct AIDE_STAT_TYPE fs; - - /* root needs special handling */ - if (!root_handled) { - root_handled = 1; - fullname=malloc((conf->root_prefix_length+2)*sizeof(char)); - strcpy(fullname, conf->root_prefix); - strcat (fullname, "/"); - if (!get_file_status(fullname, &fs)) { - add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode); - error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add, - conf->tree, attr); - - if (add > 0) { - fil = get_file_attrs (fullname, attr, &fs); - - error (240, "%s attr=%llu\n", &fullname[conf->root_prefix_length], attr); - - if (fil != NULL) { -- error (240, "%s attr=%llu\n", fil->filename, fil->attr); -+ { -+ char *fname_safe = stresc(fil->filename); -+ error (240, "%s attr=%llu\n", fname_safe, fil->attr); -+ free(fname_safe); -+ } - return fil; - } - } - } - free (fullname); - } - recursion: - next_in_dir (); - - if (in_this ()) { - - /* - Let's check if we have '.' or '..' entry. - If have, just skipit. - If don't do the 'normal' thing. - */ - if (strcmp (entp->d_name, ".") == 0 || strcmp (entp->d_name, "..") == 0) { - goto recursion; // return db_readline_disk(db); - } - - /* - Now we know that we actually can do something. - */ - - fullname = name_construct (entp->d_name); - - /* - Now we have a filename, which we must remember to free if it is - not used. - - Next thing is to see if we want to do something with it. - If not call, db_readline_disk again... - */ - - if (get_file_status(fullname, &fs)) { - free (fullname); - goto recursion; - } - add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode); - error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add, - conf->tree, attr); - - if (add > 0) { - fil = get_file_attrs (fullname, attr, &fs); - - error (240, "%s attr=%llu\n", &fullname[conf->root_prefix_length], attr); - - if (fil != NULL) { -- error (240, "%s attr=%llu\n", fil->filename, fil->attr); -+ { -+ char *fname_safe = stresc(fil->filename); -+ error (240, "%s attr=%llu\n", fname_safe, fil->attr); -+ free(fname_safe); -+ } - } else { - /* - Something went wrong during read process -> - Let's try next one. - */ - free (fullname); - goto recursion; // return db_readline_disk(db); - } - - if (add == 1) { - /* - add_children -> if dir, then add to children list. - */ - /* If ee are adding a file that is not a dir */ - /* add_child can make the determination and mark the tree - accordingly - */ - add_child (fil); - } else if (add == 2) { - /* - Don't add to children list. - */ - - /* - Should we do something? -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 - #include - #include - #include - #include - #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 - #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 - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #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 - #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_sizefullpath,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 - -diff --git a/src/gen_list.c b/src/gen_list.c -index ab257811485831b1db1b027a94b5c0447a92f923..5b4a93eef28e1930a52e8156df661ca999035f54 100644 ---- a/src/gen_list.c -+++ b/src/gen_list.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" - - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include "report.h" - #include "list.h" - #include "gen_list.h" - #include "seltree.h" - #include "db.h" -+#include "util.h" - #include "db_config.h" - #include "commandconf.h" - #include "report.h" - /*for locale support*/ - #include "locale-aide.h" - /*for locale support*/ - - #define CLOCK_SKEW 5 - - #ifdef WITH_MHASH - #include - #endif - #include "md.h" - #include "do_md.h" - - void hsymlnk(db_line* line); - void fs2db_line(struct AIDE_STAT_TYPE* fs,db_line* line); - void calc_md(struct AIDE_STAT_TYPE* old_fs,db_line* line); - void no_hash(db_line* line); - - static DB_ATTR_TYPE get_special_report_group(char* group) { - DB_ATTR_TYPE attr = get_groupval(group); - return attr==DB_ATTR_UNDEF?0:attr; - } - -@@ -971,103 +972,127 @@ static void add_file_to_tree(seltree* tree,db_line* file,int db, - } - } - - int check_rxtree(char* filename,seltree* tree,DB_ATTR_TYPE* attr, mode_t perm) - { - int retval=0; - char * tmp=NULL; - char * parentname=NULL; - seltree* pnode=NULL; - - parentname=strdup(filename); - tmp=strrchr(parentname,'/'); - if(tmp!=parentname){ - *tmp='\0'; - }else { - - if(parentname[1]!='\0'){ - /* we are in the root dir */ - parentname[1]='\0'; - } - } - - if(conf->limit!=NULL) { - retval=pcre_exec(conf->limit_crx, NULL, filename, strlen(filename), 0, PCRE_PARTIAL_SOFT, NULL, 0); - if (retval >= 0) { -- error(220, "check_rxtree: %s does match limit: %s\n", filename, conf->limit); -+ char *fname_safe = stresc(filename); -+ char *limit_safe = conf->limit?stresc(conf->limit):NULL; -+ error(220, "check_rxtree: %s does match limit: %s\n", fname_safe, limit_safe?limit_safe:""); -+ free(fname_safe); -+ free(limit_safe); - } else if (retval == PCRE_ERROR_PARTIAL) { -- error(220, "check_rxtree: %s does PARTIAL match limit: %s\n", filename, conf->limit); -+ char *fname_safe = stresc(filename); -+ char *limit_safe = conf->limit?stresc(conf->limit):NULL; -+ error(220, "check_rxtree: %s does PARTIAL match limit: %s\n", fname_safe, limit_safe?limit_safe:""); - if(S_ISDIR(perm) && get_seltree_node(tree,filename)==NULL){ -- error(220, "check_rxtree: creating new seltree node for '%s'\n", filename); -+ error(220, "check_rxtree: creating new seltree node for '%s'\n", fname_safe); - new_seltree_node(tree,filename,0,NULL); - } -+ free(fname_safe); -+ free(limit_safe); - return -1; - } else { -- error(220, "check_rxtree: %s does NOT match limit: %s\n", filename, conf->limit); -+ char *fname_safe = stresc(filename); -+ char *limit_safe = conf->limit?stresc(conf->limit):NULL; -+ error(220, "check_rxtree: %s does NOT match limit: %s\n", fname_safe, limit_safe?limit_safe:""); -+ free(fname_safe); -+ free(limit_safe); - return -2; - } - } - - pnode=get_seltree_node(tree,parentname); - - *attr=0; - retval=check_node_for_match(pnode,filename, perm, 0,attr); - - free(parentname); - - return retval; - } - - db_line* get_file_attrs(char* filename,DB_ATTR_TYPE attr, struct AIDE_STAT_TYPE *fs) - { - db_line* line=NULL; - time_t cur_time; - - if(!(attr&DB_RDEV)) - fs->st_rdev=0; - /* - Get current time for future time notification. - */ - cur_time=time(NULL); - - if (cur_time==(time_t)-1) { - char* er=strerror(errno); - if (er==NULL) { - error(0,_("Can not get current time. strerror failed for %i\n"),errno); - } else { - error(0,_("Can not get current time with reason %s\n"),er); - } - } else { - - if(fs->st_atime>cur_time){ -- error(CLOCK_SKEW,_("%s atime in future\n"),filename); -+ { -+ char *fname_safe = stresc(filename); -+ error(CLOCK_SKEW,_("%s atime in future\n"),fname_safe); -+ free(fname_safe); -+ } - } - if(fs->st_mtime>cur_time){ -- error(CLOCK_SKEW,_("%s mtime in future\n"),filename); -+ { -+ char *fname_safe = stresc(filename); -+ error(CLOCK_SKEW,_("%s mtime in future\n"),fname_safe); -+ free(fname_safe); -+ } - } - if(fs->st_ctime>cur_time){ -- error(CLOCK_SKEW,_("%s ctime in future\n"),filename); -+ { -+ char *fname_safe = stresc(filename); -+ error(CLOCK_SKEW,_("%s ctime in future\n"),fname_safe); -+ free(fname_safe); -+ } - } - } - - /* - Malloc if we have something to store.. - */ - - line=(db_line*)malloc(sizeof(db_line)); - - memset(line,0,sizeof(db_line)); - - /* - We want filename - */ - - line->attr=attr|DB_FILENAME; - - /* - Just copy some needed fields. - */ - - line->fullpath=filename; - line->filename=&filename[conf->root_prefix_length]; - line->perm_o=fs->st_mode; - line->size_o=fs->st_size; -@@ -1198,51 +1223,55 @@ void populate_tree(seltree* tree) - initdbwarningprinted=1; - } - } - } - } - if(conf->action&DO_INIT) { - write_tree(tree); - } - } - - void hsymlnk(db_line* line) { - - if((S_ISLNK(line->perm_o))){ - int len=0; - #ifdef WITH_ACL - if(conf->no_acl_on_symlinks!=1) { - line->attr&=(~DB_ACL); - } - #endif - - if(conf->warn_dead_symlinks==1) { - struct AIDE_STAT_TYPE fs; - int sres; - sres=AIDE_STAT_FUNC(line->fullpath,&fs); - if (sres!=0 && sres!=EACCES) { -- error(4,"Dead symlink detected at %s\n",line->fullpath); -+ { -+ char *fp_safe = stresc(line->fullpath); -+ error(4,"Dead symlink detected at %s\n",fp_safe); -+ free(fp_safe); -+ } - } - if(!(line->attr&DB_RDEV)) - fs.st_rdev=0; - } - /* - Is this valid?? - No, We should do this elsewhere. - */ - line->linkname=(char*)malloc(_POSIX_PATH_MAX+1); - if(line->linkname==NULL){ - error(0,_("malloc failed in hsymlnk()\n")); - abort(); - } - - /* - Remember to nullify the buffer, because man page says - - readlink places the contents of the symbolic link path in - the buffer buf, which has size bufsiz. readlink does not - append a NUL character to buf. It will truncate the con- - tents (to a length of bufsiz characters), in case the - buffer is too small to hold all of the contents. - - */ - memset(line->linkname,0,_POSIX_PATH_MAX+1); -diff --git a/src/util.c b/src/util.c -index 21c75a2f176270f47f480c8143984e8a00ce8780..7e3da74a6acbf6e656b833591972be06fb1ae0f1 100644 ---- a/src/util.c -+++ b/src/util.c -@@ -82,101 +82,142 @@ url_t* parse_url(char* val) - - if(r[0]!='\0'){ - r[0]='\0'; - r++; - } - u->type=url_unknown; - for(i=0;itype=url_value[i]; - break; - } - } - - switch (u->type) { - case url_file : { - if(r[0]=='/'&&(r+1)[0]=='/'&&(r+2)[0]=='/'){ - u->value=strdup(r+2); - break; - } - if(r[0]=='/'&&(r+1)[0]=='/'&&(r+2)[0]!='/'){ - char*hostname=(char*)malloc(sizeof(char)*MAXHOSTNAMELEN); - char* t=r+2; - r+=2; - for(i=0;r[0]!='/'&&r[0]!='\0';r++,i++); - if(r[0]=='\0'){ -- error(0,"Invalid file-URL,no path after hostname: file:%s\n",t); -+ char *t_safe = stresc(t); -+ error(0,"Invalid file-URL,no path after hostname: file:%s\n",t_safe); -+ free(t_safe); - free(u); - free(val_copy); - free(hostname); -- return NULL; -+ return NULL; - } - u->value=strdup(r); - r[0]='\0'; - if(gethostname(hostname,MAXHOSTNAMELEN)==-1){ - strncpy(hostname,"localhost",MAXHOSTNAMELEN); - } - - if( (strcmp(t,"localhost")==0)||(strcmp(t,hostname)==0)){ - free(hostname); - break; - } else { -- error(0,"Invalid file-URL, cannot use hostname other than localhost or %s: file:%s\n",hostname,u->value); -+ char *value_safe = stresc(u->value); -+ error(0,"Invalid file-URL, cannot use hostname other than localhost or %s: file:%s\n",hostname,value_safe); -+ free(value_safe); - free(u->value); - free(u); - free(val_copy); -- free(hostname); -- return NULL; -+ free(hostname); -+ return NULL; - } - - break; - } - u->value=strdup(r); - - break; - } - case url_https : - case url_http : - case url_ftp : { - u->value=strdup(val); - break; - } - case url_unknown : { - error(0,"Unknown URL-type:%s\n",val_copy); - break; - } - default : { - u->value=strdup(r); - break; - } - } - - free(val_copy); - - return u; - } - -+static size_t escape_str(const char *unescaped_str, char *str, size_t s) { -+ size_t n = 0; -+ size_t i = 0; -+ char c; -+ while (i < s && (c = unescaped_str[i])) { -+ if ((c >= 0 && (c < 0x1f || c == 0x7f)) || -+ (c == '\\' && isdigit(unescaped_str[i+1]) -+ && isdigit(unescaped_str[i+2]) -+ && isdigit(unescaped_str[i+3]))) { -+ if (str) { snprintf(&str[n], 5, "\\%03o", c); } -+ n += 4; -+ } else { -+ if (str) { str[n] = c; } -+ n++; -+ } -+ i++; -+ } -+ if (str) { str[n] = '\0'; } -+ n++; -+ return n; -+} -+ -+char *strnesc(const char *unescaped_str, size_t s) { -+ int n = escape_str(unescaped_str, NULL, s); -+ char *str = malloc(n); -+ if (str == NULL) { -+ error(0, "malloc: failed to allocate %d bytes of memory\n", n); -+ exit(1); -+ } -+ escape_str(unescaped_str, str, s); -+ return str; -+} -+ -+char *stresc(const char *unescaped_str) { -+ return strnesc(unescaped_str, strlen(unescaped_str)); -+} -+ - /* Returns 1 if the string contains unsafe characters, 0 otherwise. */ - int contains_unsafe (const char *s) - { - for (; *s; s++) - if (strchr (URL_UNSAFE,(int) *s)||!ISPRINT((int)*s)) - return 1; - return 0; - } - - /* Decodes the forms %xy in a URL to the character the hexadecimal - code of which is xy. xy are hexadecimal digits from - [0123456789ABCDEF] (case-insensitive). If x or y are not - hex-digits or `%' precedes `\0', the sequence is inserted - literally. */ - - void decode_string (char* s) - { - char *p = s; - - for (; *s; s++, p++) - { - if (*s != '%') - *p = *s; - else - { - diff --git a/SOURCES/aide-0.16-Use-LDADD-for-adding-curl-library-to-the-linker-comm.patch b/SOURCES/aide-0.16-Use-LDADD-for-adding-curl-library-to-the-linker-comm.patch deleted file mode 100644 index 0c4fc17..0000000 --- a/SOURCES/aide-0.16-Use-LDADD-for-adding-curl-library-to-the-linker-comm.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c7caa6027c92b28aa11b8da74d56357e12f56d67 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20Kope=C4=8Dek?= -Date: Wed, 20 Feb 2019 12:00:56 +0100 -Subject: [PATCH] Use LDADD for adding curl library to the linker command - ---- - Makefile.am | 2 +- - configure.ac | 5 +++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 4b05d7a..1541d56 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -55,7 +55,7 @@ if USE_CURL - aide_SOURCES += include/fopen.h src/fopen.c - endif - --aide_LDADD = -lm @PCRELIB@ @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ @E2FSATTRSLIB@ @ELFLIB@ -+aide_LDADD = -lm @PCRELIB@ @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ @E2FSATTRSLIB@ @ELFLIB@ @CURLLIB@ - AM_CFLAGS = @AIDE_DEFS@ -W -Wall -g - AM_CPPFLAGS = -I$(top_srcdir) \ - -I$(top_srcdir)/include \ -diff --git a/configure.ac b/configure.ac -index 3598ebe..0418c59 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -702,24 +702,25 @@ if test x$with_zlib = xyes; then - compoptionstring="${compoptionstring}WITH_ZLIB\\n" - fi - -+CURLLIB= - if test x$with_curl = xyes; then - AC_PATH_PROG(curlconfig, "curl-config") - if test "_$curlconfig" != _ ; then - CURL_CFLAGS=`$curlconfig --cflags` -- CURL_LIBS=`$curlconfig --libs` -+ CURLLIB=`$curlconfig --libs` - else - AC_MSG_ERROR([You don't have curl properly installed. Install it or try --without-curl.]) - fi - AC_CHECK_HEADERS(curl/curl.h,, - [AC_MSG_ERROR([You don't have curl properly installed. Install it or try --without-curl.])]) - CFLAGS="$CFLAGS $CURL_CFLAGS" -- LDFLAGS="$LDFLAGS $CURL_LIBS" - AC_CHECK_LIB(curl,curl_easy_init,havecurl=yes, - [AC_MSG_ERROR([You don't have curl properly installed. Install it or try --without-curl.])] - ) - AC_DEFINE(WITH_CURL,1,[use curl]) - compoptionstring="${compoptionstring}WITH_CURL\\n" - fi -+AC_SUBST(CURLLIB) - AM_CONDITIONAL(USE_CURL, test x$havecurl = xyes) - - AC_ARG_WITH(mhash, --- -2.20.1 - diff --git a/SOURCES/aide-0.16-crash-elf.patch b/SOURCES/aide-0.16-crash-elf.patch deleted file mode 100644 index 5aa3472..0000000 --- a/SOURCES/aide-0.16-crash-elf.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- ./src/do_md.c 2018-03-19 05:10:19.994957024 -0400 -+++ ./src/do_md.c 2018-03-19 05:19:05.829957024 -0400 -@@ -135,8 +135,13 @@ - continue; - - while (!bingo && (data = elf_getdata (scn, data)) != NULL) { -- int maxndx = data->d_size / shdr.sh_entsize; -+ int maxndx; - int ndx; -+ -+ if (shdr.sh_entsize != 0) -+ maxndx = data->d_size / shdr.sh_entsize; -+ else -+ continue; - - for (ndx = 0; ndx < maxndx; ++ndx) { - (void) gelf_getdyn (data, ndx, &dyn); diff --git a/SOURCES/aide-0.16-crypto-disable-haval-and-others.patch b/SOURCES/aide-0.16-crypto-disable-haval-and-others.patch deleted file mode 100644 index a066fd9..0000000 --- a/SOURCES/aide-0.16-crypto-disable-haval-and-others.patch +++ /dev/null @@ -1,153 +0,0 @@ -diff -up ./include/md.h.crypto ./include/md.h ---- ./include/md.h.crypto 2016-07-25 22:56:55.000000000 +0200 -+++ ./include/md.h 2018-08-29 15:00:30.827491299 +0200 -@@ -149,6 +149,7 @@ int init_md(struct md_container*); - int update_md(struct md_container*,void*,ssize_t); - int close_md(struct md_container*); - void md2line(struct md_container*,struct db_line*); -+DB_ATTR_TYPE get_available_crypto(); - - - #endif /*_MD_H_INCLUDED*/ -diff -up ./src/aide.c.crypto ./src/aide.c ---- ./src/aide.c.crypto 2018-08-29 15:00:30.825491309 +0200 -+++ ./src/aide.c 2018-08-29 15:00:30.827491299 +0200 -@@ -349,7 +349,7 @@ static void setdefaults_before_config() - - conf->db_attrs = 0; - #if defined(WITH_MHASH) || defined(WITH_GCRYPT) -- conf->db_attrs |= DB_MD5|DB_TIGER|DB_HAVAL|DB_CRC32|DB_SHA1|DB_RMD160|DB_SHA256|DB_SHA512; -+ conf->db_attrs |= get_available_crypto(); - #ifdef WITH_MHASH - conf->db_attrs |= DB_GOST; - #ifdef HAVE_MHASH_WHIRLPOOL -diff -up ./src/md.c.crypto ./src/md.c ---- ./src/md.c.crypto 2018-08-29 15:00:30.823491319 +0200 -+++ ./src/md.c 2018-08-29 15:02:28.013903479 +0200 -@@ -78,6 +78,49 @@ DB_ATTR_TYPE hash_gcrypt2attr(int i) { - return r; - } - -+const char * hash_gcrypt2str(int i) { -+ char * r = "?"; -+#ifdef WITH_GCRYPT -+ switch (i) { -+ case GCRY_MD_MD5: { -+ r = "MD5"; -+ break; -+ } -+ case GCRY_MD_SHA1: { -+ r = "SHA1"; -+ break; -+ } -+ case GCRY_MD_RMD160: { -+ r = "RMD160"; -+ break; -+ } -+ case GCRY_MD_TIGER: { -+ r = "TIGER"; -+ break; -+ } -+ case GCRY_MD_HAVAL: { -+ r = "HAVAL"; -+ break; -+ } -+ case GCRY_MD_SHA256: { -+ r = "SHA256"; -+ break; -+ } -+ case GCRY_MD_SHA512: { -+ r = "SHA512"; -+ break; -+ } -+ case GCRY_MD_CRC32: { -+ r = "CRC32"; -+ break; -+ } -+ default: -+ break; -+ } -+#endif -+ return r; -+} -+ - DB_ATTR_TYPE hash_mhash2attr(int i) { - DB_ATTR_TYPE r=0; - #ifdef WITH_MHASH -@@ -163,6 +206,44 @@ DB_ATTR_TYPE hash_mhash2attr(int i) { - Initialise md_container according it's todo_attr field - */ - -+DB_ATTR_TYPE get_available_crypto() { -+ -+ DB_ATTR_TYPE ret = 0; -+ -+/* -+ * This function is usually called before config processing -+ * and default verbose level is 5 -+ */ -+#define lvl 255 -+ -+ error(lvl, "get_available_crypto called\n"); -+ -+#ifdef WITH_GCRYPT -+ -+ /* -+ * some initialization for FIPS -+ */ -+ gcry_check_version(NULL); -+ error(lvl, "Found algos:"); -+ -+ for(int i=0;i<=HASH_GCRYPT_COUNT;i++) { -+ -+ if ( (hash_gcrypt2attr(i) & HASH_USE_GCRYPT) == 0 ) -+ continue; -+ -+ if (gcry_md_algo_info(i, GCRYCTL_TEST_ALGO, NULL, NULL) == 0) { -+ ret |= hash_gcrypt2attr(i); -+ error(lvl, " %s", hash_gcrypt2str(i)); -+ } -+ } -+ error(lvl, "\n"); -+ -+#endif -+ -+ error(lvl, "get_available_crypto_returned with %lld\n", ret); -+ return ret; -+} -+ - int init_md(struct md_container* md) { - - int i; -@@ -201,18 +282,27 @@ int init_md(struct md_container* md) { - } - #endif - #ifdef WITH_GCRYPT -- if(gcry_md_open(&md->mdh,0,GCRY_MD_FLAG_SECURE)!=GPG_ERR_NO_ERROR){ -+ if(gcry_md_open(&md->mdh,0,GCRY_MD_FLAG_SECURE)!=GPG_ERR_NO_ERROR){ - error(0,"gcrypt_md_open failed\n"); - exit(IO_ERROR); - } - for(i=0;i<=HASH_GCRYPT_COUNT;i++) { -+ -+ - if (((hash_gcrypt2attr(i)&HASH_USE_GCRYPT)&md->todo_attr)!=0) { -- DB_ATTR_TYPE h=hash_gcrypt2attr(i); -- error(255,"inserting %llu\n",h); -+ -+ DB_ATTR_TYPE h=hash_gcrypt2attr(i); -+ -+ if (gcry_md_algo_info(i, GCRYCTL_TEST_ALGO, NULL, NULL) != 0) { -+ error(0,"Algo %s is not available\n", hash_gcrypt2str(i)); -+ exit(-1); -+ } -+ -+ error(255,"inserting %llu\n",h); - if(gcry_md_enable(md->mdh,i)==GPG_ERR_NO_ERROR){ - md->calc_attr|=h; - } else { -- error(0,"gcry_md_enable %i failed",i); -+ error(0,"gcry_md_enable %i failed\n",i); - md->todo_attr&=~h; - } - } diff --git a/SOURCES/aide-0.16b1-fipsfix.patch b/SOURCES/aide-0.16b1-fipsfix.patch deleted file mode 100644 index 434d74e..0000000 --- a/SOURCES/aide-0.16b1-fipsfix.patch +++ /dev/null @@ -1,103 +0,0 @@ -diff -up ./src/aide.c.orig ./aide-0.16b1/src/aide.c ---- ./src/aide.c.orig 2016-07-12 11:10:08.013158385 +0200 -+++ ./src/aide.c 2016-07-12 11:30:54.867833064 +0200 -@@ -511,9 +511,28 @@ int main(int argc,char**argv) - #endif - umask(0177); - init_sighandler(); -- - setdefaults_before_config(); - -+#if WITH_GCRYPT -+ error(255,"Gcrypt library initialization\n"); -+ /* -+ * Initialize libgcrypt as per -+ * http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html -+ * -+ * -+ */ -+ gcry_control(GCRYCTL_SET_ENFORCED_FIPS_FLAG, 0); -+ gcry_control(GCRYCTL_INIT_SECMEM, 1); -+ -+ if(!gcry_check_version(GCRYPT_VERSION)) { -+ error(0,"libgcrypt version mismatch\n"); -+ exit(VERSION_MISMATCH_ERROR); -+ } -+ -+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); -+#endif /* WITH_GCRYPT */ -+ -+ - if(read_param(argc,argv)==RETFAIL){ - error(0, _("Invalid argument\n") ); - exit(INVALID_ARGUMENT_ERROR); -@@ -646,6 +665,9 @@ int main(int argc,char**argv) - } - #endif - } -+#ifdef WITH_GCRYPT -+ gcry_control(GCRYCTL_TERM_SECMEM, 0); -+#endif /* WITH_GCRYPT */ - return RETOK; - } - const char* aide_key_3=CONFHMACKEY_03; -diff -up ./src/md.c.orig ./aide-0.16b1/src/md.c ---- ./src/md.c.orig 2016-04-15 23:30:16.000000000 +0200 -+++ ./src/md.c 2016-07-12 11:35:04.007675329 +0200 -@@ -201,14 +201,7 @@ int init_md(struct md_container* md) { - } - #endif - #ifdef WITH_GCRYPT -- error(255,"Gcrypt library initialization\n"); -- if(!gcry_check_version(GCRYPT_VERSION)) { -- error(0,"libgcrypt version mismatch\n"); -- exit(VERSION_MISMATCH_ERROR); -- } -- gcry_control(GCRYCTL_DISABLE_SECMEM, 0); -- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); -- if(gcry_md_open(&md->mdh,0,0)!=GPG_ERR_NO_ERROR){ -+ if(gcry_md_open(&md->mdh,0,GCRY_MD_FLAG_SECURE)!=GPG_ERR_NO_ERROR){ - error(0,"gcrypt_md_open failed\n"); - exit(IO_ERROR); - } -@@ -299,7 +292,7 @@ int close_md(struct md_container* md) { - - /*. There might be more hashes in the library. Add those here.. */ - -- gcry_md_reset(md->mdh); -+ gcry_md_close(md->mdh); - #endif - - #ifdef WITH_MHASH -diff -up ./src/util.c.orig ./aide-0.16b1/src/util.c ---- ./src/util.c.orig 2016-07-12 11:39:17.023437355 +0200 -+++ ./src/util.c 2016-07-12 11:39:51.618721157 +0200 -@@ -519,28 +519,5 @@ int syslog_facility_lookup(char *s) - return(AIDE_SYSLOG_FACILITY); - } - --/* We need these dummy stubs to fool the linker into believing that -- we do not need them at link time */ -- --void* dlopen(char*filename,int flag) --{ -- return NULL; --} -- --void* dlsym(void*handle,char*symbol) --{ -- return NULL; --} -- --void* dlclose(void*handle) --{ -- return NULL; --} -- --const char* dlerror(void) --{ -- return NULL; --} -- - const char* aide_key_2=CONFHMACKEY_02; - const char* db_key_2=DBHMACKEY_02; diff --git a/SOURCES/aide-0.16rc1-man.patch b/SOURCES/aide-0.16rc1-man.patch deleted file mode 100644 index 4715552..0000000 --- a/SOURCES/aide-0.16rc1-man.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -up ./doc/aide.1.in.orig ./doc/aide.1.in ---- ./doc/aide.1.in.orig 2016-07-12 16:10:01.724595895 +0200 -+++ ./doc/aide.1.in 2016-07-12 16:06:21.968639822 +0200 -@@ -103,9 +103,9 @@ echo | base64 \-d | h - .SH FILES - .IP \fB@sysconfdir@/aide.conf\fR - Default aide configuration file. --.IP \fB@sysconfdir@/aide.db\fR -+.IP \fB@localstatedir@/lib/aide/aide.db\fR - Default aide database. --.IP \fB@sysconfdir@/aide.db.new\fR -+.IP \fB@localstatedir@/lib/aide/aide.db.new\fR - Default aide output database. - .SH SEE ALSO - .BR aide.conf (5) diff --git a/SOURCES/aide-0.19.2-syslog-format.patch b/SOURCES/aide-0.19.2-syslog-format.patch new file mode 100644 index 0000000..53f4ca7 --- /dev/null +++ b/SOURCES/aide-0.19.2-syslog-format.patch @@ -0,0 +1,657 @@ +From f3e62eb87e0a0e9c6fd43c933670447c8ab0517a Mon Sep 17 00:00:00 2001 +From: Cropi +Date: Thu, 28 May 2026 14:50:34 +0200 +Subject: [PATCH] conf, report: add syslog_format config option + +Re-implement the syslog_format option that existed as a Red Hat downstream +patch against aide 0.16 but was dropped during the rebase to 0.19.2. + +Customers upgrading from RHEL 9.7 (aide 0.16) to RHEL 9.8 (aide 0.19.2) +received a fatal parse error on startup if their aide.conf contained +'syslog_format = true' (RHEL-178317). + +The option is implemented as a new REPORT_FORMAT_SYSLOG value in the +existing report format module system, rather than as a standalone boolean, +which fits the 0.19.2 architecture cleanly. + +syslog_format = yes/true is equivalent to report_format = syslog +Both spellings are accepted; last-write wins. + +When active, the standard multi-line report is replaced with a compact +semicolon-delimited format where every file event is one line: + + AIDE found differences between database and filesystem!! + summary;total_number_of_files=N;added_files=N;removed_files=N;changed_files=N + file=/usr/sbin/sshd;Mtime_old=...;Mtime_new=...;SHA256_old=...;SHA256_new=... + dir=/etc/cron.d; added + file=/usr/bin/old; removed + +Each line is emitted with a single report_printf() call so that when used +with report_url=syslog: exactly one syslog message is produced +per file event. + +The module implements its own unconditional tree walker (not gated on +report_level) so added and removed entries are always included, matching +the original patch behaviour. ACL and xattr values are formatted directly +from db_line fields rather than through get_attribute_values() to avoid +embedded newlines breaking the single-line invariant. The original patch's +uninitialized 'char *A' in the ACL path is fixed. + +Signed-off-by: Cropi +--- + Makefile.am | 1 + + doc/aide.conf.5 | 28 ++++ + include/conf_ast.h | 1 + + include/db_config.h | 1 + + include/report.h | 3 + + include/report_syslog.h | 28 ++++ + src/aide.c | 1 + + src/conf_ast.c | 1 + + src/conf_eval.c | 8 + + src/conf_lex.l | 7 + + src/report.c | 16 +- + src/report_syslog.c | 338 ++++++++++++++++++++++++++++++++++++++++ + 12 files changed, 432 insertions(+), 1 deletion(-) + create mode 100644 include/report_syslog.h + create mode 100644 src/report_syslog.c + +diff --git a/Makefile.am b/Makefile.am +index f78a96c..356b983 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -31,6 +31,7 @@ aide_SOURCES = src/aide.c include/aide.h \ + include/report.h src/report.c \ + include/report_plain.h src/report_plain.c \ + include/report_json.h src/report_json.c \ ++ include/report_syslog.h src/report_syslog.c \ + include/conf_ast.h src/conf_ast.c \ + include/conf_eval.h src/conf_eval.c \ + include/conf_lex.h src/conf_lex.l \ +diff --git a/doc/aide.conf.5 b/doc/aide.conf.5 +index 4ad9f3e..5366be4 100644 +--- a/doc/aide.conf.5 ++++ b/doc/aide.conf.5 +@@ -266,6 +266,34 @@ The report format to use. The available report formats are as follows: + + \fBjson\fP: Print report in json machine-readable format. + .RE ++.IP "syslog_format (type: bool, default: \fBno\fR)" ++Valid values are \fByes\fR, \fBtrue\fR, \fBno\fR and \fBfalse\fR. ++ ++When enabled, the standard multi-line report is replaced with a compact ++semicolon-delimited format where every file event is emitted as a single line. ++This ensures that when used with \fBreport_url=syslog:\fILOG_FACILITY\fR, exactly ++one syslog message is produced per changed, added, or removed file. ++ ++Output starts with a header line when differences are found: ++.nf ++AIDE found differences between database and filesystem!! ++.fi ++Followed by a summary line: ++.nf ++summary;total_number_of_files=\fIN\fP;added_files=\fIN\fP;removed_files=\fIN\fP;changed_files=\fIN\fP ++.fi ++Then one line per changed, added, or removed entry: ++.nf ++file=/usr/sbin/sshd;Mtime_old=...;Mtime_new=...;SHA256_old=...;SHA256_new=... ++dir=/etc/cron.d; added ++file=/usr/bin/old; removed ++.fi ++ ++The maximum size of a single syslog message depends on the syslog daemon ++(typically 1\(en8\ KB). Lines exceeding this limit will be silently truncated ++by the syslog daemon. This is not controlled by AIDE. ++ ++The \fBreport_summarize_changes\fR option has no effect in this format. + + .IP "report_base16 (type: bool, default: \fBfalse\fR, added in AIDE v0.17)" + Base16 encode the checksums in the report. The default is to +diff --git a/include/conf_ast.h b/include/conf_ast.h +index 8892a05..424f734 100644 +--- a/include/conf_ast.h ++++ b/include/conf_ast.h +@@ -53,6 +53,7 @@ typedef enum config_option { + REPORT_FORMAT_OPTION, + LIMIT_CMDLINE_OPTION, + NUM_WORKERS, ++ SYSLOG_FORMAT_OPTION, + } config_option; + + typedef struct { +diff --git a/include/db_config.h b/include/db_config.h +index 4173a4b..363631e 100644 +--- a/include/db_config.h ++++ b/include/db_config.h +@@ -133,6 +133,7 @@ typedef struct db_config { + int report_detailed_init; + int report_base16; + int report_quiet; ++ int syslog_format; + bool report_append; + + DB_ATTR_TYPE report_ignore_added_attrs; +diff --git a/include/report.h b/include/report.h +index 2ec3539..b2efa55 100644 +--- a/include/report.h ++++ b/include/report.h +@@ -48,6 +48,7 @@ typedef enum { + REPORT_FORMAT_UNKNOWN = 0, + REPORT_FORMAT_PLAIN = 1, + REPORT_FORMAT_JSON = 2, ++ REPORT_FORMAT_SYSLOG = 3, + } REPORT_FORMAT; + + extern const ATTRIBUTE report_attrs_order[]; +@@ -138,6 +139,8 @@ typedef struct report_format_module { + void (*print_report_summary)(report_t*); + } report_format_module; + ++DB_ATTR_TYPE get_report_attributes(seltree*, report_t*); ++ + char* get_file_type_string(mode_t); + char* get_summarize_changes_string(report_t*, seltree*); + char* get_summary_string(report_t*); +diff --git a/include/report_syslog.h b/include/report_syslog.h +new file mode 100644 +index 0000000..4da9ae4 +--- /dev/null ++++ b/include/report_syslog.h +@@ -0,0 +1,28 @@ ++/* ++ * AIDE (Advanced Intrusion Detection Environment) ++ * ++ * Copyright (C) 2025 Hannes von Haugwitz ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef _REPORT_SYSLOG_H_INCLUDED ++#define _REPORT_SYSLOG_H_INCLUDED ++ ++#include "report.h" ++ ++extern report_format_module report_module_syslog; ++ ++#endif +diff --git a/src/aide.c b/src/aide.c +index 6f728a9..f9a9cd4 100644 +--- a/src/aide.c ++++ b/src/aide.c +@@ -439,6 +439,7 @@ static void setdefaults_before_config(void) + conf->report_detailed_init=0; + conf->report_base16=0; + conf->report_quiet=0; ++ conf->syslog_format=0; + conf->report_append=false; + conf->report_ignore_added_attrs = 0; + conf->report_ignore_removed_attrs = 0; +diff --git a/src/conf_ast.c b/src/conf_ast.c +index 366bc3f..7b66aed 100644 +--- a/src/conf_ast.c ++++ b/src/conf_ast.c +@@ -58,6 +58,7 @@ config_option_t config_options[] = { + { REPORT_FORMAT_OPTION, NULL, NULL }, + { LIMIT_CMDLINE_OPTION, "limit", "Limit" }, + { NUM_WORKERS, NULL, NULL }, ++ { SYSLOG_FORMAT_OPTION, NULL, NULL }, + }; + + static ast* new_ast_node(void) { +diff --git a/src/conf_eval.c b/src/conf_eval.c +index 5774ce6..bb39610 100644 +--- a/src/conf_eval.c ++++ b/src/conf_eval.c +@@ -264,6 +264,9 @@ static void eval_config_statement(config_option_statement statement, int linenum + REPORT_FORMAT report_format = get_report_format(str); + if (report_format != REPORT_FORMAT_UNKNOWN) { + conf->report_format = report_format; ++ for (list *l = conf->report_urls; l; l = l->next) { ++ ((report_t *)l->data)->format = report_format; ++ } + LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_CONFIG, "set 'report_format' option to '%s' (raw: %d)", str, report_format) + } else { + LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "invalid report format: '%s'", str); +@@ -315,6 +318,11 @@ static void eval_config_statement(config_option_statement statement, int linenum + LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_NOTICE, "'num_workers' option already set (ignore new value '%s')", str) + } + break; ++ case SYSLOG_FORMAT_OPTION: ++ b = string_expression_to_bool(statement.e, linenumber, filename, linebuf); ++ conf->syslog_format = b; ++ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_CONFIG, "set 'syslog_format' to '%s'", btoa(b)) ++ break; + } + } + +diff --git a/src/conf_lex.l b/src/conf_lex.l +index 877a125..1a9654f 100644 +--- a/src/conf_lex.l ++++ b/src/conf_lex.l +@@ -362,6 +362,13 @@ LOG_LEVEL lex_log_level = LOG_LEVEL_DEBUG; + BEGIN (STRINGEQHUNT); + return (CONFIGOPTION); + } ++"syslog_format" { ++ LOG_LEX_TOKEN(lex_log_level, CONFIGOPTION (SYSLOG_FORMAT_OPTION), conftext) ++ conflval.option = SYSLOG_FORMAT_OPTION; ++ BEGIN (STRINGEQHUNT); ++ return (CONFIGOPTION); ++} ++ + + "report_level" { + LOG_LEX_TOKEN(lex_log_level, CONFIGOPTION (REPORT_LEVEL_OPTION), conftext) +diff --git a/src/report.c b/src/report.c +index 9e4d0d0..f87754c 100644 +--- a/src/report.c ++++ b/src/report.c +@@ -59,6 +59,7 @@ + #include "report.h" + #include "report_plain.h" + #include "report_json.h" ++#include "report_syslog.h" + /*for locale support*/ + #include "locale-aide.h" + /*for locale support*/ +@@ -146,6 +147,7 @@ struct report_format { + static struct report_format report_format_array[] = { + { REPORT_FORMAT_PLAIN, "plain" }, + { REPORT_FORMAT_JSON, "json" }, ++ { REPORT_FORMAT_SYSLOG, "syslog" }, + { REPORT_FORMAT_UNKNOWN, NULL } + }; + +@@ -509,6 +511,15 @@ bool init_report_urls(void) { + } + } + ++ } ++ /* syslog_format is a downstream-only option that must win over report_format ++ * regardless of declaration order in the config file. Enforce it here, ++ * after the entire config AST has been evaluated, so no subsequent ++ * report_format setting can accidentally override the user's intent. */ ++ if (conf->syslog_format) { ++ for (l=conf->report_urls; l; l=l->next) { ++ ((report_t *)l->data)->format = REPORT_FORMAT_SYSLOG; ++ } + } + return true; + } +@@ -677,7 +688,7 @@ char* get_summarize_changes_string(report_t* report, seltree* node) { + + + +-static DB_ATTR_TYPE get_report_attributes(seltree* node, report_t *report) { ++DB_ATTR_TYPE get_report_attributes(seltree* node, report_t *report) { + db_line* oline = node->old_data; + db_line* nline = node->new_data; + DB_ATTR_TYPE attrs = node->changed_attrs; +@@ -966,6 +977,9 @@ int gen_report(seltree* node) { + case REPORT_FORMAT_JSON: + print_report(report, node, report_module_json); + break; ++ case REPORT_FORMAT_SYSLOG: ++ print_report(report, node, report_module_syslog); ++ break; + case REPORT_FORMAT_UNKNOWN: + /* skip unknown report format */ + break; +diff --git a/src/report_syslog.c b/src/report_syslog.c +new file mode 100644 +index 0000000..920e927 +--- /dev/null ++++ b/src/report_syslog.c +@@ -0,0 +1,338 @@ ++/* ++ * AIDE (Advanced Intrusion Detection Environment) ++ * ++ * Copyright (C) 2025 Hannes von Haugwitz ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "config.h" ++#include "aide.h" ++#include ++#include ++#include ++#include ++#include ++#include "attributes.h" ++#include "base64.h" ++#include "db.h" ++#include "db_line.h" ++#include "hashsum.h" ++#include "report.h" ++#include "report_syslog.h" ++#include "seltree.h" ++#include "seltree_struct.h" ++#include "tree.h" ++#include "util.h" ++ ++/* Returns the compact syslog file-type prefix, or NULL when mode is unknown ++ * (mode & S_IFMT == 0), in which case callers omit the "type=" prefix. */ ++static const char *get_syslog_type_prefix(mode_t mode) { ++ switch (mode & S_IFMT) { ++ case S_IFREG: return "file"; ++ case S_IFDIR: return "dir"; ++ case S_IFLNK: return "link"; ++ case S_IFBLK: return "blockd"; ++ case S_IFCHR: return "chard"; ++#ifdef S_IFIFO ++ case S_IFIFO: return "fifo"; ++#endif ++#ifdef S_IFSOCK ++ case S_IFSOCK: return "socket"; ++#endif ++ case 0: return NULL; ++ default: return "unknown"; ++ } ++} ++ ++/* Returns the key name for attribute a. attr_sizeg is the only exception: ++ * its details_string is "Size (>)" which contains '>', so we substitute ++ * "Size" to match the original patch's explicit details_string[] change. */ ++static const char *get_attr_key(ATTRIBUTE a) { ++ if (a == attr_sizeg) { ++ return "Size"; ++ } ++ return attributes[a].details_string; ++} ++ ++#ifdef WITH_XATTR ++ ++#define SYSLOG_PRINTABLE_XATTR_VALS \ ++ "0123456789" \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ ".-_:;,[]{}<>()!@#$%^&*|\\/?~" ++ ++/* Appends one side's xattr values to stream in compact syslog format. ++ * Format: ;XAttrs_=|[1]key=val|[2]key=val| */ ++static void build_xattrs_compact(FILE *stream, db_line *line, const char *side) { ++ xattrs_type *xattrs = line ? line->xattrs : NULL; ++ ++ if (!xattrs || xattrs->num == 0) { ++ fprintf(stream, ";XAttrs_%s=|num=0|", side); ++ return; ++ } ++ ++ fprintf(stream, ";XAttrs_%s=|num=%zu|", side, xattrs->num); ++ ++ for (size_t i = 0; i < xattrs->num; i++) { ++ const char *key = xattrs->ents[i].key; ++ const char *val = (const char *)xattrs->ents[i].val; ++ size_t vsz = xattrs->ents[i].vsz; ++ ++ /* Check printability (replicates xstrnspn logic from report.c). */ ++ size_t plen = 0; ++ while (plen < vsz && strchr(SYSLOG_PRINTABLE_XATTR_VALS, val[plen])) ++ plen++; ++ bool printable = (plen == vsz) || (plen == vsz - 1 && val[plen] == '\0'); ++ ++ if (printable) { ++ fprintf(stream, "[%zu]%s=%s|", i + 1, key, val); ++ } else { ++ char *b64 = encode_base64((byte *)xattrs->ents[i].val, vsz); ++ fprintf(stream, "[%zu]%s<=>%s|", i + 1, key, b64 ? b64 : ""); ++ free(b64); ++ } ++ } ++} ++#endif /* WITH_XATTR */ ++ ++#ifdef WITH_POSIX_ACL ++/* Appends one side's ACL to stream in compact syslog format. ++ * Format: ;ACL_=A:|D: ++ * ++ * Both A and D are initialized to "" before the conditionals, fixing ++ * the uninitialized-pointer bug in the original 0.16 patch. */ ++static void build_acl_compact(FILE *stream, db_line *line, const char *side) { ++ acl_type *acl = line ? line->acl : NULL; ++ ++ const char *A = ""; ++ const char *D = ""; ++ if (acl) { ++ if (acl->acl_a) { A = acl->acl_a; } ++ if (acl->acl_d) { D = acl->acl_d; } ++ } ++ ++ /* Write A component, replacing newlines with spaces. */ ++ fprintf(stream, ";ACL_%s=A:", side); ++ for (const char *p = A; *p; p++) { ++ fputc(*p == '\n' ? ' ' : *p, stream); ++ } ++ ++ /* Write D component, replacing newlines with spaces. */ ++ fprintf(stream, "|D:"); ++ for (const char *p = D; *p; p++) { ++ fputc(*p == '\n' ? ' ' : *p, stream); ++ } ++} ++#endif /* WITH_POSIX_ACL */ ++ ++/* Assembles a complete syslog line for one file event into *out. ++ * ++ * Invariant: this function never calls report_printf(). The caller emits ++ * the result with exactly one report_printf() call to avoid fragmenting ++ * syslog messages (each report_printf to url_syslog calls vsyslog() once). ++ * ++ * Cases: ++ * oline != NULL && nline != NULL → changed entry ++ * oline == NULL → added entry ++ * nline == NULL → removed entry ++ * ++ * *out is heap-allocated by open_memstream; caller must free() it. */ ++static void build_syslog_line(report_t *report, db_line *oline, db_line *nline, ++ DB_ATTR_TYPE attrs, char **out) { ++ db_line *ref = nline ? nline : oline; ++ const char *type = get_syslog_type_prefix(ref->perm); ++ ++ char *buf = NULL; ++ size_t bufsz = 0; ++ FILE *stream = open_memstream(&buf, &bufsz); ++ ++ /* Write "type=path" prefix. */ ++ if (type) { ++ fprintf(stream, "%s=%s", type, ref->filename); ++ } else { ++ fprintf(stream, "%s", ref->filename); ++ } ++ ++ if (oline && nline) { ++ /* Changed entry: emit only differing attributes. */ ++ for (int j = 0; j < report_attrs_order_length; j++) { ++ ATTRIBUTE a = report_attrs_order[j]; ++ ++ switch (a) { ++ case attr_allhashsums: ++ /* Expand to each compiled-in hash, mirroring print_dbline_attrs(). */ ++ for (int i = 0; i < num_hashes; i++) { ++ if (!(ATTR(hashsums[i].attribute) & attrs)) { continue; } ++ const char *key = get_attr_key(hashsums[i].attribute); ++ if (!key) { continue; } ++ char **oval = NULL, **nval = NULL; ++ get_attribute_values(ATTR(hashsums[i].attribute), oline, &oval, report); ++ get_attribute_values(ATTR(hashsums[i].attribute), nline, &nval, report); ++ fprintf(stream, ";%s_old=%s;%s_new=%s", ++ key, oval ? oval[0] : "", key, nval ? nval[0] : ""); ++ if (oval) { free(oval[0]); free(oval); } ++ if (nval) { free(nval[0]); free(nval); } ++ } ++ break; ++ ++ case attr_size: ++ /* attr_size and attr_sizeg share this slot in report_attrs_order. */ ++ if (ATTR(attr_size) & attrs) { ++ const char *key = get_attr_key(attr_size); ++ if (key) { ++ char **oval = NULL, **nval = NULL; ++ get_attribute_values(ATTR(attr_size), oline, &oval, report); ++ get_attribute_values(ATTR(attr_size), nline, &nval, report); ++ fprintf(stream, ";%s_old=%s;%s_new=%s", ++ key, oval ? oval[0] : "", key, nval ? nval[0] : ""); ++ if (oval) { free(oval[0]); free(oval); } ++ if (nval) { free(nval[0]); free(nval); } ++ } ++ } ++ if (ATTR(attr_sizeg) & attrs) { ++ const char *key = get_attr_key(attr_sizeg); /* returns "Size" */ ++ if (key) { ++ char **oval = NULL, **nval = NULL; ++ get_attribute_values(ATTR(attr_sizeg), oline, &oval, report); ++ get_attribute_values(ATTR(attr_sizeg), nline, &nval, report); ++ fprintf(stream, ";%s_old=%s;%s_new=%s", ++ key, oval ? oval[0] : "", key, nval ? nval[0] : ""); ++ if (oval) { free(oval[0]); free(oval); } ++ if (nval) { free(nval[0]); free(nval); } ++ } ++ } ++ break; ++ ++ default: ++ if (!(ATTR(a) & attrs)) { break; } ++#ifdef WITH_XATTR ++ if (a == attr_xattrs) { ++ build_xattrs_compact(stream, oline, "old"); ++ build_xattrs_compact(stream, nline, "new"); ++ break; ++ } ++#endif ++#ifdef WITH_POSIX_ACL ++ if (a == attr_acl) { ++ build_acl_compact(stream, oline, "old"); ++ build_acl_compact(stream, nline, "new"); ++ break; ++ } ++#endif ++ { ++ const char *key = get_attr_key(a); ++ if (!key) { break; } ++ char **oval = NULL, **nval = NULL; ++ get_attribute_values(ATTR(a), oline, &oval, report); ++ get_attribute_values(ATTR(a), nline, &nval, report); ++ fprintf(stream, ";%s_old=%s;%s_new=%s", ++ key, oval ? oval[0] : "", key, nval ? nval[0] : ""); ++ if (oval) { free(oval[0]); free(oval); } ++ if (nval) { free(nval[0]); free(nval); } ++ } ++ break; ++ } ++ } ++ } else if (!oline) { ++ fprintf(stream, "; added"); ++ } else { ++ fprintf(stream, "; removed"); ++ } ++ ++ fclose(stream); ++ *out = buf; ++} ++ ++/* Emits exactly one syslog line for a file event. */ ++static void emit_syslog_entry(report_t *report, db_line *oline, db_line *nline, ++ DB_ATTR_TYPE attrs) { ++ char *line = NULL; ++ build_syslog_line(report, oline, nline, attrs, &line); ++ report_printf(report, "%s\n", line); ++ free(line); ++} ++ ++/* Unconditional tree walker — does not gate added/removed on report->level, ++ * matching the original patch's print_syslog_format() behavior. */ ++static void syslog_walk_tree(report_t *report, seltree *node) { ++ pthread_rwlock_rdlock(&node->rwlock); ++ ++ if (node->checked & NODE_CHANGED) { ++ emit_syslog_entry(report, node->old_data, node->new_data, ++ get_report_attributes(node, report)); ++ } ++ if (node->checked & NODE_ADDED) { ++ emit_syslog_entry(report, NULL, node->new_data, ++ node->new_data->attr & ~report->ignore_added_attrs); ++ } ++ if (node->checked & NODE_REMOVED) { ++ emit_syslog_entry(report, node->old_data, NULL, ++ node->old_data->attr & ~report->ignore_removed_attrs); ++ } ++ ++ for (tree_node *x = tree_walk_first(node->children); x != NULL; x = tree_walk_next(x)) { ++ syslog_walk_tree(report, tree_get_data(x)); ++ } ++ ++ pthread_rwlock_unlock(&node->rwlock); ++} ++ ++/* ── Module callbacks ─────────────────────────────────────────────────── */ ++ ++static void noop_header(report_t *report) { (void)report; } ++static void noop_footer(report_t *report) { (void)report; } ++static void noop_databases(report_t *report) { (void)report; } ++static void noop_config_options(report_t *report) { (void)report; } ++static void noop_report_options(report_t *report) { (void)report; } ++static void noop_starttime_version(report_t *r, const char *t, const char *v) { (void)r; (void)t; (void)v; } ++static void noop_endtime_runtime(report_t *r, const char *t, long rt) { (void)r; (void)t; (void)rt; } ++static void noop_new_database_written(report_t *report) { (void)report; } ++static void noop_entries(report_t *r, seltree *n, const int f) { (void)r; (void)n; (void)f; } ++static void noop_diff_attrs(report_t *report) { (void)report; } ++static void noop_summary(report_t *report) { (void)report; } ++ ++/* Emits header + summary when there are differences. Two separate ++ * report_printf() calls — each becomes one syslog message. */ ++static void syslog_outline(report_t *report) { ++ if (report->nadd || report->nrem || report->nchg) { ++ report_printf(report, "AIDE found differences between database and filesystem!!\n"); ++ report_printf(report, ++ "summary;total_number_of_files=%ld;added_files=%ld;" ++ "removed_files=%ld;changed_files=%ld\n", ++ report->ntotal, report->nadd, report->nrem, report->nchg); ++ } ++} ++ ++static void syslog_details(report_t *report, seltree *node) { ++ syslog_walk_tree(report, node); ++} ++ ++report_format_module report_module_syslog = { ++ .print_report_config_options = noop_config_options, ++ .print_report_databases = noop_databases, ++ .print_report_details = syslog_details, ++ .print_report_diff_attrs_entries = noop_diff_attrs, ++ .print_report_endtime_runtime = noop_endtime_runtime, ++ .print_report_entries = noop_entries, ++ .print_report_footer = noop_footer, ++ .print_report_header = noop_header, ++ .print_report_new_database_written = noop_new_database_written, ++ .print_report_outline = syslog_outline, ++ .print_report_report_options = noop_report_options, ++ .print_report_starttime_version = noop_starttime_version, ++ .print_report_summary = noop_summary, ++}; +-- +2.54.0 + diff --git a/SOURCES/aide-0.19.2.tar.gz.asc b/SOURCES/aide-0.19.2.tar.gz.asc new file mode 100644 index 0000000..99be423 --- /dev/null +++ b/SOURCES/aide-0.19.2.tar.gz.asc @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +iQGzBAABCgAdFiEEVJXNoXyawXqyOEGnGO6GOGAi71cFAmict6oACgkQGO6GOGAi +71e/Awv/cP4/UJSVJlaUjRLoeRIayqFxAxZeku1OK1cNuGo5aRp47WsxZFpGkkMc +eNhrtOpukD0CohFdsBFabd2KweaaY67pbCSTXxQBjhEMtYLb+Z5b441cJChJQgeL +q2P09mCGmOoJ4li7VxF2Kjy4uTj4C64SoXFnkYgMzfgBQBC0wD3HBisN8tRG9M4w +4kQa8ZvsO5hFEiFuVhBfLwDKLaUXf5MDcst1Q9MeAGxwvQN5xaSivOwSoCqhVgSv +cDBo1RmhYSf43vUuXTAgclC3WD1y6qm0Si/naVnwVvvN2ij4cGfnb89ixd6qGlKY +HV4klaVQWRQwSyDlhbTcHVxvwnopW+5YZ5SeF3Yl7XohaL89hLEEDxFcLQkrslzV +wR0B0lCtmbZfVhWsnZScNZvT9Cnco7p4FMkkYIHOEVad6kFH3RRXHH320kUD3aWl +hAKXLvuEnYmE//prriUlnh7Q4rsyh9N6ZLgdZxrdPcVbNSAzRiMd8A4kh/H5oMY9 +rFqw9YnF +=JV2j +-----END PGP SIGNATURE----- diff --git a/SOURCES/aide-configure.patch b/SOURCES/aide-configure.patch deleted file mode 100644 index e9030eb..0000000 --- a/SOURCES/aide-configure.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --color -ru a/configure.ac b/configure.ac ---- a/configure.ac 2021-05-20 09:31:11.686987129 +0200 -+++ b/configure.ac 2021-05-20 09:39:43.369967457 +0200 -@@ -784,11 +784,11 @@ - [if test "x$withval" = "xmd5" ;then - CONFIGHMACTYPE="MHASH_MD5" - else if test "x$withval" = "xsha1" ;then -- CONFIGHMACTYPE="MHASH_SHA1" -+ CONFIGHMACTYPE="MHASH_SHA1" - else if test "x$withval" = "xsha256" ;then -- CONFIGHMACTYPE="MHASH_SHA256" -+ CONFIGHMACTYPE="MHASH_SHA256" - else if test "x$withval" = "xsha512" ;then -- CONFIGHMACTYPE="MHASH_SHA512" -+ CONFIGHMACTYPE="MHASH_SHA512" - else - echo "Valid parameters for --with-confighmactype are md5, sha1, sha256 and sha512" - exit 1 -@@ -799,7 +799,6 @@ - AC_DEFINE_UNQUOTED(CONFIGHMACTYPE,$CONFIGHMACTYPE,[hash type for config file check])], - [ - AC_DEFINE_UNQUOTED(CONFIGHMACTYPE,MHASH_MD5,[hash type for config file check])] --, - ) - - AC_ARG_WITH([confighmackey], -@@ -846,18 +845,18 @@ - - AC_ARG_WITH([dbhmactype], - AC_HELP_STRING([--with-dbhmactype=TYPE], -- [Hash type to use for checking db. Valid values are md5 and sha1.]), -+ [Hash type to use for checking db. Valid values are md5, sha1, sha256 and sha512.]), - [if test "x$withval" = "xmd5" ;then - DBHMACTYPE="MHASH_MD5" - else if test "x$withval" = "xsha1" ;then -- DBHMACTYPE="MHASH_SHA1" -+ DBHMACTYPE="MHASH_SHA1" - else if test "x$withval" = "xsha256" ;then -- CONFIGHMACTYPE="MHASH_SHA256" -+ DBHMACTYPE="MHASH_SHA256" - else if test "x$withval" = "xsha512" ;then -- CONFIGHMACTYPE="MHASH_SHA512" -+ DBHMACTYPE="MHASH_SHA512" - else -- echo "Valid parameters for --with-dbhmactype are md5, sha1, sha256 and sha512" -- exit 1 -+ echo "Valid parameters for --with-dbhmactype are md5, sha1, sha256 and sha512" -+ exit 1 - fi - fi - fi diff --git a/SOURCES/aide-db-problem.patch b/SOURCES/aide-db-problem.patch deleted file mode 100644 index 1994284..0000000 --- a/SOURCES/aide-db-problem.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -up aide-0.16/src/commandconf.c.rhcase03736158 aide-0.16/src/commandconf.c ---- aide-0.16/src/commandconf.c.rhcase03736158 2024-03-01 11:06:35.305712992 +0100 -+++ aide-0.16/src/commandconf.c 2024-03-01 11:08:07.726499878 +0100 -@@ -306,6 +306,7 @@ int db_input_wrapper(char* buf, int max_ - retval=0; - buf[0]='\0'; - }else { -+ buf[0]='\0'; - if((retval=gzread(*db_gzp,buf,max_size))<0){ - error(0,_("gzread() failed: gzerr=%s!\n"),gzerror(*db_gzp,&err)); - retval=0; diff --git a/SOURCES/aide-migrate-config b/SOURCES/aide-migrate-config new file mode 100755 index 0000000..43a6b31 --- /dev/null +++ b/SOURCES/aide-migrate-config @@ -0,0 +1,588 @@ +#!/bin/bash +# aide-migrate-config -- migrate AIDE configuration files from pre-0.19 syntax +# +# Usage: aide-migrate-config [--dry-run] [--skip-init] +# +# --dry-run Report what would change; do not modify any file. +# --skip-init Migrate config files only; do not reinitialise the database. +# Path to the main AIDE config (e.g. /etc/aide.conf). + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Globals +# --------------------------------------------------------------------------- +readonly SCRIPT="$(basename "$0")" +readonly TIMESTAMP="$(date +%Y%m%d_%H%M%S)" + +DRY_RUN=false +SKIP_INIT=false +REINIT_NEEDED=false +# Parallel arrays: BACKUP_ORIG[i] → BACKUP_COPY[i] +BACKUP_ORIG=() +BACKUP_COPY=() + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- +usage() { + echo "Usage: $SCRIPT [--dry-run] [--skip-init] " >&2 + exit 1 +} + +die() { + echo "$SCRIPT: error: $*" >&2 + exit 1 +} + +info() { + echo "$SCRIPT: $*" >&2 +} + +# log_action MESSAGE +# Log a migration action. Prefixes with "would " in dry-run mode. +log_action() { + if $DRY_RUN; then + info " would $*" + else + info " $*" + fi +} + +# config_has FILE KEY +# Return 0 if FILE contains a KEY= directive. +config_has() { + local file="$1" key="$2" + grep -qE "^[[:space:]]*${key}[[:space:]]*=" "$file" +} + +# config_del FILE KEY +# Delete all lines matching KEY= from FILE in-place. +config_del() { + local file="$1" key="$2" + sed -E -i "/^[[:space:]]*${key}[[:space:]]*=/d" "$file" +} + +# config_rename FILE OLD_KEY NEW_KEY +# Rename OLD_KEY= to NEW_KEY= in FILE in-place. +config_rename() { + local file="$1" old_key="$2" new_key="$3" + sed -E -i "s/^([[:space:]]*)${old_key}([[:space:]]*=)/\1${new_key}\2/" "$file" +} + +# append_setting FILE CONTENT +# Append "CONTENT\n" to FILE, guaranteeing it starts on a fresh line. +# No-op if the key extracted from CONTENT already exists in FILE. +append_setting() { + local file="$1" content="$2" + local key="${content%%=*}" + config_has "$file" "$key" && return 0 + if [[ -s "$file" ]] && [[ "$(tail -c1 "$file" | wc -l)" -eq 0 ]]; then + printf '\n' >> "$file" + fi + printf '%s\n' "$content" >> "$file" +} + +# backup_file FILE +# Create a timestamped backup of FILE. No-op in dry-run mode. +backup_file() { + local file="$1" + local backup="${file}.bak.${TIMESTAMP}" + if $DRY_RUN; then + return 0 + fi + cp -p -- "$file" "$backup" + BACKUP_ORIG+=("$file") + BACKUP_COPY+=("$backup") + info "backup: $backup" +} + +# restore_backups +# Called by ERR trap; restores every backed-up file. +restore_backups() { + local i + for i in "${!BACKUP_ORIG[@]}"; do + cp -p -- "${BACKUP_COPY[$i]}" "${BACKUP_ORIG[$i]}" && \ + info "restored: ${BACKUP_ORIG[$i]}" || \ + info "WARNING: could not restore ${BACKUP_ORIG[$i]} from ${BACKUP_COPY[$i]}" + done +} + +# --------------------------------------------------------------------------- +# Include-file discovery +# --------------------------------------------------------------------------- + +# extract_includes CONFIG_FILE +# Print one absolute path per line for each file pulled in by @@include directives. +extract_includes() { + local config="$1" + local dir + dir="$(dirname "$config")" + + grep -E '^[[:space:]]*@@include[[:space:]]' "$config" 2>/dev/null | \ + while IFS= read -r line; do + # Strip the @@include keyword + local args + args="${line#*@@include}" + args="${args#"${args%%[! ]*}"}" # ltrim + + # Count tokens to distinguish FILE vs DIRECTORY REGEX forms + local tok1 tok2 + tok1="${args%% *}" + tok2="${args#* }" + + if [[ "$tok1" == "$args" ]]; then + # Single token: @@include FILE + if [[ "$tok1" = /* ]]; then + echo "$tok1" + else + echo "${dir}/${tok1}" + fi + else + # Two tokens: @@include DIRECTORY REGEX + local incdir regex + incdir="$tok1" + regex="$tok2" + if [[ "$incdir" != /* ]]; then + incdir="${dir}/${incdir}" + fi + if [[ -d "$incdir" ]]; then + find "$incdir" -maxdepth 1 -type f -regex "$regex" | sort + fi + fi + done +} + +# --------------------------------------------------------------------------- +# Config file migration +# --------------------------------------------------------------------------- + +# needs_migration FILE +# Return 0 (true) if FILE contains any pattern requiring migration. +needs_migration() { + local f="$1" + # Removed/renamed config options + local _key + for _key in database grouped summarize_changes ignore_list report_attributes verbose; do + config_has "$f" "$_key" && return 0 + done + # sql: value starts with sql: (PostgreSQL backend removed) + grep -qE '^[[:space:]]*[a-z_]+[[:space:]]*=[[:space:]]*sql:' "$f" && return 0 + # any h character in report_ignore_e2fsattrs value + grep -qE '^[[:space:]]*report_ignore_e2fsattrs[[:space:]]*=.*h' "$f" && return 0 + # removed/deprecated hashsums; dash at end of character class to avoid range error in GNU sed + grep -v '^[[:space:]]*#' "$f" | \ + grep -qE '[+[:space:]=-](crc32b|crc32|tiger|haval|whirlpool|md5|sha1|rmd160|gost)([+[:space:]-]|$)' && return 0 + # standalone S attribute in an expression (skip comment lines) + grep -v '^[[:space:]]*#' "$f" | grep -qE '(^|[+=[:space:]-])S([+[:space:]-]|$)' && return 0 + # deprecated preprocessor macros + grep -qE '^[[:space:]]*@@(ifdef|ifndef|ifhost|ifnhost)[[:space:]]' "$f" && return 0 + # missing trailing newline + [[ -s "$f" ]] && [[ "$(tail -c1 "$f" | wc -l)" -eq 0 ]] && return 0 + return 1 +} + +# remove_hashsum FILE HASHSUM +# Remove a single hashsum token from all group/rule expressions in FILE (in-place). +# Handles all positions: +hash, -hash, hash+ (first), and hash$ (last with minus prefix). +remove_hashsum() { + local file="$1" hash="$2" + + # Pass 1: remove hash when it is preceded by an operator (+ or -) + # Keep whatever follows (next operator, space, or end-of-line). + sed -E -i \ + -e "/^[[:space:]]*#/!s/[+-]${hash}([+[:space:]-])/\1/g" \ + -e "/^[[:space:]]*#/!s/[+-]${hash}$//" \ + "$file" + + # Pass 2: remove hash at the start of an expression (after = or whitespace), + # not preceded by an operator (those were handled in pass 1). + sed -E -i \ + -e "/^[[:space:]]*#/!s/(=[[:space:]]*)${hash}([+[:space:]-])/\1\2/g" \ + -e "/^[[:space:]]*#/!s/(=[[:space:]]*)${hash}$/\1/" \ + -e "/^[[:space:]]*#/!s/([[:space:]])${hash}([+[:space:]-])/\1\2/g" \ + -e "/^[[:space:]]*#/!s/([[:space:]])${hash}$/\1/" \ + "$file" + + # Clean up artifacts: double operators, dangling operator after '=', trailing operator. + sed -E -i \ + -e '/^[[:space:]]*#/!s/[+][+]/+/g' \ + -e '/^[[:space:]]*#/!s/[+][-]/+/g' \ + -e '/^[[:space:]]*#/!s/[-][+]/-/g' \ + -e '/^[[:space:]]*#/!s/(=[[:space:]]*)[+-]/\1/g' \ + -e '/^[[:space:]]*#/!s/[+-]$//' \ + "$file" +} + +# migrate_config_file FILE +# Apply all config transformations to FILE. Sets global REINIT_NEEDED when needed. +migrate_config_file() { + local file="$1" + + if [[ ! -f "$file" ]]; then + info "WARNING: $file not found, skipping" + return 0 + fi + if [[ ! -r "$file" ]]; then + info "WARNING: $file is not readable, skipping" + return 0 + fi + + if ! needs_migration "$file"; then + info "no migration needed: $file" + return 0 + fi + + info "migrating: $file" + backup_file "$file" + + local tmpfile + tmpfile="$(mktemp "${file}.XXXXXX")" + # Ensure tmpfile is cleaned up if we exit abnormally before the final mv + trap "rm -f '$tmpfile'; restore_backups" ERR + cp -p -- "$file" "$tmpfile" + + # ----------------------------------------------------------------------- + # Rename removed config options + # The 'database' key anchors to KEY= so it cannot match 'database_in'/'database_out'. + # ----------------------------------------------------------------------- + config_has "$tmpfile" database && log_action "rename: database= → database_in=" + config_has "$tmpfile" grouped && log_action "rename: grouped= → report_grouped=" + config_has "$tmpfile" summarize_changes && log_action "rename: summarize_changes= → report_summarize_changes=" + config_has "$tmpfile" ignore_list && log_action "rename: ignore_list= → report_ignore_changed_attrs=" + config_has "$tmpfile" report_attributes && log_action "rename: report_attributes= → report_force_attrs=" + if ! $DRY_RUN; then + config_rename "$tmpfile" database database_in + config_rename "$tmpfile" grouped report_grouped + config_rename "$tmpfile" summarize_changes report_summarize_changes + config_rename "$tmpfile" ignore_list report_ignore_changed_attrs + config_rename "$tmpfile" report_attributes report_force_attrs + fi + + # ----------------------------------------------------------------------- + # Replace verbose= with the equivalent 0.19 options + # ----------------------------------------------------------------------- + if config_has "$tmpfile" verbose; then + log_action "remove verbose=" + config_has "$tmpfile" log_level || log_action "add log_level=warning" + config_has "$tmpfile" report_level || log_action "add report_level=changed_attributes" + if ! $DRY_RUN; then + config_del "$tmpfile" verbose + append_setting "$tmpfile" 'log_level=warning' + append_setting "$tmpfile" 'report_level=changed_attributes' + fi + fi + + # ----------------------------------------------------------------------- + # Remove sql: database URL lines (PostgreSQL backend removed) + # Match lines whose value (after =) begins with sql:. + # ----------------------------------------------------------------------- + if grep -qE '^[[:space:]]*[a-z_]+[[:space:]]*=[[:space:]]*sql:' "$tmpfile"; then + log_action "remove sql: database URL lines" + if $DRY_RUN; then + # Check which keys survive after sql: removal (i.e. have at least one non-sql: value) + grep -E '^[[:space:]]*database_out[[:space:]]*=' "$tmpfile" | \ + grep -qvE '^[[:space:]]*[a-z_]+[[:space:]]*=[[:space:]]*sql:' || \ + info " would add default database_out=file:/var/lib/aide/aide.db.new.gz" + grep -E '^[[:space:]]*database_in[[:space:]]*=' "$tmpfile" | \ + grep -qvE '^[[:space:]]*[a-z_]+[[:space:]]*=[[:space:]]*sql:' || \ + info " would add default database_in=file:/var/lib/aide/aide.db.gz" + fi + if ! $DRY_RUN; then + sed -E -i '/^[[:space:]]*[a-z_]+[[:space:]]*=[[:space:]]*sql:/d' "$tmpfile" + config_has "$tmpfile" database_out || { + append_setting "$tmpfile" 'database_out=file:/var/lib/aide/aide.db.new.gz' + info " WARNING: sql: URL removed; default database_out added." \ + "Verify storage path before running aide --init." + } + config_has "$tmpfile" database_in || { + append_setting "$tmpfile" 'database_in=file:/var/lib/aide/aide.db.gz' + info " WARNING: sql: database_in removed; default database_in added." \ + "Verify path before running aide --init." + } + fi + REINIT_NEEDED=true + fi + + # ----------------------------------------------------------------------- + # Remove 'h' from report_ignore_e2fsattrs + # Use the sed address form to remove ALL 'h' characters from the value line. + # ----------------------------------------------------------------------- + if grep -qE '^[[:space:]]*report_ignore_e2fsattrs[[:space:]]*=.*h' "$tmpfile"; then + log_action "remove 'h' from report_ignore_e2fsattrs" + if ! $DRY_RUN; then + sed -E -i '/^[[:space:]]*report_ignore_e2fsattrs[[:space:]]*=/s/h//g' "$tmpfile" + sed -E -i '/^[[:space:]]*report_ignore_e2fsattrs[[:space:]]*=[[:space:]]*$/d' "$tmpfile" + fi + fi + + # ----------------------------------------------------------------------- + # Remove deprecated and removed hashsums + # Process crc32b before crc32 to avoid prefix collision. + # Character classes use dash at end to prevent GNU sed range-error. + # ----------------------------------------------------------------------- + local hash changed_hashes=false + for hash in crc32b crc32 tiger haval whirlpool md5 sha1 rmd160 gost; do + if grep -v '^[[:space:]]*#' "$tmpfile" | grep -qE "(^|[+[:space:]=-])${hash}([+[:space:]-]|\$)"; then + log_action "remove hashsum: $hash" + if ! $DRY_RUN; then + remove_hashsum "$tmpfile" "$hash" + fi + changed_hashes=true + REINIT_NEEDED=true + fi + done + + # Post-removal: fill any group definition whose RHS became empty with sha256 + if $changed_hashes; then + if ! $DRY_RUN; then + while IFS= read -r lineno; do + [[ -z "$lineno" ]] && continue + sed -i "${lineno}s/=.*/= sha256/" "$tmpfile" + info " group on line $lineno became empty after hashsum removal; added sha256" + done < <(grep -nE '^[A-Za-z0-9]+[[:space:]]*=[[:space:]]*[+-]?[[:space:]]*$' \ + "$tmpfile" | cut -d: -f1) + else + info " note: any group containing only deprecated hashsums will have sha256 substituted" + fi + fi + + # ----------------------------------------------------------------------- + # Replace deprecated S attribute with growing+s + # Applies since AIDE 0.16 is being replaced; growing+s is unknown to 0.16. + # Character classes use dash at end to prevent GNU sed range-error. + # ----------------------------------------------------------------------- + if grep -qE '(^|[+=[:space:]-])S([+[:space:]-]|$)' "$tmpfile"; then + log_action "replace S attribute with growing+s" + if ! $DRY_RUN; then + sed -E -i \ + -e '/^[[:space:]]*#/!s/([+=[:space:]-])S([+[:space:]-]|$)/\1growing+s\2/g' \ + -e '/^[[:space:]]*#/!s/^S([+[:space:]-]|$)/growing+s\1/g' \ + "$tmpfile" + fi + fi + + # ----------------------------------------------------------------------- + # Replace deprecated @@ifdef/@@ifndef/@@ifhost/@@ifnhost macros + # ----------------------------------------------------------------------- + if grep -qE '^[[:space:]]*@@(ifdef|ifndef|ifhost|ifnhost)[[:space:]]' "$tmpfile"; then + log_action "replace deprecated @@ifdef/@@ifndef/@@ifhost/@@ifnhost macros" + if ! $DRY_RUN; then + sed -E -i \ + -e 's/^([[:space:]]*)@@ifdef([[:space:]])/\1@@if defined\2/g' \ + -e 's/^([[:space:]]*)@@ifndef([[:space:]])/\1@@if not defined\2/g' \ + -e 's/^([[:space:]]*)@@ifhost([[:space:]])/\1@@if hostname\2/g' \ + -e 's/^([[:space:]]*)@@ifnhost([[:space:]])/\1@@if not hostname\2/g' \ + "$tmpfile" + fi + fi + + # ----------------------------------------------------------------------- + # Ensure file ends with a newline + # ----------------------------------------------------------------------- + local last_byte + last_byte="$(tail -c1 "$tmpfile" | od -An -tx1 | tr -d ' \n')" + if [[ -n "$last_byte" && "$last_byte" != '0a' ]]; then + log_action "add missing trailing newline" + $DRY_RUN || echo "" >> "$tmpfile" + fi + + # H group's content changed in 0.19; warn if used without a custom definition. + # Only reached when the file had real 0.16-style options, so this never fires on a + # clean 0.19 config. + if grep -qE '(^|[+[:space:]-])H([+[:space:]-]|$)' "$tmpfile" 2>/dev/null; then + if ! grep -qE '^[[:space:]]*H[[:space:]]*=' "$tmpfile"; then + info "NOTE: built-in H group in use without custom definition;" \ + "H content changed in 0.19 — run 'aide --init' to rebuild the database" + fi + fi + + # ----------------------------------------------------------------------- + # Commit changes + # ----------------------------------------------------------------------- + if ! $DRY_RUN; then + mv -- "$tmpfile" "$file" + # Restore original permissions + chmod --reference="${BACKUP_COPY[-1]}" "$file" 2>/dev/null || true + else + rm -f "$tmpfile" + fi + + # Disarm the local ERR trap and re-arm the global one + trap - ERR + trap restore_backups ERR +} + +# --------------------------------------------------------------------------- +# Post-migration warnings +# --------------------------------------------------------------------------- +check_and_warn() { + local file="$1" + + # Warn if a rule path starts with a macro variable. + # Only flag lines where @@{...} appears at the very start (after optional whitespace); + # mid-path macros like /path/@@{VAR}/sub are valid and must not be flagged. + local macro_rules + macro_rules="$(grep -nE '^[[:space:]]*@@\{[^}]+\}' "$file" 2>/dev/null || true)" + if [[ -n "$macro_rules" ]]; then + info "WARNING ($file): the following rule paths start with a macro variable." \ + "Rewrite them so the path begins with a literal '/':" + echo "$macro_rules" >&2 + fi + + # Warn if a group name contains non-alphanumeric characters. + # Require an uppercase first letter to avoid false positives on config option names. + # Underscores are accepted by AIDE 0.19.2; only '-' and '.' cause parse errors. + local bad_groups + bad_groups="$(grep -nE '^[A-Z][A-Za-z0-9]*[-.][A-Za-z0-9][^=]*[[:space:]]*=' \ + "$file" 2>/dev/null || true)" + if [[ -n "$bad_groups" ]]; then + info "WARNING ($file): the following group names contain non-alphanumeric characters." \ + "Rename groups and all their references to [A-Za-z0-9] only:" + echo "$bad_groups" >&2 + fi +} + +# --------------------------------------------------------------------------- +# Database reinitialisation +# --------------------------------------------------------------------------- + +# expand_aide_macros CONFIG VALUE +# Expand @@{NAME} references in VALUE using @@define lines from CONFIG. +expand_aide_macros() { + local config="$1" value="$2" + local key val + while IFS= read -r defline; do + key="$(echo "$defline" | awk '{print $2}')" + val="$(echo "$defline" | awk '{$1=$2=""; print substr($0,3)}')" + value="${value//@@\{${key}\}/$val}" + done < <(grep -E '^[[:space:]]*@@define[[:space:]]' "$config" || true) + echo "$value" +} + +# reinit_database CONFIG_FILE +# Backup the existing database, run aide --init, move the new DB into place. +reinit_database() { + local config="$1" + + # Parse database_in path (file: URLs only) + local raw_in + raw_in="$(grep -E '^[[:space:]]*database_in[[:space:]]*=' "$config" | \ + head -1 | sed -E 's/^[^=]+=file://')" || true + [[ -z "$raw_in" ]] && { info "WARNING: database_in not found in config; skipping reinit"; return 0; } + local db_in + db_in="$(expand_aide_macros "$config" "$raw_in")" + + # Parse database_out path (file: URLs only) + local raw_out + raw_out="$(grep -E '^[[:space:]]*database_out[[:space:]]*=' "$config" | \ + head -1 | sed -E 's/^[^=]+=file://')" || true + [[ -z "$raw_out" ]] && { info "WARNING: database_out not found in config; skipping reinit"; return 0; } + local db_out + db_out="$(expand_aide_macros "$config" "$raw_out")" + + if [[ ! -f "$db_in" ]]; then + info "no existing database at $db_in; run 'aide --init -c $config' when ready" + return 0 + fi + + info "reinitialising database (this may take several minutes)..." + backup_file "$db_in" + aide --init -c "$config" + if [[ ! -f "$db_out" ]]; then + die "aide --init completed but output database not found at $db_out" + fi + mv -- "$db_out" "$db_in" + chmod 0600 "$db_in" + chown root:root "$db_in" + info "database reinitialised: $db_in" +} + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- +main() { + # CLI flags are out of scope for this script + info "Note: This script migrates aide config files only." \ + "If you use '--verbose' or '--report' flags in wrapper scripts," \ + "cron jobs, or systemd units, remove those flags manually." + + # Argument parsing + local config_file="" + while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) DRY_RUN=true; shift ;; + --skip-init) SKIP_INIT=true; shift ;; + -h|--help) usage ;; + --) shift; break ;; + -*) die "unknown option: $1" ;; + *) config_file="$1"; shift ;; + esac + done + [[ $# -gt 0 ]] && die "unexpected argument: $1" + [[ -z "$config_file" ]] && usage + [[ -f "$config_file" ]] || die "config file not found: $config_file" + [[ -r "$config_file" ]] || die "config file not readable: $config_file" + $DRY_RUN || [[ -w "$config_file" ]] || die "config file not writable: $config_file" + + # Verify aide >= 0.19 is installed + local aide_ver + aide_ver="$(aide --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)" || true + if [[ -z "$aide_ver" ]]; then + info "aide not found; skipping migration" + exit 0 + fi + local aide_major aide_minor + aide_major="${aide_ver%%.*}" + aide_minor="${aide_ver#*.}" + if [[ "$aide_major" -lt 1 && "$aide_minor" -lt 19 ]]; then + info "aide $aide_ver < 0.19; skipping migration" + exit 0 + fi + + $DRY_RUN && info "DRY-RUN mode: no files will be modified" + + # Global ERR trap for cleanup + trap restore_backups ERR + + # Collect all config files to process + local -a config_files=("$config_file") + while IFS= read -r inc; do + [[ -f "$inc" ]] && config_files+=("$inc") + done < <(extract_includes "$config_file") + + # Migrate each config file + local f + for f in "${config_files[@]}"; do + migrate_config_file "$f" + done + + # Post-migration warnings + for f in "${config_files[@]}"; do + check_and_warn "$f" + done + + # Validate the resulting config + if ! $DRY_RUN; then + if ! aide --config-check -c "$config_file" >/dev/null 2>&1; then + info "ERROR: aide --config-check failed after migration; restoring all backups" + restore_backups + exit 1 + fi + info "aide --config-check passed" + fi + + # Database reinit + if $REINIT_NEEDED && ! $SKIP_INIT && ! $DRY_RUN; then + reinit_database "$config_file" + elif $REINIT_NEEDED && $SKIP_INIT && ! $DRY_RUN; then + info "database reinitialisation required but --skip-init set;" \ + "run 'aide --init -c $config_file' manually" + elif $REINIT_NEEDED && $DRY_RUN; then + info "would require database reinitialisation after migration" + fi + + info "migration complete" +} + +main "$@" diff --git a/SOURCES/aide-static-analysis.patch b/SOURCES/aide-static-analysis.patch deleted file mode 100644 index 78b79ce..0000000 --- a/SOURCES/aide-static-analysis.patch +++ /dev/null @@ -1,171 +0,0 @@ -Only in b: config.log -diff --color -ru a/contrib/sshaide.sh b/contrib/sshaide.sh ---- a/contrib/sshaide.sh 2016-07-25 22:56:55.000000000 +0200 -+++ b/contrib/sshaide.sh 2021-05-20 11:11:24.112542472 +0200 -@@ -260,7 +260,7 @@ - _randword=`grep -n . ${_wordlist} | grep "^${_linenum}:" | cut -d: -f2` - - # If $_randword has anything other than lower-case chars, try again -- (echo ${_randword} | LC_ALL=C grep '[^a-z]' 2>&1 >> /dev/null \ -+ ({ echo ${_randword} | LC_ALL=C grep '[^a-z]' 2>&1; } >> /dev/null \ - && gen_rand_word ) || \ - - # Return the word -diff --color -ru a/src/commandconf.c b/src/commandconf.c ---- a/src/commandconf.c 2021-05-20 10:37:53.842382143 +0200 -+++ b/src/commandconf.c 2021-05-25 14:16:43.278526146 +0200 -@@ -313,7 +313,7 @@ - } else { - /* gzread returns 0 even if uncompressed bytes were read*/ - error(240,"nread=%d,strlen(buf)=%lu,errno=%s,gzerr=%s\n", -- retval,(unsigned long)strnlen((char*)buf, max_size), -+ retval,(unsigned long)strnlen((char*)buf, retval), - strerror(errno),gzerror(*db_gzp,&err)); - if(retval==0){ - retval=strnlen((char*)buf, max_size); -@@ -836,6 +836,11 @@ - } - break; - } -+ default: { -+ error(0,"Unsupported dbtype.\n"); -+ free(u); -+ break; -+ } - } - } - free(val); -@@ -900,7 +905,7 @@ - } else { - error_init(u,0); - } -- -+ free(u->value); - free(u); - } - -diff --color -ru a/src/db_disk.c b/src/db_disk.c ---- a/src/db_disk.c 2021-05-20 10:37:53.842382143 +0200 -+++ b/src/db_disk.c 2021-05-20 12:37:00.081493364 +0200 -@@ -125,10 +125,10 @@ - - ret = (char *) malloc (len); - ret[0] = (char) 0; -- strncpy(ret, conf->root_prefix, conf->root_prefix_length+1); -- strncat (ret, r->path, len2); -+ strcpy(ret, conf->root_prefix); -+ strcat (ret, r->path); - if (r->path[len2 - 1] != '/') { -- strncat (ret, "/", 1); -+ strcat (ret, "/"); - } - strcat (ret, s); - return ret; -@@ -207,8 +207,8 @@ - if (!root_handled) { - root_handled = 1; - fullname=malloc((conf->root_prefix_length+2)*sizeof(char)); -- strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1); -- strncat (fullname, "/", 1); -+ strcpy(fullname, conf->root_prefix); -+ strcat (fullname, "/"); - if (!get_file_status(&fullname[conf->root_prefix_length], &fs)) { - add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode); - error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add, -@@ -346,8 +346,8 @@ - error (255, "r->childs %p, r->parent %p,r->checked %i\n", - r->childs, r->parent, r->checked); - fullname=malloc((conf->root_prefix_length+strlen(r->path)+1)*sizeof(char)); -- strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1); -- strncat(fullname, r->path, strlen(r->path)); -+ strcpy(fullname, conf->root_prefix); -+ strcat(fullname, r->path); - dirh=open_dir(fullname); - if (! dirh) { - -@@ -441,8 +441,8 @@ - - - char* fullname=malloc((conf->root_prefix_length+2)*sizeof(char)); -- strncpy(fullname, conf->root_prefix, conf->root_prefix_length+1); -- strncat (fullname, "/", 1); -+ strcpy(fullname, conf->root_prefix); -+ strcat (fullname, "/"); - dirh=open_dir(fullname); - free(fullname); - -diff --color -ru a/src/error.c b/src/error.c ---- a/src/error.c 2021-05-20 10:37:53.836382037 +0200 -+++ b/src/error.c 2021-05-21 11:49:09.781313097 +0200 -@@ -125,7 +125,7 @@ - fh=be_init(0,url,0); - if(fh!=NULL) { - conf->report_fd=list_append(conf->report_fd,(void*)fh); -- conf->report_url=list_append(conf->report_url,(void*)url); -+ conf->report_url=list_append(conf->report_url,(void*)strdup(url)); - return RETOK; - } - -diff --color -ru a/src/util.c b/src/util.c ---- a/src/util.c 2021-05-20 10:37:53.843382160 +0200 -+++ b/src/util.c 2021-05-25 11:04:39.507278771 +0200 -@@ -105,13 +105,15 @@ - for(i=0;r[0]!='/'&&r[0]!='\0';r++,i++); - if(r[0]=='\0'){ - error(0,"Invalid file-URL,no path after hostname: file:%s\n",t); -+ free(u); -+ free(val_copy); - free(hostname); - return NULL; - } - u->value=strdup(r); - r[0]='\0'; - if(gethostname(hostname,MAXHOSTNAMELEN)==-1){ -- strncpy(hostname,"localhost", 10); -+ strncpy(hostname,"localhost",MAXHOSTNAMELEN); - } - - if( (strcmp(t,"localhost")==0)||(strcmp(t,hostname)==0)){ -@@ -119,6 +121,9 @@ - break; - } else { - error(0,"Invalid file-URL, cannot use hostname other than localhost or %s: file:%s\n",hostname,u->value); -+ free(u->value); -+ free(u); -+ free(val_copy); - free(hostname); - return NULL; - } -@@ -229,6 +234,10 @@ - int i=0; - - pc=(char*)malloc(sizeof(char)*11); -+ if (!pc) { -+ error(0, "Memory allocation failed.\n"); -+ return NULL; -+ } - for(i=0;i<10;i++){ - pc[i]='-'; - } -@@ -369,14 +378,17 @@ - - if (path != NULL) { - if (path[0] == '~') { -- if((homedir=getenv("HOME")) != NULL) { -+ if ((homedir=getenv("HOME")) != NULL) { - path_len = strlen(path+sizeof(char)); - homedir_len = strlen(homedir); - full_len = homedir_len+path_len; - full = malloc(sizeof(char) * (full_len+1)); -- strncpy(full, homedir, homedir_len); -- strncpy(full+homedir_len, path+sizeof(char), path_len); -- full[full_len] = '\0'; -+ if (!full) { -+ error(0, "Memory allocation failed.\n"); -+ return path; -+ } -+ strcpy(full, homedir); -+ strcat(full, path+sizeof(char)); - free(path); - /* Don't free(homedir); because it is not safe on some platforms */ - path = full; diff --git a/SOURCES/aide-tmpfiles.conf b/SOURCES/aide-tmpfiles.conf new file mode 100644 index 0000000..ec8f4b4 --- /dev/null +++ b/SOURCES/aide-tmpfiles.conf @@ -0,0 +1,2 @@ +d /var/log/aide 0700 root root - +d /var/lib/aide 0700 root root - diff --git a/SOURCES/aide.conf b/SOURCES/aide.conf index a6d6ce0..1f8a145 100644 --- a/SOURCES/aide.conf +++ b/SOURCES/aide.conf @@ -4,7 +4,7 @@ @@define LOGDIR /var/log/aide # The location of the database to be read. -database=file:@@{DBDIR}/aide.db.gz +database_in=file:@@{DBDIR}/aide.db.gz # The location of the database to be written. #database_out=sql:host:port:database:login_name:passwd:table @@ -14,19 +14,49 @@ database_out=file:@@{DBDIR}/aide.db.new.gz # Whether to gzip the output to database gzip_dbout=yes +# Database attributes to include in report (H = all compiled hashsums, default) +database_attrs=H + +# Add metadata to database (version info, timestamps) +database_add_metadata=yes + +# Warn about unrestricted rules during config check (default: false) +config_check_warn_unrestricted_rules=false + +# Number of workers for parallel processing (default: 1, can use percentage) +num_workers=1 + # Default. -verbose=5 +log_level=warning +report_level=changed_attributes + +# Report format (plain or json) +report_format=plain + +# Group files in report by added/removed/changed +report_grouped=yes + +# Summarize changes in report +report_summarize_changes=yes + +# Don't report if no differences found +report_quiet=no + +# Report encoding (base64 is default, base16 available) +report_base16=no report_url=file:@@{LOGDIR}/aide.log report_url=stdout #report_url=stderr -#NOT IMPLEMENTED report_url=mailto:root@foo.com -#NOT IMPLEMENTED report_url=syslog:LOG_AUTH +#report_url=syslog:LOG_AUTH # These are the default rules. # +#ftype: file type +#fstype: file system type (Linux-only) #p: permissions -#i: inode: +#i: inode +#l: link name (symbolic links only) #n: number of links #u: user #g: group @@ -35,270 +65,292 @@ report_url=stdout #m: mtime #a: atime #c: ctime -#S: check for growing size #acl: Access Control Lists #selinux SELinux security context #xattrs: Extended file attributes -#md5: md5 checksum -#sha1: sha1 checksum +#e2fsattrs: file attributes on Linux file system +#caps: file capabilities (Linux-only) + +# Hashsums attributes (regular files only) #sha256: sha256 checksum #sha512: sha512 checksum -#rmd160: rmd160 checksum -#tiger: tiger checksum +#sha512_256: SHA-512 checksum truncated to 256 output bits +#sha3_256: SHA3-256 checksum (modern) +#sha3_512: SHA3-512 checksum (modern) +#stribog256: GOST R 34.11-2012, 256 bit +#stribog512: GOST R 34.11-2012, 512 bit -#haval: haval checksum (MHASH only) -#gost: gost checksum (MHASH only) -#crc32: crc32 checksum (MHASH only) -#whirlpool: whirlpool checksum (MHASH only) +# Special attributes for advanced use cases: +#I: ignore changed filename - detects moved files by inode +#growing: ignore growing file size/timestamps for logs +#compressed: ignore compression - compares uncompressed content +#ANF: allow new files - new files ignored in report +#ARF: allow removed files - missing files ignored in report -#R: p+i+n+u+g+s+m+c+acl+selinux+xattrs+md5 -#L: p+i+n+u+g+acl+selinux+xattrs -#E: Empty group -#>: Growing logfile p+u+g+i+n+S+acl+selinux+xattrs +# Default groups in AIDE v0.19: +# R = p+ftype+i+l+n+u+g+s+m+c+sha3_256+X +# L = p+ftype+i+l+n+u+g+X +# > = Growing file p+ftype+l+u+g+i+n+s+growing+X +# H = all compiled in (and not deprecated) hashsums +# X = acl+selinux+xattrs+e2fsattrs+caps (if compiled in) +# E = Empty group +# Use 'aide --version' to list the default compound groups. # You can create custom rules like this. -# With MHASH... -# ALLXTRAHASHES = sha1+rmd160+sha256+sha512+whirlpool+tiger+haval+gost+crc32 -ALLXTRAHASHES = sha1+rmd160+sha256+sha512+tiger -# Everything but access time (Ie. all changes) +# Note: Removed deprecated/removed hashsums (tiger, haval, crc32, crc32b, whirlpool, md5, sha1, rmd160, gost) +ALLXTRAHASHES = sha256+sha512+sha512_256+sha3_256+sha3_512+stribog256+stribog512 +# Everything but access time (Ie. all changes) - updated with modern hashsums EVERYTHING = R+ALLXTRAHASHES -# Sane -# NORMAL = R+sha512 -NORMAL = p+i+n+u+g+s+m+c+acl+selinux+xattrs+sha512 +# Base + sha512 (strong) +NORMAL = R+sha512-m-c -# For directories, don't bother doing hashes -DIR = p+i+n+u+g+acl+selinux+xattrs +# Content only - added file type and strong hash +CONTENT = ftype+sha512 -# Access control only -PERMS = p+u+g+acl+selinux+xattrs +# For directories, don't bother doing hashes - added file type and link name +DIR = ftype+p+i+l+n+u+g+acl+selinux+xattrs -# Logfile are special, in that they often change -LOG = p+u+g+n+S+acl+selinux+xattrs +# Access control only - added file type and link name +PERMS = ftype+p+u+g+acl+selinux+xattrs -# Content + file type. -CONTENT = sha512+ftype - -# Extended content + file type + access. -CONTENT_EX = sha512+ftype+p+u+g+n+acl+selinux+xattrs +# Logfiles are special, in that they often change due to log rotation +# Track only: permissions, file type, user, group, number of links, SELinux context, extended attributes +# Allow new files (ANF) and allow removed files (ARF) due to log rotation techniques +# Don't track: size, inodes, timestamps, checksums and some special attributes (these change frequently with log rotation) +LOG = p+ftype+u+g+n+ANF+ARF+selinux+xattrs # Some files get updated automatically, so the inode/ctime/mtime change -# but we want to know when the data inside them changes -DATAONLY = p+n+u+g+s+acl+selinux+xattrs+sha512 +# but we want to know when the data inside them changes - updated with modern hash +DATAONLY = ftype+p+l+n+u+g+s+acl+selinux+xattrs+sha256 # Next decide what directories/files you want in the database. -/boot CONTENT_EX -/opt CONTENT - -# Admins dot files constantly change, just check perms -/root/\..* PERMS -!/root/.xauth* -# Otherwise get all of /root. -/root CONTENT_EX - +/boot NORMAL +/bin NORMAL +/sbin NORMAL +/lib NORMAL +/lib64 NORMAL +# Monitor /opt selectively to avoid noise from auto-updating applications +/opt CONTENT +/usr NORMAL # These are too volatile !/usr/src !/usr/tmp -# Otherwise get all of /usr. -/usr CONTENT_EX +# Admins dot files constantly change, just check perms +/root/\..* PERMS +!/root/.xauth* +/root NORMAL + +# Check only permissions, inode, user and group for /etc, but +# cover some important files closely. +!/etc/mtab +# Ignore backup files +!/etc/.*~ # trusted databases -/etc/hosts$ CONTENT_EX -/etc/host.conf$ CONTENT_EX -/etc/hostname$ CONTENT_EX -/etc/issue$ CONTENT_EX -/etc/issue.net$ CONTENT_EX -/etc/protocols$ CONTENT_EX -/etc/services$ CONTENT_EX -/etc/localtime$ CONTENT_EX -/etc/alternatives CONTENT_EX -/etc/sysconfig CONTENT_EX -/etc/mime.types$ CONTENT_EX -/etc/terminfo CONTENT_EX -/etc/exports$ CONTENT_EX -/etc/fstab$ CONTENT_EX -/etc/passwd$ CONTENT_EX -/etc/group$ CONTENT_EX -/etc/gshadow$ CONTENT_EX -/etc/shadow$ CONTENT_EX -/etc/subgid$ CONTENT_EX -/etc/subuid$ CONTENT_EX -/etc/security/opasswd$ CONTENT_EX -/etc/skel CONTENT_EX -/etc/sssd CONTENT_EX -/etc/machine-id$ CONTENT_EX -/etc/swid CONTENT_EX -/etc/system-release-cpe$ CONTENT_EX -/etc/shells$ CONTENT_EX -/etc/tmux.conf$ CONTENT_EX -/etc/xattr.conf$ CONTENT_EX +/etc/hosts$ NORMAL +/etc/host.conf$ NORMAL +/etc/hostname$ NORMAL +/etc/issue$ NORMAL +/etc/issue.net$ NORMAL +/etc/protocols$ NORMAL +/etc/services$ NORMAL +/etc/localtime$ NORMAL +/etc/alternatives NORMAL +/etc/mime.types$ NORMAL +/etc/terminfo NORMAL +/etc/exports$ NORMAL +/etc/fstab$ NORMAL +/etc/passwd$ NORMAL +/etc/group$ NORMAL +/etc/gshadow$ NORMAL +/etc/shadow$ NORMAL +/etc/subgid$ NORMAL +/etc/subuid$ NORMAL +/etc/skel NORMAL +/etc/sssd NORMAL +/etc/swid NORMAL +/etc/system-release-cpe$ NORMAL +/etc/tmux.conf$ NORMAL +/etc/xattr.conf$ NORMAL # networking -/etc/firewalld CONTENT_EX +/etc/firewalld NORMAL !/etc/NetworkManager/system-connections -/etc/NetworkManager CONTENT_EX -/etc/networks$ CONTENT_EX -/etc/dhcp CONTENT_EX -/etc/wpa_supplicant CONTENT_EX +/etc/NetworkManager NORMAL +/etc/networks$ NORMAL +/etc/dhcp NORMAL +/etc/wpa_supplicant NORMAL /etc/resolv.conf$ DATAONLY -/etc/nscd.conf$ CONTENT_EX # logins and accounts -/etc/login.defs$ CONTENT_EX -/etc/libuser.conf$ CONTENT_EX +/etc/login.defs$ NORMAL +/etc/libuser.conf$ NORMAL /var/log/faillog$ PERMS /var/log/lastlog$ PERMS /var/run/faillock PERMS -/etc/pam.d CONTENT_EX -/etc/security CONTENT_EX -/etc/securetty$ CONTENT_EX -/etc/polkit-1 CONTENT_EX -/etc/sudo.conf$ CONTENT_EX -/etc/sudoers$ CONTENT_EX -/etc/sudoers.d CONTENT_EX +/etc/pam.d NORMAL +/etc/security NORMAL +/etc/securetty$ NORMAL +/etc/polkit-1 NORMAL +/etc/sudo.conf$ NORMAL +/etc/sudoers$ NORMAL +/etc/sudoers.d NORMAL -# Shell/X startup files -/etc/profile$ CONTENT_EX -/etc/profile.d CONTENT_EX -/etc/bashrc$ CONTENT_EX -/etc/bash_completion.d CONTENT_EX -/etc/zprofile$ CONTENT_EX -/etc/zshrc$ CONTENT_EX -/etc/zlogin$ CONTENT_EX -/etc/zlogout$ CONTENT_EX -/etc/X11 CONTENT_EX +# Shell/X starting files +/etc/profile$ NORMAL +/etc/profile.d NORMAL +/etc/bashrc$ NORMAL +/etc/bash_completion.d NORMAL +/etc/zprofile$ NORMAL +/etc/zshrc$ NORMAL +/etc/zlogin$ NORMAL +/etc/zlogout$ NORMAL +/etc/X11 NORMAL +/etc/shells$ NORMAL # Pkg manager -/etc/dnf CONTENT_EX -/etc/yum.conf$ CONTENT_EX -/etc/yum CONTENT_EX -/etc/yum.repos.d CONTENT_EX +/etc/dnf NORMAL +/etc/yum.repos.d NORMAL + +# auditing +# AIDE produces an audit record, so this becomes perpetual motion. +/var/log/audit PERMS +/etc/audit NORMAL +/etc/libaudit.conf$ NORMAL +/etc/aide.conf$ NORMAL + +# System logs with proper logrotate handling +/etc/rsyslog.conf$ NORMAL +/etc/rsyslog.d NORMAL +/etc/logrotate.conf$ NORMAL +/etc/logrotate.d NORMAL +/etc/systemd/journald.conf$ NORMAL + +# Log directory +/var/log LOG +# Journal files - exclude xattrs and link count due to systemd journal's user.crtime_usec extended attribute changes and new directory creation +/var/log/journal LOG-xattrs-n + +/var/run/utmp LOG + + +# secrets +/etc/pkcs11 NORMAL +/etc/pki NORMAL +/etc/ssl NORMAL +/etc/certmonger NORMAL +/var/lib/systemd/random-seed$ PERMS + +# init system +/etc/systemd NORMAL +/etc/sysconfig NORMAL +/etc/rc.d NORMAL +/etc/tmpfiles.d NORMAL +/etc/machine-id$ NORMAL + +# boot config +/etc/default NORMAL +/etc/grub.d NORMAL +/etc/grub2.cfg$ NORMAL +/etc/dracut.conf$ NORMAL +/etc/dracut.conf.d NORMAL + +# glibc linker +/etc/ld.so.cache$ NORMAL +/etc/ld.so.conf$ NORMAL +/etc/ld.so.conf.d NORMAL +/etc/ld.so.preload$ NORMAL + +# kernel config +/etc/sysctl.conf$ NORMAL +/etc/sysctl.d NORMAL +/etc/modprobe.d NORMAL +/etc/modules-load.d NORMAL +/etc/depmod.d NORMAL +/etc/udev NORMAL +/etc/crypttab$ NORMAL + +#### Daemons #### + +# cron jobs +/var/spool/at CONTENT +/etc/at.allow$ CONTENT +/etc/at.deny$ CONTENT +/etc/anacrontab$ NORMAL +/etc/cron.allow$ NORMAL +/etc/cron.deny$ NORMAL +/etc/cron.d NORMAL +/etc/cron.daily NORMAL +/etc/cron.hourly NORMAL +/etc/cron.monthly NORMAL +/etc/cron.weekly NORMAL +/etc/crontab$ NORMAL +/var/spool/cron/root CONTENT + +# time keeping +/etc/chrony.conf$ NORMAL +/etc/chrony.keys$ NORMAL + +# mail +/etc/aliases$ NORMAL +/etc/aliases.db$ NORMAL +/etc/postfix NORMAL + +# ssh +/etc/ssh/sshd_config$ NORMAL +/etc/ssh/ssh_config$ NORMAL + +# stunnel +/etc/stunnel NORMAL + +# ftp +/etc/vsftpd CONTENT + +# printing +/etc/cups NORMAL +/etc/cupshelpers NORMAL +/etc/avahi NORMAL + +# web server +/etc/httpd NORMAL + +# dns +/etc/named NORMAL +/etc/named.conf$ NORMAL +/etc/named.iscdlv.key$ NORMAL +/etc/named.rfc1912.zones$ NORMAL +/etc/named.root.key$ NORMAL + +# xinetd +/etc/xinetd.conf$ NORMAL +/etc/xinetd.d NORMAL + +# IPsec +/etc/ipsec.conf$ NORMAL +/etc/ipsec.secrets$ NORMAL +/etc/ipsec.d NORMAL + +# USBGuard +/etc/usbguard NORMAL + +# Now everything else +/etc PERMS # This gets new/removes-old filenames daily !/var/log/sa # As we are checking it, we've truncated yesterdays size to zero. !/var/log/aide.log -# auditing -# AIDE produces an audit record, so this becomes perpetual motion. -/var/log/audit PERMS -/etc/audit CONTENT_EX -/etc/libaudit.conf$ CONTENT_EX -/etc/aide.conf$ CONTENT_EX - -# System logs -/etc/rsyslog.conf$ CONTENT_EX -/etc/rsyslog.d CONTENT_EX -/etc/logrotate.conf$ CONTENT_EX -/etc/logrotate.d CONTENT_EX -/etc/systemd/journald.conf$ CONTENT_EX -/var/log LOG+ANF+ARF -/var/run/utmp LOG - -# secrets -/etc/pkcs11 CONTENT_EX -/etc/pki CONTENT_EX -/etc/crypto-policies CONTENT_EX -/etc/certmonger CONTENT_EX -/var/lib/systemd/random-seed$ PERMS - -# init system -/etc/systemd CONTENT_EX -/etc/rc.d CONTENT_EX -/etc/tmpfiles.d CONTENT_EX - -# boot config -/etc/default CONTENT_EX -/etc/grub.d CONTENT_EX -/etc/dracut.conf$ CONTENT_EX -/etc/dracut.conf.d CONTENT_EX - -# glibc linker -/etc/ld.so.cache$ CONTENT_EX -/etc/ld.so.conf$ CONTENT_EX -/etc/ld.so.conf.d CONTENT_EX -/etc/ld.so.preload$ CONTENT_EX - -# kernel config -/etc/sysctl.conf$ CONTENT_EX -/etc/sysctl.d CONTENT_EX -/etc/modprobe.d CONTENT_EX -/etc/modules-load.d CONTENT_EX -/etc/depmod.d CONTENT_EX -/etc/udev CONTENT_EX -/etc/crypttab$ CONTENT_EX - -#### Daemons #### - -# cron jobs -/etc/at.allow$ CONTENT -/etc/at.deny$ CONTENT -/etc/anacrontab$ CONTENT_EX -/etc/cron.allow$ CONTENT_EX -/etc/cron.deny$ CONTENT_EX -/etc/cron.d CONTENT_EX -/etc/cron.daily CONTENT_EX -/etc/cron.hourly CONTENT_EX -/etc/cron.monthly CONTENT_EX -/etc/cron.weekly CONTENT_EX -/etc/crontab$ CONTENT_EX -/var/spool/cron/root CONTENT - -# time keeping -/etc/chrony.conf$ CONTENT_EX -/etc/chrony.keys$ CONTENT_EX - -# mail -/etc/aliases$ CONTENT_EX -/etc/aliases.db$ CONTENT_EX -/etc/postfix CONTENT_EX - -# ssh -/etc/ssh/sshd_config$ CONTENT_EX -/etc/ssh/ssh_config$ CONTENT_EX - -# stunnel -/etc/stunnel CONTENT_EX - -# printing -/etc/cups CONTENT_EX -/etc/cupshelpers CONTENT_EX -/etc/avahi CONTENT_EX - -# web server -/etc/httpd CONTENT_EX - -# dns -/etc/named CONTENT_EX -/etc/named.conf$ CONTENT_EX -/etc/named.iscdlv.key$ CONTENT_EX -/etc/named.rfc1912.zones$ CONTENT_EX -/etc/named.root.key$ CONTENT_EX - -# xinetd -/etc/xinetd.conf$ CONTENT_EX -/etc/xinetd.d CONTENT_EX - -# IPsec -/etc/ipsec.conf$ CONTENT_EX -/etc/ipsec.secrets$ CONTENT_EX -/etc/ipsec.d CONTENT_EX - -# USB guard -/etc/usbguard CONTENT_EX - -# Ignore some files -!/boot/grub2/grubenv$ -!/etc/mtab$ -!/etc/.*~ - -# Now everything else -/etc PERMS - # With AIDE's default verbosity level of 5, these would give lots of # warnings upon tree traversal. It might change with future version. # #=/lost\+found DIR #=/home DIR + +# Ditto /var/log/sa reason... +!/var/log/httpd +# /boot/grub2/grubenv's timestamp is getting modified continuously due to "boot_success" implementation +!/boot/grub2/grubenv diff --git a/SOURCES/coverity.patch b/SOURCES/coverity.patch deleted file mode 100644 index 9b981be..0000000 --- a/SOURCES/coverity.patch +++ /dev/null @@ -1,642 +0,0 @@ -diff -up ./include/be.h.coverity ./include/be.h ---- ./include/be.h.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./include/be.h 2018-10-10 19:27:18.680632681 +0200 -@@ -22,6 +22,6 @@ - #define _BE_H_INCLUDED - #include "db_config.h" - --FILE* be_init(int inout,url_t* u,int iszipped); -+void* be_init(int inout,url_t* u,int iszipped); - - #endif /* _BE_H_INCLUDED */ -diff -up ./include/db_config.h.coverity ./include/db_config.h ---- ./include/db_config.h.coverity 2018-10-10 19:27:18.672632611 +0200 -+++ ./include/db_config.h 2018-10-10 19:27:18.681632689 +0200 -@@ -376,7 +376,7 @@ typedef struct db_config { - #endif - - url_t* initial_report_url; -- FILE* initial_report_fd; -+ void* initial_report_fd; - - /* report_url is a list of url_t*s */ - list* report_url; -diff -up ./src/aide.c.coverity ./src/aide.c ---- ./src/aide.c.coverity 2018-10-10 19:27:18.678632663 +0200 -+++ ./src/aide.c 2018-10-10 19:27:18.681632689 +0200 -@@ -278,7 +278,7 @@ static void setdefaults_before_config() - error(0,_("Couldn't get hostname")); - free(s); - } else { -- s=(char*)realloc((void*)s,strlen(s)+1); -+ // s=(char*)realloc((void*)s,strlen(s)+1); - do_define("HOSTNAME",s); - } - -@@ -506,8 +506,6 @@ static void setdefaults_after_config() - int main(int argc,char**argv) - { - int errorno=0; -- byte* dig=NULL; -- char* digstr=NULL; - - #ifdef USE_LOCALE - setlocale(LC_ALL,""); -@@ -544,6 +542,10 @@ int main(int argc,char**argv) - } - - errorno=commandconf('C',conf->config_file); -+ if (errorno==RETFAIL){ -+ error(0,_("Configuration error\n")); -+ exit(INVALID_CONFIGURELINE_ERROR); -+ } - - errorno=commandconf('D',""); - if (errorno==RETFAIL){ -@@ -594,6 +596,9 @@ int main(int argc,char**argv) - } - } - #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); -diff -up ./src/base64.c.coverity ./src/base64.c ---- ./src/base64.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/base64.c 2018-10-10 19:27:18.681632689 +0200 -@@ -209,6 +209,7 @@ byte* decode_base64(char* src,size_t ssi - case FAIL: - error(3, "decode_base64: Illegal character: %c\n", *inb); - error(230, "decode_base64: Illegal line:\n%s\n", src); -+ free(outbuf); - return NULL; - break; - case SKIP: -@@ -260,7 +261,7 @@ size_t length_base64(char* src,size_t ss - int l; - int left; - size_t pos; -- unsigned long triple; -+ //unsigned long triple; - - error(235, "decode base64\n"); - /* Exit on empty input */ -@@ -273,7 +274,7 @@ size_t length_base64(char* src,size_t ss - inb = src; - - l = 0; -- triple = 0; -+ //triple = 0; - pos=0; - left = ssize; - /* -@@ -293,7 +294,7 @@ size_t length_base64(char* src,size_t ss - case SKIP: - break; - default: -- triple = triple<<6 | (0x3f & i); -+ //triple = triple<<6 | (0x3f & i); - l++; - break; - } -@@ -302,10 +303,10 @@ size_t length_base64(char* src,size_t ss - switch(l) - { - case 2: -- triple = triple>>4; -+ //triple = triple>>4; - break; - case 3: -- triple = triple>>2; -+ //triple = triple>>2; - break; - default: - break; -@@ -314,7 +315,7 @@ size_t length_base64(char* src,size_t ss - { - pos++; - } -- triple = 0; -+ //triple = 0; - l = 0; - } - inb++; -diff -up ./src/be.c.coverity ./src/be.c ---- ./src/be.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/be.c 2018-10-10 19:27:18.681632689 +0200 -@@ -117,9 +117,9 @@ static char* get_first_value(char** in){ - - #endif - --FILE* be_init(int inout,url_t* u,int iszipped) -+void* be_init(int inout,url_t* u,int iszipped) - { -- FILE* fh=NULL; -+ void* fh=NULL; - long a=0; - char* err=NULL; - int fd; -diff -up ./src/commandconf.c.coverity ./src/commandconf.c ---- ./src/commandconf.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/commandconf.c 2018-10-10 19:27:18.682632698 +0200 -@@ -106,7 +106,7 @@ int commandconf(const char mode,const ch - rv=0; - } else { - -- rv=access(config,R_OK); -+ if (config != NULL) rv=access(config,R_OK); - if(rv==-1){ - error(0,_("Cannot access config file: %s: %s\n"),config,strerror(errno)); - } -@@ -166,14 +166,11 @@ int commandconf(const char mode,const ch - int conf_input_wrapper(char* buf, int max_size, FILE* in) - { - int retval=0; -- int c=0; -- char* tmp=NULL; -- void* key=NULL; -- int keylen=0; - - /* FIXME Add support for gzipped config. :) */ - #ifdef WITH_MHASH - /* Read a character at a time until we are doing md */ -+ int c=0; - if(conf->do_configmd){ - retval=fread(buf,1,max_size,in); - }else { -@@ -185,6 +182,9 @@ int conf_input_wrapper(char* buf, int ma - #endif - - #ifdef WITH_MHASH -+ char* tmp=NULL; -+ void* key=NULL; -+ int keylen=0; - if(conf->do_configmd||conf->config_check){ - if(((conf->do_configmd==1)&&conf->config_check)||!conf->confmd){ - if(conf->do_configmd==1){ -@@ -276,6 +276,9 @@ int db_input_wrapper(char* buf, int max_ - #endif - break; - } -+ default: { -+ return 0; -+ } - } - - #ifdef WITH_CURL -@@ -651,7 +654,6 @@ int handle_endif(int doit,int allow_else - case 0 : { - conferror("@@endif or @@else expected"); - return -1; -- count=0; - } - - default : { -@@ -816,6 +818,7 @@ void do_dbdef(int dbtype,char* val) - if(u==NULL||u->type==url_unknown||u->type==url_stdout - ||u->type==url_stderr) { - error(0,_("Unsupported input URL-type:%s\n"),val); -+ free(u); - } - else { - *conf_db_url=u; -@@ -825,6 +828,7 @@ void do_dbdef(int dbtype,char* val) - case DB_WRITE: { - if(u==NULL||u->type==url_unknown||u->type==url_stdin){ - error(0,_("Unsupported output URL-type:%s\n"),val); -+ free(u); - } - else{ - conf->db_out_url=u; -@@ -848,6 +852,7 @@ void do_dbindef(char* val) - if(u==NULL||u->type==url_unknown||u->type==url_stdout - ||u->type==url_stderr) { - error(0,_("Unsupported input URL-type:%s\n"),val); -+ free(u); - } - else { - conf->db_in_url=u; -@@ -869,6 +874,7 @@ void do_dboutdef(char* val) - * both input and output urls */ - if(u==NULL||u->type==url_unknown||u->type==url_stdin){ - error(0,_("Unsupported output URL-type:%s\n"),val); -+ free(u); - } - else{ - conf->db_out_url=u; -@@ -894,7 +900,8 @@ void do_repurldef(char* val) - } else { - error_init(u,0); - } -- -+ -+ free(u); - } - - void do_verbdef(char* val) -@@ -984,7 +991,7 @@ void do_report_ignore_e2fsattrs(char* va - break; - } - } -- *val++; -+ val++; - } - } - #endif -diff -up ./src/compare_db.c.coverity ./src/compare_db.c ---- ./src/compare_db.c.coverity 2018-10-10 19:27:18.673632619 +0200 -+++ ./src/compare_db.c 2018-10-10 19:27:18.682632698 +0200 -@@ -312,7 +312,7 @@ static int acl2array(acl_type* acl, char - if (conf->syslog_format) { - *values = malloc(2 * sizeof(char*)); - -- char *A, *D = ""; -+ char *A= "", *D = ""; - - if (acl->acl_a) { A = acl->acl_a; } - if (acl->acl_d) { D = acl->acl_d; } -diff -up ./src/conf_lex.l.coverity ./src/conf_lex.l ---- ./src/conf_lex.l.coverity 2018-10-10 19:27:18.673632619 +0200 -+++ ./src/conf_lex.l 2018-10-10 19:27:18.682632698 +0200 -@@ -133,7 +133,7 @@ int var_in_conflval=0; - [\ \t]*\n { - conf_lineno++; - return (TNEWLINE); -- BEGIN 0; -+// BEGIN 0; - } - - \+ { -diff -up ./src/db.c.coverity ./src/db.c ---- ./src/db.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/db.c 2018-10-10 19:27:18.683632707 +0200 -@@ -27,6 +27,7 @@ - #include "db_file.h" - #include "db_disk.h" - #include "md.h" -+#include "fopen.h" - - #ifdef WITH_PSQL - #include "db_sql.h" -@@ -269,6 +270,9 @@ db_line* db_readline(int db){ - db_order=&(conf->db_new_order); - break; - } -+ default: { -+ return NULL; -+ } - } - - switch (db_url->type) { -@@ -368,7 +372,7 @@ db_line* db_char2line(char** ss,int db){ - - int i; - db_line* line=(db_line*)malloc(sizeof(db_line)*1); -- int* db_osize=0; -+ int* db_osize=NULL; - DB_FIELD** db_order=NULL; - - switch (db) { -@@ -382,6 +386,10 @@ db_line* db_char2line(char** ss,int db){ - db_order=&(conf->db_new_order); - break; - } -+ default: { -+ free(line); -+ return NULL; -+ } - } - - -@@ -601,7 +609,9 @@ db_line* db_char2line(char** ss,int db){ - size_t vsz = 0; - - tval = strtok(NULL, ","); -- line->xattrs->ents[num].key = db_readchar(strdup(tval)); -+ char * tmp = strdup(tval); -+ line->xattrs->ents[num].key = db_readchar(tmp); -+ free(tmp); - tval = strtok(NULL, ","); - val = base64tobyte(tval, strlen(tval), &vsz); - line->xattrs->ents[num].val = val; -@@ -648,6 +658,8 @@ db_line* db_char2line(char** ss,int db){ - - default : { - error(0,_("Not implemented in db_char2line %i \n"),(*db_order)[i]); -+ free_db_line(line); -+ free(line); - return NULL; - } - -@@ -826,7 +838,7 @@ void db_close() { - case url_ftp: - { - if (conf->db_out!=NULL) { -- url_fclose(conf->db_out); -+ url_fclose((URL_FILE*)conf->db_out); - } - break; - } -diff -up ./src/db_disk.c.coverity ./src/db_disk.c ---- ./src/db_disk.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/db_disk.c 2018-10-10 19:28:00.108995089 +0200 -@@ -79,9 +79,15 @@ static DIR *open_dir(char* path) { - - static void next_in_dir (void) - { -+ - #ifdef HAVE_READDIR_R -- if (dirh != NULL) -+ if (dirh != NULL) { -+#pragma GCC diagnostic push -+#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - rdres = AIDE_READDIR_R_FUNC (dirh, entp, resp); -+#pragma GCC diagnostic pop -+ } -+ - #else - #ifdef HAVE_READDIR - if (dirh != NULL) { -diff -up ./src/db_file.c.coverity ./src/db_file.c ---- ./src/db_file.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/db_file.c 2018-10-10 19:27:18.683632707 +0200 -@@ -171,7 +171,7 @@ int dofprintf( const char* s,...) - int db_file_read_spec(int db){ - - int i=0; -- int* db_osize=0; -+ int* db_osize=NULL; - DB_FIELD** db_order=NULL; - - switch (db) { -@@ -187,6 +187,9 @@ int db_file_read_spec(int db){ - db_lineno=&db_new_lineno; - break; - } -+ default: { -+ return RETFAIL; -+ } - } - - *db_order=(DB_FIELD*) malloc(1*sizeof(DB_FIELD)); -@@ -198,13 +201,10 @@ int db_file_read_spec(int db){ - int l; - - -- /* Yes... we do not check if realloc returns nonnull */ -- -- *db_order=(DB_FIELD*) -- realloc((void*)*db_order, -+ void * tmp = realloc((void*)*db_order, - ((*db_osize)+1)*sizeof(DB_FIELD)); -- -- if(*db_order==NULL){ -+ if (tmp != NULL) *db_order=(DB_FIELD*) tmp; -+ else { - return RETFAIL; - } - -@@ -291,8 +291,8 @@ char** db_readline_file(int db){ - int* domd=NULL; - #ifdef WITH_MHASH - MHASH* md=NULL; --#endif - char** oldmdstr=NULL; -+#endif - int* db_osize=0; - DB_FIELD** db_order=NULL; - FILE** db_filep=NULL; -@@ -302,9 +302,9 @@ char** db_readline_file(int db){ - case DB_OLD: { - #ifdef WITH_MHASH - md=&(conf->dboldmd); -+ oldmdstr=&(conf->old_dboldmdstr); - #endif - domd=&(conf->do_dboldmd); -- oldmdstr=&(conf->old_dboldmdstr); - - db_osize=&(conf->db_in_size); - db_order=&(conf->db_in_order); -@@ -316,9 +316,9 @@ char** db_readline_file(int db){ - case DB_NEW: { - #ifdef WITH_MHASH - md=&(conf->dbnewmd); -+ oldmdstr=&(conf->old_dbnewmdstr); - #endif - domd=&(conf->do_dbnewmd); -- oldmdstr=&(conf->old_dbnewmdstr); - - db_osize=&(conf->db_new_size); - db_order=&(conf->db_new_order); -@@ -328,7 +328,9 @@ char** db_readline_file(int db){ - break; - } - } -- -+ -+ if (db_osize == NULL) return NULL; -+ - if (*db_osize==0) { - db_buff(db,*db_filep); - -@@ -737,8 +739,6 @@ int db_writespec_file(db_config* dbconf) - int i=0; - int j=0; - int retval=1; -- void*key=NULL; -- int keylen=0; - struct tm* st; - time_t tim=time(&tim); - st=localtime(&tim); -@@ -750,6 +750,8 @@ int db_writespec_file(db_config* dbconf) - - #ifdef WITH_MHASH - /* From hereon everything must MD'd before write to db */ -+ void*key=NULL; -+ int keylen=0; - if((key=get_db_key())!=NULL){ - keylen=get_db_key_len(); - dbconf->do_dbnewmd=1; -diff -up ./src/do_md.c.coverity ./src/do_md.c ---- ./src/do_md.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/do_md.c 2018-10-10 19:27:18.683632707 +0200 -@@ -202,7 +202,6 @@ void calc_md(struct AIDE_STAT_TYPE* old_ - and we don't read from a pipe :) - */ - struct AIDE_STAT_TYPE fs; -- int sres=0; - int stat_diff,filedes; - #ifdef WITH_PRELINK - pid_t pid; -@@ -237,7 +236,7 @@ void calc_md(struct AIDE_STAT_TYPE* old_ - return; - } - -- sres=AIDE_FSTAT_FUNC(filedes,&fs); -+ AIDE_FSTAT_FUNC(filedes,&fs); - if(!(line->attr&DB_RDEV)) - fs.st_rdev=0; - -@@ -331,7 +330,7 @@ void calc_md(struct AIDE_STAT_TYPE* old_ - } - #endif - #endif /* not HAVE_MMAP */ -- buf=malloc(READ_BLOCK_SIZE); -+// buf=malloc(READ_BLOCK_SIZE); - #if READ_BLOCK_SIZE>SSIZE_MAX - #error "READ_BLOCK_SIZE" is too large. Max value is SSIZE_MAX, and current is READ_BLOCK_SIZE - #endif -diff -up ./src/gen_list.c.coverity ./src/gen_list.c ---- ./src/gen_list.c.coverity 2016-07-25 22:56:55.000000000 +0200 -+++ ./src/gen_list.c 2018-10-10 19:27:18.684632716 +0200 -@@ -843,15 +843,15 @@ static void add_file_to_tree(seltree* tr - DB_ATTR_TYPE localignorelist=0; - DB_ATTR_TYPE ignored_added_attrs, ignored_removed_attrs, ignored_changed_attrs; - -+ if(file==NULL){ -+ error(0, "add_file_to_tree was called with NULL db_line\n"); -+ } -+ - node=get_seltree_node(tree,file->filename); - - if(!node){ - node=new_seltree_node(tree,file->filename,0,NULL); - } -- -- if(file==NULL){ -- error(0, "add_file_to_tree was called with NULL db_line\n"); -- } - - /* add note to this node which db has modified it */ - node->checked|=db; -diff -up ./src/md.c.coverity ./src/md.c ---- ./src/md.c.coverity 2018-10-10 19:27:18.679632672 +0200 -+++ ./src/md.c 2018-10-10 19:27:18.684632716 +0200 -@@ -36,8 +36,8 @@ - */ - - DB_ATTR_TYPE hash_gcrypt2attr(int i) { -- DB_ATTR_TYPE r=0; - #ifdef WITH_GCRYPT -+ DB_ATTR_TYPE r=0; - switch (i) { - case GCRY_MD_MD5: { - r=DB_MD5; -@@ -74,13 +74,15 @@ DB_ATTR_TYPE hash_gcrypt2attr(int i) { - default: - break; - } --#endif - return r; -+#else /* !WITH_GCRYPT */ -+ return 0; -+#endif - } - - const char * hash_gcrypt2str(int i) { -- char * r = "?"; - #ifdef WITH_GCRYPT -+ char * r = "?"; - switch (i) { - case GCRY_MD_MD5: { - r = "MD5"; -@@ -117,13 +119,17 @@ const char * hash_gcrypt2str(int i) { - default: - break; - } --#endif - return r; -+#else /* !WITH_GCRYPT */ -+ return "?"; -+#endif - } - -+#pragma GCC diagnostic push -+#pragma GCC diagnostic ignored "-Wunused-parameter" - DB_ATTR_TYPE hash_mhash2attr(int i) { -- DB_ATTR_TYPE r=0; - #ifdef WITH_MHASH -+ DB_ATTR_TYPE r=0; - switch (i) { - case MHASH_CRC32: { - r=DB_CRC32; -@@ -198,10 +204,15 @@ DB_ATTR_TYPE hash_mhash2attr(int i) { - default: - break; - } --#endif -+ - return r; -+#else /*!WITH_MHASH */ -+ return 0; -+#endif - } - -+#pragma GCC diagnostic pop -+ - /* - Initialise md_container according it's todo_attr field - */ -@@ -317,7 +328,6 @@ int init_md(struct md_container* md) { - */ - - int update_md(struct md_container* md,void* data,ssize_t size) { -- int i; - - error(255,"update_md called\n"); - -@@ -328,6 +338,7 @@ int update_md(struct md_container* md,vo - #endif - - #ifdef WITH_MHASH -+ int i; - - for(i=0;i<=HASH_MHASH_COUNT;i++) { - if (md->mhash_mdh[i]!=MHASH_FAILED) { -@@ -348,7 +359,6 @@ int update_md(struct md_container* md,vo - */ - - int close_md(struct md_container* md) { -- int i; - #ifdef _PARAMETER_CHECK_ - if (md==NULL) { - return RETFAIL; -@@ -356,6 +366,7 @@ int close_md(struct md_container* md) { - #endif - error(255,"close_md called \n"); - #ifdef WITH_MHASH -+ int i; - for(i=0;i<=HASH_MHASH_COUNT;i++) { - if (md->mhash_mdh[i]!=MHASH_FAILED) { - mhash (md->mhash_mdh[i], NULL, 0); -diff -up ./src/util.c.coverity ./src/util.c ---- ./src/util.c.coverity 2018-10-10 19:27:18.670632593 +0200 -+++ ./src/util.c 2018-10-10 19:27:18.684632716 +0200 -@@ -105,13 +105,15 @@ url_t* parse_url(char* val) - for(i=0;r[0]!='/'&&r[0]!='\0';r++,i++); - if(r[0]=='\0'){ - error(0,"Invalid file-URL,no path after hostname: file:%s\n",t); -+ free(hostname); - return NULL; - } - u->value=strdup(r); - r[0]='\0'; - if(gethostname(hostname,MAXHOSTNAMELEN)==-1){ -- strncpy(hostname,"localhost", 10); -+ strncpy(hostname,"localhost", 10); - } -+ - if( (strcmp(t,"localhost")==0)||(strcmp(t,hostname)==0)){ - free(hostname); - break; -@@ -120,7 +122,7 @@ url_t* parse_url(char* val) - free(hostname); - return NULL; - } -- free(hostname); -+ - break; - } - u->value=strdup(r); diff --git a/SOURCES/rootPrefix.patch b/SOURCES/rootPrefix.patch deleted file mode 100644 index 30a6e9d..0000000 --- a/SOURCES/rootPrefix.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -Naur aide-0.16.orig/src/db_disk.c aide-0.16/src/db_disk.c ---- aide-0.16.orig/src/db_disk.c 2024-03-11 16:45:06.594013966 -0400 -+++ aide-0.16/src/db_disk.c 2024-03-11 16:45:06.584013966 -0400 -@@ -209,7 +209,7 @@ - fullname=malloc((conf->root_prefix_length+2)*sizeof(char)); - strcpy(fullname, conf->root_prefix); - strcat (fullname, "/"); -- if (!get_file_status(&fullname[conf->root_prefix_length], &fs)) { -+ if (!get_file_status(fullname, &fs)) { - add = check_rxtree (&fullname[conf->root_prefix_length], conf->tree, &attr, fs.st_mode); - error (240, "%s match=%d, tree=%p, attr=%llu\n", &fullname[conf->root_prefix_length], add, - conf->tree, attr); -@@ -255,7 +255,7 @@ - If not call, db_readline_disk again... - */ - -- if (get_file_status(&fullname[conf->root_prefix_length], &fs)) { -+ if (get_file_status(fullname, &fs)) { - free (fullname); - goto recursion; - } diff --git a/SPECS/aide.spec b/SPECS/aide.spec index 532444d..f069cb5 100644 --- a/SPECS/aide.spec +++ b/SPECS/aide.spec @@ -1,21 +1,28 @@ Summary: Intrusion detection environment Name: aide -Version: 0.16 -Release: 105%{?dist} -URL: http://sourceforge.net/projects/aide +Version: 0.19.2 +Release: 5%{?dist}.1 +URL: https://github.com/aide/aide License: GPLv2+ -Source0: %{url}/files/aide/%{version}/%{name}-%{version}.tar.gz -Source1: aide.conf -Source2: README.quickstart -Source3: aide.logrotate +Source0: %{url}/releases/download/v%{version}/%{name}-%{version}.tar.gz +Source1: %{url}/releases/download/v%{version}/%{name}-%{version}.tar.gz.asc +# gpg2 --recv-keys 2BBBD30FAAB29B3253BCFBA6F6947DAB68E7B931 +# gpg2 --export --export-options export-minimal 2BBBD30FAAB29B3253BCFBA6F6947DAB68E7B931 >gpgkey-aide.gpg +Source2: gpgkey-aide.gpg +Source3: aide.conf +Source4: README.quickstart +Source5: aide.logrotate +Source6: aide-tmpfiles.conf +Source7: aide-migrate-config +Patch0: aide-0.19.2-syslog-format.patch BuildRequires: gcc BuildRequires: make BuildRequires: bison flex BuildRequires: pcre-devel -BuildRequires: libgpg-error-devel libgcrypt-devel +BuildRequires: libgpg-error-devel nettle-devel BuildRequires: zlib-devel BuildRequires: libcurl-devel BuildRequires: libacl-devel @@ -23,71 +30,99 @@ BuildRequires: pkgconfig(libselinux) BuildRequires: libattr-devel BuildRequires: e2fsprogs-devel BuildRequires: audit-libs-devel -BuildRequires: autoconf automake libtool - -# Customize the database file location in the man page. -Patch1: aide-0.16rc1-man.patch -# fix aide in FIPS mode -Patch2: aide-0.16b1-fipsfix.patch -# Bug 1674637 - aide: FTBFS in Fedora rawhide/f30 -Patch3: aide-0.16-Use-LDADD-for-adding-curl-library-to-the-linker-comm.patch - -Patch4: aide-0.15-syslog-format.patch -Patch5: aide-0.16-crypto-disable-haval-and-others.patch -Patch6: coverity.patch -Patch7: aide-0.16-crash-elf.patch -Patch8: aide-configure.patch -Patch9: aide-static-analysis.patch -Patch10: aide-0.16-CVE-2021-45417.patch -Patch11: aide-db-problem.patch -Patch12: rootPrefix.patch -Patch13: aide-0.16-CVE-2025-54389.patch +BuildRequires: autoconf automake libtool autoconf-archive +BuildRequires: systemd-rpm-macros +# For verifying signatures +BuildRequires: gnupg2 %description AIDE (Advanced Intrusion Detection Environment) is a file integrity checker and intrusion detection program. %prep +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' %autosetup -p1 -cp -a %{S:2} . +cp -a %{SOURCE4} . %build autoreconf -ivf %configure \ --disable-static \ --with-config_file=%{_sysconfdir}/aide.conf \ - --with-gcrypt \ + --without-gcrypt \ + --with-nettle \ --with-zlib \ --with-curl \ --with-posix-acl \ --with-selinux \ --with-xattr \ --with-e2fsattrs \ - --with-audit \ - --with-confighmactype=sha512 \ - --with-dbhmactype=sha512 + --with-audit %make_build %install %make_install bindir=%{_sbindir} -install -Dpm0644 -t %{buildroot}%{_sysconfdir} %{S:1} -install -Dpm0644 %{S:3} %{buildroot}%{_sysconfdir}/logrotate.d/aide +install -Dpm0644 -t %{buildroot}%{_sysconfdir} %{SOURCE3} +install -Dpm0644 %{SOURCE5} %{buildroot}%{_sysconfdir}/logrotate.d/aide mkdir -p %{buildroot}%{_localstatedir}/log/aide mkdir -p -m0700 %{buildroot}%{_localstatedir}/lib/aide +# Install tmpfiles config +install -Dpm0644 %{SOURCE6} %{buildroot}%{_tmpfilesdir}/aide.conf +install -Dpm0755 %{SOURCE7} %{buildroot}%{_sbindir}/aide-migrate-config %files %license COPYING -%doc AUTHORS ChangeLog NEWS README doc/manual.html contrib/ +%doc AUTHORS ChangeLog NEWS README %doc README.quickstart %{_sbindir}/aide +%{_sbindir}/aide-migrate-config %{_mandir}/man1/*.1* %{_mandir}/man5/*.5* %config(noreplace) %attr(0600,root,root) %{_sysconfdir}/aide.conf %config(noreplace) %{_sysconfdir}/logrotate.d/aide %dir %attr(0700,root,root) %{_localstatedir}/lib/aide %dir %attr(0700,root,root) %{_localstatedir}/log/aide +%{_tmpfilesdir}/aide.conf + +%post +if [ $1 -ge 2 ]; then + /usr/sbin/aide-migrate-config /etc/aide.conf 2>&1 | \ + tee -a /var/log/aide/aide-migrate.log || : +fi %changelog +* Tue May 26 2026 Attila Lakatos - 0.19.2-5.1 +- Re-add syslog_format config option dropped during rebase to 0.19.2 +Resolves: RHEL-178539 +- Add aide-migrate-config to automate config migration from pre-0.19 syntax + +* Wed Oct 15 2025 Attila Lakatos - 0.19.2-5 +- Adjust default config to avoid false positives in /etc +Resolves: RHEL-83776 + +* Thu Oct 09 2025 Attila Lakatos - 0.19.2-4 +- /boot/grub2/grubenv is excluded from check due to boot_success implementation +Resolves: RHEL-83776 + +* Tue Sep 30 2025 Attila Lakatos - 0.19.2-3 +- Do not monitor link count in /var/log/journal +Resolves: RHEL-83776 + +* Thu Sep 25 2025 Attila Lakatos - 0.19.2-2 +RHEL 9.8.0 ERRATUM +- Modernize config file +Resolves: RHEL-83776 + +* Tue Sep 16 2025 Attila Lakatos - 0.19.2-1 +RHEL 9.8.0 ERRATUM +- rebase to 0.19.2 +Resolves: RHEL-110573 +- Switch to libnettle for hashing +- prevent aide from crashing if database is a HTTPS URL +Resolves: RHEL-76014 +- prevent aide from exiting if a file is truncated during check +Resolves: RHEL-1569 + * Wed Aug 20 2025 Attila Lakatos - 0.16-105 RHEL 9.7 ERRATUM - CVE-2025-54389 aide: improper output neutralization enables bypassing