Leaked source code of windows server 2003
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.

609 lines
13 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. sslconfigprovclient.cxx
  5. Abstract:
  6. SSL CONFIG PROV client
  7. Client provides easy way of retrieving SSL related parameters
  8. through named pipes.
  9. Only one pipe connection is currently supported and
  10. all client threads have to share it
  11. ( exclusive access is maintained by locking )
  12. Client side is guaranteed not to use any COM stuff.
  13. Not using COM was requirement from NT Security folks
  14. to enable HTTPFilter be hosted in lsass
  15. Author:
  16. Jaroslav Dunajsky April-24-2001
  17. Environment:
  18. Win32 - User Mode
  19. Project:
  20. Stream Filter Worker Process
  21. --*/
  22. #include "precomp.hxx"
  23. HRESULT
  24. SSL_CONFIG_PROV_CLIENT::Initialize(
  25. IN SSL_CONFIG_CHANGE_CALLBACK * pSslConfigChangeCallback,
  26. IN OPTIONAL PVOID pvParam
  27. )
  28. /*++
  29. Routine Description:
  30. Connect to SSL_CONFIG_PIPE
  31. Arguments:
  32. Return Value:
  33. HRESULT
  34. --*/
  35. {
  36. HRESULT hr = E_FAIL;
  37. IF_DEBUG( TRACE )
  38. {
  39. DBGPRINTF(( DBG_CONTEXT,
  40. "SSL_CONFIG_PROV_CLIENT::Initialize()\n"
  41. ));
  42. }
  43. //
  44. // store the callback function pointer, and first parameter
  45. //
  46. _pSslConfigChangeCallback = pSslConfigChangeCallback;
  47. _pSslConfigChangeCallbackParameter = pvParam;
  48. //
  49. // Initialize parent (it will handle all the pipe initialization)
  50. //
  51. return SSL_CONFIG_PIPE::PipeInitializeClient( WSZ_SSL_CONFIG_PIPE );
  52. }
  53. HRESULT
  54. SSL_CONFIG_PROV_CLIENT::Terminate(
  55. VOID
  56. )
  57. /*++
  58. Routine Description:
  59. Cleanup
  60. Arguments:
  61. Return Value:
  62. HRESULT
  63. --*/
  64. {
  65. IF_DEBUG( TRACE )
  66. {
  67. DBGPRINTF(( DBG_CONTEXT,
  68. "SSL_CONFIG_PROV_CLIENT::Terminate()\n"
  69. ));
  70. }
  71. _SslConfigChangeProvClient.StopListeningForChanges();
  72. SSL_CONFIG_PIPE::PipeDisconnect();
  73. return SSL_CONFIG_PIPE::PipeTerminate();
  74. }
  75. HRESULT
  76. SSL_CONFIG_PROV_CLIENT::MaintainPipeConnection(
  77. VOID
  78. )
  79. /*++
  80. Routine Description:
  81. Maintain pipe connection. If connection is not opened
  82. then reopen it
  83. Caller must assure that Pipe is locked when this call is made
  84. Arguments:
  85. Return Value:
  86. HRESULT
  87. --*/
  88. {
  89. HRESULT hr = E_FAIL;
  90. //
  91. // Config change provider has easy way to find out
  92. // if pipe was disconnected because it is actively listening on it
  93. // we assume that if config change provider is connected already, then
  94. // the config provider is connected as well
  95. //
  96. if ( !_SslConfigChangeProvClient.IsConnected() )
  97. {
  98. //
  99. // Check if config provider was ever connected
  100. // If previous connection failed
  101. // (the reason would most likely be crash of inetinfo)
  102. // it is safer to terminate all connections and
  103. // then try to reconnect
  104. //
  105. DBG_ASSERT( IsPipeLocked() );
  106. _SslConfigChangeProvClient.StopListeningForChanges();
  107. SSL_CONFIG_PIPE::PipeDisconnect();
  108. //
  109. // Connect to change notification pipe
  110. //
  111. hr = _SslConfigChangeProvClient.StartListeningForChanges(
  112. _pSslConfigChangeCallback,
  113. _pSslConfigChangeCallbackParameter );
  114. if ( FAILED( hr ) )
  115. {
  116. return hr;
  117. }
  118. //
  119. // Connect to ssl config pipe
  120. //
  121. hr = SSL_CONFIG_PIPE::PipeConnect();
  122. if (FAILED( hr ) )
  123. {
  124. _SslConfigChangeProvClient.StopListeningForChanges();
  125. return hr;
  126. }
  127. //
  128. // Notify user of the config provider
  129. // that all data received so far that may be cached
  130. // should be flushed
  131. //
  132. DBG_ASSERT( _pSslConfigChangeCallback != NULL );
  133. (* _pSslConfigChangeCallback) (
  134. _pSslConfigChangeCallbackParameter,
  135. CMD_CHANGED_ALL,
  136. 0 );
  137. return hr;
  138. }
  139. return S_OK;
  140. }
  141. HRESULT
  142. SSL_CONFIG_PROV_CLIENT::GetOneSiteSecureBindings(
  143. IN DWORD dwSiteId,
  144. OUT MULTISZ * pSecureBindings
  145. )
  146. /*++
  147. Routine Description:
  148. Retrieve secure bindings for specified site
  149. Arguments:
  150. Return Value:
  151. HRESULT
  152. --*/
  153. {
  154. DWORD dwReturnedSiteId = 0;
  155. IF_DEBUG( TRACE )
  156. {
  157. DBGPRINTF(( DBG_CONTEXT,
  158. "GetOneSiteSecureBindings( %d )\n",
  159. dwSiteId ));
  160. }
  161. SSL_CONFIG_PIPE_COMMAND Command;
  162. HRESULT hr = E_FAIL;
  163. DBG_ASSERT( pSecureBindings != NULL );
  164. Command.dwCommandId = CMD_GET_ONE_SITE_SECURE_BINDINGS;
  165. Command.dwParameter1 = dwSiteId;
  166. PipeLock();
  167. //
  168. // assure that pipe will be open
  169. //
  170. hr = MaintainPipeConnection();
  171. if ( FAILED( hr ) )
  172. {
  173. goto Cleanup;
  174. }
  175. hr = PipeSendCommand( &Command );
  176. if ( FAILED( hr ) )
  177. {
  178. goto Cleanup;
  179. }
  180. hr = ReceiveOneSiteSecureBindings( &dwReturnedSiteId ,
  181. pSecureBindings );
  182. Cleanup:
  183. if( FAILED( hr ) )
  184. {
  185. IF_DEBUG( TRACE )
  186. {
  187. DBGPRINTF(( DBG_CONTEXT,
  188. "GetOneSiteSecureBindings( %d ) leaving with error. hr = 0x%x\n",
  189. hr ));
  190. }
  191. }
  192. PipeUnlock();
  193. return hr;
  194. }
  195. HRESULT
  196. SSL_CONFIG_PROV_CLIENT::ReceiveOneSiteSecureBindings(
  197. OUT DWORD * pdwSiteId,
  198. OUT MULTISZ * pSecureBindings
  199. )
  200. /*++
  201. Routine Description:
  202. read secure bindings from pipe
  203. Note: it's caller's responsibility to have pipe access locked
  204. Arguments:
  205. Return Value:
  206. HRESULT
  207. --*/
  208. {
  209. SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
  210. HRESULT hr = E_FAIL;
  211. DBG_ASSERT( pSecureBindings != NULL );
  212. DBG_ASSERT( pdwSiteId != NULL );
  213. DBG_ASSERT( IsPipeLocked() );
  214. hr = PipeReceiveResponseHeader( &ResponseHeader );
  215. if ( FAILED( hr ) )
  216. {
  217. goto failed;
  218. }
  219. DBG_ASSERT( ResponseHeader.dwCommandId == CMD_GET_ONE_SITE_SECURE_BINDINGS );
  220. *pdwSiteId = ResponseHeader.dwParameter1;
  221. if ( FAILED ( ResponseHeader.hrErrorCode ) )
  222. {
  223. //
  224. // return error reported by ssl configuration info provider
  225. //
  226. //BUGBUG always read data to clean up pipe
  227. hr = ResponseHeader.hrErrorCode;
  228. goto failed;
  229. }
  230. if ( !pSecureBindings->Resize( ResponseHeader.dwResponseSize ) )
  231. {
  232. hr = HRESULT_FROM_WIN32( GetLastError());
  233. goto failed;
  234. }
  235. hr = PipeReceiveData( ResponseHeader.dwResponseSize,
  236. reinterpret_cast<BYTE *>(pSecureBindings->QueryPtr()) );
  237. if ( FAILED( hr ) )
  238. {
  239. goto failed;
  240. }
  241. return S_OK;
  242. failed:
  243. DBG_ASSERT( FAILED( hr ) );
  244. return hr;
  245. }
  246. HRESULT
  247. SSL_CONFIG_PROV_CLIENT::StartAllSitesSecureBindingsEnumeration(
  248. VOID
  249. )
  250. /*++
  251. Routine Description:
  252. Lock named pipe for exclusive access
  253. Send command over named pipe to read all secure bindings
  254. Note: StopSiteSecureBindingsEnumeration() must be called
  255. to unlock named pipe (after successfull
  256. StartAllSitesSecureBindingsEnumeration() call )
  257. Arguments:
  258. Return Value:
  259. HRESULT
  260. --*/
  261. {
  262. SSL_CONFIG_PIPE_COMMAND Command;
  263. SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
  264. HRESULT hr = E_FAIL;
  265. IF_DEBUG( TRACE )
  266. {
  267. DBGPRINTF(( DBG_CONTEXT,
  268. "StartAllSitesSecureBindingsEnumeration\n",
  269. hr ));
  270. }
  271. Command.dwCommandId = CMD_GET_ALL_SITES_SECURE_BINDINGS;
  272. Command.dwParameter1 = 0;
  273. PipeLock();
  274. //
  275. // assure that pipe will be open
  276. //
  277. hr = MaintainPipeConnection();
  278. if ( FAILED( hr ) )
  279. {
  280. goto Failure;
  281. }
  282. hr = PipeSendCommand( &Command );
  283. if ( FAILED( hr ) )
  284. {
  285. goto Failure;
  286. }
  287. hr = PipeReceiveResponseHeader( &ResponseHeader );
  288. if ( FAILED( hr ) )
  289. {
  290. goto Failure;
  291. }
  292. DBG_ASSERT( ResponseHeader.dwCommandId == Command.dwCommandId );
  293. //
  294. // Response size 0 means that reponse will be terminated by
  295. // special termination record
  296. //
  297. DBG_ASSERT( ResponseHeader.dwResponseSize == 0 );
  298. if ( FAILED( ResponseHeader.hrErrorCode ) )
  299. {
  300. hr = ResponseHeader.hrErrorCode;
  301. goto Failure;
  302. }
  303. hr = S_OK;
  304. return hr;
  305. Failure:
  306. IF_DEBUG( TRACE )
  307. {
  308. DBGPRINTF(( DBG_CONTEXT,
  309. "StartAllSitesSecureBindingsEnumeration() leaving with error. hr = 0x%x\n",
  310. hr ));
  311. }
  312. PipeUnlock();
  313. return hr;
  314. }
  315. HRESULT
  316. SSL_CONFIG_PROV_CLIENT::StopAllSitesSecureBindingsEnumeration(
  317. VOID
  318. )
  319. /*++
  320. Routine Description:
  321. If all enumerated data was not read using GetNextSiteSecureBindings()
  322. it will read the leftover. Then unlock access to named pipe
  323. Note: call only after successful StartAllSitesSecureBindingsEnumeration()
  324. Arguments:
  325. Return Value:
  326. HRESULT
  327. --*/
  328. {
  329. IF_DEBUG( TRACE )
  330. {
  331. DBGPRINTF(( DBG_CONTEXT,
  332. "StopAllSitesSecureBindingsEnumeration\n"
  333. ));
  334. }
  335. PipeUnlock();
  336. return S_OK;
  337. }
  338. HRESULT
  339. SSL_CONFIG_PROV_CLIENT::GetNextSiteSecureBindings(
  340. OUT DWORD * pdwId,
  341. OUT MULTISZ * pSecureBindings
  342. )
  343. /*++
  344. Routine Description:
  345. Enumerate all Secure Bindings after StartSiteSecureBindingsEnumeration()
  346. was called
  347. Note: StopSiteSecureBindingsEnumeration() must always be called
  348. afterwards to unlock named pipe
  349. Note: only those sites that contain secure bindings will be enumerated
  350. Arguments:
  351. pdwId - ID of the enumerated site
  352. pSecureBindings - secure bindings
  353. Return Value:
  354. HRESULT
  355. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) means that all Sites
  356. have been enumerated already. This signals the end of enumeration
  357. --*/
  358. {
  359. return ReceiveOneSiteSecureBindings ( pdwId,
  360. pSecureBindings );
  361. }
  362. HRESULT
  363. SSL_CONFIG_PROV_CLIENT::GetOneSiteSslConfiguration(
  364. IN DWORD dwSiteId,
  365. OUT SITE_SSL_CONFIGURATION * pSiteSslConfiguration
  366. )
  367. /*++
  368. Routine Description:
  369. Get all SSL configuration parameters for specified site
  370. Arguments:
  371. dwSiteId
  372. SiteSslConfiguration
  373. Return Value:
  374. HRESULT
  375. --*/
  376. {
  377. SSL_CONFIG_PIPE_COMMAND Command;
  378. SSL_CONFIG_PIPE_RESPONSE_HEADER ResponseHeader;
  379. HRESULT hr = E_FAIL;
  380. IF_DEBUG( TRACE )
  381. {
  382. DBGPRINTF(( DBG_CONTEXT,
  383. "GetOneSiteSslConfiguration( %d )\n",
  384. dwSiteId ));
  385. }
  386. Command.dwCommandId = CMD_GET_SSL_CONFIGURATION;
  387. Command.dwParameter1 = dwSiteId;
  388. //
  389. // Get exclusive access to pipe
  390. //
  391. PipeLock();
  392. //
  393. // assure that pipe will be open
  394. //
  395. hr = MaintainPipeConnection();
  396. if ( FAILED( hr ) )
  397. {
  398. goto Cleanup;
  399. }
  400. //
  401. // Send command to request SSL CONFIGURATION
  402. //
  403. hr = PipeSendCommand( &Command );
  404. if ( FAILED( hr ) )
  405. {
  406. goto Cleanup;
  407. }
  408. //
  409. // Receive response header and later addition response data if available
  410. //
  411. hr = PipeReceiveResponseHeader( &ResponseHeader );
  412. if ( FAILED( hr ) )
  413. {
  414. goto Cleanup;
  415. }
  416. if ( ResponseHeader.dwCommandId != CMD_GET_SSL_CONFIGURATION ||
  417. ResponseHeader.dwResponseSize != sizeof(*pSiteSslConfiguration) )
  418. {
  419. DBG_ASSERT( FALSE );
  420. hr = E_FAIL;
  421. goto Cleanup;
  422. }
  423. if ( FAILED ( ResponseHeader.hrErrorCode ) )
  424. {
  425. //
  426. // return error reported by ssl configuration info provider
  427. //
  428. hr = ResponseHeader.hrErrorCode;
  429. //
  430. // Read data to cleanup the pipe
  431. //
  432. PipeReceiveData( sizeof(*pSiteSslConfiguration),
  433. reinterpret_cast<BYTE *>(pSiteSslConfiguration) );
  434. goto Cleanup;
  435. }
  436. //
  437. // Receive additional data
  438. //
  439. hr = PipeReceiveData( sizeof(*pSiteSslConfiguration),
  440. reinterpret_cast<BYTE *>(pSiteSslConfiguration) );
  441. if ( FAILED( hr ) )
  442. {
  443. goto Cleanup;
  444. }
  445. hr = S_OK;
  446. Cleanup:
  447. if ( FAILED( hr ) )
  448. {
  449. IF_DEBUG( TRACE )
  450. {
  451. DBGPRINTF(( DBG_CONTEXT,
  452. "GetOneSiteSslConfiguration( %d ) leaving with error. hr = 0x%x\n",
  453. dwSiteId,
  454. hr ));
  455. }
  456. }
  457. //
  458. // Done with pipe
  459. //
  460. PipeUnlock();
  461. return hr;
  462. }