source: nscp/trunk/modules/CheckEventLog/CheckEventLog.cpp @ 7b51081

Last change on this file since 7b51081 was 7b51081, checked in by Michael Medin <michael@…>, 6 years ago

Getting ready for the 0.2.7 release, a few minor fixes here and there...

  • Property mode set to 100644
File size: 11.9 KB
Line 
1// CheckEventLog.cpp : Defines the entry point for the DLL application.
2//
3
4#include "stdafx.h"
5#include "CheckEventLog.h"
6#include <strEx.h>
7#include <time.h>
8#include <utils.h>
9
10CheckEventLog gCheckEventLog;
11
12BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
13{
14        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
15        return TRUE;
16}
17
18CheckEventLog::CheckEventLog() {
19}
20CheckEventLog::~CheckEventLog() {
21}
22
23
24bool CheckEventLog::loadModule() {
25        return true;
26}
27bool CheckEventLog::unloadModule() {
28        return true;
29}
30
31bool CheckEventLog::hasCommandHandler() {
32        return true;
33}
34bool CheckEventLog::hasMessageHandler() {
35        return false;
36}
37
38
39
40class EventLogRecord {
41        EVENTLOGRECORD *pevlr_;
42        __int64 currentTime_;
43public:
44        EventLogRecord(EVENTLOGRECORD *pevlr, __int64 currentTime) : pevlr_(pevlr), currentTime_(currentTime) {
45        }
46        inline __int64 timeGenerated() const {
47                return (currentTime_-pevlr_->TimeGenerated)*1000;
48        }
49        inline __int64 timeWritten() const {
50                return (currentTime_-pevlr_->TimeWritten)*1000;
51        }
52        inline std::string eventSource() const {
53                return reinterpret_cast<LPSTR>(reinterpret_cast<LPBYTE>(pevlr_) + sizeof(EVENTLOGRECORD));
54        }
55        inline DWORD eventID() const {
56                return (pevlr_->EventID&0xffff);
57        }
58        inline DWORD severity() const {
59                return (pevlr_->EventID>>30);
60        }
61
62        inline DWORD eventType() const {
63                return pevlr_->EventType;
64        }
65/*
66        std::string userSID() const {
67                if (pevlr_->UserSidOffset == 0)
68                        return "";
69                PSID p = reinterpret_cast<PSID>(reinterpret_cast<LPBYTE>(pevlr_) + + pevlr_->UserSidOffset);
70                LPSTR user = new CHAR[1025];
71                LPSTR domain = new CHAR[1025];
72                DWORD userLen = 1024;
73                DWORD domainLen = 1024;
74                SID_NAME_USE sidName;
75                LookupAccountSid(NULL, p, user, &userLen, domain, &domainLen, &sidName);
76                user[userLen] = 0;
77                domain[domainLen] = 0;
78                return std::string(domain) + "\\" + std::string(user);
79        }
80        */
81
82        std::string enumStrings() const {
83                std::string ret;
84                LPSTR p = reinterpret_cast<LPSTR>(reinterpret_cast<LPBYTE>(pevlr_) + pevlr_->StringOffset);
85                for (unsigned int i =0;i<pevlr_->NumStrings;i++) {
86                        std::string s = p;
87                        if (!s.empty())
88                                s += ", ";
89                        ret += s;
90                        p+= strlen(p)+1;
91                }
92                return ret;
93        }
94
95        static DWORD appendType(DWORD dwType, std::string sType) {
96                return dwType | translateType(sType);
97        }
98        static DWORD subtractType(DWORD dwType, std::string sType) {
99                return dwType & (!translateType(sType));
100        }
101        static DWORD translateType(std::string sType) {
102                if (sType == "error")
103                        return EVENTLOG_ERROR_TYPE;
104                if (sType == "warning")
105                        return EVENTLOG_WARNING_TYPE;
106                if (sType == "info")
107                        return EVENTLOG_INFORMATION_TYPE;
108                if (sType == "auditSuccess")
109                        return EVENTLOG_AUDIT_SUCCESS;
110                if (sType == "auditFailure")
111                        return EVENTLOG_AUDIT_FAILURE;
112                return strEx::stoi(sType);
113        }
114        static std::string translateType(DWORD dwType) {
115                if (dwType == EVENTLOG_ERROR_TYPE)
116                        return "error";
117                if (dwType == EVENTLOG_WARNING_TYPE)
118                        return "warning";
119                if (dwType == EVENTLOG_INFORMATION_TYPE)
120                        return "info";
121                if (dwType == EVENTLOG_AUDIT_SUCCESS)
122                        return "auditSuccess";
123                if (dwType == EVENTLOG_AUDIT_FAILURE)
124                        return "auditFailure";
125                return strEx::itos(dwType);
126        }
127        static DWORD translateSeverity(std::string sType) {
128                if (sType == "success")
129                        return 0;
130                if (sType == "informational")
131                        return 1;
132                if (sType == "warning")
133                        return 2;
134                if (sType == "error")
135                        return 3;
136                return strEx::stoi(sType);
137        }
138        static std::string translateSeverity(DWORD dwType) {
139                if (dwType == 0)
140                        return "success";
141                if (dwType == 1)
142                        return "informational";
143                if (dwType == 2)
144                        return "warning";
145                if (dwType == 3)
146                        return "error";
147                return strEx::itos(dwType);
148        }
149        std::string render(std::string syntax) {
150                strEx::replace(syntax, "%source%", eventSource());
151                strEx::replace(syntax, "%generated%", strEx::format_date(pevlr_->TimeGenerated, DATE_FORMAT));
152                strEx::replace(syntax, "%written%", strEx::format_date(pevlr_->TimeWritten, DATE_FORMAT));
153                strEx::replace(syntax, "%type%", translateType(eventType()));
154                strEx::replace(syntax, "%severity%", translateSeverity(severity()));
155                strEx::replace(syntax, "%strings%", enumStrings());
156                strEx::replace(syntax, "%id%", strEx::itos(eventID()));
157                return syntax;
158        }
159};
160
161
162struct eventlog_filter {
163        filters::filter_all_strings eventSource;
164        filters::filter_all_numeric<unsigned int, filters::handlers::eventtype_handler> eventType;
165        filters::filter_all_numeric<unsigned int, filters::handlers::eventseverity_handler> eventSeverity;
166        filters::filter_all_strings message;
167        filters::filter_all_times timeWritten;
168        filters::filter_all_times timeGenerated;
169        filters::filter_all_numeric<DWORD, filters::handlers::eventtype_handler> eventID;
170
171        inline bool hasFilter() {
172                return eventSource.hasFilter() || eventType.hasFilter() || eventID.hasFilter() || eventSeverity.hasFilter() || message.hasFilter() ||
173                        timeWritten.hasFilter() || timeGenerated.hasFilter();
174        }
175        bool matchFilter(const EventLogRecord &value) const {
176                if ((eventSource.hasFilter())&&(eventSource.matchFilter(value.eventSource())))
177                        return true;
178                else if ((eventType.hasFilter())&&(eventType.matchFilter(value.eventType())))
179                        return true;
180                else if ((eventSeverity.hasFilter())&&(eventSeverity.matchFilter(value.severity())))
181                        return true;
182                else if ((eventID.hasFilter())&&(eventID.matchFilter(value.eventID())))
183                        return true;
184                else if ((message.hasFilter())&&(message.matchFilter(value.enumStrings())))
185                        return true;
186                else if ((timeWritten.hasFilter())&&(timeWritten.matchFilter(value.timeWritten())))
187                        return true;
188                else if ((timeGenerated.hasFilter())&&(timeGenerated.matchFilter(value.timeGenerated())))
189                        return true;
190                return false;
191        }
192};
193
194
195#define MAP_FILTER(value, obj, filtermode) \
196                        else if (p__.first == value) { eventlog_filter filter; filter.obj = p__.second; filter_chain.push_back(filteritem_type(filtermode, filter)); }
197
198
199#define BUFFER_SIZE 1024*64
200NSCAPI::nagiosReturn CheckEventLog::handleCommand(const strEx::blindstr command, const unsigned int argLen, char **char_args, std::string &message, std::string &perf) {
201        if (command != "CheckEventLog")
202                return NSCAPI::returnIgnored;
203        typedef checkHolders::CheckConatiner<checkHolders::MaxMinBoundsULongInteger> EventLogQueryConatiner;
204        typedef std::pair<int,eventlog_filter> filteritem_type;
205        typedef std::list<filteritem_type > filterlist_type;
206        NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK;
207        std::list<std::string> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args);
208
209        std::list<std::string> files;
210        filterlist_type filter_chain;
211        EventLogQueryConatiner query;
212
213        bool bPerfData = true;
214        bool bFilterIn = true;
215        bool bFilterAll = false;
216        bool bFilterNew = false;
217        bool bShowDescriptions = false;
218        unsigned int truncate = 0;
219        std::string syntax;
220        const int filter_plus = 1;
221        const int filter_minus = 2;
222        const int filter_normal = 3;
223        const int filter_compat = 3;
224
225        try {
226                MAP_OPTIONS_BEGIN(stl_args)
227                        MAP_OPTIONS_NUMERIC_ALL(query, "")
228                        MAP_OPTIONS_STR2INT("truncate", truncate)
229                        MAP_OPTIONS_BOOL_TRUE("descriptions", bShowDescriptions)
230                        MAP_OPTIONS_PUSH("file", files)
231                        MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData)
232                        MAP_OPTIONS_BOOL_EX("filter", bFilterNew, "new", "old")
233                        MAP_OPTIONS_BOOL_EX("filter", bFilterIn, "in", "out")
234                        MAP_OPTIONS_BOOL_EX("filter", bFilterAll, "all", "any")
235                        MAP_OPTIONS_STR("syntax", syntax)
236/*
237                        MAP_FILTER_OLD("filter-eventType", eventType)
238                        MAP_FILTER_OLD("filter-severity", eventSeverity)
239                        MAP_FILTER_OLD("filter-eventID", eventID)
240                        MAP_FILTER_OLD("filter-eventSource", eventSource)
241                        MAP_FILTER_OLD("filter-generated", timeGenerated)
242                        MAP_FILTER_OLD("filter-written", timeWritten)
243                        MAP_FILTER_OLD("filter-message", message)
244*/
245                        MAP_FILTER("filter+eventType", eventType, filter_plus)
246                        MAP_FILTER("filter+severity", eventSeverity, filter_plus)
247                        MAP_FILTER("filter+eventID", eventID, filter_plus)
248                        MAP_FILTER("filter+eventSource", eventSource, filter_plus)
249                        MAP_FILTER("filter+generated", timeGenerated, filter_plus)
250                        MAP_FILTER("filter+written", timeWritten, filter_plus)
251                        MAP_FILTER("filter+message", message, filter_plus)
252
253                        MAP_FILTER("filter.eventType", eventType, filter_normal)
254                        MAP_FILTER("filter.severity", eventSeverity, filter_normal)
255                        MAP_FILTER("filter.eventID", eventID, filter_normal)
256                        MAP_FILTER("filter.eventSource", eventSource, filter_normal)
257                        MAP_FILTER("filter.generated", timeGenerated, filter_normal)
258                        MAP_FILTER("filter.written", timeWritten, filter_normal)
259                        MAP_FILTER("filter.message", message, filter_normal)
260
261                        MAP_FILTER("filter-eventType", eventType, filter_minus)
262                        MAP_FILTER("filter-severity", eventSeverity, filter_minus)
263                        MAP_FILTER("filter-eventID", eventID, filter_minus)
264                        MAP_FILTER("filter-eventSource", eventSource, filter_minus)
265                        MAP_FILTER("filter-generated", timeGenerated, filter_minus)
266                        MAP_FILTER("filter-written", timeWritten, filter_minus)
267                        MAP_FILTER("filter-message", message, filter_minus)
268
269                        MAP_OPTIONS_MISSING(message, "Unknown argument: ")
270                MAP_OPTIONS_END()
271        } catch (filters::parse_exception e) {
272                message = e.getMessage();
273                return NSCAPI::returnUNKNOWN;
274        } catch (filters::filter_exception e) {
275                message = e.getMessage();
276                return NSCAPI::returnUNKNOWN;
277        }
278
279        unsigned long int hit_count = 0;
280
281        for (std::list<std::string>::const_iterator cit2 = files.begin(); cit2 != files.end(); ++cit2) {
282                HANDLE hLog = OpenEventLog(NULL, (*cit2).c_str());
283                if (hLog == NULL) {
284                        message = "Could not open the '" + (*cit2) + "' event log.";
285                        return NSCAPI::returnUNKNOWN;
286                }
287
288                //DWORD dwThisRecord;
289                DWORD dwRead, dwNeeded;
290                EVENTLOGRECORD *pevlr;
291                BYTE bBuffer[BUFFER_SIZE];
292
293                pevlr = reinterpret_cast<EVENTLOGRECORD*>(&bBuffer);
294
295                __time64_t ltime;
296                _time64(&ltime);
297
298                //GetOldestEventLogRecord(hLog, &dwThisRecord);
299
300                while (ReadEventLog(hLog, EVENTLOG_FORWARDS_READ|EVENTLOG_SEQUENTIAL_READ,
301                        0, pevlr, BUFFER_SIZE, &dwRead, &dwNeeded))
302                {
303                        while (dwRead > 0)
304                        {
305                                bool bMatch = bFilterAll;
306                                EventLogRecord record(pevlr, ltime);
307
308                                for (filterlist_type::const_iterator cit3 = filter_chain.begin(); cit3 != filter_chain.end(); ++cit3 ) {
309                                        int mode = (*cit3).first;
310                                        bool bTmpMatched = (*cit3).second.matchFilter(record);
311                                        if (!bFilterNew) {
312                                                if (bFilterAll) {
313                                                        if (!bTmpMatched) {
314                                                                bMatch = false;
315                                                                break;
316                                                        }
317                                                } else {
318                                                        if (bTmpMatched) {
319                                                                bMatch = true;
320                                                                break;
321                                                        }
322                                                }
323                                        } else {
324                                                if ((mode == filter_minus)&&(bTmpMatched)) {
325                                                        // a -<filter> hit so thrash item and bail out!
326                                                        bMatch = false;
327                                                        break;
328                                                } else if ((mode == filter_plus)&&(!bTmpMatched)) {
329                                                                // a +<filter> missed hit so thrash item and bail out!
330                                                                bMatch = false;
331                                                                break;
332                                                } else if (bTmpMatched) {
333                                                        bMatch = true;
334                                                }
335                                        }
336                                }
337                                bool match = false;
338                                if ((!bFilterNew)&&((bFilterIn&&bMatch)||(!bFilterIn&&!bMatch))) {
339                                        match = true;
340                                } else if (bFilterNew&&bMatch) {
341                                        match = true;
342                                }
343
344                                if (match) {
345                                        if (!syntax.empty()) {
346                                                strEx::append_list(message, record.render(syntax));
347                                        } else if (!bShowDescriptions) {
348                                                strEx::append_list(message, record.eventSource());
349                                        } else {
350                                                strEx::append_list(message, record.eventSource());
351                                                message += "(" + EventLogRecord::translateType(record.eventType()) + ", " +
352                                                        strEx::itos(record.eventID()) + ", " + EventLogRecord::translateSeverity(record.severity()) + ")";
353                                                message += "[" + record.enumStrings() + "]";
354                                        }
355                                        hit_count++;
356                                }
357                                dwRead -= pevlr->Length;
358                                pevlr = (EVENTLOGRECORD *) ((LPBYTE) pevlr + pevlr->Length);
359                        }
360                        pevlr = (EVENTLOGRECORD *) &bBuffer;
361                }
362                CloseEventLog(hLog);
363        }
364
365        if (!bPerfData)
366                query.perfData = false;
367        query.runCheck(hit_count, returnCode, message, perf);
368        if ((truncate > 0) && (message.length() > (truncate-4)))
369                message = message.substr(0, truncate-4) + "...";
370        if (message.empty())
371                message = "Eventlog check ok";
372        return returnCode;
373}
374
375
376NSC_WRAPPERS_MAIN_DEF(gCheckEventLog);
377NSC_WRAPPERS_IGNORE_MSG_DEF();
378NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckEventLog);
Note: See TracBrowser for help on using the repository browser.