Server : Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6 System : Windows NT USER-PC 6.1 build 7601 (Windows 7 Professional Edition Service Pack 1) AMD64 User : User ( 0) PHP Version : 7.4.6 Disable Function : NONE Directory : C:/xampp/FileZillaFTP/source/ |
// 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); }