488 lines
11 KiB
C++
488 lines
11 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 <crypt.h>
|
|
#include <lmcons.h>
|
|
#include <ntsam.h>
|
|
#include <samrpc.h>
|
|
#include <samisrv.h>
|
|
#include <lsarpc.h>
|
|
#include <lsaisrv.h>
|
|
#include <ntmsv1_0.h>
|
|
#include <certmap.h>
|
|
#include "mapsam.h"
|
|
}
|
|
|
|
#include <pac.hxx>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|