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.

1573 lines
44 KiB

  1. // RFCProto.cpp : This file contains the
  2. // Created: Feb '98
  3. // Author : a-rakeba
  4. // History:
  5. // Copyright (C) 1998 Microsoft Corporation
  6. // All rights reserved.
  7. // Microsoft Confidential
  8. #include <CmnHdr.h>
  9. #ifdef WHISTLER_BUILD
  10. #include "ntverp.h"
  11. #else
  12. #include <SolarVer.h>
  13. #endif //WHISTLER_BUILD
  14. #include <Common.ver>
  15. #include <RFCProto.h>
  16. #include <Debug.h>
  17. #include <FSM.h>
  18. #include <TelnetD.h>
  19. #include <Session.h>
  20. #include <Scraper.h>
  21. #include <vtnt.h>
  22. #pragma warning( disable: 4242 )
  23. #pragma warning( disable: 4127 )
  24. #pragma warning(disable: 4100)
  25. #pragma warning(disable: 4244)
  26. extern FSM_TRANSITION telnetTransTable[];
  27. extern FSM_TRANSITION subNegTransTable[];
  28. using namespace _Utils;
  29. using CDebugLevel::TRACE_DEBUGGING;
  30. using CDebugLevel::TRACE_HANDLE;
  31. using CDebugLevel::TRACE_SOCKET;
  32. COORD g_coCurPosOnClient = { 0, 3 };
  33. CRFCProtocol::CRFCProtocol()
  34. {
  35. fSubTermType = false;
  36. m_dwSubNawsByteNumber = 0;
  37. fSubAuth = false;
  38. m_wNTLMDataBufferIndex = 0;
  39. fSubNaws = false;
  40. m_fSubNawsFirstTime = true;
  41. m_dwExcludeTerm = 0;
  42. m_pSession = 0;
  43. SfuZeroMemory( m_remoteOptions, sizeof( m_remoteOptions ) );
  44. SfuZeroMemory( m_localOptions, sizeof( m_localOptions ) );
  45. m_fPasswordConcealMode = false;
  46. //optionCmd = ?
  47. //m_telnetState = ?
  48. //m_subNegState = ?
  49. m_fWaitingForResponseToA_DO_ForTO_ECHO = false;
  50. m_fWaitingForAResponseToA_WILL_ForTO_ECHO = false;;
  51. m_fWaitingForResponseToA_DO_ForTO_SGA = false;
  52. m_fWaitingForAResponseToA_WILL_ForTO_SGA = false;
  53. m_fWaitingForResponseToA_DO_ForTO_TXBINARY = false;
  54. m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY = false;
  55. m_fWaitingForResponseToA_DO_ForTO_TERMTYPE = false;
  56. m_fWaitingForAResponseToA_DO_ForTO_AUTH = false;
  57. m_fWaitingForResponseToA_DO_ForTO_NAWS = false;
  58. m_bIsUserNameProvided = false;
  59. m_fSubNewEnv = false;
  60. m_dwWhatVal = E_UNDEFINED;
  61. m_dwWhichVar = E_UNKNOWN;
  62. m_szCurrentEnvVariable[0] = 0;
  63. m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON = false;
  64. BuildFSMs();
  65. }
  66. CRFCProtocol::~CRFCProtocol()
  67. {
  68. }
  69. void
  70. CRFCProtocol::Init ( CSession* pSession )
  71. {
  72. _chASSERT( pSession != 0 );
  73. m_pSession = pSession;
  74. }
  75. bool
  76. CRFCProtocol::InitialNegotiation
  77. (
  78. )
  79. {
  80. UCHAR puchBuffer[1024];
  81. PUCHAR pCursor;
  82. INT bytes_to_write;
  83. pCursor = puchBuffer;
  84. m_pSession->CIoHandler::m_SocketControlState = CIoHandler::STATE_INIT;
  85. if( m_pSession->m_dwNTLMSetting != NO_NTLM )
  86. {
  87. // this is actually the place where we need to figure out if we can do
  88. // authentication and what kind. If there atleast one authentication type
  89. // available then we send the DO AUTH option to the client else we don't.
  90. // For now this checks for only NTLM auth. has to be made more generic in V2.
  91. if ( m_pSession->StartNTLMAuth() )
  92. {
  93. m_fWaitingForAResponseToA_DO_ForTO_AUTH = true;
  94. DO_OPTION( pCursor, TO_AUTH );
  95. pCursor += 3;
  96. }
  97. else
  98. {
  99. // since we don't have any security package the registry setting is
  100. //meaningless, we should just fall back to the username/password.
  101. m_pSession->m_dwNTLMSetting = NO_NTLM;
  102. }
  103. }
  104. m_fWaitingForAResponseToA_WILL_ForTO_ECHO = true;
  105. WILL_OPTION( pCursor, TO_ECHO );
  106. pCursor += 3;
  107. m_fWaitingForAResponseToA_WILL_ForTO_SGA = true;
  108. WILL_OPTION( pCursor, TO_SGA );
  109. pCursor += 3;
  110. m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON = true;
  111. DO_OPTION( pCursor, TO_NEW_ENVIRON );
  112. pCursor += 3;
  113. m_fWaitingForResponseToA_DO_ForTO_NAWS = true;
  114. DO_OPTION( pCursor, TO_NAWS );
  115. pCursor += 3;
  116. m_fWaitingForResponseToA_DO_ForTO_TXBINARY = true;
  117. DO_OPTION( pCursor, TO_TXBINARY );
  118. pCursor += 3;
  119. m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY = true;
  120. WILL_OPTION( pCursor, TO_TXBINARY );
  121. pCursor += 3;
  122. if( NO_NTLM == m_pSession->m_dwNTLMSetting )
  123. {
  124. m_pSession->CIoHandler::m_SocketControlState = CIoHandler::STATE_BANNER_FOR_AUTH;
  125. }
  126. //This is before we start writing anything on to the socket asyncronously.
  127. //So, writing to m_WriteToSocketBuff does not cause problem
  128. bytes_to_write = (INT) (pCursor - puchBuffer);
  129. if (bytes_to_write &&
  130. ((m_pSession->CIoHandler::m_dwWriteToSocketIoLength + bytes_to_write) < MAX_WRITE_SOCKET_BUFFER))
  131. {
  132. memcpy( m_pSession->CIoHandler::m_WriteToSocketBuff, puchBuffer, bytes_to_write);
  133. m_pSession->CIoHandler::m_dwWriteToSocketIoLength += bytes_to_write;
  134. return ( true );
  135. }
  136. return ( false );
  137. }
  138. // have to keep updating m_WriteToSocketBuffer while in Action() functions
  139. // have to set the IO response to WRITE_TO_SOCKET and somehow convey this
  140. // have to keep updating pButBack
  141. // have to finally update the lpdwIoSize
  142. CIoHandler::IO_OPERATIONS
  143. CRFCProtocol::ProcessDataReceivedOnSocket
  144. (
  145. LPDWORD lpdwIoSize
  146. )
  147. {
  148. #define TWO_K 2048
  149. CIoHandler::IO_OPERATIONS ioOpsToPerform = 0;
  150. LPBYTE pByte;
  151. LPBYTE pPutBack = m_pSession->CIoHandler::m_pReadFromSocketBufferCursor;
  152. DWORD dwLength = *lpdwIoSize;
  153. UCHAR szMsgBuf[TWO_K];
  154. UCHAR* p = szMsgBuf;
  155. szMsgBuf[0] = 0;
  156. INT tableIndex;
  157. for( pByte = m_pSession->CIoHandler::m_pReadFromSocketBufferCursor;
  158. pByte<(m_pSession->CIoHandler::m_pReadFromSocketBufferCursor + dwLength);
  159. ++pByte )
  160. {
  161. tableIndex = m_telnetFSM[ m_telnetState ][ *pByte ];
  162. if( (p - szMsgBuf) > TWO_K )
  163. {
  164. _TRACE( TRACE_DEBUGGING, "too much data; possible suspicious activity" );
  165. _chASSERT( 0 );
  166. }
  167. else
  168. {
  169. (this->*(telnetTransTable[ tableIndex ].pmfnAction))(&pPutBack,&p,*pByte);
  170. }
  171. m_telnetState = telnetTransTable[ tableIndex ].uchNextState;
  172. }
  173. DWORD dwMsgLen = p - szMsgBuf;
  174. if( dwMsgLen > 0 )
  175. {
  176. if (dwMsgLen > TWO_K)
  177. {
  178. dwMsgLen = TWO_K;
  179. }
  180. m_pSession->CIoHandler::WriteToSocket( szMsgBuf, dwMsgLen);
  181. ioOpsToPerform |= CIoHandler::WRITE_TO_SOCKET;
  182. }
  183. *lpdwIoSize = pPutBack - m_pSession->CIoHandler::m_pReadFromSocketBufferCursor;
  184. return ( ioOpsToPerform );
  185. #undef TWO_K
  186. }
  187. void CRFCProtocol::BuildFSMs( void )
  188. {
  189. FSMInit( m_telnetFSM, telnetTransTable, NUM_TS_STATES );
  190. m_telnetState = TS_DATA;
  191. FSMInit( m_subNegFSM, subNegTransTable, NUM_SS_STATES );
  192. m_subNegState = SS_START;
  193. }
  194. void
  195. CRFCProtocol::FSMInit
  196. (
  197. UCHAR fSM[][ NUM_CHARS ],
  198. void* transTable1,
  199. INT numStates
  200. )
  201. {
  202. FSM_TRANSITION* transTable = (FSM_TRANSITION*)transTable1;
  203. INT s, tableIndex, c;
  204. for( c = 0; c < NUM_CHARS; ++c)
  205. {
  206. for( tableIndex = 0; tableIndex < numStates; ++tableIndex )
  207. {
  208. fSM[ tableIndex ][ c ] = T_INVALID;
  209. }
  210. }
  211. for( tableIndex = 0; transTable[ tableIndex ].uchCurrState != FS_INVALID;
  212. ++tableIndex )
  213. {
  214. s = transTable[ tableIndex ].uchCurrState;
  215. if( transTable[ tableIndex ].wInputChar == TC_ANY )
  216. {
  217. for( c = 0; c < NUM_CHARS; ++c )
  218. {
  219. if( fSM[ s ][ c ] == T_INVALID )
  220. {
  221. fSM[ s ][ c ] = tableIndex;
  222. }
  223. }
  224. }
  225. else
  226. {
  227. fSM[ s ][ transTable[ tableIndex ].wInputChar ] = tableIndex;
  228. }
  229. }
  230. for( c = 0; c < NUM_CHARS; ++c)
  231. {
  232. for( tableIndex = 0; tableIndex < numStates; ++tableIndex )
  233. {
  234. if( fSM[ tableIndex ][ c ] == T_INVALID )
  235. {
  236. fSM[ tableIndex ][ c ] = 32;//tableIndex;
  237. }
  238. }
  239. }
  240. }
  241. void CRFCProtocol::NoOp( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  242. {
  243. _TRACE( TRACE_DEBUGGING, "NoOp()" );
  244. }
  245. void CRFCProtocol::GoAhead( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  246. {
  247. _TRACE( TRACE_DEBUGGING, "GoAhead()" );
  248. }
  249. void CRFCProtocol::EraseLine( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  250. {
  251. _TRACE( TRACE_DEBUGGING, "EraseLine()" );
  252. }
  253. void CRFCProtocol::EraseChar( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  254. {
  255. _TRACE( TRACE_DEBUGGING, "EraseChar()" );
  256. }
  257. #define INCREMENT_ROWS( rows, inc ) \
  258. { \
  259. rows += inc; \
  260. if( rows >= m_pSession->CSession::m_wRows ) \
  261. { \
  262. rows = m_pSession->CSession::m_wRows - 1;\
  263. wTypeOfCoords = RELATIVE_COORDS;\
  264. }\
  265. }
  266. #define INCREMENT_COLS( cols, inc ) \
  267. { \
  268. cols += inc;\
  269. if( cols >= m_pSession->CSession::m_wCols ) \
  270. {\
  271. cols = 0;\
  272. }\
  273. }
  274. #define IGNORE_0x0A_FOLLOWING_0x0D( dwIndex, dwDataLen ) \
  275. if( dwIndex < dwDataLen && rgchSessionData[ dwIndex -1 ] == L'\r' && rgchSessionData[ dwIndex] == L'\n' ) \
  276. { \
  277. dwIndex++; \
  278. }
  279. void CRFCProtocol::FillVtntHeader( UCHAR *pucBlob, WORD wTypeOfCoords,
  280. WORD wNoOfRows, WORD wNoOfCols,
  281. WORD wCurrenRowOnClient, WORD wCurrenColOnClient,
  282. SHORT *psCurrentCol,
  283. LPTSTR rgchSessionData, DWORD dwDataLen )
  284. {
  285. if( !pucBlob )
  286. {
  287. return;
  288. }
  289. //Fill the header
  290. VTNT_CHAR_INFO* pVTNTCharInfo = ( VTNT_CHAR_INFO* ) pucBlob;
  291. //csbi.wAttributes is filled by v2 server with following meaning
  292. //When a scrolling case is detected, this is set to 1.
  293. pVTNTCharInfo->csbi.wAttributes = wTypeOfCoords;
  294. pVTNTCharInfo->coDest.X = 0;
  295. pVTNTCharInfo->coDest.Y = 0;
  296. pVTNTCharInfo->coSizeOfData.Y = wNoOfRows;
  297. pVTNTCharInfo->coSizeOfData.X = wNoOfCols;
  298. pVTNTCharInfo->srDestRegion.Left = wCurrenColOnClient;
  299. pVTNTCharInfo->srDestRegion.Top = wCurrenRowOnClient;
  300. pVTNTCharInfo->srDestRegion.Right = pVTNTCharInfo->srDestRegion.Left + pVTNTCharInfo->coSizeOfData.X - 1;
  301. pVTNTCharInfo->srDestRegion.Bottom = wCurrenRowOnClient + pVTNTCharInfo->coSizeOfData.Y - 1;
  302. pVTNTCharInfo->coCursorPos.Y = pVTNTCharInfo->srDestRegion.Bottom;
  303. //Fill char info structs
  304. //iterate thru each character in the string
  305. //for each character store the corr. values in CHAR_INFO struct
  306. PCHAR_INFO pCharInfo = ( PCHAR_INFO )(pucBlob + sizeof( VTNT_CHAR_INFO ));
  307. DWORD dwIndex = 0;
  308. DWORD dwCtr = 0;
  309. DWORD dwSize = wNoOfRows * wNoOfCols;
  310. WORD wLastNonSpaceCol = 0;
  311. while( dwCtr < dwSize )
  312. {
  313. if( dwIndex >= dwDataLen )
  314. {
  315. if( !wLastNonSpaceCol )
  316. {
  317. wLastNonSpaceCol = dwCtr;
  318. }
  319. pCharInfo[dwCtr].Char.UnicodeChar = L' ';
  320. }
  321. else
  322. {
  323. if( rgchSessionData[ dwIndex ] == L'\t' )
  324. {
  325. rgchSessionData[ dwIndex ] = L' ';
  326. }
  327. else if( rgchSessionData[ dwIndex ] == L'\r' )
  328. {
  329. rgchSessionData[ dwIndex ] = L' ';
  330. while ( dwCtr < dwSize - 1 && ( ( dwCtr + 1 ) % wNoOfCols != 0 || dwCtr == 0 ) )
  331. {
  332. pCharInfo[dwCtr].Char.UnicodeChar = L' ';
  333. pCharInfo[dwCtr].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  334. dwCtr++;
  335. }
  336. }
  337. else if( rgchSessionData[ dwIndex ] == L'\n' )
  338. {
  339. dwIndex++;
  340. continue;
  341. }
  342. pCharInfo[dwCtr].Char.UnicodeChar = rgchSessionData[ dwIndex ];
  343. }
  344. pCharInfo[dwCtr].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  345. dwIndex++;
  346. dwCtr++;
  347. }
  348. if( !wLastNonSpaceCol )
  349. {
  350. wLastNonSpaceCol = dwCtr;
  351. }
  352. pVTNTCharInfo->coCursorPos.X = ( wCurrenColOnClient + wLastNonSpaceCol ) % m_pSession->CSession::m_wCols;
  353. if( psCurrentCol )
  354. {
  355. *psCurrentCol = pVTNTCharInfo->coCursorPos.X;
  356. }
  357. }
  358. //caller gets data blob and its size
  359. //this needs to sent to the client
  360. //caller needs to free memory
  361. /*
  362. The following routine is primarily used for stream mode and vtnt.
  363. cmd outputs a stream of ascii chars. When in vtnt, the client expects VTNT_CHAR_INFO structs.
  364. The chars should be in the form of rectangles of console screen.
  365. So, This routine does this conversion. For this,
  366. 1)We need to keep track of cursor position on client
  367. 2)Know For any given bloc of data whether to start on a new row on client or on the current row
  368. We break the data from cmd into two rectangle.
  369. 1) rectagle on the current row of breadth 1 ( one row rectangle )
  370. 2) rectangle from next row onwards ( second rectangle )
  371. */
  372. bool
  373. CRFCProtocol::StrToVTNTResponse
  374. (
  375. LPSTR rgchData,
  376. DWORD dwDataSize,
  377. VOID** ppResponse,
  378. DWORD* pdwSize
  379. )
  380. {
  381. _TRACE( TRACE_DEBUGGING, "StrToVTNTResponse()" );
  382. DWORD dwIndex = 0;
  383. COORD coRectSize = { m_pSession->CSession::m_wCols, 0 }; //size of the rectagular data
  384. WORD wNoOfColsOnCurrentRow = 0;
  385. WORD wSpacesInserted = 0;
  386. LPTSTR rgchSessionData = 0;
  387. DWORD dwDataLen = 0;
  388. static WORD wTypeOfCoords = ABSOLUTE_COORDS;
  389. if( rgchData == NULL || pdwSize == NULL || ppResponse == NULL )
  390. {
  391. return ( false );
  392. }
  393. dwDataLen = MultiByteToWideChar( GetConsoleCP(), 0, rgchData, dwDataSize, NULL, 0 );
  394. rgchSessionData = new WCHAR[ dwDataLen ];
  395. if( !rgchSessionData )
  396. {
  397. return false;
  398. }
  399. MultiByteToWideChar( GetConsoleCP(), 0, rgchData, dwDataSize, rgchSessionData, dwDataLen );
  400. //make one pass over the stream from cmd to find the amt of space needed to hold converted VTNT data
  401. dwIndex = 0;
  402. //Find number of chars on to the current row. ie; on the one row rectangle
  403. while( dwIndex < dwDataLen && //Size of data
  404. g_coCurPosOnClient.X + ( WORD )dwIndex < coRectSize.X && //In a single row on client
  405. rgchSessionData[ dwIndex ] != L'\r' && //Not new line
  406. g_coCurPosOnClient.X !=0
  407. )
  408. {
  409. dwIndex ++;
  410. IGNORE_0x0A_FOLLOWING_0x0D( dwIndex, dwDataLen );
  411. }
  412. wNoOfColsOnCurrentRow = dwIndex;
  413. if( g_coCurPosOnClient.X !=0 && rgchSessionData[ dwIndex ] == L'\r' )
  414. {
  415. dwIndex++;
  416. IGNORE_0x0A_FOLLOWING_0x0D( dwIndex, dwDataLen );
  417. wNoOfColsOnCurrentRow = coRectSize.X - g_coCurPosOnClient.X;
  418. wSpacesInserted = wNoOfColsOnCurrentRow - ( dwIndex - 1 );
  419. }
  420. //Find the number of rows
  421. while( dwIndex < dwDataLen )
  422. {
  423. WORD wCol = 0;
  424. while( dwIndex + wCol < dwDataLen &&
  425. rgchSessionData[ dwIndex + wCol ] != L'\r' &&
  426. wCol < coRectSize.X )
  427. {
  428. wCol++;
  429. }
  430. dwIndex += wCol;
  431. dwIndex++;
  432. coRectSize.Y++;
  433. IGNORE_0x0A_FOLLOWING_0x0D( dwIndex, dwDataLen );
  434. }
  435. int size = 0;
  436. if( wNoOfColsOnCurrentRow > 0 )
  437. {
  438. //size for one row rectangle
  439. size += sizeof( VTNT_CHAR_INFO ) + sizeof( CHAR_INFO ) * wNoOfColsOnCurrentRow;
  440. }
  441. if( coRectSize.Y > 0 )
  442. {
  443. //size for rest of rectangle
  444. size += sizeof( VTNT_CHAR_INFO ) + sizeof( CHAR_INFO ) * coRectSize.Y * coRectSize.X;
  445. }
  446. UCHAR* pucBlob = new UCHAR[ size ];
  447. UCHAR* pucBlobHead = pucBlob;
  448. if( !pucBlob )
  449. {
  450. _chASSERT( 0 );
  451. goto ExitOnError;
  452. }
  453. SfuZeroMemory( pucBlob, size );
  454. if( wNoOfColsOnCurrentRow > 0 )
  455. {
  456. //Fill one row rectangle
  457. FillVtntHeader( pucBlob, wTypeOfCoords,
  458. 1, wNoOfColsOnCurrentRow,
  459. g_coCurPosOnClient.Y, g_coCurPosOnClient.X,
  460. NULL,
  461. rgchSessionData, wNoOfColsOnCurrentRow );
  462. INCREMENT_COLS( g_coCurPosOnClient.X, wNoOfColsOnCurrentRow );
  463. pucBlob += sizeof( VTNT_CHAR_INFO ) + sizeof( CHAR_INFO ) * wNoOfColsOnCurrentRow;
  464. }
  465. if( coRectSize.Y > 0 )
  466. {
  467. //Fill second rectangle
  468. if( g_coCurPosOnClient.Y != 0 )
  469. {
  470. g_coCurPosOnClient.Y++;
  471. }
  472. FillVtntHeader( pucBlob, wTypeOfCoords,
  473. coRectSize.Y, coRectSize.X,
  474. g_coCurPosOnClient.Y, 0,
  475. &g_coCurPosOnClient.X,
  476. rgchSessionData+wNoOfColsOnCurrentRow-wSpacesInserted,
  477. dwDataLen - ( wNoOfColsOnCurrentRow-wSpacesInserted ) );
  478. INCREMENT_ROWS( g_coCurPosOnClient.Y, coRectSize.Y - 1 );
  479. }
  480. *ppResponse = (VOID*) pucBlobHead;
  481. *pdwSize = size;
  482. delete[] rgchSessionData;
  483. return ( true );
  484. ExitOnError:
  485. delete[] rgchSessionData;
  486. return ( false );
  487. }
  488. void CRFCProtocol::AreYouThere( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  489. {
  490. _TRACE( TRACE_DEBUGGING, "AreYouThere()" );
  491. if( !m_pSession->CSession::m_bIsStreamMode &&
  492. m_pSession->CIoHandler::m_SocketControlState == m_pSession->CIoHandler::STATE_SESSION )
  493. {
  494. m_pSession->CScraper::WriteMessageToCmd( L"\r\nYES\r\n" );
  495. }
  496. else
  497. {
  498. if( _strcmpi( VTNT, m_pSession->CSession::m_pszTermType ) == 0 )
  499. {
  500. DWORD dwSize = 0;
  501. PCHAR pResponse = NULL;
  502. if( !StrToVTNTResponse( " YES ", strlen( " YES " ), (VOID**) &pResponse, &dwSize ) )
  503. {
  504. return;
  505. }
  506. if( !pResponse || (dwSize == 0) )
  507. {
  508. return;
  509. }
  510. memcpy( *pBuffer, pResponse, dwSize ); // Don't know size of pBuffer, Baskar. Attack ?
  511. *pBuffer += dwSize;
  512. delete [] pResponse;
  513. }
  514. else
  515. {
  516. (*pBuffer)[0] = '\r';
  517. (*pBuffer)[1] = '\n';
  518. (*pBuffer)[2] = '[';
  519. (*pBuffer)[3] = 'Y';
  520. (*pBuffer)[4] = 'e';
  521. (*pBuffer)[5] = 's';
  522. (*pBuffer)[6] = ']';
  523. (*pBuffer)[7] = '\r';
  524. (*pBuffer)[8] = '\n';
  525. (*pBuffer)[9] = 0;
  526. *pBuffer += 9;
  527. }
  528. }
  529. }
  530. void CRFCProtocol::AbortOutput( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  531. {
  532. _TRACE( TRACE_DEBUGGING, "AbortOutput()" );
  533. }
  534. void CRFCProtocol::InterruptProcess( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b)
  535. {
  536. _TRACE( TRACE_DEBUGGING, "InterruptProcess()" );
  537. _chVERIFY2( GenerateConsoleCtrlEvent( CTRL_C_EVENT, 0 ) );
  538. }
  539. void CRFCProtocol::Break( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  540. {
  541. _TRACE( TRACE_DEBUGGING, "Break()" );
  542. _chVERIFY2( GenerateConsoleCtrlEvent( CTRL_C_EVENT, 0 ) );
  543. }
  544. void CRFCProtocol::DataMark( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  545. {
  546. // basically a no op for now
  547. _TRACE( TRACE_DEBUGGING, "DataMark()" );
  548. }
  549. void CRFCProtocol::PutBack( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  550. {
  551. _TRACE( TRACE_DEBUGGING, "PutBack()" );
  552. *( *ppPutBack ) = b;
  553. (*ppPutBack)++;
  554. }
  555. void CRFCProtocol::RecordOption( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  556. {
  557. _TRACE( TRACE_DEBUGGING, "RecordOption()" );
  558. m_optionCmd = b;
  559. }
  560. void CRFCProtocol::Abort( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  561. {
  562. // basically a no op for now
  563. _TRACE( TRACE_DEBUGGING, "Abort()" );
  564. }
  565. void CRFCProtocol::WillNotSup( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  566. {
  567. //DO, DONT logic
  568. _TRACE( TRACE_DEBUGGING, "WillNotSup() - %d ", b );
  569. if( m_optionCmd == TC_DO )
  570. {
  571. if( m_localOptions[ b ] == ENABLED )
  572. {
  573. }
  574. else
  575. {
  576. PUCHAR p = *pBuffer;
  577. WONT_OPTION( p, b );
  578. *pBuffer += 3;
  579. }
  580. }
  581. else if( m_optionCmd == TC_DONT )
  582. {
  583. if( m_localOptions[ b ] == ENABLED )
  584. {
  585. m_localOptions[ b ] = DISABLED;
  586. }
  587. else
  588. {
  589. }
  590. }
  591. }
  592. void CRFCProtocol::DoNotSup( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  593. {
  594. //WILL, WONT logic
  595. _TRACE( TRACE_DEBUGGING, "DoNotSup() - %d ", b );
  596. if( m_optionCmd == TC_WILL )
  597. {
  598. if( m_remoteOptions[ b ] == ENABLED )
  599. {
  600. }
  601. else
  602. {
  603. PUCHAR p = *pBuffer;
  604. DONT_OPTION( p, b );
  605. *pBuffer += 3;
  606. }
  607. }
  608. else if( m_optionCmd == TC_WONT )
  609. {
  610. if( m_remoteOptions[ b ] == ENABLED )
  611. {
  612. m_remoteOptions[ b ] = DISABLED;
  613. }
  614. else
  615. {
  616. }
  617. }
  618. return;
  619. }
  620. void CRFCProtocol::DoEcho( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  621. {
  622. //WILL, WONT logic
  623. _TRACE( TRACE_DEBUGGING, "DoEcho()" );
  624. if( m_optionCmd == TC_WILL )
  625. {
  626. if( m_remoteOptions[ b ] == ENABLED )
  627. {
  628. }
  629. else if( m_fWaitingForResponseToA_DO_ForTO_ECHO )
  630. {
  631. m_remoteOptions[ b ] = ENABLED;
  632. m_fWaitingForResponseToA_DO_ForTO_ECHO = false;
  633. }
  634. else
  635. {
  636. m_remoteOptions[ b ] = ENABLED;
  637. PUCHAR p = *pBuffer;
  638. DO_OPTION( p, b );
  639. *pBuffer += 3;
  640. m_fWaitingForResponseToA_DO_ForTO_ECHO = true;
  641. }
  642. }
  643. else if( m_optionCmd == TC_WONT )
  644. {
  645. if( m_fWaitingForResponseToA_DO_ForTO_ECHO )
  646. {
  647. m_fWaitingForResponseToA_DO_ForTO_ECHO = false;
  648. }
  649. else if( m_remoteOptions[ b ] == ENABLED )
  650. {
  651. m_remoteOptions[ b ] = DISABLED;
  652. }
  653. else
  654. {
  655. }
  656. }
  657. return;
  658. }
  659. void CRFCProtocol::DoNaws( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  660. {
  661. //WILL, WONT logic
  662. _TRACE( TRACE_DEBUGGING, "DoNaws()" );
  663. if( m_optionCmd == TC_WILL )
  664. {
  665. if( m_remoteOptions[ b ] == ENABLED )
  666. {
  667. }
  668. else if( m_fWaitingForResponseToA_DO_ForTO_NAWS )
  669. {
  670. m_remoteOptions[ b ] = ENABLED;
  671. m_fWaitingForResponseToA_DO_ForTO_NAWS = false;
  672. }
  673. else
  674. {
  675. PUCHAR p = *pBuffer;
  676. DO_OPTION( p, b );
  677. *pBuffer += 3;
  678. m_fWaitingForResponseToA_DO_ForTO_NAWS = true;
  679. m_remoteOptions[ b ] = ENABLED;
  680. }
  681. }
  682. else if( m_optionCmd == TC_WONT )
  683. {
  684. if( m_fWaitingForResponseToA_DO_ForTO_NAWS )
  685. {
  686. m_fWaitingForResponseToA_DO_ForTO_NAWS = false;
  687. }
  688. else if( m_remoteOptions[ b ] == ENABLED )
  689. {
  690. m_remoteOptions[ b ] = DISABLED;
  691. }
  692. else
  693. {
  694. }
  695. }
  696. return;
  697. }
  698. void CRFCProtocol::DoSuppressGA( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  699. {
  700. //WILL, WONT logic
  701. _TRACE( TRACE_DEBUGGING, "DoSuppressGA()" );
  702. if( m_optionCmd == TC_WILL )
  703. {
  704. if( m_remoteOptions[ b ] == ENABLED )
  705. {
  706. }
  707. else if( m_fWaitingForResponseToA_DO_ForTO_SGA )
  708. {
  709. m_remoteOptions[ b ] = ENABLED;
  710. m_fWaitingForResponseToA_DO_ForTO_SGA = false;
  711. }
  712. else
  713. {
  714. m_remoteOptions[ b ] = ENABLED;
  715. PUCHAR p = *pBuffer;
  716. DO_OPTION( p, b );
  717. *pBuffer += 3;
  718. m_fWaitingForResponseToA_DO_ForTO_SGA = true;
  719. }
  720. }
  721. else if( m_optionCmd == TC_WONT )
  722. {
  723. if( m_fWaitingForResponseToA_DO_ForTO_SGA )
  724. {
  725. m_fWaitingForResponseToA_DO_ForTO_SGA = false;
  726. }
  727. else if( m_remoteOptions[ b ] == ENABLED )
  728. {
  729. m_remoteOptions[ b ] = DISABLED;
  730. }
  731. else
  732. {
  733. }
  734. }
  735. }
  736. void CRFCProtocol::DoTxBinary( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  737. {
  738. //WILL, WONT logic
  739. _TRACE( TRACE_DEBUGGING, "DoTxBinary()" );
  740. if( m_optionCmd == TC_WILL )
  741. {
  742. if( m_remoteOptions[ b ] == ENABLED )
  743. {
  744. }
  745. else if( m_fWaitingForResponseToA_DO_ForTO_TXBINARY )
  746. {
  747. m_remoteOptions[ b ] = ENABLED;
  748. m_fWaitingForResponseToA_DO_ForTO_TXBINARY = false;
  749. }
  750. else
  751. {
  752. m_remoteOptions[ b ] = ENABLED;
  753. PUCHAR p = *pBuffer;
  754. DO_OPTION( p, b );
  755. *pBuffer += 3;
  756. m_fWaitingForResponseToA_DO_ForTO_TXBINARY = true;
  757. }
  758. }
  759. else if( m_optionCmd == TC_WONT )
  760. {
  761. if( m_fWaitingForResponseToA_DO_ForTO_TXBINARY )
  762. {
  763. m_fWaitingForResponseToA_DO_ForTO_TXBINARY = false;
  764. }
  765. else if( m_remoteOptions[ b ] == ENABLED )
  766. {
  767. m_remoteOptions[ b ] = DISABLED;
  768. }
  769. else
  770. {
  771. }
  772. DisAllowVtnt( pBuffer );
  773. }
  774. }
  775. void CRFCProtocol::AskForSendingNewEnviron( PUCHAR* pBuffer )
  776. {
  777. if( m_remoteOptions[ TO_NEW_ENVIRON ] == ENABLED )
  778. {
  779. DWORD dwLen = 0;
  780. //dwLen will be incremented by the macro and will leave
  781. //it with exact number of bytes used
  782. DO_NEW_ENVIRON_SUB_NE( (*pBuffer ), TO_NEW_ENVIRON, dwLen );
  783. *pBuffer += dwLen;
  784. //This is broken into 2 sub negos for supporting linux.
  785. //When we ask, user, sfutlntvar, sfutlntmode variables in single shot, it
  786. // is not giving data about even user. So, ask in 2 phases.
  787. dwLen = 0;
  788. DO_NEW_ENVIRON_SUB_NE_MY_VARS( (*pBuffer ), TO_NEW_ENVIRON, dwLen );
  789. *pBuffer += dwLen;
  790. }
  791. }
  792. void CRFCProtocol::AskForSendingTermType( PUCHAR* pBuffer )
  793. {
  794. if( m_remoteOptions[ TO_TERMTYPE ] == ENABLED )
  795. {
  796. DO_TERMTYPE_SUB_NE( (*pBuffer ) );
  797. *pBuffer += 6;
  798. }
  799. }
  800. void CRFCProtocol::DoNewEnviron( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  801. {
  802. //WILL, WONT logic
  803. _TRACE( TRACE_DEBUGGING, "DoNewEnviron()" );
  804. if( m_optionCmd == TC_WILL )
  805. {
  806. if( m_remoteOptions[ b ] == ENABLED )
  807. {
  808. }
  809. else if( m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON )
  810. {
  811. m_remoteOptions[ b ] = ENABLED;
  812. m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON = false;
  813. AskForSendingNewEnviron( pBuffer );
  814. }
  815. else
  816. {
  817. // Some clients are pro active, they tell us that they WILL Terminal type.
  818. PUCHAR p = *pBuffer;
  819. DO_OPTION( p, b );
  820. *pBuffer += 3;
  821. m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON = true;
  822. m_remoteOptions[ b ] = ENABLED;
  823. }
  824. }
  825. else if( m_optionCmd == TC_WONT )
  826. {
  827. //Give login prompt. No way of getting user name
  828. SubNewEnvShowLoginPrompt( ppPutBack, pBuffer, b );
  829. if( m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON )
  830. {
  831. m_fWaitingForResponseToA_DO_ForTO_NEWENVIRON = false;
  832. }
  833. else if( m_remoteOptions[ b ] == ENABLED )
  834. {
  835. m_remoteOptions[ b ] = DISABLED;
  836. }
  837. else
  838. {
  839. }
  840. }
  841. return;
  842. }
  843. void CRFCProtocol::SubNewEnvShowLoginPrompt( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  844. {
  845. m_pSession->CIoHandler::m_bWaitForEnvOptionOver = true;
  846. }
  847. void CRFCProtocol::DoTermType( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  848. {
  849. //WILL, WONT logic
  850. _TRACE( TRACE_DEBUGGING, "DoTermType()" );
  851. if( m_optionCmd == TC_WILL )
  852. {
  853. if( m_remoteOptions[ b ] == ENABLED )
  854. {
  855. }
  856. else if( m_fWaitingForResponseToA_DO_ForTO_TERMTYPE )
  857. {
  858. m_remoteOptions[ b ] = ENABLED;
  859. m_fWaitingForResponseToA_DO_ForTO_TERMTYPE = false;
  860. AskForSendingTermType( pBuffer );
  861. }
  862. else
  863. {
  864. // Some clients are pro active, they tell us that they WILL Terminal type.
  865. PUCHAR p = *pBuffer;
  866. DO_OPTION( p, b );
  867. *pBuffer += 3;
  868. m_remoteOptions[ b ] = ENABLED;
  869. m_fWaitingForResponseToA_DO_ForTO_TERMTYPE = false;
  870. }
  871. }
  872. else if( m_optionCmd == TC_WONT )
  873. {
  874. if( m_fWaitingForResponseToA_DO_ForTO_TERMTYPE )
  875. {
  876. m_fWaitingForResponseToA_DO_ForTO_TERMTYPE = false;
  877. // we default to vt100.
  878. strncpy( m_pSession->CSession::m_pszTermType, VT100, (sizeof(m_pSession->CSession::m_pszTermType) - 1));
  879. m_pSession->CSession::m_bIsStreamMode = true;//Set it to stream mode
  880. // set a flag to continue the telnet session
  881. m_pSession->CSession::m_bNegotiatedTermType = true;
  882. }
  883. else if( m_remoteOptions[ b ] == ENABLED )
  884. {
  885. m_remoteOptions[ b ] = DISABLED;
  886. // theoretically should never happen. because once this option
  887. // is enabled it should never be disabled.
  888. _chASSERT(0);
  889. }
  890. else
  891. {
  892. }
  893. }
  894. }
  895. void CRFCProtocol::DoAuthentication( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  896. {
  897. //WILL, WONT logic
  898. _TRACE( TRACE_DEBUGGING, "DoAuthentication()" );
  899. if( m_optionCmd == TC_WILL )
  900. {
  901. if( m_remoteOptions[ b ] == ENABLED )
  902. {
  903. }
  904. else if( m_fWaitingForAResponseToA_DO_ForTO_AUTH )
  905. {
  906. m_remoteOptions[ b ] = ENABLED;
  907. if ( m_pSession->CIoHandler::m_SocketControlState == CIoHandler::STATE_INIT )
  908. {
  909. m_pSession->CIoHandler::m_SocketControlState = CIoHandler::STATE_NTLMAUTH;
  910. }
  911. PUCHAR p = *pBuffer;
  912. DO_AUTH_SUB_NE_NTLM(p);
  913. *pBuffer += 8;
  914. m_fWaitingForAResponseToA_DO_ForTO_AUTH = false;
  915. }
  916. else
  917. {
  918. //presently, this should not happen
  919. }
  920. }
  921. else if( m_optionCmd == TC_WONT )
  922. {
  923. if( m_fWaitingForAResponseToA_DO_ForTO_AUTH )
  924. {
  925. m_fWaitingForAResponseToA_DO_ForTO_AUTH = false;
  926. if( m_pSession->m_dwNTLMSetting == NTLM_ONLY )
  927. {
  928. char *p = (char *)*pBuffer;
  929. sprintf(p, "%s%s", NTLM_ONLY_STR, TERMINATE); // Don't know the size of pbuffer here -- Baskar, Attack ?
  930. *pBuffer += strlen(p);
  931. m_pSession->CIoHandler::m_SocketControlState = CIoHandler::STATE_TERMINATE;
  932. m_pSession->CIoHandler::m_fShutDownAfterIO = true;
  933. }
  934. if ( m_pSession->CIoHandler::m_SocketControlState == CIoHandler::STATE_INIT )
  935. {
  936. m_pSession->CIoHandler::m_SocketControlState = CIoHandler::STATE_BANNER_FOR_AUTH;
  937. }
  938. }
  939. else if( m_remoteOptions[ b ] == ENABLED )
  940. {
  941. m_remoteOptions[ b ] = DISABLED;
  942. // theoretically should never happen. because once this option
  943. // is enabled it should never be disabled. Since server initiates
  944. // the negotiation and currently our server never re-negotiates.
  945. _chASSERT(0);
  946. }
  947. else
  948. {
  949. }
  950. }
  951. }
  952. void CRFCProtocol::WillTxBinary( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  953. {
  954. // DO, DONT logic
  955. _TRACE( TRACE_DEBUGGING, "WillTxBinary()" );
  956. if( m_optionCmd == TC_DO )
  957. {
  958. if( m_localOptions[ b ] == ENABLED )
  959. {
  960. }
  961. else if( m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY )
  962. {
  963. m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY = false;
  964. m_localOptions[ b ] = ENABLED;
  965. }
  966. else
  967. {
  968. //I want to enable this option
  969. PUCHAR p = *pBuffer;
  970. WILL_OPTION( p, b );
  971. *pBuffer += 3;
  972. m_localOptions[ b ] = ENABLED;
  973. }
  974. }
  975. else if( m_optionCmd == TC_DONT )
  976. {
  977. if( m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY )
  978. {
  979. m_fWaitingForAResponseToA_WILL_ForTO_TXBINARY = false;
  980. }
  981. else if( m_localOptions[ b ] == ENABLED )
  982. {
  983. m_localOptions[ b ] = DISABLED;
  984. }
  985. else
  986. {
  987. }
  988. DisAllowVtnt( pBuffer );
  989. }
  990. }
  991. void CRFCProtocol::DisAllowVtnt( PUCHAR *pBuffer )
  992. {
  993. //Bug:1003 - VTNT no BINARY mode
  994. //Check if Term type is VTNT. If so, renegotiate termtype.
  995. //Now that binary is nomore, VTNT is not an option. VTNT needs binary.
  996. if( !( m_dwExcludeTerm & TERMVTNT ) )
  997. {
  998. m_dwExcludeTerm = TERMVTNT;
  999. if( _strcmpi( m_pSession->CSession::m_pszTermType, VTNT ) == 0 )
  1000. {
  1001. //re negotiation of term type
  1002. AskForSendingTermType( pBuffer );
  1003. }
  1004. }
  1005. }
  1006. void CRFCProtocol::WillSuppressGA( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1007. {
  1008. // DO, DONT logic
  1009. _TRACE( TRACE_DEBUGGING, "WillSuppressGA()" );
  1010. if( m_optionCmd == TC_DO )
  1011. {
  1012. if( m_localOptions[ b ] == ENABLED )
  1013. {
  1014. }
  1015. else if( m_fWaitingForAResponseToA_WILL_ForTO_SGA )
  1016. {
  1017. m_fWaitingForAResponseToA_WILL_ForTO_SGA = false;
  1018. m_localOptions[ b ] = ENABLED;
  1019. }
  1020. else
  1021. {
  1022. //I want to enable this option
  1023. PUCHAR p = *pBuffer;
  1024. WILL_OPTION( p, b );
  1025. *pBuffer += 3;
  1026. m_localOptions[ b ] = ENABLED;
  1027. }
  1028. }
  1029. else if( m_optionCmd == TC_DONT )
  1030. {
  1031. if( m_fWaitingForAResponseToA_WILL_ForTO_SGA )
  1032. {
  1033. m_fWaitingForAResponseToA_WILL_ForTO_SGA = false;
  1034. }
  1035. else if( m_localOptions[ b ] == ENABLED )
  1036. {
  1037. m_localOptions[ b ] = DISABLED;
  1038. }
  1039. else
  1040. {
  1041. }
  1042. }
  1043. }
  1044. void CRFCProtocol::WillEcho( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1045. {
  1046. // DO, DONT logic
  1047. _TRACE( TRACE_DEBUGGING, "WillEcho()" );
  1048. if( m_optionCmd == TC_DO )
  1049. {
  1050. if( m_localOptions[ b ] == ENABLED )
  1051. {
  1052. }
  1053. else if( m_fWaitingForAResponseToA_WILL_ForTO_ECHO )
  1054. {
  1055. m_fWaitingForAResponseToA_WILL_ForTO_ECHO = false;
  1056. m_localOptions[ b ] = ENABLED;
  1057. }
  1058. else
  1059. {
  1060. //I want to enable this option
  1061. PUCHAR p = *pBuffer;
  1062. WILL_OPTION( p, b );
  1063. *pBuffer += 3;
  1064. m_localOptions[ b ] = ENABLED;
  1065. }
  1066. }
  1067. else if( m_optionCmd == TC_DONT )
  1068. {
  1069. if( m_fWaitingForAResponseToA_WILL_ForTO_ECHO )
  1070. {
  1071. m_fWaitingForAResponseToA_WILL_ForTO_ECHO = false;
  1072. }
  1073. else if( m_localOptions[ b ] == ENABLED )
  1074. {
  1075. m_localOptions[ b ] = DISABLED;
  1076. }
  1077. else
  1078. {
  1079. }
  1080. }
  1081. }
  1082. void CRFCProtocol::SubOption( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1083. {
  1084. INT tableIndex = m_subNegFSM[ m_subNegState ][ b ];
  1085. if( subNegTransTable[ tableIndex ].pmfnAction )
  1086. {
  1087. (this->*(subNegTransTable[ tableIndex ].pmfnAction))(ppPutBack, pBuffer, b);
  1088. m_subNegState = subNegTransTable[ tableIndex ].uchNextState;
  1089. }
  1090. else
  1091. {
  1092. /*Should not happen */
  1093. _chASSERT( 0 );
  1094. }
  1095. }
  1096. void CRFCProtocol::FindVariable()
  1097. {
  1098. m_dwWhichVar = E_UNKNOWN;
  1099. if( _strcmpi( m_szCurrentEnvVariable, USER ) == 0 )
  1100. {
  1101. m_dwWhichVar = E_USER;
  1102. }
  1103. else if( _strcmpi( m_szCurrentEnvVariable, SFUTLNTVER ) == 0 )
  1104. {
  1105. m_dwWhichVar = E_SFUTLNTVER;
  1106. }
  1107. else if( _strcmpi( m_szCurrentEnvVariable, SFUTLNTMODE ) == 0 )
  1108. {
  1109. m_dwWhichVar = E_SFUTLNTMODE;
  1110. }
  1111. else
  1112. {
  1113. }
  1114. }
  1115. void CRFCProtocol::SubNewEnvGetValue( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1116. {
  1117. if( m_dwWhatVal == E_UNDEFINED )
  1118. {
  1119. FindVariable();
  1120. m_szCurrentEnvVariable[0] = 0;
  1121. }
  1122. /* Here,
  1123. if m_szCurrentEnvVariable[0] != 0, variable has value as in m_szCurrentEnvVariable[0]
  1124. else it has value as in m_dwWhatVal */
  1125. switch( m_dwWhichVar )
  1126. {
  1127. case E_USER:
  1128. {
  1129. m_bIsUserNameProvided = true;
  1130. strncpy(m_pSession->CSession::m_pszUserName, m_szCurrentEnvVariable, (sizeof(m_pSession->CSession::m_pszUserName) - 1));
  1131. }
  1132. break;
  1133. case E_SFUTLNTVER:
  1134. //set by default to current version
  1135. if( _strcmpi( m_szCurrentEnvVariable, VERSION1 ) == 0 )
  1136. {
  1137. ;// version 1
  1138. }
  1139. else if( _strcmpi( m_szCurrentEnvVariable, VERSION2 ) == 0 )
  1140. {
  1141. m_pSession->CSession::m_bIsTelnetVersion2 = true; //version 2
  1142. }
  1143. break;
  1144. case E_SFUTLNTMODE:
  1145. if( _strcmpi( m_szCurrentEnvVariable, STREAM ) == 0 )
  1146. {
  1147. m_pSession->CSession::m_bIsStreamMode = true;//Set it to stream mode
  1148. }
  1149. break;
  1150. }
  1151. m_dwWhichVar = E_UNKNOWN;
  1152. m_dwWhatVal = E_UNDEFINED;
  1153. m_szCurrentEnvVariable[0] = 0;
  1154. }
  1155. void CRFCProtocol::SubNewEnvGetVariable( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1156. {
  1157. /*For us, it doesn't matter whether a variable is VAR or USERVAR
  1158. Not bothering about any difference between IS and INFO */
  1159. /* VALUE is present */
  1160. m_dwWhatVal = E_DEFINED_BUT_NONE;
  1161. m_dwWhichVar = E_UNKNOWN;
  1162. if( m_szCurrentEnvVariable[0] != 0 )
  1163. {
  1164. FindVariable();
  1165. }
  1166. else
  1167. {
  1168. //Should not happen
  1169. _chASSERT( 0 );
  1170. }
  1171. m_szCurrentEnvVariable[0] = 0;
  1172. }
  1173. void CRFCProtocol::SubNewEnvGetString( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1174. {
  1175. static char str[] = " ";
  1176. str[0] = b;
  1177. if( strlen( m_szCurrentEnvVariable ) < MAX_PATH )
  1178. {
  1179. strcat( m_szCurrentEnvVariable, str );
  1180. }
  1181. m_fSubNewEnv = true;
  1182. }
  1183. void CRFCProtocol::SubTermType( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1184. {
  1185. char str[2];
  1186. str[0] = ( char ) b;
  1187. str[1] = 0;
  1188. if( strlen( m_pSession->CSession::m_pszTermType ) < MAX_PATH )
  1189. strcat( m_pSession->CSession::m_pszTermType, str );
  1190. fSubTermType = true;
  1191. }
  1192. void CRFCProtocol::SubAuth( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1193. {
  1194. if( m_wNTLMDataBufferIndex >= 2047 )
  1195. {
  1196. //if this happens, it is likely that somebody is screwing around.
  1197. _TRACE( TRACE_DEBUGGING, "Error: NTLMDataBuffer overflow" );
  1198. _chASSERT( 0 );
  1199. }
  1200. else
  1201. {
  1202. m_NTLMDataBuffer[ m_wNTLMDataBufferIndex++ ] = b;
  1203. }
  1204. fSubAuth = true;
  1205. }
  1206. #define MAX_ROWS 300
  1207. #define MAX_COLS 300
  1208. void CRFCProtocol::SubNaws( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1209. {
  1210. m_dwSubNawsByteNumber++;
  1211. //we ignore 1st and 3rd bytes because that is too many rows and
  1212. //cols for NT to support
  1213. if( 2 == m_dwSubNawsByteNumber )
  1214. {
  1215. if( b > 0 && b <= MAX_COLS )
  1216. m_pSession->CSession::m_wCols = b;
  1217. }
  1218. if( 4 == m_dwSubNawsByteNumber )
  1219. {
  1220. if( b > 0 && b <= MAX_ROWS )
  1221. m_pSession->CSession::m_wRows = b;
  1222. }
  1223. fSubNaws = true;
  1224. }
  1225. void CRFCProtocol::ChangeCurrentTerm()
  1226. {
  1227. if( !( m_pSession->CScraper::m_dwTerm & TERMVTNT ) )
  1228. {
  1229. m_pSession->CScraper::DeleteCMStrings();
  1230. }
  1231. m_pSession->CSession::InitTerm();
  1232. }
  1233. void CRFCProtocol::SubEnd( LPBYTE* ppPutBack, PUCHAR* pBuffer, BYTE b )
  1234. {
  1235. //other clients might first send DEC-vt100
  1236. //best to follow Assigned Numbers RFC
  1237. //and also change our ( not so compliant ;-) ) GUI telnet client
  1238. if( fSubTermType )
  1239. {
  1240. if( _strcmpi( VT52, m_pSession->CSession::m_pszTermType ) == 0 ||
  1241. _strcmpi( VT100, m_pSession->CSession::m_pszTermType ) == 0 ||
  1242. _strcmpi( ANSI, m_pSession->CSession::m_pszTermType ) == 0 ||
  1243. ( !( m_dwExcludeTerm & TERMVTNT ) &&
  1244. _strcmpi( VTNT, m_pSession->CSession::m_pszTermType ) == 0 ) )
  1245. {
  1246. // we got a good term type.
  1247. // set a flag to continue the telnet session
  1248. m_pSession->CSession::m_bNegotiatedTermType = true;
  1249. if( m_pSession->CSession::m_dwTerm != 0 )
  1250. {
  1251. ChangeCurrentTerm();
  1252. }
  1253. }
  1254. else
  1255. {
  1256. if( _strcmpi( m_szPrevTermType,
  1257. m_pSession->CSession::m_pszTermType ) != 0 )
  1258. {
  1259. (*pBuffer)[0] = TC_IAC;
  1260. (*pBuffer)[1] = TC_SB;
  1261. (*pBuffer)[2] = TO_TERMTYPE;
  1262. (*pBuffer)[3] = TT_SEND;
  1263. (*pBuffer)[4] = TC_IAC;
  1264. (*pBuffer)[5] = TC_SE;
  1265. (*pBuffer)[6] = 0;
  1266. *pBuffer += 6;
  1267. strncpy(m_szPrevTermType, m_pSession->CSession::m_pszTermType, (sizeof(m_szPrevTermType) - 1));
  1268. m_pSession->CSession::m_pszTermType[0] = 0;
  1269. }
  1270. else
  1271. {
  1272. //the client sent the same term type twice
  1273. //this means that the client has sent the last term type
  1274. //in its list
  1275. // this means that the client supports terminal types
  1276. // but it does not support anything we support;
  1277. // too bad ; either we should default to vt100
  1278. // or we should demand that the client don't do
  1279. // terminal types and we should go into NVT ASCII (tty) mode
  1280. // The client doesn't support anything that we like, we
  1281. // default to vt100 instead of doing the right thing as described
  1282. // above.
  1283. strncpy( m_pSession->CSession::m_pszTermType, VT100, (sizeof(m_pSession->CSession::m_pszTermType)-1));
  1284. m_pSession->CSession::m_bIsStreamMode = true;//Set it to stream mode
  1285. // set a flag to continue the telnet session
  1286. m_pSession->CSession::m_bNegotiatedTermType = true;
  1287. if( m_pSession->CSession::m_dwTerm != 0 )
  1288. {
  1289. ChangeCurrentTerm();
  1290. }
  1291. }
  1292. }
  1293. fSubTermType = false;
  1294. }
  1295. if( fSubAuth )
  1296. {
  1297. m_pSession->CIoHandler::DoNTLMAuth( (unsigned char*) m_NTLMDataBuffer,
  1298. m_wNTLMDataBufferIndex, pBuffer );
  1299. m_wNTLMDataBufferIndex = 0;
  1300. fSubAuth = false;
  1301. }
  1302. if( fSubNaws )
  1303. {
  1304. fSubNaws = false;
  1305. if( !m_fSubNawsFirstTime )
  1306. {
  1307. //For the first time we need to wait till IOHandles are created for
  1308. //Making following initialization
  1309. if( !m_pSession->CScraper::SetCmdInfo() )
  1310. {
  1311. _chASSERT( 0 );
  1312. }
  1313. }
  1314. else
  1315. {
  1316. m_fSubNawsFirstTime = false;
  1317. }
  1318. m_dwSubNawsByteNumber = 0;
  1319. }
  1320. if( m_fSubNewEnv )
  1321. {
  1322. SubNewEnvGetValue( ppPutBack, pBuffer, b );
  1323. m_fSubNewEnv = false;
  1324. }
  1325. m_subNegState = SS_START;
  1326. }
  1327. /*From RFC:
  1328. Specifically careful analysis should be done to determine which variables are "safe"
  1329. to set prior to having the client login. An example of a bad choice would be permitting
  1330. a variable to be changed that allows an intruder to circumvent or compromise the
  1331. login/authentication program itself */