1 /*
2 * PROJECT: ReactOS Winlogon
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security utility infrastructure implementation of Winlogon
5 * COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org>
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include "winlogon.h"
11
12 /* DEFINES ******************************************************************/
13
14 #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
15 DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
16 DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
17 DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
18
19 #define DESKTOP_ADMINS_LIMITED (DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | \
20 DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_ENUMERATE)
21
22 #define DESKTOP_INTERACTIVE_LIMITED (STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | \
23 DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW)
24
25 #define DESKTOP_WINLOGON_ADMINS_LIMITED (STANDARD_RIGHTS_REQUIRED | DESKTOP_ENUMERATE)
26
27 #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
28 WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
29 WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
30 WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
31 STANDARD_RIGHTS_REQUIRED)
32
33 #define WINSTA_ADMINS_LIMITED (WINSTA_READATTRIBUTES | WINSTA_ENUMERATE)
34
35 #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
36 GENERIC_EXECUTE | GENERIC_ALL)
37
38 /* GLOBALS ******************************************************************/
39
40 static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
41
42 /* FUNCTIONS ****************************************************************/
43
44 /**
45 * @brief
46 * Converts an absolute security descriptor to a self-relative
47 * format.
48 *
49 * @param[in] AbsoluteSd
50 * A pointer to an absolute security descriptor to be
51 * converted.
52 *
53 * @return
54 * Returns a pointer to a converted security descriptor in
55 * self-relative format. If the function fails, NULL is returned
56 * otherwise.
57 *
58 * @remarks
59 * The function allocates the security descriptor buffer in memory
60 * heap, the caller is entirely responsible for freeing such buffer
61 * from when it's no longer needed.
62 */
63 PSECURITY_DESCRIPTOR
ConvertToSelfRelative(_In_ PSECURITY_DESCRIPTOR AbsoluteSd)64 ConvertToSelfRelative(
65 _In_ PSECURITY_DESCRIPTOR AbsoluteSd)
66 {
67 PSECURITY_DESCRIPTOR RelativeSd;
68 DWORD DescriptorLength = 0;
69
70 /* Determine the size for our buffer to allocate */
71 if (!MakeSelfRelativeSD(AbsoluteSd, NULL, &DescriptorLength) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
72 {
73 ERR("ConvertToSelfRelative(): Unexpected error code (error code %lu -- must be ERROR_INSUFFICIENT_BUFFER)\n", GetLastError());
74 return NULL;
75 }
76
77 /* Allocate the buffer now */
78 RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(),
79 HEAP_ZERO_MEMORY,
80 DescriptorLength);
81 if (RelativeSd == NULL)
82 {
83 ERR("ConvertToSelfRelative(): Failed to allocate buffer for relative SD!\n");
84 return NULL;
85 }
86
87 /* Convert the security descriptor now */
88 if (!MakeSelfRelativeSD(AbsoluteSd, RelativeSd, &DescriptorLength))
89 {
90 ERR("ConvertToSelfRelative(): Failed to convert the security descriptor to a self relative format (error code %lu)\n", GetLastError());
91 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
92 return NULL;
93 }
94
95 return RelativeSd;
96 }
97
98 /**
99 * @brief
100 * Creates a security descriptor for the default
101 * window station upon its creation.
102 *
103 * @param[out] WinstaSd
104 * A pointer to a created security descriptor for
105 * the window station.
106 *
107 * @return
108 * Returns TRUE if the function has successfully
109 * created the security descriptor, FALSE otherwise.
110 */
111 BOOL
CreateWinstaSecurity(_Out_ PSECURITY_DESCRIPTOR * WinstaSd)112 CreateWinstaSecurity(
113 _Out_ PSECURITY_DESCRIPTOR *WinstaSd)
114 {
115 BOOL Success = FALSE;
116 SECURITY_DESCRIPTOR AbsoluteSd;
117 PSECURITY_DESCRIPTOR RelativeSd = NULL;
118 PSID WinlogonSid = NULL, AdminsSid = NULL, NetworkServiceSid = NULL; /* NetworkServiceSid is a HACK, see the comment below for information */
119 DWORD DaclSize;
120 PACL Dacl;
121
122 /* Create the Winlogon SID */
123 if (!AllocateAndInitializeSid(&NtAuthority,
124 1,
125 SECURITY_LOCAL_SYSTEM_RID,
126 0, 0, 0, 0, 0, 0, 0,
127 &WinlogonSid))
128 {
129 ERR("CreateWinstaSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
130 return FALSE;
131 }
132
133 /* Create the admins SID */
134 if (!AllocateAndInitializeSid(&NtAuthority,
135 2,
136 SECURITY_BUILTIN_DOMAIN_RID,
137 DOMAIN_ALIAS_RID_ADMINS,
138 0, 0, 0, 0, 0, 0,
139 &AdminsSid))
140 {
141 ERR("CreateWinstaSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError());
142 goto Quit;
143 }
144
145 /* HACK: Create the network service SID */
146 if (!AllocateAndInitializeSid(&NtAuthority,
147 1,
148 SECURITY_NETWORK_SERVICE_RID,
149 0, 0, 0, 0, 0, 0, 0,
150 &NetworkServiceSid))
151 {
152 ERR("CreateWinstaSecurity(): Failed to create the network service SID (error code %lu)\n", GetLastError());
153 goto Quit;
154 }
155
156 /*
157 * Build up the DACL size. This includes a number
158 * of four ACEs of two different SIDs. The first two
159 * ACEs give both window station and generic access
160 * to Winlogon, the last two give limited window station
161 * and desktop access to admins.
162 *
163 * ===================== !!!MUST READ!!! =====================
164 *
165 * HACK -- Include in the DACL two more ACEs for network
166 * service SID. Network services will be granted full
167 * access to the default window station. Whilst technically
168 * services that are either network or local ones are part
169 * and act on behalf of the system, what we are doing here
170 * is a hack because of two reasons:
171 *
172 * 1) Winlogon does not allow default window station (Winsta0)
173 * access to network services on Windows. As a matter of fact,
174 * network services must access their own service window station
175 * (aka Service-0x0-3e4$) which never gets created. Why it never
176 * gets created is explained on the second point.
177 *
178 * 2) Our LSASS terribly lacks in code that handles special logon
179 * service types, NetworkService and LocalService. For this reason
180 * whenever an access token is created for a network service process
181 * for example, its authentication ID (aka LogonId represented as a LUID)
182 * is a uniquely generated ID by LSASS for this process. This is wrong
183 * on so many levels, partly because a network service is not a regular
184 * service and network services have their own special authentication logon
185 * ID (with its respective LUID as {0x3e4, 0x0}). On top of that, a network
186 * service process must have an impersonation token but for whatever reason
187 * we are creating a primary access token instead.
188 *
189 * FOR ANYONE WHO'S INTERESTED ON FIXING THIS, DO NOT FORGET TO REMOVE THIS
190 * HACK!!!
191 *
192 * =========================== !!!END!!! ================================
193 */
194 DaclSize = sizeof(ACL) +
195 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
196 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
197 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
198 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
199 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid) +
200 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid);
201
202 /* Allocate the DACL now */
203 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
204 HEAP_ZERO_MEMORY,
205 DaclSize);
206 if (Dacl == NULL)
207 {
208 ERR("CreateWinstaSecurity(): Failed to allocate memory buffer for DACL!\n");
209 goto Quit;
210 }
211
212 /* Initialize it */
213 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
214 {
215 ERR("CreateWinstaSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError());
216 goto Quit;
217 }
218
219 /* First ACE -- give full winsta access to Winlogon */
220 if (!AddAccessAllowedAceEx(Dacl,
221 ACL_REVISION,
222 NO_PROPAGATE_INHERIT_ACE,
223 WINSTA_ALL,
224 WinlogonSid))
225 {
226 ERR("CreateWinstaSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
227 goto Quit;
228 }
229
230 /* Second ACE -- give full generic access to Winlogon */
231 if (!AddAccessAllowedAceEx(Dacl,
232 ACL_REVISION,
233 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
234 GENERIC_ACCESS,
235 WinlogonSid))
236 {
237 ERR("CreateWinstaSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
238 goto Quit;
239 }
240
241 /* Third ACE -- give limited winsta access to admins */
242 if (!AddAccessAllowedAceEx(Dacl,
243 ACL_REVISION,
244 NO_PROPAGATE_INHERIT_ACE,
245 WINSTA_ADMINS_LIMITED,
246 AdminsSid))
247 {
248 ERR("CreateWinstaSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
249 goto Quit;
250 }
251
252 /* Fourth ACE -- give limited desktop access to admins */
253 if (!AddAccessAllowedAceEx(Dacl,
254 ACL_REVISION,
255 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
256 DESKTOP_ADMINS_LIMITED,
257 AdminsSid))
258 {
259 ERR("CreateWinstaSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
260 goto Quit;
261 }
262
263 /* HACK: Fifth ACE -- give full access to network services */
264 if (!AddAccessAllowedAceEx(Dacl,
265 ACL_REVISION,
266 NO_PROPAGATE_INHERIT_ACE,
267 WINSTA_ALL,
268 NetworkServiceSid))
269 {
270 ERR("CreateWinstaSecurity(): Failed to set ACE for network service (error code %lu)\n", GetLastError());
271 goto Quit;
272 }
273
274 /* HACK: Sixth ACE -- give full generic access to network services */
275 if (!AddAccessAllowedAceEx(Dacl,
276 ACL_REVISION,
277 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
278 GENERIC_ACCESS,
279 NetworkServiceSid))
280 {
281 ERR("CreateWinstaSecurity(): Failed to set ACE for network service (error code %lu)\n", GetLastError());
282 goto Quit;
283 }
284
285 /* Initialize the security descriptor */
286 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
287 {
288 ERR("CreateWinstaSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
289 goto Quit;
290 }
291
292 /* Set the DACL to the descriptor */
293 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
294 {
295 ERR("CreateWinstaSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
296 goto Quit;
297 }
298
299 /* Convert it to self-relative format */
300 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
301 if (RelativeSd == NULL)
302 {
303 ERR("CreateWinstaSecurity(): Failed to convert security descriptor to self relative format!\n");
304 goto Quit;
305 }
306
307 /* Give the descriptor to the caller */
308 *WinstaSd = RelativeSd;
309 Success = TRUE;
310
311 Quit:
312 if (WinlogonSid != NULL)
313 {
314 FreeSid(WinlogonSid);
315 }
316
317 if (AdminsSid != NULL)
318 {
319 FreeSid(AdminsSid);
320 }
321
322 /* HACK */
323 if (NetworkServiceSid != NULL)
324 {
325 FreeSid(NetworkServiceSid);
326 }
327 /* END HACK */
328
329 if (Dacl != NULL)
330 {
331 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
332 }
333
334 if (Success == FALSE)
335 {
336 if (RelativeSd != NULL)
337 {
338 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
339 }
340 }
341
342 return Success;
343 }
344
345 /**
346 * @brief
347 * Creates a security descriptor for the default
348 * application desktop upon its creation.
349 *
350 * @param[out] ApplicationDesktopSd
351 * A pointer to a created security descriptor for
352 * the application desktop.
353 *
354 * @return
355 * Returns TRUE if the function has successfully
356 * created the security descriptor, FALSE otherwise.
357 */
358 BOOL
CreateApplicationDesktopSecurity(_Out_ PSECURITY_DESCRIPTOR * ApplicationDesktopSd)359 CreateApplicationDesktopSecurity(
360 _Out_ PSECURITY_DESCRIPTOR *ApplicationDesktopSd)
361 {
362 BOOL Success = FALSE;
363 SECURITY_DESCRIPTOR AbsoluteSd;
364 PSECURITY_DESCRIPTOR RelativeSd = NULL;
365 PSID WinlogonSid = NULL, AdminsSid = NULL, NetworkServiceSid = NULL; /* NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for information */
366 DWORD DaclSize;
367 PACL Dacl;
368
369 /* Create the Winlogon SID */
370 if (!AllocateAndInitializeSid(&NtAuthority,
371 1,
372 SECURITY_LOCAL_SYSTEM_RID,
373 0, 0, 0, 0, 0, 0, 0,
374 &WinlogonSid))
375 {
376 ERR("CreateApplicationDesktopSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
377 return FALSE;
378 }
379
380 /* Create the admins SID */
381 if (!AllocateAndInitializeSid(&NtAuthority,
382 2,
383 SECURITY_BUILTIN_DOMAIN_RID,
384 DOMAIN_ALIAS_RID_ADMINS,
385 0, 0, 0, 0, 0, 0,
386 &AdminsSid))
387 {
388 ERR("CreateApplicationDesktopSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError());
389 goto Quit;
390 }
391
392 /* HACK: Create the network service SID */
393 if (!AllocateAndInitializeSid(&NtAuthority,
394 1,
395 SECURITY_NETWORK_SERVICE_RID,
396 0, 0, 0, 0, 0, 0, 0,
397 &NetworkServiceSid))
398 {
399 ERR("CreateApplicationDesktopSecurity(): Failed to create the network service SID (error code %lu)\n", GetLastError());
400 goto Quit;
401 }
402
403 /*
404 * Build up the DACL size. This includes a number
405 * of two ACEs of two different SIDs. The first ACE
406 * gives full access to Winlogon, the last one gives
407 * limited desktop access to admins.
408 */
409 DaclSize = sizeof(ACL) +
410 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
411 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
412 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid); /* HACK */
413
414 /* Allocate the DACL now */
415 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
416 HEAP_ZERO_MEMORY,
417 DaclSize);
418 if (Dacl == NULL)
419 {
420 ERR("CreateApplicationDesktopSecurity(): Failed to allocate memory buffer for DACL!\n");
421 goto Quit;
422 }
423
424 /* Initialize it */
425 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
426 {
427 ERR("CreateApplicationDesktopSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError());
428 goto Quit;
429 }
430
431 /* First ACE -- Give full desktop power to Winlogon */
432 if (!AddAccessAllowedAceEx(Dacl,
433 ACL_REVISION,
434 0,
435 DESKTOP_ALL,
436 WinlogonSid))
437 {
438 ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
439 goto Quit;
440 }
441
442 /* Second ACE -- Give limited desktop power to admins */
443 if (!AddAccessAllowedAceEx(Dacl,
444 ACL_REVISION,
445 0,
446 DESKTOP_ADMINS_LIMITED,
447 AdminsSid))
448 {
449 ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
450 goto Quit;
451 }
452
453 /* HACK: Third ACE -- Give full desktop power to network services */
454 if (!AddAccessAllowedAceEx(Dacl,
455 ACL_REVISION,
456 0,
457 DESKTOP_ALL,
458 NetworkServiceSid))
459 {
460 ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for network services (error code %lu)\n", GetLastError());
461 goto Quit;
462 }
463
464 /* Initialize the security descriptor */
465 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
466 {
467 ERR("CreateApplicationDesktopSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
468 goto Quit;
469 }
470
471 /* Set the DACL to the descriptor */
472 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
473 {
474 ERR("CreateApplicationDesktopSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
475 goto Quit;
476 }
477
478 /* Conver it to self-relative format */
479 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
480 if (RelativeSd == NULL)
481 {
482 ERR("CreateApplicationDesktopSecurity(): Failed to convert security descriptor to self relative format!\n");
483 goto Quit;
484 }
485
486 /* Give the descriptor to the caller */
487 *ApplicationDesktopSd = RelativeSd;
488 Success = TRUE;
489
490 Quit:
491 if (WinlogonSid != NULL)
492 {
493 FreeSid(WinlogonSid);
494 }
495
496 if (AdminsSid != NULL)
497 {
498 FreeSid(AdminsSid);
499 }
500
501 /* HACK */
502 if (NetworkServiceSid != NULL)
503 {
504 FreeSid(NetworkServiceSid);
505 }
506 /* END HACK */
507
508 if (Dacl != NULL)
509 {
510 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
511 }
512
513 if (Success == FALSE)
514 {
515 if (RelativeSd != NULL)
516 {
517 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
518 }
519 }
520
521 return Success;
522 }
523
524 /**
525 * @brief
526 * Creates a security descriptor for the default
527 * Winlogon desktop. This descriptor serves as a
528 * security measure for the winlogon desktop so
529 * that only Winlogon itself (and admins) can
530 * interact with it.
531 *
532 * @param[out] WinlogonDesktopSd
533 * A pointer to a created security descriptor for
534 * the Winlogon desktop.
535 *
536 * @return
537 * Returns TRUE if the function has successfully
538 * created the security descriptor, FALSE otherwise.
539 */
540 BOOL
CreateWinlogonDesktopSecurity(_Out_ PSECURITY_DESCRIPTOR * WinlogonDesktopSd)541 CreateWinlogonDesktopSecurity(
542 _Out_ PSECURITY_DESCRIPTOR *WinlogonDesktopSd)
543 {
544 BOOL Success = FALSE;
545 SECURITY_DESCRIPTOR AbsoluteSd;
546 PSECURITY_DESCRIPTOR RelativeSd = NULL;
547 PSID WinlogonSid = NULL, AdminsSid = NULL;
548 DWORD DaclSize;
549 PACL Dacl;
550
551 /* Create the Winlogon SID */
552 if (!AllocateAndInitializeSid(&NtAuthority,
553 1,
554 SECURITY_LOCAL_SYSTEM_RID,
555 0, 0, 0, 0, 0, 0, 0,
556 &WinlogonSid))
557 {
558 ERR("CreateWinlogonDesktopSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
559 return FALSE;
560 }
561
562 /* Create the admins SID */
563 if (!AllocateAndInitializeSid(&NtAuthority,
564 2,
565 SECURITY_BUILTIN_DOMAIN_RID,
566 DOMAIN_ALIAS_RID_ADMINS,
567 0, 0, 0, 0, 0, 0,
568 &AdminsSid))
569 {
570 ERR("CreateWinlogonDesktopSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError());
571 goto Quit;
572 }
573
574 /*
575 * Build up the DACL size. This includes a number
576 * of two ACEs of two different SIDs. The first ACE
577 * gives full access to Winlogon, the last one gives
578 * limited desktop access to admins.
579 */
580 DaclSize = sizeof(ACL) +
581 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
582 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid);
583
584 /* Allocate the DACL now */
585 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
586 HEAP_ZERO_MEMORY,
587 DaclSize);
588 if (Dacl == NULL)
589 {
590 ERR("CreateWinlogonDesktopSecurity(): Failed to allocate memory buffer for DACL!\n");
591 goto Quit;
592 }
593
594 /* Initialize it */
595 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
596 {
597 ERR("CreateWinlogonDesktopSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError());
598 goto Quit;
599 }
600
601 /* First ACE -- Give full desktop access to Winlogon */
602 if (!AddAccessAllowedAceEx(Dacl,
603 ACL_REVISION,
604 0,
605 DESKTOP_ALL,
606 WinlogonSid))
607 {
608 ERR("CreateWinlogonDesktopSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
609 goto Quit;
610 }
611
612 /* Second ACE -- Give limited desktop access to admins */
613 if (!AddAccessAllowedAceEx(Dacl,
614 ACL_REVISION,
615 0,
616 DESKTOP_WINLOGON_ADMINS_LIMITED,
617 AdminsSid))
618 {
619 ERR("CreateWinlogonDesktopSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
620 goto Quit;
621 }
622
623 /* Initialize the security descriptor */
624 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
625 {
626 ERR("CreateWinlogonDesktopSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
627 goto Quit;
628 }
629
630 /* Set the DACL to the descriptor */
631 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
632 {
633 ERR("CreateWinlogonDesktopSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
634 goto Quit;
635 }
636
637 /* Conver it to self-relative format */
638 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
639 if (RelativeSd == NULL)
640 {
641 ERR("CreateWinlogonDesktopSecurity(): Failed to convert security descriptor to self relative format!\n");
642 goto Quit;
643 }
644
645 /* Give the descriptor to the caller */
646 *WinlogonDesktopSd = RelativeSd;
647 Success = TRUE;
648
649 Quit:
650 if (WinlogonSid != NULL)
651 {
652 FreeSid(WinlogonSid);
653 }
654
655 if (AdminsSid != NULL)
656 {
657 FreeSid(AdminsSid);
658 }
659
660 if (Dacl != NULL)
661 {
662 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
663 }
664
665 if (Success == FALSE)
666 {
667 if (RelativeSd != NULL)
668 {
669 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
670 }
671 }
672
673 return Success;
674 }
675
676 /**
677 * @brief
678 * Creates a security descriptor for the screen
679 * saver desktop.
680 *
681 * @param[out] ScreenSaverDesktopSd
682 * A pointer to a created security descriptor for
683 * the screen-saver desktop.
684 *
685 * @return
686 * Returns TRUE if the function has successfully
687 * created the security descriptor, FALSE otherwise.
688 */
689 BOOL
CreateScreenSaverSecurity(_Out_ PSECURITY_DESCRIPTOR * ScreenSaverDesktopSd)690 CreateScreenSaverSecurity(
691 _Out_ PSECURITY_DESCRIPTOR *ScreenSaverDesktopSd)
692 {
693 BOOL Success = FALSE;
694 SECURITY_DESCRIPTOR AbsoluteSd;
695 PSECURITY_DESCRIPTOR RelativeSd = NULL;
696 PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL;
697 DWORD DaclSize;
698 PACL Dacl;
699
700 /* Create the Winlogon SID */
701 if (!AllocateAndInitializeSid(&NtAuthority,
702 1,
703 SECURITY_LOCAL_SYSTEM_RID,
704 0, 0, 0, 0, 0, 0, 0,
705 &WinlogonSid))
706 {
707 ERR("CreateScreenSaverSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
708 return FALSE;
709 }
710
711 /* Create the admins SID */
712 if (!AllocateAndInitializeSid(&NtAuthority,
713 2,
714 SECURITY_BUILTIN_DOMAIN_RID,
715 DOMAIN_ALIAS_RID_ADMINS,
716 0, 0, 0, 0, 0, 0,
717 &AdminsSid))
718 {
719 ERR("CreateScreenSaverSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError());
720 goto Quit;
721 }
722
723 /* Create the interactive logon SID */
724 if (!AllocateAndInitializeSid(&NtAuthority,
725 1,
726 SECURITY_INTERACTIVE_RID,
727 0, 0, 0, 0, 0, 0, 0,
728 &InteractiveSid))
729 {
730 ERR("CreateScreenSaverSecurity(): Failed to create the interactive SID (error code %lu)\n", GetLastError());
731 goto Quit;
732 }
733
734 /*
735 * Build up the DACL size. This includes a number
736 * of three ACEs of three different SIDs. The first ACE
737 * gives full access to Winlogon, the second one gives
738 * limited desktop access to admins and the last one
739 * gives full desktop access to users who have logged in
740 * interactively.
741 */
742 DaclSize = sizeof(ACL) +
743 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
744 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
745 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid);
746
747 /* Allocate the DACL now */
748 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
749 HEAP_ZERO_MEMORY,
750 DaclSize);
751 if (Dacl == NULL)
752 {
753 ERR("CreateScreenSaverSecurity(): Failed to allocate memory buffer for DACL!\n");
754 goto Quit;
755 }
756
757 /* Initialize it */
758 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
759 {
760 ERR("CreateScreenSaverSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError());
761 goto Quit;
762 }
763
764 /* First ACE -- Give full desktop access to Winlogon */
765 if (!AddAccessAllowedAceEx(Dacl,
766 ACL_REVISION,
767 0,
768 DESKTOP_ALL,
769 WinlogonSid))
770 {
771 ERR("CreateScreenSaverSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
772 goto Quit;
773 }
774
775 /* Second ACE -- Give limited desktop access to admins */
776 if (!AddAccessAllowedAceEx(Dacl,
777 ACL_REVISION,
778 NO_PROPAGATE_INHERIT_ACE,
779 DESKTOP_ADMINS_LIMITED,
780 AdminsSid))
781 {
782 ERR("CreateScreenSaverSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
783 goto Quit;
784 }
785
786 /* Third ACE -- Give full desktop access to interactive logon users */
787 if (!AddAccessAllowedAceEx(Dacl,
788 ACL_REVISION,
789 NO_PROPAGATE_INHERIT_ACE,
790 DESKTOP_INTERACTIVE_LIMITED,
791 InteractiveSid))
792 {
793 ERR("CreateScreenSaverSecurity(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError());
794 goto Quit;
795 }
796
797 /* Initialize the security descriptor */
798 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
799 {
800 ERR("CreateScreenSaverSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
801 goto Quit;
802 }
803
804 /* Set the DACL to the descriptor */
805 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
806 {
807 ERR("CreateScreenSaverSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
808 goto Quit;
809 }
810
811 /* Conver it to self-relative format */
812 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
813 if (RelativeSd == NULL)
814 {
815 ERR("CreateScreenSaverSecurity(): Failed to convert security descriptor to self relative format!\n");
816 goto Quit;
817 }
818
819 /* Give the descriptor to the caller */
820 *ScreenSaverDesktopSd = RelativeSd;
821 Success = TRUE;
822
823 Quit:
824 if (WinlogonSid != NULL)
825 {
826 FreeSid(WinlogonSid);
827 }
828
829 if (AdminsSid != NULL)
830 {
831 FreeSid(AdminsSid);
832 }
833
834 if (InteractiveSid != NULL)
835 {
836 FreeSid(InteractiveSid);
837 }
838
839 if (Dacl != NULL)
840 {
841 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
842 }
843
844 if (Success == FALSE)
845 {
846 if (RelativeSd != NULL)
847 {
848 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
849 }
850 }
851
852 return Success;
853 }
854
855 /**
856 * @brief
857 * Assigns access to the specific logon user to
858 * the default window station. Such access is
859 * given to the user when it has logged in.
860 *
861 * @param[in] WinSta
862 * A handle to a window station where the
863 * user is given access to it.
864 *
865 * @param[in] LogonSid
866 * A pointer to a logon SID that represents
867 * the logged in user in question.
868 *
869 * @return
870 * Returns TRUE if the function has successfully
871 * assigned access to the user, FALSE otherwise.
872 */
873 BOOL
AllowWinstaAccessToUser(_In_ HWINSTA WinSta,_In_ PSID LogonSid)874 AllowWinstaAccessToUser(
875 _In_ HWINSTA WinSta,
876 _In_ PSID LogonSid)
877 {
878 BOOL Success = FALSE;
879 SECURITY_DESCRIPTOR AbsoluteSd;
880 PSECURITY_DESCRIPTOR RelativeSd = NULL;
881 PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL, NetworkServiceSid = NULL; /* NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for information */
882 SECURITY_INFORMATION SecurityInformation;
883 DWORD DaclSize;
884 PACL Dacl;
885
886 /* Create the Winlogon SID */
887 if (!AllocateAndInitializeSid(&NtAuthority,
888 1,
889 SECURITY_LOCAL_SYSTEM_RID,
890 0, 0, 0, 0, 0, 0, 0,
891 &WinlogonSid))
892 {
893 ERR("AllowWinstaAccessToUser(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
894 return FALSE;
895 }
896
897 /* Create the admins SID */
898 if (!AllocateAndInitializeSid(&NtAuthority,
899 2,
900 SECURITY_BUILTIN_DOMAIN_RID,
901 DOMAIN_ALIAS_RID_ADMINS,
902 0, 0, 0, 0, 0, 0,
903 &AdminsSid))
904 {
905 ERR("AllowWinstaAccessToUser(): Failed to create the admins SID (error code %lu)\n", GetLastError());
906 goto Quit;
907 }
908
909 /* Create the interactive logon SID */
910 if (!AllocateAndInitializeSid(&NtAuthority,
911 1,
912 SECURITY_INTERACTIVE_RID,
913 0, 0, 0, 0, 0, 0, 0,
914 &InteractiveSid))
915 {
916 ERR("AllowWinstaAccessToUser(): Failed to create the interactive SID (error code %lu)\n", GetLastError());
917 goto Quit;
918 }
919
920 /* HACK: Create the network service SID */
921 if (!AllocateAndInitializeSid(&NtAuthority,
922 1,
923 SECURITY_NETWORK_SERVICE_RID,
924 0, 0, 0, 0, 0, 0, 0,
925 &NetworkServiceSid))
926 {
927 ERR("AllowWinstaAccessToUser(): Failed to create the network service SID (error code %lu)\n", GetLastError());
928 goto Quit;
929 }
930
931 /*
932 * Build up the DACL size. This includes a number
933 * of eight ACEs of four different SIDs. The first ACE
934 * gives full winsta access to Winlogon, the second one gives
935 * generic access to Winlogon. Such approach is the same
936 * for both interactive logon users and logon user as well.
937 * Only admins are given limited powers.
938 */
939 DaclSize = sizeof(ACL) +
940 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
941 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
942 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
943 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
944 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) +
945 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) +
946 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
947 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
948 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid) + /* HACK */
949 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid);
950
951 /* Allocate the DACL now */
952 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
953 HEAP_ZERO_MEMORY,
954 DaclSize);
955 if (Dacl == NULL)
956 {
957 ERR("AllowWinstaAccessToUser(): Failed to allocate memory buffer for DACL!\n");
958 goto Quit;
959 }
960
961 /* Initialize it */
962 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
963 {
964 ERR("AllowWinstaAccessToUser(): Failed to initialize DACL (error code %lu)\n", GetLastError());
965 goto Quit;
966 }
967
968 /* First ACE -- Give full winsta access to Winlogon */
969 if (!AddAccessAllowedAceEx(Dacl,
970 ACL_REVISION,
971 NO_PROPAGATE_INHERIT_ACE,
972 WINSTA_ALL,
973 WinlogonSid))
974 {
975 ERR("AllowWinstaAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
976 goto Quit;
977 }
978
979 /* Second ACE -- Give generic access to Winlogon */
980 if (!AddAccessAllowedAceEx(Dacl,
981 ACL_REVISION,
982 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
983 GENERIC_ACCESS,
984 WinlogonSid))
985 {
986 ERR("AllowWinstaAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
987 goto Quit;
988 }
989
990 /* Third ACE -- Give limited winsta access to admins */
991 if (!AddAccessAllowedAceEx(Dacl,
992 ACL_REVISION,
993 NO_PROPAGATE_INHERIT_ACE,
994 WINSTA_ADMINS_LIMITED,
995 AdminsSid))
996 {
997 ERR("AllowWinstaAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
998 goto Quit;
999 }
1000
1001 /* Fourth ACE -- Give limited desktop access to admins */
1002 if (!AddAccessAllowedAceEx(Dacl,
1003 ACL_REVISION,
1004 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
1005 DESKTOP_ADMINS_LIMITED,
1006 AdminsSid))
1007 {
1008 ERR("AllowWinstaAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
1009 goto Quit;
1010 }
1011
1012 /* Fifth ACE -- Give full winsta access to interactive logon users */
1013 if (!AddAccessAllowedAceEx(Dacl,
1014 ACL_REVISION,
1015 NO_PROPAGATE_INHERIT_ACE,
1016 WINSTA_ALL,
1017 InteractiveSid))
1018 {
1019 ERR("AllowWinstaAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError());
1020 goto Quit;
1021 }
1022
1023 /* Sixth ACE -- Give generic access to interactive logon users */
1024 if (!AddAccessAllowedAceEx(Dacl,
1025 ACL_REVISION,
1026 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
1027 GENERIC_ACCESS,
1028 InteractiveSid))
1029 {
1030 ERR("AllowWinstaAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError());
1031 goto Quit;
1032 }
1033
1034 /* Seventh ACE -- Give full winsta access to logon user */
1035 if (!AddAccessAllowedAceEx(Dacl,
1036 ACL_REVISION,
1037 NO_PROPAGATE_INHERIT_ACE,
1038 WINSTA_ALL,
1039 LogonSid))
1040 {
1041 ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError());
1042 goto Quit;
1043 }
1044
1045 /* Eighth ACE -- Give generic access to logon user */
1046 if (!AddAccessAllowedAceEx(Dacl,
1047 ACL_REVISION,
1048 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
1049 GENERIC_ACCESS,
1050 LogonSid))
1051 {
1052 ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError());
1053 goto Quit;
1054 }
1055
1056 /* HACK : Ninenth ACE -- Give full winsta access to network services */
1057 if (!AddAccessAllowedAceEx(Dacl,
1058 ACL_REVISION,
1059 NO_PROPAGATE_INHERIT_ACE,
1060 WINSTA_ALL,
1061 NetworkServiceSid))
1062 {
1063 ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon network service SID (error code %lu)\n", GetLastError());
1064 goto Quit;
1065 }
1066
1067 /* HACK: Tenth ACE -- Give generic access to network services */
1068 if (!AddAccessAllowedAceEx(Dacl,
1069 ACL_REVISION,
1070 INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
1071 GENERIC_ACCESS,
1072 NetworkServiceSid))
1073 {
1074 ERR("AllowWinstaAccessToUser(): Failed to set ACE for network service SID (error code %lu)\n", GetLastError());
1075 goto Quit;
1076 }
1077
1078 /* Initialize the security descriptor */
1079 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
1080 {
1081 ERR("AllowWinstaAccessToUser(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
1082 goto Quit;
1083 }
1084
1085 /* Set the DACL to descriptor */
1086 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
1087 {
1088 ERR("AllowWinstaAccessToUser(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
1089 goto Quit;
1090 }
1091
1092 /* Convert it to self-relative format */
1093 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
1094 if (RelativeSd == NULL)
1095 {
1096 ERR("AllowWinstaAccessToUser(): Failed to convert security descriptor to self relative format!\n");
1097 goto Quit;
1098 }
1099
1100 /* Set new winsta security based on this descriptor */
1101 SecurityInformation = DACL_SECURITY_INFORMATION;
1102 if (!SetUserObjectSecurity(WinSta, &SecurityInformation, RelativeSd))
1103 {
1104 ERR("AllowWinstaAccessToUser(): Failed to set window station security descriptor (error code %lu)\n", GetLastError());
1105 goto Quit;
1106 }
1107
1108 Success = TRUE;
1109
1110 Quit:
1111 if (WinlogonSid != NULL)
1112 {
1113 FreeSid(WinlogonSid);
1114 }
1115
1116 if (AdminsSid != NULL)
1117 {
1118 FreeSid(AdminsSid);
1119 }
1120
1121 if (InteractiveSid != NULL)
1122 {
1123 FreeSid(InteractiveSid);
1124 }
1125
1126 /* HACK */
1127 if (NetworkServiceSid != NULL)
1128 {
1129 FreeSid(NetworkServiceSid);
1130 }
1131 /* END HACK */
1132
1133 if (Dacl != NULL)
1134 {
1135 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
1136 }
1137
1138 if (RelativeSd != NULL)
1139 {
1140 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
1141 }
1142
1143 return Success;
1144 }
1145
1146 /**
1147 * @brief
1148 * Assigns access to the specific logon user to
1149 * the default desktop. Such access is given to
1150 * the user when it has logged in.
1151 *
1152 * @param[in] Desktop
1153 * A handle to a desktop where the user
1154 * is given access to it.
1155 *
1156 * @param[in] LogonSid
1157 * A pointer to a logon SID that represents
1158 * the logged in user in question.
1159 *
1160 * @return
1161 * Returns TRUE if the function has successfully
1162 * assigned access to the user, FALSE otherwise.
1163 */
1164 BOOL
AllowDesktopAccessToUser(_In_ HDESK Desktop,_In_ PSID LogonSid)1165 AllowDesktopAccessToUser(
1166 _In_ HDESK Desktop,
1167 _In_ PSID LogonSid)
1168 {
1169 BOOL Success = FALSE;
1170 SECURITY_DESCRIPTOR AbsoluteSd;
1171 PSECURITY_DESCRIPTOR RelativeSd = NULL;
1172 PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL, NetworkServiceSid = NULL; /* NetworkServiceSid is a HACK, see the comment in CreateWinstaSecurity for information */
1173 SECURITY_INFORMATION SecurityInformation;
1174 DWORD DaclSize;
1175 PACL Dacl;
1176
1177 /* Create the Winlogon SID */
1178 if (!AllocateAndInitializeSid(&NtAuthority,
1179 1,
1180 SECURITY_LOCAL_SYSTEM_RID,
1181 0, 0, 0, 0, 0, 0, 0,
1182 &WinlogonSid))
1183 {
1184 ERR("AllowDesktopAccessToUser(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError());
1185 return FALSE;
1186 }
1187
1188 /* Create the admins SID */
1189 if (!AllocateAndInitializeSid(&NtAuthority,
1190 2,
1191 SECURITY_BUILTIN_DOMAIN_RID,
1192 DOMAIN_ALIAS_RID_ADMINS,
1193 0, 0, 0, 0, 0, 0,
1194 &AdminsSid))
1195 {
1196 ERR("AllowDesktopAccessToUser(): Failed to create the admins SID (error code %lu)\n", GetLastError());
1197 goto Quit;
1198 }
1199
1200 /* Create the interactive logon SID */
1201 if (!AllocateAndInitializeSid(&NtAuthority,
1202 1,
1203 SECURITY_INTERACTIVE_RID,
1204 0, 0, 0, 0, 0, 0, 0,
1205 &InteractiveSid))
1206 {
1207 ERR("AllowDesktopAccessToUser(): Failed to create the interactive SID (error code %lu)\n", GetLastError());
1208 goto Quit;
1209 }
1210
1211 /* HACK: Create the network service SID */
1212 if (!AllocateAndInitializeSid(&NtAuthority,
1213 1,
1214 SECURITY_NETWORK_SERVICE_RID,
1215 0, 0, 0, 0, 0, 0, 0,
1216 &NetworkServiceSid))
1217 {
1218 ERR("AllowDesktopAccessToUser(): Failed to create the network service SID (error code %lu)\n", GetLastError());
1219 goto Quit;
1220 }
1221
1222 /*
1223 * Build up the DACL size. This includes a number
1224 * of four ACEs of four different SIDs. The first ACE
1225 * gives full desktop access to Winlogon, the second one gives
1226 * generic limited desktop access to admins. The last two give
1227 * full power to both interactive logon users and logon user as
1228 * well.
1229 */
1230 DaclSize = sizeof(ACL) +
1231 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) +
1232 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) +
1233 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) +
1234 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) +
1235 sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(NetworkServiceSid); /* HACK */
1236
1237 /* Allocate the DACL now */
1238 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
1239 HEAP_ZERO_MEMORY,
1240 DaclSize);
1241 if (Dacl == NULL)
1242 {
1243 ERR("AllowDesktopAccessToUser(): Failed to allocate memory buffer for DACL!\n");
1244 goto Quit;
1245 }
1246
1247 /* Initialize it */
1248 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION))
1249 {
1250 ERR("AllowDesktopAccessToUser(): Failed to initialize DACL (error code %lu)\n", GetLastError());
1251 goto Quit;
1252 }
1253
1254 /* First ACE -- Give full desktop access to Winlogon */
1255 if (!AddAccessAllowedAceEx(Dacl,
1256 ACL_REVISION,
1257 0,
1258 DESKTOP_ALL,
1259 WinlogonSid))
1260 {
1261 ERR("AllowDesktopAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError());
1262 goto Quit;
1263 }
1264
1265 /* Second ACE -- Give limited desktop access to admins */
1266 if (!AddAccessAllowedAceEx(Dacl,
1267 ACL_REVISION,
1268 0,
1269 DESKTOP_ADMINS_LIMITED,
1270 AdminsSid))
1271 {
1272 ERR("AllowDesktopAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError());
1273 goto Quit;
1274 }
1275
1276 /* Third ACE -- Give full desktop access to interactive logon users */
1277 if (!AddAccessAllowedAceEx(Dacl,
1278 ACL_REVISION,
1279 0,
1280 DESKTOP_ALL,
1281 InteractiveSid))
1282 {
1283 ERR("AllowDesktopAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError());
1284 goto Quit;
1285 }
1286
1287 /* Fourth ACE -- Give full desktop access to logon user */
1288 if (!AddAccessAllowedAceEx(Dacl,
1289 ACL_REVISION,
1290 0,
1291 DESKTOP_ALL,
1292 LogonSid))
1293 {
1294 ERR("AllowDesktopAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError());
1295 goto Quit;
1296 }
1297
1298 /* HACK: Fifth ACE -- Give full desktop to network services */
1299 if (!AddAccessAllowedAceEx(Dacl,
1300 ACL_REVISION,
1301 0,
1302 DESKTOP_ALL,
1303 NetworkServiceSid))
1304 {
1305 ERR("AllowDesktopAccessToUser(): Failed to set ACE for network service SID (error code %lu)\n", GetLastError());
1306 goto Quit;
1307 }
1308
1309 /* Initialize the security descriptor */
1310 if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION))
1311 {
1312 ERR("AllowDesktopAccessToUser(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError());
1313 goto Quit;
1314 }
1315
1316 /* Set the DACL to the descriptor */
1317 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
1318 {
1319 ERR("AllowDesktopAccessToUser(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError());
1320 goto Quit;
1321 }
1322
1323 /* Conver it to self-relative format */
1324 RelativeSd = ConvertToSelfRelative(&AbsoluteSd);
1325 if (RelativeSd == NULL)
1326 {
1327 ERR("AllowDesktopAccessToUser(): Failed to convert security descriptor to self relative format!\n");
1328 goto Quit;
1329 }
1330
1331 /* Assign new security to desktop based on this descriptor */
1332 SecurityInformation = DACL_SECURITY_INFORMATION;
1333 if (!SetUserObjectSecurity(Desktop, &SecurityInformation, RelativeSd))
1334 {
1335 ERR("AllowDesktopAccessToUser(): Failed to set desktop security descriptor (error code %lu)\n", GetLastError());
1336 goto Quit;
1337 }
1338
1339 Success = TRUE;
1340
1341 Quit:
1342 if (WinlogonSid != NULL)
1343 {
1344 FreeSid(WinlogonSid);
1345 }
1346
1347 if (AdminsSid != NULL)
1348 {
1349 FreeSid(AdminsSid);
1350 }
1351
1352 if (InteractiveSid != NULL)
1353 {
1354 FreeSid(InteractiveSid);
1355 }
1356
1357 /* HACK */
1358 if (NetworkServiceSid != NULL)
1359 {
1360 FreeSid(NetworkServiceSid);
1361 }
1362 /* END HACK */
1363
1364 if (Dacl != NULL)
1365 {
1366 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
1367 }
1368
1369 if (RelativeSd != NULL)
1370 {
1371 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
1372 }
1373
1374 return Success;
1375 }
1376
1377 /**
1378 * @brief
1379 * Assigns both window station and desktop access
1380 * to the specific session currently active on the
1381 * system.
1382 *
1383 * @param[in] Session
1384 * A pointer to an active session.
1385 *
1386 * @return
1387 * Returns TRUE if the function has successfully
1388 * assigned access to the current session, FALSE otherwise.
1389 */
1390 BOOL
AllowAccessOnSession(_In_ PWLSESSION Session)1391 AllowAccessOnSession(
1392 _In_ PWLSESSION Session)
1393 {
1394 BOOL Success = FALSE;
1395 DWORD Index, SidLength, GroupsLength = 0;
1396 PTOKEN_GROUPS TokenGroup = NULL;
1397 PSID LogonSid;
1398
1399 /* Get required buffer size and allocate the TOKEN_GROUPS buffer */
1400 if (!GetTokenInformation(Session->UserToken,
1401 TokenGroups,
1402 TokenGroup,
1403 0,
1404 &GroupsLength))
1405 {
1406 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1407 {
1408 ERR("AllowAccessOnSession(): Unexpected error code returned, must be ERROR_INSUFFICIENT_BUFFER (error code %lu)\n", GetLastError());
1409 return FALSE;
1410 }
1411
1412 TokenGroup = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, GroupsLength);
1413 if (TokenGroup == NULL)
1414 {
1415 ERR("AllowAccessOnSession(): Failed to allocate memory buffer for token group!\n");
1416 return FALSE;
1417 }
1418 }
1419
1420 /* Get the token group information from the access token */
1421 if (!GetTokenInformation(Session->UserToken,
1422 TokenGroups,
1423 TokenGroup,
1424 GroupsLength,
1425 &GroupsLength))
1426 {
1427 ERR("AllowAccessOnSession(): Failed to retrieve the token group information (error code %lu)\n", GetLastError());
1428 goto Quit;
1429 }
1430
1431 /* Loop through the groups to find the logon SID */
1432 for (Index = 0; Index < TokenGroup->GroupCount; Index++)
1433 {
1434 if ((TokenGroup->Groups[Index].Attributes & SE_GROUP_LOGON_ID)
1435 == SE_GROUP_LOGON_ID)
1436 {
1437 LogonSid = TokenGroup->Groups[Index].Sid;
1438 break;
1439 }
1440 }
1441
1442 /* Allow window station access to this user within this session */
1443 if (!AllowWinstaAccessToUser(Session->InteractiveWindowStation, LogonSid))
1444 {
1445 ERR("AllowAccessOnSession(): Failed to allow winsta access to the logon user!\n");
1446 goto Quit;
1447 }
1448
1449 /* Allow application desktop access to this user within this session */
1450 if (!AllowDesktopAccessToUser(Session->ApplicationDesktop, LogonSid))
1451 {
1452 ERR("AllowAccessOnSession(): Failed to allow application desktop access to the logon user!\n");
1453 goto Quit;
1454 }
1455
1456 /* Get the length of this logon SID */
1457 SidLength = GetLengthSid(LogonSid);
1458
1459 /* Assign the window station to this logged in user */
1460 if (!SetWindowStationUser(Session->InteractiveWindowStation,
1461 &Session->LogonId,
1462 LogonSid,
1463 SidLength))
1464 {
1465 ERR("AllowAccessOnSession(): Failed to assign the window station to the logon user!\n");
1466 goto Quit;
1467 }
1468
1469 Success = TRUE;
1470
1471 Quit:
1472 if (TokenGroup != NULL)
1473 {
1474 RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroup);
1475 }
1476
1477 return Success;
1478 }
1479
1480 /* EOF */
1481