/*++ 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 // // 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 //