482 lines
10 KiB
C
482 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1995-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rpcbind.c
|
||
|
||
Abstract:
|
||
|
||
Domain Name System (DNS) Server -- Admin Client API
|
||
|
||
RPC binding routines for client.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) September 1995
|
||
|
||
Environment:
|
||
|
||
User Mode Win32
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "dnsclip.h"
|
||
#include <rpcutil.h>
|
||
|
||
|
||
//
|
||
// Local machine name
|
||
//
|
||
// Keep this as static data to check when attempt to access local
|
||
// machine by name.
|
||
// Buffer is large enough to hold unicode version of name.
|
||
//
|
||
|
||
static WCHAR wszLocalMachineName[MAX_COMPUTERNAME_LENGTH + 1] = L"";
|
||
|
||
LPWSTR pwszLocalMachineName = wszLocalMachineName;
|
||
|
||
LPSTR pszLocalMachineName = (LPSTR) wszLocalMachineName;
|
||
|
||
|
||
|
||
//
|
||
// NT4 uses ANSI\UTF8 string for binding
|
||
//
|
||
|
||
DWORD
|
||
FindProtocolToUseNt4(
|
||
IN LPSTR pszServerName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determine which protocol to use.
|
||
|
||
This is determined from server name:
|
||
- noneexistent or local -> use LPC
|
||
- valid IpAddress -> use TCP/IP
|
||
- otherwise named pipes
|
||
|
||
Arguments:
|
||
|
||
pszServerName -- server name we want to bind to
|
||
|
||
Return Value:
|
||
|
||
DNS_RPC_USE_TCPIP
|
||
DNS_RPC_USE_NP
|
||
DNS_RPC_USE_LPC
|
||
|
||
--*/
|
||
{
|
||
DWORD dwComputerNameLength;
|
||
DWORD dwIpAddress;
|
||
DWORD status;
|
||
|
||
DNSDBG( RPC, (
|
||
"FindProtocolToUseNt4(%s)\n",
|
||
pszServerName ));
|
||
|
||
//
|
||
// no address given, use LPC
|
||
//
|
||
|
||
if ( pszServerName == NULL ||
|
||
*pszServerName == 0 ||
|
||
(*pszServerName == '.' && *(pszServerName+1) == 0) )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
|
||
//
|
||
// if valid IP address, use TCP/IP
|
||
// - except if loopback address, then use LPC
|
||
//
|
||
|
||
dwIpAddress = inet_addr( pszServerName );
|
||
|
||
if ( dwIpAddress != INADDR_NONE )
|
||
{
|
||
if( strcmp( "127.0.0.1", pszServerName ) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
return( DNS_RPC_USE_TCPIP );
|
||
}
|
||
|
||
//
|
||
// DNS name -- use TCP/IP
|
||
//
|
||
|
||
if ( strchr( pszServerName, '.' ) )
|
||
{
|
||
status = Dns_ValidateName_UTF8(
|
||
pszServerName,
|
||
DnsNameHostnameFull );
|
||
|
||
if ( status == ERROR_SUCCESS || status == DNS_ERROR_NON_RFC_NAME )
|
||
{
|
||
return( DNS_RPC_USE_TCPIP );
|
||
}
|
||
}
|
||
|
||
//
|
||
// pszServerName is netBIOS computer name
|
||
//
|
||
// check if local machine name -- then use LPC
|
||
// - save copy of local computer name if don't have it
|
||
//
|
||
|
||
if ( *pszLocalMachineName == '\0' )
|
||
{
|
||
dwComputerNameLength = MAX_COMPUTERNAME_LENGTH;
|
||
if( ! GetComputerName(
|
||
pszLocalMachineName,
|
||
&dwComputerNameLength ) )
|
||
{
|
||
*pszLocalMachineName = '\0';
|
||
}
|
||
}
|
||
|
||
if ( (*pszLocalMachineName != '\0') )
|
||
{
|
||
// if the machine has "\\" skip it for name compare.
|
||
|
||
if ( *pszServerName == '\\' )
|
||
{
|
||
pszServerName += 2;
|
||
}
|
||
if ( _stricmp(pszLocalMachineName, pszServerName) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
if ( _stricmp( "localhost", pszServerName) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
}
|
||
|
||
//
|
||
// remote machine name -- use named pipes
|
||
//
|
||
|
||
return( DNS_RPC_USE_NAMED_PIPE );
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// NT5 binding handle is unicode
|
||
//
|
||
|
||
DWORD
|
||
FindProtocolToUse(
|
||
IN LPWSTR pwszServerName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determine which protocol to use.
|
||
|
||
This is determined from server name:
|
||
- noneexistent or local -> use LPC
|
||
- valid IpAddress -> use TCP/IP
|
||
- otherwise named pipes
|
||
|
||
Arguments:
|
||
|
||
pwszServerName -- server name we want to bind to
|
||
|
||
Return Value:
|
||
|
||
DNS_RPC_USE_TCPIP
|
||
DNS_RPC_USE_NP
|
||
DNS_RPC_USE_LPC
|
||
|
||
--*/
|
||
{
|
||
DWORD nameLength;
|
||
DWORD ipaddr;
|
||
DWORD status;
|
||
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
||
|
||
|
||
DNSDBG( RPC, (
|
||
"FindProtocolToUse(%S)\n",
|
||
pwszServerName ));
|
||
|
||
//
|
||
// no address given, use LPC
|
||
// special case "." as local machine for convenience in dnscmd.exe
|
||
//
|
||
|
||
if ( pwszServerName == NULL ||
|
||
*pwszServerName == 0 ||
|
||
(*pwszServerName == L'.' && *(pwszServerName+1) == 0) )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
|
||
//
|
||
// use TCP/IP?
|
||
// => possibile if
|
||
// - name has dot
|
||
// - converts into max size DNS name buffer
|
||
// => check for
|
||
// - IP address
|
||
// - then check if DNS name
|
||
//
|
||
|
||
if ( wcschr( pwszServerName, L'.' )
|
||
&&
|
||
Dns_UnicodeToUtf8(
|
||
pwszServerName,
|
||
wcslen( pwszServerName ),
|
||
nameBuffer,
|
||
DNS_MAX_NAME_BUFFER_LENGTH ) )
|
||
{
|
||
ipaddr = inet_addr( nameBuffer );
|
||
|
||
if ( ipaddr != INADDR_NONE )
|
||
{
|
||
if( strcmp( "127.0.0.1", nameBuffer ) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
return( DNS_RPC_USE_TCPIP );
|
||
}
|
||
|
||
status = Dns_ValidateName_UTF8(
|
||
nameBuffer,
|
||
DnsNameHostnameFull );
|
||
|
||
if ( status == ERROR_SUCCESS || status == DNS_ERROR_NON_RFC_NAME )
|
||
{
|
||
return( DNS_RPC_USE_TCPIP );
|
||
}
|
||
}
|
||
|
||
//
|
||
// pwszServerName is netBIOS computer name
|
||
//
|
||
// check if local machine name -- then use LPC
|
||
// - save copy of local computer name if don't have it
|
||
//
|
||
|
||
if ( *pwszLocalMachineName == 0 )
|
||
{
|
||
nameLength = MAX_COMPUTERNAME_LENGTH;
|
||
if( ! GetComputerNameW(
|
||
pwszLocalMachineName,
|
||
&nameLength ) )
|
||
{
|
||
*pwszLocalMachineName = 0;
|
||
}
|
||
}
|
||
|
||
if ( *pwszLocalMachineName != 0 )
|
||
{
|
||
// if the machine has "\\" skip it for name compare.
|
||
|
||
if ( *pwszServerName == '\\' )
|
||
{
|
||
pwszServerName += 2;
|
||
}
|
||
if ( _wcsicmp( pwszLocalMachineName, pwszServerName) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
if ( _wcsicmp( L"localhost", pwszServerName) == 0 )
|
||
{
|
||
return( DNS_RPC_USE_LPC );
|
||
}
|
||
}
|
||
|
||
//
|
||
// remote machine name -- use named pipes
|
||
//
|
||
|
||
return( DNS_RPC_USE_NAMED_PIPE );
|
||
}
|
||
|
||
|
||
|
||
handle_t
|
||
DNSSRV_RPC_HANDLE_bind(
|
||
IN DNSSRV_RPC_HANDLE pszServerName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get binding handle to a DNS server.
|
||
|
||
This routine is called from the DNS client stubs when
|
||
it is necessary create an RPC binding to the DNS server.
|
||
|
||
Arguments:
|
||
|
||
pszServerName - String containing the name of the server to bind with.
|
||
|
||
Return Value:
|
||
|
||
The binding handle if successful.
|
||
NULL if bind unsuccessful.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS status;
|
||
LPWSTR binding;
|
||
handle_t bindingHandle;
|
||
DWORD RpcProtocol;
|
||
PSEC_WINNT_AUTH_IDENTITY_W pAuth=NULL;
|
||
|
||
//
|
||
// determine protocol from pszServerName
|
||
//
|
||
|
||
RpcProtocol = FindProtocolToUse( (LPWSTR)pszServerName );
|
||
|
||
IF_DNSDBG( RPC )
|
||
{
|
||
DNS_PRINT(( "RPC Protocol = %d.\n", RpcProtocol ));
|
||
}
|
||
|
||
if( RpcProtocol == DNS_RPC_USE_LPC )
|
||
{
|
||
status = RpcStringBindingComposeW(
|
||
0,
|
||
L"ncalrpc",
|
||
NULL,
|
||
DNS_RPC_LPC_EP_W,
|
||
// "Security=Impersonation Dynamic False",
|
||
L"Security=Impersonation Static True",
|
||
&binding );
|
||
}
|
||
else if( RpcProtocol == DNS_RPC_USE_NAMED_PIPE )
|
||
{
|
||
status = RpcStringBindingComposeW(
|
||
0,
|
||
L"ncacn_np",
|
||
(LPWSTR) pszServerName,
|
||
DNS_RPC_NAMED_PIPE_W,
|
||
L"Security=Impersonation Static True",
|
||
&binding );
|
||
}
|
||
else
|
||
{
|
||
status = RpcStringBindingComposeW(
|
||
0,
|
||
L"ncacn_ip_tcp",
|
||
(LPWSTR) pszServerName,
|
||
DNS_RPC_SERVER_PORT_W,
|
||
NULL,
|
||
&binding );
|
||
}
|
||
|
||
|
||
if ( status != RPC_S_OK )
|
||
{
|
||
DNS_PRINT((
|
||
"ERROR: RpcStringBindingCompose failed for protocol %d.\n"
|
||
"\tStatus = %d.\n",
|
||
RpcProtocol,
|
||
status ));
|
||
goto Cleanup;
|
||
}
|
||
|
||
status = RpcBindingFromStringBindingW(
|
||
binding,
|
||
&bindingHandle );
|
||
|
||
if ( status != RPC_S_OK )
|
||
{
|
||
DNS_PRINT((
|
||
"ERROR: RpcBindingFromStringBinding failed.\n"
|
||
"\tStatus = %d.\n",
|
||
status ));
|
||
goto Cleanup;
|
||
}
|
||
|
||
if( RpcProtocol == DNS_RPC_USE_TCPIP )
|
||
{
|
||
//
|
||
// Tell RPC to do the security thing.
|
||
//
|
||
|
||
status = RpcBindingSetAuthInfoA(
|
||
bindingHandle, // binding handle
|
||
DNS_RPC_SECURITY, // app name to security provider
|
||
RPC_C_AUTHN_LEVEL_CONNECT, // auth level
|
||
DNS_RPC_SECURITY_AUTH_ID, // Auth package ID
|
||
pAuth, // client auth info, NULL specified logon info.
|
||
RPC_C_AUTHZ_NAME );
|
||
|
||
if ( status != RPC_S_OK )
|
||
{
|
||
DNS_PRINT((
|
||
"ERROR: RpcBindingSetAuthInfo failed.\n"
|
||
"\tStatus = %d.\n",
|
||
status ));
|
||
goto Cleanup;
|
||
}
|
||
}
|
||
|
||
Cleanup:
|
||
|
||
RpcStringFreeW( &binding );
|
||
|
||
if ( status != RPC_S_OK )
|
||
{
|
||
SetLastError( status );
|
||
return( NULL );
|
||
}
|
||
return bindingHandle;
|
||
}
|
||
|
||
|
||
|
||
void
|
||
DNSSRV_RPC_HANDLE_unbind(
|
||
IN DNSSRV_RPC_HANDLE pszServerName,
|
||
IN handle_t BindHandle
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Unbind from DNS server.
|
||
|
||
Called from the DNS client stubs when it is necessary to unbind
|
||
from a server.
|
||
|
||
Arguments:
|
||
|
||
pszServerName - This is the name of the server from which to unbind.
|
||
|
||
BindingHandle - This is the binding handle that is to be closed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
UNREFERENCED_PARAMETER(pszServerName);
|
||
|
||
DNSDBG( RPC, ( "RpcBindingFree()\n" ));
|
||
|
||
RpcBindingFree( &BindHandle );
|
||
}
|
||
|
||
//
|
||
// End rpcbind.c
|
||
//
|