//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: mapsam.cxx // // Contents: // // Classes: // // Functions: // // History: 10-17-96 RichardW Created // //---------------------------------------------------------------------------- extern "C" { #include "sslp.h" #include #include #include #include #include #include #include #include #include #include "mapsam.h" } #include //+--------------------------------------------------------------------------- // // Function: SslDuplicateString // // Synopsis: Duplicate a unicode string // // Arguments: [Dest] -- // [Source] -- // // History: 10-18-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- NTSTATUS SslDuplicateString( PUNICODE_STRING Dest, PUNICODE_STRING Source ) { Dest->Buffer = (PWSTR) LocalAlloc( LMEM_FIXED, Source->Length + sizeof(WCHAR) ); if ( Dest->Buffer ) { Dest->Length = Source->Length ; Dest->MaximumLength = Source->Length + sizeof(WCHAR) ; CopyMemory( Dest->Buffer, Source->Buffer, Source->Length ); Dest->Buffer[ Dest->Length / 2 ] = L'\0'; return( STATUS_SUCCESS ); } return( STATUS_NO_MEMORY ); } //+------------------------------------------------------------------------- // // Function: SslMakeDomainRelativeSid // // Synopsis: Given a domain Id and a relative ID create the corresponding // SID allocated from the LSA heap. // // Effects: // // Arguments: // // DomainId - The template SID to use. // // RelativeId - The relative Id to append to the DomainId. // // Requires: // // Returns: Sid - Returns a pointer to a buffer allocated from the LsaHeap // containing the resultant Sid. // // Notes: // // //-------------------------------------------------------------------------- PSID SslMakeDomainRelativeSid( IN PSID DomainId, IN ULONG RelativeId ) { UCHAR DomainIdSubAuthorityCount; ULONG Size; PSID Sid; // // Allocate a Sid which has one more sub-authority than the domain ID. // DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId )); Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1); if ((Sid = LocalAlloc( LMEM_FIXED, Size )) == NULL ) { return NULL; } // // Initialize the new SID to have the same inital value as the // domain ID. // if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) { LocalFree( Sid ); return NULL; } // // Adjust the sub-authority count and // add the relative Id unique to the newly allocated SID // (*(RtlSubAuthorityCountSid( Sid ))) ++; *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId; return Sid; } //+------------------------------------------------------------------------- // // Function: SslDuplicateSid // // Synopsis: Duplicates a SID // // Effects: allocates memory with LsaFunctions.AllocateLsaHeap // // Arguments: DestinationSid - Receives a copy of the SourceSid // SourceSid - SID to copy // // Requires: // // Returns: STATUS_SUCCESS - the copy succeeded // STATUS_INSUFFICIENT_RESOURCES - the call to allocate memory // failed // // Notes: // // //-------------------------------------------------------------------------- NTSTATUS SslDuplicateSid( OUT PSID * DestinationSid, IN PSID SourceSid ) { ULONG SidSize; DsysAssert(RtlValidSid(SourceSid)); SidSize = RtlLengthSid(SourceSid); *DestinationSid = (PSID) LocalAlloc( LMEM_FIXED, SidSize ); if (*DestinationSid == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( *DestinationSid, SourceSid, SidSize ); return(STATUS_SUCCESS); } NTSTATUS SslpGetPacForUser( IN SAMPR_HANDLE UserHandle, OUT PPACTYPE * ppPac ) { PSAMPR_USER_ALL_INFORMATION UserAll = NULL ; PSAMPR_USER_INFO_BUFFER UserAllInfo = NULL ; NTSTATUS Status ; PPACTYPE pNewPac = NULL ; PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL ; *ppPac = NULL ; Status = pSamrQueryInformationUser( UserHandle, UserAllInformation, &UserAllInfo ); if ( !NT_SUCCESS( Status ) ) { return( Status ); } UserAll = &UserAllInfo->All ; if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED ) { Status = STATUS_ACCOUNT_DISABLED ; goto GetPac_Cleanup; } Status = pSamrGetGroupsForUser( UserHandle, &GroupsBuffer ); if ( !NT_SUCCESS( Status ) ) { goto GetPac_Cleanup ; } Status = PAC_Init( UserAll, GroupsBuffer, GlobalDomainSid, &GlobalDomainName, &GlobalMachineName, NULL, ppPac ); GetPac_Cleanup: if ( UserAllInfo ) { pSamIFree_SAMPR_USER_INFO_BUFFER( UserAllInfo, UserAllInformation ); } if ( GroupsBuffer ) { pSamIFree_SAMPR_GET_GROUPS_BUFFER( GroupsBuffer ); } return( Status ); } NTSTATUS SslGetPacForUser( IN PUNICODE_STRING AlternateName, IN BOOL AllowGuest, OUT PUCHAR * pPacData, OUT PULONG pPacDataSize ) { NTSTATUS Status ; PVOID UserHandle ; *pPacData = NULL ; *pPacDataSize = 0 ; Status = LsaTable->OpenSamUser( AlternateName, SecNameAlternateId, &SslNamePrefix, AllowGuest, 0, &UserHandle ); if ( NT_SUCCESS( Status ) ) { Status = LsaTable->GetUserAuthData( UserHandle, pPacData, pPacDataSize ); (VOID) LsaTable->CloseSamUser( UserHandle ); } return Status ; } NTSTATUS SslCreateTokenFromPac( IN PUCHAR MarshalledPac, IN ULONG MarshalledPacSize, OUT PLUID NewLogonId, OUT PHANDLE Token ) { PLSA_TOKEN_INFORMATION_V1 TokenInformation = NULL ; PLSA_TOKEN_INFORMATION_NULL TokenNull = NULL ; PVOID LsaTokenInformation = NULL ; LUID LogonId ; UNICODE_STRING UserName ; UNICODE_STRING DomainName ; UNICODE_STRING Workstation ; NTSTATUS Status ; NTSTATUS SubStatus ; HANDLE TokenHandle = NULL ; RtlInitUnicodeString( &UserName, L"Certificate User" ); RtlInitUnicodeString( &DomainName, GlobalDomainName.Buffer ); // // Now create the token. // LsaTokenInformation = TokenInformation; // // Create a logon session. // NtAllocateLocallyUniqueId(&LogonId); Status = LsaTable->CreateLogonSession( &LogonId ); if (!NT_SUCCESS(Status)) { DebugOut((DEB_ERROR,"Failed to create logon session: 0x%x\n",Status)); goto CreateToken_Cleanup; } // // We would normally pass in the client workstation name when creating // the token, but this information is not available since the client is // sitting on the other side of an SSL connection. // RtlInitUnicodeString( &Workstation, NULL ); Status = LsaTable->CreateToken( &LogonId, &SslSource, Network, LsaTokenInformationV1, LsaTokenInformation, NULL, // no token groups &UserName, &DomainName, &Workstation, &TokenHandle, &SubStatus ); if (!NT_SUCCESS(Status)) { DebugOut((DEB_ERROR,"Failed to create token: 0x%x\n",Status)); goto CreateToken_Cleanup; } TokenInformation = NULL; TokenNull = NULL; if (!NT_SUCCESS(SubStatus)) { DebugOut((DEB_ERROR,"Failed to create token, substatus = 0x%x\n",SubStatus)); Status = SubStatus; goto CreateToken_Cleanup; } // // If the caller wanted an identify level token, duplicate the token // now. // #if 0 if ((ContextFlags & ISC_RET_IDENTIFY) != 0) { if (!DuplicateTokenEx( TokenHandle, TOKEN_ALL_ACCESS, NULL, // no security attributes SecurityIdentification, TokenImpersonation, &TempTokenHandle )) { DebugOut((DEB_ERROR,"Failed to duplicate token\n")); DsysAssert(GetLastError() == ERROR_NO_SYSTEM_RESOURCES); Status = STATUS_INSUFFICIENT_RESOURCES; goto CreateToken_Cleanup; } Status = NtClose(TokenHandle); DsysAssert(NT_SUCCESS(Status)); TokenHandle = TempTokenHandle; TempTokenHandle = NULL; } #endif // // Check the delegation information to see if we need to create // a logon session for this. // *NewLogonId = LogonId; *Token = TokenHandle; CreateToken_Cleanup: if (TokenInformation != NULL) { if ( TokenInformation->User.User.Sid != NULL ) { LocalFree( TokenInformation->User.User.Sid ); } if ( TokenInformation->Groups != NULL ) { ULONG i; for ( i=0; i < TokenInformation->Groups->GroupCount; i++ ) { LocalFree( TokenInformation->Groups->Groups[i].Sid ); } LocalFree( TokenInformation->Groups ); } if ( TokenInformation->PrimaryGroup.PrimaryGroup != NULL ) { LocalFree( TokenInformation->PrimaryGroup.PrimaryGroup ); } LocalFree( TokenInformation ); } if (TokenNull != NULL) { LocalFree(TokenNull); } if (!NT_SUCCESS(Status)) { // // Note: if we have created a token, we don't want to delete // the logon session here because we will end up dereferencing // the logon session twice. // if (TokenHandle != NULL) { NtClose(TokenHandle); } else if ((LogonId.LowPart != 0) || (LogonId.HighPart != 0)) { LsaTable->DeleteLogonSession(&LogonId); } } return(Status); }