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.

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