source: nscp/trunk/modules/CheckEventLog/CheckEventLog.cpp @ e0705d4

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

Initial release

  • Property mode set to 100644
File size: 9.4 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
9CheckEventLog gCheckEventLog;
10
11BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
12{
13        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
14        return TRUE;
15}
16
17CheckEventLog::CheckEventLog() {
18}
19CheckEventLog::~CheckEventLog() {
20}
21
22
23bool CheckEventLog::loadModule() {
24        return true;
25}
26bool CheckEventLog::unloadModule() {
27        return true;
28}
29
30std::string CheckEventLog::getModuleName() {
31        return "NSClient compatibility Module.";
32}
33NSCModuleWrapper::module_version CheckEventLog::getModuleVersion() {
34        NSCModuleWrapper::module_version version = {0, 0, 1 };
35        return version;
36}
37
38bool CheckEventLog::hasCommandHandler() {
39        return true;
40}
41bool CheckEventLog::hasMessageHandler() {
42        return false;
43}
44
45
46class EventLogRecord {
47        EVENTLOGRECORD *pevlr_;
48public:
49        EventLogRecord(EVENTLOGRECORD *pevlr) : pevlr_(pevlr) {
50        }
51        inline DWORD timeGenerated() {
52                return pevlr_->TimeGenerated;
53        }
54        inline DWORD timeWritten() {
55                return pevlr_->TimeWritten;
56        }
57        inline std::string eventSource() {
58                return reinterpret_cast<LPSTR>(reinterpret_cast<LPBYTE>(pevlr_) + sizeof(EVENTLOGRECORD));
59        }
60
61        inline DWORD eventType() {
62                return pevlr_->EventType;
63        }
64
65        std::string enumStrings() {
66                std::string ret;
67                LPSTR p = reinterpret_cast<LPSTR>(reinterpret_cast<LPBYTE>(pevlr_) + pevlr_->StringOffset);
68                for (unsigned int i =0;i<pevlr_->NumStrings;i++) {
69                        std::string s = p;
70                        if (!s.empty())
71                                s += ", ";
72                        ret += s;
73                        p+= strlen(p)+1;
74                }
75                return ret;
76        }
77
78        static DWORD appendType(DWORD dwType, std::string sType) {
79                return dwType | translateType(sType);
80        }
81        static DWORD subtractType(DWORD dwType, std::string sType) {
82                return dwType & (!translateType(sType));
83        }
84        static DWORD translateType(std::string sType) {
85                if (sType == "error")
86                        return EVENTLOG_ERROR_TYPE;
87                if (sType == "warning")
88                        return EVENTLOG_WARNING_TYPE;
89                if (sType == "info")
90                        return EVENTLOG_INFORMATION_TYPE;
91                if (sType == "auditSuccess")
92                        return EVENTLOG_AUDIT_SUCCESS;
93                if (sType == "auditFailure")
94                        return EVENTLOG_AUDIT_FAILURE;
95                return 0;
96        }
97
98};
99
100
101struct searchQuery {
102        struct searchQueryBundle {
103                struct searchQueryItem {
104                        DWORD eventType_;
105                        std::string eventSource_;
106                        bool notSetValue_;
107                        DWORD writtenBeforeDelta_ ;
108                        DWORD writtenAfterDelta_ ;
109                        DWORD generatedBeforeDelta_;
110                        DWORD generatedAfterDelta_;
111
112                        searchQueryItem(bool notSetValue)
113                                : eventType_(0), notSetValue_(notSetValue),
114                                writtenBeforeDelta_(0), writtenAfterDelta_(0) ,
115                                generatedBeforeDelta_(0), generatedAfterDelta_(0)
116                        {}
117
118                        inline bool matchDateWritten(DWORD now, DWORD written) const {
119                                if ((writtenAfterDelta_ == 0)&&(writtenBeforeDelta_ == 0))
120                                        return notSetValue_;
121                                bool ret = true;
122                                if (writtenAfterDelta_ != 0) {
123                                        if (writtenAfterDelta_+written <= now)
124                                                ret = false;
125                                }
126                                if (writtenBeforeDelta_ != 0) {
127                                        if (writtenBeforeDelta_+written > now)
128                                                ret = false;
129                                }
130                                return ret;
131                        }
132                        inline bool matchDateGenerated(DWORD now, DWORD written) const {
133                                if ((generatedAfterDelta_ == 0)&&(generatedBeforeDelta_ == 0))
134                                        return notSetValue_;
135                                bool ret = true;
136                                if (generatedAfterDelta_ != 0) {
137                                        if (generatedAfterDelta_+written <= now)
138                                                ret = false;
139                                }
140                                if (generatedBeforeDelta_ != 0) {
141                                        if (generatedBeforeDelta_+written > now)
142                                                ret = false;
143                                }
144                                return ret;
145                        }
146                        inline bool matchType(DWORD eventType) const {
147                                if (eventType_ == 0)
148                                        return notSetValue_;
149                                return eventType_ & eventType;
150                        }
151                        inline bool matchSource(std::string eventSource) const {
152                                if (eventSource_.empty())
153                                        return notSetValue_;
154                                return eventSource_ == eventSource;
155                        }
156                        std::string toString() const {
157                                std::stringstream ss;
158                                ss << "    Event type: " << eventType_ << std::endl;
159                                ss << "    Event source: " << eventSource_ << std::endl;
160                                ss << "    Written delta: " << writtenAfterDelta_ << " > " << writtenBeforeDelta_ << std::endl;
161                                ss << "    Generated delta: " << generatedAfterDelta_ << " > " << generatedBeforeDelta_ << std::endl;
162                                return ss.str();
163                        }
164                };
165                struct searchQueryItem require;
166                struct searchQueryItem exclude;
167                searchQueryBundle() : require(true), exclude(false) {}
168                std::string toString() {
169                        return "  Required:\n" + require.toString()  + "\n  Exlude:\n" + exclude.toString();
170                }
171        };
172
173        searchQueryBundle warn;
174        searchQueryBundle critical;
175        unsigned int truncate;
176        bool descriptions;
177        searchQuery() : truncate(0), descriptions(false) {}
178
179        std::string toString() {
180                return "Warn:\n" + warn.toString()  + "\nCritical:\n" + critical.toString();
181        }
182
183};
184
185void addToQueryItem(searchQuery::searchQueryBundle::searchQueryItem &item, std::string arg) {
186        std::pair<std::string,std::string> p = strEx::split(arg, "=");
187        if (p.first == "eventType")
188                item.eventType_ = EventLogRecord::appendType(item.eventType_, p.second);
189        else if (p.first == "eventSource")
190                item.eventSource_ = p.second;
191}
192void addToQueryBundle(searchQuery::searchQueryBundle &bundle, std::string arg) {
193        std::pair<std::string,std::string> p = strEx::split(arg, ".");
194        if (p.first == "require")
195                addToQueryItem(bundle.require, p.second);
196        else if (p.first == "exclude")
197                addToQueryItem(bundle.exclude, p.second);
198}
199void addToQuery(searchQuery &q, std::string arg) {
200        std::pair<std::string,std::string> p = strEx::split(arg, ".");
201        if (p.first == "warn")
202                addToQueryBundle(q.warn, p.second);
203        else if (p.first == "critical")
204                addToQueryBundle(q.critical, p.second);
205        else if (p.first == "all") {
206                addToQueryBundle(q.warn, p.second);
207                addToQueryBundle(q.critical, p.second);
208        } else {
209                std::pair<std::string,std::string> p = strEx::split(arg, "=");
210                if (p.first == "truncate")
211                        q.truncate = strEx::stoi(p.second);
212                else if (p.first == "descriptions")
213                        q.descriptions = true;
214        }
215}
216
217searchQuery buildQury(std::list<std::string> args) {
218        searchQuery ret;
219        for (std::list<std::string>::const_iterator it = args.begin(); it!=args.end(); it++) {
220                addToQuery(ret, *it);
221        }
222        return ret;
223}
224// huffa&CheckEventLog&Application&1&<type>&<query>&huffa...
225// request: CheckEventLog&<logfile>&<Query strings>
226// Return: <return state>&<log entry 1> - <log entry 2>...
227// <return state>       0 - No errors
228//                                      1 - Unknown
229//                                      2 - Errors
230#define BUFFER_SIZE 1024*64
231
232std::string CheckEventLog::handleCommand(const std::string command, const unsigned int argLen, char **char_args) {
233        if (command != "CheckEventLog")
234                return "";
235        std::list<std::string> args = NSCHelper::makelist(argLen, char_args);
236        if (args.size() < 2)
237                return "Missing argument";
238        std::string ret;
239        bool critical = false;
240        std::string logFile = args.front(); args.pop_front();
241        searchQuery query = buildQury(args);
242        NSC_DEBUG_MSG_STD("Base query: " + query.toString());
243
244        HANDLE hLog = OpenEventLog(NULL, logFile.c_str());
245        if (hLog == NULL)
246                return "Could not open the Application event log.";
247
248        DWORD dwThisRecord, dwRead, dwNeeded;
249        EVENTLOGRECORD *pevlr;
250        BYTE bBuffer[BUFFER_SIZE];
251
252        pevlr = reinterpret_cast<EVENTLOGRECORD*>(&bBuffer);
253
254        // get time now !!!
255        __time64_t ltime;
256        _time64(&ltime);
257        DWORD currentTime = ltime;
258
259        GetOldestEventLogRecord(hLog, &dwThisRecord);
260
261        while (ReadEventLog(hLog, EVENTLOG_FORWARDS_READ|EVENTLOG_SEQUENTIAL_READ,
262                0, pevlr, BUFFER_SIZE, &dwRead, &dwNeeded))
263        {
264                while (dwRead > 0)
265                {
266                        bool match = false;
267                        bool c = false;
268                        EventLogRecord record(pevlr);
269
270                        if ( query.critical.require.matchType(record.eventType()) &&
271                                query.critical.require.matchSource(record.eventSource()) &&
272                                query.critical.require.matchDateGenerated(currentTime, record.timeGenerated()) &&
273                                query.critical.require.matchDateWritten(currentTime, record.timeWritten())
274                                ) {
275                                        match = true;
276                                        c = true;
277                                }
278                        if ( query.critical.exclude.matchType(record.eventType()) ||
279                                query.critical.exclude.matchSource(record.eventSource()) ||
280                                query.critical.require.matchDateGenerated(currentTime, record.timeGenerated()) ||
281                                query.critical.require.matchDateWritten(currentTime, record.timeWritten())
282                                ) {
283                                        match = false;
284                                        c = false;
285                                }
286
287                        if ( query.warn.require.matchType(record.eventType()) &&
288                                query.warn.require.matchSource(record.eventSource()) &&
289                                query.critical.require.matchDateGenerated(currentTime, record.timeGenerated()) &&
290                                query.critical.require.matchDateWritten(currentTime, record.timeWritten())
291                                )
292                                match = true;
293                        if ( query.warn.exclude.matchType(record.eventType()) ||
294                                query.warn.exclude.matchSource(record.eventSource()) ||
295                                query.critical.require.matchDateGenerated(currentTime, record.timeGenerated()) ||
296                                query.critical.require.matchDateWritten(currentTime, record.timeWritten())
297                                )
298                                match = false;
299                       
300                        if (match) {
301                                if (c)
302                                        critical = true;
303                                if (!ret.empty())
304                                        ret += " - ";
305                                ret += record.eventSource();
306                                if (query.descriptions) {
307                                        std::string s = record.enumStrings();
308                                        if (!s.empty())
309                                                ret += " [" + s + "]" ;
310                                }
311                        }
312                        dwRead -= pevlr->Length;
313                        pevlr = (EVENTLOGRECORD *)
314                                ((LPBYTE) pevlr + pevlr->Length);
315                }
316
317                pevlr = (EVENTLOGRECORD *) &bBuffer;
318        }
319
320        CloseEventLog(hLog);
321        if (critical)
322                ret = "CRITICAL: " + ret;
323        else if (!ret.empty())
324                ret = "WARNING: " + ret;
325        else
326                ret = "OK: No errors/warnings in eventlog.";
327        if (query.truncate != 0)
328                ret = ret.substr(0, query.truncate);
329        return ret;
330}
331
332
333NSC_WRAPPERS_MAIN_DEF(gCheckEventLog);
334NSC_WRAPPERS_IGNORE_MSG_DEF();
335NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckEventLog);
Note: See TracBrowser for help on using the repository browser.