Imported Upstream version 2.7
[ossec-hids.git] / src / win32 / extract-win-el.c
1 /* @(#) $Id: ./src/win32/extract-win-el.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All right reserved.
6  *
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
10  * Foundation
11  */
12
13
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <time.h>
18
19 #include <windows.h>
20
21 #define BUFFER_SIZE 2048*64
22 #define DEFAULT_FILE    "C:\\ossec-extracted-evt.log"
23
24 FILE *fp;
25 char *file = DEFAULT_FILE;
26 char *name = "ossec-extract-evtlog.exe";
27
28 /* Event logging local structure */
29 typedef struct _os_el
30 {
31     int time_of_last;   
32     char *name;
33
34     EVENTLOGRECORD *er;
35     HANDLE h;
36
37     DWORD record;
38 }os_el;
39 os_el el[3];
40 int el_last = 0;
41
42
43 /** int startEL(char *app, os_el *el)
44  * Starts the event logging for each el
45  */
46 int startEL(char *app, os_el *el)
47 {
48     /* Opening the event log */
49     el->h = OpenEventLog(NULL, app);
50     if(!el->h)
51     {
52         return(0);      
53     }
54
55     el->name = app;
56     GetOldestEventLogRecord(el->h, &el->record);
57
58     return(1);
59 }
60
61
62
63 /** char *el_getCategory(int category_id)
64  * Returns a string related to the category id of the log.
65  */
66 char *el_getCategory(int category_id)
67 {
68     char *cat;
69     switch(category_id)
70     {
71         case EVENTLOG_ERROR_TYPE:
72             cat = "ERROR";
73             break;
74         case EVENTLOG_WARNING_TYPE:
75             cat = "WARNING";
76             break;
77         case EVENTLOG_INFORMATION_TYPE:
78             cat = "INFORMATION";
79             break;
80         case EVENTLOG_AUDIT_SUCCESS:
81             cat = "AUDIT_SUCCESS";
82             break;
83         case EVENTLOG_AUDIT_FAILURE:
84             cat = "AUDIT_FAILURE";
85             break;
86         default:
87             cat = "Unknown";
88             break;
89     }
90     return(cat);
91 }
92
93
94 /** int el_getEventDLL(char *evt_name, char *source, char *event)
95  * Returns the event.
96  */
97 int el_getEventDLL(char *evt_name, char *source, char *event)
98 {
99     HKEY key;
100     DWORD ret;
101     char keyname[256];
102
103
104     keyname[255] = '\0';
105
106     snprintf(keyname, 254,
107             "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s",
108             evt_name,
109             source);
110
111     /* Opening registry */      
112     if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_ALL_ACCESS, &key)
113             != ERROR_SUCCESS)
114     {
115         return(0);
116     }
117
118
119     ret = MAX_PATH -1;  
120     if (RegQueryValueEx(key, "EventMessageFile", NULL,
121                 NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS)
122     {
123         event[0] = '\0';        
124         return(0);
125     }
126
127     RegCloseKey(key);
128     return(1);
129 }
130
131
132
133 /** char *el_getmessage()
134  * Returns a descriptive message of the event.
135  */
136 char *el_getMessage(EVENTLOGRECORD *er,  char *name,
137                     char * source, LPTSTR *el_sstring)
138 {
139     DWORD fm_flags = 0;
140     char tmp_str[257];
141     char event[MAX_PATH +1];
142     char *curr_str;
143     char *next_str;
144     LPSTR message = NULL;
145
146     HMODULE hevt;
147
148     /* Initializing variables */
149     event[MAX_PATH] = '\0';
150     tmp_str[256] = '\0';
151
152     /* Flags for format event */
153     fm_flags |= FORMAT_MESSAGE_FROM_HMODULE;
154     fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
155     fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
156
157     /* Get the file name from the registry (stored on event) */
158     if(!el_getEventDLL(name, source, event))
159     {
160         return(NULL);   
161     }   
162
163     curr_str = event;
164
165     /* If our event has multiple libraries, try each one of them */
166     while((next_str = strchr(curr_str, ';')))
167     {
168         *next_str = '\0';
169         next_str++;
170
171         ExpandEnvironmentStrings(curr_str, tmp_str, 255);
172         hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES);
173         if(hevt)
174         {
175             if(!FormatMessage(fm_flags, hevt, er->EventID,
176                         0,
177                         (LPTSTR) &message, 0, el_sstring))
178             {
179                 message = NULL;         
180             }
181             FreeLibrary(hevt);
182
183             /* If we have a message, we can return it */
184             if(message)
185                 return(message);
186         }
187
188         curr_str = next_str;            
189     }
190
191     ExpandEnvironmentStrings(curr_str, tmp_str, 255);
192     hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES);
193     if(hevt)
194     {
195         int hr;
196         if(!(hr = FormatMessage(fm_flags, hevt, er->EventID,
197                         0,
198                         (LPTSTR) &message, 0, el_sstring)))
199         {
200             message = NULL;             
201         }
202         FreeLibrary(hevt);
203
204         /* If we have a message, we can return it */
205         if(message)
206             return(message);
207     }
208
209     return(NULL);
210 }
211
212
213
214 /** void readel(os_el *el)
215  * Reads the event log.
216  */
217 void readel(os_el *el, int printit)
218 {
219     DWORD nstr;
220     DWORD user_size;
221     DWORD domain_size;
222     DWORD read, needed;
223     int size_left;
224     int str_size;
225
226     char mbuffer[BUFFER_SIZE];
227     LPSTR sstr = NULL;
228
229     char *tmp_str = NULL;
230     char *category;
231     char *source;
232     char *computer_name;
233     char *descriptive_msg;
234
235     char el_user[257];
236     char el_domain[257];
237     char el_string[1025];
238     char final_msg[1024];
239     LPSTR el_sstring[57];
240
241     /* Er must point to the mbuffer */
242     el->er = (EVENTLOGRECORD *) &mbuffer;
243
244     /* Zeroing the last values */
245     el_string[1024] = '\0';
246     el_user[256] = '\0';
247     el_domain[256] = '\0';
248     final_msg[1023] = '\0';
249     el_sstring[56] = NULL;
250
251     /* Reading the event log */ 
252     while(ReadEventLog(el->h,
253                 EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
254                 0,
255                 el->er, BUFFER_SIZE -1, &read, &needed))
256     {
257         while(read > 0)
258         {
259
260             /* We need to initialize every variable before the loop */
261             category = el_getCategory(el->er->EventType);
262             source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
263             computer_name = source + strlen(source) + 1;
264             descriptive_msg = NULL;
265
266
267             /* Initialing domain/user size */
268             user_size = 255; domain_size = 255;
269             el_domain[0] = '\0';
270             el_user[0] = '\0';
271
272
273             /* We must have some description */
274             if(el->er->NumStrings)
275             {   
276                 size_left = 1020;       
277
278                 sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
279                 el_string[0] = '\0';
280
281                 for (nstr = 0;nstr < el->er->NumStrings;nstr++)
282                 {
283                     str_size = strlen(sstr);    
284                     strncat(el_string, sstr, size_left);
285
286                     tmp_str= strchr(el_string, '\0');
287                     if(tmp_str)
288                     {
289                         *tmp_str = ' ';         
290                         tmp_str++; *tmp_str = '\0';
291                     }
292                     size_left-=str_size + 1;
293
294                     if(nstr <= 54)
295                         el_sstring[nstr] = (LPSTR)sstr;
296
297                     sstr = strchr( (LPSTR)sstr, '\0');
298                     sstr++;
299                 }
300
301                 /* Get a more descriptive message (if available) */
302                 descriptive_msg = el_getMessage(el->er, el->name, source,
303                                                         el_sstring);
304                 if(descriptive_msg != NULL)
305                 {
306                     /* Remove any \n or \r */
307                     tmp_str = descriptive_msg;
308                     while((tmp_str = strchr(tmp_str, '\n')))
309                     {
310                         *tmp_str = ' ';
311                         tmp_str++;              
312                     }                   
313
314                     tmp_str = descriptive_msg;
315                     while((tmp_str = strchr(tmp_str, '\r')))
316                     {
317                         *tmp_str = ' ';
318                         tmp_str++;              
319                     }                   
320                 }
321             }
322             else
323             {
324                 strncpy(el_string, "(no message)", 1020);       
325             }
326
327
328             /* Getting username */
329             if (el->er->UserSidLength)
330             {
331                 SID_NAME_USE account_type;
332                 if(!LookupAccountSid(NULL, (SID *)((LPSTR)el->er + el->er->UserSidOffset),
333                             el_user, &user_size, el_domain, &domain_size, &account_type))               
334                 {
335                     strncpy(el_user, "(no user)", 255);
336                     strncpy(el_domain, "no domain", 255);
337                 }
338
339             }
340
341             else
342             {
343                 strncpy(el_user, "(no user)", 255);     
344                 strncpy(el_domain, "no domain", 255);   
345             }
346
347
348             if(printit)
349             {
350                 DWORD _evtid = 65535;
351                 int id = (int)el->er->EventID & _evtid;
352
353                 snprintf(final_msg, 1022,
354                         "%d WinEvtLog: %s: %s(%d): %s: %s(%s): %s",
355                                 (int)el->er->TimeGenerated,     
356                         el->name,
357                         category,
358                         id,
359                         source,
360                         el_user,
361                         el_domain,
362                         descriptive_msg != NULL?descriptive_msg:el_string);     
363
364                 fprintf(fp, "%s\n", final_msg); 
365             }
366
367             if(descriptive_msg != NULL)
368                 LocalFree(descriptive_msg);
369
370             /* Changing the point to the er */
371             read -= el->er->Length;
372             el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
373         }               
374
375         /* Setting er to the beginning of the buffer */ 
376         el->er = (EVENTLOGRECORD *)&mbuffer;
377     }
378 }
379
380
381 /** void win_startel()
382  * Starts the event logging for windows
383  */
384 void win_startel(char *evt_log)
385 {
386     startEL(evt_log, &el[el_last]);
387     readel(&el[el_last],1);
388     el_last++;
389 }
390
391 void help()
392 {
393    printf(" OSSEC HIDS - Windows event log extract\n"); 
394    printf("%s -h                Shows this help message\n", name);      
395    printf("%s -e                Extract logs to '%s'\n", name, DEFAULT_FILE);
396    printf("%s -f        <file>  Extract logs to the file specified\n", name);   
397    exit(0);     
398 }
399 /** main **/
400 int main(int argc, char **argv)
401 {
402    name = argv[0];      
403    if((argc == 2)&&(strcmp(argv[1], "-e") == 0))
404    {
405    }
406    else if((argc == 3)&&(strcmp(argv[1], "-f") == 0))
407    {
408       file = argv[2];   
409    }
410    else
411       help();
412
413    fp = fopen(file, "w");
414    if(!fp)
415    {
416       printf("Unable to open file '%s'\n", file);
417       exit(1);
418    }
419
420    win_startel("Application");  
421    win_startel("System");       
422    win_startel("Security");     
423
424    fclose(fp);
425    return(0);
426 }
427
428 /* EOF */