diff --git a/dll/win32/lsasrv/authpackage.c b/dll/win32/lsasrv/authpackage.c index 8a335be6d6b..462329b826e 100644 --- a/dll/win32/lsasrv/authpackage.c +++ b/dll/win32/lsasrv/authpackage.c @@ -1627,9 +1627,18 @@ LsapLogonUser(PLSA_API_MSG RequestMsg, else if (TokenInformationType == LsaTokenInformationV1) { TOKEN_PRIVILEGES NoPrivileges = {0}; + PSECURITY_DESCRIPTOR TokenSd; + ULONG TokenSdSize; TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation; + /* Set up a security descriptor for token object itself */ + Status = LsapCreateTokenSd(&TokenInfo1->User, &TokenSd, &TokenSdSize); + if (!NT_SUCCESS(Status)) + { + TokenSd = NULL; + } + Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); Qos.ImpersonationLevel = SecurityImpersonation; Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; @@ -1639,7 +1648,7 @@ LsapLogonUser(PLSA_API_MSG RequestMsg, ObjectAttributes.RootDirectory = NULL; ObjectAttributes.ObjectName = NULL; ObjectAttributes.Attributes = 0; - ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityDescriptor = TokenSd; ObjectAttributes.SecurityQualityOfService = &Qos; /* Create the logon token */ @@ -1656,6 +1665,10 @@ LsapLogonUser(PLSA_API_MSG RequestMsg, &TokenInfo1->PrimaryGroup, &TokenInfo1->DefaultDacl, &RequestMsg->LogonUser.Request.SourceContext); + + /* Free the allocated security descriptor */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TokenSd); + if (!NT_SUCCESS(Status)) { ERR("NtCreateToken failed (Status 0x%08lx)\n", Status); diff --git a/dll/win32/lsasrv/lsasrv.h b/dll/win32/lsasrv/lsasrv.h index a73b66c672e..2ba5fa1b917 100644 --- a/dll/win32/lsasrv/lsasrv.h +++ b/dll/win32/lsasrv/lsasrv.h @@ -436,6 +436,12 @@ NTSTATUS LsapCreateSecretSd(PSECURITY_DESCRIPTOR *SecretSd, PULONG SecretSdSize); +NTSTATUS +LsapCreateTokenSd( + _In_ const TOKEN_USER *User, + _Outptr_ PSECURITY_DESCRIPTOR *TokenSd, + _Out_ PULONG TokenSdSize); + /* session.c */ VOID LsapInitLogonSessions(VOID); diff --git a/dll/win32/lsasrv/security.c b/dll/win32/lsasrv/security.c index 10fd7352a23..6bb61cdfa65 100644 --- a/dll/win32/lsasrv/security.c +++ b/dll/win32/lsasrv/security.c @@ -599,4 +599,180 @@ done: return Status; } + +/** + * @brief + * Creates a security descriptor for the token + * object. + * + * @param[in] User + * A primary user to be given to the function. + * This user represents the owner that is in + * charge of this object. + * + * @param[out] TokenSd + * A pointer to an allocated security descriptor + * for the token object. + * + * @param[out] TokenSdSize + * A pointer to a returned size of the descriptor. + * + * @return + * STATUS_SUCCESS is returned if the function has + * successfully created the security descriptor. + * STATUS_INVALID_PARAMETER is returned if one of the + * parameters are not valid. STATUS_INSUFFICIENT_RESOURCES + * is returned if memory heap allocation for specific + * security buffers couldn't be done. A NTSTATUS status + * code is returned otherwise. + * + * @remarks + * Bot the local system and user are given full access rights + * for the token (they can open it, read and write into it, etc.) + * whereas admins can only read from the token. This security + * descriptor is TO NOT BE confused with the default DACL of the + * token which is another thing that serves different purpose. + */ +NTSTATUS +LsapCreateTokenSd( + _In_ const TOKEN_USER *User, + _Outptr_ PSECURITY_DESCRIPTOR *TokenSd, + _Out_ PULONG TokenSdSize) +{ + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + ULONG RelativeSdSize = 0; + PSID AdministratorsSid = NULL; + PSID LocalSystemSid = NULL; + PACL Dacl = NULL; + ULONG DaclSize; + NTSTATUS Status; + + if (TokenSd == NULL || TokenSdSize == NULL) + return STATUS_INVALID_PARAMETER; + + *TokenSd = NULL; + *TokenSdSize = 0; + + /* Initialize the SD */ + Status = RtlCreateSecurityDescriptor(&AbsoluteSd, + SECURITY_DESCRIPTOR_REVISION); + if (!NT_SUCCESS(Status)) + return Status; + + Status = RtlAllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &LocalSystemSid); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdministratorsSid); + if (!NT_SUCCESS(Status)) + goto done; + + /* Allocate and initialize the DACL */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LocalSystemSid) + + sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(AdministratorsSid) + + sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(User->User.Sid); + + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = RtlCreateAcl(Dacl, + DaclSize, + ACL_REVISION); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + TOKEN_ALL_ACCESS, + LocalSystemSid); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + TOKEN_READ, + AdministratorsSid); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + TOKEN_ALL_ACCESS, + User->User.Sid); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd, + TRUE, + Dacl, + FALSE); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd, + AdministratorsSid, + FALSE); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd, + RelativeSd, + &RelativeSdSize); + if (Status != STATUS_BUFFER_TOO_SMALL) + goto done; + + RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + RelativeSdSize); + if (RelativeSd == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd, + RelativeSd, + &RelativeSdSize); + if (!NT_SUCCESS(Status)) + goto done; + + *TokenSd = RelativeSd; + *TokenSdSize = RelativeSdSize; + +done: + if (Dacl != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + + if (AdministratorsSid != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid); + + if (LocalSystemSid != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid); + + if (!NT_SUCCESS(Status)) + { + if (RelativeSd != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + + return Status; +} + /* EOF */