summaryrefslogtreecommitdiff
path: root/userland.c
diff options
context:
space:
mode:
authortumagonx2017-08-08 10:54:53 +0700
committertumagonx2017-08-08 10:54:53 +0700
commit2acec63b2ed75bf4b71ad257db573c4b8f9639e7 (patch)
treea8bea139ddd26116d44ea182b0b8436f2162e6e3 /userland.c
initial commit
Diffstat (limited to 'userland.c')
-rw-r--r--userland.c573
1 files changed, 573 insertions, 0 deletions
diff --git a/userland.c b/userland.c
new file mode 100644
index 0000000..805a413
--- /dev/null
+++ b/userland.c
@@ -0,0 +1,573 @@
1/*
2 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
3 *
4 * Module Name:
5 *
6 * userland.c
7 *
8 * Abstract:
9 *
10 * This module defines various types routines used to interact with userland agent service.
11 *
12 * Author:
13 *
14 * Eugene Tsyrklevich 18-Apr-2004
15 *
16 * Revision History:
17 *
18 * None.
19 */
20
21
22#include "userland.h"
23#include "procname.h"
24#include "process.h"
25
26
27#ifdef ALLOC_PRAGMA
28#pragma alloc_text (INIT, InitUserland)
29#pragma alloc_text (PAGE, ShutdownUserland)
30#pragma alloc_text (PAGE, UserlandPostBootup)
31#endif
32
33
34BOOLEAN ActiveUserAgent = FALSE;
35
36PKEVENT UserlandRequestUserEvent = NULL;
37HANDLE UserlandRequestUserEventHandle = NULL;
38
39PUSERLAND_REQUEST_HEADER UserlandRequestList = NULL;
40KSPIN_LOCK gUserlandRequestListSpinLock;
41
42BOOLEAN CacheSid = TRUE;
43ULONG CachedSidSize = 0, CachedSidReplySize = 0;
44PVOID CachedSid = NULL;
45PSID_RESOLVE_REPLY CachedSidReply = NULL;
46
47UCHAR SeqId = 0; /* global sequence id used for matching up userland requests & replies */
48
49
50
51/*
52 * UserlandPostBootup()
53 *
54 * Description:
55 * Initializes userland related data once computer is done booting up.
56 *
57 * \BaseNamedObjects object directory is not created until the Win32® system initializes.
58 * Therefore, drivers that are loaded at boot time cannot create event objects in their DriverEntry
59 * routines that are visible to user-mode programs.
60 *
61 * Parameters:
62 * None.
63 *
64 * Returns:
65 * TRUE to indicate success, FALSE if failed.
66 */
67
68BOOLEAN
69UserlandPostBootup()
70{
71 UNICODE_STRING uszUserlandRequestEvent;
72
73
74 ASSERT(BootingUp == FALSE);
75
76
77 KeInitializeSpinLock(&gUserlandRequestListSpinLock);
78
79
80 /* Create an event for userland agent service to monitor */
81#define USERLAND_REQUEST_EVENT_NAME L"\\BaseNamedObjects\\OzoneUserlandRequestEvent"
82
83 RtlInitUnicodeString(&uszUserlandRequestEvent, USERLAND_REQUEST_EVENT_NAME);
84
85
86 if ((UserlandRequestUserEvent = IoCreateNotificationEvent(&uszUserlandRequestEvent, &UserlandRequestUserEventHandle)) == NULL)
87 {
88 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("UserlandPostBootup: IoCreateNotificationEvent failed\n"));
89 return FALSE;
90 }
91
92 KeClearEvent(UserlandRequestUserEvent);
93
94
95 return TRUE;
96}
97
98
99
100/*
101 * IssueUserlandSidResolveRequest()
102 *
103 * Description:
104 * Resolves binary SID to its ASCII representation by querying a userland agent.
105 *
106 * Parameters:
107 * .
108 *
109 * Returns:
110 * TRUE to indicate success, FALSE otherwise.
111 */
112
113BOOLEAN
114IssueUserlandSidResolveRequest(PIMAGE_PID_ENTRY Process)
115{
116 PSID_RESOLVE_REQUEST pSidResolveRequest;
117 USHORT Size;
118 PCHAR UserSidBuffer;
119 KIRQL irql;
120 LARGE_INTEGER liDelay;
121 NTSTATUS status;
122
123
124 ASSERT(Process);
125
126
127 if (!ActiveUserAgent)
128 {
129 LOG(LOG_SS_MISC, LOG_PRIORITY_VERBOSE, ("IssueUserlandSidResolveRequest: no Agent Service\n"));
130 return FALSE;
131 }
132
133 if (KeGetCurrentIrql() != PASSIVE_LEVEL)
134 {
135 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Running at high IRQL\n"));
136 return FALSE;
137 }
138
139 if (Process->ProcessId == SystemProcessId)
140 {
141 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Cannot issue requests on behalf of SYSTEM process\n"));
142// return FALSE;
143 }
144
145
146 /*
147 * the following code assumes that SID_RESOLVE_REQUESTS consists of USERLAND_REQUEST_HEADER
148 * followed by PSID_AND_ATTRIBUTES.
149 *
150 * GetCurrentUserSid() allocates memory for user sid + PSID_AND_ATTRIBUTES and converts SID
151 * from absolute into relative format.
152 */
153
154 Size = sizeof(USERLAND_REQUEST_HEADER);
155 UserSidBuffer = GetCurrentUserSid(&Size);
156
157 if (UserSidBuffer == NULL)
158 {
159 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: out of memory\n"));
160 return FALSE;
161 }
162
163 /* check for a previously resolved cached SID */
164 while (CacheSid == TRUE)
165 {
166 int SidSize = Size - sizeof(USERLAND_REQUEST_HEADER);
167
168
169 /* cache hit? */
170 if (CachedSid && CachedSidReply &&
171 SidSize == CachedSidSize &&
172 memcmp(UserSidBuffer + sizeof(USERLAND_REQUEST_HEADER), CachedSid, CachedSidSize) == 0)
173 {
174 Process->WaitingForUserRequestId = 0;
175 Process->UserlandReply = ExAllocatePoolWithTag(PagedPool, CachedSidReplySize, _POOL_TAG);
176
177 if (Process->UserlandReply == NULL)
178 {
179 ExFreePoolWithTag(UserSidBuffer, _POOL_TAG);
180 return FALSE;
181 }
182
183 memcpy(Process->UserlandReply, CachedSidReply, CachedSidReplySize);
184
185 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Cache hit. Returning username %S\n", CachedSidReply->UserName));
186
187 ExFreePoolWithTag(UserSidBuffer, _POOL_TAG);
188
189 return TRUE;
190 }
191
192
193 /* cache miss */
194 CachedSidSize = SidSize;
195
196 if (CachedSid)
197 ExFreePoolWithTag(CachedSid, _POOL_TAG);
198
199 CachedSid = ExAllocatePoolWithTag(PagedPool, SidSize, _POOL_TAG);
200
201 if (CachedSid == NULL)
202 {
203 ExFreePoolWithTag(UserSidBuffer, _POOL_TAG);
204 return FALSE;
205 }
206
207 memcpy(CachedSid, UserSidBuffer + sizeof(USERLAND_REQUEST_HEADER), SidSize);
208
209 if (CachedSidReply)
210 {
211 ExFreePoolWithTag(CachedSidReply, _POOL_TAG);
212 CachedSidReply = NULL;
213 }
214
215 break;
216 }
217
218
219 pSidResolveRequest = (PSID_RESOLVE_REQUEST) UserSidBuffer;
220
221
222 pSidResolveRequest->RequestHeader.RequestType = USERLAND_SID_RESOLVE_REQUEST;
223 pSidResolveRequest->RequestHeader.RequestSize = Size;
224 pSidResolveRequest->RequestHeader.ProcessId = Process->ProcessId;
225
226 if (++SeqId == 0) SeqId = 1;
227 pSidResolveRequest->RequestHeader.SeqId = SeqId;
228
229
230 KeAcquireSpinLock(&gUserlandRequestListSpinLock, &irql);
231 {
232 pSidResolveRequest->RequestHeader.Next = UserlandRequestList;
233 UserlandRequestList = (PUSERLAND_REQUEST_HEADER) pSidResolveRequest;
234 }
235 KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql);
236
237
238 Process->WaitingForUserRequestId = SeqId;
239 Process->UserlandReply = NULL;
240
241
242 KeClearEvent(&Process->UserlandRequestDoneEvent);
243
244
245 /* signal the userland agent service */
246 if (UserlandRequestUserEvent)
247 {
248 /* pulse twice since userland sometimes misses single pulses */
249 KeSetEvent(UserlandRequestUserEvent, 0, FALSE);
250 KeClearEvent(UserlandRequestUserEvent);
251
252 KeSetEvent(UserlandRequestUserEvent, 0, FALSE);
253 KeClearEvent(UserlandRequestUserEvent);
254 }
255 else
256 {
257 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: UserlandRequestUserEvent is NULL\n"));
258 }
259
260
261 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d IssueUserlandSidResolveRequest: Waiting for agent service\n", CURRENT_PROCESS_PID));
262
263
264 /* wait for the userland service to reply (wait for maximum of USERLAND_REQUEST_TIMEOUT seconds) */
265 liDelay.QuadPart = SECONDS(USERLAND_REQUEST_TIMEOUT);
266
267 status = KeWaitForSingleObject(&Process->UserlandRequestDoneEvent, UserRequest, KernelMode, FALSE, &liDelay);
268
269
270 Process->WaitingForUserRequestId = 0;
271
272 if (status == STATUS_TIMEOUT)
273 {
274 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: KeWaitForSingleObject timed out\n"));
275 }
276 else
277 {
278 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: KeWaitForSingleObject returned\n"));
279
280 /* cache the resolved Sid */
281 if (CacheSid == TRUE && Process->UserlandReply != NULL)
282 {
283 CachedSidReply = ExAllocatePoolWithTag(PagedPool, Process->UserlandReply->ReplySize, _POOL_TAG);
284
285 if (CachedSidReply)
286 {
287 memcpy(CachedSidReply, Process->UserlandReply, Process->UserlandReply->ReplySize);
288
289 CachedSidReplySize = Process->UserlandReply->ReplySize;
290 }
291 }
292 }
293
294
295 /* at this point UserSidBuffer/pSidResolveRequest has already been deallocated in driver.c!DriverDeviceControl */
296
297
298 return TRUE;
299}
300
301
302
303/*
304 * IssueUserlandAskUserRequest()
305 *
306 * Description:
307 * .
308 *
309 * Parameters:
310 * .
311 *
312 * Returns:
313 * .
314 */
315
316ACTION_TYPE
317IssueUserlandAskUserRequest(RULE_TYPE RuleType, UCHAR OperationType, PCHAR ObjectName)
318{
319 ACTION_TYPE Action = ACTION_DENY_DEFAULT;
320 PIMAGE_PID_ENTRY Process;
321 PASK_USER_REQUEST pAskUserRequest;
322 USHORT Size;
323 KIRQL irql;
324 LARGE_INTEGER liDelay;
325 NTSTATUS status;
326
327#define NAME_BUFFER_SIZE 256
328 ANSI_STRING asObjectName;
329 UNICODE_STRING usObjectName;
330 WCHAR ObjectNameW[NAME_BUFFER_SIZE] = { 0 };
331
332
333 ASSERT(ObjectName);
334
335
336 if (!ActiveUserAgent)
337 {
338 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: no Agent Service\n"));
339 return Action;
340 }
341
342 if (KeGetCurrentIrql() != PASSIVE_LEVEL)
343 {
344 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: Running at high IRQL\n"));
345 return FALSE;
346 }
347
348
349 if (CURRENT_PROCESS_PID == SystemProcessId)
350 {
351 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: Cannot issue requests on behalf of SYSTEM process\n"));
352 return FALSE;
353 }
354
355
356 Process = FindImagePidEntry(CURRENT_PROCESS_PID, 0);
357 if (Process == NULL)
358 {
359 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: Process %d not found\n", CURRENT_PROCESS_PID));
360 return Action;
361 }
362
363
364 /* \KnownDlls section rules need to be converted to DLLs */
365 if (RuleType == RULE_SECTION)
366 {
367 if (_strnicmp(ObjectName, "\\KnownDlls\\", 11) == 0)
368 {
369 ObjectName += 11;
370 RuleType = RULE_DLL;
371 OperationType = OP_LOAD;
372 }
373 }
374
375
376 ObjectName = FilterObjectName(ObjectName);
377
378 usObjectName.Length = 0;
379 usObjectName.MaximumLength = sizeof(ObjectNameW);
380 usObjectName.Buffer = ObjectNameW;
381
382 RtlInitAnsiString(&asObjectName, ObjectName);
383
384 RtlAnsiStringToUnicodeString(&usObjectName, &asObjectName, FALSE);
385 ObjectNameW[ asObjectName.Length ] = 0;
386
387
388 /* extra +1 for ProcessName zero termination */
389 Size = sizeof(ASK_USER_REQUEST) + (wcslen(ObjectNameW) + wcslen(Process->ImageName) + 1) * sizeof(WCHAR);
390
391 pAskUserRequest = ExAllocatePoolWithTag(NonPagedPool, Size, _POOL_TAG);
392
393 if (pAskUserRequest == NULL)
394 {
395 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: out of memory\n"));
396 return Action;
397 }
398
399
400 pAskUserRequest->RequestHeader.RequestType = USERLAND_ASK_USER_REQUEST;
401 pAskUserRequest->RequestHeader.RequestSize = Size;
402 pAskUserRequest->RequestHeader.ProcessId = Process->ProcessId;
403
404 if (++SeqId == 0) SeqId = 1;
405 pAskUserRequest->RequestHeader.SeqId = SeqId;
406
407 pAskUserRequest->RuleType = RuleType;
408 pAskUserRequest->OperationType = OperationType;
409 pAskUserRequest->ObjectNameLength = (USHORT) wcslen(ObjectNameW);
410 pAskUserRequest->ProcessNameLength = (USHORT) wcslen(Process->ImageName);
411
412 wcscpy(pAskUserRequest->ObjectName, ObjectNameW);
413
414 /* process name follows the object name */
415 wcscpy(pAskUserRequest->ObjectName + pAskUserRequest->ObjectNameLength + 1, Process->ImageName);
416
417
418 KeAcquireSpinLock(&gUserlandRequestListSpinLock, &irql);
419 {
420 pAskUserRequest->RequestHeader.Next = UserlandRequestList;
421 UserlandRequestList = (PUSERLAND_REQUEST_HEADER) pAskUserRequest;
422 }
423 KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql);
424
425
426 Process->WaitingForUserRequestId = SeqId;
427 Process->UserlandReply = NULL;
428
429
430 KeClearEvent(&Process->UserlandRequestDoneEvent);
431
432
433 /* signal the userland agent service */
434 if (UserlandRequestUserEvent)
435 {
436 /* pulse twice since userland sometimes misses single pulses */
437 KeSetEvent(UserlandRequestUserEvent, 0, FALSE);
438 KeClearEvent(UserlandRequestUserEvent);
439
440 KeSetEvent(UserlandRequestUserEvent, 0, FALSE);
441 KeClearEvent(UserlandRequestUserEvent);
442 }
443 else
444 {
445 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: UserlandRequestUserEvent is NULL\n"));
446 }
447
448
449 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d IssueUserlandAskUserRequest: Waiting for agent service\n", CURRENT_PROCESS_PID));
450
451
452 /* wait for the user/userland service to reply (wait for maximum of USERLAND_REQUEST_TIMEOUT seconds) */
453 liDelay.QuadPart = SECONDS(USERLAND_REQUEST_TIMEOUT);
454
455 status = KeWaitForSingleObject(&Process->UserlandRequestDoneEvent, UserRequest, KernelMode, FALSE, &liDelay);
456
457
458 Process->WaitingForUserRequestId = 0;
459
460 if (status != STATUS_TIMEOUT)
461 {
462 PASK_USER_REPLY pAskUserReply = (PASK_USER_REPLY) Process->UserlandReply;
463
464 if (pAskUserReply)
465 {
466 Action = pAskUserReply->Action;
467
468 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: received back action %d\n", Action));
469
470 ExFreePoolWithTag(Process->UserlandReply, _POOL_TAG);
471 Process->UserlandReply = NULL;
472 }
473
474 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: IssueUserlandAskUserRequest returned\n"));
475 }
476 else
477 {
478 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandAskUserRequest: KeWaitForSingleObject timed out\n"));
479
480 //XXX need to remove pAskUserRequest from the list
481 }
482
483
484 /* at this point pAskUserRequest has already been deallocated in driver.c!DriverDeviceControl */
485
486
487 return Action;
488}
489
490
491
492/*
493 * InitUserland()
494 *
495 * Description:
496 * Initializes all the userland related data.
497 *
498 * NOTE: Called once during driver initialization (DriverEntry()).
499 *
500 * Parameters:
501 * None.
502 *
503 * Returns:
504 * TRUE to indicate success, FALSE if failed.
505 */
506
507BOOLEAN
508InitUserland()
509{
510 if (BootingUp == FALSE)
511 {
512 if (UserlandPostBootup() == FALSE)
513
514 return FALSE;
515 }
516
517
518 return TRUE;
519}
520
521
522
523/*
524 * ShutdownUserland()
525 *
526 * Description:
527 * XXX.
528 *
529 * NOTE: Called once during driver unload (DriverUnload()).
530 *
531 * Parameters:
532 * None.
533 *
534 * Returns:
535 * Nothing.
536 */
537
538VOID
539ShutdownUserland()
540{
541 PUSERLAND_REQUEST_HEADER tmp;
542 KIRQL irql;
543
544
545 if (UserlandRequestUserEventHandle)
546 ZwClose(UserlandRequestUserEventHandle);
547
548
549 KeAcquireSpinLock(&gUserlandRequestListSpinLock, &irql);
550 {
551 while (UserlandRequestList)
552 {
553 tmp = UserlandRequestList;
554 UserlandRequestList = UserlandRequestList->Next;
555
556 ExFreePoolWithTag(tmp, _POOL_TAG);
557 }
558 }
559 KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql);
560
561
562 if (CachedSid)
563 {
564 ExFreePoolWithTag(CachedSid, _POOL_TAG);
565 CachedSid = NULL;
566 }
567
568 if (CachedSidReply)
569 {
570 ExFreePoolWithTag(CachedSidReply, _POOL_TAG);
571 CachedSidReply = NULL;
572 }
573}