📄 buffio.cpp
字号:
dwBytesToRecv = dwMaxBufferSize - m_iNextIn;
else
dwBytesToRecv = dwAvailable;
if(!AllocMem(dwBytesToRecv+1))
myretleave(INPUT_ERROR, 103);
}
else { // Read in only requested amount of POST
dwBytesToRecv = min(dwAvailable,dwBytesRemainingToBeRead);
// we don't call AllocMem() here because we allocated all we'll need at top of function.
}
DEBUGMSG(ZONE_REQUEST_VERBOSE,(L"HTTPD: RecvToBuf: available bytes=%d, bytes we'll recv=%d\r\n",dwAvailable,dwBytesToRecv));
}
#if defined (DEBUG)
else
DEBUGMSG(ZONE_REQUEST_VERBOSE,(L"HTTPD: RecvToBuf has %d bytes of data already from SSL negotiation, using it instead of calling recv()\r\n",m_iNextIn));
#endif
DEBUGCHK((m_iSize-m_iNextIn) >= (int)dwBytesToRecv);
BufferConsistencyChecks();
int iRecv = 0;
if (fSSLSkipFirstRead) {
// We already have data from SSL handshake that needs to be decrypted.
// trick receive logic into thinking we read preexisting data
// into buffer on the loop above. After this point, there's no difference
// between if we got data left over from handshake or if we got it from first receive
// at any point during the request.
iRecv = m_iNextIn;
m_iNextIn = 0;
fSSLSkipFirstRead = FALSE;
}
else {
// typical case, read data.
iRecv = recv(sock, m_pszBuf+m_iNextIn, dwBytesToRecv, 0) ;
DEBUGMSG(ZONE_SOCKET, (L"HTTPD: recv(%x) got %d\r\n", sock, iRecv));
if (iRecv == 0 && !fForceSSLRenegotiate) {
DEBUGMSG(ZONE_REQUEST_VERBOSE,(L"HTTPD: RecvToBuf: iRecv==0, m_iNextIn=%d\r\n",m_iNextIn));
myretleave((m_iNextIn ? INPUT_OK : INPUT_TIMEOUT), 0);
} // got EOF. If we have any data return OK, else return TIMEOUT
else if (iRecv == SOCKET_ERROR) {
DEBUGMSG(ZONE_REQUEST_VERBOSE,(L"HTTPD: RecvToBuf: iRecv==SOCKET_ERROR, m_iNextIn=%d\r\n",m_iNextIn));
myretleave(((GetLastError()==WSAECONNRESET) ? INPUT_TIMEOUT : INPUT_ERROR), 104);
}
}
// The following block is executed if we want to decrypt SSL. When reading http
// headers on secure channel, always do SSLDecrypt because we don't know how big headers
// will be. When reading in POST data, if we know we haven't recv()'d enough data yet, call
// recv() again before starting decryption as an optimization.
if (fForceSSLRenegotiate || (fIsSecure && (fReadHeaders || (0 >= (int)dwBytesRemainingToBeRead-iRecv)))) {
DWORD dwBytesDecryptedInCall=0, dwExtra=0, dwIgnore=0;
DWORD dwSSLOffsetOrg = dwSSLOffset;
DWORD dwDecLen = dwSSLOffset+iRecv;
BOOL fCompletedRenegotiate = FALSE;
// Calls into SSL/HTTP layer to perform decryption. See function definition for explanation of paramaters.
SECURITY_STATUS scRet = pRequest->SSLDecrypt(m_pszBuf+m_iNextDecrypt,
dwDecLen,&dwBytesDecryptedInCall,&dwSSLOffset,&dwExtra,&dwIgnore,&fCompletedRenegotiate);
if ((scRet != SEC_E_OK) &&
(scRet != SEC_E_INCOMPLETE_MESSAGE)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: SSLDecrypt fails, scRet=0x%08x\r\n",scRet));
myretleave(INPUT_ERROR,115);
}
DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: dwBytesDecryptedInCall=%d,dwBytesDecrypted=%d,dwIgnore=%d,dwBytesRemainingToBeRead=%d,dwDecLen=%d,dwSSLOffset=%d,dwSSLOffsetOrg=%d\r\n",
dwBytesDecryptedInCall,dwBytesDecrypted,dwIgnore,dwBytesRemainingToBeRead,dwDecLen,dwSSLOffset,dwSSLOffsetOrg));
dwBytesDecrypted += dwBytesDecryptedInCall;
m_iNextDecrypt += dwBytesDecryptedInCall;
// iRecv is number of bytes previous receive call got, however because
// we may be throwing out unneeded trailer information the next place
// we read in may be a little lower than it was before call.
if (scRet == SEC_E_OK)
iRecv = (int)(dwBytesDecryptedInCall-dwSSLOffsetOrg);
else
iRecv -= (int) dwIgnore;
dwBytesRemainingToBeRead -= dwIgnore;
// we renegotiate and don't have any POST data to read, or have finished with POST data
if (fForceSSLRenegotiate && fCompletedRenegotiate) {
DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: SSLDecrypt completed negotiate, dwBytesDecryptedInCall=%d,m_iNextIn=%d\r\n",dwBytesDecryptedInCall,m_iNextIn + dwBytesDecryptedInCall));
if (scRet == SEC_E_OK)
m_iNextIn += iRecv;
myretleave(scRet == S_OK ? INPUT_OK : INPUT_ERROR,119);
}
// Once we get 1st part of unencrypted data we'll start scanning over the HTTP headers.
if (fReadHeaders && dwBytesDecryptedInCall)
fScanHeadersForCRLF = TRUE;
if (scRet == SEC_E_OK) {
if (!fReadHeaders) {
if (dwBytesDecrypted >= dwLength)
dwBytesRemainingToBeRead = 0;
else
dwBytesRemainingToBeRead = iRecv + dwLength - dwBytesDecrypted;
}
}
else if (scRet == SEC_E_INCOMPLETE_MESSAGE && !fReadHeaders) {
// We don't have complete message but we know how long it's going to be.
// This will make main loop continue. For Headers we just call elsewhere.
DWORD dwBytesToAlloc;
if (! safeIntUAdd(dwExtra,iRecv,(UINT*)&dwBytesToAlloc)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: ERROR: Integer overflow on attempting to allocate data\r\n"));
DEBUGCHK(0);
myretleave(INPUT_ERROR, 103);
}
if (!AllocMem(dwBytesToAlloc))
myretleave(INPUT_ERROR, 103);
dwBytesRemainingToBeRead += dwExtra;
}
// we've read all the POST data off the wire, however we still
// need more packets to come across to contain the renegotiation information.
if ((dwBytesRemainingToBeRead == 0) && fSSLRenegotiate && !fForceSSLRenegotiate) {
DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: All POST data read but still need renegotiate for client certs, fForceSSLRenegotiate=TRUE\r\n"));
fForceSSLRenegotiate = TRUE;
}
}
else
dwSSLOffset += iRecv;
m_iNextIn += iRecv;
WriteBufferToDebugOut(FALSE);
if (dwBytesRemainingToBeRead)
dwBytesRemainingToBeRead -= iRecv;
BufferConsistencyChecks();
DEBUGCHK(!fReadHeaders || (int)dwMaxBufferSize >= m_iNextIn);
}
DEBUGCHK(0); // no fall through
done:
BufferConsistencyChecks();
// Always make this buffer into a null terminated string
if (m_pszBuf) {
m_pszBuf[m_iNextIn] = 0;
}
WriteBufferToDebugOut(TRUE);
DEBUGMSG(ZONE_REQUEST, (L"HTTPD: end RecvToBuf (ret=%d err=%d iGLE=%d)\r\n", ret, err, GLE(err)));
return ret;
}
// tokenize the input stream: We always skip leading white-space
// once we're in the token, we stop on whitespace or EOL, depending
// on the fWS param
BOOL CBuffer::NextToken(PSTR* ppszTok, int* piLen, BOOL fWS, BOOL fColon) {
int i, j;
// restore saved char, if any
if(m_chSaved) {
DEBUGCHK(m_pszBuf[m_iNextOut]==0);
m_pszBuf[m_iNextOut] = m_chSaved;
m_chSaved = 0;
}
for(i=m_iNextOut; i<m_iNextIn; i++) {
// if not whitespace break
if(! (m_pszBuf[i]==' ' || m_pszBuf[i]=='\t') )
break;
}
for(j=i; j<m_iNextIn; j++) {
// if we get an EOL, it's always end of token
if(m_pszBuf[j]=='\r' || m_pszBuf[j]=='\n')
break;
// if fWS==TRUE and we got white-space, then end of token
if(fWS && (m_pszBuf[j]==' ' || m_pszBuf[j]=='\t'))
break;
// HTTP 1.1 headers may start immediatly without a space between name/value
// (i.e. header-name:value).
if (fColon && (j>0) && (m_pszBuf[j-1]==':'))
break;
}
m_iNextOut = j;
*piLen = (j-i);
*ppszTok = &(m_pszBuf[i]);
if(i==j) {
DEBUGMSG(ZONE_TOKEN, (L"HTTPD: Got NULL token"));
return FALSE;
}
else {
// save a char so we can null-terminate the current token
m_chSaved = m_pszBuf[m_iNextOut];
m_pszBuf[m_iNextOut] = 0;
DEBUGMSG(ZONE_TOKEN, (L"HTTPD: Got token (%a) Len %d\r\n", *ppszTok, (*piLen)));
return TRUE;
}
}
// skip rest of current line and CRLF
BOOL CBuffer::NextLine() {
int i, j;
// restore saved char, if any
if(m_chSaved) {
DEBUGCHK(m_pszBuf[m_iNextOut]==0);
m_pszBuf[m_iNextOut] = m_chSaved;
m_chSaved = 0;
}
for(i=m_iNextOut, j=i+1; j<m_iNextIn; i++, j++) {
if(m_pszBuf[i]=='\r' && m_pszBuf[j]=='\n') {
m_iNextOut = j+1;
DEBUGMSG(ZONE_TOKEN, (L"HTTPD: NextLine: OK\r\n"));
return TRUE;
}
}
DEBUGMSG(ZONE_TOKEN, (L"HTTPD: NextLine: error\r\n"));
return FALSE;
}
BOOL CBuffer::AppendData(PCSTR pszData, int iLen) {
// make sure we have enough memory
DWORD dwBytesToAlloc;
if (! safeIntUAdd(iLen,1,(UINT*)&dwBytesToAlloc)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: ERROR: Integer overflow on attempting to allocate data\r\n"));
DEBUGCHK(0);
return FALSE;
}
if(!AllocMem(dwBytesToAlloc))
return FALSE;
DEBUGCHK((m_iSize-m_iNextIn) >= iLen);
memcpy(m_pszBuf+m_iNextIn, pszData, iLen);
m_iNextIn += iLen;
return TRUE;
}
BOOL CBuffer::SendBuffer(CHttpRequest *pRequest) {
DEBUGCHK(m_iNextOut==0);
DEBUGCHK(m_chSaved==0);
if(!m_iNextIn) {
DEBUGMSG(ZONE_REQUEST_VERBOSE, (L"HTTPD: SendBuffer: empty\r\n"));
return TRUE;
}
BOOL fRet = pRequest->SendData(m_pszBuf,m_iNextIn);
m_iNextIn = 0;
return fRet;
}
#if defined (DEBUG)
void CBuffer::WriteBufferToDebugOut(BOOL fPrintAll) {
int i = 0;
if (! (ZONE_REQUEST_VERBOSE & dpCurSettings.ulZoneMask))
return;
DEBUGMSG(1,(L"HTTPD: m_iSize = %d, m_iNextOut = %d, m_iNextIn = %d, m_iNextInFollow = %d\r\n",m_iSize,m_iNextOut,m_iNextIn,m_iNextInFollow));
DEBUGMSG(1,(L"HTTPD: m_iNextRequestBegin = %d, m_iNextRequestSize =%d, m_iNextDecrypt=%d\r\n",m_iNextRequestBegin,m_iNextRequestSize,m_iNextDecrypt));
#if defined (DEBUG_PRINT_ALL_BYTES)
if (fPrintAll) {
DEBUGMSG(1,(L"--BEGIN BUFFER\r\n"));
for (i = m_iNextOut; i < m_iNextIn; i += 8) {
DEBUGMSG(1,(L"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
m_pszBuf[i], m_pszBuf[i+1],m_pszBuf[i+2],m_pszBuf[i+3],
m_pszBuf[i+4],m_pszBuf[i+5],m_pszBuf[i+6],m_pszBuf[i+7]));
}
DEBUGMSG(1,(L"--END BUFFER\r\n"));
}
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -