windows-nt/Source/XPSP1/NT/ds/security/dsrole/server/netname.c

335 lines
8.3 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
netname.c
Abstract:
Miscellaneous network naming helper functions
Author:
Mac McLain (MacM) Oct 16, 1997
Environment:
User Mode
Revision History:
--*/
#include <setpch.h>
#include <dssetp.h>
#include <lmcons.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <lmerr.h>
#include <lmjoin.h>
#include <netsetup.h>
#include <lsarpc.h>
#include <db.h>
#include <lsasrvmm.h>
#include <lsaisrv.h>
#include <dns.h>
#include <dnsapi.h>
#define MAX_NAME_ATTEMPTS 260
DWORD
WINAPI
DsRolepDnsNameToFlatName(
IN LPWSTR DnsName,
OUT LPWSTR *FlatName,
OUT PULONG StatusFlag
)
/*++
Routine Description:
Determines the suggested netbios domain name for the given dns name
Arguments:
DnsName - The Dns domain name to generate a flat name for
FlatName - Where the flat name is to be returned
StatusFlag - Where the status is returned
Returns:
STATUS_SUCCESS - Success
--*/
{
DWORD Win32Error = ERROR_SUCCESS;
NTSTATUS Status;
PPOLICY_DNS_DOMAIN_INFO DnsDomainInfo = NULL;
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo;
BOOLEAN FindFromDns = TRUE;
WCHAR NbDomainName[ DNLEN + 1], NbNameAdd[ 4 ];
PWSTR Current = NULL;
WCHAR BaseChar;
ULONG CurrentAttempt = 0;
ULONG i,j;
*StatusFlag = 0;
DsRolepLogPrint(( DEB_TRACE,
"Getting NetBIOS name for Dns name %ws\n",
DnsName ));
//
// First, see if we are part of domain currently or not. If we are, then it's a simple
// matter of returning the current Netbios domain name.
//
Status = LsaIQueryInformationPolicyTrusted(
PolicyAccountDomainInformation,
( PLSAPR_POLICY_INFORMATION * )&AccountDomainInfo );
if ( NT_SUCCESS( Status ) ) {
Status = LsaIQueryInformationPolicyTrusted(
PolicyDnsDomainInformation,
( PLSAPR_POLICY_INFORMATION * )&DnsDomainInfo );
if ( !NT_SUCCESS( Status ) ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyAccountDomainInformation,
( PLSAPR_POLICY_INFORMATION )AccountDomainInfo );
}
}
if ( NT_SUCCESS( Status ) ) {
if ( DnsDomainInfo->Sid == NULL || AccountDomainInfo->DomainSid == NULL ||
!RtlEqualSid( AccountDomainInfo->DomainSid, DnsDomainInfo->Sid ) ) {
//
// We're not a member of the domain
//
FindFromDns = TRUE;
} else {
//
// We are a domain member
//
WCHAR *BufDomainName = NULL;
BufDomainName = (WCHAR*)malloc(DnsDomainInfo->Name.Length+sizeof(WCHAR));
if (BufDomainName) {
CopyMemory(BufDomainName,DnsDomainInfo->Name.Buffer,DnsDomainInfo->Name.Length);
BufDomainName[DnsDomainInfo->Name.Length/sizeof(WCHAR)] = L'\0';
DsRolepLogPrint(( DEB_TRACE,
"Using existing NetBIOS domain name %ws\n",
BufDomainName ));
free(BufDomainName);
}
*FlatName = MIDL_user_allocate(
( DnsDomainInfo->Name.Length + 1 ) * sizeof( WCHAR ) );
if ( *FlatName == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RtlCopyMemory( *FlatName, DnsDomainInfo->Name.Buffer,
DnsDomainInfo->Name.Length );
( *FlatName )[DnsDomainInfo->Name.Length / sizeof( WCHAR )] = UNICODE_NULL;
*StatusFlag = DSROLE_FLATNAME_UPGRADE;
*StatusFlag |= DSROLE_FLATNAME_DEFAULT;
FindFromDns = FALSE;
}
}
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyAccountDomainInformation,
( PLSAPR_POLICY_INFORMATION )AccountDomainInfo );
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyDnsDomainInformation,
( PLSAPR_POLICY_INFORMATION )DnsDomainInfo );
}
//
// If there was no domain name defined, we'll have to get one from the dns name
//
if ( Win32Error == ERROR_SUCCESS && FindFromDns ) {
//
// Ok, to start with, pull off the first DNLEN characters from the DNS name
//
RtlZeroMemory(NbDomainName, sizeof(WCHAR)*(DNLEN+1) );
wcsncpy( NbDomainName, DnsName, DNLEN );
Current = wcschr( NbDomainName, L'.' );
if ( Current ) {
*Current = UNICODE_NULL;
}
//
// See if the name is currently in use or not
//
DsRolepLogPrint(( DEB_TRACE,
"Testing default NetBIOS name %ws\n",
NbDomainName ));
Win32Error = NetpValidateName( NULL,
NbDomainName,
NULL,
NULL,
NetSetupNonExistentDomain );
if ( Win32Error == ERROR_SUCCESS ) {
*StatusFlag = DSROLE_FLATNAME_DEFAULT;
} else if ( Win32Error == ERROR_DUP_NAME ) {
//
// Position on the last character in the name
//
Current = NbDomainName + wcslen( NbDomainName ) - 1;
ASSERT(Current <= (NbDomainName + DNLEN - 1));
//
// If our name is less than the max. Set our current next to the last character
//
if ( (NbDomainName + DNLEN - 1) != Current ) {
Current++;
*( Current + 1 ) = UNICODE_NULL;
}
while ( CurrentAttempt < MAX_NAME_ATTEMPTS ) {
_ultow( CurrentAttempt, NbNameAdd, 10 );
ASSERT( wcslen( NbNameAdd ) < 4 );
//
// See if we need to adjust the position of where we copy
//
if ( CurrentAttempt == 10 || CurrentAttempt == 100 ) {
if ( (NbDomainName + DNLEN) < (Current + wcslen(NbNameAdd)) ) {
Current--;
}
}
wcscpy( Current, NbNameAdd );
DsRolepLogPrint(( DEB_TRACE,
"Testing default NetBIOS name %ws\n",
NbDomainName ));
Win32Error = NetpValidateName( NULL,
NbDomainName,
NULL,
NULL,
NetSetupNonExistentDomain );
//
// If we've found a name that is in use, try again
//
if ( Win32Error != ERROR_DUP_NAME ) {
break;
}
CurrentAttempt++;
}
}
//
// If we found a valid name, return it
//
if ( Win32Error == ERROR_SUCCESS ) {
*FlatName = MIDL_user_allocate( ( wcslen( NbDomainName ) + 1 ) * sizeof( WCHAR ) );
if ( *FlatName == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
wcscpy( *FlatName, NbDomainName );
DsRolepLogPrint(( DEB_TRACE,
"Found usable NetBIOS domain name %ws\n",
NbDomainName ));
}
}
}
return( Win32Error );
}
DWORD
DsRolepIsDnsNameChild(
IN LPWSTR ParentDnsName,
IN LPWSTR ChildDnsName
)
/*++
Routine Description:
Determines whether the child dns domain name is indeed a child of the parent. This means
that the only difference between the names is the left most component of the child dns name.
Arguments:
ParentDnsName - The Dns domain name of the parent
ChildDnsName - The Dns name of the childe .
Returns:
STATUS_SUCCESS - Success
ERROR_INVALID_DOMAINNAME - The child dns name is not a child of the parent dns name
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
PWSTR Sep = wcschr( ChildDnsName, L'.' );
if ( Sep == NULL || !DnsNameCompare_W( Sep + 1, ParentDnsName ) ) {
Win32Err = ERROR_INVALID_DOMAINNAME;
}
return( Win32Err );
}