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 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 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 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 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 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 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 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 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 /* 1450 * FIXME: Desktop security management is broken. The application desktop gets created 1451 * with CreateDesktopW() API call with an initial and defined security descriptor for it yet 1452 * when we are giving access to the logged in user, SetUserObjectSecurity() API call fails to set 1453 * new security because the desktop in question has no prior security descriptor (when it's 1454 * been assigned even before!!!). This chunk of code must be enabled when this gets fixed. 1455 */ 1456 #if 0 1457 /* Allow application desktop access to this user within this session */ 1458 if (!AllowDesktopAccessToUser(Session->ApplicationDesktop, LogonSid)) 1459 { 1460 ERR("AllowAccessOnSession(): Failed to allow application desktop access to the logon user!\n"); 1461 goto Quit; 1462 } 1463 #endif 1464 1465 /* Get the length of this logon SID */ 1466 SidLength = GetLengthSid(LogonSid); 1467 1468 /* Assign the window station to this logged in user */ 1469 if (!SetWindowStationUser(Session->InteractiveWindowStation, 1470 &Session->LogonId, 1471 LogonSid, 1472 SidLength)) 1473 { 1474 ERR("AllowAccessOnSession(): Failed to assign the window station to the logon user!\n"); 1475 goto Quit; 1476 } 1477 1478 Success = TRUE; 1479 1480 Quit: 1481 if (TokenGroup != NULL) 1482 { 1483 RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroup); 1484 } 1485 1486 return Success; 1487 } 1488 1489 /* EOF */ 1490