530 lines
14 KiB
C++
530 lines
14 KiB
C++
//+-----------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1992 - 1994
|
|
//
|
|
// File: policy.cxx
|
|
//
|
|
// Contents: SpmBuildCairoToken
|
|
//
|
|
//
|
|
// History: 23-May-1994 MikeSw Created
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
#include <lsapch.hxx>
|
|
extern "C"
|
|
{
|
|
#include "adtp.h"
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: LsapCreateToken
|
|
//
|
|
// Synopsis: Builds a token from the various pieces of information
|
|
// generated during a logon.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: pUserSid - sid of user to create token for
|
|
// pTokenGroups - groups passed in to LogonUser or from PAC to
|
|
// be put in token
|
|
// pTokenPrivs - privileges from PAC to put in token
|
|
// TokenType - type of token to create
|
|
// pTokenSource - source of the token
|
|
// pLogonId - Gets logon ID
|
|
// phToken - Get handle to token
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: TokenInformation is always freed, even on failure.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
LsapCreateToken(
|
|
IN PLUID LogonId,
|
|
IN PTOKEN_SOURCE TokenSource,
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
|
|
IN LSA_TOKEN_INFORMATION_TYPE InputTokenInformationType,
|
|
IN PVOID InputTokenInformation,
|
|
IN PTOKEN_GROUPS LocalGroups,
|
|
IN PUNICODE_STRING AccountName,
|
|
IN PUNICODE_STRING AuthorityName,
|
|
IN PUNICODE_STRING WorkstationName,
|
|
IN OPTIONAL PUNICODE_STRING ProfilePath,
|
|
OUT PHANDLE Token,
|
|
OUT PNTSTATUS SubStatus
|
|
)
|
|
{
|
|
SECPKG_PRIMARY_CRED PrimaryCredential;
|
|
|
|
ZeroMemory( &PrimaryCredential, sizeof(PrimaryCredential) );
|
|
|
|
|
|
if( AccountName != NULL )
|
|
{
|
|
PrimaryCredential.DownlevelName = *AccountName;
|
|
}
|
|
|
|
if( AuthorityName != NULL )
|
|
{
|
|
PrimaryCredential.DomainName = *AuthorityName;
|
|
}
|
|
|
|
return LsapCreateTokenEx(
|
|
LogonId,
|
|
TokenSource,
|
|
LogonType,
|
|
ImpersonationLevel,
|
|
InputTokenInformationType,
|
|
InputTokenInformation,
|
|
LocalGroups,
|
|
WorkstationName,
|
|
ProfilePath,
|
|
&PrimaryCredential,
|
|
SecSessionPrimaryCred,
|
|
Token,
|
|
SubStatus
|
|
);
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: LsapCreateTokenEx
|
|
//
|
|
// Synopsis: Builds a token from the various pieces of information
|
|
// generated during a logon.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: pUserSid - sid of user to create token for
|
|
// pTokenGroups - groups passed in to LogonUser or from PAC to
|
|
// be put in token
|
|
// pTokenPrivs - privileges from PAC to put in token
|
|
// TokenType - type of token to create
|
|
// pTokenSource - source of the token
|
|
// pLogonId - Gets logon ID
|
|
// phToken - Get handle to token
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: TokenInformation is always freed, even on failure.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
LsapCreateTokenEx(
|
|
IN PLUID LogonId,
|
|
IN PTOKEN_SOURCE TokenSource,
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
|
|
IN LSA_TOKEN_INFORMATION_TYPE InputTokenInformationType,
|
|
IN PVOID InputTokenInformation,
|
|
IN PTOKEN_GROUPS LocalGroups,
|
|
IN PUNICODE_STRING WorkstationName,
|
|
IN PUNICODE_STRING ProfilePath,
|
|
IN PVOID SessionInformation,
|
|
IN SECPKG_SESSIONINFO_TYPE SessionInformationType,
|
|
OUT PHANDLE Token,
|
|
OUT PNTSTATUS SubStatus
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PPRIVILEGE_SET PrivilegesAssigned = NULL;
|
|
PLSA_TOKEN_INFORMATION_V2 TokenInformationV2 = NULL;
|
|
PLSA_TOKEN_INFORMATION_NULL TokenInformationNull = NULL;
|
|
LSA_TOKEN_INFORMATION_TYPE OriginalTokenType = InputTokenInformationType;
|
|
QUOTA_LIMITS QuotaLimits;
|
|
PUNICODE_STRING NewAccountName = NULL;
|
|
PUNICODE_STRING NewAuthorityName = NULL;
|
|
PUNICODE_STRING NewProfilePath = NULL;
|
|
UNICODE_STRING LocalAccountName = { 0 };
|
|
UNICODE_STRING LocalAuthorityName = { 0 };
|
|
UNICODE_STRING LocalProfilePath = { 0 };
|
|
PSID NewUserSid = NULL;
|
|
LSA_TOKEN_INFORMATION_TYPE TokenInformationType = InputTokenInformationType;
|
|
PVOID TokenInformation = InputTokenInformation;
|
|
|
|
PSECPKG_PRIMARY_CRED PrimaryCredential;
|
|
PUNICODE_STRING AccountName;
|
|
PUNICODE_STRING AuthorityName;
|
|
|
|
|
|
*Token = NULL;
|
|
*SubStatus = STATUS_SUCCESS;
|
|
|
|
if( SessionInformationType != SecSessionPrimaryCred )
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
PrimaryCredential = (PSECPKG_PRIMARY_CRED)SessionInformation;
|
|
|
|
AccountName = &PrimaryCredential->DownlevelName;
|
|
AuthorityName = &PrimaryCredential->DomainName;
|
|
|
|
//
|
|
// Pass the token information through the Local Security Policy
|
|
// Filter/Augmentor. This may cause some or all of the token
|
|
// information to be replaced/augmented.
|
|
//
|
|
|
|
Status = LsapAuUserLogonPolicyFilter(
|
|
LogonType,
|
|
&TokenInformationType,
|
|
&TokenInformation,
|
|
LocalGroups,
|
|
&QuotaLimits,
|
|
&PrivilegesAssigned
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Check if we only allow admins to logon. We do allow null session
|
|
// connections since they are severly restricted, though. Since the
|
|
// token type may have been changed, we use the token type originally
|
|
// returned by the package.
|
|
//
|
|
|
|
if (LsapAllowAdminLogonsOnly &&
|
|
((OriginalTokenType == LsaTokenInformationV1) ||
|
|
(OriginalTokenType == LsaTokenInformationV2))&&
|
|
!LsapSidPresentInGroups(
|
|
((PLSA_TOKEN_INFORMATION_V2) TokenInformation)->Groups,
|
|
(SID *)LsapAliasAdminsSid)) {
|
|
|
|
//
|
|
// Set the status to be invalid workstation, since all accounts
|
|
// except administrative ones are locked out for this
|
|
// workstation.
|
|
//
|
|
|
|
*SubStatus = STATUS_INVALID_WORKSTATION;
|
|
Status = STATUS_ACCOUNT_RESTRICTION;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Case on the token information returned (and subsequently massaged)
|
|
// to create the correct kind of token.
|
|
//
|
|
|
|
switch (TokenInformationType) {
|
|
|
|
case LsaTokenInformationNull:
|
|
|
|
TokenInformationNull = (PLSA_TOKEN_INFORMATION_NULL) TokenInformation;
|
|
|
|
//
|
|
// The user hasn't logged on to any particular account.
|
|
// An impersonation token with WORLD as owner
|
|
// will be created.
|
|
//
|
|
|
|
|
|
Status = LsapCreateNullToken(
|
|
LogonId,
|
|
TokenSource,
|
|
TokenInformationNull,
|
|
Token
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LsaTokenInformationV1:
|
|
case LsaTokenInformationV2:
|
|
|
|
TokenInformationV2 = (PLSA_TOKEN_INFORMATION_V2) TokenInformation;
|
|
|
|
//
|
|
// the type of token created depends upon the type of logon
|
|
// being requested:
|
|
//
|
|
// InteractiveLogon => PrimaryToken
|
|
// BatchLogon => PrimaryToken
|
|
// NetworkLogon => ImpersonationToken
|
|
//
|
|
|
|
if (LogonType != Network) {
|
|
|
|
//
|
|
// Primary token
|
|
//
|
|
|
|
Status = LsapCreateV2Token(
|
|
LogonId,
|
|
TokenSource,
|
|
TokenInformationV2,
|
|
TokenPrimary,
|
|
ImpersonationLevel,
|
|
Token
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
//
|
|
// Impersonation token
|
|
//
|
|
|
|
Status = LsapCreateV2Token(
|
|
LogonId,
|
|
TokenSource,
|
|
TokenInformationV2,
|
|
TokenImpersonation,
|
|
ImpersonationLevel,
|
|
Token
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Copy out the User Sid
|
|
//
|
|
|
|
Status = LsapDuplicateSid( &NewUserSid, TokenInformationV2->User.User.Sid );
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Audit special privilege assignment, if there were any
|
|
//
|
|
|
|
if ( PrivilegesAssigned != NULL ) {
|
|
|
|
//
|
|
// Examine the list of privileges being assigned, and
|
|
// audit special privileges as appropriate.
|
|
//
|
|
|
|
LsapAdtAuditSpecialPrivileges( PrivilegesAssigned, *LogonId, NewUserSid );
|
|
|
|
}
|
|
|
|
|
|
NewAccountName = &LocalAccountName ;
|
|
NewAuthorityName = &LocalAuthorityName ;
|
|
|
|
|
|
//
|
|
// If the original was a null session, set the user name & domain name
|
|
// to be anonymous.
|
|
//
|
|
|
|
if (OriginalTokenType == LsaTokenInformationNull)
|
|
{
|
|
NewAccountName->Buffer = (LPWSTR) LsapAllocateLsaHeap(WellKnownSids[LsapAnonymousSidIndex].Name.MaximumLength);
|
|
if (NewAccountName->Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
NewAccountName->MaximumLength = WellKnownSids[LsapAnonymousSidIndex].Name.MaximumLength;
|
|
RtlCopyUnicodeString(
|
|
NewAccountName,
|
|
&WellKnownSids[LsapAnonymousSidIndex].Name
|
|
);
|
|
|
|
NewAuthorityName->Buffer = (LPWSTR) LsapAllocateLsaHeap(WellKnownSids[LsapAnonymousSidIndex].DomainName.MaximumLength);
|
|
if (NewAuthorityName->Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
NewAuthorityName->MaximumLength = WellKnownSids[LsapAnonymousSidIndex].DomainName.MaximumLength;
|
|
RtlCopyUnicodeString(
|
|
NewAuthorityName,
|
|
&WellKnownSids[LsapAnonymousSidIndex].DomainName
|
|
);
|
|
|
|
}
|
|
else
|
|
{
|
|
NewAccountName->Buffer = (LPWSTR) LsapAllocateLsaHeap(AccountName->MaximumLength);
|
|
if (NewAccountName->Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
NewAccountName->MaximumLength = AccountName->MaximumLength;
|
|
RtlCopyUnicodeString(
|
|
NewAccountName,
|
|
AccountName
|
|
);
|
|
|
|
NewAuthorityName->Buffer = (LPWSTR) LsapAllocateLsaHeap(AuthorityName->MaximumLength);
|
|
if (NewAuthorityName->Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
NewAuthorityName->MaximumLength = AuthorityName->MaximumLength;
|
|
RtlCopyUnicodeString(
|
|
NewAuthorityName,
|
|
AuthorityName
|
|
);
|
|
|
|
if (ARGUMENT_PRESENT(ProfilePath) ) {
|
|
NewProfilePath = &LocalProfilePath ;
|
|
|
|
NewProfilePath->Buffer = (LPWSTR) LsapAllocateLsaHeap(ProfilePath->MaximumLength);
|
|
if (NewProfilePath->Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
NewProfilePath->MaximumLength = ProfilePath->MaximumLength;
|
|
RtlCopyUnicodeString(
|
|
NewProfilePath,
|
|
ProfilePath
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
Status = LsapSetLogonSessionAccountInfo(
|
|
LogonId,
|
|
NewAccountName,
|
|
NewAuthorityName,
|
|
NewProfilePath,
|
|
&NewUserSid,
|
|
LogonType,
|
|
PrimaryCredential
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
LocalAccountName.Buffer = NULL ;
|
|
LocalAuthorityName.Buffer = NULL ;
|
|
LocalProfilePath.Buffer = NULL ;
|
|
|
|
//
|
|
// Set the token on the session
|
|
//
|
|
|
|
Status = LsapSetSessionToken( *Token, LogonId );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// Clean up on failure
|
|
//
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// If we successfully built the token,
|
|
// free it.
|
|
//
|
|
|
|
if ( *Token != NULL ) {
|
|
NtClose( *Token );
|
|
*Token = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Always free the token information because the policy filter
|
|
// changes it.
|
|
//
|
|
|
|
switch (TokenInformationType) {
|
|
|
|
case LsaTokenInformationNull:
|
|
|
|
LsapFreeTokenInformationNull( (PLSA_TOKEN_INFORMATION_NULL) TokenInformation );
|
|
break;
|
|
|
|
case LsaTokenInformationV1:
|
|
|
|
LsapFreeTokenInformationV1( (PLSA_TOKEN_INFORMATION_V1) TokenInformation );
|
|
break;
|
|
|
|
case LsaTokenInformationV2:
|
|
|
|
LsapFreeTokenInformationV2( (PLSA_TOKEN_INFORMATION_V2) TokenInformation );
|
|
break;
|
|
|
|
}
|
|
|
|
if ( LocalAccountName.Buffer != NULL )
|
|
{
|
|
LsapFreeLsaHeap( LocalAccountName.Buffer );
|
|
}
|
|
|
|
if ( LocalAuthorityName.Buffer != NULL )
|
|
{
|
|
LsapFreeLsaHeap( LocalAuthorityName.Buffer );
|
|
}
|
|
|
|
if ( LocalProfilePath.Buffer != NULL )
|
|
{
|
|
LsapFreeLsaHeap( LocalProfilePath.Buffer );
|
|
}
|
|
|
|
if (NewUserSid != NULL) {
|
|
LsapFreeLsaHeap( NewUserSid );
|
|
}
|
|
if ( PrivilegesAssigned != NULL ) {
|
|
|
|
MIDL_user_free( PrivilegesAssigned );
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|