//+----------------------------------------------------------------------- // // Microsoft Windows // // Copyright (c) Microsoft Corporation 1992 - 1994 // // File: policy.cxx // // Contents: SpmBuildCairoToken // // // History: 23-May-1994 MikeSw Created // //------------------------------------------------------------------------ #include 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); }