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.

566 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: rpc.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10-Nov-95 MarkBl Created.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include "debug.hxx"
  20. #if !defined(_CHICAGO_)
  21. #include "atsvc.h"
  22. #endif // !defined(_CHICAGO_)
  23. #include "SASecRPC.h"
  24. typedef HRESULT (* BindFunction)(LPWSTR, RPC_BINDING_HANDLE *);
  25. RPC_STATUS BindNetBIOSOverNetBEUI(LPWSTR, RPC_BINDING_HANDLE *);
  26. RPC_STATUS BindNetBIOSOverTCP(LPWSTR, RPC_BINDING_HANDLE *);
  27. RPC_STATUS BindNetBIOSOverIPX(LPWSTR, RPC_BINDING_HANDLE *);
  28. RPC_STATUS BindNamedPipe(LPWSTR, RPC_BINDING_HANDLE *);
  29. RPC_STATUS BindSPX(LPWSTR, RPC_BINDING_HANDLE *);
  30. RPC_STATUS BindTCPIP(LPWSTR, RPC_BINDING_HANDLE *);
  31. RPC_STATUS BindViaProtocol(LPTSTR , LPWSTR , RPC_BINDING_HANDLE * );
  32. extern "C" handle_t GenericBind(LPCWSTR, RPC_IF_HANDLE);
  33. extern "C" void GenericUnbind(LPCWSTR, RPC_BINDING_HANDLE);
  34. BindFunction grgProtocolBindFuncs[] = {
  35. BindNamedPipe,
  36. BindTCPIP,
  37. BindSPX,
  38. NULL
  39. };
  40. RPC_BINDING_HANDLE gRpcHandle = NULL;
  41. #if !defined(_CHICAGO_)
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Function: ATSVC_HANDLE_bind
  45. //
  46. // Synopsis: Called from RPC on auto bind.
  47. //
  48. // Arguments: [ServerName] -- Server to bind to.
  49. //
  50. // Returns: RPC_STATUS code
  51. //
  52. // Notes: None.
  53. //
  54. //----------------------------------------------------------------------------
  55. extern "C" handle_t
  56. ATSVC_HANDLE_bind(ATSVC_HANDLE ServerName)
  57. {
  58. return(GenericBind(ServerName, atsvc_ClientIfHandle));
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: ATSVC_HANDLE_unbind
  63. //
  64. // Synopsis: Unbind. Free the handle.
  65. //
  66. // Arguments: [ServerName] -- Unused.
  67. // [BindingHandle] -- Binding handle to free.
  68. //
  69. // Returns: RPC_STATUS code
  70. //
  71. // Notes: None.
  72. //
  73. //----------------------------------------------------------------------------
  74. extern "C" void
  75. ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, RPC_BINDING_HANDLE BindingHandle)
  76. {
  77. GenericUnbind(ServerName, BindingHandle);
  78. }
  79. #endif // !defined(_CHICAGO_)
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Function: SASEC_HANDLE_bind
  83. //
  84. // Synopsis: Called from RPC on auto bind.
  85. //
  86. // Arguments: [ServerName] -- Server to bind to.
  87. //
  88. // Returns: RPC_STATUS code
  89. //
  90. // Notes: None.
  91. //
  92. //----------------------------------------------------------------------------
  93. extern "C" handle_t
  94. SASEC_HANDLE_bind(SASEC_HANDLE ServerName)
  95. {
  96. RPC_BINDING_HANDLE BindingHandle;
  97. RPC_STATUS RpcStatus;
  98. if ((BindingHandle = GenericBind(ServerName,
  99. sasec_ClientIfHandle)) != NULL)
  100. {
  101. //
  102. // Set the connection to be authenticated and all arguments encrypted.
  103. //
  104. RpcStatus = RpcBindingSetAuthInfo(BindingHandle,
  105. NULL,
  106. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  107. RPC_C_AUTHN_WINNT,
  108. NULL,
  109. RPC_C_AUTHZ_NONE);
  110. //
  111. // Refuse the bind, if the requested authentication failed.
  112. //
  113. if (RpcStatus != RPC_S_OK)
  114. {
  115. GenericUnbind(ServerName, BindingHandle);
  116. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  117. return(NULL);
  118. }
  119. }
  120. return(BindingHandle);
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Function: SASEC_HANDLE_unbind
  125. //
  126. // Synopsis: Unbind. Free the handle.
  127. //
  128. // Arguments: [ServerName] -- Unused.
  129. // [BindingHandle] -- Binding handle to free.
  130. //
  131. // Returns: RPC_STATUS code
  132. //
  133. // Notes: None.
  134. //
  135. //----------------------------------------------------------------------------
  136. extern "C" void
  137. SASEC_HANDLE_unbind(SASEC_HANDLE ServerName, RPC_BINDING_HANDLE BindingHandle)
  138. {
  139. GenericUnbind(ServerName, BindingHandle);
  140. }
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Function: GenericBind
  144. //
  145. // Synopsis:
  146. //
  147. // Arguments: [ServerName] -- Server to bind to.
  148. // [ClientIfHandle] -- Specific interface.
  149. // Returns:
  150. //
  151. // Notes: None.
  152. //
  153. //----------------------------------------------------------------------------
  154. extern "C" handle_t
  155. GenericBind(LPCWSTR ServerName, RPC_IF_HANDLE ClientIfHandle)
  156. {
  157. RPC_BINDING_HANDLE BindingHandle = NULL;
  158. RPC_STATUS RpcStatus;
  159. //
  160. // If local, use LRPC. Otherwise, try multiple protocols.
  161. //
  162. if (ServerName == NULL)
  163. {
  164. RpcStatus = BindViaProtocol(TEXT("ncalrpc"), NULL, &BindingHandle);
  165. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  166. if (RpcStatus == RPC_S_OK)
  167. {
  168. RpcStatus = RpcEpResolveBinding(BindingHandle, ClientIfHandle);
  169. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  170. }
  171. }
  172. else
  173. {
  174. BindFunction pBindFunc;
  175. pBindFunc = grgProtocolBindFuncs[0];
  176. int i = 0;
  177. //
  178. // Iterate through the protocols until we find one that can connect.
  179. //
  180. do
  181. {
  182. RpcStatus = pBindFunc((LPWSTR)ServerName, &BindingHandle);
  183. if (RpcStatus == RPC_S_OK)
  184. {
  185. //
  186. // For the named pipes protocol, we use a static endpoint,
  187. // so the call to RpcEpResolveBinding is not needed.
  188. //
  189. // BUGBUG : review the above. Also, should we be specifying
  190. // authentication info?
  191. //
  192. if (pBindFunc != BindNamedPipe)
  193. {
  194. RpcStatus = RpcEpResolveBinding(BindingHandle,
  195. ClientIfHandle);
  196. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  197. }
  198. }
  199. else if (RpcStatus == RPC_S_PROTSEQ_NOT_SUPPORTED)
  200. {
  201. //
  202. // If the protocol is not on this computer, then rearrange
  203. // the list so it is not tried anymore.
  204. //
  205. CopyMemory(&grgProtocolBindFuncs[i],
  206. &grgProtocolBindFuncs[i + 1],
  207. sizeof(grgProtocolBindFuncs) -
  208. (&grgProtocolBindFuncs[i + 1] - &grgProtocolBindFuncs[0]));
  209. i--;
  210. }
  211. //
  212. // Try the next protocol's connection function.
  213. //
  214. if (RpcStatus != RPC_S_OK)
  215. {
  216. i++;
  217. pBindFunc = grgProtocolBindFuncs[i];
  218. }
  219. } while (!((RpcStatus == RPC_S_OK) || (pBindFunc == NULL)));
  220. }
  221. return(BindingHandle);
  222. }
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Function: GenericUnbind
  226. //
  227. // Synopsis:
  228. //
  229. // Arguments: [ServerName] -- Server to bind to.
  230. //
  231. // Returns:
  232. //
  233. // Notes: None.
  234. //
  235. //----------------------------------------------------------------------------
  236. extern "C" void
  237. GenericUnbind(LPCWSTR ServerName, RPC_BINDING_HANDLE BindingHandle)
  238. {
  239. UNREFERENCED_PARAMETER(ServerName);
  240. if (BindingHandle != NULL) {
  241. RPC_STATUS RpcStatus = RpcBindingFree(&BindingHandle);
  242. schAssert(RpcStatus == RPC_S_OK);
  243. }
  244. }
  245. //+---------------------------------------------------------------------------
  246. //
  247. // Function: BindingFromStringBinding
  248. //
  249. // Synopsis: Bind then free the string binding passed.
  250. //
  251. // Arguments: [StringBinding] -- Target string binding.
  252. // [pBindingHandle] -- Returned binding handle.
  253. //
  254. // Returns: RPC_STATUS code
  255. //
  256. // Notes: None.
  257. //
  258. //----------------------------------------------------------------------------
  259. RPC_STATUS
  260. BindingFromStringBinding(
  261. LPTSTR * StringBinding,
  262. RPC_BINDING_HANDLE * pBindingHandle)
  263. {
  264. RPC_STATUS RpcStatus;
  265. #if defined(UNICODE)
  266. RpcStatus = RpcBindingFromStringBinding(*StringBinding, pBindingHandle);
  267. RpcStringFree(StringBinding);
  268. #else
  269. RpcStatus = RpcBindingFromStringBinding((UCHAR *)*StringBinding,
  270. pBindingHandle);
  271. RpcStringFree((UCHAR **)StringBinding);
  272. #endif // defined(UNICODE)
  273. if (RpcStatus != RPC_S_OK)
  274. {
  275. *pBindingHandle = NULL;
  276. }
  277. return(RpcStatus);
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Function: BindViaProtocol
  282. //
  283. // Synopsis: Bind via the specified protocol.
  284. //
  285. // Arguments: [ServerName] -- Server name to bind to.
  286. // [pBindingHandle] -- Returned binding handle.
  287. //
  288. // Returns: RPC_STATUS code
  289. //
  290. // Notes: None.
  291. //
  292. //----------------------------------------------------------------------------
  293. RPC_STATUS
  294. BindViaProtocol(
  295. LPTSTR rpc_protocol,
  296. LPWSTR ServerName,
  297. RPC_BINDING_HANDLE * pBindingHandle)
  298. {
  299. TCHAR tszServerName[SA_MAX_COMPUTERNAME_LENGTH + 3]; // plus 3 for "\\" and NULL
  300. RPC_STATUS RpcStatus;
  301. LPTSTR StringBinding;
  302. LPTSTR PlainServerName;
  303. *pBindingHandle = NULL;
  304. schDebugOut((DEB_ITRACE,
  305. "Attempting RPC bind via protocol \"%ws\"\n",
  306. rpc_protocol));
  307. if (ServerName != NULL)
  308. {
  309. wcscpy(tszServerName, ServerName);
  310. }
  311. //
  312. // Ignore leading "\\"
  313. //
  314. if (ServerName != NULL && ServerName[0] == L'\\' &&
  315. ServerName[1] == L'\\')
  316. {
  317. PlainServerName = &tszServerName[2];
  318. }
  319. else
  320. {
  321. PlainServerName = ServerName != NULL ? tszServerName : NULL;
  322. }
  323. RpcStatus = RpcStringBindingCompose(NULL,
  324. rpc_protocol,
  325. PlainServerName,
  326. NULL, // endpoint
  327. NULL,
  328. &StringBinding);
  329. if (RpcStatus != RPC_S_OK)
  330. {
  331. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  332. return(RpcStatus);
  333. }
  334. return(BindingFromStringBinding(&StringBinding, pBindingHandle));
  335. }
  336. //+---------------------------------------------------------------------------
  337. //
  338. // Function: BindNetBIOSOverNetBEUI
  339. //
  340. // Synopsis: Attempt to bind via netbeui.
  341. //
  342. // Arguments: [ServerName] -- Server name to bind to.
  343. // [pBindingHandle] -- Returned binding handle.
  344. //
  345. // Returns: RPC_STATUS code
  346. //
  347. // Notes: None.
  348. //
  349. //----------------------------------------------------------------------------
  350. RPC_STATUS
  351. BindNetBIOSOverNetBEUI(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  352. {
  353. return(BindViaProtocol(TEXT("ncacn_nb_nb"),
  354. ServerName,
  355. pBindingHandle));
  356. }
  357. //+---------------------------------------------------------------------------
  358. //
  359. // Function: BindNetBIOSOverTCP
  360. //
  361. // Synopsis: Attempt to bind via tcp over netbios.
  362. //
  363. // Arguments: [ServerName] -- Server name to bind to.
  364. // [pBindingHandle] -- Returned binding handle.
  365. //
  366. // Returns: RPC_STATUS code
  367. //
  368. // Notes: None.
  369. //
  370. //----------------------------------------------------------------------------
  371. RPC_STATUS
  372. BindNetBIOSOverTCP(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  373. {
  374. return(BindViaProtocol(TEXT("ncacn_nb_tcp"),
  375. ServerName,
  376. pBindingHandle));
  377. }
  378. //+---------------------------------------------------------------------------
  379. //
  380. // Function: BindNetBIOSOverIPX
  381. //
  382. // Synopsis: Attempt to bind via ipx over netbios.
  383. //
  384. // Arguments: [ServerName] -- Server name to bind to.
  385. // [pBindingHandle] -- Returned binding handle.
  386. //
  387. // Returns: RPC_STATUS code
  388. //
  389. // Notes: None.
  390. //
  391. //----------------------------------------------------------------------------
  392. RPC_STATUS
  393. BindNetBIOSOverIPX(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  394. {
  395. return(BindViaProtocol(TEXT("ncacn_nb_ipx"),
  396. ServerName,
  397. pBindingHandle));
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Function: BindNamedPipe
  402. //
  403. // Synopsis: Attempt to bind via named pipes.
  404. //
  405. // Arguments: [ServerName] -- Server name to bind to.
  406. // [pBindingHandle] -- Returned binding handle.
  407. //
  408. // Returns: ERROR_INVALID_COMPUTERNAME
  409. // RPC_STATUS code
  410. //
  411. // Notes: Server side *not* supported in Win95.
  412. //
  413. //----------------------------------------------------------------------------
  414. RPC_STATUS
  415. BindNamedPipe(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  416. {
  417. RPC_STATUS RpcStatus;
  418. LPTSTR StringBinding;
  419. LPWSTR SlashServerName;
  420. WCHAR Buffer[SA_MAX_COMPUTERNAME_LENGTH + 3]; // plus 3 for '\\' and NULL
  421. int have_slashes;
  422. ULONG NameLen;
  423. *pBindingHandle = NULL;
  424. if (ServerName[1] == L'\\')
  425. {
  426. have_slashes = 1;
  427. }
  428. else
  429. {
  430. have_slashes = 0;
  431. }
  432. //
  433. // Be nice and prepend slashes if not supplied.
  434. //
  435. NameLen = wcslen(ServerName);
  436. if ((!have_slashes) && (NameLen > 0))
  437. {
  438. if ((NameLen + 2) >= sizeof(Buffer))
  439. {
  440. return(ERROR_INVALID_COMPUTERNAME);
  441. }
  442. Buffer[0] = L'\\';
  443. Buffer[1] = L'\\';
  444. wcscpy(&Buffer[2], ServerName);
  445. SlashServerName = Buffer;
  446. }
  447. else
  448. {
  449. SlashServerName = ServerName;
  450. }
  451. RpcStatus = RpcStringBindingCompose(0,
  452. TEXT("ncacn_np"),
  453. SlashServerName,
  454. TEXT("\\PIPE\\atsvc"),
  455. NULL,
  456. &StringBinding);
  457. if (RpcStatus != RPC_S_OK)
  458. {
  459. CHECK_HRESULT(HRESULT_FROM_WIN32(RpcStatus));
  460. return(RpcStatus);
  461. }
  462. return(BindingFromStringBinding(&StringBinding, pBindingHandle));
  463. }
  464. //+---------------------------------------------------------------------------
  465. //
  466. // Function: BindSPX
  467. //
  468. // Synopsis: Attempt to bind over SPX.
  469. //
  470. // Arguments: [ServerName] -- Server name to bind to.
  471. // [pBindingHandle] -- Returned binding handle.
  472. //
  473. // Returns: RPC_STATUS code
  474. //
  475. // Notes: None.
  476. //
  477. //----------------------------------------------------------------------------
  478. RPC_STATUS
  479. BindSPX(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  480. {
  481. return(BindViaProtocol(TEXT("ncacn_spx"),
  482. ServerName,
  483. pBindingHandle));
  484. }
  485. //+---------------------------------------------------------------------------
  486. //
  487. // Function: BindTCPIP
  488. //
  489. // Synopsis: Attempt to bind over TCP/IP.
  490. //
  491. // Arguments: [ServerName] -- Server name to bind to.
  492. // [pBindingHandle] -- Returned binding handle.
  493. //
  494. // Returns: RPC_STATUS code
  495. //
  496. // Notes: None.
  497. //
  498. //----------------------------------------------------------------------------
  499. RPC_STATUS
  500. BindTCPIP(LPWSTR ServerName, RPC_BINDING_HANDLE * pBindingHandle)
  501. {
  502. return(BindViaProtocol(TEXT("ncacn_ip_tcp"),
  503. ServerName,
  504. pBindingHandle));
  505. }