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

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
makeconn.cxx
Abstract:
This file contains the MakeConnection method
Contents:
CFsm_MakeConnection::RunSM
HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm
Author:
Keith Moore (keithmo) 16-Nov-1994
Revision History:
29-Apr-97 rfirth
Conversion to FSM
--*/
#include <wininetp.h>
#include <perfdiag.hxx>
#include "httpp.h"
//
// HTTP Request Handle Object methods
//
DWORD
CFsm_MakeConnection::RunSM(
IN CFsm * Fsm
)
/*++
Routine Description:
description-of-function.
Arguments:
Fsm -
Return Value:
DWORD
--*/
{
DEBUG_ENTER((DBG_HTTP,
Dword,
"CFsm_MakeConnection::RunSM",
"%#x",
Fsm
));
START_SENDREQ_PERF();
CFsm_MakeConnection * stateMachine = (CFsm_MakeConnection *)Fsm;
HTTP_REQUEST_HANDLE_OBJECT * pRequest;
DWORD error;
pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
switch (Fsm->GetState()) {
case FSM_STATE_INIT:
case FSM_STATE_CONTINUE:
error = pRequest->MakeConnection_Fsm(stateMachine);
break;
default:
error = ERROR_WINHTTP_INTERNAL_ERROR;
Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
INET_ASSERT(FALSE);
break;
}
STOP_SENDREQ_PERF();
DEBUG_LEAVE(error);
return error;
}
DWORD
HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm(
IN CFsm_MakeConnection * Fsm
)
/*++
Routine Description:
description-of-function.
Arguments:
Fsm -
Return Value:
DWORD
--*/
{
DEBUG_ENTER((DBG_HTTP,
Dword,
"HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm",
"%#x",
Fsm
));
PERF_ENTER(MakeConnection_Fsm);
CFsm_MakeConnection & fsm = *Fsm;
FSM_STATE state = fsm.GetState();
DWORD error = fsm.GetError();
INTERNET_HANDLE_OBJECT * pInternet;
pInternet = GetRootHandle (this);
if (state == FSM_STATE_INIT) {
if (GetAuthState() == AUTHSTATE_NEEDTUNNEL) {
state = FSM_STATE_1;
} else if (IsTalkingToSecureServerViaProxy()) {
state = FSM_STATE_3;
} else {
state = FSM_STATE_6;
}
} else {
state = fsm.GetFunctionState();
}
switch (state) {
case FSM_STATE_1:
//
// If we're attempting to do NTLM authentication using Proxy tunnelling
// and we don't have a keep-alive socket to use, then create one
//
if (!(IsWantKeepAlive() && (_Socket != NULL) && _Socket->IsOpen())) {
fsm.SetFunctionState(FSM_STATE_2);
error = OpenProxyTunnel();
if ((error != ERROR_SUCCESS)
|| ((GetStatusCode() != HTTP_STATUS_OK) && (GetStatusCode() != 0))) {
goto quit;
}
} else {
goto quit;
}
//
// fall through
//
case FSM_STATE_2:
if ((error != ERROR_SUCCESS)
|| ((GetStatusCode() != HTTP_STATUS_OK) && (GetStatusCode() != 0))) {
goto quit;
}
//
// Bind Socket Object with Proper HostName,
// so we can check for valid common name
// in the handshake.
//
if (_Socket->IsSecure()) {
/* SCLE ref */
error = ((ICSecureSocket *)_Socket)->SetHostName(GetHostName(), pInternet->GetSslSessionCache());
if (error != ERROR_SUCCESS) {
goto quit;
}
}
//
// Undo the proxy-ified info found in this Request Object, make it seem like
// we're doing a connect connection, since we're about to do something like it
// ( a tunnelled connection through the firewall )
//
error = SetServerInfoWithScheme(INTERNET_SCHEME_HTTP, FALSE);
if (error != ERROR_SUCCESS) {
goto quit;
}
LPSTR urlPath;
DWORD urlPathLength;
//
// get URL-path again if it was changed during tunnel creation
//
error = CrackUrl(GetURL(),
lstrlen(GetURL()),
FALSE, // don't escape URL-path
NULL, // don't care about scheme type
NULL, // or scheme name
NULL, // or scheme name length
NULL, // or host name
NULL, // or host name length
NULL, // or port
NULL, // or user name
NULL, // or user name length
NULL, // or password
NULL, // or password length
&urlPath,
&urlPathLength,
NULL, // don't care about extra
NULL, // or extra length
NULL
);
if (error != ERROR_SUCCESS) {
goto quit;
}
if (LockHeaders())
{
ModifyRequest(HTTP_METHOD_TYPE_GET,
urlPath,
urlPathLength,
NULL,
0
);
UnlockHeaders();
}
else
{
error = ERROR_NOT_ENOUGH_MEMORY;
goto quit;
}
//SetProxyNTLMTunnelling(FALSE);
SetRequestUsingProxy(FALSE); // don't generate proxy stuff.
break;
case FSM_STATE_3:
//
// Hack for SSL2 Client Hello bug in IIS Servers.
// Need to ReOpen connection after failure with
// a Client Hello Message.
//
if (_Socket != NULL) {
((ICSecureSocket *)_Socket)->SetProviderIndex(0);
}
attempt_ssl_connect:
//
// Attempt to do the connect
//
fsm.SetFunctionState(FSM_STATE_4);
error = OpenProxyTunnel();
if (error == ERROR_IO_PENDING) {
goto quit;
}
//
// fall through
//
case FSM_STATE_4:
if ((error != ERROR_SUCCESS) || (GetStatusCode() != HTTP_STATUS_OK)) {
goto quit;
}
//
// Bind Socket Object with Proper HostName,
// so we can check for valid common name
// in the handshake.
//
INET_ASSERT(_Socket->IsSecure());
/* SCLE ref */
error = ((ICSecureSocket *)_Socket)->SetHostName(GetHostName(), pInternet->GetSslSessionCache());
if (error != ERROR_SUCCESS) {
goto quit;
}
//
// if the app wants a secure channel (PCT/SSL) then we must negotiate
// the security here
//
//
// dwProviderIndex will be managed by SecureHandshakeWithServer,
// And will be set to 0 when we can't try anymore.
//
DWORD asyncFlags;
//
// find out if we're async. N.B. see Assumes
//
asyncFlags = IsAsyncHandle() ? SF_NON_BLOCKING : 0;
//
// If we're Posting or sending data, make sure
// the SSL connection knows about it, for the
// purposes of generating errors.
//
if ((GetMethodType() == HTTP_METHOD_TYPE_POST)
|| (GetMethodType() == HTTP_METHOD_TYPE_PUT)) {
asyncFlags |= SF_SENDING_DATA;
}
fsm.SetFunctionState(FSM_STATE_5);
error = ((ICSecureSocket *)_Socket)->SecureHandshakeWithServer(
(asyncFlags | SF_ENCRYPT),
&fsm.m_bAttemptReconnect);
if (error == ERROR_IO_PENDING) {
goto quit;
}
//
// fall through
//
case FSM_STATE_5:
if (error != ERROR_SUCCESS) {
if (error == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
if (_Socket->IsSecure())
{
if(m_pSecurityInfo)
{
/* SCLE ref */
m_pSecurityInfo->Release();
}
/* SCLE ref */
m_pSecurityInfo = ((ICSecureSocket *)_Socket)->GetSecurityEntry();
}
}
//
// we disconnected the socket and we won't attempt to reconnect. We
// need to release the connection to balance the connection limiter
//
if (!fsm.m_bAttemptReconnect)
{
ReleaseConnection(TRUE, // bClose
FALSE, // bIndicate
TRUE // bDispose
);
}
else
{
_Socket->Disconnect();
}
}
//
// SSL2 hack for old IIS servers.
// We re-open the socket, and call again.
//
if (fsm.m_bAttemptReconnect) {
goto attempt_ssl_connect;
}
break;
case FSM_STATE_6:
fsm.SetFunctionState(FSM_STATE_7);
error = OpenConnection(FALSE, FALSE);
if (error == ERROR_IO_PENDING) {
break;
}
case FSM_STATE_7:
//dprintf("HTTP connect took %d msec\n", GetTickCount() - _dwQuerySetCookieHeader);
//hack
if (error == ERROR_SUCCESS &&
_Socket &&
_Socket->IsSecure() &&
m_pSecurityInfo == NULL
)
{
/* SCLE ref */
m_pSecurityInfo = ((ICSecureSocket *)_Socket)->GetSecurityEntry();
}
break;
default:
INET_ASSERT(FALSE);
error = ERROR_WINHTTP_INTERNAL_ERROR;
break;
}
quit:
if (error != ERROR_IO_PENDING) {
fsm.SetDone();
// PERF_LEAVE(MakeConnection_Fsm);
}
PERF_LEAVE(MakeConnection_Fsm);
DEBUG_LEAVE(error);
return error;
}