Mineplex/.FILES USED TO GET TO WHERE WE ARE PRESENTLY/xampp/FileZillaFTP/source/AsyncGssSocketLayer.cpp
Daniel Waggner 76a7ae65df PUUUUUSH
2023-05-17 14:44:01 -07:00

1190 lines
29 KiB
C++

// GSSAsyncSocksifiedSocket.cpp: implementation of the CAsyncGssSocketLayer class.
//
//////////////////////////////////////////////////////////////////////
// Part of this code is copyright 2001 Massachusetts Institute of Technology
#include "stdafx.h"
#include "resource.h"
#include "AsyncGssSocketLayer.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define BUFSIZE (1024*8)
CAsyncGssSocketLayer::CAsyncGssSocketLayer()
{
m_hGSS_API = NULL;
m_transfer = FALSE;
m_bInitialized=FALSE;
m_bUseGSS=FALSE;
m_nGssNetworkError=0;
m_gotAuth=0;
m_nShutDown = 0;
pFzGss_ProcessCommand = NULL;
pFzGss_InitGSS = NULL;
pFzGss_KillGSS = NULL;
pFzGss_DecryptMessage = NULL;
pFzGss_EncryptMessage = NULL;
pFzGss_EncryptData = NULL;
pFzGss_DecryptData = NULL;
m_pSendBuffer = NULL;
m_nSendBufferLen = 0;
m_nSendBufferSize = 0;
m_pReceiveBuffer = NULL;
m_nReceiveBufferLen = 0;
m_nReceiveBufferSize = 0;
m_pDecryptedReceiveBuffer = NULL;
m_nDecryptedReceiveBufferLen = 0;
m_nDecryptedReceiveBufferSize = 0;
m_nAwaitingReply = 0;
}
CAsyncGssSocketLayer::~CAsyncGssSocketLayer()
{
delete [] m_pSendBuffer;
delete [] m_pReceiveBuffer;
delete [] m_pDecryptedReceiveBuffer;
KillGSSData();
}
int CAsyncGssSocketLayer::Send(const void* lpBuf, int nBufLen, int nFlags)
{
if (m_gotAuth == GSSAPI_AUTHENTICATION_SUCCEEDED && m_bUseGSS)
{
if (m_nAwaitingReply == 3)
{
m_nAwaitingReply = 0;
int res = SendNext(lpBuf, nBufLen, nFlags);
if (res == nBufLen)
m_nAwaitingReply = 0;
return res;
}
if (m_nShutDown)
{
SetLastError(WSAESHUTDOWN);
return SOCKET_ERROR;
}
if (!nBufLen)
return 0;
if (m_nSendBufferLen > BUFSIZE)
{
SetLastError(WSAEWOULDBLOCK);
return SOCKET_ERROR;
}
char sendme[4096];
char *encBuffer = m_tmpBuffer;
int encBufferLen = 0;
if ((nBufLen*1.5) > (1024*32))
encBuffer = new char[(int)(nBufLen * 1.5)];
memcpy(encBuffer, (char*)lpBuf, nBufLen);
if (m_transfer)
{
if (nBufLen>4000)
nBufLen=4000;
encBuffer[nBufLen] = '\0';
encBufferLen = pFzGss_EncryptData(m_pData, encBuffer, nBufLen, sendme);
if (!encBufferLen)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return 0;
}
}
else
{
encBuffer[nBufLen]='\0';
int len = pFzGss_EncryptMessage(m_pData, encBuffer, sendme);
if (!len)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return 0;
}
char *str = new char[strlen(encBuffer) + 30];
sprintf(str, "Encrypted command: %s", encBuffer);
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_INFO, (int)str);
delete [] str;
strcat(encBuffer, "\r\n");
encBufferLen = strlen(encBuffer);
}
if (m_nSendBufferLen)
{
ASSERT(m_nSendBufferLen <= m_nSendBufferSize);
ASSERT(m_pSendBuffer);
int numsent = SendNext(m_pSendBuffer, m_nSendBufferLen, 0);
if (!numsent)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return 0;
}
else if (numsent == SOCKET_ERROR && GetLastError()!=WSAEWOULDBLOCK)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return SOCKET_ERROR;
}
else if (numsent != m_nSendBufferLen)
{
if (numsent == SOCKET_ERROR)
numsent = 0;
if (!m_pSendBuffer)
{
m_pSendBuffer = new char[encBufferLen * 2];
m_nSendBufferSize = encBufferLen * 2;
}
else if (m_nSendBufferSize < (m_nSendBufferLen + encBufferLen))
{
char *tmp = m_pSendBuffer;
m_pSendBuffer = new char[m_nSendBufferSize + encBufferLen + 4096];
m_nSendBufferSize = m_nSendBufferSize + encBufferLen + 4096;
memcpy(m_pSendBuffer, tmp+numsent, m_nSendBufferLen-numsent);
delete [] tmp;
}
else
memmove(m_pSendBuffer, m_pSendBuffer + numsent, m_nSendBufferLen - numsent);
memcpy(m_pSendBuffer + m_nSendBufferLen - numsent, encBuffer, encBufferLen);
m_nSendBufferLen += encBufferLen-numsent;
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return nBufLen;
}
else
m_nSendBufferLen = 0;
}
int numsent = SendNext(encBuffer, encBufferLen, 0);
if (!numsent)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return 0;
}
if (numsent == SOCKET_ERROR)
{
if (GetLastError() != WSAEWOULDBLOCK)
{
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return SOCKET_ERROR;
}
else
{
if (m_nSendBufferSize < encBufferLen)
{
delete [] m_pSendBuffer;
m_pSendBuffer = new char[encBufferLen * 2];
m_nSendBufferSize = encBufferLen * 2;
}
memcpy(m_pSendBuffer, encBuffer, encBufferLen);
m_nSendBufferLen = encBufferLen;
}
}
else if (numsent != encBufferLen)
{
if (m_nSendBufferSize < encBufferLen)
{
delete [] m_pSendBuffer;
m_pSendBuffer = new char[encBufferLen * 2];
m_nSendBufferSize = encBufferLen * 2;
}
memcpy(m_pSendBuffer, encBuffer+numsent, encBufferLen-numsent);
m_nSendBufferLen = encBufferLen-numsent;
}
if (encBuffer != m_tmpBuffer)
delete [] encBuffer;
return nBufLen;
}
else
return SendNext(lpBuf, nBufLen, nFlags);
}
/*
This method calls its super method to receive data.
If authentication succeeded at some point, then it tries to decrypt the data.
After decryption, it adds \r\n to the end of the buffer.
This method currently does not handle the MSG_PEEK flag, it also ignores nBufLen.
*/
int CAsyncGssSocketLayer::Receive(void *lpBuf, int nBufLen, int nFlags)
{
if (m_gotAuth == GSSAPI_AUTHENTICATION_SUCCEEDED && m_bUseGSS)
{
if (m_nShutDown)
{
SetLastError(WSAESHUTDOWN);
return SOCKET_ERROR;
}
if (!nBufLen)
return 0;
BOOL bTriggerRead = TRUE;
if (!m_nDecryptedReceiveBufferLen)
{
bTriggerRead = FALSE;
OnReceive(0);
}
if (m_nDecryptedReceiveBufferLen)
{
ASSERT(m_pDecryptedReceiveBuffer && m_nDecryptedReceiveBufferLen<=m_nDecryptedReceiveBufferSize);
if (m_nDecryptedReceiveBufferLen > nBufLen)
{
memcpy(lpBuf, m_pDecryptedReceiveBuffer, nBufLen);
memmove(m_pDecryptedReceiveBuffer, m_pDecryptedReceiveBuffer + nBufLen, m_nDecryptedReceiveBufferLen-nBufLen);
m_nDecryptedReceiveBufferLen -= nBufLen;
ASSERT(nBufLen>0);
if (bTriggerRead)
TriggerEvent(FD_READ, 0);
return nBufLen;
}
else if (m_nDecryptedReceiveBufferLen == nBufLen)
{
memcpy(lpBuf, m_pDecryptedReceiveBuffer, nBufLen);
m_nDecryptedReceiveBufferLen = 0;
if (m_nGssNetworkError == -1)
{
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
}
else if (bTriggerRead)
TriggerEvent(FD_READ, 0);
return nBufLen;
}
else
{
memcpy(lpBuf, m_pDecryptedReceiveBuffer, m_nDecryptedReceiveBufferLen);
int res = m_nDecryptedReceiveBufferLen;
m_nDecryptedReceiveBufferLen = 0;
if (m_nGssNetworkError == -1)
{
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
}
else if (bTriggerRead)
TriggerEvent(FD_READ, 0);
return res;
}
}
else
{
if (m_nGssNetworkError==-1)
return 0;
else if (m_nGssNetworkError)
{
WSASetLastError(m_nGssNetworkError);
return SOCKET_ERROR;
}
else
{
WSASetLastError(WSAEWOULDBLOCK);
return SOCKET_ERROR;
}
}
}
else
return ReceiveNext(lpBuf, nBufLen, nFlags);
}
void CAsyncGssSocketLayer::OnReceive(int nErrorCode)
{
if (!m_bUseGSS || m_gotAuth != GSSAPI_AUTHENTICATION_SUCCEEDED)
{
TriggerEvent(FD_READ, nErrorCode, TRUE);
return;
}
//Don't decrypt additional data if buffer for decrypted data is not empty
if (m_nDecryptedReceiveBufferLen && (GetLayerState()==attached || GetLayerState()==connected))
{
TriggerEvent(FD_READ, nErrorCode, TRUE);
return;
}
char sendme[4096];
//TRACE(m_transfer?"GSS OnReceive: called, transfer mode\n":"GSS OnReceive: called\n");
int count = 10;
while(count--)
{
if (m_transfer)
{
if (m_nReceiveBufferLen < 4)
{
if (!m_pReceiveBuffer)
{
ASSERT(!m_nReceiveBufferLen);
ASSERT(!m_nReceiveBufferSize);
m_pReceiveBuffer = new char[4096];
m_nReceiveBufferSize = 4096;
m_nReceiveBufferLen = 0;
}
int numread = ReceiveNext(m_pReceiveBuffer+m_nReceiveBufferLen, 4 - m_nReceiveBufferLen);
if (!numread)
{
m_nGssNetworkError = -1;
if (!m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_CLOSE, 0, TRUE);
return;
}
else if (numread == SOCKET_ERROR)
{
if (GetLastError() != WSAEWOULDBLOCK)
{
TriggerEvent(FD_CLOSE, 0, TRUE);
m_nGssNetworkError = GetLastError();
}
else
if (m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_READ, nErrorCode, TRUE);
return;
}
m_nReceiveBufferLen += numread;
if (m_nReceiveBufferLen != 4)
{
if (m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_READ, nErrorCode, TRUE);
return;
}
char tmp = m_pReceiveBuffer[0];
m_pReceiveBuffer[0] = m_pReceiveBuffer[3];
m_pReceiveBuffer[3] = tmp;
tmp = m_pReceiveBuffer[1];
m_pReceiveBuffer[1] = m_pReceiveBuffer[2];
m_pReceiveBuffer[2] = tmp;
unsigned int len = *(unsigned int*)m_pReceiveBuffer;
if (len<4 || len > (1024*1024*4))
{
m_nGssNetworkError = WSAEMSGSIZE;
TriggerEvent(FD_CLOSE, 0, TRUE);
return;
}
if (m_nReceiveBufferSize < (len+4))
{
delete [] m_pReceiveBuffer;
m_pReceiveBuffer = new char[len * 2 + 4];
m_nReceiveBufferSize = len * 2 + 4;
}
memcpy(m_pReceiveBuffer, &len, 4);
m_nReceiveBufferLen = 4;
}
ASSERT(m_pReceiveBuffer);
int len = *(int*)m_pReceiveBuffer;
ASSERT(len>4 && len < (1024*1024*4));
int lenToReceive = len - m_nReceiveBufferLen + 4;
int numread = ReceiveNext(m_pReceiveBuffer + m_nReceiveBufferLen, lenToReceive);
if (!numread)
{
m_nGssNetworkError = -1;
if (!m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_CLOSE, 0, TRUE);
return;
}
else if (numread == SOCKET_ERROR)
{
if (GetLastError() != WSAEWOULDBLOCK)
{
m_nGssNetworkError = GetLastError();
TriggerEvent(FD_CLOSE, 0, TRUE);
}
return;
}
m_nReceiveBufferLen += numread;
if (numread != lenToReceive)
{
if (m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_READ, nErrorCode, TRUE);
return;
}
ASSERT(m_nReceiveBufferLen-4 == len);
char * decBuffer = m_tmpBuffer;
if ((len*1.5) > (1024*32))
decBuffer = new char[(int)(len * 1.5)];
memcpy(decBuffer, m_pReceiveBuffer+4, len);
m_nReceiveBufferLen = 0;
int nDecrypted = pFzGss_DecryptData(m_pData, decBuffer, len, sendme);
if (nDecrypted <= 0)
{
if (!m_nDecryptedReceiveBufferLen)
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
if (decBuffer != m_tmpBuffer)
delete [] decBuffer;
return;
}
//Add line to decrypted buffer
if (!m_pDecryptedReceiveBuffer)
{
ASSERT(!m_nDecryptedReceiveBufferSize && !m_nDecryptedReceiveBufferLen);
m_pDecryptedReceiveBuffer = new char[nDecrypted * 2];
m_nDecryptedReceiveBufferSize = nDecrypted * 2;
m_nDecryptedReceiveBufferLen = 0;
}
else if (m_nDecryptedReceiveBufferSize < (m_nDecryptedReceiveBufferLen+nDecrypted))
{
char *tmp=m_pDecryptedReceiveBuffer;
m_pDecryptedReceiveBuffer = new char[m_nDecryptedReceiveBufferSize + nDecrypted + 4096];
m_nDecryptedReceiveBufferSize = m_nDecryptedReceiveBufferSize + nDecrypted + 4096;
memcpy(m_pDecryptedReceiveBuffer, tmp, m_nDecryptedReceiveBufferLen);
delete [] tmp;
}
memcpy(m_pDecryptedReceiveBuffer + m_nDecryptedReceiveBufferLen, decBuffer, nDecrypted);
m_nDecryptedReceiveBufferLen += nDecrypted;
if (decBuffer != m_tmpBuffer)
delete [] decBuffer;
}
else
{
if (m_nAwaitingReply == 1)
{
ReceiveReply();
return;
}
int numread = ReceiveNext(m_tmpBuffer, BUFSIZE);
if (!numread)
{
m_nGssNetworkError = -1;
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
return;
}
else if ( numread == SOCKET_ERROR )
{
if ( WSAGetLastError() != WSAEWOULDBLOCK )
{
m_nGssNetworkError = GetLastError();
TriggerEvent(FD_CLOSE, 0, TRUE);
}
else if (m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_READ, 0, TRUE);
return;
}
if (!m_pReceiveBuffer)
{
ASSERT(!m_nReceiveBufferLen && !m_nReceiveBufferSize);
m_pReceiveBuffer = new char[numread * 2];
m_nReceiveBufferSize = numread * 2;
}
else if (m_nReceiveBufferSize < (m_nReceiveBufferLen + numread))
{
char *tmp=m_pReceiveBuffer;
m_pReceiveBuffer = new char[m_nReceiveBufferLen + numread + 4096];
m_nReceiveBufferSize = m_nReceiveBufferLen + numread + 4096;
memcpy(m_pReceiveBuffer, tmp, m_nReceiveBufferLen);
delete [] tmp;
}
memcpy(m_pReceiveBuffer+m_nReceiveBufferLen, m_tmpBuffer, numread);
int nOldLen = m_nReceiveBufferLen;
m_nReceiveBufferLen += numread;
//Now search for complete lines and decrypt them
for (unsigned int i = nOldLen; i < m_nReceiveBufferLen; i++)
{
if (m_pReceiveBuffer[i] == '\n')
{
if (!i)
{
if (m_nReceiveBufferLen > 1)
memmove(m_pReceiveBuffer, m_pReceiveBuffer+1, m_nReceiveBufferLen - 1);
m_nReceiveBufferLen--;
i--;
continue;
}
if (m_pReceiveBuffer[i-1] == '\r')
{
//We've found a line
char *decBuffer = m_tmpBuffer;
if ((i*1.5) > (1024*32))
decBuffer = new char[(int)(i * 1.5)];
memcpy(decBuffer, m_pReceiveBuffer, i-2);
decBuffer[i-1] = '\0';
//Delete encrypted line from receive buffer
if (!(m_nReceiveBufferLen-i-1))
m_nReceiveBufferLen = 0;
else
{
memmove(m_pReceiveBuffer, m_pReceiveBuffer+i+1, m_nReceiveBufferLen - i - 1);
m_nReceiveBufferLen -= i + 1;
}
// Decrypt line
char *str = new char[strlen(decBuffer) + 30];
sprintf(str, "Encrypted reply: %s", decBuffer);
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_INFO, (int)str);
delete [] str;
int nDecrypted = pFzGss_DecryptMessage(m_pData, decBuffer, sendme);
if (!nDecrypted)
{
m_nGssNetworkError = -1;
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
if (decBuffer != m_tmpBuffer)
delete [] decBuffer;
return;
}
nDecrypted = strlen(decBuffer);
if (m_nAwaitingReply && m_nAwaitingReply<3)
{
while (decBuffer[nDecrypted - 1]=='\n' || decBuffer[nDecrypted - 1]=='\r')
nDecrypted--;
decBuffer[nDecrypted] = 0;
m_nAwaitingReply = 0;
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_REPLY, (int)decBuffer);
if (decBuffer[nDecrypted - 1]!='\n')
{
decBuffer[nDecrypted++]='\r';
decBuffer[nDecrypted++]='\n';
decBuffer[nDecrypted] = 0;
}
int res = pFzGss_ProcessReply(m_pData, decBuffer);
if (res == 1)
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_AUTHCOMPLETE, 0);
else if (res!=-1)
{
m_gotAuth = 0;
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_AUTHFAILED, 0);
}
if (decBuffer != m_tmpBuffer)
delete [] decBuffer;
}
else
{
if (decBuffer[nDecrypted - 1]!='\n')
{
decBuffer[nDecrypted++]='\r';
decBuffer[nDecrypted++]='\n';
decBuffer[nDecrypted] = 0;
}
//Add line to decrypted buffer
if (!m_pDecryptedReceiveBuffer)
{
m_pDecryptedReceiveBuffer = new char[nDecrypted * 2];
m_nDecryptedReceiveBufferSize = nDecrypted * 2;
m_nDecryptedReceiveBufferLen=0;
}
else if (m_nDecryptedReceiveBufferSize < (m_nDecryptedReceiveBufferLen+nDecrypted))
{
char *tmp=m_pDecryptedReceiveBuffer;
m_pDecryptedReceiveBuffer = new char[m_nDecryptedReceiveBufferSize + nDecrypted + 4096];
m_nDecryptedReceiveBufferSize = m_nDecryptedReceiveBufferSize + nDecrypted + 4096;
memcpy(m_pDecryptedReceiveBuffer, tmp, m_nDecryptedReceiveBufferLen);
delete [] tmp;
}
memcpy(m_pDecryptedReceiveBuffer + m_nDecryptedReceiveBufferLen, decBuffer, nDecrypted);
m_nDecryptedReceiveBufferLen += nDecrypted;
if (decBuffer != m_tmpBuffer)
delete [] decBuffer;
}
//Try to decrypt any additional lines
i=-1;
}
}
}
}
}
}
void CAsyncGssSocketLayer::Close()
{
CloseNext();
m_nAwaitingReply = 0;
m_nGssNetworkError=0;
if (!m_transfer)
m_gotAuth = 0;
m_nSendBufferLen = 0;
m_nReceiveBufferLen = 0;
m_nDecryptedReceiveBufferLen = 0;
KillGSSData();
}
BOOL CAsyncGssSocketLayer::UnLoadGSSLibrary()
{
if (m_hGSS_API)
{
FreeLibrary(m_hGSS_API);
m_hGSS_API = NULL;
}
return TRUE;
}
BOOL CAsyncGssSocketLayer::LoadGSSLibrary()
{
if (m_hGSS_API)
return TRUE;
m_hGSS_API = LoadLibrary(GFTPDLL);
return !(m_hGSS_API==NULL);
}
BOOL CAsyncGssSocketLayer::InitGSS(BOOL bSpawned, BOOL promptPassword)
{
if (m_bUseGSS)
return TRUE;
if (m_bInitialized)
return TRUE;
if (!m_hGSS_API)
LoadGSSLibrary();
if (!m_hGSS_API)
return FALSE;
if (m_hGSS_API)
{
pFzGss_ProcessCommand = (t_FzGss_ProcessCommand)GetProcAddress(m_hGSS_API, "ProcessCommand");
pFzGss_DecryptMessage = (t_FzGss_DecryptMessage)GetProcAddress(m_hGSS_API, "DecryptMessage");
pFzGss_EncryptMessage = (t_FzGss_EncryptMessage)GetProcAddress(m_hGSS_API, "EncryptMessage");
pFzGss_EncryptData = (t_FzGss_EncryptData)GetProcAddress(m_hGSS_API , "EncryptData");
pFzGss_DecryptData = (t_FzGss_DecryptData)GetProcAddress(m_hGSS_API, "DecryptData");
pFzGss_InitGSS = (t_FzGss_InitGSS)GetProcAddress(m_hGSS_API, "InitGSS");
pFzGss_KillGSS = (t_FzGss_KillGSS)GetProcAddress(m_hGSS_API, "KillGSS");
pFzGss_DoClientAuth = (t_FzGss_DoClientAuth)GetProcAddress(m_hGSS_API, "DoClientAuth");
pFzGss_ProcessReply = (t_FzGss_ProcessReply)GetProcAddress(m_hGSS_API, "ProcessReply");
pFzGss_GetUserFromKrbTicket = (t_FzGss_GetUserFromKrbTicket)GetProcAddress(m_hGSS_API, "GetUserFromKrbTicket");
if (!pFzGss_ProcessCommand || !pFzGss_InitGSS || !pFzGss_KillGSS||
!pFzGss_DecryptMessage || !pFzGss_EncryptMessage || !pFzGss_EncryptData ||
!pFzGss_DecryptData ||
!pFzGss_DoClientAuth ||
!pFzGss_ProcessReply ||
!pFzGss_GetUserFromKrbTicket
)
{
return FALSE;
}
}
if (!bSpawned)
{
m_pData=new void*;
if (!pFzGss_InitGSS(m_pData, Callback, this, promptPassword))
{
UnLoadGSSLibrary();
return FALSE;
}
}
if (!bSpawned)
m_bInitialized = TRUE;
m_bUseGSS = TRUE;
return TRUE;
}
BOOL CAsyncGssSocketLayer::KillGSSData()
{
if (!m_bUseGSS)
return FALSE;
if (!m_bInitialized)
return TRUE;
m_bUseGSS = FALSE;
pFzGss_KillGSS(m_pData);
m_bInitialized = FALSE;
delete m_pData;
m_pData = NULL;
UnLoadGSSLibrary();
return TRUE;
}
BOOL CAsyncGssSocketLayer::InitTransferChannel(CAsyncGssSocketLayer *pSocket)
{
KillGSSData();
InitGSS(TRUE);
m_pData = pSocket->m_pData;
m_bUseGSS = pSocket->m_bUseGSS;
m_gotAuth = pSocket->m_gotAuth;
m_transfer = TRUE;
return TRUE;
}
void CAsyncGssSocketLayer::OnSend(int nErrorCode)
{
if (!m_nSendBufferLen)
TriggerEvent(FD_WRITE, nErrorCode, TRUE);
else
{
ASSERT(m_pSendBuffer);
int numsent = SendNext(m_pSendBuffer, m_nSendBufferLen, 0);
if (!numsent)
TriggerEvent(FD_CLOSE, nErrorCode, TRUE);
else if (numsent == SOCKET_ERROR)
{
if (GetLastError() != WSAEWOULDBLOCK)
TriggerEvent(FD_CLOSE, nErrorCode, TRUE);
}
else if (numsent != m_nSendBufferLen)
{
memmove(m_pSendBuffer, m_pSendBuffer + numsent, m_nSendBufferLen - numsent);
m_nSendBufferLen -= numsent;
}
else
{
m_nSendBufferLen = 0;
if (ShutDownComplete())
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_SHUTDOWN_COMPLETE, 0);
else
TriggerEvent(FD_WRITE, nErrorCode, TRUE);
}
}
}
BOOL CAsyncGssSocketLayer::ShutDown(int nHow /*=sends*/)
{
if (m_gotAuth == GSSAPI_AUTHENTICATION_SUCCEEDED && m_bUseGSS)
{
if (m_nShutDown)
{
if (m_nSendBufferLen)
return FALSE;
else
return TRUE;
}
m_nShutDown = 1;
char sendme[4096];
char *encBuffer = m_tmpBuffer;
int encBufferLen = 0;
encBufferLen = pFzGss_EncryptData(m_pData, encBuffer, 0, sendme);
if (!encBufferLen)
{
WSASetLastError(WSAENETDOWN);
return FALSE;
}
encBuffer[encBufferLen++] = '\r';
encBuffer[encBufferLen++] = '\n';
if (m_nSendBufferLen)
{
ASSERT(m_pSendBuffer);
int numsent = SendNext(m_pSendBuffer, m_nSendBufferLen, 0);
if (!numsent)
return TRUE;
else if (numsent == SOCKET_ERROR && GetLastError()!=WSAEWOULDBLOCK)
return TRUE;
else if (numsent != m_nSendBufferLen)
{
if (numsent == SOCKET_ERROR)
numsent = 0;
if (m_nSendBufferSize < (m_nSendBufferLen + encBufferLen))
{
char *tmp = m_pSendBuffer;
m_pSendBuffer = new char[m_nSendBufferSize + encBufferLen + 4096];
m_nSendBufferSize = m_nSendBufferSize + encBufferLen + 4096;
memcpy(m_pSendBuffer, tmp+numsent, m_nSendBufferLen-numsent);
delete [] tmp;
}
else
memmove(m_pSendBuffer, m_pSendBuffer + numsent, m_nSendBufferLen - numsent);
memcpy(m_pSendBuffer + m_nSendBufferLen-numsent, encBuffer, encBufferLen);
m_nSendBufferLen += encBufferLen-numsent;
WSASetLastError(WSAEWOULDBLOCK);
return FALSE;
}
else
m_nSendBufferLen = 0;
}
int numsent = SendNext(encBuffer, encBufferLen, 0);
if (!numsent)
return TRUE;
if (numsent == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
if (m_nSendBufferSize < encBufferLen)
{
delete [] m_pSendBuffer;
m_pSendBuffer = new char[encBufferLen * 2];
m_nSendBufferLen = encBufferLen * 2;
}
memcpy(m_pSendBuffer, encBuffer, encBufferLen);
m_nSendBufferLen = encBufferLen;
return FALSE;
}
return TRUE;
}
if (numsent != encBufferLen)
{
if (m_nSendBufferSize < encBufferLen)
{
delete [] m_pSendBuffer;
m_pSendBuffer = new char[encBufferLen * 2];
m_nSendBufferSize = encBufferLen * 2;
}
memcpy(m_pSendBuffer, encBuffer+numsent, encBufferLen-numsent);
m_nSendBufferLen = encBufferLen-numsent;
}
if (m_nSendBufferLen)
{
WSASetLastError(WSAEWOULDBLOCK);
return FALSE;
}
else
return TRUE;
}
else
return ShutDownNext();
}
BOOL CAsyncGssSocketLayer::ShutDownComplete()
{
//If a ShutDown was issued, has the connection already been shut down?
if (!m_nShutDown)
return FALSE;
else if (m_gotAuth != GSSAPI_AUTHENTICATION_SUCCEEDED || !m_bUseGSS)
return FALSE;
else if (m_nSendBufferLen)
return FALSE;
else
return TRUE;
}
int CAsyncGssSocketLayer::ProcessCommand(const char *command, const char *args, char *sendme)
{
ASSERT(command);
ASSERT(sendme);
if (!m_bUseGSS)
{
strcpy(sendme, "501 GSSAPI not initialized");
return -1;
}
char *argBuffer = m_tmpBuffer;
if ((strlen(args) + 1000) >= (1024*32))
argBuffer = new char[strlen(args) + 1000];
if (!strcmp(command, "ADAT"))
{
SOCKADDR_IN his_addr;
SOCKADDR_IN ctrl_addr;
int addrlen = sizeof (his_addr);
if (!GetPeerName((SOCKADDR*)&his_addr, &addrlen))
{
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
sprintf(sendme, "501 unable to getpeername");
return -1;
}
addrlen = sizeof (ctrl_addr);
if (!GetSockName((SOCKADDR*)&ctrl_addr, &addrlen))
{
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
sprintf(sendme, "501 unable to getsockname");
return -1;
}
char localname[513];
struct hostent *hp;
if (gethostname(localname, 512))
{
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
sprintf(sendme, "501 couldn't get local hostname (%d)", errno);
return -1;
}
hp = gethostbyname(localname);
if (!hp)
{
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
sprintf(sendme, "501 couldn't canonicalize local hostname");
return -1;
}
strncpy(localname, hp->h_name, sizeof(localname) - 1);
localname[sizeof(localname) - 1] = '\0';
memcpy(argBuffer, &his_addr.sin_addr.s_addr, 4);
memcpy(argBuffer+4, &ctrl_addr.sin_addr.s_addr, 4);
strcpy(argBuffer + 8, localname);
strcpy(argBuffer + 8 + strlen(localname) + 1, args);
}
else
strcpy(argBuffer, args);
int res = pFzGss_ProcessCommand(m_pData, command, argBuffer, sendme);
if (!strcmp(command, "ADAT") && res != -1)
{
m_nAwaitingReply = 3;
m_gotAuth = GSSAPI_AUTHENTICATION_SUCCEEDED;
}
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
return res;
}
BOOL CAsyncGssSocketLayer::AuthSuccessful() const
{
return m_gotAuth == GSSAPI_AUTHENTICATION_SUCCEEDED;
}
int CAsyncGssSocketLayer::ProcessCommand(const char *command, const char *args1, const char *args2, char *sendme)
{
ASSERT(command);
ASSERT(sendme);
if (!m_bUseGSS)
{
strcpy(sendme, "501 GSSAPI not initialized");
return -1;
}
char *argBuffer = m_tmpBuffer;
if ((strlen(args1) + strlen(args2) + 10) >= (1024*32))
argBuffer = new char[strlen(args1) + strlen(args2) + 10];
strcpy(argBuffer, args1);
strcpy(argBuffer + strlen(args1) + 1, args2);
int res = pFzGss_ProcessCommand(m_pData, command, argBuffer, sendme);
if (!strcmp(command, "ADAT") && res != -1)
m_gotAuth = GSSAPI_AUTHENTICATION_SUCCEEDED;
if (argBuffer != m_tmpBuffer)
delete [] argBuffer;
return res;
}
int CAsyncGssSocketLayer::GetClientAuth(const char* pHost)
{
if (m_hGSS_API)
{
char *hostname;
int res;
hostname = new char[strlen(pHost)+1];
strcpy(hostname, pHost);
memset(&m_myAddr, 0, sizeof(m_myAddr));
int SockAddrLen = sizeof(m_myAddr);
if (!GetPeerName(&m_myAddr, &SockAddrLen))
{
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_ERROR, (int)"GetAuth() GetPeerName() failed");
return FALSE;
}
memset(&m_hisAddr, 0, sizeof(m_hisAddr));
if (!GetSockName(&m_hisAddr, &SockAddrLen))
{
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_ERROR, (int)"GetAuth() GetSockName() failed");
return FALSE;
}
res = pFzGss_DoClientAuth(m_pData, hostname,
&m_myAddr,
&m_hisAddr,
'P', 0);
m_gotAuth = res;
if (m_gotAuth == -1)
m_gotAuth = 1;
delete [] hostname;
return res;
}
else
{
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_ERROR, (int)"GetClientAuth(933): GSS api not initialized!");
m_gotAuth = 0;//SEND_DATA_IN_THE_CLEAR;
}
return m_gotAuth;
}
void CAsyncGssSocketLayer::OnClose(int nErrorCode)
{
if (!m_nGssNetworkError)
m_nGssNetworkError = -1;
if (!nErrorCode)
OnReceive(0);
if (!m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_CLOSE, nErrorCode, TRUE);
}
int CALLBACK CAsyncGssSocketLayer::Callback(void *pData, int nParam1, int nParam2, int nParam3)
{
CAsyncGssSocketLayer *pLayer = reinterpret_cast<CAsyncGssSocketLayer *>(pData);
switch (nParam1)
{
case 0:
pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_INFO, nParam2);
break;
case 1:
{
char *buffer = (char *)nParam2;
int len = strlen(buffer);
if (nParam3)
{
pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_COMMAND, nParam3);
char *str = new char[strlen((char *)nParam2)+25];
sprintf(str, "Encrypted command: %s", (char *)nParam2);
pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_INFO, (int)str);
delete [] str;
}
else
pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_COMMAND, nParam2);
pLayer->m_nAwaitingReply = nParam3 ? 2:1;
if (!pLayer->m_pSendBuffer)
{
pLayer->m_pSendBuffer = new char[len + 4096];
pLayer->m_nSendBufferSize = len + 4096;
}
else if (pLayer->m_nSendBufferSize < (pLayer->m_nSendBufferLen + len + 2))
{
char *tmp = pLayer->m_pSendBuffer;
pLayer->m_pSendBuffer = new char[pLayer->m_nSendBufferLen + len + 4096];
pLayer->m_nSendBufferSize = pLayer->m_nSendBufferLen + len + 4096;
memcpy(pLayer->m_pSendBuffer, tmp, pLayer->m_nSendBufferLen);
delete [] tmp;
}
memcpy(pLayer->m_pSendBuffer+pLayer->m_nSendBufferLen, (char *)nParam2, len);
pLayer->m_pSendBuffer[pLayer->m_nSendBufferLen+len] = '\r';
pLayer->m_pSendBuffer[pLayer->m_nSendBufferLen+len+1] = '\n';
pLayer->m_nSendBufferLen += len + 2;
pLayer->TriggerEvent(FD_WRITE, 0);
break;
}
}
return 0;
}
void CAsyncGssSocketLayer::ReceiveReply()
{
if (m_nReceiveBufferSize < 4096)
{
delete [] m_pReceiveBuffer;
m_pReceiveBuffer = new char[4096];
m_nReceiveBufferSize = 4096;
}
char buffer;
int numread = ReceiveNext(&buffer, 1);
if (!numread)
{
m_nGssNetworkError = -1;
//Trigger OnClose()
TriggerEvent(FD_CLOSE, 0, TRUE);
return;
}
else if ( numread == SOCKET_ERROR )
{
if ( WSAGetLastError() != WSAEWOULDBLOCK )
{
m_nGssNetworkError = GetLastError();
TriggerEvent(FD_CLOSE, 0, TRUE);
}
else if (m_nDecryptedReceiveBufferLen)
TriggerEvent(FD_READ, 0, TRUE);
return;
}
if (buffer == 0 || buffer=='\r' || buffer=='\n')
{
if (!m_nReceiveBufferLen)
return;
m_nAwaitingReply = 0;
m_pReceiveBuffer[m_nReceiveBufferLen] = 0;
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_REPLY, (int)m_pReceiveBuffer);
int res = pFzGss_ProcessReply(m_pData, m_pReceiveBuffer);
m_nReceiveBufferLen = 0;
if (res == 1)
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_AUTHCOMPLETE, 0);
else if (res==-1)
return;
else
{
m_gotAuth = 0;
DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, GSS_AUTHFAILED, 0);
}
}
else if (m_nReceiveBufferLen < 4095)
m_pReceiveBuffer[m_nReceiveBufferLen++] = buffer;
}
BOOL CAsyncGssSocketLayer::GetUserFromKrbTicket(char *buffer)
{
if (!m_gotAuth || !m_bUseGSS || !m_pData || !pFzGss_GetUserFromKrbTicket)
return FALSE;
return pFzGss_GetUserFromKrbTicket(m_pData, buffer);
}