⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 session.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }

        //
        // Update the response headers
        //
        
        headers.UpdateResponse();
        cbNewHeaders = headers.GetBufferSize();
        *pcchBuffer += (cbNewHeaders - cchHeaders);
        *pcchSent = fAdditionalContent ? (cbNewHeaders + cbTotalContent) : *pcchBuffer;
    
        pBuffer = buffer.GetBuffer(*pcchBuffer);  // add one for a null terminating char
        if(! pBuffer) {
            dwRetVal = ERROR_OUTOFMEMORY;
            IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Insufficient memory to allocate send buffer.\n")));
            goto exit;
        }

        // Copy response buffer
        headers.GetResponseBuffer(pBuffer);

        // Copy content back after headers
        if (cbContent) {
            memcpy(&pBuffer[cbNewHeaders], pContent, cbContent);
        }
    }

    //
    // Send the data along to the client
    //

    dwRetVal = SendData(m_sockClient, (char *)pBuffer, *pcchSent);

exit:
    if (ERROR_SUCCESS != dwRetVal) {
        SendMessage(m_sockClient, "502", gc_Reason502, g_pErrors->szMiscError, g_pErrors->cchMiscError);
    }
    
    return dwRetVal;
}

void CHttpSession::ClearRecvBuf(CBuffer& buffer)
{
    DWORD dwRetVal;
    PBYTE pBuffer = buffer.GetBuffer(0, FALSE);
    
    while (m_cbRequestRemain > 0) {
        int cbRecved = 0;
        SOCKET sock = m_sockClient;
        SessionUnlock();
        dwRetVal = NonBlockingRecv(sock, pBuffer, buffer.GetSize(), &cbRecved);
        SessionLock();
        if ((ERROR_SUCCESS != dwRetVal) || (0 == cbRecved)) {
            break;
        }
        m_cbRequestRemain -= cbRecved;
    }

    m_cbRequestRemain = 0;
}

DWORD CHttpSession::HandleConnectRequest(stringi& strHost, stringi& strPort)
{
    DWORD dwRetVal = ERROR_SUCCESS;

    //
    // Only accept CONNECT requests on HTTPS port.  CONNECT requests on other ports represent
    // a security risk and therefore, are rejected.
    //

    if (strPort == DEFAULT_HTTPS_PORT_SZ) {
        dwRetVal = ConnectServer(strHost, DEFAULT_HTTPS_PORT);
        if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }

        CHttpHeaders response;
        response.strStatusCode = "200";
        response.strReason = gc_Reason200Conn;
        response.UpdateResponse();
        
        dwRetVal = SendCustomPacket(m_sockClient, response);
        if (ERROR_SUCCESS == dwRetVal) {
            m_fSSLTunnel = TRUE;
        }
    }
    else {
        IFDBG(DebugOut(ZONE_OUTPUT, _T("WebProxy: A CONNECT request was attempted on a port other than 443 - this is not allowed.\n")));
        dwRetVal = ERROR_INVALID_PARAMETER;
    }
    
exit:
    return dwRetVal;
}

DWORD CHttpSession::ConnectServer(const char* szHost, int iPort)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    CHAR szPort[16];
    stringi strNewHost;
    ADDRINFO *pAI = NULL;

    IFDBG(DebugOut(ZONE_CONNECT, _T("WebProxy: Trying to connect to host %S on port %d in session %d.\n"), szHost, iPort, m_dwSessionId));

    sprintf(szPort, "%d", iPort);
    dwRetVal = getaddrinfo(szHost, szPort, NULL, &pAI);
    if (ERROR_SUCCESS != dwRetVal) {
        goto exit;        
    }

    m_sockServer = socket(pAI->ai_family, SOCK_STREAM, 0);
    if (! m_sockServer.valid()) {
        dwRetVal = WSAGetLastError();
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Error creating socket %d.\n"), dwRetVal));
        goto exit;
    }

    // Connect to host
    if (SOCKET_ERROR == connect(m_sockServer, pAI->ai_addr, pAI->ai_addrlen)) {
        dwRetVal = WSAGetLastError();
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Connect call failed with error %d.\n"), dwRetVal));
        m_sockServer.close();
        goto exit;
    }

    m_strServerName = szHost;
    
    IFDBG(DebugOut(ZONE_CONNECT, _T("WebProxy: Connected to host %S on port %d in session %d.\n"), szHost, ((iPort == -1) ? DEFAULT_HTTP_PORT : iPort), m_dwSessionId));

exit:
    if (pAI) {
        freeaddrinfo(pAI);
    }
    
    return dwRetVal;
}

DWORD CHttpSession::HandleAuthentication(CHttpHeaders& headers, CBuffer& buffer, BOOL* pfCloseConnection)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    DWORD dwAuthType = 0;
    CHttpHeaders response;
    BOOL fAuthSuccess = FALSE;
    int cbUser = MAX_USER_NAME;

    while (1) {
        // Get authorization data
        g_pParser->ParseAuthorization(headers, &dwAuthType);

        if ((AUTH_TYPE_UNKNOWN == dwAuthType) || (headers.strProxyAuthorization == "")) {
            //
            // Unknown Authentication type, resend Authenticate headers
            //
            
            *pfCloseConnection = TRUE;
            response.strProxyConnection = gc_ConnClose;

            if (g_pSettings->fNTLMAuth) {
                response.strProxyAuthenticate = gc_AuthNTLM;
            }
            if (g_pSettings->fBasicAuth) {
                response.strProxyAuthenticate2 = gc_AuthBasic;
            }
        }
        else if (AUTH_TYPE_NTLM == dwAuthType) {        
            //
            // NTLM Authentication
            //
            
            string strNTLMAuth;
            int cbNTLMAuthOut;
            
            GetMaxNTLMBuffBase64Size((DWORD *)&cbNTLMAuthOut);
            strNTLMAuth.reserve(cbNTLMAuthOut);
            m_strUser.reserve(cbUser);

            dwRetVal = HandleNTLMAuth(headers.strProxyAuthorization, strNTLMAuth.get_buffer(), cbNTLMAuthOut, m_strUser.get_buffer(), cbUser, &m_auth);
            if (ERROR_INSUFFICIENT_BUFFER == dwRetVal) {
                cbUser *= 2;
                FreeNTLMHandles(&m_auth);
                m_auth.m_Conversation = NTLM_NO_INIT_CONTEXT;
                continue;
            }
            else if (ERROR_SUCCESS != dwRetVal) {
                FreeNTLMHandles(&m_auth);
                m_auth.m_Conversation = NTLM_NO_INIT_CONTEXT;
                goto exit;
            }

            if (NTLM_DONE == m_auth.m_Conversation) {
                FreeNTLMHandles(&m_auth);
                m_auth.m_Conversation = NTLM_NO_INIT_CONTEXT;
            }

            //
            // If m_strUser is empty then we did not authenticate on this pass.  In this case strNTLMAuth should have data in
            // which case you will return this to the client.  If strNTLMAuth is also NULL then we failed to authenticate and
            // should start from the beginning again.
            //
            
            if (m_strUser != "") {
                fAuthSuccess = TRUE;
            }
            else if (strNTLMAuth != "") {
                response.strConnection = gc_ConnKeepAlive;
                response.strProxyConnection = gc_ConnKeepAlive;
                response.strProxyAuthenticate = gc_AuthNTLM;
                response.strProxyAuthenticate += " ";
                response.strProxyAuthenticate += strNTLMAuth;
            }
            else {
                *pfCloseConnection = TRUE;
                response.strProxyConnection = gc_ConnClose;
                
                if (g_pSettings->fNTLMAuth) {
                    response.strProxyAuthenticate = gc_AuthNTLM;
                }
                if (g_pSettings->fBasicAuth) {
                    response.strProxyAuthenticate2 = gc_AuthBasic;
                }
            }
        }
        else {
            //
            // Basic authentication
            //

            m_strUser.reserve(cbUser);
            
            dwRetVal = HandleBasicAuth(headers.strProxyAuthorization, &fAuthSuccess, m_strUser.get_buffer(), cbUser);
            if (ERROR_SUCCESS != dwRetVal) {
                goto exit;
            }

            if ((! fAuthSuccess) || (m_strUser == "")) {
                *pfCloseConnection = TRUE;
                response.strProxyConnection = gc_ConnClose;
                if (g_pSettings->fNTLMAuth) {
                    response.strProxyAuthenticate = gc_AuthNTLM;
                }
                if (g_pSettings->fBasicAuth) {
                    response.strProxyAuthenticate2 = gc_AuthBasic;
                }
            }
        }
        
        break;
    }

    // 
    // If we did not successfully authenticate, then respond to the client now with
    // a 407 error.
    //
    
    if (! fAuthSuccess) {
        ClearRecvBuf(buffer);
        
        response.strStatusCode = "407";
        response.strReason = gc_Reason407;

        char szBuf[5];
        response.strContentLength = _itoa(g_pErrors->cchProxyAuthFailed, szBuf, 10);

        response.UpdateResponse();

        // Send headers
        dwRetVal = SendCustomPacket(m_sockClient, response);
        if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }

        // Send "auth failed" content message
        dwRetVal = SendData(m_sockClient, g_pErrors->szProxyAuthFailed, g_pErrors->cchProxyAuthFailed);
        if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }

        IFDBG(DebugOut(ZONE_AUTH, _T("WebProxy: Sent authentication response with status 407, to client in session %d.\n"), m_dwSessionId));
    }

exit:
    return dwRetVal;
}

DWORD CHttpSession::HandleProxyPacRequest(void)
{
    CHAR szProxyPac[1024];
    int cchProxyPac;
    
    IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: Sending proxy.pac file to client.\n")));

    g_pSettings->Lock();

    ULONG ulIpMask = inet_addr(g_pSettings->strPrivateMaskV4);
    ULONG ulIpAddr = inet_addr(g_pSettings->strPrivateAddrV4);
    
    sockaddr_in dest;
    dest.sin_addr.S_un.S_addr = (ulIpAddr  & ulIpMask);
    string strDest = inet_ntoa(dest.sin_addr);

    sprintf(szProxyPac, gc_szProxyPac, (LPCSTR)strDest, (LPCSTR)g_pSettings->strPrivateMaskV4, (LPCSTR)g_pSettings->strPrivateAddrV4, g_pSettings->iPort);
    cchProxyPac = strlen(szProxyPac);

    g_pSettings->Unlock();

    return SendMessage(m_sockClient, "200", gc_Reason200, szProxyPac, cchProxyPac);
}

DWORD CHttpSession::ProxyRecv(SOCKET sock, CBuffer& buffer, int* pcbTotalRecved, int cbRemain, int* pcbHeaders)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    int cbHeaders = 0;
    
    PBYTE pBuffer = buffer.GetBuffer(0, FALSE);
    ASSERT(pBuffer);
    
    ASSERT(pcbTotalRecved);
        
    //
    // If all headers have not yet been read, we have to read them.  Otherwise, this is just reading
    // another chunk of data.
    //

    while (0 == cbHeaders) {
        int cbBuffer;
        int cbRecved = 0;
        int cbRecvBufferIn;
        PBYTE pBuff;

        // If we have recved some data and are still in this loop then we have to recv more.  Double the buffer
        // size and proceed to recv more data.
        cbBuffer = *pcbTotalRecved;
        if (cbBuffer >= DEFAULT_BUFFER_SIZE - 1) {
            cbBuffer *= 2;
            if (cbBuffer > g_pSettings->iMaxBufferSize) {
                dwRetVal = ERROR_INVALID_DATA;
                goto exit;
            }
        }
        else {
            cbBuffer = DEFAULT_BUFFER_SIZE - 1;
        }

        pBuffer = buffer.GetBuffer(cbBuffer + 1, *pcbTotalRecved ? TRUE : FALSE);    // add 1 to append '\0'
        if(! pBuffer) {
            dwRetVal = ERROR_OUTOFMEMORY;
            IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Insufficient memory to allocate recv buffer.\n")));
            goto exit;
        }

        pBuff = pBuffer;

        cbRecvBufferIn = buffer.GetSize() - *pcbTotalRecved - 1;
        if ((cbRemain > 0) && (cbRecvBufferIn > cbRemain)) {
            //
            // If we have read all the headers and size of recv buffer is larger than what is left
            // that has to be read, then just read the amount that has to be read for this response.
            // Doing this ensures the start of a response will always be at the start of a packet.
            //
            cbRecvBufferIn = cbRemain;
        }

        SessionUnlock();        
        dwRetVal = NonBlockingRecv(sock, &pBuff[*pcbTotalRecved], cbRecvBufferIn, &cbRecved);
        SessionLock();
        if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }

        IFDBG(DebugOut(ZONE_PACKETS, _T("Received the following packet:\n")));
        IFDBG(DumpBuff(pBuff, cbRecved));

        *pcbTotalRecved += cbRecved;
        pBuff[*pcbTotalRecved] = '\0';

        // If we have already parsed the headers or we are just tunneling SSL data, 
        // then break from this loop now.
        if ((0 != cbRemain) || m_fSSLTunnel) {
            break;
        }

        // Both IE and Netscape append CRLF to POST but do not count it as part of the content-length.  It is possible
        // for these two bytes to be sent in their own packet and get unrecognized until this point.
        if ((m_strCurrMethod == gc_MethodPost) && (cbRecved == 2) && (pBuff[0] == '\r') && (pBuff[1] == '\n')) {
            m_cbRequestRemain = 2; // Reset this to two bytes left
            break;
        }

        // This call will return 0 if all the headers have not been recved
        cbHeaders = GetHeadersLength(pBuff);
    }

exit:
    if (pcbHeaders) {
        *pcbHeaders = cbHeaders;
    }
    
    return dwRetVal;
}


DWORD CHttpSession::ReadChunkSize(SOCKET recvSock, CBuffer& buffer, int* pcbRecved, DWORD* pdwChunkSize, DWORD* pdwChunkHeaderSize)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    DWORD dwReadAttempts = 0;

    ASSERT(pcbRecved);    
    ASSERT(pdwChunkSize);
    ASSERT(pdwChunkHeaderSize);

    *pdwChunkSize = 0;
    *pdwChunkHeaderSize = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -