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.

425 lines
10 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. makeconn.cxx
  5. Abstract:
  6. This file contains the MakeConnection method
  7. Contents:
  8. CFsm_MakeConnection::RunSM
  9. HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm
  10. Author:
  11. Keith Moore (keithmo) 16-Nov-1994
  12. Revision History:
  13. 29-Apr-97 rfirth
  14. Conversion to FSM
  15. --*/
  16. #include <wininetp.h>
  17. #include <perfdiag.hxx>
  18. #include "httpp.h"
  19. //
  20. // HTTP Request Handle Object methods
  21. //
  22. DWORD
  23. CFsm_MakeConnection::RunSM(
  24. IN CFsm * Fsm
  25. )
  26. /*++
  27. Routine Description:
  28. description-of-function.
  29. Arguments:
  30. Fsm -
  31. Return Value:
  32. DWORD
  33. --*/
  34. {
  35. DEBUG_ENTER((DBG_HTTP,
  36. Dword,
  37. "CFsm_MakeConnection::RunSM",
  38. "%#x",
  39. Fsm
  40. ));
  41. START_SENDREQ_PERF();
  42. CFsm_MakeConnection * stateMachine = (CFsm_MakeConnection *)Fsm;
  43. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  44. DWORD error;
  45. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
  46. switch (Fsm->GetState()) {
  47. case FSM_STATE_INIT:
  48. case FSM_STATE_CONTINUE:
  49. error = pRequest->MakeConnection_Fsm(stateMachine);
  50. break;
  51. default:
  52. error = ERROR_WINHTTP_INTERNAL_ERROR;
  53. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  54. INET_ASSERT(FALSE);
  55. break;
  56. }
  57. STOP_SENDREQ_PERF();
  58. DEBUG_LEAVE(error);
  59. return error;
  60. }
  61. DWORD
  62. HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm(
  63. IN CFsm_MakeConnection * Fsm
  64. )
  65. /*++
  66. Routine Description:
  67. description-of-function.
  68. Arguments:
  69. Fsm -
  70. Return Value:
  71. DWORD
  72. --*/
  73. {
  74. DEBUG_ENTER((DBG_HTTP,
  75. Dword,
  76. "HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm",
  77. "%#x",
  78. Fsm
  79. ));
  80. PERF_ENTER(MakeConnection_Fsm);
  81. CFsm_MakeConnection & fsm = *Fsm;
  82. FSM_STATE state = fsm.GetState();
  83. DWORD error = fsm.GetError();
  84. INTERNET_HANDLE_OBJECT * pInternet;
  85. pInternet = GetRootHandle (this);
  86. if (state == FSM_STATE_INIT) {
  87. if (GetAuthState() == AUTHSTATE_NEEDTUNNEL) {
  88. state = FSM_STATE_1;
  89. } else if (IsTalkingToSecureServerViaProxy()) {
  90. state = FSM_STATE_3;
  91. } else {
  92. state = FSM_STATE_6;
  93. }
  94. } else {
  95. state = fsm.GetFunctionState();
  96. }
  97. switch (state) {
  98. case FSM_STATE_1:
  99. //
  100. // If we're attempting to do NTLM authentication using Proxy tunnelling
  101. // and we don't have a keep-alive socket to use, then create one
  102. //
  103. if (!(IsWantKeepAlive() && (_Socket != NULL) && _Socket->IsOpen())) {
  104. fsm.SetFunctionState(FSM_STATE_2);
  105. error = OpenProxyTunnel();
  106. if ((error != ERROR_SUCCESS)
  107. || ((GetStatusCode() != HTTP_STATUS_OK) && (GetStatusCode() != 0))) {
  108. goto quit;
  109. }
  110. } else {
  111. goto quit;
  112. }
  113. //
  114. // fall through
  115. //
  116. case FSM_STATE_2:
  117. if ((error != ERROR_SUCCESS)
  118. || ((GetStatusCode() != HTTP_STATUS_OK) && (GetStatusCode() != 0))) {
  119. goto quit;
  120. }
  121. //
  122. // Bind Socket Object with Proper HostName,
  123. // so we can check for valid common name
  124. // in the handshake.
  125. //
  126. if (_Socket->IsSecure()) {
  127. /* SCLE ref */
  128. error = ((ICSecureSocket *)_Socket)->SetHostName(GetHostName(), pInternet->GetSslSessionCache());
  129. if (error != ERROR_SUCCESS) {
  130. goto quit;
  131. }
  132. }
  133. //
  134. // Undo the proxy-ified info found in this Request Object, make it seem like
  135. // we're doing a connect connection, since we're about to do something like it
  136. // ( a tunnelled connection through the firewall )
  137. //
  138. error = SetServerInfoWithScheme(INTERNET_SCHEME_HTTP, FALSE);
  139. if (error != ERROR_SUCCESS) {
  140. goto quit;
  141. }
  142. LPSTR urlPath;
  143. DWORD urlPathLength;
  144. //
  145. // get URL-path again if it was changed during tunnel creation
  146. //
  147. error = CrackUrl(GetURL(),
  148. lstrlen(GetURL()),
  149. FALSE, // don't escape URL-path
  150. NULL, // don't care about scheme type
  151. NULL, // or scheme name
  152. NULL, // or scheme name length
  153. NULL, // or host name
  154. NULL, // or host name length
  155. NULL, // or port
  156. NULL, // or user name
  157. NULL, // or user name length
  158. NULL, // or password
  159. NULL, // or password length
  160. &urlPath,
  161. &urlPathLength,
  162. NULL, // don't care about extra
  163. NULL, // or extra length
  164. NULL
  165. );
  166. if (error != ERROR_SUCCESS) {
  167. goto quit;
  168. }
  169. if (LockHeaders())
  170. {
  171. ModifyRequest(HTTP_METHOD_TYPE_GET,
  172. urlPath,
  173. urlPathLength,
  174. NULL,
  175. 0
  176. );
  177. UnlockHeaders();
  178. }
  179. else
  180. {
  181. error = ERROR_NOT_ENOUGH_MEMORY;
  182. goto quit;
  183. }
  184. //SetProxyNTLMTunnelling(FALSE);
  185. SetRequestUsingProxy(FALSE); // don't generate proxy stuff.
  186. break;
  187. case FSM_STATE_3:
  188. //
  189. // Hack for SSL2 Client Hello bug in IIS Servers.
  190. // Need to ReOpen connection after failure with
  191. // a Client Hello Message.
  192. //
  193. if (_Socket != NULL) {
  194. ((ICSecureSocket *)_Socket)->SetProviderIndex(0);
  195. }
  196. attempt_ssl_connect:
  197. //
  198. // Attempt to do the connect
  199. //
  200. fsm.SetFunctionState(FSM_STATE_4);
  201. error = OpenProxyTunnel();
  202. if (error == ERROR_IO_PENDING) {
  203. goto quit;
  204. }
  205. //
  206. // fall through
  207. //
  208. case FSM_STATE_4:
  209. if ((error != ERROR_SUCCESS) || (GetStatusCode() != HTTP_STATUS_OK)) {
  210. goto quit;
  211. }
  212. //
  213. // Bind Socket Object with Proper HostName,
  214. // so we can check for valid common name
  215. // in the handshake.
  216. //
  217. INET_ASSERT(_Socket->IsSecure());
  218. /* SCLE ref */
  219. error = ((ICSecureSocket *)_Socket)->SetHostName(GetHostName(), pInternet->GetSslSessionCache());
  220. if (error != ERROR_SUCCESS) {
  221. goto quit;
  222. }
  223. //
  224. // if the app wants a secure channel (PCT/SSL) then we must negotiate
  225. // the security here
  226. //
  227. //
  228. // dwProviderIndex will be managed by SecureHandshakeWithServer,
  229. // And will be set to 0 when we can't try anymore.
  230. //
  231. DWORD asyncFlags;
  232. //
  233. // find out if we're async. N.B. see Assumes
  234. //
  235. asyncFlags = IsAsyncHandle() ? SF_NON_BLOCKING : 0;
  236. //
  237. // If we're Posting or sending data, make sure
  238. // the SSL connection knows about it, for the
  239. // purposes of generating errors.
  240. //
  241. if ((GetMethodType() == HTTP_METHOD_TYPE_POST)
  242. || (GetMethodType() == HTTP_METHOD_TYPE_PUT)) {
  243. asyncFlags |= SF_SENDING_DATA;
  244. }
  245. fsm.SetFunctionState(FSM_STATE_5);
  246. error = ((ICSecureSocket *)_Socket)->SecureHandshakeWithServer(
  247. (asyncFlags | SF_ENCRYPT),
  248. &fsm.m_bAttemptReconnect);
  249. if (error == ERROR_IO_PENDING) {
  250. goto quit;
  251. }
  252. //
  253. // fall through
  254. //
  255. case FSM_STATE_5:
  256. if (error != ERROR_SUCCESS) {
  257. if (error == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
  258. {
  259. if (_Socket->IsSecure())
  260. {
  261. if(m_pSecurityInfo)
  262. {
  263. /* SCLE ref */
  264. m_pSecurityInfo->Release();
  265. }
  266. /* SCLE ref */
  267. m_pSecurityInfo = ((ICSecureSocket *)_Socket)->GetSecurityEntry();
  268. }
  269. }
  270. //
  271. // we disconnected the socket and we won't attempt to reconnect. We
  272. // need to release the connection to balance the connection limiter
  273. //
  274. if (!fsm.m_bAttemptReconnect)
  275. {
  276. ReleaseConnection(TRUE, // bClose
  277. FALSE, // bIndicate
  278. TRUE // bDispose
  279. );
  280. }
  281. else
  282. {
  283. _Socket->Disconnect();
  284. }
  285. }
  286. //
  287. // SSL2 hack for old IIS servers.
  288. // We re-open the socket, and call again.
  289. //
  290. if (fsm.m_bAttemptReconnect) {
  291. goto attempt_ssl_connect;
  292. }
  293. break;
  294. case FSM_STATE_6:
  295. fsm.SetFunctionState(FSM_STATE_7);
  296. error = OpenConnection(FALSE, FALSE);
  297. if (error == ERROR_IO_PENDING) {
  298. break;
  299. }
  300. case FSM_STATE_7:
  301. //dprintf("HTTP connect took %d msec\n", GetTickCount() - _dwQuerySetCookieHeader);
  302. //hack
  303. if (error == ERROR_SUCCESS &&
  304. _Socket &&
  305. _Socket->IsSecure() &&
  306. m_pSecurityInfo == NULL
  307. )
  308. {
  309. /* SCLE ref */
  310. m_pSecurityInfo = ((ICSecureSocket *)_Socket)->GetSecurityEntry();
  311. }
  312. break;
  313. default:
  314. INET_ASSERT(FALSE);
  315. error = ERROR_WINHTTP_INTERNAL_ERROR;
  316. break;
  317. }
  318. quit:
  319. if (error != ERROR_IO_PENDING) {
  320. fsm.SetDone();
  321. // PERF_LEAVE(MakeConnection_Fsm);
  322. }
  323. PERF_LEAVE(MakeConnection_Fsm);
  324. DEBUG_LEAVE(error);
  325. return error;
  326. }