test: security.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# security.c

Go to the documentation of this file.

    00001 /**************************** Module Header ********************************\
    00002 * Module Name: security.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * Securable Object Routines
    00007 *
    00008 * History:
    00009 * 12-31-90 JimA       Created.
    00010 * 04-14-92 RichardW   Changed ACE_HEADER
    00011 \***************************************************************************/
    00012
    00013 #define _SECURITY 1
    00014 #include "precomp.h"
    00015 #pragma hdrstop
    00016
    00017 #pragma alloc_text(INIT, InitSecurity)
    00018
    00019 /*
    00020  * General security stuff
    00021  */
    00022 PSECURITY_DESCRIPTOR gpsdInitWinSta;
    00023
    00024 PRIVILEGE_SET psTcb = { 1, PRIVILEGE_SET_ALL_NECESSARY,
    00025     { SE_TCB_PRIVILEGE, 0 }
    00026 };
    00027
    00028 /***************************************************************************\
    00029 * AllocAce
    00030 *
    00031 * Allocates and initializes an ACE list.
    00032 *
    00033 * History:
    00034 * 04-25-91 JimA         Created.
    00035 \***************************************************************************/
    00036
    00037 PACCESS_ALLOWED_ACE AllocAce(
    00038     PACCESS_ALLOWED_ACE pace,
    00039     BYTE bType,
    00040     BYTE bFlags,
    00041     ACCESS_MASK am,
    00042     PSID psid,
    00043     LPDWORD lpdwLength)
    00044 {
    00045     PACCESS_ALLOWED_ACE paceNew;
    00046     DWORD iEnd;
    00047     DWORD dwLength, dwLengthSid;
    00048
    00049     /*
    00050      * Allocate space for the ACE.
    00051      */
    00052     dwLengthSid = RtlLengthSid(psid);
    00053     dwLength = dwLengthSid + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
    00054     if (pace == NULL) {
    00055         iEnd = 0;
    00056         pace = UserAllocPoolWithQuota(dwLength, TAG_SECURITY);
    00057         if (pace == NULL)
    00058             return NULL;
    00059     } else {
    00060         iEnd = *lpdwLength;
    00061         paceNew = UserAllocPoolWithQuota(iEnd + dwLength, TAG_SECURITY);
    00062         if (paceNew == NULL)
    00063             return NULL;
    00064         RtlCopyMemory(paceNew, pace, iEnd);
    00065         UserFreePool(pace);
    00066         pace = paceNew;
    00067     }
    00068     *lpdwLength = dwLength + iEnd;
    00069
    00070     /*
    00071      * Insert the new ACE.
    00072      */
    00073     paceNew = (PACCESS_ALLOWED_ACE)((PBYTE)pace + iEnd);
    00074     paceNew->Header.AceType = bType;
    00075     paceNew->Header.AceSize = (USHORT)dwLength;
    00076     paceNew->Header.AceFlags = bFlags;
    00077     paceNew->Mask = am;
    00078     RtlCopySid(dwLengthSid, &paceNew->SidStart, psid);
    00079     return pace;
    00080 }
    00081
    00082 /***************************************************************************\
    00083 * CreateSecurityDescriptor
    00084 *
    00085 * Allocates and initializes a security descriptor.
    00086 *
    00087 * History:
    00088 * 04-25-91 JimA         Created.
    00089 \***************************************************************************/
    00090
    00091 PSECURITY_DESCRIPTOR CreateSecurityDescriptor(
    00092     PACCESS_ALLOWED_ACE paceList,
    00093     DWORD cbAce,
    00094     BOOLEAN fDaclDefaulted)
    00095 {
    00096     PSECURITY_DESCRIPTOR psd;
    00097     PACL pacl;
    00098     NTSTATUS Status;
    00099
    00100     /*
    00101      * Allocate the security descriptor
    00102      */
    00103     psd = (PSECURITY_DESCRIPTOR)UserAllocPoolWithQuota(
    00104             cbAce + sizeof(ACL) + SECURITY_DESCRIPTOR_MIN_LENGTH,
    00105             TAG_SECURITY);
    00106     if (psd == NULL)
    00107         return NULL;
    00108     RtlCreateSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
    00109
    00110     /*
    00111      * Initialize the ACL
    00112      */
    00113     pacl = (PACL)((PBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
    00114     Status = RtlCreateAcl(pacl, sizeof(ACL) + cbAce, ACL_REVISION);
    00115     if (NT_SUCCESS(Status)) {
    00116
    00117         /*
    00118          * Add the ACEs to the ACL.
    00119          */
    00120         Status = RtlAddAce(pacl, ACL_REVISION, MAXULONG, paceList, cbAce);
    00121         if (NT_SUCCESS(Status)) {
    00122
    00123             /*
    00124              * Initialize the SD
    00125              */
    00126             Status = RtlSetDaclSecurityDescriptor(psd, (BOOLEAN)TRUE,
    00127                     pacl, fDaclDefaulted);
    00128             RtlSetSaclSecurityDescriptor(psd, (BOOLEAN)FALSE, NULL,
    00129                     (BOOLEAN)FALSE);
    00130             RtlSetOwnerSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
    00131             RtlSetGroupSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
    00132         }
    00133     }
    00134
    00135     if (!NT_SUCCESS(Status)) {
    00136         UserFreePool(psd);
    00137         return NULL;
    00138     }
    00139
    00140     return psd;
    00141 }
    00142
    00143 /***************************************************************************\
    00144 * InitSecurity
    00145 *
    00146 * Initialize global security information.
    00147 *
    00148 * History:
    00149 * 01-29-91 JimA         Created.
    00150 \***************************************************************************/
    00151
    00152 BOOL InitSecurity(
    00153     VOID)
    00154 {
    00155     PACCESS_ALLOWED_ACE paceList = NULL, pace;
    00156     DWORD dwLength;
    00157
    00158     /*
    00159      * Get access to exported constants
    00160      */
    00161     SeEnableAccessToExports();
    00162
    00163     /*
    00164      * Create ACE list.
    00165      */
    00166     paceList = AllocAce(NULL,
    00167             ACCESS_ALLOWED_ACE_TYPE,
    00168             CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE,
    00169             WinStaMapping.GenericAll,
    00170             SeExports->SeWorldSid,
    00171             &dwLength);
    00172     if (paceList == NULL)
    00173         return FALSE;
    00174
    00175     pace = AllocAce(paceList,
    00176             ACCESS_ALLOWED_ACE_TYPE,
    00177             CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE,
    00178             WinStaMapping.GenericAll,
    00179             SeExports->SeRestrictedSid,
    00180             &dwLength);
    00181     if (pace == NULL) {
    00182         UserFreePool(paceList);
    00183         return FALSE;
    00184     }
    00185     paceList = pace;
    00186
    00187     pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
    00188             OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
    00189             GENERIC_ALL, SeExports->SeWorldSid, &dwLength);
    00190     if (pace == NULL) {
    00191         UserFreePool(paceList);
    00192         return FALSE;
    00193     }
    00194     paceList = pace;
    00195
    00196     pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
    00197             OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
    00198             GENERIC_ALL, SeExports->SeRestrictedSid, &dwLength);
    00199     if (pace == NULL) {
    00200         UserFreePool(paceList);
    00201         return FALSE;
    00202     }
    00203     paceList = pace;
    00204
    00205     pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
    00206             0, DIRECTORY_QUERY | DIRECTORY_CREATE_OBJECT,
    00207             SeExports->SeAliasAdminsSid, &dwLength);
    00208     if (pace == NULL) {
    00209         UserFreePool(paceList);
    00210         return FALSE;
    00211     }
    00212     paceList = pace;
    00213
    00214     pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
    00215             0, DIRECTORY_TRAVERSE, SeExports->SeWorldSid, &dwLength);
    00216     if (pace == NULL) {
    00217         UserFreePool(paceList);
    00218         return FALSE;
    00219     }
    00220     paceList = pace;
    00221
    00222     pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
    00223             0, DIRECTORY_TRAVERSE, SeExports->SeRestrictedSid, &dwLength);
    00224     if (pace == NULL) {
    00225         UserFreePool(paceList);
    00226         return FALSE;
    00227     }
    00228     paceList = pace;
    00229
    00230     /*
    00231      * Create the SD
    00232      */
    00233     gpsdInitWinSta = CreateSecurityDescriptor(paceList, dwLength, FALSE);
    00234     UserFreePool(paceList);
    00235
    00236     if (gpsdInitWinSta == NULL) {
    00237         RIPMSG0(RIP_WARNING, "Initial windowstation security was not created!");
    00238     }
    00239
    00240     return (BOOL)(gpsdInitWinSta != NULL);
    00241 }
    00242
    00243
    00244 /***************************************************************************\
    00245 * TestForInteractiveUser
    00246 *
    00247 * Returns STATUS_SUCCESS if the LUID passed represents an
    00248 * interactiveUser user logged on by winlogon, otherwise FALSE
    00249 *
    00250 * History:
    00251 * 03-08-95 JimA         Created.
    00252 \***************************************************************************/
    00253
    00254 NTSTATUS
    00255 TestForInteractiveUser(
    00256     PLUID pluidCaller
    00257     )
    00258 {
    00259     PWINDOWSTATION pwinsta;
    00260
    00261     UserAssert(grpWinStaList != NULL);
    00262
    00263     /*
    00264      * !!!
    00265      *
    00266      * This relies on the fact that there is only ONE interactive
    00267      * windowstation and that it is the first one in the list.
    00268      * If multiple windowstations are ever supported
    00269      * a lookup will have to be done here.
    00270      */
    00271     pwinsta = grpWinStaList;
    00272
    00273     /*
    00274      * Compare it with the id of the logged on user.
    00275      */
    00276     if (RtlEqualLuid(pluidCaller, &pwinsta->luidUser))
    00277         return STATUS_SUCCESS;
    00278     else
    00279         return STATUS_ACCESS_DENIED;
    00280 }
    00281
    00282
    00283
    00284 /***************************************************************************\
    00285 * _UserTestForWinStaAccess
    00286 *
    00287 * Returns STATUS_SUCCESS if the current user has GENERIC_EXECUTE access on
    00288 *  WindowStation pstrWinSta
    00289 *
    00290 *
    00291 * History:
    00292 * 06-05-96  Created     SalimC
    00293 \***************************************************************************/
    00294 NTSTATUS
    00295 _UserTestForWinStaAccess(
    00296     PUNICODE_STRING pstrWinSta,
    00297     BOOL fInherit
    00298     )
    00299 {
    00300     PTOKEN_STATISTICS   pStats;
    00301     ULONG               BytesRequired;
    00302     PWINDOWSTATION      pwinsta;
    00303     HWINSTA             hwsta = NULL;
    00304     OBJECT_ATTRIBUTES   ObjAttr;
    00305     POBJECT_ATTRIBUTES  pObjAttr = NULL;
    00306     PUNICODE_STRING     pstrStatic;
    00307     NTSTATUS            Status =  STATUS_SUCCESS;
    00308     SIZE_T              cbObjA;
    00309     UNICODE_STRING      strDefWinSta;
    00310     HANDLE              htoken;
    00311
    00312     CheckCritIn();
    00313
    00314     UserAssert(NtCurrentTeb());
    00315     UserAssert(pstrWinSta->Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
    00316
    00317     /*
    00318      * If we are testing against Default WindowStation (WinSta0) retreive
    00319      * pwinsta from the top of the grpwinstaList instead of doing an
    00320      * OpenWindowStation()
    00321      *
    00322      * !!!
    00323      *
    00324      * This relies on the fact that there is only ONE interactive
    00325      * windowstation and that it is the first one in the list.
    00326      * If multiple windowstations are ever supported
    00327      * a lookup will have to be done instead.
    00328      */
    00329     RtlInitUnicodeString(&strDefWinSta, DEFAULT_WINSTA);
    00330     if (RtlEqualUnicodeString(pstrWinSta, &strDefWinSta, TRUE)) {
    00331
    00332
    00333         if (!NT_SUCCESS(Status = OpenEffectiveToken(&htoken))) {
    00334             return Status;
    00335         }
    00336
    00337         Status = ZwQueryInformationToken(
    00338                      htoken,                 // Handle
    00339                      TokenStatistics,           // TokenInformationClass
    00340                      NULL,                      // TokenInformation
    00341                      0,                         // TokenInformationLength
    00342                      &BytesRequired             // ReturnLength
    00343                      );
    00344
    00345         if (Status != STATUS_BUFFER_TOO_SMALL) {
    00346             ZwClose(htoken);
    00347             return Status;
    00348         }
    00349
    00350         //
    00351         // Allocate space for the user info
    00352         //
    00353
    00354         pStats = (PTOKEN_STATISTICS)UserAllocPoolWithQuota(BytesRequired, TAG_SECURITY);
    00355         if (pStats == NULL) {
    00356             Status = STATUS_NO_MEMORY;
    00357             ZwClose(htoken);
    00358             return Status;
    00359         }
    00360
    00361         //
    00362         // Read in the user info
    00363         //
    00364
    00365         if (!NT_SUCCESS(Status = ZwQueryInformationToken(
    00366                      htoken,             // Handle
    00367                      TokenStatistics,       // TokenInformationClass
    00368                      pStats,                // TokenInformation
    00369                      BytesRequired,         // TokenInformationLength
    00370                      &BytesRequired         // ReturnLength
    00371                      ))) {
    00372             ZwClose(htoken);
    00373             UserFreePool(pStats);
    00374             return Status;
    00375         }
    00376
    00377         /*
    00378          * Make sure that current process has access to this window station
    00379          */
    00380         Status = STATUS_ACCESS_DENIED;
    00381
    00382         if (grpWinStaList != NULL) {
    00383
    00384             /*
    00385              * !!!
    00386              *
    00387              * This relies on the fact that there is only ONE interactive
    00388              * windowstation and that it is the first one in the list.
    00389              * If multiple windowstations are ever supported
    00390              * a lookup will have to be done here.
    00391              */
    00392             pwinsta = grpWinStaList;
    00393
    00394             /*
    00395              * For now we will just do the user luid test till we figure out
    00396              * what fInherit means for a Multi-User system
    00397              */
    00398             if (fInherit) {
    00399                 if ( (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) ||
    00400                      (RtlEqualLuid(&pStats->AuthenticationId, &luidSystem)) ||
    00401                      (AccessCheckObject(pwinsta, GENERIC_EXECUTE, (KPROCESSOR_MODE)(gbSecureDesktop ? UserMode : KernelMode), &WinStaMapping)) )  {
    00402                    Status = STATUS_SUCCESS;
    00403                 }
    00404             } else {
    00405                 /* Bug 42905. Service Controller clears the flag
    00406                  * ScStartupInfo.dwFlags &= (~STARTF_DESKTOPINHERIT) to make services
    00407                  * running under the context of system non-interactive. Hence if fInherit
    00408                  * is false don't do the SystemLuid and AccessCheckObject tests.
    00409                  */
    00410
    00411                 if (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) {
    00412                    Status = STATUS_SUCCESS;
    00413                 }
    00414             }
    00415         }
    00416
    00417         ZwClose(htoken);
    00418         UserFreePool(pStats);
    00419         return Status;
    00420     }
    00421
    00422     if (gbSecureDesktop) {
    00423         /*
    00424          * Since we don't have a pointer to the WindowStation Object we will do
    00425          * a OpenWindowStation() to make sure we have the desired access.
    00426          */
    00427         cbObjA = sizeof(*pObjAttr) + sizeof(*pstrStatic);
    00428         Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
    00429                 &pObjAttr, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE);
    00430         pstrStatic = (PUNICODE_STRING)((PBYTE)pObjAttr + sizeof(*pObjAttr));
    00431
    00432         if (NT_SUCCESS(Status)) {
    00433
    00434             /*
    00435              * Note -- the string must be in client-space or the
    00436              * address validation in OpenWindowStation will fail.
    00437              *
    00438              * This code is called from xxxResolveDesktop and the buffer of the passed-in string
    00439              * is in the teb already.
    00440              */
    00441             try {
    00442                 *pstrStatic = *pstrWinSta;
    00443                 InitializeObjectAttributes( pObjAttr,
    00444                                             pstrStatic,
    00445                                             OBJ_CASE_INSENSITIVE,
    00446                                             NULL,
    00447                                             NULL
    00448                                             );
    00449             } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    00450                 Status = GetExceptionCode();
    00451             }
    00452
    00453             if (NT_SUCCESS(Status)) {
    00454                 hwsta = _OpenWindowStation(pObjAttr, GENERIC_EXECUTE, UserMode);
    00455             }
    00456         } else {
    00457             return Status;
    00458         }
    00459
    00460         if (pObjAttr != NULL) {
    00461             ZwFreeVirtualMemory(NtCurrentProcess(), &pObjAttr, &cbObjA,
    00462                             MEM_RELEASE);
    00463         }
    00464     } else {
    00465         InitializeObjectAttributes( &ObjAttr,
    00466                                     pstrWinSta,
    00467                                     OBJ_CASE_INSENSITIVE,
    00468                                     NULL,
    00469                                     NULL
    00470                                     );
    00471         hwsta = _OpenWindowStation(&ObjAttr, GENERIC_EXECUTE, KernelMode);
    00472     }
    00473
    00474     if (!hwsta) {
    00475         return STATUS_ACCESS_DENIED;
    00476     }
    00477
    00478     Status = ZwClose(hwsta);
    00479
    00480     UserAssert(NT_SUCCESS(Status));
    00481     return Status;
    00482 }
    00483 /***************************************************************************\
    00484 * CheckGrantedAccess
    00485 *
    00486 * Confirms all requested accesses are granted and sets error status.
    00487 *
    00488 * History:
    00489 * 06-26-95 JimA       Created.
    00490 \***************************************************************************/
    00491
    00492 BOOL CheckGrantedAccess(
    00493     ACCESS_MASK amGranted,
    00494     ACCESS_MASK amRequest)
    00495 {
    00496
    00497     /*
    00498      * Check the granted access.
    00499      */
    00500     if (!RtlAreAllAccessesGranted(amGranted, amRequest)) {
    00501         RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
    00502         return FALSE;
    00503     }
    00504     return TRUE;
    00505 }
    00506
    00507 /***************************************************************************\
    00508 * CheckWinstaWriteAttributesAccess
    00509 *
    00510 * Checks if the current process has WINSTA_WRITEATTRIBUTES access
    00511 * to its windowstation, and whether that windowstation is an
    00512 * interactive windowstation.
    00513 *
    00514 * History:
    00515 * 06-Jun-1996 adams     Created.
    00516 \***************************************************************************/
    00517
    00518 BOOL CheckWinstaWriteAttributesAccess(void)
    00519 {
    00520     PPROCESSINFO ppiCurrent = PpiCurrent();
    00521
    00522     /*
    00523      * winlogon has rights to all windowstations.
    00524      */
    00525     if (PsGetCurrentProcess()->UniqueProcessId == gpidLogon)
    00526         return TRUE;
    00527
    00528     if (!(ppiCurrent->W32PF_Flags & W32PF_IOWINSTA)) {
    00529         RIPERR0(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION,
    00530                 RIP_WARNING,
    00531                 "Operation invalid on a non-interactive WindowStation.");
    00532
    00533         return FALSE;
    00534     }
    00535
    00536     if (!RtlAreAllAccessesGranted(ppiCurrent->amwinsta, WINSTA_WRITEATTRIBUTES)) {
    00537         RIPERR0(ERROR_ACCESS_DENIED,
    00538                 RIP_WARNING,
    00539                 "WINSTA_WRITEATTRIBUTES access to WindowStation denied.");
    00540
    00541         return FALSE;
    00542     }
    00543     return TRUE;
    00544 }
    00545
    00546 /***************************************************************************\
    00547 * AccessCheckObject
    00548 *
    00549 * Performs an access check on an object
    00550 *
    00551 * History:
    00552 * 12-31-90 JimA       Created.
    00553 \***************************************************************************/
    00554
    00555 BOOL AccessCheckObject(
    00556     PVOID pobj,
    00557     ACCESS_MASK amRequest,
    00558     KPROCESSOR_MODE AccessMode,
    00559     CONST GENERIC_MAPPING *pGenericMapping)
    00560 {
    00561     NTSTATUS Status;
    00562     ACCESS_STATE AccessState;
    00563     BOOLEAN fAccessGranted;
    00564     AUX_ACCESS_DATA AuxData;
    00565     BOOLEAN bMutexLocked = (pGenericMapping == (&KeyMapping));
    00566     /*
    00567      * Due to a resource problem in the object manager, we must pass in a TRUE
    00568      * when checking access for registry keys, even if we do not explicitly have
    00569      * the object type mutex.  If we do not, we can get into a deadlock situation with this mutex
    00570      * and the CmpRegistry lock.
    00571      */
    00572
    00573     SeCreateAccessState(&AccessState, &AuxData, amRequest, (PGENERIC_MAPPING)pGenericMapping);
    00574     fAccessGranted = ObCheckObjectAccess(
    00575             pobj,
    00576             &AccessState,
    00577             bMutexLocked,
    00578             AccessMode,
    00579             &Status);
    00580     SeDeleteAccessState(&AccessState);
    00581     return (BOOL)(fAccessGranted == TRUE);
    00582 }
    00583
    00584 /***************************************************************************\
    00585 * IsPrivileged
    00586 *
    00587 * Check to see if the client has the specified privileges
    00588 *
    00589 * History:
    00590 * 01-02-91 JimA       Created.
    00591 \***************************************************************************/
    00592
    00593 BOOL IsPrivileged(
    00594     PPRIVILEGE_SET ppSet)
    00595 {
    00596     SECURITY_SUBJECT_CONTEXT Context;
    00597     BOOLEAN bHeld;
    00598
    00599     SeCaptureSubjectContext(&Context);
    00600     SeLockSubjectContext(&Context);
    00601
    00602     bHeld = SePrivilegeCheck(ppSet, &Context, UserMode);
    00603     SePrivilegeObjectAuditAlarm(NULL, &Context, 0, ppSet, bHeld, UserMode);
    00604
    00605     SeUnlockSubjectContext(&Context);
    00606     SeReleaseSubjectContext(&Context);
    00607
    00608     if (!bHeld)
    00609         RIPERR0(ERROR_PRIVILEGE_NOT_HELD, RIP_VERBOSE, "");
    00610
    00611     /*
    00612      * Return result of privilege check
    00613      */
    00614     return (BOOL)bHeld;
    00615 }
    00616
    00617 /***************************************************************************\
    00618 * _GetUserObjectInformation (API)
    00619 *
    00620 * Gets information about a secure USER object
    00621 *
    00622 * History:
    00623 * 04-25-94 JimA       Created.
    00624 \***************************************************************************/
    00625
    00626 BOOL _GetUserObjectInformation(
    00627     HANDLE h,
    00628     int nIndex,
    00629     PVOID ccxpvInfo,
    00630     DWORD nLength,
    00631     LPDWORD lpnLengthNeeded)
    00632 {
    00633     PUSEROBJECTFLAGS puof;
    00634     BOOL fSuccess = TRUE;
    00635     PVOID pObject;
    00636     POBJECT_HEADER pHead;
    00637     DWORD dwLengthNeeded = 0;
    00638     OBJECT_HANDLE_INFORMATION ohi;
    00639     PUNICODE_STRING pstrInfo;
    00640     PWINDOWSTATION pwinsta;
    00641     NTSTATUS Status;
    00642
    00643     /*
    00644      * Validate the object
    00645      */
    00646     Status = ObReferenceObjectByHandle(
    00647             h,
    00648             0,
    00649             NULL,
    00650             UserMode,   // this is always called from the client side
    00651             &pObject,
    00652             &ohi);
    00653     if (!NT_SUCCESS(Status)) {
    00654         RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
    00655         return FALSE;
    00656     }
    00657
    00658     pHead = OBJECT_TO_OBJECT_HEADER(pObject);
    00659     if (pHead->Type != *ExWindowStationObjectType &&
    00660             pHead->Type != *ExDesktopObjectType) {
    00661         RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
    00662         ObDereferenceObject(pObject);
    00663         return FALSE;
    00664     }
    00665
    00666 #ifdef LOGDESKTOPLOCKS
    00667     if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
    00668         LogDesktop(pObject, LD_REF_FN_GETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrentShared());
    00669     }
    00670 #endif
    00671
    00672     try {
    00673         switch (nIndex) {
    00674         case UOI_FLAGS:
    00675             dwLengthNeeded = sizeof(USEROBJECTFLAGS);
    00676             if (nLength < sizeof(USEROBJECTFLAGS)) {
    00677                 RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
    00678                 fSuccess = FALSE;
    00679                 break;
    00680             }
    00681             puof = ccxpvInfo;
    00682             puof->fInherit = (ohi.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE;
    00683             puof->fReserved = 0;
    00684             puof->dwFlags = 0;
    00685             if (pHead->Type == *ExDesktopObjectType) {
    00686                 if (CheckHandleFlag(h, HF_DESKTOPHOOK))
    00687                     puof->dwFlags |= DF_ALLOWOTHERACCOUNTHOOK;
    00688             } else {
    00689                 if (!(((PWINDOWSTATION)pObject)->dwWSF_Flags & WSF_NOIO))
    00690                     puof->dwFlags |= WSF_VISIBLE;
    00691             }
    00692             break;
    00693
    00694         case UOI_NAME:
    00695             pstrInfo = POBJECT_NAME(pObject);
    00696             goto docopy;
    00697
    00698         case UOI_TYPE:
    00699             pstrInfo = &pHead->Type->Name;
    00700 docopy:
    00701             if (pstrInfo) {
    00702                 dwLengthNeeded = pstrInfo->Length + sizeof(WCHAR);
    00703                 if (dwLengthNeeded > nLength) {
    00704                     RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
    00705                     fSuccess = FALSE;
    00706                     break;
    00707                 }
    00708                 RtlCopyMemory(ccxpvInfo, pstrInfo->Buffer, pstrInfo->Length);
    00709                 *(PWCHAR)((PBYTE)ccxpvInfo + pstrInfo->Length) = 0;
    00710             } else {
    00711                 dwLengthNeeded = 0;
    00712             }
    00713             break;
    00714
    00715         case UOI_USER_SID:
    00716             if (pHead->Type == *ExWindowStationObjectType)
    00717                 pwinsta = pObject;
    00718             else
    00719                 pwinsta = ((PDESKTOP)pObject)->rpwinstaParent;
    00720             if (pwinsta->psidUser == NULL) {
    00721                 dwLengthNeeded = 0;
    00722             } else {
    00723                 dwLengthNeeded = RtlLengthSid(pwinsta->psidUser);
    00724                 if (dwLengthNeeded > nLength) {
    00725                     RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
    00726                     fSuccess = FALSE;
    00727                     break;
    00728                 }
    00729                 RtlCopyMemory(ccxpvInfo, pwinsta->psidUser, dwLengthNeeded);
    00730             }
    00731             break;
    00732
    00733         default:
    00734             RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
    00735             fSuccess = FALSE;
    00736             break;
    00737         }
    00738     } except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
    00739         fSuccess = FALSE;
    00740     }
    00741
    00742     *lpnLengthNeeded = dwLengthNeeded;
    00743
    00744 #ifdef LOGDESKTOPLOCKS
    00745     if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
    00746         LogDesktop(pObject, LD_DEREF_FN_GETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrentShared());
    00747     }
    00748 #endif
    00749
    00750     ObDereferenceObject(pObject);
    00751
    00752     return fSuccess;
    00753 }
    00754
    00755 /***************************************************************************\
    00756 * _SetUserObjectInformation (API)
    00757 *
    00758 * Sets information about a secure USER object
    00759 *
    00760 * History:
    00761 * 04-25-94 JimA       Created.
    00762 \***************************************************************************/
    00763
    00764 BOOL _SetUserObjectInformation(
    00765     HANDLE h,
    00766     int nIndex,
    00767     PVOID ccxpvInfo,
    00768     DWORD nLength)
    00769 {
    00770     PUSEROBJECTFLAGS puof;
    00771     BOOL fSuccess = TRUE;
    00772     PVOID pObject;
    00773     POBJECT_HEADER pHead;
    00774     DWORD dwLengthNeeded = 0;
    00775     OBJECT_HANDLE_INFORMATION ohi;
    00776     OBJECT_HANDLE_FLAG_INFORMATION ofi;
    00777     NTSTATUS Status;
    00778
    00779     /*
    00780      * Validate the object
    00781      */
    00782     Status = ObReferenceObjectByHandle(
    00783             h,
    00784             0,
    00785             NULL,
    00786             UserMode,   // this is always called from the client side
    00787             &pObject,
    00788             &ohi);
    00789     if (!NT_SUCCESS(Status)) {
    00790         RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
    00791         return FALSE;
    00792     }
    00793
    00794     pHead = OBJECT_TO_OBJECT_HEADER(pObject);
    00795     if (pHead->Type != *ExWindowStationObjectType &&
    00796             pHead->Type != *ExDesktopObjectType) {
    00797         RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
    00798         ObDereferenceObject(pObject);
    00799         return FALSE;
    00800     }
    00801
    00802 #ifdef LOGDESKTOPLOCKS
    00803     if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
    00804         LogDesktop(pObject, LD_REF_FN_SETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrent());
    00805     }
    00806 #endif
    00807
    00808     try {
    00809         switch (nIndex) {
    00810         case UOI_FLAGS:
    00811             if (nLength < sizeof(USEROBJECTFLAGS)) {
    00812                 RIPERR0(ERROR_INVALID_DATA, RIP_VERBOSE, "");
    00813                 fSuccess = FALSE;
    00814                 break;
    00815             }
    00816             puof = ccxpvInfo;
    00817             ZwQueryObject(h, ObjectHandleFlagInformation,
    00818                     &ofi, sizeof(ofi), NULL);
    00819             ofi.Inherit = (puof->fInherit != FALSE);
    00820             ZwSetInformationObject(h, ObjectHandleFlagInformation,
    00821                     &ofi, sizeof(ofi));
    00822             if (pHead->Type == *ExDesktopObjectType) {
    00823                 SetHandleFlag(h, HF_DESKTOPHOOK,
    00824                         puof->dwFlags & DF_ALLOWOTHERACCOUNTHOOK);
    00825             }
    00826             break;
    00827         default:
    00828             RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
    00829             fSuccess = FALSE;
    00830             break;
    00831         }
    00832     } except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
    00833         fSuccess = FALSE;
    00834     }
    00835
    00836 #ifdef LOGDESKTOPLOCKS
    00837     if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
    00838         LogDesktop(pObject, LD_DEREF_FN_SETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrent());
    00839     }
    00840 #endif
    00841
    00842     ObDereferenceObject(pObject);
    00843
    00844     return fSuccess;
    00845 }
    00846
    00847 /***************************************************************************\
    00848 * UserScreenAccessCheck
    00849 *
    00850 * Called from the engine to determine if the thread's desktop is
    00851 * active and the process has WINSTA_READSCREEN access.
    00852 *
    00853 * Note that we may or may not be in USER's critical section when this
    00854 * is called.  This is OK as long as we don't reference thing belonging
    00855 * to other threads.  If we did try to enter the critical section here,
    00856 * a deadlock may occur between the engine and user.
    00857 *
    00858 * History:
    00859 * 05-20-93 JimA         Created.
    00860 * 11-22-96 BradG        Brought back to life.
    00861 \***************************************************************************/
    00862
    00863 BOOL FASTCALL UserScreenAccessCheck(VOID)
    00864 {
    00865     UserAssert(PtiCurrentShared() != NULL);
    00866
    00867     return (
    00868             PtiCurrentShared() != NULL && PtiCurrentShared()->rpdesk == grpdeskRitInput &&
    00869             (W32GetCurrentProcess()->W32PF_Flags & (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)) ==
    00870                     (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA));
    00871 }