Source code of Windows XP (NT5)
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.

481 lines
10 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. rpcbind.c
  5. Abstract:
  6. Domain Name System (DNS) Server -- Admin Client API
  7. RPC binding routines for client.
  8. Author:
  9. Jim Gilroy (jamesg) September 1995
  10. Environment:
  11. User Mode Win32
  12. Revision History:
  13. --*/
  14. #include "dnsclip.h"
  15. #include <rpcutil.h>
  16. //
  17. // Local machine name
  18. //
  19. // Keep this as static data to check when attempt to access local
  20. // machine by name.
  21. // Buffer is large enough to hold unicode version of name.
  22. //
  23. static WCHAR wszLocalMachineName[MAX_COMPUTERNAME_LENGTH + 1] = L"";
  24. LPWSTR pwszLocalMachineName = wszLocalMachineName;
  25. LPSTR pszLocalMachineName = (LPSTR) wszLocalMachineName;
  26. //
  27. // NT4 uses ANSI\UTF8 string for binding
  28. //
  29. DWORD
  30. FindProtocolToUseNt4(
  31. IN LPSTR pszServerName
  32. )
  33. /*++
  34. Routine Description:
  35. Determine which protocol to use.
  36. This is determined from server name:
  37. - noneexistent or local -> use LPC
  38. - valid IpAddress -> use TCP/IP
  39. - otherwise named pipes
  40. Arguments:
  41. pszServerName -- server name we want to bind to
  42. Return Value:
  43. DNS_RPC_USE_TCPIP
  44. DNS_RPC_USE_NP
  45. DNS_RPC_USE_LPC
  46. --*/
  47. {
  48. DWORD dwComputerNameLength;
  49. DWORD dwIpAddress;
  50. DWORD status;
  51. DNSDBG( RPC, (
  52. "FindProtocolToUseNt4(%s)\n",
  53. pszServerName ));
  54. //
  55. // no address given, use LPC
  56. //
  57. if ( pszServerName == NULL ||
  58. *pszServerName == 0 ||
  59. (*pszServerName == '.' && *(pszServerName+1) == 0) )
  60. {
  61. return( DNS_RPC_USE_LPC );
  62. }
  63. //
  64. // if valid IP address, use TCP/IP
  65. // - except if loopback address, then use LPC
  66. //
  67. dwIpAddress = inet_addr( pszServerName );
  68. if ( dwIpAddress != INADDR_NONE )
  69. {
  70. if( strcmp( "127.0.0.1", pszServerName ) == 0 )
  71. {
  72. return( DNS_RPC_USE_LPC );
  73. }
  74. return( DNS_RPC_USE_TCPIP );
  75. }
  76. //
  77. // DNS name -- use TCP/IP
  78. //
  79. if ( strchr( pszServerName, '.' ) )
  80. {
  81. status = Dns_ValidateName_UTF8(
  82. pszServerName,
  83. DnsNameHostnameFull );
  84. if ( status == ERROR_SUCCESS || status == DNS_ERROR_NON_RFC_NAME )
  85. {
  86. return( DNS_RPC_USE_TCPIP );
  87. }
  88. }
  89. //
  90. // pszServerName is netBIOS computer name
  91. //
  92. // check if local machine name -- then use LPC
  93. // - save copy of local computer name if don't have it
  94. //
  95. if ( *pszLocalMachineName == '\0' )
  96. {
  97. dwComputerNameLength = MAX_COMPUTERNAME_LENGTH;
  98. if( ! GetComputerName(
  99. pszLocalMachineName,
  100. &dwComputerNameLength ) )
  101. {
  102. *pszLocalMachineName = '\0';
  103. }
  104. }
  105. if ( (*pszLocalMachineName != '\0') )
  106. {
  107. // if the machine has "\\" skip it for name compare.
  108. if ( *pszServerName == '\\' )
  109. {
  110. pszServerName += 2;
  111. }
  112. if ( _stricmp(pszLocalMachineName, pszServerName) == 0 )
  113. {
  114. return( DNS_RPC_USE_LPC );
  115. }
  116. if ( _stricmp( "localhost", pszServerName) == 0 )
  117. {
  118. return( DNS_RPC_USE_LPC );
  119. }
  120. }
  121. //
  122. // remote machine name -- use named pipes
  123. //
  124. return( DNS_RPC_USE_NAMED_PIPE );
  125. }
  126. //
  127. // NT5 binding handle is unicode
  128. //
  129. DWORD
  130. FindProtocolToUse(
  131. IN LPWSTR pwszServerName
  132. )
  133. /*++
  134. Routine Description:
  135. Determine which protocol to use.
  136. This is determined from server name:
  137. - noneexistent or local -> use LPC
  138. - valid IpAddress -> use TCP/IP
  139. - otherwise named pipes
  140. Arguments:
  141. pwszServerName -- server name we want to bind to
  142. Return Value:
  143. DNS_RPC_USE_TCPIP
  144. DNS_RPC_USE_NP
  145. DNS_RPC_USE_LPC
  146. --*/
  147. {
  148. DWORD nameLength;
  149. DWORD ipaddr;
  150. DWORD status;
  151. CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  152. DNSDBG( RPC, (
  153. "FindProtocolToUse(%S)\n",
  154. pwszServerName ));
  155. //
  156. // no address given, use LPC
  157. // special case "." as local machine for convenience in dnscmd.exe
  158. //
  159. if ( pwszServerName == NULL ||
  160. *pwszServerName == 0 ||
  161. (*pwszServerName == L'.' && *(pwszServerName+1) == 0) )
  162. {
  163. return( DNS_RPC_USE_LPC );
  164. }
  165. //
  166. // use TCP/IP?
  167. // => possibile if
  168. // - name has dot
  169. // - converts into max size DNS name buffer
  170. // => check for
  171. // - IP address
  172. // - then check if DNS name
  173. //
  174. if ( wcschr( pwszServerName, L'.' )
  175. &&
  176. Dns_UnicodeToUtf8(
  177. pwszServerName,
  178. wcslen( pwszServerName ),
  179. nameBuffer,
  180. DNS_MAX_NAME_BUFFER_LENGTH ) )
  181. {
  182. ipaddr = inet_addr( nameBuffer );
  183. if ( ipaddr != INADDR_NONE )
  184. {
  185. if( strcmp( "127.0.0.1", nameBuffer ) == 0 )
  186. {
  187. return( DNS_RPC_USE_LPC );
  188. }
  189. return( DNS_RPC_USE_TCPIP );
  190. }
  191. status = Dns_ValidateName_UTF8(
  192. nameBuffer,
  193. DnsNameHostnameFull );
  194. if ( status == ERROR_SUCCESS || status == DNS_ERROR_NON_RFC_NAME )
  195. {
  196. return( DNS_RPC_USE_TCPIP );
  197. }
  198. }
  199. //
  200. // pwszServerName is netBIOS computer name
  201. //
  202. // check if local machine name -- then use LPC
  203. // - save copy of local computer name if don't have it
  204. //
  205. if ( *pwszLocalMachineName == 0 )
  206. {
  207. nameLength = MAX_COMPUTERNAME_LENGTH;
  208. if( ! GetComputerNameW(
  209. pwszLocalMachineName,
  210. &nameLength ) )
  211. {
  212. *pwszLocalMachineName = 0;
  213. }
  214. }
  215. if ( *pwszLocalMachineName != 0 )
  216. {
  217. // if the machine has "\\" skip it for name compare.
  218. if ( *pwszServerName == '\\' )
  219. {
  220. pwszServerName += 2;
  221. }
  222. if ( _wcsicmp( pwszLocalMachineName, pwszServerName) == 0 )
  223. {
  224. return( DNS_RPC_USE_LPC );
  225. }
  226. if ( _wcsicmp( L"localhost", pwszServerName) == 0 )
  227. {
  228. return( DNS_RPC_USE_LPC );
  229. }
  230. }
  231. //
  232. // remote machine name -- use named pipes
  233. //
  234. return( DNS_RPC_USE_NAMED_PIPE );
  235. }
  236. handle_t
  237. DNSSRV_RPC_HANDLE_bind(
  238. IN DNSSRV_RPC_HANDLE pszServerName
  239. )
  240. /*++
  241. Routine Description:
  242. Get binding handle to a DNS server.
  243. This routine is called from the DNS client stubs when
  244. it is necessary create an RPC binding to the DNS server.
  245. Arguments:
  246. pszServerName - String containing the name of the server to bind with.
  247. Return Value:
  248. The binding handle if successful.
  249. NULL if bind unsuccessful.
  250. --*/
  251. {
  252. RPC_STATUS status;
  253. LPWSTR binding;
  254. handle_t bindingHandle;
  255. DWORD RpcProtocol;
  256. PSEC_WINNT_AUTH_IDENTITY_W pAuth=NULL;
  257. //
  258. // determine protocol from pszServerName
  259. //
  260. RpcProtocol = FindProtocolToUse( (LPWSTR)pszServerName );
  261. IF_DNSDBG( RPC )
  262. {
  263. DNS_PRINT(( "RPC Protocol = %d.\n", RpcProtocol ));
  264. }
  265. if( RpcProtocol == DNS_RPC_USE_LPC )
  266. {
  267. status = RpcStringBindingComposeW(
  268. 0,
  269. L"ncalrpc",
  270. NULL,
  271. DNS_RPC_LPC_EP_W,
  272. // "Security=Impersonation Dynamic False",
  273. L"Security=Impersonation Static True",
  274. &binding );
  275. }
  276. else if( RpcProtocol == DNS_RPC_USE_NAMED_PIPE )
  277. {
  278. status = RpcStringBindingComposeW(
  279. 0,
  280. L"ncacn_np",
  281. (LPWSTR) pszServerName,
  282. DNS_RPC_NAMED_PIPE_W,
  283. L"Security=Impersonation Static True",
  284. &binding );
  285. }
  286. else
  287. {
  288. status = RpcStringBindingComposeW(
  289. 0,
  290. L"ncacn_ip_tcp",
  291. (LPWSTR) pszServerName,
  292. DNS_RPC_SERVER_PORT_W,
  293. NULL,
  294. &binding );
  295. }
  296. if ( status != RPC_S_OK )
  297. {
  298. DNS_PRINT((
  299. "ERROR: RpcStringBindingCompose failed for protocol %d.\n"
  300. "\tStatus = %d.\n",
  301. RpcProtocol,
  302. status ));
  303. goto Cleanup;
  304. }
  305. status = RpcBindingFromStringBindingW(
  306. binding,
  307. &bindingHandle );
  308. if ( status != RPC_S_OK )
  309. {
  310. DNS_PRINT((
  311. "ERROR: RpcBindingFromStringBinding failed.\n"
  312. "\tStatus = %d.\n",
  313. status ));
  314. goto Cleanup;
  315. }
  316. if( RpcProtocol == DNS_RPC_USE_TCPIP )
  317. {
  318. //
  319. // Tell RPC to do the security thing.
  320. //
  321. status = RpcBindingSetAuthInfoA(
  322. bindingHandle, // binding handle
  323. DNS_RPC_SECURITY, // app name to security provider
  324. RPC_C_AUTHN_LEVEL_CONNECT, // auth level
  325. DNS_RPC_SECURITY_AUTH_ID, // Auth package ID
  326. pAuth, // client auth info, NULL specified logon info.
  327. RPC_C_AUTHZ_NAME );
  328. if ( status != RPC_S_OK )
  329. {
  330. DNS_PRINT((
  331. "ERROR: RpcBindingSetAuthInfo failed.\n"
  332. "\tStatus = %d.\n",
  333. status ));
  334. goto Cleanup;
  335. }
  336. }
  337. Cleanup:
  338. RpcStringFreeW( &binding );
  339. if ( status != RPC_S_OK )
  340. {
  341. SetLastError( status );
  342. return( NULL );
  343. }
  344. return bindingHandle;
  345. }
  346. void
  347. DNSSRV_RPC_HANDLE_unbind(
  348. IN DNSSRV_RPC_HANDLE pszServerName,
  349. IN handle_t BindHandle
  350. )
  351. /*++
  352. Routine Description:
  353. Unbind from DNS server.
  354. Called from the DNS client stubs when it is necessary to unbind
  355. from a server.
  356. Arguments:
  357. pszServerName - This is the name of the server from which to unbind.
  358. BindingHandle - This is the binding handle that is to be closed.
  359. Return Value:
  360. None.
  361. --*/
  362. {
  363. UNREFERENCED_PARAMETER(pszServerName);
  364. DNSDBG( RPC, ( "RpcBindingFree()\n" ));
  365. RpcBindingFree( &BindHandle );
  366. }
  367. //
  368. // End rpcbind.c
  369. //