new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / dodiff.c
1 /* Copyright (C) 2010 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation.
8  */
9
10 #include "dodiff.h"
11
12 #include "shared.h"
13
14 static int _add2last(const char *str, size_t strsize, const char *file)
15 {
16     FILE *fp;
17
18     fp = fopen(file, "w");
19     if (!fp) {
20         /* Try to create the directories */
21         char *dirrule = NULL;
22         char *diragent = NULL;
23
24         dirrule = strrchr(file, '/');
25         if (!dirrule) {
26             merror("%s: ERROR: Invalid file name to diff: %s",
27                    ARGV0, file);
28             return (0);
29         }
30         *dirrule = '\0';
31
32         diragent = strrchr(file, '/');
33         if (!diragent) {
34             merror("%s: ERROR: Invalid file name to diff (2): %s",
35                    ARGV0, file);
36             return (0);
37         }
38         *diragent = '\0';
39
40         /* Check if the diragent exists */
41         if (IsDir(file) != 0) {
42             if (mkdir(file, 0770) == -1) {
43                 merror(MKDIR_ERROR, ARGV0, file, errno, strerror(errno));
44                 return (0);
45             }
46         }
47         *diragent = '/';
48
49         if (IsDir(file) != 0) {
50             if (mkdir(file, 0770) == -1) {
51                 merror(MKDIR_ERROR, ARGV0, file, errno, strerror(errno));
52                 return (0);
53             }
54         }
55         *dirrule = '/';
56
57         fp = fopen(file, "w");
58         if (!fp) {
59             merror(FOPEN_ERROR, ARGV0, file, errno, strerror(errno));
60             return (0);
61         }
62     }
63
64     fwrite(str, strsize + 1, 1, fp);
65     fclose(fp);
66     return (1);
67 }
68
69 int doDiff(RuleInfo *rule, const Eventinfo *lf)
70 {
71     time_t date_of_change;
72     char *htpt = NULL;
73     char flastfile[OS_SIZE_2048 + 1];
74     char flastcontent[OS_SIZE_8192 + 1];
75
76     /* Clean up global */
77     flastcontent[0] = '\0';
78     flastcontent[OS_SIZE_8192] = '\0';
79     rule->last_events[0] = NULL;
80
81     if (lf->hostname[0] == '(') {
82         htpt = strchr(lf->hostname, ')');
83         if (htpt) {
84             *htpt = '\0';
85         }
86         snprintf(flastfile, OS_SIZE_2048, "%s/%s/%d/%s", DIFF_DIR, lf->hostname + 1,
87                  rule->sigid, DIFF_LAST_FILE);
88
89         if (htpt) {
90             *htpt = ')';
91         }
92         htpt = NULL;
93     } else {
94         snprintf(flastfile, OS_SIZE_2048, "%s/%s/%d/%s", DIFF_DIR, lf->hostname,
95                  rule->sigid, DIFF_LAST_FILE);
96     }
97
98     /* lf->size can't be too long */
99     if (lf->size >= OS_SIZE_8192) {
100         merror("%s: ERROR: event size (%ld) too long for diff.", ARGV0, lf->size);
101         return (0);
102     }
103
104     /* Check if last diff exists */
105     date_of_change = File_DateofChange(flastfile);
106     if (date_of_change <= 0) {
107         if (!_add2last(lf->log, lf->size, flastfile)) {
108             merror("%s: ERROR: unable to create last file: %s", ARGV0, flastfile);
109             return (0);
110         }
111         return (0);
112     } else {
113         FILE *fp;
114         size_t n;
115         fp = fopen(flastfile, "r");
116         if (!fp) {
117             merror(FOPEN_ERROR, ARGV0, flastfile, errno, strerror(errno));
118             return (0);
119         }
120
121         n = fread(flastcontent, 1, OS_SIZE_8192, fp);
122         if (n > 0) {
123             flastcontent[n] = '\0';
124         } else {
125             merror("%s: ERROR: read error on %s", ARGV0, flastfile);
126             fclose(fp);
127             return (0);
128         }
129         fclose(fp);
130     }
131
132     /* Nothing changed */
133     if (strcmp(flastcontent, lf->log) == 0) {
134         return (0);
135     }
136
137     if (!_add2last(lf->log, lf->size, flastfile)) {
138         merror("%s: ERROR: unable to create last file: %s", ARGV0, flastfile);
139     }
140
141     rule->last_events[0] = "Previous output:";
142     rule->last_events[1] = flastcontent;
143     return (1);
144 }
145