windows-nt/Source/XPSP1/NT/ds/security/base/lsa/server/policy.cxx
2020-09-26 16:20:57 +08:00

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);
}