summaryrefslogtreecommitdiff
path: root/log.c
diff options
context:
space:
mode:
authortumagonx2017-08-08 10:54:53 +0700
committertumagonx2017-08-08 10:54:53 +0700
commit2acec63b2ed75bf4b71ad257db573c4b8f9639e7 (patch)
treea8bea139ddd26116d44ea182b0b8436f2162e6e3 /log.c
initial commit
Diffstat (limited to 'log.c')
-rw-r--r--log.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..7048b05
--- /dev/null
+++ b/log.c
@@ -0,0 +1,459 @@
1/*
2 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
3 *
4 * Module Name:
5 *
6 * log.c
7 *
8 * Abstract:
9 *
10 * This module implements various alert logging routines.
11 *
12 * Author:
13 *
14 * Eugene Tsyrklevich 24-Mar-2004
15 *
16 * Revision History:
17 *
18 * None.
19 */
20
21
22#include "log.h"
23#include "procname.h"
24#include "policy.h" // CDrive declaration
25
26
27#ifdef ALLOC_PRAGMA
28#pragma alloc_text (INIT, InitLog)
29#pragma alloc_text (PAGE, ShutdownLog)
30#pragma alloc_text (PAGE, LogPostBootup)
31#endif
32
33
34KSPIN_LOCK gLogSpinLock;
35
36PKEVENT LogUserEvent = NULL;
37HANDLE LogUserEventHandle = NULL;
38
39PSECURITY_ALERT LogList = NULL; /* alert queue */
40PSECURITY_ALERT LastAlert = NULL; /* pointer to the last queued alert, used for quick inserts */
41
42USHORT NumberOfAlerts; /* number of queued alerts */
43
44
45
46/*
47 * GetObjectAccessAlertPriority()
48 *
49 * Description:
50 * Figure out a priority for object access alert category.
51 *
52 * Parameters:
53 * AlertSubSystem
54 * Operation
55 * ActionTaken
56 *
57 * Returns:
58 * Chosen priority.
59 */
60
61ALERT_PRIORITY
62GetObjectAccessAlertPriority(UCHAR AlertSubSystem, UCHAR Operation, ACTION_TYPE ActionTaken)
63{
64 switch (AlertSubSystem)
65 {
66 case RULE_FILE:
67 case RULE_DIRECTORY:
68 case RULE_NAMEDPIPE:
69 case RULE_REGISTRY:
70 case RULE_SECTION:
71 case RULE_JOB:
72 case RULE_PORT:
73 case RULE_SYMLINK:
74
75 /* default actions are given low priority */
76 if (ActionTaken & ACTION_DEFAULT)
77 return ALERT_PRIORITY_LOW;
78
79 /* non-read operations are marked medium priority */
80 if (Operation != OP_READ)
81 return ALERT_PRIORITY_MEDIUM;
82
83 /* whilst read operations are marked low priority */
84 return ALERT_PRIORITY_LOW;
85
86
87 /* high priority rules */
88 case RULE_DLL:
89 case RULE_PROCESS:
90 case RULE_DRIVER:
91 case RULE_NETWORK:
92 case RULE_SERVICE:
93
94 return ALERT_PRIORITY_HIGH;
95
96
97 case RULE_TIME:
98 case RULE_TOKEN:
99
100 return ALERT_PRIORITY_MEDIUM;
101
102
103 /* low priority rules */
104 case RULE_MAILSLOT:
105 case RULE_EVENT:
106 case RULE_SEMAPHORE:
107 case RULE_MUTANT:
108 case RULE_DIROBJ:
109 case RULE_ATOM:
110 case RULE_SYSCALL:
111 case RULE_TIMER:
112
113 return ALERT_PRIORITY_LOW;
114
115
116 default:
117 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("GetAlertPriority: Unknown alert subsystem %d\n", AlertSubSystem));
118 return ALERT_PRIORITY_MEDIUM;
119 }
120}
121
122
123
124/*
125 * FilterObjectName()
126 *
127 * Description:
128 * .
129 *
130 * Parameters:
131 * .
132 *
133 * Returns:
134 * Nothing.
135 */
136//XXX move elsewhere
137PCHAR
138FilterObjectName(PCHAR ObjectName)
139{
140 if (_strnicmp(ObjectName, "\\??\\PIPE\\", 9) == 0)
141 return ObjectName + 3;
142
143 if (_strnicmp(ObjectName, "\\??\\", 4) == 0)
144 return ObjectName + 4;
145
146 if (_strnicmp(ObjectName, "\\DosDevices\\", 12) == 0)
147 return ObjectName + 12;
148
149 if (_strnicmp(ObjectName, "\\BaseNamedObjects\\", 18) == 0)
150 return ObjectName + 18;
151
152 if (_strnicmp(ObjectName, CDrive, CDriveLength) == 0 && CDriveLength)
153 {
154 /* replace any possible \device\harddiskvolumeX references with a DOS C:\ name */
155 ObjectName[CDriveLength-2] = 'C';
156 ObjectName[CDriveLength-1] = ':';
157
158 ObjectName += CDriveLength - 2;
159 }
160
161
162 return ObjectName;
163}
164
165
166
167/*
168 * LogAlert()
169 *
170 * Description:
171 * .
172 *
173 * Parameters:
174 * .
175 *
176 * Returns:
177 * Nothing.
178 */
179
180VOID
181LogAlert(UCHAR AlertSubSystem, UCHAR OperationType, UCHAR AlertRuleNumber, ACTION_TYPE ActionTaken, ALERT_PRIORITY AlertPriority, PWSTR PolicyFilename, USHORT PolicyLineNumber, PCHAR ObjectName)
182{
183 USHORT Size;
184 PSECURITY_ALERT pAlert;
185 KIRQL irql;
186
187#define NAME_BUFFER_SIZE 256
188 ANSI_STRING asObjectName;
189 UNICODE_STRING usObjectName;
190 WCHAR ProcessName[NAME_BUFFER_SIZE], ObjectNameW[NAME_BUFFER_SIZE] = { 0 };
191 USHORT ObjectNameLength = 0, ProcessNameLength = 0, PolicyNameLength = 0;
192
193/*
194 if (PolicyFilename == NULL)
195 {
196 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, (("LogAlert: NULL PolicyFilename\n"));
197 return;
198 }
199*/
200
201 /* \KnownDlls section rules need to be converted to DLLs */
202 if (AlertSubSystem == RULE_SECTION)
203 {
204 if (_strnicmp(ObjectName, "\\KnownDlls\\", 11) == 0)
205 {
206 ObjectName += 11;
207 AlertSubSystem = RULE_DLL;
208 OperationType = OP_LOAD;
209 }
210 }
211
212
213 if (ObjectName)
214 {
215 ObjectName = FilterObjectName(ObjectName);
216
217 usObjectName.Length = 0;
218 usObjectName.MaximumLength = sizeof(ObjectNameW);
219 usObjectName.Buffer = ObjectNameW;
220
221 RtlInitAnsiString(&asObjectName, ObjectName);
222
223 RtlAnsiStringToUnicodeString(&usObjectName, &asObjectName, FALSE);
224 ObjectNameW[ asObjectName.Length ] = 0;
225 }
226
227
228 wcsncpy(ProcessName, GetCurrentProcessName(), NAME_BUFFER_SIZE - 1);
229 ProcessName[NAME_BUFFER_SIZE - 1] = 0;
230
231
232 /*
233 * extra +1 for ProcessName & PolicyName zero termination
234 * (ObjectName zero is covered by SECURITY_ALERT wchar[1] declaration)
235 */
236
237 if (ObjectName)
238 ObjectNameLength = (USHORT) wcslen(ObjectNameW);
239
240 ProcessNameLength = (USHORT) wcslen(ProcessName);
241
242 if (PolicyFilename)
243 PolicyNameLength = (USHORT) wcslen(PolicyFilename);
244
245 Size = sizeof(SECURITY_ALERT) + (ObjectNameLength + ProcessNameLength + 1 + PolicyNameLength + 1) * sizeof(WCHAR);
246
247
248 if ((pAlert = (PSECURITY_ALERT) GetCurrentUserSid(&Size)) == NULL)
249 {
250 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("NULL UserInfo. Security Alert\n"));
251 return;
252 }
253
254
255 pAlert->Next = NULL;
256 pAlert->Size = Size;
257 pAlert->AlertSubsystem = AlertSubSystem;
258 pAlert->AlertType = OperationType;
259 pAlert->AlertRuleNumber = AlertRuleNumber;
260 pAlert->Priority = AlertPriority;
261 pAlert->ObjectNameLength = ObjectNameLength;
262 pAlert->ProcessNameLength = ProcessNameLength;
263 pAlert->PolicyNameLength = PolicyNameLength;
264 pAlert->ProcessId = (ULONG) PsGetCurrentProcessId();
265 pAlert->Action = ActionTaken;
266 pAlert->PolicyLineNumber = PolicyLineNumber;
267
268
269 if (ObjectName)
270 wcscpy(pAlert->ObjectName, ObjectNameW);
271
272 /* process name follows the object name */
273 wcscpy(pAlert->ObjectName + ObjectNameLength + 1, ProcessName);
274
275 /* policy name follows the process name */
276 if (PolicyFilename)
277 wcscpy(pAlert->ObjectName + ObjectNameLength + 1 + ProcessNameLength + 1, PolicyFilename);
278
279 /* save the alert for user agent to pick-up */
280 if (ObjectName)
281 {
282 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%S Alert. Name %S. Object type %d. Alert type %d.\n", ProcessName, pAlert->ObjectName, pAlert->AlertSubsystem, pAlert->AlertType));
283 }
284 else
285 {
286 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%S Alert. Object type %d. Alert type %d.\n", ProcessName, pAlert->AlertSubsystem, pAlert->AlertType));
287 }
288
289
290 KeAcquireSpinLock(&gLogSpinLock, &irql);
291 {
292 /*
293 * Put a ceiling on how many alerts we can queue, otherwise we can run out of memory
294 * if userland service is down
295 */
296
297 if (NumberOfAlerts > MAXIMUM_OUTSTANDING_ALERTS)
298 {
299 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("LogAlert: Exceeded maximum number of queued alerts. Dropping.\n"));
300
301 ExFreePoolWithTag(pAlert, _POOL_TAG);
302
303 KeReleaseSpinLock(&gLogSpinLock, irql);
304
305 return;
306 }
307
308 ++NumberOfAlerts;
309
310 /*
311 * Append alerts to the end of the list so that they show up in a proper order when
312 * picked up by the userland service
313 */
314
315 if (LogList == NULL)
316 {
317 /* first alert on the list */
318 LastAlert = LogList = pAlert;
319 }
320 else
321 {
322 LastAlert->Next = pAlert;
323 LastAlert = pAlert;
324 }
325
326// pAlert->Next = LogList;
327// LogList = pAlert;
328 }
329 KeReleaseSpinLock(&gLogSpinLock, irql);
330
331
332 /*
333 * Pulse the event to notify the user agent.
334 * User-mode apps can't reset a kernel mode event, which is why we're pulsing it here.
335 */
336
337 if (LogUserEvent)
338 {
339 KeSetEvent(LogUserEvent, 0, FALSE);
340 KeClearEvent(LogUserEvent);
341 }
342}
343
344
345
346/*
347 * LogPostBootup()
348 *
349 * Description:
350 * Initializes logging related data once computer is done booting up.
351 *
352 * \BaseNamedObjects object directory is not created until the Win32® system initializes.
353 * Therefore, drivers that are loaded at boot time cannot create event objects in their DriverEntry
354 * routines that are visible to user-mode programs.
355 *
356 * Parameters:
357 * None.
358 *
359 * Returns:
360 * TRUE to indicate success, FALSE if failed.
361 */
362
363BOOLEAN
364LogPostBootup()
365{
366 UNICODE_STRING uszLogEventString;
367
368
369 ASSERT(BootingUp == FALSE);
370
371
372 /* Create events for user-mode processes to monitor */
373 RtlInitUnicodeString(&uszLogEventString, LOG_USER_EVENT_NAME);
374
375
376 if ((LogUserEvent = IoCreateNotificationEvent(&uszLogEventString, &LogUserEventHandle)) == NULL)
377 {
378 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("LogPostBootup: IoCreateNotificationEvent failed\n"));
379 return FALSE;
380 }
381
382 KeClearEvent(LogUserEvent);
383
384
385 return TRUE;
386}
387
388
389
390/*
391 * InitLog()
392 *
393 * Description:
394 * Initializes logging related data.
395 *
396 * NOTE: Called once during driver initialization (DriverEntry()).
397 *
398 * Parameters:
399 * None.
400 *
401 * Returns:
402 * TRUE to indicate success, FALSE if failed.
403 */
404
405BOOLEAN
406InitLog()
407{
408 KeInitializeSpinLock(&gLogSpinLock);
409
410
411 if (BootingUp == FALSE)
412
413 return LogPostBootup();
414
415
416 return TRUE;
417}
418
419
420
421/*
422 * ShutdownLog()
423 *
424 * Description:
425 * Clean up the logging subsystem - close all the handles & delete any outstanding alerts.
426 *
427 * NOTE: Called once during driver unload (DriverUnload()).
428 *
429 * Parameters:
430 * None.
431 *
432 * Returns:
433 * Nothing.
434 */
435
436VOID
437ShutdownLog()
438{
439 PSECURITY_ALERT tmp;
440 KIRQL irql;
441
442
443 if (LogUserEventHandle)
444 ZwClose(LogUserEventHandle);
445
446
447 /* XXX logs will need to be flushed to a file and then sent to MC */
448 KeAcquireSpinLock(&gLogSpinLock, &irql);
449 {
450 while (LogList)
451 {
452 tmp = LogList;
453 LogList = LogList->Next;
454
455 ExFreePoolWithTag(tmp, _POOL_TAG);
456 }
457 }
458 KeReleaseSpinLock(&gLogSpinLock, irql);
459}