1 /* @(#) $Id: ./src/logcollector/read_win_el.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
15 #include "logcollector.h"
18 /* This is only for windows */
21 #define BUFFER_SIZE 2048*256
25 /* Event logging local structure */
39 /** Global variables **/
41 /* Maximum of 9 event log sources. */
44 void *vista_sec_id_hash = NULL;
45 void *dll_hash = NULL;
49 /** int startEL(char *app, os_el *el)
50 * Starts the event logging for each el
52 int startEL(char *app, os_el *el)
54 DWORD NumberOfRecords = 0;
56 /* Opening the event log */
57 el->h = OpenEventLog(NULL, app);
60 merror(EVTLOG_OPEN, ARGV0, app);
65 if(GetOldestEventLogRecord(el->h, &el->record) == 0)
67 /* Unable to read oldest event log record */
68 merror(EVTLOG_GETLAST, ARGV0, app);
74 if(GetNumberOfEventLogRecords(el->h, &NumberOfRecords) == 0)
76 merror(EVTLOG_GETLAST, ARGV0, app);
82 if(NumberOfRecords <= 0)
87 return((int)NumberOfRecords);
92 /** char *el_getCategory(int category_id)
93 * Returns a string related to the category id of the log.
95 char *el_getCategory(int category_id)
100 case EVENTLOG_ERROR_TYPE:
103 case EVENTLOG_WARNING_TYPE:
106 case EVENTLOG_INFORMATION_TYPE:
109 case EVENTLOG_AUDIT_SUCCESS:
110 cat = "AUDIT_SUCCESS";
112 case EVENTLOG_AUDIT_FAILURE:
113 cat = "AUDIT_FAILURE";
124 /** char *el_getEventDLL(char *evt_name, char *source, char *event)
127 char *el_getEventDLL(char *evt_name, char *source, char *event)
137 snprintf(keyname, 510,
138 "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s",
143 /* Checking if we have it in memory. */
144 ret_str = OSHash_Get(dll_hash, keyname + 42);
151 /* Opening registry */
152 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0,
153 KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
160 if (RegQueryValueEx(key, "EventMessageFile", NULL,
161 NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS)
169 /* Adding to memory. */
173 skey = strdup(keyname + 42);
174 sval = strdup(event);
178 OSHash_Add(dll_hash, skey, sval);
182 merror(MEM_ERROR, ARGV0);
192 /** char *el_vista_getmessage()
193 * Returns a descriptive message of the event - Vista only.
195 char *el_vista_getMessage(int evt_id_int, LPTSTR *el_sstring)
198 LPSTR message = NULL;
203 /* Flags for format event */
204 fm_flags |= FORMAT_MESSAGE_FROM_STRING;
205 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
206 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
209 /* Getting descriptive message. */
211 snprintf(evt_id, 15, "%d", evt_id_int);
213 desc_string = OSHash_Get(vista_sec_id_hash, evt_id);
220 if(!FormatMessage(fm_flags, desc_string, 0, 0,
221 (LPTSTR) &message, 0, el_sstring))
231 /** char *el_getmessage()
232 * Returns a descriptive message of the event.
234 char *el_getMessage(EVENTLOGRECORD *er, char *name,
235 char * source, LPTSTR *el_sstring)
239 char event[MAX_PATH +1];
242 LPSTR message = NULL;
246 /* Initializing variables */
247 event[MAX_PATH] = '\0';
251 /* Flags for format event */
252 fm_flags |= FORMAT_MESSAGE_FROM_HMODULE;
253 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
254 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
258 /* Get the file name from the registry (stored on event) */
259 if(!(curr_str = el_getEventDLL(name, source, event)))
266 /* If our event has multiple libraries, try each one of them */
267 while((next_str = strchr(curr_str, ';')))
271 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
273 /* Reverting back old value. */
277 /* Loading library. */
278 hevt = LoadLibraryEx(tmp_str, NULL,
279 DONT_RESOLVE_DLL_REFERENCES |
280 LOAD_LIBRARY_AS_DATAFILE);
283 if(!FormatMessage(fm_flags, hevt, er->EventID, 0,
284 (LPTSTR) &message, 0, el_sstring))
290 /* If we have a message, we can return it */
296 curr_str = next_str +1;
300 /* Getting last value. */
301 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
302 hevt = LoadLibraryEx(tmp_str, NULL,
303 DONT_RESOLVE_DLL_REFERENCES |
304 LOAD_LIBRARY_AS_DATAFILE);
308 if(!(hr = FormatMessage(fm_flags, hevt, er->EventID,
310 (LPTSTR) &message, 0, el_sstring)))
316 /* If we have a message, we can return it */
326 /** void readel(os_el *el)
327 * Reads the event log.
329 void readel(os_el *el, int printit)
331 DWORD _evtid = 65535;
340 char mbuffer[BUFFER_SIZE +1];
343 char *tmp_str = NULL;
347 char *descriptive_msg;
349 char el_user[OS_FLSIZE +1];
350 char el_domain[OS_FLSIZE +1];
351 char el_string[OS_MAXSTR +1];
352 char final_msg[OS_MAXSTR +1];
353 LPSTR el_sstring[OS_FLSIZE +1];
355 /* Er must point to the mbuffer */
356 el->er = (EVENTLOGRECORD *) &mbuffer;
358 /* Zeroing the values */
359 el_string[OS_MAXSTR] = '\0';
360 el_user[OS_FLSIZE] = '\0';
361 el_domain[OS_FLSIZE] = '\0';
362 final_msg[OS_MAXSTR] = '\0';
363 el_sstring[0] = NULL;
364 el_sstring[OS_FLSIZE] = NULL;
367 /* Event log is not open */
373 /* Reading the event log */
374 while(ReadEventLog(el->h,
375 EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
377 el->er, BUFFER_SIZE -1, &read, &needed))
381 /* Setting er to the beginning of the buffer */
382 el->er = (EVENTLOGRECORD *)&mbuffer;
390 /* We need to initialize every variable before the loop */
391 category = el_getCategory(el->er->EventType);
392 source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
393 computer_name = source + strlen(source) + 1;
394 descriptive_msg = NULL;
397 /* Getting event id. */
398 id = (int)el->er->EventID & _evtid;
402 /* Initialing domain/user size */
403 user_size = 255; domain_size = 255;
409 /* We must have some description */
410 if(el->er->NumStrings)
412 size_left = OS_MAXSTR - OS_SIZE_1024;
414 sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
417 for (nstr = 0;nstr < el->er->NumStrings;nstr++)
419 str_size = strlen(sstr);
422 strncat(el_string, sstr, size_left);
425 tmp_str = strchr(el_string, '\0');
429 tmp_str++; *tmp_str = '\0';
433 merror("%s: Invalid application string (size+)",
436 size_left-=str_size + 2;
440 el_sstring[nstr] = (LPSTR)sstr;
441 el_sstring[nstr +1] = NULL;
444 sstr = strchr( (LPSTR)sstr, '\0');
451 /* Get a more descriptive message (if available) */
452 if(isVista && strcmp(el->name, "Security") == 0)
454 descriptive_msg = el_vista_getMessage(id, el_sstring);
459 descriptive_msg = el_getMessage(el->er,
465 if(descriptive_msg != NULL)
467 /* Remove any \n or \r */
468 /* Replace tabs from the argument field to spaces.
469 * So whenever we have option:\tvalue\t, it will
470 * become option: value\t
472 tmp_str = descriptive_msg;
473 while(*tmp_str != '\0')
477 else if(*tmp_str == '\r')
479 else if((*tmp_str == ':') && (tmp_str[1] == '\t'))
491 strncpy(el_string, "(no message)", 128);
495 /* Getting username */
496 if(el->er->UserSidLength)
498 SID_NAME_USE account_type;
499 if(!LookupAccountSid(NULL,
500 (SID *)((LPSTR)el->er +
501 el->er->UserSidOffset),
508 strncpy(el_user, "(no user)", 255);
509 strncpy(el_domain, "no domain", 255);
514 else if(isVista && strcmp(el->name, "Security") == 0)
516 int uid_array_id = -1;
534 if((uid_array_id >= 0) &&
535 el_sstring[uid_array_id] &&
536 el_sstring[uid_array_id +1])
538 strncpy(el_user, el_sstring[uid_array_id], OS_FLSIZE);
539 strncpy(el_domain, el_sstring[uid_array_id +1], OS_FLSIZE);
543 strncpy(el_user, "(no user)", 255);
544 strncpy(el_domain, "no domain", 255);
550 strncpy(el_user, "(no user)", 255);
551 strncpy(el_domain, "no domain", 255);
557 DWORD _evtid = 65535;
558 int id = (int)el->er->EventID & _evtid;
560 final_msg[OS_MAXSTR - OS_LOG_HEADER] = '\0';
561 final_msg[OS_MAXSTR - OS_LOG_HEADER -1] = '\0';
563 snprintf(final_msg, OS_MAXSTR - OS_LOG_HEADER -1,
564 "WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s",
572 descriptive_msg != NULL?descriptive_msg:el_string);
574 if(SendMSG(logr_queue, final_msg, "WinEvtLog",
577 merror(QUEUE_SEND, ARGV0);
581 if(descriptive_msg != NULL)
583 LocalFree(descriptive_msg);
586 /* Changing the point to the er */
587 read -= el->er->Length;
588 el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
591 /* Setting er to the beginning of the buffer */
592 el->er = (EVENTLOGRECORD *)&mbuffer;
597 if(id == ERROR_HANDLE_EOF)
603 /* Event log was cleared. */
604 else if(id == ERROR_EVENTLOG_FILE_CHANGED)
606 char msg_alert[512 +1];
607 msg_alert[512] = '\0';
608 merror("%s: WARN: Event log cleared: '%s'", ARGV0, el->name);
611 /* Send message about cleared */
612 snprintf(msg_alert, 512, "ossec: Event log cleared: '%s'", el->name);
613 SendMSG(logr_queue, msg_alert, "WinEvtLog", LOCALFILE_MQ);
616 /* Closing the event log and reopenning. */
617 CloseEventLog(el->h);
621 if(startEL(el->name, el) < 0)
623 merror("%s: ERROR: Unable to reopen event log '%s'",
630 debug1("%s: WARN: Error reading event log: %d", ARGV0, id);
635 /** void win_read_vista_sec()
636 * Reads vista security description.
638 void win_read_vista_sec()
641 char buf[OS_MAXSTR +1];
645 /* Vista security csv. */
646 fp = fopen("vista_sec.csv", "r");
649 merror("%s: ERROR: Unable to read vista security descriptions.",
655 /* Creating the hash. */
656 vista_sec_id_hash = OSHash_Create();
657 if(!vista_sec_id_hash)
659 merror("%s: ERROR: Unable to read vista security descriptions.",
665 /* Reading the whole file and adding to memory. */
666 while(fgets(buf, OS_MAXSTR, fp) != NULL)
671 /* Getting the last occurence of \n */
672 if ((p = strrchr(buf, '\n')) != NULL)
677 p = strchr(buf, ',');
680 merror("%s: ERROR: Invalid entry on the Vista security "
681 "description.", ARGV0);
688 /* Removing white spaces. */
693 /* Allocating memory. */
698 merror("%s: ERROR: Invalid entry on the Vista security "
699 "description.", ARGV0);
704 /* Inserting on hash. */
705 OSHash_Add(vista_sec_id_hash, key, desc);
712 /** void win_startel()
713 * Starts the event logging for windows
715 void win_startel(char *evt_log)
717 int entries_count = 0;
722 merror(EVTLOG_DUP, ARGV0, evt_log);
727 /* Creating the dll hash. */
730 dll_hash = OSHash_Create();
733 merror("%s: ERROR: Unable to create DLL hash.",
739 /* Starting event log -- going to last available record */
740 if((entries_count = startEL(evt_log, &el[el_last])) < 0)
742 merror(INV_EVTLOG, ARGV0, evt_log);
747 readel(&el[el_last], 0);
753 /** void win_readel()
754 * Reads the event logging for windows
760 /* Sleep plus 2 seconds before reading again */