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 epoch_to_human(int time)
93 * Returns a string that is a human readable
94 * datetime from an epoch int.
96 char *epoch_to_human(time_t epoch)
101 ts = localtime(&epoch);
102 strftime(buf, sizeof(buf), "%Y %b %d %H:%M:%S", ts);
107 /** char *el_getCategory(int category_id)
108 * Returns a string related to the category id of the log.
110 char *el_getCategory(int category_id)
115 case EVENTLOG_ERROR_TYPE:
118 case EVENTLOG_WARNING_TYPE:
121 case EVENTLOG_INFORMATION_TYPE:
124 case EVENTLOG_AUDIT_SUCCESS:
125 cat = "AUDIT_SUCCESS";
127 case EVENTLOG_AUDIT_FAILURE:
128 cat = "AUDIT_FAILURE";
139 /** char *el_getEventDLL(char *evt_name, char *source, char *event)
142 char *el_getEventDLL(char *evt_name, char *source, char *event)
152 snprintf(keyname, 510,
153 "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s",
158 /* Checking if we have it in memory. */
159 ret_str = OSHash_Get(dll_hash, keyname + 42);
166 /* Opening registry */
167 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0,
168 KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
175 if (RegQueryValueEx(key, "EventMessageFile", NULL,
176 NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS)
184 /* Adding to memory. */
188 skey = strdup(keyname + 42);
189 sval = strdup(event);
193 OSHash_Add(dll_hash, skey, sval);
197 merror(MEM_ERROR, ARGV0);
207 /** char *el_vista_getmessage()
208 * Returns a descriptive message of the event - Vista only.
210 char *el_vista_getMessage(int evt_id_int, LPTSTR *el_sstring)
213 LPSTR message = NULL;
218 /* Flags for format event */
219 fm_flags |= FORMAT_MESSAGE_FROM_STRING;
220 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
221 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
224 /* Getting descriptive message. */
226 snprintf(evt_id, 15, "%d", evt_id_int);
228 desc_string = OSHash_Get(vista_sec_id_hash, evt_id);
235 if(!FormatMessage(fm_flags, desc_string, 0, 0,
236 (LPTSTR) &message, 0, el_sstring))
246 /** char *el_getmessage()
247 * Returns a descriptive message of the event.
249 char *el_getMessage(EVENTLOGRECORD *er, char *name,
250 char * source, LPTSTR *el_sstring)
254 char event[MAX_PATH +1];
257 LPSTR message = NULL;
261 /* Initializing variables */
262 event[MAX_PATH] = '\0';
266 /* Flags for format event */
267 fm_flags |= FORMAT_MESSAGE_FROM_HMODULE;
268 fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
269 fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
273 /* Get the file name from the registry (stored on event) */
274 if(!(curr_str = el_getEventDLL(name, source, event)))
281 /* If our event has multiple libraries, try each one of them */
282 while((next_str = strchr(curr_str, ';')))
286 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
288 /* Reverting back old value. */
292 /* Loading library. */
293 hevt = LoadLibraryEx(tmp_str, NULL,
294 DONT_RESOLVE_DLL_REFERENCES |
295 LOAD_LIBRARY_AS_DATAFILE);
298 if(!FormatMessage(fm_flags, hevt, er->EventID, 0,
299 (LPTSTR) &message, 0, el_sstring))
305 /* If we have a message, we can return it */
311 curr_str = next_str +1;
315 /* Getting last value. */
316 ExpandEnvironmentStrings(curr_str, tmp_str, 255);
317 hevt = LoadLibraryEx(tmp_str, NULL,
318 DONT_RESOLVE_DLL_REFERENCES |
319 LOAD_LIBRARY_AS_DATAFILE);
323 if(!(hr = FormatMessage(fm_flags, hevt, er->EventID,
325 (LPTSTR) &message, 0, el_sstring)))
331 /* If we have a message, we can return it */
341 /** void readel(os_el *el)
342 * Reads the event log.
344 void readel(os_el *el, int printit)
346 DWORD _evtid = 65535;
355 char mbuffer[BUFFER_SIZE +1];
358 char *tmp_str = NULL;
362 char *descriptive_msg;
364 char el_user[OS_FLSIZE +1];
365 char el_domain[OS_FLSIZE +1];
366 char el_string[OS_MAXSTR +1];
367 char final_msg[OS_MAXSTR +1];
368 LPSTR el_sstring[OS_FLSIZE +1];
370 /* Er must point to the mbuffer */
371 el->er = (EVENTLOGRECORD *) &mbuffer;
373 /* Zeroing the values */
374 el_string[OS_MAXSTR] = '\0';
375 el_user[OS_FLSIZE] = '\0';
376 el_domain[OS_FLSIZE] = '\0';
377 final_msg[OS_MAXSTR] = '\0';
378 el_sstring[0] = NULL;
379 el_sstring[OS_FLSIZE] = NULL;
382 /* Event log is not open */
388 /* Reading the event log */
389 while(ReadEventLog(el->h,
390 EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
392 el->er, BUFFER_SIZE -1, &read, &needed))
396 /* Setting er to the beginning of the buffer */
397 el->er = (EVENTLOGRECORD *)&mbuffer;
405 /* We need to initialize every variable before the loop */
406 category = el_getCategory(el->er->EventType);
407 source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
408 computer_name = source + strlen(source) + 1;
409 descriptive_msg = NULL;
412 /* Getting event id. */
413 id = (int)el->er->EventID & _evtid;
417 /* Initialing domain/user size */
418 user_size = 255; domain_size = 255;
424 /* We must have some description */
425 if(el->er->NumStrings)
427 size_left = OS_MAXSTR - OS_SIZE_1024;
429 sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
432 for (nstr = 0;nstr < el->er->NumStrings;nstr++)
434 str_size = strlen(sstr);
437 strncat(el_string, sstr, size_left);
440 tmp_str = strchr(el_string, '\0');
444 tmp_str++; *tmp_str = '\0';
448 merror("%s: Invalid application string (size+)",
451 size_left-=str_size + 2;
455 el_sstring[nstr] = (LPSTR)sstr;
456 el_sstring[nstr +1] = NULL;
459 sstr = strchr( (LPSTR)sstr, '\0');
466 /* Get a more descriptive message (if available) */
467 if(isVista && strcmp(el->name, "Security") == 0)
469 descriptive_msg = el_vista_getMessage(id, el_sstring);
474 descriptive_msg = el_getMessage(el->er,
480 if(descriptive_msg != NULL)
483 win_format_event_string(descriptive_msg);
488 strncpy(el_string, "(no message)", 128);
492 /* Getting username */
493 if(el->er->UserSidLength)
495 SID_NAME_USE account_type;
496 if(!LookupAccountSid(NULL,
497 (SID *)((LPSTR)el->er +
498 el->er->UserSidOffset),
505 strncpy(el_user, "(no user)", 255);
506 strncpy(el_domain, "no domain", 255);
511 else if(isVista && strcmp(el->name, "Security") == 0)
513 int uid_array_id = -1;
531 if((uid_array_id >= 0) &&
532 el_sstring[uid_array_id] &&
533 el_sstring[uid_array_id +1])
535 strncpy(el_user, el_sstring[uid_array_id], OS_FLSIZE);
536 strncpy(el_domain, el_sstring[uid_array_id +1], OS_FLSIZE);
540 strncpy(el_user, "(no user)", 255);
541 strncpy(el_domain, "no domain", 255);
547 strncpy(el_user, "(no user)", 255);
548 strncpy(el_domain, "no domain", 255);
554 DWORD _evtid = 65535;
555 int id = (int)el->er->EventID & _evtid;
557 final_msg[OS_MAXSTR - OS_LOG_HEADER] = '\0';
558 final_msg[OS_MAXSTR - OS_LOG_HEADER -1] = '\0';
560 snprintf(final_msg, OS_MAXSTR - OS_LOG_HEADER -1,
561 "%s WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s",
562 epoch_to_human((int)el->er->TimeGenerated),
570 descriptive_msg != NULL?descriptive_msg:el_string);
572 if(SendMSG(logr_queue, final_msg, "WinEvtLog",
575 merror(QUEUE_SEND, ARGV0);
579 if(descriptive_msg != NULL)
581 LocalFree(descriptive_msg);
584 /* Changing the point to the er */
585 read -= el->er->Length;
586 el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
589 /* Setting er to the beginning of the buffer */
590 el->er = (EVENTLOGRECORD *)&mbuffer;
595 if(id == ERROR_HANDLE_EOF)
601 /* Event log was cleared. */
602 else if(id == ERROR_EVENTLOG_FILE_CHANGED)
604 char msg_alert[512 +1];
605 msg_alert[512] = '\0';
606 merror("%s: WARN: Event log cleared: '%s'", ARGV0, el->name);
609 /* Send message about cleared */
610 snprintf(msg_alert, 512, "ossec: Event log cleared: '%s'", el->name);
611 SendMSG(logr_queue, msg_alert, "WinEvtLog", LOCALFILE_MQ);
614 /* Closing the event log and reopenning. */
615 CloseEventLog(el->h);
619 if(startEL(el->name, el) < 0)
621 merror("%s: ERROR: Unable to reopen event log '%s'",
628 debug1("%s: WARN: Error reading event log: %d", ARGV0, id);
633 /** void win_read_vista_sec()
634 * Reads vista security description.
636 void win_read_vista_sec()
639 char buf[OS_MAXSTR +1];
643 /* Vista security csv. */
644 fp = fopen("vista_sec.csv", "r");
647 merror("%s: ERROR: Unable to read vista security descriptions.",
653 /* Creating the hash. */
654 vista_sec_id_hash = OSHash_Create();
655 if(!vista_sec_id_hash)
657 merror("%s: ERROR: Unable to read vista security descriptions.",
663 /* Reading the whole file and adding to memory. */
664 while(fgets(buf, OS_MAXSTR, fp) != NULL)
669 /* Getting the last occurence of \n */
670 if ((p = strrchr(buf, '\n')) != NULL)
675 p = strchr(buf, ',');
678 merror("%s: ERROR: Invalid entry on the Vista security "
679 "description.", ARGV0);
686 /* Removing white spaces. */
691 /* Allocating memory. */
696 merror("%s: ERROR: Invalid entry on the Vista security "
697 "description.", ARGV0);
702 /* Inserting on hash. */
703 OSHash_Add(vista_sec_id_hash, key, desc);
710 /** void win_startel()
711 * Starts the event logging for windows
713 void win_startel(char *evt_log)
715 int entries_count = 0;
720 merror(EVTLOG_DUP, ARGV0, evt_log);
725 /* Creating the dll hash. */
728 dll_hash = OSHash_Create();
731 merror("%s: ERROR: Unable to create DLL hash.",
737 /* Starting event log -- going to last available record */
738 if((entries_count = startEL(evt_log, &el[el_last])) < 0)
740 merror(INV_EVTLOG, ARGV0, evt_log);
745 readel(&el[el_last], 0);
751 /** void win_readel()
752 * Reads the event logging for windows
758 /* Sleep plus 2 seconds before reading again */