Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

551 lines
13 KiB

//+----------------------------------------------------------------------------
//
// Copyright (C) 1996, Microsoft Corporation
//
// File: domain.c
//
// Contents: Code to figure out domain dfs addresses
//
// Classes: None
//
// Functions: I_NetDfsIsThisADomainName
//
// DfspInitDomainList
// DfspInitDomainListFromRegistry
// DfspInitDomainListFromLSA
// DfspInsertLsaDomainList
//
// History: Feb 7, 1996 Milans created
//
//-----------------------------------------------------------------------------
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntlsa.h> // LsaEnumerateTrustedDomains
#include <windows.h>
#include <lm.h> // NetWkstaGetInfo
#include <netdfs.h>
#include "domain.h"
//
// Global structure describing list of trusted domains
//
static struct {
ULONG cDomains;
UNICODE_STRING ustrThisDomain;
PUNICODE_STRING rgustrDomains;
ULONG cbNameBuffer;
PWSTR wszNameBuffer;
} DfsDomainInfo;
static BOOL DomainListInited = FALSE;
//
// Key and value name for trusted domain list in the registry. These are only
// available on non-DC machines.
//
#define REG_KEY_TRUSTED_DOMAINS \
L"SYSTEM\\CurrentControlSet\\Services\\NetLogon\\Parameters"
#define REG_VALUE_TRUSTED_DOMAINS \
L"TrustedDomainList"
//
// Private functions
//
VOID
DfspInitDomainList();
DWORD
DfspInitDomainListFromRegistry(
IN HKEY hkey);
DWORD
DfspInitDomainListFromLSA();
NTSTATUS
DfspInsertLsaDomainList(
PLSA_TRUST_INFORMATION rglsaDomainList,
ULONG cDomains);
//+----------------------------------------------------------------------------
//
// Function: I_NetDfsIsThisADomainName
//
// Synopsis: Runs down the list of domains in DfsDomainInfo and tries
// to match the given name with one of the entries in the list.
//
// Arguments: [wszName] -- Name to find in DfsDomainInfo
//
// Returns: [ERROR_SUCCESS] -- Name is indeed a domain name.
//
// [ERROR_FILE_NOT_FOUND] -- Name is not in the DfsDomainInfo
// list.
//
//-----------------------------------------------------------------------------
DWORD
I_NetDfsIsThisADomainName(
LPWSTR wszName)
{
USHORT cbLength, i;
BOOLEAN fFound = FALSE;
if (!DomainListInited)
DfspInitDomainList();
if (!DomainListInited)
return( ERROR_FILE_NOT_FOUND );
cbLength = wcslen( wszName ) * sizeof(WCHAR);
if (cbLength == DfsDomainInfo.ustrThisDomain.Length) {
fFound = (_wcsnicmp(
wszName,
DfsDomainInfo.ustrThisDomain.Buffer,
DfsDomainInfo.ustrThisDomain.Length) == 0);
}
for (i = 0; i < DfsDomainInfo.cDomains && !fFound; i++) {
if (cbLength == DfsDomainInfo.rgustrDomains[i].Length) {
fFound = (_wcsnicmp(
wszName,
DfsDomainInfo.rgustrDomains[i].Buffer,
cbLength) == 0);
}
}
return( fFound ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND );
}
//+----------------------------------------------------------------------------
//
// Function: DfspInitDomainList
//
// Synopsis: Initializes the list of trusted domains so that their Dfs's
// may be accessed.
//
// Arguments: None
//
// Returns: Nothing.
//
//-----------------------------------------------------------------------------
VOID
DfspInitDomainList()
{
PWKSTA_INFO_100 wki100;
DWORD dwErr;
HKEY hkey;
ZeroMemory( &DfsDomainInfo, sizeof(DfsDomainInfo) );
//
// Get our own domain name
//
dwErr = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wki100 );
if (dwErr == ERROR_SUCCESS) {
if (wki100->wki100_langroup != NULL) {
DfsDomainInfo.ustrThisDomain.Length =
wcslen(wki100->wki100_langroup) * sizeof(WCHAR);
DfsDomainInfo.ustrThisDomain.MaximumLength =
DfsDomainInfo.ustrThisDomain.Length + sizeof(UNICODE_NULL);
DfsDomainInfo.ustrThisDomain.Buffer = (LPWSTR)
MIDL_user_allocate( DfsDomainInfo.ustrThisDomain.MaximumLength );
if (DfsDomainInfo.ustrThisDomain.Buffer != NULL) {
wcscpy(
DfsDomainInfo.ustrThisDomain.Buffer,
wki100->wki100_langroup);
}
}
NetApiBufferFree( wki100 );
}
//
// Next try to open the trusted domain list in the registry...
//
if (dwErr == ERROR_SUCCESS) {
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_TRUSTED_DOMAINS, &hkey);
if (dwErr == ERROR_SUCCESS) {
dwErr = DfspInitDomainListFromRegistry( hkey );
RegCloseKey( hkey );
}
//
// If either the key was not found, or DfspInitDomainListFromRegistry
// returned ERROR_FILE_NOT_FOUND, try to initialize the list from the
// LSA.
//
if (dwErr == ERROR_FILE_NOT_FOUND) {
dwErr = DfspInitDomainListFromLSA();
}
}
if (dwErr == ERROR_SUCCESS) {
DomainListInited = TRUE;
} else {
if (DfsDomainInfo.ustrThisDomain.Buffer != NULL)
MIDL_user_free( DfsDomainInfo.ustrThisDomain.Buffer );
if (DfsDomainInfo.rgustrDomains != NULL)
MIDL_user_free( DfsDomainInfo.rgustrDomains );
if (DfsDomainInfo.wszNameBuffer != NULL)
MIDL_user_free( DfsDomainInfo.wszNameBuffer );
}
}
//+----------------------------------------------------------------------------
//
// Function: DfspInitDomainListFromRegistry
//
// Synopsis: Reads the trusted domain list from the registry.
//
// Arguments: [hkey] -- Handle to the key that contains the
// TrustedDomainList value.
//
// Returns: [ERROR_SUCCESS] -- Successfully read in the list
//
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate memory for
// list.
//
// [ERROR_FILE_NOT_FOUND] -- Unable to find the
// TrustedDomainList value in the registry.
//
//-----------------------------------------------------------------------------
DWORD
DfspInitDomainListFromRegistry(
IN HKEY hkey)
{
DWORD dwErr, dwType, cbSize;
PBYTE pBuffer = NULL;
cbSize = 1024;
do {
if (pBuffer)
MIDL_user_free( pBuffer );
pBuffer = (PBYTE) MIDL_user_allocate( cbSize );
if (pBuffer != NULL) {
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_TRUSTED_DOMAINS,
NULL,
&dwType,
pBuffer,
&cbSize);
} else {
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
} while ( dwErr == ERROR_MORE_DATA );
if (dwErr == ERROR_SUCCESS) {
//
// Good, we have the data. Now, we simply have to put them in the
// rgustrDomains list. The returned buffer contains a list of
// NULL terminated domain names, with the last one doubly NULL
// terminated.
//
PWCHAR pwch = (PWCHAR) pBuffer;
while (*pwch != UNICODE_NULL) {
if (*(pwch+1) == UNICODE_NULL) {
DfsDomainInfo.cDomains++;
pwch++;
}
pwch++;
}
DfsDomainInfo.rgustrDomains = (PUNICODE_STRING) MIDL_user_allocate(
DfsDomainInfo.cDomains *
sizeof(UNICODE_STRING));
if (DfsDomainInfo.rgustrDomains != NULL) {
ULONG i;
DfsDomainInfo.wszNameBuffer = (LPWSTR) pBuffer;
DfsDomainInfo.cbNameBuffer = cbSize;
for (i = 0, pwch = (PWCHAR) pBuffer;
i < DfsDomainInfo.cDomains;
i++) {
RtlInitUnicodeString(
&DfsDomainInfo.rgustrDomains[i],
pwch);
pwch += (DfsDomainInfo.rgustrDomains[i].Length +
sizeof(UNICODE_NULL)) / sizeof(WCHAR);
}
} else {
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
}
if ((dwErr != ERROR_SUCCESS) && (pBuffer != NULL))
MIDL_user_free( pBuffer );
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspInitDomainListFromLSA
//
// Synopsis: Retrieves the list of trusted domains from the LSA.
//
// Arguments: None
//
// Returns: [ERROR_SUCCESS] -- Successfully inited list.
//
// [ERROR_NOT_ENOUGH_MEMORY] -- Out of memory condition
//
//-----------------------------------------------------------------------------
DWORD
DfspInitDomainListFromLSA()
{
DWORD dwErr;
NTSTATUS status;
OBJECT_ATTRIBUTES oa;
LSA_HANDLE hlsa;
LSA_ENUMERATION_HANDLE hEnum = (LSA_ENUMERATION_HANDLE) NULL;
PLSA_TRUST_INFORMATION rglsaDomainInfo = NULL;
ZeroMemory( &oa, sizeof(OBJECT_ATTRIBUTES) );
status = LsaOpenPolicy(
NULL, // SystemName
&oa, // LSA Object Attributes
POLICY_VIEW_LOCAL_INFORMATION, // Desired Access
&hlsa);
if (NT_SUCCESS(status)) {
do {
ULONG cEnum;
status = LsaEnumerateTrustedDomains(
hlsa,
&hEnum,
(PVOID) &rglsaDomainInfo,
LSA_MAXIMUM_ENUMERATION_LENGTH,
&cEnum);
if (NT_SUCCESS(status)) {
status = DfspInsertLsaDomainList(
rglsaDomainInfo,
cEnum);
LsaFreeReturnBuffer( rglsaDomainInfo );
}
} while ( status == STATUS_SUCCESS );
}
switch (status) {
case STATUS_SUCCESS:
case STATUS_NO_MORE_ENTRIES:
dwErr = ERROR_SUCCESS;
break;
case STATUS_INSUFFICIENT_RESOURCES:
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
default:
dwErr = ERROR_UNEXP_NET_ERR;
break;
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspInsertLsaDomainList
//
// Synopsis: Helper function to insert a part of the trusted domain list
// into the DfsDomainInfo.
//
// Arguments: [rglsaDomainList] -- Array of LSA_TRUST_INFORMATIONs.
// [cDomains] -- Number of elements in rglsaDomainList
//
// Returns: [STATUS_SUCCESS] -- Successfully appended domain list to
// DfsDomainInfo.
//
// [STATUS_INSUFFICIENT_RESOURCES] -- Unable to allocate memory
// for new list.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspInsertLsaDomainList(
PLSA_TRUST_INFORMATION rglsaDomainList,
ULONG cDomains)
{
PUNICODE_STRING rgustrDomains = NULL;
PWSTR wszNameBuffer = NULL, pwch;
ULONG cTotalDomains, cbNameBuffer, i, j;
cTotalDomains = DfsDomainInfo.cDomains + cDomains;
cbNameBuffer = DfsDomainInfo.cbNameBuffer;
for (i = 0; i < cDomains; i++) {
cbNameBuffer += rglsaDomainList[i].Name.Length + sizeof(UNICODE_NULL);
}
wszNameBuffer = (PWSTR) MIDL_user_allocate( cbNameBuffer );
if (wszNameBuffer == NULL) {
return( STATUS_INSUFFICIENT_RESOURCES );
}
rgustrDomains = (PUNICODE_STRING) MIDL_user_allocate(
cTotalDomains * sizeof(UNICODE_STRING));
if (rgustrDomains == NULL) {
MIDL_user_free( wszNameBuffer );
return( STATUS_INSUFFICIENT_RESOURCES );
}
//
// Copy over the existing DfsDomainInfo
//
if (DfsDomainInfo.cDomains != 0) {
CopyMemory(
wszNameBuffer,
DfsDomainInfo.wszNameBuffer,
DfsDomainInfo.cbNameBuffer);
CopyMemory(
rgustrDomains,
DfsDomainInfo.rgustrDomains,
DfsDomainInfo.cDomains * sizeof(UNICODE_STRING));
}
pwch = (PWSTR) (((PCHAR) wszNameBuffer) + DfsDomainInfo.cbNameBuffer);
for (j = 0, i = DfsDomainInfo.cDomains; j < cDomains; j++, i++) {
CopyMemory(
pwch,
rglsaDomainList[j].Name.Buffer,
rglsaDomainList[j].Name.Length);
pwch[ rglsaDomainList[j].Name.Length / sizeof(WCHAR) ] = UNICODE_NULL;
RtlInitUnicodeString(
&rgustrDomains[i],
pwch);
pwch += (rglsaDomainList[j].Name.Length / sizeof(WCHAR) + 1);
}
if (DfsDomainInfo.cDomains != 0) {
MIDL_user_free( DfsDomainInfo.rgustrDomains );
MIDL_user_free( DfsDomainInfo.wszNameBuffer );
}
DfsDomainInfo.cDomains = cTotalDomains;
DfsDomainInfo.rgustrDomains = rgustrDomains;
DfsDomainInfo.wszNameBuffer = wszNameBuffer;
DfsDomainInfo.cbNameBuffer = cbNameBuffer;
return( STATUS_SUCCESS );
}