Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

581 lines
14 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
adtutil.c
Abstract:
Misc helper functions
Author:
15-August-2000 kumarp
--*/
#include <lsapch2.h>
#include "adtp.h"
NTSTATUS
ImpersonateAnyClient(); // from ntdsa
VOID
UnImpersonateAnyClient(); // from ntdsa
ULONG
LsapSafeWcslen(
UNALIGNED WCHAR *p,
LONG MaxLength
)
/*++
Safewcslen - Strlen that won't exceed MaxLength
Routine Description:
This routine is called to determine the size of a UNICODE_STRING
(taken from elfapi.c)
Arguments:
p - The string to count.
MaxLength - The maximum length to look at.
Return Value:
Number of bytes in the string (or MaxLength)
--*/
{
ULONG Count = 0;
if (p)
{
while ((MaxLength > 0) && (*p++ != UNICODE_NULL))
{
MaxLength -= sizeof(WCHAR);
Count += sizeof(WCHAR);
}
}
return Count;
}
BOOL
LsapIsValidUnicodeString(
IN PUNICODE_STRING pUString
)
/*++
Routine Description:
Verify the unicode string. The string is invalid if:
The UNICODE_STRING structure ptr is NULL.
The MaximumLength field is invalid (too small).
The Length field is incorrect.
(taken from elfapi.c)
Arguments:
pUString - String to verify.
Return Value:
TRUE if the string is valid
FALSE otherwise
--*/
{
return !(!pUString ||
(pUString->MaximumLength < pUString->Length) ||
(pUString->Length != LsapSafeWcslen(pUString->Buffer,
pUString->Length)));
}
BOOLEAN
LsapAdtLookupDriveLetter(
IN PUNICODE_STRING FileName,
OUT PUSHORT DeviceNameLength,
OUT PWCHAR DriveLetter
)
/*++
Routine Description:
This routine will take a file name and compare it to the
list of device names obtained during LSA initialization.
If one of the device names matches the prefix of the file
name the corresponding drive letter will be returned.
Arguments:
FileName - Supplies a unicode string containing the file
name obtained from the file system.
DeviceNameLength - If successful, returns the length of
the device name.
DriveLetter - If successful, returns the drive letter
corresponding to the device object.
Return Value:
Returns TRUE of a mapping is found, FALSE otherwise.
--*/
{
LONG i = 0;
PUNICODE_STRING DeviceName;
USHORT OldLength;
for (i = MAX_DRIVE_MAPPING - 1; i >= 0; i--)
{
if (DriveMappingArray[i].DeviceName.Buffer != NULL ) {
DeviceName = &DriveMappingArray[i].DeviceName;
//
// If the device name is longer than the passed file name,
// it can't be a match.
//
if ( DeviceName->Length > FileName->Length ) {
continue;
}
//
// Temporarily truncate the file name to be the same
// length as the device name by adjusting the length field
// in its unicode string structure. Then compare them and
// see if they match.
//
// The test above ensures that this is a safe thing to
// do.
//
OldLength = FileName->Length;
FileName->Length = DeviceName->Length;
if ( RtlEqualUnicodeString( FileName, DeviceName, TRUE ) ) {
//
// We've got a match.
//
FileName->Length = OldLength;
*DriveLetter = DriveMappingArray[i].DriveLetter;
*DeviceNameLength = DeviceName->Length;
return( TRUE );
}
FileName->Length = OldLength;
}
}
return( FALSE );
}
VOID
LsapAdtSubstituteDriveLetter(
IN OUT PUNICODE_STRING FileName
)
/*++
Routine Description:
Takes a filename and replaces the device name part with a
drive letter, if possible.
The string will be edited directly in place, which means that
the Length field will be adjusted, and the Buffer contents will
be moved so that the drive letter is at the beginning of the
buffer. No memory will be allocated or freed.
Arguments:
FileName - Supplies a pointer to a unicode string containing
a filename.
Return Value:
None.
--*/
{
WCHAR DriveLetter;
USHORT DeviceNameLength;
PWCHAR p;
PWCHAR FilePart;
USHORT FilePartLength;
if ( LsapAdtLookupDriveLetter( FileName, &DeviceNameLength, &DriveLetter )) {
p = FileName->Buffer;
FilePart = (PWCHAR)((PCHAR)(FileName->Buffer) + DeviceNameLength);
FilePartLength = FileName->Length - DeviceNameLength;
*p = DriveLetter;
*++p = L':';
//
// THIS IS AN OVERLAPPED COPY! DO NOT USE RTLCOPYMEMORY!
//
RtlMoveMemory( ++p, FilePart, FilePartLength );
FileName->Length = FilePartLength + 2 * sizeof( WCHAR );
}
}
NTSTATUS
LsapQueryClientInfo(
PTOKEN_USER *UserSid,
PLUID AuthenticationId
)
/*++
Routine Description:
This routine impersonates our client, opens the thread token, and
extracts the User Sid. It puts the Sid in memory allocated via
LsapAllocateLsaHeap, which must be freed by the caller.
Arguments:
None.
Return Value:
Returns a pointer to heap memory containing a copy of the Sid, or
NULL.
--*/
{
NTSTATUS Status;
HANDLE TokenHandle;
ULONG ReturnLength;
TOKEN_STATISTICS TokenStats;
BOOLEAN bImpersonatingAnonymous = FALSE;
Status = NtOpenThreadToken(
NtCurrentThread(),
TOKEN_QUERY,
TRUE, // OpenAsSelf
&TokenHandle
);
if (!NT_SUCCESS(Status))
{
if (Status != STATUS_NO_TOKEN)
{
return Status;
}
if (LsaDsStateInfo.DsInitializedAndRunning)
{
Status = I_RpcMapWin32Status(ImpersonateAnyClient());
}
else
{
Status = I_RpcMapWin32Status(RpcImpersonateClient(NULL));
}
if (Status == RPC_NT_CANNOT_SUPPORT)
{
Status = NtImpersonateAnonymousToken(NtCurrentThread());
bImpersonatingAnonymous = TRUE;
}
if (NT_SUCCESS(Status))
{
NTSTATUS DbgStatus;
Status = NtOpenThreadToken(
NtCurrentThread(),
TOKEN_QUERY,
TRUE, // OpenAsSelf
&TokenHandle
);
if (bImpersonatingAnonymous)
{
HANDLE NewTokenHandle = NULL;
DbgStatus = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
(PVOID)&NewTokenHandle,
(ULONG)sizeof(HANDLE)
);
ASSERT(NT_SUCCESS(DbgStatus));
}
else
{
if (LsaDsStateInfo.DsInitializedAndRunning)
{
UnImpersonateAnyClient();
}
else
{
DbgStatus = I_RpcMapWin32Status(RpcRevertToSelf());
ASSERT(NT_SUCCESS(DbgStatus));
}
}
if (!NT_SUCCESS(Status))
{
return Status;
}
}
else if (Status == RPC_NT_NO_CALL_ACTIVE)
{
Status = NtOpenProcessToken(
NtCurrentProcess(),
TOKEN_QUERY,
&TokenHandle
);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
else
{
return Status;
}
}
Status = NtQueryInformationToken(
TokenHandle,
TokenUser,
NULL,
0,
&ReturnLength
);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
NtClose(TokenHandle);
return Status;
}
*UserSid = LsapAllocateLsaHeap(ReturnLength);
if (*UserSid == NULL)
{
NtClose(TokenHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = NtQueryInformationToken(
TokenHandle,
TokenUser,
*UserSid,
ReturnLength,
&ReturnLength
);
if (!NT_SUCCESS(Status))
{
NtClose(TokenHandle);
LsapFreeLsaHeap(*UserSid);
*UserSid = NULL;
return Status;
}
Status = NtQueryInformationToken(
TokenHandle,
TokenStatistics,
(PVOID)&TokenStats,
sizeof(TOKEN_STATISTICS),
&ReturnLength
);
NtClose(TokenHandle);
if (!NT_SUCCESS(Status))
{
LsapFreeLsaHeap(*UserSid);
*UserSid = NULL;
return Status;
}
*AuthenticationId = TokenStats.AuthenticationId;
return STATUS_SUCCESS;
}
BOOL
LsapIsLocalOrNetworkService(
IN PUNICODE_STRING pUserName,
IN PUNICODE_STRING pUserDomain
)
/*++
Routine Description:
This routine checks to see if the passed account name represents
a local or network service
Arguments:
pUserName - unicode user name
pUserDomain - unicode domain name
Return Value:
TRUE if the passed account name represents a local or network service
FALSE otherwise
--*/
{
#define LOCALSERVICE_NAME L"LocalService"
#define NETWORKSERVICE_NAME L"NetworkService"
#define NTAUTHORITY_NAME L"NT AUTHORITY"
static UNICODE_STRING LocalServiceName = { sizeof(LOCALSERVICE_NAME) - sizeof(WCHAR),
sizeof(LOCALSERVICE_NAME),
LOCALSERVICE_NAME };
static UNICODE_STRING NetworkServiceName = { sizeof(NETWORKSERVICE_NAME) - sizeof(WCHAR),
sizeof(NETWORKSERVICE_NAME),
NETWORKSERVICE_NAME };
static UNICODE_STRING NTAuthorityName = { sizeof(NTAUTHORITY_NAME) - sizeof(WCHAR),
sizeof(NTAUTHORITY_NAME),
NTAUTHORITY_NAME };
PUNICODE_STRING pLocalServiceName;
PUNICODE_STRING pNetworkServiceName;
PUNICODE_STRING pLocalDomainName;
if ( !pUserName || !pUserDomain )
{
return FALSE;
}
//
// Hardcoded english strings for LocalService and NetworkService
// since the account names may come from the registry (which isn't
// localized).
//
pLocalDomainName = &WellKnownSids[LsapLocalServiceSidIndex].DomainName;
pNetworkServiceName = &WellKnownSids[LsapNetworkServiceSidIndex].Name;
pLocalServiceName = &WellKnownSids[LsapLocalServiceSidIndex].Name;
//
// check both hardcode and localized names
//
if (((RtlCompareUnicodeString(&NTAuthorityName, pUserDomain, TRUE) == 0) &&
((RtlCompareUnicodeString(&LocalServiceName, pUserName, TRUE) == 0) ||
(RtlCompareUnicodeString(&NetworkServiceName, pUserName, TRUE) == 0))) ||
((RtlCompareUnicodeString(pLocalDomainName, pUserDomain, TRUE) == 0) &&
((RtlCompareUnicodeString(pLocalServiceName, pUserName, TRUE) == 0) ||
(RtlCompareUnicodeString(pNetworkServiceName, pUserName, TRUE) == 0))))
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL
LsapIsAnonymous(
IN PUNICODE_STRING pUserName,
IN PUNICODE_STRING pUserDomain
)
/*++
Routine Description:
This routine checks to see if the passed account name represents
an anonymous logon.
Arguments:
pUserName - unicode user name
pUserDomain - unicode domain name
Return Value:
TRUE if the passed account name represents the anonymous logon.
FALSE otherwise
--*/
{
#define ANONYMOUS_NAME L"ANONYMOUS LOGON"
#define NTAUTHORITY_NAME L"NT AUTHORITY"
static UNICODE_STRING AnonymousName = { sizeof(ANONYMOUS_NAME) - sizeof(WCHAR),
sizeof(ANONYMOUS_NAME),
ANONYMOUS_NAME };
static UNICODE_STRING NTAuthorityName = { sizeof(NTAUTHORITY_NAME) - sizeof(WCHAR),
sizeof(NTAUTHORITY_NAME),
NTAUTHORITY_NAME };
PUNICODE_STRING pLocalDomainName = &WellKnownSids[LsapLocalServiceSidIndex].DomainName;
PUNICODE_STRING pAnonymousName = &WellKnownSids[LsapAnonymousSidIndex].Name;
if ( !pUserName || !pUserDomain )
{
return FALSE;
}
//
// check both hardcode and localized names
//
if (((RtlCompareUnicodeString(&NTAuthorityName, pUserDomain, TRUE) == 0) &&
(RtlCompareUnicodeString(&AnonymousName, pUserName, TRUE) == 0)) ||
((RtlCompareUnicodeString(pLocalDomainName, pUserDomain, TRUE) == 0) &&
(RtlCompareUnicodeString(pAnonymousName, pUserName, TRUE) == 0)))
{
return TRUE;
}
return FALSE;
}