1 /* @(#) $Id: read_win_el.c,v 1.21 2009/09/04 19:23:11 dcid Exp $ */
3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 3) as published by the FSF - Free Software
14 #include "logcollector.h"
17 /* This is only for windows */
20 #define BUFFER_SIZE 2048*256
24 /* Event logging local structure */
38 /** Global variables **/
40 /* Maximum of 9 event log sources. */
43 void *vista_sec_id_hash = NULL;
44 void *dll_hash = NULL;
48 /** int startEL(char *app, os_el *el)
49 * Starts the event logging for each el
51 int startEL(char *app, os_el *el)
53 DWORD NumberOfRecords = 0;
55 /* Opening the event log */
56 el->h = OpenEventLog(NULL, app);
59 merror(EVTLOG_OPEN, ARGV0, app);
64 if(GetOldestEventLogRecord(el->h, &el->record) == 0)
66 /* Unable to read oldest event log record */
67 merror(EVTLOG_GETLAST, ARGV0, app);
73 if(GetNumberOfEventLogRecords(el->h, &NumberOfRecords) == 0)
75 merror(EVTLOG_GETLAST, ARGV0, app);
81 if(NumberOfRecords <= 0)
86 return((int)NumberOfRecords);
91 /** char *el_getCategory(int category_id)
92 * Returns a string related to the category id of the log.
94 char *el_getCategory(int category_id)
99 case EVENTLOG_ERROR_TYPE:
102 case EVENTLOG_WARNING_TYPE:
105 case EVENTLOG_INFORMATION_TYPE:
108 case EVENTLOG_AUDIT_SUCCESS:
109 cat = "AUDIT_SUCCESS";
111 case EVENTLOG_AUDIT_FAILURE:
112 cat = "AUDIT_FAILURE";
123 /** char *el_getEventDLL(char *evt_name, char *source, char *event)
126 char *el_getEventDLL(char *evt_name, char *source, char *event)
136 snprintf(keyname, 510,
137 "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s",
142 /* Checking if we have it in memory. */
143 ret_str = OSHash_Get(dll_hash, keyname + 42);
150 /* Opening registry */
151 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0,
152 KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
159 if (RegQueryValueEx(key, "EventMessageFile", NULL,
160 NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS)
168 /* Adding to memory. */
172 skey = strdup(keyname + 42);
173 sval = strdup(event);
177 OSHash_Add(dll_hash, skey, sval);
181 merror(MEM_ERROR, ARGV0);
191 /** char *el_vista_getmessage()
192 * Returns a descriptive message of the event - Vista only.
194 char *el_vista_getMessage(int evt_id_int, LPTSTR *el_sstring)
197 LPSTR message = NULL;
202 /* Flags for format event */
203 fm_flags |= FORMAT_MESSAGE_FROM_STRING;
204 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
205 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
208 /* Getting descriptive message. */
210 snprintf(evt_id, 15, "%d", evt_id_int);
212 desc_string = OSHash_Get(vista_sec_id_hash, evt_id);
219 if(!FormatMessage(fm_flags, desc_string, 0, 0,
220 (LPTSTR) &message, 0, el_sstring))
230 /** char *el_getmessage()
231 * Returns a descriptive message of the event.
233 char *el_getMessage(EVENTLOGRECORD *er, char *name,
234 char * source, LPTSTR *el_sstring)
238 char event[MAX_PATH +1];
241 LPSTR message = NULL;
245 /* Initializing variables */
246 event[MAX_PATH] = '\0';
250 /* Flags for format event */
251 fm_flags |= FORMAT_MESSAGE_FROM_HMODULE;
252 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
253 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
257 /* Get the file name from the registry (stored on event) */
258 if(!(curr_str = el_getEventDLL(name, source, event)))
265 /* If our event has multiple libraries, try each one of them */
266 while((next_str = strchr(curr_str, ';')))
270 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
272 /* Reverting back old value. */
276 /* Loading library. */
277 hevt = LoadLibraryEx(tmp_str, NULL,
278 DONT_RESOLVE_DLL_REFERENCES |
279 LOAD_LIBRARY_AS_DATAFILE);
282 if(!FormatMessage(fm_flags, hevt, er->EventID, 0,
283 (LPTSTR) &message, 0, el_sstring))
289 /* If we have a message, we can return it */
295 curr_str = next_str +1;
299 /* Getting last value. */
300 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
301 hevt = LoadLibraryEx(tmp_str, NULL,
302 DONT_RESOLVE_DLL_REFERENCES |
303 LOAD_LIBRARY_AS_DATAFILE);
307 if(!(hr = FormatMessage(fm_flags, hevt, er->EventID,
309 (LPTSTR) &message, 0, el_sstring)))
315 /* If we have a message, we can return it */
325 /** void readel(os_el *el)
326 * Reads the event log.
328 void readel(os_el *el, int printit)
330 DWORD _evtid = 65535;
339 char mbuffer[BUFFER_SIZE +1];
342 char *tmp_str = NULL;
346 char *descriptive_msg;
348 char el_user[OS_FLSIZE +1];
349 char el_domain[OS_FLSIZE +1];
350 char el_string[OS_MAXSTR +1];
351 char final_msg[OS_MAXSTR +1];
352 LPSTR el_sstring[OS_FLSIZE +1];
354 /* Er must point to the mbuffer */
355 el->er = (EVENTLOGRECORD *) &mbuffer;
357 /* Zeroing the values */
358 el_string[OS_MAXSTR] = '\0';
359 el_user[OS_FLSIZE] = '\0';
360 el_domain[OS_FLSIZE] = '\0';
361 final_msg[OS_MAXSTR] = '\0';
362 el_sstring[0] = NULL;
363 el_sstring[OS_FLSIZE] = NULL;
366 /* Event log is not open */
372 /* Reading the event log */
373 while(ReadEventLog(el->h,
374 EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
376 el->er, BUFFER_SIZE -1, &read, &needed))
380 /* Setting er to the beginning of the buffer */
381 el->er = (EVENTLOGRECORD *)&mbuffer;
389 /* We need to initialize every variable before the loop */
390 category = el_getCategory(el->er->EventType);
391 source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
392 computer_name = source + strlen(source) + 1;
393 descriptive_msg = NULL;
396 /* Getting event id. */
397 id = (int)el->er->EventID & _evtid;
401 /* Initialing domain/user size */
402 user_size = 255; domain_size = 255;
408 /* We must have some description */
409 if(el->er->NumStrings)
411 size_left = OS_MAXSTR - OS_SIZE_1024;
413 sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
416 for (nstr = 0;nstr < el->er->NumStrings;nstr++)
418 str_size = strlen(sstr);
421 strncat(el_string, sstr, size_left);
424 tmp_str = strchr(el_string, '\0');
428 tmp_str++; *tmp_str = '\0';
432 merror("%s: Invalid application string (size+)",
435 size_left-=str_size + 2;
439 el_sstring[nstr] = (LPSTR)sstr;
440 el_sstring[nstr +1] = NULL;
443 sstr = strchr( (LPSTR)sstr, '\0');
450 /* Get a more descriptive message (if available) */
451 if(isVista && strcmp(el->name, "Security") == 0)
453 descriptive_msg = el_vista_getMessage(id, el_sstring);
458 descriptive_msg = el_getMessage(el->er,
464 if(descriptive_msg != NULL)
466 /* Remove any \n or \r */
467 /* Replace tabs from the argument field to spaces.
468 * So whenever we have option:\tvalue\t, it will
469 * become option: value\t
471 tmp_str = descriptive_msg;
472 while(*tmp_str != '\0')
476 else if(*tmp_str == '\r')
478 else if((*tmp_str == ':') && (tmp_str[1] == '\t'))
490 strncpy(el_string, "(no message)", 128);
494 /* Getting username */
495 if(el->er->UserSidLength)
497 SID_NAME_USE account_type;
498 if(!LookupAccountSid(NULL,
499 (SID *)((LPSTR)el->er +
500 el->er->UserSidOffset),
507 strncpy(el_user, "(no user)", 255);
508 strncpy(el_domain, "no domain", 255);
513 else if(isVista && strcmp(el->name, "Security") == 0)
515 int uid_array_id = -1;
533 if((uid_array_id >= 0) &&
534 el_sstring[uid_array_id] &&
535 el_sstring[uid_array_id +1])
537 strncpy(el_user, el_sstring[uid_array_id], OS_FLSIZE);
538 strncpy(el_domain, el_sstring[uid_array_id +1], OS_FLSIZE);
542 strncpy(el_user, "(no user)", 255);
543 strncpy(el_domain, "no domain", 255);
549 strncpy(el_user, "(no user)", 255);
550 strncpy(el_domain, "no domain", 255);
556 DWORD _evtid = 65535;
557 int id = (int)el->er->EventID & _evtid;
559 final_msg[OS_MAXSTR - OS_LOG_HEADER] = '\0';
560 final_msg[OS_MAXSTR - OS_LOG_HEADER -1] = '\0';
562 snprintf(final_msg, OS_MAXSTR - OS_LOG_HEADER -1,
563 "WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s",
571 descriptive_msg != NULL?descriptive_msg:el_string);
573 if(SendMSG(logr_queue, final_msg, "WinEvtLog",
576 merror(QUEUE_SEND, ARGV0);
580 if(descriptive_msg != NULL)
582 LocalFree(descriptive_msg);
585 /* Changing the point to the er */
586 read -= el->er->Length;
587 el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
590 /* Setting er to the beginning of the buffer */
591 el->er = (EVENTLOGRECORD *)&mbuffer;
596 if(id == ERROR_HANDLE_EOF)
602 /* Event log was cleared. */
603 else if(id == ERROR_EVENTLOG_FILE_CHANGED)
605 char msg_alert[512 +1];
606 msg_alert[512] = '\0';
607 merror("%s: WARN: Event log cleared: '%s'", ARGV0, el->name);
610 /* Send message about cleared */
611 snprintf(msg_alert, 512, "ossec: Event log cleared: '%s'", el->name);
612 SendMSG(logr_queue, msg_alert, "WinEvtLog", LOCALFILE_MQ);
615 /* Closing the event log and reopenning. */
616 CloseEventLog(el->h);
620 if(startEL(el->name, el) < 0)
622 merror("%s: ERROR: Unable to reopen event log '%s'",
629 debug1("%s: WARN: Error reading event log: %d", ARGV0, id);
634 /** void win_read_vista_sec()
635 * Reads vista security description.
637 void win_read_vista_sec()
640 char buf[OS_MAXSTR +1];
644 /* Vista security csv. */
645 fp = fopen("vista_sec.csv", "r");
648 merror("%s: ERROR: Unable to read vista security descriptions.",
654 /* Creating the hash. */
655 vista_sec_id_hash = OSHash_Create();
656 if(!vista_sec_id_hash)
658 merror("%s: ERROR: Unable to read vista security descriptions.",
664 /* Reading the whole file and adding to memory. */
665 while(fgets(buf, OS_MAXSTR, fp) != NULL)
670 /* Getting the last occurence of \n */
671 if ((p = strrchr(buf, '\n')) != NULL)
676 p = strchr(buf, ',');
679 merror("%s: ERROR: Invalid entry on the Vista security "
680 "description.", ARGV0);
687 /* Removing white spaces. */
692 /* Allocating memory. */
697 merror("%s: ERROR: Invalid entry on the Vista security "
698 "description.", ARGV0);
703 /* Inserting on hash. */
704 OSHash_Add(vista_sec_id_hash, key, desc);
711 /** void win_startel()
712 * Starts the event logging for windows
714 void win_startel(char *evt_log)
716 int entries_count = 0;
721 merror(EVTLOG_DUP, ARGV0, evt_log);
726 /* Creating the dll hash. */
729 dll_hash = OSHash_Create();
732 merror("%s: ERROR: Unable to create DLL hash.",
738 /* Starting event log -- going to last available record */
739 if((entries_count = startEL(evt_log, &el[el_last])) < 0)
741 merror(INV_EVTLOG, ARGV0, evt_log);
746 readel(&el[el_last], 0);
752 /** void win_readel()
753 * Reads the event logging for windows
759 /* Sleep plus 2 seconds before reading again */